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
automation: the region refusal leaves a deeper suspended run uncancelled when a middle link of the suspension chain cannot be read #29333
Filing gate: ① out-of-scope finding of the #29166 dev (os-dev-report 6576781813, open_questions[1]), confirmed by the seat reading resolveSuspensionChain on main (read, not run). Filed by domain:server seat 3. ⛔ Not a claim. Suggested-grade: p3 · same defect class as #29166 item (1), one link deeper.
Reach: a region whose body calls a subflow or map whose child run suspends through a chain of two or more linked runs, while the store answers for the child but fails for a deeper link.
Reader who acts: the domain:server lane (packages/services/service-automation/src/engine.tsresolveSuspensionChain, dag-traversal.tsrunRegion).
resolveSuspensionChain (engine.ts ~L6975) walks the chain with the degrading loadSuspendedRun, which turns a store read failure into null. When the child is readable but a deeper link's read fails, the walk stops early and returns a partial chain. The deeper run is then neither cancelled nor recorded at error; only the degrading read's warn remains.
Wanted
When runRegion cancels the chain, walk it with the strict loader (the shape cancelRun already uses), cancel every link it can read, and record at error each link it cannot read, naming the run id. The region refusal itself is unchanged and still thrown after.
Tests: a three-run chain whose middle link's store read fails; the readable links are cancelled; one error record names the unreadable link; ablation.
Clause-② expected: no (cancels that should have happened now happen). Metadata-protocol: none.
Dedupe: searched resolveSuspensionChain, region suspension chain cancel, partial chain deeper run not cancelled; nearest #29166 (empty chain only), #28897 (closed). New.
Claim: PM loop round 1 · card thread · 2026-11-02T13:15Z
Session: session_01ADHkmQJdgarUjPLNgFBY67 (the seat); the card thread is session_01ADHkmS5997viAw9y7Jknnz
Account: os-steve (the seat's linked user; the card's assignee)
Branch: claude/project-thread-y9hvos
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#3
Ruling-ref: the maintainer, verbatim, in the project thread: 「开 server 2、3、5 号席位, 前任已经下班,接手所有开发,包括跟进之前未完成的开发落地。」
File surface: packages/services/service-automation/src/dag-traversal.ts (runRegion cancel walk) and engine.ts (a strict walk beside resolveSuspensionChain) + tests
Container & model: card thread cmsg_01FdL1XeUyvVNxLreh3F4Qi9JeMXnsbKRJxMbW9ZUq9nDf, mode:thread, model: opus (--tier names no path mandate: PM's call, default), effort: medium
Clause-②: no — cancels that should have happened now happen
Metadata-protocol: none
Responsibility: the card thread measures, codes, tests and opens the PR; the seat reviews and lands
Thread-read: 6577811795
Premise: holds (site re-read on origin/main57cde8cb by the seat before dispatch)
Serial constraints cleared: PR #29329 (#29166) edits runRegion and is in the merge queue: the PR opens only after it merges, on a merged main
Resume-from: none — fresh from origin/main
State: pm:queue → pm:dispatched, assigned to os-steve, recorded by this claim. Order: project file server-seat3/standard-order.md + server-seat3/29333-delta.md.
{
"issue": 29333,
"status": "done",
"branch": "claude/project-thread-y9hvos",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29403",
"session": "session_01ADHkmS5997viAw9y7Jknnz",
"premise_still_valid": true,
"summary": "runRegion's region-refusal cancel now walks the child's suspension chain through resolveSuspensionChainForCancel: the same one walk as resolveSuspensionChain (now walkSuspensionChain with the loader as its only parameter) read through loadSuspendedRunStrict. Every read link is cancelled deepest first; the link whose read threw is still handed to cancelRun and one error record names it, since runs below it were never reached. resolveSuspensionChain keeps the degrading loader for the resume gate. #29329's empty-chain branch is subsumed (unreadable child = unreadable link); its two tests pass unedited.",
"tests": "head a06cb531: service-automation typecheck exit 0; vitest Test Files 260/260, Tests 3342/3342 (os-verify-lock VERDICT command-exit 0); subflow-region-suspension.test.ts 24/24. New: middle-link-unreadable three-run chain + all-readable CONTROL. Ablation on e6d2696f via ablation-replace (loadSuspendedRunStrict -> loadSuspendedRun in the cancel walk): anchor 1->0, blob c937469c8834->ebabde87953c, 3 failed / 21 passed (new case + both #29166 cases), CONTROL green; restored blob == HEAD, git diff HEAD empty. src import, no dist leg.",
"gates": "dispatch-gates --commands on a06cb531: 62 derived; --ran: 62 run, 0 NOT-MEASURED, all exit 0. check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads first exit 3 (prerequisite), re-run exit 0 after git fetch of fixture 621a4876 and turbo build ./packages/** (78/78). pnpm lint exit 0 (same lock run, VERDICT command-exit 0). CI check-runs: in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and Clause-②: no without a (narrowing) arm",
"line_budget": "+144 / -18 over 4 files (changeset 10, dag-traversal.ts +30/-14, engine.ts +43/-4, test +61)",
"files_changed": [
".changeset/29333-region-refusal-deeper-chain-cancel.md",
"packages/services/service-automation/src/dag-traversal.ts",
"packages/services/service-automation/src/engine.ts",
"packages/services/service-automation/src/subflow-region-suspension.test.ts"
],
"deviations": [
"The pre-merge branch first merged #29329's head branch (a72981df) to build ahead of its landing; after #29329 squash-merged, merging main conflicted in the two files and was resolved to this branch's side. The PR was opened only after #29329 merged.",
"No forced test edits."
],
"mcp_calls": "4 — mcp__github__pull_request_read x4 (get_diff/get/get_status on #29329, get on #29403); no MCP writes",
"api_writes": "2 — fleet relay pr_create (#29403), post-stamped os-dev-report comment on #29333",
"open_questions": [
{
"question": "Runs BELOW the unreadable link stay parked: their ids live only in that link's correlation and SuspendedRun has no parent pointer. The error record names the unreadable run and tells the operator to cancel the rest once the store answers. Should a later card add a parent pointer so the cancel can find them without that row?",
"options": [
"A leave it: the error record is the answer (no format change)",
"B file a card for a parentRunId on SuspendedRun (persisted-row shape change, likely needs spec/migration review)"
],
"recommendation": "A, because it needs a store outage across two reads to bite and B touches the persisted row shape"
}
],
"security_findings": "none",
"out_of_scope_findings": []
}
Landed: merged as 02bceb70. When a region refuses a child that suspended, the cancel now walks the child's suspension chain through the strict loader. Every link it reads is cancelled deepest first. A link it cannot read still goes to cancelRun, and one error record names it. The degrading walk for the resume gate is unchanged.
Seat ACCEPT 6579325074 is on the PR. Clause-②: no, so no contract-review face applied, and CI on head a06cb531 was green. The open question was ruled A: the error record is the answer and no parentRunId card is filed. Fixes #29333 closed this card on merge.
State: pm:dispatched and the assignee removed in the same round.
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p3 ·
domain:server·pm:queue· 2026-11-02T13:02Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#3 · os-steve · session_01ADHkmQJdgarUjPLNgFBY67
Claim: PM loop round 1 · card thread · 2026-11-02T13:15Z
Session:
session_01ADHkmQJdgarUjPLNgFBY67(the seat); the card thread issession_01ADHkmS5997viAw9y7JknnzAccount:
os-steve(the seat's linked user; the card's assignee)Branch:
claude/project-thread-y9hvosWorktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#3Ruling-ref: the maintainer, verbatim, in the project thread: 「开 server 2、3、5 号席位, 前任已经下班,接手所有开发,包括跟进之前未完成的开发落地。」
File surface:
packages/services/service-automation/src/dag-traversal.ts(runRegioncancel walk) andengine.ts(a strict walk besideresolveSuspensionChain) + testsContainer & model: card thread
cmsg_01FdL1XeUyvVNxLreh3F4Qi9JeMXnsbKRJxMbW9ZUq9nDf,mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: mediumClause-②: no — cancels that should have happened now happen
Metadata-protocol: none
Responsibility: the card thread measures, codes, tests and opens the PR; the seat reviews and lands
Thread-read: 6577811795
Premise: holds (site re-read on
origin/main57cde8cbby the seat before dispatch)Serial constraints cleared: PR #29329 (#29166) edits runRegion and is in the merge queue: the PR opens only after it merges, on a merged main
Resume-from: none — fresh from
origin/mainState:
pm:queue→pm:dispatched, assigned toos-steve, recorded by this claim. Order: project file server-seat3/standard-order.md + server-seat3/29333-delta.md.objectstack-fleet commentedon Nov 2, 2026
domain:server#3 · os-steve · session_01ADHkmS5997viAw9y7Jknnz
os-dev-report
{ "issue": 29333, "status": "done", "branch": "claude/project-thread-y9hvos", "pr": "https://github.com/objectstack-ai/objectstack/pull/29403", "session": "session_01ADHkmS5997viAw9y7Jknnz", "premise_still_valid": true, "summary": "runRegion's region-refusal cancel now walks the child's suspension chain through resolveSuspensionChainForCancel: the same one walk as resolveSuspensionChain (now walkSuspensionChain with the loader as its only parameter) read through loadSuspendedRunStrict. Every read link is cancelled deepest first; the link whose read threw is still handed to cancelRun and one error record names it, since runs below it were never reached. resolveSuspensionChain keeps the degrading loader for the resume gate. #29329's empty-chain branch is subsumed (unreadable child = unreadable link); its two tests pass unedited.", "tests": "head a06cb531: service-automation typecheck exit 0; vitest Test Files 260/260, Tests 3342/3342 (os-verify-lock VERDICT command-exit 0); subflow-region-suspension.test.ts 24/24. New: middle-link-unreadable three-run chain + all-readable CONTROL. Ablation on e6d2696f via ablation-replace (loadSuspendedRunStrict -> loadSuspendedRun in the cancel walk): anchor 1->0, blob c937469c8834->ebabde87953c, 3 failed / 21 passed (new case + both #29166 cases), CONTROL green; restored blob == HEAD, git diff HEAD empty. src import, no dist leg.", "gates": "dispatch-gates --commands on a06cb531: 62 derived; --ran: 62 run, 0 NOT-MEASURED, all exit 0. check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads first exit 3 (prerequisite), re-run exit 0 after git fetch of fixture 621a4876 and turbo build ./packages/** (78/78). pnpm lint exit 0 (same lock run, VERDICT command-exit 0). CI check-runs: in_progress at report time.", "dogfood_battery": "n/a — no ! in the PR title and Clause-②: no without a (narrowing) arm", "line_budget": "+144 / -18 over 4 files (changeset 10, dag-traversal.ts +30/-14, engine.ts +43/-4, test +61)", "files_changed": [ ".changeset/29333-region-refusal-deeper-chain-cancel.md", "packages/services/service-automation/src/dag-traversal.ts", "packages/services/service-automation/src/engine.ts", "packages/services/service-automation/src/subflow-region-suspension.test.ts" ], "deviations": [ "The pre-merge branch first merged #29329's head branch (a72981df) to build ahead of its landing; after #29329 squash-merged, merging main conflicted in the two files and was resolved to this branch's side. The PR was opened only after #29329 merged.", "No forced test edits." ], "mcp_calls": "4 — mcp__github__pull_request_read x4 (get_diff/get/get_status on #29329, get on #29403); no MCP writes", "api_writes": "2 — fleet relay pr_create (#29403), post-stamped os-dev-report comment on #29333", "open_questions": [ { "question": "Runs BELOW the unreadable link stay parked: their ids live only in that link's correlation and SuspendedRun has no parent pointer. The error record names the unreadable run and tells the operator to cancel the rest once the store answers. Should a later card add a parent pointer so the cancel can find them without that row?", "options": [ "A leave it: the error record is the answer (no format change)", "B file a card for a parentRunId on SuspendedRun (persisted-row shape change, likely needs spec/migration review)" ], "recommendation": "A, because it needs a store outage across two reads to bite and B touches the persisted row shape" } ], "security_findings": "none", "out_of_scope_findings": [] }Stamped 2026-11-02T14:11Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#3 · os-steve · session_01ADHkmQJdgarUjPLNgFBY67
Landing record · #29333 · PR #29403
domain:serverseat 3 ·session_01ADHkmQJdgarUjPLNgFBY67· 2026-11-02T15:03Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-29403-*'git merge-base --is-ancestor 02bceb70b3 origin/maingit grep -n "private async resolveSuspensionChainForCancel" origin/main -- packages/services/service-automation/src/engine.ts02bceb70. When a region refuses a child that suspended, the cancel now walks the child's suspension chain through the strict loader. Every link it reads is cancelled deepest first. A link it cannot read still goes tocancelRun, and oneerrorrecord names it. The degrading walk for the resume gate is unchanged.6579325074is on the PR.Clause-②: no, so no contract-review face applied, and CI on heada06cb531was green. The open question was ruled A: theerrorrecord is the answer and noparentRunIdcard is filed.Fixes #29333closed this card on merge.pm:dispatchedand the assignee removed in the same round.