v3.4.1 - what the config says is what routing does #177
No reviewers
Labels
No labels
already-shipped
bug
documentation
duplicate
enhancement
external-review
good first issue
help wanted
in progress
invalid
needs-decision
proposal
question
security
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: crenshawdev/cadence-archived#177
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "cadence/v3.4.1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #129, #134, #135.
Three surfaces described the review gates and nothing had ever compared them.
config.mjs getanswered a gate from the schema default when no layer set one,config.schema.json's prose named a level's gate, androute-table.jsonis what actually fires.phase_diffwas the case already on the floor: the schema called itadvisoryatshipped, the route table firesoff.GAT-03 - all four
review.triggers.*.gatedefaults move to thenullsentinel, and eachpurposestring names the gate forsolo,shippedandcriticalread offroute-table.json.risk_surfacemoved with them despite agreeing at every level today: a scalar default legal only while every cell equals it goes quiet the first time a cell moves. Thereviewgrid did not move - it is the authority.GAT-02 -
config.mjs getof a gate no layer pinned answersnullplus onewarnings[]entry namingroute.mjs resolve, so a reader can tell "no layer set this" from "this project pinned it". A pinned gate still reads back byte-identical, a keylessgetcarries no gate warning, andcheck review.triggers.diff.gate=nullstill refuses withmust be one of: off, advisory, blocking, adjudicated.ENF-02 -
self-verify.mjscheck 18,gate-agreement: compares every trigger's schema default AND its prose against the route grid, over six codes, as a pure lib atcadence-core/bin/lib/gate-agreement.mjsunit-tested from frozen fixtures. Watched to FAIL against the unpatched tree before the fix landed, reportingplan,diffandphase_diffand namingphase_diffwithshipped.The workaround came out with the defect:
workflows/execute.mdandworkflows/plan.mdno longer carry the paragraph explaining why a gate must not be pre-fetched throughconfig.mjs get, andreferences/config-catalog.md's gate row stops publishing a per-key scalar default routing never fires.Verification
node cadence-core/bin/self-verify.mjsexits 0,problems: [],checkednamesgate-agreementnode --test cadence-core/bin/*.test.mjs- 1870 pass, 0 fail, no test file removed, no count-pin loosenednpx tsc -p tsconfig.ci.jsonexit 0Known gap
gate-agreementcompares the default against the cells, not against thenullsentinel, so a trigger whose three cells agree could regress its default and stay green.risk_surfaceis that case today. Filed inCAPTURE.md.`review.triggers.<t>.gate` is described by three surfaces - the schema's `default`, the schema's `purpose`, and route-table.json's `review` grid - and nothing made them agree. lib/gate-agreement.mjs is the one statement of that agreement, taking the parsed schema keys, the parsed table and the caller's level/gate vocabularies, and returning `{code, detail}` entries. Two distinguishable halves, both mandatory. `gate-default-drift` fires when a scalar default names a gate the grid does not fire at some level; `gate-prose-missing` / `gate-prose-drift` fire when the purpose carries no `<gate> at <level>` clause for solo, shipped and critical or names the wrong gate at one. The prose half is never opt-in: reading it only where a clause already exists lets a maintainer silence it by deleting one sentence, the hole check 14 closes for CONTRACTS rows. `null` is exempt specifically - it is the "no scalar claim, the level decides" sentinel - while any other non-gate default is `gate-default-invalid`, since nothing in the tree checks a schema default against its own `values` enum and `config.mjs get` answers whatever is written there. An unusable grid, a non-object row and a non-string purpose report under a code rather than throwing. The trigger list is derived from the schema's own key names, so a fifth trigger is walked the day its key lands. The test holds the four schema rows and the `review` grid exactly as they ship today as frozen literals rather than disk reads, so the pre-patch failing evidence stays re-runnable after the schema moves onto the grid. Not wired into self-verify.mjs yet: the repo stays green at this commit.config.mjs getreports an unset gate as unset 5356dc92f1`workflows/execute.md:35-39` and `workflows/plan.md:58-62` carried the same warning: do not pre-fetch a gate through `config.mjs get`, BECAUSE that seam would answer the schema default. The instruction stays - fire(trigger) still takes every gate from the routing bundle, which is what makes the stakes level reach a fire site rather than only the seam - and the reason goes, because it is no longer true. An unset gate now answers `null` and names `route.mjs resolve`, so the seam is not a source for a level's gate either way. Both files sit at exactly their weight-budgets.json row and the budget check fails on shrink as well as growth, so both rows are re-measured and re-pinned here: execute.md 25289 -> 25287, plan.md 22041 -> 22067. No other row moves. `.planning/DOCS-CLAIMS.md` rows EXECUTE-07 and PLAN-09 quoted the retired sentence at `accurate`; both move to the stale-then-corrected form CONFIG-02 models, citing this phase. The AC5 sweep is repo-wide, not the two edited files. `grep -rniE "schema default|schema DEFAULT" cadence-core docs README.md skills` returns neither execute.md nor plan.md, and every remaining hit is a legitimate use of the phrase: route-table.json:9 states the RULE that route.mjs must never turn a schema default into a user assertion bin/route.mjs:47 the same rule, at the resolver (D-04) bin/lib/gate-agreement.mjs:209 the new check's own detail, naming why a non-gate default is a problem bin/config.mjs:236, :242 the new null-means-unset copy, and the pre-existing description of the layering references/conventions.md:73 the layering rule generally; D-11 rules it is not a criterion-4 hit workflows/context.md:93 `memory.backend` really does default to `builtin` bin/planning.mjs:1898 the same `memory.backend` default prose-agreement.test.mjs:107, :181, route.test.mjs:564, config-seams.test.mjs:340, :434, :789, global-only-keys.test.mjs:119, config.test.mjs:252, :281, :290, :294, :366, :758, :1010, :1074 test prose about non-gate keys resolving at their defaults, plus the new block's own description of the defect it closes No hit anywhere claims that a `get` of a GATE returns the schema default.