Repository navigation
Skills optimization flight — skills/objectstack-automation: RESTRUCTURE (≈ −1,125 tok net / −2,105 gross) — the package teaches a control-flow trio with zero authorings (parallel_gateway/join_gateway/boundary_event) and never mentions the trio the corpus uses (parallel/try_catch/loop); notify (#1 node type, 20 uses) has one table cell; the description still promises ETL pipelines removed in spec 17 #14308
Description
Activity
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentationpriority:p1High: required for production / M2High: required for production / M2and removed
on Sep 2, 2026 Claim: PM loop round 3
Session:session_01LraLgQVGq8egUwfYZpbYt1
Branch:claude/issue-14308-skills-automation-optimization
Worktree:objectstack-issue-14308
Domain:domain:skills
File surface:skills/objectstack-automation/SKILL.md+skills/objectstack-automation/evals/approvals/test-revise-loop.md(AUTO-H-01), both shrink-only (ceilings 12,768 / 1,329, headroom 0 / 0);evals/README.mduntouched (AUTO-B-04 deferred, #14296 item 2); generatedreferences/_index.mduntouched; no file deleted ⇒ ⛔ no edit toscripts/check-skills-token-ratchet.mjs;skills/README.md+content/docs/ai/skills-reference.mdxregenerated only because the drift gate demands it after the AUTO-A-01/A-02/A-03 description edits; ⛔ no other package (stop on breach; explain in the report)
Container & model: M (1,001-line entry file + one eval, 25 findings, control-flow model rewrite),mode:subagent,model: opus—--tierreads no path-derived mandate; the content limb applies, compensated by the seat's in-seat review atCONTRACT_REVIEW_TIER
Clause-②: yes — the ADR-0031 structured control-flow rows, thenotifysilent-success semantics (skipped: truewhen messaging is absent), the capability → surface table, and the two flow-filter rules ported from the query flight are contract claims ⇒needs:contract-reviewon both carriers at PR creation
Serial constraints cleared: the query flight (PR #14443, in patch round) points at this package's flow-filter rule (SKILL.md:157-164at base) — keep that section addressable, and it now carries two funded additions the query flight deleted on this card's ruling (precedence onconfig.filterwith placeholder pass-through and variable shadowing; the static-checkability split:objectstack validateFAILS a{record.…}filter token naming an unknown field or an un-expanded relation hop, the same reference outside a filter stays a warning, an unresolved flow variable is not statically checkable) — paid insideSKILL.md; hooks →objectstack-data/references/data-hooks.md(path kept by the delivered data flight PR #14427); screen flows stay here (objectstack-ui points at this package);skills/objectstack-automation/**byte-identical between a59f78d and origin/maina98b61b3(seat-measured 07:3xZ); no open PR touches this package; in flight alongside #14305 (ai) and #14307 (upgrade) on disjoint directoriesDecision re-read: no maintainer ruling on this card; binding inputs = the mandate, the value gate, the ratchet discipline, and #14296 (item 2 deferred: eval stub). AUTO-B-05 (generator map) goes out as an out-of-scope finding card for the spec lane. Landing form: first line
Part of #14308(the deferred eval stub keeps the card open).
Generated by Claude Code
Dev claim (os-dev subagent, dispatched by the skills lane seat).
Session:
session_01LraLgQVGq8egUwfYZpbYt1(the harness reports the same session id as the dispatching seat — subagent under the same session URL; the distinguishing identity bit is the branch below)
Branch:claude/issue-14308-skills-automation-optimization(empty branch pushed at claim time as the write probe)
Worktree:../objectstack-issue-14308, baseorigin/main=a98b61b3ef695431db26097a28ae8e5f1dec8fdfRead channel: repo-scoped REST is 403 for this seat (
GitHub access is not enabled for this session.) ⇒ card body + full comment thread read via the public-repo page payload (zero quota); MCP reserved for writes and one targeted dedupe search.Body verified complete — it ends with the
Refs: #14292 · #14296 · #13658.line. No earlier dev claim on the card; nothing to collide with.File surface (hard):
skills/objectstack-automation/SKILL.md+skills/objectstack-automation/evals/approvals/test-revise-loop.md, both shrink-only;skills/README.md+content/docs/ai/skills-reference.mdxonly as generator output. Landing form:Part of #14308(AUTO-B-04 deferred to #14296 item 2 ⇒ the card stays open).The audit record follows as the next comment.
Generated by Claude Code
audit-record — skills/objectstack-automation (read-only audit at a59f78d)
Transliteration key. The GitHub body sanitizer is measured to delete angle-bracket /
tag-shaped fragments (even inside backticks), so the two such spans in the source file are
respelled below. The file on the seat's disk is unchanged; this is a lossless rendering.OS-CHECK-MARKER(AUTO-E-01 row) — in the source this is an HTML comment whose entire
body isos:check, i.e. the opt-in marker linecheck-skill-examples.tslooks for on the
line directly above a fence.IDENT(AUTO-H-01 row) — in the source this is the angle-bracketed placeholderidthat
stood for each lint rule id inside thegrep -rn ... packages/lint/srccommand.
Everything else is verbatim.
Audit —
skills/objectstack-automation/(read-only)Pinned ref: objectstack
origin/main=a59f78d. The four package files are byte-identical
betweenorigin/mainand the working checkout (git diff --stat origin/main HEAD -- skills/objectstack-automation-> empty), so all spans below are valid at the pinned ref.Measured baseline
File tokens (ratchet) ceiling headroom SKILL.md12,768 12,768 0 evals/approvals/test-revise-loop.md1,329 1,329 0 evals/README.md414 414 0 references/_index.md835 - generator-owned authored total 14,511 package total 15,346 Source:
node scripts/check-skills-token-ratchet.mjs. Zero headroom on all three authored files.Internal weight of
SKILL.md(bytes/4, measured bysed -n 'A,Bp' | wc -c):Section span tokens % of file Frontmatter + intro + When to Use 1-46 481 4% Flows 47-240 2,245 18% State machines & Approvals 243-650 5,873 46% - Approvals alone 296-650 5,246 41% Triggers 653-782 1,412 11% Best Practices 785-822 412 3% Common Pitfalls (1-10) 824-951 1,779 14% - "Valid-but-silently-wrong" 6-10 836-951 1,630 13% Blueprint + Verify + References 953-1001 563 4% Real-usage corpus (dimension E/F basis)
Grepped:
examples/**(app-crm,app-showcase,app-todo),packages/apps/**,apps/**,
packages/triggers/*,packages/plugins/plugin-approvals,packages/plugins/plugin-webhooks.
4*.flow.tsfiles +examples/app-showcase/src/automation/flows/index.ts(1,759 lines,
24 flows) +jobs/+webhooks/. Zero*.trigger.tsfiles exist anywhere.Node-type frequency across every real flow (
grep -o "type: '[a-z_]*'" | sort | uniq -c):node type usages SKILL.md coverage notify20 1 table row ( SKILL.md:97), no config exampleapproval15 355 tokens of tables + 3 examples screen9 1 table row ( SKILL.md:100), no exampleupdate_record/get_record/decision5 each example + notes connector_action4 1 table row assignment/loop4 / 3 1 table row each http/create_record3 each example ( http)try_catch2 absent parallel2 absent subflow/script2 each table row + pitfall 9 map/wait/delete_record/approval_revise1 each table rows; approval_revisegets 875 tokparallel_gateway/join_gateway/boundary_event0 3 table rows + BP #2 + pitfall 2 Approval-config knob frequency:
behavior17,approvers15,group21,lockRecord9,
minApprovals2,maxRevisions2,onEmptyApprovers2,decisionOutputs1,
approvalStatusField0,escalation/escalateTo/timeoutHours0,resolveAs0.
Findings
id dim file:span evidence (measured / quoted) proposal d tok value gate (1)(2)(3) conf human-floor AUTO-A-01 A, G SKILL.md:24-25,SKILL.md:35Intro: "This skill covers Flows ..., Triggers ..., and ETL pipelines." When-to-Use bullet: "You are designing an ETL pipeline for data synchronisation." The L2 ETL layer was retired at spec 17 - packages/spec/src/migrations/entries/semantic/17.etl-pipeline-layer-retired.ts:7-11("the whole L2 layer ofautomation/etl.zod.ts, its four enums and theETLfactory - 9 defs, 27 exported names"), replacement(removed - no protocol surface replaces it, deliberately);packages/spec/src/shared/retry-policy.zod.ts:138"ETLPipeline.retrydid the same until #6414 retired the L2 ETL layer". The package declarescompatibility: Requires @objectstack/spec 17.x(SKILL.md:12) and carries zero ETL body content (grep -n ETL SKILL.md-> only 24 and 35).DELETEboth mentions-40 (1) yes - stops routing "design an ETL pipeline" into a package with no ETL content (2) yes, deletion IS the fix (3) n/a HIGH yes (retired semantics) AUTO-A-02 A, F frontmatter SKILL.md:4-5vs bodyFrontmatter promises "...scheduled jobs, and webhooks". The body teaches scheduled flows and inbound webhook flow triggers only. defineJob(packages/spec/src/system/job.zod.ts:170, registered viadefineStack({ jobs })-packages/spec/src/stack.zod.ts:458) anddefineWebhook(packages/spec/src/automation/webhook.zod.ts,defineStack({ webhooks })) have zero coverage in any published skill:grep -rn "defineJob|JobSchema|jobs:" skills/*/SKILL.md skills/*/rules/*.md skills/*/references/*.md-> 0 hits. Both are real:examples/app-showcase/src/automation/jobs/index.ts:16(cron +retryPolicy+handler),examples/app-showcase/src/automation/webhooks/index.ts:17(triggers: ['create','update','delete']).webhook.zod.tsis already listed in this package's ownreferences/_index.md:18.ADDa 6-line "Three automation collections:flows/jobs/webhooks" construct - paid by AUTO-D-03 + AUTO-D-04+180 (paid) (1) yes - an agent asked "fan task changes out to an external endpoint" currently learns only the httpnode (2) no - this capability text exists nowhere (3) yes, a tableHIGH yes (adds published capability text) AUTO-A-03 A, F SKILL.md:57,SKILL.md:100skills/objectstack-ui/SKILL.md:11-13routes screen flows out to here ("interactive screen flows / wizards (those are*.flow.tswithtype: 'screen'- see objectstack-automation)"), andskills/README.md:101-103repeats it. This package's total screen-flow content is two table rows. Real corpus: 9type: 'screen'occurrences, and the corpus has had to encode the contract in comments -examples/app-todo/src/flows/task.flow.ts:288-289"Select options are{ value, label }pairs (the screen contract's shape - bare strings fail the executor's config parse, #4277)" and:326-329"The screen contract has nomessage/buttonskeys ...description+waitForInput: trueis the declared way to pause on a message-only confirmation screen". Schema atpackages/spec/src/automation/builtin-node-config.zod.ts:423-455, not inreferences/_index.md.ADDascreen-node config row-set + the{value,label}/waitForInputpitfall - paid by AUTO-D-01 + AUTO-D-06+200 (paid) (1) yes - decides two documented-nowhere authoring choices (2) no (3) yes, a table + one OK/NO pair HIGH yes AUTO-B-01 B SKILL.md:296-650vs836-95141% of the file is Approvals (5,246 tok) while the highest-decision-density block - "Valid-but-silently-wrong (passes build, fails at runtime)" pitfalls 6-10, 1,630 tok - begins at line 836, i.e. 84% depth, behind ~800 lines. Those five pitfalls each change a specific keystroke (single-brace interpolation, outputVariableholds the record, date-equality never matches,script= registered function, bare CEL).MOVE-TO- promote the "Valid-but-silently-wrong" block to immediately after the Flows section0 (1) yes - reorders what an agent reads first (2) no (3) n/a MED yes (restructures) AUTO-B-02 B, D SKILL.md:131-187Five stacked blockquotes (893 tok) sit between the "Flow Example" heading and the example itself. Only the first (133-139, 131 tok - edgesnotnext,filteris awheremap,fieldsnotvalues,labelrequired) is about the code that follows. The rest are three separate sub-topics (fault edges 399 tok,readonly/runAs200 tok, elevate-the-write 151 tok).MOVE-TO- keep 133-139 adjacent to the fence; relocate 141-186 to a "runAs & failure routing" subsection after it0 (1) yes - the example is the copy target and sits 57 lines below its heading (2) no (3) n/a MED yes (restructures) AUTO-B-03 B, D SKILL.md:800-812vsSKILL.md:277-294"State Machine Design (ADR-0020)" best practices restate the Notes block 520 lines earlier, item for item: BP1 "Author it as a state_machinevalidation rule ... not aworkflowmetadata type (retired)" <-249-257; BP2 "A state mapped to[]is a final/dead-end state" <-257-258+ code comment272; BP4 "Put guards in a siblingscript/conditionalrule" <-284-286; BP5 "Put side-effects ... in a record-triggered Flow (ADR-0019)" <-286-288. Only BP3 (implicit any->any is lenient) is new.DELETEBP1/2/4/5;MERGE-INTOthe Notes block the one surviving sentence-150 (1) no for the 4 duplicates (2) yes (3) n/a HIGH no AUTO-B-04 B, H evals/README.md:13-43;SKILL.md(noevalslink)grep -n evals SKILL.md-> 0 hits: the eval tree is an orphan, unreachable from the entry file.evals/README.md:17-27ships a "Planned structure" ASCII tree naming four files that do not exist (test-quorum-behaviors.md,test-schedule-binding.md,test-decision-edges.md,test-time-relative.md) - verified byfind skills/objectstack-automation -type f(4 files total).:29-43"Format" and "Contributing" are maintainer instructions shipped to every customer install.DELETEevals/README.md:13-43(keep the header + current-evals table)-270 (1) no - a plan for unwritten files changes no authoring decision (2) yes (3) n/a HIGH no AUTO-B-05 B references/_index.md:16+ absent rowsThe generated Core list points at automation/state-machine.zod.ts, which ADR-0020 retired as a record-lifecycle declaration; its own header says so (packages/spec/src/automation/state-machine.zod.ts:15-21: "the top-levelworkflowmetadata type andobject.stateMachinesare both gone") and its single surviving door isai/agent.zod.ts:197lifecycle, marked[EXPERIMENTAL - not enforced] ... Parsed but no runtime consumer yet. Meanwhileautomation/builtin-node-config.zod.tsandautomation/io-node-config.zod.ts- the per-node-typeconfigshapes (NotifyConfigSchema, screenfields,httptimeoutMs) - are in neither list. Root cause: the generator map atpackages/spec/scripts/build-skill-references.ts:120-129.RETIRE-SURFACE(dropstate-machine.zod.tsfrom the map) +ADDthe two node-config files+10 (1) yes - changes which file the agent Reads for a node's config keys (2) partially (3) n/a (generated) HIGH yes (generator map change) AUTO-B-06 B, D SKILL.md:866-887vsSKILL.md:736-782Pitfall 8 (332 tok) and the Time-relative-triggers section (535 tok) open with the same rule. 736-740: "Don't express 'act N days before/after a date' ... as arecord_changeflow gated on date-equality (end_date == daysFromNow(60)) - that predicate is only evaluated when the record happens to change".866-870: "Time-relative rules ... are SCHEDULE flows, not record-change date-equality.record.end_date == daysFromNow(60)on arecord-*trigger only fires if the record happens to be written on that exact day". Pitfall 8's unique half is the time-component equality failure + the abutting-window$gte/$ltconstruct (875-887).MERGE-INTO SKILL.md:736-782- fold 871-887 in, delete 866-870-90 (1) no for the restated half (2) yes (3) the surviving half already IS a construct HIGH no AUTO-B-07 B, D SKILL.md:971-983vs842-859,943-949"Verify your work" restates two pitfalls. 976-978: "Node values take the single-braceflow-templatedialect ... no validator checks its call names, so an unknown function is NOT build-checked - it throwsFlowExpressionFunctionErrorat run time" <-856-859: "any other name in call position fails the node ... The build does not catch these (conditions are checked, call-position names are not)".971-974<-946-949("An UNKNOWN function (PRIOR(), a typo'd name) and a{...}-wrapped field ref both fail the build").DELETE SKILL.md:971-983, keep theos validate/os buildcommand block (985-991)-190 (1) no - third statement of the same two facts (2) yes (3) n/a HIGH no AUTO-C-01 C, D SKILL.md:42and943-946vsobjectstack-formula/SKILL.md:160-205The CEL stdlib is enumerated twice inside this package, and both times immediately defers elsewhere. SKILL.md:42-43: "(now(),today(),daysFromNow(n),daysBetween(a, b),isBlank(v),coalesce(v, fb)) ... See the objectstack-formula skill for the full CEL contract".SKILL.md:943-946repeats a longer version, then "see objectstack-formula for the full table." Authoritative table:objectstack-formula/SKILL.md:166-201. The frontmatter already says "load objectstack-formula alongside" (SKILL.md:9-10).DELETEthe enumeration inSKILL.md:42-43; keep the pointer-45 (1) no - an agent that needs the stdlib loads formula (2) yes (3) formula's table is the anchor HIGH no AUTO-C-02 C SKILL.md:596,600-606vsobjectstack-data/references/data-hooks.md:364-376Cheat-sheet rows 2-3 are object-hook rows ("Object hook handler ( ctx) |ctx.input(write payload);ctx.resultafter the write |ctx.previous"), followed by an 8-line paragraph "There is noctx.record.HookContextdeclaresinput/result/previous/session/ql...".objectstack-data/references/data-hooks.md:364-376carries the same contract as its own table plus the nuance this file omits (:376"Action bodies additionally receivectx.recordIdandctx.record"). Hooks are routed to objectstack-data by this package's own frontmatter (SKILL.md:7-9).DELETE SKILL.md:600-606and cheat-sheet rows 2-3; keep rows 1 and 4 with a one-line pointer-208 (1) no - this package's reader authors flows (2) yes (3) the surviving 2-row table stays a construct HIGH no AUTO-C-03 C SKILL.md:962vsobjectstack-ui/SKILL.md:1878-1897CRM Blueprint row 4: "Action-to-flow bridge | src/actions/*.actions.ts| Trigger screen flows viaAction.type = 'flow'for user-driven automation entry". objectstack-ui already carries the canonical,os:check-marked and therefore type-checked example of exactly this (defineAction({ ... type: 'flow', target: 'lead_conversion', locations: [...] })); actions are objectstack-ui's declared domain (objectstack-ui/SKILL.md:42).DELETErow 4-35 (1) no - a lower-information restatement of a verified example one package over (2) yes (3) ui's example survives HIGH no AUTO-C-04 C, D SKILL.md:731-734vsskills/README.md:87,objectstack-formula/SKILL.md:383,399"(Salesforce-flavor OLD/NEWwere removed in M9.5 and now fault the predicate.)" is the fourth copy:skills/README.md:87"LegacyOLD/NEWevaluate tonullsince M9.5";objectstack-formula/SKILL.md:383(translation row) and:399. The link to objectstack-formula is already on the next line (SKILL.md:734).DELETEthe parenthetical-35 (1) no (2) yes (3) formula's translation table is the anchor HIGH no AUTO-D-01 D SKILL.md:152-164212 tokens of justification prose inside the fault-edge blockquote: "It is not a way past a guardrail. ... A failure is a guard when re-running unchanged could never succeed and the fix is to edit metadata ... Never add a fault edge to silence such an error: a dropped filter condition widens the query, so routing it would let a delete_recordempty the object while the run reported success."REWRITE-AS-CONSTRUCT- one row: "Routes: 404 / rate-limit / rejected write / failed subflow. Does not route (fatal either way): missing required config key, dropped filter token, nesting-ceiling recursion, unscoped run."-150 (1) the surviving row yes; the essay no (2) partially (3) yes, a two-cell row HIGH no AUTO-D-02 D SKILL.md:404-409(+evals/approvals/test-revise-loop.md:61)ADR narration: "ADR-0044 D3 first prescribed an ordinary waithere and its 2026-07-28 amendment reversed that - awaitisresumeAuthority: 'any', so a rawPOST /api/v1/automation/:name/runs/:runId/resumewalked the back-edge with no submitter check and no audit row, and could destroy the run outright." The decision it changes is already stated at401-404, again at433-436, and again in the eval's mistakes table.DELETEthe amendment history (keep "the window is a service-owned pause (resumeAuthority: 'service')")-115 (1) no - history of a reversal changes nothing for an author writing today (2) yes (3) n/a HIGH no AUTO-D-03 D SKILL.md:443-459"Re-homing the old process model" - a 6-row table mapping pre-ADR-0019 ApprovalProcess.create({...})concepts onto the flow graph, opening "If you've seen the pre-ADR-0019 ... shape". Cross-major migration is objectstack-upgrade's declared domain (objectstack-upgrade/SKILL.md:4-9). Every row's destination is already taught in "Branching, side-effects & rejection" (SKILL.md:622-636).DELETE(orMOVE-TO objectstack-upgrade)-225 (1) no for a new author (2) yes (3) 622-636 is the surviving construct MED yes (removes published capability text) AUTO-D-04 D SKILL.md:895-902"The other dispatch forms were retired in spec 17 because none of them ran: config.actionType: 'email' | 'slack'were logger-backed stubs that delivered nothing ... and inlineconfig.scriptJS was never executed (no server-side sandbox). ... Stored flows convert withos migrate meta --from 16." The same words already ship inside the spec the agent Reads (packages/spec/src/automation/flow.zod.ts:41-43), andos migrate metais objectstack-upgrade's surface (objectstack-upgrade/SKILL.md:141-145). Maintainer principle 2026-08-27 argues against dual-spelling history in a 17.x-only package.DELETEthe retirement narration; keep the positive prescription-110 (1) no - an author on 17.x never types actionType(2) yes (3) the surviving sentence is the prescriptionMED yes (retired semantics) AUTO-D-05 D SKILL.md:926-941"The rule is load-bearing: a scriptstep reports no record metrics in the run summary because every write a pure function causes is a downstream node that counts itself. A function that writes anyway makes its run reportacted: 0- indistinguishable from a sweep that silently did nothing." 215 tokens of why, after the rule and its OK/NO code pair are already given (904-924). Theeffect: 'writes'escape hatch IS decision-changing and real (examples/app-showcase/src/automation/jobs/sweep-project-health.ts:33-38).REWRITE-AS-CONSTRUCT- keep the 4-linedefineStack({ functions })fence (936-941) with a one-line caption; delete 926-935-130 (1) the fence yes; the rationale no (2) partially (3) yes, the code fence survives HIGH no AUTO-D-06 D, G SKILL.md:787-798"Best Practices -> Flow Design", 5 items / 137 tok. #1 "Keep flows small and composable", #3 "Use variables for all dynamic values", #4 "Prefer get_recordover multiplehttpcalls" are generic engineering advice changing no ObjectStack keystroke. #5 "Always settimeoutMsonhttpnodes. Unset means no timeout at all" duplicates the in-example comment atSKILL.md:228. #2 "Addboundary_eventnodes for timeout and error scenarios" is actively wrong guidance - see AUTO-F-01.DELETEthe whole subsection-137 (1) no (2) yes (3) n/a HIGH no AUTO-D-07 D SKILL.md:826-835Common Pitfalls 1-5 (144 tok). #1 "Circular flow references. ... Use a depth counter or visitedset to detect cycles" is engine-implementer advice - a metadata author has no such lever, and the platform already enforces a nesting ceiling (referenced atSKILL.md:158). #2 is BPMN-interop (AUTO-F-01). #5 "Scheduled flows without idempotency" is restated atSKILL.md:691.DELETE#1, #2, #5;MERGE-INTOthe Flows section the two surviving clauses-110 (1) no (2) yes (3) n/a MED no AUTO-D-08 D SKILL.md:22-25,29-35The intro paragraph and the 5-bullet "When to Use This Skill" restate the frontmatter description(SKILL.md:3-10), which is the field the loader routes on (skills/README.md:73). Both are paid on every session; the frontmatter is loaded anyway.DELETE SKILL.md:22-25; keep the When-to-Use bullets minus the ETL one (AUTO-A-01)-60 (1) no - routing already happened by the time the body is read (2) yes (3) n/a MED no AUTO-D-09 D SKILL.md:814-820"Best Practices -> Trigger Design", 3 items / 88 tok. #3 "Use the start-node conditionto narrow when the trigger fires" restates the code comment atSKILL.md:722and the prose at655-659. #2 (guardrecord-after-updateself-writes) is the one decision-changing item.MERGE-INTO SKILL.md:707-729- keep #2, delete #1/#3-60 (1) #2 yes, #1/#3 no (2) yes (3) n/a MED no AUTO-E-01 E SKILL.md- 1 of 13 TS fences markedpackages/spec/scripts/check-skill-examples.ts:18-23: "this gate is opt-in: a self-contained, should-compile block is marked by aOS-CHECK-MARKERHTML comment on the line directly above its fence." Measured: 13 TypeScript fences (10typescript at 114/188/259/310/420/522/543/667/709/749, 3 indentedts at 875/909/936); exactly one carries the marker (SKILL.md:542). Bundle comparison (grep -rc 'os:check' skills/*/SKILL.md): ui 11, api 6, data 4, ai 4, i18n 4, platform 2, formula 2, upgrade 1, automation 1, query 0, pm-dispatch 0.ADDmarkers to the two blocks that can be made self-contained (schedule flow188-239, record-change trigger709-729) with theirimport { defineFlow }line+30 (paid by AUTO-D-06) (1) yes - an unverified example is what the gate's own header calls "teaching code that no longer compiles" (2) no (3) yes, the examples ARE the constructs HIGH no AUTO-E-02 E SKILL.md:310-380,709-729,749-775,667-676Unmarked fences that would fail a type-check if marked: (a) 310,709,749use thecel`...`tag with no import (grep -n "^import" SKILL.md-> one hit, line 544, inside the marked block); (b)709-729omitsedges, whichFlowSchemarequires (packages/spec/src/automation/flow.zod.ts:659- no.optional()), soFlowSchema.parserejects it; (c)667-676callsdefineStack({...})with no import. None is false - each is a legitimate fragment - but (b) reads as a whole flow (it hasname/label/type/nodes), which is the shape an agent copies.REWRITE-AS-CONSTRUCT- make709-729a node-only fragment so it cannot be copied as a complete flow-20 (1) yes - removes a copyable-but-unparseable flow (2) partially (3) yes MED no AUTO-E-03 E derived top-5 tasks vs coverage Top-5 real authoring tasks by corpus frequency: (1) event->notify (20 notifynodes across 9 flows) - no example, no config keys; (2) approval chain (15approvalnodes, 8 flows) - 3 examples OK; (3) scheduled sweep / digest (5type:'schedule';flows/index.ts:362,1619;jobs/index.ts:16) - 1 flow example OK, nodefineJob; (4) screen wizard (9screen) - no example; (5) outbound integration (connector_action4,http3,defineWebhook1) -httpinside one example,connector_actionno example,defineWebhookabsent. 2 of 5 top tasks have no canonical example; a 3rd is half-covered.ADDa notify-config fence + a screen-node fence (AUTO-A-03, AUTO-E-04)see rows (1) yes (2) no (3) yes HIGH yes AUTO-E-04 E, F SKILL.md:97(whole coverage ofnotify)notifyis the most-used node type in the corpus (20 usages) and its entire documentation is one table cell: "notify| Send a notification through the messaging service (inbox channel by default)". Real config keys in use (grep -A8 "type: 'notify'"overexamples/):recipients13,title10,topic9,message8,severity7,channels7,sourceObject/sourceId4,actionUrl. Schema:packages/spec/src/automation/io-node-config.zod.ts:179-218. The silent-failure case is undocumented:packages/services/service-automation/src/builtin/notify-node.ts:313-320- with nomessagingservice registered the executor logs "[notify] no messaging service registered; notification ... not delivered" and returns success withoutput: { delivered: 0, failed: 0, skipped: true }. Textbook material for this package's own "Valid-but-silently-wrong" section.ADDan 8-linenotifyconfig fence + one line in the capability table (AUTO-F-02) - paid by AUTO-D-03 + AUTO-D-05+140 (paid) (1) yes - the #1 node type has zero authorable detail and a documented silent no-op (2) no (3) yes, a fence + a table row HIGH yes AUTO-F-01 F, G SKILL.md:76-77,79,791-792,828-829The package teaches only the BPMN-interop control-flow trio and never mentions the ADR-0031 structured constructs. Measured usage in examples/:parallel_gateway0,join_gateway0,boundary_event0;parallel2 (flows/index.ts:929, 1207),try_catch2 (:1009, 1226),loopcontainer 3,map1. The repo's own coverage waivers say it outright -examples/app-showcase/src/coverage.ts:295-300: "parallel_gateway: BPMN-interop lowering target - the author-facing form is the ADR-0031 structuredparallelcontainer (FanOutNotifyFlow)"; "boundary_event: BPMN-interop form; the author-facing equivalents the showcase demos are the ADR-0031try_catchcontainer (ResilientSyncFlow) andwaittimers". The spec agrees:packages/spec/src/automation/control-flow.zod.ts:5-11,42-46- the constructs are "the native + AI-authored flow model ... the right substrate for LLM authoring", while the gateways "remain author-invisible interchange representations".grep -n "try_catch|ADR-0031|config.body" skills/objectstack-automation/**-> 0 hits.control-flow.zod.tsreachesreferences/_index.md:23only as a transitive dependency.ADD3 rows to the Control-Flow node table (parallel/try_catch/loopwithconfig.body, plus "the*_gateway/boundary_eventtrio is BPMN-interop lowering, not author-facing") +DELETEBP #2 and pitfall #2 (AUTO-D-06, AUTO-D-07)+120, net -127 with its payers (1) yes - changes which node type the agent emits for fan-out and for error handling (2) no - the payer is elsewhere (3) yes, table rows HIGH yes (changes published capability text) AUTO-F-02 F SKILL.md:661-676"Prerequisite - enable the triggerscapability" listsrequires: ['automation','triggers']+'job'+'queue'. It omits the two capabilities the corpus's two most-used node types need.examples/app-showcase/objectstack.config.ts:92-107documents them inline: "approvals- ApprovalsServicePlugin, so theapprovalflow node (ADR-0019) is contributed to the engine"; "messaging- MessagingServicePlugin, so thenotifynode delivers to the inbox channel (sys_inbox_messagerows) instead of degrading to a logged no-op"; the real list is['ui','automation','approvals','messaging','triggers','job','marketplace','webhooks','realtime']. Confirmed in the executor (notify-node.ts:313-320). An agent following this section authors an approval flow (15 real usages) and a notify node (20) and gets a node type with no registered executor and a silent success that delivered nothing.REWRITE-AS-CONSTRUCT- a capability->surface table (automation->engine;triggers->record-change/schedule/api binding;job->cron + timeRelative sweep;queue->inbound webhook (503 without);approvals->approval/approval_revise;messaging->notifydelivery;webhooks->defineStack({ webhooks }))+40 (1) yes - the highest-frequency silent failure this package can prevent (2) no (3) yes, a 7-row table replacing prose HIGH yes AUTO-F-03 F zero-real-usage documented surfaces Grepped examples/**,packages/apps/**,apps/**for every approval knob the package documents:approvalStatusField0 (yet promoted as Approval Best Practice #2,SKILL.md:641-643),escalation/escalateTo/timeoutHours0 (SKILL.md:619),resolveAs0 (SKILL.md:495,524,533). All three are live implementations, not speculative surface -packages/plugins/plugin-approvals/src/approval-service.ts:1420(const resolveAs = String(a.resolveAs ?? 'user')) andpackages/plugins/plugin-approvals/src/approvals-plugin.ts:293-335(SLA escalation scan job, ADR-0042). Zero usage in examples is evidence, not proof; I grepped only the three example apps +packages/apps+apps.no change - recorded so a future trim does not mistake them for dead surface 0 n/a HIGH no AUTO-G-01 G SKILL.md:37-43vs554,573+ corpusThe package instructs "Use the P`...`andcel`...`tagged templates from@objectstack/spec" for "Everycondition/guard/entryCondition/ filtervaluein this skill", then usescel`in 8 places (329, 366, 372, 374, 524, 527, 533, 723) and plain strings in its only type-checked block (SKILL.md:554condition: "status == 'submitted'",:573) and in its eval (evals/approvals/test-revise-loop.md:31). The real corpus is unanimously plain strings:grep -rn "cel`" examples/**/flows-> 0 hits; all 20 flow/edge conditions are bare strings (examples/app-showcase/src/automation/flows/index.ts:39,153,212,281,282,325,438,691,808,924,1004,1099,1201,1258,1259,1501,1502,1532,1582,1696).REWRITE-AS-CONSTRUCT- one sentence: "A condition slot takes a plain CEL string; thecel`...`tag is the same string with author-time validation. Both parse - pick one per file."-10 (1) yes - an agent currently cannot tell which of two spellings the package endorses (2) no (3) yes HIGH no AUTO-G-02 G SKILL.md:59,313,712vs corpusBoth record-change examples declare type: 'record_change'. The corpus overwhelmingly declarestype: 'autolaunched'with the same start-node binding: 16 flows inexamples/app-showcase/src/automation/flows/index.tspairtype: 'autolaunched'with arecord-*triggerType, versus 1 usingtype: 'record_change'(:1683). Not a falsehood - the engine derives the binding from the start node regardless (packages/services/service-automation/src/engine.ts:2169-2189resolveTriggerBinding) and a lint rule does key onrecord_change(packages/lint/src/validate-flow-trigger-readiness.ts:604-631) - but the package never says the two coexist, and its own eval usesautolaunched(evals/approvals/test-revise-loop.md:27) against its own examples.ADDone clause to therecord_changeFlow-Types row ("autolaunched+ arecord-*start binding behaves identically;record_changeadditionally opts into the trigger-readiness lint")+20 (1) yes - resolves a live contradiction between the skill's examples and its eval (2) no (3) yes, one table cell MED no AUTO-H-01 H, I evals/approvals/test-revise-loop.md(1,329 tok) vsSKILL.md:382-442(875 tok)2,204 tokens - 15% of the authored package - go to ADR-0044 send-back, a surface with 1 real usage ( examples/app-showcase/src/automation/flows/index.ts:248, the singleapproval_revisenode). The eval restates the SKILL section rather than testing beyond it: the canonical shape (eval23-50~SKILL.md:420-431), the four lint findings (eval59-65~SKILL.md:433-441), thewait-vs-approval_reviseamendment rationale (eval61~SKILL.md:404-409), the same showcase pointer (eval52-53~SKILL.md:440-441). By contrastnotify(20 usages) gets ~15 tokens. All lint ids in the eval are real (grep -rn IDENT packages/lint/src-> 1 non-test hit each for the fourflow-approval-revise-*plusflow-error-label-not-fault,flow-date-equality-filter), so no rubric row would teach a grader to fail a correct answer.DELETEthe eval's Expected-Output fence and the Common-Mistakes rows that restate SKILL.md; keep Scenario + Validation Criteria-700 (1) no - a grader needs criteria, not a second copy of the rule (2) yes (3) the Validation Criteria list survives as the construct HIGH yes (restructures a shipped file) AUTO-H-02 H evals/README.md:11+ package-wideThe eval suite covers exactly one of the package's ~40 rules - the one with the fewest real usages. Nothing tests the rules that gate the corpus's actual output: single-brace vs double-brace interpolation ( SKILL.md:842-859),filteras awheremap vs UI filter triples (SKILL.md:135-138), unguarded decision edges running in parallel (SKILL.md:343-346),runAs: 'system'forreadonlywrites (SKILL.md:166-176). Sibling comparison: no other package ships a prose eval fixture (ls skills/*/evals-> README-only except ui's 1,102-token JSON).ADD- after AUTO-H-01's trim, onetest-decision-edgeseval (already listed as planned atevals/README.md:24)+250 (paid by AUTO-H-01) (1) yes - grades the rule with the widest blast radius (2) no (3) yes, an eval IS a construct MED yes AUTO-I-01 I package = 14,511 authored tokens 3rd-largest SKILL.mdin the bundle (ui 25,441 > pm-dispatch 14,549 > data 13,892 > platform 12,984 > automation 12,768). Distinct real-usage patterns found in F: 14 (record-change->notify, approval chain, per-group/quorum sign-off, dynamic/expression approvers, send-back loop, scheduled digest, timeRelative sweep, screen wizard, subflow composition, loop/map batch, parallel fan-out, try_catch resilience, connector/http integration, inbound webhook) plus 2 uncovered collections (jobs,webhooks).900 authored tokens per pattern, but distributed 41% to one pattern family. Sum of DELETE/MERGE rows above: -2,105; sum of paid ADDs: +980; net **-1,125 (-7.8%)** while raising covered patterns from 12 to 16.- -1,125 net - HIGH - Incidental falsehoods (by-product, not the job)
where claim implementation truth SKILL.md:24-25,SKILL.md:35"This skill covers ... and ETL pipelines" / "You are designing an ETL pipeline for data synchronisation." The L2 ETL layer (9 defs, 27 exported names) was removed in spec 17 with no replacement surface - packages/spec/src/migrations/entries/semantic/17.etl-pipeline-layer-retired.ts:7-20; corroborated atpackages/spec/src/shared/retry-policy.zod.ts:86,138. The package declarescompatibility: Requires @objectstack/spec 17.x. Filed as AUTO-A-01.SKILL.md:791-792Best Practice: "Always handle errors. Add boundary_eventnodes for timeout and error scenarios."boundary_eventhas 0 authorings in the whole corpus and the repo's own waiver calls it a non-authored BPMN-interop form whose "author-facing equivalents ... are the ADR-0031try_catchcontainer ... andwaittimers" (examples/app-showcase/src/coverage.ts:299-300);packages/spec/src/automation/control-flow.zod.ts:42-46calls the trio "author-invisible interchange representations". Filed as AUTO-F-01.Not re-verified: the 2026-08-31 factual sweep (program #13658) is treated as done. The two rows
above surfaced while measuring dimensions A/G and F respectively.
Generated by Claude Code
os-dev-report
{ "issue": 14308, "status": "done", "branch": "claude/issue-14308-skills-automation-optimization", "pr": "https://github.com/objectstack-ai/objectstack/pull/14467", "premise_still_valid": true, "summary": "Implemented the audit record on skills/objectstack-automation: the ADR-0031 structured control-flow trio (parallel / try_catch / loop-container) is now taught and the zero-authoring BPMN trio demoted to one 'not author-facing' row; notify got a config fence plus its documented silent no-op; the capability table gained approvals and messaging; both ported flow-filter rules from the query flight landed under a new addressable heading; the ETL promise and the boundary_event advice are gone; 20 delete/merge findings applied; the eval deduplicated. SKILL.md 12,768 -> 12,269 tok (-499, ceiling 12,768, headroom 499); eval 1,329 -> 550 (-779); package authored total -1,278. Delivered -499 against an adjusted target of -818 in SKILL.md; the 319-token gap is itemised in the PR body against the card's own funded allowances (AUTO-E-04 +192 over, AUTO-F-02 +60 over, both verified contract content) — nothing was cut from the audit's delete list to close it. Two sub-premises were false and are listed in the PR body: the frontmatter description never contained the ETL claim (body only, lines 24 and 35), and NotifyConfigSchema spans io-node-config.zod.ts:178-258, not :179-218 (re-located by content). AUTO-H-02 was not implemented because it requires a new file, which this card forbids; AUTO-B-04 stays deferred to #14296 item 2, which is why the PR says 'Part of', not a closing keyword. PM-side half-state: the card arrived with assignee already set and 4 labels; I touched neither except to add needs:contract-review. Repo-scoped REST is 403 for this seat (session gate) with the credential alive at 15,000/hr — card and comments were read via the zero-quota public-page payload channel, writes via MCP, and the channel switch is declared here.", "tests": "Baselines on origin/main a98b61b3 before the first edit, all green: check-skills-token-ratchet (SKILL.md 12768/12768 headroom 0, eval 1329/1329 headroom 0), check:skill-compatibility, check:skill-identifier-liveness (Leg 1 490 citations; Leg 2 8 sections), check:skill-examples (265 blocks), check:skill-docs. Built the @objectstack/spec and @objectstack/client-react closures first, under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14308 — VERDICT command-exit 0, held 419s, waited 0s — so check:skill-examples could not false-green on a stale dist. Gate family re-derived AFTER regeneration: 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands' printed 36 commands over the 4 changed paths (change set taken from git, merge base a98b61b3e); ALL 36 were run at head 2926abc9d518b61220ba9dd2e288607cdef43247, each exit code captured by redirecting to a file BEFORE any pipe. Result: 35 exit 0; 1 NOT MEASURED — check-test-completeness.mjs exits 3 with 'PREREQUISITE NOT MET' (it grades a saved turbo test log the derived family gives it no argument for; its own text says this is not a red), recorded as not measured rather than green. Final readings at head: check-skills-token-ratchet 'SKILL.md is 12269 tokens (ceiling 12768; headroom 499)' and 'test-revise-loop.md is 550 tokens (ceiling 1329; headroom 779)', exit 0; check:skill-examples '266 prose examples type-check across 3 surface(s)' exit 0 (265 -> 266, the newly marked block); check:skill-identifier-liveness 'Leg 1: 495 citation(s) ... Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)' exit 0 (490 -> 495: the new identifiers are live); check:skill-docs 'Skill docs in sync' exit 0; check-nul-bytes 'OK (scanned 7902 text file(s) ... no raw ASCII control bytes)' exit 0, plus a direct grep -naP C0 scan of the four changed files, clean. ABLATION on the newly marked os:check block, run on the COMMITTED tree so the restore leg had a real reference: mutated type:'schedule' to type:'schedulez' inside it; mutation proven on disk by blob hash 8824aa3f -> 0019f5e2 (not by the editor's exit code); check:skill-examples went RED, exit 1, with \"error TS2820: Type '\\\"schedulez\\\"' is not assignable to type '\\\"api\\\" | \\\"screen\\\" | \\\"autolaunched\\\" | \\\"record_change\\\" | \\\"schedule\\\"'\" — so the marker really drives a semantic pass. Restored via 'git checkout HEAD -- $REPO_ROOT/skills/...' (absolute path, HEAD named explicitly to bypass the index) under a trap on EXIT INT TERM; restoration proven by blob hash back to 8824aa3f, git diff HEAD empty, and 0 occurrences of the injected token; restore leg re-measured green at 266 blocks, exit 0. No package build is involved in this ablation — the gate reads the skill file directly, so there is no dist leg to preflight, and that is stated rather than assumed. PM mechanical assumptions: (1) CONFIRMED — 'git diff --stat a59f78d HEAD -- skills/objectstack-automation' is empty on my base, and SKILL.md is 1,001 lines, so every audited span was valid; (2) CONFIRMED — the description edit forced BOTH skills/README.md and content/docs/ai/skills-reference.mdx, and the re-derived family grew to 36 with the docs cluster; (3) REFUTED in the binding direction — BINDINGS in check-skill-identifier-liveness.mjs:284-350 registers 8 exhaustive sections and NONE is in objectstack-automation, so the node-type table is not bound and the gateway-row rewrite could not unbind an assertion (checked before the first deletion, and green after); (4) HONOURED — only the schedule-flow example is marked; the notify fence is a config fragment and stays unmarked, with the reason in the PR body.", "mcp_calls": "13 — 3 comments (claim, audit record, this report), 2 search_issues (a known-hit control query first, then the dedupe query), 1 issue create (#14466), 1 create_pull_request, 3 label reads, 2 label writes, 1 pull_request_read for the body read-back. Every card/comment READ went through the zero-quota public-page payload channel instead, because repo-scoped REST is 403 for this seat.", "open_questions": [], "out_of_scope_findings": [ "filed as #14466: [finding] the objectstack-automation reference index routes to the ADR-0020-retired state-machine.zod.ts and omits both per-node config schemas — SKILL_MAP in packages/spec/scripts/build-skill-references.ts:120-129 (audit id AUTO-B-05, deferred by this card's ruling to the spec lane). Deduped against a healthy in-session search; nearest neighbour #14462 is the same defect class for objectstack-ai and is named in the card as a probable single fix. finding label, unassigned, no pm-state, no priority.", "not filed, recorded for triage: objectstack-upgrade carries no pre-ADR-0019 ApprovalProcess.create re-home table, so AUTO-D-03's deleted 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 and rejection', so this is a judgement to confirm rather than a regression; it is listed in the PR body under 'follow-up for objectstack-upgrade'. Every other merge-into anchor was re-verified at head and is equal or stronger (objectstack-data references/data-hooks.md:346 and :358, objectstack-formula SKILL.md:160-172 and :383/:399, objectstack-ui SKILL.md:905)." ] }Labels:
skip-changeset+needs:contract-reviewon the PR,needs:contract-reviewon this card — all read back. The PR label read-back showed one EXTRA label (documentation) that a concurrent labeler added around my whole-group write; nothing was stripped, so no re-attach was needed. PR stays draft (governed face), and the card stays open (AUTO-B-04 deferred to #14296 item 2).
Generated by Claude Code
ACCEPT — PR #14467 @
2926abc9, verified against GitHub, not the report.
Session:session_01LraLgQVGq8egUwfYZpbYt1· seat review in-seat at CONTRACT_REVIEW_TIER (served model readclaude-fable-5-1).Landing form. Draft; first line
Part of #14308(AUTO-B-04 deferred to #14296 item 2 keeps this card open); no closing keyword (guard green). Four files against merge basea98b61b3:skills/objectstack-automation/SKILL.md(+…/−, 590 lines changed),evals/approvals/test-revise-loop.md, and the two generated catalog files whose diff is the description only. Ratchet: SKILL.mdceil(49076 / 4) = 12,269≤ 12,768 (headroom 499); the evalceil(2197 / 4) = 550≤ 1,329; no ceiling raised, no new file (AUTO-H-02's new eval correctly not created), script untouched.CI at
2926abc9: green —Lint & Repo Gatessuccess; Type Check ×5, Test Core 1–6, Build Docs, Governed Surface Queue Guard, single-writer / same-issue / Part-of guards, Spec property liveness, doc links, PR size, Check Changeset all success.Contract review — PASS. Every new claim read at source (base
a98b61b3):- The authored trio vs the BPMN trio:
packages/spec/src/automation/control-flow.zod.ts:41-46namesloop/parallel/try_catchas the canonical construct ids andparallel_gateway/join_gateway/boundary_eventas "author-invisible interchange representations".LoopConfigSchema(:163-219):collection,iteratorVariabledefault'item',indexVariable,maxIterations,body;ParallelConfigSchema(:257-268):branches.min(2), "implicit join at block end";TryCatchConfigSchema(:301-320):try,catch,errorVariabledefault'$error',retry, and the guidance string that there is nofinally. Rows match. notify:NotifyConfigSchemais astrictObjectatio-node-config.zod.ts:178-258;recipientsrequired (string or string[]);titleandtemplatemutually exclusive bysuperRefine;severityclosed enuminfo | warning | critical; the RAW-vs-interpolated note at:160-168(channels,topic,severity,templatenever interpolate);sourceObject/sourceIdpair-or-dropped at:169-172.notify-node.ts:313-325: no messaging service ⇒success: true,output: { delivered: 0, failed: 0, skipped: true },metrics: { acted: 0 }— verbatim. Inbox delivery objectsys_inbox_message(service-messaging/src/inbox-channel.ts).- Capability table: all seven tokens (
automation,triggers,job,queue,approvals,messaging,webhooks) are inplatform-capabilities.ts:31-66. record_changevsautolaunched: the engine binds from the start node'sconfig.triggerType(service-automation/src/engine.ts:2206-2247,record-*→ arecord_changebinding regardless offlow.type); the trigger-readiness lint keys ontype: 'record_change'(validate-flow-trigger-readiness.ts:45,:153,:535).- The two ported flow-filter rules:
interpolateFilter(builtin/template.ts:368-411) — whole-string token, flow variables keep precedence, an unresolved recognised placeholder passes through verbatim (isKnownFilterToken,context-tokens.zod.ts:219), onlyfiltergets the hand-off;validate-flow-template-paths.ts:36-50(severity follows position),:403-424/:427-456(inFilter ? 'error' : 'warning', relation hop needsconfig.expand,:276-290),:59-62(onlyrecord.-prefixed tokens are checkable). - ETL removed at spec 17 (
17.etl-pipeline-layer-retired.ts:7-12); the showcase waiver namestry_catchandwaitas the author-facing equivalents (coverage.ts:299-300);defineJob(job.zod.ts:170),defineWebhook(webhook.zod.ts:245), thejobs/webhooksstack collections (stack.zod.ts:459,:523). - Both
premise_falsecorrections (no ETL in the description;NotifyConfigSchemaspans:178-258) are right.
Labels.
needs:contract-reviewstripped from #14308 and #14467 by this comment's author under the 2026-08-31 ruling; card →documentation,priority:p1,pm:dispatched,domain:skills; PR →size/l,skip-changeset.Next. Reviewers os-zhuang + hotlong requested with
draft: true; the merge is the maintainer's. At merge this card flipspm:dispatched→pm:blockedwithBlocked-by: #14296. Seat ledger: #14466 joins #14462 as the generatorSKILL_MAPdefect class for one spec-lane fix; the pre-ADR-0019ApprovalProcess.createre-home judgement is recorded against objectstack-upgrade.
Generated by Claude Code
- The authored trio vs the BPMN trio:
Round 1 MERGED — PR #14467 landed on
mainat 12:23Z. The card stays open for its second round, claimed in the same stroke.Claim: PM loop round 4 — second round on this card
Session:session_01LraLgQVGq8egUwfYZpbYt1
Branch:claude/issue-14308-automation-eval-stub-removal(fresh fromorigin/main; round 1's branch is merged and is not reused)
Worktree:objectstack-issue-14308-r2
Domain:domain:skills
File surface: DELETEskills/objectstack-automation/evals/README.md(414 tokens — the planned-structure stub AUTO-B-04 deferred); drop its ceiling row fromscripts/check-skills-token-ratchet.mjs(the one edit to that script a flight may make); ⛔ the REAL fixtureskills/objectstack-automation/evals/approvals/test-revise-loop.md(550 tokens after round 1) stays — item 2 keeps real fixtures; ⛔ nothing else
Container & model: S (two-file mechanical deletion under a ruling; no contract claim),mode:subagent,model: sonnet— the floor; the seat reviews the diff by hand
Clause-②: no ⇒ ⛔ noneeds:contract-review
Ruling executed: #14296 item 2 = A (comment 5507419465, 09:27Z) — planned-eval stubs deleted, ceilings step down; quoted in the PR body
Serial constraints cleared: no open PR touchesskills/objectstack-automation/**; the ratchet script is touched only to drop one row (#14564 api, the query round 2 and the i18n flight each drop their own — different lines, merges clean); light flight, no heavy slotLanding form: the ACCEPT ledger above names AUTO-B-04 as the only deferral, so this PR closes the card — first line
Fixes #14308. The linkSKILL.mdcarries to the real fixture stays valid. Governed ⇒ draft;skip-changeset. State stayspm:dispatched.
Generated by Claude Code
Dev claim (os-dev subagent, round 2 on this card).
Session:
session_01LraLgQVGq8egUwfYZpbYt1
Branch:claude/issue-14308-automation-eval-stub-removal(fresh fromorigin/main— round 1's branch is merged, not reused). Empty branch pushed as the write probe; push succeeded, no retry needed.
Worktree:../objectstack-issue-14308-r2, baseorigin/main=7286dd58e806ed321cbdfc23a1c455db8f80b1adRead channel: card, comments, and the #14296 ruling comment (5507419465) all read via
mcp__github__issue_read— no 403 observed on this seat for this run.File surface (hard, per the seat's round-2 claim comment 5509573208): DELETE
skills/objectstack-automation/evals/README.md(planned-structure stub, AUTO-B-04, #14296 item 2); drop its one ceiling row fromscripts/check-skills-token-ratchet.mjs— the only edit to that script; the real fixtureskills/objectstack-automation/evals/approvals/test-revise-loop.mdand its ratchet row stay untouched; ⛔ no other file, no prose edit.Confirmed before touching anything:
evals/README.mdis the planned-structure stub — its "Planned structure" ASCII tree listsevals/approvals/test-quorum-behaviors.md,evals/flows/test-schedule-binding.md,evals/flows/test-decision-edges.md,evals/triggers/test-time-relative.md, none of which exist in the repo;skills/objectstack-automation/SKILL.mdcurrently has zero references toevals/at all, so nothing links to the file being deleted.Following PR #14564 (objectstack-api, same ruling, same shape) as the template.
Generated by Claude Code
- added a commit that references this issue
on Sep 2, 2026 os-dev-report
{ "issue": 14308, "status": "done", "branch": "claude/issue-14308-automation-eval-stub-removal", "pr": "https://github.com/objectstack-ai/objectstack/pull/14578", "premise_still_valid": true, "summary": "Round 2 of #14308, executing the maintainer's ruling on #14296 item 2 (comment 5507419465, 1A 2A 3A 4A): deleted skills/objectstack-automation/evals/README.md, the planned-structure eval stub deferred by round 1 (PR #14467, merged) as AUTO-B-04, and dropped its one ceiling row from scripts/check-skills-token-ratchet.mjs -- the only edit to that script. Verified before touching anything that the README is the stub (its 'Planned structure' ASCII tree names four eval files that do not exist anywhere in the repo) and not a real fixture. The real fixture skills/objectstack-automation/evals/approvals/test-revise-loop.md and its ratchet row (ceiling 1329, currently 550 tokens) are untouched, and skills/objectstack-automation/SKILL.md carries zero references to evals/ so nothing links to the deleted file. Two-file diff only, no prose edit, no new file, no ceiling raised, no other package touched -- following PR #14564 (objectstack-api, same ruling, same shape) as the template.", "tests": "Reverse verification pair (the load-bearing evidence): with the README deleted via git rm but its ratchet row still present, `node scripts/check-skills-token-ratchet.mjs` exits 1 with `cannot read skills/objectstack-automation/evals/README.md -- red, not a skip (#4690)`, matching the header's documented behaviour verbatim. After dropping the row, the same command exits 0: `36 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted` (was 37 before the deletion -- exactly the dropped row); `--self-test` -> `64 cases pass` (the row is keyed by exact relative path; nothing else in the self-test depends on it). Also green pre- and post-edit: `pnpm check:published-readme-links` (176 outbound links, 103/103 relative targets found -- the deleted file was linked from nothing), `pnpm check:skill-compatibility` (11 SKILL.md reconciled against 78 workspace packages), `pnpm check:skill-identifier-liveness` (Leg 1: 484 citations over 46 files; Leg 2: 8 exhaustive sections, 0 gaps -- unaffected by the deletion, the README carried no identifier binding), `pnpm --filter @objectstack/spec check:skill-docs` (Skill docs in sync, no regeneration needed -- neither generated file lists evals/), `node scripts/check-nul-bytes.mjs` (7953 files scanned, clean) plus a direct grep -naP C0-control scan of the changed script file (0 hits). Gate family re-derived AFTER the final commit: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` printed 24 commands (matching the PM's mechanism assumption); ALL 24 run under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14308-r2, at head 81ec9d3d (confirmed equal to the pushed remote head via git fetch + rev-parse), every exit code captured to a file before any pipe. Result: 22 exit 0, 2 NOT MEASURED -- node scripts/check-test-completeness.mjs exits 3 (PREREQUISITE NOT MET, no saved turbo test log to grade -- CI supplies it) and pnpm --filter @objectstack/lint run check:doc-formula-expressions exits 3 (PREREQUISITE NOT MET, @objectstack/formula not built -- this flight touches neither formula nor its docs, so building it just to green a prerequisite would be verification-face padding; CI's own closure build supplies a real reading). Both are the gates' own documented not-a-finding exit code, not treated as red. check:pm-dispatch-gates (the ~19-minute self-test, 1240 cases) passed at exit 0. Full per-command table with result lines is in the PR body.", "mcp_calls": "13 -- 3 issue_read (card get, card comments, #14296 ruling comment), 1 pull_request_read for the #14564 template, 1 add_issue_comment (claim), 2 search_pull_requests (serial-constraint checks on the automation path and the ratchet script path, both 0 open), 1 create_pull_request, 2 pull_request_read (body read-back, label read-back), 1 issue_write (skip-changeset label), 1 issue_read get_labels (errored -- PRs are not resolvable through that method, informational only), 1 add_issue_comment for this report.", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
ACCEPT — round 2, PR #14578 @
81ec9d3d, verified against GitHub, not the report.
Session:session_01LraLgQVGq8egUwfYZpbYt1Diff read by the seat: exactly two files —
skills/objectstack-automation/evals/README.mddeleted (43 lines, the planned-structure stub) and one row removed fromscripts/check-skills-token-ratchet.mjs(['skills/objectstack-automation/evals/README.md', 414]); 44 deletions, 0 additions, one commit. The real fixtureskills/objectstack-automation/evals/approvals/test-revise-loop.mdis still on the branch with its row intact (git ls-treeon the head). No prose touched, no ceiling changed, no other package. The ratchet red → green pair and the 64/64 self-test are the gate's own documented behaviour (#4690).Landing form: draft; first line
Fixes #14308— correct: the round-1 ACCEPT ledger named AUTO-B-04 as this card's only deferral, so the merge closes the card. Labelsdocumentation,size/s,skip-changeset(no contract claim ⇒ noneeds:contract-review, correctly). Ruling quoted (#14296 item 2 = A).CI at
81ec9d3d: green —Lint & Repo Gatessuccess (13:27Z), Type Check ×5, Test Core 1–6, Governed Surface Queue Guard, the single-writer / same-issue / Part-of guards, doc links, PR size, Check Changeset all success.Next. Reviewers os-zhuang + hotlong requested with
draft: true; the merge is the maintainer's. At merge the card closes byFixes; the seat stripspm:dispatchedafterwards.
Generated by Claude Code
Member card of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02, verbatim: 「审核所有的 skills,进行全面的优化。」). Filed by the skills lane seat (session
session_01LraLgQVGq8egUwfYZpbYt1). Read-only audit at objectstackorigin/maina59f78d; 25 findings. Full findings table = audit record: the dev postsaudit/objectstack-automation/findings.md(seat scratchpad) verbatim as the first comment at claim time.Audit summary
SKILL.md1,001 lines / 12,768 tok (headroom 0) ·evals/approvals/test-revise-loop.md1,329 ·evals/README.md414 · generated 835 — package 15,346; all three ratcheted files at zero headroom. Approvals:296-650= 5,246 tok = 41% of the file; the highest-density block ("Valid-but-silently-wrong" pitfalls 6–10,:836-951) starts at 84% depth. Real usage: 4*.flow.ts+ the showcase's 24 flows + jobs + webhooks; zero*.trigger.ts. Node-type frequency:notify20,approval15,screen9,update_record/get_record/decision5,connector_action4,loop3,try_catch2,parallel2,approval_revise1 —parallel_gateway/join_gateway/boundary_event0. 14 real patterns; 12 covered; 2 wholedefineStackcollections (jobs,webhooks) missing. Verdict RESTRUCTURE: wrong control-flow model taught; order inverts value; evals orphaned (grep evals SKILL.md→ 0) and inverted (1,329 tok on the least-used node); the generated index misroutes to the ADR-0020-retiredstate-machine.zod.ts.Top findings
evals/approvals/test-revise-loop.md:23-65vsSKILL.md:382-442evals/README.md:13-43SKILL.md:596,600-606ctx.record" — anchorobjectstack-data/references/data-hooks.mdSKILL.md:971-983os validateblockSKILL.md:800-812277-294SKILL.md:152-164SKILL.md:787-798:228; #2 wrong)SKILL.md:443-459SKILL.md:926-941functionsfence, drop the rationaleSKILL.md:404-409SKILL.md:866-870736-782SKILL.md:895-902SKILL.md:826-835:691):76-77,79,791-792,828-829parallel/try_catch/loop-container rows; mark the*_gateway/boundary_eventtrio as BPMN lowering, not author-facing (control-flow.zod.ts:42-46)SKILL.md:661-676approvals+messaging(notifyreturns success withskipped: truewhen messaging is absent —notify-node.ts:313-320)Incidental falsehoods (fix in this flight)
SKILL.md:24-25,:35— "covers … ETL pipelines" / "designing an ETL pipeline": the L2 ETL layer was removed in spec 17 with no replacement (17.etl-pipeline-layer-retired.ts:7-20); the package declares 17.x and has zero ETL body content. Also the frontmatter/description (AUTO-A-01).SKILL.md:791-792— "Always handle errors. Addboundary_eventnodes": 0 authorings; the showcase's own waiver (coverage.ts:299-300) namestry_catchandwaitas the author-facing equivalents.Three funded additions
notifyconfig fence (AUTO-E-04, +140, paid by AUTO-D-03 + AUTO-D-05) — the 8 keys actually used (recipients13,title10,topic9,message8,severity7,channels7,sourceObject/sourceId4,actionUrl), schemaio-node-config.zod.ts:179-218, plus one "Valid-but-silently-wrong" line for the messaging-absent silent success.Flight scope
IMPLEMENT (shrink-only): rows 1, 3–15 and the findings file at HIGH or MED; the three funded additions; falsehoods 1–2 incl. the description; AUTO-A-02/A-03 (add
jobs/webhooksand screen-flow routing to the description — paid by same-file deletions); AUTO-B-01/B-02 reorder (free — bring the "Valid-but-silently-wrong" block up); link the eval fromSKILL.md.ANCHOR RULINGS: hooks →
objectstack-data/references/data-hooks.md(AUTO-C-02: delete + pointer). The objectstack-query flight points at this package's:157-164flow-filter rule — keep that section stable. Screen flows vs views: this package owns screen flows; objectstack-ui points here.DEFER: AUTO-B-04 (eval stub, #14296 item 2); AUTO-B-05 (generator map
build-skill-references.ts:120-129→ out-of-scope card for the spec lane: dropstate-machine.zod.ts, addbuiltin-node-config.zod.ts/io-node-config.zod.ts).Flight constraints (binding)
Fixes #<this card>; governed ⇒ stays draft; review requests are the seat's step..describe()string ⇒ spec-side twin card.node scripts/check-skills-token-ratchet.mjs,pnpm --filter @objectstack/spec check:skill-examples,pnpm check:skill-compatibility,pnpm check:skill-identifier-liveness, plusnode scripts/pm/dispatch-gates.mjs --commands <changed paths>; record the head sha.needs:contract-reviewon both carriers (the control-flow rows and thenotifysilent-success semantics are contract claims).Refs: #14292 · #14296 · #13658.