-
v3.4.1 - what the config says is what routing does
StableAll checks were successfultest / node-test (git, 22) (push) Successful in 22stest / node-test (git, 24) (push) Successful in 19stest / node-test (other, 22) (push) Successful in 15stest / node-test (other, 24) (push) Successful in 16stest / node-test (planning, 22) (push) Successful in 1m4stest / node-test (planning, 24) (push) Successful in 1m3stest / node-test (prose, 22) (push) Successful in 26stest / node-test (prose, 24) (push) Successful in 30stest / node-test (review, 22) (push) Successful in 19stest / node-test (review, 24) (push) Successful in 17stest / node-test (routing, 22) (push) Successful in 26stest / node-test (routing, 24) (push) Successful in 26stest / self-verify (push) Successful in 13stest / typecheck (push) Successful in 18sreleased this
2026-08-15 19:50:32 +00:00 | 747 commits to main since this releaseFixed
-
The schema said one gate, the route table fired another. Three surfaces
described the review gates and nothing had ever compared them.
config.schema.json:81gavereview.triggers.phase_diff.gatea default of
advisoryand its purpose string said "advisory at shipped", while
route-table.json'sreview.shipped.phase_difffiredoff. That one cell
was the visible half. The invisible half is that aconfig.mjs getof any
gate no layer had set answered with the SCHEMA DEFAULT rather than with what
the stakes level actually fires, so all four triggers could disagree and
nothing said so.All four
review.triggers.*.gatedefaults are now thenullsentinel, and
each purpose string names the gate forsolo,shippedandcriticalread
straight offroute-table.json.risk_surfacemoved with them even though
its three cells agree today: a scalar default that is legal only while every
level's cell equals it passes quietly right up to the first cell that moves.
Thereviewgrid did not move at all - it is the authority, and this release
is the other two surfaces catching up to it.The workaround came out with the defect.
workflows/execute.mdcarried a
paragraph telling a caller not to pre-fetch a gate throughconfig.mjs get
because the answer would be the schema default rather than the level's;
workflows/plan.mdcarried the same one. Both now state the shipped
behaviour, andreferences/config-catalog.md's gate row stops publishing a
per-key scalar default that routing never fires.
Added
-
self-verify.mjscheck 18,gate-agreement. The check that makes the
fix above stay fixed, and the reason one visible cell was worth a release.
self-verify.mjsalready failed in both directions on rung files and on the
three routing grids, and it already readconfig.schema.jsonfor the gate and
stakes vocabularies - it had both files open and had never compared a trigger's
gate across them, so the drift was invisible to the one check whose job is
catching exactly this.It compares every
review.triggers.<t>.gateschema default AND itspurpose
prose againstroute-table.json'sreview[level][trigger], over six codes
(gate-default-drift,gate-default-invalid,gate-prose-missing,
gate-prose-drift,gate-grid-missing,gate-row-malformed). The rule is a
pure lib atcadence-core/bin/lib/gate-agreement.mjs, unit-tested from frozen
fixtures rather than from the live files, so the tests do not move when the
grid does.It was watched to FAIL before the fix landed, not inspected: run against the
unpatched tree it reportedplan,diffandphase_diff, naming
phase_difftogether withshippedby name.
Changed
-
config.mjs getreports an unset gate as unset. A gate no layer pinned
now answersnullwith onewarnings[]entry namingroute.mjs resolveas
what decides it for a level, so a reader can tell "no layer set this, the
stakes level decides" from "this project pinned it". A pinned gate still reads
back byte-identical with no warning, a keylessgetcarries no gate warning at
all, andconfig.mjs check review.triggers.diff.gate=nullstill refuses with
must be one of: off, advisory, blocking, adjudicated- thevaluesarrays
stayed four-membered, sosetandcheckbehave exactly as before.Known gap, filed rather than papered over:
gate-agreementcompares the
default against the cells, not against thenullsentinel, so a gate whose
three cells happen to be identical could regress its default and stay green.
risk_surfaceis that case today.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
-