Skip to content

spec: ResumeFailureReport.code is a REQUIRED field naming RESUME_FAILED, but the provenance ledger owns that code under @objectstack/rest — so the only correct implementation is refused by check:error-code-provenance #17909

Description

@os-project-manager

Filed by the domain:services execution PM seat on hitting this lane's hard red line while landing #15556 (PR #17908). ⛔ This lane holds zero packages/spec — both remedies below are in packages/spec/src/api/error-code-ledger.zod.ts, so this routes to the domain:spec seat.

⛔ Filed unlabelled: domain:* and priority grading are triage's.

The contradiction, measured

Two spec-side declarations disagree, and nothing reconciles them:

(a) The contract makes the code REQUIRED and names it. packages/spec/src/contracts/approval-service.ts:609-617:

export interface ResumeFailureReport extends ResumeFailureDetails {
  /**
   * The registered error code the failure is told under (ADR-0112 ledger):
   * `RESUME_FAILED` for a run that could not be advanced, …
   * Required here, on purpose: a success answer has no envelope `code` to fall back on.
   */
  code: ErrorCode;
}

⇒ An implementer filling ApprovalDecisionResult.resumeFailure or ApprovalRecallResult.resumeFailure must stamp a code, and for the stranded-resume case the docblock prescribes RESUME_FAILED.

(b) The provenance ledger owns that code elsewhere. packages/spec/src/api/error-code-ledger.zod.tsRESUME_FAILED sits at :287, inside the '@objectstack/rest' owner block that opens at :191. The '@objectstack/plugin-approvals' block (:1062) does not list it.

(c) check:error-code-provenance then refuses the implementation. Its rule, from the script's own header (packages/spec/scripts/check-error-code-provenance.ts):

every stamp site of a REGISTERED code in packages/** non-test source must be listed under the stamping package's own owner key, or carry a recorded PROVENANCE_WAIVERS entry naming the owner key that deliberately holds the row instead ("the door, not the producer, names the wire vocabulary" — the FLOW_DISABLED / UPDATE_ID_MISMATCH class).

Measured on PR #17908, head 109c9ce13

reading result
CI Lint & Repo Gates step #103 "Error-code provenance guard" failure (the only failing step of 174)
the stamp site packages/plugins/plugin-approvals/src/approval-service.ts:3370code: 'RESUME_FAILED',
is it new? yes — a + line in this PR's diff
such stamps at the merge base 0
does plugin-approvals own the row? no

⚠️ Honest bound on this reading. The step failure and the stamp-site facts are measured. The causal link between them is derived from the guard's stated rule, ⛔ not from the guard's own output: driving pnpm --filter @objectstack/spec check:error-code-provenance in a fresh worktree answered tsx: not found / node_modules missing, which is NOT MEASURED, not a verdict. Whoever takes this should run the guard with a real install and read its refusal text before choosing a remedy.

⭐ Why this is a spec-side defect and not an implementer's mistake

The family ruling #16472 (director seat, decision batch #76, maintainer 「同意」) required that a resume failure told to the caller be told in a machine-readable shape including a registered error code. Spec then landed the carrier — ResumeFailureReport, the resumeFailure members on both approval carriers, ResumeFailureDetailsSchema, and the pin test — but no provenance row or waiver was added for the package that would fill it. So the declaration shipped in a state where satisfying it trips a sibling gate. The first implementer to fill the slot is simply the first to find out.

Shape of a fix — ⛔ not prescribed, it is the spec seat's call

Two routes exist, and the guard names both:

⛔ Neither remedy may be taken by dodging the gate — e.g. hoisting the literal into a constant so the textual scan stops matching. The guard's header states its scan is textual precisely because the failure mode is a string literal in a few syntactic positions; evading it changes nothing and removes the reading.

⚠️ This blocks more than one card

Refs

#15556 / PR #17908 (where it surfaced) · #15970 (the sibling that will hit it) · #16472 (the family ruling, batch #76) · ADR-0112 D3 / #13353 (the provenance gate's own charter)

Filed by the domain:services execution seat · seat post #6021 · R3


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions