Uh oh!
There was an error while loading. Please reload this page.
feat(spec): compile-check skills/ TypeScript examples (anti-drift, #3094) - #3224
Conversation
…stack/spec (#3094) The TypeScript in skills/ is the first thing an AI copies when authoring metadata, yet nothing type-checked it, so it rotted silently. A new `check:skill-examples` gate extracts every code block tagged with an inert `<!-- os:check -->` comment and runs it through `tsc --noEmit` against the built spec declarations — the exact surface a consumer's import resolves to. Opt-in by marker (not a `` ```ts check `` fence-meta) so the fence info-string stays a bare ``` ```ts ``` and the existing `check:doc-authoring` scanner keeps seeing the block. Module resolution is a `paths` map derived from the spec's own `exports`, so it self-updates as subpath exports change. Runs after the build step in the required `TypeScript Type Check` job, alongside the other "real consumer" gates (api-surface, downstream-contract, example-app typecheck). Four provable red modes: a type error in a tagged block, spec not built, zero marked blocks (vacuous-green guard), a misplaced/orphan marker. Tagging 19 self-contained examples surfaced real drift, now fixed: - objectstack-data: `ObjectSchema` imported from the root instead of `/data` (×2) - objectstack-platform: the removed `Data` namespace (`const { Field } = Data`) → `import { Field } from '@objectstack/spec/data'` (×2) - objectstack-ui: a `defineAction` example using `P` without importing it Non-self-contained fragments (local-module imports, external object refs) are left untagged by design. One deeper drift is deferred: the platform feature-flags example uses a top-level `featureFlags` key absent from `ObjectStackDefinitionInput` (flags live in the kernel capability config) — left as-authored, untagged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📓 Docs Drift CheckThis PR changes 1 package(s): 102 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
Uh oh!
There was an error while loading. Please reload this page.
os-zhuang
commented
Jul 19, 2026
Follow-up for the deferred feature-flags drift (noted in the PR description): #3248 — the platform |
Closes#3094.
What
Adds
check:skill-examples— a CI gate that type-checks the TypeScript examples insideskills/against the built@objectstack/spec, so a renamed export or tightened union fails here instead of in a third party's editor. This is the "示例不漂移" layer; the existingcheck:skill-refs/check:skill-docsonly cover the "目录不漂移" (generated reference indexes).Design
<!-- os:check -->HTML comment on the line directly above its fence. Full extraction of every```tsblock is infeasible — most are fragments (acolumns: [...]subtree) that need a hand-authored wrapper and produce false-positive noise.```ts checkfence-meta: that would leave the fence info-string non-standard and punch a hole in the existingcheck:doc-authoringscanner (which keys on^\``(ts|typescript|tsx)$). The comment keeps the fence a bare```ts `, so every existing scanner still sees the block.dist/*.d.tsvia a tsconfigpathsmap derived from the spec's ownexportsfield — the exact surfaceimport { … } from '@objectstack/spec'resolves to for a consumer, and it self-updates as subpath exports change.TypeScript Type Checkjob after the build step, next to its fellow "real consumer" gates (check:api-surface,downstream-contract, example-app typecheck) — not before the build likecheck:skill-refs.skills/**/SKILL.md:<real line>.Proven-red (門必先证明能红)
dist/*.d.ts)Drift the gate immediately surfaced (fixed here)
Tagging 19 self-contained examples turned up real, shipping drift:
ObjectSchemaimported from the package root; it's only exported from/data(×2).Datanamespace (import { Data } … ; const { Field } = Data) →import { Field } from '@objectstack/spec/data'(×2).defineActionexample usingP`…`withoutimport { P }.Non-self-contained fragments (local-module imports like
./apps/crm/objectstack.config, external object refs likeOpportunity) are left untagged by design — they can't compile standalone and aren't meant to.Deferred (documented, not silently dropped)
The platform feature-flags example uses a top-level
featureFlagskey that isn't inObjectStackDefinitionInput— feature flags live in the kernel capability config (features: FeatureFlagSchema[], nested), andenvironmentis a single enum (dev|staging|prod|all), not an array. Correcting it is a non-trivial rewrite of that section, so the block is left exactly as authored and untagged, to be fixed in a follow-up rather than shipping a guessed correction.Growing coverage
New self-contained examples opt in by adding
<!-- os:check -->above their fence. A misplaced marker errors (orphan guard), so under-coverage can't hide.