Skip to content

ADR 0094: Final lifecycle checks require clean trees

Vocabulary amendment: Current pointers use ratchetsstandards, finishdone, graduateaccept, integrateupdate, the retired product-category wording → discern, the gate, or the bar, the gate-pass artifact → the receipt, the shared-branch label → the trunk; the decision and reasoning are unchanged.

Status: accepted

Context

§

discern's lifecycle has two kinds of feedback:

  • fast iteration feedback, such as prepare, test, and targeted project commands, which is useful while a tree is still changing;
  • final lifecycle feedback, such as a recorded done pass, standards, and acceptance, whose answer only matters for the tree that will actually be handed off or landed.

Agents tended to blur those two modes. A common sequence was to run done on uncommitted work, receive a green result, commit afterward, and then ask acceptance to land the branch. The later commit changed the tree from the one done validated, so acceptance had to validate again. Standards had a similar failure mode: because they are intentionally slow and outside done, running them during ordinary dirty-tree iteration made repeat runs likely without improving confidence in the final branch.

Acceptance also had an older convenience path that WIP-committed uncommitted changes, removed the worktree, checked the branch out in the main checkout, and soft-reset the WIP commit so those changes landed staged. That preserved bytes, but it made acceptance both a final lifecycle operation and an implicit dirty-tree transport mechanism.

Decision

§

Final lifecycle operations now prefer a clean, committed tree:

  • done still may be run on dirty work, but a dirty green run records no gate receipt and hints that agents should use prepare or test while iterating, then commit and run done again on the clean HEAD.
  • status reports the current gate receipt state and only gives the ready-for-review hint when a clean ahead branch has a receipt honored at its current HEAD.
  • non-dry-run standards require a clean worktree whenever standards are configured. --dry-run remains free to preview the plan, and --force exists only for standard authoring or debugging.
  • accept refuses dirty worktrees. It no longer creates WIP commits, and no longer soft-resets them into the main checkout.

update remains the canonical way to bring the trunk into a worktree. It performs its own preconditions and is idempotent, so guidance should tell agents to call it directly instead of running preliminary git checks.

Consequences

§

The efficient final path is now:

  1. iterate with prepare, test, or targeted commands;
  2. commit the intended final tree;
  3. run done on the clean HEAD;
  4. run standards as needed on the same clean tree;
  5. accept only when the user explicitly asks for handoff or landing.

Acceptance becomes simpler and less surprising: it lands committed branch history only. Moving uncommitted work between contexts is outside discern's acceptance lifecycle.

Standard authoring keeps an escape hatch. A person adding or debugging a standard can use --force to run the metric command before committing the standard itself, but ordinary agent guidance should treat non-dry-run standards as clean-tree checks.

Alternatives considered

§
  • Keep dirty acceptance and improve the prose. That would leave a feature whose existence invites agents to treat acceptance as a WIP handoff tool.
  • Make standards always clean-tree-only with no override. That is simpler for agents, but awkward while designing a new metric command.
  • Automatically commit before final checks. discern cannot know the user's desired commit boundary or message. The final commit is project work, not a discern side effect.
choose openEsc close