Commit f26fb8e
fix(spec,objectql): correct six false
Fixes #17664
Clause-②: no
`aliases` has **two** jobs, not one: filling a gap the distance fallback
leaves empty, and **overruling** a hit the fallback reaches and gets
wrong. The lookup is `aliases[aliasProbe(key)] ??
findClosestMatches(key, knownKeys, budget, 1)[0]` — the table is
consulted first and wins outright — and the budget is `Math.max(2,
Math.floor(key.length / 3))`. A sentence saying distance "cannot reach"
the cited case denies the second job. In three of the six places
corrected here, the cited case is itself an example of it.
## The three sites the card names — three separate verdicts
Measured against the **real** `findClosestMatches` and each shape's own
key list (read off `.shape`, never transcribed), at `origin/main`
`1124c4564`.
### 1. `packages/objectql/src/validation/record-validator.ts` — FALSE,
high confidence
Cited: *"The rename IS the prescription, and edit distance cannot reach
it (`latitude` -> `lat`)"*.
`latitude` is 8 characters, so the budget is 2. `lat` is 5 edits away
and out of reach — but the fallback is **not silent**: the declared
`altitude` is exactly 2 edits away, inside the budget. The refusal an
author would see without the alias, printed by the ablation below:
```
Unrecognized key(s) on this location value: `latitude`. Did you mean `latitude` -> `altitude`?
```
So the entry is overruling a confident wrong answer, and the sentence
cites it as proof that no such category exists. Confidence: **high** —
the ablation reproduces the wrong answer verbatim from the running
schema.
### 2. `packages/spec/src/data/default-value-shape.ts` — FALSE, high
confidence, plus a second error
Same sentence, same measurement, so the same verdict. This site carries
an **additional** error the card does not name: the docblock's own
worked example is `postal_code -> postalCode` on `AddressValueSchema`,
and it attributes that output to the curated `aliases` map.
`postal_code` is not an alias key on that shape at all — scoring folds
case and separators on **both** sides, so it is **1** edit against a
budget of 3 and the example is the plain fallback's own answer. The
corrected text names both channels and says which produced which.
Confidence: **high** (both halves re-measured).
### 3. `packages/spec/src/data/driver/turso.zod.ts` — FALSE, high
confidence, and in a different position from the other two
Two things set this one apart, and they are the same distinction read
twice.
**Position.** Sites 1 and 2 cite a single example inline, as proof of a
rule. This one is a *blanket header standing above a table*: *"Semantic
near-misses only — the spellings edit distance cannot reach."* The word
doing the damage is **only**, and it is quantified over six rows.
**Bucket.** Sites 1 and 2 are in the **overrule** bucket (reachable,
fallback answers a *different* key). `uri` is in the **agrees** bucket:
3 characters, budget 2, and `uri`/`url` differ by **1**, so the bare
fallback already answers `url` — identically. Five of the six rows
(`connectionstring`, `dsn`, `database`, `databaseurl`, `syncinterval`)
are genuine gaps; `uri` is not, and the row's real value is that it
keeps answering `url` if this shape ever gains a key within 2 of `uri`.
Confidence: **high** for the `uri` row; the other five rows are
re-measured and the header's claim holds for them.
## Three more carriers of the *same* claim, fixed in place
The `latitude -> lat` sentence has five carriers, not two. Three more
were corrected here under the bounded in-place-fix exemption, and all
four of its conditions are named and shown:
1. **Same defect class as the card** — literally the same false sentence
about the same alias entry on the same shape, falsified by the same
measurement. `packages/spec/src/data/field-value.zod.ts` (the table's
*own* comment), `packages/spec/src/data/field-value.test.ts`,
`packages/spec/src/data/default-value-shape.test.ts`.
2. **Mechanical, with the form already pinned** — the correction form is
the one PR #17662 landed in `packages/spec/src/kernel/manifest.zod.ts`:
name the budget formula and where it lives, give the exact distances,
say which of the two roles the entry plays, and name the pin test. Prose
only.
3. **No other claim holds the file** — the open-PR holder map was
rebuilt from scratch over all **33** open PRs (281 file rows). Lit
control: it names #19119 holding 10 files, matching the dispatch's own
reading. Dark control: a fabricated path matches 0 rows. All five
carrier paths read FREE.
4. **Same gate family, no new verification surface** — every one is
under `packages/spec/src/data/**`, already inside this card's declared
file surface, and adds no gate. The two new `describe` blocks live in
test files the card's own sites already depend on.
Leaving them would have made the repository contradict itself inside one
alias table's documentation. The boundary held elsewhere: the same claim
shape about a *different* table is reported below, not fixed.
## Pins
`aliases` entries are now asserted **by role**, because the two roles
fail differently:
- `packages/spec/src/data/field-value.test.ts` — `longitude` (GAP:
nothing within budget), `latitude` (OVERRULE, with the negative half
asserted: the reachable wrong answer must **not** appear), and `altitud`
as the control that a plain typo still rides the fallback.
- `packages/spec/src/data/driver/turso.test.ts` — `dsn` (GAP) beside
`uri` (reachable, agreeing).
## Population re-derivation, its radius, and one target outside it
The card reports the phrase pattern occurring **19 times across 17
tracked files** and roughly a dozen unclassified. Re-derived at
`origin/main` `1124c4564`, printing every hit, never a count:
| instrument | flatten | result |
|---|---|---|
| the card's own pattern | leading JSDoc star stripped per line | 20
hits / 17 files |
| this PR's pattern | leading JSDoc star **and** leading `//` stripped
per line | **24 hits / 20 files** |
**The card's instrument has a demonstrable blind spot, and it hides
carriers of this very defect.** The card's prescription names the
JSDoc-star wrap and stops there. A **line-comment** wrap is invisible to
it: when `//` falls between "edit" and "distance", or between "distance"
and "cannot", the flattened text reads `edit // distance cannot reach`
and no pattern anchored on the adjacent phrase can see it. Three hits in
two files surface only under the comment-aware flatten, and two of them
are further carriers of the false `latitude -> lat` claim — including
`field-value.zod.ts`, the file that **owns** the alias.
**Radius.** This instrument sees: tracked files at one commit of
`objectstack-ai/objectstack`, matching the literal words "edit distance"
plus a negated modal plus "reach". It does **not** see: other
repositories, untracked files, published npm tarballs, GitHub issue and
PR bodies, or any **paraphrase** that does not spell "edit distance".
**One named target outside it:**
`packages/spec/src/automation/builtin-node-config.zod.ts` says
*"`object` -> `objectName` is four edits against a threshold of two, so
the suggester would say nothing at all for the single most common wrong
spelling on this surface"*. That is exactly the same claim about exactly
the same mechanism, and both patterns score that file **0**. Lit control
on the same file: the paraphrase itself matches twice. (Re-measured:
`object -> objectName` really is a GAP on every CRUD node config, so it
is true — but the radius, not the truth, is the point.) The sibling repo
`objectui` was also swept and carries no member of this pattern.
## Acceptance notes — noted, not filed
Four members of the population are **FALSE** and left alone, with the
reason each is out of scope:
- `packages/spec/src/ui/action.zod.ts` — *"Edit distance cannot reach
these (`visibleWhen` -> `visible` is 4 apart)"* heads a ~50-row table
containing **6 overruling** rows (`path -> target` with the fallback
reaching `patch` at 1; also `args`, `success`, `style`, `op`, `acl`) and
5 agreeing ones. The cited example is itself a genuine GAP, so this is a
false *blanket*, not a false example. Different table, different lane
(`packages/spec/src/ui/**`, outside this card's file surface).
- `packages/spec/src/data/object-strictness-batch20.test.ts` — the
`describe` title *"aliases — semantic near-misses edit distance cannot
reach"* blankets three cases, and `export -> exportCsv` is an
**overrule** (the fallback reaches `import` at 2). Inside the file
surface, but a different alias table: fixing it would widen the diff
past the coherence boundary above.
- `packages/spec/CHANGELOG.md` — *"Three spelled-out near-misses that
edit distance cannot reach are curated as aliases: `filesystem` and
`paths` point at `fs`, and `hosts` points at `network`"*. `hosts` is an
**overrule** (the fallback reaches `hooks` at 2) — the very row PR
#17662 corrected in the source. RELEASE-OWNED: AGENTS.md prescribes
amending a released entry in a dedicated docs-only PR, never as a rider
on code changes.
- `packages/objectql/CHANGELOG.md` — carries the `latitude -> lat`
claim. RELEASE-OWNED, same remedy.
One more, true but worth knowing:
`packages/spec/src/data/field-value.zod.ts`'s **second** citation
(`zipCode -> postalCode`, a genuine GAP) sits above a table whose
`postcode -> postalCode` row is in the **agrees** bucket. The sentence
is scoped to `zipCode` and is therefore true; it is noted because it is
one edit away from being the same blanket error as the turso header.
Also noted: the whole class would be closed by a guard rather than by
sweeps — an assertion that no comment attached to a `strictObject`
options literal claims unreachability for a row that measures reachable.
`shared/alias-integrity.test.ts` already forces every table and already
computes what is needed. That is a new gate and a decision, not a rider
on this PR.
## Evidence
- **Ablation** (one-off; the tree was restored and the restore proved):
removing `latitude: 'lat'` from `LocationValueSchema`'s table through
`scripts/ablation-replace.mjs` — anchor hit 1 -> 0, blob `ac90b42d814a`
-> `2610f8d9477b` — turns the new pin **red** and prints the runtime
refusal quoted in site 1 above. Restored: blob back to `ac90b42d814a`,
equal to HEAD, `git diff HEAD` empty.
- **Tests**: `packages/spec` 494 files / 14526 tests pass;
`packages/objectql` 299 files / 5003 tests pass. All five new pins
confirmed to have run by name.
- **Typecheck**: `pnpm --filter @objectstack/spec --filter
@objectstack/objectql typecheck` exit 0.
- **Gates**: all **85** families derived by
`scripts/pm/dispatch-gates.mjs` for this change set are accounted for —
83 exit 0, 2 NOT MEASURED (`check:dual-build-cjs-loads`,
`check:type-check-debt`), both of which printed `PREREQUISITE NOT MET —
nothing was measured` because they need a full-repo build. Those are
CI's run; neither can be moved by a comment-and-test diff.
- **Lint**: the repo-wide run, not a narrowing — `pnpm lint` exit 0 at
`f61417bb2d`, **6878** files linted, 0 errors, 0 warnings, and all 7
edited source files verified present in the linted population.
## What on the card turned out otherwise
- Still present, not already fixed: all three cited sites were
re-derived against `origin/main` before anything was written.
- The card's census is an **undercount** for a named mechanical reason
(the `//` wrap), and two of the hits it misses are carriers of the
defect it is about.
- The card's "roughly a dozen unclassified" re-derives to **17** hits,
of which 7 are false — 3 the card names, 3 fixed here as the same claim,
4 reported above.
- The card's own numbers have moved with the tree: its census read 384
surfaces / 1910 alias entries / 1658 gap / 211 agreeing / 41 overruling;
the same sweep today reads **419 / 2139 / 1862 / 228 / 49**. Lit control
`visibleWhen` still classifies GAP in 4 tables; a fabricated alias token
matches 0 rows.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3)_
Co-authored-by: Claude <noreply@anthropic.com>edit distance cannot reach citations (#19126)1 parent 70e1a82 commit f26fb8e
8 files changed
Lines changed: 188 additions & 17 deletions
File tree
- .changeset
- packages
- objectql/src/validation
- spec/src/data
- driver
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
555 | 555 | | |
556 | 556 | | |
557 | 557 | | |
558 | | - | |
559 | | - | |
560 | | - | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
561 | 569 | | |
562 | 570 | | |
563 | 571 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
141 | | - | |
142 | | - | |
143 | | - | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
144 | 149 | | |
145 | 150 | | |
146 | 151 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
126 | 143 | | |
127 | 144 | | |
128 | 145 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
70 | 71 | | |
71 | 72 | | |
72 | 73 | | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
73 | 110 | | |
74 | 111 | | |
75 | 112 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
84 | 94 | | |
85 | 95 | | |
86 | 96 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
| 35 | + | |
34 | 36 | | |
35 | 37 | | |
36 | 38 | | |
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
40 | 64 | | |
41 | 65 | | |
42 | 66 | | |
| |||
388 | 412 | | |
389 | 413 | | |
390 | 414 | | |
391 | | - | |
392 | | - | |
393 | | - | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
394 | 420 | | |
395 | 421 | | |
396 | 422 | | |
| |||
412 | 438 | | |
413 | 439 | | |
414 | 440 | | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
415 | 480 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
398 | 398 | | |
399 | 399 | | |
400 | 400 | | |
401 | | - | |
402 | | - | |
403 | | - | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
404 | 419 | | |
405 | 420 | | |
406 | 421 | | |
| |||
0 commit comments