@azerogluemin/ai-bootstrap 0.4.2 → 0.6.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/dist/applier/agents-installer.d.ts +1 -6
  3. package/dist/applier/agents-installer.js +16 -64
  4. package/dist/applier/agents-installer.js.map +1 -1
  5. package/dist/applier/pool.d.ts +34 -0
  6. package/dist/applier/pool.js +166 -0
  7. package/dist/applier/pool.js.map +1 -0
  8. package/dist/applier/preset-definitions.d.ts +15 -0
  9. package/dist/applier/preset-definitions.js +225 -0
  10. package/dist/applier/preset-definitions.js.map +1 -0
  11. package/dist/applier/preset-scaffolder.d.ts +14 -0
  12. package/dist/applier/preset-scaffolder.js +526 -0
  13. package/dist/applier/preset-scaffolder.js.map +1 -0
  14. package/dist/applier/skills-installer.d.ts +5 -3
  15. package/dist/applier/skills-installer.js +26 -75
  16. package/dist/applier/skills-installer.js.map +1 -1
  17. package/dist/commands/help.d.ts +1 -0
  18. package/dist/commands/help.js +98 -0
  19. package/dist/commands/help.js.map +1 -0
  20. package/dist/commands/mcp.js +50 -5
  21. package/dist/commands/mcp.js.map +1 -1
  22. package/dist/commands/new.js +74 -164
  23. package/dist/commands/new.js.map +1 -1
  24. package/dist/commands/scan.d.ts +1 -0
  25. package/dist/commands/scan.js +42 -0
  26. package/dist/commands/scan.js.map +1 -0
  27. package/dist/commands/skills.js +65 -1
  28. package/dist/commands/skills.js.map +1 -1
  29. package/dist/index.js +10 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/utils/paths.d.ts +3 -0
  32. package/dist/utils/paths.js +8 -1
  33. package/dist/utils/paths.js.map +1 -1
  34. package/dist/wizard.js +63 -75
  35. package/dist/wizard.js.map +1 -1
  36. package/package.json +1 -1
  37. package/templates/skills/art-director/SKILL.md +209 -0
  38. package/templates/skills/backend-developer/SKILL.md +198 -0
  39. package/templates/skills/cinematographer/SKILL.md +233 -0
  40. package/templates/skills/colorist/SKILL.md +210 -0
  41. package/templates/skills/devops-developer/SKILL.md +263 -0
  42. package/templates/skills/editor/SKILL.md +166 -0
  43. package/templates/skills/frontend-developer/SKILL.md +147 -0
  44. package/templates/skills/mobile-developer/SKILL.md +227 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,159 @@ All notable changes to `@azerogluemin/ai-bootstrap` are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.6.0] — 2026-06-21
9
+
10
+ Preset-based project bootstrap — folder scaffolding + CLAUDE.md per preset.
11
+
12
+ ### Added — 8 new production skills
13
+
14
+ Real production-quality content (~150-280 lines each, with sources):
15
+
16
+ Dev specialists:
17
+ - `frontend-developer` — React 19/Next 16/Vue 3/Svelte 5, state mgmt, performance, WCAG 2.2, testing
18
+ - `backend-developer` — REST/GraphQL, NestJS/Hono/FastAPI, multi-tenant, OWASP, caching, queues
19
+ - `devops-developer` — Docker, K8s, CI/CD, IaC, secrets, monitoring, SLOs
20
+ - `mobile-developer` — React Native (New Arch), Flutter, native iOS/Android, offline sync
21
+
22
+ Film production specialists:
23
+ - `editor` — Cut grammar, J/L cuts, vertical pacing, sound editing, Resolve/Premiere/FCP/CapCut
24
+ - `colorist` — Scopes (waveform/vector/parade), LUT design, Pixar/Wong Kar-wai/Deakins/A24 looks
25
+ - `art-director` — Visual treatment, mood board, palette per scene/character, era research (AZ-specific)
26
+ - `cinematographer` — Camera/lens/light decision trees, Deakins/Lubezki/Fraser craft
27
+
28
+ ### Added — 3 project presets
29
+
30
+ Replaces bundle abstraction in user-facing CLI. Each preset includes
31
+ folder structure + CLAUDE.md template + skill+agent install list + MCP suggestions.
32
+
33
+ **SaaS Development** (~58 skills, ~50 agents, ~22 MCPs)
34
+ - Folders: \`apps/{web,api,admin}\`, \`packages/{ui,db,shared}\`, \`docs/00-27\`, \`infra/\`, \`scripts/\`
35
+ - CLAUDE.md rules: TS strict, multi-tenant, JWT+refresh, OWASP, decisions-log append-only
36
+ - 28 numbered docs scaffolded (00-claude-code-guide → 27-go-live-runbook)
37
+
38
+ **Social Page** (~44 skills, ~22 agents, ~21 MCPs)
39
+ - Folders: \`strategy/\`, \`calendar/\`, \`days/YYYY-MM-DD/{characters,shots,video,music,thumbnail,final}\`,
40
+ \`prompts-library/\`, \`assets/\`, \`analytics/\`
41
+ - CLAUDE.md rules: **Prompt-first** (vizual təsdiqsiz fayl qadağa), daily folder isolation
42
+ - Strategy MD skeletons: brand-guide, content-pillars, audience-personas, competitors
43
+
44
+ **AI Studio** (~34 skills, ~11 agents, ~14 MCPs)
45
+ - Folders: \`projects/<client>/{brief,characters,locations,shots,video,music}\`,
46
+ \`days/YYYY-MM-DD/\`, \`references/{pixar-style,cinematography,color-grading}\`,
47
+ \`prompts-library/\`
48
+ - CLAUDE.md rules: Prompt-first, style refs before prompt, file naming convention
49
+ - NO social platform skills/MCPs (studio doesn't publish)
50
+
51
+ ### Changed — `ai-bootstrap new` is now preset-based
52
+
53
+ Previous (v0.5.0): multi-select bundle checkbox
54
+ New (v0.6.0): single-select preset → 3 questions only:
55
+ 1. Layihə adı?
56
+ 2. Bu qovluqda nə qurmaq istəyirsən? (SaaS / Social Page / AI Studio)
57
+ 3. Qısa təsvir?
58
+
59
+ After selection: skills+agents symlinked from pool, MCPs auto-suggested,
60
+ folder structure scaffolded, CLAUDE.md written with preset-specific rules.
61
+
62
+ ### Architecture
63
+
64
+ - New: \`packages/cli/src/applier/preset-definitions.ts\` — 3 preset metadata
65
+ - New: \`packages/cli/src/applier/preset-scaffolder.ts\` — folder scaffolder per preset
66
+ - Bundles still exist internally (\`resolvePlan\`, \`SKILL_BUNDLES\`, \`AGENT_BUNDLES\`)
67
+ but no longer surface to users — presets replaced them
68
+ - Project state schema bumped to v2.0: \`{ preset, name, description, createdAt }\`
69
+
70
+ ### Tests
71
+
72
+ - 176 passing (was 142): 121 smoke + 55 e2e
73
+ - New: 30+ preset definition assertions (skill counts, MCP presence, preset uniqueness)
74
+ - New: 11 scaffolder assertions (SaaS 28 docs, Social strategy MDs, AI Studio refs)
75
+
76
+ ### Migration
77
+
78
+ - v0.5.0 projects (multi-bundle): continue to work; new \`ai-bootstrap new\` writes preset state
79
+ - Old multi-bundle CLAUDE.md template still readable; project state v2.0 backward compat
80
+
81
+ [0.6.0]: https://github.com/eminazeroglu/ai-bootstrap/releases/tag/v0.6.0
82
+
83
+ ## [0.5.0] — 2026-06-21
84
+
85
+ Big architectural + UX redesign from real-world test feedback.
86
+
87
+ ### Added — Pool + Symlink architecture
88
+
89
+ - `~/.claude/skills-pool/` — ALL skills stored ONCE on disk (~3.8 MB total)
90
+ - `~/.claude/agents-pool/` — same for agents
91
+ - User-scope (`~/.claude/skills/`) and project-scope (`<project>/.claude/skills/`)
92
+ are now **symlinks** pointing to pool entries (POSIX), junctions (Windows),
93
+ or copies (Windows fallback when admin not available)
94
+ - **Result**: 10 creator projects = 1 pool copy + 260 symlinks, not 260 file copies
95
+ - Updates to a skill propagate to every project automatically (pnpm-style pattern)
96
+
97
+ ### Changed — wizard simplified 6 steps → 1
98
+
99
+ Previous (v0.4.x): 15+ questions across 6 steps. Real user got overwhelmed,
100
+ hit SIGINT mid-flow, asked "why is this asking globally?".
101
+
102
+ New (v0.5.0): **3 questions only**:
103
+ 1. Adın?
104
+ 2. Əsas dilin? (az/en/ru/tr)
105
+ 3. Sən kimsən, nə edirsən? (1-2 cümlə)
106
+
107
+ Removed entirely:
108
+ - Projects scan step (no projects on fresh machine — `ai-bootstrap scan <path>` later)
109
+ - Bundle selection step (auto-installs `foundation` user-scope; project bundles via `new`)
110
+ - MCPs full picker (auto-installs 9 free MCPs: filesystem, memory, git, fetch,
111
+ time, arxiv, youtube-transcript, puppeteer, playwright)
112
+ - Memory configuration step (defaults: markdown-only, learning-keeper ON, all logs ON)
113
+ - GitHub backup step (use `ai-bootstrap backup init` when ready)
114
+
115
+ ### Changed — `ai-bootstrap new` simplified
116
+
117
+ Previous: 5 questions (single-bundle + override confirm + custom rules).
118
+ New: **3 questions only**:
119
+ 1. Layihə adı?
120
+ 2. Bundle(lər)? (**multi-select checkbox** — pick multiple at once)
121
+ 3. Qısa təsvir? (1-2 cümlə)
122
+
123
+ Removed:
124
+ - Single-bundle intent selection (replaced by multi-select)
125
+ - Bundle override confirm (multi-select handles it)
126
+ - Custom rules question (placeholder added to CLAUDE.md instead)
127
+
128
+ ### Added — new commands
129
+
130
+ - `ai-bootstrap help` — comprehensive guide (full tour, not just brief --help)
131
+ - `ai-bootstrap add` (no args) — **interactive multi-select** of all bundles + skills + agents
132
+ - `ai-bootstrap mcp add` — multi-select MCP picker (was missing)
133
+ - `ai-bootstrap mcp add github notion slack` — direct add
134
+ - `ai-bootstrap scan ~/MyJobs` — manual project scan (replaces removed wizard step)
135
+
136
+ ### Quality
137
+
138
+ - Cross-platform link helper: `linkFromPool()` tries symlink → junction → copy
139
+ - Pool sync detects newer template versions and refreshes pool entries
140
+ - 142 tests still passing (87 smoke + 55 e2e)
141
+
142
+ ### Workflow
143
+
144
+ ```bash
145
+ # 1) Maşına bir dəfə (3 sual, 30 saniyə):
146
+ npm install -g @azerogluemin/ai-bootstrap@latest
147
+ ai-bootstrap
148
+
149
+ # 2) Hər yeni layihə (3 sual, 20 saniyə):
150
+ cd ~/Projects/yeni-layihə
151
+ ai-bootstrap new
152
+ ```
153
+
154
+ ### Migration
155
+
156
+ - v0.4.x project copies → v0.5.0 symlinks: run `ai-bootstrap update` to switch
157
+ - Or `ai-bootstrap remove --all` then `ai-bootstrap new` per project
158
+
159
+ [0.5.0]: https://github.com/eminazeroglu/ai-bootstrap/releases/tag/v0.5.0
160
+
8
161
  ## [0.4.2] — 2026-06-21
9
162
 
10
163
  README quick-start fixed — global install upfront.
@@ -8,11 +8,6 @@ export interface AgentInstallResult {
8
8
  agent: string;
9
9
  error: string;
10
10
  }[];
11
+ linkMode?: 'symlink' | 'junction' | 'copy';
11
12
  }
12
- /**
13
- * Install agents into a target agents directory.
14
- * @param agentNames List of agent IDs to install
15
- * @param targetAgentsDir Absolute path. Default `~/.claude/agents/`; pass
16
- * `<project>/.claude/agents/` for project-scope.
17
- */
18
13
  export declare function installAgents(agentNames: string[], targetAgentsDir?: string): AgentInstallResult;
@@ -1,79 +1,31 @@
1
- // Install selected agents to ~/.claude/agents/
2
- // Copies agent directories from packages/templates/agents/<name>/
3
- // (Copy not symlink: npm cache may be cleaned, breaking symlinks.)
4
- import { existsSync, cpSync, rmSync } from 'node:fs';
5
- import { join, resolve } from 'node:path';
6
- import { fileURLToPath } from 'node:url';
1
+ // Install agents into a target agents directory by linking from the pool.
2
+ // Same architecture as skills-installer (v0.5.0 Pool+Symlink).
3
+ import { existsSync } from 'node:fs';
4
+ import { join } from 'node:path';
7
5
  import { ensureDir, AGENTS_DIR } from '../utils/paths.js';
8
- function templatesAgentsPath() {
9
- // Lookup order:
10
- // 1) ./templates/agents/ — published npm package (bundled via prepack)
11
- // 2) ../templates/agents/ — sibling templates package (monorepo dev)
12
- const here = fileURLToPath(import.meta.url);
13
- const cliRoot = resolve(here, '..', '..', '..');
14
- const candidates = [
15
- join(cliRoot, 'templates', 'agents'),
16
- resolve(cliRoot, '..', 'templates', 'agents'),
17
- ];
18
- for (const c of candidates) {
19
- if (existsSync(c))
20
- return c;
21
- }
22
- return candidates[0];
23
- }
24
- /**
25
- * Install agents into a target agents directory.
26
- * @param agentNames List of agent IDs to install
27
- * @param targetAgentsDir Absolute path. Default `~/.claude/agents/`; pass
28
- * `<project>/.claude/agents/` for project-scope.
29
- */
6
+ import { ensurePool, linkFromPool, poolHasAgent, poolAgentPath } from './pool.js';
30
7
  export function installAgents(agentNames, targetAgentsDir = AGENTS_DIR) {
31
- const result = {
32
- installed: [],
33
- skipped: [],
34
- errors: [],
35
- };
8
+ const result = { installed: [], skipped: [], errors: [] };
9
+ ensurePool();
36
10
  ensureDir(targetAgentsDir);
37
- const templatesDir = templatesAgentsPath();
38
- if (!existsSync(templatesDir)) {
39
- for (const name of agentNames) {
40
- result.skipped.push({
41
- agent: name,
42
- reason: 'agents templates folder yoxdur (Mərhələ C-5-də yaradılır)',
43
- });
44
- }
45
- return result;
46
- }
47
11
  for (const name of agentNames) {
48
- const sourceDir = join(templatesDir, name);
49
- const targetDir = join(targetAgentsDir, name);
50
- if (!existsSync(sourceDir)) {
51
- result.skipped.push({
52
- agent: name,
53
- reason: `template yoxdur: ${name} (skill hələ yazılmayıb)`,
54
- });
12
+ if (!poolHasAgent(name)) {
13
+ result.skipped.push({ agent: name, reason: `Pool-da yoxdur: ${name}` });
55
14
  continue;
56
15
  }
57
- if (existsSync(targetDir)) {
58
- result.skipped.push({
59
- agent: name,
60
- reason: 'artıq install olunub',
61
- });
16
+ const target = join(targetAgentsDir, name);
17
+ if (existsSync(target)) {
18
+ result.skipped.push({ agent: name, reason: 'artıq quraşdırılıb' });
62
19
  continue;
63
20
  }
64
21
  try {
65
- cpSync(sourceDir, targetDir, { recursive: true, dereference: true });
22
+ const mode = linkFromPool(poolAgentPath(name), target);
66
23
  result.installed.push(name);
24
+ if (!result.linkMode)
25
+ result.linkMode = mode;
67
26
  }
68
27
  catch (err) {
69
- try {
70
- rmSync(targetDir, { recursive: true, force: true });
71
- }
72
- catch { /* best-effort */ }
73
- result.errors.push({
74
- agent: name,
75
- error: err instanceof Error ? err.message : String(err),
76
- });
28
+ result.errors.push({ agent: name, error: err instanceof Error ? err.message : String(err) });
77
29
  }
78
30
  }
79
31
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"agents-installer.js","sourceRoot":"","sources":["../../src/applier/agents-installer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agents-installer.js","sourceRoot":"","sources":["../../src/applier/agents-installer.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,+DAA+D;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AASlF,MAAM,UAAU,aAAa,CAC3B,UAAoB,EACpB,kBAA0B,UAAU;IAEpC,MAAM,MAAM,GAAuB,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAE9E,UAAU,EAAE,CAAC;IACb,SAAS,CAAC,eAAe,CAAC,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,mBAAmB,IAAI,EAAE,EAAE,CAAC,CAAC;YACxE,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC;YACnE,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;YACvD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,34 @@
1
+ export interface PoolResult {
2
+ skillsPool: string;
3
+ agentsPool: string;
4
+ skillsAdded: number;
5
+ skillsUpdated: number;
6
+ agentsAdded: number;
7
+ agentsUpdated: number;
8
+ errors: {
9
+ item: string;
10
+ error: string;
11
+ }[];
12
+ }
13
+ /**
14
+ * Ensure the pool exists and is up-to-date with the bundled templates.
15
+ * Idempotent: safe to call on every install/update.
16
+ *
17
+ * Strategy: compare modification times. If template is newer, refresh pool entry.
18
+ */
19
+ export declare function ensurePool(): PoolResult;
20
+ /**
21
+ * Create a cross-platform link from a pool entry to a target location.
22
+ * - POSIX: symlink
23
+ * - Windows: try junction (no admin needed for dirs), fall back to copy on failure
24
+ *
25
+ * Returns 'symlink' | 'junction' | 'copy' to indicate what was used.
26
+ */
27
+ export declare function linkFromPool(poolEntry: string, targetPath: string): 'symlink' | 'junction' | 'copy';
28
+ /**
29
+ * Check whether a pool entry exists for the given name.
30
+ */
31
+ export declare function poolHasSkill(name: string): boolean;
32
+ export declare function poolHasAgent(name: string): boolean;
33
+ export declare function poolSkillPath(name: string): string;
34
+ export declare function poolAgentPath(name: string): string;
@@ -0,0 +1,166 @@
1
+ // Pool — single source of truth for skill + agent templates.
2
+ //
3
+ // Architecture (v0.5.0):
4
+ // ~/.claude/skills-pool/<skill>/ — every skill, ONE copy on disk
5
+ // ~/.claude/agents-pool/<agent>/ — every agent, ONE copy
6
+ // ~/.claude/skills/<skill> — symlink → pool (user scope)
7
+ // <project>/.claude/skills/<skill> — symlink → pool (project scope)
8
+ //
9
+ // Pool is populated from the bundled templates on first run (or update).
10
+ // pnpm-style: many references, one underlying store.
11
+ //
12
+ // Cross-platform:
13
+ // macOS / Linux / WSL2 — symlinkSync('dir')
14
+ // Windows native — try junction ('junction'); fall back to copy if no admin
15
+ //
16
+ // When a new version of @azerogluemin/ai-bootstrap is installed:
17
+ // - `ai-bootstrap update` re-runs ensurePool() → pool gets new content
18
+ // - All symlinks in user-scope + projects auto-see the update
19
+ // - No per-project re-install needed
20
+ import { existsSync, readdirSync, statSync, lstatSync, cpSync, symlinkSync, rmSync, realpathSync } from 'node:fs';
21
+ import { join, resolve, dirname } from 'node:path';
22
+ import { fileURLToPath } from 'node:url';
23
+ import { IS_WINDOWS, SKILLS_POOL_DIR, AGENTS_POOL_DIR, ensureDir } from '../utils/paths.js';
24
+ /**
25
+ * Resolve absolute path to the bundled templates folder.
26
+ * Same lookup as skills-installer used in v0.4.x.
27
+ */
28
+ function templatesRoot() {
29
+ const here = fileURLToPath(import.meta.url);
30
+ const cliRoot = resolve(here, '..', '..', '..');
31
+ const candidates = [
32
+ join(cliRoot, 'templates'), // published npm pkg (prepack)
33
+ resolve(cliRoot, '..', 'templates'), // monorepo dev sibling
34
+ ];
35
+ for (const c of candidates) {
36
+ if (existsSync(c))
37
+ return c;
38
+ }
39
+ return candidates[0];
40
+ }
41
+ /**
42
+ * Ensure the pool exists and is up-to-date with the bundled templates.
43
+ * Idempotent: safe to call on every install/update.
44
+ *
45
+ * Strategy: compare modification times. If template is newer, refresh pool entry.
46
+ */
47
+ export function ensurePool() {
48
+ const result = {
49
+ skillsPool: SKILLS_POOL_DIR,
50
+ agentsPool: AGENTS_POOL_DIR,
51
+ skillsAdded: 0,
52
+ skillsUpdated: 0,
53
+ agentsAdded: 0,
54
+ agentsUpdated: 0,
55
+ errors: [],
56
+ };
57
+ ensureDir(SKILLS_POOL_DIR);
58
+ ensureDir(AGENTS_POOL_DIR);
59
+ const root = templatesRoot();
60
+ syncCategory(join(root, 'skills'), SKILLS_POOL_DIR, result, 'skills');
61
+ syncCategory(join(root, 'agents'), AGENTS_POOL_DIR, result, 'agents');
62
+ return result;
63
+ }
64
+ function syncCategory(src, dst, result, category) {
65
+ if (!existsSync(src))
66
+ return;
67
+ const items = readdirSync(src);
68
+ for (const name of items) {
69
+ const srcItem = join(src, name);
70
+ const dstItem = join(dst, name);
71
+ try {
72
+ const srcStat = statSync(srcItem);
73
+ if (!srcStat.isDirectory())
74
+ continue;
75
+ if (!existsSync(dstItem)) {
76
+ cpSync(srcItem, dstItem, { recursive: true, dereference: true });
77
+ if (category === 'skills')
78
+ result.skillsAdded++;
79
+ else
80
+ result.agentsAdded++;
81
+ continue;
82
+ }
83
+ // Update check: if template SKILL.md/AGENT.md is newer than pool's, refresh
84
+ const markerFile = category === 'skills' ? 'SKILL.md' : 'AGENT.md';
85
+ const srcMarker = join(srcItem, markerFile);
86
+ const dstMarker = join(dstItem, markerFile);
87
+ if (existsSync(srcMarker) && existsSync(dstMarker)) {
88
+ const srcM = statSync(srcMarker).mtimeMs;
89
+ const dstM = statSync(dstMarker).mtimeMs;
90
+ if (srcM > dstM) {
91
+ rmSync(dstItem, { recursive: true, force: true });
92
+ cpSync(srcItem, dstItem, { recursive: true, dereference: true });
93
+ if (category === 'skills')
94
+ result.skillsUpdated++;
95
+ else
96
+ result.agentsUpdated++;
97
+ }
98
+ }
99
+ }
100
+ catch (err) {
101
+ result.errors.push({ item: name, error: err instanceof Error ? err.message : String(err) });
102
+ }
103
+ }
104
+ }
105
+ /**
106
+ * Create a cross-platform link from a pool entry to a target location.
107
+ * - POSIX: symlink
108
+ * - Windows: try junction (no admin needed for dirs), fall back to copy on failure
109
+ *
110
+ * Returns 'symlink' | 'junction' | 'copy' to indicate what was used.
111
+ */
112
+ export function linkFromPool(poolEntry, targetPath) {
113
+ const parent = dirname(targetPath);
114
+ ensureDir(parent);
115
+ if (existsSync(targetPath) || isBrokenSymlink(targetPath)) {
116
+ // Caller is responsible for skipping; we don't overwrite blindly
117
+ throw new Error(`Target already exists: ${targetPath}`);
118
+ }
119
+ if (!IS_WINDOWS) {
120
+ symlinkSync(poolEntry, targetPath, 'dir');
121
+ return 'symlink';
122
+ }
123
+ // Windows: try junction first (no admin needed for directories)
124
+ try {
125
+ symlinkSync(poolEntry, targetPath, 'junction');
126
+ return 'junction';
127
+ }
128
+ catch {
129
+ // Fall back to copy (admin required for true symlinks; junctions failed too)
130
+ cpSync(poolEntry, targetPath, { recursive: true, dereference: true });
131
+ return 'copy';
132
+ }
133
+ }
134
+ function isBrokenSymlink(p) {
135
+ try {
136
+ const ls = lstatSync(p);
137
+ if (!ls.isSymbolicLink())
138
+ return false;
139
+ try {
140
+ realpathSync(p);
141
+ return false;
142
+ }
143
+ catch {
144
+ return true;
145
+ }
146
+ }
147
+ catch {
148
+ return false;
149
+ }
150
+ }
151
+ /**
152
+ * Check whether a pool entry exists for the given name.
153
+ */
154
+ export function poolHasSkill(name) {
155
+ return existsSync(join(SKILLS_POOL_DIR, name));
156
+ }
157
+ export function poolHasAgent(name) {
158
+ return existsSync(join(AGENTS_POOL_DIR, name));
159
+ }
160
+ export function poolSkillPath(name) {
161
+ return join(SKILLS_POOL_DIR, name);
162
+ }
163
+ export function poolAgentPath(name) {
164
+ return join(AGENTS_POOL_DIR, name);
165
+ }
166
+ //# sourceMappingURL=pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/applier/pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export type PresetId = 'saas-development' | 'social-page' | 'ai-studio';
2
+ export interface PresetDefinition {
3
+ id: PresetId;
4
+ label: string;
5
+ description: string;
6
+ skills: string[];
7
+ agents: string[];
8
+ mcps: string[];
9
+ }
10
+ export declare const SAAS_DEVELOPMENT: PresetDefinition;
11
+ export declare const SOCIAL_PAGE: PresetDefinition;
12
+ export declare const AI_STUDIO: PresetDefinition;
13
+ export declare const PRESETS: Record<PresetId, PresetDefinition>;
14
+ export declare function getPreset(id: PresetId): PresetDefinition;
15
+ export declare function listPresets(): PresetDefinition[];