Skip to content

fix(capture-recovery): type attempt counters as AttemptNumber, brand captureId at ingress - #36

Open
obvious-autobuild[bot] wants to merge 1 commit into
masterfrom
fix/capture-recovery-attempt-type
Open

obvious-autobuild[bot] wants to merge 1 commit into
masterfrom
fix/capture-recovery-attempt-type

Conversation

@obvious-autobuild

Copy link
Copy Markdown
Contributor

Why

PR #15 (9ea7e73) merged with the recovery schemas referencing domain's ExtractionAttempt — which contract v0.3 adaptation A5 renamed to name the attempt record — where a numeric counter was intended (the canonical counter type is AttemptNumber, itself introduced by A5's rename note in packages/domain/src/extraction.ts). The mismatch fails three gates on master for every PR in the repo: pnpm turbo run typecheck (10/11), test (7/8, runtime: fail-closed decodeStoredState rejects numeric attempts — "Expected object" at fixture event steps[2].attempt), and build (5/6).

Acceptance criteria

  1. pnpm turbo run typecheck green (11/11) on the exact head.
  2. pnpm turbo run test green (8/8) — includes capture-recovery's 20 bun tests / 107 assertions.
  3. pnpm turbo run build green (6/6).
  4. bun test ./security green (29/0); month-history journeys 28/28; evaluation harness 6/6.
  5. No behavior change: fixtures, reducer arithmetic (state.attempt + 1, event.attempt < state.attempt), timeline entries, and test expectations already used numeric semantics everywhere — the schemas now match the code's actual contract.

What changed

  • state.ts — CaptureRecoveryState.attempt and DiscardReceipt.attempt typed as AttemptNumber (was ExtractionAttempt).
  • events.ts — SubmitRejected.attempt and ExtractionResultArrived.attempt typed as AttemptNumber.
  • reducer.ts — createCapture brands captureId at ingress via Schema.decodeSync(CaptureId) so the branded state field is honestly constructed (fail-closed on empty; fixtures/tests unchanged at call sites).
  • test/recovery.test.ts — the two captureId list expectations use the same brand helper.

Tradeoffs

Alternatives rejected: loosening the state schema (captureId: Schema.String) would weaken the canonical identifier alignment the package's own comment pins ("Same identifier space as the canonical extraction envelope"); leaving the repair to ride in PR #33 would put an unrelated package inside a reviewed catch-up PR's diff. Kept: schema-only alignment with the already-shipped v0.3 rename; zero runtime behavior change.

Verification

All run at this branch's head 48e4b81 (parent 9ea7e73): turbo typecheck 11/11, test 8/8, build 6/6 (uncached); capture-recovery bun test 20 pass / 0 fail; security 29/0; journeys 28/28; harness 6/6.

Human author: Gilbert Polanco (gilbertpolanco42@gmail.com)

🔗 Obvious Project · 🧵 Obvious Thread

…captureId at ingress

PR #15's recovery schemas referenced domain's `ExtractionAttempt` (the
attempt RECORD, per contract v0.3 adaptation A5) where the numeric counter
was intended — the record type that v0.3 renamed AWAY from that name. The
fixtures, reducer arithmetic (attempt + 1), comparisons, and expectations
all treat attempt as a number, so the wrong field type failed three gates
on master: typecheck (TS2322/TS2365 across state/replay/tests), runtime
test (fail-closed decodeStoredState rejected numeric attempts — "Expected
object"), and build.

- state.ts: CaptureRecoveryState.attempt and DiscardReceipt.attempt →
  AttemptNumber
- events.ts: SubmitRejected.attempt and ExtractionResultArrived.attempt →
  AttemptNumber
- reducer.ts: createCapture brands captureId at ingress via
  Schema.decodeSync(CaptureId) (canonical identifier space, fail-closed on
  empty) so the branded state field is honestly constructed
- test: brand the two captureId expectations the same way

No behavior change: every fixture, reducer branch, and expectation already
used numeric semantics; this aligns the schemas with the code's actual
contract and unblocks the shared typecheck/test/build gates for all PRs.

Co-authored-by: Gilbert Polanco <gilbertpolanco42@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants