javi-forge 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +191 -3
  2. package/ci-local/hooks/pre-push +17 -13
  3. package/dist/commands/analyze.d.ts +1 -1
  4. package/dist/commands/analyze.js +15 -15
  5. package/dist/commands/atlassian-mcp.d.ts +42 -0
  6. package/dist/commands/atlassian-mcp.js +98 -0
  7. package/dist/commands/ci.d.ts +3 -3
  8. package/dist/commands/ci.js +185 -147
  9. package/dist/commands/crash-recovery.d.ts +34 -0
  10. package/dist/commands/crash-recovery.js +123 -0
  11. package/dist/commands/doctor.d.ts +2 -2
  12. package/dist/commands/doctor.js +113 -61
  13. package/dist/commands/harness-audit.d.ts +35 -0
  14. package/dist/commands/harness-audit.js +277 -0
  15. package/dist/commands/init.d.ts +1 -1
  16. package/dist/commands/init.js +415 -118
  17. package/dist/commands/llmstxt.d.ts +1 -1
  18. package/dist/commands/llmstxt.js +36 -34
  19. package/dist/commands/parallel-batch.d.ts +42 -0
  20. package/dist/commands/parallel-batch.js +90 -0
  21. package/dist/commands/plugin.d.ts +26 -1
  22. package/dist/commands/plugin.js +138 -24
  23. package/dist/commands/secret-scanner.d.ts +30 -0
  24. package/dist/commands/secret-scanner.js +272 -0
  25. package/dist/commands/security-analysis.d.ts +74 -0
  26. package/dist/commands/security-analysis.js +487 -0
  27. package/dist/commands/security.d.ts +31 -0
  28. package/dist/commands/security.js +445 -0
  29. package/dist/commands/skill-scanner.d.ts +63 -0
  30. package/dist/commands/skill-scanner.js +383 -0
  31. package/dist/commands/skills.d.ts +139 -0
  32. package/dist/commands/skills.js +895 -0
  33. package/dist/commands/supply-chain.d.ts +23 -0
  34. package/dist/commands/supply-chain.js +126 -0
  35. package/dist/commands/tdd-pipeline.d.ts +17 -0
  36. package/dist/commands/tdd-pipeline.js +144 -0
  37. package/dist/commands/tdd.d.ts +21 -0
  38. package/dist/commands/tdd.js +120 -0
  39. package/dist/commands/team-presets.d.ts +53 -0
  40. package/dist/commands/team-presets.js +201 -0
  41. package/dist/commands/workflow.d.ts +23 -0
  42. package/dist/commands/workflow.js +114 -0
  43. package/dist/constants.d.ts +21 -0
  44. package/dist/constants.js +208 -37
  45. package/dist/index.js +400 -54
  46. package/dist/lib/agent-skills.d.ts +73 -0
  47. package/dist/lib/agent-skills.js +260 -0
  48. package/dist/lib/auto-skill-install.d.ts +37 -0
  49. package/dist/lib/auto-skill-install.js +92 -0
  50. package/dist/lib/auto-wire.d.ts +20 -0
  51. package/dist/lib/auto-wire.js +240 -0
  52. package/dist/lib/claudemd.d.ts +20 -0
  53. package/dist/lib/claudemd.js +222 -0
  54. package/dist/lib/codex-export.d.ts +16 -0
  55. package/dist/lib/codex-export.js +109 -0
  56. package/dist/lib/common.d.ts +1 -1
  57. package/dist/lib/common.js +52 -44
  58. package/dist/lib/context.d.ts +27 -0
  59. package/dist/lib/context.js +204 -0
  60. package/dist/lib/docker.d.ts +1 -1
  61. package/dist/lib/docker.js +141 -112
  62. package/dist/lib/frontmatter.d.ts +1 -1
  63. package/dist/lib/frontmatter.js +29 -15
  64. package/dist/lib/plugin.d.ts +19 -1
  65. package/dist/lib/plugin.js +174 -47
  66. package/dist/lib/skill-publish.d.ts +40 -0
  67. package/dist/lib/skill-publish.js +146 -0
  68. package/dist/lib/stack-detector.d.ts +38 -0
  69. package/dist/lib/stack-detector.js +207 -0
  70. package/dist/lib/template.d.ts +16 -1
  71. package/dist/lib/template.js +46 -17
  72. package/dist/lib/workflow/discovery.d.ts +19 -0
  73. package/dist/lib/workflow/discovery.js +68 -0
  74. package/dist/lib/workflow/index.d.ts +5 -0
  75. package/dist/lib/workflow/index.js +5 -0
  76. package/dist/lib/workflow/parser.d.ts +16 -0
  77. package/dist/lib/workflow/parser.js +198 -0
  78. package/dist/lib/workflow/renderer.d.ts +9 -0
  79. package/dist/lib/workflow/renderer.js +152 -0
  80. package/dist/lib/workflow/validator.d.ts +10 -0
  81. package/dist/lib/workflow/validator.js +189 -0
  82. package/dist/tasks/index.d.ts +4 -0
  83. package/dist/tasks/index.js +4 -0
  84. package/dist/tasks/scaffold-tasks.d.ts +3 -0
  85. package/dist/tasks/scaffold-tasks.js +14 -0
  86. package/dist/tasks/task-id.d.ts +30 -0
  87. package/dist/tasks/task-id.js +55 -0
  88. package/dist/tasks/task-tracker.d.ts +15 -0
  89. package/dist/tasks/task-tracker.js +81 -0
  90. package/dist/types/index.d.ts +252 -5
  91. package/dist/types/index.js +11 -1
  92. package/dist/ui/AnalyzeUI.d.ts +1 -1
  93. package/dist/ui/AnalyzeUI.js +38 -39
  94. package/dist/ui/App.d.ts +5 -3
  95. package/dist/ui/App.js +92 -46
  96. package/dist/ui/AutoSkills.d.ts +9 -0
  97. package/dist/ui/AutoSkills.js +124 -0
  98. package/dist/ui/CI.d.ts +2 -2
  99. package/dist/ui/CI.js +24 -26
  100. package/dist/ui/CIContext.d.ts +1 -1
  101. package/dist/ui/CIContext.js +3 -2
  102. package/dist/ui/CISelector.d.ts +2 -2
  103. package/dist/ui/CISelector.js +23 -15
  104. package/dist/ui/Doctor.d.ts +1 -1
  105. package/dist/ui/Doctor.js +35 -29
  106. package/dist/ui/Header.d.ts +1 -1
  107. package/dist/ui/Header.js +14 -14
  108. package/dist/ui/HookProfileSelector.d.ts +9 -0
  109. package/dist/ui/HookProfileSelector.js +54 -0
  110. package/dist/ui/LlmsTxt.d.ts +1 -1
  111. package/dist/ui/LlmsTxt.js +31 -22
  112. package/dist/ui/MemorySelector.d.ts +2 -2
  113. package/dist/ui/MemorySelector.js +28 -16
  114. package/dist/ui/NameInput.d.ts +1 -1
  115. package/dist/ui/NameInput.js +21 -21
  116. package/dist/ui/OptionSelector.d.ts +8 -2
  117. package/dist/ui/OptionSelector.js +83 -26
  118. package/dist/ui/Plugin.d.ts +4 -3
  119. package/dist/ui/Plugin.js +89 -29
  120. package/dist/ui/Progress.d.ts +3 -3
  121. package/dist/ui/Progress.js +23 -22
  122. package/dist/ui/Skills.d.ts +11 -0
  123. package/dist/ui/Skills.js +148 -0
  124. package/dist/ui/StackSelector.d.ts +2 -2
  125. package/dist/ui/StackSelector.js +26 -16
  126. package/dist/ui/Summary.d.ts +3 -3
  127. package/dist/ui/Summary.js +60 -50
  128. package/dist/ui/Welcome.d.ts +1 -1
  129. package/dist/ui/Welcome.js +15 -16
  130. package/dist/ui/theme.d.ts +1 -1
  131. package/dist/ui/theme.js +6 -6
  132. package/package.json +9 -6
  133. package/templates/common/atlassian/mcp-atlassian-snippet.json +16 -0
  134. package/templates/common/repoforge/mcp-repoforge-snippet.json +11 -0
  135. package/templates/common/repoforge/repoforge.yaml +34 -0
  136. package/templates/github/deploy-docker-zero-downtime.yml +140 -0
  137. package/templates/github/repoforge-graph.yml +45 -0
  138. package/templates/gitlab/deploy-docker-zero-downtime.yml +57 -0
  139. package/templates/local-ai/.env.example +17 -0
  140. package/templates/local-ai/docker-compose.yml +95 -0
  141. package/templates/security-hooks/claude-settings-security.json +30 -0
  142. package/templates/security-hooks/commit-msg-signing +29 -0
  143. package/templates/security-hooks/pre-commit-permissions +74 -0
  144. package/templates/security-hooks/pre-commit-secrets +74 -0
  145. package/templates/security-hooks/pre-push-branch-protection +62 -0
  146. package/templates/security-hooks/pre-push-deps +83 -0
  147. package/templates/security-hooks/pre-push-signing +67 -0
  148. package/templates/woodpecker/deploy-docker-zero-downtime.yml +50 -0
  149. package/templates/workflows/ci-pipeline.dot +15 -0
  150. package/templates/workflows/feature-flow.dot +21 -0
  151. package/templates/workflows/release.dot +16 -0
  152. package/dist/__integration__/helpers.d.ts +0 -20
  153. package/dist/__integration__/helpers.d.ts.map +0 -1
  154. package/dist/__integration__/helpers.js +0 -31
  155. package/dist/__integration__/helpers.js.map +0 -1
  156. package/dist/commands/analyze.d.ts.map +0 -1
  157. package/dist/commands/analyze.js.map +0 -1
  158. package/dist/commands/ci.d.ts.map +0 -1
  159. package/dist/commands/ci.js.map +0 -1
  160. package/dist/commands/doctor.d.ts.map +0 -1
  161. package/dist/commands/doctor.js.map +0 -1
  162. package/dist/commands/init.d.ts.map +0 -1
  163. package/dist/commands/init.js.map +0 -1
  164. package/dist/commands/llmstxt.d.ts.map +0 -1
  165. package/dist/commands/llmstxt.js.map +0 -1
  166. package/dist/commands/plugin.d.ts.map +0 -1
  167. package/dist/commands/plugin.js.map +0 -1
  168. package/dist/constants.d.ts.map +0 -1
  169. package/dist/constants.js.map +0 -1
  170. package/dist/index.d.ts.map +0 -1
  171. package/dist/index.js.map +0 -1
  172. package/dist/lib/common.d.ts.map +0 -1
  173. package/dist/lib/common.js.map +0 -1
  174. package/dist/lib/docker.d.ts.map +0 -1
  175. package/dist/lib/docker.js.map +0 -1
  176. package/dist/lib/frontmatter.d.ts.map +0 -1
  177. package/dist/lib/frontmatter.js.map +0 -1
  178. package/dist/lib/plugin.d.ts.map +0 -1
  179. package/dist/lib/plugin.js.map +0 -1
  180. package/dist/lib/template.d.ts.map +0 -1
  181. package/dist/lib/template.js.map +0 -1
  182. package/dist/types/index.d.ts.map +0 -1
  183. package/dist/types/index.js.map +0 -1
  184. package/dist/ui/AnalyzeUI.d.ts.map +0 -1
  185. package/dist/ui/AnalyzeUI.js.map +0 -1
  186. package/dist/ui/App.d.ts.map +0 -1
  187. package/dist/ui/App.js.map +0 -1
  188. package/dist/ui/CI.d.ts.map +0 -1
  189. package/dist/ui/CI.js.map +0 -1
  190. package/dist/ui/CIContext.d.ts.map +0 -1
  191. package/dist/ui/CIContext.js.map +0 -1
  192. package/dist/ui/CISelector.d.ts.map +0 -1
  193. package/dist/ui/CISelector.js.map +0 -1
  194. package/dist/ui/Doctor.d.ts.map +0 -1
  195. package/dist/ui/Doctor.js.map +0 -1
  196. package/dist/ui/Header.d.ts.map +0 -1
  197. package/dist/ui/Header.js.map +0 -1
  198. package/dist/ui/LlmsTxt.d.ts.map +0 -1
  199. package/dist/ui/LlmsTxt.js.map +0 -1
  200. package/dist/ui/MemorySelector.d.ts.map +0 -1
  201. package/dist/ui/MemorySelector.js.map +0 -1
  202. package/dist/ui/NameInput.d.ts.map +0 -1
  203. package/dist/ui/NameInput.js.map +0 -1
  204. package/dist/ui/OptionSelector.d.ts.map +0 -1
  205. package/dist/ui/OptionSelector.js.map +0 -1
  206. package/dist/ui/Plugin.d.ts.map +0 -1
  207. package/dist/ui/Plugin.js.map +0 -1
  208. package/dist/ui/Progress.d.ts.map +0 -1
  209. package/dist/ui/Progress.js.map +0 -1
  210. package/dist/ui/StackSelector.d.ts.map +0 -1
  211. package/dist/ui/StackSelector.js.map +0 -1
  212. package/dist/ui/Summary.d.ts.map +0 -1
  213. package/dist/ui/Summary.js.map +0 -1
  214. package/dist/ui/Welcome.d.ts.map +0 -1
  215. package/dist/ui/Welcome.js.map +0 -1
  216. package/dist/ui/theme.d.ts.map +0 -1
  217. package/dist/ui/theme.js.map +0 -1
@@ -1,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.
@@ -20,5 +20,30 @@ export declare function runPluginSearch(query: string | undefined, onStep: StepC
20
20
  * Validate a local plugin directory.
21
21
  */
22
22
  export declare function runPluginValidate(pluginDir: string, onStep: StepCallback): Promise<void>;
23
+ /**
24
+ * Sync detected plugins into the project manifest.
25
+ */
26
+ export declare function runPluginSync(projectDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
27
+ /**
28
+ * Export an installed plugin to Agent Skills spec format.
29
+ */
30
+ export declare function runPluginExport(name: string, onStep: StepCallback): Promise<void>;
31
+ /**
32
+ * Export an installed plugin to Codex-compatible TOML subagent files.
33
+ */
34
+ export declare function runPluginExportCodex(name: string, onStep: StepCallback): Promise<void>;
35
+ /**
36
+ * Import an Agent Skills spec package and convert to javi-forge plugin format.
37
+ */
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>;
23
48
  export {};
24
49
  //# sourceMappingURL=plugin.d.ts.map
@@ -1,4 +1,6 @@
1
- import { installPlugin, removePlugin, listInstalledPlugins, validatePlugin, searchRegistry, } from '../lib/plugin.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";
2
4
  function report(onStep, id, label, status, detail) {
3
5
  onStep({ id, label, status, detail });
4
6
  }
@@ -6,73 +8,185 @@ function report(onStep, id, label, status, detail) {
6
8
  * Add (install) a plugin from a GitHub source.
7
9
  */
8
10
  export async function runPluginAdd(source, dryRun, onStep) {
9
- const stepId = 'plugin-add';
10
- report(onStep, stepId, `Install plugin: ${source}`, 'running');
11
+ const stepId = "plugin-add";
12
+ report(onStep, stepId, `Install plugin: ${source}`, "running");
11
13
  const result = await installPlugin(source, { dryRun });
12
14
  if (result.success) {
13
- 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}`);
14
18
  }
15
19
  else {
16
- report(onStep, stepId, `Install plugin: ${source}`, 'error', result.error);
20
+ report(onStep, stepId, `Install plugin: ${source}`, "error", result.error);
17
21
  }
18
22
  }
19
23
  /**
20
24
  * Remove an installed plugin by name.
21
25
  */
22
26
  export async function runPluginRemove(name, dryRun, onStep) {
23
- const stepId = 'plugin-remove';
24
- report(onStep, stepId, `Remove plugin: ${name}`, 'running');
27
+ const stepId = "plugin-remove";
28
+ report(onStep, stepId, `Remove plugin: ${name}`, "running");
25
29
  const result = await removePlugin(name, { dryRun });
26
30
  if (result.success) {
27
- 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}`);
28
32
  }
29
33
  else {
30
- report(onStep, stepId, `Remove plugin: ${name}`, 'error', result.error);
34
+ report(onStep, stepId, `Remove plugin: ${name}`, "error", result.error);
31
35
  }
32
36
  }
33
37
  /**
34
38
  * List all installed plugins.
35
39
  */
36
40
  export async function runPluginList(onStep) {
37
- const stepId = 'plugin-list';
38
- report(onStep, stepId, 'List installed plugins', 'running');
41
+ const stepId = "plugin-list";
42
+ report(onStep, stepId, "List installed plugins", "running");
39
43
  const plugins = await listInstalledPlugins();
40
44
  if (plugins.length === 0) {
41
- report(onStep, stepId, 'List installed plugins', 'done', 'no plugins installed');
45
+ report(onStep, stepId, "List installed plugins", "done", "no plugins installed");
42
46
  }
43
47
  else {
44
- const summary = plugins.map(p => `${p.name}@${p.version}`).join(', ');
45
- 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}`);
46
50
  }
47
51
  }
48
52
  /**
49
53
  * Search the remote plugin registry.
50
54
  */
51
55
  export async function runPluginSearch(query, onStep) {
52
- const stepId = 'plugin-search';
53
- report(onStep, stepId, `Search plugins${query ? `: ${query}` : ''}`, 'running');
56
+ const stepId = "plugin-search";
57
+ report(onStep, stepId, `Search plugins${query ? `: ${query}` : ""}`, "running");
54
58
  const results = await searchRegistry(query);
55
59
  if (results.length === 0) {
56
- 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");
57
63
  }
58
64
  else {
59
- const summary = results.map(p => `${p.id} — ${p.description}`).join('\n ');
60
- 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}`);
61
69
  }
62
70
  }
63
71
  /**
64
72
  * Validate a local plugin directory.
65
73
  */
66
74
  export async function runPluginValidate(pluginDir, onStep) {
67
- const stepId = 'plugin-validate';
68
- report(onStep, stepId, `Validate plugin: ${pluginDir}`, 'running');
75
+ const stepId = "plugin-validate";
76
+ report(onStep, stepId, `Validate plugin: ${pluginDir}`, "running");
69
77
  const result = await validatePlugin(pluginDir);
70
78
  if (result.valid) {
71
- 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}`);
72
80
  }
73
81
  else {
74
- const msgs = result.errors.map(e => ` ${e.path}: ${e.message}`).join('\n');
75
- 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}`);
86
+ }
87
+ }
88
+ /**
89
+ * Sync detected plugins into the project manifest.
90
+ */
91
+ export async function runPluginSync(projectDir, dryRun, onStep) {
92
+ const stepId = "plugin-sync";
93
+ report(onStep, stepId, "Sync plugins", "running");
94
+ try {
95
+ const result = await syncPlugins(projectDir, { dryRun });
96
+ const parts = [];
97
+ if (result.added.length > 0)
98
+ parts.push(`added: ${result.added.join(", ")}`);
99
+ if (result.removed.length > 0)
100
+ parts.push(`removed: ${result.removed.join(", ")}`);
101
+ if (result.unchanged.length > 0)
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`);
107
+ if (parts.length === 0)
108
+ parts.push("no plugins detected");
109
+ const prefix = dryRun ? "dry-run: " : "";
110
+ report(onStep, stepId, "Sync plugins", "done", `${prefix}${parts.join(" | ")}`);
111
+ }
112
+ catch (e) {
113
+ const msg = e instanceof Error ? e.message : String(e);
114
+ report(onStep, stepId, "Sync plugins", "error", msg);
115
+ }
116
+ }
117
+ /**
118
+ * Export an installed plugin to Agent Skills spec format.
119
+ */
120
+ export async function runPluginExport(name, onStep) {
121
+ const stepId = "plugin-export";
122
+ report(onStep, stepId, `Export plugin: ${name}`, "running");
123
+ const result = await exportPluginAsAgentSkills(name);
124
+ if (result.success) {
125
+ report(onStep, stepId, `Export plugin: ${name}`, "done", `exported to ${result.path}`);
126
+ }
127
+ else {
128
+ report(onStep, stepId, `Export plugin: ${name}`, "error", result.error);
129
+ }
130
+ }
131
+ /**
132
+ * Export an installed plugin to Codex-compatible TOML subagent files.
133
+ */
134
+ export async function runPluginExportCodex(name, onStep) {
135
+ const stepId = "plugin-export-codex";
136
+ report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "running");
137
+ const result = await exportPluginAsCodexToml(name);
138
+ if (result.success) {
139
+ report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "done", `exported ${result.files.length} TOML file(s)`);
140
+ }
141
+ else {
142
+ report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "error", result.error);
143
+ }
144
+ }
145
+ /**
146
+ * Import an Agent Skills spec package and convert to javi-forge plugin format.
147
+ */
148
+ export async function runPluginImport(sourceDir, dryRun, onStep) {
149
+ const stepId = "plugin-import";
150
+ report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, "running");
151
+ const result = await importAgentSkillsPackage(sourceDir, { dryRun });
152
+ if (result.success) {
153
+ report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, "done", dryRun
154
+ ? `dry-run: would import ${result.name}`
155
+ : `imported ${result.name}`);
156
+ }
157
+ else {
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);
76
190
  }
77
191
  }
78
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