Skip to content

Commit 72bf22a

Browse files
committed
docs(spec): correct the surface-population citation from 136 to the measured 389
The figure 136 does not reproduce. It came from a one-off census script whose forcing walk was weaker than the audit's in four ways: it imported only `*.zod.ts` plus `index.ts` (225 of 1012 modules under `packages/spec/src`), returned early on function-valued schemas, capped its walk at depth 12 instead of 40, and never invoked a deferred error map, so surfaces that register on first use never registered at all. Re-measured with `alias-integrity.test.ts`'s own instrument copied verbatim: 389 unique surfaces, 421 raw registrations, 388 distinct surface strings. Those are three different facts, so each citation now says which one it quotes. The conclusion is unchanged and was re-derived over the larger population: the same four fuzzy instances, the same single declared-alias row left alone. The attestation table gains the pairs the undercount had hidden (min/max 11 rather than 3, input/output and read/write 2 each). Comment-only in the source: `check:api-surface-declarations` reports "declaration text unchanged (17 entry points, 5364 declarations)" and `check:generated` all 16 artifacts up to date. Claude-Session: https://claude.ai/code/session_01AmH9bKvGoLjiY86Q4Z3og2 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9c2725b commit 72bf22a

2 files changed

Lines changed: 31 additions & 13 deletions

File tree

‎.changeset/18572-suggester-opposite-pole.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ authored `dateField` (9 chars, budget max(2, 9/3) = 3)
1919
- **The fallback's answer is screened; a declared `aliases` entry never is.** When the guessed candidate carries an axis token the authored key does not, and the shape also declares its opposite-pole sibling, the rename is replaced by a prescription naming both ends: *"`dateField` does not say which end of the range it binds, and this surface declares both `startDateField` and `endDateField` — opposite ends of one axis. Write the one you mean: both parse, so guessing binds the wrong end silently."* A human-written alias is a statement about one spelling and outranks this; only a coin flip is replaced. `this field` keeps answering `length` with `maxLength` exactly as it declares.
2020
- ⛔ **No alias was added and the accepted key set does not move.** `dateField` was refused before this change and is refused after it; what changed is the sentence the refusal carries. Naming both ends rather than picking one is the answer `field.zod.ts` already writes by hand for `visible` — 「the two answers have opposite polarity … Naming both is the only answer that cannot be acted on wrongly」 — generalised to the keys nobody thought to enumerate, which is the set a fuzzy suggester answers.
2121
- **The guard separates an omission from a typo, and that condition was measured.** It fires only when the authored key is at least as close to the candidate MINUS its axis token as to the candidate itself. Without it `axLength` — one dropped character in `maxLength`, with `minLength` declared beside it — would lose a perfectly good suggestion. With it, `axLength` reads as the typo it is (distance 1 vs 2) and `dateField` as the axis-silent key it is (distance 3 vs 0).
22-
- **Census, not just the filed case.** Over 136 registered `strictObject` surfaces the trap occurs four times, all four fixed here: `dateField` on the calendar, timeline and gantt configs, and `baselineField` on the gantt config (`baselineStartField` / `baselineEndField`). The axis vocabulary is held to the shapes: `alias-integrity.test.ts` now fails on an axis row no surface declares both ends of, the same dead-entry judgement it already applies to `aliases` and `guidance`.
22+
- **Census, not just the filed case.** Over **389 unique authoring surfaces** — the population `alias-integrity.test.ts`'s forcing walk registers, deduplicated by its own key (surface + alias table + sorted shape keys); the same walk also yields 421 raw `strictObject` registrations and 388 distinct surface strings, which are different facts — the trap occurs four times, all four fixed here: `dateField` on the calendar, timeline and gantt configs, and `baselineField` on the gantt config (`baselineStartField` / `baselineEndField`). The axis vocabulary is held to the shapes: `alias-integrity.test.ts` now fails on an axis row no surface declares both ends of, the same dead-entry judgement it already applies to `aliases` and `guidance`.

‎packages/spec/src/shared/polarity-axes.ts‎

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,36 @@
7272
* match is a claim nothing judges. So this table is NOT a general antonym
7373
* dictionary, and rows are not added ahead of the shape that needs them.
7474
*
75-
* Attested on 2026-09-20 over 136 registered surfaces (one row per pair, with
76-
* the surfaces that declare both poles):
77-
*
78-
* | axis | attested by |
79-
* |:----------------|:---------------------------------------------------------------|
80-
* | `start` / `end` | `startDateField` / `endDateField` on calendar, gantt, timeline; |
81-
* | | `baselineStartField` / `baselineEndField` on gantt; `start` / |
82-
* | | `end` on the gantt shift band |
83-
* | `min` / `max` | `minLength` / `maxLength` and `min` / `max` on form field; |
84-
* | | `minRows` / `maxRows` on subform |
85-
* | `input` / `output` | `inputMapping` / `outputMapping` on API endpoint |
86-
* | `read` / `write` | `read` / `write` on the `api` data source |
75+
* Attested on 2026-09-20 over **389 unique authoring surfaces** — the population
76+
* `alias-integrity.test.ts`'s own forcing walk registers, deduplicated by its
77+
* own key (surface + alias table + sorted shape keys). ⚠️ State which reading
78+
* you are quoting: the same walk also yields **421** raw `strictObject`
79+
* registrations (factories that build one shape from several call sites) and
80+
* **388** distinct surface STRINGS (two surfaces share a name). They are three
81+
* different facts and only the first is the count of surfaces this table was
82+
* judged against.
83+
*
84+
* Pair counts below are that measurement, one row per axis:
85+
*
86+
* | axis | pairs | attested by |
87+
* |:-------------------|------:|:-------------------------------------------------|
88+
* | `start` / `end` | 5 | `startDateField` / `endDateField` on calendar, |
89+
* | | | gantt and timeline; `baselineStartField` / |
90+
* | | | `baselineEndField` on gantt; `start` / `end` on |
91+
* | | | the gantt shift band |
92+
* | `min` / `max` | 11 | `minLength` / `maxLength` and `min` / `max` on |
93+
* | | | form field and on field; `minRows` / `maxRows` on |
94+
* | | | subform; `minZoom` / `maxZoom` on the ER diagram; |
95+
* | | | `minDate` / `maxDate` on `object-timeline`; and |
96+
* | | | `min` / `max` on screen field, chart axis, zoom |
97+
* | | | settings and the datasource pool config |
98+
* | `input` / `output` | 2 | `inputMapping` / `outputMapping` on API endpoint; |
99+
* | | | `isInput` / `isOutput` on a flow variable |
100+
* | `read` / `write` | 2 | `read` / `write` on the `api` data source; |
101+
* | | | `readScope` / `writeScope` on object permission |
102+
*
103+
* ⛔ These counts are a reading, not a floor: the gate that keeps them honest is
104+
* the attestation test, which re-derives them from the shapes on every run.
87105
*
88106
* The order inside a pair is the order the two ends are NAMED IN, so a message
89107
* reads `startDateField` before `endDateField` however the candidates happened

0 commit comments

Comments
 (0)