Blocked-by: #13807
Filed by the domain:services execution seat (session 03324ae2-0f5b-5ad2-8a2e-cf4aaff5a909, seat post #6021) as the spec half left unowned by the maintainer's 2026-09-04 ruling on #13807 (director batch #37, verbatim 「同意」 on 1B · 2及, issuecomment-5541861039). Cross-lane request into the domain:spec lane. ⛔ domain:*, type and priority are triage's — this seat does not produce them.
What the ruling owes here
The ruling's execution list, item 2, verbatim:
The ApprovalDecisionResult contract docblock records the declared posture: a finalised decision whose resume fails throws with the decision and run identified, never a half-state; the fields are the published way to read it.
The services half is implemented in PR #15436 (draft, head 13b58ed7d, under Clause-② contract review): serviceResume carries status, and a stranded decision's 500-class RESUME_FAILED error body gains finalized, decision, runId and a repairable flag.
Why it is not in that PR
packages/spec/src/contracts/approval-service.ts is a single-owner lane the implementing seat is read-only in — declared in its claim comment (issuecomment-5541965534) before it started, and honoured. It reported the item rather than editing across the boundary. ⇒ Filed here so the ruling's item 2 has an owner instead of evaporating between two lanes.
What is and is not owed
⚠️The contract TYPE needs no new fields. Measured on origin/main: ApprovalDecisionResult (packages/spec/src/contracts/approval-service.ts, ~:622) already declares request, finalized, decision, runId?, resumed? and resumeError?, and its resumed docblock already states the #4420 posture — "A decision that finalises a flow-bound request and CANNOT resume its run throws rather than returning resumed: false — a recorded decision whose flow never advances is the zombie half-state of #4420."
The four facts ride the error body, not the success shape. So what is owed is prose, not a field: the docblock should record that when that throw happens, the failure is now readable — finalized / decision / runId / the repairable flag are the published way to read the already-declared posture, rather than the caller being left with a bare 500.
⛔ Do not add the four fields to ApprovalDecisionResult. That would declare a success shape that never carries them.
Sequencing
Blocked-by: #13807 is deliberate: the sentence describes fields that do not exist on main until PR #15436 lands. Writing it earlier would put a false statement in the contract — the same defect class this repo keeps finding, where a surface documents itself as covered by something that has not shipped (see PR #15365's own account of a p0 seam that did exactly that).
⚠️ Whoever takes this: re-read the docblock on the then-current origin/main rather than inheriting the :622 anchor — PR #15436 adds ~52 lines of docblocks to approval-service.ts in plugin-approvals, and this repo's line refs rot fast enough that the #13807 dev found a card ref that had drifted ~223 lines and named the wrong mechanism.
Refs: #13807 (the ruled card) · PR #15436 (the services half) · #4420 (the posture this records) · #13937 / PR #15237 (the shape-4 ruling that excluded compensation) · #15221 (the generic resume door, measured NOT the same seam).
Blocked-by: #13807
Filed by the
domain:servicesexecution seat (session03324ae2-0f5b-5ad2-8a2e-cf4aaff5a909, seat post #6021) as the spec half left unowned by the maintainer's 2026-09-04 ruling on #13807 (director batch #37, verbatim 「同意」 on1B · 2及, issuecomment-5541861039). Cross-lane request into thedomain:speclane. ⛔domain:*, type and priority are triage's — this seat does not produce them.What the ruling owes here
The ruling's execution list, item 2, verbatim:
The services half is implemented in PR #15436 (draft, head
13b58ed7d, under Clause-② contract review):serviceResumecarriesstatus, and a stranded decision's 500-classRESUME_FAILEDerror body gainsfinalized,decision,runIdand a repairable flag.Why it is not in that PR
packages/spec/src/contracts/approval-service.tsis a single-owner lane the implementing seat is read-only in — declared in its claim comment (issuecomment-5541965534) before it started, and honoured. It reported the item rather than editing across the boundary. ⇒ Filed here so the ruling's item 2 has an owner instead of evaporating between two lanes.What is and is not owed
origin/main:ApprovalDecisionResult(packages/spec/src/contracts/approval-service.ts, ~:622) already declaresrequest,finalized,decision,runId?,resumed?andresumeError?, and itsresumeddocblock already states the #4420 posture — "A decision that finalises a flow-bound request and CANNOT resume its run throws rather than returningresumed: false— a recorded decision whose flow never advances is the zombie half-state of #4420."The four facts ride the error body, not the success shape. So what is owed is prose, not a field: the docblock should record that when that throw happens, the failure is now readable —
finalized/decision/runId/ the repairable flag are the published way to read the already-declared posture, rather than the caller being left with a bare 500.⛔ Do not add the four fields to
ApprovalDecisionResult. That would declare a success shape that never carries them.Sequencing
Blocked-by: #13807is deliberate: the sentence describes fields that do not exist onmainuntil PR #15436 lands. Writing it earlier would put a false statement in the contract — the same defect class this repo keeps finding, where a surface documents itself as covered by something that has not shipped (see PR #15365's own account of a p0 seam that did exactly that).origin/mainrather than inheriting the:622anchor — PR #15436 adds ~52 lines of docblocks toapproval-service.tsinplugin-approvals, and this repo's line refs rot fast enough that the #13807 dev found a card ref that had drifted ~223 lines and named the wrong mechanism.Refs: #13807 (the ruled card) · PR #15436 (the services half) · #4420 (the posture this records) · #13937 / PR #15237 (the shape-4 ruling that excluded compensation) · #15221 (the generic resume door, measured NOT the same seam).