javi-forge 1.6.0 → 1.7.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 (322) hide show
  1. package/README.md +45 -1
  2. package/ci-local/README.md +56 -11
  3. package/ci-local/ci-local.ps1 +445 -0
  4. package/ci-local/ci-local.sh +52 -9
  5. package/ci-local/docker/python.Dockerfile +7 -0
  6. package/ci-local/hooks/commit-msg +120 -44
  7. package/ci-local/hooks/commit-msg.test.sh +286 -0
  8. package/ci-local/hooks/pre-commit +9 -1
  9. package/ci-local/hooks/pre-push +13 -2
  10. package/ci-local/install.ps1 +367 -0
  11. package/ci-local/install.sh +151 -5
  12. package/ci-local/uninstall.ps1 +85 -0
  13. package/ci-local/uninstall.sh +95 -0
  14. package/dist/cli/dispatch/ci.d.ts +12 -0
  15. package/dist/cli/dispatch/ci.js +38 -0
  16. package/dist/cli/dispatch/security.d.ts +11 -0
  17. package/dist/cli/dispatch/security.js +68 -0
  18. package/dist/cli/dispatch/simple-renderers.d.ts +16 -0
  19. package/dist/cli/dispatch/simple-renderers.js +65 -0
  20. package/dist/cli/dispatch/skill-publish.d.ts +15 -0
  21. package/dist/cli/dispatch/skill-publish.js +44 -0
  22. package/dist/cli/dispatch/skills-cmd.d.ts +13 -0
  23. package/dist/cli/dispatch/skills-cmd.js +93 -0
  24. package/dist/cli/dispatch/tdd.d.ts +11 -0
  25. package/dist/cli/dispatch/tdd.js +45 -0
  26. package/dist/cli/dispatch/types.d.ts +29 -0
  27. package/dist/cli/dispatch/types.js +2 -0
  28. package/dist/cli/dispatch/workflow.d.ts +11 -0
  29. package/dist/cli/dispatch/workflow.js +67 -0
  30. package/dist/cli/help.d.ts +127 -0
  31. package/dist/cli/help.js +138 -0
  32. package/dist/cli/runtime.d.ts +16 -0
  33. package/dist/cli/runtime.js +38 -0
  34. package/dist/cli/validators.d.ts +17 -0
  35. package/dist/cli/validators.js +35 -0
  36. package/dist/commands/analyze.d.ts +1 -1
  37. package/dist/commands/analyze.js +14 -16
  38. package/dist/commands/ci.d.ts +50 -3
  39. package/dist/commands/ci.js +537 -182
  40. package/dist/commands/doctor.d.ts +2 -2
  41. package/dist/commands/doctor.js +112 -62
  42. package/dist/commands/init/report.d.ts +13 -0
  43. package/dist/commands/init/report.js +13 -0
  44. package/dist/commands/init/steps/agent-skills.d.ts +13 -0
  45. package/dist/commands/init/steps/agent-skills.js +45 -0
  46. package/dist/commands/init/steps/ai-sync.d.ts +15 -0
  47. package/dist/commands/init/steps/ai-sync.js +62 -0
  48. package/dist/commands/init/steps/ci.d.ts +24 -0
  49. package/dist/commands/init/steps/ci.js +74 -0
  50. package/dist/commands/init/steps/claude-md.d.ts +14 -0
  51. package/dist/commands/init/steps/claude-md.js +54 -0
  52. package/dist/commands/init/steps/code-graph.d.ts +16 -0
  53. package/dist/commands/init/steps/code-graph.js +68 -0
  54. package/dist/commands/init/steps/context-dir.d.ts +13 -0
  55. package/dist/commands/init/steps/context-dir.js +47 -0
  56. package/dist/commands/init/steps/docker-deploy.d.ts +16 -0
  57. package/dist/commands/init/steps/docker-deploy.js +60 -0
  58. package/dist/commands/init/steps/ghagga.d.ts +15 -0
  59. package/dist/commands/init/steps/ghagga.js +58 -0
  60. package/dist/commands/init/steps/git.d.ts +25 -0
  61. package/dist/commands/init/steps/git.js +81 -0
  62. package/dist/commands/init/steps/gitignore.d.ts +13 -0
  63. package/dist/commands/init/steps/gitignore.js +39 -0
  64. package/dist/commands/init/steps/local-ai.d.ts +14 -0
  65. package/dist/commands/init/steps/local-ai.js +53 -0
  66. package/dist/commands/init/steps/manifest.d.ts +13 -0
  67. package/dist/commands/init/steps/manifest.js +58 -0
  68. package/dist/commands/init/steps/memory.d.ts +15 -0
  69. package/dist/commands/init/steps/memory.js +60 -0
  70. package/dist/commands/init/steps/mock.d.ts +13 -0
  71. package/dist/commands/init/steps/mock.js +64 -0
  72. package/dist/commands/init/steps/sdd.d.ts +12 -0
  73. package/dist/commands/init/steps/sdd.js +40 -0
  74. package/dist/commands/init/steps/security.d.ts +28 -0
  75. package/dist/commands/init/steps/security.js +103 -0
  76. package/dist/commands/init/types.d.ts +30 -0
  77. package/dist/commands/init/types.js +2 -0
  78. package/dist/commands/init.d.ts +5 -4
  79. package/dist/commands/init.js +42 -387
  80. package/dist/commands/llmstxt.d.ts +1 -1
  81. package/dist/commands/llmstxt.js +36 -34
  82. package/dist/commands/plugin.d.ts +10 -1
  83. package/dist/commands/plugin.js +92 -47
  84. package/dist/commands/security.d.ts +11 -5
  85. package/dist/commands/security.js +236 -77
  86. package/dist/commands/skills/analysis.d.ts +19 -0
  87. package/dist/commands/skills/analysis.js +211 -0
  88. package/dist/commands/skills/benchmark.d.ts +6 -0
  89. package/dist/commands/skills/benchmark.js +82 -0
  90. package/dist/commands/skills/constants.d.ts +10 -0
  91. package/dist/commands/skills/constants.js +27 -0
  92. package/dist/commands/skills/directives.d.ts +21 -0
  93. package/dist/commands/skills/directives.js +101 -0
  94. package/dist/commands/skills/parsing.d.ts +16 -0
  95. package/dist/commands/skills/parsing.js +108 -0
  96. package/dist/commands/skills/rules.d.ts +5 -0
  97. package/dist/commands/skills/rules.js +32 -0
  98. package/dist/commands/skills/scoring.d.ts +47 -0
  99. package/dist/commands/skills/scoring.js +306 -0
  100. package/dist/commands/skills.d.ts +8 -69
  101. package/dist/commands/skills.js +9 -490
  102. package/dist/commands/tdd-pipeline.d.ts +17 -0
  103. package/dist/commands/tdd-pipeline.js +144 -0
  104. package/dist/commands/tdd.d.ts +1 -1
  105. package/dist/commands/tdd.js +21 -18
  106. package/dist/commands/workflow.d.ts +23 -0
  107. package/dist/commands/workflow.js +116 -0
  108. package/dist/constants.d.ts +15 -1
  109. package/dist/constants.js +161 -122
  110. package/dist/index.js +43 -280
  111. package/dist/lib/agent-skills.d.ts +36 -1
  112. package/dist/lib/agent-skills.js +168 -19
  113. package/dist/lib/atlassian-mcp.d.ts +42 -0
  114. package/dist/lib/atlassian-mcp.js +98 -0
  115. package/dist/lib/auto-skill-install.d.ts +37 -0
  116. package/dist/lib/auto-skill-install.js +91 -0
  117. package/dist/lib/auto-wire.d.ts +20 -0
  118. package/dist/lib/auto-wire.js +240 -0
  119. package/dist/lib/ci-config.d.ts +65 -0
  120. package/dist/lib/ci-config.js +297 -0
  121. package/dist/lib/claudemd.d.ts +13 -1
  122. package/dist/lib/claudemd.js +174 -24
  123. package/dist/lib/codex-export.d.ts +1 -1
  124. package/dist/lib/codex-export.js +26 -32
  125. package/dist/lib/common.d.ts +1 -1
  126. package/dist/lib/common.js +52 -44
  127. package/dist/lib/context.d.ts +17 -2
  128. package/dist/lib/context.js +142 -13
  129. package/dist/lib/crash-recovery.d.ts +34 -0
  130. package/dist/lib/crash-recovery.js +123 -0
  131. package/dist/lib/docker.d.ts +23 -2
  132. package/dist/lib/docker.js +168 -131
  133. package/dist/lib/exec.d.ts +10 -0
  134. package/dist/lib/exec.js +11 -0
  135. package/dist/lib/frontmatter.d.ts +1 -1
  136. package/dist/lib/frontmatter.js +29 -15
  137. package/dist/lib/harness-audit.d.ts +35 -0
  138. package/dist/lib/harness-audit.js +277 -0
  139. package/dist/lib/parallel-batch.d.ts +42 -0
  140. package/dist/lib/parallel-batch.js +88 -0
  141. package/dist/lib/plugin.d.ts +9 -3
  142. package/dist/lib/plugin.js +127 -70
  143. package/dist/lib/secret-scanner.d.ts +30 -0
  144. package/dist/lib/secret-scanner.js +274 -0
  145. package/dist/lib/security-analysis.d.ts +74 -0
  146. package/dist/lib/security-analysis.js +489 -0
  147. package/dist/lib/skill-publish.d.ts +40 -0
  148. package/dist/lib/skill-publish.js +164 -0
  149. package/dist/lib/skill-scanner.d.ts +63 -0
  150. package/dist/lib/skill-scanner.js +383 -0
  151. package/dist/lib/stack-detector.d.ts +38 -0
  152. package/dist/lib/stack-detector.js +207 -0
  153. package/dist/lib/supply-chain.d.ts +23 -0
  154. package/dist/lib/supply-chain.js +126 -0
  155. package/dist/lib/team-presets.d.ts +53 -0
  156. package/dist/lib/team-presets.js +201 -0
  157. package/dist/lib/template.d.ts +16 -1
  158. package/dist/lib/template.js +46 -17
  159. package/dist/lib/workflow/discovery.d.ts +27 -0
  160. package/dist/lib/workflow/discovery.js +85 -0
  161. package/dist/lib/workflow/index.d.ts +5 -0
  162. package/dist/lib/workflow/index.js +5 -0
  163. package/dist/lib/workflow/parser.d.ts +16 -0
  164. package/dist/lib/workflow/parser.js +198 -0
  165. package/dist/lib/workflow/renderer.d.ts +9 -0
  166. package/dist/lib/workflow/renderer.js +152 -0
  167. package/dist/lib/workflow/validator.d.ts +10 -0
  168. package/dist/lib/workflow/validator.js +189 -0
  169. package/dist/tasks/index.d.ts +4 -0
  170. package/dist/tasks/index.js +4 -0
  171. package/dist/tasks/scaffold-tasks.d.ts +3 -0
  172. package/dist/tasks/scaffold-tasks.js +14 -0
  173. package/dist/tasks/task-id.d.ts +30 -0
  174. package/dist/tasks/task-id.js +59 -0
  175. package/dist/tasks/task-tracker.d.ts +15 -0
  176. package/dist/tasks/task-tracker.js +81 -0
  177. package/dist/types/index.d.ts +134 -6
  178. package/dist/types/index.js +11 -1
  179. package/dist/ui/AnalyzeUI.d.ts +1 -1
  180. package/dist/ui/AnalyzeUI.js +38 -39
  181. package/dist/ui/App.d.ts +5 -3
  182. package/dist/ui/App.js +86 -46
  183. package/dist/ui/AutoSkills.d.ts +9 -0
  184. package/dist/ui/AutoSkills.js +124 -0
  185. package/dist/ui/CI.d.ts +2 -2
  186. package/dist/ui/CI.js +24 -26
  187. package/dist/ui/CIContext.d.ts +1 -1
  188. package/dist/ui/CIContext.js +2 -2
  189. package/dist/ui/CISelector.d.ts +2 -2
  190. package/dist/ui/CISelector.js +23 -15
  191. package/dist/ui/Doctor.d.ts +1 -1
  192. package/dist/ui/Doctor.js +35 -29
  193. package/dist/ui/Header.d.ts +1 -1
  194. package/dist/ui/Header.js +14 -14
  195. package/dist/ui/HookProfileSelector.d.ts +9 -0
  196. package/dist/ui/HookProfileSelector.js +54 -0
  197. package/dist/ui/LlmsTxt.d.ts +1 -1
  198. package/dist/ui/LlmsTxt.js +31 -22
  199. package/dist/ui/MemorySelector.d.ts +2 -2
  200. package/dist/ui/MemorySelector.js +28 -16
  201. package/dist/ui/NameInput.d.ts +1 -1
  202. package/dist/ui/NameInput.js +21 -21
  203. package/dist/ui/OptionSelector.d.ts +6 -2
  204. package/dist/ui/OptionSelector.js +83 -32
  205. package/dist/ui/Plugin.d.ts +4 -3
  206. package/dist/ui/Plugin.js +78 -35
  207. package/dist/ui/Progress.d.ts +3 -3
  208. package/dist/ui/Progress.js +23 -22
  209. package/dist/ui/Skills.d.ts +2 -2
  210. package/dist/ui/Skills.js +61 -32
  211. package/dist/ui/StackSelector.d.ts +2 -2
  212. package/dist/ui/StackSelector.js +27 -17
  213. package/dist/ui/Summary.d.ts +3 -3
  214. package/dist/ui/Summary.js +60 -50
  215. package/dist/ui/Welcome.d.ts +1 -1
  216. package/dist/ui/Welcome.js +15 -16
  217. package/dist/ui/theme.d.ts +1 -1
  218. package/dist/ui/theme.js +6 -6
  219. package/lib/common.psm1 +167 -0
  220. package/lib/common.sh +30 -0
  221. package/package.json +46 -24
  222. package/templates/common/atlassian/mcp-atlassian-snippet.json +16 -0
  223. package/templates/common/repoforge/mcp-repoforge-snippet.json +11 -0
  224. package/templates/common/repoforge/repoforge.yaml +34 -0
  225. package/templates/github/deploy-docker-zero-downtime.yml +140 -0
  226. package/templates/github/repoforge-graph.yml +45 -0
  227. package/templates/gitlab/deploy-docker-zero-downtime.yml +57 -0
  228. package/templates/local-ai/.env.example +17 -0
  229. package/templates/local-ai/docker-compose.yml +95 -0
  230. package/templates/security-hooks/claude-settings-security.json +30 -0
  231. package/templates/security-hooks/commit-msg-signing +29 -0
  232. package/templates/security-hooks/pre-commit-permissions +74 -0
  233. package/templates/security-hooks/pre-commit-secrets +74 -0
  234. package/templates/security-hooks/pre-push-branch-protection +62 -0
  235. package/templates/security-hooks/pre-push-deps +83 -0
  236. package/templates/security-hooks/pre-push-signing +67 -0
  237. package/templates/woodpecker/deploy-docker-zero-downtime.yml +50 -0
  238. package/templates/workflows/ci-pipeline.dot +15 -0
  239. package/templates/workflows/feature-flow.dot +21 -0
  240. package/templates/workflows/release.dot +16 -0
  241. package/dist/__integration__/helpers.d.ts +0 -20
  242. package/dist/__integration__/helpers.d.ts.map +0 -1
  243. package/dist/__integration__/helpers.js +0 -31
  244. package/dist/__integration__/helpers.js.map +0 -1
  245. package/dist/commands/analyze.d.ts.map +0 -1
  246. package/dist/commands/analyze.js.map +0 -1
  247. package/dist/commands/ci.d.ts.map +0 -1
  248. package/dist/commands/ci.js.map +0 -1
  249. package/dist/commands/doctor.d.ts.map +0 -1
  250. package/dist/commands/doctor.js.map +0 -1
  251. package/dist/commands/init.d.ts.map +0 -1
  252. package/dist/commands/init.js.map +0 -1
  253. package/dist/commands/llmstxt.d.ts.map +0 -1
  254. package/dist/commands/llmstxt.js.map +0 -1
  255. package/dist/commands/plugin.d.ts.map +0 -1
  256. package/dist/commands/plugin.js.map +0 -1
  257. package/dist/commands/security.d.ts.map +0 -1
  258. package/dist/commands/security.js.map +0 -1
  259. package/dist/commands/skills.d.ts.map +0 -1
  260. package/dist/commands/skills.js.map +0 -1
  261. package/dist/commands/tdd.d.ts.map +0 -1
  262. package/dist/commands/tdd.js.map +0 -1
  263. package/dist/constants.d.ts.map +0 -1
  264. package/dist/constants.js.map +0 -1
  265. package/dist/index.d.ts.map +0 -1
  266. package/dist/index.js.map +0 -1
  267. package/dist/lib/agent-skills.d.ts.map +0 -1
  268. package/dist/lib/agent-skills.js.map +0 -1
  269. package/dist/lib/claudemd.d.ts.map +0 -1
  270. package/dist/lib/claudemd.js.map +0 -1
  271. package/dist/lib/codex-export.d.ts.map +0 -1
  272. package/dist/lib/codex-export.js.map +0 -1
  273. package/dist/lib/common.d.ts.map +0 -1
  274. package/dist/lib/common.js.map +0 -1
  275. package/dist/lib/context.d.ts.map +0 -1
  276. package/dist/lib/context.js.map +0 -1
  277. package/dist/lib/docker.d.ts.map +0 -1
  278. package/dist/lib/docker.js.map +0 -1
  279. package/dist/lib/frontmatter.d.ts.map +0 -1
  280. package/dist/lib/frontmatter.js.map +0 -1
  281. package/dist/lib/plugin.d.ts.map +0 -1
  282. package/dist/lib/plugin.js.map +0 -1
  283. package/dist/lib/template.d.ts.map +0 -1
  284. package/dist/lib/template.js.map +0 -1
  285. package/dist/types/index.d.ts.map +0 -1
  286. package/dist/types/index.js.map +0 -1
  287. package/dist/ui/AnalyzeUI.d.ts.map +0 -1
  288. package/dist/ui/AnalyzeUI.js.map +0 -1
  289. package/dist/ui/App.d.ts.map +0 -1
  290. package/dist/ui/App.js.map +0 -1
  291. package/dist/ui/CI.d.ts.map +0 -1
  292. package/dist/ui/CI.js.map +0 -1
  293. package/dist/ui/CIContext.d.ts.map +0 -1
  294. package/dist/ui/CIContext.js.map +0 -1
  295. package/dist/ui/CISelector.d.ts.map +0 -1
  296. package/dist/ui/CISelector.js.map +0 -1
  297. package/dist/ui/Doctor.d.ts.map +0 -1
  298. package/dist/ui/Doctor.js.map +0 -1
  299. package/dist/ui/Header.d.ts.map +0 -1
  300. package/dist/ui/Header.js.map +0 -1
  301. package/dist/ui/LlmsTxt.d.ts.map +0 -1
  302. package/dist/ui/LlmsTxt.js.map +0 -1
  303. package/dist/ui/MemorySelector.d.ts.map +0 -1
  304. package/dist/ui/MemorySelector.js.map +0 -1
  305. package/dist/ui/NameInput.d.ts.map +0 -1
  306. package/dist/ui/NameInput.js.map +0 -1
  307. package/dist/ui/OptionSelector.d.ts.map +0 -1
  308. package/dist/ui/OptionSelector.js.map +0 -1
  309. package/dist/ui/Plugin.d.ts.map +0 -1
  310. package/dist/ui/Plugin.js.map +0 -1
  311. package/dist/ui/Progress.d.ts.map +0 -1
  312. package/dist/ui/Progress.js.map +0 -1
  313. package/dist/ui/Skills.d.ts.map +0 -1
  314. package/dist/ui/Skills.js.map +0 -1
  315. package/dist/ui/StackSelector.d.ts.map +0 -1
  316. package/dist/ui/StackSelector.js.map +0 -1
  317. package/dist/ui/Summary.d.ts.map +0 -1
  318. package/dist/ui/Summary.js.map +0 -1
  319. package/dist/ui/Welcome.d.ts.map +0 -1
  320. package/dist/ui/Welcome.js.map +0 -1
  321. package/dist/ui/theme.d.ts.map +0 -1
  322. package/dist/ui/theme.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,306 +1,69 @@
1
1
  #!/usr/bin/env node
2
- import path from 'path';
3
- import React from 'react';
4
- import { render } from 'ink';
5
- import { PassThrough } from 'node:stream';
6
- import meow from 'meow';
7
- import updateNotifier from 'update-notifier';
8
- import { createRequire } from 'module';
9
- import App from './ui/App.js';
10
- import Doctor from './ui/Doctor.js';
11
- import AnalyzeUI from './ui/AnalyzeUI.js';
12
- import Plugin from './ui/Plugin.js';
13
- import Skills from './ui/Skills.js';
14
- import LlmsTxt from './ui/LlmsTxt.js';
15
- import CI from './ui/CI.js';
16
- import { CIProvider as CIContextProvider } from './ui/CIContext.js';
2
+ import { createRequire } from "node:module";
3
+ import meow from "meow";
4
+ import { handleCi } from "./cli/dispatch/ci.js";
5
+ import { handleSecurity } from "./cli/dispatch/security.js";
6
+ import { handleAnalyze, handleDoctor, handleInitDefault, handleLlmsTxt, handlePlugin, } from "./cli/dispatch/simple-renderers.js";
7
+ import { handleSkillPublish } from "./cli/dispatch/skill-publish.js";
8
+ import { handleSkillsCmd } from "./cli/dispatch/skills-cmd.js";
9
+ import { handleTdd } from "./cli/dispatch/tdd.js";
10
+ import { handleWorkflow } from "./cli/dispatch/workflow.js";
11
+ import { FLAGS_SCHEMA, HELP_TEXT } from "./cli/help.js";
12
+ import { createInkStdin, detectCI, setupUpdateNotifier, } from "./cli/runtime.js";
17
13
  // Check for updates in background (non-blocking, cached 24h)
18
14
  const _require = createRequire(import.meta.url);
19
- const pkg = _require('../package.json');
20
- updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 * 24 }).notify();
21
- const cli = meow(`
22
- Usage
23
- $ javi-forge [command] [options]
24
-
25
- Commands
26
- init Bootstrap a new project (default)
27
- ci Run CI simulation (lint + compile + test + security + ghagga)
28
- tdd init Install TDD-enforcing pre-commit hook (auto-detects stack)
29
- analyze Run repoforge skills analysis
30
- doctor Show health report
31
- plugin add Install a plugin from GitHub (org/repo)
32
- plugin remove Remove an installed plugin
33
- plugin list List installed plugins
34
- plugin search Search the plugin registry
35
- plugin validate Validate a local plugin directory
36
- plugin sync Auto-detect and wire installed plugins
37
- plugin export Export plugin to Agent Skills spec format (skills.json)
38
- plugin import Import an Agent Skills spec package as a javi-forge plugin
39
- skills doctor Show skills health report (add --deep for conflict detection)
40
- skills budget Show token cost of loaded skills (add -b N for custom budget)
41
- skills score Score a skill on quality dimensions (completeness, clarity, testability, token-efficiency)
42
- skills benchmark Benchmark a skill with structural quality checks
43
- security baseline Create security baseline from current audit findings
44
- security check Check for regressions against baseline (exits non-zero if found)
45
- security update Re-snapshot baseline (acknowledge current vulns)
46
- llms-txt Generate AI-friendly llms.txt for current project
47
-
48
- Options
49
- --dry-run Preview changes without writing files
50
- --stack Project stack (node, python, go, rust, java-gradle, java-maven, elixir)
51
- --ci CI provider (github, gitlab, woodpecker)
52
- --memory Memory module (engram, obsidian-brain, memory-simple, none)
53
- --project-name Project name (skips name prompt)
54
- --ghagga Enable GHAGGA review system
55
- --mock Enable mock-first mode (no real API keys needed)
56
- --batch Non-interactive mode (auto-proceed, no keyboard input)
57
- --deep Enable deep analysis (conflict + duplicate detection)
58
- --budget, -b Token budget limit for skills (default: 8000)
59
- --skills-dir Custom skills directory path
60
- --version Show version
61
- --help Show this help
62
-
63
- CI options (javi-forge ci)
64
- --quick Lint + compile only (fast, for pre-commit)
65
- --shell Open interactive shell in CI container
66
- --detect Show detected stack and exit
67
- --no-docker Run commands natively (no Docker)
68
- --no-ci-ghagga Skip GHAGGA review
69
- --no-security Skip Semgrep security scan
70
- --timeout N Per-step timeout in seconds (default: 600)
71
-
72
- CI hooks (javi-forge ci init)
73
- Install git hooks that call javi-forge ci.
74
- No files copied — hooks reference the global CLI.
75
-
76
- Examples
77
- $ javi-forge
78
- $ javi-forge init --dry-run
79
- $ javi-forge init --stack node --ci github
80
- $ javi-forge ci
81
- $ javi-forge ci init
82
- $ javi-forge tdd init
83
- $ javi-forge ci --quick
84
- $ javi-forge ci --no-ci-ghagga --no-security
85
- $ javi-forge ci --no-docker
86
- $ javi-forge ci --shell
87
- $ javi-forge analyze
88
- $ javi-forge doctor
89
- $ javi-forge plugin add mapbox/agent-skills
90
- $ javi-forge plugin list
91
- `, {
15
+ const pkg = _require("../package.json");
16
+ setupUpdateNotifier(pkg);
17
+ const cli = meow(HELP_TEXT, {
92
18
  importMeta: import.meta,
93
- flags: {
94
- dryRun: { type: 'boolean', default: false },
95
- stack: { type: 'string', default: '' },
96
- ci: { type: 'string', default: '' },
97
- memory: { type: 'string', default: '' },
98
- projectName: { type: 'string', default: '' },
99
- ghagga: { type: 'boolean', default: false },
100
- mock: { type: 'boolean', default: false },
101
- batch: { type: 'boolean', default: false },
102
- // CI flags
103
- quick: { type: 'boolean', default: false },
104
- shell: { type: 'boolean', default: false },
105
- detect: { type: 'boolean', default: false },
106
- docker: { type: 'boolean', default: true },
107
- ciGhagga: { type: 'boolean', default: true },
108
- security: { type: 'boolean', default: true },
109
- timeout: { type: 'number', default: 600 },
110
- // Skills flags
111
- deep: { type: 'boolean', default: false },
112
- budget: { type: 'number', shortFlag: 'b', default: 8000 },
113
- skillsDir: { type: 'string', default: '' },
114
- }
19
+ flags: FLAGS_SCHEMA,
115
20
  });
116
- const subcommand = cli.input[0] ?? 'init';
117
- const VALID_STACKS = ['node', 'python', 'go', 'rust', 'java-gradle', 'java-maven', 'elixir'];
118
- const VALID_CI = ['github', 'gitlab', 'woodpecker'];
119
- const VALID_MEMORY = ['engram', 'obsidian-brain', 'memory-simple', 'none'];
120
- const isCI = cli.flags.batch || process.env['CI'] === '1' || process.env['CI'] === 'true';
121
- // When stdin doesn't support raw mode (pipes, subprocesses, CI), provide a fake
122
- // stdin stream so Ink doesn't crash trying to enable raw mode on a non-TTY pipe.
123
- const isTTY = process.stdin.isTTY === true;
124
- const fakeStdin = new PassThrough();
125
- Object.defineProperty(fakeStdin, 'isTTY', { value: false });
126
- const inkStdin = isTTY ? process.stdin : fakeStdin;
21
+ const subcommand = cli.input[0] ?? "init";
22
+ const isCI = detectCI(cli.flags);
23
+ const inkStdin = createInkStdin();
127
24
  switch (subcommand) {
128
- case 'tdd': {
129
- if (cli.input[1] === 'init') {
130
- const { installTddHooks } = await import('./commands/tdd.js');
131
- const { installed, errors } = await installTddHooks(process.cwd());
132
- if (installed.length > 0) {
133
- console.log(`\u2713 Installed TDD hooks: ${installed.join(', ')}`);
134
- console.log(' Pre-commit hook enforces tests must pass before commit');
135
- }
136
- for (const err of errors) {
137
- console.error(`\u2717 ${err}`);
138
- }
139
- process.exit(errors.length > 0 ? 1 : 0);
140
- }
141
- else {
142
- console.error('Usage: javi-forge tdd init');
143
- console.error(' init Install TDD-enforcing pre-commit hook');
144
- process.exit(1);
145
- }
25
+ case "tdd": {
26
+ await handleTdd(cli);
27
+ break;
28
+ }
29
+ case "ci": {
30
+ await handleCi(cli, { inkStdin, isCI });
31
+ break;
32
+ }
33
+ case "doctor": {
34
+ handleDoctor(cli, { inkStdin, isCI });
146
35
  break;
147
36
  }
148
- case 'ci': {
149
- // Sub-command: javi-forge ci init → install git hooks
150
- if (cli.input[1] === 'init') {
151
- const { installCIHooks } = await import('./commands/ci.js');
152
- const { installed, errors } = await installCIHooks(process.cwd());
153
- if (installed.length > 0) {
154
- console.log(`✓ Installed git hooks: ${installed.join(', ')}`);
155
- console.log(' Hooks call javi-forge ci (with npx fallback)');
156
- }
157
- for (const err of errors) {
158
- console.error(`✗ ${err}`);
159
- }
160
- process.exit(errors.length > 0 ? 1 : 0);
161
- break;
162
- }
163
- const ciMode = cli.flags.detect ? 'detect'
164
- : cli.flags.shell ? 'shell'
165
- : cli.flags.quick ? 'quick'
166
- : 'full';
167
- render(React.createElement(CIContextProvider, { isCI: true },
168
- React.createElement(CI, { projectDir: process.cwd(), mode: ciMode, noDocker: !cli.flags.docker, noGhagga: !cli.flags.ciGhagga, noSecurity: !cli.flags.security, timeout: cli.flags.timeout })), { stdin: inkStdin });
37
+ case "analyze": {
38
+ handleAnalyze(cli, { inkStdin, isCI });
169
39
  break;
170
40
  }
171
- case 'doctor': {
172
- render(React.createElement(CIContextProvider, { isCI: isCI },
173
- React.createElement(Doctor, null)), { stdin: inkStdin });
41
+ case "workflow": {
42
+ await handleWorkflow(cli);
174
43
  break;
175
44
  }
176
- case 'analyze': {
177
- render(React.createElement(CIContextProvider, { isCI: isCI },
178
- React.createElement(AnalyzeUI, { dryRun: cli.flags.dryRun })), { stdin: inkStdin });
45
+ case "llms-txt": {
46
+ handleLlmsTxt(cli, { inkStdin, isCI });
179
47
  break;
180
48
  }
181
- case 'llms-txt': {
182
- render(React.createElement(CIContextProvider, { isCI: isCI },
183
- React.createElement(LlmsTxt, { projectDir: process.cwd(), dryRun: cli.flags.dryRun })), { stdin: inkStdin });
49
+ case "plugin": {
50
+ handlePlugin(cli, { inkStdin, isCI });
184
51
  break;
185
52
  }
186
- case 'plugin': {
187
- const pluginAction = cli.input[1];
188
- const VALID_PLUGIN_ACTIONS = ['add', 'remove', 'list', 'search', 'validate', 'sync', 'export', 'import'];
189
- const action = pluginAction && VALID_PLUGIN_ACTIONS.includes(pluginAction) ? pluginAction : 'list';
190
- const target = cli.input[2];
191
- render(React.createElement(CIContextProvider, { isCI: isCI },
192
- React.createElement(Plugin, { action: action, target: target, dryRun: cli.flags.dryRun })), { stdin: inkStdin });
53
+ case "skills": {
54
+ await handleSkillsCmd(cli, { inkStdin, isCI });
193
55
  break;
194
56
  }
195
- case 'skills': {
196
- const skillsAction = cli.input[1];
197
- const VALID_SKILLS_ACTIONS = ['doctor', 'budget', 'score', 'benchmark'];
198
- if (!skillsAction || !VALID_SKILLS_ACTIONS.includes(skillsAction)) {
199
- console.error('Usage: javi-forge skills <doctor|budget|score|benchmark>');
200
- console.error(' doctor Show skills health report (add --deep for conflict detection)');
201
- console.error(' budget Show token cost of loaded skills (add -b N for custom budget)');
202
- console.error(' score Score a skill on quality dimensions (0-100)');
203
- console.error(' benchmark Benchmark a skill with structural quality checks');
204
- process.exit(1);
205
- break;
206
- }
207
- // Score and benchmark are non-interactive CLI commands
208
- if (skillsAction === 'score' || skillsAction === 'benchmark') {
209
- const targetSkill = cli.input[2];
210
- if (!targetSkill) {
211
- console.error(`Usage: javi-forge skills ${skillsAction} <skill-name>`);
212
- process.exit(1);
213
- break;
214
- }
215
- const skillsDir = cli.flags.skillsDir || path.join(process.env['HOME'] ?? '~', '.claude', 'skills');
216
- const skillPath = path.join(skillsDir, targetSkill, 'SKILL.md');
217
- if (skillsAction === 'score') {
218
- const { scoreSkill } = await import('./commands/skills.js');
219
- const result = await scoreSkill(skillPath, cli.flags.budget);
220
- if (!result) {
221
- console.error(`\u2717 Skill not found: ${skillPath}`);
222
- process.exit(1);
223
- break;
224
- }
225
- console.log(`\nSkill: ${result.skillName}`);
226
- console.log(` Completeness: ${result.completeness}/100`);
227
- console.log(` Clarity: ${result.clarity}/100`);
228
- console.log(` Testability: ${result.testability}/100`);
229
- console.log(` Token Efficiency: ${result.tokenEfficiency}/100`);
230
- console.log(` Overall: ${result.overall}/100`);
231
- console.log(` Threshold: ${result.threshold}`);
232
- console.log(` Status: ${result.passing ? '\u2713 PASSING' : '\u2717 FAILING'}`);
233
- process.exit(result.passing ? 0 : 1);
234
- }
235
- else {
236
- const { benchmarkSkill } = await import('./commands/skills.js');
237
- const result = await benchmarkSkill(skillPath);
238
- if (!result) {
239
- console.error(`\u2717 Skill not found: ${skillPath}`);
240
- process.exit(1);
241
- break;
242
- }
243
- console.log(`\nBenchmark: ${result.skillName}`);
244
- for (const check of result.checks) {
245
- const icon = check.passed ? '\u2713' : '\u2717';
246
- console.log(` ${icon} ${check.name}${check.detail ? ` — ${check.detail}` : ''}`);
247
- }
248
- console.log(`\n Pass rate: ${result.passRate}%`);
249
- process.exit(result.passRate >= 50 ? 0 : 1);
250
- }
251
- break;
252
- }
253
- const skillsMode = skillsAction;
254
- render(React.createElement(CIContextProvider, { isCI: isCI },
255
- React.createElement(Skills, { mode: skillsMode, budget: cli.flags.budget, deep: cli.flags.deep, skillsDir: cli.flags.skillsDir || undefined })), { stdin: inkStdin });
57
+ case "skill": {
58
+ await handleSkillPublish(cli);
256
59
  break;
257
60
  }
258
- case 'security': {
259
- const securityAction = cli.input[1];
260
- const VALID_SECURITY_ACTIONS = ['baseline', 'check', 'update'];
261
- if (!securityAction || !VALID_SECURITY_ACTIONS.includes(securityAction)) {
262
- console.error('Usage: javi-forge security <baseline|check|update>');
263
- console.error(' baseline Create security baseline from current audit findings');
264
- console.error(' check Check for regressions against baseline');
265
- console.error(' update Re-snapshot baseline (acknowledge current vulns)');
266
- process.exit(1);
267
- break;
268
- }
269
- const { runSecurity } = await import('./commands/security.js');
270
- const mode = securityAction;
271
- try {
272
- const result = await runSecurity(mode, process.cwd(), (step) => {
273
- const icon = step.status === 'done' ? '\u2713'
274
- : step.status === 'error' ? '\u2717'
275
- : step.status === 'skipped' ? '-'
276
- : '\u25CB';
277
- console.log(`${icon} ${step.label}`);
278
- if (step.detail)
279
- console.log(` ${step.detail}`);
280
- });
281
- if (mode === 'check' && result && result.regressions.length > 0) {
282
- process.exit(1);
283
- }
284
- }
285
- catch {
286
- process.exit(1);
287
- }
61
+ case "security": {
62
+ await handleSecurity(cli);
288
63
  break;
289
64
  }
290
- case 'init':
291
65
  default: {
292
- const presetStack = VALID_STACKS.includes(cli.flags.stack)
293
- ? cli.flags.stack
294
- : undefined;
295
- const presetCI = VALID_CI.includes(cli.flags.ci)
296
- ? cli.flags.ci
297
- : undefined;
298
- const presetMemory = VALID_MEMORY.includes(cli.flags.memory)
299
- ? cli.flags.memory
300
- : undefined;
301
- const presetName = cli.flags.projectName || undefined;
302
- render(React.createElement(CIContextProvider, { isCI: isCI },
303
- React.createElement(App, { dryRun: cli.flags.dryRun, presetStack: presetStack, presetCI: presetCI, presetMemory: presetMemory, presetName: presetName, presetGhagga: cli.flags.ghagga, presetMock: cli.flags.mock ?? false })), { stdin: inkStdin });
66
+ handleInitDefault(cli, { inkStdin, isCI });
304
67
  break;
305
68
  }
306
69
  }
@@ -1,4 +1,4 @@
1
- import type { PluginManifest, AgentSkillsManifest } from '../types/index.js';
1
+ import type { AgentSkillsManifest, AggregatedSkillsManifest, InstalledPlugin, PluginManifest } from "../types/index.js";
2
2
  /**
3
3
  * Convert a javi-forge PluginManifest to an Agent Skills spec manifest.
4
4
  */
@@ -35,4 +35,39 @@ export declare function importAgentSkillsPackage(sourceDir: string, options?: {
35
35
  name?: string;
36
36
  error?: string;
37
37
  }>;
38
+ /**
39
+ * Aggregate multiple installed plugins into a single Agent Skills spec manifest.
40
+ * This enables the entire registry (or a project's installed plugins) to be
41
+ * discoverable via `npx skills add` by any of the 40+ compatible AI agents.
42
+ *
43
+ * Pure function — no I/O.
44
+ */
45
+ export declare function aggregatePluginsToSkillsJson(plugins: InstalledPlugin[], registryName?: string, registryVersion?: string): AggregatedSkillsManifest;
46
+ /**
47
+ * Generate a project-level skills.json from all installed plugins in a project.
48
+ * Writes the aggregated manifest to the project's .javi-forge/ directory.
49
+ */
50
+ export declare function generateProjectSkillsJson(projectDir: string, options?: {
51
+ dryRun?: boolean;
52
+ registryName?: string;
53
+ }): Promise<{
54
+ success: boolean;
55
+ path?: string;
56
+ skillCount: number;
57
+ pluginCount: number;
58
+ error?: string;
59
+ }>;
60
+ /**
61
+ * Generate a skills.json from all globally installed plugins.
62
+ * Writes to the global plugins directory.
63
+ */
64
+ export declare function generateGlobalSkillsJson(options?: {
65
+ dryRun?: boolean;
66
+ }): Promise<{
67
+ success: boolean;
68
+ path?: string;
69
+ skillCount: number;
70
+ pluginCount: number;
71
+ error?: string;
72
+ }>;
38
73
  //# sourceMappingURL=agent-skills.d.ts.map
@@ -1,12 +1,12 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import { AGENT_SKILLS_MANIFEST_FILE, PLUGIN_MANIFEST_FILE, PLUGINS_DIR } from '../constants.js';
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ import { AGENT_SKILLS_MANIFEST_FILE, PLUGIN_MANIFEST_FILE, PLUGINS_DIR, } from "../constants.js";
4
4
  // ── Conversion ─────────────────────────────────────────────────────────────
5
5
  /**
6
6
  * Convert a javi-forge PluginManifest to an Agent Skills spec manifest.
7
7
  */
8
8
  export function pluginToAgentSkills(manifest, source) {
9
- const skills = (manifest.skills ?? []).map(s => ({
9
+ const skills = (manifest.skills ?? []).map((s) => ({
10
10
  name: s,
11
11
  description: `${s} skill from ${manifest.name}`,
12
12
  path: `skills/${s}`,
@@ -27,8 +27,8 @@ export function agentSkillsToPlugin(agentManifest) {
27
27
  name: agentManifest.name,
28
28
  version: agentManifest.version,
29
29
  description: agentManifest.description,
30
- skills: agentManifest.skills.map(s => s.name),
31
- tags: ['agent-skills-import'],
30
+ skills: agentManifest.skills.map((s) => s.name),
31
+ tags: ["agent-skills-import"],
32
32
  };
33
33
  }
34
34
  // ── File I/O ───────────────────────────────────────────────────────────────
@@ -37,15 +37,15 @@ export function agentSkillsToPlugin(agentManifest) {
37
37
  */
38
38
  export async function generateAgentSkillsManifest(pluginDir, source) {
39
39
  const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_FILE);
40
- if (!await fs.pathExists(manifestPath)) {
41
- return { success: false, error: 'plugin.json not found' };
40
+ if (!(await fs.pathExists(manifestPath))) {
41
+ return { success: false, error: "plugin.json not found" };
42
42
  }
43
43
  let manifest;
44
44
  try {
45
- manifest = await fs.readJson(manifestPath);
45
+ manifest = (await fs.readJson(manifestPath));
46
46
  }
47
47
  catch {
48
- return { success: false, error: 'invalid plugin.json' };
48
+ return { success: false, error: "invalid plugin.json" };
49
49
  }
50
50
  const agentManifest = pluginToAgentSkills(manifest, source);
51
51
  const outPath = path.join(pluginDir, AGENT_SKILLS_MANIFEST_FILE);
@@ -58,7 +58,7 @@ export async function generateAgentSkillsManifest(pluginDir, source) {
58
58
  */
59
59
  export async function exportPluginAsAgentSkills(name) {
60
60
  const pluginDir = path.join(PLUGINS_DIR, name);
61
- if (!await fs.pathExists(pluginDir)) {
61
+ if (!(await fs.pathExists(pluginDir))) {
62
62
  return { success: false, error: `plugin "${name}" is not installed` };
63
63
  }
64
64
  return generateAgentSkillsManifest(pluginDir);
@@ -70,18 +70,23 @@ export async function exportPluginAsAgentSkills(name) {
70
70
  export async function importAgentSkillsPackage(sourceDir, options = {}) {
71
71
  const { dryRun = false } = options;
72
72
  const skillsPath = path.join(sourceDir, AGENT_SKILLS_MANIFEST_FILE);
73
- if (!await fs.pathExists(skillsPath)) {
74
- return { success: false, error: 'skills.json not found' };
73
+ if (!(await fs.pathExists(skillsPath))) {
74
+ return { success: false, error: "skills.json not found" };
75
75
  }
76
76
  let agentManifest;
77
77
  try {
78
- agentManifest = await fs.readJson(skillsPath);
78
+ agentManifest = (await fs.readJson(skillsPath));
79
79
  }
80
80
  catch {
81
- return { success: false, error: 'invalid skills.json' };
81
+ return { success: false, error: "invalid skills.json" };
82
82
  }
83
- if (!agentManifest.name || !agentManifest.version || !agentManifest.description) {
84
- return { success: false, error: 'skills.json missing required fields (name, version, description)' };
83
+ if (!agentManifest.name ||
84
+ !agentManifest.version ||
85
+ !agentManifest.description) {
86
+ return {
87
+ success: false,
88
+ error: "skills.json missing required fields (name, version, description)",
89
+ };
85
90
  }
86
91
  const pluginName = agentManifest.name;
87
92
  if (dryRun) {
@@ -96,7 +101,9 @@ export async function importAgentSkillsPackage(sourceDir, options = {}) {
96
101
  await fs.copy(sourceDir, destDir);
97
102
  // Generate plugin.json from skills.json
98
103
  const pluginManifest = agentSkillsToPlugin(agentManifest);
99
- await fs.writeJson(path.join(destDir, PLUGIN_MANIFEST_FILE), pluginManifest, { spaces: 2 });
104
+ await fs.writeJson(path.join(destDir, PLUGIN_MANIFEST_FILE), pluginManifest, {
105
+ spaces: 2,
106
+ });
100
107
  // Write install metadata
101
108
  const installedPlugin = {
102
109
  name: pluginName,
@@ -105,7 +112,149 @@ export async function importAgentSkillsPackage(sourceDir, options = {}) {
105
112
  source: `agent-skills:${sourceDir}`,
106
113
  manifest: pluginManifest,
107
114
  };
108
- await fs.writeJson(path.join(destDir, '.installed.json'), installedPlugin, { spaces: 2 });
115
+ await fs.writeJson(path.join(destDir, ".installed.json"), installedPlugin, {
116
+ spaces: 2,
117
+ });
109
118
  return { success: true, name: pluginName };
110
119
  }
120
+ // ── Aggregation ──────────────────────────────────────────────────────────
121
+ /**
122
+ * Aggregate multiple installed plugins into a single Agent Skills spec manifest.
123
+ * This enables the entire registry (or a project's installed plugins) to be
124
+ * discoverable via `npx skills add` by any of the 40+ compatible AI agents.
125
+ *
126
+ * Pure function — no I/O.
127
+ */
128
+ export function aggregatePluginsToSkillsJson(plugins, registryName = "javi-forge-registry", registryVersion = "1.0.0") {
129
+ const skills = [];
130
+ const sources = [];
131
+ for (const plugin of plugins) {
132
+ const { manifest } = plugin;
133
+ if (!manifest)
134
+ continue;
135
+ sources.push({
136
+ plugin: manifest.name,
137
+ version: manifest.version,
138
+ ...(manifest.repository ? { repository: manifest.repository } : {}),
139
+ });
140
+ for (const skillName of manifest.skills ?? []) {
141
+ skills.push({
142
+ name: `${manifest.name}/${skillName}`,
143
+ description: `${skillName} skill from ${manifest.name} plugin`,
144
+ path: `plugins/${manifest.name}/skills/${skillName}`,
145
+ });
146
+ }
147
+ }
148
+ return {
149
+ name: registryName,
150
+ version: registryVersion,
151
+ description: `Aggregated skills from ${plugins.length} javi-forge plugin(s)`,
152
+ skills,
153
+ sources,
154
+ };
155
+ }
156
+ /**
157
+ * Generate a project-level skills.json from all installed plugins in a project.
158
+ * Writes the aggregated manifest to the project's .javi-forge/ directory.
159
+ */
160
+ export async function generateProjectSkillsJson(projectDir, options = {}) {
161
+ const { dryRun = false, registryName } = options;
162
+ const pluginsDir = path.join(projectDir, ".javi-forge", "plugins");
163
+ if (!(await fs.pathExists(pluginsDir))) {
164
+ return {
165
+ success: false,
166
+ skillCount: 0,
167
+ pluginCount: 0,
168
+ error: "no plugins directory found",
169
+ };
170
+ }
171
+ const entries = await fs.readdir(pluginsDir);
172
+ const plugins = [];
173
+ for (const entry of entries) {
174
+ if (entry.startsWith("."))
175
+ continue;
176
+ const metaPath = path.join(pluginsDir, entry, ".installed.json");
177
+ if (await fs.pathExists(metaPath)) {
178
+ try {
179
+ const meta = (await fs.readJson(metaPath));
180
+ if (meta.name)
181
+ plugins.push(meta);
182
+ }
183
+ catch {
184
+ /* skip corrupt entries */
185
+ }
186
+ }
187
+ }
188
+ if (plugins.length === 0) {
189
+ return {
190
+ success: false,
191
+ skillCount: 0,
192
+ pluginCount: 0,
193
+ error: "no installed plugins found",
194
+ };
195
+ }
196
+ const projectName = registryName ?? path.basename(projectDir);
197
+ const aggregated = aggregatePluginsToSkillsJson(plugins, projectName);
198
+ const outPath = path.join(projectDir, AGENT_SKILLS_MANIFEST_FILE);
199
+ if (!dryRun) {
200
+ await fs.writeJson(outPath, aggregated, { spaces: 2 });
201
+ }
202
+ return {
203
+ success: true,
204
+ path: outPath,
205
+ skillCount: aggregated.skills.length,
206
+ pluginCount: plugins.length,
207
+ };
208
+ }
209
+ /**
210
+ * Generate a skills.json from all globally installed plugins.
211
+ * Writes to the global plugins directory.
212
+ */
213
+ export async function generateGlobalSkillsJson(options = {}) {
214
+ const { dryRun = false } = options;
215
+ if (!(await fs.pathExists(PLUGINS_DIR))) {
216
+ return {
217
+ success: false,
218
+ skillCount: 0,
219
+ pluginCount: 0,
220
+ error: "no plugins directory found",
221
+ };
222
+ }
223
+ const entries = await fs.readdir(PLUGINS_DIR);
224
+ const plugins = [];
225
+ for (const entry of entries) {
226
+ if (entry.startsWith("."))
227
+ continue;
228
+ const metaPath = path.join(PLUGINS_DIR, entry, ".installed.json");
229
+ if (await fs.pathExists(metaPath)) {
230
+ try {
231
+ const meta = (await fs.readJson(metaPath));
232
+ if (meta.name)
233
+ plugins.push(meta);
234
+ }
235
+ catch {
236
+ /* skip corrupt entries */
237
+ }
238
+ }
239
+ }
240
+ if (plugins.length === 0) {
241
+ return {
242
+ success: false,
243
+ skillCount: 0,
244
+ pluginCount: 0,
245
+ error: "no installed plugins found",
246
+ };
247
+ }
248
+ const aggregated = aggregatePluginsToSkillsJson(plugins);
249
+ const outPath = path.join(PLUGINS_DIR, AGENT_SKILLS_MANIFEST_FILE);
250
+ if (!dryRun) {
251
+ await fs.writeJson(outPath, aggregated, { spaces: 2 });
252
+ }
253
+ return {
254
+ success: true,
255
+ path: outPath,
256
+ skillCount: aggregated.skills.length,
257
+ pluginCount: plugins.length,
258
+ };
259
+ }
111
260
  //# sourceMappingURL=agent-skills.js.map