mirror of https://github.com/garrytan/gstack.git
test: harden regression test — Bun.Glob, SKILL.md scan, codex review check
Fixes three gaps found by adversarial review: 1. fs.readdirSync recursive hits ELOOP on .claude/skills/gstack symlink. Switched to Bun.Glob with followSymlinks:false. 2. Generated SKILL.md files now scanned (not just .tmpl sources). 3. New test: codex review commands must not use inline git rev-parse (codex review doesn't support -C, so cd "$_REPO_ROOT" is the fix). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
844169a446
commit
af0a26ee1f
|
|
@ -1684,14 +1684,8 @@ describe('codex commands must not use inline $(git rev-parse --show-toplevel) fo
|
||||||
|
|
||||||
test('no generated SKILL.md has codex exec with inline $(git rev-parse --show-toplevel) in -C flag', () => {
|
test('no generated SKILL.md has codex exec with inline $(git rev-parse --show-toplevel) in -C flag', () => {
|
||||||
const violations: string[] = [];
|
const violations: string[] = [];
|
||||||
const skillMdFiles = fs.readdirSync(ROOT, { recursive: true })
|
const skillMdGlob = new Bun.Glob('**/SKILL.md');
|
||||||
.filter((f): f is string =>
|
const skillMdFiles = Array.from(skillMdGlob.scanSync({ cwd: ROOT, followSymlinks: false }));
|
||||||
typeof f === 'string' &&
|
|
||||||
f.endsWith('SKILL.md') &&
|
|
||||||
!f.includes('node_modules') &&
|
|
||||||
!f.includes('.claude') &&
|
|
||||||
!f.includes('.agents') &&
|
|
||||||
!f.includes('.tmpl'));
|
|
||||||
for (const rel of skillMdFiles) {
|
for (const rel of skillMdFiles) {
|
||||||
const abs = path.join(ROOT, rel);
|
const abs = path.join(ROOT, rel);
|
||||||
if (!fs.existsSync(abs)) continue;
|
if (!fs.existsSync(abs)) continue;
|
||||||
|
|
@ -1706,4 +1700,38 @@ describe('codex commands must not use inline $(git rev-parse --show-toplevel) fo
|
||||||
}
|
}
|
||||||
expect(violations).toEqual([]);
|
expect(violations).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('codex review commands must be preceded by cd "$_REPO_ROOT" (no -C support)', () => {
|
||||||
|
// codex review does not support -C, so the pattern must be:
|
||||||
|
// _REPO_ROOT=$(git rev-parse --show-toplevel) || { ... }
|
||||||
|
// cd "$_REPO_ROOT"
|
||||||
|
// codex review ...
|
||||||
|
// NOT: codex review ... with inline $(git rev-parse --show-toplevel)
|
||||||
|
const allFiles = [
|
||||||
|
...Array.from(tmplGlob.scanSync({ cwd: ROOT, followSymlinks: false })),
|
||||||
|
...Array.from(new Bun.Glob('**/SKILL.md').scanSync({ cwd: ROOT, followSymlinks: false })),
|
||||||
|
...fs.readdirSync(path.join(ROOT, 'scripts/resolvers'))
|
||||||
|
.filter(f => f.endsWith('.ts'))
|
||||||
|
.map(f => `scripts/resolvers/${f}`),
|
||||||
|
'scripts/gen-skill-docs.ts',
|
||||||
|
];
|
||||||
|
const violations: string[] = [];
|
||||||
|
for (const rel of allFiles) {
|
||||||
|
const abs = path.join(ROOT, rel);
|
||||||
|
if (!fs.existsSync(abs)) continue;
|
||||||
|
const content = fs.readFileSync(abs, 'utf-8');
|
||||||
|
const lines = content.split('\n');
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const line = lines[i];
|
||||||
|
// Skip non-executable lines (markdown table cells, prose references)
|
||||||
|
if (line.includes('|') && line.includes('`/codex review`')) continue;
|
||||||
|
if (line.includes('`codex review`')) continue;
|
||||||
|
// Check for codex review with inline $(git rev-parse)
|
||||||
|
if (line.includes('codex review') && line.includes('$(git rev-parse --show-toplevel)')) {
|
||||||
|
violations.push(`${rel}:${i + 1} — inline git rev-parse in codex review`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(violations).toEqual([]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue