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
LIST 1. Design the mechanics for a GitHub Actions workflow, present in every fleet repo, that runs ALL formatters on main and auto-commits the resulting diff to main.
Questions to answer: (a) token strategy — the default GITHUB_TOKEN may not trigger downstream checks on its pushes; what per-repo secret/App token works fleet-wide and how is it provisioned per repo? (b) infinite-loop guard — a GitHub variable vs checking the previous commit's message/title; which is robust when the format commit itself produces a further diff? (c) concurrency — cancel-in-progress so a newer push supersedes a running format job instead of racing merges. (d) failure behaviour — what happens when the formatter diff conflicts or CI on the format commit goes red?
Program: Drew's 2026-10-28 directive (full text: hatch-personal memory/topics/id-program-2026-10-28.md).
Working pattern: parallel investigations, then the named synthesis issue merges them into a full design. Route guidance: Workhorse by default; Specialist/Summit for synthesis and ramification-heavy work. A result that says "done" is not the endpoint — the orchestrator reviews it and may commission another round. Deliverables: a markdown design/investigation doc (mermaid/SVG diagrams welcome) linked from this issue, plus follow-up issues for anything buildable. Build a proof of concept where the design calls for one, but do NOT build the permanent feature on top of an unreviewed PoC.
Triage input from #1997 (mcpx testing: format.yaml auto-format), triaged 2026-10-29 (queue task 2906) — the mcpx-side facts you need, so the PoC does not re-derive them:
A blocking format check already exists in this repo:.github/workflows/nix-ci.yml:4-12,29-60 — job treefmt ("treefmt check"), runs on both pull_request and push: [main], and checks only the changed files of the diff (git diff --name-only "$base...$GITHUB_SHA" → nix run .#format-check). base_sha comes from github.event.pull_request.base.sha || github.event.before, with an all-zeros fallback to HEAD^.
No autofix workflow exists anywhere in .github/workflows/ (no format*/*fix*), so a formatting diff that reaches main turns the check red and nothing repairs it.
No branch protection and no rulesets (/branches/main/protection unset, /rulesets → []), so a GITHUB_TOKEN push to main would succeed today and break the day protection is enabled. Nothing currently pushes formatting.
Ordering conflict to decide first: if the auto-fix commits to main, the main-side treefmt check must not be able to block the repair it needs — otherwise "fix only when CI is green" can never fire, because whenever CI is green the tree is already formatted (analysis in mcpx testing: format.yaml -- auto-format after a green run; PR head vs main #1997, "The conflict to resolve first", option 1). Note the same reasoning applies whether the gate reads the check job or the whole run.
What the autofix actually earns in this repo is drift that bypasses a PR: a formatter version bump in flake.lock, a direct push, or a merge that skipped the hook — PRs already get a blocking gate, so a per-PR autofix push is optional rather than the main value.
Full analysis: #1997 (comment) (this is the mcpx-side input to #2014/#2015; #1997 stays open pending their decision rather than growing a second workflow).
Top priority — ID program wave-1. Drew directed this be picked up in the next runs (2026-10-29): enqueued directly as triage task 3335 in repo-health-code-pilot at queue priority 20 (only breakage-class work at priority 10 outranks it). Wave-1 is the ungated investigations and designs; syntheses and PoCs stay gated on their named inputs. Investigation route: Workhorse.
Task: Investigate investigate: fleet-wide format auto-fix workflow — push token, loop guard, concurrency #2014 (ID program wave-1, LIST 1): design the mechanics for a fleet-wide format auto-fix workflow (all formatters on main, auto-commit the diff to main) answering (a) token strategy, (b) infinite-loop guard, (c) concurrency, (d) failure behaviour — grounded in the fleet's actual current workflows, with a design doc linked from this issue and follow-on work routed.
Expectation: investigation verdict + design doc + follow-up routing posted this shift; no permanent feature built on an unreviewed PoC.
No fleet-wide format auto-fix exists. code has only the treefmt check (nix-ci.yml, changed files, contents: read); opencode and dezren39/nix have no auto-fix workflow (nix does carry a root treefmt.toml). The building blocks all exist in-fleet: code's mod-tidy.yml already auto-commits to main, and openchamber's nix-hashes.yml already runs an App-token bake bot.
The four answers (full reasoning in the design doc)
(a) Token — GitHub App token, fleet standard. Minted per run (actions/create-github-app-token), scoped to contents: write. Decisive reason: pushes made with the default GITHUB_TOKEN trigger no downstream workflows, so a format commit would land on main unverified (and is rejected outright where required checks gate main). The App's pushes get full CI; the token is short-lived, single-permission, per-repo revocable. This is openchamber's proven pattern (incl. its persist-credentials: false lesson — a persisted GITHUB_TOKEN shadows the App token and 403s). PATs rejected (standing, broad, person-tied). GITHUB_TOKEN stays acceptable only for trivially-safe mechanical commits — mod-tidy's exact case. Provisioning: install one fleet App per repo + org/repo secrets + ruleset bypass actor, else the bake-bot auto-PR fallback.
(b) Loop guard — layered; the either/or is a false choice. L1 actor/subject skip (head commit is the bot's [format] commit → exit; a variable cannot express "the previous commit was mine"). L2 idempotence — the load-bearing backstop: a converged tree yields no diff, no commit, no push (what mod-tidy already survives on). L3 consecutive-commit cap: if the format commit itself produces a further diff (non-idempotent/fighting formatters — a bug, not a loop to feed), refuse a third consecutive bot commit, fail, and summon a human via the standing issue. A repo variable FORMAT_AUTOFIX_ENABLED is included as a kill switch — that's what variables are for; they are not the guard.
(d) Failure behaviour — all-or-nothing, visible, never silently reverted. Any formatter error → no commit (never a half-formatted tree). Rebase conflict → abort push, update one standing "format auto-fix: debt and failures" issue (also the target for L3 trips and repeat crashes). CI red on the format commit is a normal main breakage — the repos' main-broken watchers surface it; remedy is revert or fix-forward by a human/agent, never auto-revert (red may be a real defect the formatter exposed).
Routing
PoC implementation in developing-today/code only enqueued as queue task 3374 (workflow landed with the kill switch off; verification sequence on main once App provisioning exists, else the exact blocked remainder is recorded). Fleet rollout (opencode, openchamber, nix) is a separate follow-up after PoC review — no permanent feature on an unreviewed PoC. Open items for the reviewer are named in the doc: reuse-vs-dedicated App is Drew's call; per-repo ruleset state decides direct-push vs auto-PR fallback at rollout.
Fresh check this shift: issue #2014 is OPEN, labelled status/blocked + queue/blocked + priority/high — no hard-stop labels, and no in-flight session in its recent notes. Latest notes are from 2026-10-29: the investigation was completed under task 3335 (all four questions decided, design doc linked, PoC routed), and the PoC task 3374 was then blocked as a packet defect — "premise superseded by auto-format.yml already on main" (note 6496196151). The claimant should re-verify that supersession at current main and drive issue #2014 to its terminal decision from there.
🤖 Agent note · triaged → closing COMPLETED: the investigation is delivered and its output is consumed (also resolving the 2026-10-29 "needs a decision" block)
The deliverable was an investigation answering four mechanics questions for a fleet-wide "format on main, auto-commit the diff" workflow. That was delivered on 2026-10-29 (task 3335):
Design doc:files/designs/code-format-auto-fix-workflow.md (goal workspace), linked from this issue.
(a) token: GitHub App token, because GITHUB_TOKEN pushes trigger no downstream checks.
(b) loop guard: layered — actor/subject skip + idempotence as the load-bearing backstop + consecutive-commit cap + a kill-switch variable.
The decision this block was waiting for (settled here, fresh state 2026-11-03, maind3476bce7)
Accept the landed auto-format.yml as the PoC's de-facto implementation, and reconcile the design to it. This is no longer a near-miss frozen at merge time — it has been iterated three times since, each iteration reasoned in the workflow header:
3121df72d — 15-minute schedule instead of a push trigger (Drew, 2026-11-02: push-triggered runs starved their own concurrency group; three cancelled runs in a row while drift accumulated).
Deliberate divergences from the design doc, recorded here so nobody re-litigates them as defects:
Design doc
As-built
Why settled
Fleet GitHub App token
repo-scoped fine-grained PAT (REPO_AUTOMATION_TOKEN)
Single repo, single purpose; the App's decisive advantage (downstream CI on the push) is met by the PAT, and the fleet-App provisioning question stays with rollout (#2230), not the PoC
per-ref concurrency, cancel true
one group, cancel false + AUTO_FORMAT_LAST_SUCCESS_SHA
A fixer's input is a tree state, not a run; cancelling a pass mid-diff was the bug, and the variable makes a stale queued pass a no-op
full-tree pass
changed files since last success, 25 h fallback
Cheaper per run; correctness rests on the schedule cadence, not the range
kill switch, L3 cap, standing failure issue
none of the three
Now optional hardening, not blockers: the trigger is scheduled (not push-chained), and idempotence is the loop guard. Revisit only if #4787 shows a real loop
Where the remaining work actually lives (do not duplicate it here)
Policy of record: .github/ci-policy.md §"Formatting is not a merge gate" documents the auto-fix-on-main behaviour this issue asked to design.
Why close rather than keep open
An investigation whose questions are answered, whose design has been reconciled to a landed and maintained implementation, and whose residuals are each owned by a live issue has no remaining work in this issue. Leaving it OPEN under status/blocked is the exact label/queue desync the coverage pass is trying to clean up. Reopen if#2015 or #4787 concludes the mechanics must be revisited.
Labels: cleared queue/queued, queue/blocked, status/blocked (stale); closing as completed.
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 8465 (small_fix, queued, priority 40) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03
Activity
developing-today commentedon Oct 29, 2026
CODE-935
dezren39 commentedon Oct 29, 2026
Parent epic: #2055 — fleet expansion & placement program (2026-10-28 directive).
dezren39 commentedon Oct 29, 2026
Triage input from #1997 (mcpx testing:
format.yamlauto-format), triaged 2026-10-29 (queue task2906) — the mcpx-side facts you need, so the PoC does not re-derive them:.github/workflows/nix-ci.yml:4-12,29-60— jobtreefmt("treefmt check"), runs on bothpull_requestandpush: [main], and checks only the changed files of the diff (git diff --name-only "$base...$GITHUB_SHA"→nix run .#format-check).base_shacomes fromgithub.event.pull_request.base.sha || github.event.before, with an all-zeros fallback toHEAD^..github/workflows/(noformat*/*fix*), so a formatting diff that reachesmainturns the check red and nothing repairs it./branches/main/protectionunset,/rulesets→[]), so aGITHUB_TOKENpush tomainwould succeed today and break the day protection is enabled. Nothing currently pushes formatting.main, the main-sidetreefmt checkmust not be able to block the repair it needs — otherwise "fix only when CI is green" can never fire, because whenever CI is green the tree is already formatted (analysis in mcpx testing: format.yaml -- auto-format after a green run; PR head vs main #1997, "The conflict to resolve first", option 1). Note the same reasoning applies whether the gate reads the check job or the whole run.flake.lock, a direct push, or a merge that skipped the hook — PRs already get a blocking gate, so a per-PR autofix push is optional rather than the main value.Full analysis: #1997 (comment) (this is the mcpx-side input to #2014/#2015; #1997 stays open pending their decision rather than growing a second workflow).
dezren39 commentedon Oct 29, 2026
Top priority — ID program wave-1. Drew directed this be picked up in the next runs (2026-10-29): enqueued directly as triage task 3335 in repo-health-code-pilot at queue priority 20 (only breakage-class work at priority 10 outranks it). Wave-1 is the ungated investigations and designs; syntheses and PoCs stay gated on their named inputs. Investigation route: Workhorse.
dezren39 commentedon Oct 29, 2026
🤖 Agent note · picked up
dezren39 commentedon Oct 29, 2026
🤖 Agent note · investigation complete — all four questions decided, design doc linked, PoC routed
files/designs/code-format-auto-fix-workflow.mdin the keep-the-four-repos-healthy goal workspace (investigate: fleet-wide format auto-fix workflow — push token, loop guard, concurrency #2014 investigation, LIST 1)Premise verified
No fleet-wide format auto-fix exists. code has only the treefmt check (
nix-ci.yml, changed files,contents: read); opencode and dezren39/nix have no auto-fix workflow (nix does carry a roottreefmt.toml). The building blocks all exist in-fleet: code'smod-tidy.ymlalready auto-commits to main, and openchamber'snix-hashes.ymlalready runs an App-token bake bot.The four answers (full reasoning in the design doc)
actions/create-github-app-token), scoped tocontents: write. Decisive reason: pushes made with the defaultGITHUB_TOKENtrigger no downstream workflows, so a format commit would land on main unverified (and is rejected outright where required checks gate main). The App's pushes get full CI; the token is short-lived, single-permission, per-repo revocable. This is openchamber's proven pattern (incl. itspersist-credentials: falselesson — a persisted GITHUB_TOKEN shadows the App token and 403s). PATs rejected (standing, broad, person-tied). GITHUB_TOKEN stays acceptable only for trivially-safe mechanical commits — mod-tidy's exact case. Provisioning: install one fleet App per repo + org/repo secrets + ruleset bypass actor, else the bake-bot auto-PR fallback.[format]commit → exit; a variable cannot express "the previous commit was mine"). L2 idempotence — the load-bearing backstop: a converged tree yields no diff, no commit, no push (what mod-tidy already survives on). L3 consecutive-commit cap: if the format commit itself produces a further diff (non-idempotent/fighting formatters — a bug, not a loop to feed), refuse a third consecutive bot commit, fail, and summon a human via the standing issue. A repo variableFORMAT_AUTOFIX_ENABLEDis included as a kill switch — that's what variables are for; they are not the guard.cancel-in-progress: true, deliberately opposite CI: push-to-main verification runs share one cancellable group — 11 of the last 18 id-check main runs were cancelled by the next merge #392. Verification runs are run_id-keyed so no merge's verification is ever cancelled; a fixer's input is a tree state, and a run formatting a stale SHA is worse than wasted (its push races). Push protocol completes the safety: non-force push; on rejection, fetch + rebase + re-run formatters + retry ≤2, then fail.main-brokenwatchers surface it; remedy is revert or fix-forward by a human/agent, never auto-revert (red may be a real defect the formatter exposed).Routing
PoC implementation in developing-today/code only enqueued as queue task 3374 (workflow landed with the kill switch off; verification sequence on main once App provisioning exists, else the exact blocked remainder is recorded). Fleet rollout (opencode, openchamber, nix) is a separate follow-up after PoC review — no permanent feature on an unreviewed PoC. Open items for the reviewer are named in the doc: reuse-vs-dedicated App is Drew's call; per-repo ruleset state decides direct-push vs auto-PR fallback at rollout.
8 remaining items
dezren39 commentedon Nov 3, 2026
🤖 Agent note · handed off
opencode; the laptop claimant launches the bound opencode session, which drives task 7456 to its terminal stateFresh check this shift: issue #2014 is OPEN, labelled
status/blocked+queue/blocked+priority/high— no hard-stop labels, and no in-flight session in its recent notes. Latest notes are from 2026-10-29: the investigation was completed under task 3335 (all four questions decided, design doc linked, PoC routed), and the PoC task 3374 was then blocked as a packet defect — "premise superseded by auto-format.yml already on main" (note 6496196151). The claimant should re-verify that supersession at current main and drive issue #2014 to its terminal decision from there.dezren39 commentedon Nov 3, 2026
🤖 Agent note · triaged → closing COMPLETED: the investigation is delivered and its output is consumed (also resolving the 2026-10-29 "needs a decision" block)
repo-worker-code, OpenChamber scheduled lane (queue task 7456, coverage-pass triage)What this issue asked for, and where it landed
The deliverable was an investigation answering four mechanics questions for a fleet-wide "format on main, auto-commit the diff" workflow. That was delivered on 2026-10-29 (task 3335):
files/designs/code-format-auto-fix-workflow.md(goal workspace), linked from this issue.GITHUB_TOKENpushes trigger no downstream checks.cancel-in-progress: true.packet_defectbecause.github/workflows/auto-format.ymlhad already landed via PR ci: name the PR tier basic, state the merge requirement, replace Auto Assign with the repo sweeper (#1781) #2148 and the block asked for a decision: accept the landed workflow as the PoC, or amend it toward the design.The decision this block was waiting for (settled here, fresh state 2026-11-03,
maind3476bce7)Accept the landed
auto-format.ymlas the PoC's de-facto implementation, and reconcile the design to it. This is no longer a near-miss frozen at merge time — it has been iterated three times since, each iteration reasoned in the workflow header:3121df72d— 15-minute schedule instead of a push trigger (Drew, 2026-11-02: push-triggered runs starved their own concurrency group; three cancelled runs in a row while drift accumulated).d5c18e992— record success on the workflow-only exit path (ci(auto-format): workflow-only exit never records success — LAST_SUCCESS_SHA stalls and every 15-min run re-diffs the same range #4752).df09437df— push and record success withREPO_AUTOMATION_TOKEN, a repo-scoped fine-grained PAT, precisely becauseGITHUB_TOKENcannot write repository variables and cannot push workflow files (fix(ci): auto-format push is rejected when the format diff touches workflow files (PR #2148) #3118), and its pushes do trigger downstream checks.Deliberate divergences from the design doc, recorded here so nobody re-litigates them as defects:
REPO_AUTOMATION_TOKEN)AUTO_FORMAT_LAST_SUCCESS_SHAWhere the remaining work actually lives (do not duplicate it here)
status/in-progress+ claimed, updated 2026-11-03T14:57Z). That is the PoC/replication home.df09437dfPAT change already addresses its token half. That is the operational-defect home..github/ci-policy.md§"Formatting is not a merge gate" documents the auto-fix-on-main behaviour this issue asked to design.Why close rather than keep open
An investigation whose questions are answered, whose design has been reconciled to a landed and maintained implementation, and whose residuals are each owned by a live issue has no remaining work in this issue. Leaving it OPEN under
status/blockedis the exact label/queue desync the coverage pass is trying to clean up.Reopen if #2015 or #4787 concludes the mechanics must be revisited.
queue/queued,queue/blocked,status/blocked(stale); closing as completed.files/designs/code-format-auto-fix-workflow.mddeveloping-today commentedon Nov 3, 2026
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 8465 (small_fix, queued, priority 40) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03