@pratikpsl/agent-skills 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -8
- package/dist/bin/agent-skills.d.ts +3 -0
- package/dist/bin/agent-skills.d.ts.map +1 -0
- package/dist/bin/agent-skills.js +6 -0
- package/dist/bin/agent-skills.js.map +1 -0
- package/dist/cli/commands/add.d.ts +3 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +71 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/dotnet-setup.d.ts +14 -0
- package/dist/cli/commands/dotnet-setup.d.ts.map +1 -0
- package/dist/cli/commands/dotnet-setup.js +110 -0
- package/dist/cli/commands/dotnet-setup.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +36 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +3 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +37 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +29 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/copy-skills.d.ts +28 -0
- package/dist/core/copy-skills.d.ts.map +1 -0
- package/dist/core/copy-skills.js +60 -0
- package/dist/core/copy-skills.js.map +1 -0
- package/dist/core/load-pack.d.ts +15 -0
- package/dist/core/load-pack.d.ts.map +1 -0
- package/dist/core/load-pack.js +35 -0
- package/dist/core/load-pack.js.map +1 -0
- package/dist/core/manifest.d.ts +29 -0
- package/dist/core/manifest.d.ts.map +1 -0
- package/dist/core/manifest.js +75 -0
- package/dist/core/manifest.js.map +1 -0
- package/dist/core/resolve-pack.d.ts +7 -0
- package/dist/core/resolve-pack.d.ts.map +1 -0
- package/dist/core/resolve-pack.js +38 -0
- package/dist/core/resolve-pack.js.map +1 -0
- package/package.json +8 -5
- package/templates/dotnet/AgentSkills/entry-points/AGENTS.md +50 -0
- package/templates/dotnet/AgentSkills/entry-points/CLAUDE.md +50 -0
- package/templates/dotnet/AgentSkills/entry-points/antigravity-instructions.md +50 -0
- package/templates/dotnet/AgentSkills/entry-points/copilot-instructions.md +50 -0
- package/templates/dotnet/AgentSkills/entry-points/cursor-instructions.md +50 -0
- package/templates/dotnet/AgentSkills/memory/index.md +22 -0
- package/templates/dotnet/AgentSkills/memory/lessons/design.md +3 -0
- package/{src/templates → templates}/dotnet/AgentSkills/memory/lessons/infra.md +1 -0
- package/{src/templates → templates}/dotnet/manifest.json +8 -2
- package/bin/agent-skills.js +0 -7
- package/src/__tests__/copySkills.test.js +0 -161
- package/src/__tests__/list.test.js +0 -49
- package/src/__tests__/manifest.test.js +0 -72
- package/src/commands/add.js +0 -89
- package/src/commands/dotnet-setup.js +0 -67
- package/src/commands/init.js +0 -42
- package/src/commands/list.js +0 -41
- package/src/index.js +0 -33
- package/src/lib/copySkills.js +0 -84
- package/src/lib/manifest.js +0 -117
- package/src/lib/resolvePack.js +0 -44
- package/src/templates/dotnet/AgentSkills/entry-points/AGENTS.md +0 -16
- package/src/templates/dotnet/AgentSkills/entry-points/CLAUDE.md +0 -16
- package/src/templates/dotnet/AgentSkills/entry-points/copilot-instructions.md +0 -16
- package/src/templates/dotnet/AgentSkills/entry-points/cursor-instructions.md +0 -16
- package/src/templates/dotnet/AgentSkills/memory/index.md +0 -22
- package/src/templates/dotnet/AgentSkills/memory/lessons/design.md +0 -3
- /package/{src/templates → templates}/dotnet/AgentSkills/OPERATING.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/README.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/agents/README.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/agents/architect.agent.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/agents/developer.agent.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/memory/lessons/api.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/memory/lessons/auth.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/memory/lessons/csharp.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/memory/lessons/db.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/memory/lessons/mcp.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/memory/lessons/testing.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/memory/schema.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/INDEX.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/README.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/code-standards/SKILL.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/core/SKILL.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/csharp-xunit/SKILL.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/design/SKILL.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/dotnet-api/SKILL.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/dotnet-best-practices/SKILL.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/harness/SKILL.md +0 -0
- /package/{src/templates → templates}/dotnet/AgentSkills/skills/mcp_dotnet/SKILL.md +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// src/core/manifest.ts
|
|
2
|
+
// Reads and validates a pack's manifest.json.
|
|
3
|
+
//
|
|
4
|
+
// The manifest is the contract between a skills pack and the CLI.
|
|
5
|
+
// It declares what skills exist, where their source files are, and where
|
|
6
|
+
// they should be placed in the target project.
|
|
7
|
+
import { readFileSync, existsSync } from "fs";
|
|
8
|
+
import path from "path";
|
|
9
|
+
/**
|
|
10
|
+
* Reads and validates the manifest.json for a pack.
|
|
11
|
+
*
|
|
12
|
+
* @throws When manifest is missing, unreadable, or structurally invalid.
|
|
13
|
+
*/
|
|
14
|
+
export function readManifest(packDir) {
|
|
15
|
+
const manifestPath = path.join(packDir, "manifest.json");
|
|
16
|
+
if (!existsSync(manifestPath)) {
|
|
17
|
+
throw new Error(`manifest.json not found in pack at "${packDir}". ` +
|
|
18
|
+
`This pack may be malformed or out of date.`);
|
|
19
|
+
}
|
|
20
|
+
let raw;
|
|
21
|
+
try {
|
|
22
|
+
raw = readFileSync(manifestPath, "utf8");
|
|
23
|
+
// Strip UTF-8 BOM if present.
|
|
24
|
+
if (raw.charCodeAt(0) === 0xfeff) {
|
|
25
|
+
raw = raw.slice(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
30
|
+
throw new Error(`Could not read manifest.json: ${message}`);
|
|
31
|
+
}
|
|
32
|
+
let manifest;
|
|
33
|
+
try {
|
|
34
|
+
manifest = JSON.parse(raw);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
38
|
+
throw new Error(`manifest.json at "${manifestPath}" is not valid JSON: ${message}`);
|
|
39
|
+
}
|
|
40
|
+
validateManifest(manifest, manifestPath);
|
|
41
|
+
return manifest;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Throws with a descriptive message if the manifest does not meet the
|
|
45
|
+
* required shape.
|
|
46
|
+
*/
|
|
47
|
+
function validateManifest(manifest, filePath) {
|
|
48
|
+
if (typeof manifest !== "object" || manifest === null) {
|
|
49
|
+
throw new Error(`manifest.json at "${filePath}" must be a JSON object.`);
|
|
50
|
+
}
|
|
51
|
+
const obj = manifest;
|
|
52
|
+
const required = ["name", "version", "skills"];
|
|
53
|
+
for (const key of required) {
|
|
54
|
+
if (!(key in obj)) {
|
|
55
|
+
throw new Error(`manifest.json is missing required field "${key}".`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!Array.isArray(obj.skills)) {
|
|
59
|
+
throw new Error(`manifest.json "skills" must be an array.`);
|
|
60
|
+
}
|
|
61
|
+
for (const [i, skill] of obj.skills.entries()) {
|
|
62
|
+
const entry = skill;
|
|
63
|
+
for (const field of ["name", "description", "path"]) {
|
|
64
|
+
if (typeof entry[field] !== "string" || !entry[field].trim()) {
|
|
65
|
+
throw new Error(`manifest.json skills[${i}] is missing or has an empty "${field}" field.`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// dest is optional; when present it must be a non-empty string.
|
|
69
|
+
if ("dest" in entry &&
|
|
70
|
+
(typeof entry.dest !== "string" || !entry.dest.trim())) {
|
|
71
|
+
throw new Error(`manifest.json skills[${i}] has an invalid "dest" field — must be a non-empty string when present.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/core/manifest.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,8CAA8C;AAC9C,EAAE;AACF,kEAAkE;AAClE,yEAAyE;AACzE,+CAA+C;AAE/C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,IAAI,MAAM,MAAM,CAAC;AA0BxB;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAEzD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,uCAAuC,OAAO,KAAK;YACjD,4CAA4C,CAC/C,CAAC;IACJ,CAAC;IAED,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACzC,8BAA8B;QAC9B,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;YACjC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,QAAiB,CAAC;IACtB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,IAAI,KAAK,CACb,qBAAqB,YAAY,wBAAwB,OAAO,EAAE,CACnE,CAAC;IACJ,CAAC;IAED,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACzC,OAAO,QAAoB,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,QAAiB,EAAE,QAAgB;IAC3D,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,0BAA0B,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,GAAG,GAAG,QAAmC,CAAC;IAEhD,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAC;IACxD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,4CAA4C,GAAG,IAAI,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAK,GAAG,CAAC,MAAoB,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,KAAgC,CAAC;QAC/C,KAAK,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,CAAU,EAAE,CAAC;YAC7D,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,CAAE,KAAK,CAAC,KAAK,CAAY,CAAC,IAAI,EAAE,EAAE,CAAC;gBACzE,MAAM,IAAI,KAAK,CACb,wBAAwB,CAAC,iCAAiC,KAAK,UAAU,CAC1E,CAAC;YACJ,CAAC;QACH,CAAC;QACD,gEAAgE;QAChE,IACE,MAAM,IAAI,KAAK;YACf,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EACtD,CAAC;YACD,MAAM,IAAI,KAAK,CACb,wBAAwB,CAAC,0EAA0E,CACpG,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-pack.d.ts","sourceRoot":"","sources":["../../src/core/resolve-pack.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6BpD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/core/resolve-pack.ts
|
|
2
|
+
// Locates a templates folder bundled inside the package itself.
|
|
3
|
+
// Since everything is in one package, no runtime npm fetching is needed.
|
|
4
|
+
//
|
|
5
|
+
// Templates live at the repo/package root under `templates/<packName>/`.
|
|
6
|
+
import { existsSync } from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
/** Canonical directory names for built-in packs. */
|
|
12
|
+
const PACK_ALIASES = {
|
|
13
|
+
dotnet: "dotnet",
|
|
14
|
+
"skills-dotnet": "dotnet",
|
|
15
|
+
"@pratikpsl/agent-skills-dotnet": "dotnet",
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Resolves a pack name or alias to its installed directory.
|
|
19
|
+
*
|
|
20
|
+
* @throws When the pack cannot be located.
|
|
21
|
+
*/
|
|
22
|
+
export function resolvePack(packName) {
|
|
23
|
+
const normalized = PACK_ALIASES[packName] ??
|
|
24
|
+
packName
|
|
25
|
+
.replace(/^@pratikpsl\/agent-skills-/, "")
|
|
26
|
+
.replace(/^skills-/, "");
|
|
27
|
+
// templates/ lives three levels up from dist/core/ (at the package root)
|
|
28
|
+
// In development (src/core/), it's two levels up — but we always run from
|
|
29
|
+
// the compiled dist/, so three levels is correct.
|
|
30
|
+
const templateDir = path.resolve(__dirname, "..", "..", "templates", normalized);
|
|
31
|
+
if (existsSync(templateDir) &&
|
|
32
|
+
existsSync(path.join(templateDir, "manifest.json"))) {
|
|
33
|
+
return templateDir;
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Pack "${packName}" (mapped to "${normalized}") is not bundled with this version of the CLI. ` +
|
|
36
|
+
`Currently available packs: dotnet`);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=resolve-pack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-pack.js","sourceRoot":"","sources":["../../src/core/resolve-pack.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,gEAAgE;AAChE,yEAAyE;AACzE,EAAE;AACF,yEAAyE;AAEzE,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,oDAAoD;AACpD,MAAM,YAAY,GAA2B;IAC3C,MAAM,EAAE,QAAQ;IAChB,eAAe,EAAE,QAAQ;IACzB,gCAAgC,EAAE,QAAQ;CAC3C,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,UAAU,GACd,YAAY,CAAC,QAAQ,CAAC;QACtB,QAAQ;aACL,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC;aACzC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAE7B,yEAAyE;IACzE,0EAA0E;IAC1E,kDAAkD;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAC9B,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,UAAU,CACX,CAAC;IAEF,IACE,UAAU,CAAC,WAAW,CAAC;QACvB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,EACnD,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,IAAI,KAAK,CACb,SAAS,QAAQ,iBAAiB,UAAU,kDAAkD;QAC5F,mCAAmC,CACtC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pratikpsl/agent-skills",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"description": "CLI to scaffold and manage AI agent skills across projects",
|
|
6
6
|
"bin": {
|
|
7
|
-
"agent-skills": "bin/agent-skills.js"
|
|
7
|
+
"agent-skills": "dist/bin/agent-skills.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"dist",
|
|
11
|
+
"templates",
|
|
12
12
|
"README.md",
|
|
13
13
|
"LICENSE"
|
|
14
14
|
],
|
|
@@ -24,14 +24,17 @@
|
|
|
24
24
|
"url": "git+https://github.com/pratiksinghlad/coding-skills-ai.git"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
|
+
"build": "tsc",
|
|
27
28
|
"test": "vitest run",
|
|
28
29
|
"test:watch": "vitest",
|
|
29
|
-
"dry-run": "npm publish --dry-run"
|
|
30
|
+
"dry-run": "npm run build && npm publish --dry-run"
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
33
|
"commander": "^12.0.0"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.15.33",
|
|
37
|
+
"typescript": "^5.8.3",
|
|
35
38
|
"vitest": "^3.0.0"
|
|
36
39
|
}
|
|
37
40
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Codex / OpenAI Entry Point
|
|
2
|
+
|
|
3
|
+
This file is a lightweight entry point for Codex and OpenAI agents.
|
|
4
|
+
|
|
5
|
+
`AgentSkills/` is the single source of truth for skills, agents, memory,
|
|
6
|
+
prerequisites, checklists, and project rules used by all coding agents and
|
|
7
|
+
AI-enabled IDEs in this repository.
|
|
8
|
+
|
|
9
|
+
## Start Here
|
|
10
|
+
|
|
11
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
12
|
+
2. Follow skill routing in `AgentSkills/skills/INDEX.md`.
|
|
13
|
+
3. Load role definitions from `AgentSkills/agents/` only when the task requires them.
|
|
14
|
+
|
|
15
|
+
Do not duplicate canonical instructions in this file. Edit shared guidance in
|
|
16
|
+
`AgentSkills/`.
|
|
17
|
+
|
|
18
|
+
## Mandatory Bootstrap (All Agents — Enforced)
|
|
19
|
+
|
|
20
|
+
Before changing any file or producing a final answer for any **code-changing**
|
|
21
|
+
task in this repository, you MUST complete the following bootstrap sequence
|
|
22
|
+
in order. Do NOT skip this sequence even for tasks that appear simple or quick.
|
|
23
|
+
|
|
24
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
25
|
+
2. Read `AgentSkills/memory/index.md`; load only the domain lesson file(s)
|
|
26
|
+
relevant to the current task (do not load all files at once).
|
|
27
|
+
3. Read `AgentSkills/skills/INDEX.md` (when it exists).
|
|
28
|
+
4. Always load `AgentSkills/skills/core/SKILL.md`.
|
|
29
|
+
5. Load any task-specific skill from `AgentSkills/skills/` that matches the task.
|
|
30
|
+
6. For .NET / C# implementation tasks, load `AgentSkills/agents/developer.agent.md`.
|
|
31
|
+
7. For design, CQRS structure, SQL schema, or architecture tasks, load
|
|
32
|
+
`AgentSkills/agents/architect.agent.md`.
|
|
33
|
+
8. Inspect the worktree context before editing so existing user changes are
|
|
34
|
+
preserved.
|
|
35
|
+
9. Define the verification path for the task before making changes.
|
|
36
|
+
|
|
37
|
+
## Completion Gate (All Agents — Enforced)
|
|
38
|
+
|
|
39
|
+
Before marking any code-changing task complete:
|
|
40
|
+
|
|
41
|
+
1. Run the pre-submit checklist in `AgentSkills/skills/core/SKILL.md`.
|
|
42
|
+
2. Run the harness validator (unless the task is documentation-only or the
|
|
43
|
+
environment cannot run it — in that case, state the reason explicitly):
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
pwsh ./tools/Harness/validate.ps1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. Do not claim completion when required checks fail. List failures clearly and
|
|
50
|
+
leave the work in a reviewable state.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Claude Entry Point
|
|
2
|
+
|
|
3
|
+
This file is a lightweight entry point for Claude (Anthropic).
|
|
4
|
+
|
|
5
|
+
`AgentSkills/` is the single source of truth for skills, agents, memory,
|
|
6
|
+
prerequisites, checklists, and project rules used by all coding agents and
|
|
7
|
+
AI-enabled IDEs in this repository.
|
|
8
|
+
|
|
9
|
+
## Start Here
|
|
10
|
+
|
|
11
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
12
|
+
2. Follow skill routing in `AgentSkills/skills/INDEX.md`.
|
|
13
|
+
3. Load role definitions from `AgentSkills/agents/` only when the task requires them.
|
|
14
|
+
|
|
15
|
+
Do not duplicate canonical instructions in this file. Edit shared guidance in
|
|
16
|
+
`AgentSkills/`.
|
|
17
|
+
|
|
18
|
+
## Mandatory Bootstrap (All Agents — Enforced)
|
|
19
|
+
|
|
20
|
+
Before changing any file or producing a final answer for any **code-changing**
|
|
21
|
+
task in this repository, you MUST complete the following bootstrap sequence
|
|
22
|
+
in order. Do NOT skip this sequence even for tasks that appear simple or quick.
|
|
23
|
+
|
|
24
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
25
|
+
2. Read `AgentSkills/memory/index.md`; load only the domain lesson file(s)
|
|
26
|
+
relevant to the current task (do not load all files at once).
|
|
27
|
+
3. Read `AgentSkills/skills/INDEX.md` (when it exists).
|
|
28
|
+
4. Always load `AgentSkills/skills/core/SKILL.md`.
|
|
29
|
+
5. Load any task-specific skill from `AgentSkills/skills/` that matches the task.
|
|
30
|
+
6. For .NET / C# implementation tasks, load `AgentSkills/agents/developer.agent.md`.
|
|
31
|
+
7. For design, CQRS structure, SQL schema, or architecture tasks, load
|
|
32
|
+
`AgentSkills/agents/architect.agent.md`.
|
|
33
|
+
8. Inspect the worktree context before editing so existing user changes are
|
|
34
|
+
preserved.
|
|
35
|
+
9. Define the verification path for the task before making changes.
|
|
36
|
+
|
|
37
|
+
## Completion Gate (All Agents — Enforced)
|
|
38
|
+
|
|
39
|
+
Before marking any code-changing task complete:
|
|
40
|
+
|
|
41
|
+
1. Run the pre-submit checklist in `AgentSkills/skills/core/SKILL.md`.
|
|
42
|
+
2. Run the harness validator (unless the task is documentation-only or the
|
|
43
|
+
environment cannot run it — in that case, state the reason explicitly):
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
pwsh ./tools/Harness/validate.ps1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. Do not claim completion when required checks fail. List failures clearly and
|
|
50
|
+
leave the work in a reviewable state.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Antigravity Entry Point
|
|
2
|
+
|
|
3
|
+
This file is a lightweight entry point for the Antigravity IDE (Google DeepMind).
|
|
4
|
+
|
|
5
|
+
`AgentSkills/` is the single source of truth for skills, agents, memory,
|
|
6
|
+
prerequisites, checklists, and project rules used by all coding agents and
|
|
7
|
+
AI-enabled IDEs in this repository.
|
|
8
|
+
|
|
9
|
+
## Start Here
|
|
10
|
+
|
|
11
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
12
|
+
2. Follow skill routing in `AgentSkills/skills/INDEX.md`.
|
|
13
|
+
3. Load role definitions from `AgentSkills/agents/` only when the task requires them.
|
|
14
|
+
|
|
15
|
+
Do not duplicate canonical instructions in this file. Edit shared guidance in
|
|
16
|
+
`AgentSkills/`.
|
|
17
|
+
|
|
18
|
+
## Mandatory Bootstrap (All Agents — Enforced)
|
|
19
|
+
|
|
20
|
+
Before changing any file or producing a final answer for any **code-changing**
|
|
21
|
+
task in this repository, you MUST complete the following bootstrap sequence
|
|
22
|
+
in order. Do NOT skip this sequence even for tasks that appear simple or quick.
|
|
23
|
+
|
|
24
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
25
|
+
2. Read `AgentSkills/memory/index.md`; load only the domain lesson file(s)
|
|
26
|
+
relevant to the current task (do not load all files at once).
|
|
27
|
+
3. Read `AgentSkills/skills/INDEX.md` (when it exists).
|
|
28
|
+
4. Always load `AgentSkills/skills/core/SKILL.md`.
|
|
29
|
+
5. Load any task-specific skill from `AgentSkills/skills/` that matches the task.
|
|
30
|
+
6. For .NET / C# implementation tasks, load `AgentSkills/agents/developer.agent.md`.
|
|
31
|
+
7. For design, CQRS structure, SQL schema, or architecture tasks, load
|
|
32
|
+
`AgentSkills/agents/architect.agent.md`.
|
|
33
|
+
8. Inspect the worktree context before editing so existing user changes are
|
|
34
|
+
preserved.
|
|
35
|
+
9. Define the verification path for the task before making changes.
|
|
36
|
+
|
|
37
|
+
## Completion Gate (All Agents — Enforced)
|
|
38
|
+
|
|
39
|
+
Before marking any code-changing task complete:
|
|
40
|
+
|
|
41
|
+
1. Run the pre-submit checklist in `AgentSkills/skills/core/SKILL.md`.
|
|
42
|
+
2. Run the harness validator (unless the task is documentation-only or the
|
|
43
|
+
environment cannot run it — in that case, state the reason explicitly):
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
pwsh ./tools/Harness/validate.ps1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. Do not claim completion when required checks fail. List failures clearly and
|
|
50
|
+
leave the work in a reviewable state.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copilot Entry Point
|
|
2
|
+
|
|
3
|
+
This file is a lightweight entry point for GitHub Copilot.
|
|
4
|
+
|
|
5
|
+
`AgentSkills/` is the single source of truth for skills, agents, memory,
|
|
6
|
+
prerequisites, checklists, and project rules used by all coding agents and
|
|
7
|
+
AI-enabled IDEs in this repository.
|
|
8
|
+
|
|
9
|
+
## Start Here
|
|
10
|
+
|
|
11
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
12
|
+
2. Follow skill routing in `AgentSkills/skills/INDEX.md`.
|
|
13
|
+
3. Load role definitions from `AgentSkills/agents/` only when the task requires them.
|
|
14
|
+
|
|
15
|
+
Do not duplicate canonical instructions in this file. Edit shared guidance in
|
|
16
|
+
`AgentSkills/`.
|
|
17
|
+
|
|
18
|
+
## Mandatory Bootstrap (All Agents — Enforced)
|
|
19
|
+
|
|
20
|
+
Before changing any file or producing a final answer for any **code-changing**
|
|
21
|
+
task in this repository, you MUST complete the following bootstrap sequence
|
|
22
|
+
in order. Do NOT skip this sequence even for tasks that appear simple or quick.
|
|
23
|
+
|
|
24
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
25
|
+
2. Read `AgentSkills/memory/index.md`; load only the domain lesson file(s)
|
|
26
|
+
relevant to the current task (do not load all files at once).
|
|
27
|
+
3. Read `AgentSkills/skills/INDEX.md` (when it exists).
|
|
28
|
+
4. Always load `AgentSkills/skills/core/SKILL.md`.
|
|
29
|
+
5. Load any task-specific skill from `AgentSkills/skills/` that matches the task.
|
|
30
|
+
6. For .NET / C# implementation tasks, load `AgentSkills/agents/developer.agent.md`.
|
|
31
|
+
7. For design, CQRS structure, SQL schema, or architecture tasks, load
|
|
32
|
+
`AgentSkills/agents/architect.agent.md`.
|
|
33
|
+
8. Inspect the worktree context before editing so existing user changes are
|
|
34
|
+
preserved.
|
|
35
|
+
9. Define the verification path for the task before making changes.
|
|
36
|
+
|
|
37
|
+
## Completion Gate (All Agents — Enforced)
|
|
38
|
+
|
|
39
|
+
Before marking any code-changing task complete:
|
|
40
|
+
|
|
41
|
+
1. Run the pre-submit checklist in `AgentSkills/skills/core/SKILL.md`.
|
|
42
|
+
2. Run the harness validator (unless the task is documentation-only or the
|
|
43
|
+
environment cannot run it — in that case, state the reason explicitly):
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
pwsh ./tools/Harness/validate.ps1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. Do not claim completion when required checks fail. List failures clearly and
|
|
50
|
+
leave the work in a reviewable state.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Cursor / Antigravity Entry Point
|
|
2
|
+
|
|
3
|
+
This file is a lightweight entry point for Cursor and Antigravity IDEs.
|
|
4
|
+
|
|
5
|
+
`AgentSkills/` is the single source of truth for skills, agents, memory,
|
|
6
|
+
prerequisites, checklists, and project rules used by all coding agents and
|
|
7
|
+
AI-enabled IDEs in this repository.
|
|
8
|
+
|
|
9
|
+
## Start Here
|
|
10
|
+
|
|
11
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
12
|
+
2. Follow skill routing in `AgentSkills/skills/INDEX.md`.
|
|
13
|
+
3. Load role definitions from `AgentSkills/agents/` only when the task requires them.
|
|
14
|
+
|
|
15
|
+
Do not duplicate canonical instructions in this file. Edit shared guidance in
|
|
16
|
+
`AgentSkills/`.
|
|
17
|
+
|
|
18
|
+
## Mandatory Bootstrap (All Agents — Enforced)
|
|
19
|
+
|
|
20
|
+
Before changing any file or producing a final answer for any **code-changing**
|
|
21
|
+
task in this repository, you MUST complete the following bootstrap sequence
|
|
22
|
+
in order. Do NOT skip this sequence even for tasks that appear simple or quick.
|
|
23
|
+
|
|
24
|
+
1. Read `AgentSkills/OPERATING.md`.
|
|
25
|
+
2. Read `AgentSkills/memory/index.md`; load only the domain lesson file(s)
|
|
26
|
+
relevant to the current task (do not load all files at once).
|
|
27
|
+
3. Read `AgentSkills/skills/INDEX.md` (when it exists).
|
|
28
|
+
4. Always load `AgentSkills/skills/core/SKILL.md`.
|
|
29
|
+
5. Load any task-specific skill from `AgentSkills/skills/` that matches the task.
|
|
30
|
+
6. For .NET / C# implementation tasks, load `AgentSkills/agents/developer.agent.md`.
|
|
31
|
+
7. For design, CQRS structure, SQL schema, or architecture tasks, load
|
|
32
|
+
`AgentSkills/agents/architect.agent.md`.
|
|
33
|
+
8. Inspect the worktree context before editing so existing user changes are
|
|
34
|
+
preserved.
|
|
35
|
+
9. Define the verification path for the task before making changes.
|
|
36
|
+
|
|
37
|
+
## Completion Gate (All Agents — Enforced)
|
|
38
|
+
|
|
39
|
+
Before marking any code-changing task complete:
|
|
40
|
+
|
|
41
|
+
1. Run the pre-submit checklist in `AgentSkills/skills/core/SKILL.md`.
|
|
42
|
+
2. Run the harness validator (unless the task is documentation-only or the
|
|
43
|
+
environment cannot run it — in that case, state the reason explicitly):
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
pwsh ./tools/Harness/validate.ps1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. Do not claim completion when required checks fail. List failures clearly and
|
|
50
|
+
leave the work in a reviewable state.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Memory Index
|
|
2
|
+
|
|
3
|
+
Always load this file first. Then load **only** the domain file(s) that match your task.
|
|
4
|
+
Do NOT load domain files you do not need. Never load all files at once.
|
|
5
|
+
|
|
6
|
+
## Domain Map
|
|
7
|
+
|
|
8
|
+
| Domain | Load when | File | Lessons |
|
|
9
|
+
| ------- | ------------------------------------------------------------- | ---------------------------------------- | ------- |
|
|
10
|
+
| api | CQRS, MediatR, commands, queries, controllers, endpoints | [lessons/api.md](lessons/api.md) | 1 |
|
|
11
|
+
| db | EF Core, migrations, schema, seeding, repositories | [lessons/db.md](lessons/db.md) | 0 |
|
|
12
|
+
| infra | Build, paths, CI, tooling, portability, AgentSkills setup | [lessons/infra.md](lessons/infra.md) | 6 |
|
|
13
|
+
| auth | Authentication, authorisation, JWT, policies, claims | [lessons/auth.md](lessons/auth.md) | 0 |
|
|
14
|
+
| testing | xUnit, test data, mocking, coverage, assertions | [lessons/testing.md](lessons/testing.md) | 0 |
|
|
15
|
+
| csharp | C# language features, async/await, naming, code style | [lessons/csharp.md](lessons/csharp.md) | 0 |
|
|
16
|
+
| design | SOLID, CQRS, Repository, patterns, architecture decisions | [lessons/design.md](lessons/design.md) | 0 |
|
|
17
|
+
| mcp | MCP server tools, transports, contracts, .NET MCP integration | [lessons/mcp.md](lessons/mcp.md) | 0 |
|
|
18
|
+
|
|
19
|
+
## Writing a lesson?
|
|
20
|
+
|
|
21
|
+
Load `memory/schema.md` for the one-line format. Do not inline logging instructions here.
|
|
22
|
+
Update the lesson count in this table after appending to the domain file.
|
|
@@ -5,3 +5,4 @@ RULE: Use repo-relative paths in all agent and IDE instruction files; never writ
|
|
|
5
5
|
RULE: When splitting a monolithic memory file into domain files, grep the whole repo for the old path and update every reference before deleting the original. #stale-reference 2026-06-07
|
|
6
6
|
RULE: Always check native command exit codes explicitly in PowerShell harness scripts. #native-exit-code 2026-06-21
|
|
7
7
|
RULE: Run dotnet format after patching C# files; this repo enforces CRLF and no final newline. #format-fail 2026-07-01
|
|
8
|
+
RULE: Always execute the full AgentSkills bootstrap sequence before any code-changing task, even simple ones. #bootstrap-skip 2026-07-05
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pratikpsl/agent-skills-dotnet",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "AI agent skill definitions for .NET/C# projects (CQRS, MediatR, EF Core, xUnit, ASP.NET Core).",
|
|
5
5
|
"skills": [
|
|
6
6
|
{
|
|
@@ -78,9 +78,15 @@
|
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"name": "entry-point:cursor",
|
|
81
|
-
"description": "Lightweight Cursor
|
|
81
|
+
"description": "Lightweight Cursor entry point — routes the agent to AgentSkills/OPERATING.md.",
|
|
82
82
|
"path": "AgentSkills/entry-points/cursor-instructions.md",
|
|
83
83
|
"dest": ".cursor/rules/instructions.md"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "entry-point:antigravity",
|
|
87
|
+
"description": "Lightweight Antigravity (Google DeepMind) entry point — routes the agent to AgentSkills/OPERATING.md.",
|
|
88
|
+
"path": "AgentSkills/entry-points/antigravity-instructions.md",
|
|
89
|
+
"dest": ".agents/GEMINI.md"
|
|
84
90
|
}
|
|
85
91
|
]
|
|
86
92
|
}
|
package/bin/agent-skills.js
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
// src/__tests__/copySkills.test.js
|
|
2
|
-
// Unit tests for the copySkills utility.
|
|
3
|
-
// Key invariants tested:
|
|
4
|
-
// 1. Files are copied when destination does not exist.
|
|
5
|
-
// 2. Existing files are NOT overwritten without --force.
|
|
6
|
-
// 3. Existing files ARE overwritten with --force.
|
|
7
|
-
// 4. Summary counts (written/skipped) are correct.
|
|
8
|
-
// 5. The optional `dest` field routes a file to a different target path (IDE entry-points).
|
|
9
|
-
|
|
10
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
11
|
-
import { mkdirSync, writeFileSync, readFileSync, rmSync, existsSync } from 'fs';
|
|
12
|
-
import path from 'path';
|
|
13
|
-
import os from 'os';
|
|
14
|
-
import { copySkills } from '../lib/copySkills.js';
|
|
15
|
-
|
|
16
|
-
function makeTempDir() {
|
|
17
|
-
const dir = path.join(os.tmpdir(), `agent-skills-copy-test-${Date.now()}`);
|
|
18
|
-
mkdirSync(dir, { recursive: true });
|
|
19
|
-
return dir;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function createSkillSource(packDir, skillRelPath, content = 'skill content') {
|
|
23
|
-
const fullPath = path.join(packDir, skillRelPath);
|
|
24
|
-
mkdirSync(fullPath, { recursive: true });
|
|
25
|
-
writeFileSync(path.join(fullPath, 'SKILL.md'), content);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
describe('copySkills', () => {
|
|
29
|
-
let packDir;
|
|
30
|
-
let targetDir;
|
|
31
|
-
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
const ts = Date.now();
|
|
34
|
-
packDir = path.join(os.tmpdir(), `agent-skills-pack-${ts}`);
|
|
35
|
-
targetDir = path.join(os.tmpdir(), `agent-skills-target-${ts}`);
|
|
36
|
-
mkdirSync(packDir, { recursive: true });
|
|
37
|
-
mkdirSync(targetDir, { recursive: true });
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
afterEach(() => {
|
|
41
|
-
rmSync(packDir, { recursive: true, force: true });
|
|
42
|
-
rmSync(targetDir, { recursive: true, force: true });
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const skills = [
|
|
46
|
-
{ name: 'core', description: 'Core principles', path: 'AgentSkills/skills/core' },
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
it('copies a skill when destination does not exist', () => {
|
|
50
|
-
createSkillSource(packDir, 'AgentSkills/skills/core');
|
|
51
|
-
|
|
52
|
-
const { written, skipped } = copySkills({ skills, packDir, targetDir, force: false });
|
|
53
|
-
|
|
54
|
-
expect(written).toHaveLength(1);
|
|
55
|
-
expect(skipped).toHaveLength(0);
|
|
56
|
-
expect(existsSync(path.join(targetDir, 'AgentSkills/skills/core/SKILL.md'))).toBe(true);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('skips an existing skill without --force', () => {
|
|
60
|
-
createSkillSource(packDir, 'AgentSkills/skills/core', 'original');
|
|
61
|
-
// Pre-create destination with different content
|
|
62
|
-
const destSkillDir = path.join(targetDir, 'AgentSkills/skills/core');
|
|
63
|
-
mkdirSync(destSkillDir, { recursive: true });
|
|
64
|
-
writeFileSync(path.join(destSkillDir, 'SKILL.md'), 'existing content');
|
|
65
|
-
|
|
66
|
-
const { written, skipped } = copySkills({ skills, packDir, targetDir, force: false });
|
|
67
|
-
|
|
68
|
-
expect(written).toHaveLength(0);
|
|
69
|
-
expect(skipped).toHaveLength(1);
|
|
70
|
-
// Existing content should be preserved
|
|
71
|
-
const content = readFileSync(path.join(destSkillDir, 'SKILL.md'), 'utf8');
|
|
72
|
-
expect(content).toBe('existing content');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('overwrites an existing skill with --force', () => {
|
|
76
|
-
createSkillSource(packDir, 'AgentSkills/skills/core', 'new content');
|
|
77
|
-
const destSkillDir = path.join(targetDir, 'AgentSkills/skills/core');
|
|
78
|
-
mkdirSync(destSkillDir, { recursive: true });
|
|
79
|
-
writeFileSync(path.join(destSkillDir, 'SKILL.md'), 'old content');
|
|
80
|
-
|
|
81
|
-
const { written, skipped } = copySkills({ skills, packDir, targetDir, force: true });
|
|
82
|
-
|
|
83
|
-
expect(written).toHaveLength(1);
|
|
84
|
-
expect(skipped).toHaveLength(0);
|
|
85
|
-
const content = readFileSync(path.join(destSkillDir, 'SKILL.md'), 'utf8');
|
|
86
|
-
expect(content).toBe('new content');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('returns correct counts for mixed written/skipped', () => {
|
|
90
|
-
const twoSkills = [
|
|
91
|
-
{ name: 'core', description: 'Core', path: 'AgentSkills/skills/core' },
|
|
92
|
-
{ name: 'design', description: 'Design', path: 'AgentSkills/skills/design' },
|
|
93
|
-
];
|
|
94
|
-
|
|
95
|
-
createSkillSource(packDir, 'AgentSkills/skills/core');
|
|
96
|
-
createSkillSource(packDir, 'AgentSkills/skills/design');
|
|
97
|
-
|
|
98
|
-
// Pre-create only core in the destination
|
|
99
|
-
const destCore = path.join(targetDir, 'AgentSkills/skills/core');
|
|
100
|
-
mkdirSync(destCore, { recursive: true });
|
|
101
|
-
writeFileSync(path.join(destCore, 'SKILL.md'), 'existing');
|
|
102
|
-
|
|
103
|
-
const { written, skipped } = copySkills({ skills: twoSkills, packDir, targetDir, force: false });
|
|
104
|
-
|
|
105
|
-
expect(written).toHaveLength(1);
|
|
106
|
-
expect(skipped).toHaveLength(1);
|
|
107
|
-
expect(written[0]).toBe('AgentSkills/skills/design');
|
|
108
|
-
expect(skipped[0]).toBe('AgentSkills/skills/core');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('copies an entry-point file to the dest path, not the source path', () => {
|
|
112
|
-
// Simulate an IDE entry-point: source lives inside the pack, dest is at project root.
|
|
113
|
-
const entryPointSkills = [
|
|
114
|
-
{
|
|
115
|
-
name: 'entry-point:claude',
|
|
116
|
-
description: 'Claude entry point',
|
|
117
|
-
path: 'AgentSkills/entry-points/CLAUDE.md',
|
|
118
|
-
dest: 'CLAUDE.md',
|
|
119
|
-
},
|
|
120
|
-
];
|
|
121
|
-
|
|
122
|
-
// Create source file (a plain file, not a directory)
|
|
123
|
-
const srcDir = path.join(packDir, 'AgentSkills/entry-points');
|
|
124
|
-
mkdirSync(srcDir, { recursive: true });
|
|
125
|
-
writeFileSync(path.join(srcDir, 'CLAUDE.md'), '# Claude Entry Point');
|
|
126
|
-
|
|
127
|
-
const { written, skipped } = copySkills({ skills: entryPointSkills, packDir, targetDir, force: false });
|
|
128
|
-
|
|
129
|
-
// Should land at target root as CLAUDE.md, not inside AgentSkills/entry-points/
|
|
130
|
-
expect(written).toHaveLength(1);
|
|
131
|
-
expect(written[0]).toBe('CLAUDE.md');
|
|
132
|
-
expect(existsSync(path.join(targetDir, 'CLAUDE.md'))).toBe(true);
|
|
133
|
-
expect(existsSync(path.join(targetDir, 'AgentSkills/entry-points/CLAUDE.md'))).toBe(false);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('skips an existing entry-point file without --force (uses dest path)', () => {
|
|
137
|
-
const entryPointSkills = [
|
|
138
|
-
{
|
|
139
|
-
name: 'entry-point:claude',
|
|
140
|
-
description: 'Claude entry point',
|
|
141
|
-
path: 'AgentSkills/entry-points/CLAUDE.md',
|
|
142
|
-
dest: 'CLAUDE.md',
|
|
143
|
-
},
|
|
144
|
-
];
|
|
145
|
-
|
|
146
|
-
const srcDir = path.join(packDir, 'AgentSkills/entry-points');
|
|
147
|
-
mkdirSync(srcDir, { recursive: true });
|
|
148
|
-
writeFileSync(path.join(srcDir, 'CLAUDE.md'), 'new content');
|
|
149
|
-
|
|
150
|
-
// Pre-create destination
|
|
151
|
-
writeFileSync(path.join(targetDir, 'CLAUDE.md'), 'existing content');
|
|
152
|
-
|
|
153
|
-
const { written, skipped } = copySkills({ skills: entryPointSkills, packDir, targetDir, force: false });
|
|
154
|
-
|
|
155
|
-
expect(written).toHaveLength(0);
|
|
156
|
-
expect(skipped).toHaveLength(1);
|
|
157
|
-
expect(skipped[0]).toBe('CLAUDE.md');
|
|
158
|
-
// Existing content untouched
|
|
159
|
-
expect(readFileSync(path.join(targetDir, 'CLAUDE.md'), 'utf8')).toBe('existing content');
|
|
160
|
-
});
|
|
161
|
-
});
|