refactor(commands): retire the navigation-only type projection - #2294
Conversation
`commands/system/navigation-projection.ts` built the five navigation client methods out of a phantom-typed registry: a `unique symbol` brand carrying Options/Result/required-ness, two conditional types to read them back, and a mapped type keyed on `clientMethod`. Nothing else ever used the concept, so the machinery existed to derive five signatures that fit in five lines. Those five now say what they mean. `BackCommandOptions`, `HomeCommandOptions`, `OrientationCommandOptions`, `AppSwitcherCommandOptions` and `TvRemoteCommandOptions` join their siblings in `packages/contracts/src/client-system.ts`, and `AgentDeviceCommandClient` declares all 14 methods in one object type. `back` keeps the `--settle` triple (#1638), and `orientation`/`tv-remote` keep their required options parameter. The five MCP output schemas move to `mcp/command-output-schemas.ts` beside the other handwritten ones, byte-identical. With the projection gone, `defineExecutableCommand`'s third overload, `ExecutableCommandProjection`, `AnyCommandDefinition.projection`, `ProjectedCommandOutputSchemas`/`projectCommandOutputSchemas` and the family's `clientCommandMethods` table have no users either. Removing the table also removes the `as unknown as` cast the client used to build eight system methods from it; the client now writes all eight out, typed. That closes the `commands/system` -> `client` inversion the client-types header called the one remaining one. Public API: the five method signatures are unchanged (structural comparison of the built `dist/src/index.d.ts` before and after: empty diff). `HomeCommandOptions` is a new published name for the shape `home` already took. Tests seen red before green: - `src/__tests__/client-system-commands.test.ts` (new): wired `home` to the `app-switcher` daemon command, saw it fail, restored. - `src/mcp/__tests__/command-tools.test.ts`: dropped `durationMs` from the inlined `tv-remote` schema, saw the dispatch-shape assertion fail, restored. - `src/commands/system/index.test.ts`: made `home`'s options parameter required, saw `expectTypeOf` fail under `pnpm typecheck`, restored.
…hemas Retiring the projection replaced an identity assert (`schema === projection.outputSchema`) with a deep-equal over properties/required, which no longer rejected an extra top-level key such as a stray `description` or `additionalProperties`. The loop now also asserts the key set is exactly type/properties/required, so the closed shape is pinned by a test again rather than by object identity. Seen red once by giving the `app-switcher` schema a description argument, which adds a top-level `description` key: the new assert failed with `+ "description"`. Green after removing it. The `deriveSettleObservationSchemas` docstring cited that deleted identity assert as the reason for copying. The press/click shared-object half is the real reason and is all that remains.
…nale The R6 baseline numbers are unchanged (5 inversions, commands -> client still 3): retiring the projection removed a client -> commands edge, which the ratchet does not count. What changed is the ARGUMENT next to those numbers. The commands/mcp -> client bullet justified itself with a zone-level cycle (client-types.ts imported ProjectedNavigationCommandClient back out of commands/system/); that cycle no longer exists, so the bullet now rests only on the port argument that was always the second half of it. docs/dependency-graph-findings.md §0/§0b/§1 carried the same claim and the same 'move the navigation-projection types out of commands/' follow-up, now recorded as answered by deletion. The blocked-shapes table in §1 now reads eight-at-the-time / three-still-blocked, matching the struck navigation row directly under it.
Size Report
npm unpacked components
Startup median (7 runs, lower is better):
Top changed chunks:
Top changed packed files
|
|
Reviewed exact head |
|
Re-reviewed exact head |
|
* origin/main: perf: bundle runtime dependencies and report full install size (#2310) ci: avoid unrelated Apple runner cache invalidation (#2303) fix(web): preserve the backend ref so snapshot refs match actionable refs (#2283) test(daemon): session-open-url-prewarm through the request seam (#2304) test(daemon): session-devices-batch-runtime through the request seam (#2305) chore(gates): layering baselines ratchet against merge-base (#2299) test(daemon): one typed conformance helper for the daemon runtime suites (#2298) chore(layering): derive the contracts export inventory from package.json (#2297) perf: bundle tar-stream to reduce install footprint (#2286) docs: simplify agent context and resolve conflicting guidance (#2287) refactor(cli): let help resolve command aliases itself and retire R12 (#2293) refactor(commands): retire the navigation-only type projection (#2294) feat(runtime): route managed leases through contained transports (#2285) refactor(contracts): build unavailable runtime facts once (#2291) refactor(cli): derive the common flag readers from the common-field table (#2292) feat(daemon): add managed allocation operation journal (#2284)
Summary
commands/system/navigation-projection.tsderived five client method signatures from aphantom-typed registry: a
unique symbolbrand carrying Options/Result/required-ness, conditionaltypes to read them back, and a mapped type keyed on
clientMethod. Nothing else used it.Before, the published
.d.tsresolvedcommand.backthroughProjectedNavigationCommandClient<DeviceCommandBaseOptions>and that brand; after, the facade saysback: (options?: BackCommandOptions) => Promise<CommandResult<'back'>>, with the five Optionstypes beside their siblings in
packages/contracts/src/client-system.ts.backkeeps its--settletriple (#1638);orientationandtv-remotekeep their requiredoptions parameter. The five MCP output schemas move next to the other handwritten ones. With the
projection gone,
defineExecutableCommand's third overload,ExecutableCommandProjection,AnyCommandDefinition.projection,projectCommandOutputSchemasand the family'sclientCommandMethodstable have no users either; dropping that table also drops theas unknown ascast the client used to build its eight system methods.Validation
Tested commit: 335506b — pnpm check:affected --run green locally (format, lint, typecheck, layering, di-seams, fallow, mcp-metadata, build, package, integration-node, macos-coverage, vitest-related, integration-progress, replay-compat, daemon-wire-compat, affected-selector, gate-manifest, gate-manifest-model, depgraph, tmpdir-leaks, tmpdir-leaks-model, coverage-model, wire-compat-model, production-exports, bundle-owner-files, fixture-cache, fixture-fallback, command-docs, agent-guidance, xctest-selection, maestro-conformance, mutation-model)
command-tools-navigation-schemas.test.ts(test-size ratchet: 1110 → 1029 + 82 lines).Public-signature evidence: built
dist/src/index.d.tsbefore and after, resolved the five methodsoff
ReturnType<typeof createAgentDeviceClient>['command']with the TypeScript checker, and printedeach one's parameter arity/optionality and fully resolved parameter/result property sets. The diff
is empty.
Each changed regression test was seen red first:
homewired toapp-switcher,durationMsdropped from the inlined
tv-remoteschema, a stray top-level key on a navigation schema, andhome's options parameter made required.