8.7 KiB
8.7 KiB
Tasks — add-storage-uri-plugin-fallback
Every checkbox MUST reflect work actually done in this change.
1. Spec authoring
- 1.1 Read
openspec/AGENTS.md§0, §0a, §0b, §0c, §13, §14 - 1.2 Read
openspec/project.md - 1.3 Read
openspec/specs/storage-uri/spec.mdto confirmUriPlugin+StorageUriResolvercontract - 1.4 Read
packages/storage/storage-uri/src/(resolver, types, conformance) for recursive-dispatch surface - 1.5 Read
packages/flow/retry/src/to confirmRetryStrategysurface for documentation cross-links - 1.6 Read
openspec/changes/complete-storage-mux/for the multi-backend failover precedent (error classification, fan-out semantics, span hierarchy) - 1.7 Draft
proposal.md,design.md,specs/storage-uri-plugin-fallback/spec.md,tasks.md - 1.8 Numbered Requirement/Scenario checklist per §0c step 6 — every requirement and every scenario in the delta tracked as an unchecked item until implementation lands
2. Scaffolding
- 2.1 Create
packages/storage/storage-uri-plugin-fallback/ - 2.2
package.jsonv0.0.0,"sideEffects": false, subpath exports per feature directory - 2.3 Deps:
@suaveplan/error,@suaveplan/events,@suaveplan/storage-uri,@suaveplan/types,@opentelemetry/api,zod,tslib - 2.4 DevDeps:
@suaveplan/storage,@suaveplan/storage-file,@suaveplan/testing,@vitest/coverage-istanbul,fast-check,mitata,typescript,vite,vite-plugin-dts,vitest - 2.5
tsconfig.json,vite.config.ts,vitest.config.tsviacreateTestConfigwiththresholds: 100/100/100/100 - 2.6 Root
README.mdwith Modules section linking every co-located.md
3. Error registry
- 3.1
src/error-codes/error-codes.ts—defineCodes("FALLBACK_URI", [...])with all 8 codes:NO_CANDIDATES,INVALID_URI,ALL_CANDIDATES_FAILED,WRITE_MIRROR_FAILED,LIST_UNION_FAILED,ABORTED,MAX_DEPTH_EXCEEDED,CIRCULAR_REFERENCE - 3.2
FallbackUriError extends SuaveplanError<FallbackUriErrorCode>withuri,candidateIndex,candidateUri,candidateErrors,mirrorOutcomes,cycleChain,depthdiscriminants (only the ones relevant to each code are populated) - 3.3
error-codes.md+error-codes.test.ts— reachability sweep proving every code is thrown from a real call site
4. Types & schemas
- 4.1
src/types/policy.types.ts—FallbackPolicy(errorClass,maxParallel,stopOnAbort,writeMode,deleteMode,listMode,listFailureMode,maxDepth,maxCandidates),FallbackPluginOptions - 4.2
src/types/policy.schemas.ts— Zod schemas:maxParallel >= 1,maxDepth >= 1 && <= 8,maxCandidates >= 1 && <= 64, mode enums - 4.3
src/types/candidate.types.ts—CandidateError,CandidateAttempt,MirrorOutcome
5. URI grammar
- 5.1
src/parse-uri/parse-fallback-uri.ts—parseFallbackUri(uri)returning{ candidates: readonly string[]; canonicalUri: string };buildFallbackUri(uris)withURLSearchParams; reject empty / oversized / non-fallbackscheme / non-empty authority - 5.2
src/parse-uri/parse-fallback-uri.md+.test.ts— exhaustive validation matrix; fast-check round-trip propertybuildFallbackUri ∘ parseFallbackUri = identityon a small generator - 5.3
src/parse-uri/abort-any.ts—AbortSignal.anyshim guarded bytypeof AbortSignal.any !== "function"
6. Classification
- 6.1
src/classify/classify.ts+.md+.test.ts— pureclassify(err, policy) => "transient" | "semantic" | "abort"per design §7; consumes@suaveplan/error#SuaveplanErrorfor code inspection
7. Recursion context
- 7.1
src/recursion/depth-context.ts+.md+.test.ts—DepthContextvalue type,withChildContexthelper that bumps depth + extends visited set, depth-cap enforcement throwingMAX_DEPTH_EXCEEDED, visited-set canonicalisation viaparseFallbackUrireserialisation
8. Walk strategies
- 8.1
src/walk/sequential.ts+.md+.test.ts— ordered fall-through; emits attempt-failed events; throwsALL_CANDIDATES_FAILEDon exhaustion withcandidateErrorspopulated - 8.2
src/walk/parallel.ts+.md+.test.ts—Promise.any-style race with concurrency cap (maxParallel); cancels pending candidates viaAbortSignal.anyonce one succeeds
9. Operations (full UriPlugin surface)
- 9.1
src/ops/read.ts+.md+.test.ts—get(key)+createReadStream(key, signal)+ range{ offset, length }propagation - 9.2
src/ops/write.ts+.md+.test.ts—set(key, bytes)+createWriteStream(key, body, signal);writeMode: "all"→Promise.allSettled+WRITE_MIRROR_FAILED;writeMode: "first-success"→ walk + background settle - 9.3
src/ops/metadata.ts+.md+.test.ts—exists+getMetadatasequential walk - 9.4
src/ops/delete.ts+.md+.test.ts— mirror delete withdeleteMode: "any-success" | "all"(default"any-success") - 9.5
src/ops/list.ts+.md+.test.ts— union with dedup;listMode: "union" | "concat";listFailureMode: "throw" | "partial"
10. Observability
- 10.1
src/observability/events.ts+.md+.test.ts— topic constants (storage-uri.fallback.attempt-failed,.attempt-succeeded,.write-mirror-partial,.cycle-detected,.depth-exceeded); emit helpers consumingEventBusLike - 10.2
src/observability/otel.ts+.md+.test.ts— counterstorage_uri.fallback_total{candidate_index, scheme, outcome}, histogramstorage_uri.fallback_walk_ms{outcome}, parent + per-attempt child spans with attribute set
11. Plugin factory
- 11.1
src/plugin/plugin.ts+.md—fallbackUriPlugin(options); wires walk + ops + observability + recursion; binds tofallbackscheme; producesUriPluginwhoseadapterexposes the full streaming-extendedStorageLikesurface - 11.2
src/plugin/plugin.test.ts— construction validation (missing resolver, bad policy), abort short-circuit, sequential success, sequential exhaustion, parallel race, mirror write, cycle, depth cap - 11.3
src/plugin/plugin.spec-conformance.test.ts—runUriPluginConformance(plugin, fixtures)pass withvalidUris/invalidUris/buildRoundTrippopulated fromparseFallbackUri/buildFallbackUri
12. Fallback-specific conformance
- 12.1
src/conformance/fallback-conformance.ts+.md—runFallbackConformance(resolver, fixtures)exporting the harness consumers (audio-IR loader, drive+CDN pairing) call from their own tests - 12.2
src/conformance/fallback-conformance.test.ts— self-test against the in-package plugin: K-fail-then-success, all-fail, abort, cycle, depth, mirror-write
13. Barrel + exports
- 13.1
src/index.ts— explicit named re-exports per §6a (NOexport *) - 13.2
package.jsonsubpath exports — one entry per feature directory; verify count matches
14. Documentation
- 14.1 Sibling
.mdfor every implementation.ts(≥ 200 words, all required sections, real-import examples) - 14.2
README.md— install, URI grammar, simple example (fallbackUriPluginregistered alongside other plugins), advanced example (mirror writes + dedup list across CDN + drive), policy reference, complementarity note linking to@suaveplan/storage-mux
15. Gates
- 15.1
bun run check - 15.2
bunx turbo lint typecheck test --filter=@suaveplan/storage-uri-plugin-fallback - 15.3
bunx turbo test:coverage --filter=@suaveplan/storage-uri-plugin-fallback(100/100/100/100) - 15.4
bun scripts/lint/check-test-runner-imports.ts→ zero output for this package - 15.5 Tier-purity grep
grep -rnE "from ['\"](node:|bun:)" packages/storage/storage-uri-plugin-fallback/src/→ empty - 15.6 Banned-pattern scan
grep -rn "@deprecated\|TODO\|FIXME\|ts-ignore\|ts-expect-error\|\.skip\|\.only" packages/storage/storage-uri-plugin-fallback/src/ --include="*.ts"→ empty - 15.7 Barrel-shape scan per §6a → empty
- 15.8 Bare-version scan → empty
- 15.9 Missing
.mdscan → empty - 15.10 README present
- 15.11 Subpath export count matches feature module count
- 15.12
bun scripts/openspec-conformance.ts @suaveplan/storage-uri-plugin-fallback - 15.13 Dependent sweep
bunx turbo test --filter=...@suaveplan/storage-uri-plugin-fallback
16. Manifest & archival
- 16.1
bun scripts/folder-reorg/generate-manifest.ts - 16.2
bun scripts/generate-missing.ts - 16.3 Update
STATUS.mdandSUMMARY.md - 16.4
bunx markdownlint-cli2 --fix - 16.5 Fold
specs/storage-uri-plugin-fallback/spec.md→openspec/specs/storage-uri-plugin-fallback/spec.md - 16.6 Move change folder →
openspec/archive/<yyyy-mm-dd>-add-storage-uri-plugin-fallback/