ci: remove the banner carve-out from the comment caps gate
Why
The gate joins blank-separated comment segments so a 2+gap+2 squirm stack
answers to one cap, but the banner carve-out undid the join at any
multiplicity: every gap-separated // --- or // ── segment kept its own
free 2-line row, so a run of banners carried unlimited prose the gate never
charged. That is the squirm shape in uniform, and it is the compliant edit
authors actually reach for: feat(oci): revalidate a stale tag against the u... (!1875 - merged) • Radamanthus Batnag • 19.4 went from
62 to 166 banners with every gate green (measured on
chore(skills): teach write-readable-go the comm... (!2015 - merged) • Radamanthus Batnag • 19.4), and that MR counters the hole with
guidance prose that nothing enforces.
We remove the carve-out entirely rather than bounding it. A bounded row still
hands every run one free block a prose preamble does not get, and any
exemption is a shape to farm. A banner is decoration: it now counts like
prose and spends the budget of whatever its run lands on. A lone banner
detached above undocumented code survives as a block of at most 2 lines, and
a banner plus a short doc fits an exported name's or the package clause's
cap of 3. Outside a _test.go file and outside a grouped declaration, a
banner above a documented unexported top-level name never fits, and the
conforming rewrite depends on the pair: deleting the banner when the doc
alone fits, detaching when the pair fits the detached cap of 2, and
compressing otherwise.
What (non-obvious)
The ratchet is unchanged: only touched segments count, so a legacy banner
header stays mergeable one segment at a time and charges when one edit
reaches a second segment. split_run and body_run collapse into one
sum_run, and the divider-detection state goes with the carve-out.
A multi-segment finding now names the touched segments (3-4,9-10) rather
than their start-end hull: the hull bracketed the untouched lines between
touched segments, which an author could cut without clearing the gate.
Single-segment findings keep the bare start line. Same findings, same
counts, new location text only (all-touched over every Go file: +1007/−1007
raw, 0 gained, 0 lost by range intersection).
One deliberate reversal: the documented squirm remediation was to open a
test-file preamble with a // --- rule, so the fleet's test files carry many
such banners. They stay grandfathered until touched, and the remediation on
touch is deletion or compression, per go-style.md's updated paragraph.
Blast radius, measured at this rebase (base 1df2de91) with the all-touched harness over every Go file and normalized by range intersection because joining re-keys spans: 349 sites gain enforcement (296 test-file, 34 unexported, 8 other, 7 exported, 4 merged doc-and-body-head) and none lose it. The five apparent losses in the raw diff are merged-class findings whose start line moved up into short banner segments that were free before and now join the doc under them, each verified against its replacement. The raw finding-text diff is +1188/−878, re-keyed by both the join and the touched-segment location format. The same measurement at the round-two tree read 152 gained, 0 lost.
Interplay: the ratchet skill landed first, in
chore(skills): teach write-readable-go the comm... (!2015 - merged) • Radamanthus Batnag • 19.4. This MR rebased onto it and
reconciles the write-readable-go evals it added. Their cap helper and
self-test probe carried the carve-out, the self-test regex read a bare line
or one range where the gate now names touched segments, and the eval prose
and go-style.md's banner-run paragraph called the gate silent on a run.
Every train run since round two failed lint:skill-scripts:write-readable-go
on the merged result. The new commit counts every segment in the helper,
accepts the segment list in the regex, and restates the prose in ratchet
terms. The file-header fixture's prompt carries the report this gate
produces, one 14-line block against the detached cap of 2, and the other
four prompts' reports match the gate unchanged. This MR leaves the
citation-only-fix question with npm remote test comments cite moved harness hel... (#915) • Unassigned.
Test plan
bash scripts/ci/check-comment-caps_test.shgreen under mawk and busybox awk, 205 assertions. Scenario 16 keeps its fixtures with joined verdicts (five findings: funcorder banner plus doc at 2 over cap 1, three-line banner joining at 4, one-line divider joining at 4, adjacent divider unchanged, box banner in a test file at 3 over cap 2) plus a fitting one-line banner and doc pair in a test file. Scenario 21 pins the ratchet and every landing class: one touched banner joins alone and passes, touching a second segment fails from either end of the run, a fresh three-banner run fails whole, a single banner above a doc fails (the explicit reversal), and each cap-3 landing (exported, the package clause, and a grouped member) is pinned in both directions, a banner over a two-line doc failing at 4 against cap 3 and a fitting three-line pair passing. Re-adding a divider carve-out gated oncapfor(c) == 3fails four assertions, where all 198 passed before the cap-3 fixtures existed.python3 .claude/skills/write-readable-go/evals/grade.py --selftest: the four probes agree with the gate (3, 4, 2, 2). The five eval fixtures run through the gate in a throwaway repository match the prompts' reports.- Tree-wide all-touched measurement as above, 349 gained, 0 lost.
scripts/ci/check-comment-caps.sh --base origin/mainon this branch: OK.- shellcheck and shfmt clean, and the pre-commit chain (markdownlint, Vale, gitlint) green on the commits. Vale's one new hit is the file's standard "unexported" spelling suggestion, present eight times on main.
Context for LLM agents
Rejected alternatives: bounding the carve-out to one free row per run (built and measured first, +18/-0 all-touched, rejected by the operator because any exemption is a shape agents farm), and guidance-only enforcement (what chore(skills): teach write-readable-go the comm... (!2015 - merged) • Radamanthus Batnag • 19.4 adds, which the measurement above shows gets routed around).
Non-goals: the citation-only-fix ratchet
(npm remote test comments cite moved harness hel... (#915) • Unassigned owns it), retroactive cleanup of
grandfathered banner runs (the ratchet cleans them on touch), any change
to directive or bare-// handling, and a redesign of the
file-header-banner-run eval around a grandfathered run the gate stays
silent on (its fixture and grader are unchanged, only its prompt's gate
paragraph and the surrounding prose moved to what this gate reports).