fix(scripts): purge reviewer/arbiter session leftovers on deregister

Deregistration only removed the base group folder, leaving the tribunal
reviewer/arbiter runtime behind: DB session rows keyed as "<folder>:reviewer"
/":arbiter" and on-disk dirs data/sessions/<folder>-reviewer/-arbiter (plus
ipc/workspaces variants). Include those role-suffixed variants in both the
sessions DELETE and the disk cleanup so a deregistered room leaves nothing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-08-21 14:10:38 +09:00
parent d57dd68fc0
commit 3f73197e6c

View File

@@ -163,7 +163,6 @@ const scheduledTaskIds = (
).map((r) => r.id);
const qS = scheduledTaskIds.map(() => '?').join(',');
const safeFolderList = [...safeFolders];
const qF = safeFolderList.map(() => '?').join(',');
const count = (t: string, where: string, a: unknown[]): number =>
(
@@ -221,15 +220,22 @@ for (const t of [
addJid(t);
}
// sessions are keyed by group folder — only purge folders not shared with a
// surviving room.
if (safeFolderList.length) {
// surviving room. Reviewer/arbiter sessions are stored under the colon-suffixed
// group_folder (e.g. "<folder>:reviewer"), so include those variants too.
const sessionFolderKeys = safeFolderList.flatMap((f) => [
f,
`${f}:reviewer`,
`${f}:arbiter`,
]);
if (sessionFolderKeys.length) {
const qSess = sessionFolderKeys.map(() => '?').join(',');
plan.push({
table: 'sessions',
n: count('sessions', `group_folder IN (${qF})`, safeFolderList),
n: count('sessions', `group_folder IN (${qSess})`, sessionFolderKeys),
run: () =>
db
.query(`DELETE FROM sessions WHERE group_folder IN (${qF})`)
.run(...safeFolderList),
.query(`DELETE FROM sessions WHERE group_folder IN (${qSess})`)
.run(...sessionFolderKeys),
});
}
@@ -250,11 +256,17 @@ if (routerPrune) console.log(` router_state.last_agent_seq: ${routerPrune}`);
// disk targets
const diskDirs: string[] = [];
for (const folder of safeFolders) {
// Tribunal rooms keep separate reviewer/arbiter runtime dirs suffixed with
// the role (e.g. data/sessions/<folder>-reviewer). Include those variants so
// deregistration leaves no leftovers.
const folderVariants = [folder, `${folder}-reviewer`, `${folder}-arbiter`];
for (const d of [
path.join(GROUPS_DIR, folder),
path.join(DATA_DIR, 'workspaces', folder),
path.join(DATA_DIR, 'sessions', folder),
path.join(DATA_DIR, 'ipc', folder),
...folderVariants.flatMap((f) => [
path.join(DATA_DIR, 'workspaces', f),
path.join(DATA_DIR, 'sessions', f),
path.join(DATA_DIR, 'ipc', f),
]),
]) {
if (fs.existsSync(d)) diskDirs.push(d);
}