forge-cc 1.0.0 → 1.0.2

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 (144) hide show
  1. package/dist/cli.js +7 -1
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +3 -2
  4. package/dist/gates/codex-gate.d.ts +0 -51
  5. package/dist/gates/codex-gate.js +0 -121
  6. package/dist/gates/codex-gate.js.map +0 -1
  7. package/dist/gates/prd-gate.d.ts +0 -7
  8. package/dist/gates/prd-gate.js +0 -193
  9. package/dist/gates/prd-gate.js.map +0 -1
  10. package/dist/gates/remediation.d.ts +0 -46
  11. package/dist/gates/remediation.js +0 -423
  12. package/dist/gates/remediation.js.map +0 -1
  13. package/dist/gates/review-gate.d.ts +0 -16
  14. package/dist/gates/review-gate.js +0 -479
  15. package/dist/gates/review-gate.js.map +0 -1
  16. package/dist/gates/runtime-gate.d.ts +0 -5
  17. package/dist/gates/runtime-gate.js +0 -99
  18. package/dist/gates/runtime-gate.js.map +0 -1
  19. package/dist/gates/test-analysis.d.ts +0 -21
  20. package/dist/gates/test-analysis.js +0 -394
  21. package/dist/gates/test-analysis.js.map +0 -1
  22. package/dist/gates/visual-capture.d.ts +0 -24
  23. package/dist/gates/visual-capture.js +0 -144
  24. package/dist/gates/visual-capture.js.map +0 -1
  25. package/dist/gates/visual-gate.d.ts +0 -18
  26. package/dist/gates/visual-gate.js +0 -234
  27. package/dist/gates/visual-gate.js.map +0 -1
  28. package/dist/gates/visual-reviewer.d.ts +0 -11
  29. package/dist/gates/visual-reviewer.js +0 -211
  30. package/dist/gates/visual-reviewer.js.map +0 -1
  31. package/dist/go/auto-chain.d.ts +0 -136
  32. package/dist/go/auto-chain.js +0 -389
  33. package/dist/go/auto-chain.js.map +0 -1
  34. package/dist/go/executor.d.ts +0 -137
  35. package/dist/go/executor.js +0 -447
  36. package/dist/go/executor.js.map +0 -1
  37. package/dist/go/finalize.d.ts +0 -108
  38. package/dist/go/finalize.js +0 -331
  39. package/dist/go/finalize.js.map +0 -1
  40. package/dist/go/linear-sync-cli.d.ts +0 -55
  41. package/dist/go/linear-sync-cli.js +0 -192
  42. package/dist/go/linear-sync-cli.js.map +0 -1
  43. package/dist/go/linear-sync.d.ts +0 -112
  44. package/dist/go/linear-sync.js +0 -375
  45. package/dist/go/linear-sync.js.map +0 -1
  46. package/dist/go/prd-queue.d.ts +0 -43
  47. package/dist/go/prd-queue.js +0 -67
  48. package/dist/go/prd-queue.js.map +0 -1
  49. package/dist/go/prd-selector.d.ts +0 -57
  50. package/dist/go/prd-selector.js +0 -101
  51. package/dist/go/prd-selector.js.map +0 -1
  52. package/dist/go/verify-loop.d.ts +0 -64
  53. package/dist/go/verify-loop.js +0 -327
  54. package/dist/go/verify-loop.js.map +0 -1
  55. package/dist/hooks/pre-commit.d.ts +0 -5
  56. package/dist/hooks/pre-commit.js +0 -75
  57. package/dist/hooks/pre-commit.js.map +0 -1
  58. package/dist/linear/issues.d.ts +0 -22
  59. package/dist/linear/issues.js +0 -51
  60. package/dist/linear/issues.js.map +0 -1
  61. package/dist/linear/milestones.d.ts +0 -11
  62. package/dist/linear/milestones.js +0 -32
  63. package/dist/linear/milestones.js.map +0 -1
  64. package/dist/linear/projects.d.ts +0 -16
  65. package/dist/linear/projects.js +0 -51
  66. package/dist/linear/projects.js.map +0 -1
  67. package/dist/reporter/human.d.ts +0 -7
  68. package/dist/reporter/human.js +0 -93
  69. package/dist/reporter/human.js.map +0 -1
  70. package/dist/reporter/json.d.ts +0 -2
  71. package/dist/reporter/json.js +0 -4
  72. package/dist/reporter/json.js.map +0 -1
  73. package/dist/setup/structural-templates.d.ts +0 -12
  74. package/dist/setup/structural-templates.js +0 -288
  75. package/dist/setup/structural-templates.js.map +0 -1
  76. package/dist/setup/templates.d.ts +0 -17
  77. package/dist/setup/templates.js +0 -109
  78. package/dist/setup/templates.js.map +0 -1
  79. package/dist/setup/test-planner.d.ts +0 -38
  80. package/dist/setup/test-planner.js +0 -91
  81. package/dist/setup/test-planner.js.map +0 -1
  82. package/dist/setup/test-scaffold.d.ts +0 -31
  83. package/dist/setup/test-scaffold.js +0 -209
  84. package/dist/setup/test-scaffold.js.map +0 -1
  85. package/dist/setup/test-templates.d.ts +0 -37
  86. package/dist/setup/test-templates.js +0 -313
  87. package/dist/setup/test-templates.js.map +0 -1
  88. package/dist/spec/generator.d.ts +0 -34
  89. package/dist/spec/generator.js +0 -227
  90. package/dist/spec/generator.js.map +0 -1
  91. package/dist/spec/interview.d.ts +0 -142
  92. package/dist/spec/interview.js +0 -287
  93. package/dist/spec/interview.js.map +0 -1
  94. package/dist/spec/linear-sync.d.ts +0 -48
  95. package/dist/spec/linear-sync.js +0 -125
  96. package/dist/spec/linear-sync.js.map +0 -1
  97. package/dist/spec/scanner.d.ts +0 -79
  98. package/dist/spec/scanner.js +0 -566
  99. package/dist/spec/scanner.js.map +0 -1
  100. package/dist/spec/templates.d.ts +0 -375
  101. package/dist/spec/templates.js +0 -95
  102. package/dist/spec/templates.js.map +0 -1
  103. package/dist/state/prd-status.d.ts +0 -62
  104. package/dist/state/prd-status.js +0 -122
  105. package/dist/state/prd-status.js.map +0 -1
  106. package/dist/state/reader.d.ts +0 -7
  107. package/dist/state/reader.js +0 -43
  108. package/dist/state/reader.js.map +0 -1
  109. package/dist/state/writer.d.ts +0 -21
  110. package/dist/state/writer.js +0 -106
  111. package/dist/state/writer.js.map +0 -1
  112. package/dist/team/consensus.d.ts +0 -28
  113. package/dist/team/consensus.js +0 -130
  114. package/dist/team/consensus.js.map +0 -1
  115. package/dist/team/index.d.ts +0 -4
  116. package/dist/team/index.js +0 -5
  117. package/dist/team/index.js.map +0 -1
  118. package/dist/team/lifecycle.d.ts +0 -37
  119. package/dist/team/lifecycle.js +0 -92
  120. package/dist/team/lifecycle.js.map +0 -1
  121. package/dist/team/reviewer.d.ts +0 -10
  122. package/dist/team/reviewer.js +0 -345
  123. package/dist/team/reviewer.js.map +0 -1
  124. package/dist/team/types.d.ts +0 -269
  125. package/dist/team/types.js +0 -70
  126. package/dist/team/types.js.map +0 -1
  127. package/dist/utils/browser.d.ts +0 -10
  128. package/dist/utils/browser.js +0 -96
  129. package/dist/utils/browser.js.map +0 -1
  130. package/dist/utils/platform.d.ts +0 -29
  131. package/dist/utils/platform.js +0 -90
  132. package/dist/utils/platform.js.map +0 -1
  133. package/dist/worktree/identity.d.ts +0 -9
  134. package/dist/worktree/identity.js +0 -32
  135. package/dist/worktree/identity.js.map +0 -1
  136. package/dist/worktree/parallel.d.ts +0 -87
  137. package/dist/worktree/parallel.js +0 -328
  138. package/dist/worktree/parallel.js.map +0 -1
  139. package/dist/worktree/session.d.ts +0 -67
  140. package/dist/worktree/session.js +0 -194
  141. package/dist/worktree/session.js.map +0 -1
  142. package/dist/worktree/state-merge.d.ts +0 -43
  143. package/dist/worktree/state-merge.js +0 -162
  144. package/dist/worktree/state-merge.js.map +0 -1
@@ -1,101 +0,0 @@
1
- /**
2
- * PRD Selector — Discovery and Presentation for PRD Picking
3
- *
4
- * Wraps the low-level prd-status module to provide higher-level functions
5
- * for the /forge:go skill's PRD selection UI. Discovers PRDs with pending
6
- * milestones, formats them for AskUserQuestion pickers, and handles
7
- * single-PRD auto-selection.
8
- */
9
- import { discoverPRDs } from "../state/prd-status.js";
10
- // ---------------------------------------------------------------------------
11
- // discoverPendingPRDs
12
- // ---------------------------------------------------------------------------
13
- /**
14
- * Discover all PRDs that have at least one pending milestone.
15
- *
16
- * Wraps `discoverPRDs()` from prd-status, filters to those with pending
17
- * milestones, and computes completion counts for each.
18
- */
19
- export async function discoverPendingPRDs(projectDir) {
20
- const allPRDs = await discoverPRDs(projectDir);
21
- const pending = [];
22
- for (const entry of allPRDs) {
23
- const milestones = Object.values(entry.status.milestones);
24
- const totalCount = milestones.length;
25
- const pendingCount = milestones.filter((m) => m.status === "pending").length;
26
- const completeCount = milestones.filter((m) => m.status === "complete").length;
27
- if (pendingCount > 0) {
28
- pending.push({
29
- slug: entry.slug,
30
- project: entry.status.project,
31
- branch: entry.status.branch,
32
- pendingCount,
33
- completeCount,
34
- totalCount,
35
- });
36
- }
37
- }
38
- return pending;
39
- }
40
- // ---------------------------------------------------------------------------
41
- // presentPRDPicker
42
- // ---------------------------------------------------------------------------
43
- /**
44
- * Format pending PRDs as label/description pairs for AskUserQuestion.
45
- *
46
- * Each option shows the project name, branch, and milestone progress.
47
- * Example label: "forge-agent-teams (2/5 complete)"
48
- * Example description: "Branch: feat/agent-teams | 3 milestones remaining"
49
- */
50
- export function presentPRDPicker(prds) {
51
- return prds.map((prd) => ({
52
- label: `${prd.project} (${prd.completeCount}/${prd.totalCount} complete)`,
53
- description: `Branch: ${prd.branch} | ${prd.pendingCount} milestone${prd.pendingCount === 1 ? "" : "s"} remaining`,
54
- }));
55
- }
56
- // ---------------------------------------------------------------------------
57
- // presentModePicker
58
- // ---------------------------------------------------------------------------
59
- /**
60
- * Return the two execution mode options for AskUserQuestion.
61
- *
62
- * - "Single milestone" — execute one milestone, then stop for review
63
- * - "Auto (all milestones)" — chain through all pending milestones
64
- */
65
- export function presentModePicker() {
66
- return [
67
- {
68
- label: "Single milestone",
69
- description: "Execute the next pending milestone, then stop for review",
70
- },
71
- {
72
- label: "Auto (all milestones)",
73
- description: "Chain through all pending milestones with fresh context resets",
74
- },
75
- ];
76
- }
77
- // ---------------------------------------------------------------------------
78
- // selectPRD
79
- // ---------------------------------------------------------------------------
80
- /**
81
- * Convenience function: discover pending PRDs and auto-select if only one.
82
- *
83
- * Returns the selected PRD and whether it was auto-selected (skipping the
84
- * picker). Returns null if no PRDs have pending milestones.
85
- */
86
- export async function selectPRD(projectDir) {
87
- const pending = await discoverPendingPRDs(projectDir);
88
- if (pending.length === 0) {
89
- return null;
90
- }
91
- if (pending.length === 1) {
92
- return { prd: pending[0], autoSelected: true };
93
- }
94
- // Multiple PRDs — caller must present the picker and resolve selection.
95
- // Return the first one with autoSelected: false to signal that the caller
96
- // should use presentPRDPicker() to let the user choose.
97
- // The caller is responsible for mapping the user's selection back to the
98
- // correct PendingPRD from the discoverPendingPRDs() result.
99
- return null;
100
- }
101
- //# sourceMappingURL=prd-selector.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prd-selector.js","sourceRoot":"","sources":["../../src/go/prd-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AA8BtD,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,UAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1D,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC;QACrC,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAC9B,CAAC,MAAM,CAAC;QACT,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAC/B,CAAC,MAAM,CAAC;QAET,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO;gBAC7B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;gBAC3B,YAAY;gBACZ,aAAa;gBACb,UAAU;aACX,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAkB;IACjD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACxB,KAAK,EAAE,GAAG,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,UAAU,YAAY;QACzE,WAAW,EAAE,WAAW,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,YAAY,aAAa,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,YAAY;KACnH,CAAC,CAAC,CAAC;AACN,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL;YACE,KAAK,EAAE,kBAAkB;YACzB,WAAW,EACT,0DAA0D;SAC7D;QACD;YACE,KAAK,EAAE,uBAAuB;YAC9B,WAAW,EACT,gEAAgE;SACnE;KACF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,UAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAEtD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACjD,CAAC;IAED,wEAAwE;IACxE,0EAA0E;IAC1E,wDAAwD;IACxD,yEAAyE;IACzE,4DAA4D;IAC5D,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,64 +0,0 @@
1
- import type { ForgeConfig, GateError, PipelineResult, Finding, TeamReviewResult } from "../types.js";
2
- import type { BuilderResponse, EscalationDecision } from "../team/consensus.js";
3
- /** Configuration for team-based review after mechanical gates pass */
4
- export interface ReviewerConfig {
5
- projectDir: string;
6
- prdPath?: string;
7
- baseBranch?: string;
8
- /** Callback to get builder responses for findings. The skill drives this via SendMessage. */
9
- onBuilderResponses?: (findings: Finding[]) => Promise<Map<string, BuilderResponse[]>>;
10
- /** Callback for unresolved escalations. Executive makes the call. */
11
- onEscalation?: (findings: Finding[]) => Promise<EscalationDecision[]>;
12
- }
13
- /** Options for the self-healing verification loop */
14
- export interface VerifyLoopOptions {
15
- projectDir: string;
16
- config: ForgeConfig;
17
- /** Override config.maxIterations */
18
- maxIterations?: number;
19
- /** Called after each pipeline run with the iteration number and result */
20
- onIteration?: (iteration: number, result: PipelineResult) => void;
21
- /**
22
- * Called when verification fails, giving the caller a chance to fix errors.
23
- * Returns true if a fix was attempted (loop will re-verify).
24
- * Returns false or is absent to re-run verification without external fix.
25
- */
26
- onFixAttempt?: (iteration: number, errors: GateError[]) => Promise<boolean>;
27
- /** Configuration for team-based review after mechanical gates pass */
28
- reviewerConfig?: ReviewerConfig;
29
- /** Called when review findings and consensus are complete */
30
- onReviewComplete?: (reviewResult: TeamReviewResult) => void;
31
- }
32
- /** Result from the complete verification loop */
33
- export interface VerifyLoopResult {
34
- passed: boolean;
35
- iterations: number;
36
- maxIterations: number;
37
- /** All pipeline results across every iteration */
38
- results: PipelineResult[];
39
- /** The last pipeline result */
40
- finalResult: PipelineResult;
41
- /** Gate names that still fail after all iterations */
42
- failedGates: string[];
43
- /** Human-readable summary of remaining errors */
44
- errorSummary: string;
45
- /** Review findings from the team reviewer (only present when reviewerConfig is provided) */
46
- reviewFindings?: TeamReviewResult;
47
- }
48
- /**
49
- * Self-healing verification loop.
50
- *
51
- * Runs the forge verification pipeline, and on failure either invokes the
52
- * `onFixAttempt` callback (so the caller can spawn a fix agent) or simply
53
- * re-runs verification. Loops until the pipeline passes or max iterations
54
- * are exhausted.
55
- */
56
- export declare function runVerifyLoop(options: VerifyLoopOptions): Promise<VerifyLoopResult>;
57
- /**
58
- * Format gate errors into a structured prompt for a fix agent.
59
- *
60
- * The output is designed to be directly usable in an AI agent prompt:
61
- * it includes file paths, line numbers, error messages, and remediation
62
- * hints so the agent can locate and fix issues without extra searching.
63
- */
64
- export declare function formatErrorsForAgent(result: PipelineResult): string;
@@ -1,327 +0,0 @@
1
- import { readFileSync, writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { runPipeline } from "../gates/index.js";
4
- import { reviewWaveDiff } from "../team/reviewer.js";
5
- import { runConsensusProtocol, escalateToExecutive, createConsensusState, recordBuilderResponse, } from "../team/consensus.js";
6
- /**
7
- * Self-healing verification loop.
8
- *
9
- * Runs the forge verification pipeline, and on failure either invokes the
10
- * `onFixAttempt` callback (so the caller can spawn a fix agent) or simply
11
- * re-runs verification. Loops until the pipeline passes or max iterations
12
- * are exhausted.
13
- */
14
- export async function runVerifyLoop(options) {
15
- const { projectDir, config, onIteration, onFixAttempt, reviewerConfig, onReviewComplete, } = options;
16
- const maxIterations = options.maxIterations ?? config.maxIterations;
17
- const results = [];
18
- // Snapshot .forge.json before the loop to detect unauthorized config mutation
19
- const configPath = join(projectDir, ".forge.json");
20
- let configSnapshot = null;
21
- try {
22
- configSnapshot = readFileSync(configPath, "utf-8");
23
- }
24
- catch {
25
- // .forge.json may not exist — skip detection
26
- }
27
- for (let iteration = 1; iteration <= maxIterations; iteration++) {
28
- const pipelineInput = {
29
- projectDir,
30
- gates: config.gates,
31
- prdPath: config.prdPath,
32
- maxIterations,
33
- devServerCommand: config.devServer?.command,
34
- devServerPort: config.devServer?.port,
35
- };
36
- const result = await runPipeline(pipelineInput);
37
- // Stamp the iteration number onto the result
38
- const stamped = {
39
- ...result,
40
- iteration,
41
- maxIterations,
42
- };
43
- results.push(stamped);
44
- onIteration?.(iteration, stamped);
45
- // Success — mechanical gates passed
46
- if (stamped.passed) {
47
- // If reviewer is configured, run team-based review before declaring success
48
- if (reviewerConfig) {
49
- const reviewResult = await runTeamReview(reviewerConfig, onFixAttempt, onReviewComplete, iteration);
50
- // If review found accepted errors that need fixing, continue the loop
51
- if (reviewResult.hasAcceptedErrors && iteration < maxIterations) {
52
- // Convert accepted findings to GateErrors for the fix callback
53
- const fixErrors = findingsToGateErrors(reviewResult.acceptedFindings);
54
- if (onFixAttempt) {
55
- await onFixAttempt(iteration, fixErrors);
56
- }
57
- // Continue the loop to re-verify after fixes
58
- continue;
59
- }
60
- // No accepted errors or at max iterations — return with review data
61
- return {
62
- passed: true,
63
- iterations: iteration,
64
- maxIterations,
65
- results,
66
- finalResult: stamped,
67
- failedGates: [],
68
- errorSummary: "",
69
- reviewFindings: reviewResult.teamReviewResult,
70
- };
71
- }
72
- // No reviewer configured — return immediately
73
- return {
74
- passed: true,
75
- iterations: iteration,
76
- maxIterations,
77
- results,
78
- finalResult: stamped,
79
- failedGates: [],
80
- errorSummary: "",
81
- };
82
- }
83
- // Not the last iteration — attempt a fix before retrying
84
- if (iteration < maxIterations) {
85
- const allErrors = collectErrors(stamped);
86
- if (onFixAttempt) {
87
- // Give the caller a chance to fix. Even if it returns false we still
88
- // loop and re-verify (the caller may have partially fixed things, or
89
- // an external process may have intervened).
90
- await onFixAttempt(iteration, allErrors);
91
- // Guard: detect if the fix agent mutated .forge.json (gate removal, etc.)
92
- if (configSnapshot !== null) {
93
- try {
94
- const currentConfig = readFileSync(configPath, "utf-8");
95
- if (currentConfig !== configSnapshot) {
96
- // Restore the original config — agents must not modify it
97
- writeFileSync(configPath, configSnapshot, "utf-8");
98
- // Add a warning to the last result so it surfaces in reports
99
- const lastResult = results[results.length - 1];
100
- if (lastResult) {
101
- lastResult.gates.push({
102
- gate: "config-guard",
103
- passed: true,
104
- errors: [],
105
- warnings: [
106
- ".forge.json was modified by a fix agent and has been restored. Agents must not modify project configuration to pass verification.",
107
- ],
108
- duration_ms: 0,
109
- });
110
- }
111
- }
112
- }
113
- catch {
114
- // Non-fatal: if we can't read the file, skip detection
115
- }
116
- }
117
- }
118
- }
119
- }
120
- // Exhausted all iterations without passing
121
- const finalResult = results[results.length - 1];
122
- const failedGates = finalResult.gates
123
- .filter((g) => !g.passed)
124
- .map((g) => g.gate);
125
- return {
126
- passed: false,
127
- iterations: maxIterations,
128
- maxIterations,
129
- results,
130
- finalResult,
131
- failedGates,
132
- errorSummary: buildErrorSummary(maxIterations, finalResult),
133
- };
134
- }
135
- // ---------------------------------------------------------------------------
136
- // Helpers
137
- // ---------------------------------------------------------------------------
138
- /** Collect all GateError items from failed gates in a pipeline result */
139
- function collectErrors(result) {
140
- return result.gates
141
- .filter((g) => !g.passed)
142
- .flatMap((g) => g.errors);
143
- }
144
- /**
145
- * Build a human-readable error summary for a failed verification run.
146
- *
147
- * Example output:
148
- * ```
149
- * Verification failed after 3 iterations.
150
- *
151
- * Failed gates:
152
- * - types: 2 errors
153
- * - src/foo.ts:10: Type 'string' not assignable to 'number'
154
- * - src/bar.ts:5: Property 'x' does not exist on type 'Y'
155
- * - lint: 1 error
156
- * - src/baz.ts:20: Unexpected any type
157
- * ```
158
- */
159
- function buildErrorSummary(iterations, result) {
160
- const lines = [];
161
- lines.push(`Verification failed after ${iterations} iteration${iterations === 1 ? "" : "s"}.`);
162
- lines.push("");
163
- const failedGates = result.gates.filter((g) => !g.passed);
164
- if (failedGates.length === 0) {
165
- return lines.join("\n");
166
- }
167
- lines.push("Failed gates:");
168
- for (const gate of failedGates) {
169
- const errorCount = gate.errors.length;
170
- lines.push(`- ${gate.gate}: ${errorCount} error${errorCount === 1 ? "" : "s"}`);
171
- for (const err of gate.errors) {
172
- const location = formatLocation(err);
173
- const prefix = location ? `${location}: ` : "";
174
- lines.push(` - ${prefix}${err.message}`);
175
- }
176
- }
177
- return lines.join("\n");
178
- }
179
- /** Format file:line location string for an error */
180
- function formatLocation(err) {
181
- if (!err.file)
182
- return "";
183
- return err.line ? `${err.file}:${err.line}` : err.file;
184
- }
185
- /**
186
- * Run the team-based review after mechanical gates pass.
187
- *
188
- * 1. Call reviewWaveDiff() to get findings from the reviewer
189
- * 2. If findings exist, call onBuilderResponses() to get builder consensus
190
- * 3. Run runConsensusProtocol() with the builder responses
191
- * 4. If escalations are needed, call onEscalation()
192
- * 5. Return the review outcome with accepted findings that need fixing
193
- */
194
- async function runTeamReview(reviewerConfig, onFixAttempt, onReviewComplete, iteration) {
195
- const startTime = Date.now();
196
- // Step 1: Get findings from the reviewer
197
- const findings = reviewWaveDiff({
198
- projectDir: reviewerConfig.projectDir,
199
- prdPath: reviewerConfig.prdPath,
200
- baseBranch: reviewerConfig.baseBranch,
201
- });
202
- // No findings — review is clean
203
- if (findings.length === 0) {
204
- const emptyResult = {
205
- findings: [],
206
- consensusResults: [],
207
- duration_ms: Date.now() - startTime,
208
- };
209
- onReviewComplete?.(emptyResult);
210
- return {
211
- teamReviewResult: emptyResult,
212
- hasAcceptedErrors: false,
213
- acceptedFindings: [],
214
- };
215
- }
216
- // Step 2: Get builder responses via SendMessage callback
217
- let responses = new Map();
218
- if (reviewerConfig.onBuilderResponses) {
219
- responses = await reviewerConfig.onBuilderResponses(findings);
220
- }
221
- // Step 3: Run consensus protocol
222
- const consensusOutcome = runConsensusProtocol(findings, responses);
223
- let allConsensusResults = [...consensusOutcome.results];
224
- // Step 4: Handle escalations if needed
225
- if (consensusOutcome.needsEscalation.length > 0 && reviewerConfig.onEscalation) {
226
- const escalationDecisions = await reviewerConfig.onEscalation(consensusOutcome.needsEscalation);
227
- // Apply escalation decisions to each finding that needed it
228
- for (let i = 0; i < consensusOutcome.needsEscalation.length; i++) {
229
- const finding = consensusOutcome.needsEscalation[i];
230
- const decision = escalationDecisions[i];
231
- if (finding && decision) {
232
- let state = createConsensusState(finding);
233
- // Replay builder responses to get to the escalation state
234
- const findingResponses = responses.get(finding.id) ?? [];
235
- for (const resp of findingResponses) {
236
- state = recordBuilderResponse(state, resp);
237
- if (state.resolved)
238
- break;
239
- }
240
- // Apply the executive decision
241
- state = escalateToExecutive(state, decision);
242
- if (state.result) {
243
- allConsensusResults.push(state.result);
244
- }
245
- }
246
- }
247
- }
248
- // Step 5: Collect accepted findings that need fixing
249
- const acceptedFindingIds = new Set(allConsensusResults
250
- .filter((r) => r.resolution === "accepted")
251
- .map((r) => r.findingId));
252
- const acceptedFindings = findings.filter((f) => acceptedFindingIds.has(f.id) && f.severity === "error");
253
- const teamReviewResult = {
254
- findings,
255
- consensusResults: allConsensusResults,
256
- duration_ms: Date.now() - startTime,
257
- };
258
- onReviewComplete?.(teamReviewResult);
259
- return {
260
- teamReviewResult,
261
- hasAcceptedErrors: acceptedFindings.length > 0,
262
- acceptedFindings,
263
- };
264
- }
265
- /** Convert review Findings into GateError[] for the fix callback */
266
- function findingsToGateErrors(findings) {
267
- return findings.map((f) => ({
268
- file: f.file,
269
- line: f.line,
270
- message: `[Review] ${f.message}`,
271
- remediation: f.remediation,
272
- }));
273
- }
274
- /**
275
- * Format gate errors into a structured prompt for a fix agent.
276
- *
277
- * The output is designed to be directly usable in an AI agent prompt:
278
- * it includes file paths, line numbers, error messages, and remediation
279
- * hints so the agent can locate and fix issues without extra searching.
280
- */
281
- export function formatErrorsForAgent(result) {
282
- const lines = [];
283
- const failedGates = result.gates.filter((g) => !g.passed);
284
- if (failedGates.length === 0) {
285
- return "All gates passed. No errors to fix.";
286
- }
287
- lines.push("# Verification Errors to Fix");
288
- lines.push("");
289
- for (const gate of failedGates) {
290
- lines.push(`## Gate: ${gate.gate} (${gate.errors.length} errors)`);
291
- lines.push("");
292
- if (gate.errors.length === 0) {
293
- lines.push("Gate failed but reported no structured errors.");
294
- lines.push("");
295
- continue;
296
- }
297
- for (const err of gate.errors) {
298
- const location = formatLocation(err);
299
- if (location) {
300
- lines.push(`### ${location}`);
301
- }
302
- else {
303
- lines.push("### (no file location)");
304
- }
305
- lines.push(`**Error:** ${err.message}`);
306
- if (err.remediation) {
307
- lines.push("");
308
- lines.push(`> **Remediation:** ${err.remediation}`);
309
- }
310
- lines.push("");
311
- }
312
- }
313
- // Add warnings as context (non-blocking but useful for agents)
314
- const gatesWithWarnings = result.gates.filter((g) => g.warnings.length > 0);
315
- if (gatesWithWarnings.length > 0) {
316
- lines.push("## Warnings (non-blocking)");
317
- lines.push("");
318
- for (const gate of gatesWithWarnings) {
319
- for (const warning of gate.warnings) {
320
- lines.push(`- [${gate.gate}] ${warning}`);
321
- }
322
- }
323
- lines.push("");
324
- }
325
- return lines.join("\n");
326
- }
327
- //# sourceMappingURL=verify-loop.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-loop.js","sourceRoot":"","sources":["../../src/go/verify-loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AASjC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAsD9B;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAA0B;IAE1B,MAAM,EACJ,UAAU,EACV,MAAM,EACN,WAAW,EACX,YAAY,EACZ,cAAc,EACd,gBAAgB,GACjB,GAAG,OAAO,CAAC;IAEZ,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa,CAAC;IACpE,MAAM,OAAO,GAAqB,EAAE,CAAC;IAErC,8EAA8E;IAC9E,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACnD,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,cAAc,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,6CAA6C;IAC/C,CAAC;IAED,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,IAAI,aAAa,EAAE,SAAS,EAAE,EAAE,CAAC;QAChE,MAAM,aAAa,GAAkB;YACnC,UAAU;YACV,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,aAAa;YACb,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO;YAC3C,aAAa,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI;SACtC,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC;QAEhD,6CAA6C;QAC7C,MAAM,OAAO,GAAmB;YAC9B,GAAG,MAAM;YACT,SAAS;YACT,aAAa;SACd,CAAC;QAEF,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,WAAW,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAElC,oCAAoC;QACpC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,4EAA4E;YAC5E,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,YAAY,GAAG,MAAM,aAAa,CACtC,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,SAAS,CACV,CAAC;gBAEF,sEAAsE;gBACtE,IAAI,YAAY,CAAC,iBAAiB,IAAI,SAAS,GAAG,aAAa,EAAE,CAAC;oBAChE,+DAA+D;oBAC/D,MAAM,SAAS,GAAG,oBAAoB,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;oBACtE,IAAI,YAAY,EAAE,CAAC;wBACjB,MAAM,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;oBAC3C,CAAC;oBACD,6CAA6C;oBAC7C,SAAS;gBACX,CAAC;gBAED,oEAAoE;gBACpE,OAAO;oBACL,MAAM,EAAE,IAAI;oBACZ,UAAU,EAAE,SAAS;oBACrB,aAAa;oBACb,OAAO;oBACP,WAAW,EAAE,OAAO;oBACpB,WAAW,EAAE,EAAE;oBACf,YAAY,EAAE,EAAE;oBAChB,cAAc,EAAE,YAAY,CAAC,gBAAgB;iBAC9C,CAAC;YACJ,CAAC;YAED,8CAA8C;YAC9C,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,UAAU,EAAE,SAAS;gBACrB,aAAa;gBACb,OAAO;gBACP,WAAW,EAAE,OAAO;gBACpB,WAAW,EAAE,EAAE;gBACf,YAAY,EAAE,EAAE;aACjB,CAAC;QACJ,CAAC;QAED,yDAAyD;QACzD,IAAI,SAAS,GAAG,aAAa,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YAEzC,IAAI,YAAY,EAAE,CAAC;gBACjB,qEAAqE;gBACrE,qEAAqE;gBACrE,4CAA4C;gBAC5C,MAAM,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBAEzC,0EAA0E;gBAC1E,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;oBAC5B,IAAI,CAAC;wBACH,MAAM,aAAa,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;wBACxD,IAAI,aAAa,KAAK,cAAc,EAAE,CAAC;4BACrC,0DAA0D;4BAC1D,aAAa,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;4BACnD,6DAA6D;4BAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;4BAC/C,IAAI,UAAU,EAAE,CAAC;gCACf,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;oCACpB,IAAI,EAAE,cAAc;oCACpB,MAAM,EAAE,IAAI;oCACZ,MAAM,EAAE,EAAE;oCACV,QAAQ,EAAE;wCACR,mIAAmI;qCACpI;oCACD,WAAW,EAAE,CAAC;iCACf,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,uDAAuD;oBACzD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IACjD,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK;SAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEtB,OAAO;QACL,MAAM,EAAE,KAAK;QACb,UAAU,EAAE,aAAa;QACzB,aAAa;QACb,OAAO;QACP,WAAW;QACX,WAAW;QACX,YAAY,EAAE,iBAAiB,CAAC,aAAa,EAAE,WAAW,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,yEAAyE;AACzE,SAAS,aAAa,CAAC,MAAsB;IAC3C,OAAO,MAAM,CAAC,KAAK;SAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;SACxB,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAS,iBAAiB,CACxB,UAAkB,EAClB,MAAsB;IAEtB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CACR,6BAA6B,UAAU,aAAa,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CACnF,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QACtC,KAAK,CAAC,IAAI,CACR,KAAK,IAAI,CAAC,IAAI,KAAK,UAAU,SAAS,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CACpE,CAAC;QACF,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,oDAAoD;AACpD,SAAS,cAAc,CAAC,GAAc;IACpC,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACzB,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;AACzD,CAAC;AAYD;;;;;;;;GAQG;AACH,KAAK,UAAU,aAAa,CAC1B,cAA8B,EAC9B,YAA+C,EAC/C,gBAAuD,EACvD,SAAiB;IAEjB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,yCAAyC;IACzC,MAAM,QAAQ,GAAG,cAAc,CAAC;QAC9B,UAAU,EAAE,cAAc,CAAC,UAAU;QACrC,OAAO,EAAE,cAAc,CAAC,OAAO;QAC/B,UAAU,EAAE,cAAc,CAAC,UAAU;KACtC,CAAC,CAAC;IAEH,gCAAgC;IAChC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,WAAW,GAAqB;YACpC,QAAQ,EAAE,EAAE;YACZ,gBAAgB,EAAE,EAAE;YACpB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACpC,CAAC;QACF,gBAAgB,EAAE,CAAC,WAAW,CAAC,CAAC;QAChC,OAAO;YACL,gBAAgB,EAAE,WAAW;YAC7B,iBAAiB,EAAE,KAAK;YACxB,gBAAgB,EAAE,EAAE;SACrB,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,IAAI,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAC;IACrD,IAAI,cAAc,CAAC,kBAAkB,EAAE,CAAC;QACtC,SAAS,GAAG,MAAM,cAAc,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAChE,CAAC;IAED,iCAAiC;IACjC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACnE,IAAI,mBAAmB,GAAG,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAExD,uCAAuC;IACvC,IAAI,gBAAgB,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,CAAC,YAAY,EAAE,CAAC;QAC/E,MAAM,mBAAmB,GAAG,MAAM,cAAc,CAAC,YAAY,CAC3D,gBAAgB,CAAC,eAAe,CACjC,CAAC;QAEF,4DAA4D;QAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACjE,MAAM,OAAO,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YACpD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;gBACxB,IAAI,KAAK,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;gBAC1C,0DAA0D;gBAC1D,MAAM,gBAAgB,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;gBACzD,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;oBACpC,KAAK,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;oBAC3C,IAAI,KAAK,CAAC,QAAQ;wBAAE,MAAM;gBAC5B,CAAC;gBACD,+BAA+B;gBAC/B,KAAK,GAAG,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAC7C,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;oBACjB,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAChC,mBAAmB;SAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC;SAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAC3B,CAAC;IAEF,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CACtC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,CAC9D,CAAC;IAEF,MAAM,gBAAgB,GAAqB;QACzC,QAAQ;QACR,gBAAgB,EAAE,mBAAmB;QACrC,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;KACpC,CAAC;IAEF,gBAAgB,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAErC,OAAO;QACL,gBAAgB;QAChB,iBAAiB,EAAE,gBAAgB,CAAC,MAAM,GAAG,CAAC;QAC9C,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,SAAS,oBAAoB,CAAC,QAAmB;IAC/C,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,YAAY,CAAC,CAAC,OAAO,EAAE;QAChC,WAAW,EAAE,CAAC,CAAC,WAAW;KAC3B,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAsB;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAE1D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,qCAAqC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM,UAAU,CAAC,CAAC;QACnE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;YAC7D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,SAAS;QACX,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YAErC,IAAI,QAAQ,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YACvC,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAExC,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,sBAAsB,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;YACtD,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAC7B,CAAC;IACF,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,IAAI,IAAI,iBAAiB,EAAE,CAAC;YACrC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACpC,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -1,5 +0,0 @@
1
- export interface HookResult {
2
- allowed: boolean;
3
- reason?: string;
4
- }
5
- export declare function checkPreCommit(projectDir: string): HookResult;
@@ -1,75 +0,0 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { execSync } from "node:child_process";
4
- import { loadConfig } from "../config/loader.js";
5
- export function checkPreCommit(projectDir) {
6
- // Wrong branch protection
7
- let branch = "unknown";
8
- try {
9
- branch = execSync("git branch --show-current", {
10
- cwd: projectDir,
11
- encoding: "utf-8",
12
- }).trim();
13
- if (branch === "main" || branch === "master") {
14
- return {
15
- allowed: false,
16
- reason: `Cannot commit directly to ${branch}. Create a feature branch first.`,
17
- };
18
- }
19
- }
20
- catch {
21
- // Can't determine branch — allow
22
- }
23
- // Check verify cache — per-branch first, fall back to legacy path
24
- const slug = branch.replace(/\//g, "-").toLowerCase();
25
- const perBranchCachePath = join(projectDir, ".forge", "verify-cache", `${slug}.json`);
26
- const legacyCachePath = join(projectDir, ".forge", "last-verify.json");
27
- const cachePath = existsSync(perBranchCachePath)
28
- ? perBranchCachePath
29
- : legacyCachePath;
30
- if (!existsSync(cachePath)) {
31
- return {
32
- allowed: false,
33
- reason: "No verification found. Run `npx forge verify` before committing.",
34
- };
35
- }
36
- try {
37
- const cache = JSON.parse(readFileSync(cachePath, "utf-8"));
38
- // Validate cache structure — treat malformed cache as invalid
39
- if (typeof cache.passed !== "boolean" || typeof cache.timestamp !== "string") {
40
- return {
41
- allowed: false,
42
- reason: "Verification cache is malformed (missing or invalid fields). Run `npx forge verify`.",
43
- };
44
- }
45
- if (!cache.passed) {
46
- return {
47
- allowed: false,
48
- reason: "Last verification FAILED. Fix errors and run `npx forge verify` again.",
49
- };
50
- }
51
- const config = loadConfig(projectDir);
52
- const age = Date.now() - new Date(cache.timestamp).getTime();
53
- if (Number.isNaN(age) || age < 0) {
54
- return {
55
- allowed: false,
56
- reason: "Verification cache has an invalid timestamp. Run `npx forge verify`.",
57
- };
58
- }
59
- if (age > config.verifyFreshness) {
60
- const ageMin = Math.round(age / 60_000);
61
- return {
62
- allowed: false,
63
- reason: `Verification is stale (${ageMin}min old). Run \`npx forge verify\` again.`,
64
- };
65
- }
66
- return { allowed: true };
67
- }
68
- catch {
69
- return {
70
- allowed: false,
71
- reason: "Could not read verification cache. Run `npx forge verify`.",
72
- };
73
- }
74
- }
75
- //# sourceMappingURL=pre-commit.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pre-commit.js","sourceRoot":"","sources":["../../src/hooks/pre-commit.ts"],"names":[],"mappings":"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"}
@@ -1,22 +0,0 @@
1
- import { LinearClient, type LinearIssue } from "./client.js";
2
- /** Valid issue states */
3
- export declare const ISSUE_STATES: readonly ["Backlog", "Todo", "In Progress", "In Review", "Done", "Canceled"];
4
- export type IssueState = (typeof ISSUE_STATES)[number];
5
- /** Create an issue under a project milestone */
6
- export declare function createMilestoneIssue(client: LinearClient, input: {
7
- title: string;
8
- description?: string;
9
- teamId: string;
10
- projectId: string;
11
- milestoneId: string;
12
- priority?: number;
13
- }): Promise<LinearIssue>;
14
- /** Resolve a state name to its UUID for a given team */
15
- export declare function resolveStateId(client: LinearClient, teamId: string, stateName: string): Promise<string>;
16
- /** Transition all issues in a milestone to a target state */
17
- export declare function transitionMilestoneIssues(client: LinearClient, projectId: string, milestoneId: string, targetState: string, teamId: string): Promise<{
18
- updated: number;
19
- issues: LinearIssue[];
20
- }>;
21
- /** Add a progress comment to an issue */
22
- export declare function addProgressComment(client: LinearClient, issueId: string, message: string): Promise<void>;