Repository navigation
Commit da4f614
docs(spec): V3_MIGRATION_GUIDE announced a relocation that never happened, and the census gains a standing unpublished-subpath control (#18866)
Fixes #18753
Clause-②: yes (widening)
Two halves, both required by the dispatch: (A) make the document true,
and (B) turn this card into a fixture the census instrument cannot lose
when the document is repaired.
All readings below were taken in this worktree at base `62b114f8b8` (the
seat's readings were taken at `be7aeb8275`, so every one was re-measured
rather than inherited). Commit cited for the gate and lint runs:
`8ac750cfe9`.
## What the re-measurement found, and where it departs from the dispatch
The card framed one fork: repoint the specifier, or declare the subpath.
The dispatching seat had already shown route (1) and route (2) are both
unavailable for two of the three. Re-measuring confirmed that and added
the cause:
| Claim in the guide | Measured at `62b114f8b8` |
|---|---|
| helpers "moved to `@objectstack/core/errors`" /
`@objectstack/core/plugin` | **False.** `466f32ea22` ("v3.0: Remove all
deprecated items") **deleted** them: 25 removed lines naming the three
symbols, **0 added** lines naming them. It created neither destination.
|
| the three symbols exist somewhere | **No.** Zero `.ts`/`.tsx` files
repo-wide name `createErrorResponse`, `getHttpStatusForCategory` or
`definePlugin`. Bright control on the same `git grep`: `defineStack`
reads **368** files. |
| `@objectstack/core` serves those subpaths | **No.** Its `exports` map
has exactly two entries, `.` and `./logger`. |
| "`ErrorResponseSchema`, `PluginDefinitionSchema` etc. remain in
`@objectstack/spec`" | **Half false.** `ErrorResponseSchema (const)` is
at `api-surface/api.json:364`; `PluginDefinitionSchema` reads **0**
across every `api-surface/*.json` file. |
The guide was created `2026-02-11`; the removal landed `2026-02-12`. It
predicted a relocation one day before a commit that did not perform it,
and ticked the checklist anyway. So the defect is not three unresolvable
imports — it is **a false completion declaration**, and there is no
resolving specifier to substitute because nothing was ever published to
replace these.
### Departure: line 28 keeps `@objectstack/spec/hub`, deliberately
The dispatch prescribed repointing line 28 at
`@objectstack/spec/system`. **This PR does not do that**, on the
dispatch's own single criterion — *after the repair, every sentence the
document says must be true of this tree today*.
Line 28 sits inside a block headed `// ❌ v2.x (deprecated, removed in
v3.0)`, and the ✅ block directly beneath it already says `import {
TenantSchema } from '@objectstack/spec/system';`. Repointing line 28
would make the ❌ and ✅ blocks identical and have the guide assert that
the **current, supported** import is the one v3.0 removed. That is a
worse falsehood than the one being repaired, and it deletes the
document's only statement of what to migrate *away from*.
Two measurements make the case stronger than a style preference:
1. **Line 28 contributes nothing to the census number anyway.** Its
block reports `TS1109` only — a syntax error from `parse({ ... })` — so
it lands in pass 1's unparseable set and tsc never type-checks it.
`@objectstack/spec/hub` produces **no TS2307 at all** in the corpus
today. The card's "measured as TS2307" holds for two of the three
specifiers, not three.
2. Both remaining ❌ blocks (sections 2 and 4) have the same property:
they are true depictions of removed APIs. The instrument's own docblock
already concedes this category for `CHANGELOG.md` — "before/after
migration snippets that deliberately show removed APIs. A failing block
here is frequently CORRECT documentation."
What the ❌ blocks did get is an explicit in-block disclaimer, modelled
on the shape `content/docs/protocol/kernel/plugin-spec.mdx` already uses
in this repository (a warn callout naming what does not exist, repeated
as an in-block comment at the point of use): each now says it is shown
so you can find and delete it, and must not be copied.
⇒ If the seat prefers the prescription as written, or prefers de-fencing
the ❌ blocks into prose so they leave the TypeScript population
entirely, both are one-line follow-ups. They are recorded as open
questions rather than taken unilaterally.
## (A) What changed in the document
- Section 2 renamed "Runtime Logic Extraction" to "Runtime Helper
Removal" — no inbound anchor references it — and now states the removal
with **no destination**, above a callout naming the relocation that
never happened.
- The table's "New Location" column is now "v3.0 disposition", reading
"Removed — no replacement export" on all three rows.
- The ✅ code block is gone. There is no ✅ counterpart to paste. In its
place: prose pointing at what actually exists — `ErrorResponseSchema`
still describes the envelope, and a plugin is an ordinary object or
class matching the `Plugin` interface exported from `@objectstack/core`
via `export * from './types.js'`.
- The two checklist items are **unticked** and reworded. The tick was
the false claim; unticking it is the first half of the repair, the
wording the second.
- The note drops `PluginDefinitionSchema` and names it as exported from
no entrypoint.
⛔ Nothing was pointed at `packages/runtime/src/error-envelope.ts`
(`buildApiError` / `apiErrorResponse`), although it is the closest live
thing: it is **not** re-exported from `@objectstack/runtime`'s index, so
naming it would repeat exactly the defect this card is about.
## (B) The synthetic control leg
`UNPUBLISHED_SUBPATH_CONTROL` reconstructs the three specifiers line for
line as the guide carried them before this repair, alongside a frozen
`UNPUBLISHED_SUBPATH_SPECIFIERS` roster the block is held equal to by a
battery.
It is synthetic for the reason `FIRING_CONTROL` is: a control that IS
the live document disarms itself the moment the document is repaired,
and the fourth instance in the next guide would be just as green. It
carries no elision marker and no syntax error, both load-bearing — a
marker would let the disqualified exclusion reading skip it, and a
syntax error would put it in pass 1's unparseable set where the three
TS2307s it exists to produce are never reported. That second point is
not theoretical: it is precisely what hides line 28 from the corpus, so
**the synthetic leg measures a specifier the live document never did.**
### The refusal-list question, and its cost
**Decision: the leg joins `controlProblems()`.** When it misbehaves, the
whole census refuses.
- What it guards is the **tolerance rule**, not the corpus. Widen
`classifyDiagnostic` until an `@objectstack/*` TS2307 is forgiven and
every unresolvable documented import in the repository goes quiet at
once. `FIRING_CONTROL` is a TS2341 and cannot notice; before this PR the
census had **no** standing control for the `unpublished-subpath` family
— the family this card is an instance of.
- Self-test-only was the alternative, and it leaves that hole open: the
census would keep printing numbers nobody could trust.
- **The cost, stated plainly:** if one of the three subpaths is ever
genuinely published, the leg stops producing TS2307 for it and **every
census refuses** until someone edits the fixture. That is the same
exposure `FIRING_CONTROL` already carries — make `ObjectKernel.logger`
public and it stops producing TS2341 — and it is answered the same way:
the refusal text names the remedy (repoint at a subpath still in no
`exports` entry, ⛔ never delete the leg, which takes the other two
guards with it) instead of leaving a stale fixture to be diagnosed.
Five batteries register against it and `SELF_TEST_BATTERY_FLOOR` rises
**30 → 35**. Two of the five drive `controlProblems()` directly, and
each first asserts a healthy control trio reports **zero** problems
before asserting a broken one reports some — otherwise a
`controlProblems` that always complained would pass.
## Evidence
**LIT — the leg fires, proven by ablation.** Each ablation asserted the
tree equalled HEAD first, proved the mutation reached disk by occurrence
count and changed blob hash, restored from HEAD under a trap, and proved
restoration by `git diff HEAD` being empty and the blob matching
`12ec6b3955b4e6fdff880705eee5a67c9b457bf6`.
| Ablation | `--self-test` | census |
|---|---|---|
| widen tolerance, `forgiven: false` to `true` on the `@objectstack/`
branch | **exit 1**, 2 failures | **exit 1** — refuses, naming all three
specifiers as `forgiven=true` |
| drop the five roster rows | **exit 1**, 6 failures, floor reports
"declares 30 batteries, below the pinned 35" | not exercised |
| drop it from `controlUnits()` | not exercised | **exit 1** —
"UNPUBLISHED_SUBPATH_CONTROL did not extract to a block" |
**DARK — nothing else moved.** `--self-test` 30 cases / 30 batteries
before, **35 / 35** after, exit 0; a roster diff against the base proves
**0** of the original 30 batteries were dropped. `FIRING_CONTROL` is
byte-identical in behaviour across both censuses: "reports 5
diagnostic(s) including TS2341 at block line 13", elision marker still
present. `GREEN_CONTROL` compiles clean in both.
**Census, before and after** (full build first — both readings share one
build, so only the document differs):
| | before | after |
|---|---|---|
| `unpublished-subpath` family | `8 diagnostics in 7 blocks` | `6
diagnostics in 6 blocks` |
| this file's share of that | 2 (`@objectstack/core/errors`,
`@objectstack/core/plugin`, both in the block at line 72) | **0** |
| `V3_MIGRATION_GUIDE.md` | `7 blocks / 5 RAW / 5 TOLERANT` | `7 blocks
/ 5 RAW / 5 TOLERANT` |
| hand-written stratum | 282 blocks / 195 RAW / 76 TOLERANT | unchanged
|
The dispatch expected `5 TOLERANT` to fall. **It did not, and that is
the correct outcome** — measured per block rather than asserted. The
repaired block went from 11 diagnostics to 3: both TS2307 gone, and all
five TS2300 "duplicate identifier" gone too, since those were an
artefact of the ❌ and ✅ lines importing the same names into one block.
What remains is `TS2724` + `TS2305` x2 — "no exported member" against
`@objectstack/spec/api` and `@objectstack/spec/kernel` — which is the
block correctly reporting that it depicts symbols v3.0 removed. Every
one of this file's five failing blocks is a ❌ example, and failing is
what a ❌ example does.
The remaining 6 in the family are all `packages/spec/CHANGELOG.md`
naming `@objectstack/spec/cloud` — release-owned history, out of scope
here.
**Gates.** Derived with `scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` from the merge base, re-derived after `git
fetch origin main` and **identical**: **65 families, 65 run, 65 exit
0**, reconciled back through `--ran` with exit codes recorded (a derived
zero, not a claimed one). `pnpm --filter @objectstack/spec typecheck`
exit 0.
**Lint.** Not narrowed — the repo-wide scan fitted in budget: `eslint .
--no-inline-config --format json` linted **6848** files with **0**
messages, exit 0, at `8ac750cfe9`. (Type-aware linting is not enabled in
`eslint.config.mjs`, so the narrowing argument was available and turned
out to be unnecessary.)
**Publish surface.** `V3_MIGRATION_GUIDE.md` is matched by **0**
`files[]` entries in any package manifest (positive control: `README.md`
**is** in `@objectstack/spec`'s `files[]`), and `scripts/` belongs to
the private root package. So nothing this diff touches publishes, which
is the `skip-changeset` criterion, and `lint.yml` names this exact case
in its own prose: "this PR edits a CI-internal script is the textbook
`skip-changeset` case — such a PR releases nothing". 1 parent 36583e9 commit da4f614
2 files changed
Lines changed: 230 additions & 19 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
| 14 | + | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
28 | 31 | | |
29 | 32 | | |
30 | 33 | | |
| |||
52 | 55 | | |
53 | 56 | | |
54 | 57 | | |
55 | | - | |
| 58 | + | |
56 | 59 | | |
57 | 60 | | |
58 | 61 | | |
59 | | - | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
60 | 71 | | |
61 | 72 | | |
62 | 73 | | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
68 | 79 | | |
69 | 80 | | |
70 | 81 | | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
71 | 92 | | |
72 | | - | |
| 93 | + | |
| 94 | + | |
73 | 95 | | |
74 | 96 | | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | 97 | | |
80 | 98 | | |
81 | | - | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
82 | 103 | | |
83 | 104 | | |
84 | 105 | | |
| |||
147 | 168 | | |
148 | 169 | | |
149 | 170 | | |
150 | | - | |
151 | | - | |
| 171 | + | |
| 172 | + | |
152 | 173 | | |
153 | 174 | | |
154 | 175 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
419 | 419 | | |
420 | 420 | | |
421 | 421 | | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 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 | + | |
| 480 | + | |
422 | 481 | | |
423 | 482 | | |
424 | 483 | | |
| |||
643 | 702 | | |
644 | 703 | | |
645 | 704 | | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
646 | 713 | | |
647 | 714 | | |
648 | 715 | | |
| |||
686 | 753 | | |
687 | 754 | | |
688 | 755 | | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
689 | 787 | | |
690 | 788 | | |
691 | 789 | | |
| |||
754 | 852 | | |
755 | 853 | | |
756 | 854 | | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
757 | 860 | | |
758 | 861 | | |
759 | 862 | | |
| |||
858 | 961 | | |
859 | 962 | | |
860 | 963 | | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
861 | 969 | | |
862 | 970 | | |
863 | 971 | | |
| |||
866 | 974 | | |
867 | 975 | | |
868 | 976 | | |
869 | | - | |
| 977 | + | |
870 | 978 | | |
871 | 979 | | |
872 | 980 | | |
873 | 981 | | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
874 | 999 | | |
875 | 1000 | | |
876 | 1001 | | |
| |||
968 | 1093 | | |
969 | 1094 | | |
970 | 1095 | | |
| 1096 | + | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 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 | + | |
971 | 1156 | | |
972 | 1157 | | |
973 | 1158 | | |
| |||
1077 | 1262 | | |
1078 | 1263 | | |
1079 | 1264 | | |
1080 | | - | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
1081 | 1271 | | |
1082 | 1272 | | |
1083 | 1273 | | |
| |||
0 commit comments