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,9 +1,17 @@
1
- import React, { useState, useEffect, useRef } from 'react';
2
- import { Box, Text, useInput } from 'ink';
3
- import { detectStack, STACK_LABELS } from '../lib/common.js';
4
- import { theme } from './theme.js';
5
- import { useCIMode } from './CIContext.js';
6
- const ALL_STACKS = ['node', 'python', 'go', 'rust', 'java-gradle', 'java-maven', 'elixir'];
1
+ import { Box, Text, useInput } from "ink";
2
+ import React, { useEffect, useRef, useState } from "react";
3
+ import { detectStack, STACK_LABELS } from "../lib/common.js";
4
+ import { useCIMode } from "./CIContext.js";
5
+ import { theme } from "./theme.js";
6
+ const ALL_STACKS = [
7
+ "node",
8
+ "python",
9
+ "go",
10
+ "rust",
11
+ "java-gradle",
12
+ "java-maven",
13
+ "elixir",
14
+ ];
7
15
  export default function StackSelector({ projectDir, onConfirm }) {
8
16
  const isCI = useCIMode();
9
17
  const autoConfirmed = useRef(false);
@@ -11,7 +19,7 @@ export default function StackSelector({ projectDir, onConfirm }) {
11
19
  const [detectedStack, setDetectedStack] = useState(null);
12
20
  const [detecting, setDetecting] = useState(true);
13
21
  useEffect(() => {
14
- detectStack(projectDir).then(result => {
22
+ detectStack(projectDir).then((result) => {
15
23
  if (result) {
16
24
  setDetectedStack(result.stackType);
17
25
  const idx = ALL_STACKS.indexOf(result.stackType);
@@ -28,13 +36,13 @@ export default function StackSelector({ projectDir, onConfirm }) {
28
36
  onConfirm(ALL_STACKS[cursor]);
29
37
  }
30
38
  }, [isCI, detecting]); // eslint-disable-line react-hooks/exhaustive-deps
31
- useInput((input, key) => {
39
+ useInput((_input, key) => {
32
40
  if (detecting)
33
41
  return;
34
42
  if (key.upArrow)
35
- setCursor(c => Math.max(0, c - 1));
43
+ setCursor((c) => Math.max(0, c - 1));
36
44
  if (key.downArrow)
37
- setCursor(c => Math.min(ALL_STACKS.length - 1, c + 1));
45
+ setCursor((c) => Math.min(ALL_STACKS.length - 1, c + 1));
38
46
  if (key.return) {
39
47
  onConfirm(ALL_STACKS[cursor]);
40
48
  }
@@ -46,20 +54,22 @@ export default function StackSelector({ projectDir, onConfirm }) {
46
54
  return (React.createElement(Box, { flexDirection: "column" },
47
55
  React.createElement(Text, { bold: true }, "Select project stack:"),
48
56
  detectedStack && (React.createElement(Text, { color: theme.success },
49
- ' ',
57
+ " ",
50
58
  "Auto-detected: ",
51
59
  STACK_LABELS[detectedStack])),
52
60
  React.createElement(Box, { marginTop: 1, flexDirection: "column", borderStyle: "single", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, borderColor: theme.muted, paddingLeft: 1 }, ALL_STACKS.map((stack, i) => (React.createElement(Box, { key: stack },
53
- React.createElement(Text, { color: i === cursor ? theme.primary : 'white' },
54
- i === cursor ? '\u25b6 ' : ' ',
55
- stack === detectedStack ? '\u25c9' : '\u25cb',
61
+ React.createElement(Text, { color: i === cursor ? theme.primary : "white" },
62
+ i === cursor ? "\u25b6 " : " ",
63
+ stack === detectedStack ? "\u25c9" : "\u25cb",
56
64
  " ",
57
65
  STACK_LABELS[stack],
58
- stack === detectedStack && (React.createElement(Text, { color: theme.success, dimColor: true }, " (detected)"))))))),
66
+ stack === detectedStack && (React.createElement(Text, { color: theme.success, dimColor: true },
67
+ " ",
68
+ "(detected)"))))))),
59
69
  React.createElement(Box, { marginTop: 1, gap: 2 },
60
70
  React.createElement(Text, { color: theme.primary }, STACK_LABELS[ALL_STACKS[cursor]]),
61
71
  React.createElement(Text, { color: theme.muted, dimColor: true },
62
- '\u2191\u2193',
63
- " navigate Enter confirm"))));
72
+ "\u2191\u2193",
73
+ " navigate Enter confirm"))));
64
74
  }
65
75
  //# sourceMappingURL=StackSelector.js.map
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import type { InitStep } from '../types/index.js';
1
+ import React from "react";
2
+ import type { InitStep } from "../types/index.js";
3
3
  interface Props {
4
4
  steps: InitStep[];
5
5
  dryRun: boolean;
@@ -7,6 +7,6 @@ interface Props {
7
7
  stack?: string;
8
8
  elapsedMs?: number;
9
9
  }
10
- export default function Summary({ steps, dryRun, projectName, stack, elapsedMs }: Props): React.JSX.Element;
10
+ export default function Summary({ steps, dryRun, projectName, stack, elapsedMs, }: Props): React.JSX.Element;
11
11
  export {};
12
12
  //# sourceMappingURL=Summary.d.ts.map
@@ -1,29 +1,35 @@
1
- import React, { useEffect } from 'react';
2
- import { Box, Text, useApp, useInput } from 'ink';
3
- import { theme } from './theme.js';
4
- import { useCIMode } from './CIContext.js';
1
+ import { Box, Text, useApp, useInput } from "ink";
2
+ import React, { useEffect } from "react";
3
+ import { useCIMode } from "./CIContext.js";
4
+ import { theme } from "./theme.js";
5
5
  /** Map stack to the install command hint */
6
6
  function getInstallHint(stack) {
7
7
  switch (stack) {
8
- case 'node': return 'pnpm install';
9
- case 'python': return 'pip install -r requirements.txt';
10
- case 'go': return 'go mod tidy';
11
- case 'rust': return 'cargo build';
12
- case 'java-gradle': return './gradlew build';
13
- case 'java-maven': return 'mvn install';
14
- case 'elixir': return 'mix deps.get';
15
- default: return null;
8
+ case "node":
9
+ return "pnpm install";
10
+ case "python":
11
+ return "pip install -r requirements.txt";
12
+ case "go":
13
+ return "go mod tidy";
14
+ case "rust":
15
+ return "cargo build";
16
+ case "java-gradle":
17
+ return "./gradlew build";
18
+ case "java-maven":
19
+ return "mvn install";
20
+ case "elixir":
21
+ return "mix deps.get";
22
+ default:
23
+ return null;
16
24
  }
17
25
  }
18
- export default function Summary({ steps, dryRun, projectName, stack, elapsedMs }) {
26
+ export default function Summary({ steps, dryRun, projectName, stack, elapsedMs, }) {
19
27
  const { exit } = useApp();
20
28
  const isCI = useCIMode();
21
- const done = steps.filter(s => s.status === 'done').length;
22
- const skipped = steps.filter(s => s.status === 'skipped').length;
23
- const errors = steps.filter(s => s.status === 'error');
24
- const elapsed = elapsedMs != null
25
- ? `${(elapsedMs / 1000).toFixed(1)}s`
26
- : null;
29
+ const done = steps.filter((s) => s.status === "done").length;
30
+ const skipped = steps.filter((s) => s.status === "skipped").length;
31
+ const errors = steps.filter((s) => s.status === "error");
32
+ const elapsed = elapsedMs != null ? `${(elapsedMs / 1000).toFixed(1)}s` : null;
27
33
  // Auto-exit in CI mode
28
34
  useEffect(() => {
29
35
  if (isCI) {
@@ -39,75 +45,79 @@ export default function Summary({ steps, dryRun, projectName, stack, elapsedMs }
39
45
  const installHint = getInstallHint(stack);
40
46
  return (React.createElement(Box, { flexDirection: "column" },
41
47
  React.createElement(Text, { bold: true, color: errors.length > 0 ? theme.warning : theme.success },
42
- dryRun ? '\u25cb Dry run complete' : '\u2713 Project scaffolded',
48
+ dryRun ? "\u25cb Dry run complete" : "\u2713 Project scaffolded",
43
49
  elapsed && React.createElement(Text, { color: theme.muted },
44
- " Completed in ",
50
+ " Completed in ",
45
51
  elapsed)),
46
52
  React.createElement(Box, { marginTop: 1 },
47
- React.createElement(Text, { color: theme.muted }, " Project: "),
53
+ React.createElement(Text, { color: theme.muted }, " Project: "),
48
54
  React.createElement(Text, { color: theme.primary, bold: true }, projectName),
49
55
  stack && React.createElement(Text, { color: theme.muted },
50
- " (",
56
+ " (",
51
57
  stack,
52
58
  ")")),
53
59
  dryRun && (React.createElement(Box, { marginTop: 1 },
54
- React.createElement(Text, { color: theme.warning, bold: true }, " No changes were made (dry run)"))),
55
- React.createElement(Box, { marginTop: 1, flexDirection: "column" }, steps.map(step => (React.createElement(Box, { key: step.id, marginLeft: 2 }, step.status === 'done' ? (React.createElement(Text, { color: theme.success },
56
- '\u2713',
60
+ React.createElement(Text, { color: theme.warning, bold: true },
61
+ " ",
62
+ "No changes were made (dry run)"))),
63
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, steps.map((step) => (React.createElement(Box, { key: step.id, marginLeft: 2 }, step.status === "done" ? (React.createElement(Text, { color: theme.success },
64
+ "\u2713",
57
65
  " ",
58
66
  step.label,
59
- step.detail ? React.createElement(Text, { color: theme.muted, dimColor: true },
60
- " ",
61
- step.detail) : null)) : step.status === 'skipped' ? (React.createElement(Text, { color: theme.muted },
62
- '\u2013',
67
+ step.detail ? (React.createElement(Text, { color: theme.muted, dimColor: true },
68
+ " ",
69
+ step.detail)) : null)) : step.status === "skipped" ? (React.createElement(Text, { color: theme.muted },
70
+ "\u2013",
63
71
  " ",
64
72
  step.label,
65
73
  step.detail ? React.createElement(Text, { dimColor: true },
66
- " ",
67
- step.detail) : null)) : step.status === 'error' ? (React.createElement(Text, { color: theme.error },
68
- '\u2717',
74
+ " ",
75
+ step.detail) : null)) : step.status === "error" ? (React.createElement(Text, { color: theme.error },
76
+ "\u2717",
69
77
  " ",
70
78
  step.label,
71
- step.detail ? React.createElement(Text, { color: theme.muted, dimColor: true },
72
- " ",
73
- step.detail) : null)) : null)))),
79
+ step.detail ? (React.createElement(Text, { color: theme.muted, dimColor: true },
80
+ " ",
81
+ step.detail)) : null)) : null)))),
74
82
  React.createElement(Box, { marginTop: 1, flexDirection: "column" },
75
83
  React.createElement(Text, { color: theme.success },
76
- " ",
77
- '\u2713',
84
+ " ",
85
+ "\u2713",
78
86
  " ",
79
87
  done,
80
88
  " steps completed"),
81
89
  skipped > 0 && (React.createElement(Text, { color: theme.muted },
82
- " ",
83
- '\u2013',
90
+ " ",
91
+ "\u2013",
84
92
  " ",
85
93
  skipped,
86
94
  " steps skipped")),
87
95
  errors.length > 0 && (React.createElement(Box, { flexDirection: "column" },
88
96
  React.createElement(Text, { color: theme.error },
89
- " ",
90
- '\u2717',
97
+ " ",
98
+ "\u2717",
91
99
  " ",
92
100
  errors.length,
93
101
  " errors:"),
94
- errors.map(e => (React.createElement(Text, { key: `err-${e.id}`, color: theme.error },
95
- " ",
96
- '\u2022',
102
+ errors.map((e) => (React.createElement(Text, { key: `err-${e.id}`, color: theme.error },
103
+ " ",
104
+ "\u2022",
97
105
  " ",
98
106
  e.label,
99
107
  ": ",
100
108
  e.detail)))))),
101
109
  !dryRun && errors.length === 0 && (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
102
- React.createElement(Text, { color: theme.muted, bold: true }, " Next steps:"),
110
+ React.createElement(Text, { color: theme.muted, bold: true },
111
+ " ",
112
+ "Next steps:"),
103
113
  React.createElement(Text, { color: theme.primary },
104
- " cd ",
114
+ " cd ",
105
115
  projectName),
106
116
  installHint && React.createElement(Text, { color: theme.primary },
107
- " ",
117
+ " ",
108
118
  installHint),
109
- React.createElement(Text, { color: theme.primary }, " npx javi-ai sync"),
110
- React.createElement(Text, { color: theme.primary }, " javi-forge doctor"))),
119
+ React.createElement(Text, { color: theme.primary }, " npx javi-ai sync"),
120
+ React.createElement(Text, { color: theme.primary }, " javi-forge doctor"))),
111
121
  React.createElement(Box, { marginTop: 1 },
112
122
  React.createElement(Text, { color: theme.muted, dimColor: true }, "Press Enter to exit"))));
113
123
  }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React from "react";
2
2
  interface Props {
3
3
  onDone: () => void;
4
4
  }
@@ -1,9 +1,9 @@
1
- import React, { useEffect } from 'react';
2
- import { Box, Text } from 'ink';
3
- import Spinner from 'ink-spinner';
4
- import Header from './Header.js';
5
- import { theme } from './theme.js';
6
- import { useCIMode } from './CIContext.js';
1
+ import { Box, Text } from "ink";
2
+ import Spinner from "ink-spinner";
3
+ import React, { useEffect } from "react";
4
+ import { useCIMode } from "./CIContext.js";
5
+ import Header from "./Header.js";
6
+ import { theme } from "./theme.js";
7
7
  export default function Welcome({ onDone }) {
8
8
  const isCI = useCIMode();
9
9
  useEffect(() => {
@@ -18,28 +18,27 @@ export default function Welcome({ onDone }) {
18
18
  React.createElement(Box, { marginTop: 1, flexDirection: "column" },
19
19
  React.createElement(Text, null,
20
20
  React.createElement(Text, { color: theme.primary },
21
- '\u25c6',
22
- " Templates "),
21
+ "\u25c6",
22
+ " Templates "),
23
23
  React.createElement(Text, { color: theme.muted }, " Go, Java, Node, Python, Rust CI")),
24
24
  React.createElement(Text, null,
25
25
  React.createElement(Text, { color: theme.success },
26
- '\u25c6',
27
- " Memory "),
26
+ "\u25c6",
27
+ " Memory "),
28
28
  React.createElement(Text, { color: theme.muted }, " Engram, Obsidian Brain")),
29
29
  React.createElement(Text, null,
30
30
  React.createElement(Text, { color: theme.accent },
31
- '\u25c6',
32
- " SDD "),
31
+ "\u25c6",
32
+ " SDD "),
33
33
  React.createElement(Text, { color: theme.muted }, " Spec-Driven Development")),
34
34
  React.createElement(Text, null,
35
35
  React.createElement(Text, { color: theme.warning },
36
- '\u25c6',
37
- " Review "),
36
+ "\u25c6",
37
+ " Review "),
38
38
  React.createElement(Text, { color: theme.muted }, " GHAGGA code review"))),
39
39
  React.createElement(Box, { marginTop: 1 },
40
40
  React.createElement(Text, { color: theme.muted },
41
41
  React.createElement(Spinner, { type: "dots" }),
42
- ' ',
43
- "Detecting your environment...")))));
42
+ " Detecting your environment...")))));
44
43
  }
45
44
  //# sourceMappingURL=Welcome.js.map
@@ -6,5 +6,5 @@ export declare const theme: {
6
6
  readonly muted: "gray";
7
7
  readonly accent: "magenta";
8
8
  };
9
- export type ThemeColor = typeof theme[keyof typeof theme];
9
+ export type ThemeColor = (typeof theme)[keyof typeof theme];
10
10
  //# sourceMappingURL=theme.d.ts.map
package/dist/ui/theme.js CHANGED
@@ -1,9 +1,9 @@
1
1
  export const theme = {
2
- primary: '#f97316', // orange
3
- success: 'green',
4
- warning: 'yellow',
5
- error: 'red',
6
- muted: 'gray',
7
- accent: 'magenta',
2
+ primary: "#f97316", // orange
3
+ success: "green",
4
+ warning: "yellow",
5
+ error: "red",
6
+ muted: "gray",
7
+ accent: "magenta",
8
8
  };
9
9
  //# sourceMappingURL=theme.js.map
@@ -0,0 +1,167 @@
1
+ # =============================================================================
2
+ # lib/common.psm1 - Shared functions for javi-forge (PowerShell)
3
+ # =============================================================================
4
+ # Mirror of lib/common.sh for Windows / PowerShell users.
5
+ #
6
+ # Import from scripts: Import-Module "$PSScriptRoot/../lib/common.psm1" -Force
7
+ # Import from ci-local: Import-Module "$PSScriptRoot/../lib/common.psm1" -Force
8
+ #
9
+ # Keep this file in sync with lib/common.sh. The function signatures use
10
+ # PowerShell verb-noun conventions but the BEHAVIOUR must match the bash
11
+ # version. Diff against lib/common.sh on every change.
12
+ # =============================================================================
13
+
14
+ Set-StrictMode -Version Latest
15
+
16
+ # =============================================================================
17
+ # Logging helpers
18
+ # =============================================================================
19
+ function Write-Ok { param([string]$Message) Write-Host " [OK] $Message" -ForegroundColor Green }
20
+ function Write-Warn { param([string]$Message) Write-Host " [WARN] $Message" -ForegroundColor Yellow }
21
+ function Write-Fail { param([string]$Message) Write-Host " [FAIL] $Message" -ForegroundColor Red }
22
+ function Write-Info { param([string]$Message) Write-Host " [INFO] $Message" -ForegroundColor Cyan }
23
+ function Write-Step { param([string]$Message) Write-Host $Message -ForegroundColor Yellow }
24
+
25
+ # =============================================================================
26
+ # Backup-FileIfExists - Create a .bak copy of a file before overwriting
27
+ # =============================================================================
28
+ function Backup-FileIfExists {
29
+ param([Parameter(Mandatory)][string]$Path)
30
+ if (Test-Path -LiteralPath $Path -PathType Leaf) {
31
+ Copy-Item -LiteralPath $Path -Destination "$Path.bak" -Force
32
+ Write-Host " Backed up existing $Path" -ForegroundColor Yellow
33
+ }
34
+ }
35
+
36
+ # =============================================================================
37
+ # Get-Stack - Auto-detect project technology stack
38
+ # =============================================================================
39
+ # Returns a hashtable with: StackType, BuildTool, JavaVersion
40
+ # Detects: java-gradle, java-maven, node, python, go, rust
41
+ # Mirrors detect_stack() from lib/common.sh.
42
+ # =============================================================================
43
+ function Get-Stack {
44
+ param([string]$ProjectDir = '.')
45
+
46
+ $result = @{
47
+ StackType = 'unknown'
48
+ BuildTool = ''
49
+ JavaVersion = '21'
50
+ }
51
+
52
+ # Allow user override via $env:CI_LOCAL_STACK. Mirrors the bash side.
53
+ $override = $env:CI_LOCAL_STACK
54
+ if ($override) {
55
+ $valid = @('node', 'python', 'go', 'rust', 'java-gradle', 'java-maven')
56
+ if ($valid -contains $override) {
57
+ $result.StackType = $override
58
+ switch ($override) {
59
+ 'node' {
60
+ if (Test-Path -LiteralPath (Join-Path $ProjectDir 'pnpm-lock.yaml') -PathType Leaf) { $result.BuildTool = 'pnpm' }
61
+ elseif (Test-Path -LiteralPath (Join-Path $ProjectDir 'yarn.lock') -PathType Leaf) { $result.BuildTool = 'yarn' }
62
+ else { $result.BuildTool = 'npm' }
63
+ }
64
+ 'python' {
65
+ if (Test-Path -LiteralPath (Join-Path $ProjectDir 'uv.lock') -PathType Leaf) { $result.BuildTool = 'uv' }
66
+ elseif (Test-Path -LiteralPath (Join-Path $ProjectDir 'poetry.lock') -PathType Leaf) { $result.BuildTool = 'poetry' }
67
+ elseif (Test-Path -LiteralPath (Join-Path $ProjectDir 'Pipfile') -PathType Leaf) { $result.BuildTool = 'pipenv' }
68
+ else { $result.BuildTool = 'pip' }
69
+ }
70
+ 'go' { $result.BuildTool = 'go' }
71
+ 'rust' { $result.BuildTool = 'cargo' }
72
+ 'java-gradle' { $result.BuildTool = 'gradle' }
73
+ 'java-maven' { $result.BuildTool = 'maven' }
74
+ }
75
+ return $result
76
+ }
77
+ Write-Warning "CI_LOCAL_STACK='$override' is not recognised. Falling back to auto-detection."
78
+ }
79
+
80
+ # Java + Gradle
81
+ $gradleKts = Join-Path $ProjectDir 'build.gradle.kts'
82
+ $gradle = Join-Path $ProjectDir 'build.gradle'
83
+ if ((Test-Path -LiteralPath $gradleKts -PathType Leaf) -or
84
+ (Test-Path -LiteralPath $gradle -PathType Leaf)) {
85
+ $result.StackType = 'java-gradle'
86
+ $result.BuildTool = 'gradle'
87
+ # Extract Java version from build file (regex parity with sh version)
88
+ $sourceFile = if (Test-Path -LiteralPath $gradleKts -PathType Leaf) { $gradleKts } else { $gradle }
89
+ try {
90
+ $content = Get-Content -LiteralPath $sourceFile -Raw -ErrorAction Stop
91
+ if ($sourceFile -like '*.kts') {
92
+ if ($content -match 'languageVersion\s*=\s*JavaLanguageVersion\.of\(\s*(\d+)') {
93
+ $result.JavaVersion = $Matches[1]
94
+ }
95
+ } else {
96
+ if ($content -match 'sourceCompatibility\s*=\s*[''"]?\s*(\d+)') {
97
+ $result.JavaVersion = $Matches[1]
98
+ }
99
+ }
100
+ } catch {
101
+ # Keep default '21'
102
+ }
103
+ return $result
104
+ }
105
+
106
+ # Java + Maven
107
+ if (Test-Path -LiteralPath (Join-Path $ProjectDir 'pom.xml') -PathType Leaf) {
108
+ $result.StackType = 'java-maven'
109
+ $result.BuildTool = 'maven'
110
+ return $result
111
+ }
112
+
113
+ # Node.js
114
+ if (Test-Path -LiteralPath (Join-Path $ProjectDir 'package.json') -PathType Leaf) {
115
+ $result.StackType = 'node'
116
+ if (Test-Path -LiteralPath (Join-Path $ProjectDir 'pnpm-lock.yaml') -PathType Leaf) { $result.BuildTool = 'pnpm' }
117
+ elseif (Test-Path -LiteralPath (Join-Path $ProjectDir 'yarn.lock') -PathType Leaf) { $result.BuildTool = 'yarn' }
118
+ else { $result.BuildTool = 'npm' }
119
+ return $result
120
+ }
121
+
122
+ # Python — uv > poetry > pipenv > pip
123
+ $pyMarker = @('pyproject.toml', 'setup.py', 'requirements.txt') |
124
+ ForEach-Object { Join-Path $ProjectDir $_ } |
125
+ Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } |
126
+ Select-Object -First 1
127
+ if ($pyMarker) {
128
+ $result.StackType = 'python'
129
+ if (Test-Path -LiteralPath (Join-Path $ProjectDir 'uv.lock') -PathType Leaf) { $result.BuildTool = 'uv' }
130
+ elseif (Test-Path -LiteralPath (Join-Path $ProjectDir 'poetry.lock') -PathType Leaf) { $result.BuildTool = 'poetry' }
131
+ elseif (Test-Path -LiteralPath (Join-Path $ProjectDir 'Pipfile') -PathType Leaf) { $result.BuildTool = 'pipenv' }
132
+ else { $result.BuildTool = 'pip' }
133
+ return $result
134
+ }
135
+
136
+ # Go
137
+ if (Test-Path -LiteralPath (Join-Path $ProjectDir 'go.mod') -PathType Leaf) {
138
+ $result.StackType = 'go'
139
+ $result.BuildTool = 'go'
140
+ return $result
141
+ }
142
+
143
+ # Rust
144
+ if (Test-Path -LiteralPath (Join-Path $ProjectDir 'Cargo.toml') -PathType Leaf) {
145
+ $result.StackType = 'rust'
146
+ $result.BuildTool = 'cargo'
147
+ return $result
148
+ }
149
+
150
+ return $result
151
+ }
152
+
153
+ # =============================================================================
154
+ # Test-CommandExists - Returns $true if a command is available in PATH
155
+ # =============================================================================
156
+ # Replaces "command -v X" from bash.
157
+ # =============================================================================
158
+ function Test-CommandExists {
159
+ param([Parameter(Mandatory)][string]$Name)
160
+ [bool](Get-Command -Name $Name -ErrorAction SilentlyContinue)
161
+ }
162
+
163
+ Export-ModuleMember -Function `
164
+ Write-Ok, Write-Warn, Write-Fail, Write-Info, Write-Step, `
165
+ Backup-FileIfExists, `
166
+ Get-Stack, `
167
+ Test-CommandExists
package/lib/common.sh CHANGED
@@ -95,6 +95,36 @@ detect_stack() {
95
95
  BUILD_TOOL=""
96
96
  JAVA_VERSION="21"
97
97
 
98
+ # Allow user to override auto-detection. Useful for hybrid projects
99
+ # (Node + Go) where the first-match rule otherwise locks the choice.
100
+ # Recognised values: node, python, go, rust, java-gradle, java-maven.
101
+ if [ -n "${CI_LOCAL_STACK:-}" ]; then
102
+ case "$CI_LOCAL_STACK" in
103
+ node|python|go|rust|java-gradle|java-maven)
104
+ STACK_TYPE="$CI_LOCAL_STACK"
105
+ case "$STACK_TYPE" in
106
+ node)
107
+ if [ -f "$project_dir/pnpm-lock.yaml" ]; then BUILD_TOOL="pnpm"
108
+ elif [ -f "$project_dir/yarn.lock" ]; then BUILD_TOOL="yarn"
109
+ else BUILD_TOOL="npm"; fi ;;
110
+ python)
111
+ if [ -f "$project_dir/uv.lock" ]; then BUILD_TOOL="uv"
112
+ elif [ -f "$project_dir/poetry.lock" ]; then BUILD_TOOL="poetry"
113
+ elif [ -f "$project_dir/Pipfile" ]; then BUILD_TOOL="pipenv"
114
+ else BUILD_TOOL="pip"; fi ;;
115
+ go) BUILD_TOOL="go" ;;
116
+ rust) BUILD_TOOL="cargo" ;;
117
+ java-gradle) BUILD_TOOL="gradle" ;;
118
+ java-maven) BUILD_TOOL="maven" ;;
119
+ esac
120
+ return
121
+ ;;
122
+ *)
123
+ echo "WARNING: CI_LOCAL_STACK='$CI_LOCAL_STACK' is not recognised. Falling back to auto-detection." >&2
124
+ ;;
125
+ esac
126
+ fi
127
+
98
128
  # Java + Gradle
99
129
  if [[ -f "$project_dir/build.gradle" || -f "$project_dir/build.gradle.kts" ]]; then
100
130
  STACK_TYPE="java-gradle"