ADR-2440: Move the praetor pin to 7458a220e1c9 and drop the exceptions for the managed workflows¶
- Status: Accepted
- Date: 2026-10-07
- Deciders: lusoris
- Tags: ci, governance, standards
Context¶
PRAETOR_REF pinned afb739ed81f3 (ADR-2321). Praetor main at 7458a220e1c99d136cda3287d0e57afba7a2668b (2026-10-07) is three commits later (cordanaLLM/praetor#826, #836, #851); #826 and #851 are breaking. The new engine's audit, run on an untouched clean clone of master b075f3a88, fails one gate. The other changes ask nothing of this tree.
| Praetor change | Finding on master | Resolution here |
|---|---|---|
#826 (fix for #815): the emitted praetor-api.yml and praetor-docs.yml push only on the default branch, listen for opened, synchronize, reopened, ready_for_review, and stop a draft with a failing first step; prior renderings are recorded so a copy refreshes without --force | .github/workflows/praetor-docs.yml holds an earlier Praetor text | both files regenerated by adopt --force in a throwaway copy and copied back |
#851, hook gate: audit and adopt fail when core.hooksPath leaves the managed hooks directory | none: no core.hooksPath is set here | planted core.hooksPath=/dev/null in a throwaway repository: audit fails and names the scope; without it the hook check is the old one |
#851, caveman C1 counts only whole-word articles (a token such as A380 is no article) | none at the audit; scripts/ci/AGENTS.d/ci-impact.md already failed the page check | page reworded, now 1 article |
| #851, snapshot lock waits; test-only changes (#755, #809, #836) | none | none |
The DevContainer bundle and the agent evasion hook changed with the engine and were regenerated in the same copy.
Decision¶
Move PRAETOR_REF in .github/workflows/standards-gate.yml to 7458a220e1c99d136cda3287d0e57afba7a2668b, under ADR-1351's conditions: engine-written files come from the engine in a throwaway copy (adopt --force --lock-source-root <praetor clone at the pin>) and only the files audit reports stale are copied back (the two workflows, the DevContainer bundle, .config/agent/hooks/block_evasion.py). .paperclip/ and .standards.yaml are not copied back: in the copy the register block names the skills adopt wrote there, which this repository does not carry (ADR-2321).
Drop the exceptions Q-076 declared for the two managed workflows, as far as the engine now allows:
push_branch_exceptionsis empty. Both workflows push only onmaster.ready_for_reviewexemption removed fromtest_every_pull_request_workflow_listens_for_ready_for_review.untiered_jobskeeps both entries, with a new reason and expiry 2027-12-31. The engine stops a draft with a failing first step and skips the rest, but the job still starts and reports a red check, and the tier contract expects a draft to start no job but the declared ones. A job-level gate cannot be added to a byte-locked file.test_praetor_managed_jobs_stop_on_a_draft_before_any_workproves the step shape (first step fails closed on a draft, every later step guarded by the opposite condition) and two planted defects show it failing.- Proof the old exceptions are gone: the routing contract run against the previous workflow text (
CI_ROUTING_WORKFLOWS_DIR) fails 6 cases; against the regenerated files it passes (39 cases). A planted push trigger without the branch filter failsexpect_no_other_branch_runs.
The state row T-CI-PRAETOR-LOCKED-WORKFLOWS-PUSH-AND-DRAFT-2026-10-07 moves to Recently closed with the draft caveat.
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
Drop the untiered_jobs entries too and teach the contract that a first-step stop is a draft gate | No exception left | Weakens a contract that expects a job-level gate; the jobs do start on a draft | The entry plus a shape test states exactly what the engine does |
| Wait for praetor to skip the job on a draft | Cleaner | Open-ended; the exception expires 2026-12-31 and fails then | The push-branch half is fixed now |
Edit the two workflows by hand to add a job-level if | Meets the contract | Audit refuses a hand edit | Forbidden by the byte lock |
| Move the pin (chosen) | Branch filter and ready_for_review arrive; the 52 daily push runs per workflow on other branches (measured 2026-10-06) stop | One exception stays |
Consequences¶
- Positive: a push to another branch starts neither workflow; a draft costs seconds, not the full gate.
- Negative: a draft pull request shows two red managed checks until it is ready; the draft-start gap is filed upstream as cordanaLLM/praetor#857, and the two
untiered_jobsentries go when it lands; a throwaway clone made withgit clone -c core.hooksPath=...persists the value and fails audit (use the option per command instead). - Neutral / follow-ups: every hook engine moves with the merge; a branch rebases onto the merged pin first.
Go API CompatibilityjoinsstrictMustReport(Q-184): the earlier reason (noready_for_review) no longer holds.test_required_and_strictfails against the previous aggregator.
Supply-chain impact¶
- Build-time fetches:
go install github.com/cordanaLLM/praetor/cmd/standardsctl@7458a220e1c9...in the gate jobs, pinned by commit. - CVE surface delta: none.
References¶
- Q-178 (follow-up of Q-108): move the pin from
afb739ed81f3to7458a220e1c9(orchestrator ledger, 2026-10-07). - Q-108: the first of the two bumps; a second, small bump follows praetor#826 (ADR-2321).
- Q-183, Q-184, Q-185: keep the two
untiered_jobsentries; moveGo API CompatibilityintostrictMustReport; file the draft-start gap upstream (orchestrator ledger, 2026-10-08). - Q-076: the exceptions for the managed workflows, expiry 2026-12-31 (ADR-2169).
- req (paraphrased): fix every finding in the repository without waivers, regenerate the managed workflows through praetor, and return real choices as questions (coordinator brief, 2026-10-07).
- ADR-1351, ADR-2153: earlier pin moves.