refactor: simplify paired review system and add reviewer container isolation

Phase 1 — Strip over-engineering (-3,665 lines):
- DB tables: 7 → 3 (remove executions, approvals, artifacts, events)
- Task statuses: 11 → 5 (active, review_ready, in_review, merge_ready, completed)
- Remove plan governance, event sourcing, gate/verdict, freshness guards
- paired-execution-context: 980 → 299 lines
- Session commands: remove /risk, /plan, /approve-plan, /request-plan-changes

Phase 2 — Container isolation for reviewers:
- Add container-runtime.ts (Docker abstraction)
- Add credential-proxy.ts (API key injection without container exposure)
- Add container-runner.ts (reviewer-specific read-only mount + tmpfs)
- Add container/Dockerfile + agent-runner (Chromium, Claude Code, Codex)
- agent-runner.ts: auto-route reviewer execution to container mode
This commit is contained in:
Eyejoker
2026-03-29 18:16:28 +09:00
parent 3dd41f749e
commit fc9f2867b9
24 changed files with 1174 additions and 4900 deletions

View File

@@ -1,19 +1,11 @@
import Database from 'better-sqlite3';
import fs from 'fs';
import path from 'path';
import { describe, it, expect, beforeEach } from 'vitest';
import {
_initTestDatabase,
_initTestDatabaseFromFile,
applyPairedEvent,
cancelSupersededPairedExecutions,
claimServiceHandoff,
completeServiceHandoffAndAdvanceTargetCursor,
createPairedApproval,
createPairedArtifact,
createPairedExecution,
createPairedTask,
createTask,
createServiceHandoff,
@@ -32,8 +24,6 @@ import {
getRegisteredAgentTypesForJid,
getMessagesSince,
getNewMessages,
getPairedExecutionById,
getPairedEventByDedupeKey,
getPairedProject,
getPairedTaskById,
getPairedWorkspace,
@@ -41,10 +31,6 @@ import {
isPairedRoomJid,
getSession,
getTaskById,
listPairedApprovalsForTask,
listPairedArtifactsForTask,
listPairedEventsForTask,
listPairedExecutionsForTask,
listPairedWorkspacesForTask,
markWorkItemDelivered,
markWorkItemDeliveryRetry,
@@ -53,7 +39,6 @@ import {
setRouterStateForService,
storeChatMetadata,
storeMessage,
updatePairedExecution,
updatePairedTask,
upsertPairedProject,
upsertPairedWorkspace,
@@ -554,12 +539,11 @@ Check the run.
});
describe('paired task state', () => {
it('stores project, task, execution, workspace, approval, and artifact state', () => {
it('stores project, task, and workspace state', () => {
upsertPairedProject({
chat_jid: 'dc:paired',
group_folder: 'paired-room',
canonical_work_dir: '/tmp/paired-room',
workspace_topology: 'shadow-snapshot',
created_at: '2026-03-28T00:00:00.000Z',
updated_at: '2026-03-28T00:00:00.000Z',
});
@@ -572,604 +556,36 @@ describe('paired task state', () => {
reviewer_service_id: 'codex-review',
title: 'wire up workspaces',
source_ref: 'HEAD',
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'not_requested',
plan_notes: null,
review_requested_at: null,
status: 'draft',
status: 'active',
created_at: '2026-03-28T00:00:00.000Z',
updated_at: '2026-03-28T00:00:00.000Z',
});
createPairedExecution({
id: 'paired-exec-1',
task_id: 'paired-task-1',
service_id: 'codex-main',
role: 'owner',
workspace_id: null,
status: 'pending',
summary: null,
created_at: '2026-03-28T00:00:00.000Z',
started_at: null,
completed_at: null,
});
upsertPairedWorkspace({
id: 'paired-task-1:owner',
task_id: 'paired-task-1',
role: 'owner',
workspace_dir: '/tmp/paired-room/owner',
snapshot_source_dir: null,
snapshot_source_fingerprint: null,
snapshot_ref: null,
status: 'ready',
snapshot_refreshed_at: null,
created_at: '2026-03-28T00:00:00.000Z',
updated_at: '2026-03-28T00:00:00.000Z',
});
const approvalId = createPairedApproval({
task_id: 'paired-task-1',
service_id: 'codex-review',
role: 'reviewer',
status: 'pending',
note: 'needs snapshot',
created_at: '2026-03-28T00:00:01.000Z',
});
const artifactId = createPairedArtifact({
task_id: 'paired-task-1',
execution_id: 'paired-exec-1',
service_id: 'codex-review',
artifact_type: 'plan_brief',
title: 'review notes',
content: 'looks fine',
file_path: null,
created_at: '2026-03-28T00:00:02.000Z',
});
expect(getPairedProject('dc:paired')?.canonical_work_dir).toBe(
'/tmp/paired-room',
);
expect(getPairedTaskById('paired-task-1')?.status).toBe('draft');
expect(getPairedTaskById('paired-task-1')?.task_policy).toBe('autonomous');
expect(getPairedTaskById('paired-task-1')?.risk_level).toBe('low');
expect(getPairedTaskById('paired-task-1')?.plan_status).toBe(
'not_requested',
);
expect(getPairedTaskById('paired-task-1')?.gate_turn_kind ?? null).toBe(
null,
);
expect(
getPairedTaskById('paired-task-1')?.last_finalized_checkpoint ?? null,
).toBe(null);
expect(getPairedTaskById('paired-task-1')?.reviewer_verdict ?? null).toBe(
null,
);
expect(getPairedExecutionById('paired-exec-1')?.status).toBe('pending');
expect(getPairedTaskById('paired-task-1')?.status).toBe('active');
expect(getPairedWorkspace('paired-task-1', 'owner')?.workspace_dir).toBe(
'/tmp/paired-room/owner',
);
expect(listPairedApprovalsForTask('paired-task-1')[0]?.id).toBe(approvalId);
expect(listPairedArtifactsForTask('paired-task-1')[0]?.id).toBe(artifactId);
});
it('dedupes paired events and keeps request_review replay-safe', () => {
createPairedTask({
id: 'paired-task-events-1',
chat_jid: 'dc:paired',
group_folder: 'paired-room',
owner_service_id: 'codex-main',
reviewer_service_id: 'codex-review',
title: null,
source_ref: 'HEAD',
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'not_requested',
review_requested_at: null,
status: 'active',
created_at: '2026-03-29T00:00:00.000Z',
updated_at: '2026-03-29T00:00:00.000Z',
});
const first = applyPairedEvent({
event: {
task_id: 'paired-task-events-1',
event_type: 'request_review',
actor_role: 'owner',
source_service_id: 'codex-main',
source_fingerprint: 'fingerprint-v1',
dedupe_key: 'msg-review-1',
payload_json: '{"request":"review"}',
created_at: '2026-03-29T00:01:00.000Z',
},
onApply: () => {
updatePairedTask('paired-task-events-1', {
status: 'review_pending',
review_requested_at: '2026-03-29T00:01:00.000Z',
updated_at: '2026-03-29T00:01:00.000Z',
});
},
});
const second = applyPairedEvent({
event: {
task_id: 'paired-task-events-1',
event_type: 'request_review',
actor_role: 'owner',
source_service_id: 'codex-main',
source_fingerprint: 'fingerprint-v2',
dedupe_key: 'msg-review-1',
payload_json: '{"request":"review-again"}',
created_at: '2026-03-29T00:02:00.000Z',
},
onApply: () => {
updatePairedTask('paired-task-events-1', {
status: 'review_ready',
review_requested_at: '2026-03-29T00:02:00.000Z',
updated_at: '2026-03-29T00:02:00.000Z',
});
},
});
expect(first.applied).toBe(true);
expect(second.applied).toBe(false);
expect(listPairedEventsForTask('paired-task-events-1')).toHaveLength(1);
expect(
getPairedEventByDedupeKey({
taskId: 'paired-task-events-1',
eventType: 'request_review',
dedupeKey: 'msg-review-1',
})?.source_fingerprint,
).toBe('fingerprint-v1');
expect(getPairedTaskById('paired-task-events-1')?.status).toBe(
'review_pending',
);
expect(getPairedTaskById('paired-task-events-1')?.review_requested_at).toBe(
'2026-03-29T00:01:00.000Z',
);
});
it('dedupes deploy_complete and atomically finalizes the checkpoint once', () => {
createPairedTask({
id: 'paired-task-events-deploy',
chat_jid: 'dc:paired',
group_folder: 'paired-room',
owner_service_id: 'codex-main',
reviewer_service_id: 'codex-review',
title: null,
source_ref: 'HEAD',
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'approved',
review_requested_at: '2026-03-29T00:00:00.000Z',
last_finalized_checkpoint: null,
gate_turn_kind: null,
reviewer_verdict: 'done',
reviewer_verdict_at: '2026-03-29T00:00:00.000Z',
reviewer_verdict_note: '**DONE** ready',
status: 'merge_ready',
created_at: '2026-03-29T00:00:00.000Z',
updated_at: '2026-03-29T00:00:00.000Z',
});
const first = applyPairedEvent({
event: {
task_id: 'paired-task-events-deploy',
event_type: 'deploy_complete',
actor_role: 'owner',
source_service_id: 'codex-main',
source_fingerprint: 'canonical-v1',
dedupe_key: 'deploy-complete:canonical-v1',
payload_json: '{"checkpoint":"canonical-v1"}',
created_at: '2026-03-29T00:01:00.000Z',
},
onApply: () => {
updatePairedTask('paired-task-events-deploy', {
status: 'merged',
last_finalized_checkpoint: 'canonical-v1',
updated_at: '2026-03-29T00:01:00.000Z',
});
},
});
const second = applyPairedEvent({
event: {
task_id: 'paired-task-events-deploy',
event_type: 'deploy_complete',
actor_role: 'owner',
source_service_id: 'codex-main',
source_fingerprint: 'canonical-v1',
dedupe_key: 'deploy-complete:canonical-v1',
payload_json: '{"checkpoint":"canonical-v1"}',
created_at: '2026-03-29T00:02:00.000Z',
},
onApply: () => {
updatePairedTask('paired-task-events-deploy', {
status: 'failed',
last_finalized_checkpoint: 'should-not-change',
updated_at: '2026-03-29T00:02:00.000Z',
});
},
});
expect(first.applied).toBe(true);
expect(second.applied).toBe(false);
expect(
listPairedEventsForTask('paired-task-events-deploy').filter(
(event) => event.event_type === 'deploy_complete',
),
).toHaveLength(1);
expect(
getPairedTaskById('paired-task-events-deploy')?.last_finalized_checkpoint,
).toBe('canonical-v1');
expect(getLatestPairedTaskForChat('dc:paired')?.status).toBe('merged');
expect(getPairedTaskById('paired-task-events-deploy')?.status).toBe(
'merged',
);
});
it('rolls back paired event insert when the coupled state update fails', () => {
createPairedTask({
id: 'paired-task-events-2',
chat_jid: 'dc:paired',
group_folder: 'paired-room',
owner_service_id: 'codex-main',
reviewer_service_id: 'codex-review',
title: null,
source_ref: 'HEAD',
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'not_requested',
review_requested_at: null,
status: 'active',
created_at: '2026-03-29T00:00:00.000Z',
updated_at: '2026-03-29T00:00:00.000Z',
});
expect(() =>
applyPairedEvent({
event: {
task_id: 'paired-task-events-2',
event_type: 'set_risk',
actor_role: 'owner',
source_service_id: 'codex-main',
source_fingerprint: 'fingerprint-v1',
dedupe_key: 'msg-risk-1',
payload_json: '{"riskLevel":"high"}',
created_at: '2026-03-29T00:01:00.000Z',
},
onApply: () => {
updatePairedTask('paired-task-events-2', {
risk_level: 'high',
updated_at: '2026-03-29T00:01:00.000Z',
});
throw new Error('boom');
},
}),
).toThrow('boom');
expect(listPairedEventsForTask('paired-task-events-2')).toHaveLength(0);
expect(getPairedTaskById('paired-task-events-2')?.risk_level).toBe('low');
});
it('keeps paired event audit history after reopening the database', () => {
const tempRoot = fs.mkdtempSync(path.join('/tmp', 'ejclaw-db-events-'));
const dbPath = path.join(tempRoot, 'messages.db');
_initTestDatabaseFromFile(dbPath);
createPairedTask({
id: 'paired-task-events-3',
chat_jid: 'dc:paired',
group_folder: 'paired-room',
owner_service_id: 'codex-main',
reviewer_service_id: 'codex-review',
title: null,
source_ref: 'HEAD',
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'not_requested',
review_requested_at: null,
status: 'active',
created_at: '2026-03-29T00:00:00.000Z',
updated_at: '2026-03-29T00:00:00.000Z',
});
applyPairedEvent({
event: {
task_id: 'paired-task-events-3',
event_type: 'request_review',
actor_role: 'owner',
source_service_id: 'codex-main',
source_fingerprint: 'fingerprint-v1',
dedupe_key: 'msg-review-3',
payload_json: '{"request":"review"}',
created_at: '2026-03-29T00:01:00.000Z',
},
onApply: () => {
updatePairedTask('paired-task-events-3', {
status: 'review_pending',
review_requested_at: '2026-03-29T00:01:00.000Z',
updated_at: '2026-03-29T00:01:00.000Z',
});
},
});
_initTestDatabaseFromFile(dbPath);
expect(listPairedEventsForTask('paired-task-events-3')).toHaveLength(1);
expect(listPairedEventsForTask('paired-task-events-3')[0]?.dedupe_key).toBe(
'msg-review-3',
);
expect(
listPairedEventsForTask('paired-task-events-3')[0]?.source_fingerprint,
).toBe('fingerprint-v1');
fs.rmSync(tempRoot, { recursive: true, force: true });
});
it('backfills governance plan_status by legacy task status during migration', () => {
const tempRoot = fs.mkdtempSync(path.join('/tmp', 'ejclaw-db-migration-'));
const dbPath = path.join(tempRoot, 'messages.db');
const legacyDb = new Database(dbPath);
legacyDb.exec(`
CREATE TABLE paired_tasks (
id TEXT PRIMARY KEY,
chat_jid TEXT NOT NULL,
group_folder TEXT NOT NULL,
owner_service_id TEXT NOT NULL,
reviewer_service_id TEXT NOT NULL,
title TEXT,
source_ref TEXT,
review_requested_at TEXT,
status TEXT NOT NULL DEFAULT 'draft',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
`);
const insertLegacyTask = legacyDb.prepare(`
INSERT INTO paired_tasks (
id,
chat_jid,
group_folder,
owner_service_id,
reviewer_service_id,
title,
source_ref,
review_requested_at,
status,
created_at,
updated_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
insertLegacyTask.run(
'paired-active',
'dc:paired',
'paired-room',
'codex-main',
'codex-review',
null,
'HEAD',
null,
'active',
'2026-03-29T00:00:00.000Z',
'2026-03-29T00:00:00.000Z',
);
insertLegacyTask.run(
'paired-draft',
'dc:paired',
'paired-room',
'codex-main',
'codex-review',
null,
'HEAD',
null,
'draft',
'2026-03-29T00:00:00.000Z',
'2026-03-29T00:00:00.000Z',
);
insertLegacyTask.run(
'paired-in-review',
'dc:paired',
'paired-room',
'codex-main',
'codex-review',
null,
'HEAD',
'2026-03-29T00:01:00.000Z',
'in_review',
'2026-03-29T00:00:00.000Z',
'2026-03-29T00:01:00.000Z',
);
insertLegacyTask.run(
'paired-merge-ready',
'dc:paired',
'paired-room',
'codex-main',
'codex-review',
null,
'HEAD',
'2026-03-29T00:02:00.000Z',
'merge_ready',
'2026-03-29T00:00:00.000Z',
'2026-03-29T00:02:00.000Z',
);
legacyDb.close();
_initTestDatabaseFromFile(dbPath);
expect(getPairedTaskById('paired-in-review')?.plan_status).toBe('approved');
expect(getPairedTaskById('paired-merge-ready')?.plan_status).toBe(
'approved',
);
expect(getPairedTaskById('paired-active')?.plan_status).toBe(
'not_requested',
);
expect(getPairedTaskById('paired-draft')?.plan_status).toBe(
'not_requested',
);
fs.rmSync(tempRoot, { recursive: true, force: true });
});
it('migrates paired task finalization fields and deploy_complete events', () => {
const tempRoot = fs.mkdtempSync(path.join('/tmp', 'ejclaw-db-finalize-'));
const dbPath = path.join(tempRoot, 'messages.db');
const legacyDb = new Database(dbPath);
legacyDb.exec(`
CREATE TABLE paired_tasks (
id TEXT PRIMARY KEY,
chat_jid TEXT NOT NULL,
group_folder TEXT NOT NULL,
owner_service_id TEXT NOT NULL,
reviewer_service_id TEXT NOT NULL,
title TEXT,
source_ref TEXT,
task_policy TEXT NOT NULL DEFAULT 'autonomous',
risk_level TEXT NOT NULL DEFAULT 'low',
plan_status TEXT NOT NULL DEFAULT 'not_requested',
review_requested_at TEXT,
gate_turn_kind TEXT,
reviewer_verdict TEXT,
reviewer_verdict_at TEXT,
reviewer_verdict_note TEXT,
status TEXT NOT NULL DEFAULT 'active',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE paired_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL,
event_type TEXT NOT NULL,
actor_role TEXT NOT NULL,
source_service_id TEXT NOT NULL,
source_fingerprint TEXT,
dedupe_key TEXT NOT NULL,
payload_json TEXT,
created_at TEXT NOT NULL
);
`);
legacyDb
.prepare(
`
INSERT INTO paired_tasks (
id,
chat_jid,
group_folder,
owner_service_id,
reviewer_service_id,
title,
source_ref,
task_policy,
risk_level,
plan_status,
review_requested_at,
gate_turn_kind,
reviewer_verdict,
reviewer_verdict_at,
reviewer_verdict_note,
status,
created_at,
updated_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`,
)
.run(
'paired-finalized',
'dc:paired',
'paired-room',
'codex-main',
'codex-review',
null,
'HEAD',
'autonomous',
'low',
'approved',
'2026-03-29T00:00:00.000Z',
null,
'done',
'2026-03-29T00:00:00.000Z',
'**DONE**',
'merge_ready',
'2026-03-29T00:00:00.000Z',
'2026-03-29T00:00:00.000Z',
);
legacyDb
.prepare(
`
INSERT INTO paired_events (
task_id,
event_type,
actor_role,
source_service_id,
source_fingerprint,
dedupe_key,
payload_json,
created_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`,
)
.run(
'paired-finalized',
'request_review',
'owner',
'codex-main',
'fingerprint-v1',
'msg-review-legacy',
null,
'2026-03-29T00:00:00.000Z',
);
legacyDb.close();
_initTestDatabaseFromFile(dbPath);
expect(
getPairedTaskById('paired-finalized')?.last_finalized_checkpoint ?? null,
).toBe(null);
applyPairedEvent({
event: {
task_id: 'paired-finalized',
event_type: 'deploy_complete',
actor_role: 'owner',
source_service_id: 'codex-main',
source_fingerprint: 'canonical-v1',
dedupe_key: 'deploy-complete:canonical-v1',
payload_json: '{"checkpoint":"canonical-v1"}',
created_at: '2026-03-29T00:01:00.000Z',
},
onApply: () => {
updatePairedTask('paired-finalized', {
status: 'merged',
last_finalized_checkpoint: 'canonical-v1',
updated_at: '2026-03-29T00:01:00.000Z',
});
},
});
expect(getPairedTaskById('paired-finalized')?.status).toBe('merged');
expect(
getPairedTaskById('paired-finalized')?.last_finalized_checkpoint,
).toBe('canonical-v1');
expect(
getPairedEventByDedupeKey({
taskId: 'paired-finalized',
eventType: 'deploy_complete',
dedupeKey: 'deploy-complete:canonical-v1',
})?.source_fingerprint,
).toBe('canonical-v1');
fs.rmSync(tempRoot, { recursive: true, force: true });
});
it('updates task and execution state and keeps one workspace per role', () => {
it('updates task state and keeps one workspace per role', () => {
createPairedTask({
id: 'paired-task-2',
chat_jid: 'dc:paired',
@@ -1178,43 +594,18 @@ describe('paired task state', () => {
reviewer_service_id: 'codex-review',
title: null,
source_ref: null,
task_policy: 'user_signoff_required',
risk_level: 'high',
plan_status: 'pending',
plan_notes: null,
review_requested_at: null,
status: 'draft',
status: 'active',
created_at: '2026-03-28T00:00:00.000Z',
updated_at: '2026-03-28T00:00:00.000Z',
});
createPairedExecution({
id: 'paired-exec-2',
task_id: 'paired-task-2',
service_id: 'codex-review',
role: 'reviewer',
workspace_id: null,
status: 'pending',
summary: null,
created_at: '2026-03-28T00:00:00.000Z',
started_at: null,
completed_at: null,
});
updatePairedTask('paired-task-2', {
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'approved',
gate_turn_kind: 'implementation_start',
reviewer_verdict: 'done_with_concerns',
reviewer_verdict_at: '2026-03-28T00:09:00.000Z',
reviewer_verdict_note: '**DONE_WITH_CONCERNS** okay to proceed',
status: 'review_pending',
status: 'review_ready',
review_requested_at: '2026-03-28T00:10:00.000Z',
updated_at: '2026-03-28T00:10:00.000Z',
});
updatePairedExecution('paired-exec-2', {
status: 'running',
started_at: '2026-03-28T00:11:00.000Z',
});
expect(getPairedTaskById('paired-task-2')?.gate_turn_kind).toBe(
'implementation_start',
@@ -1229,7 +620,7 @@ describe('paired task state', () => {
role: 'reviewer',
workspace_dir: '/tmp/reviewer-v1',
snapshot_source_dir: '/tmp/owner',
snapshot_source_fingerprint: 'fingerprint-v1',
snapshot_ref: 'fingerprint-v1',
status: 'ready',
snapshot_refreshed_at: '2026-03-28T00:10:00.000Z',
created_at: '2026-03-28T00:10:00.000Z',
@@ -1241,89 +632,20 @@ describe('paired task state', () => {
role: 'reviewer',
workspace_dir: '/tmp/reviewer-v2',
snapshot_source_dir: '/tmp/owner',
snapshot_source_fingerprint: 'fingerprint-v2',
snapshot_ref: 'fingerprint-v2',
status: 'ready',
snapshot_refreshed_at: '2026-03-28T00:12:00.000Z',
created_at: '2026-03-28T00:10:00.000Z',
updated_at: '2026-03-28T00:12:00.000Z',
});
expect(getPairedTaskById('paired-task-2')?.status).toBe('review_pending');
expect(getPairedTaskById('paired-task-2')?.task_policy).toBe('autonomous');
expect(getPairedTaskById('paired-task-2')?.risk_level).toBe('low');
expect(getPairedTaskById('paired-task-2')?.plan_status).toBe('approved');
expect(getPairedExecutionById('paired-exec-2')?.status).toBe('running');
expect(getPairedTaskById('paired-task-2')?.status).toBe('review_ready');
expect(
listPairedWorkspacesForTask('paired-task-2').map(
(workspace) => workspace.workspace_dir,
),
).toEqual(['/tmp/reviewer-v2']);
});
it('persists execution checkpoints and cancels only superseded running executions', () => {
createPairedTask({
id: 'paired-task-3',
chat_jid: 'dc:paired',
group_folder: 'paired-room',
owner_service_id: 'codex-main',
reviewer_service_id: 'codex-review',
title: null,
source_ref: 'HEAD',
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'approved',
review_requested_at: null,
status: 'active',
created_at: '2026-03-29T01:00:00.000Z',
updated_at: '2026-03-29T01:00:00.000Z',
});
createPairedExecution({
id: 'paired-exec-3a',
task_id: 'paired-task-3',
service_id: 'codex-review',
role: 'reviewer',
workspace_id: 'paired-task-3:reviewer',
checkpoint_fingerprint: 'fingerprint-v1',
status: 'running',
summary: null,
created_at: '2026-03-29T01:01:00.000Z',
started_at: '2026-03-29T01:01:00.000Z',
completed_at: null,
});
createPairedExecution({
id: 'paired-exec-3b',
task_id: 'paired-task-3',
service_id: 'codex-review',
role: 'reviewer',
workspace_id: 'paired-task-3:reviewer',
checkpoint_fingerprint: 'fingerprint-v2',
status: 'running',
summary: null,
created_at: '2026-03-29T01:02:00.000Z',
started_at: '2026-03-29T01:02:00.000Z',
completed_at: null,
});
const cancelled = cancelSupersededPairedExecutions({
taskId: 'paired-task-3',
role: 'reviewer',
exceptExecutionId: 'paired-exec-3b',
note: 'Superseded by a newer review checkpoint.',
});
expect(cancelled).toBe(1);
expect(getPairedExecutionById('paired-exec-3a')).toMatchObject({
status: 'cancelled',
checkpoint_fingerprint: 'fingerprint-v1',
});
expect(getPairedExecutionById('paired-exec-3b')).toMatchObject({
status: 'running',
checkpoint_fingerprint: 'fingerprint-v2',
});
expect(
listPairedExecutionsForTask('paired-task-3').map((execution) => execution.id),
).toEqual(['paired-exec-3a', 'paired-exec-3b']);
});
});
// --- LIMIT behavior ---