Found in smoke #10
Two related defects from PR #136 (V53.1):
Bug 1: `runMultiSurfacePipeline` exists but is never called
`packages/cli/src/cli/run.ts:188` — `runCommand` does not call `runMultiSurfacePipeline` or `resolveSurfaceTopology`. The new V53.1 functions are exported-but-unreachable. Production runs still take the legacy single-surface path: `surface_describe_self()` returns surface[0], and the pipeline iterates exactly that one surface.
Result against the 6-surface fixture: only `self-api` is exercised. The vite surfaces (`self-spa`, `v24-deferred-bugs`) get zero pages discovered, zero tests, zero clusters.
Bug 2: Phases don't stamp `detection.surface`
`BugDetection.surface` field exists per V53.1 but no phase populates it. The cluster signature prefix function in `packages/cli/src/cluster/signature.ts:27` always returns `"unknown|"`. Sample current cluster keys:
- `unknown|auth_bypass_via_unauthed_route|19f7bcb6f389`
- `unknown|sql_injection|3b1c7f42a890`
Cascading effect: the self-test evaluation in `packages/cli/src/cli/self-test.ts:250` checks `sig.startsWith(exp.signaturePrefix)` where gold prefix is just the kind name. Always-`unknown|` means the self-test reports 0/87 matched even when detection is correct.
Fix
For Bug 1
`runCommand` at `cli/run.ts:188` should:
- Call `resolveSurfaceTopology(adapter, config)` to get the surface list
- Call `runMultiSurfacePipeline` with that topology, replacing the current direct `runDiscover/runPlan/runExecute` calls
- Aggregate results from each surface's pipeline into the run summary
The legacy direct-call path can be deleted — `runMultiSurfacePipeline` already handles the single-surface fast path correctly per its tests.
For Bug 2
Where to stamp `detection.surface` (one of these or all):
- Inside `runPhaseForSurface` in `runMultiSurfacePipeline`: post-process the BugDetection[] returned from `runExecute` and stamp `surface` from the bound adapter's `getSurfaceName()`. Cleanest — phases stay agnostic, orchestrator owns the attribution.
- The `BoundSurfaceMcpAdapter` already exposes `getSurfaceName()` — use it in the orchestrator's per-surface result handler.
Tests
- Update `run.multi-surface.test.ts` to assert `runCommand` (not just `runMultiSurfacePipeline` directly) calls per-surface pipelines
- Add an assertion that emitted clusters have `detection.surface` set after orchestrator post-processing
- Update `signature.test.ts` to verify the prefix becomes the actual surface name when `detection.surface` is set
Priority
Highest. V53.1 is currently dead code; the recall blocker the spec promised to remove is still active.
Found in smoke #10
Two related defects from PR #136 (V53.1):
Bug 1: `runMultiSurfacePipeline` exists but is never called
`packages/cli/src/cli/run.ts:188` — `runCommand` does not call `runMultiSurfacePipeline` or `resolveSurfaceTopology`. The new V53.1 functions are exported-but-unreachable. Production runs still take the legacy single-surface path: `surface_describe_self()` returns surface[0], and the pipeline iterates exactly that one surface.
Result against the 6-surface fixture: only `self-api` is exercised. The vite surfaces (`self-spa`, `v24-deferred-bugs`) get zero pages discovered, zero tests, zero clusters.
Bug 2: Phases don't stamp `detection.surface`
`BugDetection.surface` field exists per V53.1 but no phase populates it. The cluster signature prefix function in `packages/cli/src/cluster/signature.ts:27` always returns `"unknown|"`. Sample current cluster keys:
Cascading effect: the self-test evaluation in `packages/cli/src/cli/self-test.ts:250` checks `sig.startsWith(exp.signaturePrefix)` where gold prefix is just the kind name. Always-`unknown|` means the self-test reports 0/87 matched even when detection is correct.
Fix
For Bug 1
`runCommand` at `cli/run.ts:188` should:
The legacy direct-call path can be deleted — `runMultiSurfacePipeline` already handles the single-surface fast path correctly per its tests.
For Bug 2
Where to stamp `detection.surface` (one of these or all):
Tests
Priority
Highest. V53.1 is currently dead code; the recall blocker the spec promised to remove is still active.