gates: two checks report success without having read what they check #116
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 project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: crenshawdev/cadence-archived#116
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Two gates return a clean answer about input they never successfully read. Both are in commands whose entire job is to not let something through.
1. milestone-prune ships Deferred requirements as Complete
lib/milestone-prune.mjs:107:No
r.status !== 'Deferred'term. Every sibling consumer has one:planning.mjs:317,:513,:1023. This one writer does not.Compounding it, the bullet removal at
:118-124scans the WHOLE file unbounded, while the Traceability removal nine lines below IS bounded to its section. So the## Deferredbullet goes too, and becausesummaries.setis last-write-wins, the deferral note becomes the shipped row's summary.Reproduced with
PERF-02 | Phase 3 | Deferredand the phase box checked:Traceability row deleted,
## Deferredbullet deleted,phases/3/deleted,ok:true, no warning. A requirement deliberately held back is now permanently recorded as delivered, and no future audit can see it. This is silent scope loss inside the command whose stated job is auditing that nothing was dropped.Fix: add the status term at
:107; bound the bullet filter at:118-124to the## Activespan the way:127-134bounds the row filter.2. The unattended-close halt gate fails open
land-cleanup.mjs:59-69returns[]on unreadable stdin, on malformed JSON, and on a valid object with nofindingsarray.lib/close-decision.mjs decideGateHaltthen returnsproceed:The last two carry
reason: "auto_close on, no surviving blocker/high finding: proceed to merge"- an affirmative claim about input the function never read.Under
git.auto_close,references/triage-gate.md:68suppresses the triage prompt entirely, so this is the ONLY remaining stop before merge, and the payload is model-composed (skills/cad-land/SKILL.md:73).The irony is in the same file:
gate()'s comment at:118-122argues at length that a torn CONFIG layer must be distinguishable fromauto_close: false. The findings side, which is strictly more consequential, got no such distinction.Fix: return a discriminated result (
{ok:false, reason:'unreadable-findings'|'bad-findings'}) and halt on it whenautoClose === true. An unprovable finding set is not an empty one.Fixed in v3.2.0 (PR #124). GAT-01, phase 2. The unattended-close gate distinguishes "no findings" from "could not read the findings": unreadable stdin, malformed JSON and a valid non-findings envelope each halt under git.auto_close with a reason naming the failure, where all three previously returned proceed. milestone-prune no longer ships a Deferred requirement as Complete.
Verified through the phase UAT walk. The milestone audit traced 12/12 requirements with 0 broken and 36/36 acceptance criteria covered.