docs(skills): settle two false claims in skills/README.md and add three cross-skill routing bullets - #14795
Merged
Merged
Conversation
…in skills/README.md
Settle `skills/README.md`'s CEL conventions and cross-skill routing list
against source.
1. `:87` — "Legacy `OLD` / `NEW` evaluate to `null` since M9.5" was false in
both halves. `M9.5` is anchored nowhere in the repo, and `OLD` / `NEW` are
not values that evaluate to `null`: they are undeclared identifiers.
`SCOPE_ROOTS` (packages/formula/src/cel-engine.ts:95) is the published
closed set of record-scope roots and contains neither, so
`firstUndeclaredReference` (:186) reports them as bare undeclared
references — the class `@objectstack/lint` raises as an error, not a
silent null. Replaced with the true clause plus the migration objectstack-
formula's own table prescribes (`OLD.x` -> `previous.x`, `NEW.x` ->
`record.x`).
2. `:105` — "AI tool params" is not a CEL site. `packages/spec/src/ai/tool.zod.ts`
carries no expression field of any kind, and the AI domain's only expression
site is `model-registry.zod.ts:121-122`, which is `TemplateExpressionInputSchema`
— the `template` dialect (`{{var}}` interpolation), not CEL. Dropped the item;
no true replacement exists, because the AI domain has no CEL predicate.
3. `:94-110` — three routing bullets added for measured load-failure modes:
labels to objectstack-i18n, protocol-major moves to objectstack-upgrade,
and the consuming UI to the objectui skills catalog.
Items 1-2 net exactly zero bytes; item 3 costs 75 tokens, at the size ruling.
The generated region and the anatomy tree are untouched.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
This was referenced Sep 3, 2026
os-zhuang
approved these changes
Sep 3, 2026
os-zhuang
marked this pull request as ready for review
September 3, 2026 02:34
os-zhuang
enabled auto-merge
September 3, 2026 02:34
Contributor
This was referenced Sep 3, 2026
This was referenced Sep 3, 2026
This was referenced Sep 3, 2026
This was referenced Sep 3, 2026
This was referenced Sep 3, 2026
Merged
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 #14794
Fixes #14566
Three edits to
skills/README.md, and nothing else. Branch point re-measured atorigin/main89a156af88— identical to the card's measurement, no drift.Head sha for every gate reading below:
39da552e61.Item 1 —
:87, theOLD/NEWclauseBefore (verbatim):
After (verbatim):
What settles it. The sentence was false in both halves.
M9.5is anchored nowhere:git grep -rn 'M9\.5' -- packages skills docsreturnsexactly one hit, this README line itself. Nothing defines the milestone it cites.
OLD/NEWare not values that evaluate tonull— they are undeclaredidentifiers.
SCOPE_ROOTS(packages/formula/src/cel-engine.ts:95-119) is thepublished, closed set of roots a record-scoped CEL site may reference; it contains
neither.
firstUndeclaredReference(packages/formula/src/cel-engine.ts:186-205)therefore reports them as bare undeclared references — the class
@objectstack/lintraises as an error, not a silent null(
packages/lint/src/validate-expressions.ts:490, "Why it is an error and not awarning").
Measured directly against the built package rather than inferred:
The replacement's prescription is objectstack-formula's own migration table, not a
new claim:
skills/objectstack-formula/SKILL.md:345-346mapsOLD.xtoprevious.xandNEW.xtorecord.x. The two published files now agree.Item 2 —
:105, "AI tool params" in the "Any CEL expression" bulletBefore (verbatim):
After (verbatim):
What settles it — and a correction to the card. The card's diagnosis is
confirmed and its prescribed replacement is false.
packages/spec/src/ai/tool.zod.tsmatchescel|formula|expressionzero times. Tool params carry no expression field of any kind.
packages/spec/src/ai/model-registry.zod.ts". There is no such field —predicateoccurs 0 times in that file. Its only expression-typed keys aresystem/userat:121-122, and those areTemplateExpressionInputSchema,which
packages/spec/src/shared/expression.zod.ts:117-124defines asdialect: 'template'—{{var}}interpolation, not CEL.skills/objectstack-ai/SKILL.md:405-407already says exactly this: the domain'sexpression site is "a model-registry
promptTemplate.system/.user;ToolSchemacarries no expression field of any kind."So the AI domain has no CEL site at all, and there is no true item to swap in.
Taking the card's stated alternative, the item is dropped rather than replaced.
Adding an AI entry to a bullet headed "Any CEL expression" would have replaced one
false claim with another.
Item 3 — three routing bullets (
:94-110)Added verbatim, in the existing bullets' shape:
skills/objectstack-i18n/SKILL.mdfrontmatterdescription— "Author ObjectStack translation bundles — object/field labels, view text …"skills/objectstack-upgrade/SKILL.mdfrontmatterdescription— "Use when a project is on an older protocol major and must move to the current one, when@objectstack/specwas bumped across a major …"git ls-tree origin/main skills/objectui/at objectuiorigin/main39af82freturnsSKILL.md,README.md,evals/,guides/,rules/Each routing claim was checked against the target skill's own frontmatter
description, so the bullet sends the reader where the skill says it triggers.The payment
Item 3's 75 tokens are the funded addition. Items 1 and 2 are funded from each
other and net to exactly zero:
, AI tool paramsfrees 16 B / 4 tok.One further payment is inside item 3 itself, and it is what brought the block from
84 tokens to the ruling's 75. Bullet 2's body does not restate "not
objectstack-platform"; the surviving site is the bullet's own heading,
"Upgrade vs. platform", which already names both sides of the decision. That is
a strict restatement removed, not meaning shaved — the routing information (which
skill wins) is intact.
No further payment was available. The one candidate examined was the
process-skill paragraph at:64-66against the frontmatter rows at:75(
compatibility— "for aprocessskill that binds to no schema") and:76(
metadata.domain— "a delivery-process skill that teaches no schema"). Rejected:the paragraph also carries two facts that survive nowhere else — that such a skill
"carries
SKILL.mdalone" (noreferences/directory) and theSKILL_MAPmechanism behind it. Deleting it would have shaved meaning, so it was left alone.
File token table
ceil(utf8_bytes / 4), whole file:89a156af88)39da552e61)The entire delta is item 3's funded block; items 1–2 contribute zero.
skills/README.mdis outside the token-ratchet population(
scripts/check-skills-token-ratchet.mjs:133), and the ratchet is green regardless.Edit-landed-on-disk proof, grep counts before → after:
M9.5AI tool paramsobjectstack-i18nobjectstack-upgradeobjectuiGates — all at head
39da552e61Every exit code captured by redirect before any pipe; each row quotes the gate's
own verdict line.
pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync(✓ skills/README.md)node scripts/check-skills-token-ratchet.mjs✓ 36 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.node scripts/check-skills-token-ratchet.mjs --self-test✓ check-skills-token-ratchet self-test: 64 cases pass.pnpm check:role-wordcheck-role-word: OK, no new occurrences of the reserved word.— 224 files, ledger unchanged at 43 baselined files / 120 occurrencespnpm check:skill-identifier-livenessOK — Leg 1: 465 citation(s) over 46 published file(s) …; Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s).pnpm check:skill-compatibility✓ 11 SKILL.md file(s) reconciled against 79 workspace packagespnpm check:published-readme-links✓ 176 outbound link(s) across 60 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 27 docs-site page(s) resolved (0 via redirect), 1 anchor(s) verified, 103/103 relative target(s) found in the tree.— the new objectui link resolvesnode scripts/check-nul-bytes.mjsOK (scanned 8064 text file(s) … no raw ASCII control bytes)Re-derived union
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands,re-derived after the last edit. Provenance line confirms it read the right tree:
"gate list derived from the tree of 'objectstack-ai/objectstack' at commit
39da552e61", change set "1 path(s) vs merge base89a156af8" =skills/README.md.All 16 commands run:
node scripts/check-ci-filter-parity.mjsnode scripts/check-cross-package-test-inputs.mjsnode scripts/check-shard-attestation.mjsnode scripts/check-test-completeness.mjspnpm --filter @objectstack/lint run check:doc-formula-expressionspnpm --filter @objectstack/spec run check:skill-docspnpm check:agent-test-spellingpnpm check:corpus-claim-driftpnpm check:cross-package-test-inputspnpm check:doc-authoringpnpm check:merge-driverpnpm check:pm-governed-mergespnpm check:role-wordpnpm check:skill-compatibilitypnpm check:skill-frame-syncpnpm check:skill-identifier-livenessTwo notes on that table:
check-test-completenessexits 3 = PREREQUISITE NOT MET, not red: it "grades asaved
turbo run testlog, and no log was named … the local reading for this gateis NOT MEASURED." CI tees the log and passes the path, so CI is unaffected.
check:doc-formula-expressionsalso exited 3 on the first pass (it imports thecompiled
@objectstack/formulaand@objectstack/lint). Rather than report anon-reading, both packages were built and the gate re-run — it is the gate nearest
this change, since item 1 introduces
previous./record.into published prose.It then measured green:
✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean by @objectstack/formula.Reverse-verification
check:skill-docscan fail, and it names this file. Guarded bytrap restore EXIT INT TERMwith absolute paths throughout; the implementation wascommitted first, so the restore leg points at a
HEADthat already contains it.counts flipping in both directions inside the generated region
(
Construct ObjectQL queries1 → 0,Construct ObjectQL queried0 → 1) and theworktree blob moving
72afcf31b7…→e60bea9ecc….✗ skills/README.md is out of date — run pnpm --filter @objectstack/spec gen:skill-docs.The gate is live and it names
skills/README.md.git checkout HEAD -- /home/user/…/skills/README.md(pinned toHEAD, never a bare checkout, so it cannot restore from a polluted index). Provedby blob hash equality against the
HEADblob (72afcf31b7…, non-empty andmatching), an empty
git diff HEAD, and the anchor counts returning to 1 / 0.ESLint
Not a narrowing — the file is outside the linted population entirely, established
with all three pieces:
the globs):
eslint --print-config skills/README.mdemits an empty document(10 bytes). Every
files:selector ineslint.config.mjsis{ts,tsx,mts,cts,js,jsx,mjs,cjs}; no selector matches markdown.--format jsonfor the file: 1 result entry,errorCount: 0,warningCount: 1, and the single message is eslint's ownFile ignored because no matching configuration was supplied.— zero rulefindings, because zero rules apply.
eslint.config.mjswhich"never enables type-aware linting (no
parserOptions.project, no typed@typescript-eslintrules) for ANY file, test or not"(
eslint.config.mjs:326-328, carrying its own positive-control measurement).No untouched file's verdict can move as a function of this diff.
A full-repo
pnpm lintis therefore provably vacuous with respect to this change.Changeset
skip-changeset, applied. This PR releases nothing: the diff is one file underskills/, andscripts/check-empty-changeset.mjs:359-362enumerates exactly thatcase — "It releases nothing (
.github/,.claude/,skills/,docs/,content/,examples/, tests-only, and the like) -> delete the changeset and applythe 'skip-changeset' label (route 2)." The script pins this shape as GREEN 3, "a
skills/**-only PR carrying NO changeset (route 2)" (:559-565). No packagepackage.json,src/, or version is touched.Scope
Untouched, as claimed: every
SKILL.md; the README's generated region between theBEGIN/END GENERATED markers (
check:skill-docsgreen proves it byte-for-byte); theanatomy tree at
:50-62, so the hunks are disjoint from PR #14786's:55— thisdiff's two hunks start at
:85and:104. No other README sentence was edited.Draft, and it stays draft — governed
skills/**, human merge is the review record.🤖 Generated with Claude Code
https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Generated by Claude Code