Skip to content

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

@os-litant

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 objectstack origin/main a59f78d; 25 findings. Full findings table = audit record: the dev posts audit/objectstack-automation/findings.md (seat scratchpad) verbatim as the first comment at claim time.

Audit summary

SKILL.md 1,001 lines / 12,768 tok (headroom 0) · evals/approvals/test-revise-loop.md 1,329 · evals/README.md 414 · 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: notify 20, approval 15, screen 9, update_record/get_record/decision 5, connector_action 4, loop 3, try_catch 2, parallel 2, approval_revise 1 — parallel_gateway/join_gateway/boundary_event 0. 14 real patterns; 12 covered; 2 whole defineStack collections (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-retired state-machine.zod.ts.

Top findings

# id span proposal Δtok
1 AUTO-H-01 evals/approvals/test-revise-loop.md:23-65 vs SKILL.md:382-442 DELETE the eval's Expected-Output fence + restating Mistakes rows; keep Scenario + Criteria −700
2 AUTO-B-04 evals/README.md:13-43 planned-structure stub (DEFERRED, #14296 item 2) −270
3 AUTO-C-02 SKILL.md:596, 600-606 DELETE hook rows + "There is no ctx.record" — anchor objectstack-data/references/data-hooks.md −208
4 AUTO-B-07 SKILL.md:971-983 DELETE — third statement of pitfalls 6 and 10; keep the os validate block −190
5 AUTO-B-03 SKILL.md:800-812 DELETE 4 of 5 State-Machine BPs — verbatim restatement of Notes 277-294 −150
6 AUTO-D-01 SKILL.md:152-164 REWRITE-AS-CONSTRUCT: "routes / does-not-route" two-cell row −150
7 AUTO-D-06 SKILL.md:787-798 DELETE "Flow Design" BPs (generic; #5 dup of :228; #2 wrong) −137
8 AUTO-D-03 SKILL.md:443-459 DELETE "Re-homing the old process model" (upgrade-skill territory) −225
9 AUTO-D-05 SKILL.md:926-941 REWRITE-AS-CONSTRUCT: keep the functions fence, drop the rationale −130
10 AUTO-D-02 SKILL.md:404-409 DELETE ADR-0044 amendment history (stated 3× more) −115
11 AUTO-B-06 SKILL.md:866-870 MERGE-INTO 736-782 −90
12 AUTO-D-04 SKILL.md:895-902 DELETE spec-17 retirement narration; keep the prescription −110
13 AUTO-D-07 SKILL.md:826-835 DELETE pitfalls 1/2/5 (engine-implementer advice, BPMN, dup of :691) −110
14 AUTO-F-01 :76-77, 79, 791-792, 828-829 ADD parallel/try_catch/loop-container rows; mark the *_gateway/boundary_event trio as BPMN lowering, not author-facing (control-flow.zod.ts:42-46) +120
15 AUTO-F-02 SKILL.md:661-676 REWRITE-AS-CONSTRUCT capability→surface table adding approvals + messaging (notify returns success with skipped: true when messaging is absent — notify-node.ts:313-320) +40

Incidental falsehoods (fix in this flight)

  1. 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).
  2. SKILL.md:791-792 — "Always handle errors. Add boundary_event nodes": 0 authorings; the showcase's own waiver (coverage.ts:299-300) names try_catch and wait as the author-facing equivalents.

Three funded additions

  1. Capability → surface table (AUTO-F-02, +40, paid by AUTO-D-06).
  2. ADR-0031 structured control-flow rows (AUTO-F-01, +120, paid by AUTO-D-06 + AUTO-D-07).
  3. notify config fence (AUTO-E-04, +140, paid by AUTO-D-03 + AUTO-D-05) — the 8 keys actually used (recipients 13, title 10, topic 9, message 8, severity 7, channels 7, sourceObject/sourceId 4, actionUrl), schema io-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/webhooks and 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 from SKILL.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-164 flow-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: drop state-machine.zod.ts, add builtin-node-config.zod.ts / io-node-config.zod.ts).

Flight constraints (binding)

  • ONE draft PR, first line Fixes #<this card>; governed ⇒ stays draft; review requests are the seat's step.
  • Token ratchet: no ratcheted file may grow; additions paid by deletions in the SAME file; ⛔ re-wrap is not payment; ⛔ no ceiling raise; ⛔ no new files; ⛔ do not touch the ratchet script.
  • ⛔ Never edit another package's files; follow-ups in the PR body. Generated files untouched. Regenerate the README index only if a drift gate requires it (report which).
  • Live surface with zero measured usage ⇒ one row pointing at its schema; retired/tombstoned ⇒ delete. A false claim matching a spec .describe() string ⇒ spec-side twin card.
  • Gates: node scripts/check-skills-token-ratchet.mjs, pnpm --filter @objectstack/spec check:skill-examples, pnpm check:skill-compatibility, pnpm check:skill-identifier-liveness, plus node scripts/pm/dispatch-gates.mjs --commands <changed paths>; record the head sha.
  • PR body: per-item 落点 | before | after keyed by finding id; per-file token delta; needs:contract-review on both carriers (the control-flow rows and the notify silent-success semantics are contract claims).

Refs: #14292 · #14296 · #13658.

Activity

  1. self-assigned this
    on Sep 2, 2026
  2. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    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.md untouched (AUTO-B-04 deferred, #14296 item 2); generated references/_index.md untouched; no file deleted ⇒ ⛔ no edit to scripts/check-skills-token-ratchet.mjs; skills/README.md + content/docs/ai/skills-reference.mdx regenerated 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 — --tier reads no path-derived mandate; the content limb applies, compensated by the seat's in-seat review at CONTRACT_REVIEW_TIER
    Clause-②: yes — the ADR-0031 structured control-flow rows, the notify silent-success semantics (skipped: true when messaging is absent), the capability → surface table, and the two flow-filter rules ported from the query flight are contract claims ⇒ needs:contract-review on 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-164 at base) — keep that section addressable, and it now carries two funded additions the query flight deleted on this card's ruling (precedence on config.filter with placeholder pass-through and variable shadowing; the static-checkability split: objectstack validate FAILS 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 inside SKILL.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/main a98b61b3 (seat-measured 07:3xZ); no open PR touches this package; in flight alongside #14305 (ai) and #14307 (upgrade) on disjoint directories

    Decision 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

  3. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    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, base origin/main = a98b61b3ef695431db26097a28ae8e5f1dec8fdf

    Read 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.mdx only 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

  4. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    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 is os:check, i.e. the opt-in marker line check-skill-examples.ts looks for on the
      line directly above a fence.
    • IDENT (AUTO-H-01 row) — in the source this is the angle-bracketed placeholder id that
      stood for each lint rule id inside the grep -rn ... packages/lint/src command.

    Everything else is verbatim.


    Audit — skills/objectstack-automation/ (read-only)

    Pinned ref: objectstack origin/main = a59f78d. The four package files are byte-identical
    between origin/main and 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.md 12,768 12,768 0
    evals/approvals/test-revise-loop.md 1,329 1,329 0
    evals/README.md 414 414 0
    references/_index.md 835 - 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 by sed -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.ts files + examples/app-showcase/src/automation/flows/index.ts (1,759 lines,
    24 flows) + jobs/ + webhooks/. Zero *.trigger.ts files exist anywhere.

    Node-type frequency across every real flow (grep -o "type: '[a-z_]*'" | sort | uniq -c):

    node type usages SKILL.md coverage
    notify 20 1 table row (SKILL.md:97), no config example
    approval 15 355 tokens of tables + 3 examples
    screen 9 1 table row (SKILL.md:100), no example
    update_record / get_record / decision 5 each example + notes
    connector_action 4 1 table row
    assignment / loop 4 / 3 1 table row each
    http / create_record 3 each example (http)
    try_catch 2 absent
    parallel 2 absent
    subflow / script 2 each table row + pitfall 9
    map / wait / delete_record / approval_revise 1 each table rows; approval_revise gets 875 tok
    parallel_gateway / join_gateway / boundary_event 0 3 table rows + BP #2 + pitfall 2

    Approval-config knob frequency: behavior 17, approvers 15, group 21, lockRecord 9,
    minApprovals 2, maxRevisions 2, onEmptyApprovers 2, decisionOutputs 1,
    approvalStatusField 0, escalation/escalateTo/timeoutHours 0, resolveAs 0.


    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:35 Intro: "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 of automation/etl.zod.ts, its four enums and the ETL factory - 9 defs, 27 exported names"), replacement (removed - no protocol surface replaces it, deliberately); packages/spec/src/shared/retry-policy.zod.ts:138 "ETLPipeline.retry did the same until #6414 retired the L2 ETL layer". The package declares compatibility: Requires @objectstack/spec 17.x (SKILL.md:12) and carries zero ETL body content (grep -n ETL SKILL.md -> only 24 and 35). DELETE both 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-5 vs body Frontmatter 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 via defineStack({ jobs }) - packages/spec/src/stack.zod.ts:458) and defineWebhook (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.ts is already listed in this package's own references/_index.md:18. ADD a 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 http node (2) no - this capability text exists nowhere (3) yes, a table HIGH yes (adds published capability text)
    AUTO-A-03 A, F SKILL.md:57, SKILL.md:100 skills/objectstack-ui/SKILL.md:11-13 routes screen flows out to here ("interactive screen flows / wizards (those are *.flow.ts with type: 'screen' - see objectstack-automation)"), and skills/README.md:101-103 repeats it. This package's total screen-flow content is two table rows. Real corpus: 9 type: '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 no message/buttons keys ... description + waitForInput: true is the declared way to pause on a message-only confirmation screen". Schema at packages/spec/src/automation/builtin-node-config.zod.ts:423-455, not in references/_index.md. ADD a screen-node config row-set + the {value,label} / waitForInput pitfall - 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-650 vs 836-951 41% 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, outputVariable holds 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 section 0 (1) yes - reorders what an agent reads first (2) no (3) n/a MED yes (restructures)
    AUTO-B-02 B, D SKILL.md:131-187 Five stacked blockquotes (893 tok) sit between the "Flow Example" heading and the example itself. Only the first (133-139, 131 tok - edges not next, filter is a where map, fields not values, label required) is about the code that follows. The rest are three separate sub-topics (fault edges 399 tok, readonly/runAs 200 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 it 0 (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-812 vs SKILL.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_machine validation rule ... not a workflow metadata type (retired)" <- 249-257; BP2 "A state mapped to [] is a final/dead-end state" <- 257-258 + code comment 272; BP4 "Put guards in a sibling script / conditional rule" <- 284-286; BP5 "Put side-effects ... in a record-triggered Flow (ADR-0019)" <- 286-288. Only BP3 (implicit any->any is lenient) is new. DELETE BP1/2/4/5; MERGE-INTO the 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 (no evals link) grep -n evals SKILL.md -> 0 hits: the eval tree is an orphan, unreachable from the entry file. evals/README.md:17-27 ships 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 by find skills/objectstack-automation -type f (4 files total). :29-43 "Format" and "Contributing" are maintainer instructions shipped to every customer install. DELETE evals/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 rows The 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-level workflow metadata type and object.stateMachines are both gone") and its single surviving door is ai/agent.zod.ts:197 lifecycle, marked [EXPERIMENTAL - not enforced] ... Parsed but no runtime consumer yet. Meanwhile automation/builtin-node-config.zod.ts and automation/io-node-config.zod.ts - the per-node-type config shapes (NotifyConfigSchema, screen fields, http timeoutMs) - are in neither list. Root cause: the generator map at packages/spec/scripts/build-skill-references.ts:120-129. RETIRE-SURFACE (drop state-machine.zod.ts from the map) + ADD the 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-887 vs SKILL.md:736-782 Pitfall 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 a record_change flow 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 a record-* 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/$lt construct (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-983 vs 842-859, 943-949 "Verify your work" restates two pitfalls. 976-978: "Node values take the single-brace flow-template dialect ... no validator checks its call names, so an unknown function is NOT build-checked - it throws FlowExpressionFunctionError at 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 the os validate / os build command 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:42 and 943-946 vs objectstack-formula/SKILL.md:160-205 The 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-946 repeats 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). DELETE the enumeration in SKILL.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-606 vs objectstack-data/references/data-hooks.md:364-376 Cheat-sheet rows 2-3 are object-hook rows ("Object hook handler (ctx) | ctx.input (write payload); ctx.result after the write | ctx.previous"), followed by an 8-line paragraph "There is no ctx.record. HookContext declares input / result / previous / session / ql...". objectstack-data/references/data-hooks.md:364-376 carries the same contract as its own table plus the nuance this file omits (:376 "Action bodies additionally receive ctx.recordId and ctx.record"). Hooks are routed to objectstack-data by this package's own frontmatter (SKILL.md:7-9). DELETE SKILL.md:600-606 and 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:962 vs objectstack-ui/SKILL.md:1878-1897 CRM Blueprint row 4: "Action-to-flow bridge | src/actions/*.actions.ts | Trigger screen flows via Action.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). DELETE row 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-734 vs skills/README.md:87, objectstack-formula/SKILL.md:383,399 "(Salesforce-flavor OLD / NEW were removed in M9.5 and now fault the predicate.)" is the fourth copy: skills/README.md:87 "Legacy OLD / NEW evaluate to null since 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). DELETE the parenthetical -35 (1) no (2) yes (3) formula's translation table is the anchor HIGH no
    AUTO-D-01 D SKILL.md:152-164 212 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_record empty 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 wait here and its 2026-07-28 amendment reversed that - a wait is resumeAuthority: 'any', so a raw POST /api/v1/automation/:name/runs/:runId/resume walked the back-edge with no submitter check and no audit row, and could destroy the run outright." The decision it changes is already stated at 401-404, again at 433-436, and again in the eval's mistakes table. DELETE the 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 (or MOVE-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 inline config.script JS was never executed (no server-side sandbox). ... Stored flows convert with os migrate meta --from 16." The same words already ship inside the spec the agent Reads (packages/spec/src/automation/flow.zod.ts:41-43), and os migrate meta is 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. DELETE the 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 prescription MED yes (retired semantics)
    AUTO-D-05 D SKILL.md:926-941 "The rule is load-bearing: a script step 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 report acted: 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). The effect: '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-line defineStack({ 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_record over multiple http calls" are generic engineering advice changing no ObjectStack keystroke. #5 "Always set timeoutMs on http nodes. Unset means no timeout at all" duplicates the in-example comment at SKILL.md:228. #2 "Add boundary_event nodes for timeout and error scenarios" is actively wrong guidance - see AUTO-F-01. DELETE the whole subsection -137 (1) no (2) yes (3) n/a HIGH no
    AUTO-D-07 D SKILL.md:826-835 Common Pitfalls 1-5 (144 tok). #1 "Circular flow references. ... Use a depth counter or visited set to detect cycles" is engine-implementer advice - a metadata author has no such lever, and the platform already enforces a nesting ceiling (referenced at SKILL.md:158). #2 is BPMN-interop (AUTO-F-01). #5 "Scheduled flows without idempotency" is restated at SKILL.md:691. DELETE #1, #2, #5; MERGE-INTO the 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-35 The 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 condition to narrow when the trigger fires" restates the code comment at SKILL.md:722 and the prose at 655-659. #2 (guard record-after-update self-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 marked packages/spec/scripts/check-skill-examples.ts:18-23: "this gate is opt-in: a self-contained, should-compile block is marked by a OS-CHECK-MARKER HTML comment on the line directly above its fence." Measured: 13 TypeScript fences (10 typescript at 114/188/259/310/420/522/543/667/709/749, 3 indented ts 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. ADD markers to the two blocks that can be made self-contained (schedule flow 188-239, record-change trigger 709-729) with their import { 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-676 Unmarked fences that would fail a type-check if marked: (a) 310, 709, 749 use the cel`...` tag with no import (grep -n "^import" SKILL.md -> one hit, line 544, inside the marked block); (b) 709-729 omits edges, which FlowSchema requires (packages/spec/src/automation/flow.zod.ts:659 - no .optional()), so FlowSchema.parse rejects it; (c) 667-676 calls defineStack({...}) with no import. None is false - each is a legitimate fragment - but (b) reads as a whole flow (it has name/label/type/nodes), which is the shape an agent copies. REWRITE-AS-CONSTRUCT - make 709-729 a 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 notify nodes across 9 flows) - no example, no config keys; (2) approval chain (15 approval nodes, 8 flows) - 3 examples OK; (3) scheduled sweep / digest (5 type:'schedule'; flows/index.ts:362,1619; jobs/index.ts:16) - 1 flow example OK, no defineJob; (4) screen wizard (9 screen) - no example; (5) outbound integration (connector_action 4, http 3, defineWebhook 1) - http inside one example, connector_action no example, defineWebhook absent. 2 of 5 top tasks have no canonical example; a 3rd is half-covered. ADD a 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 of notify) notify is 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'" over examples/): recipients 13, title 10, topic 9, message 8, severity 7, channels 7, sourceObject/sourceId 4, 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 no messaging service registered the executor logs "[notify] no messaging service registered; notification ... not delivered" and returns success with output: { delivered: 0, failed: 0, skipped: true }. Textbook material for this package's own "Valid-but-silently-wrong" section. ADD an 8-line notify config 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-829 The package teaches only the BPMN-interop control-flow trio and never mentions the ADR-0031 structured constructs. Measured usage in examples/: parallel_gateway 0, join_gateway 0, boundary_event 0; parallel 2 (flows/index.ts:929, 1207), try_catch 2 (:1009, 1226), loop container 3, map 1. 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 structured parallel container (FanOutNotifyFlow)"; "boundary_event: BPMN-interop form; the author-facing equivalents the showcase demos are the ADR-0031 try_catch container (ResilientSyncFlow) and wait timers". 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.ts reaches references/_index.md:23 only as a transitive dependency. ADD 3 rows to the Control-Flow node table (parallel / try_catch / loop with config.body, plus "the *_gateway / boundary_event trio is BPMN-interop lowering, not author-facing") + DELETE BP #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 triggers capability" lists requires: ['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-107 documents them inline: "approvals - ApprovalsServicePlugin, so the approval flow node (ADR-0019) is contributed to the engine"; "messaging - MessagingServicePlugin, so the notify node delivers to the inbox channel (sys_inbox_message rows) 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->notify delivery; 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: approvalStatusField 0 (yet promoted as Approval Best Practice #2, SKILL.md:641-643), escalation/escalateTo/timeoutHours 0 (SKILL.md:619), resolveAs 0 (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')) and packages/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-43 vs 554, 573 + corpus The package instructs "Use the P`...` and cel`...` tagged templates from @objectstack/spec" for "Every condition / guard / entryCondition / filter value in this skill", then uses cel` in 8 places (329, 366, 372, 374, 524, 527, 533, 723) and plain strings in its only type-checked block (SKILL.md:554 condition: "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; the cel`...` 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, 712 vs corpus Both record-change examples declare type: 'record_change'. The corpus overwhelmingly declares type: 'autolaunched' with the same start-node binding: 16 flows in examples/app-showcase/src/automation/flows/index.ts pair type: 'autolaunched' with a record-* triggerType, versus 1 using type: 'record_change' (:1683). Not a falsehood - the engine derives the binding from the start node regardless (packages/services/service-automation/src/engine.ts:2169-2189 resolveTriggerBinding) and a lint rule does key on record_change (packages/lint/src/validate-flow-trigger-readiness.ts:604-631) - but the package never says the two coexist, and its own eval uses autolaunched (evals/approvals/test-revise-loop.md:27) against its own examples. ADD one clause to the record_change Flow-Types row ("autolaunched + a record-* start binding behaves identically; record_change additionally 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) vs SKILL.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 single approval_revise node). The eval restates the SKILL section rather than testing beyond it: the canonical shape (eval 23-50 ~ SKILL.md:420-431), the four lint findings (eval 59-65 ~ SKILL.md:433-441), the wait-vs-approval_revise amendment rationale (eval 61 ~ SKILL.md:404-409), the same showcase pointer (eval 52-53 ~ SKILL.md:440-441). By contrast notify (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 four flow-approval-revise-* plus flow-error-label-not-fault, flow-date-equality-filter), so no rubric row would teach a grader to fail a correct answer. DELETE the 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-wide The 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), filter as a where map vs UI filter triples (SKILL.md:135-138), unguarded decision edges running in parallel (SKILL.md:343-346), runAs: 'system' for readonly writes (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, one test-decision-edges eval (already listed as planned at evals/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.md in 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 at packages/spec/src/shared/retry-policy.zod.ts:86,138. The package declares compatibility: Requires @objectstack/spec 17.x. Filed as AUTO-A-01.
    SKILL.md:791-792 Best Practice: "Always handle errors. Add boundary_event nodes for timeout and error scenarios." boundary_event has 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-0031 try_catch container ... and wait timers" (examples/app-showcase/src/coverage.ts:299-300); packages/spec/src/automation/control-flow.zod.ts:42-46 calls 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

  5. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    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-review on the PR, needs:contract-review on 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

  6. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    ACCEPT — PR #14467 @ 2926abc9, verified against GitHub, not the report.
    Session: session_01LraLgQVGq8egUwfYZpbYt1 · seat review in-seat at CONTRACT_REVIEW_TIER (served model read claude-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 base a98b61b3: 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.md ceil(49076 / 4) = 12,269 ≤ 12,768 (headroom 499); the eval ceil(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 Gates success; 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-46 names loop / parallel / try_catch as the canonical construct ids and parallel_gateway / join_gateway / boundary_event as "author-invisible interchange representations". LoopConfigSchema (:163-219): collection, iteratorVariable default 'item', indexVariable, maxIterations, body; ParallelConfigSchema (:257-268): branches .min(2), "implicit join at block end"; TryCatchConfigSchema (:301-320): try, catch, errorVariable default '$error', retry, and the guidance string that there is no finally. Rows match.
    • notify: NotifyConfigSchema is a strictObject at io-node-config.zod.ts:178-258; recipients required (string or string[]); title and template mutually exclusive by superRefine; severity closed enum info | warning | critical; the RAW-vs-interpolated note at :160-168 (channels, topic, severity, template never interpolate); sourceObject / sourceId pair-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 object sys_inbox_message (service-messaging/src/inbox-channel.ts).
    • Capability table: all seven tokens (automation, triggers, job, queue, approvals, messaging, webhooks) are in platform-capabilities.ts:31-66.
    • record_change vs autolaunched: the engine binds from the start node's config.triggerType (service-automation/src/engine.ts:2206-2247, record-* → a record_change binding regardless of flow.type); the trigger-readiness lint keys on type: '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), only filter gets the hand-off; validate-flow-template-paths.ts:36-50 (severity follows position), :403-424 / :427-456 (inFilter ? 'error' : 'warning', relation hop needs config.expand, :276-290), :59-62 (only record.-prefixed tokens are checkable).
    • ETL removed at spec 17 (17.etl-pipeline-layer-retired.ts:7-12); the showcase waiver names try_catch and wait as the author-facing equivalents (coverage.ts:299-300); defineJob (job.zod.ts:170), defineWebhook (webhook.zod.ts:245), the jobs / webhooks stack collections (stack.zod.ts:459, :523).
    • Both premise_false corrections (no ETL in the description; NotifyConfigSchema spans :178-258) are right.

    Labels. needs:contract-review stripped 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 flips pm:dispatched → pm:blocked with Blocked-by: #14296. Seat ledger: #14466 joins #14462 as the generator SKILL_MAP defect class for one spec-lane fix; the pre-ADR-0019 ApprovalProcess.create re-home judgement is recorded against objectstack-upgrade.


    Generated by Claude Code

  7. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    Round 1 MERGED — PR #14467 landed on main at 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 from origin/main; round 1's branch is merged and is not reused)
    Worktree: objectstack-issue-14308-r2
    Domain: domain:skills
    File surface: DELETE skills/objectstack-automation/evals/README.md (414 tokens — the planned-structure stub AUTO-B-04 deferred); drop its ceiling row from scripts/check-skills-token-ratchet.mjs (the one edit to that script a flight may make); ⛔ the REAL fixture skills/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 ⇒ ⛔ no needs: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 touches skills/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 slot

    Landing form: the ACCEPT ledger above names AUTO-B-04 as the only deferral, so this PR closes the card — first line Fixes #14308. The link SKILL.md carries to the real fixture stays valid. Governed ⇒ draft; skip-changeset. State stays pm:dispatched.


    Generated by Claude Code

  8. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    Dev claim (os-dev subagent, round 2 on this card).

    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14308-automation-eval-stub-removal (fresh from origin/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, base origin/main = 7286dd58e806ed321cbdfc23a1c455db8f80b1ad

    Read 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 from scripts/check-skills-token-ratchet.mjs — the only edit to that script; the real fixture skills/objectstack-automation/evals/approvals/test-revise-loop.md and its ratchet row stay untouched; ⛔ no other file, no prose edit.

    Confirmed before touching anything: evals/README.md is the planned-structure stub — its "Planned structure" ASCII tree lists evals/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.md currently has zero references to evals/ 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

  9. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    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

  10. os-litant commented on Sep 2, 2026

    @os-litant
    CollaboratorAuthor

    ACCEPT — round 2, PR #14578 @ 81ec9d3d, verified against GitHub, not the report.
    Session: session_01LraLgQVGq8egUwfYZpbYt1

    Diff read by the seat: exactly two files — skills/objectstack-automation/evals/README.md deleted (43 lines, the planned-structure stub) and one row removed from scripts/check-skills-token-ratchet.mjs (['skills/objectstack-automation/evals/README.md', 414]); 44 deletions, 0 additions, one commit. The real fixture skills/objectstack-automation/evals/approvals/test-revise-loop.md is still on the branch with its row intact (git ls-tree on 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. Labels documentation, size/s, skip-changeset (no contract claim ⇒ no needs:contract-review, correctly). Ruling quoted (#14296 item 2 = A).

    CI at 81ec9d3d: green — Lint & Repo Gates success (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 by Fixes; the seat strips pm:dispatched afterwards.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationdomain:skillspriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions