harnery 0.9.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/README.md +1 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +6 -0
- package/dist/commands/agents.d.ts +24 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +244 -13
- package/dist/commands/backup.d.ts +5 -4
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +15 -14
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +27 -1
- package/dist/commands/claude-desktop.d.ts +19 -0
- package/dist/commands/claude-desktop.d.ts.map +1 -0
- package/dist/commands/claude-desktop.js +168 -0
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +149 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +2 -3
- package/dist/commands/eml.d.ts +32 -0
- package/dist/commands/eml.d.ts.map +1 -1
- package/dist/commands/eml.js +16 -3
- package/dist/commands/harness.d.ts +11 -0
- package/dist/commands/harness.d.ts.map +1 -0
- package/dist/commands/harness.js +118 -0
- package/dist/commands/presence.d.ts +9 -4
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +88 -5
- package/dist/commands/relay.d.ts +9 -0
- package/dist/commands/relay.d.ts.map +1 -0
- package/dist/commands/relay.js +143 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +5 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +53 -17
- package/dist/core/agents/canonical-emit.d.ts +15 -0
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +41 -3
- package/dist/core/agents/cli.js +4 -2
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +44 -3
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +26 -1
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +4 -37
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +16 -43
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-projector.js +11 -2
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +3 -3
- package/dist/core/agents/state/names.d.ts +38 -3
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +46 -7
- package/dist/core/agents/state/pidmap.d.ts +5 -1
- package/dist/core/agents/state/pidmap.d.ts.map +1 -1
- package/dist/core/agents/state/pidmap.js +58 -2
- package/dist/core/agents/state/stale-sweep.d.ts +3 -2
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +6 -6
- package/dist/core/config.d.ts +68 -11
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +191 -25
- package/dist/core/context/index.d.ts +144 -0
- package/dist/core/context/index.d.ts.map +1 -0
- package/dist/core/context/index.js +380 -0
- package/dist/core/harnesses/bench.d.ts +29 -0
- package/dist/core/harnesses/bench.d.ts.map +1 -0
- package/dist/core/harnesses/bench.js +151 -0
- package/dist/core/harnesses/index.d.ts +9 -0
- package/dist/core/harnesses/index.d.ts.map +1 -0
- package/dist/core/harnesses/index.js +4 -0
- package/dist/core/harnesses/profiles.d.ts +62 -0
- package/dist/core/harnesses/profiles.d.ts.map +1 -0
- package/dist/core/harnesses/profiles.js +115 -0
- package/dist/core/harnesses/registry.d.ts +15 -0
- package/dist/core/harnesses/registry.d.ts.map +1 -0
- package/dist/core/harnesses/registry.js +113 -0
- package/dist/core/harnesses/types.d.ts +64 -0
- package/dist/core/harnesses/types.d.ts.map +1 -0
- package/dist/core/harnesses/types.js +20 -0
- package/dist/core/hooks/cli.js +280 -63
- package/dist/core/hooks/events/schema.d.ts +38 -1
- package/dist/core/hooks/events/schema.d.ts.map +1 -1
- package/dist/core/hooks/harness/events.d.ts.map +1 -1
- package/dist/core/hooks/harness/events.js +3 -0
- package/dist/core/hooks/harness/parse.d.ts +1 -1
- package/dist/core/hooks/harness/parse.d.ts.map +1 -1
- package/dist/core/hooks/harness/parse.js +4 -0
- package/dist/core/presence/blob.d.ts +40 -0
- package/dist/core/presence/blob.d.ts.map +1 -0
- package/dist/core/presence/blob.js +91 -0
- package/dist/core/presence/git.d.ts +68 -0
- package/dist/core/presence/git.d.ts.map +1 -0
- package/dist/core/presence/git.js +173 -0
- package/dist/core/presence/index.d.ts +74 -0
- package/dist/core/presence/index.d.ts.map +1 -0
- package/dist/core/presence/index.js +224 -0
- package/dist/core/presence/relay-client.d.ts +39 -0
- package/dist/core/presence/relay-client.d.ts.map +1 -0
- package/dist/core/presence/relay-client.js +295 -0
- package/dist/core/presence/relay-protocol.d.ts +94 -0
- package/dist/core/presence/relay-protocol.d.ts.map +1 -0
- package/dist/core/presence/relay-protocol.js +169 -0
- package/dist/core/workflow/billing.d.ts +1 -1
- package/dist/core/workflow/billing.d.ts.map +1 -1
- package/dist/core/workflow/billing.js +7 -1
- package/dist/core/workflow/engine.d.ts +5 -0
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +164 -16
- package/dist/core/workflow/harnesses.d.ts +3 -3
- package/dist/core/workflow/harnesses.d.ts.map +1 -1
- package/dist/core/workflow/harnesses.js +8 -17
- package/dist/core/workflow/index.d.ts +5 -0
- package/dist/core/workflow/index.d.ts.map +1 -0
- package/dist/core/workflow/index.js +3 -0
- package/dist/core/workflow/proof.d.ts +42 -0
- package/dist/core/workflow/proof.d.ts.map +1 -0
- package/dist/core/workflow/proof.js +342 -0
- package/dist/core/workflow/spawn-claude.d.ts +4 -1
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +39 -18
- package/dist/core/workflow/spawn-codex.d.ts +4 -1
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +44 -22
- package/dist/core/workflow/spawn-cursor.d.ts +4 -1
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +35 -16
- package/dist/core/workflow/types.d.ts +156 -2
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/types.js +1 -1
- package/dist/lib/browser/client.d.ts +16 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +22 -0
- package/dist/lib/browser/index.d.ts +1 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +1 -0
- package/dist/lib/browser/launch-args.d.ts +21 -0
- package/dist/lib/browser/launch-args.d.ts.map +1 -0
- package/dist/lib/browser/launch-args.js +32 -0
- package/dist/lib/claude-desktop.d.ts +105 -0
- package/dist/lib/claude-desktop.d.ts.map +1 -0
- package/dist/lib/claude-desktop.js +217 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +5 -2
- package/dist/lib/identities/assume.d.ts +51 -0
- package/dist/lib/identities/assume.d.ts.map +1 -0
- package/dist/lib/identities/assume.js +274 -0
- package/dist/lib/identities/index.d.ts +7 -7
- package/dist/lib/identities/index.d.ts.map +1 -1
- package/dist/lib/identities/index.js +24 -24
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +15 -2
- package/package.json +22 -6
- package/schemas/config.schema.json +88 -19
- package/src/commander.ts +6 -0
- package/src/commands/agents.ts +280 -14
- package/src/commands/backup.ts +17 -16
- package/src/commands/browse.ts +32 -0
- package/src/commands/claude-desktop.ts +215 -0
- package/src/commands/context.ts +174 -1
- package/src/commands/doctor.ts +2 -3
- package/src/commands/eml.ts +22 -4
- package/src/commands/harness.ts +147 -0
- package/src/commands/presence.ts +111 -5
- package/src/commands/relay.ts +160 -0
- package/src/commands/sync.ts +4 -0
- package/src/commands/workflow.ts +62 -19
- package/src/core/agents/canonical-emit.ts +41 -3
- package/src/core/agents/cli.ts +4 -2
- package/src/core/agents/render/prompt-context.ts +48 -3
- package/src/core/agents/render/session-context.ts +27 -1
- package/src/core/agents/rules/commit-conflict.ts +4 -33
- package/src/core/agents/session-events.ts +15 -39
- package/src/core/agents/state/heartbeat-projector.ts +10 -1
- package/src/core/agents/state/heartbeat-writer.ts +3 -2
- package/src/core/agents/state/names.ts +68 -9
- package/src/core/agents/state/pidmap.ts +59 -2
- package/src/core/agents/state/stale-sweep.ts +6 -11
- package/src/core/config.ts +248 -24
- package/src/core/context/index.ts +575 -0
- package/src/core/harnesses/bench.ts +214 -0
- package/src/core/harnesses/index.ts +31 -0
- package/src/core/harnesses/profiles.ts +141 -0
- package/src/core/harnesses/registry.ts +140 -0
- package/src/core/harnesses/types.ts +90 -0
- package/src/core/hooks/cli.ts +331 -62
- package/src/core/hooks/events/schema.ts +68 -0
- package/src/core/hooks/harness/events.ts +3 -0
- package/src/core/hooks/harness/parse.ts +7 -1
- package/src/core/presence/blob.ts +125 -0
- package/src/core/presence/git.ts +191 -0
- package/src/core/presence/index.ts +274 -0
- package/src/core/presence/relay-client.ts +322 -0
- package/src/core/presence/relay-protocol.ts +246 -0
- package/src/core/workflow/billing.ts +8 -2
- package/src/core/workflow/engine.ts +182 -16
- package/src/core/workflow/harnesses.ts +14 -19
- package/src/core/workflow/index.ts +43 -0
- package/src/core/workflow/proof.ts +434 -0
- package/src/core/workflow/spawn-claude.ts +39 -20
- package/src/core/workflow/spawn-codex.ts +47 -28
- package/src/core/workflow/spawn-cursor.ts +37 -18
- package/src/core/workflow/types.ts +176 -2
- package/src/lib/browser/client.ts +37 -0
- package/src/lib/browser/index.ts +1 -0
- package/src/lib/browser/launch-args.ts +33 -0
- package/src/lib/claude-desktop.ts +293 -0
- package/src/lib/docs-lint.ts +5 -2
- package/src/lib/identities/assume.ts +363 -0
- package/src/lib/identities/index.ts +28 -24
- package/src/lib/instructions/templates.ts +16 -2
|
@@ -28,29 +28,46 @@ import { createHash, randomBytes } from "node:crypto";
|
|
|
28
28
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync } from "node:fs";
|
|
29
29
|
import { isAbsolute, join, resolve } from "node:path";
|
|
30
30
|
import { pathToFileURL } from "node:url";
|
|
31
|
+
import { snapshotRepo } from "../context/index.js";
|
|
31
32
|
import { probeBilling } from "./billing.js";
|
|
33
|
+
import { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, writeWorkflowProof, } from "./proof.js";
|
|
34
|
+
import { WORKFLOW_PROOF_SCHEMA_VERSION } from "./types.js";
|
|
32
35
|
import { parseStageOutput, validateAgainstSchema } from "./validate.js";
|
|
33
36
|
const DEFAULT_MAX_AGENTS = 50;
|
|
34
37
|
const DEFAULT_CONCURRENCY = 4;
|
|
35
38
|
const DEFAULT_MAX_ATTEMPTS = 2;
|
|
36
39
|
const DEFAULT_TIMEOUT_MS = 300_000;
|
|
37
40
|
const DEFAULT_MAX_TURNS = 25;
|
|
41
|
+
export class WorkflowRunError extends Error {
|
|
42
|
+
runId;
|
|
43
|
+
proofPath;
|
|
44
|
+
constructor(message, runId, proofPath, cause) {
|
|
45
|
+
super(message, cause === undefined ? undefined : { cause });
|
|
46
|
+
this.name = "WorkflowRunError";
|
|
47
|
+
this.runId = runId;
|
|
48
|
+
this.proofPath = proofPath;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
38
51
|
export async function runWorkflow(scriptPath, opts) {
|
|
39
52
|
const absScript = isAbsolute(scriptPath) ? scriptPath : resolve(process.cwd(), scriptPath);
|
|
40
53
|
const mod = (await import(__rewriteRelativeImportExtension(pathToFileURL(absScript).href)));
|
|
41
54
|
if (typeof mod.default !== "function") {
|
|
42
55
|
throw new Error(`${scriptPath}: workflow script must \`export default async (ctx) => …\``);
|
|
43
56
|
}
|
|
44
|
-
const
|
|
57
|
+
const fallbackName = scriptPath.replace(/^.*\//, "").replace(/\.[cm]?js$/, "");
|
|
58
|
+
const meta = normalizeWorkflowMeta(mod.meta, fallbackName);
|
|
59
|
+
const name = meta.name;
|
|
45
60
|
const runId = `wf-${new Date().toISOString().replace(/[:.]/g, "-")}-${randomBytes(3).toString("hex")}`;
|
|
46
61
|
const runDir = join(opts.coordRoot, ".harnery", "workflows", runId);
|
|
47
62
|
mkdirSync(runDir, { recursive: true });
|
|
48
63
|
const journalPath = join(runDir, "journal.jsonl");
|
|
64
|
+
const proofPath = join(runDir, "proof.json");
|
|
49
65
|
const maxAgents = opts.maxAgents ?? DEFAULT_MAX_AGENTS;
|
|
50
66
|
const concurrency = opts.concurrency ?? DEFAULT_CONCURRENCY;
|
|
51
67
|
const cwd = opts.cwd ?? opts.coordRoot;
|
|
52
68
|
const log = opts.onLog ?? ((line) => process.stderr.write(`${line}\n`));
|
|
53
69
|
const defaultHarness = opts.defaultHarness ?? "claude-code";
|
|
70
|
+
const repoBefore = snapshotRepo(cwd);
|
|
54
71
|
// Per-child fixed context overhead: children spawn in `cwd` and load its
|
|
55
72
|
// repo-instructions file into their system prompt, cache-writing it once
|
|
56
73
|
// per child. A fan-out multiplies this, so surface it BEFORE the burn.
|
|
@@ -68,9 +85,15 @@ export async function runWorkflow(scriptPath, opts) {
|
|
|
68
85
|
let costUsd = 0;
|
|
69
86
|
let currentStage = "";
|
|
70
87
|
let agentSeq = 0;
|
|
88
|
+
let evidenceSeq = 0;
|
|
71
89
|
const billingProbed = new Map();
|
|
90
|
+
const agentProofs = new Map();
|
|
91
|
+
const evidenceRecords = [];
|
|
92
|
+
const acceptanceIds = new Set(meta.acceptance.map((criterion) => criterion.id));
|
|
72
93
|
const journal = (event, data) => {
|
|
73
94
|
const line = JSON.stringify({
|
|
95
|
+
schema_version: WORKFLOW_PROOF_SCHEMA_VERSION,
|
|
96
|
+
run_id: runId,
|
|
74
97
|
ts: new Date().toISOString(),
|
|
75
98
|
event,
|
|
76
99
|
stage: currentStage,
|
|
@@ -103,14 +126,35 @@ export async function runWorkflow(scriptPath, opts) {
|
|
|
103
126
|
}
|
|
104
127
|
const id = `a${++agentSeq}`;
|
|
105
128
|
const label = agentOpts.label ?? `${prompt.slice(0, 60).replace(/\s+/g, " ")}…`;
|
|
129
|
+
const proofLabel = agentOpts.label ?? id;
|
|
106
130
|
const maxAttempts = agentOpts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
107
|
-
|
|
131
|
+
const agentProof = {
|
|
132
|
+
id,
|
|
133
|
+
label: proofLabel,
|
|
134
|
+
stage: currentStage || undefined,
|
|
135
|
+
harness,
|
|
136
|
+
model: agentOpts.model,
|
|
137
|
+
status: "failed",
|
|
138
|
+
attempts: 0,
|
|
139
|
+
duration_ms: 0,
|
|
140
|
+
};
|
|
141
|
+
agentProofs.set(id, agentProof);
|
|
142
|
+
// Call identity for resume: same stage + harness + model + effort + turns + schema
|
|
108
143
|
// + ORIGINAL prompt → same key. Retry-mutated prompts never enter the key.
|
|
109
144
|
const key = agentCallKey(currentStage, harness, agentOpts, prompt);
|
|
110
145
|
const cached = resumeCache.get(key);
|
|
111
146
|
if (cached) {
|
|
112
147
|
agentsCached++;
|
|
113
|
-
|
|
148
|
+
agentProof.status = "cached";
|
|
149
|
+
agentProof.result = digestResult(cached.value, cached.kind);
|
|
150
|
+
journal("agent.cached", {
|
|
151
|
+
id,
|
|
152
|
+
label,
|
|
153
|
+
key,
|
|
154
|
+
harness,
|
|
155
|
+
model: agentOpts.model ?? null,
|
|
156
|
+
kind: cached.kind,
|
|
157
|
+
});
|
|
114
158
|
log(`[${name}] ${currentStage || "(no stage)"} → ${id} ${label} (cached from ${opts.resumeFrom})`);
|
|
115
159
|
return cached.value;
|
|
116
160
|
}
|
|
@@ -154,31 +198,49 @@ export async function runWorkflow(scriptPath, opts) {
|
|
|
154
198
|
}
|
|
155
199
|
}
|
|
156
200
|
if (agentsSpawned >= maxAgents) {
|
|
201
|
+
agentProof.error = `workflow agent cap reached (${maxAgents})`;
|
|
157
202
|
throw new Error(`workflow agent cap reached (${maxAgents}); raise --max-agents deliberately if the fan-out is intended`);
|
|
158
203
|
}
|
|
159
204
|
agentsSpawned++;
|
|
160
205
|
await acquire();
|
|
161
206
|
try {
|
|
162
|
-
journal("agent.start", {
|
|
207
|
+
journal("agent.start", {
|
|
208
|
+
id,
|
|
209
|
+
label,
|
|
210
|
+
key,
|
|
211
|
+
harness,
|
|
212
|
+
model: agentOpts.model ?? null,
|
|
213
|
+
effort: agentOpts.effort ?? null,
|
|
214
|
+
});
|
|
163
215
|
log(`[${name}] ${currentStage || "(no stage)"} → ${id} [${harness}] ${label}`);
|
|
164
216
|
let attemptPrompt = prompt;
|
|
165
217
|
let last = null;
|
|
218
|
+
let agentCostUsd = 0;
|
|
166
219
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
167
220
|
last = await spawner({
|
|
168
221
|
prompt: attemptPrompt,
|
|
169
222
|
model: agentOpts.model,
|
|
223
|
+
effort: agentOpts.effort,
|
|
170
224
|
timeoutMs: agentOpts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
171
225
|
maxTurns: agentOpts.maxTurns ?? DEFAULT_MAX_TURNS,
|
|
172
226
|
cwd,
|
|
173
227
|
runId,
|
|
174
228
|
subscriptionOnly: opts.subscriptionOnly,
|
|
175
229
|
});
|
|
230
|
+
agentProof.attempts = attempt;
|
|
231
|
+
agentProof.duration_ms += last.durationMs;
|
|
232
|
+
agentCostUsd += last.costUsd ?? 0;
|
|
176
233
|
costUsd += last.costUsd ?? 0;
|
|
177
234
|
if (!last.ok) {
|
|
178
235
|
journal("agent.attempt_failed", { id, attempt, error: last.error });
|
|
179
236
|
continue; // spawn-level failure: retry with the original prompt
|
|
180
237
|
}
|
|
181
238
|
if (!agentOpts.schema) {
|
|
239
|
+
agentProof.status = "succeeded";
|
|
240
|
+
agentProof.cost_usd =
|
|
241
|
+
agentCostUsd > 0 || last.costUsd !== undefined ? agentCostUsd : undefined;
|
|
242
|
+
agentProof.session_id = last.sessionId;
|
|
243
|
+
agentProof.result = digestResult(last.text, "text");
|
|
182
244
|
journal("agent.end", {
|
|
183
245
|
id,
|
|
184
246
|
key,
|
|
@@ -196,6 +258,11 @@ export async function runWorkflow(scriptPath, opts) {
|
|
|
196
258
|
? [parsed.error]
|
|
197
259
|
: validateAgainstSchema(parsed.value, agentOpts.schema);
|
|
198
260
|
if (problems.length === 0) {
|
|
261
|
+
agentProof.status = "succeeded";
|
|
262
|
+
agentProof.cost_usd =
|
|
263
|
+
agentCostUsd > 0 || last.costUsd !== undefined ? agentCostUsd : undefined;
|
|
264
|
+
agentProof.session_id = last.sessionId;
|
|
265
|
+
agentProof.result = digestResult(parsed.value, "json");
|
|
199
266
|
journal("agent.end", {
|
|
200
267
|
id,
|
|
201
268
|
key,
|
|
@@ -219,8 +286,16 @@ export async function runWorkflow(scriptPath, opts) {
|
|
|
219
286
|
const reason = last?.ok
|
|
220
287
|
? `schema validation failed after ${maxAttempts} attempt(s)`
|
|
221
288
|
: (last?.error ?? "spawn failed");
|
|
289
|
+
agentProof.cost_usd =
|
|
290
|
+
agentCostUsd > 0 || last?.costUsd !== undefined ? agentCostUsd : undefined;
|
|
291
|
+
agentProof.session_id = last?.sessionId;
|
|
292
|
+
agentProof.error = reason;
|
|
222
293
|
journal("agent.failed", { id, error: reason });
|
|
223
|
-
throw new Error(`agent ${
|
|
294
|
+
throw new Error(`agent ${proofLabel}: ${reason}`);
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
agentProof.error ??= error.message;
|
|
298
|
+
throw error;
|
|
224
299
|
}
|
|
225
300
|
finally {
|
|
226
301
|
release();
|
|
@@ -240,11 +315,62 @@ export async function runWorkflow(scriptPath, opts) {
|
|
|
240
315
|
journal("stage.start", { title });
|
|
241
316
|
log(`[${name}] ── stage: ${title}`);
|
|
242
317
|
};
|
|
243
|
-
const
|
|
318
|
+
const evidence = (input) => {
|
|
319
|
+
const record = createEvidenceRecord({
|
|
320
|
+
value: input,
|
|
321
|
+
sequence: evidenceSeq + 1,
|
|
322
|
+
acceptanceIds,
|
|
323
|
+
stage: currentStage || undefined,
|
|
324
|
+
});
|
|
325
|
+
evidenceSeq++;
|
|
326
|
+
evidenceRecords.push(record);
|
|
327
|
+
journal("evidence.recorded", { ...record });
|
|
328
|
+
return record.id;
|
|
329
|
+
};
|
|
330
|
+
const ctx = { agent, parallel, stage, log, evidence };
|
|
244
331
|
const t0 = Date.now();
|
|
245
|
-
|
|
332
|
+
const startedAt = new Date(t0).toISOString();
|
|
333
|
+
journal("run.start", {
|
|
334
|
+
name,
|
|
335
|
+
script: absScript,
|
|
336
|
+
objective: meta.objective ?? null,
|
|
337
|
+
acceptance: meta.acceptance,
|
|
338
|
+
max_agents: maxAgents,
|
|
339
|
+
concurrency,
|
|
340
|
+
});
|
|
246
341
|
try {
|
|
247
342
|
const result = await mod.default(ctx);
|
|
343
|
+
const endedAt = new Date().toISOString();
|
|
344
|
+
const durationMs = Date.now() - t0;
|
|
345
|
+
journal("run.end", {
|
|
346
|
+
ok: true,
|
|
347
|
+
agents: agentsSpawned,
|
|
348
|
+
cached: agentsCached,
|
|
349
|
+
cost_usd: round4(costUsd),
|
|
350
|
+
duration_ms: durationMs,
|
|
351
|
+
});
|
|
352
|
+
let proof;
|
|
353
|
+
try {
|
|
354
|
+
proof = buildWorkflowProof({
|
|
355
|
+
runId,
|
|
356
|
+
meta,
|
|
357
|
+
status: "succeeded",
|
|
358
|
+
startedAt,
|
|
359
|
+
endedAt,
|
|
360
|
+
durationMs,
|
|
361
|
+
journalPath,
|
|
362
|
+
before: repoBefore,
|
|
363
|
+
after: snapshotRepo(cwd),
|
|
364
|
+
agents: Array.from(agentProofs.values()),
|
|
365
|
+
evidence: evidenceRecords,
|
|
366
|
+
harnessEvidence: opts.harnessEvidence,
|
|
367
|
+
result,
|
|
368
|
+
});
|
|
369
|
+
writeWorkflowProof(proofPath, proof);
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
throw new WorkflowRunError(`workflow completed but its proof packet could not be written: ${error.message}`, runId, proofPath, error);
|
|
373
|
+
}
|
|
248
374
|
const report = {
|
|
249
375
|
runId,
|
|
250
376
|
name,
|
|
@@ -252,32 +378,53 @@ export async function runWorkflow(scriptPath, opts) {
|
|
|
252
378
|
agentsSpawned,
|
|
253
379
|
agentsCached,
|
|
254
380
|
costUsd: round4(costUsd),
|
|
255
|
-
durationMs
|
|
381
|
+
durationMs,
|
|
256
382
|
journalPath,
|
|
383
|
+
proofPath,
|
|
384
|
+
acceptance: proof.acceptance.summary,
|
|
257
385
|
contextTokensPerChildEstimate,
|
|
258
386
|
billing: Array.from(billingProbed.values()).map((p) => ({
|
|
259
387
|
harness: p.harness,
|
|
260
388
|
mode: opts.subscriptionOnly ? "subscription" : p.mode,
|
|
261
389
|
})),
|
|
262
390
|
};
|
|
263
|
-
journal("run.end", {
|
|
264
|
-
ok: true,
|
|
265
|
-
agents: agentsSpawned,
|
|
266
|
-
cached: agentsCached,
|
|
267
|
-
cost_usd: report.costUsd,
|
|
268
|
-
duration_ms: report.durationMs,
|
|
269
|
-
});
|
|
270
391
|
return report;
|
|
271
392
|
}
|
|
272
393
|
catch (err) {
|
|
394
|
+
if (err instanceof WorkflowRunError)
|
|
395
|
+
throw err;
|
|
396
|
+
const endedAt = new Date().toISOString();
|
|
397
|
+
const durationMs = Date.now() - t0;
|
|
273
398
|
journal("run.end", {
|
|
274
399
|
ok: false,
|
|
275
400
|
error: err.message,
|
|
276
401
|
agents: agentsSpawned,
|
|
277
402
|
cached: agentsCached,
|
|
278
403
|
cost_usd: round4(costUsd),
|
|
404
|
+
duration_ms: durationMs,
|
|
279
405
|
});
|
|
280
|
-
|
|
406
|
+
try {
|
|
407
|
+
const proof = buildWorkflowProof({
|
|
408
|
+
runId,
|
|
409
|
+
meta,
|
|
410
|
+
status: "failed",
|
|
411
|
+
startedAt,
|
|
412
|
+
endedAt,
|
|
413
|
+
durationMs,
|
|
414
|
+
journalPath,
|
|
415
|
+
before: repoBefore,
|
|
416
|
+
after: snapshotRepo(cwd),
|
|
417
|
+
agents: Array.from(agentProofs.values()),
|
|
418
|
+
evidence: evidenceRecords,
|
|
419
|
+
harnessEvidence: opts.harnessEvidence,
|
|
420
|
+
error: err.message,
|
|
421
|
+
});
|
|
422
|
+
writeWorkflowProof(proofPath, proof);
|
|
423
|
+
}
|
|
424
|
+
catch (proofError) {
|
|
425
|
+
throw new WorkflowRunError(`${err.message}; proof packet write also failed: ${proofError.message}`, runId, proofPath, err);
|
|
426
|
+
}
|
|
427
|
+
throw new WorkflowRunError(err.message, runId, proofPath, err);
|
|
281
428
|
}
|
|
282
429
|
}
|
|
283
430
|
/** Stable identity for one agent() call, for the resume cache. The ORIGINAL
|
|
@@ -287,6 +434,7 @@ function agentCallKey(stage, harness, agentOpts, prompt) {
|
|
|
287
434
|
stage,
|
|
288
435
|
harness,
|
|
289
436
|
agentOpts.model ?? null,
|
|
437
|
+
agentOpts.effort ?? null,
|
|
290
438
|
agentOpts.maxTurns ?? DEFAULT_MAX_TURNS,
|
|
291
439
|
agentOpts.schema ?? null,
|
|
292
440
|
prompt,
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* but they do drift — keep this module the single place they live.
|
|
8
8
|
*/
|
|
9
9
|
import type { HarnessName } from "./types.js";
|
|
10
|
-
export declare const HARNESS_BINARIES: Record<
|
|
11
|
-
export declare const HARNESS_INSTALL_HINTS: Record<
|
|
10
|
+
export declare const HARNESS_BINARIES: Record<string, string>;
|
|
11
|
+
export declare const HARNESS_INSTALL_HINTS: Record<string, string>;
|
|
12
12
|
/** How to authenticate each CLI with a subscription login (the billing
|
|
13
13
|
* default — see billing.ts). */
|
|
14
|
-
export declare const HARNESS_LOGIN_HINTS: Record<
|
|
14
|
+
export declare const HARNESS_LOGIN_HINTS: Record<string, string>;
|
|
15
15
|
/** One-line "it's missing, here's the fix" string for spawn adapters. */
|
|
16
16
|
export declare function notFoundError(harness: HarnessName): string;
|
|
17
17
|
//# sourceMappingURL=harnesses.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harnesses.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/harnesses.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"harnesses.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/harnesses.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEnD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAExD,CAAC;AAEF;gCACgC;AAChC,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEtD,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAK1D"}
|
|
@@ -6,25 +6,16 @@
|
|
|
6
6
|
* Install commands are the vendors' official one-liners; they drift rarely
|
|
7
7
|
* but they do drift — keep this module the single place they live.
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
cursor: "cursor-agent",
|
|
13
|
-
};
|
|
14
|
-
export const HARNESS_INSTALL_HINTS = {
|
|
15
|
-
"claude-code": "npm install -g @anthropic-ai/claude-code",
|
|
16
|
-
codex: "npm install -g @openai/codex",
|
|
17
|
-
cursor: "curl https://cursor.com/install -fsS | bash",
|
|
18
|
-
};
|
|
9
|
+
import { BUILTIN_HARNESS_PROFILES } from "../harnesses/profiles.js";
|
|
10
|
+
export const HARNESS_BINARIES = Object.fromEntries(Object.values(BUILTIN_HARNESS_PROFILES).map((profile) => [profile.id, profile.binary]));
|
|
11
|
+
export const HARNESS_INSTALL_HINTS = Object.fromEntries(Object.values(BUILTIN_HARNESS_PROFILES).map((profile) => [profile.id, profile.installHint]));
|
|
19
12
|
/** How to authenticate each CLI with a subscription login (the billing
|
|
20
13
|
* default — see billing.ts). */
|
|
21
|
-
export const HARNESS_LOGIN_HINTS =
|
|
22
|
-
"claude-code": "run `claude` and use /login",
|
|
23
|
-
codex: "codex login",
|
|
24
|
-
cursor: "cursor-agent login",
|
|
25
|
-
};
|
|
14
|
+
export const HARNESS_LOGIN_HINTS = Object.fromEntries(Object.values(BUILTIN_HARNESS_PROFILES).map((profile) => [profile.id, profile.loginHint]));
|
|
26
15
|
/** One-line "it's missing, here's the fix" string for spawn adapters. */
|
|
27
16
|
export function notFoundError(harness) {
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
const binary = HARNESS_BINARIES[harness] ?? harness;
|
|
18
|
+
const install = HARNESS_INSTALL_HINTS[harness] ?? "install the harness CLI";
|
|
19
|
+
const login = HARNESS_LOGIN_HINTS[harness] ?? "authenticate the harness CLI";
|
|
20
|
+
return `${binary} CLI not found on PATH; ` + `install: ${install} then authenticate: ${login}`;
|
|
30
21
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { runWorkflow, WorkflowRunError } from "./engine.js";
|
|
2
|
+
export { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, readWorkflowProof, renderWorkflowProof, rollupAcceptance, writeWorkflowProof, } from "./proof.js";
|
|
3
|
+
export type { AcceptanceCriterion, AcceptanceResult, AcceptanceStatus, AcceptanceSummary, AgentOpts, EngineOpts, EvidenceKind, EvidenceSource, EvidenceStatus, HarnessEvidenceCapability, HarnessEvidenceCoverage, HarnessName, ResultDigest, RunReport, Spawner, SpawnRequest, SpawnResult, StageSchema, WorkflowAgentProof, WorkflowContext, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowModule, WorkflowProof, WorkflowProofUnknown, WorkflowRepoEvidence, WorkflowRepoSnapshot, WorkflowRunStatus, } from "./types.js";
|
|
4
|
+
export { WORKFLOW_PROOF_SCHEMA_VERSION } from "./types.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,UAAU,EACV,YAAY,EACZ,cAAc,EACd,cAAc,EACd,yBAAyB,EACzB,uBAAuB,EACvB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,OAAO,EACP,YAAY,EACZ,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { runWorkflow, WorkflowRunError } from "./engine.js";
|
|
2
|
+
export { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, readWorkflowProof, renderWorkflowProof, rollupAcceptance, writeWorkflowProof, } from "./proof.js";
|
|
3
|
+
export { WORKFLOW_PROOF_SCHEMA_VERSION } from "./types.js";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { RepoSnapshot } from "../context/index.js";
|
|
2
|
+
import type { AcceptanceCriterion, AcceptanceResult, AcceptanceSummary, HarnessEvidenceCapability, ResultDigest, WorkflowAgentProof, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowProof } from "./types.js";
|
|
3
|
+
export interface NormalizedWorkflowMeta {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
objective?: string;
|
|
7
|
+
acceptance: AcceptanceCriterion[];
|
|
8
|
+
}
|
|
9
|
+
export interface BuildWorkflowProofInput {
|
|
10
|
+
runId: string;
|
|
11
|
+
meta: NormalizedWorkflowMeta;
|
|
12
|
+
status: "succeeded" | "failed";
|
|
13
|
+
startedAt: string;
|
|
14
|
+
endedAt: string;
|
|
15
|
+
durationMs: number;
|
|
16
|
+
journalPath: string;
|
|
17
|
+
before: RepoSnapshot;
|
|
18
|
+
after: RepoSnapshot;
|
|
19
|
+
agents: WorkflowAgentProof[];
|
|
20
|
+
evidence: WorkflowEvidenceRecord[];
|
|
21
|
+
harnessEvidence?: Readonly<Record<string, HarnessEvidenceCapability | undefined>>;
|
|
22
|
+
result?: unknown;
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function normalizeWorkflowMeta(meta: WorkflowMeta | undefined, fallbackName: string): NormalizedWorkflowMeta;
|
|
26
|
+
export declare function createEvidenceRecord(input: {
|
|
27
|
+
value: WorkflowEvidenceInput;
|
|
28
|
+
sequence: number;
|
|
29
|
+
acceptanceIds: ReadonlySet<string>;
|
|
30
|
+
stage?: string;
|
|
31
|
+
recordedAt?: string;
|
|
32
|
+
}): WorkflowEvidenceRecord;
|
|
33
|
+
export declare function rollupAcceptance(criteria: AcceptanceCriterion[], evidence: WorkflowEvidenceRecord[]): {
|
|
34
|
+
criteria: AcceptanceResult[];
|
|
35
|
+
summary: AcceptanceSummary;
|
|
36
|
+
};
|
|
37
|
+
export declare function digestResult(value: unknown, kind?: "text" | "json"): ResultDigest;
|
|
38
|
+
export declare function buildWorkflowProof(input: BuildWorkflowProofInput): WorkflowProof;
|
|
39
|
+
export declare function writeWorkflowProof(path: string, proof: WorkflowProof): void;
|
|
40
|
+
export declare function readWorkflowProof(coordRoot: string, runId: string): WorkflowProof;
|
|
41
|
+
export declare function renderWorkflowProof(proof: WorkflowProof): string;
|
|
42
|
+
//# sourceMappingURL=proof.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/proof.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EAEzB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,aAAa,EAId,MAAM,YAAY,CAAC;AAepB,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,mBAAmB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,sBAAsB,CAAC;IAC7B,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC,CAAC,CAAC;IAClF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,YAAY,GAAG,SAAS,EAC9B,YAAY,EAAE,MAAM,GACnB,sBAAsB,CAqCxB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,KAAK,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,sBAAsB,CA6BzB;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,QAAQ,EAAE,sBAAsB,EAAE,GACjC;IAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAuB9D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,CAQjF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,aAAa,CAwChF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAe3E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAkBjF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CA8BhE"}
|