You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
service-automation: resuming a run paused at a map node by the PARENT run id completes the parent and leaves the parked item child suspended — accepted shape or a skipped item? #27877
Filing gate: ① a behaviour measured beside a ruled card, by the #27743 dev (PR #27872, os-dev-report 6513464095, out-of-scope finding 2). Filed by domain:server seat 4. ⛔ Not a claim. No grade: triage sets the lane and grade, including whether this is the accepted shape.
A run paused at a map node (correlation map:CHILD), resumed at the parent run id with an item child whose node has resumeAuthority: any: the resume answers success, the parent is recorded completed, and the item child stays suspended (listSuspendedRuns still holds it). The map advanced past the parked item without running it.
Why it may be intended
The LINKED_RUN_PREFIXES docblock in packages/objectql/src/engine.ts names this advance as the reason the resume gate reads the child, so for open authority it may be the accepted shape. If so, the orphaned child suspension is still left behind.
Wanted (route is triage's)
Either rule it the accepted shape (and decide what happens to the orphaned child suspension), or make a parent-id resume of a map either refuse or resume the parked item. ⚠️engine.ts is on the hot-file queue (#25522, the engine.ts split, in flight).
Dedupe
Read the open domain:server titles for map + resume, suspended, parked item: none. New.
Read fresh. This is not the accepted shape. A run that completes past a parked item without running it is a silent skip. A parent-id resume of a map whose item child is still suspended is refused with a coded 409 that names the child run id to resume, and nothing advances. The LINKED_RUN_PREFIXES docblock is updated to match. That also removes the orphaned child suspension.
Claim: PM loop round 2 · 2026-10-30T04:00Z · unlocked from pm:blocked (blocker PR #27872 merged) · seat 4 filed it from #27743's report; seat 3 agreed it is seat 4's
Session: session_016WV4cxEzAw9N6UiWHC6Zp2 (card thread; seat session_016WV4d1Np3hU7RQnA13YZcL)
Account: os-elon-musk
Branch: claude/project-thread-n14t8u (the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)
Worktree: objectstack-issue-27877
Domain: domain:server
Seat: domain:server#4
File surface: packages/services/service-automation/src/engine.ts (the resume gate and the LINKED_RUN_PREFIXES docblock — this is service-automation's engine, not the objectqlengine.ts on the #25522 split), packages/services/service-automation/src/run-resume.ts, the map node under packages/services/service-automation/src/builtin/ only as the refusal needs, their tests, .changeset/*; seat amendment on triage's retriage answer 6515324504 (B, granted under the SKILL.md 跨域例外路径): the new resume code (RESUME_CHILD_PENDING; the name is the maintainer's at approval) in packages/spec/src/contracts/automation-service.ts (the AutomationResult.code union), packages/spec/src/api/automation-api.zod.ts (the TriggerFlowResponseSchema enum) and packages/spec/src/api/error-code-ledger.zod.ts (the ADR-0112 ledger row), with the spec artifacts their tooling regenerates, and one RESUME_REFUSAL_ROWS row at 409 in packages/runtime/src/domains/automation.ts, plus docs/qa/platform-checklist/areas/automation.json rows if its gate asks; no governed path
Container & model: M, mode:thread, model: default (TIER_DEFAULT), effort: high (card raised to p1 by triage 6515324504; the thread keeps its effort); a CONTRACT_REVIEW_TIER review is owed before approval (a resume accepted today is refused)
Clause-②: yes (a new public wire code is a protocol addition, per triage 6515324504; the dev names the arm from the diff — a parent-id resume accepted today is now refused)
Metadata-protocol: none
Responsibility: a parent-id resume of a run paused at a map node advances past the parked item and completes the parent, leaving the item child suspended; the platform path that covers it is the resume gate refusing with a coded 409 that names the child run id to resume, so nothing advances and no orphaned suspension is left; reached by any caller resuming a batch flow by its parent run id.
Thread-read: 6513867475
Premise: holds (service-automation/src/engine.ts on origin/main813fd9be: the LINKED_RUN_PREFIXES docblock (~L6595) states that continuing a map: parent advances past the in-flight item; the card measured the parent recorded completed with the item child still in listSuspendedRuns)
Serial constraints cleared: PR #27872 (#27743, run-resume.ts) merged; no open PR touches service-automation/src/engine.ts, run-resume.ts or builtin/map*; objectql/src/engine.ts (#25522) is not on this surface.
pm:retriage · 2026-10-30T04:09Z · route question on the claimed card (claim 6514635285 stands)
Triage 6513867475 rules a parent-id resume of a map with a suspended item child refused with a coded 409 that names the child run id. The card thread measured that no existing code fits:
AutomationResult.code is a closed union in packages/spec (contracts/automation-service.ts and the TriggerFlowResponseSchema enum), and the runtime door's RESUME_REFUSAL_ROWS (packages/runtime/src/domains/automation.ts) maps exactly one resume code to 409: RESUME_IN_PROGRESS, documented as "a concurrent resume already holds this run; treat it as benign", and the approvals contract reads it as a tolerated duplicate.
Options:
A. Reuse RESUME_IN_PROGRESS: no spec or runtime edit. The wire code would say "already being resumed", which is false here, and a client that treats it as benign stops silently, which moves the silent skip to the client.
B. A new resume code (e.g. RESUME_CHILD_PENDING): the spec union, the TriggerFlowResponseSchema enum and the error-code ledger row (packages/spec, a cross-domain exception), plus one RESUME_REFUSAL_ROWS row at 409 (packages/runtime). Clause-② stays no (narrowing); Metadata-protocol: none; the contract review already owed covers it.
Seat recommendation: B, because a machine-readable code must not lie. Asking triage to grant the packages/spec + packages/runtime surface for B, or to rule A. The thread keeps the code in one constant meanwhile, so either answer lands quickly.
Triage: retriage answer · B, a new resume code · now p1 · 2026-10-30T04:55Z
⛔ Not a claim. The claim 6514635285 stands.
B. A machine-readable code must not lie, and A moves the silent skip to the client. RESUME_CHILD_PENDING (the name is the maintainer's at approval) is added to the AutomationResult.code union, the TriggerFlowResponseSchema enum and the ADR-0112 ledger, with one RESUME_REFUSAL_ROWS row at 409.
Granted (SKILL.md 跨域例外路径): the claim declares packages/spec (the union, the enum and the ledger row) and packages/runtime/src/domains/automation.ts.
{
"issue": 27877,
"status": "needs_decision",
"branch": "claude/project-thread-n14t8u",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27951",
"session": "session_016WV4cxEzAw9N6UiWHC6Zp2",
"premise_still_valid": true,
"summary": "Measured on origin/main e41642dd: a parent-id resume of a map parked on an open item answered success, recorded the parent completed and left the item child in listSuspendedRuns. The resume gate (refuseGatedResume, run-resume.ts) now walks the linked-run chain once (resolveSuspensionChain replaces resolveEffectiveSuspension), judges authority first (a service-owned item keeps PERMISSION_DENIED 403), then refuses a resume that reaches a map: link whose item child is still suspended, naming the item run of the deepest such link; nothing is consumed. Up-bubble (resumeInternal) and subflow delegation are unchanged; a map: link whose item row is gone is not refused. The code is a placeholder RESUME_IN_PROGRESS in one constant (MAP_ITEM_PENDING_REFUSAL_CODE) because no existing code fits; the route question is the seat's pm:retriage comment 6514753022.",
"tests": "pnpm --filter @objectstack/service-automation test on 7edf37b4: 219 files / 2808 tests passed (VERDICT command-exit 0). typecheck (tsc --noEmit + check:test-typecheck) exit 0. New src/map-parent-resume-refusal.test.ts (5) + changed src/resume-authority-gate.test.ts (3): 27/27. Ablation via scripts/ablation-replace.mjs on run-resume.ts anchor 'for (let i = chain.length - 2; i >= 0; i--) {' x1 -> x0, blob 067d1647 -> 8cef8f91: 4 failed | 23 passed (the four refusal pins); restored, blob == HEAD 067d1647, git diff HEAD empty. No build needed: the tests import ./engine.js from src.",
"gates": "dispatch-gates --commands on 7edf37b4: 62 derived. 61 exit 0 (check-plugin-teardown-shape --self-test first exit 3 in the shallow clone, exit 0 after fetching commit 621a4876); 1 NOT MEASURED: check:dual-build-cjs-loads exit 3 (needs every package's dist). --ran reconcile with exit codes: 62 accounted, 61 run, 1 NOT-MEASURED, 0 UNRUN. pnpm lint exit 0. check:commit-card-trailers --range origin/main..HEAD ok. PR check-runs: in_progress at report time.",
"dogfood_battery": "7edf37b4 · os-verify-lock VERDICT command-exit 0 (23m19s) · Test Files 357 passed | 3 skipped (360) · Tests 2875 passed | 20 skipped (2895) · no failures",
"mcp_calls": "4 — mcp__github__issue_read (get #27877, get_comments #27877 x2), mcp__github__pull_request_read (get #27872); all reads, no write tool",
"api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, #27951, draft, no assignees/labels), relay comment (POST /repos/objectstack-ai/objectstack/issues/27877/comments, this report)",
"open_questions": [
{
"question": "Which code does the refusal answer? AutomationResult.code is a closed packages/spec union and the runtime RESUME_REFUSAL_ROWS maps exactly one resume code to 409, RESUME_IN_PROGRESS (documented as a benign concurrent duplicate); the order forbids a packages/spec edit.",
"options": [
"A: keep RESUME_IN_PROGRESS (no spec/runtime edit, 409 on REST and MCP today; the wire code says 'already being resumed', which is false here, and a client treating it as benign stops silently)",
"B: a new code (e.g. RESUME_CHILD_PENDING): spec contract union + TriggerFlowResponseSchema enum + error-code ledger row (packages/spec) + one RESUME_REFUSAL_ROWS row at 409 (packages/runtime); then the constant, the changeset's Now. line and the PR body's code cell change"
],
"recommendation": "B, because a machine-readable code must not lie; asked on the card in 6514753022"
}
],
"out_of_scope_findings": [
"carrier: none · noted, not filed — a map: link whose item run is gone (cancelled via cancelRun, which does not touch the parent) still lets a parent-id resume advance past that item; outside the ruling (it covers a still-suspended item) and left unchanged, stated in the PR body"
],
"deviations": [
"The order asked to reuse an existing code; none fits, so the code is a placeholder pending triage (stop-and-ask done through the seat).",
"A scratch measurement test (src/tmp-measure-27877.test.ts) was run on the unfixed tree and deleted before the commit; its output is quoted in the PR body.",
"line_budget: +327 / -35 across 6 files (engine.ts, run-resume.ts, two changed tests, one new test, one changeset)."
],
"files_changed": [
"packages/services/service-automation/src/engine.ts",
"packages/services/service-automation/src/run-resume.ts",
"packages/services/service-automation/src/map-parent-resume-refusal.test.ts",
"packages/services/service-automation/src/resume-authority-gate.test.ts",
"packages/services/service-automation/src/degraded-suspended-run-load-log-cause.test.ts",
".changeset/27877-map-parent-resume-refusal.md"
]
}
{
"issue": 27877,
"status": "done",
"branch": "claude/project-thread-n14t8u",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27951",
"head": "082f766bf69f702411796717955551f9db58aeb3",
"session": "session_016WV4cxEzAw9N6UiWHC6Zp2",
"premise_still_valid": true,
"summary": "Final report on head 082f766b, superseding 6515519800 (written at 7edf37b4, before triage's answer). Measured on origin/main e41642dd: a parent-id resume of a map parked on an open item answered success, recorded the parent completed and left the item child in listSuspendedRuns. The resume gate (refuseGatedResume, run-resume.ts) now walks the linked-run chain once (resolveSuspensionChain replaces resolveEffectiveSuspension), judges authority first (a service-owned item keeps PERMISSION_DENIED 403), then refuses a resume that reaches a map: link whose item child is still suspended, naming the item run of the deepest such link; nothing is consumed. Per triage 6515324504 (B) the refusal answers the new code RESUME_CHILD_PENDING: AutomationResult.code union + TriggerFlowResponseSchema code enum + ADR-0112 ledger row (packages/spec), one RESUME_REFUSAL_ROWS row at 409 serving the REST resume arm and MCP resume_run (packages/runtime), reference pages regenerated. Up-bubble (resumeInternal) and subflow delegation are unchanged; a map: link whose item row is gone is not refused (filed by the seat as #27971).",
"pr_body_corrections": [
"Clause-② line: the body says 'Clause-②: no (narrowing)'; the tree and the changeset say 'Clause-②: yes (narrowing)' (triage 6515324504). Metadata-protocol: none is unchanged.",
"维护者速读 · 风险与回滚 and the Measured table's After cell: the code is RESUME_CHILD_PENDING (409 on both doors), not the RESUME_IN_PROGRESS placeholder; 需要你做的: confirm the code's name at approval.",
"## Open question: resolved, B (6515324504); the surface widened to packages/spec (union, enum, ledger) and packages/runtime/src/domains/automation.ts (one 409 row) as granted.",
"What changes · Changeset: three packages patch (@objectstack/service-automation, @objectstack/spec, @objectstack/runtime), not service-automation alone.",
"Verification: superseded by this report (head 082f766b, not 7edf37b4).",
"The relay cannot re-edit the PR body; the PR-body guards check is success on 082f766b, so the body was not replaced."
],
"tests": "On 082f766b, each under os-verify-lock (slot issue-27877), VERDICT command-exit 0: build of the dogfood + runtime dependency closure (turbo, 7m23s); pnpm --filter @objectstack/service-automation test 219 files / 2808 tests passed (3m12s); pnpm --filter @objectstack/runtime test 481 files passed / 7840 tests passed | 19 skipped (7859) (10m39s). New src/map-parent-resume-refusal.test.ts (5) + changed src/resume-authority-gate.test.ts (3) inside those; runtime automation-resume-refusal-codes.test.ts (seven-row floor) and mcp-resume-run.test.ts (RESUME_CHILD_PENDING row) inside the runtime run. Ablation (7edf37b4, unchanged logic since) via scripts/ablation-replace.mjs: 4 refusal pins fail, restored, git diff HEAD empty.",
"gates": "dispatch-gates --commands on 082f766b: 110 derived, 110 run, all exit 0 (check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads included, measured this time with the pinned commit fetched and the dist closure built). --ran reconcile: 110 accounted, 0 NOT-MEASURED, 0 UNRUN. pnpm lint exit 0. check:commit-card-trailers --range origin/main..HEAD ok (4 commits). PR check-runs on 082f766b: 41 success, 9 skipped, 0 failure, none pending.",
"dogfood_battery": "082f766b · os-verify-lock VERDICT command-exit 0 (26m29s) · Test Files 357 passed | 3 skipped (360) · Tests 2875 passed | 20 skipped (2895) · no failures",
"mcp_calls": "10 — mcp__github__issue_read x4 (get #27877, get_comments #27877 x3), mcp__github__pull_request_read x3 (get #27872, get_check_runs #27951 x2), mcp__github__get_job_logs x3 (CI reds on 87f2e45a x2, the cancelled Test UI rollup on 2bc14f4a); all reads, no write tool. Also read-only gh api GETs: check-runs of 082f766b, the contract review comment 6515887943.",
"api_writes": "3 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, #27951, draft, no assignees/labels), relay comment (POST .../issues/27877/comments, 6515519800), relay comment (POST .../issues/27877/comments, this report)",
"open_questions": [],
"out_of_scope_findings": [
"carrier: #27971 (filed by the seat) — a map: link whose item run is gone (cancelled via cancelRun) still lets a parent-id resume advance past that item; client/README/QA-row doc gaps ride on it",
"carrier: none · contract-review should-fix, held by the seat (do not move the head) — resolveSuspensionChain never adds the root runId to seen, so a corrupt A->B->A correlation cycle would refuse naming the caller's own run; pre-existing walk shape, refuses in the safe direction"
],
"deviations": [
"The first order asked to reuse an existing code; none fit, the route question went through the seat to triage (6514753022 -> 6515324504, B), and the claim was amended to grant packages/spec + one runtime row.",
"A scratch measurement test (src/tmp-measure-27877.test.ts) was run on the unfixed tree and deleted before the commit; its output is quoted in the PR body.",
"The code constant is a type-annotated const, not a 'satisfies' expression, because check:dispatcher-error-vocabulary resolves only the annotated form (082f766b).",
"line_budget: +361 / -40 across 15 files (3 generated reference pages among them)."
],
"files_changed": [
".changeset/27877-map-parent-resume-refusal.md",
"content/docs/references/api/automation-api.mdx",
"content/docs/references/api/contract.mdx",
"content/docs/references/api/error-code-ledger.mdx",
"packages/runtime/src/domains/automation-resume-refusal-codes.test.ts",
"packages/runtime/src/domains/automation.ts",
"packages/runtime/src/mcp-resume-run.test.ts",
"packages/services/service-automation/src/degraded-suspended-run-load-log-cause.test.ts",
"packages/services/service-automation/src/engine.ts",
"packages/services/service-automation/src/map-parent-resume-refusal.test.ts",
"packages/services/service-automation/src/resume-authority-gate.test.ts",
"packages/services/service-automation/src/run-resume.ts",
"packages/spec/src/api/automation-api.zod.ts",
"packages/spec/src/api/error-code-ledger.zod.ts",
"packages/spec/src/contracts/automation-service.ts"
]
}
Maintainer ruling · 2026-10-30T11:21Z · the new resume refusal code's name is RESUME_CHILD_PENDING (option A): Elon, 2026-10-30 11:21Z, 「同意」 in reply to the question recommending A. This is the name confirmation triage 6515324504 reserved to the maintainer.
ACCEPT 6516871393 on PR #27951 stands on head 082f766b (no change since); landing sent now (pr_ready + automerge_enable through the relay) under the seat-term landing grant. #27971 unblocks when it merges.
Activity
objectstack-fleet commentedon Oct 30, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 审批与自动化 | none | P②
Triage: p2 ·
domain:server·area:automation·pm:blockedon PR #27872 · 2026-10-30T02:59Z⛔ Not a claim.
mapwhose item child is still suspended is refused with a coded 409 that names the child run id to resume, and nothing advances. TheLINKED_RUN_PREFIXESdocblock is updated to match. That also removes the orphaned child suspension.Blocked-by: #27872is now in the body.bug,pm:blocked.Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL
Claim: PM loop round 2 · 2026-10-30T04:00Z · unlocked from
pm:blocked(blocker PR #27872 merged) · seat 4 filed it from #27743's report; seat 3 agreed it is seat 4'sSession:
session_016WV4cxEzAw9N6UiWHC6Zp2(card thread; seatsession_016WV4d1Np3hU7RQnA13YZcL)Account:
os-elon-muskBranch:
claude/project-thread-n14t8u(the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)Worktree:
objectstack-issue-27877Domain:
domain:serverSeat:
domain:server#4File surface:
packages/services/service-automation/src/engine.ts(the resume gate and theLINKED_RUN_PREFIXESdocblock — this is service-automation's engine, not theobjectqlengine.tson the #25522 split),packages/services/service-automation/src/run-resume.ts, themapnode underpackages/services/service-automation/src/builtin/only as the refusal needs, their tests,.changeset/*; seat amendment on triage's retriage answer 6515324504 (B, granted under the SKILL.md 跨域例外路径): the new resume code (RESUME_CHILD_PENDING; the name is the maintainer's at approval) inpackages/spec/src/contracts/automation-service.ts(theAutomationResult.codeunion),packages/spec/src/api/automation-api.zod.ts(theTriggerFlowResponseSchemaenum) andpackages/spec/src/api/error-code-ledger.zod.ts(the ADR-0112 ledger row), with the spec artifacts their tooling regenerates, and oneRESUME_REFUSAL_ROWSrow at 409 inpackages/runtime/src/domains/automation.ts, plusdocs/qa/platform-checklist/areas/automation.jsonrows if its gate asks; no governed pathContainer & model:
M,mode:thread,model: default (TIER_DEFAULT),effort: high(card raised to p1 by triage 6515324504; the thread keeps its effort); aCONTRACT_REVIEW_TIERreview is owed before approval (a resume accepted today is refused)Clause-②: yes (a new public wire code is a protocol addition, per triage 6515324504; the dev names the arm from the diff — a parent-id resume accepted today is now refused)
Metadata-protocol: none
Responsibility: a parent-id resume of a run paused at a
mapnode advances past the parked item and completes the parent, leaving the item child suspended; the platform path that covers it is the resume gate refusing with a coded 409 that names the child run id to resume, so nothing advances and no orphaned suspension is left; reached by any caller resuming a batch flow by its parent run id.Thread-read: 6513867475
Premise: holds (
service-automation/src/engine.tsonorigin/main813fd9be: theLINKED_RUN_PREFIXESdocblock (~L6595) states that continuing amap:parent advances past the in-flight item; the card measured the parent recordedcompletedwith the item child still inlistSuspendedRuns)Serial constraints cleared: PR #27872 (#27743,
run-resume.ts) merged; no open PR touchesservice-automation/src/engine.ts,run-resume.tsorbuiltin/map*;objectql/src/engine.ts(#25522) is not on this surface.objectstack-fleet commentedon Oct 30, 2026
domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL
pm:retriage · 2026-10-30T04:09Z · route question on the claimed card (claim 6514635285 stands)
Triage 6513867475 rules a parent-id resume of a
mapwith a suspended item child refused with a coded 409 that names the child run id. The card thread measured that no existing code fits:AutomationResult.codeis a closed union inpackages/spec(contracts/automation-service.tsand theTriggerFlowResponseSchemaenum), and the runtime door'sRESUME_REFUSAL_ROWS(packages/runtime/src/domains/automation.ts) maps exactly one resume code to 409:RESUME_IN_PROGRESS, documented as "a concurrent resume already holds this run; treat it as benign", and the approvals contract reads it as a tolerated duplicate.Options:
RESUME_IN_PROGRESS: no spec or runtime edit. The wire code would say "already being resumed", which is false here, and a client that treats it as benign stops silently, which moves the silent skip to the client.RESUME_CHILD_PENDING): the spec union, theTriggerFlowResponseSchemaenum and the error-code ledger row (packages/spec, a cross-domain exception), plus oneRESUME_REFUSAL_ROWSrow at 409 (packages/runtime).Clause-②staysno (narrowing);Metadata-protocol: none; the contract review already owed covers it.Seat recommendation: B, because a machine-readable code must not lie. Asking triage to grant the
packages/spec+packages/runtimesurface for B, or to rule A. The thread keeps the code in one constant meanwhile, so either answer lands quickly.objectstack-fleet commentedon Oct 30, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 审批与自动化 | none | P②
Triage: retriage answer · B, a new resume code · now p1 · 2026-10-30T04:55Z
⛔ Not a claim. The claim
6514635285stands.RESUME_CHILD_PENDING(the name is the maintainer's at approval) is added to theAutomationResult.codeunion, theTriggerFlowResponseSchemaenum and the ADR-0112 ledger, with oneRESUME_REFUSAL_ROWSrow at 409.packages/spec(the union, the enum and the ledger row) andpackages/runtime/src/domains/automation.ts.onErrorabort answers the data door with a code-less 400; give it a ledgered ADR-0112 code (#27508 code half) #27597. It owesClause-②: yes. The seat'sno (narrowing)does not fit a new enum value. A contract review is owed.pm:retriageremoved.Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
os-dev-report
{ "issue": 27877, "status": "needs_decision", "branch": "claude/project-thread-n14t8u", "pr": "https://github.com/objectstack-ai/objectstack/pull/27951", "session": "session_016WV4cxEzAw9N6UiWHC6Zp2", "premise_still_valid": true, "summary": "Measured on origin/main e41642dd: a parent-id resume of a map parked on an open item answered success, recorded the parent completed and left the item child in listSuspendedRuns. The resume gate (refuseGatedResume, run-resume.ts) now walks the linked-run chain once (resolveSuspensionChain replaces resolveEffectiveSuspension), judges authority first (a service-owned item keeps PERMISSION_DENIED 403), then refuses a resume that reaches a map: link whose item child is still suspended, naming the item run of the deepest such link; nothing is consumed. Up-bubble (resumeInternal) and subflow delegation are unchanged; a map: link whose item row is gone is not refused. The code is a placeholder RESUME_IN_PROGRESS in one constant (MAP_ITEM_PENDING_REFUSAL_CODE) because no existing code fits; the route question is the seat's pm:retriage comment 6514753022.", "tests": "pnpm --filter @objectstack/service-automation test on 7edf37b4: 219 files / 2808 tests passed (VERDICT command-exit 0). typecheck (tsc --noEmit + check:test-typecheck) exit 0. New src/map-parent-resume-refusal.test.ts (5) + changed src/resume-authority-gate.test.ts (3): 27/27. Ablation via scripts/ablation-replace.mjs on run-resume.ts anchor 'for (let i = chain.length - 2; i >= 0; i--) {' x1 -> x0, blob 067d1647 -> 8cef8f91: 4 failed | 23 passed (the four refusal pins); restored, blob == HEAD 067d1647, git diff HEAD empty. No build needed: the tests import ./engine.js from src.", "gates": "dispatch-gates --commands on 7edf37b4: 62 derived. 61 exit 0 (check-plugin-teardown-shape --self-test first exit 3 in the shallow clone, exit 0 after fetching commit 621a4876); 1 NOT MEASURED: check:dual-build-cjs-loads exit 3 (needs every package's dist). --ran reconcile with exit codes: 62 accounted, 61 run, 1 NOT-MEASURED, 0 UNRUN. pnpm lint exit 0. check:commit-card-trailers --range origin/main..HEAD ok. PR check-runs: in_progress at report time.", "dogfood_battery": "7edf37b4 · os-verify-lock VERDICT command-exit 0 (23m19s) · Test Files 357 passed | 3 skipped (360) · Tests 2875 passed | 20 skipped (2895) · no failures", "mcp_calls": "4 — mcp__github__issue_read (get #27877, get_comments #27877 x2), mcp__github__pull_request_read (get #27872); all reads, no write tool", "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, #27951, draft, no assignees/labels), relay comment (POST /repos/objectstack-ai/objectstack/issues/27877/comments, this report)", "open_questions": [ { "question": "Which code does the refusal answer? AutomationResult.code is a closed packages/spec union and the runtime RESUME_REFUSAL_ROWS maps exactly one resume code to 409, RESUME_IN_PROGRESS (documented as a benign concurrent duplicate); the order forbids a packages/spec edit.", "options": [ "A: keep RESUME_IN_PROGRESS (no spec/runtime edit, 409 on REST and MCP today; the wire code says 'already being resumed', which is false here, and a client treating it as benign stops silently)", "B: a new code (e.g. RESUME_CHILD_PENDING): spec contract union + TriggerFlowResponseSchema enum + error-code ledger row (packages/spec) + one RESUME_REFUSAL_ROWS row at 409 (packages/runtime); then the constant, the changeset's Now. line and the PR body's code cell change" ], "recommendation": "B, because a machine-readable code must not lie; asked on the card in 6514753022" } ], "out_of_scope_findings": [ "carrier: none · noted, not filed — a map: link whose item run is gone (cancelled via cancelRun, which does not touch the parent) still lets a parent-id resume advance past that item; outside the ruling (it covers a still-suspended item) and left unchanged, stated in the PR body" ], "deviations": [ "The order asked to reuse an existing code; none fits, so the code is a placeholder pending triage (stop-and-ask done through the seat).", "A scratch measurement test (src/tmp-measure-27877.test.ts) was run on the unfixed tree and deleted before the commit; its output is quoted in the PR body.", "line_budget: +327 / -35 across 6 files (engine.ts, run-resume.ts, two changed tests, one new test, one changeset)." ], "files_changed": [ "packages/services/service-automation/src/engine.ts", "packages/services/service-automation/src/run-resume.ts", "packages/services/service-automation/src/map-parent-resume-refusal.test.ts", "packages/services/service-automation/src/resume-authority-gate.test.ts", "packages/services/service-automation/src/degraded-suspended-run-load-log-cause.test.ts", ".changeset/27877-map-parent-resume-refusal.md" ] }objectstack-fleet commentedon Oct 30, 2026
os-dev-report
{ "issue": 27877, "status": "done", "branch": "claude/project-thread-n14t8u", "pr": "https://github.com/objectstack-ai/objectstack/pull/27951", "head": "082f766bf69f702411796717955551f9db58aeb3", "session": "session_016WV4cxEzAw9N6UiWHC6Zp2", "premise_still_valid": true, "summary": "Final report on head 082f766b, superseding 6515519800 (written at 7edf37b4, before triage's answer). Measured on origin/main e41642dd: a parent-id resume of a map parked on an open item answered success, recorded the parent completed and left the item child in listSuspendedRuns. The resume gate (refuseGatedResume, run-resume.ts) now walks the linked-run chain once (resolveSuspensionChain replaces resolveEffectiveSuspension), judges authority first (a service-owned item keeps PERMISSION_DENIED 403), then refuses a resume that reaches a map: link whose item child is still suspended, naming the item run of the deepest such link; nothing is consumed. Per triage 6515324504 (B) the refusal answers the new code RESUME_CHILD_PENDING: AutomationResult.code union + TriggerFlowResponseSchema code enum + ADR-0112 ledger row (packages/spec), one RESUME_REFUSAL_ROWS row at 409 serving the REST resume arm and MCP resume_run (packages/runtime), reference pages regenerated. Up-bubble (resumeInternal) and subflow delegation are unchanged; a map: link whose item row is gone is not refused (filed by the seat as #27971).", "pr_body_corrections": [ "Clause-② line: the body says 'Clause-②: no (narrowing)'; the tree and the changeset say 'Clause-②: yes (narrowing)' (triage 6515324504). Metadata-protocol: none is unchanged.", "维护者速读 · 风险与回滚 and the Measured table's After cell: the code is RESUME_CHILD_PENDING (409 on both doors), not the RESUME_IN_PROGRESS placeholder; 需要你做的: confirm the code's name at approval.", "## Open question: resolved, B (6515324504); the surface widened to packages/spec (union, enum, ledger) and packages/runtime/src/domains/automation.ts (one 409 row) as granted.", "What changes · Changeset: three packages patch (@objectstack/service-automation, @objectstack/spec, @objectstack/runtime), not service-automation alone.", "Verification: superseded by this report (head 082f766b, not 7edf37b4).", "The relay cannot re-edit the PR body; the PR-body guards check is success on 082f766b, so the body was not replaced." ], "tests": "On 082f766b, each under os-verify-lock (slot issue-27877), VERDICT command-exit 0: build of the dogfood + runtime dependency closure (turbo, 7m23s); pnpm --filter @objectstack/service-automation test 219 files / 2808 tests passed (3m12s); pnpm --filter @objectstack/runtime test 481 files passed / 7840 tests passed | 19 skipped (7859) (10m39s). New src/map-parent-resume-refusal.test.ts (5) + changed src/resume-authority-gate.test.ts (3) inside those; runtime automation-resume-refusal-codes.test.ts (seven-row floor) and mcp-resume-run.test.ts (RESUME_CHILD_PENDING row) inside the runtime run. Ablation (7edf37b4, unchanged logic since) via scripts/ablation-replace.mjs: 4 refusal pins fail, restored, git diff HEAD empty.", "gates": "dispatch-gates --commands on 082f766b: 110 derived, 110 run, all exit 0 (check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads included, measured this time with the pinned commit fetched and the dist closure built). --ran reconcile: 110 accounted, 0 NOT-MEASURED, 0 UNRUN. pnpm lint exit 0. check:commit-card-trailers --range origin/main..HEAD ok (4 commits). PR check-runs on 082f766b: 41 success, 9 skipped, 0 failure, none pending.", "dogfood_battery": "082f766b · os-verify-lock VERDICT command-exit 0 (26m29s) · Test Files 357 passed | 3 skipped (360) · Tests 2875 passed | 20 skipped (2895) · no failures", "mcp_calls": "10 — mcp__github__issue_read x4 (get #27877, get_comments #27877 x3), mcp__github__pull_request_read x3 (get #27872, get_check_runs #27951 x2), mcp__github__get_job_logs x3 (CI reds on 87f2e45a x2, the cancelled Test UI rollup on 2bc14f4a); all reads, no write tool. Also read-only gh api GETs: check-runs of 082f766b, the contract review comment 6515887943.", "api_writes": "3 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, #27951, draft, no assignees/labels), relay comment (POST .../issues/27877/comments, 6515519800), relay comment (POST .../issues/27877/comments, this report)", "open_questions": [], "out_of_scope_findings": [ "carrier: #27971 (filed by the seat) — a map: link whose item run is gone (cancelled via cancelRun) still lets a parent-id resume advance past that item; client/README/QA-row doc gaps ride on it", "carrier: none · contract-review should-fix, held by the seat (do not move the head) — resolveSuspensionChain never adds the root runId to seen, so a corrupt A->B->A correlation cycle would refuse naming the caller's own run; pre-existing walk shape, refuses in the safe direction" ], "deviations": [ "The first order asked to reuse an existing code; none fit, the route question went through the seat to triage (6514753022 -> 6515324504, B), and the claim was amended to grant packages/spec + one runtime row.", "A scratch measurement test (src/tmp-measure-27877.test.ts) was run on the unfixed tree and deleted before the commit; its output is quoted in the PR body.", "The code constant is a type-annotated const, not a 'satisfies' expression, because check:dispatcher-error-vocabulary resolves only the annotated form (082f766b).", "line_budget: +361 / -40 across 15 files (3 generated reference pages among them)." ], "files_changed": [ ".changeset/27877-map-parent-resume-refusal.md", "content/docs/references/api/automation-api.mdx", "content/docs/references/api/contract.mdx", "content/docs/references/api/error-code-ledger.mdx", "packages/runtime/src/domains/automation-resume-refusal-codes.test.ts", "packages/runtime/src/domains/automation.ts", "packages/runtime/src/mcp-resume-run.test.ts", "packages/services/service-automation/src/degraded-suspended-run-load-log-cause.test.ts", "packages/services/service-automation/src/engine.ts", "packages/services/service-automation/src/map-parent-resume-refusal.test.ts", "packages/services/service-automation/src/resume-authority-gate.test.ts", "packages/services/service-automation/src/run-resume.ts", "packages/spec/src/api/automation-api.zod.ts", "packages/spec/src/api/error-code-ledger.zod.ts", "packages/spec/src/contracts/automation-service.ts" ] }objectstack-fleet commentedon Oct 30, 2026
domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL
Maintainer ruling · 2026-10-30T11:21Z · the new resume refusal code's name is
RESUME_CHILD_PENDING(option A): Elon, 2026-10-30 11:21Z, 「同意」 in reply to the question recommending A. This is the name confirmation triage 6515324504 reserved to the maintainer.ACCEPT 6516871393 on PR #27951 stands on head
082f766b(no change since); landing sent now (pr_ready+automerge_enablethrough the relay) under the seat-term landing grant. #27971 unblocks when it merges.objectstack-fleet commentedon Oct 30, 2026
domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL
Landed · 2026-10-30T12:02Z
4793aa4a(merge queue)completedbyFixes #27877RESUME_CHILD_PENDING, confirmed by the maintainer (6521448998)State:
pm:dispatchedremoved in this stroke.