# v1.13.18 tasks ## B1 — Backups - [x] `apps/server/src/services/codecontext_client.ts.bak-v1.13.18-20260522` - [x] `apps/server/src/services/tools/codecontext/get_file_analysis.ts.bak-v1.13.18-20260522` - [x] `apps/server/src/services/tools/codecontext/get_symbol_info.ts.bak-v1.13.18-20260522` - [x] `apps/server/src/services/tools/codecontext/get_dependencies.ts.bak-v1.13.18-20260522` - [x] `apps/server/src/services/tools/codecontext/get_semantic_neighborhoods.ts.bak-v1.13.18-20260522` ## B2 — Resolver implementation in `codecontext_client.ts` - [x] Import `isAbsolute`, `resolve`, `sep` from `node:path` (alongside existing `join`) - [x] Add `resolveProjectPath(projectRoot, rawPath)` helper — trim check, isAbsolute branch, realpath with ENOENT fallthrough, escape check - [x] Wire into `callCodecontext` at args-spread site — guard on `file_path.trim() !== ''` - [x] Error-shape parity verified: `file_path escapes project root ` mirrors `target_dir escapes project root ` ## B3 — Zod `.trim()` on wrapper schemas - [x] `get_file_analysis.ts` — `z.string().trim().min(1)` - [x] `get_symbol_info.ts` — `z.string().trim().optional()` - [x] `get_dependencies.ts` — `z.string().trim().optional()` - [x] `get_semantic_neighborhoods.ts` — `z.string().trim().optional()` ## B4 — Tests - [x] Added `describe('callCodecontext — file_path resolution', ...)` to `codecontext_client.test.ts` - [x] Case 1: relative path resolves to absolute inside project root - [x] Case 2: absolute path inside project root passes through - [x] Case 3: relative escape (`../../etc/passwd`) rejected with `escapes project root` - [x] Case 4: absolute path outside project root rejected - [x] Case 5: nonexistent file (ENOENT) forwarded as un-realpath'd absolute - [x] Case 6: empty string skipped by guard (treated as not provided) - [x] Case 7: wrapper without `file_path` — resolver not invoked, no `file_path` in wire body - [x] All 17 tests in `codecontext_client.test.ts` pass ## B5 — Typecheck + smoke - [x] `npx tsc --noEmit -p apps/server` — 0 errors - [x] Before-fix smoke (relative path): `{"error":"file not found: apps/server/src/services/inference/turn.ts","result":null}` - [x] Before-fix smoke (absolute path): returns `Lines: 330 / Symbols: 48` as expected ## B6 — Test asserting old buggy behavior updated - [x] `apps/server/src/services/__tests__/codecontext_tools.test.ts` — assertion at line 73 updated from `file_path: 'apps/server/src/index.ts'` to `file_path: join(projectDir, 'apps/server/src/index.ts')` to match the new resolved-absolute contract. ## B7 — OpenSpec docs - [x] `openspec/changes/v1.13.18-codecontext-file-path/proposal.md` - [x] `openspec/changes/v1.13.18-codecontext-file-path/tasks.md` - [x] `openspec/changes/v1.13.18-codecontext-file-path/design.md` ## B8 — Review-pass defence-in-depth (P2 fixes from adversarial review) - [x] `codecontext_client.ts:71` — absolute branch now goes through `resolve()` to normalise dot-segments. Closes the ENOENT-fallthrough escape gap where `/../etc/x` would prefix-match `/` literally. - [x] `codecontext_client.test.ts` — added Case 8 (absolute path with `..` resolving outside root, ENOENT branch) and Case 9 (in-project symlink whose target sits outside root). 19 tests pass. - [x] Updated `resolveProjectPath` docstring to reflect the new normalisation step.