mirror of
https://github.com/addyosmani/agent-skills.git
synced 2026-08-12 18:07:26 +02:00
Merge pull request #372 from ShiroKSH/fix/eval-validation-windows
fix: harden eval and command validation
This commit is contained in:
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
@@ -339,7 +339,7 @@ agent-skills/
|
||||
│ ├── shipping-and-launch/ # Ship
|
||||
│ └── using-agent-skills/ # Meta: how to use this pack
|
||||
├── agents/ # 4 specialist personas
|
||||
├── references/ # 5 supplementary checklists
|
||||
├── references/ # 7 supplementary checklists
|
||||
├── hooks/ # Session lifecycle hooks
|
||||
├── .claude/commands/ # 8 slash commands (Claude Code)
|
||||
├── .gemini/commands/ # 8 slash commands (Gemini CLI)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Copilot supports creating agent skills using a `.github/skills`, `.claude/skills`, or `.agents/skills` directory in your repository.
|
||||
|
||||
```bash
|
||||
mkdir -p .github
|
||||
mkdir -p .github/skills/test-driven-development .github/skills/code-review-and-quality
|
||||
|
||||
# Create files for essential skills
|
||||
cat /path/to/agent-skills/skills/test-driven-development/SKILL.md > .github/skills/test-driven-development/SKILL.md
|
||||
|
||||
@@ -132,6 +132,9 @@ The `references/` directory contains supplementary checklists:
|
||||
| `performance-checklist.md` | performance-optimization |
|
||||
| `security-checklist.md` | security-and-hardening |
|
||||
| `accessibility-checklist.md` | frontend-ui-engineering |
|
||||
| `definition-of-done.md` | all skills / every change |
|
||||
| `observability-checklist.md` | observability-and-instrumentation |
|
||||
| `orchestration-patterns.md` | context-engineering |
|
||||
|
||||
Load a reference when you need detailed patterns beyond what the skill covers.
|
||||
|
||||
|
||||
+16
-3
@@ -154,7 +154,7 @@ function loadSkills() {
|
||||
const file = path.join(SKILLS_DIR, dir, 'SKILL.md');
|
||||
if (!fs.existsSync(file)) continue;
|
||||
const src = fs.readFileSync(file, 'utf8');
|
||||
const m = src.match(/^---\n([\s\S]*?)\n---/);
|
||||
const m = src.match(/^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/);
|
||||
if (!m) continue;
|
||||
const name = (m[1].match(/^name:\s*(.+)$/m) || [])[1];
|
||||
const description = (m[1].match(/^description:\s*(.+)$/m) || [])[1];
|
||||
@@ -178,6 +178,19 @@ function loadCases() {
|
||||
});
|
||||
}
|
||||
|
||||
function resolveFixturePath(root, rel) {
|
||||
if (path.isAbsolute(rel)) {
|
||||
throw new Error(`fixture path must be relative: ${rel}`);
|
||||
}
|
||||
const resolvedRoot = path.resolve(root);
|
||||
const resolvedPath = path.resolve(resolvedRoot, rel);
|
||||
const back = path.relative(resolvedRoot, resolvedPath);
|
||||
if (back === '' || back === '..' || back.startsWith(`..${path.sep}`) || path.isAbsolute(back)) {
|
||||
throw new Error(`fixture path escapes workspace: ${rel}`);
|
||||
}
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
// ---------- tier 2 ----------
|
||||
|
||||
function runDeterministic() {
|
||||
@@ -331,11 +344,11 @@ function materializeWorkspace(ev) {
|
||||
// agent has real code to operate on rather than describing what it would do.
|
||||
const workspace = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-skills-eval-'));
|
||||
for (const rel of ev.files || []) {
|
||||
const src = path.join(FIXTURES_DIR, rel);
|
||||
const src = resolveFixturePath(FIXTURES_DIR, rel);
|
||||
if (!fs.existsSync(src)) {
|
||||
throw new Error(`fixture listed in files[] not found: evals/fixtures/${rel}`);
|
||||
}
|
||||
const dest = path.join(workspace, rel);
|
||||
const dest = resolveFixturePath(workspace, rel);
|
||||
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||
fs.cpSync(src, dest, { recursive: true });
|
||||
}
|
||||
|
||||
@@ -145,6 +145,21 @@ function main() {
|
||||
const descGemini = byTool.gemini[tomlStem];
|
||||
const descAgy = byTool.antigravity[tomlStem];
|
||||
|
||||
const malformed = [
|
||||
['.claude/commands', byTool.claude, claudeStem],
|
||||
['.gemini/commands', byTool.gemini, tomlStem],
|
||||
['commands/', byTool.antigravity, tomlStem],
|
||||
].filter(([, commands, stem]) => Object.prototype.hasOwnProperty.call(commands, stem) && commands[stem] == null);
|
||||
|
||||
if (malformed.length) {
|
||||
console.log(` ✗ ${claudeStem}`);
|
||||
for (const [toolDir, , stem] of malformed) {
|
||||
console.log(` ${toolDir}/${stem} — missing or malformed description`);
|
||||
}
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (descClaude == null || descGemini == null || descAgy == null) {
|
||||
// Missing file already flagged by parity check
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user