* feat(ci): make post-repair revalidation opt-in A CI repair used to restart the whole pipeline at Review, so every repaired check cost another full Review, Test, Document, Lint, Push, and PR pass over the change. That is the most expensive single behavior the pipeline has, and it was unconditional. ci.revalidate_repairs selects between the two deliveries. It defaults to false: the repair is published immediately through publishRunHead - the same guarded path the Push step uses, so review-approved-head continuity, the force-with-lease anchor, remote verification, the push binding, and the gate-mirror update all still apply - and the CI monitor keeps watching the same run. Set true to keep the repair local, revoke the run's review approval, and restart validation at Review so no CI repair is published without having been reviewed. The key lives in the existing ci block, so it inherits that block's global config, trusted-default-branch-only sourcing, and repo-overrides-global precedence with no new mechanism. It is a *bool so an explicit project false overrides a global true rather than reading as unset. Both CI fix paths take the same decision: the automatic auto-fix round and the manual round a person authorizes at the CI gate. No-change retries, the durable fix-attempt budget, duplicate-check suppression, transient reruns, merge-conflict handling, force-push safety, custody, and cancellation are untouched. The CI step logs which policy is in force before its first poll. VISION.md gains the constraint this default follows from: cost is a user-visible property of the gate, so a design that clearly adds significant end-to-end latency or token consumption must be opt-in. * no-mistakes(review): Preserve CI repair continuity across rebases * no-mistakes(document): Correct stale CI repair documentation * no-mistakes(ci): Fixed late gate-mirror failures misreporting published CI repairs. Published repairs now continue CI monitoring with a warning after durable remote binding, while Push-step mirror failures still propagate. Added regression coverage. Verified targeted race tests, rebase tests, make lint, and git diff --check * no-mistakes(document): Document late gate-mirror failure handling * fix(ci): decide repair publication by provable continuity A CI repair was published whenever ci.revalidate_repairs was off, and a merge-conflict repair rebases, so its head is not a descendant of the reviewed head. The publication guard was relaxed for that case with a base-ancestry exception, and a repair that reset to the rebase base satisfied it: reproduced, the reviewed commits were force-pushed away while the pipeline reported success. The actor was the CI repair agent itself, so provenance cannot stand in for the proof either. One rule now decides delivery on every CI-fix path, automatic and manual, CI failure and merge conflict alike: a repair is published without revalidating only when its continuity with the reviewed, published head can be PROVEN; when it cannot, the repair revalidates from Review. Continuity is proven when the repaired head is the run's durable review-approved commit or a descendant of it, read through the same reviewApprovedHead accessor the publication guard enforces, so the decision to publish and the guard that permits the push cannot disagree. Every failure to establish it - unreadable run, missing or malformed approval, unverifiable ancestry - counts as unproven. ci.revalidate_repairs still sets the intent identically on every path: false publishes when it is provable, true revalidates outright. Merge-conflict repairs are not carved out; they simply always land in the cannot-be-proven half, because resolving a conflict changes the commit's patch-id and no content-based guard can separate a resolved rebase from a dropped one. They now revalidate rather than being refused, so conflict repair keeps working. The base-ancestry exception and its rewriteBase plumbing are deleted; assertReviewApprovedPushHead is descendant-only again with no exception. Regressions: a genuine conflict rebase revalidates and succeeds; a reset-to-base conflict repair revalidates, never reaches the remote, and the reviewed work survives; an ordinary provable repair still publishes with the flag off and still restarts with it on; a run with no review authority revalidates rather than publishing. * no-mistakes(review): Correct merge-conflict revalidation guidance across all surfaces * no-mistakes(document): Correct CI repair revalidation documentation * no-mistakes(lint): Regenerate no-mistakes skill documentation * fix(push): record a publication only once all of it has settled The gate-mirror update ran after the push binding and the recorded head, which forced a choice between two wrong answers on a mirror failure. Returning the error made the CI monitor call an already published repair failed, and its next attempt then saw a clean, already-advanced head as producing no changes. Swallowing the error left the gate behind the remote for good, and `no-mistakes rerun` resolves its starting head from the gate, so a later rerun silently omitted the published repair. Settle the gate mirror before recording anything durable. Publication is now all-or-nothing: remote push, gate mirror, push binding, and recorded head all land or none of them are recorded. A partial failure is simply retryable - the next attempt re-enters the same path, finds the remote already at this head via an up-to-date no-op push, and completes the publication once the mirror works. The CI-repair warning special case is gone with it. Also correct four surfaces that still said the default publishes every repair, when it publishes only a repair whose continuity is provable, and make the merge-conflict regression conflict for real: the base and the feature now edit the same line, so the resolved rebase genuinely changes the commit's patch-id rather than replaying cleanly. Regressions: an unsettled publication records nothing and the retry completes it; a real conflict rebase revalidates and succeeds; a reset-to-base conflict repair revalidates and the reviewed content survives on the remote. * no-mistakes(review): Make CI repair publication atomic and retryable * no-mistakes(document): Correct CI publication documentation * fix(ci): fire the unsettled-publication retry only on real evidence The retry added for a part-way publication triggered on any clean worktree whose HEAD differed from the run's recorded head. That is not evidence a publication was attempted: a fix agent that commits and then errors leaves exactly that state, and so does a fixture whose recorded head trails the branch. The retry then ran instead of the fix round and the repair agent was never called, which is what broke TestCIStep_BitbucketAutoFixUsesLivePRHeadSHAForLogs on CI. publishRepair now records the commit whose publication it began and could not finish, and clears it on success or when the repair revalidates instead. The retry fires only for that exact commit, so it still settles a stalled publication without spending another fix attempt, and never swallows a fix round. The marker is in memory only: after a daemon restart the next fix attempt settles it instead, at the cost of one attempt, which is the honest accounting rather than a durable claim the process cannot make. Regression: a differing head with no attempted publication still runs the fix agent and never logs the retry. * no-mistakes(review): Retry unsettled publications before evaluating CI checks * no-mistakes(document): Document CI publication retry evidence * fix(ci): bound the publication retry and order the revalidation write Two defects in the repair-publication path, both reported on the PR. The unsettled-publication retry costs no repair attempt by design, so a gate mirror that could never be settled retried on every poll until the CI idle timeout - seven days by default - while the repaired commit already sat on the remote. Bound it to three attempts, then park for a person with the published head named, because a rerun would resume from the stale gate head and omit the repair. CI is testing the published commit, so no fix agent can help; what a person needs is to know the local gate is behind. recordLocalRepair advanced the in-memory head before its durable write. A failed write left the monitor watching a head the run record did not know about, still carrying its old review approval, with the revalidation the call exists to trigger silently lost. Write durably first, then advance. Regressions: the retry stops at its bound and parks naming the published head while spending only one fix attempt; a failed revalidation write leaves both the live head and the review approval untouched. * no-mistakes(review): Persist and safely settle CI publication retries * no-mistakes(document): Clarify CI publication settlement documentation * no-mistakes(ci): Serialized the process-heavy CI repair fixture tests to prevent macOS subprocess exhaustion and indefinite fake-gh stalls. Verified with 3 repeated focused runs, 25 repetitions of the previously hanging case, and the full internal/pipeline/steps suite (passed in 113.6s) * test(ci): stop paying for a monitor loop to assert a delivery decision The macOS job timed out at the 600s package cap: the repair fixture tests each drove the full CI monitor loop, so every case spent provider polls and several subprocesses on a two-core runner to observe something commitRepair already reports. Serializing them made the wall clock worse, not better. Assert the delivery decision from commitRepair - Revalidate, the remote, the review approval, the push binding - and keep exactly one monitor-loop test for the wiring that is genuinely the monitor's: turning a held repair into a restart at Review and stating the policy in force. Four full monitor loops go away and the cases run in parallel again. Coverage is unchanged: every case still asserts the same observables, and the paths that are about the monitor - the fix round not being swallowed, the bounded publication retry - still drive Execute. * revert(ci): strip the unscoped publication-retry machinery Two things were added to this branch by auto-answered review findings that were never in its scope, and the captain has declined both. Removed, not repaired: - retryPendingRepair and its CI poll-loop call site, its bound, and its exhaustion gate. New runtime behaviour in the monitor. - The durable pending-publication state it needed: SetCIPendingPublication, the ci_pending_publish_head / ci_pending_publish_attempts columns and their migration, the StepResult fields, and the restore-on-CI-entry path. A persistence and schema addition. - publishRunHead's publicationProgress return, which existed only to tell that machinery whether the remote had been verified. Three reported defects went with the code that contained them rather than being fixed: a restored pending publication bypassed by a provider skip path, a marker write that could be lost, and a marker never consumed after a daemon restart. They are not reachable once the machinery is gone. Kept unchanged: the uniform provable-continuity rule, the corrected agent guidance and docs, the single-statement UpdateRunPublication, the reference docs that no longer describe the removed mirror warning, and the real merge-conflict regression. Tests that only exercised the removed machinery go with it. What survives still covers behaviour that survives, including that a partial publication records nothing and the next attempt completes it - which is the atomicity guarantee, not the retry. * no-mistakes(document): Deduplicate CI revalidation configuration guidance
8.3 KiB
Vision
no-mistakes exists so that one deliberate push means a change was independently validated before anyone else sees it.
It serves the individual developer - increasingly an operator of many coding agents - who produces changes faster than they can hand-validate, and it turns a rough local branch into a clean, evidence-backed PR while their attention goes elsewhere.
It owns exactly one thing: the gate between a local branch and the configured push target.
One gate, one meaning
The gate is opt-in and explicit: a named remote you push to on purpose, never a rewired origin or a trap door in normal Git behavior.
Pushing through the gate is the consent boundary: it authorizes that run to validate, apply reviewable fixes, push the branch, and raise the PR, and nothing else implies that consent.
"Passed the gate" must mean at least the same thing in every repo: the core pipeline's shape and order stay fixed, and a repository may add checks on top but never remove, reorder, or dilute the core.
Customization is welcome exactly as far as it strengthens what a pass means; no durable configuration, and no classifier's guess about a change's riskiness, may quietly weaken it.
A person may explicitly skip steps for one run; a standing rule may never skip them on anyone's behalf.
A gate that cannot run completely refuses loudly with guidance; it never degrades silently into a weaker check.
Efficiency never buys itself a skipped check: when a shortcut fails, the gate falls back to the slower correct path instead of skipping the validation.
Cost is a user-visible property of the gate, not an implementation detail: pipeline latency and total token spend are already among the first things users raise, so any design that clearly adds significant end-to-end latency or token consumption must be opt-in, or confined to the extremely rare cases where it is genuinely necessary.
The default path buys the strongest guarantee it can at a price a user will keep paying; a stronger guarantee that costs another full pass over the change is offered, never imposed.
Never lose work
The first law is that the tool must not lose people's code: not the author's commits, not out-of-band commits on the target, not fixes the pipeline itself created. When safety facts cannot be verified against fresh authoritative state, refuse the operation and surface a finding; a refused push is annoying, a lost commit is unforgivable. Force is never blind: every history-rewriting update must be anchored to what the run actually observed, and a failed verification fails closed. Work the pipeline holds must always have a safe path back into the user's custody, even after a crash, a cancellation, or a terminal run. Destructive lifecycle operations require explicit intent, protect other live work by default, and leave an attribution trail.
Judgment stays human, mechanics do not
The human owns intent, judgment calls, and the merge decision; by explicit opt-in the tool may perform a merge the human already decided to make, and convenience never becomes judgment transfer. Findings separate what is objectively fixable from what is genuinely the author's call, and an unclassifiable finding fails closed to the human. Every judgment has exactly one owner: when two mechanisms would judge the same question, they are reconciled into one, never stacked on top of each other. Changes that would contradict the author's stated intent park for a decision; they are never auto-resolved. Unattended operation is real and useful, but it is always explicit consent for a bounded scope, never a quiet default. Automation of judgment may expand only by explicit user opt-in as trust is earned, never by a silent default flip. The ambition is to shrink human attention per change toward the few decisions that genuinely need a human, not to remove the human from decisions that are theirs.
Independent, adversarial validation
Validation runs in a fresh context against the actual branch, never inside the authoring session, because an author is biased toward believing its own work is correct. Validation must not hold the author hostage: runs happen in disposable isolation so the working tree stays untouched and the next task can start immediately. Reviewer and fixer are separate roles with separate memory; the reviewer never inherits the fixer's rationale, and every review pass covers the complete change. The pipeline's own fixes are author code: a change the gate wrote is reviewed with the same independence as a change the author wrote, and a reviewer never certifies its own prescription. The author's intent, with its provenance, is part of what review checks the diff against; agent confidence is not evidence. The pushed branch is untrusted input: nothing on it may choose what executes with the owner's credentials, and gate agents never adopt the identity or instructions of the code under validation.
Evidence over confidence
Every verdict must be traceable to something inspectable: findings, executed tests, gathered evidence, and the history of what was fixed and how many attempts it took. A verdict is attributable: every run records the exact tool build and configuration that produced it, so a surprising outcome can always be traced to the software that made it. Evidence stays attached to the change without contaminating it: artifacts are durable and PR-visible, but the shipped branch's history is the author's change and nothing else. The gate does not define compliance: external systems do, and the gate's duty is to publish facts sufficient for any of them to derive its own verdict. An external repository policy may explicitly exempt a class of pull requests it does not route through no-mistakes, but that policy bypass must stay distinguishable from evidence that the gate passed and must never skip a step inside a no-mistakes run. The PR a run raises is written for a reviewer who was not there: what changed, what was checked, what the risks are, and what the pipeline had to fix. Run state must honestly distinguish working, parked waiting on a human, and dead; a stall that looks alive is a lie. Failure is a first-class outcome: loud, attributed, explained, and followed by a next action. Detailed operational data stays under the user's sole control: it may follow the same operator across their own machines, but anything that leaves their custody stays minimal and never becomes a scoreboard.
Humans and agents are both first-class users
The same gate serves a person at a terminal, a coding agent driving it programmatically, and a supervisor watching many runs; those surfaces share the same approval semantics and earn the same trust. The gate is agent-agnostic: it must work with whichever supported coding agent the user prefers and keep working when one vendor's tool fails. Model and effort choices belong to the user; any routing stays inspectable and user-configured, and the gate never silently swaps the intelligence doing the validation. No forge, host, or provider is privileged in the product's identity; breadth still follows real users with real problems rather than promising parity ahead of demand.
Scope and evaluation
no-mistakes is a local tool for the person whose credentials and accountability are on the line; runs happen on their machine, under their identity, at their initiative. It is not a CI system, not an agent orchestrator, not a code host, and not a team-governance platform; CI stays the shared outer gate, and merge policy belongs to the provider. Where a repository genuinely has no outer gate, the inner gate may take on more of that duty by the user's explicit choice. The gate assumes as little as possible about what a repository contains: code or not, a change is a change, and the gate's question is always whether it is safe to share. Every change to this repository must pass through its own gate; dogfooding is the first calibration loop, and field incidents become regression tests before they become memories. A change aligns when it catches more real mistakes earlier, cuts wall-clock or babysitting without moving judgment away from the human, serves the individual operator across everything they own, or strengthens a refusal path. Changes should be resisted when they weaken what a pass means, trade data safety for convenience, spend deep complexity on a niche workflow, freeze one vendor or model into the product's identity, or grow the gate into an always-on service the user did not ask for.