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
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { exec } from "../../lib/exec.ts";
|
|
20
|
+
import { validateHarnessEffort } from "../harnesses/profiles.ts";
|
|
21
|
+
import type { HarnessInvocation, HarnessRawResult } from "../harnesses/types.ts";
|
|
20
22
|
import { buildChildEnv } from "./child-env.ts";
|
|
21
23
|
import { notFoundError } from "./harnesses.ts";
|
|
22
24
|
import type { Spawner, SpawnRequest, SpawnResult } from "./types.ts";
|
|
@@ -46,44 +48,61 @@ export function parseCursorOutput(stdout: string): {
|
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
export
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
export function buildCursorInvocation(req: SpawnRequest): HarnessInvocation {
|
|
52
|
+
validateHarnessEffort("cursor", req.effort);
|
|
52
53
|
// --trust: headless cursor-agent refuses untrusted workspaces (exit 1,
|
|
53
54
|
// "Workspace Trust Required"). Workflow children run in the engine's cwd
|
|
54
55
|
// deliberately and may edit files — the same posture as the codex adapter's
|
|
55
56
|
// `--sandbox workspace-write` — so trusting that directory is implied.
|
|
56
57
|
const argv = ["cursor-agent", "-p", req.prompt, "--output-format", "json", "--trust"];
|
|
57
58
|
if (req.model) argv.push("--model", req.model);
|
|
59
|
+
return { argv };
|
|
60
|
+
}
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
timeout: req.timeoutMs,
|
|
63
|
-
});
|
|
64
|
-
const durationMs = Date.now() - t0;
|
|
65
|
-
|
|
66
|
-
if (r.exitCode === 127) {
|
|
67
|
-
return { ok: false, text: "", durationMs, error: notFoundError("cursor") };
|
|
62
|
+
export function normalizeCursorResult(raw: HarnessRawResult): SpawnResult {
|
|
63
|
+
if (raw.exitCode === 127) {
|
|
64
|
+
return { ok: false, text: "", durationMs: raw.durationMs, error: notFoundError("cursor") };
|
|
68
65
|
}
|
|
69
|
-
if (
|
|
66
|
+
if (raw.exitCode !== 0) {
|
|
70
67
|
return {
|
|
71
68
|
ok: false,
|
|
72
69
|
text: "",
|
|
73
|
-
durationMs,
|
|
74
|
-
error: `cursor-agent exited ${
|
|
70
|
+
durationMs: raw.durationMs,
|
|
71
|
+
error: `cursor-agent exited ${raw.exitCode}: ${(raw.stderr || raw.stdout).slice(0, 500)}`,
|
|
75
72
|
};
|
|
76
73
|
}
|
|
77
74
|
|
|
78
|
-
const parsed = parseCursorOutput(
|
|
75
|
+
const parsed = parseCursorOutput(raw.stdout);
|
|
79
76
|
if (parsed.isError) {
|
|
80
77
|
return {
|
|
81
78
|
ok: false,
|
|
82
79
|
text: parsed.text,
|
|
83
80
|
sessionId: parsed.sessionId,
|
|
84
|
-
durationMs,
|
|
81
|
+
durationMs: raw.durationMs,
|
|
85
82
|
error: `cursor-agent reported is_error: ${parsed.text.slice(0, 300)}`,
|
|
86
83
|
};
|
|
87
84
|
}
|
|
88
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
ok: true,
|
|
87
|
+
text: parsed.text,
|
|
88
|
+
sessionId: parsed.sessionId,
|
|
89
|
+
durationMs: raw.durationMs,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const cursorSpawner: Spawner = async (req: SpawnRequest): Promise<SpawnResult> => {
|
|
94
|
+
const t0 = Date.now();
|
|
95
|
+
let invocation: HarnessInvocation;
|
|
96
|
+
try {
|
|
97
|
+
invocation = buildCursorInvocation(req);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
return { ok: false, text: "", durationMs: 0, error: (error as Error).message };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const r = await exec(invocation.argv, {
|
|
103
|
+
cwd: req.cwd,
|
|
104
|
+
env: buildChildEnv(req.runId, { subscriptionOnly: req.subscriptionOnly }),
|
|
105
|
+
timeout: req.timeoutMs,
|
|
106
|
+
});
|
|
107
|
+
return normalizeCursorResult({ ...r, durationMs: Date.now() - t0 });
|
|
89
108
|
};
|
|
@@ -9,6 +9,164 @@
|
|
|
9
9
|
|
|
10
10
|
import type { BillingMode, BillingProber } from "./billing.ts";
|
|
11
11
|
|
|
12
|
+
export const WORKFLOW_PROOF_SCHEMA_VERSION = 1 as const;
|
|
13
|
+
|
|
14
|
+
export type EvidenceKind = "test" | "command" | "artifact" | "change" | "review" | "observation";
|
|
15
|
+
export type EvidenceStatus = "passed" | "failed" | "observed" | "unknown";
|
|
16
|
+
export type EvidenceSource = "workflow" | "engine";
|
|
17
|
+
export type AcceptanceStatus = "satisfied" | "unsatisfied" | "unknown";
|
|
18
|
+
export type WorkflowRunStatus = "succeeded" | "failed";
|
|
19
|
+
|
|
20
|
+
export interface AcceptanceCriterion {
|
|
21
|
+
/** Stable identifier referenced by evidence, for example `tests-pass`. */
|
|
22
|
+
id: string;
|
|
23
|
+
statement: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface WorkflowEvidenceInput {
|
|
27
|
+
kind: EvidenceKind;
|
|
28
|
+
status: EvidenceStatus;
|
|
29
|
+
label: string;
|
|
30
|
+
summary?: string;
|
|
31
|
+
/** Inspectable local path, URL, command name, or other bounded reference. */
|
|
32
|
+
ref?: string;
|
|
33
|
+
/** Declared acceptance criteria this evidence bears on. */
|
|
34
|
+
acceptanceIds?: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface WorkflowEvidenceRecord {
|
|
38
|
+
id: string;
|
|
39
|
+
source: EvidenceSource;
|
|
40
|
+
recorded_at: string;
|
|
41
|
+
kind: EvidenceKind;
|
|
42
|
+
status: EvidenceStatus;
|
|
43
|
+
label: string;
|
|
44
|
+
summary?: string;
|
|
45
|
+
ref?: string;
|
|
46
|
+
stage?: string;
|
|
47
|
+
acceptance_ids: string[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface AcceptanceResult extends AcceptanceCriterion {
|
|
51
|
+
status: AcceptanceStatus;
|
|
52
|
+
evidence_ids: string[];
|
|
53
|
+
/** Sources behind the decisive evidence. Empty when status is unknown. */
|
|
54
|
+
sources: EvidenceSource[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface AcceptanceSummary {
|
|
58
|
+
satisfied: number;
|
|
59
|
+
unsatisfied: number;
|
|
60
|
+
unknown: number;
|
|
61
|
+
total: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ResultDigest {
|
|
65
|
+
kind: "text" | "json";
|
|
66
|
+
sha256: string;
|
|
67
|
+
bytes: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface WorkflowAgentProof {
|
|
71
|
+
id: string;
|
|
72
|
+
label: string;
|
|
73
|
+
stage?: string;
|
|
74
|
+
harness: HarnessName;
|
|
75
|
+
model?: string;
|
|
76
|
+
status: "succeeded" | "failed" | "cached";
|
|
77
|
+
attempts: number;
|
|
78
|
+
duration_ms: number;
|
|
79
|
+
cost_usd?: number;
|
|
80
|
+
session_id?: string;
|
|
81
|
+
result?: ResultDigest;
|
|
82
|
+
error?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface WorkflowRepoSnapshot {
|
|
86
|
+
cwd: string;
|
|
87
|
+
root?: string;
|
|
88
|
+
branch?: string;
|
|
89
|
+
head?: string;
|
|
90
|
+
dirty_paths: string[];
|
|
91
|
+
dirty_paths_truncated?: boolean;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface WorkflowRepoEvidence {
|
|
95
|
+
source: "engine";
|
|
96
|
+
before: WorkflowRepoSnapshot;
|
|
97
|
+
after: WorkflowRepoSnapshot;
|
|
98
|
+
drift: {
|
|
99
|
+
branch_changed: boolean;
|
|
100
|
+
head_changed: boolean;
|
|
101
|
+
dirty_paths_added: string[];
|
|
102
|
+
dirty_paths_cleared: string[];
|
|
103
|
+
dirty_paths_retained: string[];
|
|
104
|
+
/** True when snapshots cannot prove whether every retained dirty path changed. */
|
|
105
|
+
incomplete: boolean;
|
|
106
|
+
note?: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface HarnessEvidenceCoverage {
|
|
111
|
+
harness: HarnessName;
|
|
112
|
+
tool_evidence: {
|
|
113
|
+
support: "supported" | "partial" | "unsupported" | "unknown";
|
|
114
|
+
note?: string;
|
|
115
|
+
};
|
|
116
|
+
observed: {
|
|
117
|
+
final_results: number;
|
|
118
|
+
session_ids: number;
|
|
119
|
+
costs: number;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface WorkflowProofUnknown {
|
|
124
|
+
code:
|
|
125
|
+
| "tool_evidence_unavailable"
|
|
126
|
+
| "harness_capability_unregistered"
|
|
127
|
+
| "agent_cost_unreported"
|
|
128
|
+
| "agent_session_unreported"
|
|
129
|
+
| "repository_drift_incomplete";
|
|
130
|
+
message: string;
|
|
131
|
+
harness?: HarnessName;
|
|
132
|
+
agent_id?: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface WorkflowProof {
|
|
136
|
+
schema_version: typeof WORKFLOW_PROOF_SCHEMA_VERSION;
|
|
137
|
+
run: {
|
|
138
|
+
id: string;
|
|
139
|
+
name: string;
|
|
140
|
+
status: WorkflowRunStatus;
|
|
141
|
+
started_at: string;
|
|
142
|
+
ended_at: string;
|
|
143
|
+
duration_ms: number;
|
|
144
|
+
objective?: string;
|
|
145
|
+
error?: string;
|
|
146
|
+
result?: ResultDigest;
|
|
147
|
+
};
|
|
148
|
+
acceptance: {
|
|
149
|
+
criteria: AcceptanceResult[];
|
|
150
|
+
summary: AcceptanceSummary;
|
|
151
|
+
};
|
|
152
|
+
agents: WorkflowAgentProof[];
|
|
153
|
+
evidence: WorkflowEvidenceRecord[];
|
|
154
|
+
repository: WorkflowRepoEvidence;
|
|
155
|
+
harnesses: HarnessEvidenceCoverage[];
|
|
156
|
+
unknowns: WorkflowProofUnknown[];
|
|
157
|
+
integrity: {
|
|
158
|
+
journal: {
|
|
159
|
+
path: "journal.jsonl";
|
|
160
|
+
sha256: string;
|
|
161
|
+
bytes: number;
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface HarnessEvidenceCapability {
|
|
167
|
+
toolEvidence: HarnessEvidenceCoverage["tool_evidence"];
|
|
168
|
+
}
|
|
169
|
+
|
|
12
170
|
/** JSON-schema *subset* accepted by stage gates (see validate.ts). */
|
|
13
171
|
export interface StageSchema {
|
|
14
172
|
type: "object" | "array" | "string" | "number" | "boolean";
|
|
@@ -28,6 +186,9 @@ export interface AgentOpts {
|
|
|
28
186
|
schema?: StageSchema;
|
|
29
187
|
/** Model slug passed through to the harness CLI (default: the CLI's default). */
|
|
30
188
|
model?: string;
|
|
189
|
+
/** Reasoning effort mapped through the selected harness profile. Unsupported
|
|
190
|
+
* values fail before the vendor process starts. */
|
|
191
|
+
effort?: string;
|
|
31
192
|
/** Attempt ceiling for the schema-retry loop (default 2). */
|
|
32
193
|
maxAttempts?: number;
|
|
33
194
|
/** Subprocess timeout ms (default 300_000). */
|
|
@@ -43,7 +204,10 @@ export interface AgentOpts {
|
|
|
43
204
|
harness?: HarnessName;
|
|
44
205
|
}
|
|
45
206
|
|
|
46
|
-
|
|
207
|
+
/** Open registry key. The built-in catalog currently contains Claude Code,
|
|
208
|
+
* Codex, and Cursor; consumers may register another adapter without widening
|
|
209
|
+
* a package-owned union first. */
|
|
210
|
+
export type HarnessName = string;
|
|
47
211
|
|
|
48
212
|
/** What a spawn adapter returns for one subagent run. */
|
|
49
213
|
export interface SpawnResult {
|
|
@@ -61,6 +225,7 @@ export interface SpawnResult {
|
|
|
61
225
|
export interface SpawnRequest {
|
|
62
226
|
prompt: string;
|
|
63
227
|
model?: string;
|
|
228
|
+
effort?: string;
|
|
64
229
|
timeoutMs: number;
|
|
65
230
|
maxTurns: number;
|
|
66
231
|
cwd: string;
|
|
@@ -87,11 +252,15 @@ export interface WorkflowContext {
|
|
|
87
252
|
stage: (title: string) => void;
|
|
88
253
|
/** Narrate progress (stderr + journal). */
|
|
89
254
|
log: (message: string) => void;
|
|
255
|
+
/** Attach a bounded, sourced receipt to the run and optional acceptance criteria. */
|
|
256
|
+
evidence: (input: WorkflowEvidenceInput) => string;
|
|
90
257
|
}
|
|
91
258
|
|
|
92
259
|
export interface WorkflowMeta {
|
|
93
260
|
name: string;
|
|
94
261
|
description?: string;
|
|
262
|
+
objective?: string;
|
|
263
|
+
acceptance?: AcceptanceCriterion[];
|
|
95
264
|
}
|
|
96
265
|
|
|
97
266
|
/** Loaded script shape: `export const meta` + `export default async (ctx) => …`. */
|
|
@@ -105,7 +274,7 @@ export interface EngineOpts {
|
|
|
105
274
|
coordRoot: string;
|
|
106
275
|
/** Spawner registry keyed by harness. A single-harness caller registers one
|
|
107
276
|
* entry and names it in `defaultHarness`. */
|
|
108
|
-
spawners:
|
|
277
|
+
spawners: Readonly<Record<HarnessName, Spawner | undefined>>;
|
|
109
278
|
/** Harness used when an agent() call doesn't name one (default "claude-code"). */
|
|
110
279
|
defaultHarness?: HarnessName;
|
|
111
280
|
/** Resume: run id of a prior run whose journal supplies cached results.
|
|
@@ -131,6 +300,9 @@ export interface EngineOpts {
|
|
|
131
300
|
allowApiBilling?: boolean;
|
|
132
301
|
/** Billing-probe override for tests (default: the real probeBilling). */
|
|
133
302
|
probeBilling?: BillingProber;
|
|
303
|
+
/** Capability claims used to state whether adapter-native tool evidence was
|
|
304
|
+
* available. Missing claims remain unknown. */
|
|
305
|
+
harnessEvidence?: Readonly<Record<HarnessName, HarnessEvidenceCapability | undefined>>;
|
|
134
306
|
}
|
|
135
307
|
|
|
136
308
|
export interface RunReport {
|
|
@@ -144,6 +316,8 @@ export interface RunReport {
|
|
|
144
316
|
costUsd: number;
|
|
145
317
|
durationMs: number;
|
|
146
318
|
journalPath: string;
|
|
319
|
+
proofPath: string;
|
|
320
|
+
acceptance: AcceptanceSummary;
|
|
147
321
|
/** Estimated tokens of repo instructions (CLAUDE.md/AGENTS.md at the child
|
|
148
322
|
* cwd) that EVERY child cache-writes on spawn — the fixed per-child context
|
|
149
323
|
* overhead a fan-out multiplies. bytes/4 heuristic; 0 when no such file. */
|
|
@@ -74,6 +74,14 @@ export interface BrowserOptions {
|
|
|
74
74
|
* via this callback (e.g., a Cloudflare-bypass header for specific zones).
|
|
75
75
|
*/
|
|
76
76
|
extraHeaders?: (url: string) => Record<string, string>;
|
|
77
|
+
/**
|
|
78
|
+
* Extra Chromium command-line flags, passed through to Playwright's
|
|
79
|
+
* `launchPersistentContext` `args`. Used for environment-specific
|
|
80
|
+
* workarounds — most notably `--disable-gpu` for headed windows under
|
|
81
|
+
* WSLg (see `./launch-args.ts`). Empty/undefined means Playwright's
|
|
82
|
+
* defaults only.
|
|
83
|
+
*/
|
|
84
|
+
launchArgs?: string[];
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
export interface NavigateResult {
|
|
@@ -98,6 +106,14 @@ export interface FailedRequest {
|
|
|
98
106
|
method: string;
|
|
99
107
|
failure: string;
|
|
100
108
|
resourceType: string;
|
|
109
|
+
/** HTTP status for kind "http" entries; null for network-level failures. */
|
|
110
|
+
status: number | null;
|
|
111
|
+
/** "http" = request completed with a >=400 response; "network" = never completed (DNS, TLS, aborts, tunnel). */
|
|
112
|
+
kind: "http" | "network";
|
|
113
|
+
/** True when the entry is the main frame's document response — lets consumers
|
|
114
|
+
* distinguish an expected error-page status (a 404 route under test) from a
|
|
115
|
+
* broken subresource. */
|
|
116
|
+
document?: boolean;
|
|
101
117
|
}
|
|
102
118
|
|
|
103
119
|
export interface Diagnostics {
|
|
@@ -137,6 +153,9 @@ export class Browser {
|
|
|
137
153
|
this.context = await chromium.launchPersistentContext(this.profileDir, {
|
|
138
154
|
headless: !this.opts.headed,
|
|
139
155
|
viewport: this.opts.viewport ?? { width: 1280, height: 800 },
|
|
156
|
+
...(this.opts.launchArgs && this.opts.launchArgs.length > 0
|
|
157
|
+
? { args: this.opts.launchArgs }
|
|
158
|
+
: {}),
|
|
140
159
|
...(this.opts.recordHarPath
|
|
141
160
|
? { recordHar: { path: this.opts.recordHarPath, mode: "full" as const } }
|
|
142
161
|
: {}),
|
|
@@ -192,6 +211,24 @@ export class Browser {
|
|
|
192
211
|
method: req.method(),
|
|
193
212
|
failure: req.failure()?.errorText ?? "unknown",
|
|
194
213
|
resourceType: req.resourceType(),
|
|
214
|
+
status: null,
|
|
215
|
+
kind: "network",
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
// HTTP-level failures: `requestfailed` only fires for requests that never
|
|
219
|
+
// complete (DNS, TLS, aborts), so a script/stylesheet answered with a
|
|
220
|
+
// 4xx/5xx would otherwise be invisible to failedRequests-based gates.
|
|
221
|
+
page.on("response", (res) => {
|
|
222
|
+
if (res.status() < 400) return;
|
|
223
|
+
const req = res.request();
|
|
224
|
+
this.failedRequests.push({
|
|
225
|
+
url: res.url(),
|
|
226
|
+
method: req.method(),
|
|
227
|
+
failure: `HTTP ${res.status()}`,
|
|
228
|
+
resourceType: req.resourceType(),
|
|
229
|
+
status: res.status(),
|
|
230
|
+
kind: "http",
|
|
231
|
+
document: req.resourceType() === "document" && res.frame() === page.mainFrame(),
|
|
195
232
|
});
|
|
196
233
|
});
|
|
197
234
|
}
|
package/src/lib/browser/index.ts
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Chromium launch-arg helpers for environment-specific workarounds.
|
|
5
|
+
*
|
|
6
|
+
* The one that matters today is WSLg: a headed Chromium window renders its
|
|
7
|
+
* page to a GPU-backed surface that WSLg composites over an RDP stream to the
|
|
8
|
+
* Windows host. On a range of Windows / GPU-driver / WSLg combinations that
|
|
9
|
+
* GPU-composited surface never presents, so the window shows in the taskbar
|
|
10
|
+
* but paints blank — even though the page itself runs fine (JS, navigation,
|
|
11
|
+
* and DOM all work). Forcing Chromium onto its software compositor with
|
|
12
|
+
* `--disable-gpu` restores on-screen paint. It only matters for headed mode
|
|
13
|
+
* (headless never composites to a display) and only under WSL.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** True when running under WSL (WSL1 or WSL2). */
|
|
17
|
+
export function isWSL(): boolean {
|
|
18
|
+
if (process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP) return true;
|
|
19
|
+
try {
|
|
20
|
+
return /microsoft|wsl/i.test(readFileSync("/proc/version", "utf8"));
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Chromium launch flags to make a headed window paint under WSLg. Returns
|
|
28
|
+
* `["--disable-gpu"]` on WSL, `[]` elsewhere. Callers apply these only for
|
|
29
|
+
* headed launches. See the module doc for the failure mode.
|
|
30
|
+
*/
|
|
31
|
+
export function wslHeadedLaunchArgs(): string[] {
|
|
32
|
+
return isWSL() ? ["--disable-gpu"] : [];
|
|
33
|
+
}
|