fix: reconcile governance scaffold follow-up

This commit is contained in:
Eyejoker
2026-03-29 01:38:30 +09:00
parent dc8dd98e84
commit c76ed1d10a
9 changed files with 38 additions and 26 deletions

View File

@@ -732,9 +732,7 @@ describe('paired task state', () => {
_initTestDatabaseFromFile(dbPath); _initTestDatabaseFromFile(dbPath);
expect(getPairedTaskById('paired-in-review')?.plan_status).toBe( expect(getPairedTaskById('paired-in-review')?.plan_status).toBe('approved');
'approved',
);
expect(getPairedTaskById('paired-merge-ready')?.plan_status).toBe( expect(getPairedTaskById('paired-merge-ready')?.plan_status).toBe(
'approved', 'approved',
); );

View File

@@ -761,8 +761,7 @@ function createSchema(database: Database.Database): void {
.get() as { sql?: string } | undefined; .get() as { sql?: string } | undefined;
const pairedArtifactsSql = pairedArtifactsSqlRow?.sql || ''; const pairedArtifactsSql = pairedArtifactsSqlRow?.sql || '';
const pairedArtifactsNeedsMigration = const pairedArtifactsNeedsMigration =
pairedArtifactsSql && pairedArtifactsSql && !pairedArtifactsSql.includes("'plan_brief'");
!pairedArtifactsSql.includes("'plan_brief'");
if (pairedArtifactsNeedsMigration) { if (pairedArtifactsNeedsMigration) {
database.exec(` database.exec(`
CREATE TABLE paired_artifacts_new ( CREATE TABLE paired_artifacts_new (

View File

@@ -246,10 +246,9 @@ describe('createMessageRuntime', () => {
is_from_me: true, is_from_me: true,
}, },
]); ]);
const actualSessionCommands = const actualSessionCommands = await vi.importActual<
await vi.importActual<typeof import('./session-commands.js')>( typeof import('./session-commands.js')
'./session-commands.js', >('./session-commands.js');
);
vi.mocked(sessionCommands.handleSessionCommand).mockImplementation((opts) => vi.mocked(sessionCommands.handleSessionCommand).mockImplementation((opts) =>
actualSessionCommands.handleSessionCommand(opts), actualSessionCommands.handleSessionCommand(opts),
); );

View File

@@ -343,8 +343,10 @@ describe('paired execution context', () => {
pairedWorkspaceManager.markPairedTaskReviewReady, pairedWorkspaceManager.markPairedTaskReviewReady,
).toHaveBeenCalledWith('task-1'); ).toHaveBeenCalledWith('task-1');
expect(result?.status).toBe('ready'); expect(result?.status).toBe('ready');
if (!result || result.status !== 'ready') {
throw new Error('expected ready review result');
}
expect(result.task.status).toBe('review_ready'); expect(result.task.status).toBe('review_ready');
expect(result?.task.status).toBe('review_ready');
}); });
it('keeps review_pending and returns a pending result when owner workspace is not ready', () => { it('keeps review_pending and returns a pending result when owner workspace is not ready', () => {

View File

@@ -1,10 +1,7 @@
import { execFileSync } from 'child_process'; import { execFileSync } from 'child_process';
import crypto from 'crypto'; import crypto from 'crypto';
import { import { SERVICE_ID, normalizeServiceId } from './config.js';
SERVICE_ID,
normalizeServiceId,
} from './config.js';
import { import {
createPairedExecution, createPairedExecution,
createPairedTask, createPairedTask,

View File

@@ -100,7 +100,10 @@ describe('paired /review command path', () => {
expect(ownerResult?.workspace?.workspace_dir).toBeTruthy(); expect(ownerResult?.workspace?.workspace_dir).toBeTruthy();
const ownerWorkspaceDir = ownerResult!.workspace!.workspace_dir; const ownerWorkspaceDir = ownerResult!.workspace!.workspace_dir;
fs.writeFileSync(path.join(ownerWorkspaceDir, 'README.md'), 'owner change\n'); fs.writeFileSync(
path.join(ownerWorkspaceDir, 'README.md'),
'owner change\n',
);
process.env.EJCLAW_DATA_DIR = path.join(tempRoot, 'data-review'); process.env.EJCLAW_DATA_DIR = path.join(tempRoot, 'data-review');
process.env.SERVICE_ID = 'codex-review'; process.env.SERVICE_ID = 'codex-review';

View File

@@ -125,7 +125,9 @@ describe('paired workspace manager', () => {
runGit(['status', '--short'], reviewerWorkspace.workspace_dir), runGit(['status', '--short'], reviewerWorkspace.workspace_dir),
).toContain('M README.md'); ).toContain('M README.md');
expect(db.getPairedTaskById('paired-task-1')?.status).toBe('review_ready'); expect(db.getPairedTaskById('paired-task-1')?.status).toBe('review_ready');
expect(db.getPairedTaskById('paired-task-1')?.review_requested_at).toBeTruthy(); expect(
db.getPairedTaskById('paired-task-1')?.review_requested_at,
).toBeTruthy();
expect( expect(
db.getPairedWorkspace('paired-task-1', 'reviewer')?.snapshot_refreshed_at, db.getPairedWorkspace('paired-task-1', 'reviewer')?.snapshot_refreshed_at,
).toBeTruthy(); ).toBeTruthy();
@@ -165,6 +167,9 @@ describe('paired workspace manager', () => {
reviewer_service_id: 'codex-review', reviewer_service_id: 'codex-review',
title: null, title: null,
source_ref: 'HEAD', source_ref: 'HEAD',
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'not_requested',
review_requested_at: null, review_requested_at: null,
status: 'draft', status: 'draft',
created_at: now, created_at: now,
@@ -226,8 +231,9 @@ describe('paired workspace manager', () => {
updated_at: now, updated_at: now,
}); });
const ownerWorkspace = const ownerWorkspace = manager.provisionOwnerWorkspaceForPairedTask(
manager.provisionOwnerWorkspaceForPairedTask('paired-task-cross-service'); 'paired-task-cross-service',
);
fs.writeFileSync( fs.writeFileSync(
path.join(ownerWorkspace.workspace_dir, 'README.md'), path.join(ownerWorkspace.workspace_dir, 'README.md'),
'owner modified\n', 'owner modified\n',
@@ -700,6 +706,9 @@ describe('paired workspace manager', () => {
reviewer_service_id: 'codex-review', reviewer_service_id: 'codex-review',
title: null, title: null,
source_ref: 'HEAD', source_ref: 'HEAD',
task_policy: 'autonomous',
risk_level: 'low',
plan_status: 'not_requested',
review_requested_at: null, review_requested_at: null,
status: 'draft', status: 'draft',
created_at: now, created_at: now,
@@ -798,8 +807,12 @@ describe('paired workspace manager', () => {
expect(blocked.blockMessage).toBe( expect(blocked.blockMessage).toBe(
'Review snapshot is stale after owner changes. Retry the review once to refresh against the latest owner workspace.', 'Review snapshot is stale after owner changes. Retry the review once to refresh against the latest owner workspace.',
); );
expect(db.getPairedTaskById('paired-task-6')?.status).toBe('review_pending'); expect(db.getPairedTaskById('paired-task-6')?.status).toBe(
expect(db.getPairedTaskById('paired-task-6')?.review_requested_at).toBeTruthy(); 'review_pending',
);
expect(
db.getPairedTaskById('paired-task-6')?.review_requested_at,
).toBeTruthy();
expect(db.getPairedWorkspace('paired-task-6', 'reviewer')?.status).toBe( expect(db.getPairedWorkspace('paired-task-6', 'reviewer')?.status).toBe(
'stale', 'stale',
); );
@@ -816,6 +829,8 @@ describe('paired workspace manager', () => {
'utf-8', 'utf-8',
), ),
).toBe('owner changed again\n'); ).toBe('owner changed again\n');
expect(db.getPairedTaskById('paired-task-6')?.review_requested_at).toBeTruthy(); expect(
db.getPairedTaskById('paired-task-6')?.review_requested_at,
).toBeTruthy();
}); });
}); });

View File

@@ -504,10 +504,7 @@ export function prepareReviewerWorkspaceForExecution(
const now = new Date().toISOString(); const now = new Date().toISOString();
if (snapshotMissing || snapshotStale) { if (snapshotMissing || snapshotStale) {
if ( if (task.status === 'review_pending' || task.status === 'review_ready') {
task.status === 'review_pending' ||
task.status === 'review_ready'
) {
const refreshedWorkspace = refreshReviewerSnapshotForPairedTask(task.id); const refreshedWorkspace = refreshReviewerSnapshotForPairedTask(task.id);
updatePairedTask(task.id, { updatePairedTask(task.id, {
status: 'review_ready', status: 'review_ready',

View File

@@ -93,7 +93,9 @@ describe('isSessionCommandControlMessage', () => {
it('matches multiline review snapshot output', () => { it('matches multiline review snapshot output', () => {
expect( expect(
isSessionCommandControlMessage('Review snapshot updated.\n- Task: task-1'), isSessionCommandControlMessage(
'Review snapshot updated.\n- Task: task-1',
),
).toBe(true); ).toBe(true);
}); });