@loops-adk/core 0.1.1 → 0.2.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/README.md +105 -13
- package/assets/logo.png +0 -0
- package/dist/{agent-sdk-RF5VJZAT.js → agent-sdk-4QJDWM7N.js} +3 -3
- package/dist/{agent-sdk-RF5VJZAT.js.map → agent-sdk-4QJDWM7N.js.map} +1 -1
- package/dist/api.d.ts +108 -3
- package/dist/api.js +26 -10
- package/dist/api.js.map +1 -1
- package/dist/{chunk-XC46B4FD.js → chunk-MA6NDQMO.js} +2 -2
- package/dist/chunk-MA6NDQMO.js.map +1 -0
- package/dist/{chunk-6BDWTFOS.js → chunk-WM5QVHM2.js} +592 -35
- package/dist/chunk-WM5QVHM2.js.map +1 -0
- package/dist/{claude-cli-U7WEVAOL.js → claude-cli-75AOQUKG.js} +3 -3
- package/dist/{claude-cli-U7WEVAOL.js.map → claude-cli-75AOQUKG.js.map} +1 -1
- package/dist/{codex-6I5UZ2HM.js → codex-LYZF52WL.js} +25 -13
- package/dist/codex-LYZF52WL.js.map +1 -0
- package/dist/env/command.d.ts +1 -1
- package/dist/env/docker.d.ts +1 -1
- package/dist/env/sst.d.ts +1 -1
- package/dist/index.js +140 -11
- package/dist/index.js.map +1 -1
- package/dist/{types-B4wGVpqo.d.ts → types-Cv_3ymr9.d.ts} +118 -37
- package/package.json +10 -1
- package/skills/author-loop/SKILL.md +14 -5
- package/skills/design-agent-team/SKILL.md +108 -0
- package/skills/supervise-loop-run/SKILL.md +64 -0
- package/dist/chunk-6BDWTFOS.js.map +0 -1
- package/dist/chunk-XC46B4FD.js.map +0 -1
- package/dist/codex-6I5UZ2HM.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { redactSecrets } from './chunk-JFTXJ7I2.js';
|
|
2
|
-
import { isEngine } from './chunk-
|
|
2
|
+
import { isEngine } from './chunk-MA6NDQMO.js';
|
|
3
3
|
import { isLimitError, waitMsFor } from './chunk-Y2SD7GBL.js';
|
|
4
4
|
import { LoopError } from './chunk-I3STY7U6.js';
|
|
5
5
|
import { readFileSync, mkdtempSync, existsSync, writeFileSync, appendFileSync, readdirSync, mkdirSync, rmSync } from 'fs';
|
|
@@ -35,6 +35,19 @@ function describeConditions(input) {
|
|
|
35
35
|
return [condLabel(input)];
|
|
36
36
|
}
|
|
37
37
|
var count = (n, w) => `${n} ${w}${n === 1 ? "" : "s"}`;
|
|
38
|
+
function renderContract(value) {
|
|
39
|
+
const c = value;
|
|
40
|
+
if (!c || typeof c !== "object") return void 0;
|
|
41
|
+
const bits = [];
|
|
42
|
+
if (c.tier) bits.push(`tier ${c.tier}`);
|
|
43
|
+
if (c.outputs?.length) bits.push(`outputs ${c.outputs.join(", ")}`);
|
|
44
|
+
if (c.capabilities?.length) bits.push(`capabilities ${c.capabilities.join(", ")}`);
|
|
45
|
+
if (c.requiresSkills?.length) bits.push(`requires ${c.requiresSkills.join(", ")}`);
|
|
46
|
+
if (c.usesSkills?.length) bits.push(`uses ${c.usesSkills.join(", ")}`);
|
|
47
|
+
if (c.humanGates?.length) bits.push(`gates ${c.humanGates.join(", ")}`);
|
|
48
|
+
if (c.failureModes?.length) bits.push(`failure modes ${c.failureModes.join(", ")}`);
|
|
49
|
+
return bits.join("; ");
|
|
50
|
+
}
|
|
38
51
|
function renderPlan(meta, indent = "") {
|
|
39
52
|
if (!meta) return [`${indent}(a runnable job, shape not introspectable)`];
|
|
40
53
|
const nm = meta.name ? ` "${meta.name}"` : "";
|
|
@@ -69,6 +82,10 @@ function renderPlan(meta, indent = "") {
|
|
|
69
82
|
}
|
|
70
83
|
case "agent":
|
|
71
84
|
out.push(`${indent}agent${nm}${meta.ground ? " (grounded)" : ""}`);
|
|
85
|
+
{
|
|
86
|
+
const contract = renderContract(meta.contract);
|
|
87
|
+
if (contract) out.push(`${indent} contract: ${contract}`);
|
|
88
|
+
}
|
|
72
89
|
break;
|
|
73
90
|
case "fn":
|
|
74
91
|
out.push(`${indent}fn${nm}`);
|
|
@@ -129,12 +146,59 @@ function defineSkill(skill) {
|
|
|
129
146
|
if (!skill.instructions?.trim()) throw new Error(`defineSkill "${skill.name}": empty instructions`);
|
|
130
147
|
return skill;
|
|
131
148
|
}
|
|
149
|
+
function skillRefName(ref) {
|
|
150
|
+
return typeof ref === "string" ? ref : ref.name;
|
|
151
|
+
}
|
|
152
|
+
function validateName(value, label) {
|
|
153
|
+
if (!value?.trim()) throw new Error(`${label}: \`name\` is required`);
|
|
154
|
+
}
|
|
155
|
+
function validateSkillRef(ref, label) {
|
|
156
|
+
if (typeof ref === "string") {
|
|
157
|
+
if (!ref.trim()) throw new Error(`${label}: empty skill name`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
defineSkill(ref);
|
|
161
|
+
}
|
|
132
162
|
function defineAgent(def) {
|
|
133
163
|
if (!def.name) throw new Error("defineAgent: `name` is required");
|
|
134
164
|
if (!def.system?.trim()) throw new Error(`defineAgent "${def.name}": empty system prompt`);
|
|
135
165
|
def.skills?.forEach((s) => defineSkill(s));
|
|
166
|
+
def.requiresSkills?.forEach(
|
|
167
|
+
(s) => validateSkillRef(s, `defineAgent "${def.name}" requiresSkills`)
|
|
168
|
+
);
|
|
169
|
+
def.usesSkills?.forEach(
|
|
170
|
+
(s) => validateSkillRef(s, `defineAgent "${def.name}" usesSkills`)
|
|
171
|
+
);
|
|
172
|
+
def.outputs?.forEach(
|
|
173
|
+
(o) => validateName(o.name, `defineAgent "${def.name}" outputs`)
|
|
174
|
+
);
|
|
175
|
+
def.humanGates?.forEach(
|
|
176
|
+
(g) => validateName(g.name, `defineAgent "${def.name}" humanGates`)
|
|
177
|
+
);
|
|
178
|
+
def.failureModes?.forEach((f) => {
|
|
179
|
+
if (!f.mode?.trim())
|
|
180
|
+
throw new Error(`defineAgent "${def.name}" failureModes: \`mode\` is required`);
|
|
181
|
+
if (!f.recovery?.trim())
|
|
182
|
+
throw new Error(`defineAgent "${def.name}" failureModes "${f.mode}": \`recovery\` is required`);
|
|
183
|
+
});
|
|
136
184
|
return def;
|
|
137
185
|
}
|
|
186
|
+
function agentContract(agent) {
|
|
187
|
+
if (!agent) return void 0;
|
|
188
|
+
const summary = {};
|
|
189
|
+
if (agent.tier) summary.tier = agent.tier;
|
|
190
|
+
if (agent.capabilities?.length) summary.capabilities = [...agent.capabilities];
|
|
191
|
+
if (agent.outputs?.length) summary.outputs = agent.outputs.map((o) => o.name);
|
|
192
|
+
if (agent.requiresSkills?.length)
|
|
193
|
+
summary.requiresSkills = agent.requiresSkills.map(skillRefName);
|
|
194
|
+
if (agent.usesSkills?.length)
|
|
195
|
+
summary.usesSkills = agent.usesSkills.map(skillRefName);
|
|
196
|
+
if (agent.humanGates?.length)
|
|
197
|
+
summary.humanGates = agent.humanGates.map((g) => g.name);
|
|
198
|
+
if (agent.failureModes?.length)
|
|
199
|
+
summary.failureModes = agent.failureModes.map((f) => f.mode);
|
|
200
|
+
return Object.keys(summary).length ? summary : void 0;
|
|
201
|
+
}
|
|
138
202
|
function resolveSystem(agent) {
|
|
139
203
|
if (!agent.skills?.length) return agent.system;
|
|
140
204
|
const methods = agent.skills.map((s) => `### ${s.name}
|
|
@@ -928,6 +992,15 @@ function resetLedger(workspace) {
|
|
|
928
992
|
reset(ledgerPath(workspace));
|
|
929
993
|
}
|
|
930
994
|
|
|
995
|
+
// src/core/text.ts
|
|
996
|
+
function oneLine(text) {
|
|
997
|
+
return text.replace(/\s+/g, " ").trim();
|
|
998
|
+
}
|
|
999
|
+
function truncate(s, max) {
|
|
1000
|
+
return s.length > max ? `${s.slice(0, max).trimEnd()}
|
|
1001
|
+
\u2026` : s;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
931
1004
|
// src/core/consolidate.ts
|
|
932
1005
|
var CONSOLIDATE_SYSTEM = "You maintain a project's CONSOLIDATED LEDGER from its commit history \u2014 the bounded coarse memory a fresh context reads to continue safely. Capture the current state and the open threads, and PRESERVE every binding decision, convention and constraint with its exact values verbatim (downstream work must honour them, so dropping or generalising even one is a failure). Tight markdown; MERGE new commits into the prior ledger, deduplicate, omit only narrative \u2014 never omit a decision.";
|
|
933
1006
|
function digest(body, n = 280) {
|
|
@@ -966,11 +1039,6 @@ Output the updated consolidated ledger.`,
|
|
|
966
1039
|
return result.text.trim();
|
|
967
1040
|
}
|
|
968
1041
|
var COMPACT_SYSTEM = "You write the HANDOFF a future agent reads if it lost ALL memory of this work. Include EVERYTHING it needs to continue safely, as structured markdown: ## Why (the problem and the root cause), ## What (exactly what changed, and where \u2014 names, paths, signatures), ## Alternatives (what was ruled out and why), ## Constraints (the invariants and limits that shaped it), ## Next (what is left or to watch). Preserve every decision and specific value verbatim. Completeness matters more than brevity \u2014 drop only literal repetition and play-by-play narration, never a decision or a detail. Omit a section only if it truly has nothing. No preamble.";
|
|
969
|
-
function truncate(s, n) {
|
|
970
|
-
const t = s.trim();
|
|
971
|
-
return t.length > n ? `${t.slice(0, n).trimEnd()}
|
|
972
|
-
\u2026` : t;
|
|
973
|
-
}
|
|
974
1042
|
async function compactLedger(ctx, text, opts = {}) {
|
|
975
1043
|
const trimmed = text.trim();
|
|
976
1044
|
if (!trimmed) return "";
|
|
@@ -1039,10 +1107,6 @@ function consolidateJob(config = {}) {
|
|
|
1039
1107
|
}
|
|
1040
1108
|
|
|
1041
1109
|
// src/core/ground.ts
|
|
1042
|
-
function truncate2(s, n) {
|
|
1043
|
-
return s.length > n ? `${s.slice(0, n).trimEnd()}
|
|
1044
|
-
\u2026` : s;
|
|
1045
|
-
}
|
|
1046
1110
|
async function groundingText(workspace, opts = {}) {
|
|
1047
1111
|
const records = await log({
|
|
1048
1112
|
cwd: workspace.dir,
|
|
@@ -1059,7 +1123,7 @@ What prior iterations already did and why \u2014 read it before working so you d
|
|
|
1059
1123
|
const head = `### ${r.sha.slice(0, 7)} ${r.subject}`;
|
|
1060
1124
|
return r.body ? `${head}
|
|
1061
1125
|
|
|
1062
|
-
${
|
|
1126
|
+
${truncate(r.body, bodyChars)}` : head;
|
|
1063
1127
|
});
|
|
1064
1128
|
return `${header}
|
|
1065
1129
|
|
|
@@ -1115,12 +1179,305 @@ Commits a search judged relevant \u2014 read them before working.`;
|
|
|
1115
1179
|
const head = `### ${r.sha.slice(0, 7)} ${r.subject}`;
|
|
1116
1180
|
return r.body ? `${head}
|
|
1117
1181
|
|
|
1118
|
-
${
|
|
1182
|
+
${truncate(r.body, bodyChars)}` : head;
|
|
1119
1183
|
});
|
|
1120
1184
|
return `${header}
|
|
1121
1185
|
|
|
1122
1186
|
${entries.join("\n\n")}`;
|
|
1123
1187
|
}
|
|
1188
|
+
function normalizeFeedbackSeverity(severity) {
|
|
1189
|
+
switch (severity) {
|
|
1190
|
+
case "advisory":
|
|
1191
|
+
return "nice-to-have";
|
|
1192
|
+
case "blocking":
|
|
1193
|
+
case void 0:
|
|
1194
|
+
return "block";
|
|
1195
|
+
default:
|
|
1196
|
+
return severity;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
function isRequiredFeedbackSeverity(severity) {
|
|
1200
|
+
const normalized = normalizeFeedbackSeverity(severity);
|
|
1201
|
+
return normalized === "block" || normalized === "should-fix";
|
|
1202
|
+
}
|
|
1203
|
+
function findingLine(finding) {
|
|
1204
|
+
const reviewer = finding.reviewer ? `${finding.reviewer} ` : "";
|
|
1205
|
+
const severity = normalizeFeedbackSeverity(finding.severity);
|
|
1206
|
+
const decision = finding.decision ? ` Decision: ${finding.decision}.` : "";
|
|
1207
|
+
const recommendation = finding.recommendation ? ` Recommendation: ${oneLine(finding.recommendation)}` : "";
|
|
1208
|
+
return `- ${reviewer}[${severity}]: ${oneLine(finding.evidence)}${decision}${recommendation}`;
|
|
1209
|
+
}
|
|
1210
|
+
function defaultReason(findings) {
|
|
1211
|
+
if (!findings?.length) return "Revision requested";
|
|
1212
|
+
if (findings.length === 1) return oneLine(findings[0].evidence);
|
|
1213
|
+
return `${findings.length} findings require another pass`;
|
|
1214
|
+
}
|
|
1215
|
+
function normalizeRevision(input) {
|
|
1216
|
+
const reason = input.reason?.trim() || defaultReason(input.findings);
|
|
1217
|
+
return {
|
|
1218
|
+
reason,
|
|
1219
|
+
target: input.target,
|
|
1220
|
+
findings: input.findings,
|
|
1221
|
+
rerun: input.rerun ?? (input.target ? "target-and-dependents" : void 0),
|
|
1222
|
+
source: input.source,
|
|
1223
|
+
decision: input.decision
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
function revisionRequest(input, over = {}) {
|
|
1227
|
+
const revision = normalizeRevision(input);
|
|
1228
|
+
return {
|
|
1229
|
+
status: over.status ?? "fail",
|
|
1230
|
+
confidence: over.confidence,
|
|
1231
|
+
summary: over.summary ?? revision.reason,
|
|
1232
|
+
data: over.data,
|
|
1233
|
+
error: over.error,
|
|
1234
|
+
revision
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
function kickback(to, reason, over = {}) {
|
|
1238
|
+
return revisionRequest({ target: to, reason }, over);
|
|
1239
|
+
}
|
|
1240
|
+
function revisionFromOutcome(outcome) {
|
|
1241
|
+
return outcome.revision;
|
|
1242
|
+
}
|
|
1243
|
+
function feedbackBlock(outcome) {
|
|
1244
|
+
const revision = revisionFromOutcome(outcome);
|
|
1245
|
+
const parts = [
|
|
1246
|
+
"## Feedback to address",
|
|
1247
|
+
"A review or downstream stage requested another pass. Address this before unrelated work."
|
|
1248
|
+
];
|
|
1249
|
+
if (revision?.target) parts.push(`Target: ${revision.target}`);
|
|
1250
|
+
if (revision?.source) parts.push(`Source: ${revision.source}`);
|
|
1251
|
+
if (revision?.decision) parts.push(`Caller decision: ${revision.decision}`);
|
|
1252
|
+
const reason = revision?.reason ?? outcome.summary;
|
|
1253
|
+
if (reason) parts.push(`Reason: ${reason}`);
|
|
1254
|
+
const findings = revision?.findings ?? [];
|
|
1255
|
+
if (findings.length) {
|
|
1256
|
+
parts.push("Findings:");
|
|
1257
|
+
parts.push(findings.map(findingLine).join("\n"));
|
|
1258
|
+
}
|
|
1259
|
+
return parts.join("\n\n");
|
|
1260
|
+
}
|
|
1261
|
+
function graphPositionBlock(graph) {
|
|
1262
|
+
return [
|
|
1263
|
+
"## Graph position",
|
|
1264
|
+
`DAG: ${graph.dag}`,
|
|
1265
|
+
`Current node: ${graph.node}`,
|
|
1266
|
+
`Path: ${graph.path.join(" > ")}`,
|
|
1267
|
+
`Depends on: ${graph.needs.length ? graph.needs.join(", ") : "none"}`,
|
|
1268
|
+
`Direct dependents: ${graph.dependents.length ? graph.dependents.join(", ") : "none"}`
|
|
1269
|
+
].join("\n");
|
|
1270
|
+
}
|
|
1271
|
+
async function runReviewer(reviewer, index, ctx) {
|
|
1272
|
+
const name = reviewer.name ?? `reviewer-${index + 1}`;
|
|
1273
|
+
try {
|
|
1274
|
+
if ("job" in reviewer) {
|
|
1275
|
+
const outcome = await reviewer.job(ctx);
|
|
1276
|
+
return {
|
|
1277
|
+
name,
|
|
1278
|
+
met: outcome.status === "pass",
|
|
1279
|
+
confidence: outcome.confidence,
|
|
1280
|
+
reason: outcome.summary ?? outcome.status
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
const result = await toCondition(reviewer.review)(
|
|
1284
|
+
ctx,
|
|
1285
|
+
ctx.lastOutcome
|
|
1286
|
+
);
|
|
1287
|
+
return {
|
|
1288
|
+
name,
|
|
1289
|
+
met: result.met,
|
|
1290
|
+
confidence: result.confidence,
|
|
1291
|
+
reason: result.reason
|
|
1292
|
+
};
|
|
1293
|
+
} catch (e) {
|
|
1294
|
+
if (ctx.signal.aborted) throw e;
|
|
1295
|
+
return {
|
|
1296
|
+
name,
|
|
1297
|
+
met: false,
|
|
1298
|
+
reason: `reviewer errored: ${e instanceof Error ? e.message : String(e)}`
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
function reviewFinding(result) {
|
|
1303
|
+
return {
|
|
1304
|
+
reviewer: result.name,
|
|
1305
|
+
severity: "block",
|
|
1306
|
+
evidence: result.reason
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
function findingSeverityCounts(findings) {
|
|
1310
|
+
const counts = {};
|
|
1311
|
+
for (const finding of findings) {
|
|
1312
|
+
const severity = normalizeFeedbackSeverity(finding.severity);
|
|
1313
|
+
counts[severity] = (counts[severity] ?? 0) + 1;
|
|
1314
|
+
}
|
|
1315
|
+
return counts;
|
|
1316
|
+
}
|
|
1317
|
+
function reviewPanel(config) {
|
|
1318
|
+
const label = config.label ?? "review-panel";
|
|
1319
|
+
if (!config.reviewers.length)
|
|
1320
|
+
throw new LoopError({
|
|
1321
|
+
code: "CONFIG",
|
|
1322
|
+
message: `reviewPanel "${label}": at least one reviewer is required`
|
|
1323
|
+
});
|
|
1324
|
+
const job = async (ctx) => {
|
|
1325
|
+
ctx.emit({ kind: "job:start", ts: Date.now(), path: [...ctx.path], label });
|
|
1326
|
+
const results = await Promise.all(
|
|
1327
|
+
config.reviewers.map((reviewer, i) => runReviewer(reviewer, i, ctx))
|
|
1328
|
+
);
|
|
1329
|
+
const passedCount = results.filter((r) => r.met).length;
|
|
1330
|
+
const required = config.pass === void 0 || config.pass === "all" ? results.length : config.pass;
|
|
1331
|
+
const findings = results.filter((r) => !r.met).map(reviewFinding);
|
|
1332
|
+
const passed = passedCount >= required;
|
|
1333
|
+
const summaryHead = `Review panel: ${passedCount}/${results.length} reviewer(s) cleared`;
|
|
1334
|
+
const summary = findings.length ? `${summaryHead}.
|
|
1335
|
+
${findings.map(findingLine).join("\n")}` : `${summaryHead}.`;
|
|
1336
|
+
const scored = results.map((r) => r.confidence).filter((c) => c != null);
|
|
1337
|
+
const confidence = scored.length ? scored.reduce((sum, c) => sum + c, 0) / scored.length : void 0;
|
|
1338
|
+
const data = {
|
|
1339
|
+
findings,
|
|
1340
|
+
results,
|
|
1341
|
+
passed: passedCount,
|
|
1342
|
+
required,
|
|
1343
|
+
severityCounts: findingSeverityCounts(findings)
|
|
1344
|
+
};
|
|
1345
|
+
const outcome = passed ? { status: "pass", summary, confidence, data } : revisionRequest(
|
|
1346
|
+
{
|
|
1347
|
+
target: config.target,
|
|
1348
|
+
// A clean one-line reason. The findings ride the `findings` array, so
|
|
1349
|
+
// feedbackBlock renders them once (not embedded in the reason too) and
|
|
1350
|
+
// the records/tail `reason` stays a single tidy line. The full
|
|
1351
|
+
// multi-line `summary` is kept on the outcome below for logs/TUI.
|
|
1352
|
+
reason: `${summaryHead}.`,
|
|
1353
|
+
findings,
|
|
1354
|
+
rerun: config.rerun
|
|
1355
|
+
},
|
|
1356
|
+
{ summary, confidence, data }
|
|
1357
|
+
);
|
|
1358
|
+
ctx.emit({ kind: "job:end", ts: Date.now(), path: [...ctx.path], label, outcome });
|
|
1359
|
+
return outcome;
|
|
1360
|
+
};
|
|
1361
|
+
return setMeta(job, { kind: "reviewPanel", name: label });
|
|
1362
|
+
}
|
|
1363
|
+
async function gitOutput(cwd, args, signal) {
|
|
1364
|
+
const out = await execa("git", args, {
|
|
1365
|
+
cwd,
|
|
1366
|
+
reject: false,
|
|
1367
|
+
stripFinalNewline: false,
|
|
1368
|
+
cancelSignal: signal
|
|
1369
|
+
});
|
|
1370
|
+
return out.stdout.trim();
|
|
1371
|
+
}
|
|
1372
|
+
async function resolveFiles(ctx, patterns) {
|
|
1373
|
+
const fromGit = await gitOutput(
|
|
1374
|
+
ctx.workspace.dir,
|
|
1375
|
+
["ls-files", "--", ...patterns],
|
|
1376
|
+
ctx.signal
|
|
1377
|
+
).catch(() => "");
|
|
1378
|
+
const files = fromGit ? fromGit.split("\n").filter(Boolean) : [];
|
|
1379
|
+
if (files.length) return files;
|
|
1380
|
+
return patterns.filter((p) => existsSync(join(ctx.workspace.dir, p)));
|
|
1381
|
+
}
|
|
1382
|
+
function reviewContext(config) {
|
|
1383
|
+
return async (ctx, last) => {
|
|
1384
|
+
const max = config.maxChars ?? 6e3;
|
|
1385
|
+
const buildTests = async () => {
|
|
1386
|
+
if (!config.tests) return [];
|
|
1387
|
+
if (config.tests === true) {
|
|
1388
|
+
const lines = [];
|
|
1389
|
+
if (last?.status) lines.push(`Last outcome status: ${last.status}`);
|
|
1390
|
+
if (last?.summary) lines.push(`Last outcome summary: ${last.summary}`);
|
|
1391
|
+
if (last?.data !== void 0) {
|
|
1392
|
+
let rendered;
|
|
1393
|
+
try {
|
|
1394
|
+
rendered = JSON.stringify(last.data, null, 2);
|
|
1395
|
+
} catch {
|
|
1396
|
+
rendered = String(last.data);
|
|
1397
|
+
}
|
|
1398
|
+
lines.push(`Last outcome data: ${rendered}`);
|
|
1399
|
+
}
|
|
1400
|
+
return lines.length ? [`## Test and outcome context
|
|
1401
|
+
|
|
1402
|
+
${lines.join("\n")}`] : [];
|
|
1403
|
+
}
|
|
1404
|
+
const cwd = config.tests.cwd ?? ctx.workspace.dir;
|
|
1405
|
+
const result = await execa(
|
|
1406
|
+
config.tests.command,
|
|
1407
|
+
config.tests.args ?? [],
|
|
1408
|
+
{ cwd, reject: false, stripFinalNewline: false, cancelSignal: ctx.signal }
|
|
1409
|
+
).catch((e) => {
|
|
1410
|
+
if (ctx.signal.aborted) throw e;
|
|
1411
|
+
return {
|
|
1412
|
+
exitCode: void 0,
|
|
1413
|
+
stdout: "",
|
|
1414
|
+
stderr: e instanceof Error ? e.message : String(e)
|
|
1415
|
+
};
|
|
1416
|
+
});
|
|
1417
|
+
const exit = result.exitCode ?? "(command did not run)";
|
|
1418
|
+
return [
|
|
1419
|
+
`## Test command
|
|
1420
|
+
|
|
1421
|
+
${config.tests.command} ${(config.tests.args ?? []).join(" ")}
|
|
1422
|
+
|
|
1423
|
+
exit: ${exit}
|
|
1424
|
+
|
|
1425
|
+
stdout:
|
|
1426
|
+
${truncate(result.stdout ?? "", max)}
|
|
1427
|
+
|
|
1428
|
+
stderr:
|
|
1429
|
+
${truncate(result.stderr ?? "", max)}`
|
|
1430
|
+
];
|
|
1431
|
+
};
|
|
1432
|
+
const buildDiff = async () => {
|
|
1433
|
+
if (!config.diff) return [];
|
|
1434
|
+
const diff2 = await gitOutput(
|
|
1435
|
+
ctx.workspace.dir,
|
|
1436
|
+
["diff", "HEAD", "--"],
|
|
1437
|
+
ctx.signal
|
|
1438
|
+
).catch(() => "");
|
|
1439
|
+
return diff2 ? [`## Git diff
|
|
1440
|
+
|
|
1441
|
+
${truncate(diff2, max)}`] : [];
|
|
1442
|
+
};
|
|
1443
|
+
const buildFiles = async () => {
|
|
1444
|
+
if (!config.files?.length) return [];
|
|
1445
|
+
const files2 = await resolveFiles(ctx, config.files);
|
|
1446
|
+
const out = [];
|
|
1447
|
+
for (const file of files2) {
|
|
1448
|
+
const path = join(ctx.workspace.dir, file);
|
|
1449
|
+
if (!existsSync(path)) continue;
|
|
1450
|
+
out.push(`## File: ${file}
|
|
1451
|
+
|
|
1452
|
+
${truncate(readFileSync(path, "utf8"), max)}`);
|
|
1453
|
+
}
|
|
1454
|
+
return out;
|
|
1455
|
+
};
|
|
1456
|
+
const buildLedger = async () => {
|
|
1457
|
+
if (!config.ledger) return [];
|
|
1458
|
+
const out = [];
|
|
1459
|
+
const live = [readPrompt(ctx.workspace), readLedger(ctx.workspace)].filter(Boolean).join("\n\n");
|
|
1460
|
+
if (live) out.push(`## Live ledger
|
|
1461
|
+
|
|
1462
|
+
${truncate(live, max)}`);
|
|
1463
|
+
const committed = await groundingText(ctx.workspace, {
|
|
1464
|
+
max: 5,
|
|
1465
|
+
bodyChars: 1200,
|
|
1466
|
+
signal: ctx.signal
|
|
1467
|
+
}).catch(() => "");
|
|
1468
|
+
if (committed) out.push(truncate(committed, max));
|
|
1469
|
+
return out;
|
|
1470
|
+
};
|
|
1471
|
+
const [tests, diff, files, ledger] = await Promise.all([
|
|
1472
|
+
buildTests(),
|
|
1473
|
+
buildDiff(),
|
|
1474
|
+
buildFiles(),
|
|
1475
|
+
buildLedger()
|
|
1476
|
+
]);
|
|
1477
|
+
const sections = [...tests, ...diff, ...files, ...ledger];
|
|
1478
|
+
return sections.join("\n\n---\n\n") || "(no review context)";
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1124
1481
|
|
|
1125
1482
|
// src/core/job.ts
|
|
1126
1483
|
var HANDOFF_MARK = "===HANDOFF===";
|
|
@@ -1198,6 +1555,16 @@ var TERMINAL = (text) => ({
|
|
|
1198
1555
|
summary: text.trim().slice(0, 280),
|
|
1199
1556
|
data: text
|
|
1200
1557
|
});
|
|
1558
|
+
function withOperationalContext(ctx, userPrompt, config) {
|
|
1559
|
+
const parts = [userPrompt];
|
|
1560
|
+
if (config.consumeFeedback && ctx.lastReview) {
|
|
1561
|
+
parts.push(feedbackBlock(ctx.lastReview));
|
|
1562
|
+
}
|
|
1563
|
+
if (config.graphContext && ctx.graph) {
|
|
1564
|
+
parts.push(graphPositionBlock(ctx.graph));
|
|
1565
|
+
}
|
|
1566
|
+
return parts.join("\n\n---\n\n");
|
|
1567
|
+
}
|
|
1201
1568
|
function agentJob(config) {
|
|
1202
1569
|
const job = async (ctx) => {
|
|
1203
1570
|
const path = [...ctx.path];
|
|
@@ -1205,7 +1572,8 @@ function agentJob(config) {
|
|
|
1205
1572
|
ctx.emit({ kind: "job:start", ts: Date.now(), path, label });
|
|
1206
1573
|
const engine = ctx.resolveEngine(config.engine);
|
|
1207
1574
|
const userPrompt = typeof config.prompt === "function" ? await config.prompt(ctx) : config.prompt;
|
|
1208
|
-
const
|
|
1575
|
+
const contextualPrompt = withOperationalContext(ctx, userPrompt, config);
|
|
1576
|
+
const prompt = config.ground ? await withGrounding(ctx, contextualPrompt, config.ground) : contextualPrompt;
|
|
1209
1577
|
const system = config.system !== void 0 ? typeof config.system === "function" ? config.system(ctx) : config.system : config.agent ? resolveSystem(config.agent) : void 0;
|
|
1210
1578
|
let result;
|
|
1211
1579
|
const toolUses = /* @__PURE__ */ new Map();
|
|
@@ -1306,7 +1674,8 @@ function agentJob(config) {
|
|
|
1306
1674
|
return setMeta(job, {
|
|
1307
1675
|
kind: "agent",
|
|
1308
1676
|
name: config.label ?? config.agent?.name ?? "agent",
|
|
1309
|
-
ground: !!config.ground
|
|
1677
|
+
ground: !!config.ground,
|
|
1678
|
+
contract: agentContract(config.agent)
|
|
1310
1679
|
});
|
|
1311
1680
|
}
|
|
1312
1681
|
function composeWay(ctx, last) {
|
|
@@ -1382,14 +1751,6 @@ function commitJob(config) {
|
|
|
1382
1751
|
}
|
|
1383
1752
|
};
|
|
1384
1753
|
}
|
|
1385
|
-
function kickback(to, reason, over) {
|
|
1386
|
-
return {
|
|
1387
|
-
status: "fail",
|
|
1388
|
-
summary: reason,
|
|
1389
|
-
...over,
|
|
1390
|
-
kickback: { to, reason }
|
|
1391
|
-
};
|
|
1392
|
-
}
|
|
1393
1754
|
function fnJob(label, fn) {
|
|
1394
1755
|
const job = async (ctx) => {
|
|
1395
1756
|
const path = [...ctx.path];
|
|
@@ -1439,6 +1800,7 @@ function childContext(parent, over) {
|
|
|
1439
1800
|
log: parent.log,
|
|
1440
1801
|
depth: over.depth,
|
|
1441
1802
|
path: over.path,
|
|
1803
|
+
graph: over.graph ?? parent.graph,
|
|
1442
1804
|
// Inherit the enclosing iteration by default. A `loop` always passes one
|
|
1443
1805
|
// explicitly; a `dag`/`sequence` does not, so without this a node nested in a
|
|
1444
1806
|
// loop would reset to 0 — the "Attempt 0" confound where a retry body could not
|
|
@@ -1746,13 +2108,18 @@ function loop(config) {
|
|
|
1746
2108
|
iteration
|
|
1747
2109
|
});
|
|
1748
2110
|
}
|
|
2111
|
+
const reviewPassed = reviewOutcome.status === "pass";
|
|
2112
|
+
const restartsExhausted = config.maxReviewRestarts != null && consecutiveReviewFails + 1 >= config.maxReviewRestarts;
|
|
2113
|
+
const iterationsRemain = config.max == null || iteration < config.max;
|
|
2114
|
+
const willReenter = !reviewPassed && !restartsExhausted && iterationsRemain;
|
|
1749
2115
|
parent.emit({
|
|
1750
2116
|
kind: "loop:review",
|
|
1751
2117
|
ts: ts(),
|
|
1752
2118
|
path,
|
|
1753
|
-
outcome: reviewOutcome
|
|
2119
|
+
outcome: reviewOutcome,
|
|
2120
|
+
accepted: willReenter
|
|
1754
2121
|
});
|
|
1755
|
-
if (
|
|
2122
|
+
if (reviewPassed) {
|
|
1756
2123
|
await recordMilestone(ctxAt(iteration, last));
|
|
1757
2124
|
return finish(
|
|
1758
2125
|
{
|
|
@@ -1770,7 +2137,7 @@ function loop(config) {
|
|
|
1770
2137
|
`review did not pass (${reviewOutcome.summary ?? reviewOutcome.status}); re-entering ${config.name}`,
|
|
1771
2138
|
"warn"
|
|
1772
2139
|
);
|
|
1773
|
-
if (
|
|
2140
|
+
if (restartsExhausted) {
|
|
1774
2141
|
return finish(
|
|
1775
2142
|
{
|
|
1776
2143
|
status: "exhausted",
|
|
@@ -1866,14 +2233,14 @@ var EngineRegistry = class {
|
|
|
1866
2233
|
this.register(
|
|
1867
2234
|
"agent-sdk",
|
|
1868
2235
|
(o) => lazy(
|
|
1869
|
-
() => import('./agent-sdk-
|
|
2236
|
+
() => import('./agent-sdk-4QJDWM7N.js').then((m) => new m.AgentSdkEngine(o)),
|
|
1870
2237
|
"agent-sdk"
|
|
1871
2238
|
)
|
|
1872
2239
|
);
|
|
1873
2240
|
this.register(
|
|
1874
2241
|
"claude-cli",
|
|
1875
2242
|
(o) => lazy(
|
|
1876
|
-
() => import('./claude-cli-
|
|
2243
|
+
() => import('./claude-cli-75AOQUKG.js').then((m) => new m.ClaudeCliEngine(o)),
|
|
1877
2244
|
"claude-cli"
|
|
1878
2245
|
)
|
|
1879
2246
|
);
|
|
@@ -1886,7 +2253,7 @@ var EngineRegistry = class {
|
|
|
1886
2253
|
);
|
|
1887
2254
|
this.register(
|
|
1888
2255
|
"codex",
|
|
1889
|
-
(o) => lazy(() => import('./codex-
|
|
2256
|
+
(o) => lazy(() => import('./codex-LYZF52WL.js').then((m) => new m.CodexEngine(o)), "codex")
|
|
1890
2257
|
);
|
|
1891
2258
|
}
|
|
1892
2259
|
};
|
|
@@ -1972,6 +2339,188 @@ var Stats = class {
|
|
|
1972
2339
|
return m;
|
|
1973
2340
|
}
|
|
1974
2341
|
};
|
|
2342
|
+
function ensureDir2(path) {
|
|
2343
|
+
const dir = dirname(path);
|
|
2344
|
+
if (dir && dir !== ".") mkdirSync(dir, { recursive: true });
|
|
2345
|
+
}
|
|
2346
|
+
function outcomeSummary(outcome) {
|
|
2347
|
+
return {
|
|
2348
|
+
status: outcome.status,
|
|
2349
|
+
summary: outcome.summary,
|
|
2350
|
+
confidence: outcome.confidence
|
|
2351
|
+
};
|
|
2352
|
+
}
|
|
2353
|
+
function strongestFinding(findings) {
|
|
2354
|
+
if (!findings?.length) return void 0;
|
|
2355
|
+
const severities = findings.map((f) => normalizeFeedbackSeverity(f.severity));
|
|
2356
|
+
if (severities.includes("block")) return "block";
|
|
2357
|
+
if (severities.includes("should-fix")) return "should-fix";
|
|
2358
|
+
if (severities.includes("nice-to-have")) return "nice-to-have";
|
|
2359
|
+
if (severities.includes("approve")) return "approve";
|
|
2360
|
+
return void 0;
|
|
2361
|
+
}
|
|
2362
|
+
function emittedRevisionRecord(event, outcome) {
|
|
2363
|
+
const revision = revisionFromOutcome(outcome);
|
|
2364
|
+
return revision ? [
|
|
2365
|
+
{
|
|
2366
|
+
kind: "revision-emitted",
|
|
2367
|
+
ts: event.ts,
|
|
2368
|
+
path: event.path,
|
|
2369
|
+
sourceEvent: "job:end",
|
|
2370
|
+
revision
|
|
2371
|
+
}
|
|
2372
|
+
] : [];
|
|
2373
|
+
}
|
|
2374
|
+
function semanticRecordsFromEvent(event) {
|
|
2375
|
+
switch (event.kind) {
|
|
2376
|
+
case "job:start":
|
|
2377
|
+
return [
|
|
2378
|
+
{
|
|
2379
|
+
kind: "dispatch",
|
|
2380
|
+
ts: event.ts,
|
|
2381
|
+
path: event.path,
|
|
2382
|
+
unit: "job",
|
|
2383
|
+
label: event.label
|
|
2384
|
+
}
|
|
2385
|
+
];
|
|
2386
|
+
case "dag:node":
|
|
2387
|
+
if (event.phase === "start")
|
|
2388
|
+
return [
|
|
2389
|
+
{
|
|
2390
|
+
kind: "dispatch",
|
|
2391
|
+
ts: event.ts,
|
|
2392
|
+
path: [...event.path, event.node],
|
|
2393
|
+
unit: "dag-node",
|
|
2394
|
+
node: event.node,
|
|
2395
|
+
attempt: event.attempt
|
|
2396
|
+
}
|
|
2397
|
+
];
|
|
2398
|
+
return event.outcome ? [
|
|
2399
|
+
{
|
|
2400
|
+
kind: "completion",
|
|
2401
|
+
ts: event.ts,
|
|
2402
|
+
path: [...event.path, event.node],
|
|
2403
|
+
unit: "dag-node",
|
|
2404
|
+
label: event.node,
|
|
2405
|
+
outcome: outcomeSummary(event.outcome),
|
|
2406
|
+
attempt: event.attempt
|
|
2407
|
+
}
|
|
2408
|
+
] : [];
|
|
2409
|
+
case "job:end":
|
|
2410
|
+
return [
|
|
2411
|
+
{
|
|
2412
|
+
kind: "completion",
|
|
2413
|
+
ts: event.ts,
|
|
2414
|
+
path: event.path,
|
|
2415
|
+
unit: "job",
|
|
2416
|
+
label: event.label,
|
|
2417
|
+
outcome: outcomeSummary(event.outcome)
|
|
2418
|
+
},
|
|
2419
|
+
...emittedRevisionRecord(event, event.outcome)
|
|
2420
|
+
];
|
|
2421
|
+
case "loop:review": {
|
|
2422
|
+
if (event.outcome.status === "pass") return [];
|
|
2423
|
+
const revision = revisionFromOutcome(event.outcome);
|
|
2424
|
+
const decision = event.accepted === false ? "rejected" : "accepted";
|
|
2425
|
+
const records = [
|
|
2426
|
+
{
|
|
2427
|
+
kind: "surfacing",
|
|
2428
|
+
ts: event.ts,
|
|
2429
|
+
path: event.path,
|
|
2430
|
+
source: "loop-review",
|
|
2431
|
+
decision,
|
|
2432
|
+
severity: strongestFinding(revision?.findings),
|
|
2433
|
+
reason: revision?.reason ?? event.outcome.summary ?? event.outcome.status
|
|
2434
|
+
}
|
|
2435
|
+
];
|
|
2436
|
+
if (revision) {
|
|
2437
|
+
records.push({
|
|
2438
|
+
kind: "revision-routed",
|
|
2439
|
+
ts: event.ts,
|
|
2440
|
+
path: event.path,
|
|
2441
|
+
sourceEvent: "loop:review",
|
|
2442
|
+
decision,
|
|
2443
|
+
revision
|
|
2444
|
+
});
|
|
2445
|
+
}
|
|
2446
|
+
return records;
|
|
2447
|
+
}
|
|
2448
|
+
case "loop:end":
|
|
2449
|
+
return [
|
|
2450
|
+
{
|
|
2451
|
+
kind: "completion",
|
|
2452
|
+
ts: event.ts,
|
|
2453
|
+
path: event.path,
|
|
2454
|
+
unit: "loop",
|
|
2455
|
+
outcome: outcomeSummary(event.outcome),
|
|
2456
|
+
iterations: event.iterations
|
|
2457
|
+
}
|
|
2458
|
+
];
|
|
2459
|
+
case "dag:kickback": {
|
|
2460
|
+
const at = [...event.path, event.to];
|
|
2461
|
+
const decision = event.accepted ? "accepted" : "rejected";
|
|
2462
|
+
return [
|
|
2463
|
+
{
|
|
2464
|
+
kind: "surfacing",
|
|
2465
|
+
ts: event.ts,
|
|
2466
|
+
path: at,
|
|
2467
|
+
source: "dag-kickback",
|
|
2468
|
+
decision,
|
|
2469
|
+
severity: "block",
|
|
2470
|
+
from: event.from,
|
|
2471
|
+
to: event.to,
|
|
2472
|
+
reason: event.reason,
|
|
2473
|
+
note: event.note
|
|
2474
|
+
},
|
|
2475
|
+
{
|
|
2476
|
+
kind: "revision-routed",
|
|
2477
|
+
ts: event.ts,
|
|
2478
|
+
path: at,
|
|
2479
|
+
sourceEvent: "dag:kickback",
|
|
2480
|
+
decision,
|
|
2481
|
+
revision: {
|
|
2482
|
+
target: event.to,
|
|
2483
|
+
reason: event.reason,
|
|
2484
|
+
source: event.from,
|
|
2485
|
+
rerun: event.accepted ? "target-and-dependents" : void 0
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
];
|
|
2489
|
+
}
|
|
2490
|
+
case "dag:end":
|
|
2491
|
+
return [
|
|
2492
|
+
{
|
|
2493
|
+
kind: "completion",
|
|
2494
|
+
ts: event.ts,
|
|
2495
|
+
path: event.path,
|
|
2496
|
+
unit: "dag",
|
|
2497
|
+
outcome: outcomeSummary(event.outcome)
|
|
2498
|
+
}
|
|
2499
|
+
];
|
|
2500
|
+
default:
|
|
2501
|
+
return [];
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
function makeSemanticRecorder(path) {
|
|
2505
|
+
try {
|
|
2506
|
+
ensureDir2(path);
|
|
2507
|
+
writeFileSync(path, "");
|
|
2508
|
+
} catch {
|
|
2509
|
+
return () => {
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
return (event) => {
|
|
2513
|
+
const records = semanticRecordsFromEvent(event);
|
|
2514
|
+
if (!records.length) return;
|
|
2515
|
+
try {
|
|
2516
|
+
for (const record of records) {
|
|
2517
|
+
appendFileSync(path, `${JSON.stringify(record)}
|
|
2518
|
+
`);
|
|
2519
|
+
}
|
|
2520
|
+
} catch {
|
|
2521
|
+
}
|
|
2522
|
+
};
|
|
2523
|
+
}
|
|
1975
2524
|
var NOISE = /* @__PURE__ */ new Set([
|
|
1976
2525
|
"engine:text",
|
|
1977
2526
|
"engine:thinking"
|
|
@@ -1990,11 +2539,13 @@ function startSupervisor(input) {
|
|
|
1990
2539
|
const dir = join(runsHome(), input.runId);
|
|
1991
2540
|
mkdirSync(dir, { recursive: true });
|
|
1992
2541
|
const eventsPath = join(dir, "events.jsonl");
|
|
2542
|
+
const semanticPath = join(dir, "semantic.jsonl");
|
|
1993
2543
|
const statusPath = join(dir, "status.json");
|
|
1994
2544
|
try {
|
|
1995
2545
|
writeFileSync(eventsPath, "");
|
|
1996
2546
|
} catch {
|
|
1997
2547
|
}
|
|
2548
|
+
const semanticSink = makeSemanticRecorder(semanticPath);
|
|
1998
2549
|
const status = {
|
|
1999
2550
|
runId: input.runId,
|
|
2000
2551
|
pid: process.pid,
|
|
@@ -2025,6 +2576,7 @@ function startSupervisor(input) {
|
|
|
2025
2576
|
`);
|
|
2026
2577
|
} catch {
|
|
2027
2578
|
}
|
|
2579
|
+
semanticSink(event);
|
|
2028
2580
|
}
|
|
2029
2581
|
switch (event.kind) {
|
|
2030
2582
|
case "loop:iteration":
|
|
@@ -2101,6 +2653,9 @@ function listRuns() {
|
|
|
2101
2653
|
function runEventsPath(runId) {
|
|
2102
2654
|
return join(runsHome(), runId, "events.jsonl");
|
|
2103
2655
|
}
|
|
2656
|
+
function runSemanticRecordsPath(runId) {
|
|
2657
|
+
return join(runsHome(), runId, "semantic.jsonl");
|
|
2658
|
+
}
|
|
2104
2659
|
function formatEvent(event) {
|
|
2105
2660
|
const at = event.path.length ? `${event.path.join(" \u203A ")} ` : "";
|
|
2106
2661
|
switch (event.kind) {
|
|
@@ -2118,6 +2673,8 @@ function formatEvent(event) {
|
|
|
2118
2673
|
return `${at}\u25C2 ${event.outcome.status} (${event.iterations} iter)`;
|
|
2119
2674
|
case "dag:node":
|
|
2120
2675
|
return `${at}\xB7 node ${event.node}: ${event.phase}${event.outcome ? ` (${event.outcome.status})` : ""}`;
|
|
2676
|
+
case "dag:kickback":
|
|
2677
|
+
return `${at}\u21A9 kickback ${event.accepted ? "accepted" : "rejected"} ${event.from} -> ${event.to}: ${event.reason}${event.note ? ` (${event.note})` : ""}`;
|
|
2121
2678
|
case "dag:end":
|
|
2122
2679
|
return `${at}\u25C2 dag ${event.outcome.status}`;
|
|
2123
2680
|
case "job:start":
|
|
@@ -2150,12 +2707,12 @@ var CHECKPOINT_AT = /* @__PURE__ */ new Set([
|
|
|
2150
2707
|
"dag:end",
|
|
2151
2708
|
"job:end"
|
|
2152
2709
|
]);
|
|
2153
|
-
function
|
|
2710
|
+
function ensureDir3(path) {
|
|
2154
2711
|
const dir = dirname(path);
|
|
2155
2712
|
if (dir && dir !== ".") mkdirSync(dir, { recursive: true });
|
|
2156
2713
|
}
|
|
2157
2714
|
function makeRecorder(path) {
|
|
2158
|
-
|
|
2715
|
+
ensureDir3(path);
|
|
2159
2716
|
writeFileSync(path, "");
|
|
2160
2717
|
return (event) => {
|
|
2161
2718
|
if (NOISE2.has(event.kind)) return;
|
|
@@ -2167,14 +2724,14 @@ function makeRecorder(path) {
|
|
|
2167
2724
|
};
|
|
2168
2725
|
}
|
|
2169
2726
|
function makeCheckpointer(path, state) {
|
|
2170
|
-
|
|
2727
|
+
ensureDir3(path);
|
|
2171
2728
|
return (event) => {
|
|
2172
2729
|
if (!CHECKPOINT_AT.has(event.kind)) return;
|
|
2173
2730
|
flushCheckpoint(path, state);
|
|
2174
2731
|
};
|
|
2175
2732
|
}
|
|
2176
2733
|
function flushCheckpoint(path, state) {
|
|
2177
|
-
|
|
2734
|
+
ensureDir3(path);
|
|
2178
2735
|
try {
|
|
2179
2736
|
writeFileSync(path, JSON.stringify({ ts: Date.now(), state }, null, 2));
|
|
2180
2737
|
} catch {
|
|
@@ -2344,6 +2901,6 @@ function exitCodeFor(outcome) {
|
|
|
2344
2901
|
}
|
|
2345
2902
|
}
|
|
2346
2903
|
|
|
2347
|
-
export { Budget, EXIT_PAUSED, EngineRegistry, GhForge, MockForge, Stats, addWorktree, agentCheck, agentJob, all, always, any, appendLedger, appendPrompt, bodyPassed, buildChecksArgs, buildCreateArgs, buildEditArgs, buildMergeArgs, buildViewArgs, childContext, commandSucceeds, commit, commitJob, compactLedger, composeCommitBody, conflictedFiles, consolidate, consolidateJob, currentBranch, defineAgent, defineSkill, deleteBranch, describeConditions, ensureIgnored, exitCodeFor, fnJob, forgeChecks, formatEvent, fromFile, gateJob, groundingText, hasStagedChanges, headSha, isDirty, isForge, isRepo, jobMeta, kickback, ledgerPath, listRuns, log, loop, mergeAbort, mergeBranch, mergeNoCommit, minConfidence, never, not, predicate, promptPath, push, quorum, readLedger, readPrompt, readRunStatus, removeWorktree, renderPlan, resetLedger, resetPrompt, resolveSystem, retrieveLedger, run, runEventsPath, runsHome, setMeta, stageAll, toCondition };
|
|
2348
|
-
//# sourceMappingURL=chunk-
|
|
2349
|
-
//# sourceMappingURL=chunk-
|
|
2904
|
+
export { Budget, EXIT_PAUSED, EngineRegistry, GhForge, MockForge, Stats, addWorktree, agentCheck, agentContract, agentJob, all, always, any, appendLedger, appendPrompt, bodyPassed, buildChecksArgs, buildCreateArgs, buildEditArgs, buildMergeArgs, buildViewArgs, childContext, commandSucceeds, commit, commitJob, compactLedger, composeCommitBody, conflictedFiles, consolidate, consolidateJob, currentBranch, defineAgent, defineSkill, deleteBranch, describeConditions, ensureIgnored, exitCodeFor, feedbackBlock, fnJob, forgeChecks, formatEvent, fromFile, gateJob, graphPositionBlock, groundingText, hasStagedChanges, headSha, isDirty, isForge, isRepo, isRequiredFeedbackSeverity, jobMeta, kickback, ledgerPath, listRuns, log, loop, mergeAbort, mergeBranch, mergeNoCommit, minConfidence, never, normalizeFeedbackSeverity, not, predicate, promptPath, push, quorum, readLedger, readPrompt, readRunStatus, removeWorktree, renderPlan, resetLedger, resetPrompt, resolveSystem, retrieveLedger, reviewContext, reviewPanel, revisionFromOutcome, revisionRequest, run, runEventsPath, runSemanticRecordsPath, runsHome, semanticRecordsFromEvent, setMeta, stageAll, toCondition };
|
|
2905
|
+
//# sourceMappingURL=chunk-WM5QVHM2.js.map
|
|
2906
|
+
//# sourceMappingURL=chunk-WM5QVHM2.js.map
|