docs(core,rest): the closed-set pin headers stop resting on a typecheck-script premise that is false - #16738
Merged
Conversation
…cript core has Both headers explained the pins' placement with "`@objectstack/core` has no `typecheck` script (it is a type-check DEBT ledger entry)". False on this tree: #14613 split a `tsconfig.test.json` out of core's build config and core's `typecheck` names it via `check:test-typecheck --project`, so a directive in core's test layer is compiled, and core carries no DEBT entry either. The pins do not move. The placement conclusion stands on the reason that is true and does not depend on any package's script list: the rest package's test program resolves `@objectstack/core` to the BUILT `dist/index.d.ts`, the contract consumers resolve, while core's own program compiles core's `src` and would read `./types.ts` instead. The rest header also still said the old `type?: string` was refused by the Zod gate "at parse". Measured false (#16049, from #15638): `PluginSchema` had no runtime caller and kernel plugin objects were never parsed. The refusal is on the boot path now -- `PluginLoader.validatePluginContract` runs `PluginSchema` over every plugin object `kernel.use()` loads -- which `packages/core/src/types.ts` already records and this header did not. Comment-only: no pin moves, no `@ts-expect-error` added or deleted, no case touched, and the ratchet and ablation paragraphs are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ADLdAs2pVcH17h9tZKWMBg
…ugin-type-pin-header-drift
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
This was referenced Sep 8, 2026
os-musk
marked this pull request as ready for review
September 8, 2026 03:30
os-musk
enabled auto-merge
September 8, 2026 03:30
This was referenced Sep 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #16602
Clause-②: no
Comment drift only. Two test-file headers explained the closed-set pins' placement with a
sentence that is false on this tree, and the rest header still carried a refusal wording
that #16049 measured false. No pin moves, no
@ts-expect-erroris added or deleted, nocase is touched, and the ratchet and ablation paragraphs are unchanged.
What was false, and what replaced it
1. "
@objectstack/corehas notypecheckscript (it is a type-check DEBT ledger entry)"— carried by both headers as the reason the compile-time pins live in
packages/rest.Measured on this tree:
packages/core/package.jsondeclares"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && pnpm check:test-typecheck",and
@objectstack/coreappears in neitherDEBTnorEXEMPTnorTEST_DEBTinscripts/check-type-check-coverage.mjs. #14613 splitpackages/core/tsconfig.test.jsonout of the build config and the
typecheckscript names it viacheck:test-typecheck --project, sotsc --listFiles -p packages/core/tsconfig.test.jsonputs
packages/core/src/plugin-type-closed-set.test.tsin the program: a directive therewould be compiled, not the phantom pin
check:type-check-coveragerefuses.The false premise goes; the conclusion stays, on the reason that is true. The placement
argument now rests only on what the rest program reads, which is what the card asked for and
what the rest header already said two sentences later. Measured, same run:
tsc --listFiles -p packages/rest/tsconfig.test.jsoncontainspackages/core/dist/index.d.tsand zero files underpackages/core/src/, while core'sown program contains
packages/core/src/types.ts. So the rest pins read the BUILT.d.tsconsumers resolve and a core-side pin would read the declaration instead — a reason that
does not move when a package's script list does.
2. "
type?: string... while the Zod gate (PluginSchema.type) refused it at parse"— rest header only.
Measured false by #16049 (from #15638):
PluginSchemahad no runtime caller and kernelplugin objects were never parsed. On this tree the refusal is on the BOOT path —
PluginLoader.validatePluginContract(packages/core/src/plugin-loader.ts) runsPluginSchema.safeParseover every plugin object, called fromloadPlugin, whichkernel.use()invokes (packages/core/src/kernel.ts).packages/core/src/types.tswascorrected when that was measured; this header carried the same wording and was missed.
Both corrections are recorded in the headers themselves, in the form
types.tsalreadyuses, so the next revision cannot reintroduce them silently.
Verification
The whole subject of this card is a claim about which tsc program evaluates these
directives, so the measurement that matters is that the directives still behave. Both
packages'
typecheckscripts were read out of theirpackage.jsonand run whole:@objectstack/core— 3 legs:tsc --noEmit,tsc --noEmit -p tsconfig.examples.json,pnpm check:test-typecheck(--self-test, then--package packages/core --project tsconfig.test.json). Exit 0.check:test-typecheck: OK — 4 file(s) / 4 error(s) / 4 pinned signature(s), exactly thefour ledgered files;
plugin-type-closed-set.test.tsis unlisted and reports zero.@objectstack/rest— 2 legs:tsc --noEmit,pnpm check:test-typecheck(--self-test,then
--package packages/rest --project tsconfig.test.json). Exit 0.check:test-typecheck: OK — 0 file(s) / 0 error(s), so all three@ts-expect-errordirectives in this file are still USED — an unused one is TS2578 and reds an unlisted
file.
Both changed test files run green (
3 passedcore,4 passedrest). Gates: the 47families
scripts/pm/dispatch-gates.mjsderives for these two paths were all run and allexit 0, reconciled with
--ran:"dispatch-gates --ran: 47 derived famil(ies) accounted for — 47 run, 0 NOT-MEASURED."
Lint is CI's repo-wide run, and the narrowing here is a measurement rather than a skip:
eslint --format jsonover the two touched files reports 2 files, 0 errors, 0 warnings,and
eslint.config.mjsstates at lines 327-328 that this repo "runs oneeslint.config.mjs, which never enables type-aware linting (noparserOptions.project,no typed
@typescript-eslintrules) for ANY file, test or not" — so this diff cannotmove the verdict on any file it does not touch.
Every number above was taken on
fb15b31e69, this branch's head, with the workspaceclosure built (
turbo run build --filter='./packages/*' --filter='./packages/*/*').Changeset —
skip-changeset, and the text it comes fromGoverning text:
.github/workflows/pr-automation.yml, the Require a changeset (or theskip-changeset label) step, route 2 at lines 684-690: "It releases nothing (.github/,
.claude/, skills/, docs/, content/, examples/, tests-only, and the like) -> apply the
'skip-changeset' label." — the workflow marks that route PREFERRED with a triple
left-angle marker this body cannot carry literally — "The label is a gate-level exemption.
It produces NO input for changesets/action, so it cannot affect a release." This diff is
comment-only prose inside two
*.test.tsfiles. Both packages publishfiles: ["dist","README.md","CHANGELOG.md"], both build configsexclude**/*.test.ts,and — measured with a control that does fire — neither header's prose appears anywhere
under any
dist/, while atypes.tsdocblock sentence appears in two. It releases nothing.The WHICH LEVEL ruling above it (lines 667-682, maintainer, 2026-09-04, decision batch
#35 on #15294) governs the level if route 1 applied; it does not, because this act
changes no public surface at all — additively or otherwise.
Rejected:
AGENTS.md:1028-1030read alone — "A bug fix in a released package takes apatchchangeset — never none, and neverskip-changeset". That is the floor againstnonefor a fix that publishes; its own next clause is the predicate that decides thiscase — "that label is for a diff that publishes nothing from any released package" —
and this diff was measured to be exactly that. Citing it and stopping would invert it.
验收备注
Read the whole of both headers, as the card asked, and the rest of each still describes the
tree — with two things reported and deliberately not fixed here:
headers. Found by reading, after a comment-prose scanner that strips
//prefixes andflattens wrapping (a plain grep cannot match it: backticks sit inside the phrase and it
wraps across a comment prefix); the scanner's control was that it must find the two known
carriers, which it did.
packages/rest/src/plugin-metadata-retired-fields.pin.test.tsandpackages/core/src/plugin-loader.retired-fields.pin.test.ts— same claim about@objectstack/core, same ADR-0049 pin pair, both false for the same reason.packages/runtime/src/sandbox/quickjs-runner.test.tssays@objectstack/runtime"hasno
typecheckscript (it sits in the DEBT table)"; runtime declares"typecheck": "tsc --noEmit && pnpm check:test-typecheck"and is not in that table.packages/services/service-automation/src/flow-trigger-kind-shared-resolver.test.tssays "This package has no
typecheckscript"; it declares one too.plugin-type-closed-set.pin.test.tsline ~54, inside a case body rather than theheader, still reads "the case the old
type?: stringadmitted and the Zod gate couldonly catch at parse". Left alone: the card scopes this PR to the two headers and rules
the cases out.
Also noted, not a defect: both headers describe the pinned surface as
type?: PluginType,which since #16334 is inherited from
PluginDefinitionrather than spelled on theinterface. The sentence is true of the resulting published surface, and the file's own
positive control already pins the inherited-key identity, so nothing here is stale — only
less precise than the case comment beneath it.
🤖 Generated with Claude Code
Generated by Claude Code