Plugins: suppress duplicate id warnings for same source paths#32564
Plugins: suppress duplicate id warnings for same source paths#32564zwright8 wants to merge 1 commit intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR suppresses false-positive duplicate plugin-ID warnings when two
Confidence Score: 3/5
Last reviewed commit: 214cf0e |
| const candidates: PluginCandidate[] = [ | ||
| { | ||
| idHint: "same-source-plugin", | ||
| source, | ||
| rootDir: dir, | ||
| origin: "bundled", | ||
| }, | ||
| { | ||
| idHint: "same-source-plugin", | ||
| source, | ||
| rootDir: path.join(dir, "sub", ".."), | ||
| origin: "global", | ||
| }, | ||
| ]; | ||
|
|
||
| const realpathSpy = vi.spyOn(fs, "realpathSync").mockImplementation(() => { | ||
| throw new Error("realpath unavailable"); | ||
| }); | ||
| try { | ||
| expect(countDuplicateWarnings(loadRegistry(candidates))).toBe(0); | ||
| } finally { | ||
| realpathSpy.mockRestore(); | ||
| } |
There was a problem hiding this comment.
Test doesn't exercise source-matching code path
The test is titled "suppresses duplicate warning when source path matches but realpath is unavailable", but it never actually reaches the pathsMatch(source, source) check.
The second candidate's rootDir is path.join(dir, "sub", ".."), which path.join normalizes to the same value as dir. So pathsMatch(existing.candidate.rootDir, candidate.rootDir) returns true first, short-circuiting the OR and never evaluating the source comparison. The realpathSync mock is equally unreachable since samePlugin is already true before safeRealpathSync is called.
To genuinely test the source-matching fallback, the two candidates need rootDirs that are lexically distinct (and do not resolve to the same path via path.resolve), while sharing the same source value. For example:
const dirA = makeTempDir(); // genuinely different temp dir
const dirB = makeTempDir(); // another genuinely different temp dir
writeManifest(dirA, manifest);
writeManifest(dirB, manifest);
const source = path.join(dirA, "index.ts");
fs.writeFileSync(source, "export default {};\n", "utf-8");
const candidates: PluginCandidate[] = [
{ idHint: "same-source-plugin", source, rootDir: dirA, origin: "bundled" },
// Different rootDir but identical source — this is the case the new branch is meant to handle
{ idHint: "same-source-plugin", source, rootDir: dirB, origin: "global" },
];As written, removing the pathsMatch(existing.candidate.source, candidate.source) line from the implementation would not cause this test to fail, which means the new feature is untested.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/manifest-registry.test.ts
Line: 219-241
Comment:
**Test doesn't exercise source-matching code path**
The test is titled "suppresses duplicate warning when source path matches but realpath is unavailable", but it never actually reaches the `pathsMatch(source, source)` check.
The second candidate's `rootDir` is `path.join(dir, "sub", "..")`, which `path.join` normalizes to the same value as `dir`. So `pathsMatch(existing.candidate.rootDir, candidate.rootDir)` returns `true` first, short-circuiting the OR and never evaluating the source comparison. The `realpathSync` mock is equally unreachable since `samePlugin` is already `true` before `safeRealpathSync` is called.
To genuinely test the source-matching fallback, the two candidates need rootDirs that are lexically distinct (and do not resolve to the same path via `path.resolve`), while sharing the same `source` value. For example:
```ts
const dirA = makeTempDir(); // genuinely different temp dir
const dirB = makeTempDir(); // another genuinely different temp dir
writeManifest(dirA, manifest);
writeManifest(dirB, manifest);
const source = path.join(dirA, "index.ts");
fs.writeFileSync(source, "export default {};\n", "utf-8");
const candidates: PluginCandidate[] = [
{ idHint: "same-source-plugin", source, rootDir: dirA, origin: "bundled" },
// Different rootDir but identical source — this is the case the new branch is meant to handle
{ idHint: "same-source-plugin", source, rootDir: dirB, origin: "global" },
];
```
As written, removing the `pathsMatch(existing.candidate.source, candidate.source)` line from the implementation would not cause this test to fail, which means the new feature is untested.
How can I resolve this? If you propose a fix, please make it concise.| const samePath = | ||
| pathsMatch(existing.candidate.rootDir, candidate.rootDir) || | ||
| pathsMatch(existing.candidate.source, candidate.source); |
There was a problem hiding this comment.
Source-path equality may over-suppress valid duplicate warnings
Using pathsMatch(existing.candidate.source, candidate.source) as a standalone same-plugin signal is potentially too broad. Two genuinely distinct plugins can share the same entry-point source file while having different rootDirs (e.g., one plugin symlinks another's index.ts, or two package-manager-installed copies share a cached source). In those cases both plugins have the same manifest id AND the same source path, but they are not actually the same physical plugin — the duplicate warning should still fire.
The rootDir is the canonical identity of a plugin installation; the source file is an implementation detail that can be aliased. Consider restricting this branch to cases where both rootDir and source agree, or—at minimum—document the intentional trade-off in a comment so reviewers understand when this could produce a false negative.
const samePath =
pathsMatch(existing.candidate.rootDir, candidate.rootDir) ||
// Only treat matching sources as same-plugin when rootDirs are also
// equivalent after resolution, to avoid suppressing warnings for
// distinct plugins that happen to share an entry-point file.
(pathsMatch(existing.candidate.source, candidate.source) &&
path.resolve(existing.candidate.source).startsWith(
path.resolve(existing.candidate.rootDir),
));Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/manifest-registry.ts
Line: 212-214
Comment:
**Source-path equality may over-suppress valid duplicate warnings**
Using `pathsMatch(existing.candidate.source, candidate.source)` as a standalone same-plugin signal is potentially too broad. Two genuinely distinct plugins can share the same entry-point source file while having different `rootDir`s (e.g., one plugin symlinks another's `index.ts`, or two package-manager-installed copies share a cached source). In those cases both plugins have the same manifest `id` AND the same `source` path, but they are not actually the same physical plugin — the duplicate warning should still fire.
The `rootDir` is the canonical identity of a plugin installation; the `source` file is an implementation detail that can be aliased. Consider restricting this branch to cases where both `rootDir` and `source` agree, or—at minimum—document the intentional trade-off in a comment so reviewers understand when this could produce a false negative.
```ts
const samePath =
pathsMatch(existing.candidate.rootDir, candidate.rootDir) ||
// Only treat matching sources as same-plugin when rootDirs are also
// equivalent after resolution, to avoid suppressing warnings for
// distinct plugins that happen to share an entry-point file.
(pathsMatch(existing.candidate.source, candidate.source) &&
path.resolve(existing.candidate.source).startsWith(
path.resolve(existing.candidate.rootDir),
));
```
How can I resolve this? If you propose a fix, please make it concise.214cf0e to
7c6c532
Compare
Summary
Validation
pnpm exec vitest run src/plugins/manifest-registry.test.tsContext
This PR is one focused slice extracted from: