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
@@ -1,4 +1,4 @@
1
- import type { InitStep } from '../types/index.js';
1
+ import type { InitStep } from "../types/index.js";
2
2
  type StepCallback = (step: InitStep) => void;
3
3
  /**
4
4
  * Generate an llms.txt file — compact AI-friendly project notation.
@@ -1,7 +1,7 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import { glob } from 'glob';
4
- import { detectStack } from '../lib/common.js';
1
+ import fs from "fs-extra";
2
+ import { glob } from "glob";
3
+ import path from "path";
4
+ import { detectStack } from "../lib/common.js";
5
5
  function report(onStep, id, label, status, detail) {
6
6
  onStep({ id, label, status, detail });
7
7
  }
@@ -10,53 +10,55 @@ function report(onStep, id, label, status, detail) {
10
10
  * Reduces token usage by ~75% compared to full README + docs.
11
11
  */
12
12
  export async function generateLlmsTxt(projectDir, dryRun, onStep) {
13
- report(onStep, 'scan', 'Scan project structure', 'running');
13
+ report(onStep, "scan", "Scan project structure", "running");
14
14
  const detection = await detectStack(projectDir);
15
- const stackLabel = detection?.stackType ?? 'unknown';
15
+ const stackLabel = detection?.stackType ?? "unknown";
16
16
  // Gather project info
17
17
  const name = path.basename(projectDir);
18
- let description = '';
19
- let version = '';
18
+ let description = "";
19
+ let version = "";
20
20
  let entryPoints = [];
21
21
  let dependencies = [];
22
22
  // Try package.json (Node)
23
- const pkgPath = path.join(projectDir, 'package.json');
23
+ const pkgPath = path.join(projectDir, "package.json");
24
24
  if (await fs.pathExists(pkgPath)) {
25
25
  try {
26
26
  const pkg = await fs.readJson(pkgPath);
27
- description = pkg.description ?? '';
28
- version = pkg.version ?? '';
27
+ description = pkg.description ?? "";
28
+ version = pkg.version ?? "";
29
29
  entryPoints = pkg.main ? [pkg.main] : [];
30
30
  dependencies = Object.keys(pkg.dependencies ?? {}).slice(0, 15);
31
31
  }
32
- catch { /* ignore */ }
32
+ catch {
33
+ /* ignore */
34
+ }
33
35
  }
34
36
  // Scan source files
35
- const sourceFiles = await glob('src/**/*.{ts,tsx,js,jsx,py,go,rs}', {
37
+ const sourceFiles = await glob("src/**/*.{ts,tsx,js,jsx,py,go,rs}", {
36
38
  cwd: projectDir,
37
- ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'],
39
+ ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
38
40
  });
39
41
  // Scan test files
40
- const testFiles = await glob('**/*.{test,spec}.{ts,tsx,js,jsx,py}', {
42
+ const testFiles = await glob("**/*.{test,spec}.{ts,tsx,js,jsx,py}", {
41
43
  cwd: projectDir,
42
- ignore: ['**/node_modules/**', '**/dist/**'],
44
+ ignore: ["**/node_modules/**", "**/dist/**"],
43
45
  });
44
- report(onStep, 'scan', 'Scan project structure', 'done', `${sourceFiles.length} source, ${testFiles.length} test files`);
46
+ report(onStep, "scan", "Scan project structure", "done", `${sourceFiles.length} source, ${testFiles.length} test files`);
45
47
  // Build llms.txt content
46
- report(onStep, 'generate', 'Generate llms.txt', 'running');
48
+ report(onStep, "generate", "Generate llms.txt", "running");
47
49
  const lines = [
48
50
  `# ${name}`,
49
- '',
50
- `> ${description || 'No description'}`,
51
- '',
52
- `- stack: ${stackLabel}${detection?.buildTool ? ` (${detection.buildTool})` : ''}`,
53
- `- version: ${version || 'unknown'}`,
51
+ "",
52
+ `> ${description || "No description"}`,
53
+ "",
54
+ `- stack: ${stackLabel}${detection?.buildTool ? ` (${detection.buildTool})` : ""}`,
55
+ `- version: ${version || "unknown"}`,
54
56
  `- files: ${sourceFiles.length} source, ${testFiles.length} tests`,
55
- '',
57
+ "",
56
58
  ];
57
59
  // Structure summary (compact)
58
60
  if (sourceFiles.length > 0) {
59
- lines.push('## Structure');
61
+ lines.push("## Structure");
60
62
  const dirs = new Map();
61
63
  for (const f of sourceFiles) {
62
64
  const dir = path.dirname(f);
@@ -65,28 +67,28 @@ export async function generateLlmsTxt(projectDir, dryRun, onStep) {
65
67
  for (const [dir, count] of [...dirs.entries()].sort().slice(0, 20)) {
66
68
  lines.push(`- ${dir}/ (${count})`);
67
69
  }
68
- lines.push('');
70
+ lines.push("");
69
71
  }
70
72
  // Dependencies (compact — name only, no versions)
71
73
  if (dependencies.length > 0) {
72
- lines.push('## Dependencies');
73
- lines.push(dependencies.join(', '));
74
- lines.push('');
74
+ lines.push("## Dependencies");
75
+ lines.push(dependencies.join(", "));
76
+ lines.push("");
75
77
  }
76
78
  // Entry points
77
79
  if (entryPoints.length > 0) {
78
- lines.push('## Entry');
80
+ lines.push("## Entry");
79
81
  for (const ep of entryPoints) {
80
82
  lines.push(`- ${ep}`);
81
83
  }
82
- lines.push('');
84
+ lines.push("");
83
85
  }
84
- const content = lines.join('\n');
86
+ const content = lines.join("\n");
85
87
  const tokenEstimate = Math.ceil(content.length / 4);
86
88
  if (!dryRun) {
87
- await fs.writeFile(path.join(projectDir, 'llms.txt'), content, 'utf-8');
89
+ await fs.writeFile(path.join(projectDir, "llms.txt"), content, "utf-8");
88
90
  }
89
- report(onStep, 'generate', 'Generate llms.txt', 'done', dryRun
91
+ report(onStep, "generate", "Generate llms.txt", "done", dryRun
90
92
  ? `dry-run: ~${tokenEstimate} tokens (${content.length} chars)`
91
93
  : `written — ~${tokenEstimate} tokens (${content.length} chars)`);
92
94
  }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Parallel batch sub-agents — spawn test/lint/build runners per module
3
+ * in parallel during quality scoring. Collects results and aggregates.
4
+ */
5
+ export type JobStatus = "pending" | "running" | "done" | "error";
6
+ export interface BatchJob {
7
+ id: string;
8
+ name: string;
9
+ command: string;
10
+ module: string;
11
+ status: JobStatus;
12
+ startedAt: number | null;
13
+ completedAt: number | null;
14
+ durationMs: number;
15
+ exitCode: number | null;
16
+ stdout: string;
17
+ stderr: string;
18
+ }
19
+ export interface BatchResult {
20
+ jobs: BatchJob[];
21
+ totalDurationMs: number;
22
+ passedCount: number;
23
+ failedCount: number;
24
+ parallelism: number;
25
+ }
26
+ export interface BatchConfig {
27
+ maxParallel: number;
28
+ timeoutMs: number;
29
+ }
30
+ export declare const DEFAULT_BATCH_CONFIG: BatchConfig;
31
+ export declare function createJob(name: string, command: string, module: string): BatchJob;
32
+ export type JobExecutor = (job: BatchJob) => Promise<BatchJob>;
33
+ /**
34
+ * Default executor — runs command via child_process.
35
+ */
36
+ export declare function createShellExecutor(timeoutMs?: number): JobExecutor;
37
+ /**
38
+ * Run jobs in parallel with configurable concurrency.
39
+ */
40
+ export declare function runBatch(jobs: BatchJob[], executor: JobExecutor, config?: BatchConfig): Promise<BatchResult>;
41
+ export declare function formatBatchResult(result: BatchResult): string;
42
+ //# sourceMappingURL=parallel-batch.d.ts.map
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Parallel batch sub-agents — spawn test/lint/build runners per module
3
+ * in parallel during quality scoring. Collects results and aggregates.
4
+ */
5
+ export const DEFAULT_BATCH_CONFIG = {
6
+ maxParallel: 4,
7
+ timeoutMs: 60_000,
8
+ };
9
+ // ── Job creation ──
10
+ let _jobCounter = 0;
11
+ export function createJob(name, command, module) {
12
+ _jobCounter++;
13
+ return {
14
+ id: `job-${Date.now()}-${_jobCounter}`,
15
+ name,
16
+ command,
17
+ module,
18
+ status: "pending",
19
+ startedAt: null,
20
+ completedAt: null,
21
+ durationMs: 0,
22
+ exitCode: null,
23
+ stdout: "",
24
+ stderr: "",
25
+ };
26
+ }
27
+ /**
28
+ * Default executor — runs command via child_process.
29
+ */
30
+ export function createShellExecutor(timeoutMs = 60_000) {
31
+ return async (job) => {
32
+ const { execFile } = await import("child_process");
33
+ const { promisify } = await import("util");
34
+ const execFileAsync = promisify(execFile);
35
+ job.status = "running";
36
+ job.startedAt = Date.now();
37
+ try {
38
+ const { stdout, stderr } = await execFileAsync("sh", ["-c", job.command], { timeout: timeoutMs, maxBuffer: 5 * 1024 * 1024 });
39
+ job.stdout = stdout;
40
+ job.stderr = stderr;
41
+ job.exitCode = 0;
42
+ job.status = "done";
43
+ }
44
+ catch (err) {
45
+ const e = err;
46
+ job.stdout = e.stdout ?? "";
47
+ job.stderr = e.stderr ?? "";
48
+ job.exitCode = e.killed ? -1 : (e.code ?? 1);
49
+ job.status = "error";
50
+ }
51
+ job.completedAt = Date.now();
52
+ job.durationMs = job.completedAt - job.startedAt;
53
+ return job;
54
+ };
55
+ }
56
+ /**
57
+ * Run jobs in parallel with configurable concurrency.
58
+ */
59
+ export async function runBatch(jobs, executor, config = DEFAULT_BATCH_CONFIG) {
60
+ const start = Date.now();
61
+ const results = [];
62
+ const queue = [...jobs];
63
+ // Process in waves of maxParallel
64
+ while (queue.length > 0) {
65
+ const wave = queue.splice(0, config.maxParallel);
66
+ const waveResults = await Promise.all(wave.map((j) => executor(j)));
67
+ results.push(...waveResults);
68
+ }
69
+ return {
70
+ jobs: results,
71
+ totalDurationMs: Date.now() - start,
72
+ passedCount: results.filter((j) => j.status === "done").length,
73
+ failedCount: results.filter((j) => j.status === "error").length,
74
+ parallelism: config.maxParallel,
75
+ };
76
+ }
77
+ // ── Formatting ──
78
+ export function formatBatchResult(result) {
79
+ const status = result.failedCount === 0 ? "✅ ALL PASSED" : "❌ FAILURES";
80
+ const lines = [];
81
+ lines.push(`## Batch Result: ${status}`);
82
+ lines.push(`**Jobs**: ${result.jobs.length} | **Passed**: ${result.passedCount} | **Failed**: ${result.failedCount} | **Time**: ${result.totalDurationMs}ms | **Parallelism**: ${result.parallelism}`);
83
+ lines.push("");
84
+ for (const job of result.jobs) {
85
+ const icon = job.status === "done" ? "✓" : "✗";
86
+ lines.push(` ${icon} ${job.name} (${job.module}) — ${job.durationMs}ms [exit ${job.exitCode}]`);
87
+ }
88
+ return lines.join("\n");
89
+ }
90
+ //# sourceMappingURL=parallel-batch.js.map
@@ -1,4 +1,4 @@
1
- import type { InitStep } from '../types/index.js';
1
+ import type { InitStep } from "../types/index.js";
2
2
  type StepCallback = (step: InitStep) => void;
3
3
  /**
4
4
  * Add (install) a plugin from a GitHub source.
@@ -36,5 +36,14 @@ export declare function runPluginExportCodex(name: string, onStep: StepCallback)
36
36
  * Import an Agent Skills spec package and convert to javi-forge plugin format.
37
37
  */
38
38
  export declare function runPluginImport(sourceDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
39
+ /**
40
+ * Generate a project-level skills.json from all installed plugins.
41
+ * Makes the project discoverable by `npx skills add` and 40+ AI agents.
42
+ */
43
+ export declare function runPluginExportSkillsJson(projectDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
44
+ /**
45
+ * Generate a global skills.json from all globally installed plugins.
46
+ */
47
+ export declare function runPluginExportGlobalSkillsJson(dryRun: boolean, onStep: StepCallback): Promise<void>;
39
48
  export {};
40
49
  //# sourceMappingURL=plugin.d.ts.map
@@ -1,6 +1,6 @@
1
- import { installPlugin, removePlugin, listInstalledPlugins, validatePlugin, searchRegistry, syncPlugins, } from '../lib/plugin.js';
2
- import { exportPluginAsAgentSkills, importAgentSkillsPackage } from '../lib/agent-skills.js';
3
- import { exportPluginAsCodexToml } from '../lib/codex-export.js';
1
+ import { exportPluginAsAgentSkills, generateGlobalSkillsJson, generateProjectSkillsJson, importAgentSkillsPackage, } from "../lib/agent-skills.js";
2
+ import { exportPluginAsCodexToml } from "../lib/codex-export.js";
3
+ import { installPlugin, listInstalledPlugins, removePlugin, searchRegistry, syncPlugins, validatePlugin, } from "../lib/plugin.js";
4
4
  function report(onStep, id, label, status, detail) {
5
5
  onStep({ id, label, status, detail });
6
6
  }
@@ -8,140 +8,185 @@ function report(onStep, id, label, status, detail) {
8
8
  * Add (install) a plugin from a GitHub source.
9
9
  */
10
10
  export async function runPluginAdd(source, dryRun, onStep) {
11
- const stepId = 'plugin-add';
12
- report(onStep, stepId, `Install plugin: ${source}`, 'running');
11
+ const stepId = "plugin-add";
12
+ report(onStep, stepId, `Install plugin: ${source}`, "running");
13
13
  const result = await installPlugin(source, { dryRun });
14
14
  if (result.success) {
15
- report(onStep, stepId, `Install plugin: ${source}`, 'done', dryRun ? `dry-run: would install ${result.name}` : `installed ${result.name}`);
15
+ report(onStep, stepId, `Install plugin: ${source}`, "done", dryRun
16
+ ? `dry-run: would install ${result.name}`
17
+ : `installed ${result.name}`);
16
18
  }
17
19
  else {
18
- report(onStep, stepId, `Install plugin: ${source}`, 'error', result.error);
20
+ report(onStep, stepId, `Install plugin: ${source}`, "error", result.error);
19
21
  }
20
22
  }
21
23
  /**
22
24
  * Remove an installed plugin by name.
23
25
  */
24
26
  export async function runPluginRemove(name, dryRun, onStep) {
25
- const stepId = 'plugin-remove';
26
- report(onStep, stepId, `Remove plugin: ${name}`, 'running');
27
+ const stepId = "plugin-remove";
28
+ report(onStep, stepId, `Remove plugin: ${name}`, "running");
27
29
  const result = await removePlugin(name, { dryRun });
28
30
  if (result.success) {
29
- report(onStep, stepId, `Remove plugin: ${name}`, 'done', dryRun ? `dry-run: would remove ${name}` : `removed ${name}`);
31
+ report(onStep, stepId, `Remove plugin: ${name}`, "done", dryRun ? `dry-run: would remove ${name}` : `removed ${name}`);
30
32
  }
31
33
  else {
32
- report(onStep, stepId, `Remove plugin: ${name}`, 'error', result.error);
34
+ report(onStep, stepId, `Remove plugin: ${name}`, "error", result.error);
33
35
  }
34
36
  }
35
37
  /**
36
38
  * List all installed plugins.
37
39
  */
38
40
  export async function runPluginList(onStep) {
39
- const stepId = 'plugin-list';
40
- report(onStep, stepId, 'List installed plugins', 'running');
41
+ const stepId = "plugin-list";
42
+ report(onStep, stepId, "List installed plugins", "running");
41
43
  const plugins = await listInstalledPlugins();
42
44
  if (plugins.length === 0) {
43
- report(onStep, stepId, 'List installed plugins', 'done', 'no plugins installed');
45
+ report(onStep, stepId, "List installed plugins", "done", "no plugins installed");
44
46
  }
45
47
  else {
46
- const summary = plugins.map(p => `${p.name}@${p.version}`).join(', ');
47
- report(onStep, stepId, 'List installed plugins', 'done', `${plugins.length} plugins: ${summary}`);
48
+ const summary = plugins.map((p) => `${p.name}@${p.version}`).join(", ");
49
+ report(onStep, stepId, "List installed plugins", "done", `${plugins.length} plugins: ${summary}`);
48
50
  }
49
51
  }
50
52
  /**
51
53
  * Search the remote plugin registry.
52
54
  */
53
55
  export async function runPluginSearch(query, onStep) {
54
- const stepId = 'plugin-search';
55
- report(onStep, stepId, `Search plugins${query ? `: ${query}` : ''}`, 'running');
56
+ const stepId = "plugin-search";
57
+ report(onStep, stepId, `Search plugins${query ? `: ${query}` : ""}`, "running");
56
58
  const results = await searchRegistry(query);
57
59
  if (results.length === 0) {
58
- report(onStep, stepId, `Search plugins${query ? `: ${query}` : ''}`, 'done', query ? `no plugins matching "${query}"` : 'registry empty or unreachable');
60
+ report(onStep, stepId, `Search plugins${query ? `: ${query}` : ""}`, "done", query
61
+ ? `no plugins matching "${query}"`
62
+ : "registry empty or unreachable");
59
63
  }
60
64
  else {
61
- const summary = results.map(p => `${p.id} — ${p.description}`).join('\n ');
62
- report(onStep, stepId, `Search plugins${query ? `: ${query}` : ''}`, 'done', `${results.length} results:\n ${summary}`);
65
+ const summary = results
66
+ .map((p) => `${p.id} ${p.description}`)
67
+ .join("\n ");
68
+ report(onStep, stepId, `Search plugins${query ? `: ${query}` : ""}`, "done", `${results.length} results:\n ${summary}`);
63
69
  }
64
70
  }
65
71
  /**
66
72
  * Validate a local plugin directory.
67
73
  */
68
74
  export async function runPluginValidate(pluginDir, onStep) {
69
- const stepId = 'plugin-validate';
70
- report(onStep, stepId, `Validate plugin: ${pluginDir}`, 'running');
75
+ const stepId = "plugin-validate";
76
+ report(onStep, stepId, `Validate plugin: ${pluginDir}`, "running");
71
77
  const result = await validatePlugin(pluginDir);
72
78
  if (result.valid) {
73
- report(onStep, stepId, `Validate plugin: ${pluginDir}`, 'done', `valid — ${result.manifest?.name}@${result.manifest?.version}`);
79
+ report(onStep, stepId, `Validate plugin: ${pluginDir}`, "done", `valid — ${result.manifest?.name}@${result.manifest?.version}`);
74
80
  }
75
81
  else {
76
- const msgs = result.errors.map(e => ` ${e.path}: ${e.message}`).join('\n');
77
- report(onStep, stepId, `Validate plugin: ${pluginDir}`, 'error', `${result.errors.length} errors:\n${msgs}`);
82
+ const msgs = result.errors
83
+ .map((e) => ` ${e.path}: ${e.message}`)
84
+ .join("\n");
85
+ report(onStep, stepId, `Validate plugin: ${pluginDir}`, "error", `${result.errors.length} errors:\n${msgs}`);
78
86
  }
79
87
  }
80
88
  /**
81
89
  * Sync detected plugins into the project manifest.
82
90
  */
83
91
  export async function runPluginSync(projectDir, dryRun, onStep) {
84
- const stepId = 'plugin-sync';
85
- report(onStep, stepId, 'Sync plugins', 'running');
92
+ const stepId = "plugin-sync";
93
+ report(onStep, stepId, "Sync plugins", "running");
86
94
  try {
87
95
  const result = await syncPlugins(projectDir, { dryRun });
88
96
  const parts = [];
89
97
  if (result.added.length > 0)
90
- parts.push(`added: ${result.added.join(', ')}`);
98
+ parts.push(`added: ${result.added.join(", ")}`);
91
99
  if (result.removed.length > 0)
92
- parts.push(`removed: ${result.removed.join(', ')}`);
100
+ parts.push(`removed: ${result.removed.join(", ")}`);
93
101
  if (result.unchanged.length > 0)
94
- parts.push(`unchanged: ${result.unchanged.join(', ')}`);
102
+ parts.push(`unchanged: ${result.unchanged.join(", ")}`);
103
+ if (result.wired.length > 0)
104
+ parts.push(`wired: ${result.wired.length} capabilities`);
105
+ if (result.unwired.length > 0)
106
+ parts.push(`unwired: ${result.unwired.length} capabilities`);
95
107
  if (parts.length === 0)
96
- parts.push('no plugins detected');
97
- const prefix = dryRun ? 'dry-run: ' : '';
98
- report(onStep, stepId, 'Sync plugins', 'done', `${prefix}${parts.join(' | ')}`);
108
+ parts.push("no plugins detected");
109
+ const prefix = dryRun ? "dry-run: " : "";
110
+ report(onStep, stepId, "Sync plugins", "done", `${prefix}${parts.join(" | ")}`);
99
111
  }
100
112
  catch (e) {
101
113
  const msg = e instanceof Error ? e.message : String(e);
102
- report(onStep, stepId, 'Sync plugins', 'error', msg);
114
+ report(onStep, stepId, "Sync plugins", "error", msg);
103
115
  }
104
116
  }
105
117
  /**
106
118
  * Export an installed plugin to Agent Skills spec format.
107
119
  */
108
120
  export async function runPluginExport(name, onStep) {
109
- const stepId = 'plugin-export';
110
- report(onStep, stepId, `Export plugin: ${name}`, 'running');
121
+ const stepId = "plugin-export";
122
+ report(onStep, stepId, `Export plugin: ${name}`, "running");
111
123
  const result = await exportPluginAsAgentSkills(name);
112
124
  if (result.success) {
113
- report(onStep, stepId, `Export plugin: ${name}`, 'done', `exported to ${result.path}`);
125
+ report(onStep, stepId, `Export plugin: ${name}`, "done", `exported to ${result.path}`);
114
126
  }
115
127
  else {
116
- report(onStep, stepId, `Export plugin: ${name}`, 'error', result.error);
128
+ report(onStep, stepId, `Export plugin: ${name}`, "error", result.error);
117
129
  }
118
130
  }
119
131
  /**
120
132
  * Export an installed plugin to Codex-compatible TOML subagent files.
121
133
  */
122
134
  export async function runPluginExportCodex(name, onStep) {
123
- const stepId = 'plugin-export-codex';
124
- report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, 'running');
135
+ const stepId = "plugin-export-codex";
136
+ report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "running");
125
137
  const result = await exportPluginAsCodexToml(name);
126
138
  if (result.success) {
127
- report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, 'done', `exported ${result.files.length} TOML file(s)`);
139
+ report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "done", `exported ${result.files.length} TOML file(s)`);
128
140
  }
129
141
  else {
130
- report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, 'error', result.error);
142
+ report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "error", result.error);
131
143
  }
132
144
  }
133
145
  /**
134
146
  * Import an Agent Skills spec package and convert to javi-forge plugin format.
135
147
  */
136
148
  export async function runPluginImport(sourceDir, dryRun, onStep) {
137
- const stepId = 'plugin-import';
138
- report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, 'running');
149
+ const stepId = "plugin-import";
150
+ report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, "running");
139
151
  const result = await importAgentSkillsPackage(sourceDir, { dryRun });
140
152
  if (result.success) {
141
- report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, 'done', dryRun ? `dry-run: would import ${result.name}` : `imported ${result.name}`);
153
+ report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, "done", dryRun
154
+ ? `dry-run: would import ${result.name}`
155
+ : `imported ${result.name}`);
142
156
  }
143
157
  else {
144
- report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, 'error', result.error);
158
+ report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, "error", result.error);
159
+ }
160
+ }
161
+ /**
162
+ * Generate a project-level skills.json from all installed plugins.
163
+ * Makes the project discoverable by `npx skills add` and 40+ AI agents.
164
+ */
165
+ export async function runPluginExportSkillsJson(projectDir, dryRun, onStep) {
166
+ const stepId = "plugin-export-skills-json";
167
+ report(onStep, stepId, "Generate project skills.json", "running");
168
+ const result = await generateProjectSkillsJson(projectDir, { dryRun });
169
+ if (result.success) {
170
+ const prefix = dryRun ? "dry-run: would generate" : "generated";
171
+ report(onStep, stepId, "Generate project skills.json", "done", `${prefix} ${result.path} (${result.skillCount} skills from ${result.pluginCount} plugins)`);
172
+ }
173
+ else {
174
+ report(onStep, stepId, "Generate project skills.json", "error", result.error);
175
+ }
176
+ }
177
+ /**
178
+ * Generate a global skills.json from all globally installed plugins.
179
+ */
180
+ export async function runPluginExportGlobalSkillsJson(dryRun, onStep) {
181
+ const stepId = "plugin-export-global-skills-json";
182
+ report(onStep, stepId, "Generate global skills.json", "running");
183
+ const result = await generateGlobalSkillsJson({ dryRun });
184
+ if (result.success) {
185
+ const prefix = dryRun ? "dry-run: would generate" : "generated";
186
+ report(onStep, stepId, "Generate global skills.json", "done", `${prefix} ${result.path} (${result.skillCount} skills from ${result.pluginCount} plugins)`);
187
+ }
188
+ else {
189
+ report(onStep, stepId, "Generate global skills.json", "error", result.error);
145
190
  }
146
191
  }
147
192
  //# sourceMappingURL=plugin.js.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Secret scanner — detects leaked credentials in source files using
3
+ * a curated regex bundle. Designed for pre-commit hooks and CI gates.
4
+ */
5
+ export interface SecretPattern {
6
+ id: string;
7
+ label: string;
8
+ pattern: RegExp;
9
+ severity: "critical" | "high" | "medium";
10
+ }
11
+ export interface SecretFinding {
12
+ patternId: string;
13
+ label: string;
14
+ severity: SecretPattern["severity"];
15
+ file: string;
16
+ line: number;
17
+ match: string;
18
+ }
19
+ export interface ScanResult {
20
+ findings: SecretFinding[];
21
+ filesScanned: number;
22
+ patternsUsed: number;
23
+ }
24
+ export declare const SECRET_PATTERNS: SecretPattern[];
25
+ export declare function maskSecret(value: string): string;
26
+ export declare function shouldScanFile(filePath: string): boolean;
27
+ export declare function shouldSkipDir(dirName: string): boolean;
28
+ export declare function scanContent(content: string, filePath: string, patterns?: SecretPattern[]): SecretFinding[];
29
+ export declare function scanDirectory(dir: string, patterns?: SecretPattern[]): Promise<ScanResult>;
30
+ //# sourceMappingURL=secret-scanner.d.ts.map