feat: compile route-graph IR and inspect focus (#93) - #119
Conversation
Compile the conventional route tree (src/mcp/<server>/{tools,resources,
prompts,apps}, src/events, src/providers, src/cli, src/scripts) into an
immutable, digest-stable route-graph IR with hard collision errors
(AB4800-AB4804) and explicit routes.servers/<id> + routes.cli mode
overrides. discoverProject attaches the graph only when non-empty,
validateSource surfaces its diagnostics, and inspect gains a routes
focus (--routes) that dumps the graph bundler-style.
Towards #93.
Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
🦋 Changeset detectedLatest commit: 6654dcc The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4e22a52f0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ared route graph to inspect Reconciliation of the two Lane B PR-1 implementations (#116 closed as duplicate, #119 the keeper): - Config always wins: modules referenced by explicit scripts/hooks/bin/ lib/mcp configuration are claimed by that declaration and never become routes. This keeps examples/hooks-and-scripts and examples/mcp-app — both with src/scripts/* files, all config-claimed — route-free and building unchanged (proved by pnpm examples:check). - Codex P2 fix: the inspect routes focus no longer reloads the config and recompiles the graph (a non-idempotent config factory could diverge from the validated model, and second-pass diagnostics were mishandled). PreparedProject now carries the graph compiled during discovery, and the focus serves it directly; route-free projects serve the shared frozen emptyCompiledRouteGraph. - Test coverage ported from #116: the claim rule (examples-shaped fixture), the declared entry/command/url server-conflict branch of AB4800, and the route-free inspect focus. Part of #93
Carry discovery's graph on the invalid-source prepare path and pin inspect --routes to a single config-factory evaluation.
|
Deslop/simplify audit (orchestrated): reviewed this PR's full diff against the deslop rubric. No commits pushed — the branch head is untouched for the lander's exact-head gate; findings only. One item worth folding in before merge, three post-merge cleanups. Everything else checked clean: the conventional-entry probe copy is properly documented with its cycle rationale, Worth fixing before merge
Post-merge cleanup
Not flagged (checked, judged deliberate): the |
…uplicate api re-export Deslop audit items 1 and 4: graph.ts drops its local deepFreeze copy for the shared core/freeze.ts implementation (cycle-free import; behavior equivalent for the fresh plain-object IR), and api.ts folds the two consecutive routes/graph re-export statements into one. Part of #93
|
Deslop audit triage (Lane B lander):
|
commit: |
…ore types for consumers Route-graph compilation reads config sections (scripts, hooks, bin, lib, mcp) whose getters are untrusted until validation runs; a throwing getter must degrade to an absent graph so validation still reports AB7001 instead of the load-failure path reporting AB7000. The public-api consumer fixture also gains an ignore symlink because routes/graph.d.ts now pulls config/ignore.d.ts into the root declaration graph (ignore is a runtime dependency, matching the ajv precedent).
Keep discovery tolerant of hostile config-claim getters while forcing hostile routes access through source validation, so inspect reports AB7001 instead of silently returning ready.
Towards #93. Refs #107 and #105.
Wave 1 Lane B PR-1: the conventional route tree compiles into one immutable route-graph IR. This PR is consumer-invisible — discovery attaches nothing for route-free projects, packaging is unchanged, and the route
configextractor follows in PR-2 (soFixes #93deliberately does not apply yet).Route compiler (
packages/agent-bundle/src/routes/)graph.tscompiles the conventional roots with the same glob discipline asconfig/discover.ts(absolute, cwd, dot,followSymbolicLinks: false,onlyFiles):src/mcp/<server>/{tools,resources,prompts,apps}/*.{ts,tsx}(direct children per kind), idstool:<server>/<name>etc.,serverId: mcp:<server>.src/events/<family>/*.{ts,tsx}→event:<family>/<name>.src/providers/*.{ts,tsx}as a separateCompiledProvidercollection, not a route kind.src/cli/**andsrc/scripts/**with nested identity (cli:library/audit)._/.segments, and*.d.tsfiles are skipped.config/normalize.tswould close the cyclediscover.ts → routes/graph.ts → normalize.ts → discover.ts.config: {}(emptyRouteConfig), anddigestcovers project-relative identity only, so equal trees hash equally on every machine.AB4800routed server vssrc/mcp/<id>.tsor a declaredentry/command/url;AB4801src/cli.tsvssrc/cli/;AB4802duplicate route id;AB4803unsafe identity segment (^[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?$per segment);AB4804invalidroutesmode override.types.tsunchanged):routes.servers.<id> = 'generated'|'custom'|'command'|'remote',routes.cli = 'generated'|'conventional'. Explicitcustom/command/remoteomits that server's routes; explicitgeneratedkeeps them and is never an error against leftover files. A conflict without a mode keeps the discovered routes inconflictmode and errors — discovery is not a packaging choice.types.tsdefinesCompiledAgentRoute,RouteProvenance,CapabilityState/CapabilityEvidence(exported, not populated — Compile capability-aware host component bundles #100),CompiledProvider,CompiledServerSurface(generated|custom|command|remote|conflict),CompiledCliSurface,CompiledRouteGraph, andemptyRouteConfig.inspect.tsis the dump facade (RouteGraphInspection = CompiledRouteGraph),index.tsre-exports.Wiring (additive)
config/discover.ts:discoverProjectcompiles the graph and spreadsrouteGraphonly whenisEmptyRouteGraphis false.config/validate.ts:validateSourceappendsdiscovered.routeGraph?.diagnostics ?? [], so route collisions hard-failinspect/build.api.ts:focus?: 'bundler'|'hooks'|'routes'|'skills'; onfocus === 'routes'it runsloadConfig+compileRouteGraph+inspectRouteGraphintoselected.routes; routes surface re-exported from the advanced API.cli.ts:inspect --routeswith the existing at-most-one-focus rule; the human writer dumps the graph JSON like the bundler focus.Lane D riding this PR
docs/superpowers/specs/2026-08-26-…-parity-design.md: the filesystem-router non-goal is marked superseded (2026-08-31) by Compile filesystem routes into the Agent Bundle meta-framework #93; public authoring waits for the wave-3 renderer join (meta-framework: execution plan and sequencing #107); the rest of the non-goals are unchanged.docs/superpowers/specs/2026-08-25-capability-aware-workbench-design.md: status note that the nine-page Workbench is in tree, remaining work is tracked in Add an interactive Agent Workbench with local host discovery and lifecycle replay #105, and the spec is not the live execution plan (Status: proposedleft as-is).docs/diagnostics.md: newAB4800–AB4804table.Tests
packages/agent-bundle/tests/route-graph.test.ts(unit pool,mkdtempfixtures, not added torstest.integration-tests.ts): 12 cases covering conventional discovery (frozen IR, machine-independent digest,config: {}), skip rules, all five diagnostic codes,generated/customoverride behavior, the missingrouteGraphkey on skill-only projects, theroutesinspect focus, and the in-process CLI--routes --jsondump plus the ambiguous-focus rejection.Verified locally: unit pool 1793 passed / 0 failed (includes the 12 new cases),
rslintclean,tsctypecheck clean.Do not merge.