scripts/_sbx_reset2.mjs
Rama main · réplica de lectura del repositorio original.
// Clean ONLY William's own wechat test artifacts on Will, so a fresh DM hits
// link-to-owner. Does NOT touch the 7 other users' wechat identities (the
// owner-scoped guard fix makes those irrelevant). DRY-RUN unless CONFIRM=yes.
import pg from 'pg';
const AGENT = 'cmewkyjkh0002ld04ydjqh3pq';
const GUEST = 'usr-mv5700w4'; // pure-wechat test guest
const WX = 'o9cq804c8lCFs2mlC7igP2j6VkQ4@im.wechat'; // William's own wechat
const SESSIONS = ['wechat:2026-10-12-d7c6fc4c', '56af52db-10ff-4bcd-b954-7d0ff17ce1d5'];
const OWNER = 'usr-e334d575b366';
const LIVE = process.env.CONFIRM === 'yes';
const c = new pg.Client({ connectionString: process.env.DATABASE_URL });
await c.connect();
const q = async (sql, p) => (await c.query(sql, p)).rows;
const n = async (sql, p) => (await q(sql, p))[0].n;
// safety: GUEST must be pure-wechat artifact
const gIds = await q(`select channel, channel_user_id from user_identities where user_id=$1`, [GUEST]);
const gMemb = await q(`select agent_id, role from user_agents where user_id=$1`, [GUEST]);
const gSched = await n(`select count(*)::int n from schedules where created_by=$1`, [GUEST]);
console.log(`GUEST ${GUEST}: identities=${JSON.stringify(gIds)} memberships=${JSON.stringify(gMemb)} scheds=${gSched}`);
const pure = gIds.every(i=>i.channel==='wechat') && gMemb.every(m=>m.agent_id===AGENT) && gSched===0;
if (!pure) { console.log('ABORT: guest is not a pure-wechat artifact'); await c.end(); process.exit(1); }
const evForSess = {};
let evTotal = 0;
for (const s of SESSIONS) { const e = await n(`select count(*)::int n from session_events where agent_id=$1 and session_id=$2`,[AGENT,s]); evForSess[s]=e; evTotal+=e; }
console.log(`\nDELETE plan:`);
console.log(` user ${GUEST} (+ its membership + wechat identity ${WX})`);
console.log(` sessions: ${JSON.stringify(evForSess)} (events total ${evTotal})`);
console.log(`\nAfter: resolve('wechat','${WX}') should be NOBODY (currently -> ${await q(`select user_id from user_identities where channel='wechat' and channel_user_id=$1`,[WX]).then(r=>r[0]?.user_id||'none')})`);
console.log(`Owner ${OWNER} wechat identities (must stay 0): ${await n(`select count(*)::int n from user_identities where user_id=$1 and channel='wechat'`,[OWNER])}`);
if (!LIVE) { console.log('\nDRY-RUN — no changes. CONFIRM=yes to apply.'); await c.end(); process.exit(0); }
await c.query('begin');
try {
for (const s of SESSIONS) {
await c.query(`delete from session_events where agent_id=$1 and session_id=$2`, [AGENT, s]);
await c.query(`delete from sessions where agent_id=$1 and session_id=$2`, [AGENT, s]);
}
await c.query(`delete from user_identities where channel='wechat' and channel_user_id=$1 and user_id=$2`, [WX, GUEST]);
await c.query(`delete from user_agents where user_id=$1`, [GUEST]);
await c.query(`delete from users where user_id=$1`, [GUEST]);
await c.query('commit');
console.log('\n[LIVE] cleanup committed.');
} catch (e) { await c.query('rollback'); console.log('ROLLED BACK:', e.message); process.exitCode=1; }
console.log('VERIFY resolve:', await q(`select user_id from user_identities where channel='wechat' and channel_user_id=$1`,[WX]).then(r=>r[0]?.user_id||'NOBODY (good)'));
console.log('VERIFY guest row:', await q(`select user_id from users where user_id=$1`,[GUEST]).then(r=>r[0]?'STILL EXISTS (bad)':'deleted (good)'));
console.log('VERIFY Will owners:', JSON.stringify(await q(`select user_id,role from user_agents where agent_id=$1 and role='owner'`,[AGENT])));
await c.end();
console.log('--- done ---');