forge-cc 0.1.40 → 1.0.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 (72) hide show
  1. package/README.md +454 -338
  2. package/dist/cli.js +194 -906
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config/loader.d.ts +1 -1
  5. package/dist/config/loader.js +49 -56
  6. package/dist/config/loader.js.map +1 -1
  7. package/dist/config/schema.d.ts +37 -125
  8. package/dist/config/schema.js +13 -28
  9. package/dist/config/schema.js.map +1 -1
  10. package/dist/doctor.d.ts +10 -0
  11. package/dist/doctor.js +148 -0
  12. package/dist/doctor.js.map +1 -0
  13. package/dist/gates/index.d.ts +14 -12
  14. package/dist/gates/index.js +53 -105
  15. package/dist/gates/index.js.map +1 -1
  16. package/dist/gates/lint-gate.d.ts +2 -2
  17. package/dist/gates/lint-gate.js +60 -66
  18. package/dist/gates/lint-gate.js.map +1 -1
  19. package/dist/gates/tests-gate.d.ts +2 -4
  20. package/dist/gates/tests-gate.js +75 -203
  21. package/dist/gates/tests-gate.js.map +1 -1
  22. package/dist/gates/types-gate.d.ts +2 -2
  23. package/dist/gates/types-gate.js +53 -59
  24. package/dist/gates/types-gate.js.map +1 -1
  25. package/dist/go/linear-sync-cli.js +13 -4
  26. package/dist/go/linear-sync-cli.js.map +1 -1
  27. package/dist/go/linear-sync.d.ts +1 -0
  28. package/dist/go/linear-sync.js +67 -4
  29. package/dist/go/linear-sync.js.map +1 -1
  30. package/dist/linear/client.d.ts +34 -105
  31. package/dist/linear/client.js +85 -365
  32. package/dist/linear/client.js.map +1 -1
  33. package/dist/linear/issues.d.ts +3 -1
  34. package/dist/linear/issues.js +14 -2
  35. package/dist/linear/issues.js.map +1 -1
  36. package/dist/linear/projects.js +3 -2
  37. package/dist/linear/projects.js.map +1 -1
  38. package/dist/linear/sync.d.ts +15 -0
  39. package/dist/linear/sync.js +102 -0
  40. package/dist/linear/sync.js.map +1 -0
  41. package/dist/runner/loop.d.ts +4 -0
  42. package/dist/runner/loop.js +168 -0
  43. package/dist/runner/loop.js.map +1 -0
  44. package/dist/runner/prompt.d.ts +14 -0
  45. package/dist/runner/prompt.js +59 -0
  46. package/dist/runner/prompt.js.map +1 -0
  47. package/dist/runner/update.d.ts +1 -0
  48. package/dist/runner/update.js +72 -0
  49. package/dist/runner/update.js.map +1 -0
  50. package/dist/server.d.ts +6 -2
  51. package/dist/server.js +43 -101
  52. package/dist/server.js.map +1 -1
  53. package/dist/setup.d.ts +5 -0
  54. package/dist/setup.js +208 -0
  55. package/dist/setup.js.map +1 -0
  56. package/dist/state/cache.d.ts +3 -0
  57. package/dist/state/cache.js +23 -0
  58. package/dist/state/cache.js.map +1 -0
  59. package/dist/state/status.d.ts +66 -0
  60. package/dist/state/status.js +96 -0
  61. package/dist/state/status.js.map +1 -0
  62. package/dist/types.d.ts +46 -114
  63. package/dist/worktree/manager.d.ts +6 -103
  64. package/dist/worktree/manager.js +25 -296
  65. package/dist/worktree/manager.js.map +1 -1
  66. package/hooks/pre-commit-verify.js +109 -109
  67. package/package.json +3 -2
  68. package/skills/forge-go.md +583 -575
  69. package/skills/forge-setup.md +149 -388
  70. package/skills/forge-spec.md +367 -342
  71. package/skills/forge-triage.md +179 -133
  72. package/skills/forge-update.md +87 -93
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,wBAAwB;AACxB,uGAAuG;AAEvG,SAAS,aAAa,CAAC,GAAY;IACjC,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAC5F,CAAC;AAED,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,6CAA6C,EAC7C,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,EACpE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;AAC9C,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,0BAA0B,EAC1B,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,EACpE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;AAC9C,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,wBAAwB,EACxB,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,EACpE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;AAC9C,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,+CAA+C,EAC/C;IACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAChE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IACzE,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IAC5E,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;CACjE,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,EAAE,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAC,CAAC;QAC1F,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;AAC9C,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,kDAAkD,EAClD;IACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAChE,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,iDAAiD,CAAC;IAC1F,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IAC5E,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;CACjE,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,EAAE,EAAE;IACnE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAC,CAAC;QAC/F,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;AAC9C,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,oDAAoD,EACpD;IACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAChE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;IACzD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;CACnF,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAChE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;AAC9C,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,uDAAuD,EACvD;IACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAChE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IAC1F,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IAC3D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CACtE,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE;IACtD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;YAC/B,UAAU;YACV,KAAK;YACL,OAAO;YACP,aAAa;SACd,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;AAC9C,CAAC,CACF,CAAC;AAEF,eAAe;AACf,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EACL,YAAY,EACZ,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EACnC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;IAEF,0FAA0F;IAC1F,YAAY,CAAC,SAAS,CAAC,CAAC;IACxB,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,YAAY,CAAC,SAAS,CAAC,CAAC;IAExB,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,0DAA0D,EAC1D;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;QACjF,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;KAC3E,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE;QAC9B,MAAM,GAAG,GAAG,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QAErC,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QACvB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAE9C,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+CAA+C;AAC/C,KAAK,UAAU,WAAW;IACxB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,6BAA6B;AAC7B,MAAM,MAAM,GACV,OAAO,OAAO,KAAK,WAAW;IAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACf,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;AAEtF,IAAI,MAAM,EAAE,CAAC;IACX,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface SetupOptions {
2
+ projectDir: string;
3
+ skillsOnly?: boolean;
4
+ }
5
+ export declare function runSetup(opts: SetupOptions): Promise<void>;
package/dist/setup.js ADDED
@@ -0,0 +1,208 @@
1
+ import { readFile, writeFile, mkdir, readdir, copyFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { fileURLToPath } from "node:url";
5
+ import { dirname } from "node:path";
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ const packageRoot = join(__dirname, "..");
9
+ const FORGE_CLAUDE_SECTION = `
10
+ ## Forge Quick Reference
11
+
12
+ | Action | Command |
13
+ |--------|---------|
14
+ | Run verification | \`npx forge verify\` |
15
+ | Run specific gates | \`npx forge verify --gate types,lint\` |
16
+ | Check status | \`npx forge status\` |
17
+ | Check environment | \`npx forge doctor\` |
18
+
19
+ ## Session Protocol
20
+ - **On start:** Read CLAUDE.md, .planning/status/*.json, tasks/lessons.md
21
+ - **When lost:** Re-read planning docs
22
+
23
+ ## Session Protocol END (Mandatory)
24
+ 1. Update .planning/status/<slug>.json
25
+ 2. Update tasks/lessons.md (max 10 active)
26
+ 3. Commit doc updates to the feature branch
27
+ `;
28
+ /** Copy skill .md files from the forge-cc package to ~/.claude/commands/forge/. */
29
+ async function installSkills() {
30
+ const skillsSource = join(packageRoot, "skills");
31
+ const targetDir = join(homedir(), ".claude", "commands", "forge");
32
+ await mkdir(targetDir, { recursive: true });
33
+ let files;
34
+ try {
35
+ files = await readdir(skillsSource);
36
+ }
37
+ catch {
38
+ return [];
39
+ }
40
+ const installed = [];
41
+ for (const file of files) {
42
+ if (!file.endsWith(".md") || file === "README.md")
43
+ continue;
44
+ await copyFile(join(skillsSource, file), join(targetDir, file));
45
+ installed.push(file);
46
+ }
47
+ return installed;
48
+ }
49
+ /** Generate .forge.json with auto-detected gates if it doesn't already exist. */
50
+ async function generateForgeConfig(projectDir) {
51
+ const configPath = join(projectDir, ".forge.json");
52
+ // Don't overwrite existing config
53
+ try {
54
+ await readFile(configPath, "utf-8");
55
+ return false;
56
+ }
57
+ catch {
58
+ // File doesn't exist, proceed to create
59
+ }
60
+ // Auto-detect gates from package.json
61
+ const gateMap = {
62
+ typescript: "types",
63
+ "@biomejs/biome": "lint",
64
+ biome: "lint",
65
+ vitest: "tests",
66
+ jest: "tests",
67
+ };
68
+ const gates = new Set(["types", "lint", "tests"]);
69
+ try {
70
+ const pkgContent = await readFile(join(projectDir, "package.json"), "utf-8");
71
+ const pkg = JSON.parse(pkgContent);
72
+ const deps = {
73
+ ...pkg.dependencies,
74
+ ...pkg.devDependencies,
75
+ };
76
+ const detected = new Set();
77
+ for (const [dep, gate] of Object.entries(gateMap)) {
78
+ if (dep in deps)
79
+ detected.add(gate);
80
+ }
81
+ if (detected.size > 0) {
82
+ gates.clear();
83
+ for (const g of detected)
84
+ gates.add(g);
85
+ }
86
+ }
87
+ catch {
88
+ // No package.json, use defaults
89
+ }
90
+ // Detect Linear team if key is set
91
+ let linearTeam = "";
92
+ const apiKey = process.env.LINEAR_API_KEY;
93
+ if (apiKey) {
94
+ try {
95
+ const { ForgeLinearClient } = await import("./linear/client.js");
96
+ const client = new ForgeLinearClient({ apiKey });
97
+ const teams = await client.listTeams();
98
+ if (teams.length === 1) {
99
+ linearTeam = teams[0].key;
100
+ }
101
+ else if (teams.length > 1) {
102
+ console.log("Linear teams found:");
103
+ for (const team of teams) {
104
+ console.log(` ${team.key} — ${team.name}`);
105
+ }
106
+ console.log('Set "linearTeam" in .forge.json to your team key.');
107
+ }
108
+ }
109
+ catch {
110
+ // Linear not reachable, skip
111
+ }
112
+ }
113
+ const config = {
114
+ gates: [...gates],
115
+ maxIterations: 5,
116
+ verifyFreshness: 600000,
117
+ linearTeam,
118
+ };
119
+ await writeFile(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
120
+ return true;
121
+ }
122
+ /** Copy pre-commit hook to .forge/hooks/ in the project. */
123
+ async function installPreCommitHook(projectDir) {
124
+ const hookSource = join(packageRoot, "hooks", "pre-commit-verify.js");
125
+ const hookTarget = join(projectDir, ".forge", "hooks", "pre-commit-verify.js");
126
+ try {
127
+ await readFile(hookSource);
128
+ }
129
+ catch {
130
+ return false;
131
+ }
132
+ await mkdir(join(projectDir, ".forge", "hooks"), { recursive: true });
133
+ await copyFile(hookSource, hookTarget);
134
+ return true;
135
+ }
136
+ /** Append forge section to CLAUDE.md if not already present. */
137
+ async function updateClaudeMd(projectDir) {
138
+ const claudeMdPath = join(projectDir, "CLAUDE.md");
139
+ let content = "";
140
+ try {
141
+ content = await readFile(claudeMdPath, "utf-8");
142
+ }
143
+ catch {
144
+ // File doesn't exist, create with forge content
145
+ await writeFile(claudeMdPath, `# Project Instructions\n${FORGE_CLAUDE_SECTION}`, "utf-8");
146
+ return true;
147
+ }
148
+ // Check if forge content is already present
149
+ if (content.includes("## Forge Quick Reference") || content.includes("npx forge verify")) {
150
+ return false;
151
+ }
152
+ await writeFile(claudeMdPath, content.trimEnd() + "\n" + FORGE_CLAUDE_SECTION, "utf-8");
153
+ return true;
154
+ }
155
+ /** Validate Linear connection if API key is set. */
156
+ async function validateLinear() {
157
+ const apiKey = process.env.LINEAR_API_KEY;
158
+ if (!apiKey)
159
+ return false;
160
+ try {
161
+ const { ForgeLinearClient } = await import("./linear/client.js");
162
+ const client = new ForgeLinearClient({ apiKey });
163
+ const teams = await client.listTeams();
164
+ if (teams.length > 0) {
165
+ console.log(`Linear: authenticated (${teams.length} team${teams.length > 1 ? "s" : ""} found)`);
166
+ return true;
167
+ }
168
+ console.log("Linear: authenticated but no teams found");
169
+ return true;
170
+ }
171
+ catch {
172
+ console.log("Linear: connection failed");
173
+ return false;
174
+ }
175
+ }
176
+ export async function runSetup(opts) {
177
+ const { projectDir, skillsOnly } = opts;
178
+ // Step 2: Install skill files (always runs)
179
+ const installed = await installSkills();
180
+ if (installed.length > 0) {
181
+ console.log(`Skills synced: ${installed.join(", ")}`);
182
+ }
183
+ if (skillsOnly)
184
+ return;
185
+ // Step 1: Generate .forge.json
186
+ const configCreated = await generateForgeConfig(projectDir);
187
+ if (configCreated) {
188
+ console.log("Created .forge.json");
189
+ }
190
+ else {
191
+ console.log(".forge.json already exists, skipping");
192
+ }
193
+ // Step 3: Install pre-commit hook
194
+ const hookInstalled = await installPreCommitHook(projectDir);
195
+ if (hookInstalled) {
196
+ console.log("Pre-commit hook installed at .forge/hooks/pre-commit-verify.js");
197
+ console.log("Add to .claude/settings.json hooks to activate");
198
+ }
199
+ // Step 4: Update CLAUDE.md
200
+ const claudeUpdated = await updateClaudeMd(projectDir);
201
+ if (claudeUpdated) {
202
+ console.log("Forge section added to CLAUDE.md");
203
+ }
204
+ // Step 5: Validate Linear
205
+ await validateLinear();
206
+ console.log("\nSetup complete. Run 'npx forge doctor' to verify your environment.");
207
+ }
208
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { PipelineResult } from "../types.js";
2
+ /** Write verification results to .forge/last-verify.json. */
3
+ export declare function writeVerifyCache(projectDir: string, pipeline: PipelineResult): Promise<void>;
@@ -0,0 +1,23 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ /** Write verification results to .forge/last-verify.json. */
4
+ export async function writeVerifyCache(projectDir, pipeline) {
5
+ const forgeDir = join(projectDir, ".forge");
6
+ await mkdir(forgeDir, { recursive: true });
7
+ const cache = {
8
+ timestamp: new Date().toISOString(),
9
+ result: pipeline.result,
10
+ gates: {},
11
+ };
12
+ for (const gate of pipeline.gates) {
13
+ cache.gates[gate.gate] = {
14
+ passed: gate.passed,
15
+ errors: gate.errors.length > 0 ? gate.errors : undefined,
16
+ summary: gate.passed
17
+ ? "passed"
18
+ : `${gate.errors.length} error(s)`,
19
+ };
20
+ }
21
+ await writeFile(join(forgeDir, "last-verify.json"), JSON.stringify(cache, null, 2), "utf-8");
22
+ }
23
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/state/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAAkB,EAClB,QAAwB;IAExB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3C,MAAM,KAAK,GAAgB;QACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,KAAK,EAAE,EAAE;KACV,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAClC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;YACxD,OAAO,EAAE,IAAI,CAAC,MAAM;gBAClB,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,WAAW;SACrC,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,CACb,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAClC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAC9B,OAAO,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { z } from "zod";
2
+ import type { PRDStatus } from "../types.js";
3
+ export declare const prdStatusSchema: z.ZodObject<{
4
+ project: z.ZodString;
5
+ slug: z.ZodString;
6
+ branch: z.ZodString;
7
+ createdAt: z.ZodString;
8
+ linearProjectId: z.ZodOptional<z.ZodString>;
9
+ linearTeamId: z.ZodOptional<z.ZodString>;
10
+ milestones: z.ZodRecord<z.ZodString, z.ZodObject<{
11
+ status: z.ZodEnum<["pending", "in_progress", "complete"]>;
12
+ linearMilestoneId: z.ZodOptional<z.ZodString>;
13
+ linearIssueIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
14
+ completedAt: z.ZodOptional<z.ZodString>;
15
+ }, "strip", z.ZodTypeAny, {
16
+ status: "pending" | "in_progress" | "complete";
17
+ linearMilestoneId?: string | undefined;
18
+ linearIssueIds?: string[] | undefined;
19
+ completedAt?: string | undefined;
20
+ }, {
21
+ status: "pending" | "in_progress" | "complete";
22
+ linearMilestoneId?: string | undefined;
23
+ linearIssueIds?: string[] | undefined;
24
+ completedAt?: string | undefined;
25
+ }>>;
26
+ }, "strip", z.ZodTypeAny, {
27
+ project: string;
28
+ slug: string;
29
+ branch: string;
30
+ createdAt: string;
31
+ milestones: Record<string, {
32
+ status: "pending" | "in_progress" | "complete";
33
+ linearMilestoneId?: string | undefined;
34
+ linearIssueIds?: string[] | undefined;
35
+ completedAt?: string | undefined;
36
+ }>;
37
+ linearProjectId?: string | undefined;
38
+ linearTeamId?: string | undefined;
39
+ }, {
40
+ project: string;
41
+ slug: string;
42
+ branch: string;
43
+ createdAt: string;
44
+ milestones: Record<string, {
45
+ status: "pending" | "in_progress" | "complete";
46
+ linearMilestoneId?: string | undefined;
47
+ linearIssueIds?: string[] | undefined;
48
+ completedAt?: string | undefined;
49
+ }>;
50
+ linearProjectId?: string | undefined;
51
+ linearTeamId?: string | undefined;
52
+ }>;
53
+ /** Read and validate a PRD status file. */
54
+ export declare function readStatus(projectDir: string, slug: string): Promise<PRDStatus>;
55
+ /** Write a PRD status file atomically (temp file + rename). */
56
+ export declare function writeStatus(projectDir: string, slug: string, status: PRDStatus): Promise<void>;
57
+ /** Update a single milestone's status within a PRD status file. */
58
+ export declare function updateMilestoneStatus(projectDir: string, slug: string, milestone: string, newStatus: "pending" | "in_progress" | "complete"): Promise<PRDStatus>;
59
+ /** Discover all valid PRD status files in .planning/status/. */
60
+ export declare function discoverStatuses(projectDir: string): Promise<PRDStatus[]>;
61
+ /** Find the first pending milestone in each PRD. */
62
+ export declare function findNextPending(statuses: PRDStatus[]): Array<{
63
+ slug: string;
64
+ milestone: string;
65
+ status: PRDStatus;
66
+ }>;
@@ -0,0 +1,96 @@
1
+ import { readFile, readdir, rename, writeFile, mkdir } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { z } from "zod";
5
+ const milestoneStatusSchema = z.object({
6
+ status: z.enum(["pending", "in_progress", "complete"]),
7
+ linearMilestoneId: z.string().optional(),
8
+ linearIssueIds: z.array(z.string()).optional(),
9
+ completedAt: z.string().optional(),
10
+ });
11
+ export const prdStatusSchema = z.object({
12
+ project: z.string(),
13
+ slug: z.string(),
14
+ branch: z.string(),
15
+ createdAt: z.string(),
16
+ linearProjectId: z.string().optional(),
17
+ linearTeamId: z.string().optional(),
18
+ milestones: z.record(z.string(), milestoneStatusSchema),
19
+ });
20
+ function statusDir(projectDir) {
21
+ return join(projectDir, ".planning", "status");
22
+ }
23
+ function statusPath(projectDir, slug) {
24
+ return join(statusDir(projectDir), `${slug}.json`);
25
+ }
26
+ /** Read and validate a PRD status file. */
27
+ export async function readStatus(projectDir, slug) {
28
+ const raw = await readFile(statusPath(projectDir, slug), "utf-8");
29
+ const json = JSON.parse(raw);
30
+ return prdStatusSchema.parse(json);
31
+ }
32
+ /** Write a PRD status file atomically (temp file + rename). */
33
+ export async function writeStatus(projectDir, slug, status) {
34
+ const dir = statusDir(projectDir);
35
+ await mkdir(dir, { recursive: true });
36
+ const target = statusPath(projectDir, slug);
37
+ const temp = `${target}.${randomUUID()}.tmp`;
38
+ await writeFile(temp, JSON.stringify(status, null, 2), "utf-8");
39
+ await rename(temp, target);
40
+ }
41
+ /** Update a single milestone's status within a PRD status file. */
42
+ export async function updateMilestoneStatus(projectDir, slug, milestone, newStatus) {
43
+ const status = await readStatus(projectDir, slug);
44
+ if (!status.milestones[milestone]) {
45
+ status.milestones[milestone] = { status: newStatus };
46
+ }
47
+ else {
48
+ status.milestones[milestone].status = newStatus;
49
+ }
50
+ if (newStatus === "complete") {
51
+ status.milestones[milestone].completedAt = new Date().toISOString();
52
+ }
53
+ await writeStatus(projectDir, slug, status);
54
+ return status;
55
+ }
56
+ /** Discover all valid PRD status files in .planning/status/. */
57
+ export async function discoverStatuses(projectDir) {
58
+ const dir = statusDir(projectDir);
59
+ let entries;
60
+ try {
61
+ entries = await readdir(dir);
62
+ }
63
+ catch {
64
+ return [];
65
+ }
66
+ const statuses = [];
67
+ for (const entry of entries) {
68
+ if (!entry.endsWith(".json"))
69
+ continue;
70
+ try {
71
+ const raw = await readFile(join(dir, entry), "utf-8");
72
+ const json = JSON.parse(raw);
73
+ const parsed = prdStatusSchema.parse(json);
74
+ statuses.push(parsed);
75
+ }
76
+ catch {
77
+ // skip invalid files
78
+ }
79
+ }
80
+ return statuses;
81
+ }
82
+ /** Find the first pending milestone in each PRD. */
83
+ export function findNextPending(statuses) {
84
+ const results = [];
85
+ for (const status of statuses) {
86
+ const milestoneKeys = Object.keys(status.milestones);
87
+ for (const key of milestoneKeys) {
88
+ if (status.milestones[key].status === "pending") {
89
+ results.push({ slug: status.slug, milestone: key, status });
90
+ break;
91
+ }
92
+ }
93
+ }
94
+ return results;
95
+ }
96
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/state/status.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,131 +1,63 @@
1
- /** Structured error from a verification gate */
1
+ /** Structured error from a verification gate. */
2
2
  export interface GateError {
3
- file?: string;
4
- line?: number;
3
+ file: string;
4
+ line: number;
5
+ column?: number;
5
6
  message: string;
6
- remediation?: string;
7
+ rule?: string;
7
8
  }
8
- /** Result from a single verification gate */
9
+ /** Result of running a single verification gate. */
9
10
  export interface GateResult {
10
11
  gate: string;
11
12
  passed: boolean;
12
13
  errors: GateError[];
13
- warnings: string[];
14
- duration_ms: number;
14
+ durationMs: number;
15
15
  }
16
- /** Extended result for visual validation with screenshots */
17
- export interface VisualResult extends GateResult {
18
- screenshots: Array<{
19
- page: string;
20
- path: string;
21
- }>;
22
- consoleErrors: string[];
23
- }
24
- /** Extended result for code review with review-specific metadata */
25
- export interface ReviewResult extends GateResult {
26
- reviewFindings: Array<{
27
- type: "prd_compliance" | "rule_violation" | "style";
28
- severity: "error" | "warning";
29
- file?: string;
30
- line?: number;
31
- message: string;
32
- remediation: string;
33
- source: string;
34
- }>;
35
- }
36
- /** Input for the full verification pipeline */
37
- export interface PipelineInput {
38
- projectDir: string;
39
- appDir?: string;
40
- gates?: string[];
41
- prdPath?: string;
42
- milestoneType?: "ui" | "data" | "mixed";
43
- pages?: string[];
44
- apiEndpoints?: string[];
45
- maxIterations?: number;
46
- devServerCommand?: string;
47
- devServerPort?: number;
48
- baseBranch?: string;
49
- reviewBlocking?: boolean;
50
- }
51
- /** Result from the full verification pipeline */
52
- export interface PipelineResult {
53
- passed: boolean;
54
- iteration: number;
55
- maxIterations: number;
56
- gates: GateResult[];
57
- report: string;
58
- }
59
- /** Testing configuration from .forge.json */
60
- export interface TestingConfig {
61
- enforce: boolean;
62
- runner: "vitest" | "jest" | "none";
63
- testDir: string;
64
- sourceDir: string;
65
- structural: boolean;
66
- categories: string[];
67
- }
68
- /** Configuration from .forge.json */
16
+ /** Full configuration shape matching .forge.json. */
69
17
  export interface ForgeConfig {
70
- appDir?: string;
71
18
  gates: string[];
19
+ gateTimeouts: Record<string, number>;
72
20
  maxIterations: number;
73
- verifyFreshness: number;
74
- devServer?: {
75
- command: string;
76
- port: number;
77
- };
78
- /** Pages to capture for the visual gate */
79
- pages?: string[];
80
- prdPath?: string;
81
- linearProject?: string;
82
- review?: {
83
- blocking: boolean;
21
+ linearTeam: string;
22
+ linearStates: {
23
+ planned: string;
24
+ inProgress: string;
25
+ inReview: string;
26
+ done: string;
84
27
  };
85
- testing?: TestingConfig;
86
- /** forge-cc version used during last /forge:setup */
87
- forgeVersion?: string;
28
+ verifyFreshness: number;
29
+ forgeVersion: string;
30
+ }
31
+ /** Per-milestone status tracking. */
32
+ export interface MilestoneStatus {
33
+ status: 'pending' | 'in_progress' | 'complete';
34
+ linearMilestoneId?: string;
35
+ linearIssueIds?: string[];
36
+ completedAt?: string;
37
+ }
38
+ /** PRD status file shape stored in .planning/status/. */
39
+ export interface PRDStatus {
40
+ project: string;
41
+ slug: string;
42
+ branch: string;
43
+ createdAt: string;
44
+ linearProjectId?: string;
45
+ linearTeamId?: string;
46
+ milestones: Record<string, MilestoneStatus>;
88
47
  }
89
- /** Verification cache written to .forge/last-verify.json */
48
+ /** Cached verification result. */
90
49
  export interface VerifyCache {
91
- passed: boolean;
92
50
  timestamp: string;
93
- gates: GateResult[];
94
- branch: string;
95
- }
96
- /** Viewport configuration for multi-viewport visual capture */
97
- export interface ViewportConfig {
98
- name: string;
99
- width: number;
100
- height: number;
101
- }
102
- /** Serialized DOM node snapshot from page.evaluate() extraction */
103
- export interface DOMSnapshot {
104
- tag: string;
105
- id?: string;
106
- className?: string;
107
- visible: boolean;
108
- rect?: {
109
- x: number;
110
- y: number;
111
- width: number;
112
- height: number;
113
- };
114
- children: DOMSnapshot[];
115
- }
116
- /** Result from multi-viewport visual capture with DOM extraction */
117
- export interface VisualCaptureResult {
118
- screenshots: Array<{
119
- page: string;
120
- viewport: string;
121
- path: string;
51
+ result: 'PASSED' | 'FAILED';
52
+ gates: Record<string, {
53
+ passed: boolean;
54
+ errors?: GateError[];
55
+ summary?: string;
122
56
  }>;
123
- domSnapshots: Record<string, DOMSnapshot>;
124
- metadata: {
125
- viewports: ViewportConfig[];
126
- pagePath: string;
127
- capturedAt: string;
128
- durationMs: number;
129
- };
130
57
  }
131
- export type { AgentRole, TeamConfig, Finding, ConsensusRound, ConsensusResult, TeamReviewResult, CodexComment, } from "./team/types.js";
58
+ /** Overall result of a full verification pipeline run. */
59
+ export interface PipelineResult {
60
+ result: 'PASSED' | 'FAILED';
61
+ gates: GateResult[];
62
+ durationMs: number;
63
+ }