javi-forge 1.6.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 (231) hide show
  1. package/dist/commands/analyze.d.ts +1 -1
  2. package/dist/commands/analyze.js +15 -15
  3. package/dist/commands/atlassian-mcp.d.ts +42 -0
  4. package/dist/commands/atlassian-mcp.js +98 -0
  5. package/dist/commands/ci.d.ts +3 -3
  6. package/dist/commands/ci.js +185 -147
  7. package/dist/commands/crash-recovery.d.ts +34 -0
  8. package/dist/commands/crash-recovery.js +123 -0
  9. package/dist/commands/doctor.d.ts +2 -2
  10. package/dist/commands/doctor.js +113 -61
  11. package/dist/commands/harness-audit.d.ts +35 -0
  12. package/dist/commands/harness-audit.js +277 -0
  13. package/dist/commands/init.d.ts +1 -1
  14. package/dist/commands/init.js +384 -141
  15. package/dist/commands/llmstxt.d.ts +1 -1
  16. package/dist/commands/llmstxt.js +36 -34
  17. package/dist/commands/parallel-batch.d.ts +42 -0
  18. package/dist/commands/parallel-batch.js +90 -0
  19. package/dist/commands/plugin.d.ts +10 -1
  20. package/dist/commands/plugin.js +92 -47
  21. package/dist/commands/secret-scanner.d.ts +30 -0
  22. package/dist/commands/secret-scanner.js +272 -0
  23. package/dist/commands/security-analysis.d.ts +74 -0
  24. package/dist/commands/security-analysis.js +487 -0
  25. package/dist/commands/security.d.ts +11 -5
  26. package/dist/commands/security.js +216 -76
  27. package/dist/commands/skill-scanner.d.ts +63 -0
  28. package/dist/commands/skill-scanner.js +383 -0
  29. package/dist/commands/skills.d.ts +62 -5
  30. package/dist/commands/skills.js +439 -54
  31. package/dist/commands/supply-chain.d.ts +23 -0
  32. package/dist/commands/supply-chain.js +126 -0
  33. package/dist/commands/tdd-pipeline.d.ts +17 -0
  34. package/dist/commands/tdd-pipeline.js +144 -0
  35. package/dist/commands/tdd.d.ts +1 -1
  36. package/dist/commands/tdd.js +21 -18
  37. package/dist/commands/team-presets.d.ts +53 -0
  38. package/dist/commands/team-presets.js +201 -0
  39. package/dist/commands/workflow.d.ts +23 -0
  40. package/dist/commands/workflow.js +114 -0
  41. package/dist/constants.d.ts +15 -1
  42. package/dist/constants.js +161 -122
  43. package/dist/index.js +308 -98
  44. package/dist/lib/agent-skills.d.ts +36 -1
  45. package/dist/lib/agent-skills.js +168 -19
  46. package/dist/lib/auto-skill-install.d.ts +37 -0
  47. package/dist/lib/auto-skill-install.js +92 -0
  48. package/dist/lib/auto-wire.d.ts +20 -0
  49. package/dist/lib/auto-wire.js +240 -0
  50. package/dist/lib/claudemd.d.ts +13 -1
  51. package/dist/lib/claudemd.js +174 -24
  52. package/dist/lib/codex-export.d.ts +1 -1
  53. package/dist/lib/codex-export.js +29 -31
  54. package/dist/lib/common.d.ts +1 -1
  55. package/dist/lib/common.js +52 -44
  56. package/dist/lib/context.d.ts +17 -2
  57. package/dist/lib/context.js +142 -13
  58. package/dist/lib/docker.d.ts +1 -1
  59. package/dist/lib/docker.js +141 -112
  60. package/dist/lib/frontmatter.d.ts +1 -1
  61. package/dist/lib/frontmatter.js +29 -15
  62. package/dist/lib/plugin.d.ts +9 -3
  63. package/dist/lib/plugin.js +128 -69
  64. package/dist/lib/skill-publish.d.ts +40 -0
  65. package/dist/lib/skill-publish.js +146 -0
  66. package/dist/lib/stack-detector.d.ts +38 -0
  67. package/dist/lib/stack-detector.js +207 -0
  68. package/dist/lib/template.d.ts +16 -1
  69. package/dist/lib/template.js +46 -17
  70. package/dist/lib/workflow/discovery.d.ts +19 -0
  71. package/dist/lib/workflow/discovery.js +68 -0
  72. package/dist/lib/workflow/index.d.ts +5 -0
  73. package/dist/lib/workflow/index.js +5 -0
  74. package/dist/lib/workflow/parser.d.ts +16 -0
  75. package/dist/lib/workflow/parser.js +198 -0
  76. package/dist/lib/workflow/renderer.d.ts +9 -0
  77. package/dist/lib/workflow/renderer.js +152 -0
  78. package/dist/lib/workflow/validator.d.ts +10 -0
  79. package/dist/lib/workflow/validator.js +189 -0
  80. package/dist/tasks/index.d.ts +4 -0
  81. package/dist/tasks/index.js +4 -0
  82. package/dist/tasks/scaffold-tasks.d.ts +3 -0
  83. package/dist/tasks/scaffold-tasks.js +14 -0
  84. package/dist/tasks/task-id.d.ts +30 -0
  85. package/dist/tasks/task-id.js +55 -0
  86. package/dist/tasks/task-tracker.d.ts +15 -0
  87. package/dist/tasks/task-tracker.js +81 -0
  88. package/dist/types/index.d.ts +134 -6
  89. package/dist/types/index.js +11 -1
  90. package/dist/ui/AnalyzeUI.d.ts +1 -1
  91. package/dist/ui/AnalyzeUI.js +38 -39
  92. package/dist/ui/App.d.ts +5 -3
  93. package/dist/ui/App.js +86 -46
  94. package/dist/ui/AutoSkills.d.ts +9 -0
  95. package/dist/ui/AutoSkills.js +124 -0
  96. package/dist/ui/CI.d.ts +2 -2
  97. package/dist/ui/CI.js +24 -26
  98. package/dist/ui/CIContext.d.ts +1 -1
  99. package/dist/ui/CIContext.js +3 -2
  100. package/dist/ui/CISelector.d.ts +2 -2
  101. package/dist/ui/CISelector.js +23 -15
  102. package/dist/ui/Doctor.d.ts +1 -1
  103. package/dist/ui/Doctor.js +35 -29
  104. package/dist/ui/Header.d.ts +1 -1
  105. package/dist/ui/Header.js +14 -14
  106. package/dist/ui/HookProfileSelector.d.ts +9 -0
  107. package/dist/ui/HookProfileSelector.js +54 -0
  108. package/dist/ui/LlmsTxt.d.ts +1 -1
  109. package/dist/ui/LlmsTxt.js +31 -22
  110. package/dist/ui/MemorySelector.d.ts +2 -2
  111. package/dist/ui/MemorySelector.js +28 -16
  112. package/dist/ui/NameInput.d.ts +1 -1
  113. package/dist/ui/NameInput.js +21 -21
  114. package/dist/ui/OptionSelector.d.ts +6 -2
  115. package/dist/ui/OptionSelector.js +83 -32
  116. package/dist/ui/Plugin.d.ts +4 -3
  117. package/dist/ui/Plugin.js +78 -35
  118. package/dist/ui/Progress.d.ts +3 -3
  119. package/dist/ui/Progress.js +23 -22
  120. package/dist/ui/Skills.d.ts +2 -2
  121. package/dist/ui/Skills.js +61 -32
  122. package/dist/ui/StackSelector.d.ts +2 -2
  123. package/dist/ui/StackSelector.js +26 -16
  124. package/dist/ui/Summary.d.ts +3 -3
  125. package/dist/ui/Summary.js +60 -50
  126. package/dist/ui/Welcome.d.ts +1 -1
  127. package/dist/ui/Welcome.js +15 -16
  128. package/dist/ui/theme.d.ts +1 -1
  129. package/dist/ui/theme.js +6 -6
  130. package/package.json +9 -6
  131. package/templates/common/atlassian/mcp-atlassian-snippet.json +16 -0
  132. package/templates/common/repoforge/mcp-repoforge-snippet.json +11 -0
  133. package/templates/common/repoforge/repoforge.yaml +34 -0
  134. package/templates/github/deploy-docker-zero-downtime.yml +140 -0
  135. package/templates/github/repoforge-graph.yml +45 -0
  136. package/templates/gitlab/deploy-docker-zero-downtime.yml +57 -0
  137. package/templates/local-ai/.env.example +17 -0
  138. package/templates/local-ai/docker-compose.yml +95 -0
  139. package/templates/security-hooks/claude-settings-security.json +30 -0
  140. package/templates/security-hooks/commit-msg-signing +29 -0
  141. package/templates/security-hooks/pre-commit-permissions +74 -0
  142. package/templates/security-hooks/pre-commit-secrets +74 -0
  143. package/templates/security-hooks/pre-push-branch-protection +62 -0
  144. package/templates/security-hooks/pre-push-deps +83 -0
  145. package/templates/security-hooks/pre-push-signing +67 -0
  146. package/templates/woodpecker/deploy-docker-zero-downtime.yml +50 -0
  147. package/templates/workflows/ci-pipeline.dot +15 -0
  148. package/templates/workflows/feature-flow.dot +21 -0
  149. package/templates/workflows/release.dot +16 -0
  150. package/dist/__integration__/helpers.d.ts +0 -20
  151. package/dist/__integration__/helpers.d.ts.map +0 -1
  152. package/dist/__integration__/helpers.js +0 -31
  153. package/dist/__integration__/helpers.js.map +0 -1
  154. package/dist/commands/analyze.d.ts.map +0 -1
  155. package/dist/commands/analyze.js.map +0 -1
  156. package/dist/commands/ci.d.ts.map +0 -1
  157. package/dist/commands/ci.js.map +0 -1
  158. package/dist/commands/doctor.d.ts.map +0 -1
  159. package/dist/commands/doctor.js.map +0 -1
  160. package/dist/commands/init.d.ts.map +0 -1
  161. package/dist/commands/init.js.map +0 -1
  162. package/dist/commands/llmstxt.d.ts.map +0 -1
  163. package/dist/commands/llmstxt.js.map +0 -1
  164. package/dist/commands/plugin.d.ts.map +0 -1
  165. package/dist/commands/plugin.js.map +0 -1
  166. package/dist/commands/security.d.ts.map +0 -1
  167. package/dist/commands/security.js.map +0 -1
  168. package/dist/commands/skills.d.ts.map +0 -1
  169. package/dist/commands/skills.js.map +0 -1
  170. package/dist/commands/tdd.d.ts.map +0 -1
  171. package/dist/commands/tdd.js.map +0 -1
  172. package/dist/constants.d.ts.map +0 -1
  173. package/dist/constants.js.map +0 -1
  174. package/dist/index.d.ts.map +0 -1
  175. package/dist/index.js.map +0 -1
  176. package/dist/lib/agent-skills.d.ts.map +0 -1
  177. package/dist/lib/agent-skills.js.map +0 -1
  178. package/dist/lib/claudemd.d.ts.map +0 -1
  179. package/dist/lib/claudemd.js.map +0 -1
  180. package/dist/lib/codex-export.d.ts.map +0 -1
  181. package/dist/lib/codex-export.js.map +0 -1
  182. package/dist/lib/common.d.ts.map +0 -1
  183. package/dist/lib/common.js.map +0 -1
  184. package/dist/lib/context.d.ts.map +0 -1
  185. package/dist/lib/context.js.map +0 -1
  186. package/dist/lib/docker.d.ts.map +0 -1
  187. package/dist/lib/docker.js.map +0 -1
  188. package/dist/lib/frontmatter.d.ts.map +0 -1
  189. package/dist/lib/frontmatter.js.map +0 -1
  190. package/dist/lib/plugin.d.ts.map +0 -1
  191. package/dist/lib/plugin.js.map +0 -1
  192. package/dist/lib/template.d.ts.map +0 -1
  193. package/dist/lib/template.js.map +0 -1
  194. package/dist/types/index.d.ts.map +0 -1
  195. package/dist/types/index.js.map +0 -1
  196. package/dist/ui/AnalyzeUI.d.ts.map +0 -1
  197. package/dist/ui/AnalyzeUI.js.map +0 -1
  198. package/dist/ui/App.d.ts.map +0 -1
  199. package/dist/ui/App.js.map +0 -1
  200. package/dist/ui/CI.d.ts.map +0 -1
  201. package/dist/ui/CI.js.map +0 -1
  202. package/dist/ui/CIContext.d.ts.map +0 -1
  203. package/dist/ui/CIContext.js.map +0 -1
  204. package/dist/ui/CISelector.d.ts.map +0 -1
  205. package/dist/ui/CISelector.js.map +0 -1
  206. package/dist/ui/Doctor.d.ts.map +0 -1
  207. package/dist/ui/Doctor.js.map +0 -1
  208. package/dist/ui/Header.d.ts.map +0 -1
  209. package/dist/ui/Header.js.map +0 -1
  210. package/dist/ui/LlmsTxt.d.ts.map +0 -1
  211. package/dist/ui/LlmsTxt.js.map +0 -1
  212. package/dist/ui/MemorySelector.d.ts.map +0 -1
  213. package/dist/ui/MemorySelector.js.map +0 -1
  214. package/dist/ui/NameInput.d.ts.map +0 -1
  215. package/dist/ui/NameInput.js.map +0 -1
  216. package/dist/ui/OptionSelector.d.ts.map +0 -1
  217. package/dist/ui/OptionSelector.js.map +0 -1
  218. package/dist/ui/Plugin.d.ts.map +0 -1
  219. package/dist/ui/Plugin.js.map +0 -1
  220. package/dist/ui/Progress.d.ts.map +0 -1
  221. package/dist/ui/Progress.js.map +0 -1
  222. package/dist/ui/Skills.d.ts.map +0 -1
  223. package/dist/ui/Skills.js.map +0 -1
  224. package/dist/ui/StackSelector.d.ts.map +0 -1
  225. package/dist/ui/StackSelector.js.map +0 -1
  226. package/dist/ui/Summary.d.ts.map +0 -1
  227. package/dist/ui/Summary.js.map +0 -1
  228. package/dist/ui/Welcome.d.ts.map +0 -1
  229. package/dist/ui/Welcome.js.map +0 -1
  230. package/dist/ui/theme.d.ts.map +0 -1
  231. package/dist/ui/theme.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Supply chain protection — configures Socket Firewall and enforces
3
+ * minimum package release age to protect against typosquatting,
4
+ * dependency confusion, and malicious package takeovers.
5
+ */
6
+ import type { Stack } from "../types/index.js";
7
+ export type PackageManager = "npm" | "pnpm" | "yarn" | "pip" | "cargo" | "go";
8
+ export interface SupplyChainConfig {
9
+ packageManager: PackageManager;
10
+ minReleaseAgeHours: number;
11
+ socketEnabled: boolean;
12
+ enforceLockfile: boolean;
13
+ }
14
+ export interface SupplyChainResult {
15
+ configWritten: string[];
16
+ warnings: string[];
17
+ }
18
+ export declare function detectPackageManager(projectDir: string): PackageManager;
19
+ export declare function stackForPM(pm: PackageManager): Stack;
20
+ export declare function buildSocketConfig(pm: PackageManager): Record<string, unknown>;
21
+ export declare function buildNpmrcLines(minAgeHours: number): string[];
22
+ export declare function configureSupplyChain(projectDir: string, options?: Partial<SupplyChainConfig>): Promise<SupplyChainResult>;
23
+ //# sourceMappingURL=supply-chain.d.ts.map
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Supply chain protection — configures Socket Firewall and enforces
3
+ * minimum package release age to protect against typosquatting,
4
+ * dependency confusion, and malicious package takeovers.
5
+ */
6
+ import fs from "fs-extra";
7
+ import path from "path";
8
+ // ── Detection ──
9
+ export function detectPackageManager(projectDir) {
10
+ if (fs.existsSync(path.join(projectDir, "pnpm-lock.yaml")))
11
+ return "pnpm";
12
+ if (fs.existsSync(path.join(projectDir, "yarn.lock")))
13
+ return "yarn";
14
+ if (fs.existsSync(path.join(projectDir, "package-lock.json")))
15
+ return "npm";
16
+ if (fs.existsSync(path.join(projectDir, "Pipfile.lock")))
17
+ return "pip";
18
+ if (fs.existsSync(path.join(projectDir, "Cargo.lock")))
19
+ return "cargo";
20
+ if (fs.existsSync(path.join(projectDir, "go.sum")))
21
+ return "go";
22
+ if (fs.existsSync(path.join(projectDir, "package.json")))
23
+ return "npm";
24
+ return "npm";
25
+ }
26
+ export function stackForPM(pm) {
27
+ switch (pm) {
28
+ case "npm":
29
+ case "pnpm":
30
+ case "yarn":
31
+ return "node";
32
+ case "pip":
33
+ return "python";
34
+ case "cargo":
35
+ return "rust";
36
+ case "go":
37
+ return "go";
38
+ }
39
+ }
40
+ // ── Socket Firewall config ──
41
+ export function buildSocketConfig(pm) {
42
+ return {
43
+ version: 2,
44
+ projectType: stackForPM(pm),
45
+ issueRules: {
46
+ "pkg:npm/*": {
47
+ installScripts: "error",
48
+ telemetry: "warn",
49
+ troll: "error",
50
+ unpublished: "error",
51
+ deprecated: "warn",
52
+ unmaintained: "warn",
53
+ "new-author": "warn",
54
+ shellAccess: "error",
55
+ filesystemAccess: "warn",
56
+ networkAccess: "warn",
57
+ envAccess: "warn",
58
+ },
59
+ },
60
+ };
61
+ }
62
+ // ── npmrc / lockfile enforcement ──
63
+ export function buildNpmrcLines(minAgeHours) {
64
+ const lines = [
65
+ "# Supply chain protection — generated by javi-forge",
66
+ "engine-strict=true",
67
+ "save-exact=true",
68
+ ];
69
+ if (minAgeHours > 0) {
70
+ lines.push(`# Minimum package age: ${minAgeHours}h (enforced via CI/pre-install hook)`);
71
+ }
72
+ return lines;
73
+ }
74
+ // ── Orchestrator ──
75
+ export async function configureSupplyChain(projectDir, options = {}) {
76
+ const pm = options.packageManager ?? detectPackageManager(projectDir);
77
+ const minAge = options.minReleaseAgeHours ?? 48;
78
+ const socketEnabled = options.socketEnabled ?? true;
79
+ const enforceLockfile = options.enforceLockfile ?? true;
80
+ const configWritten = [];
81
+ const warnings = [];
82
+ // 1. Socket Firewall config
83
+ if (socketEnabled) {
84
+ const socketPath = path.join(projectDir, ".socketrc");
85
+ await fs.writeJson(socketPath, buildSocketConfig(pm), { spaces: 2 });
86
+ configWritten.push(".socketrc");
87
+ }
88
+ // 2. npmrc for node projects
89
+ if (stackForPM(pm) === "node") {
90
+ const npmrcPath = path.join(projectDir, ".npmrc");
91
+ const lines = buildNpmrcLines(minAge);
92
+ if (enforceLockfile) {
93
+ if (pm === "pnpm") {
94
+ lines.push("frozen-lockfile=true");
95
+ }
96
+ else {
97
+ lines.push("package-lock=true");
98
+ }
99
+ }
100
+ // Append to existing .npmrc if present
101
+ const existing = (await fs.pathExists(npmrcPath))
102
+ ? await fs.readFile(npmrcPath, "utf-8")
103
+ : "";
104
+ const newContent = existing
105
+ ? `${existing.trimEnd()}\n\n${lines.join("\n")}\n`
106
+ : `${lines.join("\n")}\n`;
107
+ await fs.writeFile(npmrcPath, newContent);
108
+ configWritten.push(".npmrc");
109
+ }
110
+ // 3. Supply chain metadata in baseline dir
111
+ const metaPath = path.join(projectDir, ".javi-forge", "supply-chain.json");
112
+ await fs.ensureDir(path.dirname(metaPath));
113
+ await fs.writeJson(metaPath, {
114
+ packageManager: pm,
115
+ minReleaseAgeHours: minAge,
116
+ socketEnabled,
117
+ enforceLockfile,
118
+ configuredAt: new Date().toISOString(),
119
+ }, { spaces: 2 });
120
+ configWritten.push(".javi-forge/supply-chain.json");
121
+ if (!socketEnabled) {
122
+ warnings.push("Socket Firewall disabled. Consider enabling it for supply chain protection.");
123
+ }
124
+ return { configWritten, warnings };
125
+ }
126
+ //# sourceMappingURL=supply-chain.js.map
@@ -0,0 +1,17 @@
1
+ import type { Stack, TddPipelineMode, TddPipelineResult } from "../types/index.js";
2
+ /**
3
+ * Generate a TDD pipeline enforcement pre-push hook script.
4
+ *
5
+ * - strict: tests MUST pass or push is blocked (exit 1).
6
+ * - warn: tests are run and results shown, but push is never blocked.
7
+ *
8
+ * If testCmd is null, generates a skip-only hook regardless of mode.
9
+ */
10
+ export declare function generateTddPipelineHook(mode: TddPipelineMode, testCmd: string | null, stack: Stack): string;
11
+ /**
12
+ * Install TDD pipeline pre-push hook into .git/hooks/.
13
+ * Detects the project stack automatically and generates the appropriate hook.
14
+ * Backs up any existing pre-push hook to pre-push.bak.
15
+ */
16
+ export declare function installTddPipelineHook(projectDir: string, mode: TddPipelineMode): Promise<TddPipelineResult>;
17
+ //# sourceMappingURL=tdd-pipeline.d.ts.map
@@ -0,0 +1,144 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import { detectCIStack } from "./ci.js";
4
+ import { getTddTestCommand } from "./tdd.js";
5
+ // =============================================================================
6
+ // Hook generation
7
+ // =============================================================================
8
+ /**
9
+ * Generate a TDD pipeline enforcement pre-push hook script.
10
+ *
11
+ * - strict: tests MUST pass or push is blocked (exit 1).
12
+ * - warn: tests are run and results shown, but push is never blocked.
13
+ *
14
+ * If testCmd is null, generates a skip-only hook regardless of mode.
15
+ */
16
+ export function generateTddPipelineHook(mode, testCmd, stack) {
17
+ if (!testCmd) {
18
+ return `#!/bin/bash
19
+ # =============================================================================
20
+ # TDD PIPELINE (pre-push): No test command detected for stack "${stack}"
21
+ # =============================================================================
22
+ # Install a test runner and re-run: javi-forge tdd pipeline --mode ${mode}
23
+ # =============================================================================
24
+
25
+ echo "TDD PIPELINE: No test command configured for stack '${stack}' — skipping."
26
+ exit 0
27
+ `;
28
+ }
29
+ if (mode === "warn") {
30
+ return `#!/bin/bash
31
+ # =============================================================================
32
+ # TDD PIPELINE (pre-push): WARN mode
33
+ # =============================================================================
34
+ # Flow: Spec → Tests → Fail → Implement → Pass
35
+ # Stack: ${stack} | Command: ${testCmd}
36
+ # Mode: warn — tests run but push is NEVER blocked
37
+ # To skip: git push --no-verify
38
+ # =============================================================================
39
+
40
+ echo "TDD PIPELINE [WARN]: Running tests before push..."
41
+ echo " Stack: ${stack}"
42
+ echo " Command: ${testCmd}"
43
+ echo " Mode: warn (push will proceed regardless)"
44
+ echo ""
45
+
46
+ ${testCmd} && {
47
+ echo ""
48
+ echo "TDD PIPELINE [WARN]: All tests passed."
49
+ } || {
50
+ echo ""
51
+ echo "TDD PIPELINE [WARN]: Tests FAILED — but push will proceed (warn mode)."
52
+ echo " Consider fixing tests before merging."
53
+ }
54
+
55
+ exit 0
56
+ `;
57
+ }
58
+ // strict mode (default)
59
+ return `#!/bin/bash
60
+ # =============================================================================
61
+ # TDD PIPELINE (pre-push): STRICT mode
62
+ # =============================================================================
63
+ # Flow: Spec → Tests → Fail → Implement → Pass
64
+ # Stack: ${stack} | Command: ${testCmd}
65
+ # Mode: strict — push is BLOCKED if tests fail
66
+ # To skip: git push --no-verify
67
+ # =============================================================================
68
+
69
+ set -e
70
+
71
+ echo "TDD PIPELINE [STRICT]: Running tests before push..."
72
+ echo " Stack: ${stack}"
73
+ echo " Command: ${testCmd}"
74
+ echo " Mode: strict (push blocked on failure)"
75
+ echo ""
76
+
77
+ ${testCmd} || {
78
+ echo ""
79
+ echo "TDD PIPELINE [STRICT]: FAILED — Tests did not pass."
80
+ echo " Fix failing tests before pushing."
81
+ echo " To skip: git push --no-verify"
82
+ exit 1
83
+ }
84
+
85
+ echo ""
86
+ echo "TDD PIPELINE [STRICT]: All tests passed. Push allowed."
87
+ `;
88
+ }
89
+ // =============================================================================
90
+ // Hook installation
91
+ // =============================================================================
92
+ /**
93
+ * Install TDD pipeline pre-push hook into .git/hooks/.
94
+ * Detects the project stack automatically and generates the appropriate hook.
95
+ * Backs up any existing pre-push hook to pre-push.bak.
96
+ */
97
+ export async function installTddPipelineHook(projectDir, mode) {
98
+ const result = {
99
+ installed: [],
100
+ skipped: [],
101
+ errors: [],
102
+ mode,
103
+ };
104
+ const gitDir = path.join(projectDir, ".git");
105
+ if (!(await fs.pathExists(gitDir))) {
106
+ result.errors.push("Not a git repository. Run git init first.");
107
+ return result;
108
+ }
109
+ const hooksDir = path.join(gitDir, "hooks");
110
+ await fs.ensureDir(hooksDir);
111
+ // Detect stack
112
+ let stackInfo;
113
+ try {
114
+ stackInfo = await detectCIStack(projectDir);
115
+ }
116
+ catch {
117
+ result.errors.push("Failed to detect project stack.");
118
+ return result;
119
+ }
120
+ const testCmd = await getTddTestCommand(stackInfo.stackType, stackInfo.buildTool, projectDir);
121
+ const hookContent = generateTddPipelineHook(mode, testCmd, stackInfo.stackType);
122
+ const hookPath = path.join(hooksDir, "pre-push");
123
+ // Backup existing hook
124
+ if (await fs.pathExists(hookPath)) {
125
+ const backupPath = path.join(hooksDir, "pre-push.bak");
126
+ try {
127
+ await fs.copy(hookPath, backupPath, { overwrite: true });
128
+ result.skipped.push("pre-push (backed up to pre-push.bak)");
129
+ }
130
+ catch (e) {
131
+ result.errors.push(`backup: ${e instanceof Error ? e.message : String(e)}`);
132
+ return result;
133
+ }
134
+ }
135
+ try {
136
+ await fs.writeFile(hookPath, hookContent, { mode: 0o755 });
137
+ result.installed.push("pre-push");
138
+ }
139
+ catch (e) {
140
+ result.errors.push(`pre-push: ${e instanceof Error ? e.message : String(e)}`);
141
+ }
142
+ return result;
143
+ }
144
+ //# sourceMappingURL=tdd-pipeline.js.map
@@ -1,4 +1,4 @@
1
- import type { Stack } from '../types/index.js';
1
+ import type { Stack } from "../types/index.js";
2
2
  export interface TddHookResult {
3
3
  installed: string[];
4
4
  errors: string[];
@@ -1,6 +1,6 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import { detectCIStack } from './ci.js';
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import { detectCIStack } from "./ci.js";
4
4
  // =============================================================================
5
5
  // Test command resolution
6
6
  // =============================================================================
@@ -10,22 +10,22 @@ import { detectCIStack } from './ci.js';
10
10
  */
11
11
  export async function getTddTestCommand(stack, buildTool, projectDir) {
12
12
  switch (stack) {
13
- case 'node': {
14
- const pkgPath = path.join(projectDir, 'package.json');
13
+ case "node": {
14
+ const pkgPath = path.join(projectDir, "package.json");
15
15
  try {
16
- const pkgContent = await fs.readFile(pkgPath, 'utf-8');
16
+ const pkgContent = await fs.readFile(pkgPath, "utf-8");
17
17
  if (!pkgContent.includes('"test"'))
18
18
  return null;
19
- return buildTool === 'npm' ? 'npm test' : `${buildTool} run test`;
19
+ return buildTool === "npm" ? "npm test" : `${buildTool} run test`;
20
20
  }
21
21
  catch {
22
22
  return null;
23
23
  }
24
24
  }
25
- case 'python':
26
- return 'pytest';
27
- case 'go':
28
- return 'go test ./...';
25
+ case "python":
26
+ return "pytest";
27
+ case "go":
28
+ return "go test ./...";
29
29
  default:
30
30
  return null;
31
31
  }
@@ -86,11 +86,14 @@ echo "TDD PASSED — All tests green. Commit allowed."
86
86
  * Detects the project stack automatically and generates the appropriate hook.
87
87
  */
88
88
  export async function installTddHooks(projectDir) {
89
- const gitDir = path.join(projectDir, '.git');
90
- if (!await fs.pathExists(gitDir)) {
91
- return { installed: [], errors: ['Not a git repository. Run git init first.'] };
89
+ const gitDir = path.join(projectDir, ".git");
90
+ if (!(await fs.pathExists(gitDir))) {
91
+ return {
92
+ installed: [],
93
+ errors: ["Not a git repository. Run git init first."],
94
+ };
92
95
  }
93
- const hooksDir = path.join(gitDir, 'hooks');
96
+ const hooksDir = path.join(gitDir, "hooks");
94
97
  await fs.ensureDir(hooksDir);
95
98
  // Detect stack
96
99
  let stackInfo;
@@ -98,16 +101,16 @@ export async function installTddHooks(projectDir) {
98
101
  stackInfo = await detectCIStack(projectDir);
99
102
  }
100
103
  catch {
101
- return { installed: [], errors: ['Failed to detect project stack.'] };
104
+ return { installed: [], errors: ["Failed to detect project stack."] };
102
105
  }
103
106
  const testCmd = await getTddTestCommand(stackInfo.stackType, stackInfo.buildTool, projectDir);
104
107
  const hookContent = generateTddHook(testCmd, stackInfo.stackType);
105
108
  const installed = [];
106
109
  const errors = [];
107
- const hookPath = path.join(hooksDir, 'pre-commit');
110
+ const hookPath = path.join(hooksDir, "pre-commit");
108
111
  try {
109
112
  await fs.writeFile(hookPath, hookContent, { mode: 0o755 });
110
- installed.push('pre-commit');
113
+ installed.push("pre-commit");
111
114
  }
112
115
  catch (e) {
113
116
  errors.push(`pre-commit: ${e instanceof Error ? e.message : String(e)}`);
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Agent Teams parallel dispatch presets — predefined team configurations
3
+ * for common workflows like review, debug, and security scanning.
4
+ *
5
+ * Each preset defines which sub-agents to spawn in parallel, their roles,
6
+ * and how to aggregate results.
7
+ */
8
+ export interface AgentRole {
9
+ id: string;
10
+ name: string;
11
+ skill: string;
12
+ perspective: string;
13
+ priority: "critical" | "high" | "medium" | "low";
14
+ }
15
+ export interface TeamPreset {
16
+ name: string;
17
+ description: string;
18
+ roles: AgentRole[];
19
+ aggregation: "all-must-pass" | "majority" | "any-pass";
20
+ maxParallel: number;
21
+ }
22
+ export interface TeamDispatch {
23
+ preset: string;
24
+ roles: AgentRole[];
25
+ targetFiles: string[];
26
+ context: Record<string, string>;
27
+ }
28
+ export interface AgentResult {
29
+ roleId: string;
30
+ roleName: string;
31
+ passed: boolean;
32
+ findings: string[];
33
+ severity: "critical" | "high" | "medium" | "low" | "info";
34
+ durationMs: number;
35
+ }
36
+ export interface TeamResult {
37
+ preset: string;
38
+ passed: boolean;
39
+ agents: AgentResult[];
40
+ totalDurationMs: number;
41
+ summary: string;
42
+ }
43
+ export declare const TEAM_PRESETS: Record<string, TeamPreset>;
44
+ export declare function getPreset(name: string): TeamPreset | null;
45
+ export declare function listPresets(): Array<{
46
+ name: string;
47
+ description: string;
48
+ roleCount: number;
49
+ }>;
50
+ export declare function createDispatch(presetName: string, targetFiles: string[], context?: Record<string, string>): TeamDispatch | null;
51
+ export declare function aggregateResults(preset: TeamPreset, results: AgentResult[]): TeamResult;
52
+ export declare function formatTeamResult(result: TeamResult): string;
53
+ //# sourceMappingURL=team-presets.d.ts.map
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Agent Teams parallel dispatch presets — predefined team configurations
3
+ * for common workflows like review, debug, and security scanning.
4
+ *
5
+ * Each preset defines which sub-agents to spawn in parallel, their roles,
6
+ * and how to aggregate results.
7
+ */
8
+ // ── Built-in presets ──
9
+ export const TEAM_PRESETS = {
10
+ review: {
11
+ name: "review",
12
+ description: "Multi-perspective code review team",
13
+ roles: [
14
+ {
15
+ id: "quality",
16
+ name: "Quality Reviewer",
17
+ skill: "adversarial-review",
18
+ perspective: "code quality, readability, maintainability",
19
+ priority: "high",
20
+ },
21
+ {
22
+ id: "security",
23
+ name: "Security Auditor",
24
+ skill: "adversarial-review",
25
+ perspective: "security vulnerabilities, injection, auth",
26
+ priority: "critical",
27
+ },
28
+ {
29
+ id: "testing",
30
+ name: "Test Reviewer",
31
+ skill: "testing:test-coverage",
32
+ perspective: "test coverage, edge cases, test quality",
33
+ priority: "medium",
34
+ },
35
+ ],
36
+ aggregation: "all-must-pass",
37
+ maxParallel: 3,
38
+ },
39
+ debug: {
40
+ name: "debug",
41
+ description: "Parallel debugging team",
42
+ roles: [
43
+ {
44
+ id: "hypothesis",
45
+ name: "Hypothesis Generator",
46
+ skill: "debug-mode",
47
+ perspective: "generate and rank failure hypotheses",
48
+ priority: "high",
49
+ },
50
+ {
51
+ id: "logs",
52
+ name: "Log Analyzer",
53
+ skill: "debug-mode",
54
+ perspective: "parse logs, stack traces, error patterns",
55
+ priority: "high",
56
+ },
57
+ {
58
+ id: "repro",
59
+ name: "Reproducer",
60
+ skill: "testing:e2e",
61
+ perspective: "create minimal reproduction steps",
62
+ priority: "medium",
63
+ },
64
+ ],
65
+ aggregation: "any-pass",
66
+ maxParallel: 3,
67
+ },
68
+ security: {
69
+ name: "security",
70
+ description: "Security scanning team",
71
+ roles: [
72
+ {
73
+ id: "sast",
74
+ name: "SAST Scanner",
75
+ skill: "adversarial-review",
76
+ perspective: "static analysis, code patterns, OWASP",
77
+ priority: "critical",
78
+ },
79
+ {
80
+ id: "deps",
81
+ name: "Dependency Auditor",
82
+ skill: "adversarial-review",
83
+ perspective: "supply chain, outdated deps, known CVEs",
84
+ priority: "critical",
85
+ },
86
+ {
87
+ id: "secrets",
88
+ name: "Secret Scanner",
89
+ skill: "adversarial-review",
90
+ perspective: "hardcoded secrets, API keys, credentials",
91
+ priority: "critical",
92
+ },
93
+ ],
94
+ aggregation: "all-must-pass",
95
+ maxParallel: 3,
96
+ },
97
+ "tdd-cycle": {
98
+ name: "tdd-cycle",
99
+ description: "TDD pipeline team",
100
+ roles: [
101
+ {
102
+ id: "test-writer",
103
+ name: "Test Writer",
104
+ skill: "testing:tdd",
105
+ perspective: "write failing tests first",
106
+ priority: "high",
107
+ },
108
+ {
109
+ id: "implementer",
110
+ name: "Implementer",
111
+ skill: "sdd-apply",
112
+ perspective: "make tests pass with minimal code",
113
+ priority: "high",
114
+ },
115
+ {
116
+ id: "refactorer",
117
+ name: "Refactorer",
118
+ skill: "refactoring:cleanup",
119
+ perspective: "clean up without breaking tests",
120
+ priority: "medium",
121
+ },
122
+ ],
123
+ aggregation: "all-must-pass",
124
+ maxParallel: 1, // sequential for TDD
125
+ },
126
+ };
127
+ // ── Preset management ──
128
+ export function getPreset(name) {
129
+ return TEAM_PRESETS[name] ?? null;
130
+ }
131
+ export function listPresets() {
132
+ return Object.values(TEAM_PRESETS).map((p) => ({
133
+ name: p.name,
134
+ description: p.description,
135
+ roleCount: p.roles.length,
136
+ }));
137
+ }
138
+ // ── Dispatch creation ──
139
+ export function createDispatch(presetName, targetFiles, context = {}) {
140
+ const preset = getPreset(presetName);
141
+ if (!preset)
142
+ return null;
143
+ return {
144
+ preset: presetName,
145
+ roles: preset.roles,
146
+ targetFiles,
147
+ context,
148
+ };
149
+ }
150
+ // ── Result aggregation ──
151
+ export function aggregateResults(preset, results) {
152
+ const totalDurationMs = Math.max(...results.map((r) => r.durationMs), 0);
153
+ let passed;
154
+ switch (preset.aggregation) {
155
+ case "all-must-pass":
156
+ passed = results.every((r) => r.passed);
157
+ break;
158
+ case "majority":
159
+ passed = results.filter((r) => r.passed).length > results.length / 2;
160
+ break;
161
+ case "any-pass":
162
+ passed = results.some((r) => r.passed);
163
+ break;
164
+ }
165
+ const criticalFindings = results
166
+ .filter((r) => r.severity === "critical" && !r.passed)
167
+ .flatMap((r) => r.findings);
168
+ const summary = passed
169
+ ? `All ${results.length} agents passed.`
170
+ : `${results.filter((r) => !r.passed).length}/${results.length} agents reported issues.${criticalFindings.length > 0 ? ` ${criticalFindings.length} critical findings.` : ""}`;
171
+ return {
172
+ preset: preset.name,
173
+ passed,
174
+ agents: results,
175
+ totalDurationMs,
176
+ summary,
177
+ };
178
+ }
179
+ // ── Formatting ──
180
+ export function formatTeamResult(result) {
181
+ const icon = result.passed ? "✅" : "❌";
182
+ const lines = [
183
+ `${icon} Team: ${result.preset} — ${result.summary}`,
184
+ "",
185
+ ];
186
+ for (const agent of result.agents) {
187
+ const aIcon = agent.passed ? "✓" : "✗";
188
+ const dur = `${(agent.durationMs / 1000).toFixed(1)}s`;
189
+ lines.push(` ${aIcon} ${agent.roleName} [${agent.severity}] ${dur}`);
190
+ if (agent.findings.length > 0) {
191
+ for (const f of agent.findings.slice(0, 3)) {
192
+ lines.push(` - ${f}`);
193
+ }
194
+ if (agent.findings.length > 3) {
195
+ lines.push(` ... +${agent.findings.length - 3} more`);
196
+ }
197
+ }
198
+ }
199
+ return lines.join("\n");
200
+ }
201
+ //# sourceMappingURL=team-presets.js.map
@@ -0,0 +1,23 @@
1
+ import type { InitStep } from "../types/index.js";
2
+ export type WorkflowAction = "show" | "validate" | "list";
3
+ type StepCallback = (step: InitStep) => void;
4
+ /**
5
+ * Show a workflow graph as ASCII art.
6
+ */
7
+ export declare function runWorkflowShow(projectDir: string, onStep: StepCallback, options?: {
8
+ target?: string;
9
+ template?: string;
10
+ }): Promise<string | null>;
11
+ /**
12
+ * Validate a project against a workflow graph.
13
+ */
14
+ export declare function runWorkflowValidate(projectDir: string, onStep: StepCallback, options?: {
15
+ target?: string;
16
+ template?: string;
17
+ }): Promise<string | null>;
18
+ /**
19
+ * List available workflows (project + built-in templates).
20
+ */
21
+ export declare function runWorkflowList(projectDir: string, onStep: StepCallback): Promise<string>;
22
+ export {};
23
+ //# sourceMappingURL=workflow.d.ts.map