feat: add paired review workspace flow

This commit is contained in:
Eyejoker
2026-03-28 21:14:25 +09:00
parent 79a8a2639e
commit e7f49d77da
19 changed files with 2719 additions and 20 deletions

View File

@@ -23,6 +23,12 @@ describe('extractSessionCommand', () => {
expect(extractSessionCommand('/clear', trigger)).toBe('/clear');
});
it('detects bare /review-ready', () => {
expect(extractSessionCommand('/review-ready', trigger)).toBe(
'/review-ready',
);
});
it('rejects /compact with extra text', () => {
expect(extractSessionCommand('/compact now please', trigger)).toBeNull();
});
@@ -120,6 +126,7 @@ function makeDeps(
formatMessages: vi.fn().mockReturnValue('<formatted>'),
isAdminSender: vi.fn().mockReturnValue(false),
canSenderInteract: vi.fn().mockReturnValue(true),
markReviewReady: vi.fn().mockResolvedValue('Review snapshot updated.'),
...overrides,
};
}
@@ -178,6 +185,31 @@ describe('handleSessionCommand', () => {
);
});
it('handles authorized /review-ready without invoking the agent', async () => {
const deps = makeDeps({
markReviewReady: vi.fn().mockResolvedValue(
'Review snapshot updated.\n- Task: paired-task-1',
),
});
const result = await handleSessionCommand({
missedMessages: [makeMsg('/review-ready')],
isMainGroup: true,
groupName: 'test',
triggerPattern: trigger,
timezone: 'UTC',
deps,
});
expect(result).toEqual({ handled: true, success: true });
expect(deps.markReviewReady).toHaveBeenCalledTimes(1);
expect(deps.runAgent).not.toHaveBeenCalled();
expect(deps.advanceCursor).toHaveBeenCalledWith('100');
expect(deps.sendMessage).toHaveBeenCalledWith(
'Review snapshot updated.\n- Task: paired-task-1',
);
});
it('sends denial to interactable sender in non-main group', async () => {
const deps = makeDeps();
const result = await handleSessionCommand({