@agentskit/harness 0.10.0 → 0.11.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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/capabilities/public-surface.json +105 -84
- package/dist/cli.js +353 -64
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +192 -56
- package/dist/index.js +325 -76
- package/dist/index.js.map +1 -1
- package/docs/ADR-0003-doc-bridge-context-binding.md +10 -3
- package/docs/ADR-0031-loop-observability.md +36 -0
- package/docs/LOOP.md +7 -0
- package/docs/MODULE-BOUNDARIES.md +1 -0
- package/loop.config.example.yaml +1 -1
- package/package.json +2 -2
- package/release/manifest.json +2 -2
- package/release/notes.md +6 -0
package/dist/index.js
CHANGED
|
@@ -1234,11 +1234,34 @@ var validateCapabilityManifest = (value) => {
|
|
|
1234
1234
|
var index = (root, indexPath) => JSON.parse(readFileSync(resolve(root, indexPath), "utf8"));
|
|
1235
1235
|
var text = (entry) => [entry.id, entry.type, entry.title, entry.path, entry.description, entry.body, ...Array.isArray(entry.tags) ? entry.tags : []].filter((value) => typeof value === "string").join(" ").toLowerCase();
|
|
1236
1236
|
var sourceHash = (document) => typeof document.contentHash === "string" && document.contentHash.length > 0 ? document.contentHash : hashJson(document);
|
|
1237
|
+
var tokenSeparator = /[^\p{L}\p{N}@/_-]+/gu;
|
|
1238
|
+
var tokenize = (value) => value.toLowerCase().split(tokenSeparator).filter((token) => token.length >= 2);
|
|
1239
|
+
var containsToken = (value, token) => {
|
|
1240
|
+
if (/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}]/u.test(token)) return value.includes(token);
|
|
1241
|
+
const escaped = token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1242
|
+
return new RegExp(`(?:^|[^\\p{L}\\p{N}])${escaped}(?:s|es)?(?:[^\\p{L}\\p{N}]|$)`, "u").test(value);
|
|
1243
|
+
};
|
|
1244
|
+
var score = (value, query) => tokenize(query).reduce((total, token) => total + (containsToken(value, token) ? token.length : 0), 0);
|
|
1237
1245
|
var matches = (entry, query) => {
|
|
1238
|
-
const needle = query.query.trim()
|
|
1239
|
-
|
|
1246
|
+
const needle = query.query.trim();
|
|
1247
|
+
if (!needle) return 0;
|
|
1240
1248
|
const value = text(entry);
|
|
1241
|
-
|
|
1249
|
+
if (query.scope?.length && !query.scope.some((scope) => containsToken(value, scope.toLowerCase()))) return 0;
|
|
1250
|
+
return score(value, needle);
|
|
1251
|
+
};
|
|
1252
|
+
var ownershipEntries = (document) => {
|
|
1253
|
+
if (typeof document.lookup !== "object" || document.lookup === null || Array.isArray(document.lookup)) return [];
|
|
1254
|
+
const ownership = document.lookup.ownership;
|
|
1255
|
+
if (typeof ownership !== "object" || ownership === null || Array.isArray(ownership)) return [];
|
|
1256
|
+
return Object.entries(ownership).flatMap(([id2, value]) => {
|
|
1257
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return [];
|
|
1258
|
+
const owner = value;
|
|
1259
|
+
const path = typeof owner["agentDoc"] === "string" ? owner["agentDoc"] : owner["path"];
|
|
1260
|
+
if (!path) return [];
|
|
1261
|
+
const description = typeof owner["purpose"] === "string" ? owner["purpose"] : void 0;
|
|
1262
|
+
const body3 = [owner["purpose"], owner["group"], owner["layer"], owner["agentDoc"], owner["humanDoc"]].filter((item) => typeof item === "string").join(" ");
|
|
1263
|
+
return [{ id: typeof owner["id"] === "string" ? owner["id"] : id2, type: "ownership", path, ...description ? { description } : {}, ...body3 ? { body: body3 } : {} }];
|
|
1264
|
+
});
|
|
1242
1265
|
};
|
|
1243
1266
|
var inspectDocBridgeIndex = (root, indexPath = ".doc-bridge/index.json", now4 = Date.now()) => {
|
|
1244
1267
|
const path = resolve(root, indexPath);
|
|
@@ -1253,15 +1276,30 @@ var inspectDocBridgeIndex = (root, indexPath = ".doc-bridge/index.json", now4 =
|
|
|
1253
1276
|
return { present: true, path, contentHash: null, mtimeMs: null, ageHours: null, error: error instanceof Error ? error.message : String(error) };
|
|
1254
1277
|
}
|
|
1255
1278
|
};
|
|
1256
|
-
var createDocBridgeContextProvider = ({ root, indexPath = ".doc-bridge/index.json" }) => ({
|
|
1279
|
+
var createDocBridgeContextProvider = ({ root, indexPath = ".doc-bridge/index.json", maxAgeHours, now: now4 = Date.now }) => ({
|
|
1257
1280
|
id: "doc-bridge",
|
|
1258
|
-
version: "1.
|
|
1281
|
+
version: "1.1.0",
|
|
1259
1282
|
resolve: async (query) => {
|
|
1260
1283
|
const started = Date.now();
|
|
1284
|
+
const ageBudget = maxAgeHours ?? 0;
|
|
1285
|
+
const inspection = ageBudget > 0 ? inspectDocBridgeIndex(root, indexPath, now4()) : null;
|
|
1286
|
+
if (inspection?.error) throw new Error(`Doc Bridge index is unreadable: ${inspection.error}`);
|
|
1287
|
+
if (inspection?.ageHours !== null && inspection?.ageHours !== void 0 && inspection.ageHours > ageBudget) {
|
|
1288
|
+
throw new Error(`Doc Bridge index is ${inspection.ageHours.toFixed(1)}h old; refresh it before resolving context.`);
|
|
1289
|
+
}
|
|
1261
1290
|
const document = index(root, indexPath);
|
|
1262
1291
|
const contentHash = sourceHash(document);
|
|
1263
|
-
const
|
|
1264
|
-
const
|
|
1292
|
+
const knowledge = Array.isArray(document.knowledge) ? document.knowledge.filter((value) => typeof value === "object" && value !== null && !Array.isArray(value)) : [];
|
|
1293
|
+
const ranked = [...knowledge, ...ownershipEntries(document)].map((entry) => ({ entry, score: matches(entry, query) })).filter(({ score: entryScore }) => entryScore > 0);
|
|
1294
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
1295
|
+
for (const candidate of ranked) {
|
|
1296
|
+
const path = typeof candidate.entry.path === "string" ? candidate.entry.path : String(candidate.entry.id ?? "");
|
|
1297
|
+
const current = byPath.get(path);
|
|
1298
|
+
if (!current || candidate.score > current.score || candidate.score === current.score && candidate.entry.type === "ownership" && current.entry.type !== "ownership") byPath.set(path, candidate);
|
|
1299
|
+
}
|
|
1300
|
+
const entries = [...byPath.values()].sort((left, right) => right.score - left.score || String(left.entry.id ?? "").localeCompare(String(right.entry.id ?? ""))).slice(0, 8);
|
|
1301
|
+
const maxScore = entries[0]?.score ?? 1;
|
|
1302
|
+
const references = entries.flatMap(({ entry, score: entryScore }) => typeof entry.id === "string" && typeof entry.path === "string" ? [{ id: entry.id, uri: `doc-bridge://${entry.path}`, ...typeof entry.title === "string" ? { title: entry.title } : {}, contentHash: typeof entry.contentHash === "string" ? entry.contentHash : contentHash, relevance: entryScore / maxScore }] : []);
|
|
1265
1303
|
const telemetry = { status: "measured", durationMs: Date.now() - started, contextReferences: references.length, contextCostTokens: Math.max(1, Math.ceil(JSON.stringify(references).length / 4)) };
|
|
1266
1304
|
return { providerId: "doc-bridge", query, references, sourceHash: contentHash, snapshotHash: hashContextSnapshot({ providerId: "doc-bridge", query, references, sourceHash: contentHash }), resolvedAt: (/* @__PURE__ */ new Date()).toISOString(), assurance: "contract-tested", telemetry };
|
|
1267
1305
|
}
|
|
@@ -1970,7 +2008,7 @@ var digest4 = (value, label) => {
|
|
|
1970
2008
|
if (!/^[a-f0-9]{64}$/.test(result)) fail(`${label} must be a lowercase SHA-256 digest.`, "INVALID_INPUT");
|
|
1971
2009
|
return result;
|
|
1972
2010
|
};
|
|
1973
|
-
var
|
|
2011
|
+
var score2 = (value, label) => {
|
|
1974
2012
|
const numeric = typeof value === "number" ? value : Number.NaN;
|
|
1975
2013
|
if (!Number.isFinite(numeric) || numeric < 0 || numeric > 100) fail(`${label} must be a number between 0 and 100.`, "INVALID_INPUT");
|
|
1976
2014
|
return numeric;
|
|
@@ -1988,7 +2026,7 @@ var validateCase = (value, index2) => {
|
|
|
1988
2026
|
return component2;
|
|
1989
2027
|
});
|
|
1990
2028
|
if (new Set(normalizedComponents).size !== normalizedComponents.length) fail(`cases[${index2}].components must not contain duplicates.`, "INVALID_INPUT");
|
|
1991
|
-
const baselineScore = candidate["baselineScore"] === void 0 ? void 0 :
|
|
2029
|
+
const baselineScore = candidate["baselineScore"] === void 0 ? void 0 : score2(candidate["baselineScore"], `cases[${index2}].baselineScore`);
|
|
1992
2030
|
return {
|
|
1993
2031
|
id: nonEmpty4(candidate["id"], `cases[${index2}].id`),
|
|
1994
2032
|
layer,
|
|
@@ -2026,7 +2064,7 @@ var manifestBody2 = (value) => {
|
|
|
2026
2064
|
name: nonEmpty4(value["name"], "name"),
|
|
2027
2065
|
cases,
|
|
2028
2066
|
graders,
|
|
2029
|
-
thresholds: { subjectiveQuality:
|
|
2067
|
+
thresholds: { subjectiveQuality: score2(thresholds2["subjectiveQuality"] ?? 80, "thresholds.subjectiveQuality"), maxRegression: score2(thresholds2["maxRegression"] ?? 5, "thresholds.maxRegression") },
|
|
2030
2068
|
repetitions,
|
|
2031
2069
|
provider: nonEmpty4(value["provider"], "provider"),
|
|
2032
2070
|
model: nonEmpty4(value["model"], "model"),
|
|
@@ -2251,6 +2289,14 @@ var createKvMemoryAdapter = (store, options = {}) => {
|
|
|
2251
2289
|
const scopeMatch = record3.scope === "global" || (record3.scope === "issue" ? Boolean(issueId && record3.source.includes(issueId)) : Boolean(project && record3.source.includes(project)));
|
|
2252
2290
|
return scopeMatch && (!query || `${record3.summary} ${record3.source}`.toLowerCase().includes(query));
|
|
2253
2291
|
};
|
|
2292
|
+
let allRecordsCache = null;
|
|
2293
|
+
const allRecords = async () => {
|
|
2294
|
+
if (allRecordsCache) return allRecordsCache;
|
|
2295
|
+
const ids = await store.get(indexKey);
|
|
2296
|
+
const records = Array.isArray(ids) ? await Promise.all(ids.filter((id2) => typeof id2 === "string").map((id2) => store.get(`agentskit-harness:memory:${id2}`))) : [];
|
|
2297
|
+
allRecordsCache = records.filter((record3) => Boolean(record3 && typeof record3 === "object" && record3.approved === true));
|
|
2298
|
+
return allRecordsCache;
|
|
2299
|
+
};
|
|
2254
2300
|
return {
|
|
2255
2301
|
id: options.id ?? "agentskit-kv",
|
|
2256
2302
|
version: options.version ?? "1",
|
|
@@ -2262,13 +2308,13 @@ var createKvMemoryAdapter = (store, options = {}) => {
|
|
|
2262
2308
|
const index2 = Array.isArray(ids) ? ids.filter((id2) => typeof id2 === "string") : [];
|
|
2263
2309
|
if (!index2.includes(valid.id)) await store.set(indexKey, [...index2, valid.id].sort());
|
|
2264
2310
|
await store.set(`agentskit-harness:memory:${valid.id}`, valid);
|
|
2311
|
+
allRecordsCache = null;
|
|
2265
2312
|
writes += 1;
|
|
2266
2313
|
},
|
|
2267
2314
|
async recall({ query, issueId, project, sourceRevision }) {
|
|
2268
2315
|
reads += 1;
|
|
2269
|
-
const
|
|
2270
|
-
const
|
|
2271
|
-
const hits = records.filter((record3) => Boolean(record3 && typeof record3 === "object" && record3.approved === true)).filter((record3) => matches2(record3, query.trim().toLowerCase(), issueId, project)).map((record3) => ({ record: record3, relevant: true, stale: sourceRevision !== void 0 && record3.sourceRevision !== sourceRevision }));
|
|
2316
|
+
const records = await allRecords();
|
|
2317
|
+
const hits = records.filter((record3) => matches2(record3, query.trim().toLowerCase(), issueId, project)).map((record3) => ({ record: record3, relevant: true, stale: sourceRevision !== void 0 && record3.sourceRevision !== sourceRevision }));
|
|
2272
2318
|
relevantHits += hits.length;
|
|
2273
2319
|
staleHits += hits.filter((hit) => hit.stale).length;
|
|
2274
2320
|
return hits;
|
|
@@ -2708,12 +2754,12 @@ var validatePhaseTelemetry = (value) => {
|
|
|
2708
2754
|
...machine ? { machine } : {}
|
|
2709
2755
|
};
|
|
2710
2756
|
};
|
|
2711
|
-
var average = (values) => values.length ? Number((values.reduce((
|
|
2712
|
-
var
|
|
2757
|
+
var average = (values) => values.length ? Number((values.reduce((sum2, value) => sum2 + value, 0) / values.length).toFixed(2)) : null;
|
|
2758
|
+
var score3 = (value, source, baseline = null) => ({ score: value === null ? null : Math.max(0, Math.min(100, Number(value.toFixed(2)))), status: value === null ? "unknown" : "measured", baselineDelta: value === null || baseline === null ? null : Number((value - baseline).toFixed(2)), source });
|
|
2713
2759
|
var evaluateWatchdog = ({ phases, budget }) => {
|
|
2714
2760
|
const blockers = [];
|
|
2715
|
-
const duration5 = phases.every((phase2) => phase2.durationMs !== void 0) ? phases.reduce((
|
|
2716
|
-
const totalTokens = phases.every((phase2) => phase2.tokens?.inputTokens !== void 0 && phase2.tokens.outputTokens !== void 0) ? phases.reduce((
|
|
2761
|
+
const duration5 = phases.every((phase2) => phase2.durationMs !== void 0) ? phases.reduce((sum2, phase2) => sum2 + (phase2.durationMs ?? 0), 0) : void 0;
|
|
2762
|
+
const totalTokens = phases.every((phase2) => phase2.tokens?.inputTokens !== void 0 && phase2.tokens.outputTokens !== void 0) ? phases.reduce((sum2, phase2) => sum2 + (phase2.tokens?.inputTokens ?? 0) + (phase2.tokens?.outputTokens ?? 0), 0) : void 0;
|
|
2717
2763
|
if (budget.maxDurationMs !== void 0 && duration5 !== void 0 && duration5 > budget.maxDurationMs) blockers.push({ class: "budget", reason: `Duration budget exceeded: ${duration5}ms > ${budget.maxDurationMs}ms.` });
|
|
2718
2764
|
if (budget.maxTotalTokens !== void 0 && totalTokens !== void 0 && totalTokens > budget.maxTotalTokens) blockers.push({ class: "budget", reason: `Token budget exceeded: ${totalTokens} > ${budget.maxTotalTokens}.` });
|
|
2719
2765
|
for (const phase2 of phases) {
|
|
@@ -2729,16 +2775,16 @@ var createQualityMatrix = ({ phases, baseline, budget = {} }) => {
|
|
|
2729
2775
|
const priorDurations = prior.flatMap((phase2) => phase2.durationMs === void 0 ? [] : [phase2.durationMs]);
|
|
2730
2776
|
const currentTokens = current.flatMap((phase2) => phase2.tokens?.inputTokens !== void 0 && phase2.tokens.outputTokens !== void 0 ? [phase2.tokens.inputTokens + phase2.tokens.outputTokens] : []);
|
|
2731
2777
|
const priorTokens = prior.flatMap((phase2) => phase2.tokens?.inputTokens !== void 0 && phase2.tokens.outputTokens !== void 0 ? [phase2.tokens.inputTokens + phase2.tokens.outputTokens] : []);
|
|
2732
|
-
const correctness =
|
|
2733
|
-
const completeness =
|
|
2734
|
-
const speed =
|
|
2735
|
-
const cost =
|
|
2778
|
+
const correctness = score3(average(current.map((phase2) => phase2.evidenceCoverage === void 0 ? 0 : phase2.evidenceCoverage * 100)), "mean evidence coverage");
|
|
2779
|
+
const completeness = score3(current.length ? current.filter((phase2) => phase2.outcome === "pass").length / current.length * 100 : null, "passed phases / total phases");
|
|
2780
|
+
const speed = score3(currentDurations.length && priorDurations.length ? average(priorDurations) / Math.max(1, average(currentDurations)) * 100 : null, "baseline duration / current duration", 100);
|
|
2781
|
+
const cost = score3(currentTokens.length && priorTokens.length ? average(priorTokens) / Math.max(1, average(currentTokens)) * 100 : null, "baseline tokens / current tokens", 100);
|
|
2736
2782
|
const resourceValues = current.flatMap((phase2) => phase2.machine?.cpuPercent !== void 0 && phase2.machine.memoryUsedPercent !== void 0 ? [100 - Math.max(phase2.machine.cpuPercent, phase2.machine.memoryUsedPercent)] : []);
|
|
2737
|
-
const resource =
|
|
2738
|
-
const reliability =
|
|
2783
|
+
const resource = score3(average(resourceValues), "100 - max(cpu%, memory%)");
|
|
2784
|
+
const reliability = score3(current.length ? current.filter((phase2) => phase2.outcome === "pass").length / current.length * 100 : null, "passed phases / total phases");
|
|
2739
2785
|
const dimensions = { correctness, completeness, speed, cost, resource, reliability };
|
|
2740
2786
|
const measured = Object.values(dimensions).filter((item) => item.score !== null).map((item) => item.score);
|
|
2741
|
-
const overall =
|
|
2787
|
+
const overall = score3(average(measured), "mean of measured dimensions");
|
|
2742
2788
|
const unknownMetricCount = Object.values(dimensions).filter((item) => item.status === "unknown").length + current.filter((phase2) => phase2.durationMs === void 0 || phase2.tokens === void 0 || phase2.machine === void 0).length;
|
|
2743
2789
|
const blockers = evaluateWatchdog({ phases: current, budget }).blockers;
|
|
2744
2790
|
const body3 = { type: "agentskit-harness-quality-matrix", schemaVersion: 1, dimensions, overall, phaseCount: current.length, unknownMetricCount, blockers };
|
|
@@ -4236,10 +4282,16 @@ var orcaTerminalCreate = async (runner, input, options = {}) => {
|
|
|
4236
4282
|
};
|
|
4237
4283
|
var parseOrcaSendReceipt = (result) => {
|
|
4238
4284
|
const record3 = isRecord8(result) ? result : {};
|
|
4239
|
-
const
|
|
4240
|
-
const
|
|
4241
|
-
const
|
|
4242
|
-
|
|
4285
|
+
const send = isRecord8(record3["send"]) ? record3["send"] : null;
|
|
4286
|
+
const prompt = send && isRecord8(send["prompt"]) ? send["prompt"] : null;
|
|
4287
|
+
const receipt = isRecord8(record3["receipt"]) ? record3["receipt"] : send ?? record3;
|
|
4288
|
+
const rawStages = Array.isArray(receipt["stages"]) ? receipt["stages"] : prompt && Array.isArray(prompt["stages"]) ? prompt["stages"] : [];
|
|
4289
|
+
const stages = rawStages.map((stage) => isRecord8(stage) ? str(stage["stage"], str(stage["name"])) : str(stage)).filter(Boolean);
|
|
4290
|
+
const inputAccepted = stages.some((stage) => ["input_accepted", "input_queued", "prompt_accepted", "queued"].includes(stage.toLowerCase()));
|
|
4291
|
+
const acceptedValue = receipt["accepted"] ?? send?.["accepted"];
|
|
4292
|
+
const accepted = inputAccepted || acceptedValue === true || acceptedValue !== false && (result === null || result === void 0 || Object.keys(record3).length === 0);
|
|
4293
|
+
const warnings = Array.isArray(record3["warnings"]) ? record3["warnings"] : send && Array.isArray(send["warnings"]) ? send["warnings"] : [];
|
|
4294
|
+
return { accepted, requestId: str(receipt["requestId"], str(prompt?.["requestId"], str(record3["requestId"]))) || null, stages, warnings: warnings.map((warning) => isRecord8(warning) ? str(warning["message"], JSON.stringify(warning)) : str(warning)) };
|
|
4243
4295
|
};
|
|
4244
4296
|
var orcaTerminalSend = async (runner, input, options = {}) => parseOrcaSendReceipt(await orcaJson(runner, ["terminal", "send", "--terminal", input.terminal, "--text", input.text, ...input.enter === false ? [] : ["--enter"], ...input.waitSubmitSeconds ? ["--wait-submit", String(input.waitSubmitSeconds)] : []], { ...options, timeoutMs: options.timeoutMs ?? (input.waitSubmitSeconds ?? 0) * 1e3 + 3e4 }));
|
|
4245
4297
|
var orcaTerminalWait = async (runner, input, options = {}) => {
|
|
@@ -4499,6 +4551,8 @@ var LoopConfigSchema = z.object({
|
|
|
4499
4551
|
}).prefault({}),
|
|
4500
4552
|
catalog: z.object({
|
|
4501
4553
|
sources: z.array(z.enum(["cli", "artificial-analysis", "builtin"])).default(["cli", "builtin"]),
|
|
4554
|
+
/** How long a provider's CLI-discovered model list (e.g. `grok models`) is trusted before spawning the CLI again — it rarely changes between releases. */
|
|
4555
|
+
cliCacheHours: z.number().positive().default(6),
|
|
4502
4556
|
artificialAnalysis: z.object({
|
|
4503
4557
|
enabled: z.boolean().default(false),
|
|
4504
4558
|
apiKeyEnv: nonEmpty5.default("ARTIFICIAL_ANALYSIS_API_KEY"),
|
|
@@ -5069,7 +5123,12 @@ var selectModel = (config, role, availability, extraCandidates = []) => {
|
|
|
5069
5123
|
var routeAllRoles = (config, availability, extrasByRole = {}) => Object.fromEntries(MODEL_ROLES.map((role) => [role, selectModel(config, role, availability, extrasByRole[role] ?? [])]));
|
|
5070
5124
|
var rankModels = (config, role, availability, extraCandidates = []) => {
|
|
5071
5125
|
const byId = new Map(availability.map((item) => [item.id, item]));
|
|
5072
|
-
const { ranked } = availableFromTiers(config, role, availability);
|
|
5126
|
+
const { ranked, skipped } = availableFromTiers(config, role, availability);
|
|
5127
|
+
if (config.models.routing.pin[role]) {
|
|
5128
|
+
const pinned = applyPin(config, role, availability, skipped);
|
|
5129
|
+
if (pinned) return [pinned, ...ranked.filter((item) => !(item.provider === pinned.provider && item.model === pinned.model))];
|
|
5130
|
+
if (config.models.routing.pinStrict) return [];
|
|
5131
|
+
}
|
|
5073
5132
|
const extras = [];
|
|
5074
5133
|
let extraIndex = 1e4;
|
|
5075
5134
|
for (const ref of extraCandidates) {
|
|
@@ -5190,6 +5249,32 @@ ${outcome.stderr}`);
|
|
|
5190
5249
|
}
|
|
5191
5250
|
return [];
|
|
5192
5251
|
};
|
|
5252
|
+
var cliModelsCachePath = (stateDir, provider) => join(stateDir, "catalog", `cli-${provider}.json`);
|
|
5253
|
+
var readCliModelsCache = (stateDir, provider) => {
|
|
5254
|
+
const path = cliModelsCachePath(stateDir, provider);
|
|
5255
|
+
if (!existsSync(path)) return null;
|
|
5256
|
+
try {
|
|
5257
|
+
const raw = readJson2(path);
|
|
5258
|
+
return typeof raw.fetchedAt === "string" && Array.isArray(raw.ids) ? { fetchedAt: raw.fetchedAt, ids: raw.ids } : null;
|
|
5259
|
+
} catch {
|
|
5260
|
+
return null;
|
|
5261
|
+
}
|
|
5262
|
+
};
|
|
5263
|
+
var writeCliModelsCache = (stateDir, provider, ids, now4 = /* @__PURE__ */ new Date()) => {
|
|
5264
|
+
const path = cliModelsCachePath(stateDir, provider);
|
|
5265
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
5266
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
5267
|
+
writeFileSync(tmp, `${JSON.stringify({ fetchedAt: now4.toISOString(), ids }, null, 2)}
|
|
5268
|
+
`, "utf8");
|
|
5269
|
+
renameSync(tmp, path);
|
|
5270
|
+
};
|
|
5271
|
+
var listCliModelsCached = async (provider, bin, runner, stateDir, cacheHours, now4 = () => /* @__PURE__ */ new Date()) => {
|
|
5272
|
+
const cached = readCliModelsCache(stateDir, provider);
|
|
5273
|
+
if (cached && now4().getTime() - Date.parse(cached.fetchedAt) <= cacheHours * 36e5) return cached.ids;
|
|
5274
|
+
const ids = await listCliModels(provider, bin, runner);
|
|
5275
|
+
if (ids.length) writeCliModelsCache(stateDir, provider, ids, now4());
|
|
5276
|
+
return ids.length ? ids : cached?.ids ?? [];
|
|
5277
|
+
};
|
|
5193
5278
|
var parseArtificialAnalysisPayload = (payload) => {
|
|
5194
5279
|
const root = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
5195
5280
|
const data = Array.isArray(root["data"]) ? root["data"] : Array.isArray(payload) ? payload : [];
|
|
@@ -5274,7 +5359,7 @@ var resolveCatalogCandidates = async (input) => {
|
|
|
5274
5359
|
const settings = config.models.providers[provider];
|
|
5275
5360
|
if (settings) {
|
|
5276
5361
|
try {
|
|
5277
|
-
const ids = await listCliModels(provider, settings.bin, input.runner);
|
|
5362
|
+
const ids = input.stateDir ? await listCliModelsCached(provider, settings.bin, input.runner, input.stateDir, config.models.catalog.cliCacheHours, input.now) : await listCliModels(provider, settings.bin, input.runner);
|
|
5278
5363
|
for (const id2 of ids) {
|
|
5279
5364
|
const resolved = resolveAlias(provider, id2, aliases);
|
|
5280
5365
|
const existing = builtin[provider]?.models.find((model) => model.id === resolved);
|
|
@@ -5306,9 +5391,9 @@ var resolveCatalogCandidates = async (input) => {
|
|
|
5306
5391
|
const matches2 = models.models.filter((model) => model.creatorSlug === creator || model.creatorSlug.includes(creator));
|
|
5307
5392
|
for (const model of matches2) {
|
|
5308
5393
|
const id2 = resolveAlias(provider, model.slug, aliases);
|
|
5309
|
-
const
|
|
5310
|
-
const quality =
|
|
5311
|
-
push(provider, { id: id2, quality, codingScore:
|
|
5394
|
+
const score4 = model.codingIndex ?? model.intelligenceIndex ?? 50;
|
|
5395
|
+
const quality = score4 >= 80 ? "frontier" : score4 >= 60 ? "balanced" : "fast";
|
|
5396
|
+
push(provider, { id: id2, quality, codingScore: score4, source: "artificial-analysis", creator });
|
|
5312
5397
|
}
|
|
5313
5398
|
}
|
|
5314
5399
|
}
|
|
@@ -5366,6 +5451,16 @@ var clearProviderCooldown = (stateDir, provider) => {
|
|
|
5366
5451
|
writeCooldowns(stateDir, rest);
|
|
5367
5452
|
};
|
|
5368
5453
|
var rotationStatePath = (stateDir) => join(stateDir, "queue-owner.json");
|
|
5454
|
+
var countRotationBlockingLeases = (loaded, leases) => leases.filter((lease) => {
|
|
5455
|
+
const path = join(loaded.stateDir, "issues", lease.issue, "delivery.json");
|
|
5456
|
+
if (!existsSync(path)) return true;
|
|
5457
|
+
try {
|
|
5458
|
+
const delivery = JSON.parse(readFileSync(path, "utf8"));
|
|
5459
|
+
return delivery.prNumber == null && !delivery.heldFor && !delivery.finalOutcome;
|
|
5460
|
+
} catch {
|
|
5461
|
+
return true;
|
|
5462
|
+
}
|
|
5463
|
+
}).length;
|
|
5369
5464
|
var queueOwner = (loaded) => {
|
|
5370
5465
|
const { rotation } = loaded.config.linear;
|
|
5371
5466
|
if (!rotation.enabled || !rotation.owners.length) return loaded.config.linear.person;
|
|
@@ -5860,10 +5955,10 @@ var planMemoryContext = async (input) => {
|
|
|
5860
5955
|
hits = [];
|
|
5861
5956
|
}
|
|
5862
5957
|
const selected = selectMemoryForPrompt(hits, memory);
|
|
5863
|
-
const beforeChars = input.references.reduce((
|
|
5958
|
+
const beforeChars = input.references.reduce((sum2, ref) => sum2 + JSON.stringify(ref).length, 0) + issueBudgetDefault;
|
|
5864
5959
|
const preferred = memory.preferOverDocBridge ? preferMemoryOverDocBridge(input.references, selected.hits, memory.minDocBridgeWhenMemory) : { references: input.references};
|
|
5865
5960
|
const issueCharBudget = selected.hits.length && memory.shrinkIssueCharsWhenMemory ? Math.min(issueBudgetDefault, memory.issueCharsWithMemory) : issueBudgetDefault;
|
|
5866
|
-
const afterChars = preferred.references.reduce((
|
|
5961
|
+
const afterChars = preferred.references.reduce((sum2, ref) => sum2 + JSON.stringify(ref).length, 0) + issueCharBudget + selected.approxChars;
|
|
5867
5962
|
return {
|
|
5868
5963
|
hits: selected.hits,
|
|
5869
5964
|
references: preferred.references,
|
|
@@ -6420,9 +6515,14 @@ var writeDispatchRecord = (stateDir, record3) => {
|
|
|
6420
6515
|
writeJson2(path, record3);
|
|
6421
6516
|
return path;
|
|
6422
6517
|
};
|
|
6423
|
-
var
|
|
6518
|
+
var EVENTS_ROTATE_AT_BYTES = 10 * 1024 * 1024;
|
|
6519
|
+
var appendLoopEvent = (stateDir, event2, bus, now4 = () => /* @__PURE__ */ new Date()) => {
|
|
6424
6520
|
const path = join(stateDir, "events.ndjson");
|
|
6425
6521
|
mkdirSync(dirname(path), { recursive: true });
|
|
6522
|
+
try {
|
|
6523
|
+
if (statSync(path).size > EVENTS_ROTATE_AT_BYTES) renameSync(path, join(stateDir, `events-archive-${now4().getTime()}.ndjson`));
|
|
6524
|
+
} catch {
|
|
6525
|
+
}
|
|
6426
6526
|
appendFileSync(path, `${JSON.stringify(event2)}
|
|
6427
6527
|
`, "utf8");
|
|
6428
6528
|
if (bus && typeof event2["type"] === "string") bus.emit(event2);
|
|
@@ -6454,7 +6554,7 @@ var gatherLoopState = async (input) => {
|
|
|
6454
6554
|
const leases = input.ledger.active();
|
|
6455
6555
|
const busy = busyIssues(queue, leases, worktrees, person);
|
|
6456
6556
|
const candidates = queue.filter((issue) => !busy.has(issue.identifier) && (!input.onlyIssue || issue.identifier === input.onlyIssue));
|
|
6457
|
-
return { person, providers, routing, worktrees, slots, queue, leases, busy, candidates };
|
|
6557
|
+
return { person, providers, routing, worktrees, slots, queue, leases, busy, candidates, extrasByRole };
|
|
6458
6558
|
};
|
|
6459
6559
|
var precheckTick = async (input) => {
|
|
6460
6560
|
const loaded = input.loaded ?? loadLoopConfig(input.configPath);
|
|
@@ -6495,16 +6595,7 @@ var runTick = async (input) => {
|
|
|
6495
6595
|
}
|
|
6496
6596
|
const state = await gatherLoopState({ loaded, runner: input.runner, ledger, env: input.env, platform: input.platform, now: now4, onlyIssue: input.onlyIssue, machine: input.machine });
|
|
6497
6597
|
const orchestrator = state.routing["orchestrator"] ?? { role: "orchestrator", selected: null, skipped: [] };
|
|
6498
|
-
const
|
|
6499
|
-
config,
|
|
6500
|
-
role: "orchestrator",
|
|
6501
|
-
availableProviderIds: state.providers.filter((provider) => provider.available).map((provider) => provider.id),
|
|
6502
|
-
runner: input.runner,
|
|
6503
|
-
stateDir: loaded.stateDir,
|
|
6504
|
-
env: input.env,
|
|
6505
|
-
now: now4
|
|
6506
|
-
}) : [];
|
|
6507
|
-
const orchestratorCandidates = rankModels(config, "orchestrator", state.providers, orchestratorExtras);
|
|
6598
|
+
const orchestratorCandidates = rankModels(config, "orchestrator", state.providers, state.extrasByRole["orchestrator"] ?? []);
|
|
6508
6599
|
const onProviderFailure = (failure) => {
|
|
6509
6600
|
if (dryRun) return;
|
|
6510
6601
|
const resetsAt = extractResetsAt(failure.detail, now4());
|
|
@@ -6524,7 +6615,7 @@ var runTick = async (input) => {
|
|
|
6524
6615
|
return { ...base, status: "idle", results, notes };
|
|
6525
6616
|
}
|
|
6526
6617
|
if (!state.candidates.length) {
|
|
6527
|
-
const rotation = dryRun ? { owner: state.person, advanced: false } : advanceQueueOwner(loaded, { queueEmpty: state.queue.length === 0, activeLeases: state.leases
|
|
6618
|
+
const rotation = dryRun ? { owner: state.person, advanced: false } : advanceQueueOwner(loaded, { queueEmpty: state.queue.length === 0, activeLeases: countRotationBlockingLeases(loaded, state.leases), now: now4() });
|
|
6528
6619
|
if (rotation.advanced) notes.push(`queue drained for ${state.person}; switched to ${rotation.owner}`);
|
|
6529
6620
|
else notes.push("queue has no dispatchable candidate");
|
|
6530
6621
|
return { ...base, status: "idle", results, notes };
|
|
@@ -6557,17 +6648,32 @@ The loop will not retry this issue until you remove the \`${config.resilience.pa
|
|
|
6557
6648
|
appendLoopEvent(loaded.stateDir, { at: now4().toISOString(), type: "issue.paused", issue, kind, consecutive: failureState.consecutive, reason }, bus);
|
|
6558
6649
|
await bus.runHook("onPause", { issue, kind, consecutive: failureState.consecutive, reason });
|
|
6559
6650
|
};
|
|
6651
|
+
let pinnedSkillsOnce;
|
|
6652
|
+
const getPinnedSkills = () => {
|
|
6653
|
+
if (pinnedSkillsOnce === void 0) {
|
|
6654
|
+
try {
|
|
6655
|
+
pinnedSkillsOnce = loadPinnedSkills(loaded.root, config.brief.skills, config.brief.maxSkillChars);
|
|
6656
|
+
} catch (error) {
|
|
6657
|
+
pinnedSkillsOnce = { error };
|
|
6658
|
+
throw error;
|
|
6659
|
+
}
|
|
6660
|
+
}
|
|
6661
|
+
if ("error" in pinnedSkillsOnce) throw pinnedSkillsOnce.error;
|
|
6662
|
+
return pinnedSkillsOnce;
|
|
6663
|
+
};
|
|
6560
6664
|
let dispatched = 0;
|
|
6561
6665
|
for (const candidate of state.candidates) {
|
|
6562
6666
|
if (dispatched >= budget) break;
|
|
6563
6667
|
const setupBudgetMs = config.project.setup.command ? Number.isFinite(timeBudgetMs) ? Math.min(config.project.setup.timeoutSec * 1e3, Math.max(0, timeBudgetMs - config.contract.timeoutMs - 125e3)) : config.project.setup.timeoutSec * 1e3 : 0;
|
|
6564
|
-
|
|
6668
|
+
const cachedContract = readStoredContract(loaded.stateDir, candidate.identifier);
|
|
6669
|
+
if (remainingMs() < config.contract.timeoutMs + setupBudgetMs + 12e4 && !cachedContract) {
|
|
6565
6670
|
notes.push(`time budget: ${candidate.identifier} left for the next tick (${Math.round(remainingMs() / 1e3)}s remaining)`);
|
|
6566
6671
|
continue;
|
|
6567
6672
|
}
|
|
6568
|
-
|
|
6673
|
+
const failureState = readIssueFailures(loaded.stateDir, candidate.identifier);
|
|
6674
|
+
if (failureState.pausedAt !== null) {
|
|
6569
6675
|
if (candidate.labels.includes(config.resilience.pausedLabel)) {
|
|
6570
|
-
results.push({ issue: candidate.identifier, outcome: "skipped", reason: `paused after ${
|
|
6676
|
+
results.push({ issue: candidate.identifier, outcome: "skipped", reason: `paused after ${failureState.consecutive} consecutive failures; remove the "${config.resilience.pausedLabel}" label or run "ak-harness loop resume ${candidate.identifier}" to retry` });
|
|
6571
6677
|
continue;
|
|
6572
6678
|
}
|
|
6573
6679
|
if (!dryRun) clearIssueFailures(loaded.stateDir, candidate.identifier);
|
|
@@ -6580,8 +6686,8 @@ The loop will not retry this issue until you remove the \`${config.resilience.pa
|
|
|
6580
6686
|
results.push({ issue: candidate.identifier, outcome: "failed", reason: `issue fetch failed: ${message2(error)}` });
|
|
6581
6687
|
continue;
|
|
6582
6688
|
}
|
|
6583
|
-
let stored =
|
|
6584
|
-
const
|
|
6689
|
+
let stored = cachedContract;
|
|
6690
|
+
const memoryPlan = memory ? await planMemoryContext({
|
|
6585
6691
|
adapter: memory,
|
|
6586
6692
|
config,
|
|
6587
6693
|
issueId: detail.identifier,
|
|
@@ -6589,7 +6695,7 @@ The loop will not retry this issue until you remove the \`${config.resilience.pa
|
|
|
6589
6695
|
project: config.project.name,
|
|
6590
6696
|
references: []
|
|
6591
6697
|
}) : null;
|
|
6592
|
-
if (stored && !contractIsFresh(stored, detail, config.contract.reuseHours, now4(),
|
|
6698
|
+
if (stored && !contractIsFresh(stored, detail, config.contract.reuseHours, now4(), memoryPlan?.memoryDigest)) stored = null;
|
|
6593
6699
|
if (!stored) {
|
|
6594
6700
|
if (input.skipContractGeneration) {
|
|
6595
6701
|
results.push({ issue: detail.identifier, outcome: "skipped", reason: "no cached contract; generation skipped" });
|
|
@@ -6689,16 +6795,9 @@ The loop will not retry this issue until you remove the \`${config.resilience.pa
|
|
|
6689
6795
|
}
|
|
6690
6796
|
if (setupFailed) notes.push(`${detail.identifier}: setup command failed but project.setup.required is false \u2014 continuing`);
|
|
6691
6797
|
}
|
|
6692
|
-
const briefMemory =
|
|
6693
|
-
adapter: memory,
|
|
6694
|
-
config,
|
|
6695
|
-
issueId: detail.identifier,
|
|
6696
|
-
issueTitle: detail.title,
|
|
6697
|
-
project: config.project.name,
|
|
6698
|
-
references: []
|
|
6699
|
-
}) : { memoryBlock: "", issueCharBudget: config.contract.maxIssueChars, hits: [] };
|
|
6798
|
+
const briefMemory = memoryPlan ?? { memoryBlock: "", issueCharBudget: config.contract.maxIssueChars, hits: [] };
|
|
6700
6799
|
const guidanceRefs = config.contract.maxBriefReferences > 0 && config.contract.briefScopes.length ? await resolveDocContext(loaded.root, `${detail.identifier} ${detail.title}`, config.contract.maxBriefReferences, config.contract.briefScopes) : [];
|
|
6701
|
-
const pinnedSkills =
|
|
6800
|
+
const pinnedSkills = getPinnedSkills();
|
|
6702
6801
|
const brief = renderWorkerBrief({
|
|
6703
6802
|
issue: detail,
|
|
6704
6803
|
contract: stored,
|
|
@@ -7028,7 +7127,7 @@ var providerUnavailable = (ctx, providerId) => {
|
|
|
7028
7127
|
return !match || !match.available;
|
|
7029
7128
|
};
|
|
7030
7129
|
var pickHandoffBuilder = (ctx, record3) => {
|
|
7031
|
-
const ranked = rankModels(ctx.config, "builder", ctx.providers);
|
|
7130
|
+
const ranked = rankModels(ctx.config, "builder", ctx.providers, ctx.builderExtras);
|
|
7032
7131
|
const different = ranked.find((candidate) => candidate.provider !== record3.provider || candidate.model !== record3.model);
|
|
7033
7132
|
return different ?? null;
|
|
7034
7133
|
};
|
|
@@ -7469,7 +7568,8 @@ var runDeliver = async (input) => {
|
|
|
7469
7568
|
const availableIds = providers.filter((provider) => provider.available).map((provider) => provider.id);
|
|
7470
7569
|
const catalogExtras = async (role) => config.models.routing.mode === "catalog" ? resolveCatalogCandidates({ config, role, availableProviderIds: availableIds, runner: input.runner, stateDir: loaded.stateDir, env: input.env, now: now4 }) : Promise.resolve([]);
|
|
7471
7570
|
const reviewer = rankModels(config, "reviewer", providers, await catalogExtras("reviewer"))[0] ?? null;
|
|
7472
|
-
const
|
|
7571
|
+
const builderExtras = await catalogExtras("builder");
|
|
7572
|
+
const builder = rankModels(config, "builder", providers, builderExtras)[0] ?? null;
|
|
7473
7573
|
let env = input.env ?? process.env;
|
|
7474
7574
|
if (!env["GITHUB_TOKEN"] && !env["GH_TOKEN"]) {
|
|
7475
7575
|
try {
|
|
@@ -7485,13 +7585,14 @@ var runDeliver = async (input) => {
|
|
|
7485
7585
|
const { errors } = await loadLoopPlugins(loaded.root, config.plugins.modules, bus);
|
|
7486
7586
|
for (const failure of errors) notes.push(`plugin ${failure.path} failed to load: ${failure.error}`);
|
|
7487
7587
|
}
|
|
7488
|
-
const ctx = { loaded, config, runner: input.runner, now: now4, dryRun, reviewer, builder, providers, env, ...input.assumeIdle === void 0 ? {} : { assumeIdle: input.assumeIdle }, notes, reviewDeadlineMs, bus };
|
|
7588
|
+
const ctx = { loaded, config, runner: input.runner, now: now4, dryRun, reviewer, builder, providers, env, ...input.assumeIdle === void 0 ? {} : { assumeIdle: input.assumeIdle }, notes, reviewDeadlineMs, bus, builderExtras };
|
|
7489
7589
|
const ledger = createDispatchLedger(loaded.stateDir);
|
|
7490
7590
|
const leases = new Map(ledger.active().map((lease) => [lease.issue, lease]));
|
|
7491
7591
|
const results = [];
|
|
7492
7592
|
for (const record3 of listDispatched(loaded.stateDir)) {
|
|
7493
7593
|
if (input.onlyIssue && record3.issue !== input.onlyIssue) continue;
|
|
7494
7594
|
let state = readDeliveryState(loaded.stateDir, record3.issue);
|
|
7595
|
+
if (state.finishedAt && state.finalOutcome === "merged") continue;
|
|
7495
7596
|
const lease = leases.get(record3.issue);
|
|
7496
7597
|
if (!state.finishedAt) {
|
|
7497
7598
|
const ageMinutes = minutesBetween(now4(), record3.dispatchedAt);
|
|
@@ -7530,7 +7631,6 @@ var runDeliver = async (input) => {
|
|
|
7530
7631
|
results.push(await handlePullRequest(ctx, record3, lease, state, pr));
|
|
7531
7632
|
continue;
|
|
7532
7633
|
}
|
|
7533
|
-
if (state.finishedAt && state.finalOutcome === "merged") continue;
|
|
7534
7634
|
const recordedMerge = readMergedEvent(loaded.stateDir, record3.issue);
|
|
7535
7635
|
if (recordedMerge) {
|
|
7536
7636
|
try {
|
|
@@ -8091,10 +8191,19 @@ ${step && total ? `${step}/${total} ` : ""}${title}`),
|
|
|
8091
8191
|
] }))
|
|
8092
8192
|
};
|
|
8093
8193
|
};
|
|
8194
|
+
var newestIssueMtimeMs = (stateDir, issue) => {
|
|
8195
|
+
const mtimes = [dispatchRecordPath(stateDir, issue), deliveryStatePath(stateDir, issue), contractPath(stateDir, issue)].map((path) => {
|
|
8196
|
+
try {
|
|
8197
|
+
return statSync(path).mtimeMs;
|
|
8198
|
+
} catch {
|
|
8199
|
+
return null;
|
|
8200
|
+
}
|
|
8201
|
+
}).filter((value) => value !== null);
|
|
8202
|
+
return mtimes.length ? Math.max(...mtimes) : null;
|
|
8203
|
+
};
|
|
8094
8204
|
var HARNESS_REPO_URL = "https://github.com/AgentsKit-io/harness";
|
|
8095
8205
|
var isRecord14 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8096
|
-
var
|
|
8097
|
-
const path = join(stateDir, "events.ndjson");
|
|
8206
|
+
var parseEventsFile = (path) => {
|
|
8098
8207
|
if (!existsSync(path)) return [];
|
|
8099
8208
|
return readFileSync(path, "utf8").split(/\r?\n/).filter(Boolean).flatMap((line2) => {
|
|
8100
8209
|
try {
|
|
@@ -8105,6 +8214,11 @@ var readLoopEvents = (stateDir) => {
|
|
|
8105
8214
|
}
|
|
8106
8215
|
});
|
|
8107
8216
|
};
|
|
8217
|
+
var eventsArchivePattern = /^events-archive-(\d+)\.ndjson$/;
|
|
8218
|
+
var readLoopEvents = (stateDir, sinceMs) => {
|
|
8219
|
+
const archives = existsSync(stateDir) ? readdirSync(stateDir).map((name2) => name2.match(eventsArchivePattern)).filter((match) => match !== null).map((match) => ({ path: join(stateDir, match[0]), rotatedAtMs: Number(match[1]) })).filter((archive) => sinceMs === void 0 || archive.rotatedAtMs >= sinceMs).sort((a, b) => a.rotatedAtMs - b.rotatedAtMs) : [];
|
|
8220
|
+
return [...archives.flatMap((archive) => parseEventsFile(archive.path)), ...parseEventsFile(join(stateDir, "events.ndjson"))];
|
|
8221
|
+
};
|
|
8108
8222
|
var parseSince = (value, now4) => {
|
|
8109
8223
|
if (!value) return new Date(now4.getTime() - 7 * 864e5);
|
|
8110
8224
|
const match = value.match(/^(\d+)([dhm])$/);
|
|
@@ -8151,10 +8265,11 @@ var buildSuggestions = (input) => {
|
|
|
8151
8265
|
var buildRetroReport = async (input) => {
|
|
8152
8266
|
const loaded = input.loaded ?? loadLoopConfig(input.configPath);
|
|
8153
8267
|
const { config } = loaded;
|
|
8268
|
+
const person = queueOwner(loaded);
|
|
8154
8269
|
const now4 = (input.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
8155
8270
|
const since = parseSince(input.since, now4);
|
|
8156
8271
|
const inWindow = (at) => typeof at === "string" && Date.parse(at) >= since.getTime() && Date.parse(at) <= now4.getTime();
|
|
8157
|
-
const events = readLoopEvents(loaded.stateDir).filter((event2) => inWindow(event2.at));
|
|
8272
|
+
const events = readLoopEvents(loaded.stateDir, since.getTime()).filter((event2) => inWindow(event2.at));
|
|
8158
8273
|
const counts = {};
|
|
8159
8274
|
for (const event2 of events) counts[event2.type] = (counts[event2.type] ?? 0) + 1;
|
|
8160
8275
|
const escalations = events.filter((event2) => event2.type === "contract.escalated");
|
|
@@ -8176,6 +8291,8 @@ var buildRetroReport = async (input) => {
|
|
|
8176
8291
|
if (existsSync(issuesDir)) for (const entry of readdirSync(issuesDir, { withFileTypes: true })) {
|
|
8177
8292
|
if (!entry.isDirectory()) continue;
|
|
8178
8293
|
const issue = entry.name;
|
|
8294
|
+
const newestMtime = newestIssueMtimeMs(loaded.stateDir, issue);
|
|
8295
|
+
if (newestMtime !== null && newestMtime < since.getTime()) continue;
|
|
8179
8296
|
const dispatch = readDispatchRecord(loaded.stateDir, issue);
|
|
8180
8297
|
const delivery = readDeliveryState(loaded.stateDir, issue);
|
|
8181
8298
|
const contract = readStoredContract(loaded.stateDir, issue);
|
|
@@ -8233,7 +8350,7 @@ var buildRetroReport = async (input) => {
|
|
|
8233
8350
|
else if (status === "ok") work += 1;
|
|
8234
8351
|
}
|
|
8235
8352
|
}
|
|
8236
|
-
orca = { runs, idle, work, timedOut, avgDurationSec: durations.length ? Math.round(durations.reduce((
|
|
8353
|
+
orca = { runs, idle, work, timedOut, avgDurationSec: durations.length ? Math.round(durations.reduce((sum2, value) => sum2 + value, 0) / durations.length) : null, maxDurationSec: durations.length ? Math.round(Math.max(...durations)) : null };
|
|
8237
8354
|
} catch {
|
|
8238
8355
|
orca = null;
|
|
8239
8356
|
}
|
|
@@ -8242,9 +8359,9 @@ var buildRetroReport = async (input) => {
|
|
|
8242
8359
|
generatedAt: now4.toISOString(),
|
|
8243
8360
|
window: { since: since.toISOString(), until: now4.toISOString(), days: Number(((now4.getTime() - since.getTime()) / 864e5).toFixed(2)) },
|
|
8244
8361
|
project: config.project.repo,
|
|
8245
|
-
person
|
|
8362
|
+
person,
|
|
8246
8363
|
counts,
|
|
8247
|
-
escalations: { total: escalations.length, issues: [...new Set(escalations.map((event2) => String(event2.issue ?? "?")))], reasons: [...reasonCounts.entries()].map(([reason2,
|
|
8364
|
+
escalations: { total: escalations.length, issues: [...new Set(escalations.map((event2) => String(event2.issue ?? "?")))], reasons: [...reasonCounts.entries()].map(([reason2, count3]) => ({ reason: reason2, count: count3 })).sort((left, right) => right.count - left.count) },
|
|
8248
8365
|
dispatches: { total: dispatchEvents.length, failed: counts["worker.dispatch-failed"] ?? 0, byProvider },
|
|
8249
8366
|
delivery: { merged: tally("merged"), blocked: tally("blocked"), stuck: tally("stuck"), abandoned: tally("abandoned"), inFlight: tally("in-flight"), fixRounds, reviewsClean, reviewsFindings, reviewsIncomplete, medianLeadTimeMin: median3(rows.map((row) => row.leadTimeMin).filter((value) => value !== null)) },
|
|
8250
8367
|
providers: { cooldowns, cooldownEvents: counts["provider.cooldown"] ?? 0 },
|
|
@@ -8271,7 +8388,7 @@ var renderRetroMarkdown = (report) => {
|
|
|
8271
8388
|
if (report.orca) lines.push(`| Orca runs (idle / work / timed out) | ${report.orca.runs} (${report.orca.idle} / ${report.orca.work} / ${report.orca.timedOut}) \xB7 avg ${report.orca.avgDurationSec ?? "\u2014"} s \xB7 max ${report.orca.maxDurationSec ?? "\u2014"} s |`);
|
|
8272
8389
|
lines.push("");
|
|
8273
8390
|
if (Object.keys(report.dispatches.byProvider).length) {
|
|
8274
|
-
lines.push("## Providers", "", ...Object.entries(report.dispatches.byProvider).map(([key,
|
|
8391
|
+
lines.push("## Providers", "", ...Object.entries(report.dispatches.byProvider).map(([key, count3]) => `- ${key}: ${count3} dispatch(es)`), ...report.providers.cooldowns.map((row) => `- cooldown ${row.provider} until ${row.until.slice(0, 16)}Z \u2014 ${row.reason}`), "");
|
|
8275
8392
|
}
|
|
8276
8393
|
if (report.escalations.reasons.length) {
|
|
8277
8394
|
lines.push("## Problems", "", ...report.escalations.reasons.map((row) => `- ${row.count}\xD7 ${row.reason}`), ...report.issues.filter((row) => ["blocked", "stuck", "abandoned"].includes(row.outcome)).map((row) => `- ${row.issue} ${row.outcome}${row.pr ? ` (PR #${row.pr})` : ""} after ${row.fixRounds} fix round(s), ${row.nudges} nudge(s)`), "");
|
|
@@ -8452,7 +8569,7 @@ var buildDebriefReport = (input) => {
|
|
|
8452
8569
|
}
|
|
8453
8570
|
const inFlight = rows.filter((row) => !row.finalOutcome && row.phase !== "escalated");
|
|
8454
8571
|
const held = rows.filter((row) => row.phase === "held" || row.phase === "held-incomplete-review" || row.heldFor);
|
|
8455
|
-
const events = readLoopEvents(stateDir).filter((event2) => Date.parse(event2.at) >= since.getTime());
|
|
8572
|
+
const events = readLoopEvents(stateDir, since.getTime()).filter((event2) => Date.parse(event2.at) >= since.getTime());
|
|
8456
8573
|
const recentEscalations = events.filter((event2) => event2.type === "contract.escalated").slice(-10).map((event2) => ({
|
|
8457
8574
|
issue: typeof event2.issue === "string" ? event2.issue : "?",
|
|
8458
8575
|
at: event2.at,
|
|
@@ -8534,6 +8651,138 @@ var renderDebriefMarkdown = (report) => {
|
|
|
8534
8651
|
lines.push("_Read-only. Run `ak-harness loop deliver` / `tick` to act; `loop retro` for the weekly digest._");
|
|
8535
8652
|
return lines.join("\n");
|
|
8536
8653
|
};
|
|
8654
|
+
var connectedStatuses = /* @__PURE__ */ new Set(["connected", "running", "active", "idle"]);
|
|
8655
|
+
var stalledPhases = /* @__PURE__ */ new Set(["waiting-for-pr", "awaiting-review", "review-incomplete", "fix-round"]);
|
|
8656
|
+
var heldRow = (row) => Boolean(row.heldFor) || row.phase === "held" || row.phase === "held-incomplete-review";
|
|
8657
|
+
var count2 = (events, type) => events.filter((event2) => event2.type === type).length;
|
|
8658
|
+
var sum = (events, key) => events.reduce((total, event2) => total + (typeof event2[key] === "number" && Number.isFinite(event2[key]) ? Number(event2[key]) : 0), 0);
|
|
8659
|
+
var uniqueIssues = (events, types) => new Set(events.filter((event2) => types.includes(event2.type) && typeof event2.issue === "string").map((event2) => event2.issue)).size;
|
|
8660
|
+
var assessObservability = (input) => {
|
|
8661
|
+
const anomalies = [];
|
|
8662
|
+
for (const issue of input.missingDeliveryIssues) anomalies.push({ id: "claim-without-delivery", severity: "action_required", issue, message: `${issue} has an active claim but no delivery.json`, evidence: { issue } });
|
|
8663
|
+
for (const terminal2 of input.terminals) {
|
|
8664
|
+
if (terminal2.worktreeId && connectedStatuses.has(terminal2.status.toLowerCase()) && terminal2.lastOutputAt === null && !terminal2.preview.trim()) anomalies.push({ id: "connected-without-output", severity: "warning", issue: null, message: `terminal ${terminal2.handle} is connected but has not emitted output`, evidence: { handle: terminal2.handle, worktreeId: terminal2.worktreeId, status: terminal2.status } });
|
|
8665
|
+
}
|
|
8666
|
+
for (const worktree of input.finalizedDirtyWorktrees) anomalies.push({ id: "finalized-dirty-worktree", severity: "action_required", issue: worktree.issue, message: `finalized worktree ${worktree.worktreeId} still has ${worktree.files} uncommitted file(s)`, evidence: { ...worktree } });
|
|
8667
|
+
const latestDispatch = input.events.filter((event2) => event2.type === "worker.dispatched").map((event2) => Date.parse(event2.at)).filter(Number.isFinite).sort((a, b) => b - a)[0];
|
|
8668
|
+
const quietForMin = latestDispatch === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, Math.round((Date.parse(input.generatedAt) - latestDispatch) / 6e4));
|
|
8669
|
+
if (input.queueReady > 0 && input.freeSlots > 0 && quietForMin >= 15) anomalies.push({ id: "queue-ready-no-dispatch", severity: "action_required", issue: null, message: `${input.queueReady} ready issue(s) and ${input.freeSlots} free slot(s), but no dispatch in ${Number.isFinite(quietForMin) ? `${quietForMin} min` : "the observation window"}`, evidence: { queueReady: input.queueReady, freeSlots: input.freeSlots, quietForMin } });
|
|
8670
|
+
for (const row of input.issues) {
|
|
8671
|
+
if (row.heldFor || !stalledPhases.has(row.phase) || row.ageMin === null || row.ageMin < input.workerIdleTimeoutMin) continue;
|
|
8672
|
+
anomalies.push({ id: "stalled-delivery", severity: "action_required", issue: row.issue, message: `${row.issue} is in ${row.phase} for ${row.ageMin} min (threshold ${input.workerIdleTimeoutMin} min)`, evidence: { issue: row.issue, phase: row.phase, ageMin: row.ageMin, thresholdMin: input.workerIdleTimeoutMin } });
|
|
8673
|
+
}
|
|
8674
|
+
const events = {};
|
|
8675
|
+
for (const event2 of input.events) events[event2.type] = (events[event2.type] ?? 0) + 1;
|
|
8676
|
+
const report = {
|
|
8677
|
+
status: anomalies.some((item) => item.severity === "action_required") ? "action_required" : "healthy",
|
|
8678
|
+
generatedAt: input.generatedAt,
|
|
8679
|
+
project: input.project,
|
|
8680
|
+
person: input.person,
|
|
8681
|
+
windowHours: input.windowHours,
|
|
8682
|
+
anomalies,
|
|
8683
|
+
metrics: {
|
|
8684
|
+
queueReady: input.queueReady,
|
|
8685
|
+
freeSlots: input.freeSlots,
|
|
8686
|
+
runningWorkers: input.runningWorkers,
|
|
8687
|
+
maxAgents: input.maxAgents,
|
|
8688
|
+
activeClaims: input.activeClaims,
|
|
8689
|
+
inFlight: input.issues.filter((row) => !heldRow(row)).length,
|
|
8690
|
+
held: input.issues.filter(heldRow).length,
|
|
8691
|
+
merged: input.merged,
|
|
8692
|
+
blocked: input.blocked,
|
|
8693
|
+
fixRounds: input.fixRounds,
|
|
8694
|
+
reviewFindings: input.reviewFindings,
|
|
8695
|
+
reviewIncomplete: input.reviewIncomplete,
|
|
8696
|
+
medianLeadTimeMin: input.medianLeadTimeMin,
|
|
8697
|
+
providerRemainingPercent: input.providerRemainingPercent,
|
|
8698
|
+
machine: input.machine,
|
|
8699
|
+
memory: input.memory,
|
|
8700
|
+
cache: input.cache,
|
|
8701
|
+
tokens: input.tokens,
|
|
8702
|
+
events
|
|
8703
|
+
}
|
|
8704
|
+
};
|
|
8705
|
+
return report;
|
|
8706
|
+
};
|
|
8707
|
+
var compactTerminal = (terminal2) => ({ handle: terminal2.handle, status: terminal2.status, worktreeId: terminal2.worktreeId, lastOutputAt: terminal2.lastOutputAt, preview: terminal2.preview });
|
|
8708
|
+
var dirtyFinalizedWorktrees = async (runner, worktrees) => {
|
|
8709
|
+
const out = [];
|
|
8710
|
+
for (const worktree of worktrees) {
|
|
8711
|
+
if (worktree.workspaceStatus.trim().toLowerCase() !== "completed" || !worktree.path) continue;
|
|
8712
|
+
try {
|
|
8713
|
+
const result = await runner.run(["git", "-C", worktree.path, "status", "--porcelain"], { timeoutMs: 1e4 });
|
|
8714
|
+
if (result.code === 0 && result.stdout.trim()) out.push({ worktreeId: worktree.id, issue: worktree.linkedLinearIssue, files: result.stdout.trim().split(/\r?\n/).length });
|
|
8715
|
+
} catch {
|
|
8716
|
+
}
|
|
8717
|
+
}
|
|
8718
|
+
return out;
|
|
8719
|
+
};
|
|
8720
|
+
var runObservability = async (input) => {
|
|
8721
|
+
const loaded = input.loaded ?? loadLoopConfig(input.configPath ?? "loop.config.yaml");
|
|
8722
|
+
const now4 = input.now ?? (() => /* @__PURE__ */ new Date());
|
|
8723
|
+
const at = now4();
|
|
8724
|
+
const since = parseSince(input.since ?? "24h", at);
|
|
8725
|
+
const [doctor, debrief, worktrees, terminals] = await Promise.all([
|
|
8726
|
+
runLoopDoctor({ loaded, runner: input.runner, env: input.env, platform: input.platform, now: () => at, probe: false }),
|
|
8727
|
+
Promise.resolve(buildDebriefReport({ loaded, since: input.since ?? "24h", now: () => at })),
|
|
8728
|
+
orcaWorktrees(input.runner, { bin: loaded.config.orca.bin, timeoutMs: loaded.config.orca.timeoutMs }).catch(() => []),
|
|
8729
|
+
orcaTerminalList(input.runner, {}, { bin: loaded.config.orca.bin, timeoutMs: loaded.config.orca.timeoutMs }).catch(() => [])
|
|
8730
|
+
]);
|
|
8731
|
+
const events = readLoopEvents(loaded.stateDir).filter((event2) => Date.parse(event2.at) >= since.getTime() && Date.parse(event2.at) <= at.getTime());
|
|
8732
|
+
const ledger = createDispatchLedger(loaded.stateDir);
|
|
8733
|
+
const active = ledger.active();
|
|
8734
|
+
const missingDeliveryIssues = active.filter((lease) => !existsSync(deliveryStatePath(loaded.stateDir, lease.issue))).map((lease) => lease.issue);
|
|
8735
|
+
const records = listDispatched(loaded.stateDir);
|
|
8736
|
+
const completed = records.map((record3) => ({ record: record3, state: readDeliveryState(loaded.stateDir, record3.issue) })).filter(({ state }) => state.finishedAt && Date.parse(state.finishedAt) >= since.getTime());
|
|
8737
|
+
const leadTimes = completed.map(({ record: record3, state }) => state.finishedAt ? (Date.parse(state.finishedAt) - Date.parse(record3.dispatchedAt)) / 6e4 : null).filter((value) => value !== null && Number.isFinite(value)).sort((a, b) => a - b);
|
|
8738
|
+
const medianLeadTimeMin = leadTimes.length ? leadTimes.length % 2 ? leadTimes[Math.floor(leadTimes.length / 2)] : (leadTimes[leadTimes.length / 2 - 1] + leadTimes[leadTimes.length / 2]) / 2 : null;
|
|
8739
|
+
const providerRemainingPercent = Object.fromEntries(doctor.providers.map((provider) => [provider.id, remainingUsagePercent(provider.usage, loaded.config.models.routing.usageMetric)]));
|
|
8740
|
+
const cachedContracts = records.filter((record3) => existsSync(contractPath(loaded.stateDir, record3.issue))).length;
|
|
8741
|
+
const memoryEvents = events.filter((event2) => event2.type === "memory.recalled");
|
|
8742
|
+
const tokens = { input: sum(events, "inputTokens"), output: sum(events, "outputTokens"), total: sum(events, "totalTokens"), cacheRead: sum(events, "cacheReadTokens"), cacheWrite: sum(events, "cacheWriteTokens") };
|
|
8743
|
+
const machine = { cpuCount: doctor.machine.sample.cpus, load1PerCpuPercent: doctor.machine.sample.load1PerCpuPercent, memoryUsedPercent: doctor.machine.sample.memoryUsedPercent, freeRamGb: doctor.machine.freeRamGb };
|
|
8744
|
+
const snapshot = {
|
|
8745
|
+
generatedAt: at.toISOString(),
|
|
8746
|
+
project: doctor.config.project,
|
|
8747
|
+
person: doctor.config.person,
|
|
8748
|
+
windowHours: Math.max(1, Math.round((at.getTime() - since.getTime()) / 36e5)),
|
|
8749
|
+
workerIdleTimeoutMin: loaded.config.delivery.workerIdleTimeoutMin,
|
|
8750
|
+
queueReady: doctor.queue.count,
|
|
8751
|
+
freeSlots: doctor.machine.free,
|
|
8752
|
+
runningWorkers: doctor.workers.running,
|
|
8753
|
+
maxAgents: doctor.machine.maxAgents,
|
|
8754
|
+
activeClaims: active.length,
|
|
8755
|
+
missingDeliveryIssues,
|
|
8756
|
+
terminals: terminals.map(compactTerminal),
|
|
8757
|
+
finalizedDirtyWorktrees: await dirtyFinalizedWorktrees(input.runner, worktrees),
|
|
8758
|
+
issues: debrief.inFlight.map(({ issue, phase: phase2, ageMin, heldFor }) => ({ issue, phase: phase2, ageMin, heldFor })),
|
|
8759
|
+
events,
|
|
8760
|
+
merged: uniqueIssues(events, ["pr.merged", "worker.merged"]),
|
|
8761
|
+
blocked: Math.max(records.filter((record3) => readDeliveryState(loaded.stateDir, record3.issue).finalOutcome === "blocked").length, uniqueIssues(events, ["worker.blocked"])),
|
|
8762
|
+
fixRounds: records.reduce((total, record3) => total + readDeliveryState(loaded.stateDir, record3.issue).fixRounds, 0),
|
|
8763
|
+
reviewFindings: count2(events, "pr.reviewed") - count2(events.filter((event2) => event2["status"] !== "findings"), "pr.reviewed"),
|
|
8764
|
+
reviewIncomplete: events.filter((event2) => event2.type === "pr.reviewed" && event2["status"] === "incomplete").length,
|
|
8765
|
+
medianLeadTimeMin,
|
|
8766
|
+
providerRemainingPercent,
|
|
8767
|
+
machine,
|
|
8768
|
+
memory: { recalls: memoryEvents.length, hits: sum(memoryEvents, "hits"), approxCharsSaved: sum(memoryEvents, "approxCharsSaved") },
|
|
8769
|
+
cache: { cachedContracts },
|
|
8770
|
+
tokens
|
|
8771
|
+
};
|
|
8772
|
+
return assessObservability(snapshot);
|
|
8773
|
+
};
|
|
8774
|
+
var renderObservabilityMarkdown = (report) => {
|
|
8775
|
+
const m = report.metrics;
|
|
8776
|
+
const headroom = Object.entries(m.providerRemainingPercent).map(([provider, remaining]) => `${provider} ${remaining === null ? "?" : `${remaining}%`}`).join(", ");
|
|
8777
|
+
const lines = [`# Loop observability \u2014 ${report.project} \xB7 ${report.person}`, "", `_${report.status}_ \xB7 generated ${report.generatedAt.slice(0, 19)}Z \xB7 last ${report.windowHours}h`, "", "## Metrics", "", `- Queue: ${m.queueReady} ready \xB7 ${m.freeSlots} free slot(s) \xB7 ${m.runningWorkers}/${m.maxAgents} workers`, `- Delivery: ${m.inFlight} in flight \xB7 ${m.held} held \xB7 ${m.merged} merged \xB7 ${m.blocked} blocked \xB7 ${m.fixRounds} fix round(s)`, `- Reviews: ${m.reviewFindings} findings \xB7 ${m.reviewIncomplete} incomplete`, `- Machine: ${m.machine.cpuCount} CPU \xB7 ${m.machine.load1PerCpuPercent}% load \xB7 ${m.machine.memoryUsedPercent}% memory \xB7 ${m.machine.freeRamGb} GB free`, `- Providers: ${headroom || "n/a"}`, `- Memory/cache: ${m.memory.recalls} recall(s), ${m.memory.hits} hit(s), ${m.memory.approxCharsSaved} chars saved \xB7 ${m.cache.cachedContracts} cached contract(s)`, `- Tokens observed: ${m.tokens.total || m.tokens.input + m.tokens.output || "n/a"}`, ""];
|
|
8778
|
+
if (report.anomalies.length) {
|
|
8779
|
+
lines.push("## Anomalies", "");
|
|
8780
|
+
for (const anomaly of report.anomalies) lines.push(`- **${anomaly.severity}**${anomaly.issue ? ` \xB7 ${anomaly.issue}` : ""}: ${anomaly.message}`);
|
|
8781
|
+
lines.push("");
|
|
8782
|
+
} else lines.push("## Anomalies", "", "_None detected._", "");
|
|
8783
|
+
lines.push("_Read-only. Run `ak-harness loop tick` or `deliver` to act on the queue._");
|
|
8784
|
+
return lines.join("\n");
|
|
8785
|
+
};
|
|
8537
8786
|
|
|
8538
8787
|
// src/loop/watch.ts
|
|
8539
8788
|
var defaultSleep = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
@@ -8661,6 +8910,6 @@ var watchDeliveries = async (input) => {
|
|
|
8661
8910
|
};
|
|
8662
8911
|
var formatWatchEvent = (event2) => `${event2.kind}: ${event2.issue} \xB7 ${event2.message}`;
|
|
8663
8912
|
|
|
8664
|
-
export { AGENT_REGISTRY_SCHEMA_VERSION, ARTIFACT_SCHEMA_VERSION, ARTIFACT_TYPES, ASSURANCE_LEVELS, AgentRegistryEntrySchema, AgentRegistrySchema, BENCHMARK_SCHEMA_VERSION, BLOCK_STATUSES, CAPABILITY_KINDS, CAPABILITY_MANIFEST_SCHEMA_VERSION, COMPATIBILITY_COMPONENTS, COMPATIBILITY_SCHEMA_VERSION, CONTEXT_PROVIDER_SLOT, CONTRACT_CLOSE, CONTRACT_OPEN, CONTRACT_SCHEMA_VERSION, ContractOutcomeSchema, EVAL_COMPONENTS, EVAL_LAYERS, EVAL_MANIFEST_SCHEMA_VERSION, EVENT_LOG_GENESIS, EVIDENCE_BUNDLE_SCHEMA_VERSION, FileArtifactStore, FileEventStore, HARNESS_ERROR_CATALOG, HARNESS_ERROR_CODES, HARNESS_EVENT_ENVELOPE_SCHEMA_VERSION, HARNESS_EVENT_SCHEMA_VERSION, HARNESS_EVENT_TYPES, HARNESS_PLUGIN_API_VERSION, HARNESS_REPO_URL, HarnessError, IMPROVEMENT_CYCLE_STEPS, LEARNING_STATUSES, LEGAL_TRANSITIONS, LOOP_CONFIG_FILE, LOOP_CONFIG_SCHEMA_VERSION, LOOP_LOCAL_CONFIG_FILE, LOOP_STAGES, LoopConfigSchema, MEMORY_SCOPES, MODEL_ROLES, PHASE_DECISIONS, PHASE_EFFECTS, PHASE_EFFECT_ACTIONS, PHASE_MODES, PR_FIELDS, QUALITY_DIMENSIONS, REVIEW_SEVERITIES, STATES, TaskContractSchema, WIP_STATES, activeCooldowns, adaptiveConcurrency, advanceQueueOwner, appendLoopEvent, approveRun, approvedDecision, artifactDigest, artifactFilePath, artifactIsFresh, artifactMarkdownPath, assertHuman, assessAcceptance, assessAgentEval, assessBlock, assessChecks, assessCompatibility, assessContract, assessDiscovery, assessImprovementCycle, assessIntegration, assessPilot, assessPreflight, assessProduction, assessQaTransition, assessSlots, assessWip, assessWorktreeCleanup, atLeast, authStatusFor, authorizeRun, automationName, automationPrompt, automationSpecs, availableMemoryBytes, benchmarkRuns, branchFor, briefPath, buildDebriefReport, buildListIssuesArgv, buildRetroReport, buildReviewArgv, buildSuggestions, busyIssues, cancelRun, classifyFailure, classifyHarnessError, classifyProviderFailure, classifyWatchEvent, classifyWatchPhase, cleanTaskArtifacts, clearIssueFailures, clearProviderCooldown, compareOptimization, compareVersions, composePullRequest, contractIsFresh, contractPath, cooldownPath, cooldownUntil, countRunningWorkers, createArgvRagContextProvider, createArtifactEnvelope, createCapabilityManifest, createCodingAgentAdapter, createCompatibilityManifest, createConfiguredToolRuntime, createDispatchLedger, createDocBridgeContextProvider, createDockerToolRuntime, createEvalManifest, createFileMemoryAdapter, createFileMemoryKvStore, createHarnessEventEnvelope, createInMemoryMemoryAdapter, createKvMemoryAdapter, createLinearTrackingAdapter, createLlmCache, createLlmCacheKey, createLoopEventBus, createMachineMonitor, createMcpToolBridge, createModelPolicy, createOrcaDispatchPlan, createOrcaLifecycleProjection, createPhaseArtifact, createPhaseProfile, createPluginRegistry, createPluginSlot, createPolicyGate, createProcessRunner, createProcessToolRuntime, createPullRequestApproval, createQualityMatrix, createRagContextProvider, createRichIO, createSessionRecorder, createStatusSnapshot, createToolRuntime, createTrackingAdapter, createTrackingTransition, deliveryStatePath, detectProviders, discoverIntake, dispatchRecordPath, evaluateWatchdog, executePhaseProfile, exportEvidenceBundle, extractResetsAt, fetchArtificialAnalysisModels, fetchLinearIssue, fetchLinearQueue, fetchTeamMembers, filterAndOrderQueue, findExecutable, formatWatchEvent, gatherLoopState, generateContract, githubComment, githubCommentArgv, githubCommentExists, githubLabelRemove, githubMerge, githubMergeArgv, githubOpenPullRequests, githubPullRequest, githubPullRequestsForBranch, hasLocalConfig, hashContextSnapshot, hashContextSnapshots, hashMcpArgs, inspectDocBridgeIndex, inspectEventLogLock, installLoopAutomations, installPreflight, intakeIssueId, intakePath, isDiscoveryCurrent, isIssuePaused, isStagePaused, isWsl, issueFailurePath, launchWorkerTerminal, learningToMemoryRecord, learningsPath, linearAttach, linearAttachArgv, linearCommentAdd, linearCommentAddArgv, linearLabelAdd, linearLabelArgv, linearLabelRemove, linearStatusSet, linearStatusSetArgv, listCliModels, listDispatched, listIntake, listPausedIssues, loadAgentRegistry, loadAliases, loadBenchmarkManifest, loadBuiltinCatalog, loadConfig, loadLatestRun, loadLoopConfig, loadLoopPlugins, loadPinnedSkills, localConfigPath, loopStatus, markProviderExhausted, memoryDigestOf, mergeLoopConfig, modelFor, normalizeReason, openLoopMemory, orcaAccountList, orcaAgentHooks, orcaAutomationCreateArgv, orcaAutomationEditArgv, orcaAutomationRemove, orcaAutomationRun, orcaAutomationRuns, orcaAutomationsList, orcaJson, orcaStatus, orcaTerminalCreate, orcaTerminalList, orcaTerminalScreen, orcaTerminalSend, orcaTerminalWait, orcaVersion, orcaWorktreeCreate, orcaWorktreeRemove, orcaWorktreeSet, orcaWorktreeSetArgv, orcaWorktrees, parseAgentRegistryText, parseArtificialAnalysisPayload, parseAutomationRuns, parseContractOutput, parseGrokModelsOutput, parseJsonEnvelope, parseLinearIssueDetail, parseLinearIssues, parseLoopConfigText, parseMemInfo, parseModelRef, parseOrcaAgentHooks, parseOrcaAutomations, parseOrcaSendReceipt, parseOrcaStatus, parseOrcaTerminals, parseOrcaVersion, parseOrcaWorktreeCreate, parseOrcaWorktrees, parseProviderUsage, parsePullRequest, parseRagQueryOutput, parseRetro, parseReviewResult, parseSince, parseTeamMembers, parseUsageWindows, parseVmStat, pauseIssue, planFilePreflight, planMemoryContext, planPhaseProfile, planRun, precheckCommand, precheckDeliver, precheckTick, preferMemoryOverDocBridge, promoteLearnings, promoteLearningsToMemory, promptLocalConfig, providerIdentity, providerSpecs, queueOwner, rankModels, readAaCache, readArtifactFile, readContextSnapshots, readCooldowns, readDeliveryState, readDispatchRecord, readEvidenceTrustStore, readIntake, readIssueFailures, readLearningsLedger, readLoopEvents, readOutcomeProgress, readStagePause, readStoredContract, reconcileRun, recordBenchmarkObservation, recordIssueFailure, recordStageRunResult, recoverEventLogLock, recoveryDelayMs, remainingUsagePercent, renderArtifactMarkdown, renderContractPrompt, renderDebriefMarkdown, renderFindingsForWorker, renderHandoffBrief, renderHeadlessArgv, renderLocalConfig, renderPinnedSkills, renderRetroMarkdown, renderTuiCommand, renderWorkerBrief, resolveAgentForRole, resolveAlias, resolveCatalogCandidates, resolveDocContext, resumeIssue, resumeStage, resumeStateFromArtifacts, retroLearnings, retryRun, rotationStatePath, routeAllRoles, runAdversarialReview, runAgentEval, runCodeReview, runDeliver, runEvalBattery, runGuidedInstall, runLoopDoctor, runRetroStage, runTick, runWithRecovery, runWorkflow, sampleMachine, scanForPii, selectMemoryForPrompt, selectModel, selectRuntime, severityRank, shellQuote, skillDigest, skillRefs, snapshotWatchTargets, stageEntry, stagePausePath, startRun, summarizeMachine, tiersFor, touchesProtectedPaths, transition, undeclaredOrcaProviders, uninstallLoopAutomations, unknownTelemetry, untrusted, upsertProposedLearnings, usageRankTuple, validateAdapterMetadata, validateArtifactEnvelope, validateBenchmarkManifest, validateBlockManifest, validateCacheableOperation, validateCapabilityManifest, validateCompatibilityManifest, validateConfig, validateContextSnapshot, validateContextSnapshots, validateEvalManifest, validateHarnessErrorClassification, validateHarnessEventEnvelope, validateLoopConfig, validateMemoryRecord, validateOptimizationObservation, validatePhaseTelemetry, validateSafeCommand, validateStatusSnapshot, verifyEvidenceBundle, verifyPullRequestApproval, verifyRun, watchDeliveries, worktreeNameFor, writeAaCache, writeDispatchRecord, writeIdFor, writeLearningsLedger, writeLocalConfig, writeStoredContract };
|
|
8913
|
+
export { AGENT_REGISTRY_SCHEMA_VERSION, ARTIFACT_SCHEMA_VERSION, ARTIFACT_TYPES, ASSURANCE_LEVELS, AgentRegistryEntrySchema, AgentRegistrySchema, BENCHMARK_SCHEMA_VERSION, BLOCK_STATUSES, CAPABILITY_KINDS, CAPABILITY_MANIFEST_SCHEMA_VERSION, COMPATIBILITY_COMPONENTS, COMPATIBILITY_SCHEMA_VERSION, CONTEXT_PROVIDER_SLOT, CONTRACT_CLOSE, CONTRACT_OPEN, CONTRACT_SCHEMA_VERSION, ContractOutcomeSchema, EVAL_COMPONENTS, EVAL_LAYERS, EVAL_MANIFEST_SCHEMA_VERSION, EVENT_LOG_GENESIS, EVIDENCE_BUNDLE_SCHEMA_VERSION, FileArtifactStore, FileEventStore, HARNESS_ERROR_CATALOG, HARNESS_ERROR_CODES, HARNESS_EVENT_ENVELOPE_SCHEMA_VERSION, HARNESS_EVENT_SCHEMA_VERSION, HARNESS_EVENT_TYPES, HARNESS_PLUGIN_API_VERSION, HARNESS_REPO_URL, HarnessError, IMPROVEMENT_CYCLE_STEPS, LEARNING_STATUSES, LEGAL_TRANSITIONS, LOOP_CONFIG_FILE, LOOP_CONFIG_SCHEMA_VERSION, LOOP_LOCAL_CONFIG_FILE, LOOP_STAGES, LoopConfigSchema, MEMORY_SCOPES, MODEL_ROLES, PHASE_DECISIONS, PHASE_EFFECTS, PHASE_EFFECT_ACTIONS, PHASE_MODES, PR_FIELDS, QUALITY_DIMENSIONS, REVIEW_SEVERITIES, STATES, TaskContractSchema, WIP_STATES, activeCooldowns, adaptiveConcurrency, advanceQueueOwner, appendLoopEvent, approveRun, approvedDecision, artifactDigest, artifactFilePath, artifactIsFresh, artifactMarkdownPath, assertHuman, assessAcceptance, assessAgentEval, assessBlock, assessChecks, assessCompatibility, assessContract, assessDiscovery, assessImprovementCycle, assessIntegration, assessObservability, assessPilot, assessPreflight, assessProduction, assessQaTransition, assessSlots, assessWip, assessWorktreeCleanup, atLeast, authStatusFor, authorizeRun, automationName, automationPrompt, automationSpecs, availableMemoryBytes, benchmarkRuns, branchFor, briefPath, buildDebriefReport, buildListIssuesArgv, buildRetroReport, buildReviewArgv, buildSuggestions, busyIssues, cancelRun, classifyFailure, classifyHarnessError, classifyProviderFailure, classifyWatchEvent, classifyWatchPhase, cleanTaskArtifacts, clearIssueFailures, clearProviderCooldown, compareOptimization, compareVersions, composePullRequest, contractIsFresh, contractPath, cooldownPath, cooldownUntil, countRotationBlockingLeases, countRunningWorkers, createArgvRagContextProvider, createArtifactEnvelope, createCapabilityManifest, createCodingAgentAdapter, createCompatibilityManifest, createConfiguredToolRuntime, createDispatchLedger, createDocBridgeContextProvider, createDockerToolRuntime, createEvalManifest, createFileMemoryAdapter, createFileMemoryKvStore, createHarnessEventEnvelope, createInMemoryMemoryAdapter, createKvMemoryAdapter, createLinearTrackingAdapter, createLlmCache, createLlmCacheKey, createLoopEventBus, createMachineMonitor, createMcpToolBridge, createModelPolicy, createOrcaDispatchPlan, createOrcaLifecycleProjection, createPhaseArtifact, createPhaseProfile, createPluginRegistry, createPluginSlot, createPolicyGate, createProcessRunner, createProcessToolRuntime, createPullRequestApproval, createQualityMatrix, createRagContextProvider, createRichIO, createSessionRecorder, createStatusSnapshot, createToolRuntime, createTrackingAdapter, createTrackingTransition, deliveryStatePath, detectProviders, discoverIntake, dispatchRecordPath, evaluateWatchdog, executePhaseProfile, exportEvidenceBundle, extractResetsAt, fetchArtificialAnalysisModels, fetchLinearIssue, fetchLinearQueue, fetchTeamMembers, filterAndOrderQueue, findExecutable, formatWatchEvent, gatherLoopState, generateContract, githubComment, githubCommentArgv, githubCommentExists, githubLabelRemove, githubMerge, githubMergeArgv, githubOpenPullRequests, githubPullRequest, githubPullRequestsForBranch, hasLocalConfig, hashContextSnapshot, hashContextSnapshots, hashMcpArgs, inspectDocBridgeIndex, inspectEventLogLock, installLoopAutomations, installPreflight, intakeIssueId, intakePath, isDiscoveryCurrent, isIssuePaused, isStagePaused, isWsl, issueFailurePath, launchWorkerTerminal, learningToMemoryRecord, learningsPath, linearAttach, linearAttachArgv, linearCommentAdd, linearCommentAddArgv, linearLabelAdd, linearLabelArgv, linearLabelRemove, linearStatusSet, linearStatusSetArgv, listCliModels, listCliModelsCached, listDispatched, listIntake, listPausedIssues, loadAgentRegistry, loadAliases, loadBenchmarkManifest, loadBuiltinCatalog, loadConfig, loadLatestRun, loadLoopConfig, loadLoopPlugins, loadPinnedSkills, localConfigPath, loopStatus, markProviderExhausted, memoryDigestOf, mergeLoopConfig, modelFor, normalizeReason, openLoopMemory, orcaAccountList, orcaAgentHooks, orcaAutomationCreateArgv, orcaAutomationEditArgv, orcaAutomationRemove, orcaAutomationRun, orcaAutomationRuns, orcaAutomationsList, orcaJson, orcaStatus, orcaTerminalCreate, orcaTerminalList, orcaTerminalScreen, orcaTerminalSend, orcaTerminalWait, orcaVersion, orcaWorktreeCreate, orcaWorktreeRemove, orcaWorktreeSet, orcaWorktreeSetArgv, orcaWorktrees, parseAgentRegistryText, parseArtificialAnalysisPayload, parseAutomationRuns, parseContractOutput, parseGrokModelsOutput, parseJsonEnvelope, parseLinearIssueDetail, parseLinearIssues, parseLoopConfigText, parseMemInfo, parseModelRef, parseOrcaAgentHooks, parseOrcaAutomations, parseOrcaSendReceipt, parseOrcaStatus, parseOrcaTerminals, parseOrcaVersion, parseOrcaWorktreeCreate, parseOrcaWorktrees, parseProviderUsage, parsePullRequest, parseRagQueryOutput, parseRetro, parseReviewResult, parseSince, parseTeamMembers, parseUsageWindows, parseVmStat, pauseIssue, planFilePreflight, planMemoryContext, planPhaseProfile, planRun, precheckCommand, precheckDeliver, precheckTick, preferMemoryOverDocBridge, promoteLearnings, promoteLearningsToMemory, promptLocalConfig, providerIdentity, providerSpecs, queueOwner, rankModels, readAaCache, readArtifactFile, readCliModelsCache, readContextSnapshots, readCooldowns, readDeliveryState, readDispatchRecord, readEvidenceTrustStore, readIntake, readIssueFailures, readLearningsLedger, readLoopEvents, readOutcomeProgress, readStagePause, readStoredContract, reconcileRun, recordBenchmarkObservation, recordIssueFailure, recordStageRunResult, recoverEventLogLock, recoveryDelayMs, remainingUsagePercent, renderArtifactMarkdown, renderContractPrompt, renderDebriefMarkdown, renderFindingsForWorker, renderHandoffBrief, renderHeadlessArgv, renderLocalConfig, renderObservabilityMarkdown, renderPinnedSkills, renderRetroMarkdown, renderTuiCommand, renderWorkerBrief, resolveAgentForRole, resolveAlias, resolveCatalogCandidates, resolveDocContext, resumeIssue, resumeStage, resumeStateFromArtifacts, retroLearnings, retryRun, rotationStatePath, routeAllRoles, runAdversarialReview, runAgentEval, runCodeReview, runDeliver, runEvalBattery, runGuidedInstall, runLoopDoctor, runObservability, runRetroStage, runTick, runWithRecovery, runWorkflow, sampleMachine, scanForPii, selectMemoryForPrompt, selectModel, selectRuntime, severityRank, shellQuote, skillDigest, skillRefs, snapshotWatchTargets, stageEntry, stagePausePath, startRun, summarizeMachine, tiersFor, touchesProtectedPaths, transition, undeclaredOrcaProviders, uninstallLoopAutomations, unknownTelemetry, untrusted, upsertProposedLearnings, usageRankTuple, validateAdapterMetadata, validateArtifactEnvelope, validateBenchmarkManifest, validateBlockManifest, validateCacheableOperation, validateCapabilityManifest, validateCompatibilityManifest, validateConfig, validateContextSnapshot, validateContextSnapshots, validateEvalManifest, validateHarnessErrorClassification, validateHarnessEventEnvelope, validateLoopConfig, validateMemoryRecord, validateOptimizationObservation, validatePhaseTelemetry, validateSafeCommand, validateStatusSnapshot, verifyEvidenceBundle, verifyPullRequestApproval, verifyRun, watchDeliveries, worktreeNameFor, writeAaCache, writeCliModelsCache, writeDispatchRecord, writeIdFor, writeLearningsLedger, writeLocalConfig, writeStoredContract };
|
|
8665
8914
|
//# sourceMappingURL=index.js.map
|
|
8666
8915
|
//# sourceMappingURL=index.js.map
|