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:
54
.claude/hooks/block-promote-unmerged.mjs
Executable file
54
.claude/hooks/block-promote-unmerged.mjs
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env node
|
||||
// PreToolUse(Agent) — block the session->main promotion while any developed-but-
|
||||
// unmerged task branch still exists. In the no-team flow the orchestrator tracks
|
||||
// each wave's tickets in its working context across a long synchronous turn; a
|
||||
// ticket can be lost between its developer's DONE and the REVIEW->MERGE
|
||||
// transition — its branch never merges into session/<short>, yet the orchestrator
|
||||
// believes the wave is done and dispatches the promotion merger, silently
|
||||
// dropping the work. This is the deterministic backstop.
|
||||
//
|
||||
// Behavioural counterpart: orchestrator STATE B's Promotion step reconciles
|
||||
// against disk before promoting, so in the normal case this never fires.
|
||||
|
||||
import { readFileSync } from "node:fs";
|
||||
import { createHookContext } from "./lib/context.mjs";
|
||||
import { parseDispatch } from "./lib/dispatch-parse.mjs";
|
||||
import { getUnmergedTaskBranches, git } from "./lib/git.mjs";
|
||||
import { simpleBranch, sessionBranch } from "./lib/topology.mjs";
|
||||
|
||||
const input = JSON.parse(readFileSync(0, "utf8"));
|
||||
const ctx = createHookContext(input, "block-promote-unmerged");
|
||||
const d = parseDispatch(input);
|
||||
|
||||
// Only gate the promotion-merger dispatch.
|
||||
if (d.subagentType !== "merger" || d.mode !== "promote") process.exit(0);
|
||||
|
||||
const short = ctx.sessionShort;
|
||||
const session = sessionBranch(ctx);
|
||||
|
||||
// No session branch yet → nothing to guard.
|
||||
if (
|
||||
git(["show-ref", "--verify", "--quiet", `refs/heads/${session}`]).status !== 0
|
||||
) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Task branches under refs/heads/<short>/ with commits not on the session branch.
|
||||
// <short>/simple is excluded: the single-shot rollback/migration round promotes it
|
||||
// straight to main, never into the session branch, so it is legitimately "ahead"
|
||||
// of session/<short> and must not block a wave promotion. Fails CLOSED — a
|
||||
// branch whose rev-list count can't be read is reported as unmerged.
|
||||
const unmerged = getUnmergedTaskBranches(short, session, [simpleBranch(ctx)]);
|
||||
|
||||
if (unmerged.length === 0) process.exit(0);
|
||||
|
||||
const describe = ({ branch, count }) =>
|
||||
` - ${branch} (${count === null ? "unmerged (count unavailable)" : `${count} unmerged commit(s)`})`;
|
||||
|
||||
ctx.fail(
|
||||
`Refusing to promote ${session} to the base branch — these task branches have commits NOT yet merged into the session branch:\n` +
|
||||
unmerged.map(describe).join("\n") +
|
||||
"\n" +
|
||||
"A ticket was developed but never merged (its reviewer/merger were likely never dispatched). For EACH branch above, drive its ticket through REVIEW -> MERGE (dispatch its quality-reviewer if needed, then its per-ticket merger) so its work lands on the session branch. Re-dispatch the promotion merger only once this list is empty.",
|
||||
{ log: `BLOCK unmerged=${unmerged.length}` },
|
||||
);
|
||||
Reference in New Issue
Block a user