diff --git a/scripts/pm/check-half-states.mjs b/scripts/pm/check-half-states.mjs index 825aefda37..968c210c8b 100644 --- a/scripts/pm/check-half-states.mjs +++ b/scripts/pm/check-half-states.mjs @@ -1407,6 +1407,121 @@ export const OWNERSHIP_MARKER_NEAR_MISS_FORMS = Object.freeze([ /** How many near misses one summary clause NAMES before it stops. */ export const OWNERSHIP_MARKER_NEAR_MISS_NAME_CAP = 5; +/** + * The census POPULATION — a `pm:seat` post is OUT of it (#18926). + * + * The vocabulary above asks 「does this line LOOK like an ownership record the + * reader refused?」. The population asks a prior question the first version never + * asked: 「is an ownership record owed on this thread AT ALL?」. On a `pm:seat` + * post the answer is no, and the protocol says so in as many words: a seat + * post's ownership is its BODY (the registration, the 🟢/⏳ title the H5 pair + * reads) plus its AUDIT COMMENTS — the protocol never puts a `Claim:` comment on + * one. What its comments carry instead is SHIFT NARRATION, and a shift + * narration written by a seat about its own lane opens sentences with exactly + * the directive words this vocabulary anchors on. + * + * Measured, ⛔ not assumed — objectstack's OPEN board read through the REST + * proxy 2026-09-18T13:0xZ with the tree at `784366372`, 539 open cards, 484 of + * them carrying a comment, the census run over every thread: 36 near-miss lines + * on 30 cards, of which 9 lines on 5 `pm:seat` posts (#6017 · #6021 · #6023 ×4 · + * #6026 · #6367). Every one of the nine is narration — 「Claimed and dispatched, + * batch refilled to 3:」, 「### Released clean」 — and not one of them asks + * anything of anybody. Four of the five are rows 1–4 of #18914's sixteen, filed + * as 「no readable ownership record」 where no record was ever owed. + * + * ⛔ It is NOT a silent drop, and the difference is the whole point of a census: + * an excluded thread is COUNTED and reported under its own clause member, so the + * report says 「5 `pm:seat` thread(s) OUT of the population (9 line(s))」 rather + * than shrinking a number nobody can reconstruct. A filter you cannot see is + * indistinguishable from the over-reading it replaced. + * + * ⛔ And it reads the LABEL, buying nothing: the same `labelNames` the H5/H6 seat + * rows read, off the issue the caller already holds from the label page it + * already consumed. No extra request, which is what lets the census keep its + * 「buys NOTHING」 contract. + * + * @param {object} issue — the REST issue row the sweep already holds. + * @returns {boolean} — false for a `pm:seat` post, true for every work card. + */ +export function ownershipCensusSpeaksAbout(issue) { + return !labelNames(issue ?? {}).includes('pm:seat'); +} + +/** + * The release ANNOUNCEMENT heading — a delivery report, ⛔ not an ownership + * near miss (#18926). + * + * The shape, measured on the live board rather than guessed at: a heading whose + * word is the PARTICIPLE `Released`, whose remainder names the `PR #n` that + * landed or the `pm:*` → `pm:*` transition it unblocked, and which names NO + * session. The specimen the filing card is about, pasted from the REST read of + * objectstack#17536 comment `5625672905`: + * + * `## Released — **PR #17517 merged.** `pm:blocked` → `pm:queue`; …` + * + * That line hands nothing over. #17536 was never claimed — no assignee, no + * `Claim:` of any spelling — so no `Release:` is owed on it, and the heading is + * reporting that a blocker fell, in the voice of the board rather than of a + * holder. Read as a near miss it says 「someone's release line is unreadable」 + * about a card nobody ever held. + * + * ## The three narrowings, each with the line that forced it + * + * Measured over the same corpus `ownershipCensusSpeaksAbout` names (539 open + * cards, 484 threads, 36 near-miss lines). ⚠️ Every one of these is a + * NARROWING — a line this reading declines to swallow stays in the census, which + * is the safe direction for a filter whose failure mode is silence: + * + * · HEADING forms only (`RELEASE_ANNOUNCEMENT_HEADING_FORMS`). A heading is an + * announcement; the colon-anchored DIRECTIVE spellings are how the protocol + * writes an ownership record, and `inflected-word`'s own fixture is + * `Released: session …`. The corpus carries three `separator` lines spelled + * `Release-landed: … (PR #18852)` (#18740 ×3, #16529) which name a PR and no + * session: they are NOT swallowed, because they are not headings. + * · The PARTICIPLE, ⛔ never the bare noun `Release`. `Release` opens the + * directive (`## Release: …`, `## Release + seat ruling — …`) and the corpus + * carries three such headings on live work cards (#16233 names a PR inside + * one — `### Release: PR #18523 落下了…` — and stays listed; #16712, #18172). + * `Releasing` is left unnamed: measured ZERO, and this file adds a form WITH + * its fixture, never from symmetry. + * · NO session token on the line, in either spelling (`session`, 「会话」). This + * is the clause the mechanism assumption demanded be tested: a release that + * DOES name its session is a record, readable or not, and must stay in the + * census. The corpus's own counter-example is #6023's + * `## Released tail — in flight under THIS session's process tree` — a + * participle heading that is not swallowed by this reading at all. + * + * Judged on the LINE, ⛔ not the comment: the census is line-level by + * construction, and the comment level is already `markerMatches`' — a thread + * carrying a readable record elsewhere is a question for the rows that read + * ownership, never for this one. + * + * @param {string} formId — the form the census named the line by. + * @param {string} prefix — the offending prefix the census captured. + * @param {string} line — the whole line, for the session and remainder reads. + * @returns {{ pr: boolean, transition: boolean }|null} — null when the line is + * an ordinary near miss, otherwise WHICH of the two things it names. + */ +export const RELEASE_ANNOUNCEMENT_HEADING_FORMS = Object.freeze(['heading-bare']); +/** `PR #n` in the remainder — the delivery the announcement reports. */ +export const RELEASE_ANNOUNCEMENT_PR_RE = /\bPR[ \t]*#\d+/iu; +/** A `pm:x` → `pm:y` transition — the unblocking, decorations tolerated. */ +export const RELEASE_ANNOUNCEMENT_TRANSITION_RE = + /[_*`]{0,3}pm:[a-z][a-z-]*[_*`]{0,3}[ \t]*(?:→|⇒|->|=>)[ \t]*[_*`]{0,3}pm:[a-z][a-z-]*/iu; +/** The token that makes a line a RECORD rather than an announcement. */ +export const OWNERSHIP_SESSION_TOKEN_RE = /session|会话/iu; + +export function releaseAnnouncementHeading(formId, prefix, line) { + if (!RELEASE_ANNOUNCEMENT_HEADING_FORMS.includes(String(formId))) return null; + if (String(prefix ?? '').replace(/[#_*`\s]/gu, '').toLowerCase() !== 'released') return null; + const text = String(line ?? ''); + if (OWNERSHIP_SESSION_TOKEN_RE.test(text)) return null; + const pr = RELEASE_ANNOUNCEMENT_PR_RE.test(text); + const transition = RELEASE_ANNOUNCEMENT_TRANSITION_RE.test(text); + if (!pr && !transition) return null; + return { pr, transition }; +} + /** * Every near miss on one thread — the card-level reading the census consumes. * @@ -1425,11 +1540,29 @@ export const OWNERSHIP_MARKER_NEAR_MISS_NAME_CAP = 5; * * @param {{ id?: number, body?: string }[]} commentRows — REST rows, NOT bodies: * the row names the COMMENT, and an id is what a seat opens. - * @returns {{ commentId: string|null, form: string, what: string, prefix: string }[]} + * ## The two channels (#18926), and why this is a SPLIT rather than a filter + * + * `releaseAnnouncementHeading` above names a line that looks like a refused + * release and is a delivery report. Such a line leaves `misses` and lands in + * `announcements`, with its card, its comment and its prefix intact, so the + * summary reports it under its OWN clause member. ⛔ Nothing is dropped: the two + * arrays partition exactly the lines the single array used to carry, which is + * what lets a reader reconstruct the old number from the new report and is the + * only honest shape for narrowing a census. + * + * `ownershipMarkerNearMisses` stays the near-miss half, and stays the name every + * caller and every fixture already uses. + * + * @param {{ id?: number, body?: string }[]} commentRows — REST rows, NOT bodies: + * the row names the COMMENT, and an id is what a seat opens. + * @returns {{ misses: object[], announcements: object[] }} — each member a + * `{ commentId, form, what, prefix }` row; an announcement also carries + * `names` (which of `pr` / `transition` the line spells out). */ -export function ownershipMarkerNearMisses(commentRows) { +export function ownershipMarkerNearMissCensus(commentRows) { const rows = Array.isArray(commentRows) ? commentRows : []; - const out = []; + const misses = []; + const announcements = []; for (const row of rows) { const body = String(row?.body ?? ''); const seen = new Set(); @@ -1444,18 +1577,25 @@ export function ownershipMarkerNearMisses(commentRows) { const key = `${form.id}\u0001${prefix}`; if (!seen.has(key)) { seen.add(key); - out.push({ + const named = { commentId: commentIdText(row?.id), form: form.id, what: form.what, prefix, - }); + }; + const announcement = releaseAnnouncementHeading(form.id, prefix, line); + if (announcement) announcements.push({ ...named, names: announcement }); + else misses.push(named); } break; } } } - return out; + return { misses, announcements }; +} + +export function ownershipMarkerNearMisses(commentRows) { + return ownershipMarkerNearMissCensus(commentRows).misses; } /** @@ -17703,6 +17843,19 @@ export const SWEEP_COUNT_KEYS = [ 'markerNearMissCards', 'markerNearMissJudged', 'markerNearMissNamed', + // The census POPULATION and the announcement CHANNEL (#18926). Both are + // EXCLUSIONS, so both ride this contract for one reason: an exclusion a report + // cannot print is indistinguishable from the over-reading it replaced. + // `markerNearMissSeatPosts` counts the `pm:seat` threads that left the + // population and `markerNearMissSeatLines` the near-miss lines they carried — + // the pair is what lets a reader reconstruct the pre-filter number. + // `markerNearMissAnnouncements` / `markerNearMissAnnounced` are the delivery + // reports, a count beside an ARRAY of names for `markerNearMissNamed`'s reason: + // a count alone tells a seat there is something to find and ⛔ not where. + 'markerNearMissSeatPosts', + 'markerNearMissSeatLines', + 'markerNearMissAnnouncements', + 'markerNearMissAnnounced', 'refBeyond', ]; @@ -17834,6 +17987,14 @@ export function summaryLine(counts, findingCount) { const nearMissCards = counts.markerNearMissCards ?? 0; const nearMissJudged = counts.markerNearMissJudged ?? 0; const nearMissNamed = Array.isArray(counts.markerNearMissNamed) ? counts.markerNearMissNamed : []; + // The population and the announcement channel (#18926), defaulting for the + // reason every count here does, and the ARRAY defaulting to an array. + const nearMissSeatPosts = counts.markerNearMissSeatPosts ?? 0; + const nearMissSeatLines = counts.markerNearMissSeatLines ?? 0; + const nearMissAnnouncements = counts.markerNearMissAnnouncements ?? 0; + const nearMissAnnounced = Array.isArray(counts.markerNearMissAnnounced) + ? counts.markerNearMissAnnounced + : []; const refBeyond = counts.refBeyond ?? 0; return ( `check-half-states: swept ${counts.issues} open pm-/p0-labeled issue(s), ${counts.unscoped} open ` + @@ -18299,6 +18460,27 @@ export function summaryLine(counts, findingCount) { 'offending prefix so the next decoration is ADDED to the vocabulary instead of replaying this ' + 'silently. ⚠️ A LOWER BOUND twice over: it reads only the threads other rows already bought, ' + 'and only the forms the vocabulary names. ' + + // The two EXCLUSIONS (#18926), rendered UNCONDITIONALLY beside the census + // for the clause's own reason: a narrowing nobody can see is the + // over-reading it replaced, wearing a smaller number. Both members print + // their count even at zero, so a run where nothing was excluded and a run + // where the exclusions stopped being applied cannot print alike. + `${nearMissSeatPosts} \`pm:seat\` thread(s) are OUT of that population ` + + `(${nearMissSeatLines} near-miss line(s) not listed above): a seat post's ownership is its ` + + 'BODY — the registration and the 🟢/⏳ title H5/H6 read — plus its AUDIT COMMENTS, and the ' + + 'protocol never puts a `Claim:` comment on one, so what its comments carry is SHIFT NARRATION ' + + 'in which a directive word opens a sentence. ⛔ COUNTED, never silently dropped: the two ' + + 'numbers are what let a reader reconstruct what the unfiltered census printed. ' + + `${nearMissAnnouncements} further line(s) are release ANNOUNCEMENTS rather than refused ` + + 'records — a heading whose word is the PARTICIPLE `Released`, whose remainder names the ' + + '`PR #n` that landed or the `pm:*` → `pm:*` transition it unblocked, and which names NO ' + + 'session: a delivery report on a card nobody held, so no `Release:` is owed and there is no ' + + 'unreadable record to normalise' + + `${nearMissAnnounced.length > 0 ? ` — ${nearMissAnnounced.join('; ')}` : ''}. ` + + 'The reading is deliberately NARROW and every narrowing leaves the line in the census above: ' + + 'HEADING forms only (`Release-landed: … (PR #n)` is a `separator` line and stays), the ' + + 'PARTICIPLE only (`## Release: …` opens the directive and stays), and NO session token in ' + + 'either spelling (a release that names its session is a record, readable or not, and stays). ' + `Report-only: findings are patrol input, not a gate verdict.` ); } @@ -20580,6 +20762,12 @@ async function sweep(options = {}) { markerNearMissCards: 0, markerNearMissJudged: 0, markerNearMissNamed: [], + // The population and the announcement channel (#18926), initialised on the + // same grounds: an exclusion that renders `undefined` reads as no exclusion. + markerNearMissSeatPosts: 0, + markerNearMissSeatLines: 0, + markerNearMissAnnouncements: 0, + markerNearMissAnnounced: [], maintainerActionCandidates: 0, maintainerActionProbed: 0, // H56's census (#17314) — how many of the comments H44 already read carry @@ -22792,14 +22980,30 @@ async function sweepInto(findings, seen, seenPrs, seenMerged, seenUnscoped, seen // is the denominator that says so. ⛔ It files no finding and proposes no // state either — a near miss is a line nobody read, never a half-state. // - // ⛔ Gated on NOTHING else: every population gate in this file exists to - // avoid buying a fetch, and this pass buys none. A near miss on a card no - // row speaks about is exactly the reading that would otherwise be lost. + // ⛔ Gated on NOTHING else that costs a fetch: every population gate in this + // file exists to avoid buying one, and this pass buys none. A near miss on a + // card no row speaks about is exactly the reading that would otherwise be + // lost. + // + // ⚠️ It IS gated on one thing that costs nothing — `ownershipCensusSpeaksAbout` + // (#18926), a read of the label page's own `labels` array. A `pm:seat` post is + // out of the POPULATION, not out of the report: it is counted, its lines are + // counted, and the clause says so. The reason is at the predicate, and the + // difference between the two exclusions matters — a seat post leaves the + // population (no record is owed on the THREAD), a release announcement leaves + // the near-miss CHANNEL (the LINE is not a refused record). { const nearMissRows = commentCache.get(issue.number); - if (nearMissRows !== undefined) { + if (nearMissRows !== undefined && !ownershipCensusSpeaksAbout(issue)) { + // ⛔ Counted, never silently dropped — and the LINES are counted too, + // because the population statement a reader can act on is the one that + // lets them reconstruct what the old census printed. + stats.markerNearMissSeatPosts = (stats.markerNearMissSeatPosts ?? 0) + 1; + stats.markerNearMissSeatLines = + (stats.markerNearMissSeatLines ?? 0) + ownershipMarkerNearMisses(nearMissRows).length; + } else if (nearMissRows !== undefined) { stats.markerNearMissJudged = (stats.markerNearMissJudged ?? 0) + 1; - const misses = ownershipMarkerNearMisses(nearMissRows); + const { misses, announcements } = ownershipMarkerNearMissCensus(nearMissRows); if (misses.length > 0) { stats.markerNearMissLines = (stats.markerNearMissLines ?? 0) + misses.length; stats.markerNearMissCards = (stats.markerNearMissCards ?? 0) + 1; @@ -22810,6 +23014,20 @@ async function sweepInto(findings, seen, seenPrs, seenMerged, seenUnscoped, seen ); } } + // The release-ANNOUNCEMENT channel (#18926) — its own count and its own + // names, under the same cap, so the excluded line stays as greppable as + // the ones that remain. + if (announcements.length > 0) { + stats.markerNearMissAnnouncements = + (stats.markerNearMissAnnouncements ?? 0) + announcements.length; + for (const shout of announcements) { + if (stats.markerNearMissAnnounced.length >= OWNERSHIP_MARKER_NEAR_MISS_NAME_CAP) break; + stats.markerNearMissAnnounced.push( + `#${issue.number} comment ${shout.commentId ?? 'id UNREADABLE'} 「${shout.prefix}」 ` + + `(${[shout.names.pr ? 'names a PR' : '', shout.names.transition ? 'names a `pm:*` transition' : ''].filter(Boolean).join(', ')})`, + ); + } + } } } // H58 (#17417) — the queued card whose own text says it is not queue work. @@ -24437,7 +24655,20 @@ export const SELF_TEST_BATTERIES = Object.freeze({ // one or silently dropped. A widening whose controls can drift out of the // suite is how a repair becomes a silencer, and a vocabulary nobody asserts // on is how the next decoration replays this card. - 'H2/H47/H66 decorated ownership marker': 136, + // + // ⭐ RAISED 136 → 184 by #18926 (140 → 193 registered), which is the floor + // discipline working rather than a number being tidied: that card NARROWS the + // census — a `pm:seat` thread leaves the population, a release ANNOUNCEMENT + // heading leaves the near-miss channel — and a narrowing is the one direction + // in which a suite can go green by asserting less. So the cases it adds are + // the ones that would catch that: the five measured rows as fixtures, the + // three narrowings each pinned through the corpus line that forced it (a + // `separator` release, a bare-noun heading, a participle heading naming a + // session), the positive control that a real near miss on a non-seat card is + // still listed byte-identically, and the ablation pin proving the excluded + // line IS a near miss under the vocabulary alone. ⛔ Never lower it to + // accommodate a filter that swallowed more than it declared. + 'H2/H47/H66 decorated ownership marker': 184, // Registered with the measured body cap (#18664); the pin sits just under // the count on its neighbours' grounds. What this battery floors is a // MEASUREMENT and its UNIT — `ISSUE_BODY_LIMIT` bisected to one byte on a @@ -35264,7 +35495,18 @@ Doubles as the fire's **write self-check** (step 0). \`201\` is not the reading. b(BATTERY68, '#18831 control: ⛔ …nor the other three release-prose openings the corpus carries', ownershipMarkerNearMisses(rows68('**Release checklist, platform side:** #14599\n**Release board: 5 additions**, each against a named criterion\nRelease confirmed on two readings before acting')).length, 0); b(BATTERY68, '#18831 control: the canonical spellings the reader DOES read are ⛔ never near misses, decorated or not', [ownershipMarkerNearMisses(rows68('Claim: seat, session `session_x`')).length, ownershipMarkerNearMisses(rows68('Claimed: seat, session `session_x`')).length, ownershipMarkerNearMisses(rows68('**Claim:** seat, session `session_x`')).length].join(','), '0,0,0'); b(BATTERY68, '#18831 control ⭐ the reading and this census are still COMPLEMENTS after the addition — the live #16529 record beside a canonical claim yields nothing', ownershipMarkerNearMisses(rows68(`${SPECIMEN_16529}\n**Claim:** seat, session \`session_x\``)).length, 0); - b(BATTERY68, '#18831: the release side of the HEADING form is named too, where the evidence is — a real release record written as a heading', miss68('## Released — **PR #17517 merged.** `pm:blocked` → `pm:queue`').form, 'heading-bare'); + // ⚠️ RE-POINTED by #18926, ⛔ not deleted. This case's claim — the `heading-bare` + // form names the RELEASE side, not the claim side alone — is untouched and + // still floored. What moved is its FIXTURE: the line it used to carry was + // #17536's blocker-release heading, which #18926 rules is a delivery report and + // moves to the census's announcement channel, so a fixture left here would have + // pinned this branch through a line that no longer reaches it. The replacement + // is #16712 comment 5605768467, pasted from the REST read — a live release + // heading on a work card that is NOT an announcement (it names no PR and no + // transition), so it exercises the same form on the same side. Where the old + // fixture went is pinned in the #18926 block below, ⛔ never left implicit. + b(BATTERY68, '#18831: the release side of the HEADING form is named too, where the evidence is — a real release record written as a heading', miss68('## Release + seat ruling — the reported defect is DISPROVED; what survives is a different defect in a different lane').form, 'heading-bare'); + b(BATTERY68, '#18831 ⭐ …and the fixture this case USED to carry is still named by the same form, on #18926\'s announcement channel', ownershipMarkerNearMissCensus(rows68('## Released — **PR #17517 merged.** `pm:blocked` → `pm:queue`')).announcements[0]?.form, 'heading-bare'); b(BATTERY68, '#18831: …and a `+`-suffixed CLAIMED heading, the fourth heading shape the corpus carries', miss68('## CLAIMED + dispatch order — #13457').form, 'heading-bare'); // THE READER — complements by construction, and the conservative half. @@ -35303,6 +35545,103 @@ Doubles as the fire's **write self-check** (step 0). \`201\` is not the reading. b(BATTERY68, 'H67: …and the remaining two lower bounds are still declared', h67row(I16529, { number: 16529 }).includes('LOWER BOUND, two ways'), true); b(BATTERY68, 'H67 summary: the clause declares the closure too, ⛔ rather than keeping a stale loss', saidBy('h67QueueDelivery', summaryLine(NEAR_MISS_COUNTS, 0)).includes('WAS a second way and is no longer'), true); + // ⭐ THE CENSUS POPULATION AND THE ANNOUNCEMENT CHANNEL (#18926) ----------- + // + // The card: five of #18914's sixteen 「no readable ownership record」 rows have + // NO record to normalise — four `pm:seat` posts whose comments are shift + // narration, and one blocker-release heading on a card nobody ever claimed. + // + // Every line below is PASTED from the REST read of its own comment + // (2026-09-18T12:5xZ–13:0xZ through the session proxy), ⛔ never retyped from + // the filing card's table. ⚠️ And the paste FALSIFIED the dispatch's + // assumption that the five rows' FIRST lines are the fixtures: on three of the + // five the census names a LATER narration line, and the heading the card's + // table quotes carries no near miss at all. The fixture is the line the census + // NAMES — pinned here — with the first lines beside them so the discrepancy is + // a reading rather than a silence. + const SEAT_6017 = 'Claimed and dispatched, batch refilled to 3:'; + const SEAT_6017_FIRST = '## Seat correction — the lane stopped dispatching for ~4 hours and there was no gate holding it'; + const SEAT_6021 = 'Claiming #15222 at 19:13Z I wrote, in the claim comment, a line-initial `Clause-②: yes` with its justification. The label write in the same claim was:'; + const SEAT_6026 = '### Released clean'; + const SEAT_6367 = '**Claimed and dispatched from this lane (round 1):**'; + const RELEASE_17536 = '## Released — **PR #17517 merged.** `pm:blocked` → `pm:queue`; the blocker line is struck in the body.'; + const SEAT_LINES = [SEAT_6017, SEAT_6021, SEAT_6026, SEAT_6367]; + + // The four seat lines ARE near misses as lines — the vocabulary is untouched, + // which is the ⛔ no-widening half of the ruling read from the other side. + for (const [where, line, form] of [ + ['#6017 comment 5691995598', SEAT_6017, 'bare-word'], + ['#6021 comment 5625313119', SEAT_6021, 'bare-word'], + ['#6026 comment 5274500724', SEAT_6026, 'heading-bare'], + ['#6367 comment 5294956565', SEAT_6367, 'bare-word'], + ]) { + b(BATTERY68, `#18926 ${where}: the LINE is still named by the vocabulary — ⛔ nothing was widened or narrowed there`, miss68(line).form, form); + } + b(BATTERY68, '#18926 ⭐ …and the POPULATION is what excludes them: a `pm:seat` post is out of it', ownershipCensusSpeaksAbout(issue(['pm:seat'])), false); + b(BATTERY68, '#18926 ⭐ control: an ordinary work card is IN the population, so the filter is scoped to the carrier', ownershipCensusSpeaksAbout(issue(['pm:queue', 'domain:cli'])), true); + b(BATTERY68, '#18926: …a seat post carrying a LANE label too is still out — the sticker decides, ⛔ not the lane', ownershipCensusSpeaksAbout(issue(['pm:seat', 'domain:engine'])), false); + b(BATTERY68, '#18926: …and a card with no labels at all is IN, ⛔ never excluded by absence', ownershipCensusSpeaksAbout(issue([])), true); + b(BATTERY68, '#18926: the predicate reads a missing issue as IN rather than throwing', ownershipCensusSpeaksAbout(undefined), true); + b(BATTERY68, '#18926: …and tolerates the string-label REST shape `labelNames` accepts', ownershipCensusSpeaksAbout({ labels: ['pm:seat'] }), false); + b(BATTERY68, '#18926 ⭐ the paste FALSIFIED the first-line assumption: #6017\'s own first line carries NO near miss, so the fixture is the narration line', [ownershipMarkerNearMisses(rows68(SEAT_6017_FIRST)).length, miss68(SEAT_6017).prefix].join(','), '0,Claimed'); + b(BATTERY68, '#18926: …and the four seat lines really differ from each other, so the roster is four fixtures and ⛔ not one repeated', new Set(SEAT_LINES).size, 4); + + // THE ANNOUNCEMENT CHANNEL — the line leaves `misses` and lands in + // `announcements`, ⛔ counted rather than dropped. + b(BATTERY68, '#18926 ⭐ #17536 comment 5625672905: the blocker-release heading is ⛔ NO LONGER a near miss', ownershipMarkerNearMisses(rows68(RELEASE_17536)).length, 0); + b(BATTERY68, '#18926 ⭐ …it is COUNTED on the announcement channel instead, ⛔ never silently dropped', ownershipMarkerNearMissCensus(rows68(RELEASE_17536)).announcements.length, 1); + b(BATTERY68, '#18926 …naming BOTH things the line spells out, which is what makes it a delivery report', JSON.stringify(ownershipMarkerNearMissCensus(rows68(RELEASE_17536)).announcements[0]?.names), '{"pr":true,"transition":true}'); + b(BATTERY68, '#18926 …and it keeps its card, comment and prefix, so a seat can still grep it', [ownershipMarkerNearMissCensus(rows68(RELEASE_17536)).announcements[0]?.commentId, ownershipMarkerNearMissCensus(rows68(RELEASE_17536)).announcements[0]?.prefix].join(' '), '5691473966 ## Released'); + b(BATTERY68, '#18926 ⭐ the two channels PARTITION the line — it is on exactly one of them, so no number can be reconstructed wrong', [ownershipMarkerNearMissCensus(rows68(RELEASE_17536)).misses.length, ownershipMarkerNearMissCensus(rows68(RELEASE_17536)).announcements.length].join(','), '0,1'); + b(BATTERY68, '#18926: the LINE is still read by NEITHER marker — the exclusion is the census\'s, ⛔ not the reader\'s', markerMatches(CLAIM_COMMENT_MARKER, RELEASE_17536) || markerMatches(RELEASE_COMMENT_MARKER, RELEASE_17536), false); + b(BATTERY68, '#18926 ⭐ ABLATION: under the vocabulary alone — the reading removed — the line IS a near miss, so this pin can FAIL', OWNERSHIP_MARKER_NEAR_MISS_FORMS.some((f) => { const h = f.re.exec(RELEASE_17536); return h !== null && RELEASE_17536.slice(h[0].length).trim() !== ''; }), true); + b(BATTERY68, '#18926: …and it was named `heading-bare` before the reading landed, which is the form the announcement rides', OWNERSHIP_MARKER_NEAR_MISS_FORMS.find((f) => { const h = f.re.exec(RELEASE_17536); return h !== null && RELEASE_17536.slice(h[0].length).trim() !== ''; })?.id, 'heading-bare'); + + // THE THREE NARROWINGS, each with the corpus line that forced it. Every one is + // a line that STAYS in the census: a narrowing whose controls can drift out of + // the suite is how a filter becomes a silencer. + b(BATTERY68, '#18926 narrowing ⭐ HEADING forms only: `Release-landed: … (PR #18852)` is a `separator` line and STAYS a near miss (#18740 comment 5723834336)', miss68('Release-landed: 八处(rest ×4 · spec ×4,含每包两份副本)= `18cc3b1df`(PR #18852)').form, 'separator'); + b(BATTERY68, '#18926 narrowing: …and the roster of announcement-bearing forms is exactly the one heading form, FROZEN', [RELEASE_ANNOUNCEMENT_HEADING_FORMS.join(','), Object.isFrozen(RELEASE_ANNOUNCEMENT_HEADING_FORMS)].join(' '), 'heading-bare true'); + b(BATTERY68, '#18926 narrowing: …every member of it is a DECLARED near-miss form, so the reading can never name a form the vocabulary dropped', RELEASE_ANNOUNCEMENT_HEADING_FORMS.every((id) => OWNERSHIP_MARKER_NEAR_MISS_FORMS.some((f) => f.id === id)), true); + b(BATTERY68, '#18926 narrowing ⭐ the PARTICIPLE only: `### Release: PR #18523 …` names a PR and STAYS a near miss (#16233 comment 5704218834)', miss68('### Release: PR #18523 落下了**普查与边界记录**;余下的是**路线选择**,⛔ 未落').form, 'heading'); + b(BATTERY68, '#18926 narrowing: …and so does the bare-noun heading that names no PR at all (#16712 comment 5605768467)', miss68('## Release + seat ruling — the reported defect is DISPROVED; what survives is a different defect in a different lane').form, 'heading-bare'); + b(BATTERY68, '#18926 narrowing: …`Releasing` is left UNNAMED — measured zero on the corpus, and a form arrives WITH its fixture', ownershipMarkerNearMissCensus(rows68('## Releasing — PR #17517 merged. `pm:blocked` → `pm:queue`')).announcements.length, 0); + b(BATTERY68, '#18926 narrowing ⭐ NO session token: #6023\'s participle heading names one and STAYS a near miss (comment 5552092492)', miss68('## Released tail — in flight under THIS session\'s process tree').form, 'heading-bare'); + b(BATTERY68, '#18926 narrowing ⭐ …the assumption the dispatch asked to TEST: the SAME announcement line plus a session is ⛔ not swallowed', ownershipMarkerNearMissCensus(rows68(`${RELEASE_17536} session \`session_x\``)).announcements.length, 0); + b(BATTERY68, '#18926 narrowing: …and it stays a near miss on the other channel rather than vanishing between them', ownershipMarkerNearMisses(rows68(`${RELEASE_17536} session \`session_x\``)).length, 1); + b(BATTERY68, '#18926 narrowing: …the Chinese spelling 「会话」 holds the line back too, so a Chinese-written record is ⛔ never swallowed', ownershipMarkerNearMissCensus(rows68('## Released — **PR #17517 merged.** 会话 `session_x`')).announcements.length, 0); + b(BATTERY68, '#18926 narrowing: a participle heading naming NEITHER a PR nor a transition is an ordinary near miss', ownershipMarkerNearMissCensus(rows68('## Released — the lane is clear now')).announcements.length, 0); + b(BATTERY68, '#18926: …a transition ALONE is enough, which is the half the card\'s 「label transition」 names', ownershipMarkerNearMissCensus(rows68('## Released — `pm:blocked` → `pm:queue`')).announcements.length, 1); + b(BATTERY68, '#18926: …and a PR ALONE is too', ownershipMarkerNearMissCensus(rows68('## Released — **PR #17517 merged.**')).announcements.length, 1); + b(BATTERY68, '#18926: the predicate answers null for a form it does not carry, ⛔ never a truthy default', releaseAnnouncementHeading('bare-word', 'Released', RELEASE_17536), null); + b(BATTERY68, '#18926: …and for a prefix whose word is the bare noun', releaseAnnouncementHeading('heading-bare', '## Release', '## Release — PR #17517 merged. `pm:blocked` → `pm:queue`'), null); + b(BATTERY68, '#18926: …and it tolerates missing arguments rather than throwing', [releaseAnnouncementHeading(undefined, undefined, undefined), releaseAnnouncementHeading('heading-bare', '## Released', undefined)].join(','), ','); + b(BATTERY68, '#18926: a DECORATED participle heading reads too — the prefix is measured with its decoration stripped', ownershipMarkerNearMissCensus(rows68('## **Released** — **PR #17517 merged.**')).announcements.length, 1); + b(BATTERY68, '#18926: ⛔ no `g` flag on any of the three patterns — a shared regex carrying `lastIndex` is the state bug this file refuses', [RELEASE_ANNOUNCEMENT_PR_RE, RELEASE_ANNOUNCEMENT_TRANSITION_RE, OWNERSHIP_SESSION_TOKEN_RE].every((re) => re.global === false), true); + + // ⭐ THE POSITIVE CONTROL — one of the OTHER ELEVEN, byte-identical. #14512's + // `Claiming` line is already a fixture in this battery (`M18831_14512`, + // pasted from comment 5523309738), so the control is the SAME bytes both + // halves read and ⛔ cannot drift from the thing it controls. + b(BATTERY68, '#18926 ⭐ control: a real near miss on a NON-seat card is still listed — #14512 comment 5523309738, unchanged', [miss68(M18831_14512).form, miss68(M18831_14512).prefix].join(' '), 'bare-word Claiming'); + b(BATTERY68, '#18926 ⭐ control: …and it is on the NEAR-MISS channel, ⛔ not the announcement one', [ownershipMarkerNearMissCensus(rows68(M18831_14512)).misses.length, ownershipMarkerNearMissCensus(rows68(M18831_14512)).announcements.length].join(','), '1,0'); + b(BATTERY68, '#18926 control: …and its card is IN the population', ownershipCensusSpeaksAbout(issue(['pm:queue', 'domain:spec'])), true); + b(BATTERY68, '#18926 control: the other three #18831 fixtures are untouched too, so the floor did not buy the filter with a survivor', M18831_ALL.every((line) => ownershipMarkerNearMisses(rows68(line)).length === 1), true); + + // THE SUMMARY — both exclusions print UNCONDITIONALLY, because a narrowing + // nobody can see is the over-reading it replaced wearing a smaller number. + const EXCLUSION_COUNTS = { ...NEAR_MISS_COUNTS, markerNearMissSeatPosts: 5, markerNearMissSeatLines: 9, markerNearMissAnnouncements: 1, markerNearMissAnnounced: ['#17536 comment 5625672905 「## Released」 (names a PR, names a `pm:*` transition)'] }; + b(BATTERY68, '#18926 summary ⭐ the population exclusion is stated with BOTH numbers, so the pre-filter census is reconstructible', saidBy('markerNearMiss', summaryLine(EXCLUSION_COUNTS, 0)).includes('5 `pm:seat` thread(s) are OUT of that population (9 near-miss line(s) not listed above)'), true); + b(BATTERY68, '#18926 summary: …and says WHY, in the protocol\'s own terms', saidBy('markerNearMiss', summaryLine(EXCLUSION_COUNTS, 0)).includes('a seat post\'s ownership is its BODY'), true); + b(BATTERY68, '#18926 summary: …and that it is counted rather than dropped, in as many words', saidBy('markerNearMiss', summaryLine(EXCLUSION_COUNTS, 0)).includes('⛔ COUNTED, never silently dropped'), true); + b(BATTERY68, '#18926 summary ⭐ the announcement channel is counted AND named', saidBy('markerNearMiss', summaryLine(EXCLUSION_COUNTS, 0)).includes('1 further line(s) are release ANNOUNCEMENTS') && saidBy('markerNearMiss', summaryLine(EXCLUSION_COUNTS, 0)).includes('#17536 comment 5625672905 「## Released」'), true); + b(BATTERY68, '#18926 summary: …and the three narrowings are declared on the line, so the next editor reads the scope rather than the code', ['HEADING forms only', 'PARTICIPLE only', 'NO session token'].every((phrase) => saidBy('markerNearMiss', summaryLine(EXCLUSION_COUNTS, 0)).includes(phrase)), true); + b(BATTERY68, '#18926 summary ⭐ both members render at ZERO too — a run with nothing excluded and a run where the exclusions stopped being applied must ⛔ not print alike', [saidBy('markerNearMiss', summaryLine(NEAR_MISS_COUNTS, 0)).includes('0 `pm:seat` thread(s) are OUT of that population (0 near-miss line(s) not listed above)'), saidBy('markerNearMiss', summaryLine(NEAR_MISS_COUNTS, 0)).includes('0 further line(s) are release ANNOUNCEMENTS')].join(','), 'true,true'); + b(BATTERY68, '#18926 summary: an absent announcement list renders NO names clause', saidBy('markerNearMiss', summaryLine(NEAR_MISS_COUNTS, 0)).includes('comment 5625672905'), false); + b(BATTERY68, '#18926 summary: a non-array `markerNearMissAnnounced` renders a sentence rather than throwing', saidBy('markerNearMiss', summaryLine({ repo: 'o/r', issues: 1, unscoped: 0, prs: 0, merged: 0, markerNearMissAnnounced: null }, 0)).includes('0 further line(s) are release ANNOUNCEMENTS'), true); + b(BATTERY68, '#18926 summary: ⛔ the bare shape renders numbers, ⛔ never the string `undefined`', saidBy('markerNearMiss', summaryLine({}, 0)).includes('undefined'), false); + b(BATTERY68, '#18926 summary: all four new count keys ride the enumerated forwarding contract', ['markerNearMissSeatPosts', 'markerNearMissSeatLines', 'markerNearMissAnnouncements', 'markerNearMissAnnounced'].every((k) => SWEEP_COUNT_KEYS.includes(k)), true); + // FLOOR — this battery is declared, pinned, and the roster grew with it. b(BATTERY68, 'floor: this battery is DECLARED on the roster', Object.prototype.hasOwnProperty.call(SELF_TEST_BATTERIES, BATTERY68), true); b(BATTERY68, 'floor: …with a positive pin, so an empty battery cannot satisfy it', SELF_TEST_BATTERIES[BATTERY68] > 0, true);