forge-cc 0.1.9 → 0.1.11
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.
- package/README.md +253 -178
- package/dist/cli.js +109 -8
- package/dist/cli.js.map +1 -1
- package/dist/gates/codex-gate.d.ts +51 -0
- package/dist/gates/codex-gate.js +121 -0
- package/dist/gates/codex-gate.js.map +1 -0
- package/dist/go/auto-chain.d.ts +13 -23
- package/dist/go/auto-chain.js +29 -101
- package/dist/go/auto-chain.js.map +1 -1
- package/dist/go/executor.d.ts +5 -0
- package/dist/go/executor.js +43 -5
- package/dist/go/executor.js.map +1 -1
- package/dist/go/finalize.d.ts +50 -1
- package/dist/go/finalize.js +122 -0
- package/dist/go/finalize.js.map +1 -1
- package/dist/go/prd-queue.d.ts +43 -0
- package/dist/go/prd-queue.js +67 -0
- package/dist/go/prd-queue.js.map +1 -0
- package/dist/go/prd-selector.d.ts +57 -0
- package/dist/go/prd-selector.js +101 -0
- package/dist/go/prd-selector.js.map +1 -0
- package/dist/go/verify-loop.d.ts +18 -1
- package/dist/go/verify-loop.js +119 -2
- package/dist/go/verify-loop.js.map +1 -1
- package/dist/spec/templates.d.ts +2 -2
- package/dist/state/prd-status.d.ts +59 -0
- package/dist/state/prd-status.js +121 -0
- package/dist/state/prd-status.js.map +1 -0
- package/dist/state/reader.d.ts +2 -24
- package/dist/state/reader.js +4 -77
- package/dist/state/reader.js.map +1 -1
- package/dist/state/writer.d.ts +2 -41
- package/dist/state/writer.js +14 -130
- package/dist/state/writer.js.map +1 -1
- package/dist/team/consensus.d.ts +28 -0
- package/dist/team/consensus.js +130 -0
- package/dist/team/consensus.js.map +1 -0
- package/dist/team/index.d.ts +4 -0
- package/dist/team/index.js +5 -0
- package/dist/team/index.js.map +1 -0
- package/dist/team/lifecycle.d.ts +37 -0
- package/dist/team/lifecycle.js +92 -0
- package/dist/team/lifecycle.js.map +1 -0
- package/dist/team/reviewer.d.ts +10 -0
- package/dist/team/reviewer.js +345 -0
- package/dist/team/reviewer.js.map +1 -0
- package/dist/team/types.d.ts +269 -0
- package/dist/team/types.js +70 -0
- package/dist/team/types.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/utils/browser.d.ts +1 -1
- package/dist/utils/browser.js +8 -1
- package/dist/utils/browser.js.map +1 -1
- package/dist/worktree/session.d.ts +3 -0
- package/dist/worktree/session.js +1 -0
- package/dist/worktree/session.js.map +1 -1
- package/package.json +2 -1
- package/skills/forge-go.md +176 -62
- package/skills/forge-spec.md +30 -5
package/dist/go/finalize.js
CHANGED
|
@@ -7,6 +7,128 @@
|
|
|
7
7
|
* milestone passes verification.
|
|
8
8
|
*/
|
|
9
9
|
import { execSync } from "node:child_process";
|
|
10
|
+
import { pollForCodexComments, runCodexGate, getUnresolvedComments, fetchPRComments, } from "../gates/codex-gate.js";
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// extractRepoInfo
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/**
|
|
15
|
+
* Extract the owner and repo name from the current Git remote using `gh`.
|
|
16
|
+
* Returns `null` if `gh` is unavailable or the command fails.
|
|
17
|
+
*/
|
|
18
|
+
export function extractRepoInfo(projectDir) {
|
|
19
|
+
try {
|
|
20
|
+
const raw = execSync("gh repo view --json owner,name", {
|
|
21
|
+
cwd: projectDir,
|
|
22
|
+
encoding: "utf-8",
|
|
23
|
+
timeout: 15_000,
|
|
24
|
+
}).trim();
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
return { owner: parsed.owner.login, repo: parsed.name };
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// pollAndResolvePRComments
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/**
|
|
36
|
+
* Poll for Codex review comments on a PR and attempt to resolve them
|
|
37
|
+
* using the provided `onFixComment` callback. Returns the list of
|
|
38
|
+
* comments that remain unresolved after the fix cycle.
|
|
39
|
+
*/
|
|
40
|
+
export async function pollAndResolvePRComments(options) {
|
|
41
|
+
const { owner, repo, prNumber, projectDir, pollIntervalMs, maxPolls, onFixComment, } = options;
|
|
42
|
+
// First pass: poll for comments
|
|
43
|
+
const gateResult = await runCodexGate({
|
|
44
|
+
owner,
|
|
45
|
+
repo,
|
|
46
|
+
prNumber,
|
|
47
|
+
pollIntervalMs,
|
|
48
|
+
maxPolls,
|
|
49
|
+
projectDir,
|
|
50
|
+
});
|
|
51
|
+
// If no errors (gate passed), everything is clean
|
|
52
|
+
if (gateResult.passed) {
|
|
53
|
+
return { unresolved: [], gateResult };
|
|
54
|
+
}
|
|
55
|
+
// If we have no fix callback, just return the unresolved state
|
|
56
|
+
if (!onFixComment) {
|
|
57
|
+
const comments = fetchPRComments({ owner, repo, prNumber, projectDir });
|
|
58
|
+
const unresolved = getUnresolvedComments(comments);
|
|
59
|
+
return { unresolved, gateResult };
|
|
60
|
+
}
|
|
61
|
+
// Attempt to fix each unresolved comment, tracking addressed IDs
|
|
62
|
+
const comments = fetchPRComments({ owner, repo, prNumber, projectDir });
|
|
63
|
+
const addressedIds = new Set();
|
|
64
|
+
for (const comment of comments) {
|
|
65
|
+
await onFixComment(comment);
|
|
66
|
+
addressedIds.add(comment.id);
|
|
67
|
+
}
|
|
68
|
+
// After fixes, do one more poll cycle to check for any NEW comments
|
|
69
|
+
// from a re-review (exclude already-addressed IDs so the loop converges)
|
|
70
|
+
const recheckComments = await pollForCodexComments({
|
|
71
|
+
owner,
|
|
72
|
+
repo,
|
|
73
|
+
prNumber,
|
|
74
|
+
pollIntervalMs: pollIntervalMs ?? 60_000,
|
|
75
|
+
maxPolls: 1,
|
|
76
|
+
projectDir,
|
|
77
|
+
knownIds: addressedIds,
|
|
78
|
+
});
|
|
79
|
+
const stillUnresolved = recheckComments;
|
|
80
|
+
// Build a final gate result reflecting the post-fix state
|
|
81
|
+
const finalGateResult = {
|
|
82
|
+
gate: "codex",
|
|
83
|
+
passed: stillUnresolved.length === 0,
|
|
84
|
+
errors: stillUnresolved.map((c) => ({
|
|
85
|
+
file: c.path,
|
|
86
|
+
line: c.line,
|
|
87
|
+
message: c.body,
|
|
88
|
+
remediation: "Address the Codex review comment",
|
|
89
|
+
})),
|
|
90
|
+
warnings: stillUnresolved.length === 0
|
|
91
|
+
? ["All Codex comments resolved after fix cycle"]
|
|
92
|
+
: [],
|
|
93
|
+
duration_ms: gateResult.duration_ms,
|
|
94
|
+
};
|
|
95
|
+
return { unresolved: stillUnresolved, gateResult: finalGateResult };
|
|
96
|
+
}
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// finalizeWithCodexGate
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
/**
|
|
101
|
+
* Create a PR and run the Codex review gate. The milestone only marks
|
|
102
|
+
* complete when 0 unresolved PR comments remain. If the Codex gate
|
|
103
|
+
* times out with no comments, the milestone still completes (gate is
|
|
104
|
+
* optional).
|
|
105
|
+
*/
|
|
106
|
+
export async function finalizeWithCodexGate(options) {
|
|
107
|
+
// Step 1: Create the PR
|
|
108
|
+
const pr = createPullRequest(options);
|
|
109
|
+
// If PR creation failed, return early
|
|
110
|
+
if (!pr.created) {
|
|
111
|
+
return { pr, allCommentsResolved: false };
|
|
112
|
+
}
|
|
113
|
+
// Step 2: Run the Codex review gate with pollAndResolve
|
|
114
|
+
const { unresolved, gateResult } = await pollAndResolvePRComments({
|
|
115
|
+
owner: options.owner,
|
|
116
|
+
repo: options.repo,
|
|
117
|
+
prNumber: pr.number,
|
|
118
|
+
projectDir: options.projectDir,
|
|
119
|
+
pollIntervalMs: options.codexPollIntervalMs,
|
|
120
|
+
maxPolls: options.codexMaxPolls,
|
|
121
|
+
onFixComment: options.onFixComment,
|
|
122
|
+
});
|
|
123
|
+
// Codex gate is optional: if it passed (no comments found / timed out),
|
|
124
|
+
// the milestone still completes
|
|
125
|
+
const allCommentsResolved = unresolved.length === 0;
|
|
126
|
+
return {
|
|
127
|
+
pr,
|
|
128
|
+
codexGate: gateResult,
|
|
129
|
+
allCommentsResolved,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
10
132
|
// ---------------------------------------------------------------------------
|
|
11
133
|
// buildPRTitle
|
|
12
134
|
// ---------------------------------------------------------------------------
|
package/dist/go/finalize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalize.js","sourceRoot":"","sources":["../../src/go/finalize.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"finalize.js","sourceRoot":"","sources":["../../src/go/finalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD Queue — Multi-PRD Execution Queue Manager
|
|
3
|
+
*
|
|
4
|
+
* Scans all PRDs, determines which have pending milestones, and tracks
|
|
5
|
+
* which PRDs are currently being executed by active sessions.
|
|
6
|
+
* Used by `npx forge run --all` to dispatch parallel PRD execution.
|
|
7
|
+
*/
|
|
8
|
+
export interface PRDQueueEntry {
|
|
9
|
+
slug: string;
|
|
10
|
+
project: string;
|
|
11
|
+
branch: string;
|
|
12
|
+
pendingMilestones: number;
|
|
13
|
+
nextMilestone: number | null;
|
|
14
|
+
isExecuting: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare class PRDQueue {
|
|
17
|
+
private projectDir;
|
|
18
|
+
private repoRoot;
|
|
19
|
+
constructor(projectDir: string);
|
|
20
|
+
/**
|
|
21
|
+
* Scan all PRDs and return queue entries with execution status.
|
|
22
|
+
*
|
|
23
|
+
* For each discovered PRD:
|
|
24
|
+
* - Counts pending milestones
|
|
25
|
+
* - Finds the next pending milestone number
|
|
26
|
+
* - Checks the session registry for active sessions with a matching prdSlug
|
|
27
|
+
*/
|
|
28
|
+
scanPRDs(): Promise<PRDQueueEntry[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Get PRDs that are ready to execute.
|
|
31
|
+
*
|
|
32
|
+
* A PRD is ready when it has pending milestones and is not currently
|
|
33
|
+
* being executed by any active session.
|
|
34
|
+
*/
|
|
35
|
+
getReadyPRDs(): Promise<PRDQueueEntry[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Check if a PRD is currently being executed by any active session.
|
|
38
|
+
*
|
|
39
|
+
* Loads the session registry and checks for active sessions whose
|
|
40
|
+
* `prdSlug` field matches the given slug.
|
|
41
|
+
*/
|
|
42
|
+
isExecuting(slug: string): boolean;
|
|
43
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD Queue — Multi-PRD Execution Queue Manager
|
|
3
|
+
*
|
|
4
|
+
* Scans all PRDs, determines which have pending milestones, and tracks
|
|
5
|
+
* which PRDs are currently being executed by active sessions.
|
|
6
|
+
* Used by `npx forge run --all` to dispatch parallel PRD execution.
|
|
7
|
+
*/
|
|
8
|
+
import { discoverPRDs, findNextPendingMilestone, countPendingMilestones, } from "../state/prd-status.js";
|
|
9
|
+
import { getActiveSessions } from "../worktree/session.js";
|
|
10
|
+
import { getRepoRoot } from "../worktree/manager.js";
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// PRDQueue
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
export class PRDQueue {
|
|
15
|
+
projectDir;
|
|
16
|
+
repoRoot;
|
|
17
|
+
constructor(projectDir) {
|
|
18
|
+
this.projectDir = projectDir;
|
|
19
|
+
this.repoRoot = getRepoRoot(projectDir);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Scan all PRDs and return queue entries with execution status.
|
|
23
|
+
*
|
|
24
|
+
* For each discovered PRD:
|
|
25
|
+
* - Counts pending milestones
|
|
26
|
+
* - Finds the next pending milestone number
|
|
27
|
+
* - Checks the session registry for active sessions with a matching prdSlug
|
|
28
|
+
*/
|
|
29
|
+
async scanPRDs() {
|
|
30
|
+
const prds = await discoverPRDs(this.projectDir);
|
|
31
|
+
const entries = [];
|
|
32
|
+
for (const prd of prds) {
|
|
33
|
+
const pending = await countPendingMilestones(this.projectDir, prd.slug);
|
|
34
|
+
const nextPending = await findNextPendingMilestone(this.projectDir, prd.slug);
|
|
35
|
+
entries.push({
|
|
36
|
+
slug: prd.slug,
|
|
37
|
+
project: prd.status.project,
|
|
38
|
+
branch: prd.status.branch,
|
|
39
|
+
pendingMilestones: pending,
|
|
40
|
+
nextMilestone: nextPending ? nextPending.number : null,
|
|
41
|
+
isExecuting: this.isExecuting(prd.slug),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return entries;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get PRDs that are ready to execute.
|
|
48
|
+
*
|
|
49
|
+
* A PRD is ready when it has pending milestones and is not currently
|
|
50
|
+
* being executed by any active session.
|
|
51
|
+
*/
|
|
52
|
+
async getReadyPRDs() {
|
|
53
|
+
const all = await this.scanPRDs();
|
|
54
|
+
return all.filter((entry) => entry.pendingMilestones > 0 && !entry.isExecuting);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check if a PRD is currently being executed by any active session.
|
|
58
|
+
*
|
|
59
|
+
* Loads the session registry and checks for active sessions whose
|
|
60
|
+
* `prdSlug` field matches the given slug.
|
|
61
|
+
*/
|
|
62
|
+
isExecuting(slug) {
|
|
63
|
+
const activeSessions = getActiveSessions(this.repoRoot);
|
|
64
|
+
return activeSessions.some((session) => session.prdSlug === slug);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=prd-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd-queue.js","sourceRoot":"","sources":["../../src/go/prd-queue.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAerD,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,MAAM,OAAO,QAAQ;IACX,UAAU,CAAS;IACnB,QAAQ,CAAS;IAEzB,YAAY,UAAkB;QAC5B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACjD,MAAM,OAAO,GAAoB,EAAE,CAAC;QAEpC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACxE,MAAM,WAAW,GAAG,MAAM,wBAAwB,CAChD,IAAI,CAAC,UAAU,EACf,GAAG,CAAC,IAAI,CACT,CAAC;YAEF,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO;gBAC3B,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM;gBACzB,iBAAiB,EAAE,OAAO;gBAC1B,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;gBACtD,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;aACxC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,YAAY;QAChB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,OAAO,GAAG,CAAC,MAAM,CACf,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAC7D,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,IAAY;QACtB,MAAM,cAAc,GAAG,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxD,OAAO,cAAc,CAAC,IAAI,CACxB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,KAAK,IAAI,CACtC,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
export interface PendingPRD {
|
|
10
|
+
slug: string;
|
|
11
|
+
project: string;
|
|
12
|
+
branch: string;
|
|
13
|
+
pendingCount: number;
|
|
14
|
+
completeCount: number;
|
|
15
|
+
totalCount: number;
|
|
16
|
+
}
|
|
17
|
+
export interface PRDPickerOption {
|
|
18
|
+
label: string;
|
|
19
|
+
description: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ModePickerOption {
|
|
22
|
+
label: string;
|
|
23
|
+
description: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SelectPRDResult {
|
|
26
|
+
prd: PendingPRD;
|
|
27
|
+
autoSelected: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Discover all PRDs that have at least one pending milestone.
|
|
31
|
+
*
|
|
32
|
+
* Wraps `discoverPRDs()` from prd-status, filters to those with pending
|
|
33
|
+
* milestones, and computes completion counts for each.
|
|
34
|
+
*/
|
|
35
|
+
export declare function discoverPendingPRDs(projectDir: string): Promise<PendingPRD[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Format pending PRDs as label/description pairs for AskUserQuestion.
|
|
38
|
+
*
|
|
39
|
+
* Each option shows the project name, branch, and milestone progress.
|
|
40
|
+
* Example label: "forge-agent-teams (2/5 complete)"
|
|
41
|
+
* Example description: "Branch: feat/agent-teams | 3 milestones remaining"
|
|
42
|
+
*/
|
|
43
|
+
export declare function presentPRDPicker(prds: PendingPRD[]): PRDPickerOption[];
|
|
44
|
+
/**
|
|
45
|
+
* Return the two execution mode options for AskUserQuestion.
|
|
46
|
+
*
|
|
47
|
+
* - "Single milestone" — execute one milestone, then stop for review
|
|
48
|
+
* - "Auto (all milestones)" — chain through all pending milestones
|
|
49
|
+
*/
|
|
50
|
+
export declare function presentModePicker(): ModePickerOption[];
|
|
51
|
+
/**
|
|
52
|
+
* Convenience function: discover pending PRDs and auto-select if only one.
|
|
53
|
+
*
|
|
54
|
+
* Returns the selected PRD and whether it was auto-selected (skipping the
|
|
55
|
+
* picker). Returns null if no PRDs have pending milestones.
|
|
56
|
+
*/
|
|
57
|
+
export declare function selectPRD(projectDir: string): Promise<SelectPRDResult | null>;
|
|
@@ -0,0 +1,101 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
package/dist/go/verify-loop.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import type { ForgeConfig, GateError, PipelineResult } from "../types.js";
|
|
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
|
+
}
|
|
2
13
|
/** Options for the self-healing verification loop */
|
|
3
14
|
export interface VerifyLoopOptions {
|
|
4
15
|
projectDir: string;
|
|
@@ -13,6 +24,10 @@ export interface VerifyLoopOptions {
|
|
|
13
24
|
* Returns false or is absent to re-run verification without external fix.
|
|
14
25
|
*/
|
|
15
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;
|
|
16
31
|
}
|
|
17
32
|
/** Result from the complete verification loop */
|
|
18
33
|
export interface VerifyLoopResult {
|
|
@@ -27,6 +42,8 @@ export interface VerifyLoopResult {
|
|
|
27
42
|
failedGates: string[];
|
|
28
43
|
/** Human-readable summary of remaining errors */
|
|
29
44
|
errorSummary: string;
|
|
45
|
+
/** Review findings from the team reviewer (only present when reviewerConfig is provided) */
|
|
46
|
+
reviewFindings?: TeamReviewResult;
|
|
30
47
|
}
|
|
31
48
|
/**
|
|
32
49
|
* Self-healing verification loop.
|
package/dist/go/verify-loop.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { runPipeline } from "../gates/index.js";
|
|
2
|
+
import { reviewWaveDiff } from "../team/reviewer.js";
|
|
3
|
+
import { runConsensusProtocol, escalateToExecutive, createConsensusState, recordBuilderResponse, } from "../team/consensus.js";
|
|
2
4
|
/**
|
|
3
5
|
* Self-healing verification loop.
|
|
4
6
|
*
|
|
@@ -8,7 +10,7 @@ import { runPipeline } from "../gates/index.js";
|
|
|
8
10
|
* are exhausted.
|
|
9
11
|
*/
|
|
10
12
|
export async function runVerifyLoop(options) {
|
|
11
|
-
const { projectDir, config, onIteration, onFixAttempt, } = options;
|
|
13
|
+
const { projectDir, config, onIteration, onFixAttempt, reviewerConfig, onReviewComplete, } = options;
|
|
12
14
|
const maxIterations = options.maxIterations ?? config.maxIterations;
|
|
13
15
|
const results = [];
|
|
14
16
|
for (let iteration = 1; iteration <= maxIterations; iteration++) {
|
|
@@ -29,8 +31,34 @@ export async function runVerifyLoop(options) {
|
|
|
29
31
|
};
|
|
30
32
|
results.push(stamped);
|
|
31
33
|
onIteration?.(iteration, stamped);
|
|
32
|
-
// Success —
|
|
34
|
+
// Success — mechanical gates passed
|
|
33
35
|
if (stamped.passed) {
|
|
36
|
+
// If reviewer is configured, run team-based review before declaring success
|
|
37
|
+
if (reviewerConfig) {
|
|
38
|
+
const reviewResult = await runTeamReview(reviewerConfig, onFixAttempt, onReviewComplete, iteration);
|
|
39
|
+
// If review found accepted errors that need fixing, continue the loop
|
|
40
|
+
if (reviewResult.hasAcceptedErrors && iteration < maxIterations) {
|
|
41
|
+
// Convert accepted findings to GateErrors for the fix callback
|
|
42
|
+
const fixErrors = findingsToGateErrors(reviewResult.acceptedFindings);
|
|
43
|
+
if (onFixAttempt) {
|
|
44
|
+
await onFixAttempt(iteration, fixErrors);
|
|
45
|
+
}
|
|
46
|
+
// Continue the loop to re-verify after fixes
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
// No accepted errors or at max iterations — return with review data
|
|
50
|
+
return {
|
|
51
|
+
passed: true,
|
|
52
|
+
iterations: iteration,
|
|
53
|
+
maxIterations,
|
|
54
|
+
results,
|
|
55
|
+
finalResult: stamped,
|
|
56
|
+
failedGates: [],
|
|
57
|
+
errorSummary: "",
|
|
58
|
+
reviewFindings: reviewResult.teamReviewResult,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// No reviewer configured — return immediately
|
|
34
62
|
return {
|
|
35
63
|
passed: true,
|
|
36
64
|
iterations: iteration,
|
|
@@ -117,6 +145,95 @@ function formatLocation(err) {
|
|
|
117
145
|
return "";
|
|
118
146
|
return err.line ? `${err.file}:${err.line}` : err.file;
|
|
119
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Run the team-based review after mechanical gates pass.
|
|
150
|
+
*
|
|
151
|
+
* 1. Call reviewWaveDiff() to get findings from the reviewer
|
|
152
|
+
* 2. If findings exist, call onBuilderResponses() to get builder consensus
|
|
153
|
+
* 3. Run runConsensusProtocol() with the builder responses
|
|
154
|
+
* 4. If escalations are needed, call onEscalation()
|
|
155
|
+
* 5. Return the review outcome with accepted findings that need fixing
|
|
156
|
+
*/
|
|
157
|
+
async function runTeamReview(reviewerConfig, onFixAttempt, onReviewComplete, iteration) {
|
|
158
|
+
const startTime = Date.now();
|
|
159
|
+
// Step 1: Get findings from the reviewer
|
|
160
|
+
const findings = reviewWaveDiff({
|
|
161
|
+
projectDir: reviewerConfig.projectDir,
|
|
162
|
+
prdPath: reviewerConfig.prdPath,
|
|
163
|
+
baseBranch: reviewerConfig.baseBranch,
|
|
164
|
+
});
|
|
165
|
+
// No findings — review is clean
|
|
166
|
+
if (findings.length === 0) {
|
|
167
|
+
const emptyResult = {
|
|
168
|
+
findings: [],
|
|
169
|
+
consensusResults: [],
|
|
170
|
+
duration_ms: Date.now() - startTime,
|
|
171
|
+
};
|
|
172
|
+
onReviewComplete?.(emptyResult);
|
|
173
|
+
return {
|
|
174
|
+
teamReviewResult: emptyResult,
|
|
175
|
+
hasAcceptedErrors: false,
|
|
176
|
+
acceptedFindings: [],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// Step 2: Get builder responses via SendMessage callback
|
|
180
|
+
let responses = new Map();
|
|
181
|
+
if (reviewerConfig.onBuilderResponses) {
|
|
182
|
+
responses = await reviewerConfig.onBuilderResponses(findings);
|
|
183
|
+
}
|
|
184
|
+
// Step 3: Run consensus protocol
|
|
185
|
+
const consensusOutcome = runConsensusProtocol(findings, responses);
|
|
186
|
+
let allConsensusResults = [...consensusOutcome.results];
|
|
187
|
+
// Step 4: Handle escalations if needed
|
|
188
|
+
if (consensusOutcome.needsEscalation.length > 0 && reviewerConfig.onEscalation) {
|
|
189
|
+
const escalationDecisions = await reviewerConfig.onEscalation(consensusOutcome.needsEscalation);
|
|
190
|
+
// Apply escalation decisions to each finding that needed it
|
|
191
|
+
for (let i = 0; i < consensusOutcome.needsEscalation.length; i++) {
|
|
192
|
+
const finding = consensusOutcome.needsEscalation[i];
|
|
193
|
+
const decision = escalationDecisions[i];
|
|
194
|
+
if (finding && decision) {
|
|
195
|
+
let state = createConsensusState(finding);
|
|
196
|
+
// Replay builder responses to get to the escalation state
|
|
197
|
+
const findingResponses = responses.get(finding.id) ?? [];
|
|
198
|
+
for (const resp of findingResponses) {
|
|
199
|
+
state = recordBuilderResponse(state, resp);
|
|
200
|
+
if (state.resolved)
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
// Apply the executive decision
|
|
204
|
+
state = escalateToExecutive(state, decision);
|
|
205
|
+
if (state.result) {
|
|
206
|
+
allConsensusResults.push(state.result);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Step 5: Collect accepted findings that need fixing
|
|
212
|
+
const acceptedFindingIds = new Set(allConsensusResults
|
|
213
|
+
.filter((r) => r.resolution === "accepted")
|
|
214
|
+
.map((r) => r.findingId));
|
|
215
|
+
const acceptedFindings = findings.filter((f) => acceptedFindingIds.has(f.id) && f.severity === "error");
|
|
216
|
+
const teamReviewResult = {
|
|
217
|
+
findings,
|
|
218
|
+
consensusResults: allConsensusResults,
|
|
219
|
+
duration_ms: Date.now() - startTime,
|
|
220
|
+
};
|
|
221
|
+
onReviewComplete?.(teamReviewResult);
|
|
222
|
+
return {
|
|
223
|
+
teamReviewResult,
|
|
224
|
+
hasAcceptedErrors: acceptedFindings.length > 0,
|
|
225
|
+
acceptedFindings,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/** Convert review Findings into GateError[] for the fix callback */
|
|
229
|
+
function findingsToGateErrors(findings) {
|
|
230
|
+
return findings.map((f) => ({
|
|
231
|
+
file: f.file,
|
|
232
|
+
line: f.line,
|
|
233
|
+
message: `[Review] ${f.message}`,
|
|
234
|
+
remediation: f.remediation,
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
120
237
|
/**
|
|
121
238
|
* Format gate errors into a structured prompt for a fix agent.
|
|
122
239
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-loop.js","sourceRoot":"","sources":["../../src/go/verify-loop.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify-loop.js","sourceRoot":"","sources":["../../src/go/verify-loop.ts"],"names":[],"mappings":"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"}
|