Skip to content

fix(service-automation): a corrupt correlation cycle back to the resumed run no longer names that run as its own child - #28101

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-2p9rtc
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-2p9rtc

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Elon · project thread
Part of #27971 — this PR carries the rider (comment 6516883756) and the docs half only. The card's main fix (recording a cancelled map item on a parent-id resume) waits on the maintainer's ruling (decision analysis 6523020455) and is not in this PR.

Clause-②: no
Metadata-protocol: none
Skills-docs: none — skills/** names neither RESUME_CHILD_PENDING nor map cancellation; under content/docs/** the code appears only in the generated references/api/ pages (automation-api, contract, error-code-ledger), which already list it.

维护者速读

  • 改了什么:恢复闸门沿关联 run 链往下走时,先把调用方自己的 run 记为已访问;另在客户端注释、README、QA 清单补上 409 RESUME_CHILD_PENDING。
  • 为什么改:关联数据损坏成 A→B→A 环时,拒绝信息会让调用方去恢复它正在恢复的那个 run,指错了门。
  • 风险与回滚:只影响损坏的环形关联;正常链路的遍历结果不变。回滚即还原 engine.ts 里那一行。
  • 先看:packages/services/service-automation/src/engine.ts(resolveSuspensionChain 的 seen 初值)、src/map-parent-resume-refusal.test.ts(新环形用例)。
  • 两分钟验证:pnpm --filter @objectstack/service-automation exec vitest run --maxWorkers=2 src/map-parent-resume-refusal.test.ts,预期 6 个用例全绿。
  • 需要你做的:无,席位落地。service-automation: a parent-id resume of a map whose parked item run was cancelled still advances past that item #27971 主修复的形状另在卡上等你裁决。

What changes

  • Rider 6516883756. resolveSuspensionChain (service-automation/src/engine.ts) seeds its seen set with the caller's run id before the walk. A corrupt correlation cycle A → B → A used to yield the chain [A, B, A], and the 409 RESUME_CHILD_PENDING refusal then told the caller to resume A, the run it was already resuming. The chain now ends at B and the refusal names B.
  • Docs half. 409 RESUME_CHILD_PENDING is added to the client resume() docblock's list of refusals that leave the suspension intact (packages/client/src/index.ts), to the service-automation README's code list, and to the automation checklist item automation.trigger-status-contract (acceptance[4], a new variant row, history revision 9).
  • Changeset: @objectstack/service-automation patch.

Tests

  • New pin in map-parent-resume-refusal.test.ts: names the item run, never the caller's own, when a corrupt correlation cycles back to the caller. It points the item's row back at its parent (map:PARENT), resumes the parent, and asserts the code, that the message names the item run and not the parent, and that the map state did not move.
  • Ablation (fix committed first; the test imports ./engine.js from src, so no dist is on the path): scripts/ablation-replace.mjs replaced the seeded constructor with an empty one (anchor x1 → x0, blob c3ff057c → 43ab85a7); the new pin went red (1 failed, 5 passed); the restore matched the HEAD blob c3ff057c and git diff HEAD was empty.

Acceptance notes

  • Measured on main f6adf48 for the card's main half (not changed here): after cancelRun on a parked map item, a parent-id resume advances past it. The parent completes, a downstream node sees results holding only item 2's output, and count is 1.
  • No stock showcase flow reaches 409 RESUME_CHILD_PENDING: showcase_release_signoff's item parks on an approval, which answers 403 first. The new checklist variant says so.

Verification

Package suite and typecheck at 24787ee

pnpm --filter @objectstack/service-automation test: Test Files 226 passed (226), Tests 2863 passed (2863). pnpm --filter @objectstack/service-automation typecheck: check:test-typecheck OK, 0 errors. The head after that commit only adds the changeset.

Derived gate families (dispatch-gates --commands, reconciled with --ran)

67 derived families: 66 ran with exit 0 and 1 is NOT MEASURED. 58 of them ran at 24787ee; the 9 changeset families the changeset added ran at 1b77a96. check-plugin-teardown-shape --self-test was re-run after fetching its pinned positive-control commit, and check:skill-examples after building @objectstack/client-react and its dependencies; both exit 0. NOT MEASURED: pnpm check:dual-build-cjs-loads exited 3 (prerequisite): it reads the dist/ of about 40 packages, apps and adapters included, that this container did not build. CI's run is the reading for it. node scripts/check-platform-checklist.mjs --changed-from origin/main: exit 0, 14 anchors judged, 0 lost. pnpm lint is a repo-wide scan owned by CI.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (not touched)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes. (CI)
  • 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: its generated artifacts are regenerated and committed. (not touched)
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_016WV4d1oZadHHFdEZXANxiG


Generated by Claude Code

…med run no longer names that run as its own child

resolveSuspensionChain now seeds its seen-set with the caller's run id, so an
A -> B -> A correlation cycle ends the chain at B and the map refusal names
the item run, not the run the caller is already resuming.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4d1oZadHHFdEZXANxiG
…her resume refusals

The client resume docblock, the service README's code list and the automation
checklist's trigger-status item now name the map-item refusal the resume door
answers since the parent-id gate landed.

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

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/client, @objectstack/service-automation, touching 2 documentable anchor(s). ⚠️ 1 changed file(s) yielded no anchor (packages/services/service-automation/README.md), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

⛔ 3 release-owned page(s) name something this change touched. These are read-only:

  • content/docs/releases/v16.mdx (via AutomationEngine (symbol, a top-level class))
  • content/docs/releases/v17/17-0.mdx (via AutomationEngine (symbol, a top-level class))
  • content/docs/releases/v17/17-6.mdx (via AutomationEngine (symbol, a top-level class))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/services/service-automation/README.md) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 58 of 210 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 27 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 6410029d1bb550a13429ec83f22eff523300de26 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 5c30569aecd599b488b08e8d118fe7d11be1a0d9 — the merge of head 1b77a96a014bac214f30ab480118ccb1eea432c8 into base 6410029d1bb550a13429ec83f22eff523300de26, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 5c30569aecd599b488b08e8d118fe7d11be1a0d9 && git checkout 5c30569aecd599b488b08e8d118fe7d11be1a0d9
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 6410029d1bb550a13429ec83f22eff523300de26 1b77a96a014bac214f30ab480118ccb1eea432c8 && git checkout -B drift-repro 6410029d1bb550a13429ec83f22eff523300de26 && git merge --no-ff 1b77a96a014bac214f30ab480118ccb1eea432c8

node scripts/docs-audit/affected-docs.mjs --json 6410029d1bb550a13429ec83f22eff523300de26

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 6410029d1bb550a13429ec83f22eff523300de26 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#1 · os-elon-musk · session_016WV4czVnUdQQCVKSW5J2uk

Seat ACCEPT · PR #28101 · head 1b77a96a014bac214f30ab480118ccb1eea432c8 · 2026-10-30T13:12Z

维护者速读

席位核对

  • Shape: draft → main, Part of #27971 (the card stays open for the main fix, needs-user-decision, analysis 6523020455). 6 files, +44/−5: one line + docblock in service-automation/src/engine.ts, one pin, the client docblock, the README code list, the automation checklist row (revision 9), a patch changeset. check-governed-merges --pr 28101: NOT governed.
  • Declarations: Clause-②: no, Metadata-protocol: none, Skills-docs: none (no skills/** hit; the generated references/api/ pages already list the code). Within claim 6522041026's surface.
  • Diff read (seat): new Set<string>([runId]) before the walk; a cycle back to the caller now ends the chain at the item run, so the refusal names B, not A. A normal chain never revisits the root, so its walk is unchanged. The docs wording ("an item run that is still suspended") matches main's behaviour today; the cancelled-item case is the ruling's.
  • Tests: the new cycle pin; ablation (seeded constructor → empty) red 1/6, restored to the HEAD blob. service-automation 2863/2863 (card thread, on 24787eeb; the head adds only the changeset).
  • Local gates (card thread): 67 derived families, 66 exit 0, 1 NOT MEASURED (check:dual-build-cjs-loads, exit 3, CI's).
  • Gate check-runs on this head: 49, 39 success, 10 skipped, 0 failed. mergeable_state: clean.
  • Landing: non-governed, under the maintainer's landing grant for this seat term (2026-10-30 10:20Z, seat-1 thread). Ready + auto-merge through the relay.

ACCEPT

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 30, 2026 13:13
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 30, 2026 13:13
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit d6c0a75 Oct 30, 2026
50 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-2p9rtc branch October 30, 2026 13:32
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 tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant