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
@@ -0,0 +1,189 @@
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ /**
4
+ * Built-in check functions that map node `check` attributes to project validations.
5
+ * Each check receives the project directory and returns { pass, detail }.
6
+ */
7
+ const BUILTIN_CHECKS = {
8
+ "has-linter": async (dir) => {
9
+ const eslintConfig = [
10
+ ".eslintrc",
11
+ ".eslintrc.js",
12
+ ".eslintrc.json",
13
+ ".eslintrc.yml",
14
+ "eslint.config.js",
15
+ "eslint.config.mjs",
16
+ "eslint.config.ts",
17
+ ];
18
+ const ruffConfig = ["ruff.toml", ".ruff.toml"];
19
+ const golangci = [".golangci.yml", ".golangci.yaml"];
20
+ const configs = [...eslintConfig, ...ruffConfig, ...golangci];
21
+ for (const cfg of configs) {
22
+ if (await fs.pathExists(path.join(dir, cfg))) {
23
+ return { pass: true, detail: `Found ${cfg}` };
24
+ }
25
+ }
26
+ // Check package.json for eslint dependency
27
+ const pkgPath = path.join(dir, "package.json");
28
+ if (await fs.pathExists(pkgPath)) {
29
+ try {
30
+ const pkg = (await fs.readJson(pkgPath));
31
+ const deps = {
32
+ ...pkg.devDependencies,
33
+ ...pkg.dependencies,
34
+ };
35
+ if (deps.eslint || deps.biome || deps.oxlint) {
36
+ return { pass: true, detail: "Linter found in package.json" };
37
+ }
38
+ }
39
+ catch {
40
+ /* ignore */
41
+ }
42
+ }
43
+ return { pass: false, detail: "No linter configuration found" };
44
+ },
45
+ "has-tests": async (dir) => {
46
+ const testPatterns = [
47
+ "src/**/*.test.ts",
48
+ "src/**/*.test.tsx",
49
+ "src/**/*.spec.ts",
50
+ "tests/",
51
+ "test/",
52
+ "__tests__/",
53
+ "src/**/*_test.go",
54
+ "*_test.go",
55
+ "tests/test_*.py",
56
+ "test_*.py",
57
+ ];
58
+ for (const pattern of testPatterns) {
59
+ const target = path.join(dir, pattern.split("*")[0] ?? "");
60
+ if (await fs.pathExists(target)) {
61
+ return {
62
+ pass: true,
63
+ detail: `Found test path: ${pattern.split("*")[0]}`,
64
+ };
65
+ }
66
+ }
67
+ return { pass: false, detail: "No test files or directories found" };
68
+ },
69
+ "has-ci": async (dir) => {
70
+ const ciPaths = [
71
+ ".github/workflows",
72
+ ".gitlab-ci.yml",
73
+ ".woodpecker.yml",
74
+ ".woodpecker/",
75
+ "Jenkinsfile",
76
+ ".circleci/config.yml",
77
+ ];
78
+ for (const p of ciPaths) {
79
+ if (await fs.pathExists(path.join(dir, p))) {
80
+ return { pass: true, detail: `Found ${p}` };
81
+ }
82
+ }
83
+ return { pass: false, detail: "No CI configuration found" };
84
+ },
85
+ "has-dockerfile": async (dir) => {
86
+ const dockerfiles = [
87
+ "Dockerfile",
88
+ "docker-compose.yml",
89
+ "docker-compose.yaml",
90
+ "compose.yml",
91
+ "compose.yaml",
92
+ ];
93
+ for (const f of dockerfiles) {
94
+ if (await fs.pathExists(path.join(dir, f))) {
95
+ return { pass: true, detail: `Found ${f}` };
96
+ }
97
+ }
98
+ return { pass: false, detail: "No Dockerfile or compose file found" };
99
+ },
100
+ "has-security": async (dir) => {
101
+ const secPaths = [
102
+ ".javi-forge/security-baseline.json",
103
+ "semgrep.yml",
104
+ ".semgrep.yml",
105
+ ".snyk",
106
+ ];
107
+ for (const p of secPaths) {
108
+ if (await fs.pathExists(path.join(dir, p))) {
109
+ return { pass: true, detail: `Found ${p}` };
110
+ }
111
+ }
112
+ return { pass: false, detail: "No security scanning configuration found" };
113
+ },
114
+ "has-docs": async (dir) => {
115
+ const docPaths = ["docs/", "README.md", "doc/", "documentation/"];
116
+ for (const p of docPaths) {
117
+ if (await fs.pathExists(path.join(dir, p))) {
118
+ return { pass: true, detail: `Found ${p}` };
119
+ }
120
+ }
121
+ return { pass: false, detail: "No documentation found" };
122
+ },
123
+ "has-changelog": async (dir) => {
124
+ const files = ["CHANGELOG.md", "CHANGES.md", "HISTORY.md"];
125
+ for (const f of files) {
126
+ if (await fs.pathExists(path.join(dir, f))) {
127
+ return { pass: true, detail: `Found ${f}` };
128
+ }
129
+ }
130
+ return { pass: false, detail: "No changelog found" };
131
+ },
132
+ "has-license": async (dir) => {
133
+ const files = ["LICENSE", "LICENSE.md", "LICENSE.txt", "LICENCE"];
134
+ for (const f of files) {
135
+ if (await fs.pathExists(path.join(dir, f))) {
136
+ return { pass: true, detail: `Found ${f}` };
137
+ }
138
+ }
139
+ return { pass: false, detail: "No license file found" };
140
+ },
141
+ };
142
+ /**
143
+ * Validate a project directory against a workflow graph.
144
+ * Nodes with a `check` attribute are evaluated against built-in checks.
145
+ * Nodes without a `check` attribute are skipped.
146
+ */
147
+ export async function validateWorkflow(graph, projectDir) {
148
+ const results = [];
149
+ for (const node of graph.nodes) {
150
+ if (!node.check) {
151
+ results.push({
152
+ node: node.id,
153
+ status: "skip",
154
+ detail: "No check defined",
155
+ });
156
+ continue;
157
+ }
158
+ const checkFn = BUILTIN_CHECKS[node.check];
159
+ if (!checkFn) {
160
+ results.push({
161
+ node: node.id,
162
+ status: "skip",
163
+ detail: `Unknown check: ${node.check}`,
164
+ });
165
+ continue;
166
+ }
167
+ try {
168
+ const { pass, detail } = await checkFn(projectDir);
169
+ results.push({
170
+ node: node.id,
171
+ status: pass ? "pass" : "fail",
172
+ detail,
173
+ });
174
+ }
175
+ catch (e) {
176
+ results.push({
177
+ node: node.id,
178
+ status: "fail",
179
+ detail: `Check error: ${e instanceof Error ? e.message : String(e)}`,
180
+ });
181
+ }
182
+ }
183
+ return results;
184
+ }
185
+ /** Expose check names for testing and documentation */
186
+ export function getAvailableChecks() {
187
+ return Object.keys(BUILTIN_CHECKS);
188
+ }
189
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1,4 @@
1
+ export { getDefaultScaffoldTasks } from "./scaffold-tasks.js";
2
+ export { addSubtask, buildTaskTree, createTask, findTask, generateTaskId, type TaskNode, type TaskStatus, } from "./task-id.js";
3
+ export { TaskTracker } from "./task-tracker.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ export { getDefaultScaffoldTasks } from "./scaffold-tasks.js";
2
+ export { addSubtask, buildTaskTree, createTask, findTask, generateTaskId, } from "./task-id.js";
3
+ export { TaskTracker } from "./task-tracker.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ import { type TaskNode } from "./task-id.js";
2
+ export declare function getDefaultScaffoldTasks(): TaskNode[];
3
+ //# sourceMappingURL=scaffold-tasks.d.ts.map
@@ -0,0 +1,14 @@
1
+ import { addSubtask, createTask } from "./task-id.js";
2
+ export function getDefaultScaffoldTasks() {
3
+ const setup = createTask({ title: "Setup project structure" });
4
+ addSubtask(setup, { title: "Initialize git repository" });
5
+ addSubtask(setup, { title: "Configure TypeScript" });
6
+ addSubtask(setup, { title: "Setup linter and formatter" });
7
+ const testing = createTask({ title: "Setup testing" });
8
+ addSubtask(testing, { title: "Configure test runner" });
9
+ addSubtask(testing, { title: "Write initial tests" });
10
+ const ci = createTask({ title: "Create CI pipeline" });
11
+ const deploy = createTask({ title: "Deploy to production" });
12
+ return [setup, testing, ci, deploy];
13
+ }
14
+ //# sourceMappingURL=scaffold-tasks.js.map
@@ -0,0 +1,30 @@
1
+ export type TaskStatus = "todo" | "in-progress" | "done";
2
+ export type TaskNode = {
3
+ id: string;
4
+ title: string;
5
+ description?: string;
6
+ status: TaskStatus;
7
+ parentId?: string;
8
+ children: TaskNode[];
9
+ dependencies: string[];
10
+ assignee?: string;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ };
14
+ export declare function generateTaskId(content: {
15
+ title: string;
16
+ description?: string;
17
+ parentId?: string;
18
+ }): string;
19
+ export declare function createTask(params: {
20
+ title: string;
21
+ description?: string;
22
+ parentId?: string;
23
+ }): TaskNode;
24
+ export declare function addSubtask(parent: TaskNode, childParams: {
25
+ title: string;
26
+ description?: string;
27
+ }): TaskNode;
28
+ export declare function buildTaskTree(flat: TaskNode[]): TaskNode[];
29
+ export declare function findTask(tree: TaskNode[], id: string): TaskNode | undefined;
30
+ //# sourceMappingURL=task-id.d.ts.map
@@ -0,0 +1,59 @@
1
+ import { createHash } from "node:crypto";
2
+ export function generateTaskId(content) {
3
+ const input = [
4
+ content.title,
5
+ content.description ?? "",
6
+ content.parentId ?? "",
7
+ ].join("|");
8
+ return createHash("sha256").update(input).digest("hex").slice(0, 7);
9
+ }
10
+ export function createTask(params) {
11
+ const now = new Date().toISOString();
12
+ return {
13
+ id: generateTaskId(params),
14
+ title: params.title,
15
+ description: params.description,
16
+ status: "todo",
17
+ parentId: params.parentId,
18
+ children: [],
19
+ dependencies: [],
20
+ createdAt: now,
21
+ updatedAt: now,
22
+ };
23
+ }
24
+ export function addSubtask(parent, childParams) {
25
+ const child = createTask({
26
+ title: childParams.title,
27
+ description: childParams.description,
28
+ parentId: parent.id,
29
+ });
30
+ parent.children.push(child);
31
+ return child;
32
+ }
33
+ export function buildTaskTree(flat) {
34
+ const map = new Map();
35
+ for (const node of flat) {
36
+ map.set(node.id, { ...node, children: [] });
37
+ }
38
+ const roots = [];
39
+ for (const node of map.values()) {
40
+ if (node.parentId && map.has(node.parentId)) {
41
+ map.get(node.parentId)?.children.push(node);
42
+ }
43
+ else {
44
+ roots.push(node);
45
+ }
46
+ }
47
+ return roots;
48
+ }
49
+ export function findTask(tree, id) {
50
+ for (const node of tree) {
51
+ if (node.id === id)
52
+ return node;
53
+ const found = findTask(node.children, id);
54
+ if (found)
55
+ return found;
56
+ }
57
+ return undefined;
58
+ }
59
+ //# sourceMappingURL=task-id.js.map
@@ -0,0 +1,15 @@
1
+ import { type TaskNode, type TaskStatus } from "./task-id.js";
2
+ export declare class TaskTracker {
3
+ private tasks;
4
+ addTask(title: string, description?: string, parentId?: string): TaskNode;
5
+ updateStatus(id: string, status: TaskStatus): void;
6
+ assignTask(id: string, assignee: string): void;
7
+ addDependency(taskId: string, dependsOnId: string): void;
8
+ getBlockedTasks(): TaskNode[];
9
+ getReadyTasks(): TaskNode[];
10
+ toMarkdown(): string;
11
+ toJSON(): string;
12
+ static fromJSON(json: string): TaskTracker;
13
+ private findFlat;
14
+ }
15
+ //# sourceMappingURL=task-tracker.d.ts.map
@@ -0,0 +1,81 @@
1
+ import { createTask } from "./task-id.js";
2
+ export class TaskTracker {
3
+ tasks = [];
4
+ addTask(title, description, parentId) {
5
+ const task = createTask({ title, description, parentId });
6
+ if (parentId) {
7
+ const parent = this.findFlat(parentId);
8
+ if (parent) {
9
+ parent.children.push(task);
10
+ }
11
+ }
12
+ this.tasks.push(task);
13
+ return task;
14
+ }
15
+ updateStatus(id, status) {
16
+ const task = this.findFlat(id);
17
+ if (!task)
18
+ throw new Error(`Task "${id}" not found`);
19
+ task.status = status;
20
+ task.updatedAt = new Date().toISOString();
21
+ }
22
+ assignTask(id, assignee) {
23
+ const task = this.findFlat(id);
24
+ if (!task)
25
+ throw new Error(`Task "${id}" not found`);
26
+ task.assignee = assignee;
27
+ task.updatedAt = new Date().toISOString();
28
+ }
29
+ addDependency(taskId, dependsOnId) {
30
+ const task = this.findFlat(taskId);
31
+ if (!task)
32
+ throw new Error(`Task "${taskId}" not found`);
33
+ const dep = this.findFlat(dependsOnId);
34
+ if (!dep)
35
+ throw new Error(`Dependency "${dependsOnId}" not found`);
36
+ task.dependencies.push(dependsOnId);
37
+ }
38
+ getBlockedTasks() {
39
+ return this.tasks.filter((t) => {
40
+ if (t.dependencies.length === 0)
41
+ return false;
42
+ return t.dependencies.some((depId) => {
43
+ const dep = this.findFlat(depId);
44
+ return !dep || dep.status !== "done";
45
+ });
46
+ });
47
+ }
48
+ getReadyTasks() {
49
+ return this.tasks.filter((t) => {
50
+ if (t.status !== "todo")
51
+ return false;
52
+ if (t.dependencies.length === 0)
53
+ return true;
54
+ return t.dependencies.every((depId) => {
55
+ const dep = this.findFlat(depId);
56
+ return dep?.status === "done";
57
+ });
58
+ });
59
+ }
60
+ toMarkdown() {
61
+ return this.tasks
62
+ .map((t) => {
63
+ const check = t.status === "done" ? "x" : " ";
64
+ const assignee = t.assignee ? ` @${t.assignee}` : "";
65
+ return `- [${check}] ${t.title}${assignee}`;
66
+ })
67
+ .join("\n");
68
+ }
69
+ toJSON() {
70
+ return JSON.stringify(this.tasks);
71
+ }
72
+ static fromJSON(json) {
73
+ const tracker = new TaskTracker();
74
+ tracker.tasks = JSON.parse(json);
75
+ return tracker;
76
+ }
77
+ findFlat(id) {
78
+ return this.tasks.find((t) => t.id === id);
79
+ }
80
+ }
81
+ //# sourceMappingURL=task-tracker.js.map
@@ -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;
@@ -13,6 +14,14 @@ export interface InitOptions {
13
14
  mock: boolean;
14
15
  contextDir: boolean;
15
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;
16
25
  dryRun: boolean;
17
26
  }
18
27
  export interface StackClaudeMdEntry {
@@ -28,7 +37,7 @@ export interface StackContextEntry {
28
37
  export interface InitStep {
29
38
  id: string;
30
39
  label: string;
31
- status: 'pending' | 'running' | 'done' | 'error' | 'skipped';
40
+ status: "pending" | "running" | "done" | "error" | "skipped";
32
41
  detail?: string;
33
42
  }
34
43
  export interface StackDetection {
@@ -48,7 +57,7 @@ export interface ForgeManifest {
48
57
  }
49
58
  export interface DoctorCheck {
50
59
  label: string;
51
- status: 'ok' | 'fail' | 'skip';
60
+ status: "ok" | "fail" | "skip";
52
61
  detail?: string;
53
62
  }
54
63
  export interface DoctorSection {
@@ -58,6 +67,13 @@ export interface DoctorSection {
58
67
  export interface DoctorResult {
59
68
  sections: DoctorSection[];
60
69
  }
70
+ export type TddPipelineMode = "strict" | "warn";
71
+ export interface TddPipelineResult {
72
+ installed: string[];
73
+ skipped: string[];
74
+ errors: string[];
75
+ mode: TddPipelineMode;
76
+ }
61
77
  export interface PluginManifest {
62
78
  name: string;
63
79
  version: string;
@@ -103,6 +119,21 @@ export interface PluginSyncResult {
103
119
  added: string[];
104
120
  removed: string[];
105
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[];
106
137
  }
107
138
  export interface AgentSkillEntry {
108
139
  name: string;
@@ -118,6 +149,22 @@ export interface AgentSkillsManifest {
118
149
  forge_source?: string;
119
150
  };
120
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
+ }
121
168
  export interface CodexTomlEntry {
122
169
  name: string;
123
170
  model: string;
@@ -128,7 +175,7 @@ export interface CodexExportResult {
128
175
  files?: string[];
129
176
  error?: string;
130
177
  }
131
- export type SecuritySeverity = 'critical' | 'high' | 'moderate' | 'low' | 'info';
178
+ export type SecuritySeverity = "critical" | "high" | "moderate" | "low" | "info";
132
179
  export interface SecurityFinding {
133
180
  id: string;
134
181
  severity: SecuritySeverity;
@@ -139,16 +186,33 @@ export interface SecurityFinding {
139
186
  export interface SecurityBaseline {
140
187
  version: string;
141
188
  createdAt: string;
189
+ updatedAt?: string;
142
190
  stack: string;
143
191
  buildTool: string;
144
192
  findings: SecurityFinding[];
145
193
  findingKeys: string[];
194
+ allowlist?: string[];
195
+ }
196
+ export interface SecurityCheckOptions {
197
+ minSeverity?: SecuritySeverity;
198
+ staleDays?: number;
146
199
  }
147
200
  export interface SecurityCheckResult {
148
201
  baseline: SecurityBaseline;
149
202
  current: SecurityFinding[];
150
203
  regressions: SecurityFinding[];
151
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;
152
216
  }
153
217
  export interface SkillCriticalRule {
154
218
  skillName: string;
@@ -157,22 +221,37 @@ export interface SkillCriticalRule {
157
221
  /** Normalized rule for comparison (lowercase, trimmed) */
158
222
  normalized: string;
159
223
  }
224
+ export type ConflictKind = "regex-pair" | "directive-clash";
160
225
  export interface SkillConflict {
161
226
  ruleA: SkillCriticalRule;
162
227
  ruleB: SkillCriticalRule;
163
228
  reason: string;
229
+ /** How the conflict was detected */
230
+ kind: ConflictKind;
164
231
  }
165
232
  export interface SkillBudgetEntry {
166
233
  skillName: string;
167
234
  skillPath: string;
168
235
  tokens: number;
169
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
+ }
170
247
  export interface SkillBudgetResult {
171
248
  entries: SkillBudgetEntry[];
172
249
  totalTokens: number;
173
250
  budget: number;
174
251
  overBudget: boolean;
175
252
  suggestions: string[];
253
+ /** Structured optimization sets: minimal combinations to meet budget */
254
+ optimizations: SkillBudgetSuggestion[];
176
255
  }
177
256
  export interface SkillDuplicate {
178
257
  skillA: string;
@@ -186,16 +265,26 @@ export interface SkillDoctorResult {
186
265
  budget: SkillBudgetResult;
187
266
  duplicates: SkillDuplicate[];
188
267
  }
268
+ export type SkillGrade = "A" | "B" | "C" | "D" | "F";
189
269
  export interface SkillScore {
190
270
  skillName: string;
191
271
  completeness: number;
192
272
  clarity: number;
193
273
  testability: number;
194
274
  tokenEfficiency: number;
275
+ safety: number;
276
+ agentReadiness: number;
195
277
  overall: number;
278
+ grade: SkillGrade;
196
279
  threshold: number;
197
280
  passing: boolean;
198
281
  }
282
+ export interface SkillRegistryGateResult {
283
+ skillName: string;
284
+ score: SkillScore;
285
+ accepted: boolean;
286
+ reason?: string;
287
+ }
199
288
  export interface SkillBenchmarkCheck {
200
289
  name: string;
201
290
  passed: boolean;
@@ -206,4 +295,43 @@ export interface SkillBenchmarkResult {
206
295
  checks: SkillBenchmarkCheck[];
207
296
  passRate: number;
208
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
+ }
209
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
  }