forge-cc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/.forge.json +5 -0
  2. package/AGENTS.md +42 -0
  3. package/README.md +283 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +148 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config/loader.d.ts +2 -0
  8. package/dist/config/loader.js +44 -0
  9. package/dist/config/loader.js.map +1 -0
  10. package/dist/config/schema.d.ts +57 -0
  11. package/dist/config/schema.js +15 -0
  12. package/dist/config/schema.js.map +1 -0
  13. package/dist/gates/index.d.ts +11 -0
  14. package/dist/gates/index.js +106 -0
  15. package/dist/gates/index.js.map +1 -0
  16. package/dist/gates/lint-gate.d.ts +2 -0
  17. package/dist/gates/lint-gate.js +66 -0
  18. package/dist/gates/lint-gate.js.map +1 -0
  19. package/dist/gates/prd-gate.d.ts +7 -0
  20. package/dist/gates/prd-gate.js +193 -0
  21. package/dist/gates/prd-gate.js.map +1 -0
  22. package/dist/gates/runtime-gate.d.ts +5 -0
  23. package/dist/gates/runtime-gate.js +99 -0
  24. package/dist/gates/runtime-gate.js.map +1 -0
  25. package/dist/gates/tests-gate.d.ts +2 -0
  26. package/dist/gates/tests-gate.js +116 -0
  27. package/dist/gates/tests-gate.js.map +1 -0
  28. package/dist/gates/types-gate.d.ts +2 -0
  29. package/dist/gates/types-gate.js +59 -0
  30. package/dist/gates/types-gate.js.map +1 -0
  31. package/dist/gates/visual-gate.d.ts +6 -0
  32. package/dist/gates/visual-gate.js +118 -0
  33. package/dist/gates/visual-gate.js.map +1 -0
  34. package/dist/go/auto-chain.d.ts +107 -0
  35. package/dist/go/auto-chain.js +303 -0
  36. package/dist/go/auto-chain.js.map +1 -0
  37. package/dist/go/executor.d.ts +130 -0
  38. package/dist/go/executor.js +409 -0
  39. package/dist/go/executor.js.map +1 -0
  40. package/dist/go/finalize.d.ts +58 -0
  41. package/dist/go/finalize.js +200 -0
  42. package/dist/go/finalize.js.map +1 -0
  43. package/dist/go/linear-sync.d.ts +75 -0
  44. package/dist/go/linear-sync.js +239 -0
  45. package/dist/go/linear-sync.js.map +1 -0
  46. package/dist/go/verify-loop.d.ts +47 -0
  47. package/dist/go/verify-loop.js +172 -0
  48. package/dist/go/verify-loop.js.map +1 -0
  49. package/dist/hooks/pre-commit.d.ts +5 -0
  50. package/dist/hooks/pre-commit.js +69 -0
  51. package/dist/hooks/pre-commit.js.map +1 -0
  52. package/dist/linear/client.d.ts +108 -0
  53. package/dist/linear/client.js +388 -0
  54. package/dist/linear/client.js.map +1 -0
  55. package/dist/linear/issues.d.ts +20 -0
  56. package/dist/linear/issues.js +39 -0
  57. package/dist/linear/issues.js.map +1 -0
  58. package/dist/linear/milestones.d.ts +11 -0
  59. package/dist/linear/milestones.js +32 -0
  60. package/dist/linear/milestones.js.map +1 -0
  61. package/dist/linear/projects.d.ts +16 -0
  62. package/dist/linear/projects.js +50 -0
  63. package/dist/linear/projects.js.map +1 -0
  64. package/dist/reporter/human.d.ts +2 -0
  65. package/dist/reporter/human.js +63 -0
  66. package/dist/reporter/human.js.map +1 -0
  67. package/dist/reporter/json.d.ts +2 -0
  68. package/dist/reporter/json.js +4 -0
  69. package/dist/reporter/json.js.map +1 -0
  70. package/dist/server.d.ts +2 -0
  71. package/dist/server.js +109 -0
  72. package/dist/server.js.map +1 -0
  73. package/dist/spec/generator.d.ts +14 -0
  74. package/dist/spec/generator.js +206 -0
  75. package/dist/spec/generator.js.map +1 -0
  76. package/dist/spec/interview.d.ts +104 -0
  77. package/dist/spec/interview.js +342 -0
  78. package/dist/spec/interview.js.map +1 -0
  79. package/dist/spec/linear-sync.d.ts +48 -0
  80. package/dist/spec/linear-sync.js +125 -0
  81. package/dist/spec/linear-sync.js.map +1 -0
  82. package/dist/spec/scanner.d.ts +45 -0
  83. package/dist/spec/scanner.js +473 -0
  84. package/dist/spec/scanner.js.map +1 -0
  85. package/dist/spec/templates.d.ts +345 -0
  86. package/dist/spec/templates.js +86 -0
  87. package/dist/spec/templates.js.map +1 -0
  88. package/dist/state/reader.d.ts +29 -0
  89. package/dist/state/reader.js +116 -0
  90. package/dist/state/reader.js.map +1 -0
  91. package/dist/state/writer.d.ts +60 -0
  92. package/dist/state/writer.js +222 -0
  93. package/dist/state/writer.js.map +1 -0
  94. package/dist/types.d.ts +64 -0
  95. package/dist/types.js +2 -0
  96. package/dist/types.js.map +1 -0
  97. package/dist/utils/browser.d.ts +10 -0
  98. package/dist/utils/browser.js +89 -0
  99. package/dist/utils/browser.js.map +1 -0
  100. package/hooks/pre-commit-verify.js +103 -0
  101. package/package.json +68 -0
  102. package/skills/README.md +33 -0
  103. package/skills/forge-go.md +332 -0
  104. package/skills/forge-spec.md +251 -0
  105. package/skills/forge-triage.md +133 -0
package/.forge.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "gates": ["types", "lint", "tests"],
3
+ "maxIterations": 5,
4
+ "verifyFreshness": 600000
5
+ }
package/AGENTS.md ADDED
@@ -0,0 +1,42 @@
1
+ # AGENTS.md -- forge-cc Instructions for Non-Claude Agents
2
+
3
+ forge-cc is a pre-PR verification tool. You must pass verification before committing code.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ # Run verification (required before every commit)
9
+ npx forge verify
10
+
11
+ # Check current status
12
+ npx forge status
13
+ ```
14
+
15
+ ## Rules
16
+
17
+ - Run `npx forge verify` and confirm all gates pass before any `git commit`.
18
+ - If verification fails, fix the reported errors and re-run until it passes.
19
+ - Never commit directly to `main` or `master`. Always use a feature branch.
20
+ - Exit code `0` means pass. Exit code `1` means fail.
21
+
22
+ ## Configuration
23
+
24
+ - Config file: `.forge.json` in project root.
25
+ - If no config exists, gates are auto-detected from `package.json`.
26
+ - Default gates: `types` (tsc), `lint` (biome), `tests` (npm test).
27
+
28
+ ## Structured Output
29
+
30
+ Use `npx forge verify --json` for machine-readable JSON results.
31
+
32
+ ## Run Specific Gates
33
+
34
+ Use `--gate` to run only certain gates:
35
+
36
+ ```bash
37
+ npx forge verify --gate types,lint
38
+ ```
39
+
40
+ ## More Information
41
+
42
+ See `README.md` for full documentation.
package/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # forge-cc
2
+
3
+ Pre-PR verification harness and development workflow tool for Claude Code agents. Gate runner + CLI + MCP server + workflow skills.
4
+
5
+ <!-- Badges: npm version, CI status, license -->
6
+
7
+ ## What It Does
8
+
9
+ - **Verification gates** -- runs TypeScript type-checking, linting, tests, visual screenshots, runtime endpoint validation, and PRD acceptance criteria checks against your project before you commit.
10
+ - **Mechanical enforcement** -- Claude Code PreToolUse hook and git pre-commit hook block commits that haven't passed verification. No discipline required; the machine enforces it.
11
+ - **Workflow skills** -- `/forge:triage` turns brain dumps into Linear projects, `/forge:spec` interviews you and generates a PRD with milestones, `/forge:go` executes milestones with wave-based agent teams.
12
+ - **Linear lifecycle** -- programmatic status transitions through Backlog, Planned, In Progress, In Review, and Done. Every skill keeps Linear in sync automatically.
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ # Install
18
+ npm install forge-cc
19
+
20
+ # Run verification against current project
21
+ npx forge verify
22
+
23
+ # Check last verification status
24
+ npx forge status
25
+ ```
26
+
27
+ On first run with no `.forge.json`, forge auto-detects gates from your `package.json`:
28
+ - Has `typescript` in dependencies? Enables the **types** gate.
29
+ - Has `@biomejs/biome` or `biome` in dependencies? Enables the **lint** gate.
30
+ - Has a `test` script? Enables the **tests** gate.
31
+
32
+ ## Configuration
33
+
34
+ Create a `.forge.json` in your project root to customize behavior:
35
+
36
+ ```json
37
+ {
38
+ "gates": ["types", "lint", "tests"],
39
+ "maxIterations": 5,
40
+ "verifyFreshness": 600000,
41
+ "devServer": {
42
+ "command": "npm run dev",
43
+ "port": 3000,
44
+ "readyPattern": "ready on"
45
+ },
46
+ "prdPath": ".planning/prds/active.md",
47
+ "linearProject": "My Project"
48
+ }
49
+ ```
50
+
51
+ | Option | Type | Default | Description |
52
+ |--------|------|---------|-------------|
53
+ | `gates` | `string[]` | `["types", "lint", "tests"]` | Which verification gates to run |
54
+ | `maxIterations` | `number` | `5` | Max retry iterations for the verification pipeline |
55
+ | `verifyFreshness` | `number` | `600000` | How long (ms) a passing verification stays valid. Default: 10 minutes |
56
+ | `devServer.command` | `string` | -- | Command to start the dev server (for visual/runtime gates) |
57
+ | `devServer.port` | `number` | -- | Port the dev server listens on |
58
+ | `devServer.readyPattern` | `string` | -- | Stdout pattern indicating the server is ready |
59
+ | `prdPath` | `string` | -- | Path to PRD file for acceptance criteria checking |
60
+ | `linearProject` | `string` | -- | Linear project name for lifecycle tracking |
61
+
62
+ If no `.forge.json` exists, forge auto-detects from `package.json` (see Quick Start).
63
+
64
+ ## CLI Commands
65
+
66
+ ### `forge verify`
67
+
68
+ Run verification gates against the current project.
69
+
70
+ ```bash
71
+ # Run all configured gates
72
+ npx forge verify
73
+
74
+ # Run specific gates only
75
+ npx forge verify --gate types,lint
76
+
77
+ # Output structured JSON (for programmatic use)
78
+ npx forge verify --json
79
+
80
+ # Include PRD acceptance criteria check
81
+ npx forge verify --prd .planning/prds/active.md
82
+ ```
83
+
84
+ | Flag | Description |
85
+ |------|-------------|
86
+ | `--gate <gates>` | Comma-separated list of gates to run (overrides config) |
87
+ | `--json` | Output structured JSON instead of human-readable markdown |
88
+ | `--prd <path>` | Path to PRD file for the `prd` gate |
89
+
90
+ Exit code: `0` if all gates pass, `1` if any gate fails.
91
+
92
+ Results are cached to `.forge/last-verify.json` for freshness checking by hooks.
93
+
94
+ ### `forge status`
95
+
96
+ Print current project state: branch, last verification result, config source.
97
+
98
+ ```bash
99
+ npx forge status
100
+ ```
101
+
102
+ Output includes which gates passed/failed, how long ago verification ran, and whether config is from `.forge.json` or auto-detected.
103
+
104
+ ## Verification Gates
105
+
106
+ | Gate | What It Checks | Requires |
107
+ |------|---------------|----------|
108
+ | `types` | TypeScript compilation (`tsc --noEmit`) | `typescript` in dependencies |
109
+ | `lint` | Biome linting (`biome check`) | `@biomejs/biome` in dependencies |
110
+ | `tests` | Test suite (`npm run test`) | A `test` script in `package.json` |
111
+ | `visual` | Playwright screenshots + console error detection | Dev server config, `playwright` |
112
+ | `runtime` | HTTP endpoint validation (status codes, response shape) | Dev server config, endpoint list |
113
+ | `prd` | Diff against PRD acceptance criteria | PRD file path, git history |
114
+
115
+ **Pipeline behavior:** Gates run in order. If all three core gates (types, lint, tests) fail, remaining gates are skipped. Each gate returns structured results with file paths, line numbers, and error messages.
116
+
117
+ ## Enforcement
118
+
119
+ forge-cc provides two enforcement mechanisms that block commits without passing verification.
120
+
121
+ ### Claude Code PreToolUse Hook
122
+
123
+ The recommended enforcement for Claude Code users. Intercepts `git commit` commands and checks:
124
+
125
+ 1. **Branch protection** -- blocks commits directly to `main` or `master`.
126
+ 2. **Verification required** -- blocks if no `.forge/last-verify.json` exists.
127
+ 3. **Verification passed** -- blocks if the last run failed.
128
+ 4. **Freshness** -- blocks if verification is older than `verifyFreshness` (default 10 min).
129
+
130
+ **Install:**
131
+
132
+ Add to your `.claude/settings.json`:
133
+
134
+ ```json
135
+ {
136
+ "hooks": {
137
+ "PreToolUse": [
138
+ {
139
+ "matcher": "Bash",
140
+ "hooks": [
141
+ {
142
+ "type": "command",
143
+ "command": "node node_modules/forge-cc/hooks/pre-commit-verify.js"
144
+ }
145
+ ]
146
+ }
147
+ ]
148
+ }
149
+ }
150
+ ```
151
+
152
+ ### Git Pre-Commit Hook
153
+
154
+ Standard git hook for non-Claude-Code environments. Same four checks as the PreToolUse hook.
155
+
156
+ The hook logic lives in `src/hooks/pre-commit.ts` and can be wired into any git hook runner (husky, simple-git-hooks, etc.).
157
+
158
+ ## MCP Server
159
+
160
+ forge-cc registers its gates as MCP tools so agents can call them programmatically.
161
+
162
+ **Configure in `.mcp.json`:**
163
+
164
+ ```json
165
+ {
166
+ "mcpServers": {
167
+ "forge-cc": {
168
+ "command": "node",
169
+ "args": ["node_modules/forge-cc/dist/server.js"]
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ **Available MCP tools:**
176
+
177
+ | Tool | Description |
178
+ |------|-------------|
179
+ | `forge_verify_types` | Run TypeScript type checking |
180
+ | `forge_verify_lint` | Run Biome linting |
181
+ | `forge_verify_tests` | Run project test suite |
182
+ | `forge_verify_visual` | Take screenshots, check console errors |
183
+ | `forge_verify_runtime` | Validate API endpoints |
184
+ | `forge_verify_prd` | Check changes against PRD criteria |
185
+ | `forge_run_pipeline` | Run full verification pipeline |
186
+
187
+ All tools accept `projectDir` (absolute path) and return structured JSON results.
188
+
189
+ ## Workflow Skills
190
+
191
+ Claude Code skills that drive the full development lifecycle. Invoke them with slash commands.
192
+
193
+ ### `/forge:triage` -- Brain Dump to Linear Projects
194
+
195
+ Paste unstructured ideas, sticky notes, or stream-of-consciousness text. The skill extracts distinct projects, deduplicates against your existing Linear backlog, and creates them after your confirmation.
196
+
197
+ **Flow:** Input text -> extract projects -> deduplicate against Linear -> confirm -> create in Linear (Backlog state).
198
+
199
+ ### `/forge:spec` -- Interview to PRD
200
+
201
+ Select a Linear project in Backlog state. The skill scans your codebase (structure, patterns, dependencies), conducts an adaptive interview (leading with recommendations, not blank-slate questions), generates a PRD with milestones, and syncs the plan back to Linear.
202
+
203
+ **Flow:** Select project -> scan codebase -> interview -> generate PRD -> create milestones + issues in Linear -> move project to Planned.
204
+
205
+ ### `/forge:go` -- Execute Milestones
206
+
207
+ Execute the next pending milestone from your PRD with wave-based agent teams. Each wave runs parallel agents for independent work, with verification between waves. Supports `--auto` to chain all remaining milestones without manual intervention.
208
+
209
+ **Flow:** Orient (read state) -> pre-flight checks -> execute waves -> verify -> update state -> (optional) create PR.
210
+
211
+ ## Linear Integration
212
+
213
+ forge-cc manages the full Linear project lifecycle:
214
+
215
+ ```
216
+ Backlog -> Planned -> In Progress -> In Review -> Done
217
+ | | | | |
218
+ triage spec/PRD go/execute PR created PR merged
219
+ ```
220
+
221
+ Each skill transitions projects and issues to the appropriate status automatically. The Linear client (`src/linear/client.ts`) handles GraphQL queries, and dedicated modules manage projects, milestones, and issues.
222
+
223
+ ## Multi-Developer Setup
224
+
225
+ For a new developer joining the team:
226
+
227
+ 1. **Clone the repo** that uses forge-cc.
228
+ 2. **Install dependencies:** `npm install` (forge-cc should be in `devDependencies`).
229
+ 3. **Run verification:** `npx forge verify` -- confirms your environment is set up correctly.
230
+ 4. **Check status:** `npx forge status` -- shows current branch and last verification.
231
+ 5. **Install the hook** (optional but recommended): add the PreToolUse hook to `.claude/settings.json` (see Enforcement section above).
232
+ 6. **Create a `.forge.json`** if the auto-detected gates don't match your needs.
233
+
234
+ That's it. The gates run the same commands your CI does, so if `npx forge verify` passes locally, CI will pass too.
235
+
236
+ ## Project Structure
237
+
238
+ ```
239
+ forge-cc/
240
+ src/
241
+ cli.ts # CLI entry point (npx forge)
242
+ server.ts # MCP server entry point
243
+ types.ts # Core type definitions
244
+ gates/ # Verification gates (types, lint, tests, visual, runtime, prd)
245
+ linear/ # Linear API client + lifecycle management
246
+ hooks/ # Pre-commit hook logic
247
+ config/ # .forge.json schema + auto-detection loader
248
+ reporter/ # Human (markdown) and JSON output formatting
249
+ state/ # Session state reader/writer (STATE.md, ROADMAP.md)
250
+ spec/ # Spec interview engine + PRD generation
251
+ go/ # Execution engine + verify loop + PR creation
252
+ skills/ # Claude Code skill definitions (/forge:triage, /forge:spec, /forge:go)
253
+ hooks/ # Installable hook files (PreToolUse)
254
+ tests/ # Test suite (vitest)
255
+ .forge.json # Default configuration
256
+ ```
257
+
258
+ ## Development
259
+
260
+ Working on forge-cc itself:
261
+
262
+ ```bash
263
+ # Install dependencies
264
+ npm install
265
+
266
+ # Build
267
+ npm run build
268
+
269
+ # Run tests
270
+ npm test
271
+
272
+ # Watch mode (rebuild on changes)
273
+ npm run dev
274
+
275
+ # Run verification on forge-cc itself
276
+ npm run verify
277
+ ```
278
+
279
+ **Tech stack:** TypeScript (ES2022, strict), Node.js, `@modelcontextprotocol/sdk`, Commander, Playwright, Zod, Vitest.
280
+
281
+ ## License
282
+
283
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { execSync } from "node:child_process";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { runPipeline } from "./gates/index.js";
7
+ import { loadConfig } from "./config/loader.js";
8
+ const program = new Command();
9
+ program
10
+ .name("forge")
11
+ .description("forge-cc — verification + workflow CLI for Claude Code agents")
12
+ .version("0.1.0");
13
+ program
14
+ .command("verify")
15
+ .description("Run verification gates against the current project")
16
+ .option("--gate <gates>", "Comma-separated list of gates to run (e.g., types,lint,tests)")
17
+ .option("--json", "Output structured JSON instead of human-readable report")
18
+ .option("--prd <path>", "Path to PRD for acceptance criteria matching")
19
+ .action(async (opts) => {
20
+ try {
21
+ const projectDir = process.cwd();
22
+ const config = loadConfig(projectDir);
23
+ const gates = opts.gate ? opts.gate.split(",").map((g) => g.trim()) : config.gates;
24
+ const prdPath = opts.prd ?? config.prdPath;
25
+ const result = await runPipeline({
26
+ projectDir,
27
+ gates,
28
+ prdPath,
29
+ maxIterations: config.maxIterations,
30
+ devServerCommand: config.devServer?.command,
31
+ devServerPort: config.devServer?.port,
32
+ });
33
+ // Generate report if pipeline didn't produce one
34
+ if (!result.report) {
35
+ result.report = formatReport(result);
36
+ }
37
+ // Write verify cache (non-fatal if this fails)
38
+ try {
39
+ writeVerifyCache(projectDir, result);
40
+ }
41
+ catch (cacheErr) {
42
+ const msg = cacheErr instanceof Error ? cacheErr.message : String(cacheErr);
43
+ console.error(`Warning: Could not write verify cache: ${msg}`);
44
+ }
45
+ // Output
46
+ if (opts.json) {
47
+ console.log(JSON.stringify(result, null, 2));
48
+ }
49
+ else {
50
+ console.log(result.report);
51
+ }
52
+ process.exit(result.passed ? 0 : 1);
53
+ }
54
+ catch (err) {
55
+ const message = err instanceof Error ? err.message : String(err);
56
+ console.error(`Error: forge verify failed — ${message}`);
57
+ process.exit(1);
58
+ }
59
+ });
60
+ program
61
+ .command("status")
62
+ .description("Print current project state")
63
+ .action(() => {
64
+ const projectDir = process.cwd();
65
+ // Branch
66
+ let branch = "unknown";
67
+ try {
68
+ branch = execSync("git branch --show-current", { encoding: "utf-8" }).trim();
69
+ }
70
+ catch { /* not a git repo */ }
71
+ console.log(`## Forge Status`);
72
+ console.log(`**Branch:** ${branch}`);
73
+ // Last verify
74
+ const cachePath = join(projectDir, ".forge", "last-verify.json");
75
+ if (existsSync(cachePath)) {
76
+ const cache = JSON.parse(readFileSync(cachePath, "utf-8"));
77
+ const status = cache.passed ? "PASSED" : "FAILED";
78
+ const age = Math.round((Date.now() - new Date(cache.timestamp).getTime()) / 60_000);
79
+ console.log(`**Last Verify:** ${status} (${age}min ago on ${cache.branch})`);
80
+ for (const gate of cache.gates) {
81
+ const icon = gate.passed ? "[x]" : "[ ]";
82
+ console.log(` - ${icon} ${gate.gate}: ${gate.passed ? "PASS" : "FAIL"}`);
83
+ }
84
+ }
85
+ else {
86
+ console.log(`**Last Verify:** none`);
87
+ }
88
+ // Config
89
+ const configPath = join(projectDir, ".forge.json");
90
+ if (existsSync(configPath)) {
91
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
92
+ console.log(`**Config:** .forge.json (gates: ${config.gates?.join(", ") ?? "default"})`);
93
+ }
94
+ else {
95
+ console.log(`**Config:** auto-detected (no .forge.json)`);
96
+ }
97
+ });
98
+ function writeVerifyCache(projectDir, result) {
99
+ const forgeDir = join(projectDir, ".forge");
100
+ mkdirSync(forgeDir, { recursive: true });
101
+ let branch = "unknown";
102
+ try {
103
+ branch = execSync("git branch --show-current", { encoding: "utf-8" }).trim();
104
+ }
105
+ catch { /* not a git repo */ }
106
+ const cache = {
107
+ passed: result.passed,
108
+ timestamp: new Date().toISOString(),
109
+ gates: result.gates,
110
+ branch,
111
+ };
112
+ writeFileSync(join(forgeDir, "last-verify.json"), JSON.stringify(cache, null, 2));
113
+ }
114
+ function formatReport(result) {
115
+ const lines = [];
116
+ const status = result.passed ? "PASSED" : "FAILED";
117
+ lines.push("## Verification Report");
118
+ lines.push(`**Status:** ${status}`);
119
+ const totalMs = result.gates.reduce((sum, g) => sum + g.duration_ms, 0);
120
+ lines.push(`**Duration:** ${(totalMs / 1000).toFixed(1)}s`);
121
+ lines.push("");
122
+ lines.push("### Gates");
123
+ for (const gate of result.gates) {
124
+ const icon = gate.passed ? "[x]" : "[ ]";
125
+ const dur = `${(gate.duration_ms / 1000).toFixed(1)}s`;
126
+ let suffix = "";
127
+ if (!gate.passed && gate.errors.length > 0) {
128
+ suffix = ` — ${gate.errors.length} error${gate.errors.length === 1 ? "" : "s"}`;
129
+ }
130
+ lines.push(`- ${icon} ${gate.gate}: ${gate.passed ? "PASS" : "FAIL"} (${dur})${suffix}`);
131
+ }
132
+ // Errors detail section
133
+ const withErrors = result.gates.filter(g => g.errors.length > 0);
134
+ if (withErrors.length > 0) {
135
+ lines.push("");
136
+ lines.push("### Errors");
137
+ for (const gate of withErrors) {
138
+ lines.push(`#### ${gate.gate}`);
139
+ for (const err of gate.errors) {
140
+ const loc = err.file ? `${err.file}${err.line ? `:${err.line}` : ""}` : "";
141
+ lines.push(`- ${loc ? `${loc}: ` : ""}${err.message}`);
142
+ }
143
+ }
144
+ }
145
+ return lines.join("\n");
146
+ }
147
+ program.parse();
148
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ForgeConfig } from "../types.js";
2
+ export declare function loadConfig(projectDir: string): ForgeConfig;
@@ -0,0 +1,44 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { forgeConfigSchema } from "./schema.js";
4
+ export function loadConfig(projectDir) {
5
+ const configPath = join(projectDir, ".forge.json");
6
+ if (existsSync(configPath)) {
7
+ try {
8
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
9
+ return forgeConfigSchema.parse(raw);
10
+ }
11
+ catch (err) {
12
+ const message = err instanceof Error ? err.message : String(err);
13
+ console.warn(`Warning: Failed to parse .forge.json (${message}). Falling back to auto-detect.`);
14
+ }
15
+ }
16
+ // Auto-detect from package.json
17
+ return autoDetectConfig(projectDir);
18
+ }
19
+ function autoDetectConfig(projectDir) {
20
+ const gates = [];
21
+ try {
22
+ const pkgPath = join(projectDir, "package.json");
23
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
24
+ const allDeps = {
25
+ ...pkg.dependencies,
26
+ ...pkg.devDependencies,
27
+ };
28
+ if (allDeps.typescript)
29
+ gates.push("types");
30
+ if (allDeps["@biomejs/biome"] || allDeps.biome)
31
+ gates.push("lint");
32
+ if (pkg.scripts?.test)
33
+ gates.push("tests");
34
+ }
35
+ catch {
36
+ // No package.json or invalid — use defaults
37
+ gates.push("types", "lint", "tests");
38
+ }
39
+ if (gates.length === 0) {
40
+ gates.push("types", "lint", "tests");
41
+ }
42
+ return forgeConfigSchema.parse({ gates });
43
+ }
44
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD,MAAM,UAAU,UAAU,CAAC,UAAkB;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAEnD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC1D,OAAO,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC,yCAAyC,OAAO,iCAAiC,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,OAAO,gBAAgB,CAAC,UAAU,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB;IAC1C,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAEvD,MAAM,OAAO,GAAG;YACd,GAAG,GAAG,CAAC,YAAY;YACnB,GAAG,GAAG,CAAC,eAAe;SACvB,CAAC;QAEF,IAAI,OAAO,CAAC,UAAU;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,OAAO,CAAC,gBAAgB,CAAC,IAAI,OAAO,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnE,IAAI,GAAG,CAAC,OAAO,EAAE,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;QAC5C,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,iBAAiB,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { z } from "zod";
2
+ export declare const devServerSchema: z.ZodObject<{
3
+ command: z.ZodString;
4
+ port: z.ZodNumber;
5
+ readyPattern: z.ZodOptional<z.ZodString>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ port: number;
8
+ command: string;
9
+ readyPattern?: string | undefined;
10
+ }, {
11
+ port: number;
12
+ command: string;
13
+ readyPattern?: string | undefined;
14
+ }>;
15
+ export declare const forgeConfigSchema: z.ZodObject<{
16
+ gates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
17
+ maxIterations: z.ZodDefault<z.ZodNumber>;
18
+ verifyFreshness: z.ZodDefault<z.ZodNumber>;
19
+ devServer: z.ZodOptional<z.ZodObject<{
20
+ command: z.ZodString;
21
+ port: z.ZodNumber;
22
+ readyPattern: z.ZodOptional<z.ZodString>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ port: number;
25
+ command: string;
26
+ readyPattern?: string | undefined;
27
+ }, {
28
+ port: number;
29
+ command: string;
30
+ readyPattern?: string | undefined;
31
+ }>>;
32
+ prdPath: z.ZodOptional<z.ZodString>;
33
+ linearProject: z.ZodOptional<z.ZodString>;
34
+ }, "strip", z.ZodTypeAny, {
35
+ gates: string[];
36
+ maxIterations: number;
37
+ verifyFreshness: number;
38
+ devServer?: {
39
+ port: number;
40
+ command: string;
41
+ readyPattern?: string | undefined;
42
+ } | undefined;
43
+ prdPath?: string | undefined;
44
+ linearProject?: string | undefined;
45
+ }, {
46
+ gates?: string[] | undefined;
47
+ maxIterations?: number | undefined;
48
+ verifyFreshness?: number | undefined;
49
+ devServer?: {
50
+ port: number;
51
+ command: string;
52
+ readyPattern?: string | undefined;
53
+ } | undefined;
54
+ prdPath?: string | undefined;
55
+ linearProject?: string | undefined;
56
+ }>;
57
+ export type ForgeConfigInput = z.input<typeof forgeConfigSchema>;
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ export const devServerSchema = z.object({
3
+ command: z.string(),
4
+ port: z.number().int().positive(),
5
+ readyPattern: z.string().optional(),
6
+ });
7
+ export const forgeConfigSchema = z.object({
8
+ gates: z.array(z.string()).default(["types", "lint", "tests"]),
9
+ maxIterations: z.number().int().positive().default(5),
10
+ verifyFreshness: z.number().int().positive().default(600_000),
11
+ devServer: devServerSchema.optional(),
12
+ prdPath: z.string().optional(),
13
+ linearProject: z.string().optional(),
14
+ });
15
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACjC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IAC7D,SAAS,EAAE,eAAe,CAAC,QAAQ,EAAE;IACrC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { GateResult, PipelineInput, PipelineResult } from "../types.js";
2
+ /** Gate registry -- maps gate name to its function */
3
+ export declare const gateRegistry: Record<string, (input: PipelineInput) => Promise<GateResult>>;
4
+ /** Run the full verification pipeline */
5
+ export declare function runPipeline(input: PipelineInput): Promise<PipelineResult>;
6
+ export { verifyTypes } from "./types-gate.js";
7
+ export { verifyLint } from "./lint-gate.js";
8
+ export { verifyTests } from "./tests-gate.js";
9
+ export { verifyVisual } from "./visual-gate.js";
10
+ export { verifyRuntime } from "./runtime-gate.js";
11
+ export { verifyPrd } from "./prd-gate.js";