v1.91.1.0 fix: harden Impeccable plugin discovery (#2978)

* fix(design-detect): find impeccable installed as a Claude Code plugin

The design-detector probe only ever checked <root>/<SKILL_ROOTS>/skills/impeccable/,
never the Claude Code plugin-cache layout
(<root>/.claude/plugins/cache/<marketplace>/<plugin>/<version>/skills/impeccable/).
A plugin-installed impeccable was therefore invisible: IMPECCABLE_SKILL stayed
absent, the launcher was never found (so the NOT_CACHED run hint never fired),
and its sibling engine was never considered.

Add a plugin-cache walk alongside the existing SKILL_ROOTS walk, sharing the
same presence/launcher/repo-local-exclusion/sibling-engine logic via an
extracted checkSkillDir() helper so both paths stay behaviorally identical.

Fixes #2838

* refactor(design-detect): consolidate newestSemverDir onto safeReaddir

Both did the identical try/catch-around-readdirSync; newestSemverDir now
reuses the new safeReaddir helper instead of duplicating it.

* fix: harden Impeccable plugin discovery and regression fixtures

* test: supply eval mode to the integrated detector callback adapter

---------

Co-authored-by: Som Samantray <som.samantray@gmail.com>
This commit is contained in:
Garry Tan
2026-09-25 14:32:12 -04:00
committed by GitHub
co-authored by Som Samantray
parent 7b534d3e90
commit 2a113ae7e6
18 changed files with 938 additions and 40 deletions
+15
View File
@@ -49,6 +49,17 @@ const FAKE_AWS_KEY = ['AKIA', '1234567890ABCDEF'].join('');
const CONFIG = path.join(ROOT, 'bin', 'gstack-config');
const POLICY = path.join(ROOT, 'bin', 'gstack-gbrain-repo-policy');
function isolateGitRemote(repo: string, url: string): void {
const git = (...args: string[]) => {
const result = spawnSync('git', args, { cwd: repo, encoding: 'utf8', timeout: 10_000 });
expect(result.status).toBe(0);
return result.stdout.trim();
};
expect(git('config', '--get', 'remote.origin.url')).toBe(url);
git('config', '--local', `url.${url}.insteadOf`, url);
expect(git('remote', 'get-url', 'origin')).toBe(url);
}
const FAKE = `#!/bin/sh
MODE=$(cat "$HOME/mode" 2>/dev/null || echo ok)
printf '%s\\n' "$*" >> "$HOME/calls.log"
@@ -213,6 +224,7 @@ describe('gate on: the mediated hand-off', () => {
const git = (args: string[]) => spawnSync('git', args, { cwd: repo, encoding: 'utf8', timeout: 10_000 });
git(['init', '-q']);
git(['remote', 'add', 'origin', 'https://github.com/example/denied-repo.git']);
isolateGitRemote(repo, 'https://github.com/example/denied-repo.git');
const prompt = JSON.stringify({ prompt: 'hello', cwd: repo });
for (const tier of ['deny', 'read-only']) {
const set = spawnSync('bash', [POLICY, 'set', 'https://github.com/example/denied-repo.git', tier], { env, encoding: 'utf8', timeout: 20_000 });
@@ -693,6 +705,7 @@ describe('deadline and policy failure paths (review coverage)', () => {
const git = (args: string[]) => spawnSync('git', args, { cwd: repo, encoding: 'utf8', timeout: 10_000 });
git(['init', '-q']);
git(['remote', 'add', 'origin', 'https://github.com/example/some-repo.git']);
isolateGitRemote(repo, 'https://github.com/example/some-repo.git');
// a directory where the store file should be: hasRepoPolicyStore() is true, every read fails
const storeDir = path.join(home, '.gstack', 'gbrain-repo-policy.json');
fs.mkdirSync(storeDir, { recursive: true });
@@ -742,6 +755,7 @@ describe('trust-policy lookup outcomes (review coverage, second pass)', () => {
try {
spawnSync('git', ['init', '-q'], { cwd: repo, timeout: 10_000 });
spawnSync('git', ['remote', 'add', 'origin', 'https://github.com/example/other.git'], { cwd: repo, timeout: 10_000 });
isolateGitRemote(repo, 'https://github.com/example/other.git');
expect(runHook(JSON.stringify({ prompt: 'hello', cwd: repo }), {}, repo).stdout).toContain('remembered');
} finally {
fs.rmSync(repo, { recursive: true, force: true });
@@ -755,6 +769,7 @@ describe('trust-policy lookup outcomes (review coverage, second pass)', () => {
for (const [dir, url] of [[denied, 'https://github.com/example/denied.git'], [allowed, 'https://github.com/example/allowed.git']] as const) {
spawnSync('git', ['init', '-q'], { cwd: dir, timeout: 10_000 });
spawnSync('git', ['remote', 'add', 'origin', url], { cwd: dir, timeout: 10_000 });
isolateGitRemote(dir, url);
}
expect(spawnSync('bash', [POLICY, 'set', 'https://github.com/example/denied.git', 'deny'], { env, encoding: 'utf8', timeout: 20_000 }).status).toBe(0);
const r = runHook(JSON.stringify({ prompt: 'hello', cwd: denied }), { GIT_DIR: path.join(allowed, '.git'), GIT_WORK_TREE: allowed }, denied);