Repository navigation
Commit 6cc8dcd
docs(spec): record that the record-stage manifest type is deliberately an index signature, and the runtime schema is the contract (#20191)
Fixes #19324
Clause-②: no
Ruling-ref: 5805795339 (batch #218 item 4, letter 丙). This PR carries
out ruling item 1. It adds one docblock on
`RecordStagePackageBodySchema`, at its `ZodRawShape` cast, and one
beside `AssembledInstalledPackageSchema.manifest`. Both record the four
points the ruling names. ⛔ No type change, ⛔ no schema change. Ruling
item 2 holds: the client gap pin stays, and only its comment text moves.
Per ruling item 3, the card is done when this lands.
## What changed
- **`packages/spec/src/stack.zod.ts`, `RecordStagePackageBodySchema`**
- Its published docblock gains a section, "Its published type is
deliberately an index signature", which carries all four points.
- The internal note above the declaration now says what the `as unknown
as z.ZodObject(z.ZodRawShape)` cast costs, and that the cast emits
nothing.
- **`packages/spec/src/api/package-api-assembled.zod.ts`,
`AssembledInstalledPackageSchema`**
- The docblock ends with a new section, "`manifest`'s published type is
deliberately an index signature", directly above the `manifest` line. It
replaces the old one-paragraph pointer.
- Since `c23cfb346a` the assembled declarations live in this file, not
in `package-api.zod.ts`.
- **`packages/client/src/return-type-precision.test.ts`**
- The two comments that cited `packages/spec/src/stack.zod.ts:1283` now
cite `RecordStagePackageBodySchema` by name.
- They no longer say the gap is this card's to close: it is the accepted
static contract, and the pin reddens the day the body is typed
precisely.
- Comment text only. No assertion, no `@ts-expect-error` and no binding
moved.
- **`packages/client/src/index.ts`, `ObjectStackClient.packages.list`**
(patch round 2, `a2be2ff440`)
- The TSDoc paragraph that called the asymmetry "a KNOWN GAP rather than
a design", tracked on #19324 and citing `stack.zod.ts:1283`, is
rewritten to the settled reading. The index signature is the accepted
static contract (letter 丙), the runtime Zod schema is the enforced one
so a row is narrowed by parsing, and A2 is recorded beside
`RecordStagePackageBodySchema`.
- Comment text only: every changed line of the file is a docblock line.
Nothing in the `automation` namespace is touched.
- **`.changeset/19324-record-stage-index-signature-docblock.md`**:
`@objectstack/spec` patch and `@objectstack/client` patch
(`b9b0d32d2f`).
## Which of the four points were already there
Read at `3bd28e2b2e`, before the edit.
| Ruling item 1 point | `RecordStagePackageBodySchema` |
`AssembledInstalledPackageSchema` |
|---|---|---|
| ① the published type is deliberately an index signature | Partial.
Only an internal "ANNOTATED structurally" comment, which the published
`.d.ts` drops, pointing up the file. | Partial. "The body half is
deliberately typed Record(string, unknown)". No consequence stated, and
not called the accepted contract. |
| ② the runtime Zod schema is the enforced contract | Absent at this
site. It was said only in `AssembledPackageBodySchema`'s internal note.
| Present in substance: "a wrong-shaped body is refused exactly as it is
there". Kept, restated in the new section. |
| ③ why (TS7056 / #14513) | Pointer only, in the unpublished comment. |
Pointer only, and it named `AssembledPackageBodySchema` rather than the
schema `manifest` is built from. |
| ④ A2 is the precise form | Absent | Absent |
## Premise re-measured against the BUILT declarations
Spec built at `3bd28e2b2e` (lock verdict `command-exit 0`).
- `dist/api-assembled/index.d.ts` and `.d.mts` declare `manifest` as
`z.ZodType` of Record(string, unknown) on both sides.
- `dist/index.d.ts` and `.d.mts` declare `RecordStagePackageBodySchema`
the same way, at line 23236.
- A probe program ran tsc 6.0.3 (strict, NodeNext) through the package
`exports`. `--listFiles` shows 9 spec `dist` files and 0 spec `src`
files.
- **Readings, exit 0 (all five compile):**
- R1: `InstalledPackage` assigns to `AssembledInstalledPackage`.
- R2: the whole union assigns to the assembled arm.
- R3: any object assigns to the manifest.
- R4: `string extends keyof` the manifest (an index signature).
- R5: a `{ bogus: 1, objects: 'not-an-array' }` manifest compiles
against the union.
- **Lit controls, exit 2, TS2322 twice:** the reverse assignment, and a
string manifest.
- **Runtime control:** `InstalledPackageAtEitherStageSchema.safeParse`
answers true for a valid authoring row, and false for the bogus row,
both on the union and on the assembled arm.
- The same readings hold at head `17f1e3d41c` after the edit, so the
types did not move.
## The TS7056 reading behind the "why", re-measured after the split
M1 is the decision round's reading at `d1ca8741dd`. This PR re-ran it at
`3bd28e2b2e`.
- **Mutation:** drop the artifact and record stages' structural
annotations and the `ZodRawShape` cast.
- **Result:** spec build exit 1 with exactly one error,
`src/api/package-api-assembled.zod.ts(222,14): error TS7056`. Line 222
is `PackageApiContracts`.
- **How:** through `scripts/ablation-replace.mjs`, with each anchor
hitting 1 then 0, and blob `3c09282f16` → `ac2e5f6b0b` → `7823e5e634`.
- **Restore proven:** blob == HEAD `3c09282f16`, `git diff HEAD` empty,
`git status --porcelain` empty.
The #14513 history was read from commit `7085f90531`. It covers TS7056
on the inferred type, and a named alias that turned `stack.zod` into a
shared chunk. That chunk added 42,622 definition lines to the
`qa/http-conformance` type-check program and pushed it past the then
4096 MB ceiling.
The docblock says plainly that the named-alias reading is inherited for
the record stage and was not re-measured. A2's cost is quoted with its
commit (`d1ca8741dd`), as is the fact that it was not measured on the
http-conformance program.
## One bounded fix in the same docblock
The `AssembledInstalledPackageSchema` docblock said the assembled stage
was "built from `AssembledPackageBodySchema`". That has been false since
#19373. The row's `manifest` is `RecordStagePackageBodySchema`, which
extends the artifact stage, and the artifact stage is
`ManifestSchema.extend({ ...assembledPackageBodyShape(), … })`. It now
reads "built from the same body shape as `AssembledPackageBodySchema` …
at the record stage the next section describes".
This was the decision round's own carrier note (comment 5800545221), and
it names this PR. Same docblock, same class (the text beside `manifest`
misdescribing its declaration), inside the claimed file surface, with no
new gate.
## Changeset, not `skip-changeset`: the edit ships
Measured on the rebuilt `dist` at `17f1e3d41c`:
| probe | files |
|---|---|
| new `RecordStagePackageBodySchema` section heading |
`dist/index.d.ts`, `dist/index.d.mts` |
| new `AssembledInstalledPackageSchema` section heading |
`dist/api-assembled/index.d.ts`, `dist/api-assembled/index.d.mts` |
| lit control: an existing line of the `RecordStagePackageBodySchema`
docblock | the same 2 files |
| the replaced site-2 sentence | 0 |
| the internal cast note (not TSDoc) | 0, dropped from `dist` as
expected |
Both edited files also ship as source, because `@objectstack/spec`'s
`files[]` carries `src/**/*.zod.ts`. So the edit is published and takes
a `patch` changeset, carrying `Clause-②: no`. `packages/client`
publishes only `dist`, `README.md` and `CHANGELOG.md`, so its test-file
comment ships nothing. The `packages.list` paragraph does ship: measured
on the rebuilt client `dist` at `b9b0d32d2f`, the new phrase is in
`index.d.ts`, `index.d.mts`, `index.js` and `index.mjs`. 'Tracked as
#19324' and `stack.zod.ts:1283` are in 0 files, and the lit control, the
unchanged `Array.isArray` warning, is in the same 4 files. So the
changeset also carries `@objectstack/client`: patch (`b9b0d32d2f`).
## Verification
The head is `b9b0d32d2f`. `packages/spec` did not move between
`17f1e3d41c` and `b9b0d32d2f` (`git diff` on it is empty), so the spec
readings below, taken at `17f1e3d41c`, hold at the head. The client and
gate readings were re-taken at `b9b0d32d2f`.
- **`@objectstack/spec` build:** exit 0. `pnpm --filter
@objectstack/spec check:generated`: all 15 generated artifacts up to
date.
- **`@objectstack/spec` typecheck:** exit 0 (`tsc`, scripts and test
layer).
- **`@objectstack/spec` tests, targeted:**
- 16 files / 613 tests in `--project local` and 7 files / 99 tests in
`--project repo`, all passed.
- The set: every test on the edited declarations (`package-api`,
`stack-json-stage-package-body`, `assembled-package-body`,
`api-entry-graph.pin`, `split-entries`), the tests that read
`stack.zod.ts` as text, and every spec test that walks and reads source
files.
- ⊘ NOT MEASURED locally: the full spec suite. It passed the 560 s
foreground ceiling with no verdict (exit 124). CI runs it.
- **`@objectstack/client`** (at `b9b0d32d2f`): build exit 0
(`check-dts-emitted` 1/1).
- typecheck exit 0, with `check:test-typecheck` OK at 0 files / 0 errors
/ 0 pinned. Its test program compiles `return-type-precision.test.ts`
(`--listFiles`: 1 hit, against `spec/dist/api-assembled`).
- tests: 50 files / 635 passed.
- **Cross-package tests on the assembled row:** `runtime`
`packages-read-delete-response-conformance` 17 passed, `objectql`
`registry-package-manifest-serializable` 16 passed.
- **`node scripts/pm/dispatch-gates.mjs --ran`** (re-derived and re-run
at `b9b0d32d2f`; the new path added no family): 85 families derived. 83
run, every one exit 0.
- ⊘ NOT MEASURED: `check:dual-build-cjs-loads`, which exits 3 until
every workspace package is built.
- ⊘ UNRUN: `check:type-check-debt`, which re-measures `tsc` per ledger
entry over the whole built workspace. The only test-file edit is comment
text, and the client test layer holds 0 errors.
- CI runs both.
- **ESLint, narrowed to the 4 changed `.ts` files** (at `b9b0d32d2f`):
- Scope: `--print-config` applies 6 rules to `index.ts` and 5 to each of
the other three. `--format json` reports 4 files, 0 errors, 0 warnings.
- Why untouched files cannot change: `eslint.config.mjs` never enables
type-aware linting (no `parserOptions.project`), so this diff cannot
move the verdict on any other file.
## Acceptance notes
- **`.changeset/17536-client-packages-read-doors-either-stage.md` still
calls the gap "tracked as #19324" and cites `stack.zod.ts:1283`.**
- It is a foreign changeset, and `check-empty-changeset` rule 2 forbids
editing it.
- This PR's changeset states the settled reading instead, for the same
release text.
- **Not merged with `main`.** `origin/main` is at `560b724c95`, 10
commits past the base, and none touches the five changed paths (empty
`git diff --stat` on them). CI validates the merge ref.
_Body corrected by `domain:spec` seat 2 after patch round 2
(`b9b0d32d2f`), from the dev's reported deviations: the client
paragraph, the client changeset line, the stale Acceptance note removed,
and the verification anchor._
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QcAS3qiYYZNezaxZxaUdMV)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 0bd1126 commit 6cc8dcd
5 files changed
Lines changed: 127 additions & 29 deletions
File tree
- .changeset
- packages
- client/src
- spec/src
- api
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2513 | 2513 | | |
2514 | 2514 | | |
2515 | 2515 | | |
2516 | | - | |
2517 | | - | |
2518 | | - | |
2519 | | - | |
2520 | | - | |
2521 | | - | |
2522 | | - | |
2523 | | - | |
| 2516 | + | |
| 2517 | + | |
| 2518 | + | |
| 2519 | + | |
| 2520 | + | |
| 2521 | + | |
| 2522 | + | |
| 2523 | + | |
| 2524 | + | |
| 2525 | + | |
| 2526 | + | |
| 2527 | + | |
| 2528 | + | |
2524 | 2529 | | |
2525 | 2530 | | |
2526 | 2531 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
686 | 686 | | |
687 | 687 | | |
688 | 688 | | |
689 | | - | |
690 | | - | |
691 | | - | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
692 | 693 | | |
693 | 694 | | |
694 | 695 | | |
695 | | - | |
696 | | - | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
697 | 700 | | |
698 | 701 | | |
699 | 702 | | |
| |||
761 | 764 | | |
762 | 765 | | |
763 | 766 | | |
764 | | - | |
765 | | - | |
766 | | - | |
767 | | - | |
768 | | - | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
769 | 773 | | |
770 | | - | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
771 | 777 | | |
772 | | - | |
773 | | - | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
774 | 781 | | |
775 | 782 | | |
776 | 783 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
89 | 85 | | |
90 | 86 | | |
91 | 87 | | |
| |||
124 | 120 | | |
125 | 121 | | |
126 | 122 | | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
127 | 141 | | |
128 | 142 | | |
129 | 143 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1450 | 1450 | | |
1451 | 1451 | | |
1452 | 1452 | | |
| 1453 | + | |
| 1454 | + | |
| 1455 | + | |
| 1456 | + | |
| 1457 | + | |
| 1458 | + | |
| 1459 | + | |
| 1460 | + | |
| 1461 | + | |
| 1462 | + | |
| 1463 | + | |
| 1464 | + | |
| 1465 | + | |
| 1466 | + | |
| 1467 | + | |
| 1468 | + | |
| 1469 | + | |
| 1470 | + | |
| 1471 | + | |
| 1472 | + | |
| 1473 | + | |
| 1474 | + | |
| 1475 | + | |
| 1476 | + | |
| 1477 | + | |
| 1478 | + | |
| 1479 | + | |
| 1480 | + | |
| 1481 | + | |
| 1482 | + | |
| 1483 | + | |
| 1484 | + | |
| 1485 | + | |
| 1486 | + | |
| 1487 | + | |
| 1488 | + | |
| 1489 | + | |
| 1490 | + | |
| 1491 | + | |
| 1492 | + | |
| 1493 | + | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
1453 | 1503 | | |
1454 | | - | |
1455 | 1504 | | |
1456 | 1505 | | |
1457 | 1506 | | |
| |||
0 commit comments