This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
Commit cbf5cdf
fix(scripts): the polarity census reads a table as structure, so a retired reading stops asserting (objectui#9870) (#9907)
Fixes #9870
Internal instrument only: `scripts/changeset-polarity-census.mjs` and
its pin. No published package changes.
## The defect, and what measuring it changed about the repair
The card names the last entry on the instrument's own limits list that
still read `⛔ unrepaired` about a false-positive SOURCE: an entry may
carry a table whose first column is a reading it is RETIRING and whose
later columns say what falsified it and when. That reading stood in
ASSERTION position with its own correction one cell to the right,
unread. Quotation cannot reach it — the retired reading is not quoted,
it is **tabulated**.
The limits entry also **misdescribed the mechanism, in the direction
that makes a defect look smaller**. It said the cells of one ROW were
joined into one sentence and called that join deliberate. The code doing
the joining carried the **opposite** intent in its own comment (`A table
row: the cells are independent fragments, never one sentence.`) and
achieved neither:
- `. ` cuts a sentence only before a character that is **not
lower-case** (`cutSentences`), and this corpus's later columns open with
`objectui#…` more often than not — so the cells of one row stayed one
sentence;
- a row's **last** cell got no terminator at all, so nothing separated
one row from the next. An entire table — header, delimiter row and every
data row — collapsed into **one** sentence, and every key in it was
offered to every schema named anywhere in it. That is the cartesian
window objectui#9754 closed at the sentence level, rebuilt one level up.
Measured on `.changeset/7322-object-kanban-component-props.md`, the
entry the card quotes: the whole five-row table is one sentence, opening
`--- the component is registered under TWO node type keys … 2026-09-10,
2026-09-17`.
## The direction taken — B, and why not A or C
- **A**, exclude table rows from assertion position as a class —
**refused**.
- **C**, widen quotation position to cover every tabulated reading —
**refused**. A and C differ in what the report calls the row and not in
the verdict.
- **B**, read the shape the table itself declares — **taken**.
Both refusals have the same ground, and it is the ground this family
already paid for once: a table that **asserts** is the ordinary case in
this corpus (72 entries carry one, 74 header rows, spellings like `key |
reading` and `schema (@object-ui/types/zod) | key | now also accepts`),
and a claim silently never judged is the failure that does not ring. A
and C are **cheap today** — 0 of the 40 current flags come from a table
paragraph, measured with a lit control reading 672 table-derived
sentences across 72 entries — and that cheapness is exactly what makes
them dangerous: the cost lands later, on a table nobody will re-measure.
B reads a declaration the **author** made: the header `reading below |
falsified by | landed` says in so many words that the column it points
back at is no longer a claim about today. So the rule is written on the
HEADER, never on the shape of a row. POSITION gains a third value,
`superseded`: a cell in a column the table's own header retires is
counted, **reported under its own name**, and never flagged.
Reading the header requires knowing which cell is in which column, so
the collapse above had to go first: a table is now read as structure — a
cell is its own unit of text, the delimiter row is dropped as syntax,
the header row is kept.
## The entry fee — flag set per key, before and after
`.changeset/`, parent commit `c1f039a67a` vs this branch, controls PASS
on both runs (`corpusLit` 973→976, `memberLit` 1, `resolutionLit` 3/3,
every absent control 0):
| reading | before | after |
| --- | --- | --- |
| entries scanned | 1706 | 1707 (this PR's own changeset) |
| sentences scanned | 18412 | 19104 |
| matched, ASSERTION position | 226 | 225 |
| matched, QUOTED position | 1 | 1 |
| matched, SUPERSEDED position | — | 2 |
| **candidate contradictions** | **40** | **40** |
| contradiction entries | 22 | 22 |
| schemas resolving nowhere | 3 | 2 |
**Rows that stop being flagged: none.** The 40 candidate contradictions
are the **same 40** `(entry, schema, key, polarity)` rows before and
after — set difference empty in both directions — so there is no row to
adjudicate as a correctly-dropped false positive or a lost true
positive. Nothing was gained either.
One row **does** leave a reported bucket, and it is adjudicated here:
`7322-object-kanban-component-props.md` / `KanbanSchema` leaves *schemas
resolving NOWHERE* (3 → 2). Its only assertion-position mention in the
whole corpus was the retired reading in column 1 of that table, whose
own row records that objectui#8802 retired the `KanbanSchema` arm. ⇒
**correctly-dropped FALSE POSITIVE**: a candidate whose adjudication was
already written one cell to the right. No other entry loses a row;
`KanbanSchema` had exactly one row in that bucket before and has none
after.
### Why zero rows moved, stated rather than hidden
The card cites three flagged rows on that entry from objectui#9754 slice
2's dev. They are gone already, and **not** because of anything about
tables: running the **pre-#9863** instrument over today's corpus reads
123 contradictions with four on that entry (`kanban`, `filter`,
`columns`, `cardTitle`); slice 2's window narrowing dropped them,
because a clause whose subject is not a schema symbol now pairs with
nothing. So on this corpus, at this ref, the tabulation defect is
**latent, not live** — and the join `:157` describes still happens,
which is why the card's downgrade arm does not fire. The defect is
pinned against a fixture that makes it live.
## The fixture, where the shape and its counter-shapes are live
`scripts/__tests__/fixtures/changeset-polarity/corpus/12-superseded-readings-table.md`,
parent-commit instrument vs this one:
| pair | before | after | what it is |
| --- | --- | --- | --- |
| `ObjectKanbanSchema.swimlaneWidth` | FLAG | — | retired reading,
correctly dropped |
| `SpinnerSchema.size` | FLAG | — | retired reading, correctly dropped |
| `LaneSchema.titleField` | FLAG | — | cross-ROW pairing, correctly
dropped |
| `ObjectKanbanSchema.cards` | FLAG | — | cross-ROW pairing, correctly
dropped |
| `LaneSchema.laneWidth` | FLAG | FLAG | an ordinary table asserts, and
is still read |
| `ObjectKanbanSchema.dragHandle` | — | **FLAG** | TRUE POSITIVE FOUND:
the falsifier column is a claim about today, and the collapse had
swallowed it |
Four false positives dropped, one true positive recovered, and the
anti-blindness leg (`laneWidth`) green throughout.
## Gates
- `pnpm exec vitest run
scripts/__tests__/changeset-polarity-census.test.ts` — **71 passed**,
exit 0 (path filter, so `passWithNoTests` is off and a zero-match would
have failed).
- `pnpm type-check:scripts` — exit 0, and `tsc --listFiles` confirms the
program contains **both** changed files (the coverage-only
`scripts-type-check.test.ts` was not relied on).
- `pnpm check:control-bytes`, `check:changeset-claims`,
`check:pending-changeset-literals`, `check:unreferenced-sources`,
`check:test-path-roots`, `check:entry-guard`,
`check:new-line-citations`, `check:comment-mask-corpus` — all exit 0.
- `eslint --no-inline-config` on both changed files — exit 0.
- Reverse verification and the full `scripts/` suite: see the comment
below / the report.
## ⛔ Not in this PR
`scripts/changeset-polarity-census.mjs`'s **other** unrepaired entry —
«`without` and `fails to` are read as clause-wide negators» — is
untouched and its text is byte-identical. It is a separate card and this
change does not reach its path: the negator word list, `segmentClauses`
and `readPolarity` are not modified here.
## Acceptance notes
- The `.changeset/` corpus includes this PR's own changeset
(objectui#9795 is open and unruled on that). Run rather than argued: the
new instrument reads 21 sentences out of it, 1 carrying a present-tense
declaration verb, and flags **nothing** — the verb-carrying sentence
names no schema symbol, so it is outside the population.
- Noted, not filed: `.changeset/` carries at least five `before |
after`-shaped tables whose first column is retired by MEANING rather
than by a word in the header (`page before | authority on origin/main |
page after`, `key | mirror was | mirror is`, …). They are named as
residue in the limits list; none of them flags today.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01UanLVj6xvbS6puBCewLr8L
---
_Generated by [Claude
Code](https://claude.ai/code/session_01UanLVj6xvbS6puBCewLr8L)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 5b21e79 commit cbf5cdf
4 files changed
Lines changed: 424 additions & 35 deletions
File tree
- .changeset
- scripts
- __tests__
- fixtures/changeset-polarity/corpus
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| |||
1122 | 1123 | | |
1123 | 1124 | | |
1124 | 1125 | | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
| 1255 | + | |
| 1256 | + | |
| 1257 | + | |
| 1258 | + | |
| 1259 | + | |
| 1260 | + | |
| 1261 | + | |
| 1262 | + | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
0 commit comments