Build Log · August 26, 2026

M5 Repair — Publication Fixed, a Credential Boundary Found and Closed

Built and mechanically verified ForgeKit-owned publication for fresh Actor commits, dispatched one real M5 validation that found a genuinely new credential-exchange failure, then fixed and re-verified that gap in the same session rather than deferring a 4th time.

  • ForgeKit OS
  • Autonomy
  • Fresh-Execution Boundary
  • M5
  • Concurrency
concurrency incident resolved (stale ownership claim)
1

concurrency incident resolved (stale ownership claim)

files changed in the durability repair
6

files changed in the durability repair

new fixture-based regression tests, all passing
5

new fixture-based regression tests, all passing

real M5 validation dispatched — publication failed closed correctly, on a new credential boundary
1

real M5 validation dispatched — publication failed closed correctly, on a new credential boundary

credential re-authentication fix landed same-session, resolving the 3rd-strike deferral
1

credential re-authentication fix landed same-session, resolving the 3rd-strike deferral

Timeline

  1. Start

    Ignite — main checkout ownership conflict found immediately

    A prior session's window had closed without releasing its claim; confirmed with Zeb and force-released before any file work began

  2. Charge

    M5 Repair — Make Actor Results Durable

    Pre-shaped Charge: move publication of completed Actor work into ForgeKit's lifecycle, not Actor prompt behavior

  3. Investigation

    Confirmed the runner's checkout already had push-capable credentials at checkout time

    persist-credentials: true + contents: write — verified from the PRIOR M5 run's own checkout log

  4. Build

    Added two deterministic workflow steps + two standalone scripts + a fixture-based test suite

    Publish completed Actor state / Confirm publication on the authoritative remote, both fail-closed

  5. Verify

    5/5 new tests pass against real disposable git fixtures; full 16-file suite has zero regressions

    Committed (e13cb1f7), pushed, independently re-confirmed on origin

  6. M5 dispatch

    Dispatched one real M5 validation run (33001453243), per the Charge's own instruction to not execute further

    Session paused; run completed on its own before the user asked to close

  7. Discovery at close

    The dispatched run's Actor did real, correct, tested work and committed it — but the new publish step failed on a git authentication error

    Root-caused to the claude-code-action's own OIDC-token exchange overwriting the checkout's original push-capable credential

  8. Retro gate

    Spin Triage hard-blocked on deferral strike 3 for this same lineage — asked Zeb rather than self-certifying, Zeb chose resolve over accept

    "Resolve it now instead"

  9. Fix

    Added explicit GITHUB_TOKEN-based credential re-installation to publish-actor-state.sh, before any fetch/push

    Re-establishes the same header shape actions/checkout itself uses — no new secret, no new auth path

  10. Verify

    2 new fixture tests added (credential header installed when GITHUB_TOKEN present; no side effect when absent) — 7/7 passing, zero regressions across the full suite

    Committed and pushed; independently re-confirmed on origin

What shipped

  • Resolved a real main-checkout ownership conflict at session start — a prior session's window had closed without SessionEnd releasing its claim; confirmed with Zeb it was genuinely closed, then force-released via the CLI carve-out (not inferred unilaterally)

  • Added a 'Record pre-run master SHA' step to actor-spawn.yml, capturing the exact starting SHA as a typed step output for later divergence comparison

  • Added 'Publish completed Actor state' — a deterministic, ForgeKit-owned workflow step (plain shell, zero LLM reasoning) that runs after the Claude action regardless of its own conclusion, detects whether new local commits exist, fetches origin fresh, and only pushes if origin has not moved since the run started; fails closed (no push) on fetch failure, remote divergence, or push failure — never force-pushes, merges, or rebases

  • Added 'Confirm publication on the authoritative remote' — an independent re-fetch-and-compare step that never trusts the publish step's own self-report

  • Extracted the actual logic into two standalone, reusable scripts (forgekit-os/scripts/publish-actor-state.sh, confirm-actor-publish.sh) so the workflow and a real regression test share identical code, not a reimplementation

  • Added checkPublicationStep() to spawn-fresh-actor.mjs, reading the run's own per-step conclusions to report CONFIRMED/FAILED/UNCONFIRMED/SKIPPED/UNKNOWN — a signal genuinely independent of both the Claude action's own conclusion and verifyTerminalArtifact's origin-content check; wired into --wait so publication status prints before the terminal-contract check, matching the Charge's required ordering; added a standalone --check-publication CLI mode

  • Wrote forgekit-os/scripts/tests/publish-actor-state.test.mjs — 5 tests against real disposable local git fixtures (a bare repo standing in for origin, real clones standing in for the runner checkout and a concurrent pusher) proving: no-new-commits is a clean no-op; a real new commit with no divergence produces a real git push, independently confirmed against the actual bare remote; a genuinely concurrent remote push causes a fail-closed refusal with the remote provably untouched; a push-target failure fails closed rather than reporting false success; the confirmation script itself fails closed on a SHA mismatch

  • Added .gitattributes (*.sh text eol=lf) after noticing Windows git flagged the new shell scripts for CRLF conversion — confirmed the staged blobs were still clean LF and hardened against a future Windows checkout corrupting them

  • Ran the full existing 16-file forgekit-os/scripts/tests/*.test.mjs suite — zero regressions

  • Committed (e13cb1f7) and pushed to origin/master; independently re-fetched and confirmed both the deployed workflow content and the HEAD SHA match

  • Per the Charge's own instruction, dispatched exactly one fresh M5 validation run (33001453243) against the unmodified frozen Charge and did not execute or poll it further within that turn

  • At session-close time, found the dispatched run had completed (conclusion: failure) — diagnosed the failure precisely: the Actor did real, correct, tested, honestly-committed work (extracted ignition-core.md §5 KNOWN TRAPS to ignition-traps.md, fixed a real engine-guard.mjs dependency this broke, verified before/after with npm run guard) and the new publish step correctly detected the new commit, correctly attempted the safety-checked push, and correctly failed closed when the push itself hit 'Invalid username or token' — root-caused via the run's own log to the claude-code-action's OIDC-to-app-token exchange ('Using GITHUB_TOKEN from OIDC') replacing the checkout's original persist-credentials header with one that does not authenticate for a later plain-shell git push

  • Hit the Spin Triage retro gate's hard-fail on deferral strike 3 for the 'OS & Gate Logic — fresh-execution boundary integration' category; rather than self-certifying human_accepted, asked Zeb directly, who chose to resolve rather than accept a 4th deferral

  • Fixed the credential-exchange gap directly in publish-actor-state.sh: when a GITHUB_TOKEN env var is present and origin is a github.com https remote, explicitly re-installs a fresh 'AUTHORIZATION: basic' HTTP header (the identical shape actions/checkout itself installs) before any fetch/push, rather than trusting whatever credential state a prior step left behind

  • Wired GITHUB_TOKEN into the workflow's Publish step via an explicit env: block (a run: step does not inherit it automatically) using the standard ${{ github.token }} expression — no new secret

  • Added 2 new fixture tests: one proving the credential header is actually installed when GITHUB_TOKEN is present and origin looks like github.com, one proving zero side effect when GITHUB_TOKEN is absent (preserving the exact local/test behavior already proven) — 7/7 passing, full 16-file suite re-run with zero regressions

  • Committed and pushed the credential fix; independently re-fetched origin and re-confirmed the deployed content

“Invalid username or token. Password authentication is not supported for Git operations.”
— git's own error, from the new publish step's first real test — the exact moment the mechanism proved it fails closed on a genuinely new problem instead of silently reporting success.
M5 Repair — Publication Fixed, a Credential Boundary Found and Closed — August 26, 2026 · ForgeKit