docs: the manifest surface no longer describes itself as an open object - #16327
docs: the manifest surface no longer describes itself as an open object#16327huangyiirene wants to merge 2 commits into
Conversation
…s five sites #14192 closed ManifestSchema with strictObject. Five prose sites still taught the old open-object posture; each is rewritten to teach the current refusal rather than merely to stop teaching the old permission. Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno Co-authored-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno Co-authored-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 3 package(s): 17 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 4 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 140 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e8dcf94aa876b4a4c042c78a1d7e57a9e848c6e4 && git checkout e8dcf94aa876b4a4c042c78a1d7e57a9e848c6e4
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 3e270d4e296368f6600d71fcec9902f3a14c1698 7a265fbb49ce16f35b8974a0b5c82938e5e4a74e && git checkout -B drift-repro 3e270d4e296368f6600d71fcec9902f3a14c1698 && git merge --no-ff 7a265fbb49ce16f35b8974a0b5c82938e5e4a74e
node scripts/docs-audit/affected-docs.mjs --json 3e270d4e296368f6600d71fcec9902f3a14c1698
|
|
⛔ EJECTED from the merge queue — and this is the correct outcome, exactly as written above before it happened
It did, and it is. The queue build — merge_group run
|
| job | conclusion | window |
|---|---|---|
Test Core (1/6) · (2/6) · (3/6) · (4/6) |
✅ success | 17:01:45 → 17:15:04 |
Test Core (6/6) |
✅ success | 17:01:47 → 17:29:17 (43s under the wall) |
Test Core (5/6) |
⛔ cancelled | 17:01:46 → 17:32:04 = 30m18s |
Test Core (required) |
⛔ failure | 17:32:06 → 17:32:24 |
| the other 10 jobs | ✅ success | — |
Run cancelled 17:32:25Z; the queue re-formed without this PR at the same moment (sibling #16347 moved from base 3ac024afc to 4998efa71). ⇒ Removed from the queue. Still open, unmerged.
What this settles about the earlier readings on this PR
- The
pull_requestgreen here was from the pre-fix aggregator — measured with a lit control (origin/main= 1, this head = 0 onscripts/check-shard-attestation.mjs's"an untested shard is not a passing shard"). ⇒ That green never meant the shard ran. - The queue judged it honestly, as the mechanism predicted, and refused it. ⇒ The mechanism argument for arming rather than force-re-running was right: the honest gate applied either way, and this PR did not become the seventh landing through the [finding] A single cancelled shard makes the required
Test Corecheck green over untested packages — the attestation gate zeroes the whole roster oncancelled#16157 hole. - ⛔ My ACCEPT's disclosure ("lands with a sixth of the suite unexecuted") is neither confirmed nor superseded — it is moot. Nothing landed.
Status: BLOCKED, ⛔ not a disclosure
This PR is now in the same state as sibling #16342: finished work, refused by a defect its diff cannot cause. Six files, 61 additions / 14 deletions, prose only — no schema, no export, no behaviour, no test expectation. Five of six shards passed in the queue build; the sixth was killed by the 30-minute wall.
⛔ Not re-running the shard. ⛔ Not raising timeout-minutes. ⛔ Not touching scripts/test-shard-timings.json. ⛔ Not re-arming auto-merge on the theory that another roll of the dice is a fix — this PR's own queue build shows (6/6) finishing 43 seconds under the wall and (5/6) going 18 seconds over, which is what a coin flip looks like, not a flake worth re-spending.
It waits on the timings refresh tracked at #16173, where this run is recorded as measurement 11 (5561021414) — the first observation of the defect inside the merge queue, which is the only place that decides whether anything lands.
Card #14721 keeps pm:dispatched; ⛔ nothing is stroked, because nothing landed.
Generated by Claude Code
Generated by Claude Code
|
PM — auto-merge disabled at 21:22Z. This PR is parked, not abandoned, and nothing is wrong with it. Four queue attempts, four identical outcomes:
This is #16173, not this PR. The diff is 61 lines of docblock and prose across 6 files with no code path — it cannot slow a test shard, and the four kills land within 5 seconds of each other on a wall that four unrelated PRs have hit today as well. Why park it rather than keep re-queueing. A passing build is discarded whenever anything ahead of it in the merge-queue chain is ejected — measured, not assumed: #16347 passed completely at 19:38:39 (all six shards green, 5/6 at 27:36) and was thrown away because this PR, sitting ahead of it, was ejected three minutes later. #16401 needed three green runs before it landed, for the same reason. So each attempt by this PR is not merely a coin toss for itself; at the head of the chain it also discards whatever green builds are queued behind it, including other people's. Continuing to cycle a p3 docs-only change through that is a bad trade against everyone else's throughput. Parking the lowest-value entry is the proportionate move, and I would rather spend the queue on work that is not prose. Un-park condition: re-arm as soon as #16173's shard balance is fixed — or immediately, if a maintainer would rather this land now and accept the churn. Nothing about the change needs to be revisited: the content is final, its review stands, and every non-shard check is green. This is a scheduling decision only. ⛔ I have not re-run the cancelled shard, raised any Generated by Claude Code |
Fixes #14721
ManifestSchemabecame astrictObjectat #14192. Five prose sites still described the surface it replaced. They are not inert: thepackages/specandpackages/coredocblocks land in the published declaration files (measured — the new text reaches 14specand 2coredistfiles), so an author, or an AI writing metadata, reading those declarations was told the manifest tolerates undeclared keys while the runtime now rejects them by name and offers the declared spelling.Prose that contradicts a tightened contract is the "tolerance hides bulk mistakes" shape, so the bar here was that each rewritten sentence teaches the current refusal — not merely that it stops teaching the old permission.
Clause-②: no— no schema, behaviour, export or test expectation changes.The five live sites
packages/spec/src/stack.zod.tsstrictObject:ManifestSchemais an open object"ManifestSchema.extend(...),.extend()carries the base's unknown-key handling, so an assembled body refuses undeclared keys toopackages/cli/src/commands/compile.tsmanifestis safe "becauseManifestSchemais an open object"runAuthoringRulesreads fields off the object and never hands it to a schemapackages/core/src/artifact-packages.tsdocs/audits/2026-07-...-ledger.mdapi/,system/,kernel/andcloud/are wire surface by construction"cloud/is; the other three read mixed in this file's own table 270 lines abovecontent/docs/protocol/kernel/plugin-spec.mdxcontributes.kinds[]AssembledPackageBodySchemaSite 1 keeps the
#14242collection-shape rationale — that gate is unchanged and still the reason this declaration exists. What changed is that it is no longer the only gate at that seam.Measured, not asserted
The rewrites claim a runtime behaviour, so it was measured against the built
dist, each with its negative control:AssembledPackageBodySchemainherits the closed postureREFUSED code=unrecognized_keys— message byte-identical toManifestSchema's, renamenamesapcetonamespaceintactobjects: [], both ACCEPTEDcontributes.kinds[]entries are closedREFUSEDat pathcontributes.kinds.0, renamedescriptiotodescription; clean twin ACCEPTEDengine/engines/contributesclosedREFUSEDnaming the key; clean twins ACCEPTEDdefaultDatasource: 'default',scope: 'project'An earlier probe of
contributes.kinds[]reportedinvalid_typeon a missing requiredid— a masked reading, not a refusal of the unknown key. Re-run with otherwise-valid fixtures sounrecognized_keysis what fires.Verification
All at
7a265fbb49.pnpm --filter @objectstack/spec check:generated— 15/15 artifacts up to date,check:docsandcheck:api-surfaceincludedtypecheck—spec,core,cliall greenspec482 files / 13102 passed ·core50 / 1215 ·cli(unittier) 181 / 2453 (+6 expected fail)eslint . --no-inline-config— the whole population, 6216 files, 0 errors, 0 warnings (no narrowing claimed; the full run fit)check:nul-bytes,check:doc-anchors,check:docs-single-h1,check:doc-authoring,check:docs-audit-scope,check:corpus-claim-drift— all exit 0The remaining derived families are CI's farm run, not re-derived locally.
Two sites deliberately NOT edited
manifest.zod.ts, themaindescribe) — already discharged. The describe carries the honest wording the card prescribed. The card's premise does hold (ADR-0025 is 521 lines;grep -w mainis 0 against 5 substring hits — control lit), but the surviving(ADR-0025 §3.4 step 1)citation in the JSDoc points at the pipeline's build step, which is exactly whereos plugin buildreads and rewrites the key — the same citationpackages/cli/src/commands/plugin/build.ts:5uses for the same step. Editing it would churn nine generated reference rows for no correction.ledger.md:1344) — the same stale sentence, but quoted as a historical finding, in a row that says it "is reported for its owner rather than edited here". That is the ledger recording a residue correctly. Left alone.Notes
4a1a3b0c25. The four commitsmaingained since touch none of the six files here (checked with the detector's control lit), so the readings above are not stale against them.stack.zod.tsconcurrently at:1786-2609; this PR's only hunk there is at:1144, 638 lines clear.Generated by Claude Code