Skip to content

docs(skills): the AI domain has no CEL site — correct the os validate clause in objectstack-ai - #14819

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14797-ai-skill-cel-predicate-clause
Sep 3, 2026
Merged

docs(skills): the AI domain has no CEL site — correct the os validate clause in objectstack-ai#14819
os-zhuang merged 1 commit into
mainfrom
claude/issue-14797-ai-skill-cel-predicate-clause

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes #14797

One clause in skills/objectstack-ai/SKILL.md, under Verify your work, told an author that os validate CEL-checks a model-registry prompt template. It does not, and there is no CEL site anywhere in the AI domain. Three lines change; nothing else in the file moves.

Before / after — verbatim

Before (:404-408 at 5a5336b399):

It confirms the skill / tool / model metadata conforms to the protocol and that
any CEL predicate parses and resolves — in this domain that is a model-registry
`promptTemplate.system` / `.user`; `ToolSchema` carries no expression field of
any kind. In a scaffolded project the gate is `npm run validate`. See
objectstack-platform → **Verify your work**.

After (:404-408 at 90670f2b4a):

It confirms the skill / tool / model metadata conforms to the protocol. This
domain has no CEL site — a model-registry `promptTemplate.system` / `.user` is
the `template` dialect (`{{var}}`); `ToolSchema` carries no expression field of
any kind. In a scaffolded project the gate is `npm run validate`. See
objectstack-platform → **Verify your work**.

Lines 3, 4 and 5 of the paragraph are byte-identical to before — the ToolSchema clause, the npm run validate sentence and the platform pointer are kept exactly as they were, and the diff is 3 insertions(+), 3 deletions(-) in one file.

Every claim, cited — read in this branch, not recalled

Claim Source
promptTemplate.system / .user are TemplateExpressionInputSchema packages/spec/src/ai/model-registry.zod.ts:121-122
Their own .describe() text says "supports {{var}} interpolation" same two lines
TemplateExpressionInputSchema is dialect template: a bare string becomes { dialect: 'template', source } packages/spec/src/shared/expression.zod.ts:116-124 (doc comment :116-120, union :121-124)
predicate occurs 0 times in the model registry grep -c 'predicate' packages/spec/src/ai/model-registry.zod.ts = 0
ToolSchema carries no expression field of any kind — the clause kept grep -Eic 'cel|formula|expression' packages/spec/src/ai/tool.zod.ts = 0
Those two keys are the ONLY Expression-typed sites in the whole AI domain grep -rn 'ExpressionInputSchema|ExpressionSchema|PredicateSchema|PredicateInputSchema' packages/spec/src/ai/ returns exactly three lines — the import at model-registry.zod.ts:4 and the two uses at :121-122. 22 files in packages/spec/src/ai/, no other hit.
CEL is a real dialect elsewhere, so the domain claim is a measurement and not a definition packages/spec/src/shared/expression.zod.ts:99-101ExpressionInputSchema is the one whose bare-string shorthand is dialect: 'cel'

What os validate actually does here — checked, not assumed

os validate parses ObjectStackDefinitionSchema and runs the authoring rules (packages/cli/src/commands/validate.ts:7-16 imports, :39-41 description). Two readings matter for this clause:

  • The expression-validation rule enumerates its own scope in its header — flow predicates, FLOW_NODE_EXPRESSION_PATHS slots, object validation-rule / formula predicates, and UI action visible / disabled predicates (packages/lint/src/validate-expressions.ts:4-17, scope table :34-44). Grepping that file for promptTemplate, modelRegistry, knowledgeSource or an ai/ path returns nothing: no AI slot is expression-validated.
  • So for this domain the gate's contribution is protocol/shape conformance, which is what the retained first sentence already says. The new text therefore makes no claim about a check that does not exist — it only corrects what the two keys are.

One thing the card asked for that the tree does not support

The card and the triage both proposed also naming "the 5-field cron at packages/spec/src/ai/knowledge-source.zod.ts:28" as the domain's other expression-typed site. Measured at 5a5336b399, it is not one. The field is cron: z.string().optional() at packages/spec/src/ai/knowledge-source.zod.ts:33 — a plain string; :28 is the doc comment that calls it 5-field. It is absent from the ExpressionSchema grep above. Writing "and the cron on knowledge sources" into a sentence about expression checking would have replaced one false claim with another of the same class, so it is omitted. The omission also keeps this paragraph consistent with skills/objectstack-ai/SKILL.md:332, which already tells the author that agents / tools / skills are the only AI stack collections and that knowledge sources have none.

Token accounting — shrink, per the lane rule

Convention is the ratchet's own: ceil(utf8 bytes / 4) (scripts/check-skills-token-ratchet.mjs:184, TOKEN_CONVENTION).

Bytes Tokens Lines
skills/objectstack-ai/SKILL.md before 21,903 5,476 417
skills/objectstack-ai/SKILL.md after 21,900 5,475 417
Delta -3 -1 0

Package total is the same delta — this is the only file touched, and no new file is added. The paragraph itself went 358 B to 355 B, so the new clause is shorter than the one it replaces rather than merely neutral. No re-wrap of untouched lines: the line count is unchanged and only the three lines shown above differ. The ceiling row is untouched (['skills/objectstack-ai/SKILL.md', 6806], scripts/check-skills-token-ratchet.mjs:286); lowering it is permitted but not required by the script's own discipline note at :85-87.

Fence census — nothing moved

The file's os:check machinery all sits above the edit, so it cannot have shifted. Measured both sides:

Fence lines os:check markers
Before 31, 37, 94, 115, 181, 185, 242, 258, 399, 402 93, 241
After 31, 37, 94, 115, 181, 185, 242, 258, 399, 402 93, 241

The fenced os validate comment at :400# Zod schema + CEL predicate validation + bindings (no artifact) — is deliberately not touched: it describes the command platform-wide, where CEL validation is real, and it is not this domain claim.

Edit-landed-on-disk proof

Probe Before After
grep -c 'CEL predicate parses' skills/objectstack-ai/SKILL.md 1 0
grep -c 'no CEL site' skills/objectstack-ai/SKILL.md (injected text) 0 1
grep -c 'ToolSchema' skills/objectstack-ai/SKILL.md 4 4
grep -c 'npm run validate' skills/objectstack-ai/SKILL.md 1 1

Gates — all at head 90670f2b4a

The union was re-derived after the last edit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, which reported gate list derived from the tree of 'objectstack-ai/objectstack' at commit 90670f2b4a and 16 commands over the 1-path change set. Every one was run; exit codes captured by redirect before any pipe.

Gate Exit Its own verdict line
node scripts/check-skills-token-ratchet.mjs 0 ✓ check-skills-token-ratchet: skills/objectstack-ai/SKILL.md is 5475 tokens (ceiling 6806; headroom 1331). and ✓ … 36 authored bundle file(s) within their ceilings
node scripts/check-skills-token-ratchet.mjs --self-test 0 ✓ check-skills-token-ratchet self-test: 64 cases pass.
node scripts/check-ci-filter-parity.mjs 0 OK: all 133 declared cross-package glob(s) (93 unique) are covered …
node scripts/check-cross-package-test-inputs.mjs 0 OK: 25 package(s) read outside themselves, all declared …
node scripts/check-shard-attestation.mjs 0 ✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs 3 PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named. NOT MEASURED — the log is produced by the CI test run, which this gate cannot produce.
pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 ✓ check:doc-formula-expressions (spec TSDoc, #6763): 9 @example(s) judged clean across 1120 packages/spec/src files
pnpm --filter @objectstack/spec run check:skill-docs 0 ✅ Skill docs in sync
pnpm check:agent-test-spelling 0 ✓ check-agent-test-spelling: 0 violations — 430 file(s) …
pnpm check:corpus-claim-drift 0 Scanned: 224 .md/.mdx file(s) … Rules: 4 row(s) … (no violations)
pnpm check:cross-package-test-inputs 0 All 117 self-test cases passed. / OK: 25 package(s) …
pnpm check:doc-authoring 0 ✓ doc authoring guard: 14546 customer-facing string(s) across 710 spec sources clean
pnpm check:pm-governed-merges 0 ✓ check-governed-merges --self-test: 243 assertions …
pnpm check:role-word 0 Scanned: 224 .md/.mdx file(s) read across 2 root(s) — content/docs 190, skills 34. (no violations)
pnpm check:skill-compatibility 0 ✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 79 workspace packages
pnpm check:skill-frame-sync 0 ✓ check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 files
pnpm check:skill-identifier-liveness 0 check-skill-identifier-liveness OK — Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s).

Named in the dispatch and run although the derivation did not list them:

Gate Exit Its own verdict line
pnpm --filter @objectstack/spec check:skill-examples 0 ✅ 256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
node scripts/check-nul-bytes.mjs 0 check-nul-bytes: OK (scanned 8070 text file(s) … no raw ASCII control bytes).

Three gates first answered PREREQUISITE NOT MET (exit 3) or refused, and were re-run to a real verdict rather than reported as red: check-ci-filter-parity and check-shard-attestation wanted pnpm install in the fresh worktree, and check:doc-formula-expressions / check:skill-examples wanted compiled output. Builds went through the shared lock (OS_VERIFY_LOCK_SLOT=issue-14797) — pnpm --filter @objectstack/spec --filter @objectstack/formula build, then turbo run build --filter=@objectstack/lint --filter=@objectstack/client-react --filter=@objectstack/client --concurrency=2 — both ending os-verify-lock: VERDICT command-exit 0, 34/34 turbo tasks successful. The rows above are the post-build runs. check-test-completeness is the one that stays NOT MEASURED; only CI can feed it.

ESLint — a measured total, not a narrowing

Three pieces, each read from ESLint rather than assumed:

  1. Population, from the config itself. All 7 files: blocks in eslint.config.mjs (:971, :1015, :1054, :1103, :1172, :1212, :1238 via COMMENT_SWALLOW_FILES at :785) are scoped to {ts,tsx,mts,cts,js,jsx,mjs,cjs}. grep -n '\.md\|mdx' eslint.config.mjs returns 0 hits — Markdown is not in the linted population at all.
  2. Count, from --format json. pnpm exec eslint --no-inline-config --format json skills/objectstack-ai/SKILL.md exits 0 with "errorCount":0 and the message File ignored because no matching configuration was supplied. So 0 of the 1 changed paths are lintable, and the run over the change set is complete rather than narrowed.
  3. Invariance for untouched files. The config states at :328 that there is (no parserOptions.project, no typed @typescript-eslint rules) for ANY block, and the grep confirms only parserOptions: { ecmaVersion, sourceType }. With no type-aware program there is no cross-file coupling, and this diff edits no config, manifest, tsconfig or TS/JS source — so it cannot move any untouched file's verdict.

Labels

skip-changeset: this PR releases nothing. The change set is one path under skills/**, and scripts/check-empty-changeset.mjs:359-362 enumerates that case in its own words — It releases nothing (.github/, .claude/, skills/, docs/, content/, examples/, tests-only, and the like) -> delete the changeset and apply the 'skip-changeset' label (route 2). The gate pins exactly this shape as GREEN 3 at :559-568: "a skills/**-only PR carrying NO changeset (route 2) … must be green here". No package version moves, so no changeset file is added.

needs:contract-review: the rewritten clause asserts what the AI surfaces are and what the author-time gate does with them.

Review posture

Draft, and it stays draft — governed skills/**, human merge is the review record. Not flipped ready, not enqueued, no auto-merge, no reviewers requested.

Out of scope and untouched, as the triage directed: skills/README.md:105 (PR #14795 holds it), and the reference index SKILL_MAP#14462 is a different defect and is not addressed here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

… clause

`skills/objectstack-ai/SKILL.md` told an author that `os validate` checks "any
CEL predicate parses and resolves — in this domain that is a model-registry
`promptTemplate.system` / `.user`". Those two keys are
`TemplateExpressionInputSchema` (`packages/spec/src/ai/model-registry.zod.ts`
:121-122), which `packages/spec/src/shared/expression.zod.ts:121-124` defines as
the `template` dialect — `{{var}}` interpolation, not CEL, not a predicate.
`predicate` occurs 0 times in `model-registry.zod.ts`, and those two keys are
the only Expression-typed sites anywhere in `packages/spec/src/ai/`.

The true half of the sentence is kept verbatim: `ToolSchema` carries no
expression field of any kind (`ai/tool.zod.ts` matches `cel|formula|expression`
0 times). The `npm run validate` sentence and the platform pointer are kept.
The fenced comment above the paragraph is untouched — it describes the command
platform-wide, not this domain.

Shrink-or-neutral: 21,903 B -> 21,900 B (5,476 -> 5,475 tokens at
`ceil(utf8/4)`), 417 lines unchanged, no re-wrap of untouched lines.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Sep 3, 2026
@os-litant os-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review labels Sep 3, 2026 — with Claude
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 09:20
@os-zhuang
os-zhuang enabled auto-merge September 3, 2026 09:20
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit d355c36 Sep 3, 2026
43 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14797-ai-skill-cel-predicate-clause branch September 3, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants