You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #9515 — the "nothing hand-maintained" payoff issue. With the contract registry (#9517/#9518) and the route seam (#9519) in place, every remaining hand-kept surface becomes generatable. Today's inventory of hand-maintained duplicates:
Stdio API client:apiGet/apiPost/apiDelete (packages/loopover-mcp/bin/loopover-mcp.ts:6950-7002) return payload: any; ~50 endpoints consumed via optional-chaining guesswork (payload.pendingActions ?? [], result.predictedGate, …). A Worker response rename fails silently at runtime.
Four independent CLI command lists:CLI_COMMAND_SPEC (:112-146), the 34-branch runCli if-chain (:4169-4207), printHelp (:5393-5447), and the README's 47-line command block (packages/loopover-mcp/README.md:29-76) — only fragments are pin-tested; printHelp already omits commands.
No tool-reference doc anywhere: the README dodges it ("run loopover-mcp tools"), 32 tool names are hand-typed across apps/loopover-ui/content/docs/*.mdx with zero drift check, and scripts/check-docs-drift.ts + scripts/gen-command-reference.ts have no MCP coverage at all. The miner README's tool table (packages/loopover-miner/README.md:239-286) and 18-row storage table (:112-131) are hand-kept prose (name-level parity test only).
Miner hand-copies:lib/github-token-resolution.ts re-implements the stdio MCP's config/profile/apiUrl/session resolution by hand (self-declared, :6-11); lib/tenant-credential-resolution.ts:2-3 duplicates src/orb/broker-client.ts.
The repo already owns the two mechanisms needed — the env-reference generators (gen-selfhost-env-reference.ts, packages/loopover-miner/scripts/generate-env-reference.mjs: one row set → markdown doc + typed UI module, with --check) and gen-command-reference.ts ("a hand-copy is exactly how the 9-command queue-digest family went completely undocumented"). This issue points those patterns at MCP.
One CLI source of truth.CLI_COMMAND_SPEC becomes the single typed table (command, subcommands, flags with types/repeatable/boolean, summary); runCli dispatch, printHelp, shell completion, and flag parsing (including repeatable/boolean sets and enum coercion via the contract enums) all derive from it. The regex-scraping test (test/unit/mcp-cli-completion-spec.test.ts reading the built bundle) is replaced by direct import assertions.
Generated MCP reference docs. A generator (extend gen-command-reference.ts's pattern) emits from the contract registry: (a) the README tool tables for packages/loopover-mcp and packages/loopover-miner between markers, (b) a typed apps/loopover-ui/src/lib/mcp-tool-reference.ts module for the docs site, (c) the CLI command block in the stdio README. Each with --check wired into test:ci; check-docs-drift.ts gains an MCP surface asserting every tool name mentioned in apps/loopover-ui/content/docs/** exists in the registry.
Miner dedup:github-token-resolution.ts imports the config/profile/session resolution from one shared home (@loopover/contract runtime helpers or an engine module both bins already depend on — record the choice in the PR); tenant-credential-resolution.ts imports the broker-client logic instead of duplicating it. The hand-sync header comments are deleted because the hand-sync is gone.
UI derived types (ui: derive API response types from the backend's real zod/OpenAPI schemas, stop hand-duplicating them #9282 execution): land the recorded option 1 — pilot PublicStats/PublicRulePrecision via z.infer from the shared schemas, plus the drift check preventing hand-typed API interfaces from reappearing under apps/loopover-ui/src/components/site/*; migrate remaining hand-typed API interfaces opportunistically per that issue's own scoping.
Telemetry allowlist single-sourced from one exported constant consumed by both telemetry modules and the generated README section.
Stale sample output in the stdio README (3.0.0 at :51/:61) becomes generated or version-agnostic. Full coverage per house bar; fix-what-you-find applies.
Non-goals
New tools/commands; observability behavior changes (that's the observability sub-issue — this one only single-sources the property list).
Publishing a public standalone SDK package (can be a later follow-up once the typed client exists).
Deliverables
Typed validated API client; payload: any extinct with a CI gate
CLI surfaces derived from one spec table; scraping test replaced
Every tool table, command list, help block, client type, and doc reference is generated from the contract registry or route schemas with a drift gate; a renamed response field or tool is a CI failure everywhere it matters, not a silent runtime surprise.
References
Part of #9515. Blocked by #9517 (needs the registry) and #9519 (route schemas for the client); #9282 is executed by this issue and should be cross-linked on completion.
Context
Part of #9515 — the "nothing hand-maintained" payoff issue. With the contract registry (#9517/#9518) and the route seam (#9519) in place, every remaining hand-kept surface becomes generatable. Today's inventory of hand-maintained duplicates:
apiGet/apiPost/apiDelete(packages/loopover-mcp/bin/loopover-mcp.ts:6950-7002) returnpayload: any; ~50 endpoints consumed via optional-chaining guesswork (payload.pendingActions ?? [],result.predictedGate, …). A Worker response rename fails silently at runtime.CLI_COMMAND_SPEC(:112-146), the 34-branchrunCliif-chain (:4169-4207),printHelp(:5393-5447), and the README's 47-line command block (packages/loopover-mcp/README.md:29-76) — only fragments are pin-tested;printHelpalready omits commands.branchEligibilityFromOptions(:7337-7348),validationFromOptions/parseValidationEntry(:6351-6368),parseOptions' hand-listed repeatable/boolean sets (:5483+).loopover-mcp tools"), 32 tool names are hand-typed acrossapps/loopover-ui/content/docs/*.mdxwith zero drift check, andscripts/check-docs-drift.ts+scripts/gen-command-reference.tshave no MCP coverage at all. The miner README's tool table (packages/loopover-miner/README.md:239-286) and 18-row storage table (:112-131) are hand-kept prose (name-level parity test only).lib/github-token-resolution.tsre-implements the stdio MCP's config/profile/apiUrl/session resolution by hand (self-declared,:6-11);lib/tenant-credential-resolution.ts:2-3duplicatessrc/orb/broker-client.ts.z.inferon the UI side) — its pilot (PublicStats/PublicRulePrecision) plus the drift check belong to this group.packages/loopover-mcp/lib/telemetry.ts:61-66,src/mcp/telemetry.ts, README prose:296-301).The repo already owns the two mechanisms needed — the env-reference generators (
gen-selfhost-env-reference.ts,packages/loopover-miner/scripts/generate-env-reference.mjs: one row set → markdown doc + typed UI module, with--check) andgen-command-reference.ts("a hand-copy is exactly how the 9-command queue-digest family went completely undocumented"). This issue points those patterns at MCP.Requirements
apiFetchcall sites with a thin generated/derived client whose per-endpoint response types arez.inferof the contract route schemas (api: one route-registration seam — runtime zod validation + spec emission, with a route↔spec ratchet to zero unspecced routes #9519), and whichsafeParses responses at the boundary (schema-failure → the tool's error envelope naming the endpoint + first issue path; behind the same validation posture recorded in api: one route-registration seam — runtime zod validation + spec emission, with a route↔spec ratchet to zero unspecced routes #9519). Zeropayload: anyremains — enforce with a lint/grep gate in CI.CLI_COMMAND_SPECbecomes the single typed table (command, subcommands, flags with types/repeatable/boolean, summary);runClidispatch,printHelp, shell completion, and flag parsing (including repeatable/boolean sets and enum coercion via the contract enums) all derive from it. The regex-scraping test (test/unit/mcp-cli-completion-spec.test.tsreading the built bundle) is replaced by direct import assertions.gen-command-reference.ts's pattern) emits from the contract registry: (a) the README tool tables forpackages/loopover-mcpandpackages/loopover-minerbetween markers, (b) a typedapps/loopover-ui/src/lib/mcp-tool-reference.tsmodule for the docs site, (c) the CLI command block in the stdio README. Each with--checkwired intotest:ci;check-docs-drift.tsgains an MCP surface asserting every tool name mentioned inapps/loopover-ui/content/docs/**exists in the registry.github-token-resolution.tsimports the config/profile/session resolution from one shared home (@loopover/contractruntime helpers or an engine module both bins already depend on — record the choice in the PR);tenant-credential-resolution.tsimports the broker-client logic instead of duplicating it. The hand-sync header comments are deleted because the hand-sync is gone.PublicStats/PublicRulePrecisionviaz.inferfrom the shared schemas, plus the drift check preventing hand-typed API interfaces from reappearing underapps/loopover-ui/src/components/site/*; migrate remaining hand-typed API interfaces opportunistically per that issue's own scoping.3.0.0at:51/:61) becomes generated or version-agnostic. Full coverage per house bar; fix-what-you-find applies.Non-goals
Deliverables
payload: anyextinct with a CI gate--check-gatedExpected outcome
Every tool table, command list, help block, client type, and doc reference is generated from the contract registry or route schemas with a drift gate; a renamed response field or tool is a CI failure everywhere it matters, not a silent runtime surprise.
References
Part of #9515. Blocked by #9517 (needs the registry) and #9519 (route schemas for the client); #9282 is executed by this issue and should be cross-linked on completion.