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
spec: name the terminally-failed run state on AutomationResult.status — contract half of #13937 (shape 4 ruling) #14384
Filed by the domain:services PM seat (session_01AUF1NoViznQK32gqpK8wS8) under the contract-first split rule: the services half of #13937 cannot land until this contract half does, and packages/spec belongs to the domain:spec seat alone. Named reader: the domain:spec seat. Triage: please mint domain:spec — this seat does not produce domain:*.
Provenance — the ruling, quoted verbatim from #13937 comment 5491060439 (director seat; maintainer 2026-09-01 「其他同意」)
One contract increment in packages/spec/src/contracts/automation-service.ts: give the terminally-failed-but-repairable run condition (a resume consumed the suspension, a downstream node threw, the run is recorded as failed and can be re-armed only by an explicit operator verb — #13909's condition) a platform-level name on AutomationResult.status, alongside 'completed' | 'paused' | 'failed'. The literal is the spec seat's to choose by its conventions; the semantics are fixed by the ruling. StrandedRunState stays a plugin-local report label and is not promoted.
Executable acceptance: git show origin/main:packages/spec/src/contracts/automation-service.ts | grep -n "status" shows the new literal in the AutomationResult.status union with a JSDoc line naming the condition; a pinned test in packages/spec asserts the union; changeset minor for @objectstack/spec; Clause-② review at contract tier (the ruling says so explicitly).
What it does NOT ask
No engine change, no operator verb, no REST route — those are the services half (#13937 shape 4: resumeInternal ordering untouched, explicit operator re-arm verb) and, separately, #13953 (whose door and permission model are an open question and are not bundled here).
Downstream
#13937 goes pm:blocked with Blocked-by: this card; #13909 stays blocked on #13937. When this closes, the services seat re-validates #13937's file surface on the merged ref and dispatches.
Triage (R+98) — priority:p1 · pm:blocking · needs:contract-review. domain:spec was already right and stays.
On the priority, since it is higher than the card's own weight would suggest. The contract increment itself is one union member plus a JSDoc line — small, and not urgent in isolation. It is p1 because of where it sits: #13937 is priority:p1pm:blocked and this card is its sole gate, with #13909 blocked behind that. A p2 here would let the queue pick other p1 work ahead of the only thing that unblocks a p1 chain, which is the wrong order for the same total work. pm:blocking records the relationship; the priority makes the queue act on it.
needs:contract-review is applied on the issue, not left for the PR, because the ruling you quote says so in as many words — 「触 spec ⇒ 条款②契约复审档位适用」. Dispatch at the contract-review tier.
Nothing else about the card needed changing. The scope is exact, the ruling is quoted verbatim with its provenance, the acceptance is executable, and the out-of-scope section correctly keeps the services half (#13937) and the operator-verb question (#13953) off it.
{
"issue": 14384,
"status": "done",
"branch": "claude/issue-14384-automation-result-terminal-failed-status",
"pr": "https://github.com/objectstack-ai/objectstack/pull/14636",
"head": "2c4bc2903701f758f1c6c5aa107a3c597888e9de",
"base": "a5b95ee6edd1e21e04cc43200f41fb730538b197 (origin/main at claim; the card's 2a26536 moved on with zero commits touching packages/spec/src/contracts/automation-service.ts between them)",
"premise_still_valid": true,
"literal": "stranded",
"alternatives_measured": [
"dead (TaskStatus precedent = retries exhausted, dead-lettered; reads final where the ruling's point is re-armable)",
"failed_resume / resume_failed (house snake_case shape, but names the consumption mechanism #13937 may still reorder, not the operator-facing state)",
"unresumable (false once the re-arm verb exists)",
"suspended (spec uses it for admin-suspended tenant/license/environment; collides with 'suspension' = the pause)",
"stalled / stuck / halted / incident (zero uses in spec, service-automation, plugin-approvals; 'incident' is a noun)"
],
"vocabularies_read": [
"AutomationResult.status: completed|paused|failed",
"ExecutionStatus (automation/execution.zod.ts): pending|running|paused|completed|failed|cancelled|timed_out|retrying",
"TaskStatus (system/worker.zod.ts): ...|failed|cancelled|timeout|dead",
"JobExecutionStatus (system/job.zod.ts): running|success|failed|timeout|degraded",
"StrandedRunState (plugin-approvals, report-only): missing|failed — NOT promoted, stated in the JSDoc",
"prose lineage: 'stranded' in #13807/#13909/#13937/PR #13934, inspectStrandedRequests, StrandedApprovalRequest, 8 comment sites in engine.ts"
],
"summary": "One contract increment: AutomationResult.status is now 'completed' | 'paused' | 'failed' | 'stranded' with a JSDoc paragraph naming the condition (a resume consumed the suspension, a downstream node threw, the run is recorded as failed and can be re-armed only by an explicit operator verb; distinct from 'failed'; StrandedRunState explicitly not promoted). The one Zod mirror in packages/spec/src (TriggerFlowResponseSchema.data.status, api/automation-api.zod.ts) carries the same four; a new pin test (contracts/automation-result-status.pin.test.ts) binds contract and wire at the type level (Assert over Eq, the automation-api.zod.test.ts form, compiled by check:test-typecheck) and the value level (.options + parse/refuse), and reads the JSDoc. content/docs/references/api/automation-api.mdx regenerated by gen:docs; changeset @objectstack/spec minor (additive, no ADR-0087 marker owed). No engine/verb/route change; no consumer needed even a type-only accommodation (zero exhaustive switches over the union; objectui's flowResponse.ts already types status as the three literals | string). Measured for #13937's services half: resumeInternal's catch arm returns NO status on the resumed-failure envelope today (only the run row says failed), and ExecutionStatus (what listRuns filters on) is not widened here.",
"files_changed": [
".changeset/automation-result-stranded-status.md",
"content/docs/references/api/automation-api.mdx",
"packages/spec/src/api/automation-api.zod.ts",
"packages/spec/src/contracts/automation-result-status.pin.test.ts",
"packages/spec/src/contracts/automation-service.ts"
],
"tests": "All on head 2c4bc29, exit codes captured before any pipe, heavy runs via scripts/pm/os-verify-lock.sh. spec: build exit 0 (check-dts-emitted 34/34); whole suite `Test Files 453 passed | 1 skipped (454) · Tests 12214 passed | 1 skipped (12215)` — the skip is scripts/root-entry-type-nameability.pin.test.ts (inspectDistFreshness saw dist older than src because the reverse verification touched the contract file's mtime after the build; content byte-identical), re-run after a rebuild on the same head `Test Files 1 passed (1) · Tests 2 passed (2)`; the earlier fresh-dist full run on the pre-describe-edit tree was 454 passed / 12216 passed, 0 skipped; typecheck exit 0 (`check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)`, ledger unchanged); pin file + contracts/automation-service.test.ts + api/automation-api.zod.test.ts `Test Files 3 passed (3) · Tests 61 passed (61)`; check:generated exit 0 after --fix regenerated the one stale artifact (content/docs/references/**); check:api-surface exit 0 (twice, incl. after the final rebuild); all 15 spec-scoped derived gates exit 0. Consumers (downstream filter direction; closure built first via turbo `^...` of each consumer, 55 tasks, exit 0): runtime typecheck 0 + 5 files/81 tests (narrowed to the AutomationResult-reading files); service-automation 9 files/239 tests (narrowed; package has no typecheck script — NOT MEASURED for types, ledgered by check:type-check-coverage which exits 0); plugin-approvals typecheck 0 (check:test-typecheck OK) + whole test 36 files/662; client typecheck 0 + whole test 32 files/420; verify typecheck 0 + 1 file/4 tests; rest typecheck 0; cli typecheck 0; dogfood NOT MEASURED locally. Reverse verification from the committed state: union narrowed back to three members on disk (anchor counts four-member 0 / three-member 1, diff-stat 1 file) → tsc -p packages/spec/tsconfig.test.json exit 2 with 266 error lines vs the ledgered 262 on the restored tree; the 4 new errors name exactly automation-api.zod.test.ts(52,54) TriggerFlowDataMatchesContract and automation-result-status.pin.test.ts lines 64/72/74 — direction red as predicted; restore via `git checkout HEAD -- FILE` from an absolute-path trap, proven by `git diff HEAD --quiet` exit 0 and hash-object == HEAD blob 85b3d15a. No ablation (no dist-resolved subject).",
"gates": {
"exit_0": [
"spec build",
"spec test (whole)",
"spec typecheck",
"spec check:generated",
"spec check:api-surface",
"spec check:authorable-surface",
"spec check:browser-reachable-entries",
"spec check:docs",
"spec check:dual-source-exports",
"spec check:empty-state",
"spec check:entry-nameability",
"spec check:export-origins",
"spec check:exported-any",
"spec check:liveness",
"spec check:llms-txt",
"spec check:skill-refs",
"spec check:strictness-ledger",
"spec check:variant-docs",
"spec check:yaml-examples",
"check:nul-bytes (scanned 7981 text files, no raw control bytes)",
"check:doc-authoring (14504 customer-facing strings clean)",
"check-adr-0087-registration",
"check-changeset-no-major",
"check-empty-changeset",
"check-ci-filter-parity",
"check-comment-mask-adoption",
"check-cross-package-test-inputs (both spellings)",
"check-keyed-text-bounds",
"check-plugin-teardown-shape",
"check-shard-attestation",
"check-system-context-census",
"check-undeclared-dep-imports",
"docs-audit/check-affected-docs",
"docs-audit/check-drift-comment",
"pm/release-rehearsal-clone --self-test",
"check:changeset-gate-self-tests",
"check:dispatcher-error-vocabulary",
"check:engine-double-contract",
"check:logger-receiver-detach",
"check:merge-driver",
"check:objectql-double-limit",
"check:objectui-changeset",
"check:page-declaration-shape",
"check:pm-half-states",
"check:published-files",
"check:query-options-erasure",
"check:slot-lookup",
"check:spec-parsed-alias",
"check:test-source-alias",
"check:type-check-coverage",
"check:type-source-resolution",
"check:where-matcher",
"lint check:doc-formula-expressions (exit 0 once the closure was built)",
"runtime typecheck",
"plugin-approvals typecheck",
"client typecheck",
"verify typecheck",
"rest typecheck",
"cli typecheck"
],
"not_measured": [
"check-test-completeness (exit 3 PREREQUISITE NOT MET)",
"check:dual-build-cjs-loads (exit 3: needs every package's dist)",
"check:type-check-debt (exit 3: --re-measure needs the full ledgered closure)",
"check-dev-prereqs (exit 1: asks for a full pnpm build)",
"pm/check-half-states (timed out at 240 s on its GitHub network leg; PM-side gate)",
"service-automation typecheck (no script)",
"dogfood typecheck/tests (needs the whole app closure)"
],
"ci": "in_progress — not awaited (draft PR delivered at 2c4bc29)"
},
"deviations": [
"Test narrowing, declared: runtime 6 patterns → 5 files/81 tests; service-automation 9 files/239 tests; verify 1 file/4 tests — the files that read AutomationResult; plugin-approvals and client ran whole.",
"check:doc-authoring went red on the first spelling of the .describe() (issue id in customer-facing text); the id moved to an adjacent line comment, gate re-run green — no other text changed.",
"One test skipped in the final whole-suite run (root-entry-type-nameability, dist-freshness gated by the reverse verification's mtime touch); re-run green after a rebuild on the same head.",
"PM mechanism assumption falsified: packages/rest/src/plugin-type-closed-set.pin.test.ts does not exist on origin/main; the house type-level form used is the Assert/Eq pair from packages/spec/src/api/automation-api.zod.test.ts (no @ts-expect-error; spec's typecheck compiles test files via check:test-typecheck).",
"Channel: REST repo-scoped read probed 200, so PR creation, PR label (additive POST) and the report comment went over REST; MCP used once (claim comment). No issue search was needed (nothing filed).",
"PR body read-back: my 13016 bytes stored byte-identical, then the platform appended a second bare-then-session attribution footer (90 bytes) after my session footer — no content lost, first line `Fixes #14384` intact.",
"Labels: needs:contract-review was already on the card from triage (read back: priority:p1 · pm:dispatched · domain:spec · pm:blocking · needs:contract-review); added to PR #14636 via additive POST and read back (PR labels: needs:contract-review)."
],
"labels": {
"card_14384": [
"priority:p1",
"pm:dispatched",
"domain:spec",
"pm:blocking",
"needs:contract-review"
],
"pr_14636": [
"needs:contract-review"
]
},
"mcp_calls": "1 — add_issue_comment (claim). Everything else: git, the public issue-page payload channel (3 pages), REST (probe, PR create, PR read-back, PR labels ×2, report comment + read-back).",
"open_questions": [],
"notes_for_downstream_13937": [
"resumeInternal's catch arm returns { success:false, error, durationMs, errorMessage, summary } with NO status today — the services half owns stamping 'stranded' on the result.",
"ExecutionStatus (run-row vocabulary; listRuns({ status }) filter) is not widened here; whether the row ever carries 'stranded' is the services half's to measure.",
"runtime's flow-dispatch-status.ts classifies failure by success/code, never by status — a 'stranded' envelope maps to 400 FLOW_FAILED until that half teaches it otherwise.",
"plugin-approvals' classifyStrandedRunState switches over the run ROW status with a silent default; it does not read AutomationResult.status."
],
"out_of_scope_findings": []
}
Activity
huangyiirene commentedon Sep 2, 2026
Triage (R+98) —
priority:p1·pm:blocking·needs:contract-review.domain:specwas already right and stays.On the priority, since it is higher than the card's own weight would suggest. The contract increment itself is one union member plus a JSDoc line — small, and not urgent in isolation. It is
p1because of where it sits: #13937 ispriority:p1pm:blockedand this card is its sole gate, with #13909 blocked behind that. Ap2here would let the queue pick otherp1work ahead of the only thing that unblocks ap1chain, which is the wrong order for the same total work.pm:blockingrecords the relationship; the priority makes the queue act on it.needs:contract-reviewis applied on the issue, not left for the PR, because the ruling you quote says so in as many words — 「触 spec ⇒ 条款②契约复审档位适用」. Dispatch at the contract-review tier.Nothing else about the card needed changing. The scope is exact, the ruling is quoted verbatim with its provenance, the acceptance is executable, and the out-of-scope section correctly keeps the services half (#13937) and the operator-verb question (#13953) off it.
Generated by Claude Code
claude commentedon Sep 2, 2026
os-dev-report
{ "issue": 14384, "status": "done", "branch": "claude/issue-14384-automation-result-terminal-failed-status", "pr": "https://github.com/objectstack-ai/objectstack/pull/14636", "head": "2c4bc2903701f758f1c6c5aa107a3c597888e9de", "base": "a5b95ee6edd1e21e04cc43200f41fb730538b197 (origin/main at claim; the card's 2a26536 moved on with zero commits touching packages/spec/src/contracts/automation-service.ts between them)", "premise_still_valid": true, "literal": "stranded", "alternatives_measured": [ "dead (TaskStatus precedent = retries exhausted, dead-lettered; reads final where the ruling's point is re-armable)", "failed_resume / resume_failed (house snake_case shape, but names the consumption mechanism #13937 may still reorder, not the operator-facing state)", "unresumable (false once the re-arm verb exists)", "suspended (spec uses it for admin-suspended tenant/license/environment; collides with 'suspension' = the pause)", "stalled / stuck / halted / incident (zero uses in spec, service-automation, plugin-approvals; 'incident' is a noun)" ], "vocabularies_read": [ "AutomationResult.status: completed|paused|failed", "ExecutionStatus (automation/execution.zod.ts): pending|running|paused|completed|failed|cancelled|timed_out|retrying", "TaskStatus (system/worker.zod.ts): ...|failed|cancelled|timeout|dead", "JobExecutionStatus (system/job.zod.ts): running|success|failed|timeout|degraded", "StrandedRunState (plugin-approvals, report-only): missing|failed — NOT promoted, stated in the JSDoc", "prose lineage: 'stranded' in #13807/#13909/#13937/PR #13934, inspectStrandedRequests, StrandedApprovalRequest, 8 comment sites in engine.ts" ], "summary": "One contract increment: AutomationResult.status is now 'completed' | 'paused' | 'failed' | 'stranded' with a JSDoc paragraph naming the condition (a resume consumed the suspension, a downstream node threw, the run is recorded as failed and can be re-armed only by an explicit operator verb; distinct from 'failed'; StrandedRunState explicitly not promoted). The one Zod mirror in packages/spec/src (TriggerFlowResponseSchema.data.status, api/automation-api.zod.ts) carries the same four; a new pin test (contracts/automation-result-status.pin.test.ts) binds contract and wire at the type level (Assert over Eq, the automation-api.zod.test.ts form, compiled by check:test-typecheck) and the value level (.options + parse/refuse), and reads the JSDoc. content/docs/references/api/automation-api.mdx regenerated by gen:docs; changeset @objectstack/spec minor (additive, no ADR-0087 marker owed). No engine/verb/route change; no consumer needed even a type-only accommodation (zero exhaustive switches over the union; objectui's flowResponse.ts already types status as the three literals | string). Measured for #13937's services half: resumeInternal's catch arm returns NO status on the resumed-failure envelope today (only the run row says failed), and ExecutionStatus (what listRuns filters on) is not widened here.", "files_changed": [ ".changeset/automation-result-stranded-status.md", "content/docs/references/api/automation-api.mdx", "packages/spec/src/api/automation-api.zod.ts", "packages/spec/src/contracts/automation-result-status.pin.test.ts", "packages/spec/src/contracts/automation-service.ts" ], "tests": "All on head 2c4bc29, exit codes captured before any pipe, heavy runs via scripts/pm/os-verify-lock.sh. spec: build exit 0 (check-dts-emitted 34/34); whole suite `Test Files 453 passed | 1 skipped (454) · Tests 12214 passed | 1 skipped (12215)` — the skip is scripts/root-entry-type-nameability.pin.test.ts (inspectDistFreshness saw dist older than src because the reverse verification touched the contract file's mtime after the build; content byte-identical), re-run after a rebuild on the same head `Test Files 1 passed (1) · Tests 2 passed (2)`; the earlier fresh-dist full run on the pre-describe-edit tree was 454 passed / 12216 passed, 0 skipped; typecheck exit 0 (`check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)`, ledger unchanged); pin file + contracts/automation-service.test.ts + api/automation-api.zod.test.ts `Test Files 3 passed (3) · Tests 61 passed (61)`; check:generated exit 0 after --fix regenerated the one stale artifact (content/docs/references/**); check:api-surface exit 0 (twice, incl. after the final rebuild); all 15 spec-scoped derived gates exit 0. Consumers (downstream filter direction; closure built first via turbo `^...` of each consumer, 55 tasks, exit 0): runtime typecheck 0 + 5 files/81 tests (narrowed to the AutomationResult-reading files); service-automation 9 files/239 tests (narrowed; package has no typecheck script — NOT MEASURED for types, ledgered by check:type-check-coverage which exits 0); plugin-approvals typecheck 0 (check:test-typecheck OK) + whole test 36 files/662; client typecheck 0 + whole test 32 files/420; verify typecheck 0 + 1 file/4 tests; rest typecheck 0; cli typecheck 0; dogfood NOT MEASURED locally. Reverse verification from the committed state: union narrowed back to three members on disk (anchor counts four-member 0 / three-member 1, diff-stat 1 file) → tsc -p packages/spec/tsconfig.test.json exit 2 with 266 error lines vs the ledgered 262 on the restored tree; the 4 new errors name exactly automation-api.zod.test.ts(52,54) TriggerFlowDataMatchesContract and automation-result-status.pin.test.ts lines 64/72/74 — direction red as predicted; restore via `git checkout HEAD -- FILE` from an absolute-path trap, proven by `git diff HEAD --quiet` exit 0 and hash-object == HEAD blob 85b3d15a. No ablation (no dist-resolved subject).", "gates": { "exit_0": [ "spec build", "spec test (whole)", "spec typecheck", "spec check:generated", "spec check:api-surface", "spec check:authorable-surface", "spec check:browser-reachable-entries", "spec check:docs", "spec check:dual-source-exports", "spec check:empty-state", "spec check:entry-nameability", "spec check:export-origins", "spec check:exported-any", "spec check:liveness", "spec check:llms-txt", "spec check:skill-refs", "spec check:strictness-ledger", "spec check:variant-docs", "spec check:yaml-examples", "check:nul-bytes (scanned 7981 text files, no raw control bytes)", "check:doc-authoring (14504 customer-facing strings clean)", "check-adr-0087-registration", "check-changeset-no-major", "check-empty-changeset", "check-ci-filter-parity", "check-comment-mask-adoption", "check-cross-package-test-inputs (both spellings)", "check-keyed-text-bounds", "check-plugin-teardown-shape", "check-shard-attestation", "check-system-context-census", "check-undeclared-dep-imports", "docs-audit/check-affected-docs", "docs-audit/check-drift-comment", "pm/release-rehearsal-clone --self-test", "check:changeset-gate-self-tests", "check:dispatcher-error-vocabulary", "check:engine-double-contract", "check:logger-receiver-detach", "check:merge-driver", "check:objectql-double-limit", "check:objectui-changeset", "check:page-declaration-shape", "check:pm-half-states", "check:published-files", "check:query-options-erasure", "check:slot-lookup", "check:spec-parsed-alias", "check:test-source-alias", "check:type-check-coverage", "check:type-source-resolution", "check:where-matcher", "lint check:doc-formula-expressions (exit 0 once the closure was built)", "runtime typecheck", "plugin-approvals typecheck", "client typecheck", "verify typecheck", "rest typecheck", "cli typecheck" ], "not_measured": [ "check-test-completeness (exit 3 PREREQUISITE NOT MET)", "check:dual-build-cjs-loads (exit 3: needs every package's dist)", "check:type-check-debt (exit 3: --re-measure needs the full ledgered closure)", "check-dev-prereqs (exit 1: asks for a full pnpm build)", "pm/check-half-states (timed out at 240 s on its GitHub network leg; PM-side gate)", "service-automation typecheck (no script)", "dogfood typecheck/tests (needs the whole app closure)" ], "ci": "in_progress — not awaited (draft PR delivered at 2c4bc29)" }, "deviations": [ "Test narrowing, declared: runtime 6 patterns → 5 files/81 tests; service-automation 9 files/239 tests; verify 1 file/4 tests — the files that read AutomationResult; plugin-approvals and client ran whole.", "check:doc-authoring went red on the first spelling of the .describe() (issue id in customer-facing text); the id moved to an adjacent line comment, gate re-run green — no other text changed.", "One test skipped in the final whole-suite run (root-entry-type-nameability, dist-freshness gated by the reverse verification's mtime touch); re-run green after a rebuild on the same head.", "PM mechanism assumption falsified: packages/rest/src/plugin-type-closed-set.pin.test.ts does not exist on origin/main; the house type-level form used is the Assert/Eq pair from packages/spec/src/api/automation-api.zod.test.ts (no @ts-expect-error; spec's typecheck compiles test files via check:test-typecheck).", "Channel: REST repo-scoped read probed 200, so PR creation, PR label (additive POST) and the report comment went over REST; MCP used once (claim comment). No issue search was needed (nothing filed).", "PR body read-back: my 13016 bytes stored byte-identical, then the platform appended a second bare-then-session attribution footer (90 bytes) after my session footer — no content lost, first line `Fixes #14384` intact.", "Labels: needs:contract-review was already on the card from triage (read back: priority:p1 · pm:dispatched · domain:spec · pm:blocking · needs:contract-review); added to PR #14636 via additive POST and read back (PR labels: needs:contract-review)." ], "labels": { "card_14384": [ "priority:p1", "pm:dispatched", "domain:spec", "pm:blocking", "needs:contract-review" ], "pr_14636": [ "needs:contract-review" ] }, "mcp_calls": "1 — add_issue_comment (claim). Everything else: git, the public issue-page payload channel (3 pages), REST (probe, PR create, PR read-back, PR labels ×2, report comment + read-back).", "open_questions": [], "notes_for_downstream_13937": [ "resumeInternal's catch arm returns { success:false, error, durationMs, errorMessage, summary } with NO status today — the services half owns stamping 'stranded' on the result.", "ExecutionStatus (run-row vocabulary; listRuns({ status }) filter) is not widened here; whether the row ever carries 'stranded' is the services half's to measure.", "runtime's flow-dispatch-status.ts classifies failure by success/code, never by status — a 'stranded' envelope maps to 400 FLOW_FAILED until that half teaches it otherwise.", "plugin-approvals' classifyStrandedRunState switches over the run ROW status with a silent default; it does not read AutomationResult.status." ], "out_of_scope_findings": [] }Generated by Claude Code
feat(automation): stamp status 'stranded' on the resume catch arm and…
feat(automation): stamp `status: 'stranded'` on the resume catch arm …
test(spec): contracts and conversions test titles state each cited de…