feat(mcp): route project-qualified paths in the POSIX tools - #1421
feat(mcp): route project-qualified paths in the POSIX tools#1421phernandez wants to merge 1 commit into
Conversation
Projects become mount points (#1415): every posix verb accepts <project>/path — exactly the prefixed identifiers tool outputs and stored permalinks produce — resolved by one shared helper the CLI inherits. Explicit project params win only on agreement; disagreement refuses naming both. ls with no project lists active projects as the root directory. In multi-project configs an unqualified path that matches no project refuses with the copyable project list; single project configs keep resolving unqualified paths unchanged. Motivated by measured agent behavior in the #1398 A/B runs: agents faithfully quote prefixed output identifiers, omit the project arg (shell affordances prime cwd thinking), and the stateless default was silently wrong — both surfaces wrote a perfect relation into the wrong project. Known scope gap for cloud/factory-mode surfaces noted in review; follow-up tracked on #1415. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp Signed-off-by: phernandez <paul@basicmachines.co>
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: bfd26bafa9
ℹ️ 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".
| # Single-project ergonomics unchanged; an empty config (cloud-only client) | ||
| # keeps API-side default resolution. | ||
| return ProjectPathRoute(project=None, path=path, stripped=False) |
There was a problem hiding this comment.
Discover cloud projects before default routing
In factory/global-cloud sessions with no local config.projects, this fallback handles both single-segment mount paths and pathless grep/tail calls. Consequently, ls("/") can advertise /research, but ls("/research") cannot recognize that remote project and instead routes through get_project_client(None) to the cloud default; unqualified searches likewise silently query the default even when several cloud projects exist. Discover/count the remotely accessible projects before this fallback so advertised mount roots round-trip and multi-project calls cannot read the wrong project.
AGENTS.md reference: AGENTS.md:L303-L312
Useful? React with 👍 / 👎.
Why
Implements #1415: projects become mount points in the POSIX tool namespace. Motivated by measured agent behavior in the #1398 A/B runs — tool outputs return project-prefixed identifiers, inputs demanded a separate
projectarg, agents faithfully quote outputs and omit the arg (shell affordances prime cwd-thinking), and the stateless default was silently wrong. In run 5, both surfaces' agents wrote a perfect relation into the wrong project.Stacked on #1416 (
1398-eval-test-fixes).What changed
mcp/project_context.py): first path/identifier segment naming an active project routes there with the remainder — inputs now accept exactly what outputs produce. The CLI verbs inherit it through the shared layer.projectparam + path prefix disagreeing refuses naming both; a workspace-qualified explicit param keeps its workspace (review catch — the agree-branch initially discarded it).ls /lists active projects as the root directory — in-band discovery, the mount-point view.no project 'x' — active projects: …); single-project configs resolve unqualified paths unchanged.Validated by the eval it came from (run
at-b0442a6f5cd7, Sonnet 5)The entire wrong-scope failure class vanished.
curate-connect— which agents had "solved" into the wrong project on every prior run — passed on both surfaces. Posix's metadata-search went 0/3 → 3/3 (agents brute-force it at ~2× rich's token cost, which is the remaining efficiency gap: grep/ls/find have no structured frontmatter predicates). Where the surfaces overlap cleanly, posix stays 17–24% cheaper (manual 23.8k vs 31.3k; curate 74.7k vs 89.9k). Aggregate tokens/completed: rich 72.9k, posix 88.0k (+21%, driven by the metadata brute-forcing and navigational chattiness — 13.8 vs 7.8 mean calls).Remaining failures are genuine task behavior (decoy discrimination on both surfaces, one formatting miss, one incomplete status update, one token-budget stop) — none are scope errors.
Verification
ty— clean;tests/mcp1030 passed;tests/cli933 passed (21 new resolver tests + 16 routing tests; additive-only test diffs)🤖 Generated with Claude Code
https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp