codymaster 4.6.0 → 5.2.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 (161) hide show
  1. package/CHANGELOG.md +74 -8
  2. package/README.md +192 -95
  3. package/dist/advisory-handoff.js +89 -0
  4. package/dist/advisory-report.js +105 -0
  5. package/dist/browse-server.js +251 -0
  6. package/dist/cli/command-registry.js +34 -0
  7. package/dist/cli/commands/agent.js +120 -0
  8. package/dist/cli/commands/bench.js +69 -0
  9. package/dist/cli/commands/brain.js +108 -0
  10. package/dist/cli/commands/dashboard.js +93 -0
  11. package/dist/cli/commands/design-studio.js +111 -0
  12. package/dist/cli/commands/distro.js +25 -0
  13. package/dist/cli/commands/engineering.js +596 -0
  14. package/dist/cli/commands/evolve.js +123 -0
  15. package/dist/cli/commands/mcp-serve.js +104 -0
  16. package/dist/cli/commands/project.js +324 -0
  17. package/dist/cli/commands/skill-chain.js +269 -0
  18. package/dist/cli/commands/system.js +89 -0
  19. package/dist/cli/commands/task.js +254 -0
  20. package/dist/cli/update-check.js +83 -0
  21. package/dist/cm-config.js +92 -0
  22. package/dist/cm-suggest.js +77 -0
  23. package/dist/codybench/judges/automated.js +31 -0
  24. package/dist/codybench/runners/claude-code.js +32 -0
  25. package/dist/codybench/suites/memory-retention.js +85 -0
  26. package/dist/codybench/suites/tdd-regression.js +35 -0
  27. package/dist/codybench/suites/token-efficiency.js +55 -0
  28. package/dist/codybench/types.js +2 -0
  29. package/dist/context-db.js +157 -0
  30. package/dist/continuity.js +2 -6
  31. package/dist/distro-validate.js +54 -0
  32. package/dist/execution-analyzer.js +138 -0
  33. package/dist/guardian-core.js +74 -0
  34. package/dist/index.js +36 -2759
  35. package/dist/indexer/skills-lib.js +533 -0
  36. package/dist/indexer/skills-map.js +1374 -0
  37. package/dist/indexer/skills.js +16 -0
  38. package/dist/learning-promoter.js +246 -0
  39. package/dist/mcp-context-server.js +289 -1
  40. package/dist/mcp-skills-tools.js +81 -0
  41. package/dist/retro-summary.js +70 -0
  42. package/dist/second-opinion-providers.js +79 -0
  43. package/dist/skill-chain.js +63 -1
  44. package/dist/skill-evolver.js +456 -0
  45. package/dist/skill-execution-cache.js +254 -0
  46. package/dist/smart-brain-router.js +184 -0
  47. package/dist/sprint-pipeline.js +228 -0
  48. package/dist/storage-backend.js +14 -67
  49. package/dist/token-budget.js +88 -0
  50. package/dist/utils/cli-utils.js +76 -0
  51. package/dist/utils/skill-utils.js +32 -0
  52. package/package.json +17 -7
  53. package/scripts/build-skills.mjs +51 -0
  54. package/scripts/gate-0-repo-hygiene.js +75 -0
  55. package/scripts/postinstall.js +34 -28
  56. package/scripts/security-scan.js +1 -1
  57. package/scripts/validate-skills.mjs +42 -0
  58. package/skills/CLAUDE.md +2 -7
  59. package/skills/_shared/helpers.md +2 -8
  60. package/skills/cm-ads-tracker/SKILL.md +3 -6
  61. package/skills/cm-browse/SKILL.md +34 -0
  62. package/skills/cm-conductor-worktrees/SKILL.md +28 -0
  63. package/skills/cm-content-factory/SKILL.md +1 -1
  64. package/skills/cm-content-factory/landing/docs/content/changelog.md +36 -0
  65. package/skills/cm-content-factory/landing/docs/content/deployment.md +46 -0
  66. package/skills/cm-content-factory/landing/docs/content/execution-flow.md +67 -0
  67. package/skills/cm-content-factory/landing/docs/content/memory-system.md +38 -0
  68. package/skills/cm-content-factory/landing/docs/content/openspace.md +27 -0
  69. package/skills/cm-content-factory/landing/docs/content/use-cases.md +26 -0
  70. package/skills/cm-content-factory/landing/docs/content/v5-intro.md +28 -0
  71. package/skills/cm-content-factory/landing/docs/index.html +240 -0
  72. package/skills/cm-content-factory/landing/index.html +100 -100
  73. package/skills/cm-content-factory/landing/script.js +42 -0
  74. package/skills/cm-content-factory/landing/translations.js +400 -400
  75. package/skills/cm-continuity/SKILL.md +32 -33
  76. package/skills/cm-design-studio/SKILL.md +34 -0
  77. package/skills/cm-ecosystem-roadmap/SKILL.md +15 -0
  78. package/skills/cm-engineering-meta/SKILL.md +73 -0
  79. package/skills/cm-growth-hacking/SKILL.md +1 -12
  80. package/skills/cm-guardian-runtime/SKILL.md +26 -0
  81. package/skills/cm-mcp-engineering/SKILL.md +22 -0
  82. package/skills/cm-notebooklm/SKILL.md +1 -17
  83. package/skills/cm-post-deploy-canary/SKILL.md +22 -0
  84. package/skills/cm-project-bootstrap/SKILL.md +11 -0
  85. package/skills/cm-qa-visual-cli/SKILL.md +22 -0
  86. package/skills/cm-retro-cli/SKILL.md +23 -0
  87. package/skills/cm-second-opinion-cli/SKILL.md +23 -0
  88. package/skills/cm-secret-shield/SKILL.md +2 -2
  89. package/skills/cm-security-gate/SKILL.md +1 -0
  90. package/skills/cm-skill-chain/SKILL.md +25 -4
  91. package/skills/cm-skill-evolution/SKILL.md +83 -0
  92. package/skills/cm-skill-health/SKILL.md +83 -0
  93. package/skills/cm-skill-index/SKILL.md +11 -3
  94. package/skills/cm-skill-search/SKILL.md +49 -0
  95. package/skills/cm-skill-share/SKILL.md +58 -0
  96. package/skills/cm-sprint-bus/SKILL.md +33 -0
  97. package/skills/cm-start/SKILL.md +0 -10
  98. package/skills/cm-tdd/SKILL.md +59 -72
  99. package/skills/profiles/README.md +21 -0
  100. package/skills/profiles/core.txt +23 -0
  101. package/skills/profiles/design.txt +6 -0
  102. package/skills/profiles/full.txt +62 -0
  103. package/skills/profiles/growth.txt +10 -0
  104. package/skills/profiles/knowledge.txt +7 -0
  105. package/install.sh +0 -901
  106. package/scripts/test-gemini.js +0 -13
  107. package/skills/cm-frappe-agent/SKILL.md +0 -134
  108. package/skills/cm-frappe-agent/agents/doctype-architect.md +0 -596
  109. package/skills/cm-frappe-agent/agents/erpnext-customizer.md +0 -643
  110. package/skills/cm-frappe-agent/agents/frappe-backend.md +0 -814
  111. package/skills/cm-frappe-agent/agents/frappe-custom-frontend.md +0 -557
  112. package/skills/cm-frappe-agent/agents/frappe-debugger.md +0 -625
  113. package/skills/cm-frappe-agent/agents/frappe-fixer.md +0 -275
  114. package/skills/cm-frappe-agent/agents/frappe-frontend.md +0 -660
  115. package/skills/cm-frappe-agent/agents/frappe-installer.md +0 -158
  116. package/skills/cm-frappe-agent/agents/frappe-performance.md +0 -307
  117. package/skills/cm-frappe-agent/agents/frappe-planner.md +0 -419
  118. package/skills/cm-frappe-agent/agents/frappe-remote-ops.md +0 -153
  119. package/skills/cm-frappe-agent/agents/github-workflow.md +0 -286
  120. package/skills/cm-frappe-agent/commands/frappe-app.md +0 -351
  121. package/skills/cm-frappe-agent/commands/frappe-backend.md +0 -162
  122. package/skills/cm-frappe-agent/commands/frappe-bench.md +0 -254
  123. package/skills/cm-frappe-agent/commands/frappe-debug.md +0 -263
  124. package/skills/cm-frappe-agent/commands/frappe-doctype-create.md +0 -272
  125. package/skills/cm-frappe-agent/commands/frappe-doctype-field.md +0 -310
  126. package/skills/cm-frappe-agent/commands/frappe-erpnext.md +0 -210
  127. package/skills/cm-frappe-agent/commands/frappe-fix.md +0 -59
  128. package/skills/cm-frappe-agent/commands/frappe-frontend.md +0 -210
  129. package/skills/cm-frappe-agent/commands/frappe-fullstack.md +0 -243
  130. package/skills/cm-frappe-agent/commands/frappe-github.md +0 -57
  131. package/skills/cm-frappe-agent/commands/frappe-install.md +0 -52
  132. package/skills/cm-frappe-agent/commands/frappe-plan.md +0 -442
  133. package/skills/cm-frappe-agent/commands/frappe-remote.md +0 -58
  134. package/skills/cm-frappe-agent/commands/frappe-test.md +0 -356
  135. package/skills/cm-frappe-agent/docs/README.md +0 -51
  136. package/skills/cm-frappe-agent/docs/agents-catalog.md +0 -113
  137. package/skills/cm-frappe-agent/docs/architecture.md +0 -149
  138. package/skills/cm-frappe-agent/docs/commands-catalog.md +0 -82
  139. package/skills/cm-frappe-agent/docs/resources-catalog.md +0 -66
  140. package/skills/cm-frappe-agent/docs/sitemap-urls.txt +0 -52
  141. package/skills/cm-frappe-agent/docs/sitemap.md +0 -81
  142. package/skills/cm-frappe-agent/docs/sop/user-guide.md +0 -178
  143. package/skills/cm-frappe-agent/docs/sop/vibe-coding-guide.md +0 -122
  144. package/skills/cm-frappe-agent/resources/7-layer-architecture.md +0 -985
  145. package/skills/cm-frappe-agent/resources/bench_commands.md +0 -73
  146. package/skills/cm-frappe-agent/resources/code-patterns-guide.md +0 -948
  147. package/skills/cm-frappe-agent/resources/common_pitfalls.md +0 -266
  148. package/skills/cm-frappe-agent/resources/doctype-registry.md +0 -158
  149. package/skills/cm-frappe-agent/resources/installation-guide.md +0 -289
  150. package/skills/cm-frappe-agent/resources/rest-api-patterns.md +0 -182
  151. package/skills/cm-frappe-agent/resources/scaffold_checklist.md +0 -82
  152. package/skills/cm-frappe-agent/resources/upgrade_patterns.md +0 -113
  153. package/skills/cm-frappe-agent/resources/web-form-patterns.md +0 -252
  154. package/skills/cm-frappe-agent/skills/bench-commands/SKILL.md +0 -621
  155. package/skills/cm-frappe-agent/skills/client-scripts/SKILL.md +0 -642
  156. package/skills/cm-frappe-agent/skills/doctype-patterns/SKILL.md +0 -576
  157. package/skills/cm-frappe-agent/skills/frappe-api/SKILL.md +0 -740
  158. package/skills/cm-frappe-agent/skills/remote-operations/SKILL.md +0 -47
  159. package/skills/cm-frappe-agent/skills/server-scripts/SKILL.md +0 -608
  160. package/skills/cm-frappe-agent/skills/web-forms/SKILL.md +0 -46
  161. package/skills/frappe-app-builder.zip +0 -0
@@ -0,0 +1,533 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AGENT_FOLDER_MAP = exports.WEB_FRONTEND_EXTENSIONS = exports.FRONTEND_BONUS_SKILLS = exports.FRONTEND_PACKAGES = exports.COMBO_SKILLS_MAP = exports.SKILLS_MAP = void 0;
4
+ exports.parseSettingsGradleModules = parseSettingsGradleModules;
5
+ exports.hasWebFrontendFiles = hasWebFrontendFiles;
6
+ exports.resolveWorkspaces = resolveWorkspaces;
7
+ exports.readGemfile = readGemfile;
8
+ exports.readPackageJson = readPackageJson;
9
+ exports.readDenoJson = readDenoJson;
10
+ exports.getDenoImportNames = getDenoImportNames;
11
+ exports.getAllPackageNames = getAllPackageNames;
12
+ exports.detectTechnologies = detectTechnologies;
13
+ exports.detectCombos = detectCombos;
14
+ exports.detectAgents = detectAgents;
15
+ exports.parseSkillPath = parseSkillPath;
16
+ exports.getInstalledSkillNames = getInstalledSkillNames;
17
+ exports.collectSkills = collectSkills;
18
+ const node_fs_1 = require("node:fs");
19
+ const node_path_1 = require("node:path");
20
+ const node_os_1 = require("node:os");
21
+ var skills_map_1 = require("./skills-map");
22
+ Object.defineProperty(exports, "SKILLS_MAP", { enumerable: true, get: function () { return skills_map_1.SKILLS_MAP; } });
23
+ Object.defineProperty(exports, "COMBO_SKILLS_MAP", { enumerable: true, get: function () { return skills_map_1.COMBO_SKILLS_MAP; } });
24
+ Object.defineProperty(exports, "FRONTEND_PACKAGES", { enumerable: true, get: function () { return skills_map_1.FRONTEND_PACKAGES; } });
25
+ Object.defineProperty(exports, "FRONTEND_BONUS_SKILLS", { enumerable: true, get: function () { return skills_map_1.FRONTEND_BONUS_SKILLS; } });
26
+ Object.defineProperty(exports, "WEB_FRONTEND_EXTENSIONS", { enumerable: true, get: function () { return skills_map_1.WEB_FRONTEND_EXTENSIONS; } });
27
+ Object.defineProperty(exports, "AGENT_FOLDER_MAP", { enumerable: true, get: function () { return skills_map_1.AGENT_FOLDER_MAP; } });
28
+ const skills_map_2 = require("./skills-map");
29
+ // ── Internal Constants ───────────────────────────────────────
30
+ const AGENT_FOLDER_ENTRIES = Object.entries(skills_map_2.AGENT_FOLDER_MAP);
31
+ const SCAN_SKIP_DIRS = new Set([
32
+ "node_modules",
33
+ ".git",
34
+ "vendor",
35
+ ".next",
36
+ "dist",
37
+ "build",
38
+ ".output",
39
+ ".nuxt",
40
+ ".svelte-kit",
41
+ "__pycache__",
42
+ ".cache",
43
+ "coverage",
44
+ ".turbo",
45
+ ".terraform",
46
+ "var",
47
+ "bin",
48
+ "obj",
49
+ ".vs",
50
+ ]);
51
+ const GRADLE_SCAN_ROOT_FILES = [
52
+ "build.gradle.kts",
53
+ "build.gradle",
54
+ "settings.gradle.kts",
55
+ "settings.gradle",
56
+ "gradle/libs.versions.toml",
57
+ ];
58
+ const DOTNET_SCAN_ROOT_FILES = [
59
+ "global.json",
60
+ "NuGet.Config",
61
+ "Directory.Build.props",
62
+ "Directory.Packages.props",
63
+ ];
64
+ // ── Gradle Scanning ──────────────────────────────────────────
65
+ function parseSettingsGradleModules(content) {
66
+ const modules = [];
67
+ const includeRe = /include\s*\(?\s*([^)]+)/g;
68
+ let includeMatch;
69
+ while ((includeMatch = includeRe.exec(content)) !== null) {
70
+ const args = includeMatch[1];
71
+ const quotedRe = /['"]([^'"]+)['"]/g;
72
+ let quotedMatch;
73
+ while ((quotedMatch = quotedRe.exec(args)) !== null) {
74
+ modules.push(quotedMatch[1].replace(/^:/, "").replace(/:/g, "/"));
75
+ }
76
+ }
77
+ return modules;
78
+ }
79
+ const _gradleCache = new Map();
80
+ function gradleLayoutCandidatePaths(projectDir) {
81
+ const cached = _gradleCache.get(projectDir);
82
+ if (cached)
83
+ return cached;
84
+ const candidates = [];
85
+ const seen = new Set();
86
+ function add(filePath) {
87
+ if (!seen.has(filePath)) {
88
+ candidates.push(filePath);
89
+ seen.add(filePath);
90
+ }
91
+ }
92
+ for (const f of GRADLE_SCAN_ROOT_FILES) {
93
+ add((0, node_path_1.join)(projectDir, f));
94
+ }
95
+ let entries;
96
+ try {
97
+ entries = (0, node_fs_1.readdirSync)(projectDir, { withFileTypes: true });
98
+ }
99
+ catch (_a) {
100
+ entries = [];
101
+ }
102
+ for (const e of entries) {
103
+ if (!e.isDirectory() || e.name.startsWith(".") || SCAN_SKIP_DIRS.has(e.name))
104
+ continue;
105
+ for (const g of ["build.gradle.kts", "build.gradle"]) {
106
+ add((0, node_path_1.join)(projectDir, e.name, g));
107
+ }
108
+ }
109
+ for (const settingsFile of ["settings.gradle.kts", "settings.gradle"]) {
110
+ const settingsPath = (0, node_path_1.join)(projectDir, settingsFile);
111
+ let content;
112
+ try {
113
+ content = (0, node_fs_1.readFileSync)(settingsPath, "utf-8");
114
+ }
115
+ catch (_b) {
116
+ continue;
117
+ }
118
+ for (const modulePath of parseSettingsGradleModules(content)) {
119
+ for (const g of ["build.gradle.kts", "build.gradle"]) {
120
+ add((0, node_path_1.join)(projectDir, modulePath, g));
121
+ }
122
+ }
123
+ break;
124
+ }
125
+ _gradleCache.set(projectDir, candidates);
126
+ return candidates;
127
+ }
128
+ // ── .NET Scanning ────────────────────────────────────────────
129
+ const _dotNetCache = new Map();
130
+ function dotNetLayoutCandidatePaths(projectDir) {
131
+ const cached = _dotNetCache.get(projectDir);
132
+ if (cached)
133
+ return cached;
134
+ const candidates = [];
135
+ const seen = new Set();
136
+ function add(filePath) {
137
+ if (!seen.has(filePath)) {
138
+ candidates.push(filePath);
139
+ seen.add(filePath);
140
+ }
141
+ }
142
+ for (const f of DOTNET_SCAN_ROOT_FILES) {
143
+ add((0, node_path_1.join)(projectDir, f));
144
+ }
145
+ function scan(dir, depth) {
146
+ if (depth > 2)
147
+ return;
148
+ let entries;
149
+ try {
150
+ entries = (0, node_fs_1.readdirSync)(dir, { withFileTypes: true });
151
+ }
152
+ catch (_a) {
153
+ return;
154
+ }
155
+ for (const e of entries) {
156
+ if (e.isFile()) {
157
+ const lower = e.name.toLowerCase();
158
+ if (lower.endsWith(".sln") || lower.endsWith(".csproj") || lower.endsWith(".fsproj")) {
159
+ add((0, node_path_1.join)(dir, e.name));
160
+ }
161
+ }
162
+ else if (e.isDirectory() && !e.name.startsWith(".") && !SCAN_SKIP_DIRS.has(e.name)) {
163
+ scan((0, node_path_1.join)(dir, e.name), depth + 1);
164
+ }
165
+ }
166
+ }
167
+ scan(projectDir, 0);
168
+ _dotNetCache.set(projectDir, candidates);
169
+ return candidates;
170
+ }
171
+ function resolveConfigFileContentPaths(projectDir, config) {
172
+ if (config.scanGradleLayout) {
173
+ return gradleLayoutCandidatePaths(projectDir);
174
+ }
175
+ if (config.scanDotNetLayout) {
176
+ return dotNetLayoutCandidatePaths(projectDir);
177
+ }
178
+ return (config.files || []).map((f) => (0, node_path_1.join)(projectDir, f));
179
+ }
180
+ // ── Frontend File Scanning ───────────────────────────────────
181
+ function hasWebFrontendFiles(projectDir, maxDepth = 3) {
182
+ function scan(dir, depth) {
183
+ let entries;
184
+ try {
185
+ entries = (0, node_fs_1.readdirSync)(dir, { withFileTypes: true });
186
+ }
187
+ catch (_a) {
188
+ return false;
189
+ }
190
+ for (const entry of entries) {
191
+ if (entry.isFile()) {
192
+ const name = entry.name;
193
+ if (name.endsWith(".blade.php"))
194
+ return true;
195
+ const dot = name.lastIndexOf(".");
196
+ if (dot !== -1 && skills_map_2.WEB_FRONTEND_EXTENSIONS.has(name.slice(dot)))
197
+ return true;
198
+ }
199
+ else if (entry.isDirectory() && depth < maxDepth) {
200
+ if (SCAN_SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))
201
+ continue;
202
+ if (scan((0, node_path_1.join)(dir, entry.name), depth + 1))
203
+ return true;
204
+ }
205
+ }
206
+ return false;
207
+ }
208
+ return scan(projectDir, 0);
209
+ }
210
+ // ── Workspace Resolution ──────────────────────────────────────
211
+ function parsePnpmWorkspaceYaml(content) {
212
+ const lines = content.split("\n");
213
+ const patterns = [];
214
+ let inPackages = false;
215
+ for (const raw of lines) {
216
+ const line = raw.trim();
217
+ if (line === "packages:" || line === "packages :") {
218
+ inPackages = true;
219
+ continue;
220
+ }
221
+ if (inPackages) {
222
+ if (line.startsWith("- ")) {
223
+ patterns.push(line
224
+ .slice(2)
225
+ .trim()
226
+ .replace(/^['"]|['"]$/g, ""));
227
+ }
228
+ else if (line !== "" && !line.startsWith("#")) {
229
+ break;
230
+ }
231
+ }
232
+ }
233
+ return patterns;
234
+ }
235
+ function expandWorkspacePatterns(projectDir, patterns) {
236
+ const dirs = [];
237
+ for (const pattern of patterns) {
238
+ if (pattern.includes("*")) {
239
+ const parent = (0, node_path_1.join)(projectDir, pattern.replace(/\/?\*.*$/, ""));
240
+ let entries;
241
+ try {
242
+ entries = (0, node_fs_1.readdirSync)(parent, { withFileTypes: true });
243
+ }
244
+ catch (_a) {
245
+ continue;
246
+ }
247
+ for (const entry of entries) {
248
+ if (!entry.isDirectory() || SCAN_SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))
249
+ continue;
250
+ const wsDir = (0, node_path_1.join)(parent, entry.name);
251
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(wsDir, "package.json")) ||
252
+ (0, node_fs_1.existsSync)((0, node_path_1.join)(wsDir, "deno.json")) ||
253
+ (0, node_fs_1.existsSync)((0, node_path_1.join)(wsDir, "deno.jsonc"))) {
254
+ dirs.push(wsDir);
255
+ }
256
+ }
257
+ }
258
+ else {
259
+ const wsDir = (0, node_path_1.join)(projectDir, pattern);
260
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(wsDir, "package.json")) ||
261
+ (0, node_fs_1.existsSync)((0, node_path_1.join)(wsDir, "deno.json")) ||
262
+ (0, node_fs_1.existsSync)((0, node_path_1.join)(wsDir, "deno.jsonc"))) {
263
+ dirs.push(wsDir);
264
+ }
265
+ }
266
+ }
267
+ return dirs;
268
+ }
269
+ function resolveWorkspaces(projectDir, preloaded) {
270
+ const pnpmPath = (0, node_path_1.join)(projectDir, "pnpm-workspace.yaml");
271
+ if ((0, node_fs_1.existsSync)(pnpmPath)) {
272
+ try {
273
+ const content = (0, node_fs_1.readFileSync)(pnpmPath, "utf-8");
274
+ const patterns = parsePnpmWorkspaceYaml(content);
275
+ if (patterns.length > 0) {
276
+ return expandWorkspacePatterns(projectDir, patterns).filter((d) => (0, node_path_1.resolve)(d) !== (0, node_path_1.resolve)(projectDir));
277
+ }
278
+ }
279
+ catch (_a) { }
280
+ }
281
+ const pkg = (preloaded === null || preloaded === void 0 ? void 0 : preloaded.pkg) !== undefined ? preloaded.pkg : readPackageJson(projectDir);
282
+ if (pkg) {
283
+ const ws = pkg.workspaces;
284
+ const patterns = Array.isArray(ws)
285
+ ? ws
286
+ : Array.isArray(ws === null || ws === void 0 ? void 0 : ws.packages)
287
+ ? ws.packages
288
+ : null;
289
+ if (patterns && patterns.length > 0) {
290
+ return expandWorkspacePatterns(projectDir, patterns).filter((d) => (0, node_path_1.resolve)(d) !== (0, node_path_1.resolve)(projectDir));
291
+ }
292
+ }
293
+ const denoJson = (preloaded === null || preloaded === void 0 ? void 0 : preloaded.denoJson) !== undefined ? preloaded.denoJson : readDenoJson(projectDir);
294
+ if (denoJson === null || denoJson === void 0 ? void 0 : denoJson.workspace) {
295
+ const members = Array.isArray(denoJson.workspace) ? denoJson.workspace : [];
296
+ if (members.length > 0) {
297
+ return expandWorkspacePatterns(projectDir, members).filter((d) => (0, node_path_1.resolve)(d) !== (0, node_path_1.resolve)(projectDir));
298
+ }
299
+ }
300
+ return [];
301
+ }
302
+ // ── Detection ─────────────────────────────────────────────────
303
+ function readGemfile(dir) {
304
+ const gemfilePath = (0, node_path_1.join)(dir, "Gemfile");
305
+ if (!(0, node_fs_1.existsSync)(gemfilePath))
306
+ return [];
307
+ try {
308
+ const content = (0, node_fs_1.readFileSync)(gemfilePath, "utf-8");
309
+ const gems = [];
310
+ const gemRegex = /^\s*gem\s+['"]([^'"]+)['"]/gm;
311
+ let match;
312
+ while ((match = gemRegex.exec(content)) !== null) {
313
+ gems.push(match[1]);
314
+ }
315
+ return gems;
316
+ }
317
+ catch (_a) {
318
+ return [];
319
+ }
320
+ }
321
+ function readPackageJson(dir) {
322
+ try {
323
+ return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, "package.json"), "utf-8"));
324
+ }
325
+ catch (_a) {
326
+ return null;
327
+ }
328
+ }
329
+ function readDenoJson(dir) {
330
+ for (const name of ["deno.json", "deno.jsonc"]) {
331
+ try {
332
+ return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, name), "utf-8"));
333
+ }
334
+ catch (_a) {
335
+ continue;
336
+ }
337
+ }
338
+ return null;
339
+ }
340
+ function getDenoImportNames(denoJson) {
341
+ if (!(denoJson === null || denoJson === void 0 ? void 0 : denoJson.imports))
342
+ return [];
343
+ return Object.values(denoJson.imports)
344
+ .filter((s) => typeof s === "string" && (s.startsWith("npm:") || s.startsWith("jsr:")))
345
+ .map((specifier) => {
346
+ const bare = specifier.replace(/^(?:npm|jsr):/, "");
347
+ if (bare.startsWith("@")) {
348
+ return bare.replace(/^(@[^/]+\/[^@]+).*$/, "$1");
349
+ }
350
+ return bare.replace(/@.*$/, "");
351
+ });
352
+ }
353
+ function getAllPackageNames(pkg) {
354
+ if (!pkg)
355
+ return [];
356
+ return [
357
+ ...Object.keys(pkg.dependencies || {}),
358
+ ...Object.keys(pkg.devDependencies || {}),
359
+ ];
360
+ }
361
+ function detectTechnologiesInDir(dir, { skipFrontendFiles = false, pkg: preloadedPkg, denoJson: preloadedDeno, } = {}) {
362
+ const pkg = preloadedPkg !== undefined ? preloadedPkg : readPackageJson(dir);
363
+ const allPackages = getAllPackageNames(pkg);
364
+ const deno = preloadedDeno !== undefined ? preloadedDeno : readDenoJson(dir);
365
+ const denoImports = getDenoImportNames(deno);
366
+ const allDepsSet = denoImports.length > 0 ? new Set([...allPackages, ...denoImports]) : new Set(allPackages);
367
+ const allDepsArray = denoImports.length > 0 ? [...allDepsSet] : allPackages;
368
+ let gemNames;
369
+ const detected = [];
370
+ const fileContentCache = new Map();
371
+ const existsCache = new Map();
372
+ function cachedRead(filePath) {
373
+ if (fileContentCache.has(filePath))
374
+ return fileContentCache.get(filePath);
375
+ let content = null;
376
+ try {
377
+ content = (0, node_fs_1.readFileSync)(filePath, "utf-8");
378
+ }
379
+ catch (_a) { }
380
+ fileContentCache.set(filePath, content);
381
+ if (content !== null)
382
+ existsCache.set(filePath, true);
383
+ return content;
384
+ }
385
+ function cachedExists(filePath) {
386
+ if (existsCache.has(filePath))
387
+ return existsCache.get(filePath);
388
+ const result = (0, node_fs_1.existsSync)(filePath);
389
+ existsCache.set(filePath, result);
390
+ return result;
391
+ }
392
+ for (const tech of skills_map_2.SKILLS_MAP) {
393
+ let found = false;
394
+ if (tech.detect.packages) {
395
+ found = tech.detect.packages.some((p) => allDepsSet.has(p));
396
+ }
397
+ if (!found && tech.detect.packagePatterns) {
398
+ found = tech.detect.packagePatterns.some((pattern) => allDepsArray.some((p) => pattern.test(p)));
399
+ }
400
+ if (!found && tech.detect.configFiles) {
401
+ found = tech.detect.configFiles.some((f) => cachedExists((0, node_path_1.join)(dir, f)));
402
+ }
403
+ if (!found && tech.detect.gems) {
404
+ if (gemNames === undefined)
405
+ gemNames = readGemfile(dir);
406
+ found = tech.detect.gems.some((g) => gemNames.includes(g));
407
+ }
408
+ if (!found && tech.detect.configFileContent) {
409
+ const configs = Array.isArray(tech.detect.configFileContent)
410
+ ? tech.detect.configFileContent
411
+ : [tech.detect.configFileContent];
412
+ for (const cfg of configs) {
413
+ const paths = resolveConfigFileContentPaths(dir, cfg);
414
+ const { patterns } = cfg;
415
+ for (const filePath of paths) {
416
+ const content = cachedRead(filePath);
417
+ if (content === null)
418
+ continue;
419
+ if (patterns.some((p) => content.includes(p))) {
420
+ found = true;
421
+ break;
422
+ }
423
+ }
424
+ if (found)
425
+ break;
426
+ }
427
+ }
428
+ if (found) {
429
+ detected.push(tech);
430
+ }
431
+ }
432
+ const isFrontendByPackages = allDepsArray.some((p) => skills_map_2.FRONTEND_PACKAGES.has(p));
433
+ const isFrontendByFiles = isFrontendByPackages || skipFrontendFiles ? false : hasWebFrontendFiles(dir);
434
+ return { detected, isFrontendByPackages, isFrontendByFiles };
435
+ }
436
+ function detectTechnologies(projectDir) {
437
+ const pkg = readPackageJson(projectDir);
438
+ const denoJson = readDenoJson(projectDir);
439
+ const root = detectTechnologiesInDir(projectDir, { pkg, denoJson });
440
+ const seenIds = new Map(root.detected.map((t) => [t.id, t]));
441
+ let isFrontend = root.isFrontendByPackages || root.isFrontendByFiles;
442
+ const workspaceDirs = resolveWorkspaces(projectDir, { pkg, denoJson });
443
+ for (const wsDir of workspaceDirs) {
444
+ const ws = detectTechnologiesInDir(wsDir, { skipFrontendFiles: isFrontend });
445
+ for (const tech of ws.detected) {
446
+ if (!seenIds.has(tech.id)) {
447
+ seenIds.set(tech.id, tech);
448
+ }
449
+ }
450
+ if (ws.isFrontendByPackages || ws.isFrontendByFiles) {
451
+ isFrontend = true;
452
+ }
453
+ }
454
+ const detected = [...seenIds.values()];
455
+ const detectedIds = detected.map((t) => t.id);
456
+ const combos = detectCombos(detectedIds);
457
+ return { detected, isFrontend, combos };
458
+ }
459
+ function detectCombos(detectedIds) {
460
+ const idSet = detectedIds instanceof Set ? detectedIds : new Set(detectedIds);
461
+ return skills_map_2.COMBO_SKILLS_MAP.filter((combo) => combo.requires.every((id) => idSet.has(id)));
462
+ }
463
+ // ── Agent Detection ─────────────────────────────────────────
464
+ function detectAgents(home = (0, node_os_1.homedir)()) {
465
+ const agents = ["universal"];
466
+ for (const [folder, agentName] of AGENT_FOLDER_ENTRIES) {
467
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home, folder, "skills"))) {
468
+ agents.push(agentName);
469
+ }
470
+ }
471
+ return agents;
472
+ }
473
+ function parseSkillPath(skill) {
474
+ if (skill.startsWith("http")) {
475
+ return { repo: skill, skillName: "", full: skill };
476
+ }
477
+ const parts = skill.split("/");
478
+ return {
479
+ repo: parts.slice(0, 2).join("/"),
480
+ skillName: parts.slice(2).join("/"),
481
+ full: skill,
482
+ };
483
+ }
484
+ // ── Installed Skills Detection ───────────────────────────────
485
+ function getInstalledSkillNames(projectDir) {
486
+ try {
487
+ const lock = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(projectDir, "skills-lock.json"), "utf-8"));
488
+ if ((lock === null || lock === void 0 ? void 0 : lock.skills) && typeof lock.skills === "object") {
489
+ return new Set(Object.keys(lock.skills));
490
+ }
491
+ }
492
+ catch (_a) { }
493
+ try {
494
+ const entries = (0, node_fs_1.readdirSync)((0, node_path_1.join)(projectDir, ".agents", "skills"), { withFileTypes: true });
495
+ return new Set(entries.filter((e) => e.isDirectory()).map((e) => e.name));
496
+ }
497
+ catch (_b) { }
498
+ return new Set();
499
+ }
500
+ function collectSkills({ detected, isFrontend, combos = [], installedNames = null, }) {
501
+ const skillMap = new Map();
502
+ const skills = [];
503
+ function addSkill(skill, source) {
504
+ const existing = skillMap.get(skill);
505
+ if (!existing) {
506
+ const installed = installedNames
507
+ ? installedNames.has(parseSkillPath(skill).skillName)
508
+ : false;
509
+ const entry = { skill, sources: [source], installed };
510
+ skillMap.set(skill, entry);
511
+ skills.push(entry);
512
+ }
513
+ else if (!existing.sources.includes(source)) {
514
+ existing.sources.push(source);
515
+ }
516
+ }
517
+ for (const tech of detected) {
518
+ for (const skill of tech.skills) {
519
+ addSkill(skill, tech.name);
520
+ }
521
+ }
522
+ for (const combo of combos) {
523
+ for (const skill of combo.skills) {
524
+ addSkill(skill, combo.name);
525
+ }
526
+ }
527
+ if (isFrontend) {
528
+ for (const skill of skills_map_2.FRONTEND_BONUS_SKILLS) {
529
+ addSkill(skill, "Frontend");
530
+ }
531
+ }
532
+ return skills;
533
+ }