Skip to content

Commit 38875ea

Browse files
committed
fix: lint, formatting, and test coverage for multi-project routing
1 parent beed8e7 commit 38875ea

File tree

6 files changed

+75
-38
lines changed

6 files changed

+75
-38
lines changed

CHANGELOG.md

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
- **mcp:** keep explicit `project` as the fallback when the client does not provide enough project context
99
- **mcp:** accept repo paths, subproject paths, and file paths as `project` selectors when routing is ambiguous
1010

11+
### Bug Fixes
12+
13+
- **search:** auto-heal on corrupted index now triggers a background rebuild instead of blocking the search response
14+
1115
### Documentation
1216

1317
- simplify the setup story around three cases: default rootless setup, single-project fallback, and explicit `project` retries
@@ -16,51 +20,46 @@
1620

1721
## [1.8.2](https://github.com/PatrickSys/codebase-context/compare/v1.8.1...v1.8.2) (2026-03-05)
1822

19-
2023
### Bug Fixes
2124

22-
* restore npx installs for published package ([107bc14](https://github.com/PatrickSys/codebase-context/commit/107bc14ff3a3b918d39df28703c739b3598b0cd8))
25+
- restore npx installs for published package ([107bc14](https://github.com/PatrickSys/codebase-context/commit/107bc14ff3a3b918d39df28703c739b3598b0cd8))
2326

2427
## [1.8.1](https://github.com/PatrickSys/codebase-context/compare/v1.8.0...v1.8.1) (2026-03-05)
2528

26-
2729
### Bug Fixes
2830

29-
* **get-team-patterns:** filter out legacy testing framework categories from patterns ([ed5c858](https://github.com/PatrickSys/codebase-context/commit/ed5c858063493efe328fb2ce03f95404efd34ad4))
30-
* **git:** run tests only on pre-push ([785d28b](https://github.com/PatrickSys/codebase-context/commit/785d28b3adfb4e5bebe946c2af17f958ac0c7022))
31-
* **git:** tighten pre-push formatting enforcement ([a6d95fc](https://github.com/PatrickSys/codebase-context/commit/a6d95fc297cd5dcdaba2244b9413cd5353f6f273))
31+
- **get-team-patterns:** filter out legacy testing framework categories from patterns ([ed5c858](https://github.com/PatrickSys/codebase-context/commit/ed5c858063493efe328fb2ce03f95404efd34ad4))
32+
- **git:** run tests only on pre-push ([785d28b](https://github.com/PatrickSys/codebase-context/commit/785d28b3adfb4e5bebe946c2af17f958ac0c7022))
33+
- **git:** tighten pre-push formatting enforcement ([a6d95fc](https://github.com/PatrickSys/codebase-context/commit/a6d95fc297cd5dcdaba2244b9413cd5353f6f273))
3234

3335
## [1.8.0](https://github.com/PatrickSys/codebase-context/compare/v1.7.0...v1.8.0) (2026-03-05)
3436

35-
3637
### Features
3738

38-
* CLI formatters + response types + debug gating ([#48](https://github.com/PatrickSys/codebase-context/issues/48)) ([7a6cd7b](https://github.com/PatrickSys/codebase-context/commit/7a6cd7b61e27adb62861d6a264c2ac1feba4d96d))
39-
* **cli:** status formatter + CLI gallery docs ([#56](https://github.com/PatrickSys/codebase-context/issues/56)) ([b7bc5cc](https://github.com/PatrickSys/codebase-context/commit/b7bc5cc078635a5f0a4f33e47d431d21cdb83ccc))
40-
* **impact:** persist import edge details + 2-hop impact candidates ([f296e30](https://github.com/PatrickSys/codebase-context/commit/f296e30834777770c70f9c20998576e123ea7592))
41-
* **impact:** persist import edge details and 2-hop candidates ([5bd84a1](https://github.com/PatrickSys/codebase-context/commit/5bd84a1c6174c2ae6a413579c471e68ccc30f377))
42-
* **indexing:** OpenAI embeddings + broader language coverage ([#57](https://github.com/PatrickSys/codebase-context/issues/57)) ([3c1c53b](https://github.com/PatrickSys/codebase-context/commit/3c1c53b15381640e96b2e62794436ca21a545ce4))
43-
* **refs:** tree-sitter identifier-aware symbol references ([2aa0831](https://github.com/PatrickSys/codebase-context/commit/2aa08315103fa1b87b20d4f212ab271caeee670c))
44-
* **refs:** Tree-sitter identifier-aware symbol references ([c23ffec](https://github.com/PatrickSys/codebase-context/commit/c23ffecf4174a6d683d4b985a754ca2ad840cfe1))
45-
* **watcher:** chokidar auto-refresh with debounced incremental reindex ([59e3686](https://github.com/PatrickSys/codebase-context/commit/59e36867cd4048c858b08d2c551ca94adb6738ac))
46-
* **watcher:** chokidar auto-refresh with debounced incremental reindex ([f300961](https://github.com/PatrickSys/codebase-context/commit/f300961b73b1ee867bfc43f0b2925d3f7c055447))
47-
39+
- CLI formatters + response types + debug gating ([#48](https://github.com/PatrickSys/codebase-context/issues/48)) ([7a6cd7b](https://github.com/PatrickSys/codebase-context/commit/7a6cd7b61e27adb62861d6a264c2ac1feba4d96d))
40+
- **cli:** status formatter + CLI gallery docs ([#56](https://github.com/PatrickSys/codebase-context/issues/56)) ([b7bc5cc](https://github.com/PatrickSys/codebase-context/commit/b7bc5cc078635a5f0a4f33e47d431d21cdb83ccc))
41+
- **impact:** persist import edge details + 2-hop impact candidates ([f296e30](https://github.com/PatrickSys/codebase-context/commit/f296e30834777770c70f9c20998576e123ea7592))
42+
- **impact:** persist import edge details and 2-hop candidates ([5bd84a1](https://github.com/PatrickSys/codebase-context/commit/5bd84a1c6174c2ae6a413579c471e68ccc30f377))
43+
- **indexing:** OpenAI embeddings + broader language coverage ([#57](https://github.com/PatrickSys/codebase-context/issues/57)) ([3c1c53b](https://github.com/PatrickSys/codebase-context/commit/3c1c53b15381640e96b2e62794436ca21a545ce4))
44+
- **refs:** tree-sitter identifier-aware symbol references ([2aa0831](https://github.com/PatrickSys/codebase-context/commit/2aa08315103fa1b87b20d4f212ab271caeee670c))
45+
- **refs:** Tree-sitter identifier-aware symbol references ([c23ffec](https://github.com/PatrickSys/codebase-context/commit/c23ffecf4174a6d683d4b985a754ca2ad840cfe1))
46+
- **watcher:** chokidar auto-refresh with debounced incremental reindex ([59e3686](https://github.com/PatrickSys/codebase-context/commit/59e36867cd4048c858b08d2c551ca94adb6738ac))
47+
- **watcher:** chokidar auto-refresh with debounced incremental reindex ([f300961](https://github.com/PatrickSys/codebase-context/commit/f300961b73b1ee867bfc43f0b2925d3f7c055447))
4848

4949
### Bug Fixes
5050

51-
* **cli:** formatter audit — render missing metadata fields, README callers qualifier ([d273729](https://github.com/PatrickSys/codebase-context/commit/d273729d16ffff3432b663b76db4964f5dce9822))
52-
* **cli:** remove unused MetadataDependency import ([3f08f0e](https://github.com/PatrickSys/codebase-context/commit/3f08f0ed2ed27c10c2fae3ecf31c81771b22cb88))
53-
* close v1.8 post-merge integration gaps ([#44](https://github.com/PatrickSys/codebase-context/issues/44)) ([d28460c](https://github.com/PatrickSys/codebase-context/commit/d28460c38bf91e8cb40a76501a03378c2edc11b5))
54-
* **refs:** prevent out-of-root file reads from index ([1735e3c](https://github.com/PatrickSys/codebase-context/commit/1735e3cb51f808c3bd1c9afed4f1139bad851e8f))
55-
* **watcher-tests:** await ready + harden Windows cleanup ([#55](https://github.com/PatrickSys/codebase-context/issues/55)) ([9929bb0](https://github.com/PatrickSys/codebase-context/commit/9929bb0cea7d9ad5a41f2719a8b1a48be1dc9909))
56-
* **watcher:** allow debounce 0 and harden test ([070433c](https://github.com/PatrickSys/codebase-context/commit/070433cf79dace7420c26284ceeca7fea41dc8a1))
57-
* **watcher:** queue refresh during indexing ([2d78110](https://github.com/PatrickSys/codebase-context/commit/2d781105f9d56e3b5644abe90ae88978e4d7b0d0))
58-
51+
- **cli:** formatter audit — render missing metadata fields, README callers qualifier ([d273729](https://github.com/PatrickSys/codebase-context/commit/d273729d16ffff3432b663b76db4964f5dce9822))
52+
- **cli:** remove unused MetadataDependency import ([3f08f0e](https://github.com/PatrickSys/codebase-context/commit/3f08f0ed2ed27c10c2fae3ecf31c81771b22cb88))
53+
- close v1.8 post-merge integration gaps ([#44](https://github.com/PatrickSys/codebase-context/issues/44)) ([d28460c](https://github.com/PatrickSys/codebase-context/commit/d28460c38bf91e8cb40a76501a03378c2edc11b5))
54+
- **refs:** prevent out-of-root file reads from index ([1735e3c](https://github.com/PatrickSys/codebase-context/commit/1735e3cb51f808c3bd1c9afed4f1139bad851e8f))
55+
- **watcher-tests:** await ready + harden Windows cleanup ([#55](https://github.com/PatrickSys/codebase-context/issues/55)) ([9929bb0](https://github.com/PatrickSys/codebase-context/commit/9929bb0cea7d9ad5a41f2719a8b1a48be1dc9909))
56+
- **watcher:** allow debounce 0 and harden test ([070433c](https://github.com/PatrickSys/codebase-context/commit/070433cf79dace7420c26284ceeca7fea41dc8a1))
57+
- **watcher:** queue refresh during indexing ([2d78110](https://github.com/PatrickSys/codebase-context/commit/2d781105f9d56e3b5644abe90ae88978e4d7b0d0))
5958

6059
### Performance Improvements
6160

62-
* **impact:** avoid per-candidate array alloc ([faf6e73](https://github.com/PatrickSys/codebase-context/commit/faf6e73101d1c76f17e755df35d8e34a1783a6fa))
63-
* **impact:** avoid per-candidate array allocation ([04e68eb](https://github.com/PatrickSys/codebase-context/commit/04e68eb3c7d5a2a5aaa45a82ef6823e6f13ce6a9))
61+
- **impact:** avoid per-candidate array alloc ([faf6e73](https://github.com/PatrickSys/codebase-context/commit/faf6e73101d1c76f17e755df35d8e34a1783a6fa))
62+
- **impact:** avoid per-candidate array allocation ([04e68eb](https://github.com/PatrickSys/codebase-context/commit/04e68eb3c7d5a2a5aaa45a82ef6823e6f13ce6a9))
6463

6564
## [1.7.0](https://github.com/PatrickSys/codebase-context/compare/v1.6.1...v1.7.0) (2026-02-21)
6665

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,22 @@ Or pass a file path and let the server resolve the nearest trusted project bound
244244
}
245245
```
246246

247-
If you see `selection_required`, the server could not tell which project you meant. Retry the call with `project`.
247+
If you see `selection_required`, the server could not tell which project you meant. The response looks like this:
248+
249+
```json
250+
{
251+
"status": "selection_required",
252+
"errorCode": "selection_required",
253+
"message": "Multiple projects are available and no active project could be inferred. Retry with project.",
254+
"nextAction": "retry_with_project",
255+
"availableProjects": [
256+
{ "label": "app-a", "project": "/repos/app-a", "indexStatus": "idle", "source": "root" },
257+
{ "label": "app-b", "project": "/repos/app-b", "indexStatus": "ready", "source": "root" }
258+
]
259+
}
260+
```
261+
262+
Retry the call with `project` set to one of the listed paths.
248263

249264
`codebase://context` follows the active project in the session. In unresolved multi-project sessions it returns a workspace overview. Project-scoped resources are also available via the URIs listed in that overview.
250265

src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ import {
4747
import {
4848
discoverProjectsWithinRoot,
4949
findNearestProjectBoundary,
50-
isPathWithin,
51-
type DiscoveredProjectCandidate
50+
isPathWithin
5251
} from './utils/project-discovery.js';
5352
import { readIndexMeta, validateIndexArtifacts } from './core/index-meta.js';
5453
import { TOOLS, dispatchTool, type ToolContext, type ToolResponse } from './tools/index.js';

tests/cli.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ describe('CLI', () => {
4242
});
4343

4444
it('search errors when --query has no value', async () => {
45-
await expect(handleCliCommand(['search', '--query', '--json'])).rejects.toThrow(/process\.exit:1/);
45+
await expect(handleCliCommand(['search', '--query', '--json'])).rejects.toThrow(
46+
/process\.exit:1/
47+
);
4648
expect(toolMocks.dispatchTool).not.toHaveBeenCalled();
4749
expect(errorSpy).toHaveBeenCalled();
4850
});
@@ -82,7 +84,9 @@ describe('CLI', () => {
8284
});
8385

8486
it('patterns errors on invalid category', async () => {
85-
await expect(handleCliCommand(['patterns', '--category', 'nope'])).rejects.toThrow(/process\.exit:1/);
87+
await expect(handleCliCommand(['patterns', '--category', 'nope'])).rejects.toThrow(
88+
/process\.exit:1/
89+
);
8690
expect(toolMocks.dispatchTool).not.toHaveBeenCalled();
8791
});
8892

@@ -195,6 +199,4 @@ describe('CLI', () => {
195199
await fs.rm(tempDir, { recursive: true, force: true });
196200
}
197201
});
198-
199202
});
200-

tests/multi-project-routing.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,27 @@ describe('multi-project routing', () => {
624624
expect(response.contents[0]?.text).toContain('# Codebase Intelligence');
625625
});
626626

627+
it('returns unknown_project error when project path does not exist', async () => {
628+
const { server } = await import('../src/index.js');
629+
const handler = (server as unknown as TestServer)._requestHandlers.get('tools/call');
630+
if (!handler) throw new Error('tools/call handler not registered');
631+
632+
const bogusPath = path.join(os.tmpdir(), `cc-nonexistent-${Date.now()}`);
633+
const response = await callTool(handler, 19, 'search_codebase', {
634+
query: 'feature',
635+
project: bogusPath
636+
});
637+
const payload = parsePayload(response) as {
638+
status: string;
639+
errorCode: string;
640+
message: string;
641+
};
642+
643+
expect(response.isError).toBe(true);
644+
expect(payload.errorCode).toBe('unknown_project');
645+
expect(payload.message).toContain('does not exist');
646+
});
647+
627648
it('resolves a file path selector to the nearest discovered project boundary', async () => {
628649
const filePath = path.join(nestedProjectRoot, 'src', 'auth', 'guard.ts');
629650
await fs.mkdir(path.dirname(filePath), { recursive: true });

tests/project-discovery.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import {
77
findNearestProjectBoundary,
88
isPathWithin
99
} from '../src/utils/project-discovery.js';
10-
import {
11-
CODEBASE_CONTEXT_DIRNAME
12-
} from '../src/constants/codebase-context.js';
10+
import { CODEBASE_CONTEXT_DIRNAME } from '../src/constants/codebase-context.js';
1311

1412
describe('project-discovery', () => {
1513
let tempRoot: string;
@@ -66,7 +64,10 @@ describe('project-discovery', () => {
6664
const realProject = path.join(tempRoot, 'apps', 'web');
6765

6866
await fs.mkdir(ignoredProject, { recursive: true });
69-
await fs.writeFile(path.join(ignoredProject, 'package.json'), JSON.stringify({ name: 'ignored' }));
67+
await fs.writeFile(
68+
path.join(ignoredProject, 'package.json'),
69+
JSON.stringify({ name: 'ignored' })
70+
);
7071

7172
await fs.mkdir(realProject, { recursive: true });
7273
await fs.writeFile(path.join(realProject, 'package.json'), JSON.stringify({ name: 'web' }));

0 commit comments

Comments
 (0)