You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(orchestrator): prevent per-unit MR creation in discrete mode (#232)
* fix(orchestrator): prevent per-unit MR creation in discrete mode
Three interacting bugs caused agents to open one MR per unit instead of
one per stage:
1. mergeUnitWorktree left stale unit branches on remote after local
merge — agents saw them and opened redundant MRs
2. external_review_requested gave no branching guidance — agents had
to guess which branch to MR and guessed wrong
3. Discrete mode forced ALL gates to external, overriding review:auto
stages the studio author explicitly trusted to auto-advance
Fixes: clean up remote unit branches after merge, tell the agent
exactly which branch to MR (stage→main, ONE MR), and let discrete
mode affect branching strategy without overriding review semantics.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: fix biome formatting on template literal
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(orchestrator): VCS-aware instructions and final delivery PR/MR
Agent-facing instructions now respect the storage provider:
- intent_complete: in git mode, instructs agent to open ONE MR from
haiku/{slug}/main to project mainline for final delivery; in
filesystem mode, just reports completion
- external_review_requested: branch-specific MR instructions gated
behind isGitRepo(), with neutral fallback for filesystem mode
- Review subagents: git diff step gated behind isGitRepo(), uses
getMainlineBranch() instead of hardcoded "main"
- start_units announcement: "worktree" language only in git mode
- Subagent commit instructions: explicit isGitRepo() guard
- awaiting_external_review: removed git implementation details
- Tool descriptions (haiku_review, haiku_repair): VCS-neutral
- external_review_url schema: removed "PR, MR" framing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(orchestrator): remove stale comment about non-discrete mode
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@@ -3293,7 +3290,7 @@ function buildRunInstructions(
3293
3290
)
3294
3291
for(const[name,content]ofObject.entries(agents)){
3295
3292
sections.push(
3296
-
`#### Subagent: \`${name}\`\n\n<subagent tool="Task">\n## Adversarial Review: ${name}\n\nYou are the "${name}" review agent for stage "${stage}" of intent "${slug}".\n\n## Your Mandate\n\n${content}\n\n## Instructions\n\n1. Run \`git diff main...HEAD\` to get the current diff\n2. Read the stage's output artifacts in \`.haiku/intents/${slug}/stages/${stage}/\`\n3. Review through your mandate's lens\n4. Report findings as: severity (HIGH/MEDIUM/LOW), file, line, description\n5. HIGH findings MUST be fixed before the stage can advance\n</subagent>\n`,
3293
+
`#### Subagent: \`${name}\`\n\n<subagent tool="Task">\n## Adversarial Review: ${name}\n\nYou are the "${name}" review agent for stage "${stage}" of intent "${slug}".\n\n## Your Mandate\n\n${content}\n\n## Instructions\n\n${isGitRepo() ? `1. Run \`git diff ${getMainlineBranch()}...HEAD\` to get the current diff\n2. Read the stage's output artifacts in \`.haiku/intents/${slug}/stages/${stage}/\`\n3. Review through your mandate's lens\n4. Report findings as: severity (HIGH/MEDIUM/LOW), file, line, description\n5. HIGH findings MUST be fixed before the stage can advance` : `1. Read the stage's output artifacts in \`.haiku/intents/${slug}/stages/${stage}/\`\n2. Review through your mandate's lens\n3. Report findings as: severity (HIGH/MEDIUM/LOW), file, line, description\n4. HIGH findings MUST be fixed before the stage can advance`}\n</subagent>\n`,
3297
3294
)
3298
3295
}
3299
3296
}
@@ -3324,9 +3321,16 @@ function buildRunInstructions(
3324
3321
}
3325
3322
3326
3323
case"intent_complete": {
3327
-
sections.push(
3328
-
`## Intent Complete\n\nAll stages are done for intent "${slug}". The orchestrator has marked it as completed.\n\n### Instructions\n\nReport completion summary. Suggest /haiku:gate-review then PR creation.`,
3329
-
)
3324
+
if(isGitRepo()){
3325
+
constmainline=getMainlineBranch()
3326
+
sections.push(
3327
+
`## Intent Complete\n\nAll stages are done for intent "${slug}". The orchestrator has marked it as completed.\n\n### Instructions\n\n1. Report completion summary to the user\n2. Open ONE merge request from branch \`haiku/${slug}/main\` to \`${mainline}\` for final delivery\n3. Include the H·AI·K·U browse link in the description so reviewers can see the intent, units, and knowledge artifacts\n4. Record the review URL via \`haiku_run_next { intent: "${slug}", external_review_url: "<url>" }\``,
3328
+
)
3329
+
}else{
3330
+
sections.push(
3331
+
`## Intent Complete\n\nAll stages are done for intent "${slug}". The orchestrator has marked it as completed.\n\n### Instructions\n\nReport completion summary to the user.`,
3332
+
)
3333
+
}
3330
3334
break
3331
3335
}
3332
3336
@@ -3413,7 +3417,7 @@ function buildRunInstructions(
3413
3417
externalUrl
3414
3418
? `The stage is awaiting external review at: ${externalUrl}`
3415
3419
: "The stage is awaiting external review but no review URL has been recorded."
3416
-
}\n\nThe orchestrator checks for approval automatically (branch merge detection + URL-based CLI probing). Neither detected approval yet.\n\nInform the user that the stage is waiting on external review. After the review is approved, run \`/haiku:pickup\` to continue.`,
3420
+
}\n\nThe orchestrator checks for approval automatically. Neither detected approval yet.\n\nInform the user that the stage is waiting on external review. After the review is approved, run \`/haiku:pickup\` to continue.`,
"URL where stage was submitted for external review (PR, MR, etc.)",
3560
+
description: "URL where stage was submitted for external review",
3558
3561
},
3559
3562
},
3560
3563
required: ["intent"],
@@ -3940,8 +3943,9 @@ export async function handleOrchestratorTool(
3940
3943
intent: slug,
3941
3944
stage,
3942
3945
feedback: reviewResult.feedback,
3943
-
message:
3944
-
"External review requested. Submit the work for review through your project's review process (PR, MR, review board, etc.). Include the H·AI·K·U browse link in the description so reviewers can see the intent, units, and knowledge artifacts. Record the review URL via haiku_run_next { intent, external_review_url }. Run /haiku:pickup again after approval.",
3946
+
message: isGitRepo()
3947
+
? `External review requested. Open ONE merge request from branch 'haiku/${slug}/${stage}' to 'haiku/${slug}/main'. Do NOT open separate MRs for individual units — all unit work is already merged into the stage branch. Include the H·AI·K·U browse link in the description so reviewers can see the intent, units, and knowledge artifacts. Record the review URL via haiku_run_next { intent, external_review_url }. Run /haiku:pickup again after approval.`
3948
+
: `External review requested. Submit the work for review through your project's review process. Record the review URL via haiku_run_next { intent, external_review_url }. Run /haiku:pickup again after approval.`,
"Runs a git diff against main/upstream and returns formatted pre-delivery code review instructions with diff, stats, review guidelines, and review-agent config.",
2287
+
"Returns formatted pre-delivery code review instructions with diff, stats, review guidelines, and review-agent config.",
"Scan intents for metadata issues and auto-apply safe fixes. In a git repo, the default behavior is to scan ALL `haiku/<slug>/main` intent branches sequentially via temporary worktrees, auto-apply safe fixes (overlong title trim, legacy field renames, missing defaults, studio alias migration), commit and push the fixes to each branch, and open a PR/MR back to mainline if the branch was already merged. Pass `intent` to repair a single intent in the current working directory only. Pass `skip_branches: true` to force cwd-only mode in a git repo. Pass `apply: false` to scan without applying fixes.",
2347
+
"Scan intents for metadata issues and auto-apply safe fixes. In a git repo, scans all intent branches sequentially, auto-applies safe fixes, syncs changes, and opens PRs/MRs for already-merged branches. In filesystem mode, scans intents in the current working directory. Pass `intent` to repair a single intent only. Pass `skip_branches: true` to force cwd-only mode in a git repo. Pass `apply: false` to scan without applying fixes.",
0 commit comments