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
@@ -1,397 +1,52 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import { execFile } from 'child_process';
4
- import { promisify } from 'util';
5
- import { backupIfExists, ensureDirExists } from '../lib/common.js';
6
- import { generateDependabotYml, generateCIWorkflow, getCIDestination } from '../lib/template.js';
7
- import { generateContextDir } from '../lib/context.js';
8
- import { generateClaudeMd } from '../lib/claudemd.js';
9
- import { FORGE_ROOT, MODULES_DIR, CI_LOCAL_DIR, } from '../constants.js';
10
- const execFileAsync = promisify(execFile);
11
- function report(onStep, id, label, status, detail) {
12
- onStep({ id, label, status, detail });
13
- }
1
+ import { ensureDirExists } from "../lib/common.js";
2
+ import { stepAgentSkills } from "./init/steps/agent-skills.js";
3
+ import { stepAISync } from "./init/steps/ai-sync.js";
4
+ import { stepCITemplate, stepDependabot } from "./init/steps/ci.js";
5
+ import { stepClaudeMd } from "./init/steps/claude-md.js";
6
+ import { stepCodeGraph } from "./init/steps/code-graph.js";
7
+ import { stepContextDir } from "./init/steps/context-dir.js";
8
+ import { stepDockerDeploy } from "./init/steps/docker-deploy.js";
9
+ import { stepGhagga } from "./init/steps/ghagga.js";
10
+ import { stepGitHooks, stepGitInit } from "./init/steps/git.js";
11
+ import { stepGitignore } from "./init/steps/gitignore.js";
12
+ import { stepLocalAi } from "./init/steps/local-ai.js";
13
+ import { stepManifest } from "./init/steps/manifest.js";
14
+ import { stepMemory } from "./init/steps/memory.js";
15
+ import { stepMock } from "./init/steps/mock.js";
16
+ import { stepSDD } from "./init/steps/sdd.js";
17
+ import { stepHookProfile, stepSecurityHooks } from "./init/steps/security.js";
14
18
  /**
15
19
  * Main init orchestrator: bootstraps a project with CI, git hooks,
16
- * memory module, AI config sync, SDD, and ghagga.
20
+ * memory module, AI config sync, SDD, ghagga, and friends.
21
+ *
22
+ * Pure dispatch: every step lives in src/commands/init/steps/.
17
23
  */
18
24
  export async function initProject(options, onStep) {
19
- const { projectDir, projectName, stack, ciProvider, memory, aiSync, sdd, ghagga, contextDir, claudeMd, dryRun } = options;
25
+ const { projectDir, dryRun } = options;
20
26
  // Ensure project directory exists before any steps
21
27
  if (!dryRun && projectDir) {
22
28
  await ensureDirExists(projectDir);
23
29
  }
24
- // ── Step 1: Initialize git ────────────────────────────────────────────────
25
- const stepGit = 'git-init';
26
- report(onStep, stepGit, 'Initialize git repository', 'running');
27
- try {
28
- const gitDir = path.join(projectDir, '.git');
29
- if (!await fs.pathExists(gitDir)) {
30
- if (!dryRun) {
31
- await execFileAsync('git', ['init'], { cwd: projectDir });
32
- }
33
- report(onStep, stepGit, 'Initialize git repository', 'done', 'initialized');
34
- }
35
- else {
36
- report(onStep, stepGit, 'Initialize git repository', 'done', 'already exists');
37
- }
38
- }
39
- catch (e) {
40
- report(onStep, stepGit, 'Initialize git repository', 'error', String(e));
41
- }
42
- // ── Step 2: Configure git hooks path ──────────────────────────────────────
43
- const stepHooks = 'git-hooks';
44
- report(onStep, stepHooks, 'Configure git hooks path', 'running');
45
- try {
46
- const ciLocalSrc = CI_LOCAL_DIR;
47
- const ciLocalDest = path.join(projectDir, 'ci-local');
48
- if (await fs.pathExists(ciLocalSrc)) {
49
- if (!dryRun) {
50
- await fs.copy(ciLocalSrc, ciLocalDest, { overwrite: false, errorOnExist: false });
51
- // Set core.hooksPath to ci-local/hooks
52
- const hooksDir = path.join(ciLocalDest, 'hooks');
53
- if (await fs.pathExists(hooksDir)) {
54
- // Ensure hooks are executable
55
- const hookFiles = await fs.readdir(hooksDir);
56
- for (const hook of hookFiles) {
57
- await fs.chmod(path.join(hooksDir, hook), 0o755);
58
- }
59
- await execFileAsync('git', ['config', 'core.hooksPath', 'ci-local/hooks'], { cwd: projectDir });
60
- }
61
- }
62
- report(onStep, stepHooks, 'Configure git hooks path', 'done', 'ci-local/hooks');
63
- }
64
- else {
65
- report(onStep, stepHooks, 'Configure git hooks path', 'skipped', 'no ci-local dir');
66
- }
67
- }
68
- catch (e) {
69
- report(onStep, stepHooks, 'Configure git hooks path', 'error', String(e));
70
- }
71
- // ── Step 3: Copy CI template ──────────────────────────────────────────────
72
- const stepCI = 'ci-template';
73
- report(onStep, stepCI, `Copy ${ciProvider} CI workflow`, 'running');
74
- try {
75
- const ciContent = await generateCIWorkflow(stack, ciProvider);
76
- if (ciContent) {
77
- const dest = path.join(projectDir, getCIDestination(ciProvider));
78
- if (!dryRun) {
79
- await backupIfExists(dest);
80
- await ensureDirExists(path.dirname(dest));
81
- await fs.writeFile(dest, ciContent, 'utf-8');
82
- }
83
- report(onStep, stepCI, `Copy ${ciProvider} CI workflow`, 'done', getCIDestination(ciProvider));
84
- }
85
- else {
86
- report(onStep, stepCI, `Copy ${ciProvider} CI workflow`, 'skipped', `no template for ${stack}`);
87
- }
88
- }
89
- catch (e) {
90
- report(onStep, stepCI, `Copy ${ciProvider} CI workflow`, 'error', String(e));
91
- }
92
- // ── Step 4: Generate .gitignore ───────────────────────────────────────────
93
- const stepGitignore = 'gitignore';
94
- report(onStep, stepGitignore, 'Generate .gitignore', 'running');
95
- try {
96
- const templatePath = path.join(FORGE_ROOT, '.gitignore.template');
97
- const dest = path.join(projectDir, '.gitignore');
98
- if (await fs.pathExists(templatePath) && !await fs.pathExists(dest)) {
99
- if (!dryRun) {
100
- await fs.copy(templatePath, dest);
101
- }
102
- report(onStep, stepGitignore, 'Generate .gitignore', 'done', 'from template');
103
- }
104
- else if (await fs.pathExists(dest)) {
105
- report(onStep, stepGitignore, 'Generate .gitignore', 'done', 'already exists');
106
- }
107
- else {
108
- report(onStep, stepGitignore, 'Generate .gitignore', 'skipped', 'no template');
109
- }
110
- }
111
- catch (e) {
112
- report(onStep, stepGitignore, 'Generate .gitignore', 'error', String(e));
113
- }
114
- // ── Step 5: Generate dependabot.yml ───────────────────────────────────────
115
- const stepDeps = 'dependabot';
116
- report(onStep, stepDeps, 'Generate dependabot.yml', 'running');
117
- try {
118
- if (ciProvider === 'github') {
119
- const content = await generateDependabotYml([stack], true);
120
- const dest = path.join(projectDir, '.github', 'dependabot.yml');
121
- if (!dryRun) {
122
- await backupIfExists(dest);
123
- await ensureDirExists(path.dirname(dest));
124
- await fs.writeFile(dest, content, 'utf-8');
125
- }
126
- report(onStep, stepDeps, 'Generate dependabot.yml', 'done');
127
- }
128
- else {
129
- report(onStep, stepDeps, 'Generate dependabot.yml', 'skipped', `not needed for ${ciProvider}`);
130
- }
131
- }
132
- catch (e) {
133
- report(onStep, stepDeps, 'Generate dependabot.yml', 'error', String(e));
134
- }
135
- // ── Step 6: Install memory module ─────────────────────────────────────────
136
- const stepMem = 'memory';
137
- report(onStep, stepMem, `Install memory module: ${memory}`, 'running');
138
- try {
139
- if (memory !== 'none') {
140
- const moduleSrc = path.join(MODULES_DIR, memory);
141
- if (await fs.pathExists(moduleSrc)) {
142
- if (!dryRun) {
143
- // Copy module files to project
144
- const moduleDest = path.join(projectDir, '.javi-forge', 'modules', memory);
145
- await ensureDirExists(moduleDest);
146
- await fs.copy(moduleSrc, moduleDest, { overwrite: false, errorOnExist: false });
147
- // If engram, copy .mcp-config-snippet.json to project with placeholder replacement
148
- if (memory === 'engram') {
149
- const snippetSrc = path.join(moduleSrc, '.mcp-config-snippet.json');
150
- if (await fs.pathExists(snippetSrc)) {
151
- const snippetDest = path.join(projectDir, '.mcp-config-snippet.json');
152
- let content = await fs.readFile(snippetSrc, 'utf-8');
153
- content = content.replace(/__PROJECT_NAME__/g, projectName);
154
- await fs.writeFile(snippetDest, content, 'utf-8');
155
- }
156
- }
157
- }
158
- report(onStep, stepMem, `Install memory module: ${memory}`, 'done');
159
- }
160
- else {
161
- report(onStep, stepMem, `Install memory module: ${memory}`, 'error', 'module not found');
162
- }
163
- }
164
- else {
165
- report(onStep, stepMem, `Install memory module: ${memory}`, 'skipped', 'none selected');
166
- }
167
- }
168
- catch (e) {
169
- report(onStep, stepMem, `Install memory module: ${memory}`, 'error', String(e));
170
- }
171
- // ── Step 7: AI config sync (delegated to javi-ai) ──────────────────────────
172
- const stepAI = 'ai-sync';
173
- report(onStep, stepAI, 'Sync AI config via javi-ai', 'running');
174
- try {
175
- if (aiSync) {
176
- if (!dryRun) {
177
- try {
178
- const { stderr } = await execFileAsync('npx', ['javi-ai', 'sync', '--project-dir', projectDir, '--target', 'all'], {
179
- cwd: projectDir,
180
- timeout: 120_000,
181
- });
182
- // javi-ai may exit 0 but crash (e.g. Ink raw mode error) — detect via stderr
183
- if (stderr && (stderr.includes('Raw mode is not supported') || stderr.includes('ERROR'))) {
184
- report(onStep, stepAI, 'Sync AI config via javi-ai', 'error', 'javi-ai crashed. Run manually: npx javi-ai sync --project-dir . --target all');
185
- }
186
- else {
187
- report(onStep, stepAI, 'Sync AI config via javi-ai', 'done', 'javi-ai sync --target all');
188
- }
189
- }
190
- catch (syncErr) {
191
- const msg = syncErr instanceof Error ? syncErr.message : String(syncErr);
192
- if (msg.includes('ENOENT') || msg.includes('not found') || msg.includes('ERR_MODULE_NOT_FOUND')) {
193
- report(onStep, stepAI, 'Sync AI config via javi-ai', 'error', 'javi-ai not found. Install with: npm install -g javi-ai (or run npx javi-ai sync manually)');
194
- }
195
- else {
196
- report(onStep, stepAI, 'Sync AI config via javi-ai', 'error', msg);
197
- }
198
- }
199
- }
200
- else {
201
- report(onStep, stepAI, 'Sync AI config via javi-ai', 'done', 'dry-run: would run javi-ai sync --target all');
202
- }
203
- }
204
- else {
205
- report(onStep, stepAI, 'Sync AI config via javi-ai', 'skipped', 'not selected');
206
- }
207
- }
208
- catch (e) {
209
- report(onStep, stepAI, 'Sync AI config via javi-ai', 'error', String(e));
210
- }
211
- // ── Step 8: SDD (Spec-Driven Development) ─────────────────────────────────
212
- const stepSDD = 'sdd';
213
- report(onStep, stepSDD, 'Set up SDD (openspec/)', 'running');
214
- try {
215
- if (sdd) {
216
- if (!dryRun) {
217
- const openspecDir = path.join(projectDir, 'openspec');
218
- await ensureDirExists(openspecDir);
219
- // Create a README if none exists
220
- const readmePath = path.join(openspecDir, 'README.md');
221
- if (!await fs.pathExists(readmePath)) {
222
- await fs.writeFile(readmePath, `# openspec/\n\nSpec-Driven Development artifacts for ${projectName}.\n\nSee: /sdd:new <name> to start a new change.\n`, 'utf-8');
223
- }
224
- }
225
- report(onStep, stepSDD, 'Set up SDD (openspec/)', 'done');
226
- }
227
- else {
228
- report(onStep, stepSDD, 'Set up SDD (openspec/)', 'skipped', 'not selected');
229
- }
230
- }
231
- catch (e) {
232
- report(onStep, stepSDD, 'Set up SDD (openspec/)', 'error', String(e));
233
- }
234
- // ── Step 9: GHAGGA ────────────────────────────────────────────────────────
235
- const stepGhagga = 'ghagga';
236
- report(onStep, stepGhagga, 'Install GHAGGA review system', 'running');
237
- try {
238
- if (ghagga) {
239
- const ghaggaSrc = path.join(MODULES_DIR, 'ghagga');
240
- if (await fs.pathExists(ghaggaSrc)) {
241
- if (!dryRun) {
242
- const ghaggaDest = path.join(projectDir, '.javi-forge', 'modules', 'ghagga');
243
- await ensureDirExists(ghaggaDest);
244
- await fs.copy(ghaggaSrc, ghaggaDest, { overwrite: false, errorOnExist: false });
245
- // Copy ghagga caller workflow to CI provider location
246
- if (ciProvider === 'github') {
247
- const workflowSrc = path.join(FORGE_ROOT, 'templates', 'github', 'ghagga-review.yml');
248
- if (await fs.pathExists(workflowSrc)) {
249
- const workflowDest = path.join(projectDir, '.github', 'workflows', 'ghagga-review.yml');
250
- await ensureDirExists(path.dirname(workflowDest));
251
- await fs.copy(workflowSrc, workflowDest, { overwrite: false });
252
- }
253
- }
254
- }
255
- report(onStep, stepGhagga, 'Install GHAGGA review system', 'done');
256
- }
257
- else {
258
- report(onStep, stepGhagga, 'Install GHAGGA review system', 'error', 'module not found');
259
- }
260
- }
261
- else {
262
- report(onStep, stepGhagga, 'Install GHAGGA review system', 'skipped', 'not selected');
263
- }
264
- }
265
- catch (e) {
266
- report(onStep, stepGhagga, 'Install GHAGGA review system', 'error', String(e));
267
- }
268
- // ── Step 10: Mock-first mode ───────────────────────────────────────────────
269
- const stepMock = 'mock';
270
- if (options.mock) {
271
- report(onStep, stepMock, 'Configure mock-first mode', 'running');
272
- try {
273
- if (!dryRun) {
274
- // Create .env.example with mock values
275
- const envExample = `# Mock environment — no real API keys required
276
- # Copy to .env to use: cp .env.example .env
277
-
278
- # Database
279
- DATABASE_URL=postgresql://mock:mock@localhost:5432/mock_db
280
-
281
- # Auth
282
- JWT_SECRET=mock-jwt-secret-for-local-development
283
- SESSION_SECRET=mock-session-secret
284
-
285
- # External APIs (mock mode — no real calls)
286
- MOCK_MODE=true
287
- API_KEY=mock-api-key-not-real
288
- STRIPE_KEY=sk_test_mock_not_real
289
- SENDGRID_KEY=SG.mock_not_real
290
-
291
- # Feature flags
292
- ENABLE_ANALYTICS=false
293
- ENABLE_EMAILS=false
294
- ENABLE_WEBHOOKS=false
295
- `;
296
- const envExamplePath = path.join(projectDir, '.env.example');
297
- if (!await fs.pathExists(envExamplePath)) {
298
- await fs.writeFile(envExamplePath, envExample, 'utf-8');
299
- }
300
- // Create .env from example
301
- const envPath = path.join(projectDir, '.env');
302
- if (!await fs.pathExists(envPath)) {
303
- await fs.writeFile(envPath, envExample, 'utf-8');
304
- }
305
- }
306
- report(onStep, stepMock, 'Configure mock-first mode', 'done', '.env.example + .env with mock values');
307
- }
308
- catch (e) {
309
- report(onStep, stepMock, 'Configure mock-first mode', 'error', String(e));
310
- }
311
- }
312
- else {
313
- report(onStep, stepMock, 'Configure mock-first mode', 'skipped', 'not selected');
314
- }
315
- // ── Step 11: Generate .context/ directory ──────────────────────────────────
316
- const stepContext = 'context-dir';
317
- report(onStep, stepContext, 'Generate .context/ directory', 'running');
318
- try {
319
- if (contextDir) {
320
- const contextDirPath = path.join(projectDir, '.context');
321
- if (await fs.pathExists(contextDirPath)) {
322
- report(onStep, stepContext, 'Generate .context/ directory', 'done', 'already exists');
323
- }
324
- else {
325
- if (!dryRun) {
326
- const { index, summary } = await generateContextDir(options);
327
- await ensureDirExists(contextDirPath);
328
- await fs.writeFile(path.join(contextDirPath, 'INDEX.md'), index, 'utf-8');
329
- await fs.writeFile(path.join(contextDirPath, 'summary.md'), summary, 'utf-8');
330
- }
331
- report(onStep, stepContext, 'Generate .context/ directory', 'done', dryRun ? 'dry-run: would generate .context/' : '.context/INDEX.md + summary.md');
332
- }
333
- }
334
- else {
335
- report(onStep, stepContext, 'Generate .context/ directory', 'skipped', 'not selected');
336
- }
337
- }
338
- catch (e) {
339
- report(onStep, stepContext, 'Generate .context/ directory', 'error', String(e));
340
- }
341
- // ── Step 12: Generate CLAUDE.md ────────────────────────────────────────────
342
- const stepClaudeMd = 'claude-md';
343
- report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'running');
344
- try {
345
- if (claudeMd) {
346
- const claudeMdPath = path.join(projectDir, 'CLAUDE.md');
347
- if (await fs.pathExists(claudeMdPath)) {
348
- report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'done', 'already exists');
349
- }
350
- else {
351
- if (!dryRun) {
352
- const content = generateClaudeMd(options);
353
- await fs.writeFile(claudeMdPath, content, 'utf-8');
354
- }
355
- report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'done', dryRun ? 'dry-run: would generate CLAUDE.md' : 'CLAUDE.md');
356
- }
357
- }
358
- else {
359
- report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'skipped', 'not selected');
360
- }
361
- }
362
- catch (e) {
363
- report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'error', String(e));
364
- }
365
- // ── Step 13: Write manifest ───────────────────────────────────────────────
366
- const stepManifest = 'manifest';
367
- report(onStep, stepManifest, 'Write forge manifest', 'running');
368
- try {
369
- if (!dryRun) {
370
- const manifestDir = path.join(projectDir, '.javi-forge');
371
- await ensureDirExists(manifestDir);
372
- const manifest = {
373
- version: '0.1.0',
374
- projectName,
375
- stack,
376
- ciProvider,
377
- memory,
378
- createdAt: new Date().toISOString(),
379
- updatedAt: new Date().toISOString(),
380
- modules: [
381
- ...(memory !== 'none' ? [memory] : []),
382
- ...(ghagga ? ['ghagga'] : []),
383
- ...(sdd ? ['sdd'] : []),
384
- ...(aiSync ? ['ai-config'] : []),
385
- ...(contextDir ? ['context'] : []),
386
- ...(claudeMd ? ['claude-md'] : []),
387
- ],
388
- };
389
- await fs.writeJson(path.join(manifestDir, 'manifest.json'), manifest, { spaces: 2 });
390
- }
391
- report(onStep, stepManifest, 'Write forge manifest', 'done', '.javi-forge/manifest.json');
392
- }
393
- catch (e) {
394
- report(onStep, stepManifest, 'Write forge manifest', 'error', String(e));
395
- }
30
+ // Shared context passed to every step.
31
+ const ctx = { options, projectDir, dryRun, onStep };
32
+ await stepGitInit(ctx);
33
+ await stepGitHooks(ctx);
34
+ await stepCITemplate(ctx);
35
+ await stepGitignore(ctx);
36
+ await stepDependabot(ctx);
37
+ await stepMemory(ctx);
38
+ await stepAISync(ctx);
39
+ await stepSDD(ctx);
40
+ await stepGhagga(ctx);
41
+ await stepMock(ctx);
42
+ await stepContextDir(ctx);
43
+ await stepClaudeMd(ctx);
44
+ await stepDockerDeploy(ctx);
45
+ await stepSecurityHooks(ctx);
46
+ await stepHookProfile(ctx);
47
+ await stepCodeGraph(ctx);
48
+ await stepLocalAi(ctx);
49
+ await stepAgentSkills(ctx);
50
+ await stepManifest(ctx);
396
51
  }
397
52
  //# sourceMappingURL=init.js.map
@@ -1,4 +1,4 @@
1
- import type { InitStep } from '../types/index.js';
1
+ import type { InitStep } from "../types/index.js";
2
2
  type StepCallback = (step: InitStep) => void;
3
3
  /**
4
4
  * Generate an llms.txt file — compact AI-friendly project notation.
@@ -1,7 +1,7 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import { glob } from 'glob';
4
- import { detectStack } from '../lib/common.js';
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ import { glob } from "glob";
4
+ import { detectStack } from "../lib/common.js";
5
5
  function report(onStep, id, label, status, detail) {
6
6
  onStep({ id, label, status, detail });
7
7
  }
@@ -10,53 +10,55 @@ function report(onStep, id, label, status, detail) {
10
10
  * Reduces token usage by ~75% compared to full README + docs.
11
11
  */
12
12
  export async function generateLlmsTxt(projectDir, dryRun, onStep) {
13
- report(onStep, 'scan', 'Scan project structure', 'running');
13
+ report(onStep, "scan", "Scan project structure", "running");
14
14
  const detection = await detectStack(projectDir);
15
- const stackLabel = detection?.stackType ?? 'unknown';
15
+ const stackLabel = detection?.stackType ?? "unknown";
16
16
  // Gather project info
17
17
  const name = path.basename(projectDir);
18
- let description = '';
19
- let version = '';
18
+ let description = "";
19
+ let version = "";
20
20
  let entryPoints = [];
21
21
  let dependencies = [];
22
22
  // Try package.json (Node)
23
- const pkgPath = path.join(projectDir, 'package.json');
23
+ const pkgPath = path.join(projectDir, "package.json");
24
24
  if (await fs.pathExists(pkgPath)) {
25
25
  try {
26
26
  const pkg = await fs.readJson(pkgPath);
27
- description = pkg.description ?? '';
28
- version = pkg.version ?? '';
27
+ description = pkg.description ?? "";
28
+ version = pkg.version ?? "";
29
29
  entryPoints = pkg.main ? [pkg.main] : [];
30
30
  dependencies = Object.keys(pkg.dependencies ?? {}).slice(0, 15);
31
31
  }
32
- catch { /* ignore */ }
32
+ catch {
33
+ /* ignore */
34
+ }
33
35
  }
34
36
  // Scan source files
35
- const sourceFiles = await glob('src/**/*.{ts,tsx,js,jsx,py,go,rs}', {
37
+ const sourceFiles = await glob("src/**/*.{ts,tsx,js,jsx,py,go,rs}", {
36
38
  cwd: projectDir,
37
- ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'],
39
+ ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
38
40
  });
39
41
  // Scan test files
40
- const testFiles = await glob('**/*.{test,spec}.{ts,tsx,js,jsx,py}', {
42
+ const testFiles = await glob("**/*.{test,spec}.{ts,tsx,js,jsx,py}", {
41
43
  cwd: projectDir,
42
- ignore: ['**/node_modules/**', '**/dist/**'],
44
+ ignore: ["**/node_modules/**", "**/dist/**"],
43
45
  });
44
- report(onStep, 'scan', 'Scan project structure', 'done', `${sourceFiles.length} source, ${testFiles.length} test files`);
46
+ report(onStep, "scan", "Scan project structure", "done", `${sourceFiles.length} source, ${testFiles.length} test files`);
45
47
  // Build llms.txt content
46
- report(onStep, 'generate', 'Generate llms.txt', 'running');
48
+ report(onStep, "generate", "Generate llms.txt", "running");
47
49
  const lines = [
48
50
  `# ${name}`,
49
- '',
50
- `> ${description || 'No description'}`,
51
- '',
52
- `- stack: ${stackLabel}${detection?.buildTool ? ` (${detection.buildTool})` : ''}`,
53
- `- version: ${version || 'unknown'}`,
51
+ "",
52
+ `> ${description || "No description"}`,
53
+ "",
54
+ `- stack: ${stackLabel}${detection?.buildTool ? ` (${detection.buildTool})` : ""}`,
55
+ `- version: ${version || "unknown"}`,
54
56
  `- files: ${sourceFiles.length} source, ${testFiles.length} tests`,
55
- '',
57
+ "",
56
58
  ];
57
59
  // Structure summary (compact)
58
60
  if (sourceFiles.length > 0) {
59
- lines.push('## Structure');
61
+ lines.push("## Structure");
60
62
  const dirs = new Map();
61
63
  for (const f of sourceFiles) {
62
64
  const dir = path.dirname(f);
@@ -65,28 +67,28 @@ export async function generateLlmsTxt(projectDir, dryRun, onStep) {
65
67
  for (const [dir, count] of [...dirs.entries()].sort().slice(0, 20)) {
66
68
  lines.push(`- ${dir}/ (${count})`);
67
69
  }
68
- lines.push('');
70
+ lines.push("");
69
71
  }
70
72
  // Dependencies (compact — name only, no versions)
71
73
  if (dependencies.length > 0) {
72
- lines.push('## Dependencies');
73
- lines.push(dependencies.join(', '));
74
- lines.push('');
74
+ lines.push("## Dependencies");
75
+ lines.push(dependencies.join(", "));
76
+ lines.push("");
75
77
  }
76
78
  // Entry points
77
79
  if (entryPoints.length > 0) {
78
- lines.push('## Entry');
80
+ lines.push("## Entry");
79
81
  for (const ep of entryPoints) {
80
82
  lines.push(`- ${ep}`);
81
83
  }
82
- lines.push('');
84
+ lines.push("");
83
85
  }
84
- const content = lines.join('\n');
86
+ const content = lines.join("\n");
85
87
  const tokenEstimate = Math.ceil(content.length / 4);
86
88
  if (!dryRun) {
87
- await fs.writeFile(path.join(projectDir, 'llms.txt'), content, 'utf-8');
89
+ await fs.writeFile(path.join(projectDir, "llms.txt"), content, "utf-8");
88
90
  }
89
- report(onStep, 'generate', 'Generate llms.txt', 'done', dryRun
91
+ report(onStep, "generate", "Generate llms.txt", "done", dryRun
90
92
  ? `dry-run: ~${tokenEstimate} tokens (${content.length} chars)`
91
93
  : `written — ~${tokenEstimate} tokens (${content.length} chars)`);
92
94
  }
@@ -1,4 +1,4 @@
1
- import type { InitStep } from '../types/index.js';
1
+ import type { InitStep } from "../types/index.js";
2
2
  type StepCallback = (step: InitStep) => void;
3
3
  /**
4
4
  * Add (install) a plugin from a GitHub source.
@@ -36,5 +36,14 @@ export declare function runPluginExportCodex(name: string, onStep: StepCallback)
36
36
  * Import an Agent Skills spec package and convert to javi-forge plugin format.
37
37
  */
38
38
  export declare function runPluginImport(sourceDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
39
+ /**
40
+ * Generate a project-level skills.json from all installed plugins.
41
+ * Makes the project discoverable by `npx skills add` and 40+ AI agents.
42
+ */
43
+ export declare function runPluginExportSkillsJson(projectDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
44
+ /**
45
+ * Generate a global skills.json from all globally installed plugins.
46
+ */
47
+ export declare function runPluginExportGlobalSkillsJson(dryRun: boolean, onStep: StepCallback): Promise<void>;
39
48
  export {};
40
49
  //# sourceMappingURL=plugin.d.ts.map