feat: finalize paired tasks on deploy completion

This commit is contained in:
Eyejoker
2026-03-29 06:42:03 +09:00
parent dad6f50937
commit 0e12a560a4
9 changed files with 849 additions and 3 deletions

View File

@@ -22,6 +22,10 @@ const SESSION_COMMAND_CONTROL_PATTERNS = [
/^Plan approval must be handled by the reviewer service\.$/,
/^Plan review commands are only required for high-risk tasks\.$/,
/^Plan artifacts are incomplete\.(?:\n|$)/,
/^Deployment finalized\.(?:\n|$)/,
/^Deployment finalization must be handled by the owner service\.$/,
/^Deploy completion requires a merge-ready task or the same already-finalized checkpoint\.(?:\n|$)/,
/^Deploy completion requires a canonical workDir with a readable HEAD\.$/,
/^Review is unavailable for this room\./,
];
@@ -44,6 +48,7 @@ export function extractSessionCommand(
if (text === '/compact') return '/compact';
if (text === '/clear') return '/clear';
if (text === '/review' || text === '/review-ready') return '/review';
if (text === '/deploy-complete') return '/deploy-complete';
if (/^\/risk(?:\s|$)/.test(text)) return '/risk';
if (/^\/plan(?:\s|$)/.test(text)) return '/plan';
if (text === '/approve-plan') return '/approve-plan';
@@ -109,6 +114,7 @@ export interface SessionCommandDeps {
note: string | undefined,
dedupeKey: string,
) => Promise<string | null>;
finalizeDeployment: () => Promise<string | null>;
}
function resultToText(result: string | object | null | undefined): string {
@@ -203,6 +209,15 @@ export async function handleSessionCommand(opts: {
return { handled: true, success: true };
}
if (command === '/deploy-complete') {
deps.advanceCursor(cmdMsg.timestamp);
await deps.sendMessage(
(await deps.finalizeDeployment()) ??
'Deploy finalization is unavailable for this room.',
);
return { handled: true, success: true };
}
if (command === '/risk') {
const riskArg = normalizedCommandText
.slice('/risk'.length)