ForgeKitFORGEKIT

Build Log

Gate Evidence Architecture — taxonomy, decision-record provenance fix, push gate

July 22, 2026

Completed all 4 nextItems from alloy-commit-gate-redesign-2026-07-21 in one session, then a post-build Crucible audit caught the new judgment-record primitive recreating the exact marker-wearing-a-necktie failure the session's own taxonomy was built to catch — fixed by separating decision provenance from decision wording quality, and separately caught two real security-relevant bugs (an escaped-quote bypass shared by commit and push's --no-verify check, and an incomplete push identity model) before closing.

OSGatesCrucibleTaxonomyProvenance
4
queued nextItems completed (taxonomy, model-drift fix, decision-record, push gate)
2
real security-relevant bugs found via post-build Crucible and fixed before close
46
real tests added/revised across 4 test files, all passing

What shipped

forgekit-os/gate-evidence-taxonomy.md (new — 9-dimension reusable classification template + disposition vocabulary)

forgekit-os/gate-evidence-classifications.md (new — all 6 Tier-1 gates + retro's clean-tree check classified against the taxonomy, with per-gate dispositions)

forgekit-os/scripts/arc/classify.mjs (gpt-4o → gpt-5.1-chat-latest, same model+param-retry fix crucible.mjs already used)

forgekit-os/scripts/skeptic.mjs (deleted — confirmed dead: 0 npm wiring, replaced by crucible.mjs per crucible-proposal.md, untouched since 2026-07-01, verified via full-repo search before deletion)

.claude/hooks/lib/decision-record.mjs (new — structured decision-claim primitive; REVISED mid-session after post-build Crucible found the original humanApproved boolean was self-authored-and-unverifiable — replaced with provenance: claude_authored | human_sourced + sourceRef + an explicit always-false mechanicallyVerified field, honestly naming that no hook yet captures real human approval)

.claude/hooks/tests/decision-record.test.mjs (new — 19 tests covering validation, provenance requirements, and a named/tested DELIBERATE non-fix for paraphrase-based rubber stamps)

.claude/hooks/pre-push-check.mjs (new — real Git pre-push hook; REVISED mid-session to bind identity to the full ref-update tuple — localRef/localSha/remoteRef/remoteSha/remoteName/remoteUrl — instead of commit-range-hash alone, after the audit named force-push/deletion/multi-ref/dual-remote gaps)

.claude/hooks/lib/marker.mjs (added computePushIdentity/writePushTranscript/checkPushTranscript — push's own identity model, revised mid-session per the audit)

.claude/hooks/gate-dispatch.mjs (push's anti-bypass backstop — checkPushGate, hasRealPushNoVerifyFlag; added shared stripQuotedSpans() helper, then fixed its own escaped-quote bug found via the audit)

.claude/hooks/gates.config.mjs (push gate given requirePushTranscript: true + its own design-rationale comment)

forgekit-os/scripts/install-git-hooks.mjs (extended to install both pre-commit AND pre-push hooks via a shared HOOKS array)

.claude/hooks/tests/push-gate.test.mjs (new — 11 real end-to-end scratch-repo tests including force-push, branch deletion, multi-ref push, and same-branch-different-remote)

.claude/hooks/tests/commit-gate.test.mjs (added 1 regression test for the escaped-quote fix, now 12 tests)

package.json (wired decision-record.test.mjs and push-gate.test.mjs into test:os)

My overall read... This was a strong implementation session that found real defects, but it is not ready to close yet... The judgment-record primitive still cannot prove that a human made the judgment. That is the central unresolved problem. Claude is currently treating it as a prose-quality problem. It is actually a provenance problem.

GPT, via npm run crucible:post — the post-build audit that caught decision-record.mjs's central design flaw before this retro was written