@alevental/cccp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/cccp-pipeline/SKILL.md +562 -0
- package/.claude/skills/cccp-run/SKILL.md +111 -0
- package/README.md +280 -0
- package/dist/activity-bus.d.ts +9 -0
- package/dist/activity-bus.js +10 -0
- package/dist/activity-bus.js.map +1 -0
- package/dist/agent-resolver.d.ts +29 -0
- package/dist/agent-resolver.js +122 -0
- package/dist/agent-resolver.js.map +1 -0
- package/dist/agent.d.ts +39 -0
- package/dist/agent.js +117 -0
- package/dist/agent.js.map +1 -0
- package/dist/autoresearch.d.ts +11 -0
- package/dist/autoresearch.js +295 -0
- package/dist/autoresearch.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +157 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +126 -0
- package/dist/config.js +76 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +24 -0
- package/dist/context.js +82 -0
- package/dist/context.js.map +1 -0
- package/dist/contract.d.ts +26 -0
- package/dist/contract.js +65 -0
- package/dist/contract.js.map +1 -0
- package/dist/db.d.ts +70 -0
- package/dist/db.js +358 -0
- package/dist/db.js.map +1 -0
- package/dist/dispatcher.d.ts +9 -0
- package/dist/dispatcher.js +7 -0
- package/dist/dispatcher.js.map +1 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.js +30 -0
- package/dist/errors.js.map +1 -0
- package/dist/evaluator.d.ts +23 -0
- package/dist/evaluator.js +49 -0
- package/dist/evaluator.js.map +1 -0
- package/dist/gate/auto-approve.d.ts +9 -0
- package/dist/gate/auto-approve.js +11 -0
- package/dist/gate/auto-approve.js.map +1 -0
- package/dist/gate/gate-strategy.d.ts +22 -0
- package/dist/gate/gate-strategy.js +2 -0
- package/dist/gate/gate-strategy.js.map +1 -0
- package/dist/gate/gate-watcher.d.ts +15 -0
- package/dist/gate/gate-watcher.js +64 -0
- package/dist/gate/gate-watcher.js.map +1 -0
- package/dist/logger.d.ts +24 -0
- package/dist/logger.js +22 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp/gate-notifier.d.ts +26 -0
- package/dist/mcp/gate-notifier.js +161 -0
- package/dist/mcp/gate-notifier.js.map +1 -0
- package/dist/mcp/mcp-config.d.ts +25 -0
- package/dist/mcp/mcp-config.js +80 -0
- package/dist/mcp/mcp-config.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +1 -0
- package/dist/mcp/mcp-server.js +262 -0
- package/dist/mcp/mcp-server.js.map +1 -0
- package/dist/pge.d.ts +12 -0
- package/dist/pge.js +361 -0
- package/dist/pge.js.map +1 -0
- package/dist/pipeline.d.ts +6 -0
- package/dist/pipeline.js +120 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/prompt.d.ts +67 -0
- package/dist/prompt.js +121 -0
- package/dist/prompt.js.map +1 -0
- package/dist/runner.d.ts +11 -0
- package/dist/runner.js +494 -0
- package/dist/runner.js.map +1 -0
- package/dist/scaffold/index.d.ts +14 -0
- package/dist/scaffold/index.js +260 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/templates.d.ts +47 -0
- package/dist/scaffold/templates.js +2177 -0
- package/dist/scaffold/templates.js.map +1 -0
- package/dist/stage-helpers.d.ts +7 -0
- package/dist/stage-helpers.js +27 -0
- package/dist/stage-helpers.js.map +1 -0
- package/dist/state.d.ts +43 -0
- package/dist/state.js +177 -0
- package/dist/state.js.map +1 -0
- package/dist/stream/stream-tail.d.ts +17 -0
- package/dist/stream/stream-tail.js +95 -0
- package/dist/stream/stream-tail.js.map +1 -0
- package/dist/stream/stream.d.ts +142 -0
- package/dist/stream/stream.js +251 -0
- package/dist/stream/stream.js.map +1 -0
- package/dist/temp-tracker.d.ts +6 -0
- package/dist/temp-tracker.js +24 -0
- package/dist/temp-tracker.js.map +1 -0
- package/dist/tui/cmux.d.ts +22 -0
- package/dist/tui/cmux.js +82 -0
- package/dist/tui/cmux.js.map +1 -0
- package/dist/tui/components.d.ts +21 -0
- package/dist/tui/components.js +108 -0
- package/dist/tui/components.js.map +1 -0
- package/dist/tui/dashboard.d.ts +6 -0
- package/dist/tui/dashboard.js +125 -0
- package/dist/tui/dashboard.js.map +1 -0
- package/dist/tui/detail-log.d.ts +10 -0
- package/dist/tui/detail-log.js +171 -0
- package/dist/tui/detail-log.js.map +1 -0
- package/dist/types.d.ts +273 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/examples/agents/diff-evaluator.md +57 -0
- package/examples/agents/prompt-tuner.md +30 -0
- package/examples/agents/summarizer.md +14 -0
- package/examples/autoresearch-artifacts/expected-output.md +17 -0
- package/examples/autoresearch-artifacts/prompt.md +35 -0
- package/examples/autoresearch-artifacts/source-material.md +28 -0
- package/examples/business-case.yaml +41 -0
- package/examples/cccp.yaml +48 -0
- package/examples/content-calendar.yaml +59 -0
- package/examples/customer-feedback-loop.yaml +44 -0
- package/examples/design-sprint.yaml +54 -0
- package/examples/feature-development.yaml +96 -0
- package/examples/growth-experiment.yaml +49 -0
- package/examples/incident-runbook.yaml +43 -0
- package/examples/product-launch.yaml +85 -0
- package/examples/prompt-tuning.yaml +25 -0
- package/examples/quarterly-planning.yaml +51 -0
- package/examples/sprint-cycle.yaml +67 -0
- package/package.json +47 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { openDatabase } from "../db.js";
|
|
7
|
+
import { GateNotifier } from "./gate-notifier.js";
|
|
8
|
+
import { saveState, discoverRuns } from "../state.js";
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Run resolution
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
async function resolveRun(runIdPrefix) {
|
|
13
|
+
const projectDir = process.cwd();
|
|
14
|
+
// Reload DB from disk — the runner (separate process) may have written new state.
|
|
15
|
+
const db = await openDatabase(projectDir);
|
|
16
|
+
db.reload();
|
|
17
|
+
const runs = await discoverRuns(projectDir);
|
|
18
|
+
if (runs.length === 0) {
|
|
19
|
+
return { error: "No pipeline runs found. Start one with `cccp run`." };
|
|
20
|
+
}
|
|
21
|
+
if (!runIdPrefix) {
|
|
22
|
+
if (runs.length === 1) {
|
|
23
|
+
return { run: runs[0] };
|
|
24
|
+
}
|
|
25
|
+
const listing = formatRunList(runs);
|
|
26
|
+
return {
|
|
27
|
+
error: `${runs.length} runs found. Specify run_id to select one.\n\n${listing}`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const matches = runs.filter((r) => r.state.runId.startsWith(runIdPrefix));
|
|
31
|
+
if (matches.length === 0) {
|
|
32
|
+
return { error: `No run matching "${runIdPrefix}".` };
|
|
33
|
+
}
|
|
34
|
+
if (matches.length > 1) {
|
|
35
|
+
return {
|
|
36
|
+
error: `Ambiguous run_id "${runIdPrefix}" matches ${matches.length} runs. Use more characters.`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return { run: matches[0] };
|
|
40
|
+
}
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Formatting helpers
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
function formatRunList(runs) {
|
|
45
|
+
const lines = ["Runs:"];
|
|
46
|
+
for (const { state } of runs) {
|
|
47
|
+
const short = state.runId.slice(0, 8);
|
|
48
|
+
const gate = state.gate?.status === "pending"
|
|
49
|
+
? ` | GATE: ${state.gate.stageName}`
|
|
50
|
+
: "";
|
|
51
|
+
lines.push(` ${short} ${state.pipeline} (${state.project}) ${state.status}${gate} ${state.startedAt}`);
|
|
52
|
+
}
|
|
53
|
+
return lines.join("\n");
|
|
54
|
+
}
|
|
55
|
+
function formatStatus(state) {
|
|
56
|
+
const short = state.runId.slice(0, 8);
|
|
57
|
+
const lines = [
|
|
58
|
+
`Pipeline: ${state.pipeline} (run ${short})`,
|
|
59
|
+
`Project: ${state.project}`,
|
|
60
|
+
`Status: ${state.status}`,
|
|
61
|
+
`Started: ${state.startedAt}`,
|
|
62
|
+
];
|
|
63
|
+
if (state.completedAt) {
|
|
64
|
+
lines.push(`Completed: ${state.completedAt}`);
|
|
65
|
+
}
|
|
66
|
+
lines.push("", "Stages:");
|
|
67
|
+
for (const name of state.stageOrder) {
|
|
68
|
+
const s = state.stages[name];
|
|
69
|
+
const icon = s.status === "passed"
|
|
70
|
+
? "✓"
|
|
71
|
+
: s.status === "failed" || s.status === "error"
|
|
72
|
+
? "✗"
|
|
73
|
+
: s.status === "in_progress"
|
|
74
|
+
? "⚙"
|
|
75
|
+
: s.status === "skipped"
|
|
76
|
+
? "⏭"
|
|
77
|
+
: "○";
|
|
78
|
+
const iterInfo = s.type === "pge" && s.iteration
|
|
79
|
+
? ` (iter ${s.iteration})`
|
|
80
|
+
: "";
|
|
81
|
+
const duration = s.durationMs != null
|
|
82
|
+
? ` ${(s.durationMs / 1000).toFixed(1)}s`
|
|
83
|
+
: "";
|
|
84
|
+
const artifacts = s.artifacts
|
|
85
|
+
? ` [${Object.keys(s.artifacts).join(", ")}]`
|
|
86
|
+
: "";
|
|
87
|
+
lines.push(` ${icon} ${name}: ${s.status}${iterInfo}${duration}${artifacts}`);
|
|
88
|
+
}
|
|
89
|
+
if (state.gate) {
|
|
90
|
+
lines.push("");
|
|
91
|
+
lines.push(`Gate: ${state.gate.stageName} — ${state.gate.status}`);
|
|
92
|
+
if (state.gate.prompt) {
|
|
93
|
+
lines.push(` Prompt: ${state.gate.prompt}`);
|
|
94
|
+
}
|
|
95
|
+
if (state.gate.feedback) {
|
|
96
|
+
lines.push(` Feedback: ${state.gate.feedback}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return lines.join("\n");
|
|
100
|
+
}
|
|
101
|
+
function textResult(text) {
|
|
102
|
+
return { content: [{ type: "text", text }] };
|
|
103
|
+
}
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// MCP server
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
export async function startMcpServer() {
|
|
108
|
+
const server = new McpServer({
|
|
109
|
+
name: "cccp",
|
|
110
|
+
version: "0.1.0",
|
|
111
|
+
});
|
|
112
|
+
// --- cccp_runs ---
|
|
113
|
+
server.tool("cccp_runs", "List all pipeline runs (active and completed). Shows run ID, pipeline name, project, status, and any pending gates.", {}, async () => {
|
|
114
|
+
const runs = await discoverRuns(process.cwd());
|
|
115
|
+
if (runs.length === 0) {
|
|
116
|
+
return textResult("No pipeline runs found.");
|
|
117
|
+
}
|
|
118
|
+
return textResult(formatRunList(runs));
|
|
119
|
+
});
|
|
120
|
+
// --- cccp_status ---
|
|
121
|
+
server.tool("cccp_status", "Get detailed status for a pipeline run — stages, iterations, artifacts, and pending gates. If only one run exists, it is selected automatically.", {
|
|
122
|
+
run_id: z
|
|
123
|
+
.string()
|
|
124
|
+
.optional()
|
|
125
|
+
.describe("Run ID prefix (8+ chars). Omit if only one run exists."),
|
|
126
|
+
}, async ({ run_id }) => {
|
|
127
|
+
const result = await resolveRun(run_id);
|
|
128
|
+
if ("error" in result)
|
|
129
|
+
return textResult(result.error);
|
|
130
|
+
return textResult(formatStatus(result.run.state));
|
|
131
|
+
});
|
|
132
|
+
// --- cccp_gate_respond ---
|
|
133
|
+
server.tool("cccp_gate_respond", "Approve or reject a pending human gate. Use cccp_runs or cccp_status first to see pending gates.", {
|
|
134
|
+
run_id: z
|
|
135
|
+
.string()
|
|
136
|
+
.optional()
|
|
137
|
+
.describe("Run ID prefix (8+ chars). Omit if only one run exists."),
|
|
138
|
+
approved: z
|
|
139
|
+
.boolean()
|
|
140
|
+
.describe("Whether to approve (true) or reject (false) the gate."),
|
|
141
|
+
feedback: z
|
|
142
|
+
.string()
|
|
143
|
+
.optional()
|
|
144
|
+
.describe("Optional feedback. On rejection, passed to the generator for retry."),
|
|
145
|
+
}, async ({ run_id, approved, feedback }) => {
|
|
146
|
+
const result = await resolveRun(run_id);
|
|
147
|
+
if ("error" in result)
|
|
148
|
+
return textResult(result.error);
|
|
149
|
+
const { artifactDir, state } = result.run;
|
|
150
|
+
if (!state.gate || state.gate.status !== "pending") {
|
|
151
|
+
return textResult("No pending gate on this run.");
|
|
152
|
+
}
|
|
153
|
+
state.gate.status = approved ? "approved" : "rejected";
|
|
154
|
+
state.gate.feedback = feedback;
|
|
155
|
+
state.gate.respondedAt = new Date().toISOString();
|
|
156
|
+
await saveState(state);
|
|
157
|
+
const action = approved ? "approved" : "rejected";
|
|
158
|
+
return textResult(`Gate "${state.gate.stageName}" ${action}.${feedback ? ` Feedback: ${feedback}` : ""}`);
|
|
159
|
+
});
|
|
160
|
+
// --- cccp_logs ---
|
|
161
|
+
server.tool("cccp_logs", "View recent agent activity logs for a pipeline run.", {
|
|
162
|
+
run_id: z
|
|
163
|
+
.string()
|
|
164
|
+
.optional()
|
|
165
|
+
.describe("Run ID prefix (8+ chars). Omit if only one run exists."),
|
|
166
|
+
lines: z
|
|
167
|
+
.number()
|
|
168
|
+
.optional()
|
|
169
|
+
.default(50)
|
|
170
|
+
.describe("Number of recent log lines (default 50)."),
|
|
171
|
+
}, async ({ run_id, lines }) => {
|
|
172
|
+
const result = await resolveRun(run_id);
|
|
173
|
+
if ("error" in result)
|
|
174
|
+
return textResult(result.error);
|
|
175
|
+
const cccpDir = resolve(result.run.artifactDir, ".cccp");
|
|
176
|
+
let logContent = "No agent logs found.";
|
|
177
|
+
try {
|
|
178
|
+
const files = await readdir(cccpDir);
|
|
179
|
+
const logFiles = files
|
|
180
|
+
.filter((f) => f.endsWith(".stream.jsonl"))
|
|
181
|
+
.sort()
|
|
182
|
+
.reverse();
|
|
183
|
+
if (logFiles.length > 0) {
|
|
184
|
+
const latestLog = resolve(cccpDir, logFiles[0]);
|
|
185
|
+
const raw = await readFile(latestLog, "utf-8");
|
|
186
|
+
const allLines = raw.trim().split("\n");
|
|
187
|
+
const recent = allLines.slice(-lines);
|
|
188
|
+
logContent = `Log: ${logFiles[0]} (${allLines.length} total lines)\n\n${recent.join("\n")}`;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
logContent = `Could not read log files: ${err instanceof Error ? err.message : String(err)}`;
|
|
193
|
+
}
|
|
194
|
+
return textResult(logContent);
|
|
195
|
+
});
|
|
196
|
+
// --- cccp_artifacts ---
|
|
197
|
+
server.tool("cccp_artifacts", "List or read artifacts produced by a pipeline run.", {
|
|
198
|
+
run_id: z
|
|
199
|
+
.string()
|
|
200
|
+
.optional()
|
|
201
|
+
.describe("Run ID prefix (8+ chars). Omit if only one run exists."),
|
|
202
|
+
read: z
|
|
203
|
+
.string()
|
|
204
|
+
.optional()
|
|
205
|
+
.describe("Artifact key or file path to read. Omit to list all artifacts."),
|
|
206
|
+
}, async ({ run_id, read }) => {
|
|
207
|
+
const result = await resolveRun(run_id);
|
|
208
|
+
if ("error" in result)
|
|
209
|
+
return textResult(result.error);
|
|
210
|
+
const { state, artifactDir } = result.run;
|
|
211
|
+
// Collect all artifacts across stages.
|
|
212
|
+
const allArtifacts = [];
|
|
213
|
+
for (const name of state.stageOrder) {
|
|
214
|
+
const stage = state.stages[name];
|
|
215
|
+
if (stage.artifacts) {
|
|
216
|
+
for (const [key, path] of Object.entries(stage.artifacts)) {
|
|
217
|
+
allArtifacts.push({ stage: name, key, path });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (!read) {
|
|
222
|
+
// List mode.
|
|
223
|
+
if (allArtifacts.length === 0) {
|
|
224
|
+
return textResult("No artifacts recorded for this run.");
|
|
225
|
+
}
|
|
226
|
+
const lines = [`Artifacts for run ${state.runId.slice(0, 8)}:`, ""];
|
|
227
|
+
for (const a of allArtifacts) {
|
|
228
|
+
lines.push(` [${a.stage}] ${a.key}: ${a.path}`);
|
|
229
|
+
}
|
|
230
|
+
return textResult(lines.join("\n"));
|
|
231
|
+
}
|
|
232
|
+
// Read mode — find by key or path.
|
|
233
|
+
const match = allArtifacts.find((a) => a.key === read || a.path === read || a.path.endsWith(read));
|
|
234
|
+
if (!match) {
|
|
235
|
+
// Try reading as a direct path relative to artifact dir.
|
|
236
|
+
try {
|
|
237
|
+
const content = await readFile(resolve(artifactDir, read), "utf-8");
|
|
238
|
+
return textResult(content);
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
return textResult(`Artifact "${read}" not found: ${err instanceof Error ? err.message : String(err)}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
const content = await readFile(match.path, "utf-8");
|
|
246
|
+
return textResult(`${match.key} (${match.stage}):\n\n${content}`);
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
return textResult(`Could not read artifact at ${match.path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
// --- Start server ---
|
|
253
|
+
const transport = new StdioServerTransport();
|
|
254
|
+
await server.connect(transport);
|
|
255
|
+
// --- Start gate notifier ---
|
|
256
|
+
const notifier = new GateNotifier({
|
|
257
|
+
server,
|
|
258
|
+
projectDir: process.cwd(),
|
|
259
|
+
});
|
|
260
|
+
notifier.start();
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/mcp/mcp-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,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAa,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGjE,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,KAAK,UAAU,UAAU,CACvB,WAAoB;IAEpB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACjC,kFAAkF;IAClF,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;IAC1C,EAAE,CAAC,MAAM,EAAE,CAAC;IACZ,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;IAE5C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,oDAAoD,EAAE,CAAC;IACzE,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO;YACL,KAAK,EAAE,GAAG,IAAI,CAAC,MAAM,iDAAiD,OAAO,EAAE;SAChF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAChC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CACtC,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,oBAAoB,WAAW,IAAI,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,KAAK,EAAE,qBAAqB,WAAW,aAAa,OAAO,CAAC,MAAM,6BAA6B;SAChG,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7B,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,SAAS,aAAa,CAAC,IAAqB;IAC1C,MAAM,KAAK,GAAa,CAAC,OAAO,CAAC,CAAC;IAElC,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS;YAC3C,CAAC,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE;YACpC,CAAC,CAAC,EAAE,CAAC;QACP,KAAK,CAAC,IAAI,CACR,KAAK,KAAK,KAAK,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,OAAO,MAAM,KAAK,CAAC,MAAM,GAAG,IAAI,KAAK,KAAK,CAAC,SAAS,EAAE,CAC/F,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,KAAoB;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtC,MAAM,KAAK,GAAa;QACtB,aAAa,KAAK,CAAC,QAAQ,SAAS,KAAK,GAAG;QAC5C,YAAY,KAAK,CAAC,OAAO,EAAE;QAC3B,WAAW,KAAK,CAAC,MAAM,EAAE;QACzB,YAAY,KAAK,CAAC,SAAS,EAAE;KAC9B,CAAC;IAEF,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IAE1B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,IAAI,GACR,CAAC,CAAC,MAAM,KAAK,QAAQ;YACnB,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO;gBAC7C,CAAC,CAAC,GAAG;gBACL,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa;oBAC1B,CAAC,CAAC,GAAG;oBACL,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS;wBACtB,CAAC,CAAC,GAAG;wBACL,CAAC,CAAC,GAAG,CAAC;QAChB,MAAM,QAAQ,GACZ,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,SAAS;YAC7B,CAAC,CAAC,UAAU,CAAC,CAAC,SAAS,GAAG;YAC1B,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,QAAQ,GACZ,CAAC,CAAC,UAAU,IAAI,IAAI;YAClB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YACzC,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS;YAC3B,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC7C,CAAC,CAAC,EAAE,CAAC;QAEP,KAAK,CAAC,IAAI,CACR,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,CAAC,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,EAAE,CACnE,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,oBAAoB;IACpB,MAAM,CAAC,IAAI,CACT,WAAW,EACX,qHAAqH,EACrH,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAE/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,UAAU,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,CAAC,CACF,CAAC;IAEF,sBAAsB;IACtB,MAAM,CAAC,IAAI,CACT,aAAa,EACb,kJAAkJ,EAClJ;QACE,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;KACtE,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACnB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEvD,OAAO,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACpD,CAAC,CACF,CAAC;IAEF,4BAA4B;IAC5B,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,kGAAkG,EAClG;QACE,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;QACrE,QAAQ,EAAE,CAAC;aACR,OAAO,EAAE;aACT,QAAQ,CAAC,uDAAuD,CAAC;QACpE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,qEAAqE,CAAC;KACnF,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;QACvC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEvD,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACnD,OAAO,UAAU,CAAC,8BAA8B,CAAC,CAAC;QACpD,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAClD,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;QAEvB,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QAClD,OAAO,UAAU,CACf,SAAS,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACvF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,oBAAoB;IACpB,MAAM,CAAC,IAAI,CACT,WAAW,EACX,qDAAqD,EACrD;QACE,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;QACrE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,0CAA0C,CAAC;KACxD,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;QAC1B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEvD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACzD,IAAI,UAAU,GAAG,sBAAsB,CAAC;QAExC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,QAAQ,GAAG,KAAK;iBACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;iBAC1C,IAAI,EAAE;iBACN,OAAO,EAAE,CAAC;YAEb,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;gBAChD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBAC/C,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;gBACtC,UAAU,GAAG,QAAQ,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,MAAM,oBAAoB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9F,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,UAAU,GAAG,6BAA6B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/F,CAAC;QAED,OAAO,UAAU,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC,CACF,CAAC;IAEF,yBAAyB;IACzB,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,oDAAoD,EACpD;QACE,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;QACrE,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,gEAAgE,CAAC;KAC9E,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;QACzB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEvD,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC;QAE1C,uCAAuC;QACvC,MAAM,YAAY,GAAwD,EAAE,CAAC;QAC7E,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACpB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC1D,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,aAAa;YACb,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,UAAU,CAAC,qCAAqC,CAAC,CAAC;YAC3D,CAAC;YAED,MAAM,KAAK,GAAG,CAAC,qBAAqB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACpE,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;gBAC7B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;QAED,mCAAmC;QACnC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAClE,CAAC;QAEF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,yDAAyD;YACzD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;gBACpE,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,UAAU,CAAC,aAAa,IAAI,gBAAgB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACzG,CAAC;QACH,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACpD,OAAO,UAAU,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,KAAK,SAAS,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,UAAU,CAAC,8BAA8B,KAAK,CAAC,IAAI,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrH,CAAC;IACH,CAAC,CACF,CAAC;IAEF,uBAAuB;IACvB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC;QAChC,MAAM;QACN,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE;KAC1B,CAAC,CAAC;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC"}
|
package/dist/pge.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PgeStage, PgeResult, RunContext, PipelineState } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Execute a full Plan-Generate-Evaluate cycle for a PGE stage.
|
|
4
|
+
*
|
|
5
|
+
* 0. Dispatch planner agent → task-plan.md
|
|
6
|
+
* 1. Dispatch evaluator agent (contract mode) → contract.md
|
|
7
|
+
* 2. Dispatch generator agent → deliverable
|
|
8
|
+
* 3. Dispatch evaluator agent (evaluation mode) → evaluation-N.md
|
|
9
|
+
* 4. Parse evaluation (regex on ### Overall: PASS/FAIL)
|
|
10
|
+
* 5. Route: PASS → done, FAIL + iters left → retry, FAIL + max → escalate
|
|
11
|
+
*/
|
|
12
|
+
export declare function runPgeCycle(stage: PgeStage, ctx: RunContext, state: PipelineState, onProgress?: (eventType?: string, eventData?: Record<string, unknown>) => Promise<void>): Promise<PgeResult>;
|
package/dist/pge.js
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { mkdir, readFile } from "node:fs/promises";
|
|
3
|
+
import { activityBus } from "./activity-bus.js";
|
|
4
|
+
import { DefaultAgentDispatcher } from "./dispatcher.js";
|
|
5
|
+
import { parseEvaluation } from "./evaluator.js";
|
|
6
|
+
import { AgentCrashError, MissingOutputError } from "./errors.js";
|
|
7
|
+
import { ConsoleLogger } from "./logger.js";
|
|
8
|
+
import { interpolate, resolveTaskBody, buildTaskContext, writeSystemPromptFile, } from "./prompt.js";
|
|
9
|
+
import { mergeInputs, resolveAndLoad } from "./stage-helpers.js";
|
|
10
|
+
import { updatePgeProgress, setStageArtifact } from "./state.js";
|
|
11
|
+
function getLogger(ctx) {
|
|
12
|
+
return ctx.logger ?? new ConsoleLogger();
|
|
13
|
+
}
|
|
14
|
+
function getDispatcher(ctx) {
|
|
15
|
+
return ctx.dispatcher ?? new DefaultAgentDispatcher();
|
|
16
|
+
}
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// PGE cycle
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
/**
|
|
21
|
+
* Execute a full Plan-Generate-Evaluate cycle for a PGE stage.
|
|
22
|
+
*
|
|
23
|
+
* 0. Dispatch planner agent → task-plan.md
|
|
24
|
+
* 1. Dispatch evaluator agent (contract mode) → contract.md
|
|
25
|
+
* 2. Dispatch generator agent → deliverable
|
|
26
|
+
* 3. Dispatch evaluator agent (evaluation mode) → evaluation-N.md
|
|
27
|
+
* 4. Parse evaluation (regex on ### Overall: PASS/FAIL)
|
|
28
|
+
* 5. Route: PASS → done, FAIL + iters left → retry, FAIL + max → escalate
|
|
29
|
+
*/
|
|
30
|
+
export async function runPgeCycle(stage, ctx, state, onProgress) {
|
|
31
|
+
const start = Date.now();
|
|
32
|
+
const vars = { ...ctx.variables, ...(stage.variables ?? {}) };
|
|
33
|
+
const maxIter = stage.contract.max_iterations;
|
|
34
|
+
// Resolve paths for contract, deliverable, task plan, and evaluations
|
|
35
|
+
const deliverable = interpolate(stage.contract.deliverable, vars);
|
|
36
|
+
const deliverablePath = resolve(ctx.projectDir, deliverable);
|
|
37
|
+
const stageDir = resolve(ctx.artifactDir, stage.name);
|
|
38
|
+
const contractPath = resolve(stageDir, "contract.md");
|
|
39
|
+
const taskPlanPath = resolve(stageDir, "task-plan.md");
|
|
40
|
+
await mkdir(stageDir, { recursive: true });
|
|
41
|
+
// --- Dry-run: show what would happen ---
|
|
42
|
+
if (ctx.dryRun) {
|
|
43
|
+
const logger = getLogger(ctx);
|
|
44
|
+
logger.log("\n[dry-run] PGE Stage:", stage.name);
|
|
45
|
+
logger.log(" task plan: ", taskPlanPath);
|
|
46
|
+
logger.log(" contract: ", contractPath);
|
|
47
|
+
logger.log(" deliverable: ", deliverablePath);
|
|
48
|
+
logger.log(" planner: ", stage.planner.agent);
|
|
49
|
+
if (stage.planner.operation) {
|
|
50
|
+
logger.log(" plan operation:", stage.planner.operation);
|
|
51
|
+
}
|
|
52
|
+
if (stage.plan) {
|
|
53
|
+
logger.log(" plan file: ", interpolate(stage.plan, vars));
|
|
54
|
+
}
|
|
55
|
+
logger.log(" generator: ", stage.generator.agent);
|
|
56
|
+
if (stage.generator.operation) {
|
|
57
|
+
logger.log(" gen operation:", stage.generator.operation);
|
|
58
|
+
}
|
|
59
|
+
logger.log(" evaluator: ", stage.evaluator.agent);
|
|
60
|
+
if (stage.evaluator.operation) {
|
|
61
|
+
logger.log(" eval operation:", stage.evaluator.operation);
|
|
62
|
+
}
|
|
63
|
+
logger.log(" max iters: ", maxIter);
|
|
64
|
+
logger.log(" on_fail: ", stage.on_fail ?? "stop");
|
|
65
|
+
if (stage.contract.guidance) {
|
|
66
|
+
logger.log(" guidance: (present)");
|
|
67
|
+
}
|
|
68
|
+
if (stage.contract.template) {
|
|
69
|
+
logger.log(" template: ", stage.contract.template);
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
outcome: "pass",
|
|
73
|
+
iterations: 0,
|
|
74
|
+
maxIterations: maxIter,
|
|
75
|
+
contractPath,
|
|
76
|
+
taskPlanPath,
|
|
77
|
+
durationMs: 0,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// --- Resolve task body (file or inline) ---
|
|
81
|
+
const taskBody = await resolveTaskBody(stage, vars, `Generate deliverable for: ${stage.name}`);
|
|
82
|
+
// --- Resolve all agents via search paths ---
|
|
83
|
+
const plannerAgent = await resolveAndLoad(stage.planner, ctx, stage.mcp_profile);
|
|
84
|
+
const genAgent = await resolveAndLoad(stage.generator, ctx, stage.mcp_profile);
|
|
85
|
+
const evalAgent = await resolveAndLoad(stage.evaluator, ctx, stage.mcp_profile);
|
|
86
|
+
// --- Step 0: Dispatch planner ---
|
|
87
|
+
getLogger(ctx).log(` dispatching planner: ${stage.planner.agent}`);
|
|
88
|
+
await onProgress?.("pge_planner_start", {
|
|
89
|
+
agent: stage.planner.agent,
|
|
90
|
+
});
|
|
91
|
+
const plannerInputs = mergeInputs(stage.inputs, stage.planner.inputs, vars);
|
|
92
|
+
const planFile = stage.plan ? interpolate(stage.plan, vars) : undefined;
|
|
93
|
+
const plannerPrompt = buildTaskContext({
|
|
94
|
+
task: taskBody,
|
|
95
|
+
planFile,
|
|
96
|
+
inputs: plannerInputs.length > 0 ? plannerInputs : undefined,
|
|
97
|
+
output: taskPlanPath,
|
|
98
|
+
guidance: stage.contract.guidance,
|
|
99
|
+
});
|
|
100
|
+
const plannerSystemFile = await writeSystemPromptFile(plannerAgent.markdown, ctx.tempTracker);
|
|
101
|
+
const plannerResult = await getDispatcher(ctx).dispatch({
|
|
102
|
+
userPrompt: plannerPrompt,
|
|
103
|
+
systemPromptFile: plannerSystemFile,
|
|
104
|
+
mcpConfigFile: plannerAgent.mcpFile,
|
|
105
|
+
expectedOutput: taskPlanPath,
|
|
106
|
+
cwd: ctx.projectDir,
|
|
107
|
+
allowedTools: stage.planner.allowed_tools,
|
|
108
|
+
claudeConfigDir: ctx.projectConfig?.claude_config_dir,
|
|
109
|
+
permissionMode: ctx.projectConfig?.permission_mode,
|
|
110
|
+
agentName: `${stage.name}-planner`,
|
|
111
|
+
streamLogDir: resolve(ctx.artifactDir, ".cccp"),
|
|
112
|
+
onActivity: (activity) => activityBus.emit("activity", activity),
|
|
113
|
+
quiet: ctx.quiet,
|
|
114
|
+
});
|
|
115
|
+
if (plannerResult.exitCode !== 0) {
|
|
116
|
+
throw new AgentCrashError(stage.planner.agent, plannerResult.exitCode);
|
|
117
|
+
}
|
|
118
|
+
if (!plannerResult.outputExists) {
|
|
119
|
+
throw new MissingOutputError(stage.planner.agent, taskPlanPath);
|
|
120
|
+
}
|
|
121
|
+
setStageArtifact(state, stage.name, "task-plan", taskPlanPath);
|
|
122
|
+
updatePgeProgress(state, stage.name, 0, "planner_dispatched");
|
|
123
|
+
getLogger(ctx).log(` task plan written: ${taskPlanPath}`);
|
|
124
|
+
await onProgress?.("pge_planner_done", {
|
|
125
|
+
agent: stage.planner.agent, taskPlanPath,
|
|
126
|
+
});
|
|
127
|
+
// --- Step 1: Dispatch evaluator for contract writing ---
|
|
128
|
+
getLogger(ctx).log(` dispatching contract writer: ${stage.evaluator.agent}`);
|
|
129
|
+
await onProgress?.("pge_contract_start", {
|
|
130
|
+
agent: stage.evaluator.agent,
|
|
131
|
+
});
|
|
132
|
+
const contractInputs = mergeInputs(stage.inputs, stage.evaluator.inputs, vars, [taskPlanPath]);
|
|
133
|
+
const templatePath = stage.contract.template
|
|
134
|
+
? resolve(ctx.projectDir, interpolate(stage.contract.template, vars))
|
|
135
|
+
: undefined;
|
|
136
|
+
const contractPrompt = buildTaskContext({
|
|
137
|
+
task: `Write the acceptance criteria contract for: ${stage.name}`,
|
|
138
|
+
inputs: contractInputs.length > 0 ? contractInputs : undefined,
|
|
139
|
+
output: contractPath,
|
|
140
|
+
contractTemplate: templatePath,
|
|
141
|
+
guidance: stage.contract.guidance,
|
|
142
|
+
deliverableInfo: `The generator will produce: ${deliverable}\nWrite your contract criteria to verify this deliverable.\nMax iterations: ${maxIter}`,
|
|
143
|
+
});
|
|
144
|
+
const contractSystemFile = await writeSystemPromptFile(evalAgent.markdown, ctx.tempTracker);
|
|
145
|
+
const contractResult = await getDispatcher(ctx).dispatch({
|
|
146
|
+
userPrompt: contractPrompt,
|
|
147
|
+
systemPromptFile: contractSystemFile,
|
|
148
|
+
mcpConfigFile: evalAgent.mcpFile,
|
|
149
|
+
expectedOutput: contractPath,
|
|
150
|
+
cwd: ctx.projectDir,
|
|
151
|
+
allowedTools: stage.evaluator.allowed_tools,
|
|
152
|
+
claudeConfigDir: ctx.projectConfig?.claude_config_dir,
|
|
153
|
+
permissionMode: ctx.projectConfig?.permission_mode,
|
|
154
|
+
agentName: `${stage.name}-contract`,
|
|
155
|
+
streamLogDir: resolve(ctx.artifactDir, ".cccp"),
|
|
156
|
+
onActivity: (activity) => activityBus.emit("activity", activity),
|
|
157
|
+
quiet: ctx.quiet,
|
|
158
|
+
});
|
|
159
|
+
if (contractResult.exitCode !== 0) {
|
|
160
|
+
throw new AgentCrashError(stage.evaluator.agent, contractResult.exitCode);
|
|
161
|
+
}
|
|
162
|
+
if (!contractResult.outputExists) {
|
|
163
|
+
throw new MissingOutputError(stage.evaluator.agent, contractPath);
|
|
164
|
+
}
|
|
165
|
+
setStageArtifact(state, stage.name, "contract", contractPath);
|
|
166
|
+
updatePgeProgress(state, stage.name, 0, "contract_dispatched");
|
|
167
|
+
getLogger(ctx).log(` contract written: ${contractPath}`);
|
|
168
|
+
let contractContent = "";
|
|
169
|
+
try {
|
|
170
|
+
contractContent = await readFile(contractPath, "utf-8");
|
|
171
|
+
}
|
|
172
|
+
catch { /* ignore */ }
|
|
173
|
+
await onProgress?.("pge_contract_done", {
|
|
174
|
+
agent: stage.evaluator.agent, contractPath, contractContent,
|
|
175
|
+
});
|
|
176
|
+
// Emit pge_start to signal the GE loop is beginning.
|
|
177
|
+
await onProgress?.("pge_start", {
|
|
178
|
+
planner: stage.planner.agent,
|
|
179
|
+
generator: stage.generator.agent,
|
|
180
|
+
evaluator: stage.evaluator.agent,
|
|
181
|
+
deliverable,
|
|
182
|
+
maxIterations: maxIter,
|
|
183
|
+
contractPath,
|
|
184
|
+
taskPlanPath,
|
|
185
|
+
contractContent,
|
|
186
|
+
});
|
|
187
|
+
// --- GE Iteration loop ---
|
|
188
|
+
let lastEvalPath;
|
|
189
|
+
for (let iter = 1; iter <= maxIter; iter++) {
|
|
190
|
+
getLogger(ctx).log(` iteration ${iter}/${maxIter}`);
|
|
191
|
+
const evalPath = resolve(stageDir, `evaluation-${iter}.md`);
|
|
192
|
+
// --- Step 2: Dispatch generator ---
|
|
193
|
+
const genSystemFile = await writeSystemPromptFile(genAgent.markdown, ctx.tempTracker);
|
|
194
|
+
const genInputs = mergeInputs(stage.inputs, stage.generator.inputs, vars, [taskPlanPath]);
|
|
195
|
+
const genPrompt = buildTaskContext({
|
|
196
|
+
task: taskBody,
|
|
197
|
+
contractPath,
|
|
198
|
+
inputs: genInputs.length > 0 ? genInputs : undefined,
|
|
199
|
+
output: deliverable,
|
|
200
|
+
previousEvaluation: lastEvalPath,
|
|
201
|
+
iteration: iter,
|
|
202
|
+
maxIterations: maxIter,
|
|
203
|
+
});
|
|
204
|
+
getLogger(ctx).log(` dispatching generator: ${stage.generator.agent}`);
|
|
205
|
+
await onProgress?.("pge_generator_start", {
|
|
206
|
+
iteration: iter, maxIterations: maxIter, agent: stage.generator.agent,
|
|
207
|
+
});
|
|
208
|
+
const genResult = await getDispatcher(ctx).dispatch({
|
|
209
|
+
userPrompt: genPrompt,
|
|
210
|
+
systemPromptFile: genSystemFile,
|
|
211
|
+
mcpConfigFile: genAgent.mcpFile,
|
|
212
|
+
expectedOutput: deliverablePath,
|
|
213
|
+
cwd: ctx.projectDir,
|
|
214
|
+
allowedTools: stage.generator.allowed_tools,
|
|
215
|
+
claudeConfigDir: ctx.projectConfig?.claude_config_dir,
|
|
216
|
+
permissionMode: ctx.projectConfig?.permission_mode,
|
|
217
|
+
agentName: `${stage.name}-generator`,
|
|
218
|
+
streamLogDir: resolve(ctx.artifactDir, ".cccp"),
|
|
219
|
+
onActivity: (activity) => activityBus.emit("activity", activity),
|
|
220
|
+
quiet: ctx.quiet,
|
|
221
|
+
});
|
|
222
|
+
if (genResult.exitCode !== 0) {
|
|
223
|
+
throw new AgentCrashError(stage.generator.agent, genResult.exitCode);
|
|
224
|
+
}
|
|
225
|
+
if (!genResult.outputExists) {
|
|
226
|
+
throw new MissingOutputError(stage.generator.agent, deliverable);
|
|
227
|
+
}
|
|
228
|
+
// Persist generator completion.
|
|
229
|
+
updatePgeProgress(state, stage.name, iter, "generator_dispatched");
|
|
230
|
+
setStageArtifact(state, stage.name, "deliverable", deliverablePath);
|
|
231
|
+
await onProgress?.("pge_generator_done", {
|
|
232
|
+
iteration: iter, maxIterations: maxIter,
|
|
233
|
+
agent: stage.generator.agent, deliverablePath,
|
|
234
|
+
});
|
|
235
|
+
// --- Step 3: Dispatch evaluator ---
|
|
236
|
+
const evalSystemFile = await writeSystemPromptFile(evalAgent.markdown, ctx.tempTracker);
|
|
237
|
+
const evalInputs = mergeInputs(stage.inputs, stage.evaluator.inputs, vars, [deliverable]);
|
|
238
|
+
const evalPrompt = buildTaskContext({
|
|
239
|
+
task: `Evaluate the deliverable against the contract for: ${stage.name}`,
|
|
240
|
+
contractPath,
|
|
241
|
+
inputs: evalInputs.length > 0 ? evalInputs : undefined,
|
|
242
|
+
output: evalPath,
|
|
243
|
+
iteration: iter,
|
|
244
|
+
maxIterations: maxIter,
|
|
245
|
+
evaluatorFormat: true,
|
|
246
|
+
});
|
|
247
|
+
getLogger(ctx).log(` dispatching evaluator: ${stage.evaluator.agent}`);
|
|
248
|
+
await onProgress?.("pge_evaluator_start", {
|
|
249
|
+
iteration: iter, maxIterations: maxIter, agent: stage.evaluator.agent,
|
|
250
|
+
});
|
|
251
|
+
const evalResult = await getDispatcher(ctx).dispatch({
|
|
252
|
+
userPrompt: evalPrompt,
|
|
253
|
+
systemPromptFile: evalSystemFile,
|
|
254
|
+
mcpConfigFile: evalAgent.mcpFile,
|
|
255
|
+
expectedOutput: evalPath,
|
|
256
|
+
cwd: ctx.projectDir,
|
|
257
|
+
allowedTools: stage.evaluator.allowed_tools,
|
|
258
|
+
claudeConfigDir: ctx.projectConfig?.claude_config_dir,
|
|
259
|
+
permissionMode: ctx.projectConfig?.permission_mode,
|
|
260
|
+
agentName: `${stage.name}-evaluator`,
|
|
261
|
+
streamLogDir: resolve(ctx.artifactDir, ".cccp"),
|
|
262
|
+
onActivity: (activity) => activityBus.emit("activity", activity),
|
|
263
|
+
quiet: ctx.quiet,
|
|
264
|
+
});
|
|
265
|
+
if (evalResult.exitCode !== 0) {
|
|
266
|
+
throw new AgentCrashError(stage.evaluator.agent, evalResult.exitCode);
|
|
267
|
+
}
|
|
268
|
+
if (!evalResult.outputExists) {
|
|
269
|
+
throw new MissingOutputError(stage.evaluator.agent, evalPath);
|
|
270
|
+
}
|
|
271
|
+
// Persist evaluator completion.
|
|
272
|
+
updatePgeProgress(state, stage.name, iter, "evaluator_dispatched");
|
|
273
|
+
setStageArtifact(state, stage.name, `evaluation-${iter}`, evalPath);
|
|
274
|
+
await onProgress?.("pge_evaluator_done", {
|
|
275
|
+
iteration: iter, maxIterations: maxIter,
|
|
276
|
+
agent: stage.evaluator.agent, evaluationPath: evalPath,
|
|
277
|
+
});
|
|
278
|
+
// --- Step 4: Parse evaluation ---
|
|
279
|
+
const evaluation = await parseEvaluation(evalPath);
|
|
280
|
+
if (evaluation.outcome === "parse_error") {
|
|
281
|
+
getLogger(ctx).error(` evaluation parse error: ${evaluation.error}`);
|
|
282
|
+
await onProgress?.("pge_evaluation", {
|
|
283
|
+
iteration: iter, maxIterations: maxIter,
|
|
284
|
+
outcome: "parse_error", error: evaluation.error,
|
|
285
|
+
});
|
|
286
|
+
return {
|
|
287
|
+
outcome: "error",
|
|
288
|
+
iterations: iter,
|
|
289
|
+
maxIterations: maxIter,
|
|
290
|
+
evaluationPath: evalPath,
|
|
291
|
+
contractPath,
|
|
292
|
+
taskPlanPath,
|
|
293
|
+
durationMs: Date.now() - start,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
// --- Step 5: Route ---
|
|
297
|
+
updatePgeProgress(state, stage.name, iter, "routed");
|
|
298
|
+
if (evaluation.outcome === "pass") {
|
|
299
|
+
getLogger(ctx).log(` evaluation: PASS`);
|
|
300
|
+
await onProgress?.("pge_evaluation", {
|
|
301
|
+
iteration: iter, maxIterations: maxIter,
|
|
302
|
+
outcome: "pass",
|
|
303
|
+
evaluationContent: evaluation.content ?? "",
|
|
304
|
+
evaluationPath: evalPath,
|
|
305
|
+
rawLine: evaluation.rawLine,
|
|
306
|
+
});
|
|
307
|
+
return {
|
|
308
|
+
outcome: "pass",
|
|
309
|
+
iterations: iter,
|
|
310
|
+
maxIterations: maxIter,
|
|
311
|
+
evaluationPath: evalPath,
|
|
312
|
+
contractPath,
|
|
313
|
+
taskPlanPath,
|
|
314
|
+
durationMs: Date.now() - start,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
// FAIL — check if retries remain
|
|
318
|
+
getLogger(ctx).log(` evaluation: FAIL`);
|
|
319
|
+
lastEvalPath = evalPath;
|
|
320
|
+
if (iter === maxIter) {
|
|
321
|
+
getLogger(ctx).log(` max iterations reached — escalating (${stage.on_fail ?? "stop"})`);
|
|
322
|
+
await onProgress?.("pge_evaluation", {
|
|
323
|
+
iteration: iter, maxIterations: maxIter,
|
|
324
|
+
outcome: "fail",
|
|
325
|
+
evaluationContent: evaluation.content ?? "",
|
|
326
|
+
evaluationPath: evalPath,
|
|
327
|
+
rawLine: evaluation.rawLine,
|
|
328
|
+
willRetry: false,
|
|
329
|
+
escalation: stage.on_fail ?? "stop",
|
|
330
|
+
});
|
|
331
|
+
return {
|
|
332
|
+
outcome: "fail",
|
|
333
|
+
iterations: iter,
|
|
334
|
+
maxIterations: maxIter,
|
|
335
|
+
evaluationPath: evalPath,
|
|
336
|
+
contractPath,
|
|
337
|
+
taskPlanPath,
|
|
338
|
+
durationMs: Date.now() - start,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
getLogger(ctx).log(` retrying...`);
|
|
342
|
+
await onProgress?.("pge_evaluation", {
|
|
343
|
+
iteration: iter, maxIterations: maxIter,
|
|
344
|
+
outcome: "fail",
|
|
345
|
+
evaluationContent: evaluation.content ?? "",
|
|
346
|
+
evaluationPath: evalPath,
|
|
347
|
+
rawLine: evaluation.rawLine,
|
|
348
|
+
willRetry: true,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
// Should never reach here, but TypeScript needs it
|
|
352
|
+
return {
|
|
353
|
+
outcome: "error",
|
|
354
|
+
iterations: maxIter,
|
|
355
|
+
maxIterations: maxIter,
|
|
356
|
+
contractPath,
|
|
357
|
+
taskPlanPath,
|
|
358
|
+
durationMs: Date.now() - start,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=pge.js.map
|