fix: prevent DONE↔DONE infinite loop and add AGENT_LANGUAGE setting

- Fix source_ref mismatch: update to workspace HEAD on first owner run
  so change detection compares against the correct repo
- Treat hasNewChanges === null as "no changes" at finalize to prevent
  infinite re-review when source_ref is unresolvable
- Add AGENT_LANGUAGE env var: when set, appends language instruction to
  all paired room prompts (owner, reviewer, arbiter)
This commit is contained in:
Eyejoker
2026-03-31 13:55:41 +09:00
parent 47d532e869
commit 757e33c58e
3 changed files with 39 additions and 14 deletions

View File

@@ -288,6 +288,18 @@ export function preparePairedExecutionContext(args: {
// Use a stable per-channel worktree (not per-task) so the Claude SDK
// session persists across tasks. Different channels still get isolation.
workspace = provisionOwnerWorkspaceForPairedTask(latestTask.id);
// Update source_ref from workspace HEAD so change detection compares
// against the correct repo. At task creation, source_ref is from the
// canonical workDir which may differ from the workspace clone.
if (workspace?.workspace_dir && latestTask.status === 'active') {
const wsRef = resolveCanonicalSourceRef(workspace.workspace_dir);
if (wsRef !== latestTask.source_ref) {
updatePairedTask(latestTask.id, {
source_ref: wsRef,
updated_at: now,
});
}
}
} else if (roomRoleContext.role === 'reviewer') {
const reviewerWorkspace = prepareReviewerWorkspaceForExecution(latestTask);
workspace = reviewerWorkspace.workspace;
@@ -512,28 +524,32 @@ export function completePairedExecutionContext(args: {
? hasCodeChangesSinceRef(workspace.workspace_dir, task.source_ref)
: null;
if (hasNewChanges === false) {
// No code changes since reviewer approvedfinalize complete
if (hasNewChanges === true) {
// Owner made changes after approvalneeds re-review
logger.info(
{
taskId,
sourceRef: task.source_ref,
hasNewChanges,
},
'Owner made changes after reviewer approval — re-triggering review',
);
} else {
// No code changes (false) or unable to determine (null) →
// finalize complete. Treating null as "no changes" prevents
// infinite DONE↔DONE loops when source_ref is from a different
// repo or the workspace has no matching ref.
updatePairedTask(taskId, {
status: 'completed',
completion_reason: 'done',
updated_at: now,
});
logger.info(
{ taskId, summary: args.summary?.slice(0, 100) },
{ taskId, hasNewChanges, summary: args.summary?.slice(0, 100) },
'Owner finalized after reviewer approval — task completed',
);
return;
}
// Owner made changes after approval → needs re-review
logger.info(
{
taskId,
sourceRef: task.source_ref,
hasNewChanges,
},
'Owner made changes after reviewer approval — re-triggering review',
);
}
}