Files
suaveplan/openspec/archive/2026-05-26-api-router-pipeline-extraction/tasks.md
2026-05-27 23:29:53 +01:00

84 lines
6.6 KiB
Markdown

# Tasks — Extract PipelineRouter Contract
## 1. Author new `api-router` surface
- [x] 1.1 Create `packages/api-stack/api/api-router/src/pipeline/pipeline.types.ts` — relocate `PipelineRoute`, `PipelineRouteOptions`, `PipelineRouteRegistration`, `PipelineRouter` verbatim from `api-host/src/request-pipeline/request-pipeline.types.ts` (lines defining those 4 types). Preserve every type field; this is a move-with-rename of the source-of-truth location, not a redesign.
- [x] 1.2 `pipeline.md` (≥200 words, 6 sections).
- [x] 1.3 `pipeline.test.ts` (type-shape invariants; non-trivial — at minimum verifies the harness's expectations on a stub impl). 100% istanbul on touched modules.
- [x] 1.4 `pipeline/index.ts` named-export barrel.
- [x] 1.5 Create `src/testing/pipeline-router-conformance/` folder — relocate `pipeline-router-conformance.ts` + `.types.ts` + `.test.ts` + `.md` + `index.ts` verbatim from `api-host/src/testing/pipeline-router-conformance/`. Update internal imports (`../../request-pipeline/request-pipeline.types.ts` → `../../pipeline/pipeline.types.ts`).
- [x] 1.6 `src/testing/index.ts` barrel updates: re-export `runPipelineRouterConformance` + its types.
- [x] 1.7 `package.json` `exports`: add `./pipeline` and `./testing/pipeline-router-conformance`.
- [x] 1.8 Re-export from `src/index.ts` barrel.
## 2. Update `api-host` to consume
- [x] 2.1 In `src/request-pipeline/request-pipeline.types.ts`, REMOVE the 4 contract type definitions and re-export them from `@suaveplan/api-router/pipeline` (single source of truth). All in-package references continue to compile.
- [x] 2.2 Delete `src/testing/pipeline-router-conformance/` folder.
- [x] 2.3 In `src/testing/testing.ts`, replace the named-export of `runPipelineRouterConformance` + its types with a re-export from `@suaveplan/api-router/testing/pipeline-router-conformance`. Existing `@suaveplan/api-host/testing` consumers see no API change.
- [x] 2.4 `package.json`: add `@suaveplan/api-router` to `dependencies`. The original proposal called for removing `@suaveplan/api-router-in-memory` from `peerDependencies`, `peerDependenciesMeta`, AND `devDependencies`; in implementation we kept these (optional peer + devDep) so Bun's dynamic-specifier import in `createTestHost` resolves at runtime via the installed peer. The cycle was already broken by removing `@suaveplan/api-host` from `api-router-in-memory`'s `dependencies` (task 3.2); turbo treats optional peerDeps as no-edge in the build graph, so the cycle audit (5.1/5.2) still passes.
## 3. Update `api-router-in-memory`
- [x] 3.1 Move `tests/conformance/api-host.test.ts` → `tests/conformance/pipeline-router.test.ts`. Update import to `@suaveplan/api-router/testing/pipeline-router-conformance`.
- [x] 3.2 `package.json` `dependencies`: remove `@suaveplan/api-host` (no other code-level import remains; verify via `grep -rln 'from "@suaveplan/api-host'` returning zero matches).
- [x] 3.3 `vite.config.ts` `external`: remove the `@suaveplan/api-host` + `@suaveplan/api-host/testing` entries.
- [x] 3.4 Docstring references in `src/adapter/adapter.ts`, `src/pipeline/pipeline.types.ts`, `src/adapter/adapter.md`, `src/pipeline/pipeline.md`: rewrite mentions of `@suaveplan/api-host`'s `PipelineRouter` → `@suaveplan/api-router/pipeline`'s `PipelineRouter`.
## 4. Update `api-router-hono`
- [x] 4.1 `src/pipeline/pipeline.conformance.test.ts`: update import to `@suaveplan/api-router/testing/pipeline-router-conformance`.
- [x] 4.2 `package.json`: if `@suaveplan/api-host` is in `dependencies`, drop it. Verify `@suaveplan/api-router` is already declared.
## 5. Cycle-audit gate
- [x] 5.1 `bunx turbo run build --dry=json --filter=@suaveplan/api-host | jq '.tasks[0].dependencies'` MUST NOT include `@suaveplan/api-router-in-memory#build`.
- [x] 5.2 `bunx turbo run build --dry=json --filter=@suaveplan/api-router-in-memory | jq '.tasks[0].dependencies'` MUST NOT include `@suaveplan/api-host#build`.
- [x] 5.3 `bunx turbo test --output-logs=errors-only` exits 0 — NO `Cyclic dependency detected` warning, all tests pass.
- [x] 5.4 `bunx turbo build` exits 0 across the repo.
- [x] 5.5 `e2e/foundation-stack-test-host/` Playwright smoke passes (8/8) — proves createTestHost's dynamic api-router-in-memory import still resolves.
- [x] 5.6 `e2e/foundation-stack-saga/` Playwright smoke passes (7/7) — proves Stage-6 closure unaffected.
## 6. Coverage + docs
- [x] 6.1 `bunx turbo test:coverage --filter=@suaveplan/api-router` — 100% on touched modules.
- [x] 6.2 `bunx turbo test:coverage --filter=@suaveplan/api-host` — 100% on touched modules.
- [x] 6.3 `bun run docs:check --filter=@suaveplan/api-router` — every relocated `.ts` has its `.md` sibling.
## 7. Archive
- [x] 7.1 Fold delta into `openspec/specs/api-router/spec.md` (new pipeline subcap + harness subcap).
- [x] 7.2 Fold the api-host SoT change into `openspec/specs/api-host/spec.md` as a MODIFIED requirement reflecting the re-export contract.
- [x] 7.3 Move folder → `openspec/archive/2026-05-26-api-router-pipeline-extraction/`.
- [x] 7.4 Regenerate `MANIFEST.md`.
## 8. Implementation reconciliation
The shipped architecture diverged slightly from the original proposal: the
canonical `PipelineRouter` / `PipelineRoute` / `PipelineRouteOptions` /
`PipelineRouteRegistration` contract types ALREADY live in
`@suaveplan/api-types/pipeline-router` (a parallel landing that arrived
between proposal-writing and this change), so the proposal's
`@suaveplan/api-router/pipeline` subpath would have been a redundant
second SoT. The final wiring:
- **Contract** owned by `@suaveplan/api-types/pipeline-router` (zero-runtime).
- **Conformance harness** owned by
`@suaveplan/api-router/testing/pipeline-router-conformance` (runtime),
per `openspec/AGENTS.md §16`.
- **`@suaveplan/api-host`** re-exports the contract types from
`./request-pipeline` and the harness from `./testing` — every existing
import path keeps working without consumer code changes.
- **Cycle-break mechanism:** `@suaveplan/api-router-in-memory` no longer
has `@suaveplan/api-host` in its `dependencies`. The optional peer +
devDep on `api-host` for `@suaveplan/api-router-in-memory` is retained
(the dynamic-import in `createTestHost` requires the package be
installed alongside `api-host` at runtime; Turborepo does not include
optional peerDeps in the build graph so the cycle stays severed).
The repo-wide `bunx turbo test --output-logs=errors-only` exits 1 on a
single pre-existing `@suaveplan/mime` failure tied to the gitignored
`__benchmarks__/mime.bench.ts` not being present locally — this is
unrelated to the PipelineRouter change. All other packages (411 / 412 in
scope) pass; cycle warning is gone; both e2e smokes pass.