Repository navigation
feat(scripts): report-only skill-example schema probe — ruling B step one readings - #22171
objectstack-fleet[bot] wants to merge 4 commits into
Conversation
… one) `check-corpus-claim-drift.mjs --probe-examples` runs a new measurement instrument, `scripts/skill-example-probe.mjs`: it extracts every ts/tsx/ typescript/json/json5/jsonc/yaml/yml fence from the published skills/objectstack-* markdown, statically evaluates the literals, maps each to a packages/spec schema (constructor, annotation, marker, or key ownership), judges it with the built Zod schemas, and replays the fix commits of the premise-1 cards. It exits 0 on any reading and is wired into no check script, workflow or baseline. The drift script's self-test gains four batteries that pin the probe's pure halves over synthetic schemas, so neither needs a build. Claude-Session: https://claude.ai/code/session_01CXydFDyiQwNbGFkmwrcRQq Co-authored-by: Claude <noreply@anthropic.com>
check:parse-guard refuses a raw ts.createSourceFile under scripts/. A fence body is text derived from a markdown host, so it takes the returnable door, parseDerivedText, with a certified carrier module as its origin; a body that does not parse stays a reported coverage miss of reason `syntax`. The readings are byte-identical to the raw parse. Claude-Session: https://claude.ai/code/session_01CXydFDyiQwNbGFkmwrcRQq Co-authored-by: Claude <noreply@anthropic.com>
Names the ts-parse door, the chunked alternatives, the two ownership tiers, the stack map normalization, the ComponentPropsMap dispatch and the counter-example verdict the probe now applies. Claude-Session: https://claude.ai/code/session_01CXydFDyiQwNbGFkmwrcRQq Co-authored-by: Claude <noreply@anthropic.com>
dispatch-gates' self-test anchor reads any function whose name spells self-test as a self-test entry and wants each compound one ledgered. These two only load and register cases into the drift script's own self-test, so they are renamed (registerProbeCases, loadProbeModule) rather than ledgered. Claude-Session: https://claude.ai/code/session_01CXydFDyiQwNbGFkmwrcRQq Co-authored-by: Claude <noreply@anthropic.com>
|
Closing without merging, by the ruling on #22059 (comment 6050857613, letter B, maintainer 「批 #287 同意」): the probe's hit rate is 2 / 19 (10.5%), under the bar of one half on every denominator the body reports, and its ceiling with a perfect transform is 6 / 19, so the ruling's own text falls to C: no gate, the finding process as today, and the probe's readings stay on the card. Skills seat 1, What this PR delivered is accepted as step ① of the ruling: the readings (this body, and the report 6051826214 on #22059) are the record. What it also carries, a 1,711-line probe module and four self-test batteries that no gate would run, is the shape the ruling declined as D ("an offline report nobody reads"), so it does not land. The branch The two teaching errors the catalog control surfaced ( Generated by Claude Code |
Part of #22059
Clause-②: no
Step ① of ruling B (comment 6050857613): the probe and its readings, not the gate. It adds a report-only mode,
node scripts/check-corpus-claim-drift.mjs --probe-examples [--json FILE], backed by a new modulescripts/skill-example-probe.mjs. The mode exits 0 on any reading. It is wired into nocheck:*script, no workflow and no baseline. The drift script's--self-testgains fourProbe …batteries (65 cases) that pin the probe's pure parts over synthetic schemas, so neither the self-test nor the ratchet needs a build.Headline
Every denominator is below one half, and so is the ceiling. That ceiling does not depend on how good the transform is: 9 of the 19 repairs touched no example fence at all, and 4 more changed only comments or string contents inside one.
How the probe works (the module header is the authority)
*.mdunderskills/objectstack-*withevals/excluded: 49 files. A fence is in scope when the first token of its opener ists,typescript,tsx,json,json5,jsoncoryaml/yml.jsoncis outside the dispatched list; it is admitted as JSON-with-comments and reported on its own column. Every other fence is counted as other.scripts/ts-parse.mjsand never executed. Literals are evaluated statically. The supported shapes aredefineX({…}),X.create({…})/XSchema.parse({…}), typed literals (const a: T =,satisfies T,as T),key: valuefragments, bare literals and YAML documents. A fence that does not read as a whole is split at blank lines. Same-fenceconstbindings are followed, andField.kind(…)runs on the spec's own pure helper. Anything else is opaque: issues at, under or above an opaque node are suppressed and counted, never guessed.os:check-yamlmarker's declaration. (3) Key ownership. Tier 1 is the one registry metadata type (or the stack) that declares every key, judged partially. Tier 2 is used only when tier 1 finds no owner: the one named schema the fragment is a complete instance of. A stack's map-format collections are normalised asdefineStacknormalises them. A component'spropertiesis judged by itsComponentPropsMaprow, the dispatchcheck-yaml-examplesalready performs. Schemas come from this tree's builtpackages/spec/dist, rebuilt first. The probe refuses a dist older thansrc.Census: population fences by skill and language
There are no YAML fences in the published catalog: the YAML half of the ruling has an empty population. The other fences are 27 bash, 13 with no language, 3 js, 2 md, 1 each of jsx, markdown, sql and text.
Transform and mapping coverage
no-candidate(runtime code such as hook bodies and engine calls, with no metadata literal) and 9syntax(ellipsis placeholders and prose inside the fence).ambiguous-ownerand 40unmapped(nested sub-schema fragments such aswhere:and nodeconfig:).os:checkblocks. 33 skills fences carry theos:checkmarker. The probe judges 32 of them whole.Replay: the cards premise 1 counts
The set. The premise's own listing (
domain:skills,state=all,since=2026-09-23T00:00Z, title regex as quoted) returns 116 issues across pages today, and 22 titles match. Two of them, #22120 and #22123, were created after #22059 was filed (2026-10-07T05:02Z), so 20 matched at filing, not 21. The command as written reads page 1 only; today that page holds 21 matches, the two post-filing cards included and #18964 (page 2) excluded. All 12 ids the premise names are in the set.Method. Each card's landing PR is the merged PR whose merge instant is the card's
closedtimeline event, located onmainby its squash subject. Both sides are read from the local object store and judged by this tree's schemas, which is a stated bias in both directions. A fence is touched when its body is not found verbatim on the other side. A HIT is a structural signature on a touched BEFORE fence that no touched AFTER fence carries.98d83361d9.claude/skills/pm-dispatch/SKILL.md(a seat process finding)180ef90fb7//comment in the fence8af914a30dpage:headerproperties.actionsheld an Action object;ComponentPropsMaprefuses it (expected string);os:checkblock670471718829720975b6789b2ae54f80dc9c0231eac538c96d7a09eee1b1httpnode carrying a webhook url is schema-valid (a lint advisory, not a parse)1d2024538cwhere:fragments ambiguous across 4 query schemas; see note 34957ee5ef09fb9b25362125ce9f718a5139404d8selectwith nooptions;FieldSchemarefinement;os:checkblockbff5aa2d98fea67065a3formViews.defaultis a schema-valid named form; the error is semantic1a230548cf506fb6dac3eed2dee4818ad9694fb7source:string033e5c536dMisses by class over the 22: prose 10 · comment-or-string 4 · neither 2 · transform 2 · not-in-corpus 1 · no-fix 1.
Notes:
os:checkmarker.check:skill-examplestype-checks those blocks, and it cannot see either error: a Zod refinement and an openpropertiesrecord both type-check.page:header.properties.actions; the contract is action ids (ruling B on #11592) andos validateflags the taught shape #20173's AFTER side is still red on today's schemas, forpage:headerbreadcrumb, which was retired in spec 17 after that repair. The signature the repair removed is what makes it a HIT.transformmisses. Judged by thewheremember of any of the four candidate schemas, both sides are accepted: that member accepts{ status: { $foo: 1 } }too. They would readneitherwith a perfect mapping.Control: the current catalog on this tree
There are 14 issues suppressed as opaque or open. Counter-examples: 8 are refused, as their text says (
indexing.md×2,lifecycle.md×5 rules,relationships.md:382). 2 are accepted by the schema; both are semantic ❌ (relationships.md:351lookup vs master_detail,pagination.md:75keyset field).The three reds:
skills/objectstack-ui/rules/actions.md:77(os:checkblock)customatbodymain:type: 'modal'with abody. The builtdefineActionthrows on it ("bodyonly runs fortype: 'script'…").skills/objectstack-ui/rules/actions.md:176customattargetmain:type: 'url'with notarget.defineActionthrows "Action 'target' is required when type is 'url', …".skills/objectstack-upgrade/references/examples-upgrade.md:7invalid_type/invalid_valueThe two
actions.mdsites are reported as findings for the seat to file. ⛔ This PR does not edit them. A control check confirms the existing gate misses the first one:pnpm --filter @objectstack/spec run check:skill-examplesis green on this head ("262 prose examples type-check across 3 surface(s)") with theactions.md:77block in it.Acceptance notes
check:skill-examples(os:check, TypeScript),check:yaml-examples(os:check-yaml),check:doc-formula-expressionsandcheck:doc-security-posture.Plugintype, held out byTYPE_NOT_A_SPEC_SHAPE.Verification (head
e6d00e1421)pnpm check:corpus-claim-drift: exit 0. The self-test printsOKwith the fourProbe …batteries at 14/18/21/12 cases. The ratchet prints "OK, no new claim sites", over 252 files.node scripts/check-corpus-claim-drift.mjs --probe-examples --json …: exit 0, with the readings above. Apart from its head line, the output is byte-identical on every run from before the first commit to this head.scripts/ablation-replace.mjs, each restored with blob equal to HEAD and an emptygit diff HEAD:node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon this head (30 commands): all exit 0,check:pm-dispatch-gatesincluded.scripts/:check-published-list-mirrors(both),check:dts-closure,check:engine-double-contract,check:i18n-stale-fillandcheck-dts-references --self-test: exit 0.check:published-readme-exports, PREREQUISITE NOT MET (exit 3, 45 packages unbuilt).check:console-injectionskipped (no console dist).eslint --no-inline-config --format jsonreports 2 files, 0 errors, 0 warnings.eslint.config.mjs(files: ['**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}']).parserOptions.projector typed rules are configured, so this diff cannot move a verdict on an untouched file.pnpm check:nul-bytes: exit 0. The control-byte self-scan of both files: none.Reads and writes
git push, this draft, onelabel-write, oneos-dev-reportcomment. No MCP calls.Generated by Claude Code