Skip to content

docs(skills): objectstack-automation says a paused screen's Next / Submit and step count are engine-served - #26812

Merged
os-zhuang merged 1 commit into
mainfrom
claude/project-thread-whp6tx
Oct 27, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/project-thread-whp6tx

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread

Fixes #26756

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:skills/objectstack-automation/SKILL.md 的 screen 节点行加一句:「下一步 / 提交」按钮和「第 N 步,共 M 步」不是作者写的,是引擎在屏幕暂停时读流程图给出的 progress(nextScreen none / possible / certain,只有每条路径一致时才带 step / stepCount);屏幕后面接 decision、fault 边、回环、非屏幕暂停(approval、wait)或 subflow 一律答 possible(显示「下一步」、不计步);节点 config 里写 progress 会被拒,也不要把按钮文字或步数手写进 fields。
  • 为什么改:PR feat(automation): a paused screen says whether another screen follows, and the flow runner reads Next or Submit and counts steps #26752 落地后运行时已经这样服务,但技能没教,按技能写向导的 agent 会手搓「提交」标签或「第 2 步」字段,或试图在屏幕节点上写 progress,没有任何门禁拦它。
  • 风险与回滚:只改已发布技能文本、token 上限行与一份 patch changeset,无 schema、键或行为变化;回滚即 revert 本 PR。
  • 先看:skills/objectstack-automation/SKILL.md 第 91 行的 screen 行(新增句),scripts/check-skills-token-ratchet.mjs 的 automation 行(6358 → 6466,算术在注释里),.changeset/26756-automation-skill-screen-progress.md。
  • 两分钟验证:node scripts/check-skills-token-ratchet.mjs,预期 skills/objectstack-automation/SKILL.md is 6466 tokens (ceiling 6466; headroom 0)。
  • 需要你做的:批准本 PR(skills/** 为 Tier H,需 GOVERNED_APPROVERS 的 APPROVED review;本 PR 保持 draft,席位不 ready / 不入队)。

What changes

  • skills/objectstack-automation/SKILL.md, the screen node row (the delta's "~L91" choice over L48: the node row is where an author declares config.fields[], so it is where a hand-rolled label or counter would be written). One addition, in the row's own register: Next / Submit and "Step N of M" are not authored — when the screen pauses the engine reads the graph and serves progress (nextScreen: 'none' | 'possible' | 'certain'; step / stepCount only when every path agrees), which alone labels the button and draws the counter; a decision, fault edge, loop back, non-screen pause (approval, wait) or subflow after a screen answers possible — "Next", no count; progress in a node config is refused; never hand-roll a button label or step counter into fields. Every key and value is read off origin/main: ScreenProgressSpec in packages/spec/src/contracts/automation-service.ts, its wire shape screenProgressSpecShape in packages/spec/src/api/automation-api.zod.ts, the engine's readScreenProgress in packages/services/service-automation/src/builtin/screen-nodes.ts (plain reachability for none, fewest surely-pausing screens for certain, else possible; counts only when exact), the runner's reading in ui/packages/app-shell/src/views/FlowRunner.tsx (certain / possible → Next, none → Submit, counter only with both step and stepCount), and ScreenConfigSchema in packages/spec/src/automation/builtin-node-config.zod.ts (a strictObject, so an authored progress is a named parse error, not a silent drop).
  • Paid under the standing ruling 「A:先削重复,余额按实测提高」 — fold restated wording first, then re-pin the ceiling at the measurement. Three restatements folded, each with its surviving home named:
    • Filter-operands bullet, "every other {…} token is refused, and" (-42 bytes) — Valid-but-silently-wrong item 1 lists "every CRUD filter operand" among the slots where a {…} token is refused. The trimmed bullet is re-wrapped (-2 bytes of indentation whitespace; the wrap bought nothing, the row's addition is paid by the cuts and the raise).
    • Trigger Configuration lead-in, "The binding is the START NODE — this is that node" → "This is the start node alone" (-23 bytes) — the Triggers intro already says the binding lives entirely in the flow's start node config, and the heading says "on the start node".
    • Valid-but-silently-wrong item 3, "; flow functions don't" (-22 bytes) — the item's own bold lead says a flow function does NOT read/write the database.
  • scripts/check-skills-token-ratchet.mjs: the automation row moves 6358 → 6466, pinned AT the measurement, with the arithmetic in the row comment: 25429 → 25864 priced bytes (+524 added, -89 cut, +435 net) → ceil(25864 / 4) = 6466; headroom was 3 bytes (0 tokens), so the ceiling moves +108.
  • .changeset/26756-automation-skill-screen-progress.md: @objectstack/skills patch (the catalog ships from skills/**), both declaration lines at line start.
  • No eval prompt. evals/flows-triggers-approvals.json measures 2734 tokens against a 2734 ceiling (headroom 0), so a prompt fits only with a raise, which the card excludes; said here and in the report.

Skills readings (whole file and whole package)

Reading Before (origin/main 8b27638) After (270df42)
skills/objectstack-automation/SKILL.md lines 452 451
skills/objectstack-automation/SKILL.md tokens (priced, stamp excluded) 6358 6466
All 11 skills/*/SKILL.md lines 4606 4605
All 11 skills/*/SKILL.md tokens (ceil bytes/4, stamp included) 56135 56243

Why

Once #26752 landed, a paused screen carries an engine-served progress, and the Console's FlowRunner labels the button Next or Submit and draws "Step N of M" from it. An agent authoring a wizard from the skill was told none of this: it could hand-roll a label or a counter into fields, or author progress on the screen node, and the skill did not say the runtime answers both from the graph. The docs half landed in #26752 (content/docs/automation/flows.mdx); this is the owed skill half.

Tests

No test file changes: the diff is published skill text, a ratchet row and a changeset. node scripts/check-skills-token-ratchet.mjs and its --self-test pass on the head (readings under Verification).

Acceptance notes

  • The eval file's headroom 0 is why no eval prompt is added; a later card that raises that file's ceiling under the same ruling can add one asserting that an answer never spells a "Submit" / "Next" label or a step counter into fields.
  • origin/main moved to 0f0b9f5 after this branch was cut; dispatch-gates reports none of the visible upstream commits touched what the gate list derives from, so main is not merged in (AGENTS.md §10: merge only on a reported conflict, a main-caused red or a queue removal).

Verification

Local verification on head 270df422 (worktree objectstack-issue-26756, base origin/main 8b27638):

  • Build closure: bash scripts/pm/os-verify-lock.sh -c "pnpm exec turbo run build --concurrency=2 --filter='./packages/**'" → VERDICT command-exit 0, 75/75 tasks, 8m43s under the lock (needed for the dist-reading gates below).
  • Derived gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 63 commands from the 3-path change set; each ran serially with stdin closed and its exit code captured before any pipe; every one exited 0. Reconciliation: dispatch-gates --ran → "63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN".
Readings worth quoting
  • node scripts/check-skills-token-ratchet.mjs → skills/objectstack-automation/SKILL.md is 6466 tokens (ceiling 6466; headroom 0); 81 authored bundle file(s) within their ceilings; --self-test exit 0.
  • pnpm --filter @objectstack/spec run check:skill-docs → ✓ skills/README.md, ✓ content/docs/ai/skills-reference.mdx.
  • node scripts/check-empty-changeset.mjs --base origin/main → 1 declaring changeset(s) added, none from the merge base modified.
  • pnpm check:pm-skill-id-lint, pnpm check:doc-authoring, pnpm check:nul-bytes, pnpm check:skill-compatibility, pnpm check:skill-frame-sync, pnpm check:skill-identifier-liveness, pnpm --filter @objectstack/lint run check:doc-formula-expressions, pnpm check:dual-build-cjs-loads, pnpm check:dts-closure, pnpm check:pm-dispatch-gates: exit 0 each.
  • Model tier line (dispatch-gates --tier): MANDATORY — skills/**, clause ①, no one-line exit; changed lines 48 (+40 / -8) vs the 3000 threshold.
  • CI: pnpm lint and the repo-wide farm are CI's runs; the PR's check-runs are the record for them.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (No schema touched.)
  • 2. Every name I added uses the casing for its kind. (No new identifiers; the keys named are the spec's own.)
  • 3. No formatter ran; pnpm lint is CI's run (not in the derived local list).
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: n/a.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English (the maintainer digest is Chinese by AGENTS.md › Communication).
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ADHkmS7nPHShBb87HjHRf4

…bmit and step count are engine-served

The `screen` node row of skills/objectstack-automation/SKILL.md now says
that Next / Submit and "Step N of M" are not authored: when a screen pauses
the engine reads the flow graph and serves `progress` (`nextScreen`
`none` / `possible` / `certain`; `step` / `stepCount` only when every path
agrees), and the runner labels the button and draws the counter from that
alone. A `decision`, a `fault` edge, a loop back, a non-screen pause or a
`subflow` after a screen answers `possible` ("Next", no count). A
`progress` key in the node config is refused; a hand-rolled label or
counter in `fields` is wrong.

Paid under the standing ruling: three restatements folded first (the
Filter-operands refusal clause, the Trigger Configuration lead-in, item
3's "flow functions don't"), then the token ceiling re-pinned at the
measurement (6358 -> 6466) with the arithmetic in the row comment. Patch
changeset for @objectstack/skills. No eval prompt: the eval file sits at
headroom 0.

Claude-Session: https://claude.ai/code/session_01ADHkmS7nPHShBb87HjHRf4
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tooling labels Oct 27, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT · domain:skills#1 · session_01ADHkmSrRBdu9MdC6fc33Uu · head 270df422 · 2026-10-27T17:22Z

  1. 形态 — Tier H (skills/**): the screen node row of skills/objectstack-automation/SKILL.md (L91) gains the teaching that Next / Submit and "Step N of M" are engine-served from progress, never authored; scripts/check-skills-token-ratchet.mjs row 6358 → 6466 at the measurement; patch changeset for @objectstack/skills. No eval prompt (flows-triggers-approvals.json sits at headroom 0, said in the PR).
  2. 前提实测 — the seat read origin/main: service-automation/src/builtin/screen-nodes.ts:185 serves nextScreen, :266–273 return step / stepCount only when the graph neither fans out nor loops. The three cut restatements each keep a home the reader reads: item 1 (L238–245) refuses a {…} token in every CRUD filter operand; the Triggers intro (L336) puts the binding on the start node config; item 3's lead (L273) says a script node only calls a registered function.
  3. 门禁 check-runs — dev ran the 63 derived families on the head, all exit 0 (--ran 63/63, 0 UNRUN, 0 NOT-MEASURED); build closure VERDICT 0. CI on the head is read again before landing.
  4. 接受的偏差 — the platform branch name (recorded in the claim); origin/main moved after the derivation and was not merged in (the derivation's surface did not change). Payment follows the standing ruling 「A:先削重复,余额按实测提高」: 89 B cut first, then raised by the measured remainder, arithmetic in the row comment.
  5. 范围外去向 — none. Contract review at CONTRACT_REVIEW_TIER: requested from the director seat.
  6. 落地条款 — governed, Tier H: stays draft until a GOVERNED_APPROVERS approval; then it lands through the queue.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 270df422512b9c5b9afda3a89f4666bc9d5eaa62
Local-runs: none
Scope: skills/objectstack-automation/SKILL.md + scripts/check-skills-token-ratchet.mjs, .changeset/26756-automation-skill-screen-progress.md, packages/spec/src/contracts/automation-service.ts, packages/spec/src/api/automation-api.zod.ts, packages/services/service-automation/src/builtin/screen-nodes.ts, packages/spec/src/automation/builtin-node-config.zod.ts, ui/packages/app-shell/src/views/FlowRunner.tsx, content/docs/automation/flows.mdx

Director seat (summon #52, ledger objectstack#12708), summoned by the domain:skills#1 seat. Read-only at the head above: the diff, card #26756 (filing gate ①, the skill half owed by #26752), the seat's ACCEPT 6448715005, the skill file as stored at this head and on origin/main 0ea90c7a, the cited spec, zod, engine, runner and docs lines on main, the head's check runs. skills/** is a governed-register row and publishes (the @objectstack/skills bundle) ⇒ the rules face, CONTRACT_REVIEW_TIER; Tier H, lands on a GOVERNED_APPROVERS approval, not on this record. Served at CONTRACT_REVIEW_TIER. The seat records; it does not approve, ready, queue or merge.

① Derived judgments

  • The added sentence states the published contract, key for key. ScreenProgressSpec (automation-service.ts:428): nextScreen: 'none' | 'possible' | 'certain', step? / stepCount? "present only when every path … pauses on the same number of screens"; its doc comment names the 'possible' causes in the skill's own order — "a branch (a decision, a fault path, a loop back), a pause that serves no screen, or a subflow". The wire shape screenProgressSpecShape (automation-api.zod.ts:264) says the same. The engine (screen-nodes.ts:116 readScreenProgress) serves it from the top-level graph: 'none' when no successor serves a screen, 'certain' when the fewest surely-pausing screens before any stop is ≥ 1, else 'possible' (:185–187); counts dropped on any fan-out or loop (:266), stepCount only with an exact remainder (:273). The runner (FlowRunner.tsx:235–252) reads certain / possible → Next, none → Submit, the counter only with both numbers, and ⛔ never walks the graph. ScreenConfigSchema (builtin-node-config.zod.ts:1211) is a strictObject whose keys are title, description, fields, waitForInput, objectName, idVariable, mode, recordId, defaults — no progress, so an authored one is a named refusal. The docs half (flows.mdx:1347–1351) lists the same three values with the same causes. Nothing in the sentence is invented.
  • The three cuts are restatements with a surviving home, as the seat read. "every other {…} token is refused, and" — Valid-but-silently-wrong item 1 (main L238–245) refuses a {…} token in "every CRUD filter operand", at validate, register and execute. "The binding is the START NODE — this is that node" — the Triggers intro (L335–336) says the binding "lives entirely in the flow's start node config" and the heading (L383) says "on the start node". "; flow functions don't" — item 3's own bold line (L282) says "A flow function is a PURE compute step — it does NOT read/write the database". Each cut removes a repeat; no assertion leaves the file.
  • Arithmetic verified at the head. Stored file 25884 bytes, stamp line (version: "18.2.0") 20 bytes ⇒ 25864 priced; main 25449 − 20 = 25429. The screen row grows 1081 → 1605 bytes (+524); the three hunks shrink 994 → 905 (−89); net +435 = 25864 − 25429. ceil(25864 / 4) = 6466, pinned at the measurement, headroom 0, the tap quoted verbatim in the row comment. The head's own ratchet row reads 6466.
  • No eval prompt, correctly declared. evals/flows-triggers-approvals.json is at headroom 0 and the card says "only if it fits under the file's ceiling" — the omission is the card's own clause, said in the PR body and the changeset.

② Semver level

@objectstack/skills takes a patch changeset, both declaration lines present at line start and equal to the PR body's. Skill text only; no schema, key or behaviour moves — patch is right.

③ Boundary flags

  • Governed path (skills/**, Tier H): no review yet; draft. This seat's account is not a GOVERNED_APPROVERS member; this record is not an approval and does not lift Tier H.
  • Check runs on 270df422 at this record: 26 success (incl. Governed Surface Queue Guard, Check Changeset, Lint · repo & tooling gates — home of the token ratchet — and both Type Checks), 11 expected skips, Test Core (1/8) still in_progress. Nothing red; a red there re-opens this record.
  • origin/main has moved past the branch's base (now 0ea90c7a); none of the commits since 8b276385 touch skills/objectstack-automation/ or the ratchet script, so the readings above hold against today's main and no merge-in is owed.
  • Note, not a finding: the engine is finer than the published words in one corner — an exclusive decision with a default edge whose every branch surely pauses on a screen computes 'certain', while the spec's doc comment, the zod description, flows.mdx and now this skill all say a branch answers 'possible'. The skill repeats the contract as the spec publishes it, which is the right source for a skill; the looseness belongs to feat(automation): a paused screen says whether another screen follows, and the flow runner reads Next or Submit and counts steps #26752's spec wording, already landed and PASSed (6444906744), and changes nothing an author should do.
  • Dev deviations: the platform branch name; main not merged in (judged above). No gate reads the prose; the green proves the ratchet, the changeset and the doc gates, not that an agent stops hand-rolling a label.

④ Design judgment

  • skills/objectstack-automation/SKILL.md screen row against the main premise (screen-nodes.ts:185, :266–273; ScreenProgressSpec): the row is where an author declares config.fields[], so it is the right home — a hand-rolled "Submit" label or "Step 2 of 4" field would be written exactly there, and the sentence refuses both where they would be typed. The engine-serves-it framing matches the contract's own rule that only the graph-holder answers; naming the 'possible' cases gives an author the one thing they would otherwise guess (why their wizard says "Next" with no count after a branch). The strict-config refusal of progress is read off the schema, not asserted. Holds; nothing to break. The cuts fold repeats into homes the reader still passes on the way to the same facts.

Implemented-by: claude/project-thread-whp6tx
Reviewed-by: session_01ADHkmQr732toX135tyo5zs

VERDICT: PASS


Generated by Claude Code

@os-zhuang
os-zhuang enabled auto-merge October 27, 2026 22:50
@os-zhuang
os-zhuang added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit e269d3b Oct 27, 2026
40 checks passed
@os-zhuang
os-zhuang deleted the claude/project-thread-whp6tx branch October 27, 2026 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tooling

Projects

None yet

3 participants