Files
suaveplan/openspec/archive/2026-05-16-fix-storage-uri-error-passthrough/tasks.md
2026-05-27 23:29:53 +01:00

6.0 KiB

Tasks — fix-storage-uri-error-passthrough

Every checkbox MUST reflect work actually done in this change.

1. Spec authoring

  • 1.1 Read openspec/changes/add-storage-uri/specs/storage-uri/spec.md requirements "Adapter error re-wrapping" and "Streaming writes with buffered fallback"
  • 1.2 Read openspec/changes/add-drive-uri/specs/drive-uri/spec.md — confirm the wrap-aware scenarios to tighten
  • 1.3 Read openspec/AGENTS.md §0c, §2c, §13, §13a, §14
  • 1.4 Read packages/core/error/src/error.ts (or equivalent) — confirm SuaveplanError is the right instanceof target
  • 1.5 Draft proposal.md, specs/storage-uri/spec.md (MODIFIED form), specs/drive-uri/spec.md (MODIFIED form), tasks.md
  • 1.6 Build numbered Requirement/Scenario implementation checklist (§0c step 6) — 2 MODIFIED storage-uri requirements, 3 MODIFIED drive-uri requirements

2. Storage-uri implementation

  • 2.1 Locate the resolver's error-handling branch — packages/storage/storage-uri/src/resolver/resolver.ts (#wrapAdapterError or equivalent)
  • 2.2 Change the discriminator from err instanceof StorageUriError to err instanceof SuaveplanError
  • 2.3 Same change in the write path — packages/storage/storage-uri/src/resolver/resolver.writes.ts (WRITE_UNSUPPORTED wrap branch)
  • 2.4 Verify the import is from @suaveplan/error (it already is for StorageUriError's base — SuaveplanError ships from there)
  • 2.5 Update sibling .md docs — resolver.md, resolver.writes.md — to describe the new pass-through behaviour (§4a doc-drift gate)
  • 2.6 Update README "Features" section if it claims errors are uniformly wrapped

3. Storage-uri tests

  • 3.1 src/resolver/resolver.test.ts — rename existing "wraps adapter errors as ADAPTER_ERROR" to "wraps non-SuaveplanError throwables as ADAPTER_ERROR"; assertion stays (plain Error thrown → STORAGE_URI.ADAPTER_ERROR wrap)
  • 3.2 src/resolver/resolver.test.ts — add it("passes through thrown SuaveplanError subclasses unchanged", ...) — instantiate a SuaveplanError("FOO.BAR", ...) directly (no need to import DriveUriError), throw from a fake adapter, assert resolver re-throws same instance with err.code === "FOO.BAR"
  • 3.3 src/resolver/resolver.writes.test.ts — rename existing "wraps read-only adapter error as WRITE_UNSUPPORTED" to "wraps non-Suaveplan throw on set as WRITE_UNSUPPORTED" and switch the fixture to throw a plain new Error(...) (not a StorageHttpError); assertion stays
  • 3.4 src/resolver/resolver.writes.test.ts — add it("passes through thrown SuaveplanError subclasses on write", ...) — fake adapter throws new SuaveplanError("FOO.BAR", ...) from set, assert resolver re-throws same instance
  • 3.5 Every it(...) carries { timeout: 5000 }
  • 3.6 No vi.mock; tests construct real fake adapters per CLAUDE.md rule 2
  • 3.7 All test imports remain via @suaveplan/testing/runner (rule 11)

4. Drive-uri test tightening (no production code change)

  • 4.1 packages/drive/drive-uri/src/plugins/drive/drive.test.ts — switch the DRIVE_ID_MISMATCH test from asserting err.cause.code === "DRIVE_URI.DRIVE_ID_MISMATCH" to asserting err.code === "DRIVE_URI.DRIVE_ID_MISMATCH" (and err instanceof DriveUriError)
  • 4.2 packages/drive/drive-uri/src/plugins/drive/drive.test.ts — switch the WRITE_UNSUPPORTED test to direct-code assertion
  • 4.3 packages/drive/drive-uri/src/plugins/drive-template/drive-template.test.ts — switch TEMPLATE_NOT_AVAILABLE and TEMPLATE_INVALID tests to direct-code assertion
  • 4.4 packages/drive/drive-uri/src/plugins/drive-mesh/drive-mesh.test.ts — same treatment if a .cause-based assertion exists
  • 4.5 Coverage stays at 100/100/100/100 (no production code changed; some branches in the test helpers may become unreachable — remove unused helpers if so per §7a — write the test against real behaviour, don't preserve dead code)

5. Spec annotation cleanup (drive-uri)

  • 5.1 In openspec/changes/add-drive-uri/specs/drive-uri/spec.md, remove the top-of-file > **Note — error-wrap behaviour is revisited in fix-storage-uri-error-passthrough.** paragraph (the behaviour it described is now retired by this change)
  • 5.2 Keep the second top-of-file > **Note — buffered-read signal threading is revisited in add-signal-to-storage-like.** paragraph as-is (separate concern, not retired yet)
  • 5.3 Confirm no remaining scenarios in add-drive-uri/specs/drive-uri/spec.md reference STORAGE_URI.ADAPTER_ERROR or "cause.code" indirection for drive-uri throws — if any remain, tighten them in this delta

6. Gates

  • 6.1 bunx turbo lint typecheck test --filter=@suaveplan/storage-uri
  • 6.2 bunx turbo test:coverage --filter=@suaveplan/storage-uri --force — 100/100/100/100 Istanbul
  • 6.3 bunx turbo lint typecheck test --filter=@suaveplan/drive-uri
  • 6.4 bunx turbo test:coverage --filter=@suaveplan/drive-uri --force — 100/100/100/100 Istanbul
  • 6.5 bunx turbo build --filter=@suaveplan/storage-uri @suaveplan/drive-uri
  • 6.6 Dependent sweep — bunx turbo test --filter=...@suaveplan/storage-uri (catches any consumer that asserted on err.code === "STORAGE_URI.ADAPTER_ERROR" for what is now a passed-through SuaveplanError)
  • 6.7 bun scripts/lint/check-test-runner-imports.ts
  • 6.8 Banned-pattern scan empty for both packages' src/
  • 6.9 Spec-reconciliation gate — every modified scenario's **Verified by:** test name exists verbatim

7. Manifest & archival (defer)

  • 7.1 This change folder remains in openspec/changes/ until add-storage-uri and add-drive-uri are archived together. The fold step for all three changes happens as a single archival wave so the canonical openspec/specs/storage-uri/spec.md and openspec/specs/drive-uri/spec.md reflect the final, pass-through behaviour from day one.
  • 7.2 At archive time, the modified scenarios from this delta supersede the originals in the add-storage-uri / add-drive-uri deltas during the fold.