skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens) - #14563

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization
Sep 2, 2026
Merged

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens)#14563
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14316

Member of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET. The audit record is on the card as the audit-record comment.

Transliteration key — the GitHub body sanitizer eats angle-bracket-shaped fragments, so this body spells them out: LT = opening angle bracket, GT = closing angle bracket, and a name in CAPS inside a path (record.FIELD, vars.STEP.KEY) stands for a placeholder the file writes in angle brackets.

Governed face — three of the changes below are contract-semantics claims, so this PR stays draft and carries needs:contract-review; the card carries it too.

Review round 1 — both FAILs fixed, paid in-file

In-seat contract review at d3a32664 returned FAIL on two spans, PASS on everything else. Both were re-verified at source before editing, both are fixed, and both are paid inside SKILL.md: the file lands back on 5,158 tokens exactly, the same figure it carried at review time. Nothing grew.

#what was wrongwhat it says nowverified at
1the query-axis note gave all three axes one code, 400 INVALID_FIELDwhere and searchableFields answer 400 INVALID_FIELD; orderBy answers 400 INVALID_SORTpackages/objectql/src/engine.tsassertOrderByIsMaterializable sets err.code = 'INVALID_SORT'; assertSortFieldsExist is the same code at the ingress. An agent branching on the code would have branched wrong on the sort refusal.
2the cron/template paragraph sent readers to shared/expression.zod.ts for "the formatter whitelist and the cron alias set"the seven aliases are inlined in the cron row; the template row names TEMPLATE_FORMATTERS, exported from @objectstack/formula, as the introspectable whitelist; the expression.zod.ts pointer is narrowed to the carrier lists it really declarespackages/formula/src/cron-engine.ts (@yearly @annually @monthly @weekly @daily @hourly @reboot); packages/formula/src/template-engine.ts exports TEMPLATE_FORMATTERS via packages/formula/src/index.ts. That file carried neither set, and the sets had lived in the quick references this flight deleted — so the pointer was the last mention of both, resolving to nothing.

Paid by cutting narration of the same class this flight exists to remove: the asc/desc anecdote from the new note, and the Skill Boundaries cron parenthetical now that the surfaces table names Job.schedule.expression and the dialect. Two new identifiers were added and both are live — check:skill-identifier-liveness Leg 1 went 476 → 477 citations and stayed OK.

Token delta

filebeforeafterceilingheadroom
skills/objectstack-formula/SKILL.md6,0025,1586,002844

Net −844 tokens (−14.1%), 551 → 374 lines. Convention is the ratchet's own: ceil(utf8 bytes / 4), so ceil($(wc -c < file) / 4) reproduces it. Ceiling untouched (FRM-I-01 re-lock is deferred). The generated references/_index.md (302 tok) is untouched.

Gap against the audit's −1,265, itemised per cluster — not smoothed

cluster (commit)audit est.measuredgapwhy
F-06 / A-01 / G-05 / B-04 / F-07−515−440+75the two collapsed rows keep their real carrier lists (4 cron carriers, 3 template carriers) so the last mention still points somewhere; F-07 is a small addition inside a deletion cluster
D-05 / D-04 / B-03−522−389+133all three are MERGE-INTO, not DELETE. Rules the audit's raw span estimate wrote off survive: the onError clause, "a condition that does not even compile aborts the same way", the ADR-0058 per-row statement
D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03−511−392+119B-06 and B-05 are merges: "Verify your work" absorbed the runtime-throw half of the ADR-0032 callout, and the three determinism conditions folded into the seed pattern's own note rather than vanishing
F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08+237+356+119the two contract notes have to name both refusal doors and both fault directions to be actionable; the type-checked block needs a real import
A-02+18+21+3
review round 10both fixes paid in-file

The gap is one thing four times: a MERGE-INTO finding cannot pay what a DELETE would. Where the audit measured a span's bytes, I measured what was left after the rule inside it was preserved. I did not re-wrap, pad, or cut anything the audit did not name to close the difference.

Per-item 落点 | before | after

Deletions

id落点beforeafter
FRM-F-06 / A-01### Cron surfaces, ### Template surfaces, ## Cron quick reference, ## Template quick referencefour sections, a formatter table and two code blocksone ### Cron and template surfaces table, one row each, carriers named, the seven cron aliases inlined and the formatter whitelist named. Both are live surfaces with 0 corpus usages, so neither loses its last mention; the frontmatter no longer says "Do not use for cron schedules" while the body teaches cron
FRM-D-05section 5 bulk-write prose165 tokens restating the before* table row, plus query-count and fetch-cost narrationone clause pointing back at that row; the ADR-0058 per-row semantics keep their sentence
FRM-D-04section 5 abort calloutthe pre-protocol-17 logger.warn history and its two opposite-failure examplesthe rule only: aborts on before* and after* alike, no onError escape, non-compiling conditions the same
FRM-B-06top-of-file ADR-0032 calloutADR-0032 stated 3×, and "Verify your work" cross-referenced the top-of-file notestated once, in "Verify your work", keeping both halves — build fails with a located did-you-mean, runtime throws
FRM-B-05## Determinism contracta section restating the seed pattern's own notefolded into that note
FRM-D-01 / B-07"Strategic context"why CEL beat the deleted Salesforce-flavor engine — the first content after the H1gone
FRM-D-07 / D-02Core contract tail"you do not learn three languages" + the roadmap for emitting astgone; the envelope rule both carried survives once
FRM-B-03section 5 previous totalitythe has()-on-a-declared-field rule stated once for record, again for previousone statement covering both, in the has() section
FRM-D-03 / G-03## Open questionstwo bullets citing CelExprSchemagone — the symbol has 0 hits in the repo outside this file
FRM-G-05CEL surfaces table, template notesa visibleOn / visibility deprecated-alias row, titleFormat noted twicealias row gone; titleFormat deduped to one carrier cell
FRM-B-02## See alsoa pointer at node_modules/@objectstack/formula/gone — packages/formula/package.json ships ["dist","README.md","CHANGELOG.md"], and this file already says so
FRM-D-09Core contracta type Expression block transcribing shared/expression.zod.tsone sentence and the pointer
FRM-D-08"No date arithmetic"157 tokens of prose carrying five prescriptionsa five-row table
FRM-B-04template surfaces"no js dialect" restatedone statement, in Core contract
FRM-G-01 / G-02 / G-04 / E-03throughoutobjectstack build 5×; 7.6 / M9.5 / M9.7 / M9.8; "single quotes (always)"; * 100.0os build; no milestone numbers; both quote styles; * 100

Additions (each paid by deletions in the same file)

id落点what it now teachessource
FRM-F-01after the CEL surfaces tablea formula field is virtual — no driver materialises a column, so all three query axes refuse one at both doors: where / searchableFields with 400 INVALID_FIELD, orderBy with 400 INVALID_SORT. Remedy is the stored column, in the same words the sort and search axes already usepackages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts; packages/objectql/src/filter-comparand-shape.ts; packages/objectql/src/engine.ts
FRM-F-03same placea form-view visibleWhen is CLIENT-SIDE only and faults open (true), so it is never access control — and where the opposite holds: Hook / SharingRulecondition and validation predicates abort the writepackages/spec/src/ui/view.zod.ts (FormFieldSchema / FormSectionSchemavisibleWhen); packages/metadata-core/src/form-predicate-root-policy.ts
FRM-F-02CEL syntax cheat-sheetthe two missing roots: parent (line-item cell readonlyWhen / requiredWhen) and data (metadata-editing forms, repeater rows included)packages/spec/src/data/field.zod.ts; BOUND_FORM_VIEW_PREDICATE_ROOTS
FRM-F-04translation table + its warningflow conditions bind bare identifiers — the engine spreads the record's variables to top level. The table's first row implied record. prefixing was universalpackages/services/service-automation/src/engine.ts — "bare identifiers like status / previous.status resolve — the natural authoring style for record-change start conditions"
FRM-A-02frontmatter descriptionthat this is the companion skill objectstack-data / -ui / -api / -automation each tell you to load alongside themthose four descriptions
FRM-B-01## See alsoa link to references/_index.md — formula was the only domain package that orphaned its own generated index (8 of 9 link theirs)
FRM-E-01Mandatory pattern 3the predicate block is now type-checked. Both previously marked blocks were the cron and template quick references, so no "Mandatory pattern" was checked at allsee the ablation below
FRM-F-07view-filter prohibitionnames the alternative it was withholding: date macro tokens, pointing at objectstack-query rules/filters.mdskills/objectstack-query/rules/filters.md

Anchor rulings honoured

This package is the CEL anchor; the automation flight (#14467) and the query flight (#14443) deleted their CEL restatements on that ruling. All three anchored constructs survive with their headings addressable:

  • ## ObjectStack CEL standard library — the 35-function table, untouched
  • ## Mechanical translation table (legacy → CEL) — including the OLD / NEW rows and the warning below it (the warning gained the flow-condition exception; nothing was removed)
  • ## Surfaces that take an Expression — the CEL surfaces table, minus the one deprecated alias row

The packages/formula pin tests both pass, quoted below.

Premise adjustments — no finding was forced

  • FRM-B-02, half true. The audit reads :548-551 as pointing at an unreadable package. That holds for the @objectstack/formula line. The second pointer, node_modules/@objectstack/spec/src/shared/expression.zod.ts, is readable in an installed apppackages/spec/package.json ships src/**/*.zod.ts. Kept, and the additions lean on it.
  • FRM-B-04, 2 instances not 3. The audit lists :81-83, :476-478 and :51. The first two restate "there is no js dialect" and one was deleted. :51 is the Skill Boundaries row routing L2 hook bodies to objectstack-data — a routing row that never states the claim. Realized 2 → 1.
  • FRM-D-08 is not ≈0. Measured −7 tokens as a table.
  • Everything else held at my base. skills/objectstack-formula/** is byte-identical between the audit ref a59f78d, the dispatch base 18d816a5 and my branch point 93940d49, so every skills/ span was valid unchanged; packages/** citations are re-cited above at the tree in this PR.

Follow-ups (⛔ deliberately not touched here)

Gates — head sha 291f7bd7

Re-derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsafter the round-1 edit and after merging origin/main: 36 commands, whole list run, list identical across all three derivations. Two derivations were refused as STALE and each was answered by merging origin/main rather than by reading the old copies — the first (33 commits behind, 148 family files changed) conflicted only in the two generated files, which were resolved to main's side, committed, and only then regenerated, never in MERGE state; the second (5 commits behind, changing .github/workflows/lint.yml and scripts/role-word-baseline.json, both of which the families read) merged cleanly. The @objectstack/spec + @objectstack/client-react closure was rebuilt after each merge — check:skill-examples and check:docs both refuse a stale dist and said so, by name, rather than answering falsely green.

35 / 36 green. The one non-zero is node scripts/check-test-completeness.mjsexit 3, which that script defines as a MISSING or UNREADABLE LOG — NOT MEASURED, not red. Exit codes were captured by redirecting each command to its own file before any pipe.

Card-named gates, quoting each gate's own verdict line:

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-formula/SKILL.md is 5158 tokens (ceiling 6002; headroom 844). and ✓ check-skills-token-ratchet: 37 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.
  • pnpm --filter @objectstack/spec check:skill-examples✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-identifier-livenesscheck-skill-identifier-liveness OK — Leg 1: 477 citation(s) over 47 published file(s) checked against 93135 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s). Leg 2 was checked before the first deletion: none of the 8 registered exhaustive sections is in this file.
  • pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync
  • packages/formula pin tests — pnpm --filter @objectstack/formula exec vitest run --maxWorkers=2 src/cel-stdlib-drift.test.ts src/skill-catalog-sync.test.tsTest Files 2 passed (2) / Tests 5 passed (5). The stdlib anchor is intact.
  • pnpm check:role-word — green, no ratchet-DOWN, so scripts/role-word-baseline.json is untouched.

Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14316. The pushed remote head equals the tree the gates read (291f7bd7, verified with git ls-remote).

FRM-E-01 ablation — the marker is not a phantom green

The new marker was added only after the gate passed with it, then ablated once. Mutation and restore were both proven on disk rather than by an editor's exit code:

  • HEAD blob 21ee6b50; a semantic-only mutation was injected (assigning the P tagged template's Expression result to number), leaving the block syntactically valid so the failure could only come from the semantic pass.
  • Mutation proven on disk: injected text grep -c = 1, anchor still 1, git hash-object = 79936c1f ≠ HEAD blob.
  • Gate on the mutated tree: exit 1, and it named the block — skills/objectstack-formula/SKILL.md:243:7 error TS2322: Type '{ dialect: ... }' is not assignable to type 'number'. The right file, the right line, my block.
  • Restore leg given the same treatment as the mutation leg: git checkout HEAD -- with an absolute path (never the bare form, which restores from a polluted index), inside a trap ... EXIT INT TERM using absolute paths. Proven by git hash-object = 21ee6b50 (equal to the HEAD blob, non-empty) andgit diff HEAD empty — not by the restore's exit code.
  • No rebuild was needed between legs: the gate reads the markdown directly, and the mutated artifact was that markdown, not a package dist.

Labels

skip-changeset — this PR releases nothing. Verified against the gate's own enumeration rather than assumed: scripts/check-empty-changeset.mjs carries a "GREEN 3: a skills/**-only PR carrying NO changeset (route 2)" case asserting exactly this shape must be green, and no packages/*/package.json ships skills/ in its files[]. Plus needs:contract-review, because FRM-F-01, F-03 and F-04 are contract-semantics claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…RM-F-06 / A-01 / G-05 / B-04 / F-07)
The frontmatter routes cron away ("Do not use for ... cron schedules") while the
body taught it across four sections; the corpus authors zero of it (`cron` 0,
`tmpl` 0, any formatter 0). Both are live surfaces, so each keeps ONE
schema-pointing row with its carriers; the two quick-reference sections and the
formatter table go.
- FRM-F-06 / A-01: `### Cron surfaces`, `### Template surfaces`, `## Cron quick
reference` and `## Template quick reference` collapse into one
`### Cron and template surfaces` table, two rows, pointing at
`shared/expression.zod.ts` for the full carrier list.
- FRM-G-05: the deprecated `visibleOn` / `visibility` alias row leaves the CEL
surfaces table; the two `Object.titleFormat` notes dedupe to one carrier cell.
- FRM-B-04: the third "no js dialect" restatement goes; the canonical one in
Core contract stays.
- FRM-F-07: the view-list-filter prohibition now names the alternative it was
withholding — date macro tokens, with the pointer to objectstack-query
`rules/filters.md`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…history (FRM-D-05 / D-04 / B-03)
Section 5 was 20.7% of the file (1,241 tok). The rules in it are load-bearing;
the narration around them was not.
- FRM-D-04: the pre-protocol-17 `logger.warn` history goes. Two rules were
buried in it and survive in one sentence: `before*` and `after*` abort alike
with no `onError` escape, and a condition that does not compile aborts the
same way.
- FRM-D-05: the `before*` exception restated the table row above it at 165
tokens — it is now one clause pointing back at that row. The per-row bulk
semantics keep their ADR-0058 statement; the query-count and fetch-cost
narration goes.
- FRM-B-03: the `has()`-on-a-declared-field rule was stated once for `record`
and again for `previous`. It is now one statement covering both, in the
`has()` section where the rule lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…RM-D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03)
- FRM-D-01 / B-07: "Strategic context" — why CEL was picked over the deleted
Salesforce-flavor engine — was the first content after the H1. An author
emitting a predicate does not need the engine-selection history.
- FRM-B-06: ADR-0032 was stated three times, and "Verify your work" cross-refs
the top-of-file note that carried it. One statement now, in "Verify your
work", and it keeps both halves the callout had: build fails with a located
did-you-mean, and the runtime throws.
- FRM-D-09: the `type Expression` block transcribed `shared/expression.zod.ts`.
One sentence and the pointer replace it.
- FRM-D-07 / D-02: "you do not learn three languages" and the roadmap for
emitting `ast` go; the envelope rule they both carried survives once.
The auto-wrap fact moved to the cron/template row in the previous commit.
- FRM-B-05: "Determinism contract" restated the seed pattern's own note. The
three numbered conditions fold into that note.
- FRM-D-03 / G-03: "Open questions" cited `CelExprSchema` twice; the symbol
exists nowhere in the repo (0 hits outside this file).
- FRM-G-01: the CLI is `os`, not `objectstack` — 5 mentions, now 0.
- FRM-G-02: the frontmatter pins 17.x; the retired milestone numbers are gone.
- FRM-G-04: a CEL string literal takes either quote; the corpus writes double
quotes inside P` ` more than ten times, so "(always)" was false.
- FRM-E-03: `* 100.0` was a cel-js workaround. `registerNumericCoercions`
(`packages/formula/src/stdlib.ts`) registers the mixed `double op int` /
`int op double` overloads, so `* 100` is correct now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…FRM-F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08)
The corpus measurement behind these: `type: 'formula'` fields have zero live
usages and the only hits are a removal test; flow/trigger conditions are
authored five times and the scope was taught wrong; field conditional rules are
the second-commonest task and two of their roots were missing.
- FRM-F-01: a `formula` field is virtual — `where` / `orderBy` /
`searchableFields` on one are refused `400 INVALID_FIELD` at both doors
(`packages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts`;
`packages/objectql/src/filter-comparand-shape.ts`). The filter and sort axes
were taught nowhere in the catalog. Remedy is the stored column, in the same
words the sort and search axes already use.
- FRM-F-03: a form-view `visibleWhen` is client-side only and faults OPEN
(`packages/spec/src/ui/view.zod.ts` `FormFieldSchema` / `FormSectionSchema`;
`packages/metadata-core/src/form-predicate-root-policy.ts`). The package
taught fault-closed globally, so the note says where each holds.
- FRM-F-02: the `parent` root (line-item cell `readonlyWhen` / `requiredWhen`,
`packages/spec/src/data/field.zod.ts`) and the `data` root (metadata-editing
forms, `BOUND_FORM_VIEW_PREDICATE_ROOTS`) join the cheat-sheet.
- FRM-F-04: flow conditions bind bare identifiers — the automation engine
spreads the record's variables to top level
(`packages/services/service-automation/src/engine.ts`). The translation
table's first row implied the opposite universally.
- FRM-B-02 / B-01: the `node_modules/@objectstack/formula/` pointer named a
package that ships `dist` only, which this file already says is unreadable.
Its slot goes to `references/_index.md`, which every other domain package
links and this one orphaned.
- FRM-E-01: the predicate pattern block is now type-checked. Both previously
marked blocks were the cron and template quick references, so no "Mandatory
pattern" was checked at all.
- FRM-D-08: the no-date-arithmetic rule carried five prescriptions as prose.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…cron away (FRM-A-02 / A-01)
Four host skills end their description with "load objectstack-formula
alongside" (objectstack-data, -ui, -api, -automation); this one never said it
was that companion, so an author reading it cold had no way to know why it had
been loaded.
FRM-A-01: the description also said "Do not use for ... cron schedules" while
the body taught cron across four sections. The body now carries one
schema-pointing cron row, so the exclusion goes and the Skill Boundaries table
keeps the routing to objectstack-automation.
`skills/README.md` and `content/docs/ai/skills-reference.mdx` are the generator
output of `pnpm --filter @objectstack/spec gen:skill-docs` — both move, and
nothing in them is hand-edited.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ills-formula-optimization
# Conflicts:
#	content/docs/ai/skills-reference.mdx
#	skills/README.md
Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), re-run
after the merge so it derives from all 11 SKILL.md files at the merged tree
rather than at the pre-merge one. The whole diff is the FRM-A-02 description
edit; nothing here is hand-written.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…pointer (contract review round 1)
Two spans failed in-seat contract review; both were verified at source before
editing and both are paid in-file — the file lands back on 5,158 tokens exactly,
no growth.
FAIL 1 (FRM-F-01, the query-axis note). The three axes do not share one error
code. `where` and `searchableFields` answer `400 INVALID_FIELD`, but `orderBy`
answers `400 INVALID_SORT` — `assertOrderByIsMaterializable` sets
`err.code = 'INVALID_SORT'` at the engine seam
(`packages/objectql/src/engine.ts`), and `assertSortFieldsExist` does the same
at the ingress. An agent branching on the code would have branched wrong on the
sort refusal. Both codes are now named.
FAIL 2 (the cron/template pointer). The paragraph sent readers to
`shared/expression.zod.ts` for "the formatter whitelist and the cron alias
set", and that file carries neither. Worse, the sets used to live in the quick
references this flight deleted, so the pointer was the last mention of both —
and this same file correctly says `@objectstack/formula` ships `dist` only, so
"go read it" resolves to nothing. Now: the seven aliases are inlined in the cron
row from `packages/formula/src/cron-engine.ts`, the template row names
`TEMPLATE_FORMATTERS` (really exported from `@objectstack/formula`, derived
from the formatter table in `packages/formula/src/template-engine.ts`) as the
introspectable whitelist, and the `expression.zod.ts` pointer is narrowed to
the carrier lists it does declare.
Paid by cutting narration of the same class this flight exists to remove: the
`asc`/`desc` anecdote from the new note, and the Skill Boundaries cron
parenthetical now that the surfaces table names `Job.schedule.expression` and
the dialect.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 13:07
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 2f2a0b2Sep 2, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14316-skills-formula-optimization branch September 2, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens) - #14563

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization
Sep 2, 2026
Merged

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens)#14563
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14316

Member of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET. The audit record is on the card as the audit-record comment.

Transliteration key — the GitHub body sanitizer eats angle-bracket-shaped fragments, so this body spells them out: LT = opening angle bracket, GT = closing angle bracket, and a name in CAPS inside a path (record.FIELD, vars.STEP.KEY) stands for a placeholder the file writes in angle brackets.

Governed face — three of the changes below are contract-semantics claims, so this PR stays draft and carries needs:contract-review; the card carries it too.

Review round 1 — both FAILs fixed, paid in-file

In-seat contract review at d3a32664 returned FAIL on two spans, PASS on everything else. Both were re-verified at source before editing, both are fixed, and both are paid inside SKILL.md: the file lands back on 5,158 tokens exactly, the same figure it carried at review time. Nothing grew.

#what was wrongwhat it says nowverified at
1the query-axis note gave all three axes one code, 400 INVALID_FIELDwhere and searchableFields answer 400 INVALID_FIELD; orderBy answers 400 INVALID_SORTpackages/objectql/src/engine.tsassertOrderByIsMaterializable sets err.code = 'INVALID_SORT'; assertSortFieldsExist is the same code at the ingress. An agent branching on the code would have branched wrong on the sort refusal.
2the cron/template paragraph sent readers to shared/expression.zod.ts for "the formatter whitelist and the cron alias set"the seven aliases are inlined in the cron row; the template row names TEMPLATE_FORMATTERS, exported from @objectstack/formula, as the introspectable whitelist; the expression.zod.ts pointer is narrowed to the carrier lists it really declarespackages/formula/src/cron-engine.ts (@yearly @annually @monthly @weekly @daily @hourly @reboot); packages/formula/src/template-engine.ts exports TEMPLATE_FORMATTERS via packages/formula/src/index.ts. That file carried neither set, and the sets had lived in the quick references this flight deleted — so the pointer was the last mention of both, resolving to nothing.

Paid by cutting narration of the same class this flight exists to remove: the asc/desc anecdote from the new note, and the Skill Boundaries cron parenthetical now that the surfaces table names Job.schedule.expression and the dialect. Two new identifiers were added and both are live — check:skill-identifier-liveness Leg 1 went 476 → 477 citations and stayed OK.

Token delta

filebeforeafterceilingheadroom
skills/objectstack-formula/SKILL.md6,0025,1586,002844

Net −844 tokens (−14.1%), 551 → 374 lines. Convention is the ratchet's own: ceil(utf8 bytes / 4), so ceil($(wc -c < file) / 4) reproduces it. Ceiling untouched (FRM-I-01 re-lock is deferred). The generated references/_index.md (302 tok) is untouched.

Gap against the audit's −1,265, itemised per cluster — not smoothed

cluster (commit)audit est.measuredgapwhy
F-06 / A-01 / G-05 / B-04 / F-07−515−440+75the two collapsed rows keep their real carrier lists (4 cron carriers, 3 template carriers) so the last mention still points somewhere; F-07 is a small addition inside a deletion cluster
D-05 / D-04 / B-03−522−389+133all three are MERGE-INTO, not DELETE. Rules the audit's raw span estimate wrote off survive: the onError clause, "a condition that does not even compile aborts the same way", the ADR-0058 per-row statement
D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03−511−392+119B-06 and B-05 are merges: "Verify your work" absorbed the runtime-throw half of the ADR-0032 callout, and the three determinism conditions folded into the seed pattern's own note rather than vanishing
F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08+237+356+119the two contract notes have to name both refusal doors and both fault directions to be actionable; the type-checked block needs a real import
A-02+18+21+3
review round 10both fixes paid in-file

The gap is one thing four times: a MERGE-INTO finding cannot pay what a DELETE would. Where the audit measured a span's bytes, I measured what was left after the rule inside it was preserved. I did not re-wrap, pad, or cut anything the audit did not name to close the difference.

Per-item 落点 | before | after

Deletions

id落点beforeafter
FRM-F-06 / A-01### Cron surfaces, ### Template surfaces, ## Cron quick reference, ## Template quick referencefour sections, a formatter table and two code blocksone ### Cron and template surfaces table, one row each, carriers named, the seven cron aliases inlined and the formatter whitelist named. Both are live surfaces with 0 corpus usages, so neither loses its last mention; the frontmatter no longer says "Do not use for cron schedules" while the body teaches cron
FRM-D-05section 5 bulk-write prose165 tokens restating the before* table row, plus query-count and fetch-cost narrationone clause pointing back at that row; the ADR-0058 per-row semantics keep their sentence
FRM-D-04section 5 abort calloutthe pre-protocol-17 logger.warn history and its two opposite-failure examplesthe rule only: aborts on before* and after* alike, no onError escape, non-compiling conditions the same
FRM-B-06top-of-file ADR-0032 calloutADR-0032 stated 3×, and "Verify your work" cross-referenced the top-of-file notestated once, in "Verify your work", keeping both halves — build fails with a located did-you-mean, runtime throws
FRM-B-05## Determinism contracta section restating the seed pattern's own notefolded into that note
FRM-D-01 / B-07"Strategic context"why CEL beat the deleted Salesforce-flavor engine — the first content after the H1gone
FRM-D-07 / D-02Core contract tail"you do not learn three languages" + the roadmap for emitting astgone; the envelope rule both carried survives once
FRM-B-03section 5 previous totalitythe has()-on-a-declared-field rule stated once for record, again for previousone statement covering both, in the has() section
FRM-D-03 / G-03## Open questionstwo bullets citing CelExprSchemagone — the symbol has 0 hits in the repo outside this file
FRM-G-05CEL surfaces table, template notesa visibleOn / visibility deprecated-alias row, titleFormat noted twicealias row gone; titleFormat deduped to one carrier cell
FRM-B-02## See alsoa pointer at node_modules/@objectstack/formula/gone — packages/formula/package.json ships ["dist","README.md","CHANGELOG.md"], and this file already says so
FRM-D-09Core contracta type Expression block transcribing shared/expression.zod.tsone sentence and the pointer
FRM-D-08"No date arithmetic"157 tokens of prose carrying five prescriptionsa five-row table
FRM-B-04template surfaces"no js dialect" restatedone statement, in Core contract
FRM-G-01 / G-02 / G-04 / E-03throughoutobjectstack build 5×; 7.6 / M9.5 / M9.7 / M9.8; "single quotes (always)"; * 100.0os build; no milestone numbers; both quote styles; * 100

Additions (each paid by deletions in the same file)

id落点what it now teachessource
FRM-F-01after the CEL surfaces tablea formula field is virtual — no driver materialises a column, so all three query axes refuse one at both doors: where / searchableFields with 400 INVALID_FIELD, orderBy with 400 INVALID_SORT. Remedy is the stored column, in the same words the sort and search axes already usepackages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts; packages/objectql/src/filter-comparand-shape.ts; packages/objectql/src/engine.ts
FRM-F-03same placea form-view visibleWhen is CLIENT-SIDE only and faults open (true), so it is never access control — and where the opposite holds: Hook / SharingRulecondition and validation predicates abort the writepackages/spec/src/ui/view.zod.ts (FormFieldSchema / FormSectionSchemavisibleWhen); packages/metadata-core/src/form-predicate-root-policy.ts
FRM-F-02CEL syntax cheat-sheetthe two missing roots: parent (line-item cell readonlyWhen / requiredWhen) and data (metadata-editing forms, repeater rows included)packages/spec/src/data/field.zod.ts; BOUND_FORM_VIEW_PREDICATE_ROOTS
FRM-F-04translation table + its warningflow conditions bind bare identifiers — the engine spreads the record's variables to top level. The table's first row implied record. prefixing was universalpackages/services/service-automation/src/engine.ts — "bare identifiers like status / previous.status resolve — the natural authoring style for record-change start conditions"
FRM-A-02frontmatter descriptionthat this is the companion skill objectstack-data / -ui / -api / -automation each tell you to load alongside themthose four descriptions
FRM-B-01## See alsoa link to references/_index.md — formula was the only domain package that orphaned its own generated index (8 of 9 link theirs)
FRM-E-01Mandatory pattern 3the predicate block is now type-checked. Both previously marked blocks were the cron and template quick references, so no "Mandatory pattern" was checked at allsee the ablation below
FRM-F-07view-filter prohibitionnames the alternative it was withholding: date macro tokens, pointing at objectstack-query rules/filters.mdskills/objectstack-query/rules/filters.md

Anchor rulings honoured

This package is the CEL anchor; the automation flight (#14467) and the query flight (#14443) deleted their CEL restatements on that ruling. All three anchored constructs survive with their headings addressable:

  • ## ObjectStack CEL standard library — the 35-function table, untouched
  • ## Mechanical translation table (legacy → CEL) — including the OLD / NEW rows and the warning below it (the warning gained the flow-condition exception; nothing was removed)
  • ## Surfaces that take an Expression — the CEL surfaces table, minus the one deprecated alias row

The packages/formula pin tests both pass, quoted below.

Premise adjustments — no finding was forced

  • FRM-B-02, half true. The audit reads :548-551 as pointing at an unreadable package. That holds for the @objectstack/formula line. The second pointer, node_modules/@objectstack/spec/src/shared/expression.zod.ts, is readable in an installed apppackages/spec/package.json ships src/**/*.zod.ts. Kept, and the additions lean on it.
  • FRM-B-04, 2 instances not 3. The audit lists :81-83, :476-478 and :51. The first two restate "there is no js dialect" and one was deleted. :51 is the Skill Boundaries row routing L2 hook bodies to objectstack-data — a routing row that never states the claim. Realized 2 → 1.
  • FRM-D-08 is not ≈0. Measured −7 tokens as a table.
  • Everything else held at my base. skills/objectstack-formula/** is byte-identical between the audit ref a59f78d, the dispatch base 18d816a5 and my branch point 93940d49, so every skills/ span was valid unchanged; packages/** citations are re-cited above at the tree in this PR.

Follow-ups (⛔ deliberately not touched here)

Gates — head sha 291f7bd7

Re-derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsafter the round-1 edit and after merging origin/main: 36 commands, whole list run, list identical across all three derivations. Two derivations were refused as STALE and each was answered by merging origin/main rather than by reading the old copies — the first (33 commits behind, 148 family files changed) conflicted only in the two generated files, which were resolved to main's side, committed, and only then regenerated, never in MERGE state; the second (5 commits behind, changing .github/workflows/lint.yml and scripts/role-word-baseline.json, both of which the families read) merged cleanly. The @objectstack/spec + @objectstack/client-react closure was rebuilt after each merge — check:skill-examples and check:docs both refuse a stale dist and said so, by name, rather than answering falsely green.

35 / 36 green. The one non-zero is node scripts/check-test-completeness.mjsexit 3, which that script defines as a MISSING or UNREADABLE LOG — NOT MEASURED, not red. Exit codes were captured by redirecting each command to its own file before any pipe.

Card-named gates, quoting each gate's own verdict line:

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-formula/SKILL.md is 5158 tokens (ceiling 6002; headroom 844). and ✓ check-skills-token-ratchet: 37 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.
  • pnpm --filter @objectstack/spec check:skill-examples✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-identifier-livenesscheck-skill-identifier-liveness OK — Leg 1: 477 citation(s) over 47 published file(s) checked against 93135 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s). Leg 2 was checked before the first deletion: none of the 8 registered exhaustive sections is in this file.
  • pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync
  • packages/formula pin tests — pnpm --filter @objectstack/formula exec vitest run --maxWorkers=2 src/cel-stdlib-drift.test.ts src/skill-catalog-sync.test.tsTest Files 2 passed (2) / Tests 5 passed (5). The stdlib anchor is intact.
  • pnpm check:role-word — green, no ratchet-DOWN, so scripts/role-word-baseline.json is untouched.

Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14316. The pushed remote head equals the tree the gates read (291f7bd7, verified with git ls-remote).

FRM-E-01 ablation — the marker is not a phantom green

The new marker was added only after the gate passed with it, then ablated once. Mutation and restore were both proven on disk rather than by an editor's exit code:

  • HEAD blob 21ee6b50; a semantic-only mutation was injected (assigning the P tagged template's Expression result to number), leaving the block syntactically valid so the failure could only come from the semantic pass.
  • Mutation proven on disk: injected text grep -c = 1, anchor still 1, git hash-object = 79936c1f ≠ HEAD blob.
  • Gate on the mutated tree: exit 1, and it named the block — skills/objectstack-formula/SKILL.md:243:7 error TS2322: Type '{ dialect: ... }' is not assignable to type 'number'. The right file, the right line, my block.
  • Restore leg given the same treatment as the mutation leg: git checkout HEAD -- with an absolute path (never the bare form, which restores from a polluted index), inside a trap ... EXIT INT TERM using absolute paths. Proven by git hash-object = 21ee6b50 (equal to the HEAD blob, non-empty) andgit diff HEAD empty — not by the restore's exit code.
  • No rebuild was needed between legs: the gate reads the markdown directly, and the mutated artifact was that markdown, not a package dist.

Labels

skip-changeset — this PR releases nothing. Verified against the gate's own enumeration rather than assumed: scripts/check-empty-changeset.mjs carries a "GREEN 3: a skills/**-only PR carrying NO changeset (route 2)" case asserting exactly this shape must be green, and no packages/*/package.json ships skills/ in its files[]. Plus needs:contract-review, because FRM-F-01, F-03 and F-04 are contract-semantics claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…RM-F-06 / A-01 / G-05 / B-04 / F-07)
The frontmatter routes cron away ("Do not use for ... cron schedules") while the
body taught it across four sections; the corpus authors zero of it (`cron` 0,
`tmpl` 0, any formatter 0). Both are live surfaces, so each keeps ONE
schema-pointing row with its carriers; the two quick-reference sections and the
formatter table go.
- FRM-F-06 / A-01: `### Cron surfaces`, `### Template surfaces`, `## Cron quick
reference` and `## Template quick reference` collapse into one
`### Cron and template surfaces` table, two rows, pointing at
`shared/expression.zod.ts` for the full carrier list.
- FRM-G-05: the deprecated `visibleOn` / `visibility` alias row leaves the CEL
surfaces table; the two `Object.titleFormat` notes dedupe to one carrier cell.
- FRM-B-04: the third "no js dialect" restatement goes; the canonical one in
Core contract stays.
- FRM-F-07: the view-list-filter prohibition now names the alternative it was
withholding — date macro tokens, with the pointer to objectstack-query
`rules/filters.md`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…history (FRM-D-05 / D-04 / B-03)
Section 5 was 20.7% of the file (1,241 tok). The rules in it are load-bearing;
the narration around them was not.
- FRM-D-04: the pre-protocol-17 `logger.warn` history goes. Two rules were
buried in it and survive in one sentence: `before*` and `after*` abort alike
with no `onError` escape, and a condition that does not compile aborts the
same way.
- FRM-D-05: the `before*` exception restated the table row above it at 165
tokens — it is now one clause pointing back at that row. The per-row bulk
semantics keep their ADR-0058 statement; the query-count and fetch-cost
narration goes.
- FRM-B-03: the `has()`-on-a-declared-field rule was stated once for `record`
and again for `previous`. It is now one statement covering both, in the
`has()` section where the rule lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…RM-D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03)
- FRM-D-01 / B-07: "Strategic context" — why CEL was picked over the deleted
Salesforce-flavor engine — was the first content after the H1. An author
emitting a predicate does not need the engine-selection history.
- FRM-B-06: ADR-0032 was stated three times, and "Verify your work" cross-refs
the top-of-file note that carried it. One statement now, in "Verify your
work", and it keeps both halves the callout had: build fails with a located
did-you-mean, and the runtime throws.
- FRM-D-09: the `type Expression` block transcribed `shared/expression.zod.ts`.
One sentence and the pointer replace it.
- FRM-D-07 / D-02: "you do not learn three languages" and the roadmap for
emitting `ast` go; the envelope rule they both carried survives once.
The auto-wrap fact moved to the cron/template row in the previous commit.
- FRM-B-05: "Determinism contract" restated the seed pattern's own note. The
three numbered conditions fold into that note.
- FRM-D-03 / G-03: "Open questions" cited `CelExprSchema` twice; the symbol
exists nowhere in the repo (0 hits outside this file).
- FRM-G-01: the CLI is `os`, not `objectstack` — 5 mentions, now 0.
- FRM-G-02: the frontmatter pins 17.x; the retired milestone numbers are gone.
- FRM-G-04: a CEL string literal takes either quote; the corpus writes double
quotes inside P` ` more than ten times, so "(always)" was false.
- FRM-E-03: `* 100.0` was a cel-js workaround. `registerNumericCoercions`
(`packages/formula/src/stdlib.ts`) registers the mixed `double op int` /
`int op double` overloads, so `* 100` is correct now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…FRM-F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08)
The corpus measurement behind these: `type: 'formula'` fields have zero live
usages and the only hits are a removal test; flow/trigger conditions are
authored five times and the scope was taught wrong; field conditional rules are
the second-commonest task and two of their roots were missing.
- FRM-F-01: a `formula` field is virtual — `where` / `orderBy` /
`searchableFields` on one are refused `400 INVALID_FIELD` at both doors
(`packages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts`;
`packages/objectql/src/filter-comparand-shape.ts`). The filter and sort axes
were taught nowhere in the catalog. Remedy is the stored column, in the same
words the sort and search axes already use.
- FRM-F-03: a form-view `visibleWhen` is client-side only and faults OPEN
(`packages/spec/src/ui/view.zod.ts` `FormFieldSchema` / `FormSectionSchema`;
`packages/metadata-core/src/form-predicate-root-policy.ts`). The package
taught fault-closed globally, so the note says where each holds.
- FRM-F-02: the `parent` root (line-item cell `readonlyWhen` / `requiredWhen`,
`packages/spec/src/data/field.zod.ts`) and the `data` root (metadata-editing
forms, `BOUND_FORM_VIEW_PREDICATE_ROOTS`) join the cheat-sheet.
- FRM-F-04: flow conditions bind bare identifiers — the automation engine
spreads the record's variables to top level
(`packages/services/service-automation/src/engine.ts`). The translation
table's first row implied the opposite universally.
- FRM-B-02 / B-01: the `node_modules/@objectstack/formula/` pointer named a
package that ships `dist` only, which this file already says is unreadable.
Its slot goes to `references/_index.md`, which every other domain package
links and this one orphaned.
- FRM-E-01: the predicate pattern block is now type-checked. Both previously
marked blocks were the cron and template quick references, so no "Mandatory
pattern" was checked at all.
- FRM-D-08: the no-date-arithmetic rule carried five prescriptions as prose.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…cron away (FRM-A-02 / A-01)
Four host skills end their description with "load objectstack-formula
alongside" (objectstack-data, -ui, -api, -automation); this one never said it
was that companion, so an author reading it cold had no way to know why it had
been loaded.
FRM-A-01: the description also said "Do not use for ... cron schedules" while
the body taught cron across four sections. The body now carries one
schema-pointing cron row, so the exclusion goes and the Skill Boundaries table
keeps the routing to objectstack-automation.
`skills/README.md` and `content/docs/ai/skills-reference.mdx` are the generator
output of `pnpm --filter @objectstack/spec gen:skill-docs` — both move, and
nothing in them is hand-edited.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ills-formula-optimization
# Conflicts:
#	content/docs/ai/skills-reference.mdx
#	skills/README.md
Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), re-run
after the merge so it derives from all 11 SKILL.md files at the merged tree
rather than at the pre-merge one. The whole diff is the FRM-A-02 description
edit; nothing here is hand-written.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…pointer (contract review round 1)
Two spans failed in-seat contract review; both were verified at source before
editing and both are paid in-file — the file lands back on 5,158 tokens exactly,
no growth.
FAIL 1 (FRM-F-01, the query-axis note). The three axes do not share one error
code. `where` and `searchableFields` answer `400 INVALID_FIELD`, but `orderBy`
answers `400 INVALID_SORT` — `assertOrderByIsMaterializable` sets
`err.code = 'INVALID_SORT'` at the engine seam
(`packages/objectql/src/engine.ts`), and `assertSortFieldsExist` does the same
at the ingress. An agent branching on the code would have branched wrong on the
sort refusal. Both codes are now named.
FAIL 2 (the cron/template pointer). The paragraph sent readers to
`shared/expression.zod.ts` for "the formatter whitelist and the cron alias
set", and that file carries neither. Worse, the sets used to live in the quick
references this flight deleted, so the pointer was the last mention of both —
and this same file correctly says `@objectstack/formula` ships `dist` only, so
"go read it" resolves to nothing. Now: the seven aliases are inlined in the cron
row from `packages/formula/src/cron-engine.ts`, the template row names
`TEMPLATE_FORMATTERS` (really exported from `@objectstack/formula`, derived
from the formatter table in `packages/formula/src/template-engine.ts`) as the
introspectable whitelist, and the `expression.zod.ts` pointer is narrowed to
the carrier lists it does declare.
Paid by cutting narration of the same class this flight exists to remove: the
`asc`/`desc` anecdote from the new note, and the Skill Boundaries cron
parenthetical now that the surfaces table names `Job.schedule.expression` and
the dialect.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 13:07
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 2f2a0b2Sep 2, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14316-skills-formula-optimization branch September 2, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens) - #14563

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization
Sep 2, 2026
Merged

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens)#14563
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14316

Member of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET. The audit record is on the card as the audit-record comment.

Transliteration key — the GitHub body sanitizer eats angle-bracket-shaped fragments, so this body spells them out: LT = opening angle bracket, GT = closing angle bracket, and a name in CAPS inside a path (record.FIELD, vars.STEP.KEY) stands for a placeholder the file writes in angle brackets.

Governed face — three of the changes below are contract-semantics claims, so this PR stays draft and carries needs:contract-review; the card carries it too.

Review round 1 — both FAILs fixed, paid in-file

In-seat contract review at d3a32664 returned FAIL on two spans, PASS on everything else. Both were re-verified at source before editing, both are fixed, and both are paid inside SKILL.md: the file lands back on 5,158 tokens exactly, the same figure it carried at review time. Nothing grew.

#what was wrongwhat it says nowverified at
1the query-axis note gave all three axes one code, 400 INVALID_FIELDwhere and searchableFields answer 400 INVALID_FIELD; orderBy answers 400 INVALID_SORTpackages/objectql/src/engine.tsassertOrderByIsMaterializable sets err.code = 'INVALID_SORT'; assertSortFieldsExist is the same code at the ingress. An agent branching on the code would have branched wrong on the sort refusal.
2the cron/template paragraph sent readers to shared/expression.zod.ts for "the formatter whitelist and the cron alias set"the seven aliases are inlined in the cron row; the template row names TEMPLATE_FORMATTERS, exported from @objectstack/formula, as the introspectable whitelist; the expression.zod.ts pointer is narrowed to the carrier lists it really declarespackages/formula/src/cron-engine.ts (@yearly @annually @monthly @weekly @daily @hourly @reboot); packages/formula/src/template-engine.ts exports TEMPLATE_FORMATTERS via packages/formula/src/index.ts. That file carried neither set, and the sets had lived in the quick references this flight deleted — so the pointer was the last mention of both, resolving to nothing.

Paid by cutting narration of the same class this flight exists to remove: the asc/desc anecdote from the new note, and the Skill Boundaries cron parenthetical now that the surfaces table names Job.schedule.expression and the dialect. Two new identifiers were added and both are live — check:skill-identifier-liveness Leg 1 went 476 → 477 citations and stayed OK.

Token delta

filebeforeafterceilingheadroom
skills/objectstack-formula/SKILL.md6,0025,1586,002844

Net −844 tokens (−14.1%), 551 → 374 lines. Convention is the ratchet's own: ceil(utf8 bytes / 4), so ceil($(wc -c < file) / 4) reproduces it. Ceiling untouched (FRM-I-01 re-lock is deferred). The generated references/_index.md (302 tok) is untouched.

Gap against the audit's −1,265, itemised per cluster — not smoothed

cluster (commit)audit est.measuredgapwhy
F-06 / A-01 / G-05 / B-04 / F-07−515−440+75the two collapsed rows keep their real carrier lists (4 cron carriers, 3 template carriers) so the last mention still points somewhere; F-07 is a small addition inside a deletion cluster
D-05 / D-04 / B-03−522−389+133all three are MERGE-INTO, not DELETE. Rules the audit's raw span estimate wrote off survive: the onError clause, "a condition that does not even compile aborts the same way", the ADR-0058 per-row statement
D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03−511−392+119B-06 and B-05 are merges: "Verify your work" absorbed the runtime-throw half of the ADR-0032 callout, and the three determinism conditions folded into the seed pattern's own note rather than vanishing
F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08+237+356+119the two contract notes have to name both refusal doors and both fault directions to be actionable; the type-checked block needs a real import
A-02+18+21+3
review round 10both fixes paid in-file

The gap is one thing four times: a MERGE-INTO finding cannot pay what a DELETE would. Where the audit measured a span's bytes, I measured what was left after the rule inside it was preserved. I did not re-wrap, pad, or cut anything the audit did not name to close the difference.

Per-item 落点 | before | after

Deletions

id落点beforeafter
FRM-F-06 / A-01### Cron surfaces, ### Template surfaces, ## Cron quick reference, ## Template quick referencefour sections, a formatter table and two code blocksone ### Cron and template surfaces table, one row each, carriers named, the seven cron aliases inlined and the formatter whitelist named. Both are live surfaces with 0 corpus usages, so neither loses its last mention; the frontmatter no longer says "Do not use for cron schedules" while the body teaches cron
FRM-D-05section 5 bulk-write prose165 tokens restating the before* table row, plus query-count and fetch-cost narrationone clause pointing back at that row; the ADR-0058 per-row semantics keep their sentence
FRM-D-04section 5 abort calloutthe pre-protocol-17 logger.warn history and its two opposite-failure examplesthe rule only: aborts on before* and after* alike, no onError escape, non-compiling conditions the same
FRM-B-06top-of-file ADR-0032 calloutADR-0032 stated 3×, and "Verify your work" cross-referenced the top-of-file notestated once, in "Verify your work", keeping both halves — build fails with a located did-you-mean, runtime throws
FRM-B-05## Determinism contracta section restating the seed pattern's own notefolded into that note
FRM-D-01 / B-07"Strategic context"why CEL beat the deleted Salesforce-flavor engine — the first content after the H1gone
FRM-D-07 / D-02Core contract tail"you do not learn three languages" + the roadmap for emitting astgone; the envelope rule both carried survives once
FRM-B-03section 5 previous totalitythe has()-on-a-declared-field rule stated once for record, again for previousone statement covering both, in the has() section
FRM-D-03 / G-03## Open questionstwo bullets citing CelExprSchemagone — the symbol has 0 hits in the repo outside this file
FRM-G-05CEL surfaces table, template notesa visibleOn / visibility deprecated-alias row, titleFormat noted twicealias row gone; titleFormat deduped to one carrier cell
FRM-B-02## See alsoa pointer at node_modules/@objectstack/formula/gone — packages/formula/package.json ships ["dist","README.md","CHANGELOG.md"], and this file already says so
FRM-D-09Core contracta type Expression block transcribing shared/expression.zod.tsone sentence and the pointer
FRM-D-08"No date arithmetic"157 tokens of prose carrying five prescriptionsa five-row table
FRM-B-04template surfaces"no js dialect" restatedone statement, in Core contract
FRM-G-01 / G-02 / G-04 / E-03throughoutobjectstack build 5×; 7.6 / M9.5 / M9.7 / M9.8; "single quotes (always)"; * 100.0os build; no milestone numbers; both quote styles; * 100

Additions (each paid by deletions in the same file)

id落点what it now teachessource
FRM-F-01after the CEL surfaces tablea formula field is virtual — no driver materialises a column, so all three query axes refuse one at both doors: where / searchableFields with 400 INVALID_FIELD, orderBy with 400 INVALID_SORT. Remedy is the stored column, in the same words the sort and search axes already usepackages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts; packages/objectql/src/filter-comparand-shape.ts; packages/objectql/src/engine.ts
FRM-F-03same placea form-view visibleWhen is CLIENT-SIDE only and faults open (true), so it is never access control — and where the opposite holds: Hook / SharingRulecondition and validation predicates abort the writepackages/spec/src/ui/view.zod.ts (FormFieldSchema / FormSectionSchemavisibleWhen); packages/metadata-core/src/form-predicate-root-policy.ts
FRM-F-02CEL syntax cheat-sheetthe two missing roots: parent (line-item cell readonlyWhen / requiredWhen) and data (metadata-editing forms, repeater rows included)packages/spec/src/data/field.zod.ts; BOUND_FORM_VIEW_PREDICATE_ROOTS
FRM-F-04translation table + its warningflow conditions bind bare identifiers — the engine spreads the record's variables to top level. The table's first row implied record. prefixing was universalpackages/services/service-automation/src/engine.ts — "bare identifiers like status / previous.status resolve — the natural authoring style for record-change start conditions"
FRM-A-02frontmatter descriptionthat this is the companion skill objectstack-data / -ui / -api / -automation each tell you to load alongside themthose four descriptions
FRM-B-01## See alsoa link to references/_index.md — formula was the only domain package that orphaned its own generated index (8 of 9 link theirs)
FRM-E-01Mandatory pattern 3the predicate block is now type-checked. Both previously marked blocks were the cron and template quick references, so no "Mandatory pattern" was checked at allsee the ablation below
FRM-F-07view-filter prohibitionnames the alternative it was withholding: date macro tokens, pointing at objectstack-query rules/filters.mdskills/objectstack-query/rules/filters.md

Anchor rulings honoured

This package is the CEL anchor; the automation flight (#14467) and the query flight (#14443) deleted their CEL restatements on that ruling. All three anchored constructs survive with their headings addressable:

  • ## ObjectStack CEL standard library — the 35-function table, untouched
  • ## Mechanical translation table (legacy → CEL) — including the OLD / NEW rows and the warning below it (the warning gained the flow-condition exception; nothing was removed)
  • ## Surfaces that take an Expression — the CEL surfaces table, minus the one deprecated alias row

The packages/formula pin tests both pass, quoted below.

Premise adjustments — no finding was forced

  • FRM-B-02, half true. The audit reads :548-551 as pointing at an unreadable package. That holds for the @objectstack/formula line. The second pointer, node_modules/@objectstack/spec/src/shared/expression.zod.ts, is readable in an installed apppackages/spec/package.json ships src/**/*.zod.ts. Kept, and the additions lean on it.
  • FRM-B-04, 2 instances not 3. The audit lists :81-83, :476-478 and :51. The first two restate "there is no js dialect" and one was deleted. :51 is the Skill Boundaries row routing L2 hook bodies to objectstack-data — a routing row that never states the claim. Realized 2 → 1.
  • FRM-D-08 is not ≈0. Measured −7 tokens as a table.
  • Everything else held at my base. skills/objectstack-formula/** is byte-identical between the audit ref a59f78d, the dispatch base 18d816a5 and my branch point 93940d49, so every skills/ span was valid unchanged; packages/** citations are re-cited above at the tree in this PR.

Follow-ups (⛔ deliberately not touched here)

Gates — head sha 291f7bd7

Re-derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsafter the round-1 edit and after merging origin/main: 36 commands, whole list run, list identical across all three derivations. Two derivations were refused as STALE and each was answered by merging origin/main rather than by reading the old copies — the first (33 commits behind, 148 family files changed) conflicted only in the two generated files, which were resolved to main's side, committed, and only then regenerated, never in MERGE state; the second (5 commits behind, changing .github/workflows/lint.yml and scripts/role-word-baseline.json, both of which the families read) merged cleanly. The @objectstack/spec + @objectstack/client-react closure was rebuilt after each merge — check:skill-examples and check:docs both refuse a stale dist and said so, by name, rather than answering falsely green.

35 / 36 green. The one non-zero is node scripts/check-test-completeness.mjsexit 3, which that script defines as a MISSING or UNREADABLE LOG — NOT MEASURED, not red. Exit codes were captured by redirecting each command to its own file before any pipe.

Card-named gates, quoting each gate's own verdict line:

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-formula/SKILL.md is 5158 tokens (ceiling 6002; headroom 844). and ✓ check-skills-token-ratchet: 37 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.
  • pnpm --filter @objectstack/spec check:skill-examples✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-identifier-livenesscheck-skill-identifier-liveness OK — Leg 1: 477 citation(s) over 47 published file(s) checked against 93135 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s). Leg 2 was checked before the first deletion: none of the 8 registered exhaustive sections is in this file.
  • pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync
  • packages/formula pin tests — pnpm --filter @objectstack/formula exec vitest run --maxWorkers=2 src/cel-stdlib-drift.test.ts src/skill-catalog-sync.test.tsTest Files 2 passed (2) / Tests 5 passed (5). The stdlib anchor is intact.
  • pnpm check:role-word — green, no ratchet-DOWN, so scripts/role-word-baseline.json is untouched.

Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14316. The pushed remote head equals the tree the gates read (291f7bd7, verified with git ls-remote).

FRM-E-01 ablation — the marker is not a phantom green

The new marker was added only after the gate passed with it, then ablated once. Mutation and restore were both proven on disk rather than by an editor's exit code:

  • HEAD blob 21ee6b50; a semantic-only mutation was injected (assigning the P tagged template's Expression result to number), leaving the block syntactically valid so the failure could only come from the semantic pass.
  • Mutation proven on disk: injected text grep -c = 1, anchor still 1, git hash-object = 79936c1f ≠ HEAD blob.
  • Gate on the mutated tree: exit 1, and it named the block — skills/objectstack-formula/SKILL.md:243:7 error TS2322: Type '{ dialect: ... }' is not assignable to type 'number'. The right file, the right line, my block.
  • Restore leg given the same treatment as the mutation leg: git checkout HEAD -- with an absolute path (never the bare form, which restores from a polluted index), inside a trap ... EXIT INT TERM using absolute paths. Proven by git hash-object = 21ee6b50 (equal to the HEAD blob, non-empty) andgit diff HEAD empty — not by the restore's exit code.
  • No rebuild was needed between legs: the gate reads the markdown directly, and the mutated artifact was that markdown, not a package dist.

Labels

skip-changeset — this PR releases nothing. Verified against the gate's own enumeration rather than assumed: scripts/check-empty-changeset.mjs carries a "GREEN 3: a skills/**-only PR carrying NO changeset (route 2)" case asserting exactly this shape must be green, and no packages/*/package.json ships skills/ in its files[]. Plus needs:contract-review, because FRM-F-01, F-03 and F-04 are contract-semantics claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…RM-F-06 / A-01 / G-05 / B-04 / F-07)
The frontmatter routes cron away ("Do not use for ... cron schedules") while the
body taught it across four sections; the corpus authors zero of it (`cron` 0,
`tmpl` 0, any formatter 0). Both are live surfaces, so each keeps ONE
schema-pointing row with its carriers; the two quick-reference sections and the
formatter table go.
- FRM-F-06 / A-01: `### Cron surfaces`, `### Template surfaces`, `## Cron quick
reference` and `## Template quick reference` collapse into one
`### Cron and template surfaces` table, two rows, pointing at
`shared/expression.zod.ts` for the full carrier list.
- FRM-G-05: the deprecated `visibleOn` / `visibility` alias row leaves the CEL
surfaces table; the two `Object.titleFormat` notes dedupe to one carrier cell.
- FRM-B-04: the third "no js dialect" restatement goes; the canonical one in
Core contract stays.
- FRM-F-07: the view-list-filter prohibition now names the alternative it was
withholding — date macro tokens, with the pointer to objectstack-query
`rules/filters.md`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…history (FRM-D-05 / D-04 / B-03)
Section 5 was 20.7% of the file (1,241 tok). The rules in it are load-bearing;
the narration around them was not.
- FRM-D-04: the pre-protocol-17 `logger.warn` history goes. Two rules were
buried in it and survive in one sentence: `before*` and `after*` abort alike
with no `onError` escape, and a condition that does not compile aborts the
same way.
- FRM-D-05: the `before*` exception restated the table row above it at 165
tokens — it is now one clause pointing back at that row. The per-row bulk
semantics keep their ADR-0058 statement; the query-count and fetch-cost
narration goes.
- FRM-B-03: the `has()`-on-a-declared-field rule was stated once for `record`
and again for `previous`. It is now one statement covering both, in the
`has()` section where the rule lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…RM-D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03)
- FRM-D-01 / B-07: "Strategic context" — why CEL was picked over the deleted
Salesforce-flavor engine — was the first content after the H1. An author
emitting a predicate does not need the engine-selection history.
- FRM-B-06: ADR-0032 was stated three times, and "Verify your work" cross-refs
the top-of-file note that carried it. One statement now, in "Verify your
work", and it keeps both halves the callout had: build fails with a located
did-you-mean, and the runtime throws.
- FRM-D-09: the `type Expression` block transcribed `shared/expression.zod.ts`.
One sentence and the pointer replace it.
- FRM-D-07 / D-02: "you do not learn three languages" and the roadmap for
emitting `ast` go; the envelope rule they both carried survives once.
The auto-wrap fact moved to the cron/template row in the previous commit.
- FRM-B-05: "Determinism contract" restated the seed pattern's own note. The
three numbered conditions fold into that note.
- FRM-D-03 / G-03: "Open questions" cited `CelExprSchema` twice; the symbol
exists nowhere in the repo (0 hits outside this file).
- FRM-G-01: the CLI is `os`, not `objectstack` — 5 mentions, now 0.
- FRM-G-02: the frontmatter pins 17.x; the retired milestone numbers are gone.
- FRM-G-04: a CEL string literal takes either quote; the corpus writes double
quotes inside P` ` more than ten times, so "(always)" was false.
- FRM-E-03: `* 100.0` was a cel-js workaround. `registerNumericCoercions`
(`packages/formula/src/stdlib.ts`) registers the mixed `double op int` /
`int op double` overloads, so `* 100` is correct now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…FRM-F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08)
The corpus measurement behind these: `type: 'formula'` fields have zero live
usages and the only hits are a removal test; flow/trigger conditions are
authored five times and the scope was taught wrong; field conditional rules are
the second-commonest task and two of their roots were missing.
- FRM-F-01: a `formula` field is virtual — `where` / `orderBy` /
`searchableFields` on one are refused `400 INVALID_FIELD` at both doors
(`packages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts`;
`packages/objectql/src/filter-comparand-shape.ts`). The filter and sort axes
were taught nowhere in the catalog. Remedy is the stored column, in the same
words the sort and search axes already use.
- FRM-F-03: a form-view `visibleWhen` is client-side only and faults OPEN
(`packages/spec/src/ui/view.zod.ts` `FormFieldSchema` / `FormSectionSchema`;
`packages/metadata-core/src/form-predicate-root-policy.ts`). The package
taught fault-closed globally, so the note says where each holds.
- FRM-F-02: the `parent` root (line-item cell `readonlyWhen` / `requiredWhen`,
`packages/spec/src/data/field.zod.ts`) and the `data` root (metadata-editing
forms, `BOUND_FORM_VIEW_PREDICATE_ROOTS`) join the cheat-sheet.
- FRM-F-04: flow conditions bind bare identifiers — the automation engine
spreads the record's variables to top level
(`packages/services/service-automation/src/engine.ts`). The translation
table's first row implied the opposite universally.
- FRM-B-02 / B-01: the `node_modules/@objectstack/formula/` pointer named a
package that ships `dist` only, which this file already says is unreadable.
Its slot goes to `references/_index.md`, which every other domain package
links and this one orphaned.
- FRM-E-01: the predicate pattern block is now type-checked. Both previously
marked blocks were the cron and template quick references, so no "Mandatory
pattern" was checked at all.
- FRM-D-08: the no-date-arithmetic rule carried five prescriptions as prose.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…cron away (FRM-A-02 / A-01)
Four host skills end their description with "load objectstack-formula
alongside" (objectstack-data, -ui, -api, -automation); this one never said it
was that companion, so an author reading it cold had no way to know why it had
been loaded.
FRM-A-01: the description also said "Do not use for ... cron schedules" while
the body taught cron across four sections. The body now carries one
schema-pointing cron row, so the exclusion goes and the Skill Boundaries table
keeps the routing to objectstack-automation.
`skills/README.md` and `content/docs/ai/skills-reference.mdx` are the generator
output of `pnpm --filter @objectstack/spec gen:skill-docs` — both move, and
nothing in them is hand-edited.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ills-formula-optimization
# Conflicts:
#	content/docs/ai/skills-reference.mdx
#	skills/README.md
Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), re-run
after the merge so it derives from all 11 SKILL.md files at the merged tree
rather than at the pre-merge one. The whole diff is the FRM-A-02 description
edit; nothing here is hand-written.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…pointer (contract review round 1)
Two spans failed in-seat contract review; both were verified at source before
editing and both are paid in-file — the file lands back on 5,158 tokens exactly,
no growth.
FAIL 1 (FRM-F-01, the query-axis note). The three axes do not share one error
code. `where` and `searchableFields` answer `400 INVALID_FIELD`, but `orderBy`
answers `400 INVALID_SORT` — `assertOrderByIsMaterializable` sets
`err.code = 'INVALID_SORT'` at the engine seam
(`packages/objectql/src/engine.ts`), and `assertSortFieldsExist` does the same
at the ingress. An agent branching on the code would have branched wrong on the
sort refusal. Both codes are now named.
FAIL 2 (the cron/template pointer). The paragraph sent readers to
`shared/expression.zod.ts` for "the formatter whitelist and the cron alias
set", and that file carries neither. Worse, the sets used to live in the quick
references this flight deleted, so the pointer was the last mention of both —
and this same file correctly says `@objectstack/formula` ships `dist` only, so
"go read it" resolves to nothing. Now: the seven aliases are inlined in the cron
row from `packages/formula/src/cron-engine.ts`, the template row names
`TEMPLATE_FORMATTERS` (really exported from `@objectstack/formula`, derived
from the formatter table in `packages/formula/src/template-engine.ts`) as the
introspectable whitelist, and the `expression.zod.ts` pointer is narrowed to
the carrier lists it does declare.
Paid by cutting narration of the same class this flight exists to remove: the
`asc`/`desc` anecdote from the new note, and the Skill Boundaries cron
parenthetical now that the surfaces table names `Job.schedule.expression` and
the dialect.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 13:07
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 2f2a0b2Sep 2, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14316-skills-formula-optimization branch September 2, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens) - #14563

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization
Sep 2, 2026
Merged

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens)#14563
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14316

Member of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET. The audit record is on the card as the audit-record comment.

Transliteration key — the GitHub body sanitizer eats angle-bracket-shaped fragments, so this body spells them out: LT = opening angle bracket, GT = closing angle bracket, and a name in CAPS inside a path (record.FIELD, vars.STEP.KEY) stands for a placeholder the file writes in angle brackets.

Governed face — three of the changes below are contract-semantics claims, so this PR stays draft and carries needs:contract-review; the card carries it too.

Review round 1 — both FAILs fixed, paid in-file

In-seat contract review at d3a32664 returned FAIL on two spans, PASS on everything else. Both were re-verified at source before editing, both are fixed, and both are paid inside SKILL.md: the file lands back on 5,158 tokens exactly, the same figure it carried at review time. Nothing grew.

#what was wrongwhat it says nowverified at
1the query-axis note gave all three axes one code, 400 INVALID_FIELDwhere and searchableFields answer 400 INVALID_FIELD; orderBy answers 400 INVALID_SORTpackages/objectql/src/engine.tsassertOrderByIsMaterializable sets err.code = 'INVALID_SORT'; assertSortFieldsExist is the same code at the ingress. An agent branching on the code would have branched wrong on the sort refusal.
2the cron/template paragraph sent readers to shared/expression.zod.ts for "the formatter whitelist and the cron alias set"the seven aliases are inlined in the cron row; the template row names TEMPLATE_FORMATTERS, exported from @objectstack/formula, as the introspectable whitelist; the expression.zod.ts pointer is narrowed to the carrier lists it really declarespackages/formula/src/cron-engine.ts (@yearly @annually @monthly @weekly @daily @hourly @reboot); packages/formula/src/template-engine.ts exports TEMPLATE_FORMATTERS via packages/formula/src/index.ts. That file carried neither set, and the sets had lived in the quick references this flight deleted — so the pointer was the last mention of both, resolving to nothing.

Paid by cutting narration of the same class this flight exists to remove: the asc/desc anecdote from the new note, and the Skill Boundaries cron parenthetical now that the surfaces table names Job.schedule.expression and the dialect. Two new identifiers were added and both are live — check:skill-identifier-liveness Leg 1 went 476 → 477 citations and stayed OK.

Token delta

filebeforeafterceilingheadroom
skills/objectstack-formula/SKILL.md6,0025,1586,002844

Net −844 tokens (−14.1%), 551 → 374 lines. Convention is the ratchet's own: ceil(utf8 bytes / 4), so ceil($(wc -c < file) / 4) reproduces it. Ceiling untouched (FRM-I-01 re-lock is deferred). The generated references/_index.md (302 tok) is untouched.

Gap against the audit's −1,265, itemised per cluster — not smoothed

cluster (commit)audit est.measuredgapwhy
F-06 / A-01 / G-05 / B-04 / F-07−515−440+75the two collapsed rows keep their real carrier lists (4 cron carriers, 3 template carriers) so the last mention still points somewhere; F-07 is a small addition inside a deletion cluster
D-05 / D-04 / B-03−522−389+133all three are MERGE-INTO, not DELETE. Rules the audit's raw span estimate wrote off survive: the onError clause, "a condition that does not even compile aborts the same way", the ADR-0058 per-row statement
D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03−511−392+119B-06 and B-05 are merges: "Verify your work" absorbed the runtime-throw half of the ADR-0032 callout, and the three determinism conditions folded into the seed pattern's own note rather than vanishing
F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08+237+356+119the two contract notes have to name both refusal doors and both fault directions to be actionable; the type-checked block needs a real import
A-02+18+21+3
review round 10both fixes paid in-file

The gap is one thing four times: a MERGE-INTO finding cannot pay what a DELETE would. Where the audit measured a span's bytes, I measured what was left after the rule inside it was preserved. I did not re-wrap, pad, or cut anything the audit did not name to close the difference.

Per-item 落点 | before | after

Deletions

id落点beforeafter
FRM-F-06 / A-01### Cron surfaces, ### Template surfaces, ## Cron quick reference, ## Template quick referencefour sections, a formatter table and two code blocksone ### Cron and template surfaces table, one row each, carriers named, the seven cron aliases inlined and the formatter whitelist named. Both are live surfaces with 0 corpus usages, so neither loses its last mention; the frontmatter no longer says "Do not use for cron schedules" while the body teaches cron
FRM-D-05section 5 bulk-write prose165 tokens restating the before* table row, plus query-count and fetch-cost narrationone clause pointing back at that row; the ADR-0058 per-row semantics keep their sentence
FRM-D-04section 5 abort calloutthe pre-protocol-17 logger.warn history and its two opposite-failure examplesthe rule only: aborts on before* and after* alike, no onError escape, non-compiling conditions the same
FRM-B-06top-of-file ADR-0032 calloutADR-0032 stated 3×, and "Verify your work" cross-referenced the top-of-file notestated once, in "Verify your work", keeping both halves — build fails with a located did-you-mean, runtime throws
FRM-B-05## Determinism contracta section restating the seed pattern's own notefolded into that note
FRM-D-01 / B-07"Strategic context"why CEL beat the deleted Salesforce-flavor engine — the first content after the H1gone
FRM-D-07 / D-02Core contract tail"you do not learn three languages" + the roadmap for emitting astgone; the envelope rule both carried survives once
FRM-B-03section 5 previous totalitythe has()-on-a-declared-field rule stated once for record, again for previousone statement covering both, in the has() section
FRM-D-03 / G-03## Open questionstwo bullets citing CelExprSchemagone — the symbol has 0 hits in the repo outside this file
FRM-G-05CEL surfaces table, template notesa visibleOn / visibility deprecated-alias row, titleFormat noted twicealias row gone; titleFormat deduped to one carrier cell
FRM-B-02## See alsoa pointer at node_modules/@objectstack/formula/gone — packages/formula/package.json ships ["dist","README.md","CHANGELOG.md"], and this file already says so
FRM-D-09Core contracta type Expression block transcribing shared/expression.zod.tsone sentence and the pointer
FRM-D-08"No date arithmetic"157 tokens of prose carrying five prescriptionsa five-row table
FRM-B-04template surfaces"no js dialect" restatedone statement, in Core contract
FRM-G-01 / G-02 / G-04 / E-03throughoutobjectstack build 5×; 7.6 / M9.5 / M9.7 / M9.8; "single quotes (always)"; * 100.0os build; no milestone numbers; both quote styles; * 100

Additions (each paid by deletions in the same file)

id落点what it now teachessource
FRM-F-01after the CEL surfaces tablea formula field is virtual — no driver materialises a column, so all three query axes refuse one at both doors: where / searchableFields with 400 INVALID_FIELD, orderBy with 400 INVALID_SORT. Remedy is the stored column, in the same words the sort and search axes already usepackages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts; packages/objectql/src/filter-comparand-shape.ts; packages/objectql/src/engine.ts
FRM-F-03same placea form-view visibleWhen is CLIENT-SIDE only and faults open (true), so it is never access control — and where the opposite holds: Hook / SharingRulecondition and validation predicates abort the writepackages/spec/src/ui/view.zod.ts (FormFieldSchema / FormSectionSchemavisibleWhen); packages/metadata-core/src/form-predicate-root-policy.ts
FRM-F-02CEL syntax cheat-sheetthe two missing roots: parent (line-item cell readonlyWhen / requiredWhen) and data (metadata-editing forms, repeater rows included)packages/spec/src/data/field.zod.ts; BOUND_FORM_VIEW_PREDICATE_ROOTS
FRM-F-04translation table + its warningflow conditions bind bare identifiers — the engine spreads the record's variables to top level. The table's first row implied record. prefixing was universalpackages/services/service-automation/src/engine.ts — "bare identifiers like status / previous.status resolve — the natural authoring style for record-change start conditions"
FRM-A-02frontmatter descriptionthat this is the companion skill objectstack-data / -ui / -api / -automation each tell you to load alongside themthose four descriptions
FRM-B-01## See alsoa link to references/_index.md — formula was the only domain package that orphaned its own generated index (8 of 9 link theirs)
FRM-E-01Mandatory pattern 3the predicate block is now type-checked. Both previously marked blocks were the cron and template quick references, so no "Mandatory pattern" was checked at allsee the ablation below
FRM-F-07view-filter prohibitionnames the alternative it was withholding: date macro tokens, pointing at objectstack-query rules/filters.mdskills/objectstack-query/rules/filters.md

Anchor rulings honoured

This package is the CEL anchor; the automation flight (#14467) and the query flight (#14443) deleted their CEL restatements on that ruling. All three anchored constructs survive with their headings addressable:

  • ## ObjectStack CEL standard library — the 35-function table, untouched
  • ## Mechanical translation table (legacy → CEL) — including the OLD / NEW rows and the warning below it (the warning gained the flow-condition exception; nothing was removed)
  • ## Surfaces that take an Expression — the CEL surfaces table, minus the one deprecated alias row

The packages/formula pin tests both pass, quoted below.

Premise adjustments — no finding was forced

  • FRM-B-02, half true. The audit reads :548-551 as pointing at an unreadable package. That holds for the @objectstack/formula line. The second pointer, node_modules/@objectstack/spec/src/shared/expression.zod.ts, is readable in an installed apppackages/spec/package.json ships src/**/*.zod.ts. Kept, and the additions lean on it.
  • FRM-B-04, 2 instances not 3. The audit lists :81-83, :476-478 and :51. The first two restate "there is no js dialect" and one was deleted. :51 is the Skill Boundaries row routing L2 hook bodies to objectstack-data — a routing row that never states the claim. Realized 2 → 1.
  • FRM-D-08 is not ≈0. Measured −7 tokens as a table.
  • Everything else held at my base. skills/objectstack-formula/** is byte-identical between the audit ref a59f78d, the dispatch base 18d816a5 and my branch point 93940d49, so every skills/ span was valid unchanged; packages/** citations are re-cited above at the tree in this PR.

Follow-ups (⛔ deliberately not touched here)

Gates — head sha 291f7bd7

Re-derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsafter the round-1 edit and after merging origin/main: 36 commands, whole list run, list identical across all three derivations. Two derivations were refused as STALE and each was answered by merging origin/main rather than by reading the old copies — the first (33 commits behind, 148 family files changed) conflicted only in the two generated files, which were resolved to main's side, committed, and only then regenerated, never in MERGE state; the second (5 commits behind, changing .github/workflows/lint.yml and scripts/role-word-baseline.json, both of which the families read) merged cleanly. The @objectstack/spec + @objectstack/client-react closure was rebuilt after each merge — check:skill-examples and check:docs both refuse a stale dist and said so, by name, rather than answering falsely green.

35 / 36 green. The one non-zero is node scripts/check-test-completeness.mjsexit 3, which that script defines as a MISSING or UNREADABLE LOG — NOT MEASURED, not red. Exit codes were captured by redirecting each command to its own file before any pipe.

Card-named gates, quoting each gate's own verdict line:

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-formula/SKILL.md is 5158 tokens (ceiling 6002; headroom 844). and ✓ check-skills-token-ratchet: 37 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.
  • pnpm --filter @objectstack/spec check:skill-examples✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-identifier-livenesscheck-skill-identifier-liveness OK — Leg 1: 477 citation(s) over 47 published file(s) checked against 93135 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s). Leg 2 was checked before the first deletion: none of the 8 registered exhaustive sections is in this file.
  • pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync
  • packages/formula pin tests — pnpm --filter @objectstack/formula exec vitest run --maxWorkers=2 src/cel-stdlib-drift.test.ts src/skill-catalog-sync.test.tsTest Files 2 passed (2) / Tests 5 passed (5). The stdlib anchor is intact.
  • pnpm check:role-word — green, no ratchet-DOWN, so scripts/role-word-baseline.json is untouched.

Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14316. The pushed remote head equals the tree the gates read (291f7bd7, verified with git ls-remote).

FRM-E-01 ablation — the marker is not a phantom green

The new marker was added only after the gate passed with it, then ablated once. Mutation and restore were both proven on disk rather than by an editor's exit code:

  • HEAD blob 21ee6b50; a semantic-only mutation was injected (assigning the P tagged template's Expression result to number), leaving the block syntactically valid so the failure could only come from the semantic pass.
  • Mutation proven on disk: injected text grep -c = 1, anchor still 1, git hash-object = 79936c1f ≠ HEAD blob.
  • Gate on the mutated tree: exit 1, and it named the block — skills/objectstack-formula/SKILL.md:243:7 error TS2322: Type '{ dialect: ... }' is not assignable to type 'number'. The right file, the right line, my block.
  • Restore leg given the same treatment as the mutation leg: git checkout HEAD -- with an absolute path (never the bare form, which restores from a polluted index), inside a trap ... EXIT INT TERM using absolute paths. Proven by git hash-object = 21ee6b50 (equal to the HEAD blob, non-empty) andgit diff HEAD empty — not by the restore's exit code.
  • No rebuild was needed between legs: the gate reads the markdown directly, and the mutated artifact was that markdown, not a package dist.

Labels

skip-changeset — this PR releases nothing. Verified against the gate's own enumeration rather than assumed: scripts/check-empty-changeset.mjs carries a "GREEN 3: a skills/**-only PR carrying NO changeset (route 2)" case asserting exactly this shape must be green, and no packages/*/package.json ships skills/ in its files[]. Plus needs:contract-review, because FRM-F-01, F-03 and F-04 are contract-semantics claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…RM-F-06 / A-01 / G-05 / B-04 / F-07)
The frontmatter routes cron away ("Do not use for ... cron schedules") while the
body taught it across four sections; the corpus authors zero of it (`cron` 0,
`tmpl` 0, any formatter 0). Both are live surfaces, so each keeps ONE
schema-pointing row with its carriers; the two quick-reference sections and the
formatter table go.
- FRM-F-06 / A-01: `### Cron surfaces`, `### Template surfaces`, `## Cron quick
reference` and `## Template quick reference` collapse into one
`### Cron and template surfaces` table, two rows, pointing at
`shared/expression.zod.ts` for the full carrier list.
- FRM-G-05: the deprecated `visibleOn` / `visibility` alias row leaves the CEL
surfaces table; the two `Object.titleFormat` notes dedupe to one carrier cell.
- FRM-B-04: the third "no js dialect" restatement goes; the canonical one in
Core contract stays.
- FRM-F-07: the view-list-filter prohibition now names the alternative it was
withholding — date macro tokens, with the pointer to objectstack-query
`rules/filters.md`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…history (FRM-D-05 / D-04 / B-03)
Section 5 was 20.7% of the file (1,241 tok). The rules in it are load-bearing;
the narration around them was not.
- FRM-D-04: the pre-protocol-17 `logger.warn` history goes. Two rules were
buried in it and survive in one sentence: `before*` and `after*` abort alike
with no `onError` escape, and a condition that does not compile aborts the
same way.
- FRM-D-05: the `before*` exception restated the table row above it at 165
tokens — it is now one clause pointing back at that row. The per-row bulk
semantics keep their ADR-0058 statement; the query-count and fetch-cost
narration goes.
- FRM-B-03: the `has()`-on-a-declared-field rule was stated once for `record`
and again for `previous`. It is now one statement covering both, in the
`has()` section where the rule lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…RM-D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03)
- FRM-D-01 / B-07: "Strategic context" — why CEL was picked over the deleted
Salesforce-flavor engine — was the first content after the H1. An author
emitting a predicate does not need the engine-selection history.
- FRM-B-06: ADR-0032 was stated three times, and "Verify your work" cross-refs
the top-of-file note that carried it. One statement now, in "Verify your
work", and it keeps both halves the callout had: build fails with a located
did-you-mean, and the runtime throws.
- FRM-D-09: the `type Expression` block transcribed `shared/expression.zod.ts`.
One sentence and the pointer replace it.
- FRM-D-07 / D-02: "you do not learn three languages" and the roadmap for
emitting `ast` go; the envelope rule they both carried survives once.
The auto-wrap fact moved to the cron/template row in the previous commit.
- FRM-B-05: "Determinism contract" restated the seed pattern's own note. The
three numbered conditions fold into that note.
- FRM-D-03 / G-03: "Open questions" cited `CelExprSchema` twice; the symbol
exists nowhere in the repo (0 hits outside this file).
- FRM-G-01: the CLI is `os`, not `objectstack` — 5 mentions, now 0.
- FRM-G-02: the frontmatter pins 17.x; the retired milestone numbers are gone.
- FRM-G-04: a CEL string literal takes either quote; the corpus writes double
quotes inside P` ` more than ten times, so "(always)" was false.
- FRM-E-03: `* 100.0` was a cel-js workaround. `registerNumericCoercions`
(`packages/formula/src/stdlib.ts`) registers the mixed `double op int` /
`int op double` overloads, so `* 100` is correct now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…FRM-F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08)
The corpus measurement behind these: `type: 'formula'` fields have zero live
usages and the only hits are a removal test; flow/trigger conditions are
authored five times and the scope was taught wrong; field conditional rules are
the second-commonest task and two of their roots were missing.
- FRM-F-01: a `formula` field is virtual — `where` / `orderBy` /
`searchableFields` on one are refused `400 INVALID_FIELD` at both doors
(`packages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts`;
`packages/objectql/src/filter-comparand-shape.ts`). The filter and sort axes
were taught nowhere in the catalog. Remedy is the stored column, in the same
words the sort and search axes already use.
- FRM-F-03: a form-view `visibleWhen` is client-side only and faults OPEN
(`packages/spec/src/ui/view.zod.ts` `FormFieldSchema` / `FormSectionSchema`;
`packages/metadata-core/src/form-predicate-root-policy.ts`). The package
taught fault-closed globally, so the note says where each holds.
- FRM-F-02: the `parent` root (line-item cell `readonlyWhen` / `requiredWhen`,
`packages/spec/src/data/field.zod.ts`) and the `data` root (metadata-editing
forms, `BOUND_FORM_VIEW_PREDICATE_ROOTS`) join the cheat-sheet.
- FRM-F-04: flow conditions bind bare identifiers — the automation engine
spreads the record's variables to top level
(`packages/services/service-automation/src/engine.ts`). The translation
table's first row implied the opposite universally.
- FRM-B-02 / B-01: the `node_modules/@objectstack/formula/` pointer named a
package that ships `dist` only, which this file already says is unreadable.
Its slot goes to `references/_index.md`, which every other domain package
links and this one orphaned.
- FRM-E-01: the predicate pattern block is now type-checked. Both previously
marked blocks were the cron and template quick references, so no "Mandatory
pattern" was checked at all.
- FRM-D-08: the no-date-arithmetic rule carried five prescriptions as prose.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…cron away (FRM-A-02 / A-01)
Four host skills end their description with "load objectstack-formula
alongside" (objectstack-data, -ui, -api, -automation); this one never said it
was that companion, so an author reading it cold had no way to know why it had
been loaded.
FRM-A-01: the description also said "Do not use for ... cron schedules" while
the body taught cron across four sections. The body now carries one
schema-pointing cron row, so the exclusion goes and the Skill Boundaries table
keeps the routing to objectstack-automation.
`skills/README.md` and `content/docs/ai/skills-reference.mdx` are the generator
output of `pnpm --filter @objectstack/spec gen:skill-docs` — both move, and
nothing in them is hand-edited.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ills-formula-optimization
# Conflicts:
#	content/docs/ai/skills-reference.mdx
#	skills/README.md
Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), re-run
after the merge so it derives from all 11 SKILL.md files at the merged tree
rather than at the pre-merge one. The whole diff is the FRM-A-02 description
edit; nothing here is hand-written.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…pointer (contract review round 1)
Two spans failed in-seat contract review; both were verified at source before
editing and both are paid in-file — the file lands back on 5,158 tokens exactly,
no growth.
FAIL 1 (FRM-F-01, the query-axis note). The three axes do not share one error
code. `where` and `searchableFields` answer `400 INVALID_FIELD`, but `orderBy`
answers `400 INVALID_SORT` — `assertOrderByIsMaterializable` sets
`err.code = 'INVALID_SORT'` at the engine seam
(`packages/objectql/src/engine.ts`), and `assertSortFieldsExist` does the same
at the ingress. An agent branching on the code would have branched wrong on the
sort refusal. Both codes are now named.
FAIL 2 (the cron/template pointer). The paragraph sent readers to
`shared/expression.zod.ts` for "the formatter whitelist and the cron alias
set", and that file carries neither. Worse, the sets used to live in the quick
references this flight deleted, so the pointer was the last mention of both —
and this same file correctly says `@objectstack/formula` ships `dist` only, so
"go read it" resolves to nothing. Now: the seven aliases are inlined in the cron
row from `packages/formula/src/cron-engine.ts`, the template row names
`TEMPLATE_FORMATTERS` (really exported from `@objectstack/formula`, derived
from the formatter table in `packages/formula/src/template-engine.ts`) as the
introspectable whitelist, and the `expression.zod.ts` pointer is narrowed to
the carrier lists it does declare.
Paid by cutting narration of the same class this flight exists to remove: the
`asc`/`desc` anecdote from the new note, and the Skill Boundaries cron
parenthetical now that the surfaces table names `Job.schedule.expression` and
the dialect.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 13:07
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 2f2a0b2Sep 2, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14316-skills-formula-optimization branch September 2, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens) - #14563

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization
Sep 2, 2026
Merged

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens)#14563
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14316

Member of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET. The audit record is on the card as the audit-record comment.

Transliteration key — the GitHub body sanitizer eats angle-bracket-shaped fragments, so this body spells them out: LT = opening angle bracket, GT = closing angle bracket, and a name in CAPS inside a path (record.FIELD, vars.STEP.KEY) stands for a placeholder the file writes in angle brackets.

Governed face — three of the changes below are contract-semantics claims, so this PR stays draft and carries needs:contract-review; the card carries it too.

Review round 1 — both FAILs fixed, paid in-file

In-seat contract review at d3a32664 returned FAIL on two spans, PASS on everything else. Both were re-verified at source before editing, both are fixed, and both are paid inside SKILL.md: the file lands back on 5,158 tokens exactly, the same figure it carried at review time. Nothing grew.

#what was wrongwhat it says nowverified at
1the query-axis note gave all three axes one code, 400 INVALID_FIELDwhere and searchableFields answer 400 INVALID_FIELD; orderBy answers 400 INVALID_SORTpackages/objectql/src/engine.tsassertOrderByIsMaterializable sets err.code = 'INVALID_SORT'; assertSortFieldsExist is the same code at the ingress. An agent branching on the code would have branched wrong on the sort refusal.
2the cron/template paragraph sent readers to shared/expression.zod.ts for "the formatter whitelist and the cron alias set"the seven aliases are inlined in the cron row; the template row names TEMPLATE_FORMATTERS, exported from @objectstack/formula, as the introspectable whitelist; the expression.zod.ts pointer is narrowed to the carrier lists it really declarespackages/formula/src/cron-engine.ts (@yearly @annually @monthly @weekly @daily @hourly @reboot); packages/formula/src/template-engine.ts exports TEMPLATE_FORMATTERS via packages/formula/src/index.ts. That file carried neither set, and the sets had lived in the quick references this flight deleted — so the pointer was the last mention of both, resolving to nothing.

Paid by cutting narration of the same class this flight exists to remove: the asc/desc anecdote from the new note, and the Skill Boundaries cron parenthetical now that the surfaces table names Job.schedule.expression and the dialect. Two new identifiers were added and both are live — check:skill-identifier-liveness Leg 1 went 476 → 477 citations and stayed OK.

Token delta

filebeforeafterceilingheadroom
skills/objectstack-formula/SKILL.md6,0025,1586,002844

Net −844 tokens (−14.1%), 551 → 374 lines. Convention is the ratchet's own: ceil(utf8 bytes / 4), so ceil($(wc -c < file) / 4) reproduces it. Ceiling untouched (FRM-I-01 re-lock is deferred). The generated references/_index.md (302 tok) is untouched.

Gap against the audit's −1,265, itemised per cluster — not smoothed

cluster (commit)audit est.measuredgapwhy
F-06 / A-01 / G-05 / B-04 / F-07−515−440+75the two collapsed rows keep their real carrier lists (4 cron carriers, 3 template carriers) so the last mention still points somewhere; F-07 is a small addition inside a deletion cluster
D-05 / D-04 / B-03−522−389+133all three are MERGE-INTO, not DELETE. Rules the audit's raw span estimate wrote off survive: the onError clause, "a condition that does not even compile aborts the same way", the ADR-0058 per-row statement
D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03−511−392+119B-06 and B-05 are merges: "Verify your work" absorbed the runtime-throw half of the ADR-0032 callout, and the three determinism conditions folded into the seed pattern's own note rather than vanishing
F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08+237+356+119the two contract notes have to name both refusal doors and both fault directions to be actionable; the type-checked block needs a real import
A-02+18+21+3
review round 10both fixes paid in-file

The gap is one thing four times: a MERGE-INTO finding cannot pay what a DELETE would. Where the audit measured a span's bytes, I measured what was left after the rule inside it was preserved. I did not re-wrap, pad, or cut anything the audit did not name to close the difference.

Per-item 落点 | before | after

Deletions

id落点beforeafter
FRM-F-06 / A-01### Cron surfaces, ### Template surfaces, ## Cron quick reference, ## Template quick referencefour sections, a formatter table and two code blocksone ### Cron and template surfaces table, one row each, carriers named, the seven cron aliases inlined and the formatter whitelist named. Both are live surfaces with 0 corpus usages, so neither loses its last mention; the frontmatter no longer says "Do not use for cron schedules" while the body teaches cron
FRM-D-05section 5 bulk-write prose165 tokens restating the before* table row, plus query-count and fetch-cost narrationone clause pointing back at that row; the ADR-0058 per-row semantics keep their sentence
FRM-D-04section 5 abort calloutthe pre-protocol-17 logger.warn history and its two opposite-failure examplesthe rule only: aborts on before* and after* alike, no onError escape, non-compiling conditions the same
FRM-B-06top-of-file ADR-0032 calloutADR-0032 stated 3×, and "Verify your work" cross-referenced the top-of-file notestated once, in "Verify your work", keeping both halves — build fails with a located did-you-mean, runtime throws
FRM-B-05## Determinism contracta section restating the seed pattern's own notefolded into that note
FRM-D-01 / B-07"Strategic context"why CEL beat the deleted Salesforce-flavor engine — the first content after the H1gone
FRM-D-07 / D-02Core contract tail"you do not learn three languages" + the roadmap for emitting astgone; the envelope rule both carried survives once
FRM-B-03section 5 previous totalitythe has()-on-a-declared-field rule stated once for record, again for previousone statement covering both, in the has() section
FRM-D-03 / G-03## Open questionstwo bullets citing CelExprSchemagone — the symbol has 0 hits in the repo outside this file
FRM-G-05CEL surfaces table, template notesa visibleOn / visibility deprecated-alias row, titleFormat noted twicealias row gone; titleFormat deduped to one carrier cell
FRM-B-02## See alsoa pointer at node_modules/@objectstack/formula/gone — packages/formula/package.json ships ["dist","README.md","CHANGELOG.md"], and this file already says so
FRM-D-09Core contracta type Expression block transcribing shared/expression.zod.tsone sentence and the pointer
FRM-D-08"No date arithmetic"157 tokens of prose carrying five prescriptionsa five-row table
FRM-B-04template surfaces"no js dialect" restatedone statement, in Core contract
FRM-G-01 / G-02 / G-04 / E-03throughoutobjectstack build 5×; 7.6 / M9.5 / M9.7 / M9.8; "single quotes (always)"; * 100.0os build; no milestone numbers; both quote styles; * 100

Additions (each paid by deletions in the same file)

id落点what it now teachessource
FRM-F-01after the CEL surfaces tablea formula field is virtual — no driver materialises a column, so all three query axes refuse one at both doors: where / searchableFields with 400 INVALID_FIELD, orderBy with 400 INVALID_SORT. Remedy is the stored column, in the same words the sort and search axes already usepackages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts; packages/objectql/src/filter-comparand-shape.ts; packages/objectql/src/engine.ts
FRM-F-03same placea form-view visibleWhen is CLIENT-SIDE only and faults open (true), so it is never access control — and where the opposite holds: Hook / SharingRulecondition and validation predicates abort the writepackages/spec/src/ui/view.zod.ts (FormFieldSchema / FormSectionSchemavisibleWhen); packages/metadata-core/src/form-predicate-root-policy.ts
FRM-F-02CEL syntax cheat-sheetthe two missing roots: parent (line-item cell readonlyWhen / requiredWhen) and data (metadata-editing forms, repeater rows included)packages/spec/src/data/field.zod.ts; BOUND_FORM_VIEW_PREDICATE_ROOTS
FRM-F-04translation table + its warningflow conditions bind bare identifiers — the engine spreads the record's variables to top level. The table's first row implied record. prefixing was universalpackages/services/service-automation/src/engine.ts — "bare identifiers like status / previous.status resolve — the natural authoring style for record-change start conditions"
FRM-A-02frontmatter descriptionthat this is the companion skill objectstack-data / -ui / -api / -automation each tell you to load alongside themthose four descriptions
FRM-B-01## See alsoa link to references/_index.md — formula was the only domain package that orphaned its own generated index (8 of 9 link theirs)
FRM-E-01Mandatory pattern 3the predicate block is now type-checked. Both previously marked blocks were the cron and template quick references, so no "Mandatory pattern" was checked at allsee the ablation below
FRM-F-07view-filter prohibitionnames the alternative it was withholding: date macro tokens, pointing at objectstack-query rules/filters.mdskills/objectstack-query/rules/filters.md

Anchor rulings honoured

This package is the CEL anchor; the automation flight (#14467) and the query flight (#14443) deleted their CEL restatements on that ruling. All three anchored constructs survive with their headings addressable:

  • ## ObjectStack CEL standard library — the 35-function table, untouched
  • ## Mechanical translation table (legacy → CEL) — including the OLD / NEW rows and the warning below it (the warning gained the flow-condition exception; nothing was removed)
  • ## Surfaces that take an Expression — the CEL surfaces table, minus the one deprecated alias row

The packages/formula pin tests both pass, quoted below.

Premise adjustments — no finding was forced

  • FRM-B-02, half true. The audit reads :548-551 as pointing at an unreadable package. That holds for the @objectstack/formula line. The second pointer, node_modules/@objectstack/spec/src/shared/expression.zod.ts, is readable in an installed apppackages/spec/package.json ships src/**/*.zod.ts. Kept, and the additions lean on it.
  • FRM-B-04, 2 instances not 3. The audit lists :81-83, :476-478 and :51. The first two restate "there is no js dialect" and one was deleted. :51 is the Skill Boundaries row routing L2 hook bodies to objectstack-data — a routing row that never states the claim. Realized 2 → 1.
  • FRM-D-08 is not ≈0. Measured −7 tokens as a table.
  • Everything else held at my base. skills/objectstack-formula/** is byte-identical between the audit ref a59f78d, the dispatch base 18d816a5 and my branch point 93940d49, so every skills/ span was valid unchanged; packages/** citations are re-cited above at the tree in this PR.

Follow-ups (⛔ deliberately not touched here)

Gates — head sha 291f7bd7

Re-derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsafter the round-1 edit and after merging origin/main: 36 commands, whole list run, list identical across all three derivations. Two derivations were refused as STALE and each was answered by merging origin/main rather than by reading the old copies — the first (33 commits behind, 148 family files changed) conflicted only in the two generated files, which were resolved to main's side, committed, and only then regenerated, never in MERGE state; the second (5 commits behind, changing .github/workflows/lint.yml and scripts/role-word-baseline.json, both of which the families read) merged cleanly. The @objectstack/spec + @objectstack/client-react closure was rebuilt after each merge — check:skill-examples and check:docs both refuse a stale dist and said so, by name, rather than answering falsely green.

35 / 36 green. The one non-zero is node scripts/check-test-completeness.mjsexit 3, which that script defines as a MISSING or UNREADABLE LOG — NOT MEASURED, not red. Exit codes were captured by redirecting each command to its own file before any pipe.

Card-named gates, quoting each gate's own verdict line:

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-formula/SKILL.md is 5158 tokens (ceiling 6002; headroom 844). and ✓ check-skills-token-ratchet: 37 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.
  • pnpm --filter @objectstack/spec check:skill-examples✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-identifier-livenesscheck-skill-identifier-liveness OK — Leg 1: 477 citation(s) over 47 published file(s) checked against 93135 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s). Leg 2 was checked before the first deletion: none of the 8 registered exhaustive sections is in this file.
  • pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync
  • packages/formula pin tests — pnpm --filter @objectstack/formula exec vitest run --maxWorkers=2 src/cel-stdlib-drift.test.ts src/skill-catalog-sync.test.tsTest Files 2 passed (2) / Tests 5 passed (5). The stdlib anchor is intact.
  • pnpm check:role-word — green, no ratchet-DOWN, so scripts/role-word-baseline.json is untouched.

Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14316. The pushed remote head equals the tree the gates read (291f7bd7, verified with git ls-remote).

FRM-E-01 ablation — the marker is not a phantom green

The new marker was added only after the gate passed with it, then ablated once. Mutation and restore were both proven on disk rather than by an editor's exit code:

  • HEAD blob 21ee6b50; a semantic-only mutation was injected (assigning the P tagged template's Expression result to number), leaving the block syntactically valid so the failure could only come from the semantic pass.
  • Mutation proven on disk: injected text grep -c = 1, anchor still 1, git hash-object = 79936c1f ≠ HEAD blob.
  • Gate on the mutated tree: exit 1, and it named the block — skills/objectstack-formula/SKILL.md:243:7 error TS2322: Type '{ dialect: ... }' is not assignable to type 'number'. The right file, the right line, my block.
  • Restore leg given the same treatment as the mutation leg: git checkout HEAD -- with an absolute path (never the bare form, which restores from a polluted index), inside a trap ... EXIT INT TERM using absolute paths. Proven by git hash-object = 21ee6b50 (equal to the HEAD blob, non-empty) andgit diff HEAD empty — not by the restore's exit code.
  • No rebuild was needed between legs: the gate reads the markdown directly, and the mutated artifact was that markdown, not a package dist.

Labels

skip-changeset — this PR releases nothing. Verified against the gate's own enumeration rather than assumed: scripts/check-empty-changeset.mjs carries a "GREEN 3: a skills/**-only PR carrying NO changeset (route 2)" case asserting exactly this shape must be green, and no packages/*/package.json ships skills/ in its files[]. Plus needs:contract-review, because FRM-F-01, F-03 and F-04 are contract-semantics claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…RM-F-06 / A-01 / G-05 / B-04 / F-07)
The frontmatter routes cron away ("Do not use for ... cron schedules") while the
body taught it across four sections; the corpus authors zero of it (`cron` 0,
`tmpl` 0, any formatter 0). Both are live surfaces, so each keeps ONE
schema-pointing row with its carriers; the two quick-reference sections and the
formatter table go.
- FRM-F-06 / A-01: `### Cron surfaces`, `### Template surfaces`, `## Cron quick
reference` and `## Template quick reference` collapse into one
`### Cron and template surfaces` table, two rows, pointing at
`shared/expression.zod.ts` for the full carrier list.
- FRM-G-05: the deprecated `visibleOn` / `visibility` alias row leaves the CEL
surfaces table; the two `Object.titleFormat` notes dedupe to one carrier cell.
- FRM-B-04: the third "no js dialect" restatement goes; the canonical one in
Core contract stays.
- FRM-F-07: the view-list-filter prohibition now names the alternative it was
withholding — date macro tokens, with the pointer to objectstack-query
`rules/filters.md`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…history (FRM-D-05 / D-04 / B-03)
Section 5 was 20.7% of the file (1,241 tok). The rules in it are load-bearing;
the narration around them was not.
- FRM-D-04: the pre-protocol-17 `logger.warn` history goes. Two rules were
buried in it and survive in one sentence: `before*` and `after*` abort alike
with no `onError` escape, and a condition that does not compile aborts the
same way.
- FRM-D-05: the `before*` exception restated the table row above it at 165
tokens — it is now one clause pointing back at that row. The per-row bulk
semantics keep their ADR-0058 statement; the query-count and fetch-cost
narration goes.
- FRM-B-03: the `has()`-on-a-declared-field rule was stated once for `record`
and again for `previous`. It is now one statement covering both, in the
`has()` section where the rule lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…RM-D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03)
- FRM-D-01 / B-07: "Strategic context" — why CEL was picked over the deleted
Salesforce-flavor engine — was the first content after the H1. An author
emitting a predicate does not need the engine-selection history.
- FRM-B-06: ADR-0032 was stated three times, and "Verify your work" cross-refs
the top-of-file note that carried it. One statement now, in "Verify your
work", and it keeps both halves the callout had: build fails with a located
did-you-mean, and the runtime throws.
- FRM-D-09: the `type Expression` block transcribed `shared/expression.zod.ts`.
One sentence and the pointer replace it.
- FRM-D-07 / D-02: "you do not learn three languages" and the roadmap for
emitting `ast` go; the envelope rule they both carried survives once.
The auto-wrap fact moved to the cron/template row in the previous commit.
- FRM-B-05: "Determinism contract" restated the seed pattern's own note. The
three numbered conditions fold into that note.
- FRM-D-03 / G-03: "Open questions" cited `CelExprSchema` twice; the symbol
exists nowhere in the repo (0 hits outside this file).
- FRM-G-01: the CLI is `os`, not `objectstack` — 5 mentions, now 0.
- FRM-G-02: the frontmatter pins 17.x; the retired milestone numbers are gone.
- FRM-G-04: a CEL string literal takes either quote; the corpus writes double
quotes inside P` ` more than ten times, so "(always)" was false.
- FRM-E-03: `* 100.0` was a cel-js workaround. `registerNumericCoercions`
(`packages/formula/src/stdlib.ts`) registers the mixed `double op int` /
`int op double` overloads, so `* 100` is correct now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…FRM-F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08)
The corpus measurement behind these: `type: 'formula'` fields have zero live
usages and the only hits are a removal test; flow/trigger conditions are
authored five times and the scope was taught wrong; field conditional rules are
the second-commonest task and two of their roots were missing.
- FRM-F-01: a `formula` field is virtual — `where` / `orderBy` /
`searchableFields` on one are refused `400 INVALID_FIELD` at both doors
(`packages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts`;
`packages/objectql/src/filter-comparand-shape.ts`). The filter and sort axes
were taught nowhere in the catalog. Remedy is the stored column, in the same
words the sort and search axes already use.
- FRM-F-03: a form-view `visibleWhen` is client-side only and faults OPEN
(`packages/spec/src/ui/view.zod.ts` `FormFieldSchema` / `FormSectionSchema`;
`packages/metadata-core/src/form-predicate-root-policy.ts`). The package
taught fault-closed globally, so the note says where each holds.
- FRM-F-02: the `parent` root (line-item cell `readonlyWhen` / `requiredWhen`,
`packages/spec/src/data/field.zod.ts`) and the `data` root (metadata-editing
forms, `BOUND_FORM_VIEW_PREDICATE_ROOTS`) join the cheat-sheet.
- FRM-F-04: flow conditions bind bare identifiers — the automation engine
spreads the record's variables to top level
(`packages/services/service-automation/src/engine.ts`). The translation
table's first row implied the opposite universally.
- FRM-B-02 / B-01: the `node_modules/@objectstack/formula/` pointer named a
package that ships `dist` only, which this file already says is unreadable.
Its slot goes to `references/_index.md`, which every other domain package
links and this one orphaned.
- FRM-E-01: the predicate pattern block is now type-checked. Both previously
marked blocks were the cron and template quick references, so no "Mandatory
pattern" was checked at all.
- FRM-D-08: the no-date-arithmetic rule carried five prescriptions as prose.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…cron away (FRM-A-02 / A-01)
Four host skills end their description with "load objectstack-formula
alongside" (objectstack-data, -ui, -api, -automation); this one never said it
was that companion, so an author reading it cold had no way to know why it had
been loaded.
FRM-A-01: the description also said "Do not use for ... cron schedules" while
the body taught cron across four sections. The body now carries one
schema-pointing cron row, so the exclusion goes and the Skill Boundaries table
keeps the routing to objectstack-automation.
`skills/README.md` and `content/docs/ai/skills-reference.mdx` are the generator
output of `pnpm --filter @objectstack/spec gen:skill-docs` — both move, and
nothing in them is hand-edited.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ills-formula-optimization
# Conflicts:
#	content/docs/ai/skills-reference.mdx
#	skills/README.md
Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), re-run
after the merge so it derives from all 11 SKILL.md files at the merged tree
rather than at the pre-merge one. The whole diff is the FRM-A-02 description
edit; nothing here is hand-written.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…pointer (contract review round 1)
Two spans failed in-seat contract review; both were verified at source before
editing and both are paid in-file — the file lands back on 5,158 tokens exactly,
no growth.
FAIL 1 (FRM-F-01, the query-axis note). The three axes do not share one error
code. `where` and `searchableFields` answer `400 INVALID_FIELD`, but `orderBy`
answers `400 INVALID_SORT` — `assertOrderByIsMaterializable` sets
`err.code = 'INVALID_SORT'` at the engine seam
(`packages/objectql/src/engine.ts`), and `assertSortFieldsExist` does the same
at the ingress. An agent branching on the code would have branched wrong on the
sort refusal. Both codes are now named.
FAIL 2 (the cron/template pointer). The paragraph sent readers to
`shared/expression.zod.ts` for "the formatter whitelist and the cron alias
set", and that file carries neither. Worse, the sets used to live in the quick
references this flight deleted, so the pointer was the last mention of both —
and this same file correctly says `@objectstack/formula` ships `dist` only, so
"go read it" resolves to nothing. Now: the seven aliases are inlined in the cron
row from `packages/formula/src/cron-engine.ts`, the template row names
`TEMPLATE_FORMATTERS` (really exported from `@objectstack/formula`, derived
from the formatter table in `packages/formula/src/template-engine.ts`) as the
introspectable whitelist, and the `expression.zod.ts` pointer is narrowed to
the carrier lists it does declare.
Paid by cutting narration of the same class this flight exists to remove: the
`asc`/`desc` anecdote from the new note, and the Skill Boundaries cron
parenthetical now that the surfaces table names `Job.schedule.expression` and
the dialect.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 13:07
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 2f2a0b2Sep 2, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14316-skills-formula-optimization branch September 2, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens) - #14563

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization
Sep 2, 2026
Merged

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens)#14563
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14316

Member of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET. The audit record is on the card as the audit-record comment.

Transliteration key — the GitHub body sanitizer eats angle-bracket-shaped fragments, so this body spells them out: LT = opening angle bracket, GT = closing angle bracket, and a name in CAPS inside a path (record.FIELD, vars.STEP.KEY) stands for a placeholder the file writes in angle brackets.

Governed face — three of the changes below are contract-semantics claims, so this PR stays draft and carries needs:contract-review; the card carries it too.

Review round 1 — both FAILs fixed, paid in-file

In-seat contract review at d3a32664 returned FAIL on two spans, PASS on everything else. Both were re-verified at source before editing, both are fixed, and both are paid inside SKILL.md: the file lands back on 5,158 tokens exactly, the same figure it carried at review time. Nothing grew.

#what was wrongwhat it says nowverified at
1the query-axis note gave all three axes one code, 400 INVALID_FIELDwhere and searchableFields answer 400 INVALID_FIELD; orderBy answers 400 INVALID_SORTpackages/objectql/src/engine.tsassertOrderByIsMaterializable sets err.code = 'INVALID_SORT'; assertSortFieldsExist is the same code at the ingress. An agent branching on the code would have branched wrong on the sort refusal.
2the cron/template paragraph sent readers to shared/expression.zod.ts for "the formatter whitelist and the cron alias set"the seven aliases are inlined in the cron row; the template row names TEMPLATE_FORMATTERS, exported from @objectstack/formula, as the introspectable whitelist; the expression.zod.ts pointer is narrowed to the carrier lists it really declarespackages/formula/src/cron-engine.ts (@yearly @annually @monthly @weekly @daily @hourly @reboot); packages/formula/src/template-engine.ts exports TEMPLATE_FORMATTERS via packages/formula/src/index.ts. That file carried neither set, and the sets had lived in the quick references this flight deleted — so the pointer was the last mention of both, resolving to nothing.

Paid by cutting narration of the same class this flight exists to remove: the asc/desc anecdote from the new note, and the Skill Boundaries cron parenthetical now that the surfaces table names Job.schedule.expression and the dialect. Two new identifiers were added and both are live — check:skill-identifier-liveness Leg 1 went 476 → 477 citations and stayed OK.

Token delta

filebeforeafterceilingheadroom
skills/objectstack-formula/SKILL.md6,0025,1586,002844

Net −844 tokens (−14.1%), 551 → 374 lines. Convention is the ratchet's own: ceil(utf8 bytes / 4), so ceil($(wc -c < file) / 4) reproduces it. Ceiling untouched (FRM-I-01 re-lock is deferred). The generated references/_index.md (302 tok) is untouched.

Gap against the audit's −1,265, itemised per cluster — not smoothed

cluster (commit)audit est.measuredgapwhy
F-06 / A-01 / G-05 / B-04 / F-07−515−440+75the two collapsed rows keep their real carrier lists (4 cron carriers, 3 template carriers) so the last mention still points somewhere; F-07 is a small addition inside a deletion cluster
D-05 / D-04 / B-03−522−389+133all three are MERGE-INTO, not DELETE. Rules the audit's raw span estimate wrote off survive: the onError clause, "a condition that does not even compile aborts the same way", the ADR-0058 per-row statement
D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03−511−392+119B-06 and B-05 are merges: "Verify your work" absorbed the runtime-throw half of the ADR-0032 callout, and the three determinism conditions folded into the seed pattern's own note rather than vanishing
F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08+237+356+119the two contract notes have to name both refusal doors and both fault directions to be actionable; the type-checked block needs a real import
A-02+18+21+3
review round 10both fixes paid in-file

The gap is one thing four times: a MERGE-INTO finding cannot pay what a DELETE would. Where the audit measured a span's bytes, I measured what was left after the rule inside it was preserved. I did not re-wrap, pad, or cut anything the audit did not name to close the difference.

Per-item 落点 | before | after

Deletions

id落点beforeafter
FRM-F-06 / A-01### Cron surfaces, ### Template surfaces, ## Cron quick reference, ## Template quick referencefour sections, a formatter table and two code blocksone ### Cron and template surfaces table, one row each, carriers named, the seven cron aliases inlined and the formatter whitelist named. Both are live surfaces with 0 corpus usages, so neither loses its last mention; the frontmatter no longer says "Do not use for cron schedules" while the body teaches cron
FRM-D-05section 5 bulk-write prose165 tokens restating the before* table row, plus query-count and fetch-cost narrationone clause pointing back at that row; the ADR-0058 per-row semantics keep their sentence
FRM-D-04section 5 abort calloutthe pre-protocol-17 logger.warn history and its two opposite-failure examplesthe rule only: aborts on before* and after* alike, no onError escape, non-compiling conditions the same
FRM-B-06top-of-file ADR-0032 calloutADR-0032 stated 3×, and "Verify your work" cross-referenced the top-of-file notestated once, in "Verify your work", keeping both halves — build fails with a located did-you-mean, runtime throws
FRM-B-05## Determinism contracta section restating the seed pattern's own notefolded into that note
FRM-D-01 / B-07"Strategic context"why CEL beat the deleted Salesforce-flavor engine — the first content after the H1gone
FRM-D-07 / D-02Core contract tail"you do not learn three languages" + the roadmap for emitting astgone; the envelope rule both carried survives once
FRM-B-03section 5 previous totalitythe has()-on-a-declared-field rule stated once for record, again for previousone statement covering both, in the has() section
FRM-D-03 / G-03## Open questionstwo bullets citing CelExprSchemagone — the symbol has 0 hits in the repo outside this file
FRM-G-05CEL surfaces table, template notesa visibleOn / visibility deprecated-alias row, titleFormat noted twicealias row gone; titleFormat deduped to one carrier cell
FRM-B-02## See alsoa pointer at node_modules/@objectstack/formula/gone — packages/formula/package.json ships ["dist","README.md","CHANGELOG.md"], and this file already says so
FRM-D-09Core contracta type Expression block transcribing shared/expression.zod.tsone sentence and the pointer
FRM-D-08"No date arithmetic"157 tokens of prose carrying five prescriptionsa five-row table
FRM-B-04template surfaces"no js dialect" restatedone statement, in Core contract
FRM-G-01 / G-02 / G-04 / E-03throughoutobjectstack build 5×; 7.6 / M9.5 / M9.7 / M9.8; "single quotes (always)"; * 100.0os build; no milestone numbers; both quote styles; * 100

Additions (each paid by deletions in the same file)

id落点what it now teachessource
FRM-F-01after the CEL surfaces tablea formula field is virtual — no driver materialises a column, so all three query axes refuse one at both doors: where / searchableFields with 400 INVALID_FIELD, orderBy with 400 INVALID_SORT. Remedy is the stored column, in the same words the sort and search axes already usepackages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts; packages/objectql/src/filter-comparand-shape.ts; packages/objectql/src/engine.ts
FRM-F-03same placea form-view visibleWhen is CLIENT-SIDE only and faults open (true), so it is never access control — and where the opposite holds: Hook / SharingRulecondition and validation predicates abort the writepackages/spec/src/ui/view.zod.ts (FormFieldSchema / FormSectionSchemavisibleWhen); packages/metadata-core/src/form-predicate-root-policy.ts
FRM-F-02CEL syntax cheat-sheetthe two missing roots: parent (line-item cell readonlyWhen / requiredWhen) and data (metadata-editing forms, repeater rows included)packages/spec/src/data/field.zod.ts; BOUND_FORM_VIEW_PREDICATE_ROOTS
FRM-F-04translation table + its warningflow conditions bind bare identifiers — the engine spreads the record's variables to top level. The table's first row implied record. prefixing was universalpackages/services/service-automation/src/engine.ts — "bare identifiers like status / previous.status resolve — the natural authoring style for record-change start conditions"
FRM-A-02frontmatter descriptionthat this is the companion skill objectstack-data / -ui / -api / -automation each tell you to load alongside themthose four descriptions
FRM-B-01## See alsoa link to references/_index.md — formula was the only domain package that orphaned its own generated index (8 of 9 link theirs)
FRM-E-01Mandatory pattern 3the predicate block is now type-checked. Both previously marked blocks were the cron and template quick references, so no "Mandatory pattern" was checked at allsee the ablation below
FRM-F-07view-filter prohibitionnames the alternative it was withholding: date macro tokens, pointing at objectstack-query rules/filters.mdskills/objectstack-query/rules/filters.md

Anchor rulings honoured

This package is the CEL anchor; the automation flight (#14467) and the query flight (#14443) deleted their CEL restatements on that ruling. All three anchored constructs survive with their headings addressable:

  • ## ObjectStack CEL standard library — the 35-function table, untouched
  • ## Mechanical translation table (legacy → CEL) — including the OLD / NEW rows and the warning below it (the warning gained the flow-condition exception; nothing was removed)
  • ## Surfaces that take an Expression — the CEL surfaces table, minus the one deprecated alias row

The packages/formula pin tests both pass, quoted below.

Premise adjustments — no finding was forced

  • FRM-B-02, half true. The audit reads :548-551 as pointing at an unreadable package. That holds for the @objectstack/formula line. The second pointer, node_modules/@objectstack/spec/src/shared/expression.zod.ts, is readable in an installed apppackages/spec/package.json ships src/**/*.zod.ts. Kept, and the additions lean on it.
  • FRM-B-04, 2 instances not 3. The audit lists :81-83, :476-478 and :51. The first two restate "there is no js dialect" and one was deleted. :51 is the Skill Boundaries row routing L2 hook bodies to objectstack-data — a routing row that never states the claim. Realized 2 → 1.
  • FRM-D-08 is not ≈0. Measured −7 tokens as a table.
  • Everything else held at my base. skills/objectstack-formula/** is byte-identical between the audit ref a59f78d, the dispatch base 18d816a5 and my branch point 93940d49, so every skills/ span was valid unchanged; packages/** citations are re-cited above at the tree in this PR.

Follow-ups (⛔ deliberately not touched here)

Gates — head sha 291f7bd7

Re-derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsafter the round-1 edit and after merging origin/main: 36 commands, whole list run, list identical across all three derivations. Two derivations were refused as STALE and each was answered by merging origin/main rather than by reading the old copies — the first (33 commits behind, 148 family files changed) conflicted only in the two generated files, which were resolved to main's side, committed, and only then regenerated, never in MERGE state; the second (5 commits behind, changing .github/workflows/lint.yml and scripts/role-word-baseline.json, both of which the families read) merged cleanly. The @objectstack/spec + @objectstack/client-react closure was rebuilt after each merge — check:skill-examples and check:docs both refuse a stale dist and said so, by name, rather than answering falsely green.

35 / 36 green. The one non-zero is node scripts/check-test-completeness.mjsexit 3, which that script defines as a MISSING or UNREADABLE LOG — NOT MEASURED, not red. Exit codes were captured by redirecting each command to its own file before any pipe.

Card-named gates, quoting each gate's own verdict line:

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-formula/SKILL.md is 5158 tokens (ceiling 6002; headroom 844). and ✓ check-skills-token-ratchet: 37 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.
  • pnpm --filter @objectstack/spec check:skill-examples✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-identifier-livenesscheck-skill-identifier-liveness OK — Leg 1: 477 citation(s) over 47 published file(s) checked against 93135 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s). Leg 2 was checked before the first deletion: none of the 8 registered exhaustive sections is in this file.
  • pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync
  • packages/formula pin tests — pnpm --filter @objectstack/formula exec vitest run --maxWorkers=2 src/cel-stdlib-drift.test.ts src/skill-catalog-sync.test.tsTest Files 2 passed (2) / Tests 5 passed (5). The stdlib anchor is intact.
  • pnpm check:role-word — green, no ratchet-DOWN, so scripts/role-word-baseline.json is untouched.

Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14316. The pushed remote head equals the tree the gates read (291f7bd7, verified with git ls-remote).

FRM-E-01 ablation — the marker is not a phantom green

The new marker was added only after the gate passed with it, then ablated once. Mutation and restore were both proven on disk rather than by an editor's exit code:

  • HEAD blob 21ee6b50; a semantic-only mutation was injected (assigning the P tagged template's Expression result to number), leaving the block syntactically valid so the failure could only come from the semantic pass.
  • Mutation proven on disk: injected text grep -c = 1, anchor still 1, git hash-object = 79936c1f ≠ HEAD blob.
  • Gate on the mutated tree: exit 1, and it named the block — skills/objectstack-formula/SKILL.md:243:7 error TS2322: Type '{ dialect: ... }' is not assignable to type 'number'. The right file, the right line, my block.
  • Restore leg given the same treatment as the mutation leg: git checkout HEAD -- with an absolute path (never the bare form, which restores from a polluted index), inside a trap ... EXIT INT TERM using absolute paths. Proven by git hash-object = 21ee6b50 (equal to the HEAD blob, non-empty) andgit diff HEAD empty — not by the restore's exit code.
  • No rebuild was needed between legs: the gate reads the markdown directly, and the mutated artifact was that markdown, not a package dist.

Labels

skip-changeset — this PR releases nothing. Verified against the gate's own enumeration rather than assumed: scripts/check-empty-changeset.mjs carries a "GREEN 3: a skills/**-only PR carrying NO changeset (route 2)" case asserting exactly this shape must be green, and no packages/*/package.json ships skills/ in its files[]. Plus needs:contract-review, because FRM-F-01, F-03 and F-04 are contract-semantics claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…RM-F-06 / A-01 / G-05 / B-04 / F-07)
The frontmatter routes cron away ("Do not use for ... cron schedules") while the
body taught it across four sections; the corpus authors zero of it (`cron` 0,
`tmpl` 0, any formatter 0). Both are live surfaces, so each keeps ONE
schema-pointing row with its carriers; the two quick-reference sections and the
formatter table go.
- FRM-F-06 / A-01: `### Cron surfaces`, `### Template surfaces`, `## Cron quick
reference` and `## Template quick reference` collapse into one
`### Cron and template surfaces` table, two rows, pointing at
`shared/expression.zod.ts` for the full carrier list.
- FRM-G-05: the deprecated `visibleOn` / `visibility` alias row leaves the CEL
surfaces table; the two `Object.titleFormat` notes dedupe to one carrier cell.
- FRM-B-04: the third "no js dialect" restatement goes; the canonical one in
Core contract stays.
- FRM-F-07: the view-list-filter prohibition now names the alternative it was
withholding — date macro tokens, with the pointer to objectstack-query
`rules/filters.md`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…history (FRM-D-05 / D-04 / B-03)
Section 5 was 20.7% of the file (1,241 tok). The rules in it are load-bearing;
the narration around them was not.
- FRM-D-04: the pre-protocol-17 `logger.warn` history goes. Two rules were
buried in it and survive in one sentence: `before*` and `after*` abort alike
with no `onError` escape, and a condition that does not compile aborts the
same way.
- FRM-D-05: the `before*` exception restated the table row above it at 165
tokens — it is now one clause pointing back at that row. The per-row bulk
semantics keep their ADR-0058 statement; the query-count and fetch-cost
narration goes.
- FRM-B-03: the `has()`-on-a-declared-field rule was stated once for `record`
and again for `previous`. It is now one statement covering both, in the
`has()` section where the rule lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…RM-D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03)
- FRM-D-01 / B-07: "Strategic context" — why CEL was picked over the deleted
Salesforce-flavor engine — was the first content after the H1. An author
emitting a predicate does not need the engine-selection history.
- FRM-B-06: ADR-0032 was stated three times, and "Verify your work" cross-refs
the top-of-file note that carried it. One statement now, in "Verify your
work", and it keeps both halves the callout had: build fails with a located
did-you-mean, and the runtime throws.
- FRM-D-09: the `type Expression` block transcribed `shared/expression.zod.ts`.
One sentence and the pointer replace it.
- FRM-D-07 / D-02: "you do not learn three languages" and the roadmap for
emitting `ast` go; the envelope rule they both carried survives once.
The auto-wrap fact moved to the cron/template row in the previous commit.
- FRM-B-05: "Determinism contract" restated the seed pattern's own note. The
three numbered conditions fold into that note.
- FRM-D-03 / G-03: "Open questions" cited `CelExprSchema` twice; the symbol
exists nowhere in the repo (0 hits outside this file).
- FRM-G-01: the CLI is `os`, not `objectstack` — 5 mentions, now 0.
- FRM-G-02: the frontmatter pins 17.x; the retired milestone numbers are gone.
- FRM-G-04: a CEL string literal takes either quote; the corpus writes double
quotes inside P` ` more than ten times, so "(always)" was false.
- FRM-E-03: `* 100.0` was a cel-js workaround. `registerNumericCoercions`
(`packages/formula/src/stdlib.ts`) registers the mixed `double op int` /
`int op double` overloads, so `* 100` is correct now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…FRM-F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08)
The corpus measurement behind these: `type: 'formula'` fields have zero live
usages and the only hits are a removal test; flow/trigger conditions are
authored five times and the scope was taught wrong; field conditional rules are
the second-commonest task and two of their roots were missing.
- FRM-F-01: a `formula` field is virtual — `where` / `orderBy` /
`searchableFields` on one are refused `400 INVALID_FIELD` at both doors
(`packages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts`;
`packages/objectql/src/filter-comparand-shape.ts`). The filter and sort axes
were taught nowhere in the catalog. Remedy is the stored column, in the same
words the sort and search axes already use.
- FRM-F-03: a form-view `visibleWhen` is client-side only and faults OPEN
(`packages/spec/src/ui/view.zod.ts` `FormFieldSchema` / `FormSectionSchema`;
`packages/metadata-core/src/form-predicate-root-policy.ts`). The package
taught fault-closed globally, so the note says where each holds.
- FRM-F-02: the `parent` root (line-item cell `readonlyWhen` / `requiredWhen`,
`packages/spec/src/data/field.zod.ts`) and the `data` root (metadata-editing
forms, `BOUND_FORM_VIEW_PREDICATE_ROOTS`) join the cheat-sheet.
- FRM-F-04: flow conditions bind bare identifiers — the automation engine
spreads the record's variables to top level
(`packages/services/service-automation/src/engine.ts`). The translation
table's first row implied the opposite universally.
- FRM-B-02 / B-01: the `node_modules/@objectstack/formula/` pointer named a
package that ships `dist` only, which this file already says is unreadable.
Its slot goes to `references/_index.md`, which every other domain package
links and this one orphaned.
- FRM-E-01: the predicate pattern block is now type-checked. Both previously
marked blocks were the cron and template quick references, so no "Mandatory
pattern" was checked at all.
- FRM-D-08: the no-date-arithmetic rule carried five prescriptions as prose.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…cron away (FRM-A-02 / A-01)
Four host skills end their description with "load objectstack-formula
alongside" (objectstack-data, -ui, -api, -automation); this one never said it
was that companion, so an author reading it cold had no way to know why it had
been loaded.
FRM-A-01: the description also said "Do not use for ... cron schedules" while
the body taught cron across four sections. The body now carries one
schema-pointing cron row, so the exclusion goes and the Skill Boundaries table
keeps the routing to objectstack-automation.
`skills/README.md` and `content/docs/ai/skills-reference.mdx` are the generator
output of `pnpm --filter @objectstack/spec gen:skill-docs` — both move, and
nothing in them is hand-edited.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ills-formula-optimization
# Conflicts:
#	content/docs/ai/skills-reference.mdx
#	skills/README.md
Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), re-run
after the merge so it derives from all 11 SKILL.md files at the merged tree
rather than at the pre-merge one. The whole diff is the FRM-A-02 description
edit; nothing here is hand-written.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…pointer (contract review round 1)
Two spans failed in-seat contract review; both were verified at source before
editing and both are paid in-file — the file lands back on 5,158 tokens exactly,
no growth.
FAIL 1 (FRM-F-01, the query-axis note). The three axes do not share one error
code. `where` and `searchableFields` answer `400 INVALID_FIELD`, but `orderBy`
answers `400 INVALID_SORT` — `assertOrderByIsMaterializable` sets
`err.code = 'INVALID_SORT'` at the engine seam
(`packages/objectql/src/engine.ts`), and `assertSortFieldsExist` does the same
at the ingress. An agent branching on the code would have branched wrong on the
sort refusal. Both codes are now named.
FAIL 2 (the cron/template pointer). The paragraph sent readers to
`shared/expression.zod.ts` for "the formatter whitelist and the cron alias
set", and that file carries neither. Worse, the sets used to live in the quick
references this flight deleted, so the pointer was the last mention of both —
and this same file correctly says `@objectstack/formula` ships `dist` only, so
"go read it" resolves to nothing. Now: the seven aliases are inlined in the cron
row from `packages/formula/src/cron-engine.ts`, the template row names
`TEMPLATE_FORMATTERS` (really exported from `@objectstack/formula`, derived
from the formatter table in `packages/formula/src/template-engine.ts`) as the
introspectable whitelist, and the `expression.zod.ts` pointer is narrowed to
the carrier lists it does declare.
Paid by cutting narration of the same class this flight exists to remove: the
`asc`/`desc` anecdote from the new note, and the Skill Boundaries cron
parenthetical now that the surfaces table names `Job.schedule.expression` and
the dialect.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 13:07
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 2f2a0b2Sep 2, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14316-skills-formula-optimization branch September 2, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens) - #14563

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization
Sep 2, 2026
Merged

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens)#14563
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14316

Member of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET. The audit record is on the card as the audit-record comment.

Transliteration key — the GitHub body sanitizer eats angle-bracket-shaped fragments, so this body spells them out: LT = opening angle bracket, GT = closing angle bracket, and a name in CAPS inside a path (record.FIELD, vars.STEP.KEY) stands for a placeholder the file writes in angle brackets.

Governed face — three of the changes below are contract-semantics claims, so this PR stays draft and carries needs:contract-review; the card carries it too.

Review round 1 — both FAILs fixed, paid in-file

In-seat contract review at d3a32664 returned FAIL on two spans, PASS on everything else. Both were re-verified at source before editing, both are fixed, and both are paid inside SKILL.md: the file lands back on 5,158 tokens exactly, the same figure it carried at review time. Nothing grew.

#what was wrongwhat it says nowverified at
1the query-axis note gave all three axes one code, 400 INVALID_FIELDwhere and searchableFields answer 400 INVALID_FIELD; orderBy answers 400 INVALID_SORTpackages/objectql/src/engine.tsassertOrderByIsMaterializable sets err.code = 'INVALID_SORT'; assertSortFieldsExist is the same code at the ingress. An agent branching on the code would have branched wrong on the sort refusal.
2the cron/template paragraph sent readers to shared/expression.zod.ts for "the formatter whitelist and the cron alias set"the seven aliases are inlined in the cron row; the template row names TEMPLATE_FORMATTERS, exported from @objectstack/formula, as the introspectable whitelist; the expression.zod.ts pointer is narrowed to the carrier lists it really declarespackages/formula/src/cron-engine.ts (@yearly @annually @monthly @weekly @daily @hourly @reboot); packages/formula/src/template-engine.ts exports TEMPLATE_FORMATTERS via packages/formula/src/index.ts. That file carried neither set, and the sets had lived in the quick references this flight deleted — so the pointer was the last mention of both, resolving to nothing.

Paid by cutting narration of the same class this flight exists to remove: the asc/desc anecdote from the new note, and the Skill Boundaries cron parenthetical now that the surfaces table names Job.schedule.expression and the dialect. Two new identifiers were added and both are live — check:skill-identifier-liveness Leg 1 went 476 → 477 citations and stayed OK.

Token delta

filebeforeafterceilingheadroom
skills/objectstack-formula/SKILL.md6,0025,1586,002844

Net −844 tokens (−14.1%), 551 → 374 lines. Convention is the ratchet's own: ceil(utf8 bytes / 4), so ceil($(wc -c < file) / 4) reproduces it. Ceiling untouched (FRM-I-01 re-lock is deferred). The generated references/_index.md (302 tok) is untouched.

Gap against the audit's −1,265, itemised per cluster — not smoothed

cluster (commit)audit est.measuredgapwhy
F-06 / A-01 / G-05 / B-04 / F-07−515−440+75the two collapsed rows keep their real carrier lists (4 cron carriers, 3 template carriers) so the last mention still points somewhere; F-07 is a small addition inside a deletion cluster
D-05 / D-04 / B-03−522−389+133all three are MERGE-INTO, not DELETE. Rules the audit's raw span estimate wrote off survive: the onError clause, "a condition that does not even compile aborts the same way", the ADR-0058 per-row statement
D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03−511−392+119B-06 and B-05 are merges: "Verify your work" absorbed the runtime-throw half of the ADR-0032 callout, and the three determinism conditions folded into the seed pattern's own note rather than vanishing
F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08+237+356+119the two contract notes have to name both refusal doors and both fault directions to be actionable; the type-checked block needs a real import
A-02+18+21+3
review round 10both fixes paid in-file

The gap is one thing four times: a MERGE-INTO finding cannot pay what a DELETE would. Where the audit measured a span's bytes, I measured what was left after the rule inside it was preserved. I did not re-wrap, pad, or cut anything the audit did not name to close the difference.

Per-item 落点 | before | after

Deletions

id落点beforeafter
FRM-F-06 / A-01### Cron surfaces, ### Template surfaces, ## Cron quick reference, ## Template quick referencefour sections, a formatter table and two code blocksone ### Cron and template surfaces table, one row each, carriers named, the seven cron aliases inlined and the formatter whitelist named. Both are live surfaces with 0 corpus usages, so neither loses its last mention; the frontmatter no longer says "Do not use for cron schedules" while the body teaches cron
FRM-D-05section 5 bulk-write prose165 tokens restating the before* table row, plus query-count and fetch-cost narrationone clause pointing back at that row; the ADR-0058 per-row semantics keep their sentence
FRM-D-04section 5 abort calloutthe pre-protocol-17 logger.warn history and its two opposite-failure examplesthe rule only: aborts on before* and after* alike, no onError escape, non-compiling conditions the same
FRM-B-06top-of-file ADR-0032 calloutADR-0032 stated 3×, and "Verify your work" cross-referenced the top-of-file notestated once, in "Verify your work", keeping both halves — build fails with a located did-you-mean, runtime throws
FRM-B-05## Determinism contracta section restating the seed pattern's own notefolded into that note
FRM-D-01 / B-07"Strategic context"why CEL beat the deleted Salesforce-flavor engine — the first content after the H1gone
FRM-D-07 / D-02Core contract tail"you do not learn three languages" + the roadmap for emitting astgone; the envelope rule both carried survives once
FRM-B-03section 5 previous totalitythe has()-on-a-declared-field rule stated once for record, again for previousone statement covering both, in the has() section
FRM-D-03 / G-03## Open questionstwo bullets citing CelExprSchemagone — the symbol has 0 hits in the repo outside this file
FRM-G-05CEL surfaces table, template notesa visibleOn / visibility deprecated-alias row, titleFormat noted twicealias row gone; titleFormat deduped to one carrier cell
FRM-B-02## See alsoa pointer at node_modules/@objectstack/formula/gone — packages/formula/package.json ships ["dist","README.md","CHANGELOG.md"], and this file already says so
FRM-D-09Core contracta type Expression block transcribing shared/expression.zod.tsone sentence and the pointer
FRM-D-08"No date arithmetic"157 tokens of prose carrying five prescriptionsa five-row table
FRM-B-04template surfaces"no js dialect" restatedone statement, in Core contract
FRM-G-01 / G-02 / G-04 / E-03throughoutobjectstack build 5×; 7.6 / M9.5 / M9.7 / M9.8; "single quotes (always)"; * 100.0os build; no milestone numbers; both quote styles; * 100

Additions (each paid by deletions in the same file)

id落点what it now teachessource
FRM-F-01after the CEL surfaces tablea formula field is virtual — no driver materialises a column, so all three query axes refuse one at both doors: where / searchableFields with 400 INVALID_FIELD, orderBy with 400 INVALID_SORT. Remedy is the stored column, in the same words the sort and search axes already usepackages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts; packages/objectql/src/filter-comparand-shape.ts; packages/objectql/src/engine.ts
FRM-F-03same placea form-view visibleWhen is CLIENT-SIDE only and faults open (true), so it is never access control — and where the opposite holds: Hook / SharingRulecondition and validation predicates abort the writepackages/spec/src/ui/view.zod.ts (FormFieldSchema / FormSectionSchemavisibleWhen); packages/metadata-core/src/form-predicate-root-policy.ts
FRM-F-02CEL syntax cheat-sheetthe two missing roots: parent (line-item cell readonlyWhen / requiredWhen) and data (metadata-editing forms, repeater rows included)packages/spec/src/data/field.zod.ts; BOUND_FORM_VIEW_PREDICATE_ROOTS
FRM-F-04translation table + its warningflow conditions bind bare identifiers — the engine spreads the record's variables to top level. The table's first row implied record. prefixing was universalpackages/services/service-automation/src/engine.ts — "bare identifiers like status / previous.status resolve — the natural authoring style for record-change start conditions"
FRM-A-02frontmatter descriptionthat this is the companion skill objectstack-data / -ui / -api / -automation each tell you to load alongside themthose four descriptions
FRM-B-01## See alsoa link to references/_index.md — formula was the only domain package that orphaned its own generated index (8 of 9 link theirs)
FRM-E-01Mandatory pattern 3the predicate block is now type-checked. Both previously marked blocks were the cron and template quick references, so no "Mandatory pattern" was checked at allsee the ablation below
FRM-F-07view-filter prohibitionnames the alternative it was withholding: date macro tokens, pointing at objectstack-query rules/filters.mdskills/objectstack-query/rules/filters.md

Anchor rulings honoured

This package is the CEL anchor; the automation flight (#14467) and the query flight (#14443) deleted their CEL restatements on that ruling. All three anchored constructs survive with their headings addressable:

  • ## ObjectStack CEL standard library — the 35-function table, untouched
  • ## Mechanical translation table (legacy → CEL) — including the OLD / NEW rows and the warning below it (the warning gained the flow-condition exception; nothing was removed)
  • ## Surfaces that take an Expression — the CEL surfaces table, minus the one deprecated alias row

The packages/formula pin tests both pass, quoted below.

Premise adjustments — no finding was forced

  • FRM-B-02, half true. The audit reads :548-551 as pointing at an unreadable package. That holds for the @objectstack/formula line. The second pointer, node_modules/@objectstack/spec/src/shared/expression.zod.ts, is readable in an installed apppackages/spec/package.json ships src/**/*.zod.ts. Kept, and the additions lean on it.
  • FRM-B-04, 2 instances not 3. The audit lists :81-83, :476-478 and :51. The first two restate "there is no js dialect" and one was deleted. :51 is the Skill Boundaries row routing L2 hook bodies to objectstack-data — a routing row that never states the claim. Realized 2 → 1.
  • FRM-D-08 is not ≈0. Measured −7 tokens as a table.
  • Everything else held at my base. skills/objectstack-formula/** is byte-identical between the audit ref a59f78d, the dispatch base 18d816a5 and my branch point 93940d49, so every skills/ span was valid unchanged; packages/** citations are re-cited above at the tree in this PR.

Follow-ups (⛔ deliberately not touched here)

Gates — head sha 291f7bd7

Re-derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsafter the round-1 edit and after merging origin/main: 36 commands, whole list run, list identical across all three derivations. Two derivations were refused as STALE and each was answered by merging origin/main rather than by reading the old copies — the first (33 commits behind, 148 family files changed) conflicted only in the two generated files, which were resolved to main's side, committed, and only then regenerated, never in MERGE state; the second (5 commits behind, changing .github/workflows/lint.yml and scripts/role-word-baseline.json, both of which the families read) merged cleanly. The @objectstack/spec + @objectstack/client-react closure was rebuilt after each merge — check:skill-examples and check:docs both refuse a stale dist and said so, by name, rather than answering falsely green.

35 / 36 green. The one non-zero is node scripts/check-test-completeness.mjsexit 3, which that script defines as a MISSING or UNREADABLE LOG — NOT MEASURED, not red. Exit codes were captured by redirecting each command to its own file before any pipe.

Card-named gates, quoting each gate's own verdict line:

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-formula/SKILL.md is 5158 tokens (ceiling 6002; headroom 844). and ✓ check-skills-token-ratchet: 37 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.
  • pnpm --filter @objectstack/spec check:skill-examples✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-identifier-livenesscheck-skill-identifier-liveness OK — Leg 1: 477 citation(s) over 47 published file(s) checked against 93135 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s). Leg 2 was checked before the first deletion: none of the 8 registered exhaustive sections is in this file.
  • pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync
  • packages/formula pin tests — pnpm --filter @objectstack/formula exec vitest run --maxWorkers=2 src/cel-stdlib-drift.test.ts src/skill-catalog-sync.test.tsTest Files 2 passed (2) / Tests 5 passed (5). The stdlib anchor is intact.
  • pnpm check:role-word — green, no ratchet-DOWN, so scripts/role-word-baseline.json is untouched.

Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14316. The pushed remote head equals the tree the gates read (291f7bd7, verified with git ls-remote).

FRM-E-01 ablation — the marker is not a phantom green

The new marker was added only after the gate passed with it, then ablated once. Mutation and restore were both proven on disk rather than by an editor's exit code:

  • HEAD blob 21ee6b50; a semantic-only mutation was injected (assigning the P tagged template's Expression result to number), leaving the block syntactically valid so the failure could only come from the semantic pass.
  • Mutation proven on disk: injected text grep -c = 1, anchor still 1, git hash-object = 79936c1f ≠ HEAD blob.
  • Gate on the mutated tree: exit 1, and it named the block — skills/objectstack-formula/SKILL.md:243:7 error TS2322: Type '{ dialect: ... }' is not assignable to type 'number'. The right file, the right line, my block.
  • Restore leg given the same treatment as the mutation leg: git checkout HEAD -- with an absolute path (never the bare form, which restores from a polluted index), inside a trap ... EXIT INT TERM using absolute paths. Proven by git hash-object = 21ee6b50 (equal to the HEAD blob, non-empty) andgit diff HEAD empty — not by the restore's exit code.
  • No rebuild was needed between legs: the gate reads the markdown directly, and the mutated artifact was that markdown, not a package dist.

Labels

skip-changeset — this PR releases nothing. Verified against the gate's own enumeration rather than assumed: scripts/check-empty-changeset.mjs carries a "GREEN 3: a skills/**-only PR carrying NO changeset (route 2)" case asserting exactly this shape must be green, and no packages/*/package.json ships skills/ in its files[]. Plus needs:contract-review, because FRM-F-01, F-03 and F-04 are contract-semantics claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…RM-F-06 / A-01 / G-05 / B-04 / F-07)
The frontmatter routes cron away ("Do not use for ... cron schedules") while the
body taught it across four sections; the corpus authors zero of it (`cron` 0,
`tmpl` 0, any formatter 0). Both are live surfaces, so each keeps ONE
schema-pointing row with its carriers; the two quick-reference sections and the
formatter table go.
- FRM-F-06 / A-01: `### Cron surfaces`, `### Template surfaces`, `## Cron quick
reference` and `## Template quick reference` collapse into one
`### Cron and template surfaces` table, two rows, pointing at
`shared/expression.zod.ts` for the full carrier list.
- FRM-G-05: the deprecated `visibleOn` / `visibility` alias row leaves the CEL
surfaces table; the two `Object.titleFormat` notes dedupe to one carrier cell.
- FRM-B-04: the third "no js dialect" restatement goes; the canonical one in
Core contract stays.
- FRM-F-07: the view-list-filter prohibition now names the alternative it was
withholding — date macro tokens, with the pointer to objectstack-query
`rules/filters.md`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…history (FRM-D-05 / D-04 / B-03)
Section 5 was 20.7% of the file (1,241 tok). The rules in it are load-bearing;
the narration around them was not.
- FRM-D-04: the pre-protocol-17 `logger.warn` history goes. Two rules were
buried in it and survive in one sentence: `before*` and `after*` abort alike
with no `onError` escape, and a condition that does not compile aborts the
same way.
- FRM-D-05: the `before*` exception restated the table row above it at 165
tokens — it is now one clause pointing back at that row. The per-row bulk
semantics keep their ADR-0058 statement; the query-count and fetch-cost
narration goes.
- FRM-B-03: the `has()`-on-a-declared-field rule was stated once for `record`
and again for `previous`. It is now one statement covering both, in the
`has()` section where the rule lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…RM-D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03)
- FRM-D-01 / B-07: "Strategic context" — why CEL was picked over the deleted
Salesforce-flavor engine — was the first content after the H1. An author
emitting a predicate does not need the engine-selection history.
- FRM-B-06: ADR-0032 was stated three times, and "Verify your work" cross-refs
the top-of-file note that carried it. One statement now, in "Verify your
work", and it keeps both halves the callout had: build fails with a located
did-you-mean, and the runtime throws.
- FRM-D-09: the `type Expression` block transcribed `shared/expression.zod.ts`.
One sentence and the pointer replace it.
- FRM-D-07 / D-02: "you do not learn three languages" and the roadmap for
emitting `ast` go; the envelope rule they both carried survives once.
The auto-wrap fact moved to the cron/template row in the previous commit.
- FRM-B-05: "Determinism contract" restated the seed pattern's own note. The
three numbered conditions fold into that note.
- FRM-D-03 / G-03: "Open questions" cited `CelExprSchema` twice; the symbol
exists nowhere in the repo (0 hits outside this file).
- FRM-G-01: the CLI is `os`, not `objectstack` — 5 mentions, now 0.
- FRM-G-02: the frontmatter pins 17.x; the retired milestone numbers are gone.
- FRM-G-04: a CEL string literal takes either quote; the corpus writes double
quotes inside P` ` more than ten times, so "(always)" was false.
- FRM-E-03: `* 100.0` was a cel-js workaround. `registerNumericCoercions`
(`packages/formula/src/stdlib.ts`) registers the mixed `double op int` /
`int op double` overloads, so `* 100` is correct now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…FRM-F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08)
The corpus measurement behind these: `type: 'formula'` fields have zero live
usages and the only hits are a removal test; flow/trigger conditions are
authored five times and the scope was taught wrong; field conditional rules are
the second-commonest task and two of their roots were missing.
- FRM-F-01: a `formula` field is virtual — `where` / `orderBy` /
`searchableFields` on one are refused `400 INVALID_FIELD` at both doors
(`packages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts`;
`packages/objectql/src/filter-comparand-shape.ts`). The filter and sort axes
were taught nowhere in the catalog. Remedy is the stored column, in the same
words the sort and search axes already use.
- FRM-F-03: a form-view `visibleWhen` is client-side only and faults OPEN
(`packages/spec/src/ui/view.zod.ts` `FormFieldSchema` / `FormSectionSchema`;
`packages/metadata-core/src/form-predicate-root-policy.ts`). The package
taught fault-closed globally, so the note says where each holds.
- FRM-F-02: the `parent` root (line-item cell `readonlyWhen` / `requiredWhen`,
`packages/spec/src/data/field.zod.ts`) and the `data` root (metadata-editing
forms, `BOUND_FORM_VIEW_PREDICATE_ROOTS`) join the cheat-sheet.
- FRM-F-04: flow conditions bind bare identifiers — the automation engine
spreads the record's variables to top level
(`packages/services/service-automation/src/engine.ts`). The translation
table's first row implied the opposite universally.
- FRM-B-02 / B-01: the `node_modules/@objectstack/formula/` pointer named a
package that ships `dist` only, which this file already says is unreadable.
Its slot goes to `references/_index.md`, which every other domain package
links and this one orphaned.
- FRM-E-01: the predicate pattern block is now type-checked. Both previously
marked blocks were the cron and template quick references, so no "Mandatory
pattern" was checked at all.
- FRM-D-08: the no-date-arithmetic rule carried five prescriptions as prose.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…cron away (FRM-A-02 / A-01)
Four host skills end their description with "load objectstack-formula
alongside" (objectstack-data, -ui, -api, -automation); this one never said it
was that companion, so an author reading it cold had no way to know why it had
been loaded.
FRM-A-01: the description also said "Do not use for ... cron schedules" while
the body taught cron across four sections. The body now carries one
schema-pointing cron row, so the exclusion goes and the Skill Boundaries table
keeps the routing to objectstack-automation.
`skills/README.md` and `content/docs/ai/skills-reference.mdx` are the generator
output of `pnpm --filter @objectstack/spec gen:skill-docs` — both move, and
nothing in them is hand-edited.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ills-formula-optimization
# Conflicts:
#	content/docs/ai/skills-reference.mdx
#	skills/README.md
Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), re-run
after the merge so it derives from all 11 SKILL.md files at the merged tree
rather than at the pre-merge one. The whole diff is the FRM-A-02 description
edit; nothing here is hand-written.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…pointer (contract review round 1)
Two spans failed in-seat contract review; both were verified at source before
editing and both are paid in-file — the file lands back on 5,158 tokens exactly,
no growth.
FAIL 1 (FRM-F-01, the query-axis note). The three axes do not share one error
code. `where` and `searchableFields` answer `400 INVALID_FIELD`, but `orderBy`
answers `400 INVALID_SORT` — `assertOrderByIsMaterializable` sets
`err.code = 'INVALID_SORT'` at the engine seam
(`packages/objectql/src/engine.ts`), and `assertSortFieldsExist` does the same
at the ingress. An agent branching on the code would have branched wrong on the
sort refusal. Both codes are now named.
FAIL 2 (the cron/template pointer). The paragraph sent readers to
`shared/expression.zod.ts` for "the formatter whitelist and the cron alias
set", and that file carries neither. Worse, the sets used to live in the quick
references this flight deleted, so the pointer was the last mention of both —
and this same file correctly says `@objectstack/formula` ships `dist` only, so
"go read it" resolves to nothing. Now: the seven aliases are inlined in the cron
row from `packages/formula/src/cron-engine.ts`, the template row names
`TEMPLATE_FORMATTERS` (really exported from `@objectstack/formula`, derived
from the formatter table in `packages/formula/src/template-engine.ts`) as the
introspectable whitelist, and the `expression.zod.ts` pointer is narrowed to
the carrier lists it does declare.
Paid by cutting narration of the same class this flight exists to remove: the
`asc`/`desc` anecdote from the new note, and the Skill Boundaries cron
parenthetical now that the surfaces table names `Job.schedule.expression` and
the dialect.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 13:07
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 2f2a0b2Sep 2, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14316-skills-formula-optimization branch September 2, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens) - #14563

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization
Sep 2, 2026
Merged

skills(formula): optimization flight — cut the cron/template quickrefs and section-5 narration, teach virtual formula fields and fault-open form predicates (net −844 tokens)#14563
os-zhuang merged 9 commits into
mainfrom
claude/issue-14316-skills-formula-optimization

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14316

Member of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET. The audit record is on the card as the audit-record comment.

Transliteration key — the GitHub body sanitizer eats angle-bracket-shaped fragments, so this body spells them out: LT = opening angle bracket, GT = closing angle bracket, and a name in CAPS inside a path (record.FIELD, vars.STEP.KEY) stands for a placeholder the file writes in angle brackets.

Governed face — three of the changes below are contract-semantics claims, so this PR stays draft and carries needs:contract-review; the card carries it too.

Review round 1 — both FAILs fixed, paid in-file

In-seat contract review at d3a32664 returned FAIL on two spans, PASS on everything else. Both were re-verified at source before editing, both are fixed, and both are paid inside SKILL.md: the file lands back on 5,158 tokens exactly, the same figure it carried at review time. Nothing grew.

#what was wrongwhat it says nowverified at
1the query-axis note gave all three axes one code, 400 INVALID_FIELDwhere and searchableFields answer 400 INVALID_FIELD; orderBy answers 400 INVALID_SORTpackages/objectql/src/engine.tsassertOrderByIsMaterializable sets err.code = 'INVALID_SORT'; assertSortFieldsExist is the same code at the ingress. An agent branching on the code would have branched wrong on the sort refusal.
2the cron/template paragraph sent readers to shared/expression.zod.ts for "the formatter whitelist and the cron alias set"the seven aliases are inlined in the cron row; the template row names TEMPLATE_FORMATTERS, exported from @objectstack/formula, as the introspectable whitelist; the expression.zod.ts pointer is narrowed to the carrier lists it really declarespackages/formula/src/cron-engine.ts (@yearly @annually @monthly @weekly @daily @hourly @reboot); packages/formula/src/template-engine.ts exports TEMPLATE_FORMATTERS via packages/formula/src/index.ts. That file carried neither set, and the sets had lived in the quick references this flight deleted — so the pointer was the last mention of both, resolving to nothing.

Paid by cutting narration of the same class this flight exists to remove: the asc/desc anecdote from the new note, and the Skill Boundaries cron parenthetical now that the surfaces table names Job.schedule.expression and the dialect. Two new identifiers were added and both are live — check:skill-identifier-liveness Leg 1 went 476 → 477 citations and stayed OK.

Token delta

filebeforeafterceilingheadroom
skills/objectstack-formula/SKILL.md6,0025,1586,002844

Net −844 tokens (−14.1%), 551 → 374 lines. Convention is the ratchet's own: ceil(utf8 bytes / 4), so ceil($(wc -c < file) / 4) reproduces it. Ceiling untouched (FRM-I-01 re-lock is deferred). The generated references/_index.md (302 tok) is untouched.

Gap against the audit's −1,265, itemised per cluster — not smoothed

cluster (commit)audit est.measuredgapwhy
F-06 / A-01 / G-05 / B-04 / F-07−515−440+75the two collapsed rows keep their real carrier lists (4 cron carriers, 3 template carriers) so the last mention still points somewhere; F-07 is a small addition inside a deletion cluster
D-05 / D-04 / B-03−522−389+133all three are MERGE-INTO, not DELETE. Rules the audit's raw span estimate wrote off survive: the onError clause, "a condition that does not even compile aborts the same way", the ADR-0058 per-row statement
D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03−511−392+119B-06 and B-05 are merges: "Verify your work" absorbed the runtime-throw half of the ADR-0032 callout, and the three determinism conditions folded into the seed pattern's own note rather than vanishing
F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08+237+356+119the two contract notes have to name both refusal doors and both fault directions to be actionable; the type-checked block needs a real import
A-02+18+21+3
review round 10both fixes paid in-file

The gap is one thing four times: a MERGE-INTO finding cannot pay what a DELETE would. Where the audit measured a span's bytes, I measured what was left after the rule inside it was preserved. I did not re-wrap, pad, or cut anything the audit did not name to close the difference.

Per-item 落点 | before | after

Deletions

id落点beforeafter
FRM-F-06 / A-01### Cron surfaces, ### Template surfaces, ## Cron quick reference, ## Template quick referencefour sections, a formatter table and two code blocksone ### Cron and template surfaces table, one row each, carriers named, the seven cron aliases inlined and the formatter whitelist named. Both are live surfaces with 0 corpus usages, so neither loses its last mention; the frontmatter no longer says "Do not use for cron schedules" while the body teaches cron
FRM-D-05section 5 bulk-write prose165 tokens restating the before* table row, plus query-count and fetch-cost narrationone clause pointing back at that row; the ADR-0058 per-row semantics keep their sentence
FRM-D-04section 5 abort calloutthe pre-protocol-17 logger.warn history and its two opposite-failure examplesthe rule only: aborts on before* and after* alike, no onError escape, non-compiling conditions the same
FRM-B-06top-of-file ADR-0032 calloutADR-0032 stated 3×, and "Verify your work" cross-referenced the top-of-file notestated once, in "Verify your work", keeping both halves — build fails with a located did-you-mean, runtime throws
FRM-B-05## Determinism contracta section restating the seed pattern's own notefolded into that note
FRM-D-01 / B-07"Strategic context"why CEL beat the deleted Salesforce-flavor engine — the first content after the H1gone
FRM-D-07 / D-02Core contract tail"you do not learn three languages" + the roadmap for emitting astgone; the envelope rule both carried survives once
FRM-B-03section 5 previous totalitythe has()-on-a-declared-field rule stated once for record, again for previousone statement covering both, in the has() section
FRM-D-03 / G-03## Open questionstwo bullets citing CelExprSchemagone — the symbol has 0 hits in the repo outside this file
FRM-G-05CEL surfaces table, template notesa visibleOn / visibility deprecated-alias row, titleFormat noted twicealias row gone; titleFormat deduped to one carrier cell
FRM-B-02## See alsoa pointer at node_modules/@objectstack/formula/gone — packages/formula/package.json ships ["dist","README.md","CHANGELOG.md"], and this file already says so
FRM-D-09Core contracta type Expression block transcribing shared/expression.zod.tsone sentence and the pointer
FRM-D-08"No date arithmetic"157 tokens of prose carrying five prescriptionsa five-row table
FRM-B-04template surfaces"no js dialect" restatedone statement, in Core contract
FRM-G-01 / G-02 / G-04 / E-03throughoutobjectstack build 5×; 7.6 / M9.5 / M9.7 / M9.8; "single quotes (always)"; * 100.0os build; no milestone numbers; both quote styles; * 100

Additions (each paid by deletions in the same file)

id落点what it now teachessource
FRM-F-01after the CEL surfaces tablea formula field is virtual — no driver materialises a column, so all three query axes refuse one at both doors: where / searchableFields with 400 INVALID_FIELD, orderBy with 400 INVALID_SORT. Remedy is the stored column, in the same words the sort and search axes already usepackages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts; packages/objectql/src/filter-comparand-shape.ts; packages/objectql/src/engine.ts
FRM-F-03same placea form-view visibleWhen is CLIENT-SIDE only and faults open (true), so it is never access control — and where the opposite holds: Hook / SharingRulecondition and validation predicates abort the writepackages/spec/src/ui/view.zod.ts (FormFieldSchema / FormSectionSchemavisibleWhen); packages/metadata-core/src/form-predicate-root-policy.ts
FRM-F-02CEL syntax cheat-sheetthe two missing roots: parent (line-item cell readonlyWhen / requiredWhen) and data (metadata-editing forms, repeater rows included)packages/spec/src/data/field.zod.ts; BOUND_FORM_VIEW_PREDICATE_ROOTS
FRM-F-04translation table + its warningflow conditions bind bare identifiers — the engine spreads the record's variables to top level. The table's first row implied record. prefixing was universalpackages/services/service-automation/src/engine.ts — "bare identifiers like status / previous.status resolve — the natural authoring style for record-change start conditions"
FRM-A-02frontmatter descriptionthat this is the companion skill objectstack-data / -ui / -api / -automation each tell you to load alongside themthose four descriptions
FRM-B-01## See alsoa link to references/_index.md — formula was the only domain package that orphaned its own generated index (8 of 9 link theirs)
FRM-E-01Mandatory pattern 3the predicate block is now type-checked. Both previously marked blocks were the cron and template quick references, so no "Mandatory pattern" was checked at allsee the ablation below
FRM-F-07view-filter prohibitionnames the alternative it was withholding: date macro tokens, pointing at objectstack-query rules/filters.mdskills/objectstack-query/rules/filters.md

Anchor rulings honoured

This package is the CEL anchor; the automation flight (#14467) and the query flight (#14443) deleted their CEL restatements on that ruling. All three anchored constructs survive with their headings addressable:

  • ## ObjectStack CEL standard library — the 35-function table, untouched
  • ## Mechanical translation table (legacy → CEL) — including the OLD / NEW rows and the warning below it (the warning gained the flow-condition exception; nothing was removed)
  • ## Surfaces that take an Expression — the CEL surfaces table, minus the one deprecated alias row

The packages/formula pin tests both pass, quoted below.

Premise adjustments — no finding was forced

  • FRM-B-02, half true. The audit reads :548-551 as pointing at an unreadable package. That holds for the @objectstack/formula line. The second pointer, node_modules/@objectstack/spec/src/shared/expression.zod.ts, is readable in an installed apppackages/spec/package.json ships src/**/*.zod.ts. Kept, and the additions lean on it.
  • FRM-B-04, 2 instances not 3. The audit lists :81-83, :476-478 and :51. The first two restate "there is no js dialect" and one was deleted. :51 is the Skill Boundaries row routing L2 hook bodies to objectstack-data — a routing row that never states the claim. Realized 2 → 1.
  • FRM-D-08 is not ≈0. Measured −7 tokens as a table.
  • Everything else held at my base. skills/objectstack-formula/** is byte-identical between the audit ref a59f78d, the dispatch base 18d816a5 and my branch point 93940d49, so every skills/ span was valid unchanged; packages/** citations are re-cited above at the tree in this PR.

Follow-ups (⛔ deliberately not touched here)

Gates — head sha 291f7bd7

Re-derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsafter the round-1 edit and after merging origin/main: 36 commands, whole list run, list identical across all three derivations. Two derivations were refused as STALE and each was answered by merging origin/main rather than by reading the old copies — the first (33 commits behind, 148 family files changed) conflicted only in the two generated files, which were resolved to main's side, committed, and only then regenerated, never in MERGE state; the second (5 commits behind, changing .github/workflows/lint.yml and scripts/role-word-baseline.json, both of which the families read) merged cleanly. The @objectstack/spec + @objectstack/client-react closure was rebuilt after each merge — check:skill-examples and check:docs both refuse a stale dist and said so, by name, rather than answering falsely green.

35 / 36 green. The one non-zero is node scripts/check-test-completeness.mjsexit 3, which that script defines as a MISSING or UNREADABLE LOG — NOT MEASURED, not red. Exit codes were captured by redirecting each command to its own file before any pipe.

Card-named gates, quoting each gate's own verdict line:

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-formula/SKILL.md is 5158 tokens (ceiling 6002; headroom 844). and ✓ check-skills-token-ratchet: 37 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.
  • pnpm --filter @objectstack/spec check:skill-examples✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-identifier-livenesscheck-skill-identifier-liveness OK — Leg 1: 477 citation(s) over 47 published file(s) checked against 93135 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s). Leg 2 was checked before the first deletion: none of the 8 registered exhaustive sections is in this file.
  • pnpm --filter @objectstack/spec check:skill-docs✅ Skill docs in sync
  • packages/formula pin tests — pnpm --filter @objectstack/formula exec vitest run --maxWorkers=2 src/cel-stdlib-drift.test.ts src/skill-catalog-sync.test.tsTest Files 2 passed (2) / Tests 5 passed (5). The stdlib anchor is intact.
  • pnpm check:role-word — green, no ratchet-DOWN, so scripts/role-word-baseline.json is untouched.

Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14316. The pushed remote head equals the tree the gates read (291f7bd7, verified with git ls-remote).

FRM-E-01 ablation — the marker is not a phantom green

The new marker was added only after the gate passed with it, then ablated once. Mutation and restore were both proven on disk rather than by an editor's exit code:

  • HEAD blob 21ee6b50; a semantic-only mutation was injected (assigning the P tagged template's Expression result to number), leaving the block syntactically valid so the failure could only come from the semantic pass.
  • Mutation proven on disk: injected text grep -c = 1, anchor still 1, git hash-object = 79936c1f ≠ HEAD blob.
  • Gate on the mutated tree: exit 1, and it named the block — skills/objectstack-formula/SKILL.md:243:7 error TS2322: Type '{ dialect: ... }' is not assignable to type 'number'. The right file, the right line, my block.
  • Restore leg given the same treatment as the mutation leg: git checkout HEAD -- with an absolute path (never the bare form, which restores from a polluted index), inside a trap ... EXIT INT TERM using absolute paths. Proven by git hash-object = 21ee6b50 (equal to the HEAD blob, non-empty) andgit diff HEAD empty — not by the restore's exit code.
  • No rebuild was needed between legs: the gate reads the markdown directly, and the mutated artifact was that markdown, not a package dist.

Labels

skip-changeset — this PR releases nothing. Verified against the gate's own enumeration rather than assumed: scripts/check-empty-changeset.mjs carries a "GREEN 3: a skills/**-only PR carrying NO changeset (route 2)" case asserting exactly this shape must be green, and no packages/*/package.json ships skills/ in its files[]. Plus needs:contract-review, because FRM-F-01, F-03 and F-04 are contract-semantics claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…RM-F-06 / A-01 / G-05 / B-04 / F-07)
The frontmatter routes cron away ("Do not use for ... cron schedules") while the
body taught it across four sections; the corpus authors zero of it (`cron` 0,
`tmpl` 0, any formatter 0). Both are live surfaces, so each keeps ONE
schema-pointing row with its carriers; the two quick-reference sections and the
formatter table go.
- FRM-F-06 / A-01: `### Cron surfaces`, `### Template surfaces`, `## Cron quick
reference` and `## Template quick reference` collapse into one
`### Cron and template surfaces` table, two rows, pointing at
`shared/expression.zod.ts` for the full carrier list.
- FRM-G-05: the deprecated `visibleOn` / `visibility` alias row leaves the CEL
surfaces table; the two `Object.titleFormat` notes dedupe to one carrier cell.
- FRM-B-04: the third "no js dialect" restatement goes; the canonical one in
Core contract stays.
- FRM-F-07: the view-list-filter prohibition now names the alternative it was
withholding — date macro tokens, with the pointer to objectstack-query
`rules/filters.md`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…history (FRM-D-05 / D-04 / B-03)
Section 5 was 20.7% of the file (1,241 tok). The rules in it are load-bearing;
the narration around them was not.
- FRM-D-04: the pre-protocol-17 `logger.warn` history goes. Two rules were
buried in it and survive in one sentence: `before*` and `after*` abort alike
with no `onError` escape, and a condition that does not compile aborts the
same way.
- FRM-D-05: the `before*` exception restated the table row above it at 165
tokens — it is now one clause pointing back at that row. The per-row bulk
semantics keep their ADR-0058 statement; the query-count and fetch-cost
narration goes.
- FRM-B-03: the `has()`-on-a-declared-field rule was stated once for `record`
and again for `previous`. It is now one statement covering both, in the
`has()` section where the rule lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…RM-D-01 / B-07 / B-06 / D-09 / D-07 / D-02 / B-05 / D-03 / G-03 / G-01 / G-02 / G-04 / E-03)
- FRM-D-01 / B-07: "Strategic context" — why CEL was picked over the deleted
Salesforce-flavor engine — was the first content after the H1. An author
emitting a predicate does not need the engine-selection history.
- FRM-B-06: ADR-0032 was stated three times, and "Verify your work" cross-refs
the top-of-file note that carried it. One statement now, in "Verify your
work", and it keeps both halves the callout had: build fails with a located
did-you-mean, and the runtime throws.
- FRM-D-09: the `type Expression` block transcribed `shared/expression.zod.ts`.
One sentence and the pointer replace it.
- FRM-D-07 / D-02: "you do not learn three languages" and the roadmap for
emitting `ast` go; the envelope rule they both carried survives once.
The auto-wrap fact moved to the cron/template row in the previous commit.
- FRM-B-05: "Determinism contract" restated the seed pattern's own note. The
three numbered conditions fold into that note.
- FRM-D-03 / G-03: "Open questions" cited `CelExprSchema` twice; the symbol
exists nowhere in the repo (0 hits outside this file).
- FRM-G-01: the CLI is `os`, not `objectstack` — 5 mentions, now 0.
- FRM-G-02: the frontmatter pins 17.x; the retired milestone numbers are gone.
- FRM-G-04: a CEL string literal takes either quote; the corpus writes double
quotes inside P` ` more than ten times, so "(always)" was false.
- FRM-E-03: `* 100.0` was a cel-js workaround. `registerNumericCoercions`
(`packages/formula/src/stdlib.ts`) registers the mixed `double op int` /
`int op double` overloads, so `* 100` is correct now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…FRM-F-01 / F-03 / F-02 / F-04 / B-01 / B-02 / E-01 / D-08)
The corpus measurement behind these: `type: 'formula'` fields have zero live
usages and the only hits are a removal test; flow/trigger conditions are
authored five times and the scope was taught wrong; field conditional rules are
the second-commonest task and two of their roots were missing.
- FRM-F-01: a `formula` field is virtual — `where` / `orderBy` /
`searchableFields` on one are refused `400 INVALID_FIELD` at both doors
(`packages/spec/src/migrations/entries/semantic/17.engine-find-formula-filter-refused.ts`;
`packages/objectql/src/filter-comparand-shape.ts`). The filter and sort axes
were taught nowhere in the catalog. Remedy is the stored column, in the same
words the sort and search axes already use.
- FRM-F-03: a form-view `visibleWhen` is client-side only and faults OPEN
(`packages/spec/src/ui/view.zod.ts` `FormFieldSchema` / `FormSectionSchema`;
`packages/metadata-core/src/form-predicate-root-policy.ts`). The package
taught fault-closed globally, so the note says where each holds.
- FRM-F-02: the `parent` root (line-item cell `readonlyWhen` / `requiredWhen`,
`packages/spec/src/data/field.zod.ts`) and the `data` root (metadata-editing
forms, `BOUND_FORM_VIEW_PREDICATE_ROOTS`) join the cheat-sheet.
- FRM-F-04: flow conditions bind bare identifiers — the automation engine
spreads the record's variables to top level
(`packages/services/service-automation/src/engine.ts`). The translation
table's first row implied the opposite universally.
- FRM-B-02 / B-01: the `node_modules/@objectstack/formula/` pointer named a
package that ships `dist` only, which this file already says is unreadable.
Its slot goes to `references/_index.md`, which every other domain package
links and this one orphaned.
- FRM-E-01: the predicate pattern block is now type-checked. Both previously
marked blocks were the cron and template quick references, so no "Mandatory
pattern" was checked at all.
- FRM-D-08: the no-date-arithmetic rule carried five prescriptions as prose.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…cron away (FRM-A-02 / A-01)
Four host skills end their description with "load objectstack-formula
alongside" (objectstack-data, -ui, -api, -automation); this one never said it
was that companion, so an author reading it cold had no way to know why it had
been loaded.
FRM-A-01: the description also said "Do not use for ... cron schedules" while
the body taught cron across four sections. The body now carries one
schema-pointing cron row, so the exclusion goes and the Skill Boundaries table
keeps the routing to objectstack-automation.
`skills/README.md` and `content/docs/ai/skills-reference.mdx` are the generator
output of `pnpm --filter @objectstack/spec gen:skill-docs` — both move, and
nothing in them is hand-edited.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ills-formula-optimization
# Conflicts:
#	content/docs/ai/skills-reference.mdx
#	skills/README.md
Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), re-run
after the merge so it derives from all 11 SKILL.md files at the merged tree
rather than at the pre-merge one. The whole diff is the FRM-A-02 description
edit; nothing here is hand-written.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…pointer (contract review round 1)
Two spans failed in-seat contract review; both were verified at source before
editing and both are paid in-file — the file lands back on 5,158 tokens exactly,
no growth.
FAIL 1 (FRM-F-01, the query-axis note). The three axes do not share one error
code. `where` and `searchableFields` answer `400 INVALID_FIELD`, but `orderBy`
answers `400 INVALID_SORT` — `assertOrderByIsMaterializable` sets
`err.code = 'INVALID_SORT'` at the engine seam
(`packages/objectql/src/engine.ts`), and `assertSortFieldsExist` does the same
at the ingress. An agent branching on the code would have branched wrong on the
sort refusal. Both codes are now named.
FAIL 2 (the cron/template pointer). The paragraph sent readers to
`shared/expression.zod.ts` for "the formatter whitelist and the cron alias
set", and that file carries neither. Worse, the sets used to live in the quick
references this flight deleted, so the pointer was the last mention of both —
and this same file correctly says `@objectstack/formula` ships `dist` only, so
"go read it" resolves to nothing. Now: the seven aliases are inlined in the cron
row from `packages/formula/src/cron-engine.ts`, the template row names
`TEMPLATE_FORMATTERS` (really exported from `@objectstack/formula`, derived
from the formatter table in `packages/formula/src/template-engine.ts`) as the
introspectable whitelist, and the `expression.zod.ts` pointer is narrowed to
the carrier lists it does declare.
Paid by cutting narration of the same class this flight exists to remove: the
`asc`/`desc` anecdote from the new note, and the Skill Boundaries cron
parenthetical now that the surfaces table names `Job.schedule.expression` and
the dialect.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 13:07
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 2f2a0b2Sep 2, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14316-skills-formula-optimization branch September 2, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude