javi-forge 1.5.0 → 1.6.1

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 (217) hide show
  1. package/README.md +191 -3
  2. package/ci-local/hooks/pre-push +17 -13
  3. package/dist/commands/analyze.d.ts +1 -1
  4. package/dist/commands/analyze.js +15 -15
  5. package/dist/commands/atlassian-mcp.d.ts +42 -0
  6. package/dist/commands/atlassian-mcp.js +98 -0
  7. package/dist/commands/ci.d.ts +3 -3
  8. package/dist/commands/ci.js +185 -147
  9. package/dist/commands/crash-recovery.d.ts +34 -0
  10. package/dist/commands/crash-recovery.js +123 -0
  11. package/dist/commands/doctor.d.ts +2 -2
  12. package/dist/commands/doctor.js +113 -61
  13. package/dist/commands/harness-audit.d.ts +35 -0
  14. package/dist/commands/harness-audit.js +277 -0
  15. package/dist/commands/init.d.ts +1 -1
  16. package/dist/commands/init.js +415 -118
  17. package/dist/commands/llmstxt.d.ts +1 -1
  18. package/dist/commands/llmstxt.js +36 -34
  19. package/dist/commands/parallel-batch.d.ts +42 -0
  20. package/dist/commands/parallel-batch.js +90 -0
  21. package/dist/commands/plugin.d.ts +26 -1
  22. package/dist/commands/plugin.js +138 -24
  23. package/dist/commands/secret-scanner.d.ts +30 -0
  24. package/dist/commands/secret-scanner.js +272 -0
  25. package/dist/commands/security-analysis.d.ts +74 -0
  26. package/dist/commands/security-analysis.js +487 -0
  27. package/dist/commands/security.d.ts +31 -0
  28. package/dist/commands/security.js +445 -0
  29. package/dist/commands/skill-scanner.d.ts +63 -0
  30. package/dist/commands/skill-scanner.js +383 -0
  31. package/dist/commands/skills.d.ts +139 -0
  32. package/dist/commands/skills.js +895 -0
  33. package/dist/commands/supply-chain.d.ts +23 -0
  34. package/dist/commands/supply-chain.js +126 -0
  35. package/dist/commands/tdd-pipeline.d.ts +17 -0
  36. package/dist/commands/tdd-pipeline.js +144 -0
  37. package/dist/commands/tdd.d.ts +21 -0
  38. package/dist/commands/tdd.js +120 -0
  39. package/dist/commands/team-presets.d.ts +53 -0
  40. package/dist/commands/team-presets.js +201 -0
  41. package/dist/commands/workflow.d.ts +23 -0
  42. package/dist/commands/workflow.js +114 -0
  43. package/dist/constants.d.ts +21 -0
  44. package/dist/constants.js +208 -37
  45. package/dist/index.js +400 -54
  46. package/dist/lib/agent-skills.d.ts +73 -0
  47. package/dist/lib/agent-skills.js +260 -0
  48. package/dist/lib/auto-skill-install.d.ts +37 -0
  49. package/dist/lib/auto-skill-install.js +92 -0
  50. package/dist/lib/auto-wire.d.ts +20 -0
  51. package/dist/lib/auto-wire.js +240 -0
  52. package/dist/lib/claudemd.d.ts +20 -0
  53. package/dist/lib/claudemd.js +222 -0
  54. package/dist/lib/codex-export.d.ts +16 -0
  55. package/dist/lib/codex-export.js +109 -0
  56. package/dist/lib/common.d.ts +1 -1
  57. package/dist/lib/common.js +52 -44
  58. package/dist/lib/context.d.ts +27 -0
  59. package/dist/lib/context.js +204 -0
  60. package/dist/lib/docker.d.ts +1 -1
  61. package/dist/lib/docker.js +141 -112
  62. package/dist/lib/frontmatter.d.ts +1 -1
  63. package/dist/lib/frontmatter.js +29 -15
  64. package/dist/lib/plugin.d.ts +19 -1
  65. package/dist/lib/plugin.js +174 -47
  66. package/dist/lib/skill-publish.d.ts +40 -0
  67. package/dist/lib/skill-publish.js +146 -0
  68. package/dist/lib/stack-detector.d.ts +38 -0
  69. package/dist/lib/stack-detector.js +207 -0
  70. package/dist/lib/template.d.ts +16 -1
  71. package/dist/lib/template.js +46 -17
  72. package/dist/lib/workflow/discovery.d.ts +19 -0
  73. package/dist/lib/workflow/discovery.js +68 -0
  74. package/dist/lib/workflow/index.d.ts +5 -0
  75. package/dist/lib/workflow/index.js +5 -0
  76. package/dist/lib/workflow/parser.d.ts +16 -0
  77. package/dist/lib/workflow/parser.js +198 -0
  78. package/dist/lib/workflow/renderer.d.ts +9 -0
  79. package/dist/lib/workflow/renderer.js +152 -0
  80. package/dist/lib/workflow/validator.d.ts +10 -0
  81. package/dist/lib/workflow/validator.js +189 -0
  82. package/dist/tasks/index.d.ts +4 -0
  83. package/dist/tasks/index.js +4 -0
  84. package/dist/tasks/scaffold-tasks.d.ts +3 -0
  85. package/dist/tasks/scaffold-tasks.js +14 -0
  86. package/dist/tasks/task-id.d.ts +30 -0
  87. package/dist/tasks/task-id.js +55 -0
  88. package/dist/tasks/task-tracker.d.ts +15 -0
  89. package/dist/tasks/task-tracker.js +81 -0
  90. package/dist/types/index.d.ts +252 -5
  91. package/dist/types/index.js +11 -1
  92. package/dist/ui/AnalyzeUI.d.ts +1 -1
  93. package/dist/ui/AnalyzeUI.js +38 -39
  94. package/dist/ui/App.d.ts +5 -3
  95. package/dist/ui/App.js +92 -46
  96. package/dist/ui/AutoSkills.d.ts +9 -0
  97. package/dist/ui/AutoSkills.js +124 -0
  98. package/dist/ui/CI.d.ts +2 -2
  99. package/dist/ui/CI.js +24 -26
  100. package/dist/ui/CIContext.d.ts +1 -1
  101. package/dist/ui/CIContext.js +3 -2
  102. package/dist/ui/CISelector.d.ts +2 -2
  103. package/dist/ui/CISelector.js +23 -15
  104. package/dist/ui/Doctor.d.ts +1 -1
  105. package/dist/ui/Doctor.js +35 -29
  106. package/dist/ui/Header.d.ts +1 -1
  107. package/dist/ui/Header.js +14 -14
  108. package/dist/ui/HookProfileSelector.d.ts +9 -0
  109. package/dist/ui/HookProfileSelector.js +54 -0
  110. package/dist/ui/LlmsTxt.d.ts +1 -1
  111. package/dist/ui/LlmsTxt.js +31 -22
  112. package/dist/ui/MemorySelector.d.ts +2 -2
  113. package/dist/ui/MemorySelector.js +28 -16
  114. package/dist/ui/NameInput.d.ts +1 -1
  115. package/dist/ui/NameInput.js +21 -21
  116. package/dist/ui/OptionSelector.d.ts +8 -2
  117. package/dist/ui/OptionSelector.js +83 -26
  118. package/dist/ui/Plugin.d.ts +4 -3
  119. package/dist/ui/Plugin.js +89 -29
  120. package/dist/ui/Progress.d.ts +3 -3
  121. package/dist/ui/Progress.js +23 -22
  122. package/dist/ui/Skills.d.ts +11 -0
  123. package/dist/ui/Skills.js +148 -0
  124. package/dist/ui/StackSelector.d.ts +2 -2
  125. package/dist/ui/StackSelector.js +26 -16
  126. package/dist/ui/Summary.d.ts +3 -3
  127. package/dist/ui/Summary.js +60 -50
  128. package/dist/ui/Welcome.d.ts +1 -1
  129. package/dist/ui/Welcome.js +15 -16
  130. package/dist/ui/theme.d.ts +1 -1
  131. package/dist/ui/theme.js +6 -6
  132. package/package.json +9 -6
  133. package/templates/common/atlassian/mcp-atlassian-snippet.json +16 -0
  134. package/templates/common/repoforge/mcp-repoforge-snippet.json +11 -0
  135. package/templates/common/repoforge/repoforge.yaml +34 -0
  136. package/templates/github/deploy-docker-zero-downtime.yml +140 -0
  137. package/templates/github/repoforge-graph.yml +45 -0
  138. package/templates/gitlab/deploy-docker-zero-downtime.yml +57 -0
  139. package/templates/local-ai/.env.example +17 -0
  140. package/templates/local-ai/docker-compose.yml +95 -0
  141. package/templates/security-hooks/claude-settings-security.json +30 -0
  142. package/templates/security-hooks/commit-msg-signing +29 -0
  143. package/templates/security-hooks/pre-commit-permissions +74 -0
  144. package/templates/security-hooks/pre-commit-secrets +74 -0
  145. package/templates/security-hooks/pre-push-branch-protection +62 -0
  146. package/templates/security-hooks/pre-push-deps +83 -0
  147. package/templates/security-hooks/pre-push-signing +67 -0
  148. package/templates/woodpecker/deploy-docker-zero-downtime.yml +50 -0
  149. package/templates/workflows/ci-pipeline.dot +15 -0
  150. package/templates/workflows/feature-flow.dot +21 -0
  151. package/templates/workflows/release.dot +16 -0
  152. package/dist/__integration__/helpers.d.ts +0 -20
  153. package/dist/__integration__/helpers.d.ts.map +0 -1
  154. package/dist/__integration__/helpers.js +0 -31
  155. package/dist/__integration__/helpers.js.map +0 -1
  156. package/dist/commands/analyze.d.ts.map +0 -1
  157. package/dist/commands/analyze.js.map +0 -1
  158. package/dist/commands/ci.d.ts.map +0 -1
  159. package/dist/commands/ci.js.map +0 -1
  160. package/dist/commands/doctor.d.ts.map +0 -1
  161. package/dist/commands/doctor.js.map +0 -1
  162. package/dist/commands/init.d.ts.map +0 -1
  163. package/dist/commands/init.js.map +0 -1
  164. package/dist/commands/llmstxt.d.ts.map +0 -1
  165. package/dist/commands/llmstxt.js.map +0 -1
  166. package/dist/commands/plugin.d.ts.map +0 -1
  167. package/dist/commands/plugin.js.map +0 -1
  168. package/dist/constants.d.ts.map +0 -1
  169. package/dist/constants.js.map +0 -1
  170. package/dist/index.d.ts.map +0 -1
  171. package/dist/index.js.map +0 -1
  172. package/dist/lib/common.d.ts.map +0 -1
  173. package/dist/lib/common.js.map +0 -1
  174. package/dist/lib/docker.d.ts.map +0 -1
  175. package/dist/lib/docker.js.map +0 -1
  176. package/dist/lib/frontmatter.d.ts.map +0 -1
  177. package/dist/lib/frontmatter.js.map +0 -1
  178. package/dist/lib/plugin.d.ts.map +0 -1
  179. package/dist/lib/plugin.js.map +0 -1
  180. package/dist/lib/template.d.ts.map +0 -1
  181. package/dist/lib/template.js.map +0 -1
  182. package/dist/types/index.d.ts.map +0 -1
  183. package/dist/types/index.js.map +0 -1
  184. package/dist/ui/AnalyzeUI.d.ts.map +0 -1
  185. package/dist/ui/AnalyzeUI.js.map +0 -1
  186. package/dist/ui/App.d.ts.map +0 -1
  187. package/dist/ui/App.js.map +0 -1
  188. package/dist/ui/CI.d.ts.map +0 -1
  189. package/dist/ui/CI.js.map +0 -1
  190. package/dist/ui/CIContext.d.ts.map +0 -1
  191. package/dist/ui/CIContext.js.map +0 -1
  192. package/dist/ui/CISelector.d.ts.map +0 -1
  193. package/dist/ui/CISelector.js.map +0 -1
  194. package/dist/ui/Doctor.d.ts.map +0 -1
  195. package/dist/ui/Doctor.js.map +0 -1
  196. package/dist/ui/Header.d.ts.map +0 -1
  197. package/dist/ui/Header.js.map +0 -1
  198. package/dist/ui/LlmsTxt.d.ts.map +0 -1
  199. package/dist/ui/LlmsTxt.js.map +0 -1
  200. package/dist/ui/MemorySelector.d.ts.map +0 -1
  201. package/dist/ui/MemorySelector.js.map +0 -1
  202. package/dist/ui/NameInput.d.ts.map +0 -1
  203. package/dist/ui/NameInput.js.map +0 -1
  204. package/dist/ui/OptionSelector.d.ts.map +0 -1
  205. package/dist/ui/OptionSelector.js.map +0 -1
  206. package/dist/ui/Plugin.d.ts.map +0 -1
  207. package/dist/ui/Plugin.js.map +0 -1
  208. package/dist/ui/Progress.d.ts.map +0 -1
  209. package/dist/ui/Progress.js.map +0 -1
  210. package/dist/ui/StackSelector.d.ts.map +0 -1
  211. package/dist/ui/StackSelector.js.map +0 -1
  212. package/dist/ui/Summary.d.ts.map +0 -1
  213. package/dist/ui/Summary.js.map +0 -1
  214. package/dist/ui/Welcome.d.ts.map +0 -1
  215. package/dist/ui/Welcome.js.map +0 -1
  216. package/dist/ui/theme.d.ts.map +0 -1
  217. package/dist/ui/theme.js.map +0 -1
@@ -1,6 +1,7 @@
1
- export type Stack = 'node' | 'python' | 'go' | 'rust' | 'java-gradle' | 'java-maven' | 'elixir';
2
- export type CIProvider = 'github' | 'gitlab' | 'woodpecker';
3
- export type MemoryOption = 'engram' | 'obsidian-brain' | 'memory-simple' | 'none';
1
+ export type Stack = "node" | "python" | "go" | "rust" | "java-gradle" | "java-maven" | "elixir";
2
+ export type CIProvider = "github" | "gitlab" | "woodpecker";
3
+ export type MemoryOption = "engram" | "obsidian-brain" | "memory-simple" | "none";
4
+ export type HookProfile = "minimal" | "standard" | "strict";
4
5
  export interface InitOptions {
5
6
  projectName: string;
6
7
  projectDir: string;
@@ -11,12 +12,32 @@ export interface InitOptions {
11
12
  sdd: boolean;
12
13
  ghagga: boolean;
13
14
  mock: boolean;
15
+ contextDir: boolean;
16
+ claudeMd: boolean;
17
+ securityHooks: boolean;
18
+ hookProfile: HookProfile;
19
+ codeGraph: boolean;
20
+ dockerDeploy: boolean;
21
+ /** Service name for docker rollout (default: 'app') */
22
+ dockerServiceName: string;
23
+ /** Scaffold local AI dev stack (Ollama + optional services) */
24
+ localAi: boolean;
14
25
  dryRun: boolean;
15
26
  }
27
+ export interface StackClaudeMdEntry {
28
+ skills: string[];
29
+ conventions: string;
30
+ testFramework: string;
31
+ }
32
+ export interface StackContextEntry {
33
+ tree: string;
34
+ conventions: string;
35
+ entryPoint: string;
36
+ }
16
37
  export interface InitStep {
17
38
  id: string;
18
39
  label: string;
19
- status: 'pending' | 'running' | 'done' | 'error' | 'skipped';
40
+ status: "pending" | "running" | "done" | "error" | "skipped";
20
41
  detail?: string;
21
42
  }
22
43
  export interface StackDetection {
@@ -36,7 +57,7 @@ export interface ForgeManifest {
36
57
  }
37
58
  export interface DoctorCheck {
38
59
  label: string;
39
- status: 'ok' | 'fail' | 'skip';
60
+ status: "ok" | "fail" | "skip";
40
61
  detail?: string;
41
62
  }
42
63
  export interface DoctorSection {
@@ -46,6 +67,13 @@ export interface DoctorSection {
46
67
  export interface DoctorResult {
47
68
  sections: DoctorSection[];
48
69
  }
70
+ export type TddPipelineMode = "strict" | "warn";
71
+ export interface TddPipelineResult {
72
+ installed: string[];
73
+ skipped: string[];
74
+ errors: string[];
75
+ mode: TddPipelineMode;
76
+ }
49
77
  export interface PluginManifest {
50
78
  name: string;
51
79
  version: string;
@@ -87,4 +115,223 @@ export interface InstalledPlugin {
87
115
  source: string;
88
116
  manifest: PluginManifest;
89
117
  }
118
+ export interface PluginSyncResult {
119
+ added: string[];
120
+ removed: string[];
121
+ unchanged: string[];
122
+ wired: AutoWireEntry[];
123
+ unwired: AutoWireEntry[];
124
+ }
125
+ export type AutoWireTarget = "claude-md" | "settings-json";
126
+ export interface AutoWireEntry {
127
+ plugin: string;
128
+ target: AutoWireTarget;
129
+ capability: string;
130
+ /** e.g. skill path or hook command */
131
+ value: string;
132
+ }
133
+ export interface AutoWireResult {
134
+ wired: AutoWireEntry[];
135
+ unwired: AutoWireEntry[];
136
+ errors: string[];
137
+ }
138
+ export interface AgentSkillEntry {
139
+ name: string;
140
+ description: string;
141
+ path: string;
142
+ }
143
+ export interface AgentSkillsManifest {
144
+ name: string;
145
+ version: string;
146
+ description: string;
147
+ skills: AgentSkillEntry[];
148
+ metadata?: {
149
+ forge_source?: string;
150
+ };
151
+ }
152
+ /**
153
+ * Aggregated skills.json that merges multiple plugins into a single
154
+ * Agent Skills spec manifest. Used by `npx skills add` and 40+ AI agents.
155
+ */
156
+ export interface AggregatedSkillsManifest {
157
+ name: string;
158
+ version: string;
159
+ description: string;
160
+ skills: AgentSkillEntry[];
161
+ sources: AgentSkillSource[];
162
+ }
163
+ export interface AgentSkillSource {
164
+ plugin: string;
165
+ version: string;
166
+ repository?: string;
167
+ }
168
+ export interface CodexTomlEntry {
169
+ name: string;
170
+ model: string;
171
+ instructions: string;
172
+ }
173
+ export interface CodexExportResult {
174
+ success: boolean;
175
+ files?: string[];
176
+ error?: string;
177
+ }
178
+ export type SecuritySeverity = "critical" | "high" | "moderate" | "low" | "info";
179
+ export interface SecurityFinding {
180
+ id: string;
181
+ severity: SecuritySeverity;
182
+ package: string;
183
+ title: string;
184
+ url?: string;
185
+ }
186
+ export interface SecurityBaseline {
187
+ version: string;
188
+ createdAt: string;
189
+ updatedAt?: string;
190
+ stack: string;
191
+ buildTool: string;
192
+ findings: SecurityFinding[];
193
+ findingKeys: string[];
194
+ allowlist?: string[];
195
+ }
196
+ export interface SecurityCheckOptions {
197
+ minSeverity?: SecuritySeverity;
198
+ staleDays?: number;
199
+ }
200
+ export interface SecurityCheckResult {
201
+ baseline: SecurityBaseline;
202
+ current: SecurityFinding[];
203
+ regressions: SecurityFinding[];
204
+ resolved: SecurityFinding[];
205
+ filteredRegressions: SecurityFinding[];
206
+ staleWarning?: string;
207
+ summary: SecuritySummary;
208
+ }
209
+ export interface SecuritySummary {
210
+ total: number;
211
+ bySeverity: Record<SecuritySeverity, number>;
212
+ regressionCount: number;
213
+ resolvedCount: number;
214
+ filteredCount: number;
215
+ baselineAge: number;
216
+ }
217
+ export interface SkillCriticalRule {
218
+ skillName: string;
219
+ skillPath: string;
220
+ rule: string;
221
+ /** Normalized rule for comparison (lowercase, trimmed) */
222
+ normalized: string;
223
+ }
224
+ export type ConflictKind = "regex-pair" | "directive-clash";
225
+ export interface SkillConflict {
226
+ ruleA: SkillCriticalRule;
227
+ ruleB: SkillCriticalRule;
228
+ reason: string;
229
+ /** How the conflict was detected */
230
+ kind: ConflictKind;
231
+ }
232
+ export interface SkillBudgetEntry {
233
+ skillName: string;
234
+ skillPath: string;
235
+ tokens: number;
236
+ }
237
+ export interface SkillBudgetSuggestion {
238
+ /** Skills to disable in this suggestion set */
239
+ disableSkills: string[];
240
+ /** Total tokens freed by disabling these skills */
241
+ tokensSaved: number;
242
+ /** Remaining tokens after disabling */
243
+ remainingTokens: number;
244
+ /** Whether this set brings usage under budget */
245
+ meetsbudget: boolean;
246
+ }
247
+ export interface SkillBudgetResult {
248
+ entries: SkillBudgetEntry[];
249
+ totalTokens: number;
250
+ budget: number;
251
+ overBudget: boolean;
252
+ suggestions: string[];
253
+ /** Structured optimization sets: minimal combinations to meet budget */
254
+ optimizations: SkillBudgetSuggestion[];
255
+ }
256
+ export interface SkillDuplicate {
257
+ skillA: string;
258
+ skillB: string;
259
+ /** Overlapping trigger keywords */
260
+ sharedTriggers: string[];
261
+ similarity: number;
262
+ }
263
+ export interface SkillDoctorResult {
264
+ conflicts: SkillConflict[];
265
+ budget: SkillBudgetResult;
266
+ duplicates: SkillDuplicate[];
267
+ }
268
+ export type SkillGrade = "A" | "B" | "C" | "D" | "F";
269
+ export interface SkillScore {
270
+ skillName: string;
271
+ completeness: number;
272
+ clarity: number;
273
+ testability: number;
274
+ tokenEfficiency: number;
275
+ safety: number;
276
+ agentReadiness: number;
277
+ overall: number;
278
+ grade: SkillGrade;
279
+ threshold: number;
280
+ passing: boolean;
281
+ }
282
+ export interface SkillRegistryGateResult {
283
+ skillName: string;
284
+ score: SkillScore;
285
+ accepted: boolean;
286
+ reason?: string;
287
+ }
288
+ export interface SkillBenchmarkCheck {
289
+ name: string;
290
+ passed: boolean;
291
+ detail?: string;
292
+ }
293
+ export interface SkillBenchmarkResult {
294
+ skillName: string;
295
+ checks: SkillBenchmarkCheck[];
296
+ passRate: number;
297
+ }
298
+ declare const WORKFLOW_FORMAT: {
299
+ readonly DOT: "dot";
300
+ readonly MERMAID: "mermaid";
301
+ };
302
+ export type WorkflowFormat = (typeof WORKFLOW_FORMAT)[keyof typeof WORKFLOW_FORMAT];
303
+ declare const WORKFLOW_VALIDATION_STATUS: {
304
+ readonly PASS: "pass";
305
+ readonly FAIL: "fail";
306
+ readonly SKIP: "skip";
307
+ };
308
+ export type WorkflowValidationStatus = (typeof WORKFLOW_VALIDATION_STATUS)[keyof typeof WORKFLOW_VALIDATION_STATUS];
309
+ export { WORKFLOW_FORMAT, WORKFLOW_VALIDATION_STATUS };
310
+ export interface WorkflowNode {
311
+ id: string;
312
+ label: string;
313
+ check?: string;
314
+ metadata?: Record<string, string>;
315
+ }
316
+ export interface WorkflowEdge {
317
+ from: string;
318
+ to: string;
319
+ label?: string;
320
+ }
321
+ export interface WorkflowGraph {
322
+ name: string;
323
+ nodes: WorkflowNode[];
324
+ edges: WorkflowEdge[];
325
+ format: WorkflowFormat;
326
+ }
327
+ export interface WorkflowValidationResult {
328
+ node: string;
329
+ status: WorkflowValidationStatus;
330
+ detail?: string;
331
+ }
332
+ export interface WorkflowDiscoveryEntry {
333
+ name: string;
334
+ path: string;
335
+ format: WorkflowFormat;
336
+ }
90
337
  //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1,12 @@
1
- export {};
1
+ // ── Workflow Graphs ─────────────────────────────────────────────────────────
2
+ const WORKFLOW_FORMAT = {
3
+ DOT: "dot",
4
+ MERMAID: "mermaid",
5
+ };
6
+ const WORKFLOW_VALIDATION_STATUS = {
7
+ PASS: "pass",
8
+ FAIL: "fail",
9
+ SKIP: "skip",
10
+ };
11
+ export { WORKFLOW_FORMAT, WORKFLOW_VALIDATION_STATUS };
2
12
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React from "react";
2
2
  interface Props {
3
3
  dryRun: boolean;
4
4
  }
@@ -1,10 +1,10 @@
1
- import React, { useEffect, useState } from 'react';
2
- import { Box, Text, useApp, useInput } from 'ink';
3
- import Spinner from 'ink-spinner';
4
- import { runAnalyze } from '../commands/analyze.js';
5
- import Header from './Header.js';
6
- import { theme } from './theme.js';
7
- import { useCIMode } from './CIContext.js';
1
+ import { Box, Text, useApp, useInput } from "ink";
2
+ import Spinner from "ink-spinner";
3
+ import React, { useEffect, useState } from "react";
4
+ import { runAnalyze } from "../commands/analyze.js";
5
+ import { useCIMode } from "./CIContext.js";
6
+ import Header from "./Header.js";
7
+ import { theme } from "./theme.js";
8
8
  export default function AnalyzeUI({ dryRun }) {
9
9
  const { exit } = useApp();
10
10
  const isCI = useCIMode();
@@ -12,8 +12,8 @@ export default function AnalyzeUI({ dryRun }) {
12
12
  const [finished, setFinished] = useState(false);
13
13
  const [startTime] = useState(Date.now());
14
14
  useEffect(() => {
15
- runAnalyze(process.cwd(), dryRun, (step) => setSteps(prev => {
16
- const idx = prev.findIndex(s => s.id === step.id);
15
+ runAnalyze(process.cwd(), dryRun, (step) => setSteps((prev) => {
16
+ const idx = prev.findIndex((s) => s.id === step.id);
17
17
  if (idx >= 0) {
18
18
  const next = [...prev];
19
19
  next[idx] = step;
@@ -34,9 +34,9 @@ export default function AnalyzeUI({ dryRun }) {
34
34
  if (finished && (key.return || key.escape))
35
35
  exit();
36
36
  }, { isActive: !isCI });
37
- const doneCount = steps.filter(s => s.status === 'done').length;
38
- const errorCount = steps.filter(s => s.status === 'error').length;
39
- const notInstalled = steps.some(s => s.status === 'error' && s.detail?.includes('not found'));
37
+ const doneCount = steps.filter((s) => s.status === "done").length;
38
+ const errorCount = steps.filter((s) => s.status === "error").length;
39
+ const notInstalled = steps.some((s) => s.status === "error" && s.detail?.includes("not found"));
40
40
  const elapsed = finished
41
41
  ? `${((Date.now() - startTime) / 1000).toFixed(1)}s`
42
42
  : null;
@@ -45,52 +45,51 @@ export default function AnalyzeUI({ dryRun }) {
45
45
  !finished && steps.length === 0 && (React.createElement(Box, { marginLeft: 2 },
46
46
  React.createElement(Text, { color: theme.warning },
47
47
  React.createElement(Spinner, { type: "dots" }),
48
- ' ',
49
- "Checking for repoforge..."))),
50
- React.createElement(Box, { flexDirection: "column" }, steps.map(step => (React.createElement(Box, { key: step.id, marginLeft: 2 }, step.status === 'running' ? (React.createElement(Text, { color: theme.warning },
48
+ " Checking for repoforge..."))),
49
+ React.createElement(Box, { flexDirection: "column" }, steps.map((step) => (React.createElement(Box, { key: step.id, marginLeft: 2 }, step.status === "running" ? (React.createElement(Text, { color: theme.warning },
51
50
  React.createElement(Spinner, { type: "dots" }),
52
- ' ',
53
- step.label)) : step.status === 'done' ? (React.createElement(Text, { color: theme.success },
54
- '\u2713',
51
+ " ",
52
+ step.label)) : step.status === "done" ? (React.createElement(Text, { color: theme.success },
53
+ "\u2713",
55
54
  " ",
56
55
  step.label,
57
- step.detail && React.createElement(Text, { color: theme.muted, dimColor: true },
58
- " ",
59
- step.detail))) : step.status === 'error' ? (React.createElement(Text, { color: theme.error },
60
- '\u2717',
56
+ step.detail && (React.createElement(Text, { color: theme.muted, dimColor: true },
57
+ " ",
58
+ step.detail)))) : step.status === "error" ? (React.createElement(Text, { color: theme.error },
59
+ "\u2717",
61
60
  " ",
62
61
  step.label,
63
- step.detail && React.createElement(Text, { color: theme.muted, dimColor: true },
64
- " ",
65
- step.detail))) : (React.createElement(Text, { color: theme.muted },
66
- '\u2013',
62
+ step.detail && (React.createElement(Text, { color: theme.muted, dimColor: true },
63
+ " ",
64
+ step.detail)))) : (React.createElement(Text, { color: theme.muted },
65
+ "\u2013",
67
66
  " ",
68
67
  step.label,
69
68
  step.detail && React.createElement(Text, { dimColor: true },
70
- " ",
69
+ " ",
71
70
  step.detail))))))),
72
71
  finished && notInstalled && (React.createElement(Box, { marginTop: 1, flexDirection: "column", marginLeft: 2 },
73
72
  React.createElement(Text, { color: theme.warning, bold: true }, "repoforge is not installed"),
74
73
  React.createElement(Box, { marginTop: 1, flexDirection: "column" },
75
- React.createElement(Text, { color: theme.muted }, " Install it with:"),
76
- React.createElement(Text, { color: theme.primary }, " pip install repoforge"),
77
- React.createElement(Text, { color: theme.muted }, " Then run:"),
78
- React.createElement(Text, { color: theme.primary }, " javi-forge analyze")))),
74
+ React.createElement(Text, { color: theme.muted }, " Install it with:"),
75
+ React.createElement(Text, { color: theme.primary }, " pip install repoforge"),
76
+ React.createElement(Text, { color: theme.muted }, " Then run:"),
77
+ React.createElement(Text, { color: theme.primary }, " javi-forge analyze")))),
79
78
  finished && (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
80
79
  React.createElement(Text, { bold: true, color: errorCount > 0 ? theme.warning : theme.success },
81
- dryRun ? '\u25cb Dry run complete' : '\u2713 Analysis complete',
82
- elapsed && React.createElement(Text, { color: theme.muted },
83
- " Completed in ",
84
- elapsed)),
80
+ dryRun ? "\u25cb Dry run complete" : "\u2713 Analysis complete",
81
+ elapsed && (React.createElement(Text, { color: theme.muted },
82
+ " Completed in ",
83
+ elapsed))),
85
84
  doneCount > 0 && (React.createElement(Text, { color: theme.success },
86
- " ",
87
- '\u2713',
85
+ " ",
86
+ "\u2713",
88
87
  " ",
89
88
  doneCount,
90
89
  " checks passed")),
91
90
  errorCount > 0 && (React.createElement(Text, { color: theme.error },
92
- " ",
93
- '\u2717',
91
+ " ",
92
+ "\u2717",
94
93
  " ",
95
94
  errorCount,
96
95
  " errors")),
package/dist/ui/App.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import type { Stack, CIProvider, MemoryOption } from '../types/index.js';
1
+ import React from "react";
2
+ import type { CIProvider, HookProfile, MemoryOption, Stack } from "../types/index.js";
3
3
  interface AppProps {
4
4
  dryRun?: boolean;
5
5
  presetStack?: Stack;
@@ -8,7 +8,9 @@ interface AppProps {
8
8
  presetName?: string;
9
9
  presetGhagga?: boolean;
10
10
  presetMock?: boolean;
11
+ presetLocalAi?: boolean;
12
+ presetHookProfile?: HookProfile;
11
13
  }
12
- export default function App({ dryRun, presetStack, presetCI, presetMemory, presetName, presetGhagga, presetMock, }: AppProps): React.JSX.Element;
14
+ export default function App({ dryRun, presetStack, presetCI, presetMemory, presetName, presetGhagga, presetMock, presetLocalAi, presetHookProfile, }: AppProps): React.JSX.Element;
13
15
  export {};
14
16
  //# sourceMappingURL=App.d.ts.map
package/dist/ui/App.js CHANGED
@@ -1,50 +1,85 @@
1
- import React, { useState } from 'react';
2
- import { Box } from 'ink';
3
- import path from 'path';
4
- import Welcome from './Welcome.js';
5
- import Header from './Header.js';
6
- import NameInput from './NameInput.js';
7
- import StackSelector from './StackSelector.js';
8
- import CISelector from './CISelector.js';
9
- import MemorySelector from './MemorySelector.js';
10
- import OptionSelector from './OptionSelector.js';
11
- import Progress from './Progress.js';
12
- import Summary from './Summary.js';
13
- import { initProject } from '../commands/init.js';
14
- export default function App({ dryRun = false, presetStack, presetCI, presetMemory, presetName, presetGhagga = false, presetMock = false, }) {
15
- const [stage, setStage] = useState('welcome');
16
- const [projectName, setProjectName] = useState(presetName ?? '');
17
- const [projectDir, setProjectDir] = useState(presetName ? path.resolve(process.cwd(), presetName) : '');
18
- const [stack, setStack] = useState(presetStack ?? 'node');
19
- const [ciProvider, setCIProvider] = useState(presetCI ?? 'github');
20
- const [memory, setMemory] = useState(presetMemory ?? 'engram');
1
+ import { Box } from "ink";
2
+ import path from "path";
3
+ import React, { useState } from "react";
4
+ import { initProject } from "../commands/init.js";
5
+ import CISelector from "./CISelector.js";
6
+ import Header from "./Header.js";
7
+ import HookProfileSelector from "./HookProfileSelector.js";
8
+ import MemorySelector from "./MemorySelector.js";
9
+ import NameInput from "./NameInput.js";
10
+ import OptionSelector from "./OptionSelector.js";
11
+ import Progress from "./Progress.js";
12
+ import StackSelector from "./StackSelector.js";
13
+ import Summary from "./Summary.js";
14
+ import Welcome from "./Welcome.js";
15
+ export default function App({ dryRun = false, presetStack, presetCI, presetMemory, presetName, presetGhagga = false, presetMock = false, presetLocalAi = false, presetHookProfile, }) {
16
+ const [stage, setStage] = useState("welcome");
17
+ const [projectName, setProjectName] = useState(presetName ?? "");
18
+ const [projectDir, setProjectDir] = useState(presetName ? path.resolve(process.cwd(), presetName) : "");
19
+ const [stack, setStack] = useState(presetStack ?? "node");
20
+ const [ciProvider, setCIProvider] = useState(presetCI ?? "github");
21
+ const [memory, setMemory] = useState(presetMemory ?? "engram");
21
22
  const [aiSync, setAiSync] = useState(true);
22
23
  const [sdd, setSdd] = useState(true);
24
+ const [contextDir, setContextDir] = useState(true);
25
+ const [claudeMd, setClaudeMd] = useState(true);
23
26
  const [ghagga, setGhagga] = useState(presetGhagga);
27
+ const [securityHooks, setSecurityHooks] = useState(true);
28
+ const [hookProfile, setHookProfile] = useState(presetHookProfile ?? "standard");
29
+ const [codeGraph, setCodeGraph] = useState(false);
30
+ const [localAi, setLocalAi] = useState(false);
24
31
  const [steps, setSteps] = useState([]);
25
32
  const [startTime] = useState(Date.now());
26
33
  const handleNameConfirm = (name, dir) => {
27
34
  setProjectName(name);
28
35
  setProjectDir(dir);
29
- setStage(presetStack ? 'ci' : 'stack');
36
+ setStage(presetStack ? "ci" : "stack");
30
37
  };
31
38
  const handleStackConfirm = (s) => {
32
39
  setStack(s);
33
- setStage(presetCI ? 'memory' : 'ci');
40
+ setStage(presetCI ? "memory" : "ci");
34
41
  };
35
42
  const handleCIConfirm = (p) => {
36
43
  setCIProvider(p);
37
- setStage(presetMemory ? 'options' : 'memory');
44
+ setStage(presetMemory ? "options" : "memory");
38
45
  };
39
46
  const handleMemoryConfirm = (m) => {
40
47
  setMemory(m);
41
- setStage('options');
48
+ setStage("options");
42
49
  };
43
- const handleOptionsConfirm = async (opts) => {
50
+ const handleOptionsConfirm = (opts) => {
44
51
  setAiSync(opts.aiSync);
45
52
  setSdd(opts.sdd);
53
+ setContextDir(opts.contextDir);
54
+ setClaudeMd(opts.claudeMd);
46
55
  setGhagga(opts.ghagga);
47
- setStage('running');
56
+ setSecurityHooks(opts.securityHooks);
57
+ setCodeGraph(opts.codeGraph);
58
+ setLocalAi(opts.localAi);
59
+ // If securityHooks is selected, ask for profile; otherwise skip to running
60
+ if (opts.securityHooks) {
61
+ setStage("hook-profile");
62
+ }
63
+ else {
64
+ void runInit({ ...opts, hookProfile });
65
+ }
66
+ };
67
+ const handleHookProfileConfirm = (profile) => {
68
+ setHookProfile(profile);
69
+ void runInit({
70
+ aiSync,
71
+ sdd,
72
+ contextDir,
73
+ claudeMd,
74
+ ghagga,
75
+ securityHooks,
76
+ codeGraph,
77
+ localAi,
78
+ hookProfile: profile,
79
+ });
80
+ };
81
+ const runInit = async (opts) => {
82
+ setStage("running");
48
83
  await initProject({
49
84
  projectName,
50
85
  projectDir,
@@ -54,10 +89,18 @@ export default function App({ dryRun = false, presetStack, presetCI, presetMemor
54
89
  aiSync: opts.aiSync,
55
90
  sdd: opts.sdd,
56
91
  ghagga: opts.ghagga,
92
+ contextDir: opts.contextDir,
93
+ claudeMd: opts.claudeMd,
94
+ securityHooks: opts.securityHooks,
95
+ hookProfile: opts.hookProfile,
96
+ codeGraph: opts.codeGraph,
97
+ localAi: opts.localAi,
98
+ dockerDeploy: false,
99
+ dockerServiceName: "app",
57
100
  mock: presetMock,
58
101
  dryRun,
59
- }, (step) => setSteps(prev => {
60
- const idx = prev.findIndex(s => s.id === step.id);
102
+ }, (step) => setSteps((prev) => {
103
+ const idx = prev.findIndex((s) => s.id === step.id);
61
104
  if (idx >= 0) {
62
105
  const next = [...prev];
63
106
  next[idx] = step;
@@ -65,37 +108,40 @@ export default function App({ dryRun = false, presetStack, presetCI, presetMemor
65
108
  }
66
109
  return [...prev, step];
67
110
  }));
68
- setStage('done');
111
+ setStage("done");
69
112
  };
70
- const subtitle = stage === 'running' ? 'scaffolding...' :
71
- stage === 'done' ? 'complete' :
72
- undefined;
113
+ const subtitle = stage === "running"
114
+ ? "scaffolding..."
115
+ : stage === "done"
116
+ ? "complete"
117
+ : undefined;
73
118
  return (React.createElement(Box, { flexDirection: "column", padding: 1 },
74
- stage !== 'welcome' && React.createElement(Header, { subtitle: subtitle, dryRun: dryRun }),
75
- stage === 'welcome' && (React.createElement(Welcome, { onDone: () => {
119
+ stage !== "welcome" && React.createElement(Header, { subtitle: subtitle, dryRun: dryRun }),
120
+ stage === "welcome" && (React.createElement(Welcome, { onDone: () => {
76
121
  // Skip stages for which presets are already provided
77
122
  if (presetName && presetStack && presetCI && presetMemory) {
78
- setStage('options');
123
+ setStage("options");
79
124
  }
80
125
  else if (presetName && presetStack && presetCI) {
81
- setStage('memory');
126
+ setStage("memory");
82
127
  }
83
128
  else if (presetName && presetStack) {
84
- setStage('ci');
129
+ setStage("ci");
85
130
  }
86
131
  else if (presetName) {
87
- setStage('stack');
132
+ setStage("stack");
88
133
  }
89
134
  else {
90
- setStage('name');
135
+ setStage("name");
91
136
  }
92
137
  } })),
93
- stage === 'name' && (React.createElement(NameInput, { defaultName: projectName || 'my-project', onConfirm: handleNameConfirm })),
94
- stage === 'stack' && (React.createElement(StackSelector, { projectDir: projectDir || process.cwd(), onConfirm: handleStackConfirm })),
95
- stage === 'ci' && (React.createElement(CISelector, { onConfirm: handleCIConfirm })),
96
- stage === 'memory' && (React.createElement(MemorySelector, { onConfirm: handleMemoryConfirm })),
97
- stage === 'options' && (React.createElement(OptionSelector, { onConfirm: handleOptionsConfirm, presetGhagga: presetGhagga })),
98
- stage === 'running' && (React.createElement(Progress, { steps: steps, projectName: projectName, contextLine: `${projectName} (${stack} + ${ciProvider})`, onDone: () => setStage('done') })),
99
- stage === 'done' && (React.createElement(Summary, { steps: steps, dryRun: dryRun, projectName: projectName, stack: stack, elapsedMs: Date.now() - startTime }))));
138
+ stage === "name" && (React.createElement(NameInput, { defaultName: projectName || "my-project", onConfirm: handleNameConfirm })),
139
+ stage === "stack" && (React.createElement(StackSelector, { projectDir: projectDir || process.cwd(), onConfirm: handleStackConfirm })),
140
+ stage === "ci" && React.createElement(CISelector, { onConfirm: handleCIConfirm }),
141
+ stage === "memory" && React.createElement(MemorySelector, { onConfirm: handleMemoryConfirm }),
142
+ stage === "options" && (React.createElement(OptionSelector, { onConfirm: handleOptionsConfirm, presetGhagga: presetGhagga, presetLocalAi: presetLocalAi })),
143
+ stage === "hook-profile" && (React.createElement(HookProfileSelector, { onConfirm: handleHookProfileConfirm, presetProfile: presetHookProfile })),
144
+ stage === "running" && (React.createElement(Progress, { steps: steps, projectName: projectName, contextLine: `${projectName} (${stack} + ${ciProvider})`, onDone: () => setStage("done") })),
145
+ stage === "done" && (React.createElement(Summary, { steps: steps, dryRun: dryRun, projectName: projectName, stack: stack, elapsedMs: Date.now() - startTime }))));
100
146
  }
101
147
  //# sourceMappingURL=App.js.map
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ interface AutoSkillsProps {
3
+ projectDir: string;
4
+ skillsDir?: string;
5
+ dryRun?: boolean;
6
+ }
7
+ export default function AutoSkills({ projectDir, skillsDir, dryRun, }: AutoSkillsProps): React.JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=AutoSkills.d.ts.map