mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-18 09:06:53 +03:00
Two Cursor Bugbot Medium findings on the merged monorepo context PR: - Excluded packages still listed: discoverTargetCandidates added every glob match but never applied negated workspace patterns, so an excluded package (e.g. "!packages/internal") showed up as a selectable target even though resolveWorkspaceProjectRoot sends it back to the repo root. Now filtered with the same isExcludedByWorkspacePattern check the resolver uses. - Empty app list blocks root: resolveTargetSelection returned TARGET_SELECTION_REQUIRED whenever projectRoot === repoRoot, even with zero discoverable child apps (e.g. `workspaces: ["."]`), leaving an unanswerable prompt. It now returns null (use the repo root as the project) when there are no candidates. Also documents two Greptile P2 clarity notes (the four contextSourceStatus labels incl. the dual meaning of 'fallback', and the deliberate isMonorepoRoot-before-hasGitBoundary ordering in findMonorepoRoot). Adds regression tests for both behaviors. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1e4e74793a
commit
42be79eab5
@@ -585,6 +585,39 @@ describe('loadContext (monorepo project context)', () => {
|
||||
assert.doesNotMatch(res.stdout, /^NO_PRODUCT_MD:/);
|
||||
});
|
||||
|
||||
it('excludes negated workspace packages from the selection candidates', () => {
|
||||
write('pnpm-workspace.yaml', 'packages:\n - "packages/*"\n - "!packages/internal"\n');
|
||||
write('PRODUCT.md', '# Root product\n');
|
||||
write('packages/web/src/App.jsx', 'export default null;\n');
|
||||
write('packages/internal/src/App.jsx', 'export default null;\n');
|
||||
|
||||
const res = spawnSync(process.execPath, [SCRIPT_PATH], {
|
||||
cwd: scratch,
|
||||
encoding: 'utf8',
|
||||
env: { ...process.env, IMPECCABLE_NO_UPDATE_CHECK: '1' },
|
||||
});
|
||||
assert.equal(res.status, 0);
|
||||
const selection = parseTargetSelection(res.stdout);
|
||||
const paths = selection.targetCandidates.map((candidate) => candidate.path);
|
||||
assert.ok(paths.includes('packages/web'), `expected packages/web in ${JSON.stringify(paths)}`);
|
||||
assert.ok(!paths.includes('packages/internal'), `packages/internal should be excluded: ${JSON.stringify(paths)}`);
|
||||
});
|
||||
|
||||
it('does not block on target selection when the monorepo has no child apps', () => {
|
||||
write('package.json', JSON.stringify({ private: true, workspaces: ['.'] }, null, 2));
|
||||
write('PRODUCT.md', '# Root product\n');
|
||||
write('DESIGN.md', '# Root design\n');
|
||||
|
||||
const res = spawnSync(process.execPath, [SCRIPT_PATH], {
|
||||
cwd: scratch,
|
||||
encoding: 'utf8',
|
||||
env: { ...process.env, IMPECCABLE_NO_UPDATE_CHECK: '1' },
|
||||
});
|
||||
assert.equal(res.status, 0);
|
||||
assert.doesNotMatch(res.stdout, /TARGET_SELECTION_REQUIRED/);
|
||||
assert.match(res.stdout, /# Root product/);
|
||||
});
|
||||
|
||||
it('lets --target . explicitly select the monorepo root', () => {
|
||||
writeMonorepo();
|
||||
const res = spawnSync(process.execPath, [SCRIPT_PATH, '--target', '.'], {
|
||||
|
||||
Reference in New Issue
Block a user