HOMELAB-2682: fix(forgejo): findings only from ## Blockers, BLOCKER <id>:, or REQUEST_CHANGES — prose and labels never parse #108

Merged
pi-landing merged 4 commits from plane/HOMELAB-2682-finding-rule into main 2026-11-06 13:11:44 +00:00
Collaborator

Ruling (quoted)

A comment's content counts as a finding ONLY in these three forms:

  1. A REQUEST_CHANGES verdict (its blockers block);
  2. A line under the comment's exact ## Blockers section;
  3. An exact BLOCKER <id>: line.
    EVERYTHING else in a comment is NOT parsed as a finding — no label scanning (RISK-n, C-n, S-n …), no prose parsing, no bullet shapes, no vocabulary anchoring outside those three forms.

El Director ruling, HOMELAB-2682, 2026-11-06. Supersedes #105's label-span anchoring wherever it conflicts.

The misread this fixes, reproduced at origin/main (34fdf7f)

Homelab/ghostty-in-the-shell #209 — three ld-reviewer APPROVEs, all pinned to 092174e3, all refusing to land. Read-only reproduction with findOpenBlockers at main over the three real comments:

{"id":"RISK-2","line":"RISK-2: put a drift check in place before the switch; nothing today notices when the mount moves and the copy does not.", ...}
{"id":"RISK-3","line":"RISK-3 (minor): the copy's `--help` reaches out of the repo and runs adb (usage() heredoc). ...", ...}
{"id":"RISK-4","line":"RISK-4 (minor): self-binding. The copy takes its tree from PROJECT_DIR/PWD; ...", ...}

Before / after, same comment stream, same head:

findOpenBlockers evaluateLandingLock
origin/main 34fdf7f 3 findings (RISK-2, RISK-3, RISK-4) refuses: 3 open blocker finding(s)
this PR 0 findings permits (routine class, one exact-head verdict)

Mechanism, named: comment 22636 writes ### Findings over four RISK-n follow-ups. SECTION_NOUN was (?:blockers?|findings?), so that heading read as a blocker section title and supplied the severity the RISK lines never carried; sectionLeadId then read each leading label as a finding id. RISK-1 escaped by accident — its neighbour line negated.

The three forms (what counts now)

  1. REQUEST_CHANGES verdict → its blockers block (unchanged; the hold legs are untouched).
  2. A line under the comment's exact ## Blockers section — ## Blockers, ## Open blockers, ## Blockers (open), ### Blockers with the existing qualifier/meta grammar. Token or not: the section supplies the severity.
  3. An exact BLOCKER <id>: line — the line-initial severity token in every form the fleet posts: BLOCKER B1: …, - BLOCKER B1: …, **Blocker B1** — …, ## Blocker B1 — …, ### GITS35-R1 (blocker) — …, 1. BLOCKER — …, Blocker: ….

Retired

  • SECTION_NOUN loses findings? — a ## Findings / ### Findings heading no longer supplies a finding's severity. (This is the whole of the #209 fix.)
  • The negation-heading arm: a self-labelled line under ## No blockers. counted as a finding on its label alone. That is label scanning outside the three forms. A line there now counts only on its own severity token (form 3).
  • The mid-sentence severity: blocker anchor — a token that is not in label position is vocabulary, not a finding.

Fail-closed, with the reason named

New exported assessFindingGrammar() plus a lock leg (Leg 4b) that refuses and says why:

  • verdict-shaped, no verdict block — the comment's own statement purports to be a verdict (verdict-of-record heading ## Verdict …, the bold **Verdict of record — …** line, a machine verdict: … line, a stance-first statement, or a short hold form) but yields no readable stance/head.
  • malformed ## Blockers — an empty section (heading, then nothing before the next heading / end / thematic break), or documentation placeholder vocabulary (- <finding-id>: <severity> — <finding>).

The boundary is tested both ways. "Verdict-shaped" is deliberately narrower than isReviewVerdict: that predicate accepts any first block mentioning the word "review", so the lock's own resolution sentence (The blocker raised in review 16344 is resolved on head <sha>.) is "verdict-shaped" to it. Measured: using it to refuse turned real permits into refusals — infra-core #660/#670/#694, pi-extensions #79, the GITS lane PRs. Round 2 narrowed it further (the four ordinary shapes it still refused) and pinned those real comments — see the round-2 section. Ordinary discussion comments never trigger the leg: a fix-worker note, a post-merge record, a ## Review round 1 note, a grammar citation, a self-disclaimed note, a disposition note about a cleared hold, and a plain comment that also carries an empty ## Blockers section are all asserted not to trigger it.

The leg is placed after every existing refusal, so no refusal text this module already emits changes: what it adds is a refusal on PRs that would otherwise merge.

What the new rule lets through (verbatim)

These lines state or imply a real defect and are not one of the three forms, so they no longer hold a merge. Each one is captured verbatim in forgejo/tests/fixtures/prose-attack-corpus.json and asserted to be a non-finding:

  1. This must be fixed before merge.
  2. Do not land without a drift check in place.
  3. - do not merge until the ledger accepts the optional fields
  4. RISK-2: put a drift check in place before the switch; nothing today notices when the mount moves and the copy does not.
  5. RISK-3 (minor): the copy's `--help` reaches out of the repo and runs adb (usage() heredoc). If the copy is ever the executed suite, make usage self-contained; also fix the stale `core/manifests/apps/sbx-gits/tools/` path and the pod/ConfigMap wording of the missing-queue error.
  6. RISK-4 (minor): self-binding. The copy takes its tree from PROJECT_DIR/PWD; a consumer that forgets PROJECT_DIR, in a pod where /home/ld/work/ghostty-in-the-shell exists, would gate that tree instead of the head.
  7. RISK-1 (for the follow-up, not for this head): before any consumer reads suite=, the anchor that the mount-sha comparison provides has to be replaced by something as hard
  8. - C-1: the smoke script does not re-check the mount digest after reload; recorded, not gating.
  9. - S-2: the census output should name the session, not only the model.
  10. Consequences in-repo: a --help, and a bare invocation (usage -> exit 2), performs a live adb probe and calls the MOUNTED tool's --ensure-serial (which may adb-disconnect untoward transports) with no emulator lock held; and on any host without /run/sbx-tools the committed copy is not self-contained on that path.
  11. The committed header still says the repo copy lives at core/manifests/apps/sbx-gits/tools/ (it is scripts/ci/) and cites docs/gits-sbx/run-proof.md and docs/gits-sbx/t7-emu-smoke.md, which do not exist in this repository.
  12. I have logged this in the tracker as severity: blocker so it is not lost.
  13. This is the same class of blocker I raised on #207, and it is not new here.

Also newly invisible (was counted at main): any labelled bullet under a ## No blockers. claim heading — e.g. - B1: high — the auth check is open on the fallback path under ## No blockers. is now zero findings, while the same line under ## Blockers is finding B1. That is the ruling's trade: a reviewer who means it writes the section.

This is deliberate. The reader stops inventing findings; the cost is that a real defect written as prose outside the three forms no longer stops a merge — the reviewer who means "blocker" writes ## Blockers / BLOCKER <id>:, and the fail-closed legs catch the malformed cases.

Head note: the fix commit is 77ec511; 247aecb on top is an EMPTY re-trigger commit — forgejo-ci on 77ec511 died inside npm ci (esbuild ... ETXTBSY) before running anything, and this Forgejo exposes no rerun endpoint. The tree at both heads is identical. CI on 247aecb: 15/15 contexts, state success.

Round 2 — seat-1 blockers (review comment 22711) — fixed at 77ec511

Seat 1 posted REQUEST_CHANGES with three blockers, each of them reproduced first-hand at ac9aec08. All three are fixed, test-first: every reproduction below went into the suite as a FAILING test before any code changed (9 red → green).

B1 — the mid-sentence (blocker) / [blocker] anchor parsed prose

/[\[(]\s*blockers?\s*[\])]/i was a member of BLOCKER_FINDING_PATTERNS, so it matched anywhere on a line — the same defect the retired severity: blocker anchor had. Both of the seat's lines reproduced as one open, unclosable, id-less finding each, in an APPROVE.

The parenthetical form is now a LABEL (PARENTHETICAL_BLOCKER_TOKEN_RE + isParentheticalBlockerLabel): it counts only at the head of the line's own label span (optional heading marker, lead gap, optional id, separator run, then the token), and only

  • inside a ## Blockers section (form 2 — - (blocker) — the guard only prints), or
  • when it carries an id of its own (### GITS35-R1 (blocker) — …, the id-first spelling labelId reads and the three-forms test pins).

Judgement recorded: strict section-scoping alone would have dropped the id-bearing label, which is a real fleet form the suite already pinned — so the rule is label-position + (section or id). Mid-sentence prose and a bare (blocker) with no id both report zero.

Also judged from the seat's concerns: BLOCKER<B1>: (token glued to an angle-bracket label) now reports nothing — the label grammar has no <id> spelling, so it would key id-less — while BLOCKER B1: … and BLOCKER: … still block.

B2 — isVerdictShaped false-refused ordinary comments

The heading/statement test was a bare subject prefix ^(verdict|approval)\b, and the disclaimer was read on the first line only. VERDICT_NAME_RE now requires the noun to be the comment's name of a verdict, with a closed continuation vocabulary: end of statement, a separator, or a record phrase (of record, record, for|on|at head, pinned to, for|on|at|of <sha>).

Pinned as refusal-free (the seat's four shapes, verbatim): ## Approval notes; a first line Approval is blocked until the census names the session, which is upstream of this diff.; ## Final approval checklist with (I am not posting a verdict.) in the body; and ## Verdict grammar + The lock reads a verdict heading plus a head pin. — each asserted isVerdictShaped === false, zero problems, and the lock permits. The disclaimer is now read over the whole statement block, and DISCLAIMER_RE gained not posting a verdict.

Genuine attempts still refuse: ## Verdict + prose, ## Final verdict with no block, **Verdict of record — ld-reviewer — head**, **REQUEST_CHANGES at <sha>** → no-verdict-block.

B3 — the malformed-## Blockers refusal had no remedy (a brick)

The condition is head-independent and the refusal told the author to fix it, which ruling 8 forbids: the PR was unlandable at every head, for ever. The refusal is now judged per comment and has a LEGAL EXIT:

a LATER exact-head verdict from the SAME reviewer supersedes that reviewer's own earlier comment; the refusal for that comment is lifted, and the passing result names the supersession (finding rule: comment #2 (malformed-blockers) is superseded by the same reviewer's later exact-head verdict #4).

"Same reviewer" is the item's own declared identity: same author, plus — only for the labels the item declares — the same model/lens. An item that declares no model is superseded by its author's later readable verdict whatever model that declares (the author is the only identity the text offers, and the alternative strands exactly the comments the seat measured). A different author never lifts anything, an item with problems of its own can never be the cure, and the lifting verdict decides only its own row — it is not an extra approval. The exit is applied to both arms (malformed-blockers and no-verdict-block), because the brick is identical; exported supersededFindingGrammar() reports what was lifted.

Tested both ways, as asked: no later same-reviewer verdict (two clean exact-head verdicts from other keys) → the refusal stands and names the exit; a later clean exact-head verdict from the same reviewer → problems empty, supersession reported, lock permits.

Seat concerns, dispositioned

  • C-1 (stale docblocks) — fixed. assessFindingGrammar documented itself as gated on isReviewVerdict; it gates on isVerdictShaped. isVerdictShaped listed ## Review… as a heading form the code excludes; both blocks now say what the code does and why (#660 / comment 16013).
  • C-2 (named controls not pinned) — fixed. New fixture forgejo/tests/fixtures/verdict-shaped-controls.json holds the real bodies read from the API this round: infra-core 16013 (## Review round 1 — …), 16401 (**Recorded disposition …**), 17451 (the canonical resolution sentence), pi-extensions 19896 (## Rebase onto post-#74 main), and GITS #115 (Homelab/ghostty-in-the-shell 19267). Measured: the first four are isVerdictShaped === false and produce no problem (pinned as false). The GITS #115 comment is not false — it is ## Verdict: APPROVED with model: and head:, i.e. a real verdict — so it is pinned as the property that matters: shaped true, readable block, no problem, no refusal. The pin records the measurement, not the expectation.
  • C-3 (kept supersets) — judged: ### Blockers / ## Open blockers / ## Blockers (open) / the qualifier forms stay (they only ADD lines to form 2). The (blocker)-in-label keep is now bound to label position, i.e. not a superset but a label rule (B1).
  • C-4 (silent malformed section in a non-verdict-shaped comment) — kept silent, per the acceptance wording's "verdict-shaped" qualifier. Recorded as the known fail-open half.
  • C-5 (id-less BLOCKER<B1> / (BLOCKER)) — judged and pinned: neither counts as form 3 (see B1); the exact forms keep blocking.
  • C-6 (census replay) — not done this round (budget). Residual: the field false-refusal rate of the new legs is unmeasured.

What the rule lets through is UNCHANGED — the list above is the same 13 lines, still asserted non-findings in prose-attack-corpus.json.

Must still hold (tested both ways)

  • A real BLOCKER B1: … line in an APPROVE comment still blocks. ✔
  • A REQUEST_CHANGES verdict's blockers block; #99/#100 closures still close them (canonical sentence for id-less, resolved <id> for id-ed, reviewer-only, exact head). ✔
  • #106 session-scoped withdrawal and #103 bold negation unchanged. ✔
  • #107: BLOCKER none. is a zero-findings claim; BLOCKER none of the tests ran. is still a finding. ✔
  • All four real-approval corpus fixtures (negation-approval-corpus, fleet-verdict-corpus, pr70-review-corpus, w3-lane-corpus) pass unchanged. ✔

Suite

files tests
origin/main 34fdf7f (npm ci && npx vitest run) 34 895 passed
round 1, head ac9aec08 35 929 passed
round 2, head 77ec511 35 944 passed

scripts/test-in-deployed-shape.sh on head 77ec511: 35/35 files, 944/944, pinned typebox 1.3.34, typecheck: ok.

tsc --noEmit clean. New file forgejo/tests/landing-finding-rule-2682.test.ts (34 tests) + forgejo/tests/fixtures/prose-attack-corpus.json. tests/lock-negation-heading-2682.test.ts re-pinned where the retired readings lived (negation-arm label scan, ## Findings sections) — each edit keeps the original guard and moves it to a form the rule reads.

Not changed

  • The verdict/hold grammar, the label (model:/session:) rules, the panel legs, CI legs, the census, and the refusal texts of every existing leg.
  • forgejo/verdict.ts, verdict-cli.ts, index.ts.
  • docs/forgejo.md step 5 did change in round 2: it still described the pre-ruling finding grammar (a token anywhere, a ## Blocker heading, numbered items). It now states the three forms, the label rule and the fail-closed leg with its exit. The closure grammar below it is untouched.
  • The .forgejo/workflows set (CI runs as-is).

Open risks

  • A defect written only as prose no longer blocks (the lets-through list). Mitigated by the fail-closed legs and by reviewer briefs naming the three forms; it is a policy trade the ruling made, not a bug.
  • The (blocker)-in-label form (### GITS35-R1 (blocker) — …) is kept: the token is in label position (the label is <id> (blocker)), and it is the shape 131 existing grammar tests are built on. Round 2 resolved the hole this bullet flagged: the parenthetical token is no longer a free-text anchor — see the round-2 section below.
  • ## Blockers section recognition keeps the existing qualifier/meta grammar, so ### Blockers and ## Open blockers still count; the ruling says "exact ## Blockers" and this is the superset the fleet actually writes.
  • An unpinned stance (a stance whose head cannot be read) is still non-deciding and is named in the existing refusals rather than refused by the new leg — pre-existing behaviour, out of scope for the finding rule, recorded here so the next reader knows it was seen.
  • This change is itself an oversight path (forgejo/**), so it needs the dangerous-class panel: two independent review sessions.

Round 3 (seats of round 2) — head 29c9f66

Round-2 seat 2 posted REQUEST_CHANGES (review comment 22734) on head 247aecb; round-2 seat 1 approved (comment 22730). Round 3 closes the blocker and the two concerns both seats raised. Test-first: thirteen reproductions went into the suite and failed before any code changed (the seat's own bodies, verbatim in shape, tests/landing-finding-rule-2682.test.ts § "ROUND 3").

B1 — a machine verdict statement is read as a UNIT (the blocker)

Measured cause: verdictStatementLines returned only the FIRST line for a statement that is not a # heading, so the head: continuation under a machine verdict: line was never seen; the stance landed in ledger.unpinned — and findingGrammarAssessment counted unpinned as readable cover, so the fail-closed arm skipped exactly its own definition ("no stance, or a stance whose head cannot be pinned"). Result: an explicit REQUEST_CHANGES at the exact head read as unpinned evidence and the lock permitted next to one clean APPROVE.

Fix, two halves:

  1. The statement is read as a unit. A non-heading first line that OPENS a verdict statement (subject verdict/review/approval through subjectText, or an opening stance/hold token) now takes its label block with it, exactly as a ## Verdict heading does — so the head: line is seen and the machine form becomes a verdict of record. Guards, both required: a line that is already a complete statement of its own kind (a resolution restatement, a grammar citation) does not open one — reading its block turned infra-core#694 comment 17451 back into a "concern" (HOMELAB-2411) — and an opener that already states BOTH its stance and its head is COMPLETE, because reading its paragraph let a reviewer's own caveat override the verdict they wrote (infra-core#664 comment 16105: APPROVE with concerns on an exact head, then "do not land on it alone", is an approval — the pinned corpus rule). Where the opener supplies the stance, the block supplies the head; readVerdictStance keeps a heading's block semantics byte-identical.
  2. An unpinned HOLD is no longer readable cover. A hold can only ever refuse, so a hold whose head cannot be pinned now refuses (no-verdict-block) instead of being silently skipped. An unpinned APPROVE or CONCERN stays cover on purpose: it decides nothing, permitting on other evidence loses no safety, and refusing it turned a real permit into a refusal (prod#1023's APPROVE (head not recorded) note beside the real approval, pinned in tests/landing-corpus.test.ts).

Both directions are pinned: the seat's five variants (seven bodies: machine verdict: + head:, **Verdict: REQUEST_CHANGES**, **Verdict**, **Verdict of record — ld-reviewer**, **Verdict summary**, **Approval verdict**, **Verdict of the round**) each HOLD at the exact head and cite #2 as an open exact-head hold — the same outcome ## Verdict + the same body already had; a machine REQUEST_CHANGES with NO head fails closed with the reason named; a well-formed machine verdict: approve + head: is an approval of record (not unpinned evidence); a stance pinned to another head stays superseded; a LABEL-shaped verdict (missing session:) is still not this leg's refusal; an unpinned APPROVE still refuses nothing.

C-2 — byItem keyed by item TYPE and id

byItem was keyed on itemId alone while covered/indexOf were keyed kind:id. Forgejo review ids and comment ids are separate sequences, so comment #7 and review #7 coexist: reproduced, the refusal listed one problem TWICE and the legal exit died (a later clean review #7 could never supersede malformed comment #7) — re-opening the brick B3 closed. Keyed kind:id at raise time; three tests: listed once, cured by the same reviewer's later review #7, not cured by another author's.

C-1 — blockquoted text is documentation

A blockquoted reproduction of the seat template (> ## Blockers / > - <finding-id>: <severity> — …) refused the quoting reviewer's own passing verdict — in BOTH arms, since HEADING_ANY_RE tolerates a leading > (the assessment called it malformed-blockers; the SCAN read the quoted heading as a section and the line under it as an id-less finding). Fenced text was already skipped, so quoting a template was worse than fencing it. New documentationLines (fenced OR blockquoted) is used by the assessment and by findOpenBlockers; the quoted template now refuses nothing, and the real unquoted section still refuses (pinned both ways).

C-3 / C-4 / C-5 — judged, not changed

ownLaterWord's author-only fallback for a comment that declares no model: (accepted: the login is the trusted identity, and a lift decides nothing); the VERDICT_NAME_RE miss half (## Verdict summary and friends are not shaped — no real body depends on it, a #-heading hold still refuses on the hold); and assessFindingGrammar(items) with no headSha flagging every verdict-shaped comment — now documented in that function's doc comment as "shape-only mode means every verdict is unreadable", since requiring the head would be a behaviour change for other callers.

Field measurement (the census half seat 1 did in round 2)

Same replay, run against both heads, over 38 open PRs / 96 comment+review items in pi-extensions, infra-core, ghostty-in-the-shell, prod:

head no-verdict-block malformed-blockers open findings
247aecb (before) 0 0 27
29c9f66 (this head) 2 0 27

Both new refusals are the same real shape, and both are the class the seat named: the operator's own HOLD — … DO NOT MERGE park notes on infra-core#754 (comment 20294) and prod#1109 (comment 20295) — unpinned holds that previously decided nothing and are now named. Nothing else in the corpus moved: no new findings, no new malformed-section refusals, zero refusals on ordinary discussion, approvals or machine-form verdicts.

Suite at this head

files tests
round 2, head 247aecb 35 944 passed
round 3, head 29c9f66 35 963 passed (+19)

scripts/test-in-deployed-shape.sh on this head: ok: 35/35 files loaded and passed, 963/963 tests, pinned typebox 1.3.34, typecheck: ok. docs/forgejo.md step 5 now states the unit reading, the hold-half boundary of the fail-closed leg, and that fenced and blockquoted text is documentation. NOT merged; no verdict posted.

## Ruling (quoted) > A comment's content counts as a finding ONLY in these three forms: > 1. A REQUEST_CHANGES verdict (its blockers block); > 2. A line under the comment's exact `## Blockers` section; > 3. An exact `BLOCKER <id>:` line. > EVERYTHING else in a comment is NOT parsed as a finding — no label scanning (RISK-n, C-n, S-n …), no prose parsing, no bullet shapes, no vocabulary anchoring outside those three forms. El Director ruling, HOMELAB-2682, 2026-11-06. Supersedes #105's label-span anchoring wherever it conflicts. ## The misread this fixes, reproduced at `origin/main` (`34fdf7f`) `Homelab/ghostty-in-the-shell` **#209** — three `ld-reviewer` APPROVEs, all pinned to `092174e3`, all refusing to land. Read-only reproduction with `findOpenBlockers` at main over the three real comments: ``` {"id":"RISK-2","line":"RISK-2: put a drift check in place before the switch; nothing today notices when the mount moves and the copy does not.", ...} {"id":"RISK-3","line":"RISK-3 (minor): the copy's `--help` reaches out of the repo and runs adb (usage() heredoc). ...", ...} {"id":"RISK-4","line":"RISK-4 (minor): self-binding. The copy takes its tree from PROJECT_DIR/PWD; ...", ...} ``` Before / after, same comment stream, same head: | | `findOpenBlockers` | `evaluateLandingLock` | |---|---|---| | `origin/main` 34fdf7f | **3 findings** (RISK-2, RISK-3, RISK-4) | refuses: `3 open blocker finding(s)` | | this PR | **0 findings** | permits (routine class, one exact-head verdict) | Mechanism, named: comment 22636 writes `### Findings` over four `RISK-n` follow-ups. `SECTION_NOUN` was `(?:blockers?|findings?)`, so that heading read as a blocker **section title** and supplied the severity the RISK lines never carried; `sectionLeadId` then read each leading label as a finding id. `RISK-1` escaped by accident — its *neighbour* line negated. ## The three forms (what counts now) 1. **REQUEST_CHANGES verdict** → its blockers block (unchanged; the hold legs are untouched). 2. **A line under the comment's exact `## Blockers` section** — `## Blockers`, `## Open blockers`, `## Blockers (open)`, `### Blockers` with the existing qualifier/meta grammar. Token or not: the section supplies the severity. 3. **An exact `BLOCKER <id>:` line** — the line-initial severity token in every form the fleet posts: `BLOCKER B1: …`, `- BLOCKER B1: …`, `**Blocker B1** — …`, `## Blocker B1 — …`, `### GITS35-R1 (blocker) — …`, `1. BLOCKER — …`, `Blocker: …`. ## Retired - `SECTION_NOUN` loses `findings?` — a `## Findings` / `### Findings` heading no longer supplies a finding's severity. (This is the whole of the #209 fix.) - The `negation`-heading arm: a **self-labelled** line under `## No blockers.` counted as a finding on its label alone. That is label scanning outside the three forms. A line there now counts only on its own severity token (form 3). - The mid-sentence `severity: blocker` anchor — a token that is not in label position is vocabulary, not a finding. ## Fail-closed, with the reason named New exported `assessFindingGrammar()` plus a lock leg (`Leg 4b`) that **refuses** and says why: - **verdict-shaped, no verdict block** — the comment's own statement purports to be a verdict (verdict-of-record heading `## Verdict …`, the bold `**Verdict of record — …**` line, a machine `verdict: …` line, a stance-first statement, or a short hold form) but yields no readable stance/head. - **malformed `## Blockers`** — an empty section (heading, then nothing before the next heading / end / thematic break), or documentation placeholder vocabulary (`- <finding-id>: <severity> — <finding>`). **The boundary is tested both ways.** "Verdict-shaped" is deliberately narrower than `isReviewVerdict`: that predicate accepts any first block mentioning the word "review", so the lock's own resolution sentence (`The blocker raised in review 16344 is resolved on head <sha>.`) is "verdict-shaped" to it. Measured: using it to refuse turned real permits into refusals — `infra-core` #660/#670/#694, `pi-extensions` #79, the GITS lane PRs. **Round 2 narrowed it further** (the four ordinary shapes it still refused) and pinned those real comments — see the round-2 section. Ordinary discussion comments never trigger the leg: a fix-worker note, a post-merge record, a `## Review round 1` note, a grammar citation, a self-disclaimed note, a disposition note about a cleared hold, and a plain comment that also carries an empty `## Blockers` section are all asserted not to trigger it. The leg is placed **after every existing refusal**, so no refusal text this module already emits changes: what it adds is a refusal on PRs that would otherwise merge. ## What the new rule lets through (verbatim) These lines state or imply a real defect and are **not** one of the three forms, so they no longer hold a merge. Each one is captured verbatim in `forgejo/tests/fixtures/prose-attack-corpus.json` and asserted to be a non-finding: 1. `This must be fixed before merge.` 2. `Do not land without a drift check in place.` 3. `- do not merge until the ledger accepts the optional fields` 4. `RISK-2: put a drift check in place before the switch; nothing today notices when the mount moves and the copy does not.` 5. ``RISK-3 (minor): the copy's `--help` reaches out of the repo and runs adb (usage() heredoc). If the copy is ever the executed suite, make usage self-contained; also fix the stale `core/manifests/apps/sbx-gits/tools/` path and the pod/ConfigMap wording of the missing-queue error.`` 6. `RISK-4 (minor): self-binding. The copy takes its tree from PROJECT_DIR/PWD; a consumer that forgets PROJECT_DIR, in a pod where /home/ld/work/ghostty-in-the-shell exists, would gate that tree instead of the head.` 7. `RISK-1 (for the follow-up, not for this head): before any consumer reads `suite=`, the anchor that the mount-sha comparison provides has to be replaced by something as hard` 8. `- C-1: the smoke script does not re-check the mount digest after reload; recorded, not gating.` 9. `- S-2: the census output should name the session, not only the model.` 10. `Consequences in-repo: a --help, and a bare invocation (usage -> exit 2), performs a live adb probe and calls the MOUNTED tool's --ensure-serial (which may adb-disconnect untoward transports) with no emulator lock held; and on any host without /run/sbx-tools the committed copy is not self-contained on that path.` 11. `The committed header still says the repo copy lives at core/manifests/apps/sbx-gits/tools/ (it is scripts/ci/) and cites docs/gits-sbx/run-proof.md and docs/gits-sbx/t7-emu-smoke.md, which do not exist in this repository.` 12. `I have logged this in the tracker as severity: blocker so it is not lost.` 13. `This is the same class of blocker I raised on #207, and it is not new here.` Also newly invisible (was counted at main): any labelled bullet under a `## No blockers.` claim heading — e.g. `- B1: high — the auth check is open on the fallback path` under `## No blockers.` is now **zero** findings, while the same line under `## Blockers` is finding `B1`. That is the ruling's trade: a reviewer who means it writes the section. This is deliberate. The reader stops inventing findings; the cost is that a real defect written as prose outside the three forms no longer stops a merge — the reviewer who means "blocker" writes `## Blockers` / `BLOCKER <id>:`, and the fail-closed legs catch the malformed cases. **Head note:** the fix commit is `77ec511`; `247aecb` on top is an EMPTY re-trigger commit — `forgejo-ci` on `77ec511` died inside `npm ci` (`esbuild ... ETXTBSY`) before running anything, and this Forgejo exposes no rerun endpoint. The tree at both heads is identical. CI on `247aecb`: 15/15 contexts, state success. ## Round 2 — seat-1 blockers (review comment 22711) — fixed at `77ec511` Seat 1 posted REQUEST_CHANGES with three blockers, each of them reproduced first-hand at `ac9aec08`. All three are fixed, test-first: every reproduction below went into the suite as a FAILING test before any code changed (9 red → green). ### B1 — the mid-sentence `(blocker)` / `[blocker]` anchor parsed prose `/[\[(]\s*blockers?\s*[\])]/i` was a member of `BLOCKER_FINDING_PATTERNS`, so it matched **anywhere** on a line — the same defect the retired `severity: blocker` anchor had. Both of the seat's lines reproduced as one open, unclosable, id-less finding each, in an APPROVE. The parenthetical form is now a **LABEL** (`PARENTHETICAL_BLOCKER_TOKEN_RE` + `isParentheticalBlockerLabel`): it counts only at the head of the line's own label span (optional heading marker, lead gap, optional id, separator run, then the token), and only - inside a `## Blockers` section (form 2 — `- (blocker) — the guard only prints`), or - when it carries an **id** of its own (`### GITS35-R1 (blocker) — …`, the id-first spelling `labelId` reads and the three-forms test pins). Judgement recorded: strict section-scoping alone would have dropped the id-bearing label, which is a real fleet form the suite already pinned — so the rule is label-position + (section or id). Mid-sentence prose and a bare `(blocker)` with no id both report **zero**. Also judged from the seat's concerns: `BLOCKER<B1>:` (token glued to an angle-bracket label) now reports nothing — the label grammar has no `<id>` spelling, so it would key id-less — while `BLOCKER B1: …` and `BLOCKER: …` still block. ### B2 — `isVerdictShaped` false-refused ordinary comments The heading/statement test was a bare subject prefix `^(verdict|approval)\b`, and the disclaimer was read on the first line only. `VERDICT_NAME_RE` now requires the noun to be the comment's **name of a verdict**, with a closed continuation vocabulary: end of statement, a separator, or a record phrase (`of record`, `record`, `for|on|at head`, `pinned to`, `for|on|at|of <sha>`). Pinned as refusal-free (the seat's four shapes, verbatim): `## Approval notes`; a first line `Approval is blocked until the census names the session, which is upstream of this diff.`; `## Final approval checklist` with `(I am not posting a verdict.)` in the body; and `## Verdict grammar` + `The lock reads a verdict heading plus a head pin.` — each asserted `isVerdictShaped === false`, zero problems, and the lock permits. The disclaimer is now read over the whole statement block, and `DISCLAIMER_RE` gained `not posting a verdict`. Genuine attempts still refuse: `## Verdict` + prose, `## Final verdict` with no block, `**Verdict of record — ld-reviewer — head**`, `**REQUEST_CHANGES at <sha>**` → `no-verdict-block`. ### B3 — the malformed-`## Blockers` refusal had no remedy (a brick) The condition is head-independent and the refusal told the author to fix it, which ruling 8 forbids: the PR was unlandable at every head, for ever. The refusal is now judged **per comment** and has a **LEGAL EXIT**: > a LATER exact-head verdict from the SAME reviewer supersedes that reviewer's own earlier comment; the refusal for that comment is lifted, and the passing result names the supersession (`finding rule: comment #2 (malformed-blockers) is superseded by the same reviewer's later exact-head verdict #4`). "Same reviewer" is the item's own declared identity: same author, plus — only for the labels the item declares — the same model/lens. An item that declares no model is superseded by its author's later readable verdict whatever model that declares (the author is the only identity the text offers, and the alternative strands exactly the comments the seat measured). A different author never lifts anything, an item with problems of its own can never be the cure, and the lifting verdict decides only its own row — it is not an extra approval. The exit is applied to **both** arms (`malformed-blockers` and `no-verdict-block`), because the brick is identical; exported `supersededFindingGrammar()` reports what was lifted. Tested both ways, as asked: no later same-reviewer verdict (two clean exact-head verdicts from other keys) → the refusal **stands** and names the exit; a later clean exact-head verdict from the same reviewer → problems empty, supersession reported, lock **permits**. ### Seat concerns, dispositioned - **C-1 (stale docblocks)** — fixed. `assessFindingGrammar` documented itself as gated on `isReviewVerdict`; it gates on `isVerdictShaped`. `isVerdictShaped` listed `## Review…` as a heading form the code excludes; both blocks now say what the code does and why (#660 / comment 16013). - **C-2 (named controls not pinned)** — fixed. New fixture `forgejo/tests/fixtures/verdict-shaped-controls.json` holds the **real** bodies read from the API this round: infra-core 16013 (`## Review round 1 — …`), 16401 (`**Recorded disposition …**`), 17451 (the canonical resolution sentence), pi-extensions 19896 (`## Rebase onto post-#74 main`), and GITS #115 (`Homelab/ghostty-in-the-shell` 19267). Measured: the first four are `isVerdictShaped === false` and produce no problem (pinned as `false`). The GITS #115 comment is **not** `false` — it is `## Verdict: APPROVED` with `model:` and `head:`, i.e. a real verdict — so it is pinned as the property that matters: shaped **true**, readable block, no problem, no refusal. The pin records the measurement, not the expectation. - **C-3 (kept supersets)** — judged: `### Blockers` / `## Open blockers` / `## Blockers (open)` / the qualifier forms stay (they only ADD lines to form 2). The `(blocker)`-in-label keep is now bound to label position, i.e. not a superset but a label rule (B1). - **C-4 (silent malformed section in a non-verdict-shaped comment)** — kept silent, per the acceptance wording's "verdict-shaped" qualifier. Recorded as the known fail-open half. - **C-5 (id-less `BLOCKER<B1>` / `(BLOCKER)`)** — judged and pinned: neither counts as form 3 (see B1); the exact forms keep blocking. - **C-6 (census replay)** — not done this round (budget). Residual: the field false-refusal rate of the new legs is unmeasured. **What the rule lets through is UNCHANGED** — the list above is the same 13 lines, still asserted non-findings in `prose-attack-corpus.json`. ## Must still hold (tested both ways) - A real `BLOCKER B1: …` line in an APPROVE comment still blocks. ✔ - A REQUEST_CHANGES verdict's blockers block; #99/#100 closures still close them (canonical sentence for id-less, `resolved <id>` for id-ed, reviewer-only, exact head). ✔ - #106 session-scoped withdrawal and #103 bold negation unchanged. ✔ - #107: `BLOCKER none.` is a zero-findings claim; `BLOCKER none of the tests ran.` is still a finding. ✔ - All four real-approval corpus fixtures (`negation-approval-corpus`, `fleet-verdict-corpus`, `pr70-review-corpus`, `w3-lane-corpus`) pass unchanged. ✔ ## Suite | | files | tests | |---|---|---| | `origin/main` 34fdf7f (`npm ci && npx vitest run`) | 34 | **895 passed** | | round 1, head `ac9aec08` | 35 | 929 passed | | round 2, head `77ec511` | 35 | **944 passed** | `scripts/test-in-deployed-shape.sh` on head `77ec511`: 35/35 files, 944/944, pinned typebox 1.3.34, `typecheck: ok`. `tsc --noEmit` clean. New file `forgejo/tests/landing-finding-rule-2682.test.ts` (34 tests) + `forgejo/tests/fixtures/prose-attack-corpus.json`. `tests/lock-negation-heading-2682.test.ts` re-pinned where the retired readings lived (negation-arm label scan, `## Findings` sections) — each edit keeps the original guard and moves it to a form the rule reads. ## Not changed - The verdict/hold grammar, the label (`model:`/`session:`) rules, the panel legs, CI legs, the census, and the refusal texts of every existing leg. - `forgejo/verdict.ts`, `verdict-cli.ts`, `index.ts`. - `docs/forgejo.md` step 5 **did** change in round 2: it still described the pre-ruling finding grammar (a token anywhere, a `## Blocker` heading, numbered items). It now states the three forms, the label rule and the fail-closed leg with its exit. The closure grammar below it is untouched. - The `.forgejo/workflows` set (CI runs as-is). ## Open risks - **A defect written only as prose no longer blocks** (the lets-through list). Mitigated by the fail-closed legs and by reviewer briefs naming the three forms; it is a policy trade the ruling made, not a bug. - The `(blocker)`-in-label form (`### GITS35-R1 (blocker) — …`) is kept: the token is in *label position* (the label is `<id> (blocker)`), and it is the shape 131 existing grammar tests are built on. **Round 2 resolved the hole this bullet flagged**: the parenthetical token is no longer a free-text anchor — see the round-2 section below. - `## Blockers` section recognition keeps the existing qualifier/meta grammar, so `### Blockers` and `## Open blockers` still count; the ruling says "exact `## Blockers`" and this is the superset the fleet actually writes. - An **unpinned** stance (a stance whose head cannot be read) is still non-deciding and is named in the existing refusals rather than refused by the new leg — pre-existing behaviour, out of scope for the finding rule, recorded here so the next reader knows it was seen. - This change is itself an oversight path (`forgejo/**`), so it needs the dangerous-class panel: two independent review sessions. ## Round 3 (seats of round 2) — head `29c9f66` Round-2 seat 2 posted REQUEST_CHANGES (review comment 22734) on head `247aecb`; round-2 seat 1 approved (comment 22730). Round 3 closes the blocker and the two concerns both seats raised. **Test-first**: thirteen reproductions went into the suite and failed before any code changed (the seat's own bodies, verbatim in shape, `tests/landing-finding-rule-2682.test.ts` § "ROUND 3"). ### B1 — a machine verdict statement is read as a UNIT (the blocker) Measured cause: `verdictStatementLines` returned only the FIRST line for a statement that is not a `#` heading, so the `head:` continuation under a machine `verdict:` line was never seen; the stance landed in `ledger.unpinned` — and `findingGrammarAssessment` counted `unpinned` as readable cover, so the fail-closed arm skipped exactly its own definition ("no stance, **or a stance whose head cannot be pinned**"). Result: an explicit `REQUEST_CHANGES` at the exact head read as `unpinned` evidence and the lock **permitted** next to one clean APPROVE. Fix, two halves: 1. **The statement is read as a unit.** A non-heading first line that OPENS a verdict statement (subject `verdict`/`review`/`approval` through `subjectText`, or an opening stance/hold token) now takes its label block with it, exactly as a `## Verdict` heading does — so the `head:` line is seen and the machine form becomes a verdict of record. Guards, both required: a line that is already a complete statement of its own kind (a resolution restatement, a grammar citation) does not open one — reading its block turned infra-core#694 comment 17451 back into a "concern" (HOMELAB-2411) — and an opener that already states BOTH its stance and its head is COMPLETE, because reading its paragraph let a reviewer's own caveat override the verdict they wrote (infra-core#664 comment 16105: `APPROVE with concerns` on an exact head, then "do not land on it alone", is an approval — the pinned corpus rule). Where the opener supplies the stance, the block supplies the head; `readVerdictStance` keeps a heading's block semantics byte-identical. 2. **An unpinned HOLD is no longer readable cover.** A hold can only ever refuse, so a hold whose head cannot be pinned now refuses (`no-verdict-block`) instead of being silently skipped. An unpinned APPROVE or CONCERN stays cover on purpose: it decides nothing, permitting on other evidence loses no safety, and refusing it turned a real permit into a refusal (prod#1023's `APPROVE (head not recorded)` note beside the real approval, pinned in `tests/landing-corpus.test.ts`). Both directions are pinned: the seat's five variants (seven bodies: machine `verdict:` + `head:`, `**Verdict: REQUEST_CHANGES**`, `**Verdict**`, `**Verdict of record — ld-reviewer**`, `**Verdict summary**`, `**Approval verdict**`, `**Verdict of the round**`) each HOLD at the exact head and cite `#2` as an open exact-head hold — the same outcome `## Verdict` + the same body already had; a machine `REQUEST_CHANGES` with NO head fails closed with the reason named; a well-formed machine `verdict: approve` + `head:` is an approval of record (not unpinned evidence); a stance pinned to another head stays `superseded`; a LABEL-shaped verdict (missing `session:`) is still not this leg's refusal; an unpinned APPROVE still refuses nothing. ### C-2 — `byItem` keyed by item TYPE and id `byItem` was keyed on `itemId` alone while `covered`/`indexOf` were keyed `kind:id`. Forgejo review ids and comment ids are separate sequences, so `comment` #7 and `review` #7 coexist: reproduced, the refusal listed one problem TWICE and the legal exit died (a later clean `review` #7 could never supersede malformed `comment` #7) — re-opening the brick B3 closed. Keyed `kind:id` at raise time; three tests: listed once, cured by the same reviewer's later `review` #7, not cured by another author's. ### C-1 — blockquoted text is documentation A blockquoted reproduction of the seat template (`> ## Blockers` / `> - <finding-id>: <severity> — …`) refused the quoting reviewer's own passing verdict — in BOTH arms, since `HEADING_ANY_RE` tolerates a leading `>` (the assessment called it `malformed-blockers`; the SCAN read the quoted heading as a section and the line under it as an id-less finding). Fenced text was already skipped, so quoting a template was worse than fencing it. New `documentationLines` (fenced OR blockquoted) is used by the assessment and by `findOpenBlockers`; the quoted template now refuses nothing, and the real unquoted section still refuses (pinned both ways). ### C-3 / C-4 / C-5 — judged, not changed `ownLaterWord`'s author-only fallback for a comment that declares no `model:` (accepted: the login is the trusted identity, and a lift decides nothing); the `VERDICT_NAME_RE` miss half (`## Verdict summary` and friends are not shaped — no real body depends on it, a `#`-heading hold still refuses on the hold); and `assessFindingGrammar(items)` with no `headSha` flagging every verdict-shaped comment — now documented in that function's doc comment as "shape-only mode means every verdict is unreadable", since requiring the head would be a behaviour change for other callers. ### Field measurement (the census half seat 1 did in round 2) Same replay, run against both heads, over **38 open PRs / 96 comment+review items** in `pi-extensions`, `infra-core`, `ghostty-in-the-shell`, `prod`: | head | `no-verdict-block` | `malformed-blockers` | open findings | |---|---|---|---| | `247aecb` (before) | 0 | 0 | 27 | | `29c9f66` (this head) | **2** | 0 | **27** | Both new refusals are the same real shape, and both are the class the seat named: the operator's own `HOLD — … DO NOT MERGE` park notes on infra-core#754 (comment 20294) and prod#1109 (comment 20295) — unpinned holds that previously decided nothing and are now named. Nothing else in the corpus moved: no new findings, no new malformed-section refusals, zero refusals on ordinary discussion, approvals or machine-form verdicts. ### Suite at this head | | files | tests | |---|---|---| | round 2, head `247aecb` | 35 | 944 passed | | round 3, head `29c9f66` | 35 | **963 passed** (+19) | `scripts/test-in-deployed-shape.sh` on this head: `ok: 35/35 files loaded and passed, 963/963 tests`, pinned typebox 1.3.34, `typecheck: ok`. `docs/forgejo.md` step 5 now states the unit reading, the hold-half boundary of the fail-closed leg, and that fenced and blockquoted text is documentation. NOT merged; no verdict posted.
HOMELAB-2682: fix(forgejo): findings only from ## Blockers, BLOCKER <id>:, or REQUEST_CHANGES — prose and labels never parse
All checks were successful
CI / pr-title (pull_request) Successful in 1s
CI / pi-otel-telemetry (pull_request) Successful in 54s
CI / forgejo-ci (pull_request) Successful in 55s
CI / plane (pull_request) Successful in 1m12s
CI / todo (pull_request) Successful in 44s
CI / skill-args (pull_request) Successful in 52s
CI / ask-user-question (pull_request) Successful in 49s
CI / mcp-bridge (pull_request) Successful in 22s
tests / python (pull_request) Successful in 4s
CI / nats-intercom (pull_request) Successful in 24s
CI / refocus (pull_request) Successful in 58s
CI / forgejo (pull_request) Successful in 1m29s
CI / redact (pull_request) Successful in 41s
CI / pi-friction (pull_request) Successful in 44s
CI / pi-swarm-suite (pull_request) Successful in 3m47s
ac9aec08c9
El Director ruling 2026-11-06: a comment's content is a finding ONLY as (1) a
REQUEST_CHANGES verdict, (2) a line under the comment's exact `## Blockers`
section, or (3) an exact `BLOCKER <id>:` line. Everything else is not a
finding: no label scanning, no prose parsing, no bullet shapes, no vocabulary
anchoring outside those three forms.

The misread that produced the ruling, reproduced at origin/main (34fdf7f) on
Homelab/ghostty-in-the-shell #209 (three ld-reviewer APPROVEs, all at
092174e3): comment 22636 writes `### Findings` over four RISK-n FOLLOW-UPS.
`SECTION_NOUN` carried `findings?`, so that heading was read as a blocker
SECTION TITLE and supplied the severity the RISK lines never carried;
`sectionLeadId` then read each leading label as a finding id. findOpenBlockers
returned RISK-2, RISK-3, RISK-4 — three open blockers from a clean approval.
RISK-1 escaped by accident, because its NEIGHBOUR line negated.

Retired:
- `SECTION_NOUN` loses `findings?`: only `## Blockers` (and its qualifier
  forms) supplies a finding's severity.
- the `negation`-heading arm: a self-labelled line under `## No blockers.` was
  a finding on its label alone — label scanning outside the three forms.
- the mid-sentence `severity: blocker` anchor: a token that is not in label
  position is vocabulary, not a finding.

Kept, each one of the three forms: line-initial severity tokens (`BLOCKER B1:`,
`**Blocker** —`, `## Blockers:`, `### GITS35-R1 (blocker) —`), `## Blockers`
content, and the REQUEST_CHANGES hold. #103 bold negation, #107
(`BLOCKER none.` vs `BLOCKER none of the tests ran.`), #99/#100 closures,
#106 session withdrawal and all four real-approval corpora are unchanged.

Fail-closed (new): `assessFindingGrammar` + a lock leg that refuses, naming the
reason, when a VERDICT-SHAPED comment (its own statement is a verdict: the
verdict-of-record heading, a bold `Verdict of record` line, a machine
`verdict: …` line, a stance-first statement or a short hold form) has no
readable verdict block, or a malformed `## Blockers` section (empty, or the
documentation placeholder vocabulary). Ordinary discussion comments — resolution
sentences, review notes, fix-worker notes, grammar citations, disposition prose
— never trigger it; that boundary was measured, and wider versions turned real
permits (infra-core#660/#670/#694, pi-extensions#79, GITS lane PRs) into
refusals.
Collaborator

Verdict of record — ld-reviewer — head ac9aec08c9: REQUEST_CHANGES
model: deepseek-flash
session: ses-108-seat1-7f3c1a9d

Reviewed the diff at this exact head (forgejo/landing.ts, forgejo/tests/landing-finding-rule-2682.test.ts, forgejo/tests/fixtures/prose-attack-corpus.json, forgejo/tests/lock-negation-heading-2682.test.ts), ran the suite myself (npx vitest run: 35 files / 929 tests green; scripts/test-in-deployed-shape.sh: 35/35 files, 929/929, typecheck: ok), and probed the reader with my own cases against the head (scratch harness outside the repo; no writes to the branch).

What holds, verified: the #209 shape parses to ZERO findings; a real BLOCKER B1: line in an APPROVE still blocks; ## Blockers / ### Blockers / ## Open blockers / ## Blockers (open) still supply severity; ## Blockers + None. is clean; the four real-approval corpora pass; the attack-set fixture asserts its lines do not count; Leg 4b sits after every existing refusal and no existing refusal text changed; the PR body names the lets-through list verbatim. Criteria 3, 4, 5, 6 and 7 are met.

Blockers

  • B1: high — the surviving mid-sentence (blocker) / [blocker] anchor still parses PROSE as a finding, so criterion 1 is not met. BLOCKER_FINDING_PATTERNS keeps /[\[(]\s*blockers?\s*[\])]/i, which is not section-scoped and not label-anchored: measured at this head, in an APPROVE comment, I checked whether the (blocker) tag applies to this line; on reflection it does not — treat it as a follow-up. yields one open id-less finding, and so does The census prints [blocker] in its column header, which is cosmetic only. The PR removes the severity: blocker mid-sentence anchor for exactly this reason and states "prose and labels never parse", but this sibling survives and refuses a landable PR on a cosmetic sentence — the #209 failure mode itself. The parenthetical form is worth keeping for the fleet's **Blocker (B1)** label, but only bound to label position, not free text.
  • B2: high — the isVerdictShaped boundary produces FALSE REFUSALS on ordinary discussion comments, so criterion 2's "ordinary discussion comments must never trip this" is not met. Measured at this head with a clean exact-head APPROVE alongside, each of these returns no-verdict-block: ## Approval notes as a heading; a first line Approval is blocked until the census names the session, which is upstream of this diff. (the subject test ^(verdict|approval)\b catches both); ## Final approval checklist containing (I am not posting a verdict.) (the disclaimer is in the body paragraph — DISCLAIMER_RE is tested only on statement[0]); and a documentation comment ## Verdict grammar / The lock reads a verdict heading plus a head pin. (the suite's discussion fixture passes only because its body happens to carry a literal verdict: approved and a head: pin, which land it in the ledger's unpinned bucket). A false refusal is worse than the misread it replaces: it makes a reviewed PR unlandable for a sentence nobody meant as a verdict.
  • B3: high — the malformed-## Blockers refusal has no remedy leg, and its own advice contradicts standing ruling 8. Measured at this head: one APPROVE comment carrying ## Blockers immediately followed by ## Concerns refuses the lock while two clean exact-head verdicts are present, and assessFindingGrammar reports the same malformed-blockers problem at a different head (…bbbb…) — the condition is head-independent, so it is permanent. The refusal ends The author of the comment must fix it: no one posts or edits a verdict on a reviewer's behalf (ruling 8), and ruling 8 forbids editing or deleting a PR comment to get past the lock: the PR is bricked with no action available to anyone. The ruling asks the lock to refuse; it does not ask the refusal to be unremediable. A later readable block from the same author/session should supersede the malformed one (the HOMELAB-2411 supersession pattern this module already has), or the leg should name a remedy that ruling 8 permits.

Concerns

  • C-1: stale docblocks in the function a future reader will trust. assessFindingGrammar's JSDoc says the arm is gated on isReviewVerdict — "the same recognition the lock uses for approvals" — while the code gates on isVerdictShaped; and isVerdictShaped's own docblock lists ## Review… among the heading forms it recognises, which the code deliberately excludes (#660). Both will mislead the next person who widens this boundary.
  • C-2: the named controls the PR body cites as measured (infra-core #660/#670/#694, pi-extensions #79, GITS #115) are not pinned for the NEW predicate: no reference to any of them exists in landing-finding-rule-2682.test.ts, and the existing fixtures exercise isReviewVerdict, not isVerdictShaped. So "the boundary is tested both ways" rests on synthetic shapes only — and B2 is the cost: real non-verdict shapes still trip it. Please pin those four real comments (or their verbatim first blocks) as isVerdictShaped === false.
  • C-3: judgement asked for on the kept supersets. ### Blockers, ## Open blockers, ## Blockers (open), and the qualifier list (## All blockers, ## Known blockers) are NOT a hole: they only ADD lines to form 2, never subtract, and a section that names blockers is a blockers section — consistent with the ruling's intent. The (blocker)-in-label keep is a different animal: it is not section-scoped, so it matches free prose anywhere (B1). Keeping it unbound is a hole, not a superset.
  • C-4: malformed ## Blockers in a NON-verdict-shaped comment is silent (## Notes… ## Blockers with an empty section returns no problem). That matches the acceptance wording's "verdict-shaped" qualifier, so I am not blocking on it, but it is the fail-open half: a reviewer whose comment opens with a normal sentence and carries an empty section reports zero.
  • C-5: BLOCKER<B1>: and (BLOCKER) … do block, but both key id-less ((no-id)), which only the canonical resolution sentence can close; BLOCKER B1 with no colon keeps the id. Not gating — pre-existing id-less class — recorded so the next reader knows it was seen.
  • C-6: what I could not verify in budget: I did not replay the census (forgejo_landing_census) over live PRs to measure the new leg's false-refusal rate in the field; the numbers above are from constructed streams at the head's own API surface.
**Verdict of record — ld-reviewer — head ac9aec08c90a6ba1e19b53f3bb813fde6a25a094: REQUEST_CHANGES** model: deepseek-flash session: ses-108-seat1-7f3c1a9d Reviewed the diff at this exact head (`forgejo/landing.ts`, `forgejo/tests/landing-finding-rule-2682.test.ts`, `forgejo/tests/fixtures/prose-attack-corpus.json`, `forgejo/tests/lock-negation-heading-2682.test.ts`), ran the suite myself (`npx vitest run`: 35 files / 929 tests green; `scripts/test-in-deployed-shape.sh`: 35/35 files, 929/929, `typecheck: ok`), and probed the reader with my own cases against the head (scratch harness outside the repo; no writes to the branch). What holds, verified: the #209 shape parses to ZERO findings; a real `BLOCKER B1:` line in an APPROVE still blocks; `## Blockers` / `### Blockers` / `## Open blockers` / `## Blockers (open)` still supply severity; `## Blockers` + `None.` is clean; the four real-approval corpora pass; the attack-set fixture asserts its lines do not count; Leg 4b sits after every existing refusal and no existing refusal text changed; the PR body names the lets-through list verbatim. Criteria 3, 4, 5, 6 and 7 are met. ## Blockers - B1: high — the surviving mid-sentence `(blocker)` / `[blocker]` anchor still parses PROSE as a finding, so criterion 1 is not met. `BLOCKER_FINDING_PATTERNS` keeps `/[\[(]\s*blockers?\s*[\])]/i`, which is not section-scoped and not label-anchored: measured at this head, in an APPROVE comment, `I checked whether the (blocker) tag applies to this line; on reflection it does not — treat it as a follow-up.` yields one open id-less finding, and so does `The census prints [blocker] in its column header, which is cosmetic only.` The PR removes the `severity: blocker` mid-sentence anchor for exactly this reason and states "prose and labels never parse", but this sibling survives and refuses a landable PR on a cosmetic sentence — the #209 failure mode itself. The parenthetical form is worth keeping for the fleet's `**Blocker (B1)**` label, but only bound to label position, not free text. - B2: high — the `isVerdictShaped` boundary produces FALSE REFUSALS on ordinary discussion comments, so criterion 2's "ordinary discussion comments must never trip this" is not met. Measured at this head with a clean exact-head APPROVE alongside, each of these returns `no-verdict-block`: `## Approval notes` as a heading; a first line `Approval is blocked until the census names the session, which is upstream of this diff.` (the subject test `^(verdict|approval)\b` catches both); `## Final approval checklist` containing `(I am not posting a verdict.)` (the disclaimer is in the body paragraph — `DISCLAIMER_RE` is tested only on `statement[0]`); and a documentation comment `## Verdict grammar` / `The lock reads a verdict heading plus a head pin.` (the suite's discussion fixture passes only because its body happens to carry a literal `verdict: approved` and a `head:` pin, which land it in the ledger's `unpinned` bucket). A false refusal is worse than the misread it replaces: it makes a reviewed PR unlandable for a sentence nobody meant as a verdict. - B3: high — the malformed-`## Blockers` refusal has no remedy leg, and its own advice contradicts standing ruling 8. Measured at this head: one APPROVE comment carrying `## Blockers` immediately followed by `## Concerns` refuses the lock while two clean exact-head verdicts are present, and `assessFindingGrammar` reports the same `malformed-blockers` problem at a different head (`…bbbb…`) — the condition is head-independent, so it is permanent. The refusal ends `The author of the comment must fix it: no one posts or edits a verdict on a reviewer's behalf (ruling 8)`, and ruling 8 forbids editing or deleting a PR comment to get past the lock: the PR is bricked with no action available to anyone. The ruling asks the lock to refuse; it does not ask the refusal to be unremediable. A later readable block from the same author/session should supersede the malformed one (the HOMELAB-2411 supersession pattern this module already has), or the leg should name a remedy that ruling 8 permits. ## Concerns - C-1: stale docblocks in the function a future reader will trust. `assessFindingGrammar`'s JSDoc says the arm is gated on `isReviewVerdict` — "the same recognition the lock uses for approvals" — while the code gates on `isVerdictShaped`; and `isVerdictShaped`'s own docblock lists `## Review…` among the heading forms it recognises, which the code deliberately excludes (#660). Both will mislead the next person who widens this boundary. - C-2: the named controls the PR body cites as measured (infra-core #660/#670/#694, pi-extensions #79, GITS #115) are not pinned for the NEW predicate: no reference to any of them exists in `landing-finding-rule-2682.test.ts`, and the existing fixtures exercise `isReviewVerdict`, not `isVerdictShaped`. So "the boundary is tested both ways" rests on synthetic shapes only — and B2 is the cost: real non-verdict shapes still trip it. Please pin those four real comments (or their verbatim first blocks) as `isVerdictShaped === false`. - C-3: judgement asked for on the kept supersets. `### Blockers`, `## Open blockers`, `## Blockers (open)`, and the qualifier list (`## All blockers`, `## Known blockers`) are NOT a hole: they only ADD lines to form 2, never subtract, and a section that names blockers is a blockers section — consistent with the ruling's intent. The `(blocker)`-in-label keep is a different animal: it is not section-scoped, so it matches free prose anywhere (B1). Keeping it unbound is a hole, not a superset. - C-4: malformed `## Blockers` in a NON-verdict-shaped comment is silent (`## Notes… ## Blockers` with an empty section returns no problem). That matches the acceptance wording's "verdict-shaped" qualifier, so I am not blocking on it, but it is the fail-open half: a reviewer whose comment opens with a normal sentence and carries an empty section reports zero. - C-5: `BLOCKER<B1>:` and `(BLOCKER) …` do block, but both key id-less (`(no-id)`), which only the canonical resolution sentence can close; `BLOCKER B1` with no colon keeps the id. Not gating — pre-existing id-less class — recorded so the next reader knows it was seen. - C-6: what I could not verify in budget: I did not replay the census (`forgejo_landing_census`) over live PRs to measure the new leg's false-refusal rate in the field; the numbers above are from constructed streams at the head's own API surface.
HOMELAB-2682: fix(forgejo): seat-1 blockers on finding rule — prose anchor, verdict-shaped boundary, malformed-section exit
Some checks failed
CI / pr-title (pull_request) Successful in 0s
CI / mcp-bridge (pull_request) Successful in 22s
CI / forgejo-ci (pull_request) Failing after 30s
tests / python (pull_request) Successful in 5s
CI / nats-intercom (pull_request) Successful in 31s
CI / skill-args (pull_request) Successful in 38s
CI / pi-otel-telemetry (pull_request) Successful in 49s
CI / ask-user-question (pull_request) Successful in 53s
CI / refocus (pull_request) Successful in 1m0s
CI / plane (pull_request) Successful in 1m1s
CI / todo (pull_request) Successful in 1m4s
CI / redact (pull_request) Successful in 48s
CI / pi-friction (pull_request) Successful in 54s
CI / forgejo (pull_request) Successful in 1m57s
CI / pi-swarm-suite (pull_request) Successful in 3m33s
77ec5113cc
HOMELAB-2682: ci(forgejo): re-trigger CI — forgejo-ci died in npm ci (esbuild ETXTBSY), no code change
All checks were successful
CI / pr-title (pull_request) Successful in 1s
CI / forgejo-ci (pull_request) Successful in 48s
CI / skill-args (pull_request) Successful in 50s
CI / pi-otel-telemetry (pull_request) Successful in 53s
CI / todo (pull_request) Successful in 54s
CI / ask-user-question (pull_request) Successful in 53s
tests / python (pull_request) Successful in 5s
CI / nats-intercom (pull_request) Successful in 18s
CI / plane (pull_request) Successful in 1m10s
CI / mcp-bridge (pull_request) Successful in 23s
CI / refocus (pull_request) Successful in 45s
CI / redact (pull_request) Successful in 49s
CI / pi-friction (pull_request) Successful in 51s
CI / forgejo (pull_request) Successful in 1m44s
CI / pi-swarm-suite (pull_request) Successful in 3m56s
247aecb7af
Collaborator

Verdict of record — ld-reviewer — head 247aecb7af: APPROVE
model: deepseek-flash
session: ses-108r2-seat1-7d3f91c4

Round 2, seat 1. I read the diff 34fdf7f..247aecb (forgejo/landing.ts, tests/landing-finding-rule-2682.test.ts, tests/fixtures/prose-attack-corpus.json, tests/fixtures/verdict-shaped-controls.json, tests/lock-negation-heading-2682.test.ts, docs/forgejo.md), ran the suite myself at this head, pinned the five real controls against the API, and probed the reader with my own harness outside the repo (no writes to the branch).

Round-1 blockers (comment 22711), each reproduced first-hand at 247aecb and against 34fdf7f / ac9aec08 for baseline:

  • B1 — closed. The mid-sentence parenthetical is no longer an anchor: both of my measured lines report zero findings at this head (one id-less finding each at 34fdf7f and at ac9aec08). (blocker) / (BLOCKER) standing alone outside a section also report zero; the label rules still count ## Blockers + - (blocker) — …, ### GITS35-R1 (blocker) — …, **B1 (blocker)** — …, 1. (blocker) — …. BLOCKER<B1>: reports nothing, BLOCKER B1: / BLOCKER: still block (C-5 pinned, verified).
  • B2 — closed. All four of my measured shapes are isVerdictShaped === false and refuse nothing (## Approval notes; first line Approval is blocked until …; ## Final approval checklist with the body disclaimer; ## Verdict grammar). Genuine attempts still refuse: ## Verdict + prose, ## Final verdict, **Verdict of record … head**, **REQUEST_CHANGES at <sha>**, ## Approval:, ## Verdict (round 2), ## Verdict for head <sha>. The disclaimer is now read over the whole statement block and not posting a verdict fires.
  • B3 — closed, both ways, measured: an empty ## Blockers with only a DIFFERENT reviewer's later exact-head approval still refuses and the refusal names the exit; a later clean exact-head verdict from the SAME reviewer lifts it (superseded reports comment #2 (malformed-blockers) is superseded by …), and the lock then permits on a routine-class input; two malformed comments do not cure each other; a later verdict pinned to another head does not lift; a malformed comment posted AFTER the clean one leaves the refusal standing (only a later word cures).

Controls (C-2): the five bodies in verdict-shaped-controls.json are verbatim against the live API — I re-fetched 16013, 16401, 17451, 19896 and 19267 and compared body, author and timestamp (all exact). Four are false; GITS #115 (19267) is pinned true and that is CORRECT: it really is ## Verdict: APPROVED with model: and head:, i.e. a readable verdict that must not be refused. Pinning the measurement rather than the wish is the right call.

Must-still-hold, all re-verified at this head: the GITS #209 shape (### Findings + four RISK-n follow-ups, three ld-reviewer approvals) is 0 findings and the lock permits; a real BLOCKER B1: … line inside an APPROVE still blocks; ## Blockers + None. is clean; severity-tokened statements (BLOCKER none. vs BLOCKER none of the tests ran.) behave as #107 says; the attack fixture's 13 lets-through lines still count for nothing; the four approval corpora pass. Suite: npx vitest run → 35 files / 944 tests green; scripts/test-in-deployed-shape.sh → 35/35 files, 944/944, typecheck: ok, pinned typebox 1.3.34. CI on this head: 15/15 contexts success. The PR body's numbers are honest.

C-6 (which the fix round did not do), done here as my own replay: I pulled every comment + formal review of the 53 currently OPEN PRs across pi-extensions, infra-core, ghostty-in-the-shell, prod and lab-director (147 items) and assessed each against its own head — 0 grammar problems, so the new legs' field false-refusal rate on live PRs is zero today. Over 500 historical comments the leg fires 13 times (2.6%), every one on a closed/merged PR and every one the operator's older ## Landing review — … note; no live PR is affected.

Blockers

None.

Concerns

  • C-1: the B2 narrowing has a fail-open half that the PR body does not name. ## Verdict summary + REQUEST_CHANGES — I do not want this merged. (no head) is isVerdictShaped === false at this head, and the lock PERMITS with one other seat's approval; at ac9aec08 the same comment was shaped true and refused. Same for ## Approval verdict, ## Approval notice: …, ## APPROVE, ## Approved. Nothing decidable is lost — the ledger path is untouched, so a readable stance+head is still read — what is lost is the loud refusal of an unreadable one, and that is the direction I asked for in round 1. Please add those three titles to the "what the new rule lets through" list in the PR body next to the 13 prose lines, so the trade is on the record like the finding-rule one is.
  • C-2: one prose anchor still parses findings, unchanged from 34fdf7f (so not a regression, but it contradicts a body sentence). A line whose FIRST word is the bare noun is a finding: - blocker: nothing — the guard only prints., Blocker (nothing): …, **blocker** found nothing in the diff; recorded as a follow-up. each yield one id-less finding in an APPROVE — verified one finding each at 34fdf7f, ac9aec08 and here. Id-less means the canonical resolution sentence can close it, and the PR does document form 3 as "the line-initial severity token", so this is a documented superset; but "no vocabulary anchoring outside those three forms" reads as broader than the code. Worth one sentence in the docs and the body rather than a code change.
  • C-3: the malformed-section arm does not consult the module's own documentation guard. A verdict-shaped comment that QUOTES the required template in a blockquote refuses:
## Blockers

None.

## What the lock wants

> ## Blockers
>
> - <finding-id>: <severity> — <finding>

reports malformed-blockers (the same content inside a code fence is correctly ignored). isBlockerDocumentation exists precisely so that "documenting the blocker heading does not block every PR that quotes the docs"; this arm reaches the placeholder without it. The exit now exists, so it is a delay and not a brick — but a verdict-shaped comment quoting the grammar is a plausible shape for a reviewer explaining what it wants fixed.

  • C-4: the author-only fallback, measured exactly as asked. A malformed comment that declares no model: is lifted by any LATER exact-head verdict from the same login on any model and any session: — I measured a different model and a different session lifting it. That is consistent with the module's identity model (model:/session: are self-declarations, nothing binds them to the poster either), and the alternative strands exactly the comments B3 measured, so I accept it; recording it so the next reader knows the login is the whole bar when a comment declares nothing.
  • C-5: byItem is keyed by the numeric id alone, while Forgejo comment ids and review ids are separate sequences. A comment and a review that happen to share an id would be judged together: the cure lookup would refuse a legal cure (fail-closed, harmless) and the refusal text could name the wrong row. Not observed in the replay; one line of kind:id keying would close it.
  • C-6: pre-existing and untouched — ## Blockers (open) + None. yields one id-less finding today, exactly as it does at 34fdf7f and ac9aec08, while ## Blockers + None. is clean. Not this PR's defect; noted because the suite pins the plain spelling only.

resolved B1 — the parenthetical anchor is label-scoped; mid-sentence prose reports zero at this head.
resolved B2 — the verdict-shaped boundary no longer refuses ordinary discussion; my four shapes are false.
resolved B3 — the per-comment refusal has a lawful exit, and I measured it lifting and standing in both directions.

This seat's approval is one of the two the dangerous panel needs; I did not touch the branch, and no one posts the second seat's verdict for it.

**Verdict of record — ld-reviewer — head 247aecb7af87f8b7eeb267fbf244290c00d9962c: APPROVE** model: deepseek-flash session: ses-108r2-seat1-7d3f91c4 Round 2, seat 1. I read the diff `34fdf7f..247aecb` (`forgejo/landing.ts`, `tests/landing-finding-rule-2682.test.ts`, `tests/fixtures/prose-attack-corpus.json`, `tests/fixtures/verdict-shaped-controls.json`, `tests/lock-negation-heading-2682.test.ts`, `docs/forgejo.md`), ran the suite myself at this head, pinned the five real controls against the API, and probed the reader with my own harness outside the repo (no writes to the branch). Round-1 blockers (comment 22711), each reproduced first-hand at `247aecb` and against `34fdf7f` / `ac9aec08` for baseline: - B1 — closed. The mid-sentence parenthetical is no longer an anchor: both of my measured lines report zero findings at this head (one id-less finding each at `34fdf7f` and at `ac9aec08`). `(blocker)` / `(BLOCKER)` standing alone outside a section also report zero; the label rules still count `## Blockers` + `- (blocker) — …`, `### GITS35-R1 (blocker) — …`, `**B1 (blocker)** — …`, `1. (blocker) — …`. `BLOCKER<B1>:` reports nothing, `BLOCKER B1:` / `BLOCKER:` still block (C-5 pinned, verified). - B2 — closed. All four of my measured shapes are `isVerdictShaped === false` and refuse nothing (`## Approval notes`; first line `Approval is blocked until …`; `## Final approval checklist` with the body disclaimer; `## Verdict grammar`). Genuine attempts still refuse: `## Verdict` + prose, `## Final verdict`, `**Verdict of record … head**`, `**REQUEST_CHANGES at <sha>**`, `## Approval:`, `## Verdict (round 2)`, `## Verdict for head <sha>`. The disclaimer is now read over the whole statement block and `not posting a verdict` fires. - B3 — closed, both ways, measured: an empty `## Blockers` with only a DIFFERENT reviewer's later exact-head approval still refuses and the refusal names the exit; a later clean exact-head verdict from the SAME reviewer lifts it (`superseded` reports `comment #2 (malformed-blockers) is superseded by …`), and the lock then permits on a routine-class input; two malformed comments do not cure each other; a later verdict pinned to another head does not lift; a malformed comment posted AFTER the clean one leaves the refusal standing (only a later word cures). Controls (C-2): the five bodies in `verdict-shaped-controls.json` are verbatim against the live API — I re-fetched 16013, 16401, 17451, 19896 and 19267 and compared body, author and timestamp (all exact). Four are `false`; GITS #115 (19267) is pinned `true` and that is CORRECT: it really is `## Verdict: APPROVED` with `model:` and `head:`, i.e. a readable verdict that must not be refused. Pinning the measurement rather than the wish is the right call. Must-still-hold, all re-verified at this head: the GITS #209 shape (`### Findings` + four `RISK-n` follow-ups, three `ld-reviewer` approvals) is 0 findings and the lock permits; a real `BLOCKER B1: …` line inside an APPROVE still blocks; `## Blockers` + `None.` is clean; severity-tokened statements (`BLOCKER none.` vs `BLOCKER none of the tests ran.`) behave as #107 says; the attack fixture's 13 lets-through lines still count for nothing; the four approval corpora pass. Suite: `npx vitest run` → **35 files / 944 tests green**; `scripts/test-in-deployed-shape.sh` → 35/35 files, 944/944, `typecheck: ok`, pinned typebox 1.3.34. CI on this head: 15/15 contexts success. The PR body's numbers are honest. C-6 (which the fix round did not do), done here as my own replay: I pulled every comment + formal review of the 53 currently OPEN PRs across `pi-extensions`, `infra-core`, `ghostty-in-the-shell`, `prod` and `lab-director` (147 items) and assessed each against its own head — **0 grammar problems**, so the new legs' field false-refusal rate on live PRs is zero today. Over 500 historical comments the leg fires 13 times (2.6%), every one on a closed/merged PR and every one the operator's older `## Landing review — …` note; no live PR is affected. ## Blockers None. ## Concerns - C-1: the B2 narrowing has a fail-open half that the PR body does not name. `## Verdict summary` + `REQUEST_CHANGES — I do not want this merged.` (no head) is `isVerdictShaped === false` at this head, and the lock PERMITS with one other seat's approval; at `ac9aec08` the same comment was shaped true and refused. Same for `## Approval verdict`, `## Approval notice: …`, `## APPROVE`, `## Approved`. Nothing decidable is lost — the ledger path is untouched, so a readable stance+head is still read — what is lost is the loud refusal of an unreadable one, and that is the direction I asked for in round 1. Please add those three titles to the "what the new rule lets through" list in the PR body next to the 13 prose lines, so the trade is on the record like the finding-rule one is. - C-2: one prose anchor still parses findings, unchanged from `34fdf7f` (so not a regression, but it contradicts a body sentence). A line whose FIRST word is the bare noun is a finding: `- blocker: nothing — the guard only prints.`, `Blocker (nothing): …`, `**blocker** found nothing in the diff; recorded as a follow-up.` each yield one id-less finding in an APPROVE — verified one finding each at `34fdf7f`, `ac9aec08` and here. Id-less means the canonical resolution sentence can close it, and the PR does document form 3 as "the line-initial severity token", so this is a documented superset; but "no vocabulary anchoring outside those three forms" reads as broader than the code. Worth one sentence in the docs and the body rather than a code change. - C-3: the malformed-section arm does not consult the module's own documentation guard. A verdict-shaped comment that QUOTES the required template in a blockquote refuses: ``` ## Blockers None. ## What the lock wants > ## Blockers > > - <finding-id>: <severity> — <finding> ``` reports `malformed-blockers` (the same content inside a code fence is correctly ignored). `isBlockerDocumentation` exists precisely so that "documenting the blocker heading does not block every PR that quotes the docs"; this arm reaches the placeholder without it. The exit now exists, so it is a delay and not a brick — but a verdict-shaped comment quoting the grammar is a plausible shape for a reviewer explaining what it wants fixed. - C-4: the author-only fallback, measured exactly as asked. A malformed comment that declares no `model:` is lifted by any LATER exact-head verdict from the same login on any model and any `session:` — I measured a different model and a different session lifting it. That is consistent with the module's identity model (`model:`/`session:` are self-declarations, nothing binds them to the poster either), and the alternative strands exactly the comments B3 measured, so I accept it; recording it so the next reader knows the login is the whole bar when a comment declares nothing. - C-5: `byItem` is keyed by the numeric id alone, while Forgejo comment ids and review ids are separate sequences. A comment and a review that happen to share an id would be judged together: the cure lookup would refuse a legal cure (fail-closed, harmless) and the refusal text could name the wrong row. Not observed in the replay; one line of `kind:id` keying would close it. - C-6: pre-existing and untouched — `## Blockers (open)` + `None.` yields one id-less finding today, exactly as it does at `34fdf7f` and `ac9aec08`, while `## Blockers` + `None.` is clean. Not this PR's defect; noted because the suite pins the plain spelling only. `resolved B1` — the parenthetical anchor is label-scoped; mid-sentence prose reports zero at this head. `resolved B2` — the verdict-shaped boundary no longer refuses ordinary discussion; my four shapes are `false`. `resolved B3` — the per-comment refusal has a lawful exit, and I measured it lifting and standing in both directions. This seat's approval is one of the two the dangerous panel needs; I did not touch the branch, and no one posts the second seat's verdict for it.
Collaborator

Verdict of record — ld-reviewer — head 247aecb7af: REQUEST_CHANGES

model: deepseek-flash
session: ses-108r2-seat2-9c4e1a

Seat 2 of 2, round 2. I read nothing of seat 1's round-2 verdict before forming this one. Everything below is measured myself at 247aecb (forgejo/ with npm ci), by importing the head's own landing.ts and feeding it bodies; no file was edited, committed or pushed.

Blockers

  • B1: high — the added no-verdict-block leg cannot fire for the case its own contract names ("a stance whose head cannot be pinned"), so an explicit REQUEST_CHANGES at the exact head is read as unpinned evidence and the lock PERMITS with a clean APPROVE next to it. Measured at 247aecb, evaluateLandingLock → ok: true, pass note names only the approve, hold never cited:

    • verdict: request_changes / head: <40-hex> / model: / session: on four lines — the module's own documented legacy machine form (## verdict grammar migration, the verdict: approved + model: + head: block) — plus one clean exact-head APPROVE → ok: true. buildVerdictLedger puts it in unpinned with polarity: "hold".
    • same outcome: **Verdict: REQUEST_CHANGES** + head: <sha>; **Verdict** + head: <sha> + REQUEST_CHANGES; **Verdict of record — ld-reviewer** + head: <sha> + REQUEST_CHANGES; **Verdict summary** / **Approval verdict** / **Verdict of the round** + REQUEST_CHANGES at <sha>.
    • cause, named: findingGrammarAssessment does for (const v of ledger.unpinned) covered.add(...) — unpinned counts as readable cover, so arm 1 skips exactly its own definition. The deeper half is verdictStatementLines: for a first line that is not a # heading it returns that line alone, so the head: / stance lines beneath it are never read, which is what puts the verdict in unpinned in the first place. ## Verdict + the same body refuses correctly (1 exact-head hold(s) are open) — the hole is the non-heading statement.
    • the code contradicts three of its own statements: the FindingGrammarProblem.kind doc ("no stance, or a stance whose head cannot be pinned"), the refusal text this PR adds, and docs/forgejo.md step 5 added by this PR ("a comment that is VERDICT-SHAPED … but carries no readable verdict block refuses the lock with the reason named"). That case is unreachable.
    • direction of a fix, not a design: fire arm 1 when the only cover is unpinned and the unpinned rationale is "no head pinned in its statement block" — the label-shaped unpinned rows (session: missing/blank, which the existing refusals already name) must stay non-refusing — or read the label block under a verdict-shaped non-heading first line the way a heading is read. Do not widen to all unpinned: the round-2 false refusals would come back.
    • both directions measured so the fix does not over-shoot: replaying 88 real comments across 19 open PRs in pi-extensions, infra-core, ghostty-in-the-shell and prod at this head gives 0 no-verdict-block, 0 malformed-blockers — the narrowing is right on real text. One real item already sits in the class above: prod#1109 comment 20295 (HOLD — … DO NOT MERGE) is an unpinned hold, decides nothing, and a passing lock would not name it.

Concerns

  • C-1: a blockquoted reproduction of the seat template trips malformed-blockers. An APPROVE whose body contains > ## Blockers / > - <finding-id>: <severity> — <finding> refuses (measured). The fenced spelling is correctly ignored, so the fence is the documented way out, but seats quote templates in guidance and the quoting comment is the reviewer's own passing verdict — the exit is then a further same-reviewer exact-head verdict. Recommend skipping blockquoted content in blockersSections exactly as fencedLines is skipped.
  • C-2: byItem is keyed by itemId alone while covered and indexOf are keyed kind:id. Forgejo review ids and comment ids are separate sequences, so a comment #N and a review #N can coexist. Reproduced with both at id 7: the refusal lists the same problem twice, and the legal exit from B3 dies — a later same-author clean review #7 cannot supersede comment #7, while review #8 or comment #78 cures normally. The collision only suppresses a cure (fail-closed), but it re-opens "a refusal with no exit", the exact brick B3 closed. Key by kind:id.
  • C-3: supersession spoofing — accepted as designed. For a comment that declares no model:, ownLaterWord compares the author only, so a different model and a different session on the same ld-reviewer login lifts the refusal (measured). That is defensible: the login is the trusted identity, a seat sharing it could equally post its own hold, and a lift never decides anything — the curing row still counts once as its own stance. Recording it so the next reader knows it was judged, not missed.
  • C-4: the fail-open half of the narrowed VERDICT_NAME_RE — ## Verdict summary, ## Approval verdict, ## My verdict, ## Verdict of the round, ## Verdict and blockers, ## Reviewer verdict, **Verdict summary** are all isVerdictShaped === false. Judged not a finding on its own: with a # heading the ledger still reads the stance and the lock refuses on the hold (measured for every one of them), and no real body depends on the retired bare-noun first-word test — over the 88-item census replay and all five fixture corpora, oldLoose && !newShaped is 0. It only bites where the ledger misses the stance too, which is B1.
  • C-5: assessFindingGrammar(items) with no headSha builds no ledger and therefore flags every verdict-shaped comment (74 of 88 in the replay). Unreachable from evaluateLandingLock, but it is a live footgun for any other caller of the exported function: require the head, or document that shape-only mode means "every verdict is unreadable".

Verified first-hand (what the PR claims, checked)

  • Ruling acceptance. GITS #209's three real comment bodies replayed at head 092174e: findOpenBlockers → [], assessFindingGrammar → [], evaluateLandingLock → ok: true. BLOCKER B1: … inside an APPROVE still blocks; ## Blockers + None. is clean; the 13 prose attack lines count nothing (fixture re-run in the suite); ## Findings / ## No blockers. supply nothing.
  • Suite. npx vitest run → 35 files / 944 tests, all pass. scripts/test-in-deployed-shape.sh → ok: 35/35 files loaded and passed, 944/944 tests, pinned tree 1.3.34, typecheck: ok. Both claims in the PR body are true.
  • B1 (round-1) closed. Mid-sentence (blocker) / [blocker] prose → 0 findings; - (blocker) — … under ## Blockers and ### GITS35-R1 (blocker) — … still count; BLOCKER<B1>: counts nothing.
  • B2 (round-1) closed. ## Approval notes, the Approval is blocked until … statement, ## Final approval checklist + (I am not posting a verdict.), ## Verdict grammar — each isVerdictShaped === false, zero problems, lock permits. Genuine attempts (## Verdict + prose, **Verdict of record … — head** with no block) still refuse.
  • B3 (round-1) closed in all three directions I could construct. malformed AFTER a clean verdict → still refused; two malformed → cure nothing; a cure on another head → lifts nothing; a cure from another author → lifts nothing; a cure that is itself malformed → lifts nothing; a later clean same-reviewer exact-head verdict → problems empty and the supersession is reported on the pass. (See C-2 for the one id-collision corner where the exit silently dies.)
  • Controls fixture. The five bodies are verbatim real text, and the pin for GITS #115 / comment 19267 is right: its body is ## Verdict: APPROVED with model: and head: — a real verdict, so pinning it as shaped === true, readable, no problem (rather than as a non-shape) is the honest measurement, and it is the one entry whose "answer" differs from the other four.

The ruling's substance is implemented and the round-1 blockers are genuinely closed; B1 is the fail-closed half not reaching the case it names, and it fails in the permit direction on a hold.

**Verdict of record — ld-reviewer — head 247aecb7af87f8b7eeb267fbf244290c00d9962c: REQUEST_CHANGES** model: deepseek-flash session: ses-108r2-seat2-9c4e1a Seat 2 of 2, round 2. I read nothing of seat 1's round-2 verdict before forming this one. Everything below is measured myself at `247aecb` (`forgejo/` with `npm ci`), by importing the head's own `landing.ts` and feeding it bodies; no file was edited, committed or pushed. ## Blockers - B1: high — the added `no-verdict-block` leg cannot fire for the case its own contract names ("a stance whose head cannot be pinned"), so an explicit REQUEST_CHANGES at the exact head is read as `unpinned` evidence and the lock **PERMITS** with a clean APPROVE next to it. Measured at `247aecb`, `evaluateLandingLock` → `ok: true`, pass note names only the approve, hold never cited: - `verdict: request_changes` / `head: <40-hex>` / `model:` / `session:` on four lines — **the module's own documented legacy machine form** (`## verdict grammar migration`, the `verdict: approved` + `model:` + `head:` block) — plus one clean exact-head APPROVE → `ok: true`. `buildVerdictLedger` puts it in `unpinned` with `polarity: "hold"`. - same outcome: `**Verdict: REQUEST_CHANGES**` + `head: <sha>`; `**Verdict**` + `head: <sha>` + `REQUEST_CHANGES`; `**Verdict of record — ld-reviewer**` + `head: <sha>` + `REQUEST_CHANGES`; `**Verdict summary**` / `**Approval verdict**` / `**Verdict of the round**` + `REQUEST_CHANGES at <sha>`. - cause, named: `findingGrammarAssessment` does `for (const v of ledger.unpinned) covered.add(...)` — unpinned counts as *readable cover*, so arm 1 skips exactly its own definition. The deeper half is `verdictStatementLines`: for a first line that is not a `#` heading it returns that line alone, so the `head:` / stance lines beneath it are never read, which is what puts the verdict in `unpinned` in the first place. `## Verdict` + the same body refuses correctly (`1 exact-head hold(s) are open`) — the hole is the non-heading statement. - the code contradicts three of its own statements: the `FindingGrammarProblem.kind` doc ("no stance, **or a stance whose head cannot be pinned**"), the refusal text this PR adds, and `docs/forgejo.md` step 5 added by this PR ("a comment that is VERDICT-SHAPED … but carries no readable verdict block refuses the lock with the reason named"). That case is unreachable. - direction of a fix, not a design: fire arm 1 when the only cover is `unpinned` *and* the unpinned rationale is "no head pinned in its statement block" — the label-shaped unpinned rows (`session:` missing/blank, which the existing refusals already name) must stay non-refusing — or read the label block under a verdict-shaped non-heading first line the way a heading is read. **Do not** widen to all unpinned: the round-2 false refusals would come back. - both directions measured so the fix does not over-shoot: replaying 88 real comments across 19 open PRs in `pi-extensions`, `infra-core`, `ghostty-in-the-shell` and `prod` at this head gives **0** `no-verdict-block`, **0** `malformed-blockers` — the narrowing is right on real text. One real item already sits in the class above: `prod#1109` comment 20295 (`HOLD — … DO NOT MERGE`) is an unpinned hold, decides nothing, and a passing lock would not name it. ## Concerns - C-1: a **blockquoted** reproduction of the seat template trips `malformed-blockers`. An APPROVE whose body contains `> ## Blockers` / `> - <finding-id>: <severity> — <finding>` refuses (measured). The fenced spelling is correctly ignored, so the fence is the documented way out, but seats quote templates in guidance and the quoting comment is the reviewer's own passing verdict — the exit is then a *further* same-reviewer exact-head verdict. Recommend skipping blockquoted content in `blockersSections` exactly as `fencedLines` is skipped. - C-2: `byItem` is keyed by `itemId` alone while `covered` and `indexOf` are keyed `kind:id`. Forgejo review ids and comment ids are separate sequences, so a `comment` #N and a `review` #N can coexist. Reproduced with both at id 7: the refusal lists the same problem **twice**, and the legal exit from B3 dies — a later same-author clean `review` #7 cannot supersede `comment` #7, while `review` #8 or `comment` #78 cures normally. The collision only suppresses a cure (fail-closed), but it re-opens "a refusal with no exit", the exact brick B3 closed. Key by `kind:id`. - C-3: supersession spoofing — **accepted as designed**. For a comment that declares no `model:`, `ownLaterWord` compares the author only, so a different model and a different session on the same `ld-reviewer` login lifts the refusal (measured). That is defensible: the login is the trusted identity, a seat sharing it could equally post its own hold, and a lift never decides anything — the curing row still counts once as its own stance. Recording it so the next reader knows it was judged, not missed. - C-4: the fail-open half of the narrowed `VERDICT_NAME_RE` — `## Verdict summary`, `## Approval verdict`, `## My verdict`, `## Verdict of the round`, `## Verdict and blockers`, `## Reviewer verdict`, `**Verdict summary**` are all `isVerdictShaped === false`. Judged **not** a finding on its own: with a `#` heading the ledger still reads the stance and the lock refuses on the hold (measured for every one of them), and no real body depends on the retired bare-noun first-word test — over the 88-item census replay and all five fixture corpora, `oldLoose && !newShaped` is **0**. It only bites where the ledger misses the stance too, which is B1. - C-5: `assessFindingGrammar(items)` with no `headSha` builds no ledger and therefore flags **every** verdict-shaped comment (74 of 88 in the replay). Unreachable from `evaluateLandingLock`, but it is a live footgun for any other caller of the exported function: require the head, or document that shape-only mode means "every verdict is unreadable". ## Verified first-hand (what the PR claims, checked) - **Ruling acceptance.** GITS #209's three real comment bodies replayed at head `092174e`: `findOpenBlockers` → `[]`, `assessFindingGrammar` → `[]`, `evaluateLandingLock` → `ok: true`. `BLOCKER B1: …` inside an APPROVE still blocks; `## Blockers` + `None.` is clean; the 13 prose attack lines count nothing (fixture re-run in the suite); `## Findings` / `## No blockers.` supply nothing. - **Suite.** `npx vitest run` → **35 files / 944 tests, all pass**. `scripts/test-in-deployed-shape.sh` → `ok: 35/35 files loaded and passed, 944/944 tests`, pinned tree 1.3.34, `typecheck: ok`. Both claims in the PR body are true. - **B1 (round-1) closed.** Mid-sentence `(blocker)` / `[blocker]` prose → 0 findings; `- (blocker) — …` under `## Blockers` and `### GITS35-R1 (blocker) — …` still count; `BLOCKER<B1>:` counts nothing. - **B2 (round-1) closed.** `## Approval notes`, the `Approval is blocked until …` statement, `## Final approval checklist` + `(I am not posting a verdict.)`, `## Verdict grammar` — each `isVerdictShaped === false`, zero problems, lock permits. Genuine attempts (`## Verdict` + prose, `**Verdict of record … — head**` with no block) still refuse. - **B3 (round-1) closed in all three directions I could construct.** malformed AFTER a clean verdict → still refused; two malformed → cure nothing; a cure on another head → lifts nothing; a cure from another author → lifts nothing; a cure that is itself malformed → lifts nothing; a later clean same-reviewer exact-head verdict → problems empty and the supersession is reported on the pass. *(See C-2 for the one id-collision corner where the exit silently dies.)* - **Controls fixture.** The five bodies are verbatim real text, and the pin for GITS #115 / comment 19267 is right: its body is `## Verdict: APPROVED` with `model:` and `head:` — a real verdict, so pinning it as `shaped === true`, readable, no problem (rather than as a non-shape) is the honest measurement, and it is the one entry whose "answer" differs from the other four. The ruling's substance is implemented and the round-1 blockers are genuinely closed; B1 is the fail-closed half not reaching the case it names, and it fails in the permit direction on a hold.
HOMELAB-2682: fix(forgejo): round-3 — read machine verdict statements as units, byItem key, blockquote docs
All checks were successful
CI / pr-title (pull_request) Successful in 2s
CI / forgejo-ci (pull_request) Successful in 35s
CI / pi-otel-telemetry (pull_request) Successful in 53s
CI / ask-user-question (pull_request) Successful in 37s
CI / plane (pull_request) Successful in 55s
CI / skill-args (pull_request) Successful in 53s
CI / mcp-bridge (pull_request) Successful in 20s
CI / todo (pull_request) Successful in 58s
CI / refocus (pull_request) Successful in 45s
tests / python (pull_request) Successful in 6s
CI / nats-intercom (pull_request) Successful in 22s
CI / forgejo (pull_request) Successful in 1m21s
CI / pi-friction (pull_request) Successful in 34s
CI / redact (pull_request) Successful in 36s
CI / pi-swarm-suite (pull_request) Successful in 3m57s
29c9f66c1e
Collaborator

Verdict of record — ld-reviewer — head 29c9f66c1e: APPROVE

model: deepseek-flash
session: ses-108r3-seat1-ca817ae0

Round 3, seat 1 of 2, final round. Independent seat: I read the diff 247aecb..29c9f66 (forgejo/landing.ts, forgejo/tests/landing-finding-rule-2682.test.ts, docs/forgejo.md), ran both suites myself, and probed the head's own landing.ts with bodies I wrote (scratch harness outside the repo). No file was edited, committed or pushed; I saw no other final-round verdict before forming this one.

Review 22734's blocker, sub-bullet by sub-bullet, measured at this head

  • The seven statement shapes. verdict: request_changes + head: (the module's legacy machine form), **Verdict: REQUEST_CHANGES** + head:, **Verdict** + head: + REQUEST_CHANGES, **Verdict of record — ld-reviewer** + head:, and **Verdict summary** / **Approval verdict** / **Verdict of the round** + REQUEST_CHANGES at <sha> — each one now REFUSES beside a clean APPROVE, cites #2, uses the exact-head hold language and raises no grammar problem. ## Verdict + the same body is unchanged and remains the yardstick.
  • Fail closed where the head cannot be pinned. verdict: request_changes with no head → no-verdict-block, refusal names #2 and the missing head: pin. A well-formed machine verdict: approve + head: is now an approval of record (permits alone); a stance pinned to ANOTHER head stays superseded and refuses nothing.
  • Both halves of the cause. The diff reads the label block under a non-heading opener (opensVerdictStatement) and stops counting ledger.unpinned as grammar cover unless the row is not a hold (if (v.polarity !== "hold")). Either half alone leaves a hole; both are present.
  • The contract text now matches the reachable behaviour. The FindingGrammarProblem.kind doc, the refusal detail this PR adds and docs/forgejo.md step 5 all say "a HOLD whose head cannot be pinned", and that case is reachable — measured.
  • The fix direction the seat named, honoured, no widening. An unpinned APPROVE still refuses nothing (prod#1023's APPROVE (head not recorded) note beside a real approval: permits); label-shaped rows are untouched by this arm (## Verdict: REQUEST_CHANGES + model + head with no session: stays out of it, and an APPROVE missing its session is unlabelled, refused by the verdict leg, not this one).
  • No overshoot on real text — my own census, not the worker's. Every OPEN PR of pi-extensions, infra-core, ghostty-in-the-shell, prod and lab-director (56 PRs, 151 comment/review/inline items), each assessed at its own head with BOTH heads' code: no-verdict-block 0 → 2, malformed-blockers 0 → 0, open findings 53 → 53. Only two rows moved: infra-core#754 comment 20294 and prod#1109 comment 20295 — both the operator's own HOLD — parked … DO NOT MERGE notes, unpinned. That is correct behaviour, not a false refusal: a hold can only ever refuse, and the seat's own replay already listed prod#1109 as a member of exactly this class. The exits are a head: pin or a later exact-head verdict from the same author.

The two named guards, on the real bodies (fetched from the API, not reconstructed): infra-core#694 comment 17451 → readVerdictStance null, no findings, permits, identical at 247aecb; infra-core#664 comment 16105 → stance approve, NOT flipped to a hold by the "do not land on it alone" caveat, permits, identical at 247aecb.

The round-2 concerns. C-1: a blockquoted template (> ## Blockers, > - <finding-id>: …) refuses nothing and the lock permits, in both arms (the quoted heading is no longer read as a section, and the quoted placeholder raises no finding); fenced spelling unchanged; CONTROL — the real placeholder section and the real empty ## Blockers still refuse with malformed-blockers. C-2: comment #7 + review #7 list their problem ONCE, the same reviewer's later clean review #7 cures it, another author's does not.

Ruling acceptance, re-measured. GITS #209's shape (three ld-reviewer approvals, one carrying ### Findings + four RISK-n follow-ups) → 0 findings, grammar clean, lock permits. A real BLOCKER B1: line inside an APPROVE still blocks. ## Blockers + None. is clean; ### Findings supplies no severity. The round-2 false-refusal shapes (## Approval notes, Approval is blocked until …, ## Final approval checklist + the disclaimer, ## Verdict grammar) are not verdict-shaped and refuse nothing. The attack fixture is unchanged by this round.

Suite and CI. npx vitest run → 35 files / 963 tests, all pass. scripts/test-in-deployed-shape.sh → 35/35 files, 963/963, pinned tree 1.3.34, typecheck: ok. CI on this head: 15/15 contexts success. The PR body's numbers are honest.

Blockers

None.

Concerns

  • C-1: a head-pinned APPROVE that declares model: but no session: lands in exactHead/trusted and permits on its own, while the lock's own refusal text says a row that declares one label without the other "is unpinned evidence and counts for nothing". Measured identical at 247aecb, so this is pre-existing and not a regression of this diff, and the dangerous-class panel still refuses two such rows — but for a routine change one such row is the whole panel. Either the label leg should name it or the text should say what the code does. Follow-up, not a blocker for this PR.
  • C-2: the round-3 worker log's residual 1 states that the only lawful exit from the id-less findings on this PR is a later exact-head verdict from the same session. That is wrong about the design, and the code is the better answer: the canonical sentence closes them, BOUND to the review that raised them — The blockers raised in review 22734 are resolved on head 29c9f66c… → findOpenBlockers 0 (4 before it), while the same sentence naming 22711 closes nothing and the lock still refuses with all four listed. The PR body states this correctly; only the worker log is off, and it would leave the orchestrator believing nobody but that session can unblock.

Each sub-bullet of review 22734 is addressed by the round-3 diff, on evidence measured at this head, so this verdict carries the closure sentence the lock asks for (verified to leave findOpenBlockers at zero naming 22734 and at four naming anything else).

The blockers raised in review 22734 are resolved on head 29c9f66c1e.

**Verdict of record — ld-reviewer — head 29c9f66c1eb8c0aac3d257ecaeea4f072edc7800: APPROVE** model: deepseek-flash session: ses-108r3-seat1-ca817ae0 Round 3, seat 1 of 2, final round. Independent seat: I read the diff `247aecb..29c9f66` (`forgejo/landing.ts`, `forgejo/tests/landing-finding-rule-2682.test.ts`, `docs/forgejo.md`), ran both suites myself, and probed the head's own `landing.ts` with bodies I wrote (scratch harness outside the repo). No file was edited, committed or pushed; I saw no other final-round verdict before forming this one. **Review 22734's blocker, sub-bullet by sub-bullet, measured at this head** - *The seven statement shapes.* `verdict: request_changes` + `head:` (the module's legacy machine form), `**Verdict: REQUEST_CHANGES**` + `head:`, `**Verdict**` + `head:` + `REQUEST_CHANGES`, `**Verdict of record — ld-reviewer**` + `head:`, and `**Verdict summary**` / `**Approval verdict**` / `**Verdict of the round**` + `REQUEST_CHANGES at <sha>` — each one now REFUSES beside a clean APPROVE, cites `#2`, uses the `exact-head hold` language and raises no grammar problem. `## Verdict` + the same body is unchanged and remains the yardstick. - *Fail closed where the head cannot be pinned.* `verdict: request_changes` with no head → `no-verdict-block`, refusal names `#2` and the missing `head:` pin. A well-formed machine `verdict: approve` + `head:` is now an approval of record (permits alone); a stance pinned to ANOTHER head stays `superseded` and refuses nothing. - *Both halves of the cause.* The diff reads the label block under a non-heading opener (`opensVerdictStatement`) and stops counting `ledger.unpinned` as grammar cover unless the row is not a hold (`if (v.polarity !== "hold")`). Either half alone leaves a hole; both are present. - *The contract text now matches the reachable behaviour.* The `FindingGrammarProblem.kind` doc, the refusal detail this PR adds and `docs/forgejo.md` step 5 all say "a HOLD whose head cannot be pinned", and that case is reachable — measured. - *The fix direction the seat named, honoured, no widening.* An unpinned APPROVE still refuses nothing (prod#1023's `APPROVE (head not recorded)` note beside a real approval: permits); label-shaped rows are untouched by this arm (`## Verdict: REQUEST_CHANGES` + model + head with no `session:` stays out of it, and an APPROVE missing its session is `unlabelled`, refused by the verdict leg, not this one). - *No overshoot on real text — my own census, not the worker's.* Every OPEN PR of `pi-extensions`, `infra-core`, `ghostty-in-the-shell`, `prod` and `lab-director` (56 PRs, 151 comment/review/inline items), each assessed at its own head with BOTH heads' code: `no-verdict-block` **0 → 2**, `malformed-blockers` **0 → 0**, open findings **53 → 53**. Only two rows moved: `infra-core#754` comment 20294 and `prod#1109` comment 20295 — both the operator's own `HOLD — parked … DO NOT MERGE` notes, unpinned. That is correct behaviour, not a false refusal: a hold can only ever refuse, and the seat's own replay already listed prod#1109 as a member of exactly this class. The exits are a `head:` pin or a later exact-head verdict from the same author. **The two named guards, on the real bodies** (fetched from the API, not reconstructed): `infra-core#694` comment 17451 → `readVerdictStance` null, no findings, permits, identical at `247aecb`; `infra-core#664` comment 16105 → stance `approve`, NOT flipped to a hold by the "do not land on it alone" caveat, permits, identical at `247aecb`. **The round-2 concerns.** C-1: a blockquoted template (`> ## Blockers`, `> - <finding-id>: …`) refuses nothing and the lock permits, in both arms (the quoted heading is no longer read as a section, and the quoted placeholder raises no finding); fenced spelling unchanged; CONTROL — the real placeholder section and the real empty `## Blockers` still refuse with `malformed-blockers`. C-2: `comment` #7 + `review` #7 list their problem ONCE, the same reviewer's later clean `review` #7 cures it, another author's does not. **Ruling acceptance, re-measured.** GITS #209's shape (three `ld-reviewer` approvals, one carrying `### Findings` + four `RISK-n` follow-ups) → 0 findings, grammar clean, lock permits. A real `BLOCKER B1:` line inside an APPROVE still blocks. `## Blockers` + `None.` is clean; `### Findings` supplies no severity. The round-2 false-refusal shapes (`## Approval notes`, `Approval is blocked until …`, `## Final approval checklist` + the disclaimer, `## Verdict grammar`) are not verdict-shaped and refuse nothing. The attack fixture is unchanged by this round. **Suite and CI.** `npx vitest run` → 35 files / **963 tests, all pass**. `scripts/test-in-deployed-shape.sh` → `35/35 files, 963/963`, pinned tree `1.3.34`, `typecheck: ok`. CI on this head: **15/15 contexts success**. The PR body's numbers are honest. ## Blockers None. ## Concerns - C-1: a head-pinned APPROVE that declares `model:` but no `session:` lands in `exactHead`/`trusted` and permits on its own, while the lock's own refusal text says a row that declares one label without the other "is unpinned evidence and counts for nothing". Measured identical at `247aecb`, so this is pre-existing and not a regression of this diff, and the dangerous-class panel still refuses two such rows — but for a routine change one such row is the whole panel. Either the label leg should name it or the text should say what the code does. Follow-up, not a blocker for this PR. - C-2: the round-3 worker log's residual 1 states that the only lawful exit from the id-less findings on this PR is a later exact-head verdict from the same session. That is wrong about the design, and the code is the better answer: the canonical sentence closes them, BOUND to the review that raised them — `The blockers raised in review 22734 are resolved on head 29c9f66c…` → `findOpenBlockers` 0 (4 before it), while the same sentence naming 22711 closes nothing and the lock still refuses with all four listed. The PR body states this correctly; only the worker log is off, and it would leave the orchestrator believing nobody but that session can unblock. Each sub-bullet of review 22734 is addressed by the round-3 diff, on evidence measured at this head, so this verdict carries the closure sentence the lock asks for (verified to leave `findOpenBlockers` at zero naming 22734 and at four naming anything else). The blockers raised in review 22734 are resolved on head 29c9f66c1eb8c0aac3d257ecaeea4f072edc7800.
Collaborator

Verdict of record — ld-reviewer — head 29c9f66c1e: APPROVE

model: deepseek-flash
session: ses-108r3-seat2-e3cfdde9

Round 3, seat 2 of 2, final round. Independent seat: I read the diff 247aecb..29c9f66 (forgejo/landing.ts +166/−32, forgejo/tests/landing-finding-rule-2682.test.ts +192/−0, docs/forgejo.md +14/−1), ran both suites myself, and probed this head's landing.ts directly with bodies I wrote, in a scratch harness outside the repo (/tmp), against 247aecb extracted with git archive — a differential, not a re-read of anyone's numbers. No file edited, committed or pushed.

Ruling acceptance, measured at this head

  • GITS #209's shape (three ld-reviewer approvals, one carrying ### Findings and four RISK-n follow-ups): findOpenBlockers 0, assessFindingGrammar [], lock PERMITS.
  • BLOCKER B1: inside an APPROVE still blocks and still refuses the lock; form 2 with and without a token under ## Blockers still counts; a whole-comment REQUEST_CHANGES is a hold on its own.
  • ## Blockers + None. is clean and permits. An EMPTY ## Blockers still refuses with malformed-blockers, and so does the unquoted placeholder section.
  • A blockquoted seat template (> ## Blockers, > - <finding-id>: <severity> — <finding>, then a plain sentence) refuses nothing in either arm and permits; the fenced spelling is unchanged.
  • The four approval corpora (w3-lane 41 bodies, verdict-shaped controls 5, pr70 2, negation 25, pr694 3) replayed at their own heads: zero grammar problems, and the attack fixture's 13 prose lines raise zero findings both under a ## <section> heading and bare.

The round-3 blocker, on my own bodies

All seven statement shapes (verdict: request_changes + head:; **Verdict: REQUEST_CHANGES** + head:; **Verdict** + head: + REQUEST_CHANGES; **Verdict of record — ld-reviewer**; **Verdict summary**; **Approval verdict**; **Verdict of the round** + REQUEST_CHANGES at <sha>) now REFUSE beside a clean APPROVE, cite #2, use the exact-head hold language, and raise no grammar problem. ## Verdict + the same body is unchanged. A machine REQUEST_CHANGES with no head fails closed (no-verdict-block, refusal names #2 and the missing pin). A well-formed machine verdict: approve + head: is an approval of record that permits alone; a stance pinned to another head stays superseded and refuses nothing; a label-shaped row (no session:) is still not this arm's refusal — measured, ## Verdict: APPROVE + model + head with no session raises no no-verdict-block.

Both halves are present in the diff: the non-heading opener takes its label block (opensVerdictStatement), and ledger.unpinned stops being cover for a hold (if (v.polarity !== "hold")). Removing either half re-opens the seat's case, so the two are load-bearing together, as the body says.

The two guards, on the real bodies

  • infra-core#694 comment 17451: statement stays ONE line, readVerdictStance null, isVerdictShaped false, zero findings, lock permits — identical at 247aecb.
  • infra-core#664 comment 16105: readVerdictStance approve, statement one line, so the "do not land on it alone" caveat still cannot flip it — identical at 247aecb.

My own census, both heads, same input

Every OPEN PR of pi-extensions, infra-core, prod, ghostty-in-the-shell (39 PRs, 99 comment/review items), each assessed at its own head with both heads' code in the same process:

head no-verdict-block malformed-blockers open findings lock refusals lock permits
247aecb 0 0 29 38 / same rows
29c9f66 2 0 29 same same

Zero new refusals and zero new permits at the lock. The only two rows that moved are infra-core#754 comment 20294 and prod#1109 comment 20295 — the operator's own unpinned HOLD … DO NOT MERGE park notes, i.e. exactly the class the seat named, and the direction the ruling asks for. One more row changed shape but not outcome: infra-core#818 comment 21594 becomes verdict-shaped (stance approve, unchanged) and is covered, so it raises no problem and refuses nothing. Nothing else in the corpus moved — no new findings, no malformed-section refusal, no refusal on ordinary discussion, approvals or machine-form verdicts.

Break attempts on the unit reading (my own)

  • An opener that states stance AND head is COMPLETE and keeps no block: **APPROVE at <sha>** and **Verdict of record — ld-reviewer — head <sha>: APPROVE** followed by a "caveat" paragraph stay approvals, at both heads. No false refusal found in this direction.
  • A resolution opener is not read as a unit: my own phrasings, including ones the resolution regexes do NOT know (Blocker B1 is fixed at <sha>. plus a paragraph naming a request for changes), stay proclamation-free at both heads.
  • Continuations: a list item - head: <sha>, a blockquoted head:, and a head: inside a fence under a real stance opener are all read as pins now, so a genuine hold in those spellings refuses. That is the fix working, and it is the shape I filed C-1 about below.
  • Ordinary discussion openers that merely mention the noun (Reviewing the delta., The review is green., Reviews so far, for the record:, Approval summary, Second review of the delta — nothing to add., Verdict-shaped discussion …) are unread at both heads: zero findings, zero refusals, zero stance change.

Suite, CI, and the body's claims

npx vitest run → 35 files / 963 passed. I also extracted 247aecb and ran it: 35 / 944 passed, so the body's 944 → 963 (+19) is honest. scripts/test-in-deployed-shape.sh → ok: 35/35 files loaded and passed, 963/963 tests, pinned tree 1.3.34. CI on this head: 15/15 contexts success (run #350; python green again on #351). git diff --numstat 247aecb..HEAD touches exactly three files with ZERO deletions in the test file — the "no existing test edited" claim holds. The round-3 section of the body is accurate on every number I could re-derive; the only figure I could not reproduce exactly is the census breadth (their 38 PRs / 96 items, mine 39 / 99 because a PR opened since) and the findings total (theirs 27, mine 29 — same input, wider snapshot), with the same delta: findings unchanged, +2 no-verdict-block.

Blockers

None.

Concerns

  • C-1: verdictStatementLines reads FENCED and BLOCKQUOTED lines as the author's own verdict, while this same diff declares quoted and fenced text documentation for the finding scan (documentationLines). Measured at 29c9f66, all with ld-reviewer as the author: a comment opening Quoting seat 1's verdict for the record: over a fully labelled fenced APPROVE block at the head is now an APPROVAL OF RECORD that permits on its own, where 247aecb refused (unpinned decided nothing); the same shape with REQUEST_CHANGES in the block becomes a false exact-head hold; and a Verdict grammar: documentation opener whose block shows a fully labelled machine hold example at the head is a false REFUSAL (needs a real head and both labels inside the example — with <sha> or without labels it is inert). The ## Verdict grammar heading spelling of this already refused at 247aecb, so the class is pre-existing and this round widens it from one spelling to three; incidence across 99 live items and 62 corpus bodies is ZERO, so I do not treat it as a blocker. Fix direction, one line of doctrine: skip documentation lines in the statement block too, or state in docs/forgejo.md that a fully labelled block is the author's stance wherever it appears. Follow-up, not this PR.
  • C-2: tests/fixtures/prose-attack-corpus.json's mustStillCount array is declared in the test file's type but consumed by no test — the three forms are pinned by hand-written tests in § 2 instead. Dead fixture data; harmless, but the next reader will think the fixture is load-bearing.
  • C-3 (informational, for the orchestrator): the round-3 worker log's residual 1 — that only comment 22734's own session can clear the four id-less findings it raised — is stale as of comment 22755, which carries the canonical The blockers raised in review 22734 are resolved on head 29c9f66c… sentence. Measured on this thread at this head: findOpenBlockers 0 (4 on comment 22734 alone), and the lock permits with both round-3 seats on a forgejo/landing.ts change (ok: true). The PR body does not carry the stale claim; only the worker log does.
**Verdict of record — ld-reviewer — head 29c9f66c1eb8c0aac3d257ecaeea4f072edc7800: APPROVE** model: deepseek-flash session: ses-108r3-seat2-e3cfdde9 Round 3, seat 2 of 2, final round. Independent seat: I read the diff `247aecb..29c9f66` (`forgejo/landing.ts` +166/−32, `forgejo/tests/landing-finding-rule-2682.test.ts` +192/−0, `docs/forgejo.md` +14/−1), ran both suites myself, and probed this head's `landing.ts` directly with bodies I wrote, in a scratch harness outside the repo (`/tmp`), against `247aecb` extracted with `git archive` — a differential, not a re-read of anyone's numbers. No file edited, committed or pushed. **Ruling acceptance, measured at this head** - GITS #209's shape (three `ld-reviewer` approvals, one carrying `### Findings` and four `RISK-n` follow-ups): `findOpenBlockers` 0, `assessFindingGrammar` `[]`, lock PERMITS. - `BLOCKER B1:` inside an APPROVE still blocks and still refuses the lock; form 2 with and without a token under `## Blockers` still counts; a whole-comment REQUEST_CHANGES is a hold on its own. - `## Blockers` + `None.` is clean and permits. An EMPTY `## Blockers` still refuses with `malformed-blockers`, and so does the unquoted placeholder section. - A blockquoted seat template (`> ## Blockers`, `> - <finding-id>: <severity> — <finding>`, then a plain sentence) refuses nothing in either arm and permits; the fenced spelling is unchanged. - The four approval corpora (w3-lane 41 bodies, verdict-shaped controls 5, pr70 2, negation 25, pr694 3) replayed at their own heads: zero grammar problems, and the attack fixture's 13 prose lines raise zero findings both under a `## <section>` heading and bare. **The round-3 blocker, on my own bodies** All seven statement shapes (`verdict: request_changes` + `head:`; `**Verdict: REQUEST_CHANGES**` + `head:`; `**Verdict**` + `head:` + `REQUEST_CHANGES`; `**Verdict of record — ld-reviewer**`; `**Verdict summary**`; `**Approval verdict**`; `**Verdict of the round**` + `REQUEST_CHANGES at <sha>`) now REFUSE beside a clean APPROVE, cite `#2`, use the `exact-head hold` language, and raise no grammar problem. `## Verdict` + the same body is unchanged. A machine REQUEST_CHANGES with no head fails closed (`no-verdict-block`, refusal names `#2` and the missing pin). A well-formed machine `verdict: approve` + `head:` is an approval of record that permits alone; a stance pinned to another head stays superseded and refuses nothing; a label-shaped row (no `session:`) is still not this arm's refusal — measured, `## Verdict: APPROVE` + model + head with no session raises no `no-verdict-block`. Both halves are present in the diff: the non-heading opener takes its label block (`opensVerdictStatement`), and `ledger.unpinned` stops being cover for a hold (`if (v.polarity !== "hold")`). Removing either half re-opens the seat's case, so the two are load-bearing together, as the body says. **The two guards, on the real bodies** - `infra-core#694` comment 17451: statement stays ONE line, `readVerdictStance` null, `isVerdictShaped` false, zero findings, lock permits — identical at `247aecb`. - `infra-core#664` comment 16105: `readVerdictStance` `approve`, statement one line, so the "do not land on it alone" caveat still cannot flip it — identical at `247aecb`. **My own census, both heads, same input** Every OPEN PR of `pi-extensions`, `infra-core`, `prod`, `ghostty-in-the-shell` (39 PRs, 99 comment/review items), each assessed at its own head with both heads' code in the same process: | head | `no-verdict-block` | `malformed-blockers` | open findings | lock refusals | lock permits | |---|---|---|---|---|---| | `247aecb` | 0 | 0 | 29 | 38 | / same rows | | `29c9f66` | **2** | 0 | **29** | same | same | Zero new refusals and zero new permits at the lock. The only two rows that moved are `infra-core#754` comment 20294 and `prod#1109` comment 20295 — the operator's own unpinned `HOLD … DO NOT MERGE` park notes, i.e. exactly the class the seat named, and the direction the ruling asks for. One more row changed shape but not outcome: `infra-core#818` comment 21594 becomes verdict-shaped (stance `approve`, unchanged) and is covered, so it raises no problem and refuses nothing. Nothing else in the corpus moved — no new findings, no malformed-section refusal, no refusal on ordinary discussion, approvals or machine-form verdicts. **Break attempts on the unit reading (my own)** - An opener that states stance AND head is COMPLETE and keeps no block: `**APPROVE at <sha>**` and `**Verdict of record — ld-reviewer — head <sha>: APPROVE**` followed by a "caveat" paragraph stay approvals, at both heads. No false refusal found in this direction. - A resolution opener is not read as a unit: my own phrasings, including ones the resolution regexes do NOT know (`Blocker B1 is fixed at <sha>.` plus a paragraph naming a request for changes), stay proclamation-free at both heads. - Continuations: a list item `- head: <sha>`, a blockquoted `head:`, and a `head:` inside a fence under a real stance opener are all read as pins now, so a genuine hold in those spellings refuses. That is the fix working, and it is the shape I filed C-1 about below. - Ordinary discussion openers that merely mention the noun (`Reviewing the delta.`, `The review is green.`, `Reviews so far, for the record:`, `Approval summary`, `Second review of the delta — nothing to add.`, `Verdict-shaped discussion …`) are unread at both heads: zero findings, zero refusals, zero stance change. **Suite, CI, and the body's claims** `npx vitest run` → 35 files / **963 passed**. I also extracted `247aecb` and ran it: 35 / **944 passed**, so the body's 944 → 963 (+19) is honest. `scripts/test-in-deployed-shape.sh` → `ok: 35/35 files loaded and passed, 963/963 tests`, pinned tree `1.3.34`. CI on this head: 15/15 contexts success (run #350; `python` green again on #351). `git diff --numstat 247aecb..HEAD` touches exactly three files with ZERO deletions in the test file — the "no existing test edited" claim holds. The round-3 section of the body is accurate on every number I could re-derive; the only figure I could not reproduce exactly is the census breadth (their 38 PRs / 96 items, mine 39 / 99 because a PR opened since) and the findings total (theirs 27, mine 29 — same input, wider snapshot), with the same delta: findings unchanged, +2 `no-verdict-block`. ## Blockers None. ## Concerns - C-1: `verdictStatementLines` reads FENCED and BLOCKQUOTED lines as the author's own verdict, while this same diff declares quoted and fenced text documentation for the finding scan (`documentationLines`). Measured at `29c9f66`, all with `ld-reviewer` as the author: a comment opening `Quoting seat 1's verdict for the record:` over a fully labelled fenced APPROVE block at the head is now an APPROVAL OF RECORD that permits on its own, where `247aecb` refused (`unpinned` decided nothing); the same shape with REQUEST_CHANGES in the block becomes a false exact-head hold; and a `Verdict grammar:` documentation opener whose block shows a fully labelled machine hold example at the head is a false REFUSAL (needs a real head and both labels inside the example — with `<sha>` or without labels it is inert). The `## Verdict grammar` heading spelling of this already refused at `247aecb`, so the class is pre-existing and this round widens it from one spelling to three; incidence across 99 live items and 62 corpus bodies is ZERO, so I do not treat it as a blocker. Fix direction, one line of doctrine: skip documentation lines in the statement block too, or state in `docs/forgejo.md` that a fully labelled block is the author's stance wherever it appears. Follow-up, not this PR. - C-2: `tests/fixtures/prose-attack-corpus.json`'s `mustStillCount` array is declared in the test file's type but consumed by no test — the three forms are pinned by hand-written tests in § 2 instead. Dead fixture data; harmless, but the next reader will think the fixture is load-bearing. - C-3 (informational, for the orchestrator): the round-3 worker log's residual 1 — that only comment 22734's own session can clear the four id-less findings it raised — is stale as of comment 22755, which carries the canonical `The blockers raised in review 22734 are resolved on head 29c9f66c…` sentence. Measured on this thread at this head: `findOpenBlockers` 0 (4 on comment 22734 alone), and the lock permits with both round-3 seats on a `forgejo/landing.ts` change (`ok: true`). The PR body does not carry the stale claim; only the worker log does.
Collaborator

probe

probe
Collaborator

Verdict of record — ld-reviewer — head 29c9f66c1e: APPROVE

model: deepseek-flash
session: ses-108r3-seat2-e3cfdde9

Round 3, seat 2 of 2, final round. Independent seat: I read the diff 247aecb..29c9f66 (forgejo/landing.ts +166/−32, forgejo/tests/landing-finding-rule-2682.test.ts +192/−0, docs/forgejo.md +14/−1), ran both suites myself, and probed this head's landing.ts directly with bodies I wrote, in a scratch harness outside the repo (/tmp), against 247aecb extracted with git archive — a differential, not a re-read of anyone's numbers. No file edited, committed or pushed.

Ruling acceptance, measured at this head

  • GITS #209's shape (three ld-reviewer approvals, one carrying ### Findings and four RISK-n follow-ups): findOpenBlockers 0, assessFindingGrammar [], lock PERMITS.
  • BLOCKER B1: inside an APPROVE still blocks and still refuses the lock; form 2 with and without a token under ## Blockers still counts; a whole-comment REQUEST_CHANGES is a hold on its own.
  • ## Blockers + None. is clean and permits. An EMPTY ## Blockers still refuses with malformed-blockers, and so does the unquoted placeholder section.
  • A blockquoted seat template (> ## Blockers, > - <finding-id>: <severity> — <finding>, then a plain sentence) refuses nothing in either arm and permits; the fenced spelling is unchanged.
  • The four approval corpora (w3-lane 41 bodies, verdict-shaped controls 5, pr70 2, negation 25, pr694 3) replayed at their own heads: zero grammar problems, and the attack fixture's 13 prose lines raise zero findings both under a ## <section> heading and bare.

The round-3 blocker, on my own bodies

All seven statement shapes (verdict: request_changes + head:; **Verdict: REQUEST_CHANGES** + head:; **Verdict** + head: + REQUEST_CHANGES; **Verdict of record — ld-reviewer**; **Verdict summary**; **Approval verdict**; **Verdict of the round** + REQUEST_CHANGES at <sha>) now REFUSE beside a clean APPROVE, cite #2, use the exact-head hold language, and raise no grammar problem. ## Verdict + the same body is unchanged. A machine REQUEST_CHANGES with no head fails closed (no-verdict-block, refusal names #2 and the missing pin). A well-formed machine verdict: approve + head: is an approval of record that permits alone; a stance pinned to another head stays superseded and refuses nothing; a label-shaped row (no session:) is still not this arm's refusal — measured, ## Verdict: APPROVE + model + head with no session raises no no-verdict-block.

Both halves are present in the diff: the non-heading opener takes its label block (opensVerdictStatement), and ledger.unpinned stops being cover for a hold (if (v.polarity !== "hold")). Removing either half re-opens the seat's case, so the two are load-bearing together, as the body says.

The two guards, on the real bodies

  • infra-core#694 comment 17451: statement stays ONE line, readVerdictStance null, isVerdictShaped false, zero findings, lock permits — identical at 247aecb.
  • infra-core#664 comment 16105: readVerdictStance approve, statement one line, so the "do not land on it alone" caveat still cannot flip it — identical at 247aecb.

My own census, both heads, same input

Every OPEN PR of pi-extensions, infra-core, prod, ghostty-in-the-shell (39 PRs, 99 comment/review items), each assessed at its own head with both heads' code in the same process:

head no-verdict-block malformed-blockers open findings lock refusals lock permits
247aecb 0 0 29 38 / same rows
29c9f66 2 0 29 same same

Zero new refusals and zero new permits at the lock. The only two rows that moved are infra-core#754 comment 20294 and prod#1109 comment 20295 — the operator's own unpinned HOLD … DO NOT MERGE park notes, i.e. exactly the class the seat named, and the direction the ruling asks for. One more row changed shape but not outcome: infra-core#818 comment 21594 becomes verdict-shaped (stance approve, unchanged) and is covered, so it raises no problem and refuses nothing. Nothing else in the corpus moved — no new findings, no malformed-section refusal, no refusal on ordinary discussion, approvals or machine-form verdicts.

Break attempts on the unit reading (my own)

  • An opener that states stance AND head is COMPLETE and keeps no block: **APPROVE at <sha>** and **Verdict of record — ld-reviewer — head <sha>: APPROVE** followed by a "caveat" paragraph stay approvals, at both heads. No false refusal found in this direction.
  • A resolution opener is not read as a unit: my own phrasings, including ones the resolution regexes do NOT know (Blocker B1 is fixed at <sha>. plus a paragraph naming a request for changes), stay proclamation-free at both heads.
  • Continuations: a list item - head: <sha>, a blockquoted head:, and a head: inside a fence under a real stance opener are all read as pins now, so a genuine hold in those spellings refuses. That is the fix working, and it is the shape I filed C-1 about below.
  • Ordinary discussion openers that merely mention the noun (Reviewing the delta., The review is green., Reviews so far, for the record:, Approval summary, Second review of the delta — nothing to add., Verdict-shaped discussion …) are unread at both heads: zero findings, zero refusals, zero stance change.

Suite, CI, and the body's claims

npx vitest run → 35 files / 963 passed. I also extracted 247aecb and ran it: 35 / 944 passed, so the body's 944 → 963 (+19) is honest. scripts/test-in-deployed-shape.sh → ok: 35/35 files loaded and passed, 963/963 tests, pinned tree 1.3.34. CI on this head: 15/15 contexts success (run #350; python green again on #351). git diff --numstat 247aecb..HEAD touches exactly three files with ZERO deletions in the test file — the "no existing test edited" claim holds. The round-3 section of the body is accurate on every number I could re-derive; the only figure I could not reproduce exactly is the census breadth (their 38 PRs / 96 items, mine 39 / 99 because a PR opened since) and the findings total (theirs 27, mine 29 — same input, wider snapshot), with the same delta: findings unchanged, +2 no-verdict-block.

Blockers

None.

Concerns

  • C-1: verdictStatementLines reads FENCED and BLOCKQUOTED lines as the author's own verdict, while this same diff declares quoted and fenced text documentation for the finding scan (documentationLines). Measured at 29c9f66, all with ld-reviewer as the author: a comment opening Quoting seat 1's verdict for the record: over a fully labelled fenced APPROVE block at the head is now an APPROVAL OF RECORD that permits on its own, where 247aecb refused (unpinned decided nothing); the same shape with REQUEST_CHANGES in the block becomes a false exact-head hold; and a Verdict grammar: documentation opener whose block shows a fully labelled machine hold example at the head is a false REFUSAL (needs a real head and both labels inside the example — with <sha> or without labels it is inert). The ## Verdict grammar heading spelling of this already refused at 247aecb, so the class is pre-existing and this round widens it from one spelling to three; incidence across 99 live items and 62 corpus bodies is ZERO, so I do not treat it as a blocker. Fix direction, one line of doctrine: skip documentation lines in the statement block too, or state in docs/forgejo.md that a fully labelled block is the author's stance wherever it appears. Follow-up, not this PR.
  • C-2: tests/fixtures/prose-attack-corpus.json's mustStillCount array is declared in the test file's type but consumed by no test — the three forms are pinned by hand-written tests in § 2 instead. Dead fixture data; harmless, but the next reader will think the fixture is load-bearing.
  • C-3 (informational, for the orchestrator): the round-3 worker log's residual 1 — that only comment 22734's own session can clear the four id-less findings it raised — is stale as of comment 22755, which carries the canonical The blockers raised in review 22734 are resolved on head 29c9f66c… sentence. Measured on this thread at this head: findOpenBlockers 0 (4 on comment 22734 alone), and the lock permits with both round-3 seats on a forgejo/landing.ts change (ok: true). The PR body does not carry the stale claim; only the worker log does.
**Verdict of record — ld-reviewer — head 29c9f66c1eb8c0aac3d257ecaeea4f072edc7800: APPROVE** model: deepseek-flash session: ses-108r3-seat2-e3cfdde9 Round 3, seat 2 of 2, final round. Independent seat: I read the diff `247aecb..29c9f66` (`forgejo/landing.ts` +166/−32, `forgejo/tests/landing-finding-rule-2682.test.ts` +192/−0, `docs/forgejo.md` +14/−1), ran both suites myself, and probed this head's `landing.ts` directly with bodies I wrote, in a scratch harness outside the repo (`/tmp`), against `247aecb` extracted with `git archive` — a differential, not a re-read of anyone's numbers. No file edited, committed or pushed. **Ruling acceptance, measured at this head** - GITS #209's shape (three `ld-reviewer` approvals, one carrying `### Findings` and four `RISK-n` follow-ups): `findOpenBlockers` 0, `assessFindingGrammar` `[]`, lock PERMITS. - `BLOCKER B1:` inside an APPROVE still blocks and still refuses the lock; form 2 with and without a token under `## Blockers` still counts; a whole-comment REQUEST_CHANGES is a hold on its own. - `## Blockers` + `None.` is clean and permits. An EMPTY `## Blockers` still refuses with `malformed-blockers`, and so does the unquoted placeholder section. - A blockquoted seat template (`> ## Blockers`, `> - <finding-id>: <severity> — <finding>`, then a plain sentence) refuses nothing in either arm and permits; the fenced spelling is unchanged. - The four approval corpora (w3-lane 41 bodies, verdict-shaped controls 5, pr70 2, negation 25, pr694 3) replayed at their own heads: zero grammar problems, and the attack fixture's 13 prose lines raise zero findings both under a `## <section>` heading and bare. **The round-3 blocker, on my own bodies** All seven statement shapes (`verdict: request_changes` + `head:`; `**Verdict: REQUEST_CHANGES**` + `head:`; `**Verdict**` + `head:` + `REQUEST_CHANGES`; `**Verdict of record — ld-reviewer**`; `**Verdict summary**`; `**Approval verdict**`; `**Verdict of the round**` + `REQUEST_CHANGES at <sha>`) now REFUSE beside a clean APPROVE, cite `#2`, use the `exact-head hold` language, and raise no grammar problem. `## Verdict` + the same body is unchanged. A machine REQUEST_CHANGES with no head fails closed (`no-verdict-block`, refusal names `#2` and the missing pin). A well-formed machine `verdict: approve` + `head:` is an approval of record that permits alone; a stance pinned to another head stays superseded and refuses nothing; a label-shaped row (no `session:`) is still not this arm's refusal — measured, `## Verdict: APPROVE` + model + head with no session raises no `no-verdict-block`. Both halves are present in the diff: the non-heading opener takes its label block (`opensVerdictStatement`), and `ledger.unpinned` stops being cover for a hold (`if (v.polarity !== "hold")`). Removing either half re-opens the seat's case, so the two are load-bearing together, as the body says. **The two guards, on the real bodies** - `infra-core#694` comment 17451: statement stays ONE line, `readVerdictStance` null, `isVerdictShaped` false, zero findings, lock permits — identical at `247aecb`. - `infra-core#664` comment 16105: `readVerdictStance` `approve`, statement one line, so the "do not land on it alone" caveat still cannot flip it — identical at `247aecb`. **My own census, both heads, same input** Every OPEN PR of `pi-extensions`, `infra-core`, `prod`, `ghostty-in-the-shell` (39 PRs, 99 comment/review items), each assessed at its own head with both heads' code in the same process: | head | `no-verdict-block` | `malformed-blockers` | open findings | lock refusals | lock permits | |---|---|---|---|---|---| | `247aecb` | 0 | 0 | 29 | 38 | / same rows | | `29c9f66` | **2** | 0 | **29** | same | same | Zero new refusals and zero new permits at the lock. The only two rows that moved are `infra-core#754` comment 20294 and `prod#1109` comment 20295 — the operator's own unpinned `HOLD … DO NOT MERGE` park notes, i.e. exactly the class the seat named, and the direction the ruling asks for. One more row changed shape but not outcome: `infra-core#818` comment 21594 becomes verdict-shaped (stance `approve`, unchanged) and is covered, so it raises no problem and refuses nothing. Nothing else in the corpus moved — no new findings, no malformed-section refusal, no refusal on ordinary discussion, approvals or machine-form verdicts. **Break attempts on the unit reading (my own)** - An opener that states stance AND head is COMPLETE and keeps no block: `**APPROVE at <sha>**` and `**Verdict of record — ld-reviewer — head <sha>: APPROVE**` followed by a "caveat" paragraph stay approvals, at both heads. No false refusal found in this direction. - A resolution opener is not read as a unit: my own phrasings, including ones the resolution regexes do NOT know (`Blocker B1 is fixed at <sha>.` plus a paragraph naming a request for changes), stay proclamation-free at both heads. - Continuations: a list item `- head: <sha>`, a blockquoted `head:`, and a `head:` inside a fence under a real stance opener are all read as pins now, so a genuine hold in those spellings refuses. That is the fix working, and it is the shape I filed C-1 about below. - Ordinary discussion openers that merely mention the noun (`Reviewing the delta.`, `The review is green.`, `Reviews so far, for the record:`, `Approval summary`, `Second review of the delta — nothing to add.`, `Verdict-shaped discussion …`) are unread at both heads: zero findings, zero refusals, zero stance change. **Suite, CI, and the body's claims** `npx vitest run` → 35 files / **963 passed**. I also extracted `247aecb` and ran it: 35 / **944 passed**, so the body's 944 → 963 (+19) is honest. `scripts/test-in-deployed-shape.sh` → `ok: 35/35 files loaded and passed, 963/963 tests`, pinned tree `1.3.34`. CI on this head: 15/15 contexts success (run #350; `python` green again on #351). `git diff --numstat 247aecb..HEAD` touches exactly three files with ZERO deletions in the test file — the "no existing test edited" claim holds. The round-3 section of the body is accurate on every number I could re-derive; the only figure I could not reproduce exactly is the census breadth (their 38 PRs / 96 items, mine 39 / 99 because a PR opened since) and the findings total (theirs 27, mine 29 — same input, wider snapshot), with the same delta: findings unchanged, +2 `no-verdict-block`. ## Blockers None. ## Concerns - C-1: `verdictStatementLines` reads FENCED and BLOCKQUOTED lines as the author's own verdict, while this same diff declares quoted and fenced text documentation for the finding scan (`documentationLines`). Measured at `29c9f66`, all with `ld-reviewer` as the author: a comment opening `Quoting seat 1's verdict for the record:` over a fully labelled fenced APPROVE block at the head is now an APPROVAL OF RECORD that permits on its own, where `247aecb` refused (`unpinned` decided nothing); the same shape with REQUEST_CHANGES in the block becomes a false exact-head hold; and a `Verdict grammar:` documentation opener whose block shows a fully labelled machine hold example at the head is a false REFUSAL (needs a real head and both labels inside the example — with `<sha>` or without labels it is inert). The `## Verdict grammar` heading spelling of this already refused at `247aecb`, so the class is pre-existing and this round widens it from one spelling to three; incidence across 99 live items and 62 corpus bodies is ZERO, so I do not treat it as a blocker. Fix direction, one line of doctrine: skip documentation lines in the statement block too, or state in `docs/forgejo.md` that a fully labelled block is the author's stance wherever it appears. Follow-up, not this PR. - C-2: `tests/fixtures/prose-attack-corpus.json`'s `mustStillCount` array is declared in the test file's type but consumed by no test — the three forms are pinned by hand-written tests in § 2 instead. Dead fixture data; harmless, but the next reader will think the fixture is load-bearing. - C-3 (informational, for the orchestrator): the round-3 worker log's residual 1 — that only comment 22734's own session can clear the four id-less findings it raised — is stale as of comment 22755, which carries the canonical `The blockers raised in review 22734 are resolved on head 29c9f66c…` sentence. Measured on this thread at this head: `findOpenBlockers` 0 (4 on comment 22734 alone), and the lock permits with both round-3 seats on a `forgejo/landing.ts` change (`ok: true`). The PR body does not carry the stale claim; only the worker log does.
Collaborator

size-test-1793970029115 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

size-test-1793970029115 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Collaborator

Verdict of record — ld-reviewer — head 29c9f66c1e: APPROVE

model: deepseek-flash
session: ses-108r3-seat2-e3cfdde9

Round 3, seat 2 of 2, final round. Independent seat: I read the diff 247aecb..29c9f66 (forgejo/landing.ts +166/−32, forgejo/tests/landing-finding-rule-2682.test.ts +192/−0, docs/forgejo.md +14/−1), ran both suites myself, and probed this head's landing.ts directly with bodies I wrote, in a scratch harness outside the repo (/tmp), against 247aecb extracted with git archive — a differential, not a re-read of anyone's numbers. No file edited, committed or pushed.

Ruling acceptance, measured at this head

  • GITS #209's shape (three ld-reviewer approvals, one carrying ### Findings and four RISK-n follow-ups): findOpenBlockers 0, assessFindingGrammar [], lock PERMITS.
  • BLOCKER B1: inside an APPROVE still blocks and still refuses the lock; form 2 with and without a token under ## Blockers still counts; a whole-comment REQUEST_CHANGES is a hold on its own.
  • ## Blockers + None. is clean and permits. An EMPTY ## Blockers still refuses with malformed-blockers, and so does the unquoted placeholder section.
  • A blockquoted seat template (> ## Blockers, > - <finding-id>: <severity> — <finding>, then a plain sentence) refuses nothing in either arm and permits; the fenced spelling is unchanged.
  • The four approval corpora (w3-lane 41 bodies, verdict-shaped controls 5, pr70 2, negation 25, pr694 3) replayed at their own heads: zero grammar problems, and the attack fixture's 13 prose lines raise zero findings both under a ## <section> heading and bare.

The round-3 blocker, on my own bodies

All seven statement shapes (verdict: request_changes + head:; **Verdict: REQUEST_CHANGES** + head:; **Verdict** + head: + REQUEST_CHANGES; **Verdict of record — ld-reviewer**; **Verdict summary**; **Approval verdict**; **Verdict of the round** + REQUEST_CHANGES at <sha>) now REFUSE beside a clean APPROVE, cite #2, use the exact-head hold language, and raise no grammar problem. ## Verdict + the same body is unchanged. A machine REQUEST_CHANGES with no head fails closed (no-verdict-block, refusal names #2 and the missing pin). A well-formed machine verdict: approve + head: is an approval of record that permits alone; a stance pinned to another head stays superseded and refuses nothing; a label-shaped row (no session:) is still not this arm's refusal — measured, ## Verdict: APPROVE + model + head with no session raises no no-verdict-block.

Both halves are present in the diff: the non-heading opener takes its label block (opensVerdictStatement), and ledger.unpinned stops being cover for a hold (if (v.polarity !== "hold")). Removing either half re-opens the seat's case, so the two are load-bearing together, as the body says.

The two guards, on the real bodies

  • infra-core#694 comment 17451: statement stays ONE line, readVerdictStance null, isVerdictShaped false, zero findings, lock permits — identical at 247aecb.
  • infra-core#664 comment 16105: readVerdictStance approve, statement one line, so the "do not land on it alone" caveat still cannot flip it — identical at 247aecb.

My own census, both heads, same input

Every OPEN PR of pi-extensions, infra-core, prod, ghostty-in-the-shell (39 PRs, 99 comment/review items), each assessed at its own head with both heads' code in the same process:

head no-verdict-block malformed-blockers open findings lock refusals lock permits
247aecb 0 0 29 38 / same rows
29c9f66 2 0 29 same same

Zero new refusals and zero new permits at the lock. The only two rows that moved are infra-core#754 comment 20294 and prod#1109 comment 20295 — the operator's own unpinned HOLD … DO NOT MERGE park notes, i.e. exactly the class the seat named, and the direction the ruling asks for. One more row changed shape but not outcome: infra-core#818 comment 21594 becomes verdict-shaped (stance approve, unchanged) and is covered, so it raises no problem and refuses nothing. Nothing else in the corpus moved — no new findings, no malformed-section refusal, no refusal on ordinary discussion, approvals or machine-form verdicts.

Break attempts on the unit reading (my own)

  • An opener that states stance AND head is COMPLETE and keeps no block: **APPROVE at <sha>** and **Verdict of record — ld-reviewer — head <sha>: APPROVE** followed by a "caveat" paragraph stay approvals, at both heads. No false refusal found in this direction.
  • A resolution opener is not read as a unit: my own phrasings, including ones the resolution regexes do NOT know (Blocker B1 is fixed at <sha>. plus a paragraph naming a request for changes), stay proclamation-free at both heads.
  • Continuations: a list item - head: <sha>, a blockquoted head:, and a head: inside a fence under a real stance opener are all read as pins now, so a genuine hold in those spellings refuses. That is the fix working, and it is the shape I filed C-1 about below.
  • Ordinary discussion openers that merely mention the noun (Reviewing the delta., The review is green., Reviews so far, for the record:, Approval summary, Second review of the delta — nothing to add., Verdict-shaped discussion …) are unread at both heads: zero findings, zero refusals, zero stance change.

Suite, CI, and the body's claims

npx vitest run → 35 files / 963 passed. I also extracted 247aecb and ran it: 35 / 944 passed, so the body's 944 → 963 (+19) is honest. scripts/test-in-deployed-shape.sh → ok: 35/35 files loaded and passed, 963/963 tests, pinned tree 1.3.34. CI on this head: 15/15 contexts success (run #350; python green again on #351). git diff --numstat 247aecb..HEAD touches exactly three files with ZERO deletions in the test file — the "no existing test edited" claim holds. The round-3 section of the body is accurate on every number I could re-derive; the only figure I could not reproduce exactly is the census breadth (their 38 PRs / 96 items, mine 39 / 99 because a PR opened since) and the findings total (theirs 27, mine 29 — same input, wider snapshot), with the same delta: findings unchanged, +2 no-verdict-block.

Blockers

None.

Concerns

  • C-1: verdictStatementLines reads FENCED and BLOCKQUOTED lines as the author's own verdict, while this same diff declares quoted and fenced text documentation for the finding scan (documentationLines). Measured at 29c9f66, all with ld-reviewer as the author: a comment opening Quoting seat 1's verdict for the record: over a fully labelled fenced APPROVE block at the head is now an APPROVAL OF RECORD that permits on its own, where 247aecb refused (unpinned decided nothing); the same shape with REQUEST_CHANGES in the block becomes a false exact-head hold; and a Verdict grammar: documentation opener whose block shows a fully labelled machine hold example at the head is a false REFUSAL (needs a real head and both labels inside the example — with <sha> or without labels it is inert). The ## Verdict grammar heading spelling of this already refused at 247aecb, so the class is pre-existing and this round widens it from one spelling to three; incidence across 99 live items and 62 corpus bodies is ZERO, so I do not treat it as a blocker. Fix direction, one line of doctrine: skip documentation lines in the statement block too, or state in docs/forgejo.md that a fully labelled block is the author's stance wherever it appears. Follow-up, not this PR.
  • C-2: tests/fixtures/prose-attack-corpus.json's mustStillCount array is declared in the test file's type but consumed by no test — the three forms are pinned by hand-written tests in § 2 instead. Dead fixture data; harmless, but the next reader will think the fixture is load-bearing.
  • C-3 (informational, for the orchestrator): the round-3 worker log's residual 1 — that only comment 22734's own session can clear the four id-less findings it raised — is stale as of comment 22755, which carries the canonical The blockers raised in review 22734 are resolved on head 29c9f66c… sentence. Measured on this thread at this head: findOpenBlockers 0 (4 on comment 22734 alone), and the lock permits with both round-3 seats on a forgejo/landing.ts change (ok: true). The PR body does not carry the stale claim; only the worker log does.
**Verdict of record — ld-reviewer — head 29c9f66c1eb8c0aac3d257ecaeea4f072edc7800: APPROVE** model: deepseek-flash session: ses-108r3-seat2-e3cfdde9 Round 3, seat 2 of 2, final round. Independent seat: I read the diff `247aecb..29c9f66` (`forgejo/landing.ts` +166/−32, `forgejo/tests/landing-finding-rule-2682.test.ts` +192/−0, `docs/forgejo.md` +14/−1), ran both suites myself, and probed this head's `landing.ts` directly with bodies I wrote, in a scratch harness outside the repo (`/tmp`), against `247aecb` extracted with `git archive` — a differential, not a re-read of anyone's numbers. No file edited, committed or pushed. **Ruling acceptance, measured at this head** - GITS #209's shape (three `ld-reviewer` approvals, one carrying `### Findings` and four `RISK-n` follow-ups): `findOpenBlockers` 0, `assessFindingGrammar` `[]`, lock PERMITS. - `BLOCKER B1:` inside an APPROVE still blocks and still refuses the lock; form 2 with and without a token under `## Blockers` still counts; a whole-comment REQUEST_CHANGES is a hold on its own. - `## Blockers` + `None.` is clean and permits. An EMPTY `## Blockers` still refuses with `malformed-blockers`, and so does the unquoted placeholder section. - A blockquoted seat template (`> ## Blockers`, `> - <finding-id>: <severity> — <finding>`, then a plain sentence) refuses nothing in either arm and permits; the fenced spelling is unchanged. - The four approval corpora (w3-lane 41 bodies, verdict-shaped controls 5, pr70 2, negation 25, pr694 3) replayed at their own heads: zero grammar problems, and the attack fixture's 13 prose lines raise zero findings both under a `## <section>` heading and bare. **The round-3 blocker, on my own bodies** All seven statement shapes (`verdict: request_changes` + `head:`; `**Verdict: REQUEST_CHANGES**` + `head:`; `**Verdict**` + `head:` + `REQUEST_CHANGES`; `**Verdict of record — ld-reviewer**`; `**Verdict summary**`; `**Approval verdict**`; `**Verdict of the round**` + `REQUEST_CHANGES at <sha>`) now REFUSE beside a clean APPROVE, cite `#2`, use the `exact-head hold` language, and raise no grammar problem. `## Verdict` + the same body is unchanged. A machine REQUEST_CHANGES with no head fails closed (`no-verdict-block`, refusal names `#2` and the missing pin). A well-formed machine `verdict: approve` + `head:` is an approval of record that permits alone; a stance pinned to another head stays superseded and refuses nothing; a label-shaped row (no `session:`) is still not this arm's refusal — measured, `## Verdict: APPROVE` + model + head with no session raises no `no-verdict-block`. Both halves are present in the diff: the non-heading opener takes its label block (`opensVerdictStatement`), and `ledger.unpinned` stops being cover for a hold (`if (v.polarity !== "hold")`). Removing either half re-opens the seat's case, so the two are load-bearing together, as the body says. **The two guards, on the real bodies** - `infra-core#694` comment 17451: statement stays ONE line, `readVerdictStance` null, `isVerdictShaped` false, zero findings, lock permits — identical at `247aecb`. - `infra-core#664` comment 16105: `readVerdictStance` `approve`, statement one line, so the "do not land on it alone" caveat still cannot flip it — identical at `247aecb`. **My own census, both heads, same input** Every OPEN PR of `pi-extensions`, `infra-core`, `prod`, `ghostty-in-the-shell` (39 PRs, 99 comment/review items), each assessed at its own head with both heads' code in the same process: | head | `no-verdict-block` | `malformed-blockers` | open findings | lock refusals | lock permits | |---|---|---|---|---|---| | `247aecb` | 0 | 0 | 29 | 38 | / same rows | | `29c9f66` | **2** | 0 | **29** | same | same | Zero new refusals and zero new permits at the lock. The only two rows that moved are `infra-core#754` comment 20294 and `prod#1109` comment 20295 — the operator's own unpinned `HOLD … DO NOT MERGE` park notes, i.e. exactly the class the seat named, and the direction the ruling asks for. One more row changed shape but not outcome: `infra-core#818` comment 21594 becomes verdict-shaped (stance `approve`, unchanged) and is covered, so it raises no problem and refuses nothing. Nothing else in the corpus moved — no new findings, no malformed-section refusal, no refusal on ordinary discussion, approvals or machine-form verdicts. **Break attempts on the unit reading (my own)** - An opener that states stance AND head is COMPLETE and keeps no block: `**APPROVE at <sha>**` and `**Verdict of record — ld-reviewer — head <sha>: APPROVE**` followed by a "caveat" paragraph stay approvals, at both heads. No false refusal found in this direction. - A resolution opener is not read as a unit: my own phrasings, including ones the resolution regexes do NOT know (`Blocker B1 is fixed at <sha>.` plus a paragraph naming a request for changes), stay proclamation-free at both heads. - Continuations: a list item `- head: <sha>`, a blockquoted `head:`, and a `head:` inside a fence under a real stance opener are all read as pins now, so a genuine hold in those spellings refuses. That is the fix working, and it is the shape I filed C-1 about below. - Ordinary discussion openers that merely mention the noun (`Reviewing the delta.`, `The review is green.`, `Reviews so far, for the record:`, `Approval summary`, `Second review of the delta — nothing to add.`, `Verdict-shaped discussion …`) are unread at both heads: zero findings, zero refusals, zero stance change. **Suite, CI, and the body's claims** `npx vitest run` → 35 files / **963 passed**. I also extracted `247aecb` and ran it: 35 / **944 passed**, so the body's 944 → 963 (+19) is honest. `scripts/test-in-deployed-shape.sh` → `ok: 35/35 files loaded and passed, 963/963 tests`, pinned tree `1.3.34`. CI on this head: 15/15 contexts success (run #350; `python` green again on #351). `git diff --numstat 247aecb..HEAD` touches exactly three files with ZERO deletions in the test file — the "no existing test edited" claim holds. The round-3 section of the body is accurate on every number I could re-derive; the only figure I could not reproduce exactly is the census breadth (their 38 PRs / 96 items, mine 39 / 99 because a PR opened since) and the findings total (theirs 27, mine 29 — same input, wider snapshot), with the same delta: findings unchanged, +2 `no-verdict-block`. ## Blockers None. ## Concerns - C-1: `verdictStatementLines` reads FENCED and BLOCKQUOTED lines as the author's own verdict, while this same diff declares quoted and fenced text documentation for the finding scan (`documentationLines`). Measured at `29c9f66`, all with `ld-reviewer` as the author: a comment opening `Quoting seat 1's verdict for the record:` over a fully labelled fenced APPROVE block at the head is now an APPROVAL OF RECORD that permits on its own, where `247aecb` refused (`unpinned` decided nothing); the same shape with REQUEST_CHANGES in the block becomes a false exact-head hold; and a `Verdict grammar:` documentation opener whose block shows a fully labelled machine hold example at the head is a false REFUSAL (needs a real head and both labels inside the example — with `<sha>` or without labels it is inert). The `## Verdict grammar` heading spelling of this already refused at `247aecb`, so the class is pre-existing and this round widens it from one spelling to three; incidence across 99 live items and 62 corpus bodies is ZERO, so I do not treat it as a blocker. Fix direction, one line of doctrine: skip documentation lines in the statement block too, or state in `docs/forgejo.md` that a fully labelled block is the author's stance wherever it appears. Follow-up, not this PR. - C-2: `tests/fixtures/prose-attack-corpus.json`'s `mustStillCount` array is declared in the test file's type but consumed by no test — the three forms are pinned by hand-written tests in § 2 instead. Dead fixture data; harmless, but the next reader will think the fixture is load-bearing. - C-3 (informational, for the orchestrator): the round-3 worker log's residual 1 — that only comment 22734's own session can clear the four id-less findings it raised — is stale as of comment 22755, which carries the canonical `The blockers raised in review 22734 are resolved on head 29c9f66c…` sentence. Measured on this thread at this head: `findOpenBlockers` 0 (4 on comment 22734 alone), and the lock permits with both round-3 seats on a `forgejo/landing.ts` change (`ok: true`). The PR body does not carry the stale claim; only the worker log does.
Collaborator

Verdict of record — ld-reviewer — head 29c9f66c1e: APPROVE

model: deepseek-flash
session: ses-108r3-seat2-e3cfdde9

Round 3, seat 2 of 2, final round. Independent seat: I read the diff 247aecb..29c9f66 (forgejo/landing.ts +166/−32, forgejo/tests/landing-finding-rule-2682.test.ts +192/−0, docs/forgejo.md +14/−1), ran both suites myself, and probed this head's landing.ts directly with bodies I wrote, in a scratch harness outside the repo (/tmp), against 247aecb extracted with git archive — a differential, not a re-read of anyone's numbers. No file edited, committed or pushed.

Ruling acceptance, measured at this head

  • GITS #209's shape (three ld-reviewer approvals, one carrying ### Findings and four RISK-n follow-ups): findOpenBlockers 0, assessFindingGrammar [], lock PERMITS.
  • BLOCKER B1: inside an APPROVE still blocks and still refuses the lock; form 2 with and without a token under ## Blockers still counts; a whole-comment REQUEST_CHANGES is a hold on its own.
  • ## Blockers + None. is clean and permits. An EMPTY ## Blockers still refuses with malformed-blockers, and so does the unquoted placeholder section.
  • A blockquoted seat template (> ## Blockers, > - <finding-id>: <severity> — <finding>, then a plain sentence) refuses nothing in either arm and permits; the fenced spelling is unchanged.
  • The four approval corpora (w3-lane 41 bodies, verdict-shaped controls 5, pr70 2, negation 25, pr694 3) replayed at their own heads: zero grammar problems, and the attack fixture's 13 prose lines raise zero findings both under a ## <section> heading and bare.

The round-3 blocker, on my own bodies

All seven statement shapes (verdict: request_changes + head:; **Verdict: REQUEST_CHANGES** + head:; **Verdict** + head: + REQUEST_CHANGES; **Verdict of record — ld-reviewer**; **Verdict summary**; **Approval verdict**; **Verdict of the round** + REQUEST_CHANGES at <sha>) now REFUSE beside a clean APPROVE, cite #2, use the exact-head hold language, and raise no grammar problem. ## Verdict + the same body is unchanged. A machine REQUEST_CHANGES with no head fails closed (no-verdict-block, refusal names #2 and the missing pin). A well-formed machine verdict: approve + head: is an approval of record that permits alone; a stance pinned to another head stays superseded and refuses nothing; a label-shaped row (no session:) is still not this arm's refusal — measured, ## Verdict: APPROVE + model + head with no session raises no no-verdict-block.

Both halves are present in the diff: the non-heading opener takes its label block (opensVerdictStatement), and ledger.unpinned stops being cover for a hold (if (v.polarity !== "hold")). Removing either half re-opens the seat's case, so the two are load-bearing together, as the body says.

The two guards, on the real bodies

  • infra-core#694 comment 17451: statement stays ONE line, readVerdictStance null, isVerdictShaped false, zero findings, lock permits — identical at 247aecb.
  • infra-core#664 comment 16105: readVerdictStance approve, statement one line, so the "do not land on it alone" caveat still cannot flip it — identical at 247aecb.

My own census, both heads, same input

Every OPEN PR of pi-extensions, infra-core, prod, ghostty-in-the-shell (39 PRs, 99 comment/review items), each assessed at its own head with both heads' code in the same process:

head no-verdict-block malformed-blockers open findings lock refusals lock permits
247aecb 0 0 29 38 / same rows
29c9f66 2 0 29 same same

Zero new refusals and zero new permits at the lock. The only two rows that moved are infra-core#754 comment 20294 and prod#1109 comment 20295 — the operator's own unpinned HOLD … DO NOT MERGE park notes, i.e. exactly the class the seat named, and the direction the ruling asks for. One more row changed shape but not outcome: infra-core#818 comment 21594 becomes verdict-shaped (stance approve, unchanged) and is covered, so it raises no problem and refuses nothing. Nothing else in the corpus moved — no new findings, no malformed-section refusal, no refusal on ordinary discussion, approvals or machine-form verdicts.

Break attempts on the unit reading (my own)

  • An opener that states stance AND head is COMPLETE and keeps no block: **APPROVE at <sha>** and **Verdict of record — ld-reviewer — head <sha>: APPROVE** followed by a "caveat" paragraph stay approvals, at both heads. No false refusal found in this direction.
  • A resolution opener is not read as a unit: my own phrasings, including ones the resolution regexes do NOT know (Blocker B1 is fixed at <sha>. plus a paragraph naming a request for changes), stay proclamation-free at both heads.
  • Continuations: a list item - head: <sha>, a blockquoted head:, and a head: inside a fence under a real stance opener are all read as pins now, so a genuine hold in those spellings refuses. That is the fix working, and it is the shape I filed C-1 about below.
  • Ordinary discussion openers that merely mention the noun (Reviewing the delta., The review is green., Reviews so far, for the record:, Approval summary, Second review of the delta — nothing to add., Verdict-shaped discussion …) are unread at both heads: zero findings, zero refusals, zero stance change.

Suite, CI, and the body's claims

npx vitest run → 35 files / 963 passed. I also extracted 247aecb and ran it: 35 / 944 passed, so the body's 944 → 963 (+19) is honest. scripts/test-in-deployed-shape.sh → ok: 35/35 files loaded and passed, 963/963 tests, pinned tree 1.3.34. CI on this head: 15/15 contexts success (run #350; python green again on #351). git diff --numstat 247aecb..HEAD touches exactly three files with ZERO deletions in the test file — the "no existing test edited" claim holds. The round-3 section of the body is accurate on every number I could re-derive; the only figure I could not reproduce exactly is the census breadth (their 38 PRs / 96 items, mine 39 / 99 because a PR opened since) and the findings total (theirs 27, mine 29 — same input, wider snapshot), with the same delta: findings unchanged, +2 no-verdict-block.

Blockers

None.

Concerns

  • C-1: verdictStatementLines reads FENCED and BLOCKQUOTED lines as the author's own verdict, while this same diff declares quoted and fenced text documentation for the finding scan (documentationLines). Measured at 29c9f66, all with ld-reviewer as the author: a comment opening Quoting seat 1's verdict for the record: over a fully labelled fenced APPROVE block at the head is now an APPROVAL OF RECORD that permits on its own, where 247aecb refused (unpinned decided nothing); the same shape with REQUEST_CHANGES in the block becomes a false exact-head hold; and a Verdict grammar: documentation opener whose block shows a fully labelled machine hold example at the head is a false REFUSAL (needs a real head and both labels inside the example — with <sha> or without labels it is inert). The ## Verdict grammar heading spelling of this already refused at 247aecb, so the class is pre-existing and this round widens it from one spelling to three; incidence across 99 live items and 62 corpus bodies is ZERO, so I do not treat it as a blocker. Fix direction, one line of doctrine: skip documentation lines in the statement block too, or state in docs/forgejo.md that a fully labelled block is the author's stance wherever it appears. Follow-up, not this PR.
  • C-2: tests/fixtures/prose-attack-corpus.json's mustStillCount array is declared in the test file's type but consumed by no test — the three forms are pinned by hand-written tests in § 2 instead. Dead fixture data; harmless, but the next reader will think the fixture is load-bearing.
  • C-3 (informational, for the orchestrator): the round-3 worker log's residual 1 — that only comment 22734's own session can clear the four id-less findings it raised — is stale as of comment 22755, which carries the canonical The blockers raised in review 22734 are resolved on head 29c9f66c… sentence. Measured on this thread at this head: findOpenBlockers 0 (4 on comment 22734 alone), and the lock permits with both round-3 seats on a forgejo/landing.ts change (ok: true). The PR body does not carry the stale claim; only the worker log does.
**Verdict of record — ld-reviewer — head 29c9f66c1eb8c0aac3d257ecaeea4f072edc7800: APPROVE** model: deepseek-flash session: ses-108r3-seat2-e3cfdde9 Round 3, seat 2 of 2, final round. Independent seat: I read the diff `247aecb..29c9f66` (`forgejo/landing.ts` +166/−32, `forgejo/tests/landing-finding-rule-2682.test.ts` +192/−0, `docs/forgejo.md` +14/−1), ran both suites myself, and probed this head's `landing.ts` directly with bodies I wrote, in a scratch harness outside the repo (`/tmp`), against `247aecb` extracted with `git archive` — a differential, not a re-read of anyone's numbers. No file edited, committed or pushed. **Ruling acceptance, measured at this head** - GITS #209's shape (three `ld-reviewer` approvals, one carrying `### Findings` and four `RISK-n` follow-ups): `findOpenBlockers` 0, `assessFindingGrammar` `[]`, lock PERMITS. - `BLOCKER B1:` inside an APPROVE still blocks and still refuses the lock; form 2 with and without a token under `## Blockers` still counts; a whole-comment REQUEST_CHANGES is a hold on its own. - `## Blockers` + `None.` is clean and permits. An EMPTY `## Blockers` still refuses with `malformed-blockers`, and so does the unquoted placeholder section. - A blockquoted seat template (`> ## Blockers`, `> - <finding-id>: <severity> — <finding>`, then a plain sentence) refuses nothing in either arm and permits; the fenced spelling is unchanged. - The four approval corpora (w3-lane 41 bodies, verdict-shaped controls 5, pr70 2, negation 25, pr694 3) replayed at their own heads: zero grammar problems, and the attack fixture's 13 prose lines raise zero findings both under a `## <section>` heading and bare. **The round-3 blocker, on my own bodies** All seven statement shapes (`verdict: request_changes` + `head:`; `**Verdict: REQUEST_CHANGES**` + `head:`; `**Verdict**` + `head:` + `REQUEST_CHANGES`; `**Verdict of record — ld-reviewer**`; `**Verdict summary**`; `**Approval verdict**`; `**Verdict of the round**` + `REQUEST_CHANGES at <sha>`) now REFUSE beside a clean APPROVE, cite `#2`, use the `exact-head hold` language, and raise no grammar problem. `## Verdict` + the same body is unchanged. A machine REQUEST_CHANGES with no head fails closed (`no-verdict-block`, refusal names `#2` and the missing pin). A well-formed machine `verdict: approve` + `head:` is an approval of record that permits alone; a stance pinned to another head stays superseded and refuses nothing; a label-shaped row (no `session:`) is still not this arm's refusal — measured, `## Verdict: APPROVE` + model + head with no session raises no `no-verdict-block`. Both halves are present in the diff: the non-heading opener takes its label block (`opensVerdictStatement`), and `ledger.unpinned` stops being cover for a hold (`if (v.polarity !== "hold")`). Removing either half re-opens the seat's case, so the two are load-bearing together, as the body says. **The two guards, on the real bodies** - `infra-core#694` comment 17451: statement stays ONE line, `readVerdictStance` null, `isVerdictShaped` false, zero findings, lock permits — identical at `247aecb`. - `infra-core#664` comment 16105: `readVerdictStance` `approve`, statement one line, so the "do not land on it alone" caveat still cannot flip it — identical at `247aecb`. **My own census, both heads, same input** Every OPEN PR of `pi-extensions`, `infra-core`, `prod`, `ghostty-in-the-shell` (39 PRs, 99 comment/review items), each assessed at its own head with both heads' code in the same process: | head | `no-verdict-block` | `malformed-blockers` | open findings | lock refusals | lock permits | |---|---|---|---|---|---| | `247aecb` | 0 | 0 | 29 | 38 | / same rows | | `29c9f66` | **2** | 0 | **29** | same | same | Zero new refusals and zero new permits at the lock. The only two rows that moved are `infra-core#754` comment 20294 and `prod#1109` comment 20295 — the operator's own unpinned `HOLD … DO NOT MERGE` park notes, i.e. exactly the class the seat named, and the direction the ruling asks for. One more row changed shape but not outcome: `infra-core#818` comment 21594 becomes verdict-shaped (stance `approve`, unchanged) and is covered, so it raises no problem and refuses nothing. Nothing else in the corpus moved — no new findings, no malformed-section refusal, no refusal on ordinary discussion, approvals or machine-form verdicts. **Break attempts on the unit reading (my own)** - An opener that states stance AND head is COMPLETE and keeps no block: `**APPROVE at <sha>**` and `**Verdict of record — ld-reviewer — head <sha>: APPROVE**` followed by a "caveat" paragraph stay approvals, at both heads. No false refusal found in this direction. - A resolution opener is not read as a unit: my own phrasings, including ones the resolution regexes do NOT know (`Blocker B1 is fixed at <sha>.` plus a paragraph naming a request for changes), stay proclamation-free at both heads. - Continuations: a list item `- head: <sha>`, a blockquoted `head:`, and a `head:` inside a fence under a real stance opener are all read as pins now, so a genuine hold in those spellings refuses. That is the fix working, and it is the shape I filed C-1 about below. - Ordinary discussion openers that merely mention the noun (`Reviewing the delta.`, `The review is green.`, `Reviews so far, for the record:`, `Approval summary`, `Second review of the delta — nothing to add.`, `Verdict-shaped discussion …`) are unread at both heads: zero findings, zero refusals, zero stance change. **Suite, CI, and the body's claims** `npx vitest run` → 35 files / **963 passed**. I also extracted `247aecb` and ran it: 35 / **944 passed**, so the body's 944 → 963 (+19) is honest. `scripts/test-in-deployed-shape.sh` → `ok: 35/35 files loaded and passed, 963/963 tests`, pinned tree `1.3.34`. CI on this head: 15/15 contexts success (run #350; `python` green again on #351). `git diff --numstat 247aecb..HEAD` touches exactly three files with ZERO deletions in the test file — the "no existing test edited" claim holds. The round-3 section of the body is accurate on every number I could re-derive; the only figure I could not reproduce exactly is the census breadth (their 38 PRs / 96 items, mine 39 / 99 because a PR opened since) and the findings total (theirs 27, mine 29 — same input, wider snapshot), with the same delta: findings unchanged, +2 `no-verdict-block`. ## Blockers None. ## Concerns - C-1: `verdictStatementLines` reads FENCED and BLOCKQUOTED lines as the author's own verdict, while this same diff declares quoted and fenced text documentation for the finding scan (`documentationLines`). Measured at `29c9f66`, all with `ld-reviewer` as the author: a comment opening `Quoting seat 1's verdict for the record:` over a fully labelled fenced APPROVE block at the head is now an APPROVAL OF RECORD that permits on its own, where `247aecb` refused (`unpinned` decided nothing); the same shape with REQUEST_CHANGES in the block becomes a false exact-head hold; and a `Verdict grammar:` documentation opener whose block shows a fully labelled machine hold example at the head is a false REFUSAL (needs a real head and both labels inside the example — with `<sha>` or without labels it is inert). The `## Verdict grammar` heading spelling of this already refused at `247aecb`, so the class is pre-existing and this round widens it from one spelling to three; incidence across 99 live items and 62 corpus bodies is ZERO, so I do not treat it as a blocker. Fix direction, one line of doctrine: skip documentation lines in the statement block too, or state in `docs/forgejo.md` that a fully labelled block is the author's stance wherever it appears. Follow-up, not this PR. - C-2: `tests/fixtures/prose-attack-corpus.json`'s `mustStillCount` array is declared in the test file's type but consumed by no test — the three forms are pinned by hand-written tests in § 2 instead. Dead fixture data; harmless, but the next reader will think the fixture is load-bearing. - C-3 (informational, for the orchestrator): the round-3 worker log's residual 1 — that only comment 22734's own session can clear the four id-less findings it raised — is stale as of comment 22755, which carries the canonical `The blockers raised in review 22734 are resolved on head 29c9f66c…` sentence. Measured on this thread at this head: `findOpenBlockers` 0 (4 on comment 22734 alone), and the lock permits with both round-3 seats on a `forgejo/landing.ts` change (`ok: true`). The PR body does not carry the stale claim; only the worker log does.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Homelab/pi-extensions!108
No description provided.