snapshot of https://github.com/marmelab/atomic-crm.git (main, 2026-09-18; blobs > 131072B omitted)
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
This commit is contained in:
69
.claude/hooks/force-foreground-orchestrator-dispatch.mjs
Executable file
69
.claude/hooks/force-foreground-orchestrator-dispatch.mjs
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env node
|
||||
// PreToolUse(Agent) - force the orchestrator's pipeline dispatches to run FOREGROUND.
|
||||
//
|
||||
// Root cause (transcript forensics + a probe): the VS Code extension defaults the Agent
|
||||
// tool to BACKGROUND, and a nested subagent (the orchestrator, spawnDepth >= 1) is NEVER
|
||||
// re-invoked when a background child completes. So a background dispatch from the
|
||||
// orchestrator ends its turn "to await a notification" that never comes - review / merge /
|
||||
// promotion never run and finished dev work is orphaned.
|
||||
// A probe confirmed explicit run_in_background:false DOES block (child output inline) while
|
||||
// the default is async; CLI defaults to foreground, so the bug only ever bit the extension.
|
||||
//
|
||||
// Enforcement (the prose guard in orchestrator.md was ignored): DENY any orchestrator->child
|
||||
// pipeline dispatch that is not explicitly run_in_background:false, forcing a re-dispatch
|
||||
// with false. Detection is by the CHILD role - only the orchestrator dispatches these - so
|
||||
// main->orchestrator (child=orchestrator) and the fire-and-forget documentator are never
|
||||
// touched. Fail-open: any error or unrecognized shape allows the dispatch.
|
||||
|
||||
import { readFileSync } from "node:fs";
|
||||
import { createHookContext } from "./lib/context.mjs";
|
||||
import { parseDispatch } from "./lib/dispatch-parse.mjs";
|
||||
import { pipelineRoleSet } from "./lib/teams.mjs";
|
||||
|
||||
// Pipeline roles whose result the orchestrator MUST consume in the same turn come
|
||||
// from harness.config.json (config.roles `pipeline` flag), so this set and the
|
||||
// one in block-duplicate-dispatch share one source. The orchestrator
|
||||
// (main->orchestrator hop) and documentator (fire-and-forget) are excluded
|
||||
// (pipeline:false): their background dispatch is correct.
|
||||
const PIPELINE_ROLES = pipelineRoleSet();
|
||||
|
||||
let input;
|
||||
try {
|
||||
input = JSON.parse(readFileSync(0, "utf8"));
|
||||
} catch {
|
||||
process.exit(0); // no / unparseable payload -> allow
|
||||
}
|
||||
|
||||
const ctx = createHookContext(input, "force-foreground-orchestrator-dispatch");
|
||||
|
||||
try {
|
||||
const d = parseDispatch(input);
|
||||
const childRole = PIPELINE_ROLES.has(d.subagentType)
|
||||
? d.subagentType
|
||||
: PIPELINE_ROLES.has(d.role)
|
||||
? d.role
|
||||
: "";
|
||||
|
||||
// Not an orchestrator->pipeline-child dispatch -> none of our business.
|
||||
if (!childRole) ctx.accept("not a pipeline dispatch");
|
||||
|
||||
// Read run_in_background RAW: parseDispatch coerces absent->false, but the difference
|
||||
// matters here - in the extension, ABSENT means the background default, which is the bug.
|
||||
// Only an EXPLICIT false is safe.
|
||||
const rib = input.tool_input?.run_in_background;
|
||||
if (rib === false) ctx.accept(`${childRole} foreground (explicit false)`);
|
||||
|
||||
ctx.block({
|
||||
reason:
|
||||
`Nested orchestrator dispatch of "${childRole}" must be FOREGROUND. A nested subagent ` +
|
||||
`is never re-invoked when a background child completes, so this dispatch would orphan ` +
|
||||
`the pipeline (review/merge/promotion never run). Re-dispatch it with ` +
|
||||
`run_in_background: false - verified to block and return the child's result inline in ` +
|
||||
`this runtime.`,
|
||||
log: `blocked ${childRole} rib=${rib === undefined ? "absent" : String(rib)}`,
|
||||
});
|
||||
} catch (e) {
|
||||
// Never let this gate break a real dispatch.
|
||||
ctx.log(`error, allowing: ${String(e).slice(0, 120)}`);
|
||||
process.exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user