feat(spec): compile-check skills/ TypeScript examples (anti-drift, #3094)#3224
Merged
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.
|
Contributor
📓 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:
|
Contributor
Author
|
Follow-up for the deferred feature-flags drift (noted in the PR description): #3248 — the platform |
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.
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.