skills(automation): optimization flight — the authored control-flow trio taught and the BPMN trio demoted, notify given its fence, the eval deduplicated, hooks and ETL pointed away (net −1,278 tokens) - #14467
Merged
os-zhuang merged 3 commits intoSep 2, 2026
Merged
Conversation
The eval restated SKILL.md's "Send-back for revision (ADR-0044)" section rather than testing beyond it: the canonical shape, the four lint findings, the wait-vs-approval_revise rationale and the showcase pointer all had a second copy here. 2,204 tokens -- 15% of the authored package -- went to a surface with one real authoring in the whole corpus, while `notify` (20 authorings) got 15. Delete the Expected-Output fence and the Common-Mistakes rows that restate the skill; keep Scenario + Validation Criteria, which is what a grader needs. The one row that did NOT restate SKILL.md (a "revise mode" re-suspend of the approval node) survives as criterion 7, so no graded fact is lost. 1,329 -> 550 tokens (ceiling 1,329). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…BPMN one
The package taught only `parallel_gateway` / `join_gateway` / `boundary_event`
-- 0 authorings anywhere in the corpus -- and never mentioned the ADR-0031
structured constructs the corpus actually uses (`loop` 3, `try_catch` 2,
`parallel` 2). `notify`, the most-used node type at 20 authorings, had one table
cell and no config keys, including no mention of its documented silent no-op.
ADD (funded, each claim verified at source):
AUTO-F-01 `parallel` / `try_catch` / `loop`-container rows; the gateway trio
marked BPMN-interop lowering, not author-facing.
AUTO-F-02 capability -> surface table, adding `approvals` and `messaging`.
AUTO-E-04 `notify` config fence + the messaging-absent silent success.
ported flow-filter precedence + the static-checkability split (this
package is the anchor; the query flight deleted its copy).
AUTO-G-02 `autolaunched` + a `record-*` binding behaves like `record_change`.
AUTO-E-01 os:check marker on the schedule-flow example (265 -> 266 blocks).
AUTO-A-02/A-03 `jobs` / `webhooks` collections and screen-flow routing in the
description.
DELETE / MERGE: AUTO-A-01 (ETL, retired at spec 17), AUTO-B-03, AUTO-B-06,
AUTO-B-07, AUTO-C-01, AUTO-C-02, AUTO-C-03, AUTO-C-04, AUTO-D-01..D-09,
AUTO-E-02. REORDER (free): AUTO-B-01, AUTO-B-02.
12,768 -> 12,269 tokens (ceiling 12,768; every addition paid in this file).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Generator output only -- `pnpm --filter @objectstack/spec gen:skill-docs`. `check:skill-docs` is a drift gate, so the AUTO-A-01/A-02/A-03 description edit forces both files. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
This was referenced Sep 2, 2026
os-zhuang
approved these changes
Sep 2, 2026
os-zhuang
marked this pull request as ready for review
September 2, 2026 11:24
os-zhuang
enabled auto-merge
September 2, 2026 11:24
os-zhuang
deleted the
claude/issue-14308-skills-automation-optimization
branch
September 2, 2026 12:23
os-litant
pushed a commit
that referenced
this pull request
Sep 2, 2026
… row #14296 item 2 = A (comment 5507419465): the planned-eval stubs are deleted and their ceilings step down; real fixtures stay. This is round 2 of #14308 — round 1 (PR #14467, merged) implemented every finding in skills/objectstack-automation/SKILL.md and deferred AUTO-B-04, the evals/README.md planned-structure stub, to this ruling. Deletes skills/objectstack-automation/evals/README.md (414 tokens — the template listing planned eval files that do not exist) and drops its one ceiling row from scripts/check-skills-token-ratchet.mjs. The real fixture evals/approvals/test-revise-loop.md and its ratchet row are untouched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #14308
Skills optimization flight for
skills/objectstack-automation, implementing the audit record posted on that card (25 findings, read-only audit ata59f78d). Shrink-only under the token ratchet: every addition is paid by deletions in the same file, no ceiling was raised, no file added or deleted, andscripts/check-skills-token-ratchet.mjswas not touched.Head sha for every gate reading below:
2926abc9d518b61220ba9dd2e288607cdef43247.Per-file token delta
skills/objectstack-automation/SKILL.mdskills/objectstack-automation/evals/approvals/test-revise-loop.mdLines, the primary reading for a
skills/**diff:SKILL.md1,001 → 949 (−52); the eval 81 → 37 (−44). Whole published bundle, all 11SKILL.mdfiles: 10,183 → 10,131 lines, 114,923 → 114,424 tokens (−499).evals/README.md(414) and the generatedreferences/_index.md(835) are untouched.skills/README.mdandcontent/docs/ai/skills-reference.mdxare generator output only —pnpm --filter @objectstack/spec gen:skill-docs, forced by the description edit; their diff is the two description lines and nothing else.Per-item — 落点 | before | after
Byte deltas are exact per-edit measurements; token figures are
ceil(bytes/4), the ratchet's own convention. Composite rows are marked.The two falsehoods
:22-25+ When-to-Use:35packages/spec/src/migrations/entries/semantic/17.etl-pipeline-layer-retired.ts:7-20) and the package declares 17.x.grep -n ETL SKILL.mdis now 0.:76-79, BP:791, pitfall:828boundary_eventnodes" — a form with 0 authoringsexamples/app-showcase/src/coverage.ts:299-300); the advice is gone and the trio now has exactly one row, marking it BPMN-interop lowering (never deleted the last mention, per the ruling)Funded additions — every claim verified at source
#### Control Flowtableparallel/try_catchabsent;loop= one clauseloop(config.body,iteratorVariabledefaultitem,indexVariable,maxIterations),parallel(config.branches[], ≥ 2, implicit join),try_catch(config.try/catch,errorVariabledefault$error,config.retry, nofinally); the trio collapsed into one "not author-facing" rowpackages/spec/src/automation/control-flow.zod.ts:41-46(the three type ids vs the "author-invisible interchange representations"),:163-219LoopConfigSchema,:257-268ParallelConfigSchema(.min(2)),:301-320TryCatchConfigSchemaincl. thefinallyguidance string### Prerequisiteautomation/triggers/job/queueapprovalsandmessaging, each with what its absence doespackages/spec/src/kernel/platform-capabilities.ts:31-66(all 7 tokens are canonical),examples/app-showcase/objectstack.config.ts:92-107(the inline rationale forapprovals/messaging),packages/services/service-automation/src/builtin/notify-node.ts:313-325:97, the whole coverage ofnotify### notifysection with the 8-key fence, plus the RAW-vs-interpolated split marked inlinepackages/spec/src/automation/io-node-config.zod.ts:178-258— re-located by content:NotifyConfigSchemaspans 178-258 on this base, not the audit's:179-218.severityis a closedz.enum(['info','warning','critical'])at:242; the interpolate/RAW split is the module note at:160-168; thesourceObject/sourceIdpair-or-dropped rule at:169-172notifyreturns success withoutput: { delivered: 0, failed: 0, skipped: true }andmetrics.acted: 0when no messaging service is registerednotify-node.ts:313-325verbatimrecord_changerowautolaunched+ arecord-*start binding behaves identically;record_changeadditionally opts into the trigger-readiness lintpackages/services/service-automation/src/engine.tsresolveTriggerBinding;packages/lint/src/validate-flow-trigger-readiness.tskeys onrecord_changeos:checkmarkerimport { defineFlow },status: 'active') — the gate went 265 → 266 blockspackages/spec/scripts/check-skill-examples.ts:18-23jobs(defineJob) /webhooks(defineWebhook) stack collections and the screen-flow / wizard route objectstack-ui points herepackages/spec/src/system/job.zod.ts:170,packages/spec/src/automation/webhook.zod.ts:245,packages/spec/src/stack.zod.ts:459+:523;skills/objectstack-ui/SKILL.md:11-13grep -n evals SKILL.md→ 0 hits, the eval tree was unreachableevals/approvals/test-revise-loop.mdThe two rules ported from the query flight
The query flight (#14443) deleted 21 lines of flow-filter text on the ruling that this package is the anchor, and found two rules the anchor lacked. Both are backed at source and both landed, in a new
### Filter tokens (config.filter)heading — which is also the addressable anchor that ruling asks this package to keep (it was:157-164on base, inside an unnamed blockquote; it now has a heading of its own).config.filter{current_user_id},{current_year_start}) passes through verbatim for the query engine to expand — so a flow variable named after a placeholder shadows it. Onlyfiltergets the hand-off;title/message/fields/urlkeep plain interpolation.packages/services/service-automation/src/builtin/template.ts:368-411—interpolateFilter, incl. the whole-string regex/^\{([^{}]+)\}$/and the comment "Flow variables keep precedence — only an unresolved token is considered for hand-off".isKnownFilterTokenispackages/spec/src/data/context-tokens.zod.ts:219.{record.…}token inside a filter naming an unknown field, or hopping a relation the start node does not list inconfig.expand, is an ERROR atobjectstack validate(the condition is DROPPED and the node refuses to execute). The same reference outside a filter is a warning. A{var}naming a flow variable or node output is not statically checkable at all.packages/lint/src/validate-flow-template-paths.ts:36-50(severity follows the runtime consequence, by position),:403-424(unknown field,severity: inFilter ? 'error' : 'warning'),:427-456(relation hop, same split,config.expandopt-in at:276-290),:59-62(onlyrecord.-prefixed tokens are checked — the third clause).Cost: +1,226 bytes (+307 tok), paid inside
SKILL.md. This is the amount the card's target explicitly excludes ("minus the two ported rules below").Deletions and merges
### Flow Examplerun-up### Failure routing & runAs### State Machine DesignBPsfromstate is not guarded) merged into that Notes block## Verify your workos validate/os buildblock and the one clause nothing else carries (a bare ref resolves, so a typo there is advisory) kept:37-43:596,:600-606ctx.recordparagraphreferences/data-hooks.md:731-734OLD/NEWretirement:152-164:404-409### Re-homing the old process modelapprovalsstack collection) moved into the surviving blockquote:895-902:926-941defineStack({ functions })fence kept with a one-line caption### Flow DesignBPsendnode) folded into the flow-example blockquote, #4 into the trigger blockquote:22-25### Trigger DesignBPsconditiontextname/label/type/nodes) but omittededges, whichFlowSchemarequiresComposite row:
AUTO-D-06+AUTO-B-03+AUTO-D-09were one contiguous## Best Practicessection; deleting all three subsections removed it entirely — −1,648 bytes, against +230 re-added for B-03's surviving item and +248 for the D-09/D-07 survivors.premise_false
premise_false: AUTO-A-01 (description half)— the card says the falsehood is also in "the frontmatter/description". It is not: thedescriptionon base reads "Flows (visual logic), Triggers, Approvals, state machines, scheduled jobs, and webhooks" and never mentions ETL.grep -n ETL SKILL.mdon base returns exactly lines 24 and 35, both body. Nothing was deleted from the description on this account; the description edit that did land is AUTO-A-02/A-03.premise_false: AUTO-E-04 span—io-node-config.zod.ts:179-218does not boundNotifyConfigSchemaon this base; the schema is:178-258and three of the eight documented keys (severity,sourceObject/sourceId,actionUrl) sit past:218. Re-located by content, as instructed; every key was read at its real line.Everything else in the flight scope had a true premise. Two findings were not implemented, by constraint rather than by premise:
test-decision-edgeseval) — it needs a new file, and "⛔ no new files" is a hard line on this card. Left for the eval-suite card, [Decision] Skills optimization program — batch 1 (4 items): new-file ceilings for splits · planned-eval stubs · react-blocks double rendering · published pm-dispatch scope #14296.approvalStatusField,escalation/escalateTo/timeoutHoursandresolveAshave 0 usages in the example corpus but are live implementations (packages/plugins/plugin-approvals/src/approval-service.ts:1420,approvals-plugin.ts:293-335). Re-checked on this base and left in place, so a future trim does not mistake them for dead surface.os:checkmarking — what is and is not claimedPer the ruling, only blocks that compile against
@objectstack/specdeclarations are marked.check:skill-examplescounts 265 → 266 marked blocks.notifyconfig fence is aconfig: { … }fragment — the shape an author copies into a node — and is not self-contained. Making it compile would mean wrapping it in a wholedefineFlow, which would teach a different thing and cost roughly triple. The audit's other candidate, the record-change trigger example, was deliberately turned into a node-only fragment by AUTO-E-02, which is incompatible with marking it; the copy hazard AUTO-E-02 names is removed instead.Reverse verification of the new marker
To prove the new marker is not a phantom green, on the committed tree: mutated
type: 'schedule'totype: 'schedulez'inside the marked block, confirmed the mutation reached disk by blob hash (8824aa3f…→0019f5e2…), andcheck:skill-exampleswent red witherror TS2820: Type '"schedulez"' is not assignable to type '"api" | "screen" | "autolaunched" | "record_change" | "schedule"'. Restored withgit checkout HEAD --the absolute path under an EXIT/INT/TERM trap; restoration proven by blob hash back to8824aa3f…,git diff HEADempty, and 0 occurrences of the injected token. The restore leg was re-measured: 266 blocks, exit 0. No package build is involved — this gate reads the skill file directly, so there is nodist/leg to preflight.follow-up for other packages
Anchors were re-verified at this head; all are equal or stronger than the text deleted here, so nothing is owed except the last item.
references/data-hooks.md:346carries thectxtable AUTO-C-02 deleted here, plus at:358the nuance this file omitted ("Action bodies additionally receivectx.recordIdandctx.record"). Stronger. Path kept by the delivered data flight. Nothing owed.SKILL.md:160-172is the stdlib table (AUTO-C-01),:383and:399theOLD/NEWtranslation row and its warning (AUTO-C-04).skills/README.md:87carries the same. Stronger. Nothing owed.SKILL.md:905is theos:check-markeddefineAction({ type: 'flow' … })example (AUTO-C-03). Type-checked, so stronger. Nothing owed.SKILL.md:82-93carriesos migrate meta --from 16and its variants (AUTO-D-04). Stronger. Owed: it carries no pre-ADR-0019ApprovalProcess.create({…})re-home table, so AUTO-D-03's content now has no home in any package. The audit's own reasoning is that every destination is taught in this file under "Branching, side-effects & rejection", so this is recorded as a judgement to confirm, not a regression to fix — a follow-up for objectstack-upgrade if a maintainer wants the cross-major mapping preserved.Out-of-scope card filed
#14466 —
[finding]theobjectstack-automationreference index routes to the ADR-0020-retiredstate-machine.zod.tsand omits both per-nodeconfigschemas (SKILL_MAPinpackages/spec/scripts/build-skill-references.ts:120-129). This is audit id AUTO-B-05, deferred by this card's ruling because the fix lives inpackages/spec. Unassigned,findinglabel, no pm-state, no priority. Deduped first against a healthy in-session search (a known-hit control query returned this card, so an empty result would have been a real reading); the nearest neighbour is #14462, the same defect class forobjectstack-ai— worth triaging together, possibly one fix.Gap against the card's target
The card targets ≈ −1,125 net in
SKILL.md, "minus the two ported rules". Delivered −499. Itemised rather than smoothed:Where the gap sits, measured against the card's own funded allowances:
AUTO-E-04cost +332 tok against +140 funded (+192 over) andAUTO-F-02+100 against +40 (+60 over). Both overruns are verified contract content, not prose: thenotifyRAW-vs-interpolated split and the per-capability "absent ⇒" column. Two trim passes brought them down from +359 and +143. The remaining ~67 tok is spread across merge survivors (AUTO-B-03,AUTO-D-09/AUTO-D-07) that the audit costed at 0 and that landed as short blockquotes instead. Nothing was cut from the audit's delete list to close it, and no verified fact was dropped to reach a number.The eval over-delivered in the other direction: −779 against −700 funded.
Gates
Every exit code captured before any pipe, at head
2926abc9. The full family was re-derived after regeneration —node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, which reads the change set from git itself (4 paths vs merge basea98b61b3e) — and all 36 commands it printed were run.node scripts/check-skills-token-ratchet.mjs;pnpm --filter @objectstack/spec check:skill-examples(266 blocks, run after building the@objectstack/specand@objectstack/client-reactclosures so it could not false-green on a staledist/);pnpm --filter @objectstack/spec check:skill-docs;pnpm check:skill-compatibility;pnpm check:skill-identifier-liveness;pnpm check:skill-frame-sync;pnpm check:doc-authoring;pnpm check:doc-anchors;pnpm check:published-readme-links;pnpm check:corpus-claim-drift; the 20 docs-family gates the.mdxpulls in.node scripts/check-test-completeness.mjsexits 3 withPREREQUISITE NOT MET— it grades a savedturbo run testlog, and the derived family names it with no argument. Its own text says this branch "is not a red, and there is nothing here to fix". Recorded as not measured, not as green.node scripts/check-nul-bytes.mjsgreen (7,902 files, no raw control bytes); the four changed files also scanned directly withgrep -naPfor the C0 range — clean.origin/mainbefore the first edit and were green, so every reading above is a delta against a known-green base.Liveness moved in the right direction: Leg 1 went 490 → 495 citations checked against the implementation word tokens, i.e. the five new identifiers this PR writes are all live. Leg 2 has no binding on this package (
BINDINGSinscripts/check-skill-identifier-liveness.mjs:284-350registers 8 sections, none inobjectstack-automation), so the node-type table is not registered exhaustive and the gateway-row rewrite could not silently unbind an assertion — checked before the first deletion, as instructed.Labels and landing form
skip-changesetapplies and is verified against the gate's own enumeration, not a remembered list:scripts/check-empty-changeset.mjs:357-359names ".github/,.claude/,skills/,docs/,content/,examples/, tests-only, and the like" as the releases-nothing route, and the diff is exactlyskills/**plus one generatedcontent/docs/**file.needs:contract-reviewis applied to both carriers — the ADR-0031 control-flow rows, thenotifyskipped: truesemantics, the capability table and the two ported flow-filter rules are all contract claims.Governed face, so this stays draft. The card stays open on purpose: AUTO-B-04 (the
evals/README.mdplanned-structure stub) is deferred to #14296 item 2, which is why the first line isPart ofand no closing keyword appears anywhere in this body.🤖 Generated with Claude Code
https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Generated by Claude Code