• v1.13.18-codecontext-file-path: resolve file_path against project root in codecontext wrappers

    indifferentketchup released this 2026-05-22 21:54:16 +00:00

    Four codecontext sidecar wrappers — get_file_analysis (required
    file_path), get_symbol_info, get_dependencies, and get_semantic_neighborhoods
    (optional) — forwarded file_path to the HTTP sidecar unchanged. The
    sidecar's internal file index is keyed on absolute paths, so any
    relative path from the model returned "File not found in graph".
    Three back-to-back failures observed in one chat on 2026-05-22
    17:56 UTC, ~48 s of wasted tool budget.

    Resolver

    Add resolveProjectPath(projectRoot, rawPath) in codecontext_client.ts:
    trim check → absolute/relative branch (both go through resolve() so
    dot-segments normalise) → realpath with ENOENT fallthrough → escape
    check using the realpathed value. Error shape mirrors the existing
    target_dir escape error byte-for-byte; only the field name differs.

    Wired into callCodecontext at the args-spread site, guarded on
    file_path presence + non-empty. All four wrappers benefit from one
    call site; wrappers without file_path (overview, framework, watch,
    search) are unaffected.

    Schema trim

    .trim() added to all four file_path Zod schemas:

    get_file_analysis: z.string().trim().min(1)
    get_symbol_info: z.string().trim().optional()
    get_dependencies: z.string().trim().optional()
    get_semantic_neighborhoods: z.string().trim().optional()

    Absorbs trailing newlines / whitespace from model output before the
    resolver sees the value.

    Adversarial review fixes

    Adversarial pass surfaced two P2 findings:

    1. Absolute path with .. resolving outside the project root (e.g.
      <projectRoot>/../etc/passwd) that ENOENTs at realpath would slip
      through the literal prefix-check: the raw string starts with
      <projectRoot>/. Fix: resolve() the absolute branch's candidate
      too, so dot-segments normalise before the prefix check.

    2. No symlink-escape test coverage. Realpath's stated purpose
      (catching in-project symlinks pointing outside the project) was
      never tested. Added: create a tmpdir outside projectRoot,
      symlink projectRoot/evil-link → outside file, assert rejection.

    Tests

    codecontext_client.test.ts: 19 tests (10 baseline + 9 new file_path
    resolution cases). Cases cover: relative→absolute, absolute-inside,
    relative-escape, absolute-outside, ENOENT-fallthrough, empty-string,
    wrapper-without-file_path, absolute-with-..-ENOENT,
    symlink-leaving-root.

    codecontext_tools.test.ts: one assertion updated to expect the
    resolved-absolute file_path on the wire (previously asserted the raw
    relative path passed through, which is exactly the bug being fixed).

    Full suite: 301 passed, 7 skipped.

    Affected / unaffected

    • get_codebase_overview, get_framework_analysis, watch_changes,
      search_symbols: no file_path arg → resolver guard skips them. No
      behavior change.
    • get_semantic_neighborhoods IS in SYNTHESIS_TOOLS — previously-failing
      relative-path calls will now successfully synthesize. Desirable, not
      a regression.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    Downloads