v1.91.367.0 fix(ship): collect never counts a non-review as clean, and a severity word used as a word is no finding (GST-434, GST-435) (#3677)

* fix(ship): collect counts a reply with no finding and no clean marker as a non-review, never clean (GSTA-167)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): a label word used as a word is no finding, and a paragraph finding keeps its detail bullets (GST-435)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): a negation counts only when it applies to the label; compact table rows keep their label; register the review-ledger fixtures (pre-landing review)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): negation stops at a conjunction, a summary line with a blocker stays, detail bullets need no gap and no locus; a re-sent review voids a refusal and the outside voice can be collected unavailable (pre-landing review)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): bold and code marks keep a negated label a word, a subject phrase with and/or stays negated, table negation counts, --unavailable refuses an output with findings, VOIDED needs a re-send (fix-check)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): a quoted label counts at the end of its line and in table cells, which ends a negated subject, and a negated subject never cancels a label on a file:line line (fix-check)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): a line naming a file:line or a table row always keeps a finding; "of which" stays inside a negated subject (fix-check)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(ship): the review-pass fake outside voice ends with its Recommendation: line, the marker its brief prescribes (#3665 integration)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* revert(ship): parseFindings labels and negation back to main; GST-435 moves to its own PR (seed branch gsta-435-seed). Keeps the non-review rule and the detail-bullet merge (split)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
Garry Tanandcapy-ai[bot] authored and GitHub committed 2026-10-31 13:03:38 +00:00
1 parent 12dc6782c2
commit 41a67b996d
12 files changed
+307 -32

No files matched your search

+16 -5
View File
@@ -473,7 +473,14 @@ ones, and the arm lost blockers. `bin/gstack-review-dispatch` closes both ends:
second line for the same field starts another: `Severity` raises its label,
`Blocks: yes` makes it CRITICAL and `Blocks: no` never lowers it; an inline
`Blocks: yes` is CRITICAL too, and with no finding above it is one. The native
adversarial voice's FIXABLE collects as CRITICAL (normalizer v2, GSTA-167). A phantom finding costs a fold; a lost one costs the gate.
adversarial voice's FIXABLE collects as CRITICAL (normalizer v2, GSTA-167). An unnumbered, unlabeled bullet with no file:line
under a paragraph finding whose Severity or Blocks line has not come yet is that finding's detail, so the field line after it
lands on the finding; a numbered item is its own finding.
A phantom finding costs a fold; a lost one costs the gate.
A reply with no finding counts as a review only with the clean marker its own brief asks for: `NO FINDINGS` alone on a
line for the specialists, the batched specialist, the targeted reader, the Red Team and fix-check, the `Recommendation:`
line for the outside voice, either for the native adversarial voice. Without one (a refusal, an empty reply, a reader
that never saw the diff) collect records `review: false`, prints `COLLECT_NOT_REVIEWED` and exits 1.
4. Lead judgment writes `judged.jsonl`; `judge` refuses a set that drops a merged
finding, lowers its severity, folds it into a less severe duplicate, or adds or
promotes one without a reason (`JUDGMENT_REJECTED`). A merged file missing any id
@@ -481,10 +488,14 @@ ones, and the arm lost blockers. `bin/gstack-review-dispatch` closes both ends:
5. `verify --ledger <f>` replays all of it from the run's ledger: rendered against
dispatched hashes per render (each render is one dispatch of its reader, so a
two-pass ledger checks pass-1 sends against pass-1 briefs; a later render prints as
`<reader>@2`), a collected output for every sent reader (`NOT_COLLECTED`
otherwise; a reader that failed is collected from its failure text, where any
label word becomes a finding the judge folds, and its coverage is logged
`unavailable` in the review-log row). A mismatched send re-sent
`<reader>@2`), a collected output that is a review for every sent reader (`NOT_COLLECTED`
otherwise, and the output row `NOT_REVIEWED`; the marker is checked again in the output file when it is unchanged, so an
older ledger meets the same rule; a non-review the same dispatch later replaced with a review, by re-sending the brief, is `VOIDED`
and counted in `voided=N`). The outside voice may fail without blocking: `collect --unavailable '<reason>'` records its failure text
as missing coverage (`COLLECT_UNAVAILABLE`); an empty reason or an output that holds findings is refused (exit 2), so a partial
answer is collected normally and loses nothing. Verify prints its brief and output `UNAVAILABLE` and `unavailable=N` on the
verdict line, and its coverage is logged `unavailable` in the review-log row; any other reader is refused (exit 2), because its
missing coverage leaves the review incomplete. A mismatched send re-sent
byte-exact before anything was collected is void and counted (`voided=N` on the
verdict line); one that produced an output stays `MISMATCH`. Then output hashes
against the merged lines they produced, and the judgment rerun against the