You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 98b6fcd
Browse filesBrowse the repository at this point in the historyBrowse files
`api-surface-declarations/<entry>.txt` — every export of every published entry point now ships a readable pin of the `.d.ts` declaration text the packed build actually emits for it, and the 27-entry `api-surface-signatures.json` hash it subsumes is retired (#16045).
6
+
7
+
`Clause-②: yes (widening)`
8
+
9
+
Until now this package pinned its public surface on one axis. `api-surface/<entry>.json` records each export as `name (kind)` — 5336 rows across 17 entry points, re-derived on the landing tree — and a signature change, a renamed interface field and a dropped union member move **none** of them. The only shape pin was `api-surface-signatures.json`: 27 rows, 0.5% of the surface, and reference-level even there, because it hashed `checker.typeToString()`, which prints `z.input<typeof ActionSchema>` without expanding it. A breaking shape change to a ratified public type could pass every witness green.
10
+
11
+
-**Text, ⛔ not a hash, deliberately.** A digest answers "did the bytes move" with one opaque bit whose known failure at scale is that a red one gets *accepted* rather than investigated. Each shard holds one block per declaration — `// ── Name (kind) ──` followed by the declaration verbatim — so a diff names the export and shows the change, and the existing review discipline is what guards it.
12
+
-**The input is the packed `.d.ts` reached through the `exports` map**, i.e. the declarations a consumer installs, never `src/`. Two of the manifest's 19 `exports` entries are asset subpaths with no declaration (`./openapi.json`, `./package.json`), which is why this artifact and `api-surface/` both hold 17 shards.
13
+
-**What it costs, measured on the landing tree**: 12,661,943 bytes (12.08 MiB) of text across 17 shards, 237,706 lines, 1.02 MiB gzipped against this package's ~17.6 MiB compressed `dist`. The skew is extreme — the median declaration is 81 bytes and the 20 largest hold ~65% of the bytes, because a Zod schema's packed declaration is its fully expanded structural type. That expansion is exactly what makes an inner field rename visible; it also means four declarations exceed 20,000 lines each.
14
+
-**Leading TSDoc is excluded**, so a re-worded `.describe()` does not churn this artifact — documentation drift stays `check:docs`'s axis.
15
+
-**The retirement is a strict superset, proven before it landed**: all 27 factory names resolve to a declaration block in `api-surface-declarations/root.txt`, 0 missing. For those 27 declarations text and hash discriminate the same amount (both print a type reference); what is *gained* is the 5309 other declarations, including the schemas those factories point at, whose expanded blocks are where an inner-key narrowing shows up. Nothing published read the retired file: it was not in this package's `files[]`.
16
+
-**Sharded per entry point from day one**, for the reason `api-surface/` is: the merge queue rebuilds server-side where no custom merge driver runs, so two PRs sharing one generated file evict the second.
17
+
18
+
Regenerate with `pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec gen:api-surface-declarations`; `check:api-surface-declarations` names that command when it fails. It reads the built dist, so a missing or stale one is a hard refusal in both modes rather than a green run over nothing.
docs(spec): the `RETIRED_KEYS_BY_MAJOR` Lifecycle docblock names both rejected states, and stops contradicting check (b3)'s printed remedy
6
+
7
+
`RETIRED_KEYS_BY_MAJOR`'s docblock is shipped text — it reaches consumers in `dist/index.d.ts` — and since check (b3) landed, two of its sentences were false:
8
+
9
+
-**「The one state the gate rejects」**. Check (b3) rejects a *second* state: a NESTED row whose def this build emits but whose dotted path it does not. That state has no aging clock behind it (a nested key never reaches `authorable-surface/` at all), so it is not the aged-out steady state the paragraph described.
10
+
-**「Entries are permanent」**, against check (b3)'s own refusal text, which ends `… or delete the entry from packages/spec/src/migrations/registry.ts`. An author following the docblock would not delete; an author following the gate would — two shipped instructions in this repo pushing two people who each did as they were told in opposite directions.
11
+
12
+
The Lifecycle paragraph now:
13
+
14
+
- scopes the aging-out steady state to a **top-level** tombstone, and says why a nested row can never be in it;
15
+
- lists **both** rejected states with the check that owns each and the remedy that check prints — still-LIVE (b2), nested-and-unresolvable (b3) — and states the routing rule that decides which one a row is judged by (a row is read as a path only when its `name` half carries a dot AND this build emits no top-level property of that exact name, so a live dotted top-level key such as `@odata.context` stays on (b2)'s map);
16
+
- reconciles permanence with deletion instead of leaving them to contradict: a row that was ever TRUE of some build is history and is never deleted, while a row (b2) or (b3) refuses was never true of any build, so deleting it removes a false claim rather than a record;
17
+
- repeats (b3)'s own ⛔ — it cannot yet tell a wrong row apart from every truthful one, and for the shapes it names the remedy is to teach the check, never to delete a row that is telling the truth.
18
+
19
+
The `## What reads it` bullet for check (b) and the `@see` roster gain (b3) for the same reason: it reads this table, and neither named it.
20
+
21
+
**No behaviour moves.** No gate, schema, export or registry entry is touched — the set of metadata that validates is byte-for-byte what it was. What changes is the text an author reads when a gate refuses their row.
The TypeScript examples in these packages' **published**`README.md` now compile against the package they document — 43 of the 44 blocks the `measure-markdown-ts-blocks` census reported as syntactically valid and wrong, in documents that ship inside the npm tarball.
25
+
26
+
`README.md` is listed in every one of these packages' `files[]`, so these bytes are the artefact a consumer — or a consumer's AI — reads and copies. What the census counted was not style: the examples named options the packages no longer accept, chained a method that returns a promise, and implemented interfaces they never imported.
27
+
28
+
The corrections, by class:
29
+
30
+
-**Legacy option vocabulary.**`@objectstack/client-react`'s hooks take `fields` / `orderBy` / `limit` / `where`, not `select` / `sort` / `top` / `filters`, and `PaginatedResult` carries `records`, not `value`. `@objectstack/service-job` takes `timeoutMs`, `@objectstack/service-queue` takes `maxAttempts`, and `IDataEngine.find` takes `where`.
31
+
-**Async registration used synchronously.**`ObjectKernel.use()` returns `Promise<this>`, so `kernel.use(a).use(b)` does not chain; the examples now `await` each registration. `ObjectKernelConfig` has no `plugins` member.
32
+
-**Interfaces implemented but never imported.** Several plugin examples wrote `implements Plugin` with no import, which bound to the DOM's `Plugin`; they now import `Plugin` / `PluginContext` and declare the required `init`. `PluginContext.getService<T>()` has no default type argument, so the examples that read a service now name its contract.
33
+
-**Removed or never-existing API.**`@objectstack/driver-memory`'s default export is a legacy `onEnable` object that `kernel.use()` refuses — the quick start now registers through `DriverPlugin`; its persistence adapters take an options bag under `persistence.adapter`. `defineStack` has no `driver` key. `@objectstack/rest`'s `RestServer` takes the host `IHttpServer` first and `registerRoutes()` takes no arguments; `RouteManager` is constructed on a server. `@objectstack/spec`'s `ObjectSchema.parse()` returns the value — the `{ success, data }` envelope is `safeParse`'s. `useMutation` has no `onMutate` / mutation context.
34
+
35
+
No runtime code changed and no gate was added (#18715 ruling F). One block is deliberately left: `@objectstack/knowledge-ragflow`'s README writes `source.options.datasetId`, which is what the shipped adapter reads and what `KnowledgeSourceSchema` does not declare — correcting the document either way would contradict one of the two, so the conflict is reported rather than papered over.
0 commit comments