Files
suaveplan/openspec/changes/add-import-sse-progress/tasks.md
2026-05-27 23:29:53 +01:00

3.4 KiB

Tasks: add-import-sse-progress

0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. OTel — extend instruments bundle

  • Add sseConnected: Counter (import.sse.connected) to ImportInstruments.
  • Add sseEventsSent: Counter (import.sse.events_sent) labelled by kind.
  • Add sseDisconnected: Counter (import.sse.disconnected) labelled by reason.
  • Update src/otel/instruments.md to describe the three new counters.
  • Extend src/otel/instruments.test.ts to assert the new counters round-trip through a fresh MeterProvider.

2. Route — GET /:id/progress

  • Create src/routes/progress-sse/progress-sse.ts exporting registerProgressSseRoute(app, deps).
  • Wire the handler into createImportRoutes in src/routes/build-routes.ts.
  • Subscribe to service.bus (import.progress, import.completed, import.failed) — NO polling.
  • Forward the request AbortSignal to detach the listener on client disconnect.
  • Frame format: id: <jobId>-<seq>, event: progress|complete|failed, JSON-stringified ImportProgress payload, double-newline terminator.
  • Initial frame: snapshot from service.getJob(id, ownerId) so the client sees current state before the first bus tick.
  • Terminal events (complete / failed) close the stream cleanly.

3. Errors

  • Reuse IMPORT.NOT_FOUND for foreign-owner / missing jobs (404 problem+json).
  • Reuse IMPORT.UNAUTHENTICATED (via requireAuth() middleware already in build-routes.ts) for the 401 path.
  • No new error codes added.

4. Tests

  • src/routes/progress-sse/progress-sse.test.ts covering eight scenarios listed in proposal.md#source-mapping.
  • Tests use Hono's app.request() returning a Response with a streamed body; assertions read via body.getReader() and decode UTF-8.
  • No mocks. Real ImportService, real Hono, real in-memory MeterProvider.

5. Docs

  • src/routes/progress-sse/progress-sse.md (≥200 words, Purpose / Features / Usage Basic / Usage Advanced / API Reference / Implementation Notes).
  • Update package README.md Features list and routes table to include the new SSE endpoint.

6. Subpath export

  • Add ./routes/progress-sse/progress-sse to package.json#exports.

7. Gates (in order)

  • bunx biome check src/
  • bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-import
  • bunx turbo test:coverage --filter=@suaveplan/api-plugin-import (100/100/100/100)
  • bun scripts/openspec-conformance.ts @suaveplan/api-plugin-import (0 errors)
  • bunx turbo build --filter=@suaveplan/api-plugin-import

8. Archive

  • Fold spec delta into openspec/specs/api-plugin-import/spec.md.
  • mv openspec/changes/add-import-sse-progress openspec/archive/2026-05-20-add-import-sse-progress.