harnery 0.10.0 → 0.12.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 -1
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +2 -0
- package/dist/commands/policy.d.ts +6 -0
- package/dist/commands/policy.d.ts.map +1 -0
- package/dist/commands/policy.js +42 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +62 -2
- package/dist/core/policy/evaluate.d.ts +14 -0
- package/dist/core/policy/evaluate.d.ts.map +1 -0
- package/dist/core/policy/evaluate.js +238 -0
- package/dist/core/policy/file.d.ts +3 -0
- package/dist/core/policy/file.d.ts.map +1 -0
- package/dist/core/policy/file.js +20 -0
- package/dist/core/policy/index.d.ts +5 -0
- package/dist/core/policy/index.d.ts.map +1 -0
- package/dist/core/policy/index.js +3 -0
- package/dist/core/policy/types.d.ts +91 -0
- package/dist/core/policy/types.d.ts.map +1 -0
- package/dist/core/policy/types.js +1 -0
- 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 +412 -47
- 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 +49 -0
- package/dist/core/workflow/proof.d.ts.map +1 -0
- package/dist/core/workflow/proof.js +375 -0
- package/dist/core/workflow/types.d.ts +180 -0
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/types.js +1 -1
- package/package.json +16 -6
- package/src/commander.ts +2 -0
- package/src/commands/policy.ts +50 -0
- package/src/commands/workflow.ts +82 -2
- package/src/core/policy/evaluate.ts +311 -0
- package/src/core/policy/file.ts +20 -0
- package/src/core/policy/index.ts +26 -0
- package/src/core/policy/types.ts +107 -0
- package/src/core/workflow/engine.ts +452 -53
- package/src/core/workflow/index.ts +44 -0
- package/src/core/workflow/proof.ts +485 -0
- package/src/core/workflow/types.ts +210 -0
|
@@ -7,8 +7,193 @@
|
|
|
7
7
|
* Design record: decision 0015 (portable coordination-aware workflows).
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import type {
|
|
11
|
+
DispatchCostEstimator,
|
|
12
|
+
ExternalMutationRequest,
|
|
13
|
+
NormalizedPolicy,
|
|
14
|
+
PolicyAskResolver,
|
|
15
|
+
PolicyDecision,
|
|
16
|
+
PolicyIsolation,
|
|
17
|
+
PolicyNetworkAccess,
|
|
18
|
+
PolicySpec,
|
|
19
|
+
} from "../policy/index.ts";
|
|
10
20
|
import type { BillingMode, BillingProber } from "./billing.ts";
|
|
11
21
|
|
|
22
|
+
export const WORKFLOW_PROOF_SCHEMA_VERSION = 1 as const;
|
|
23
|
+
|
|
24
|
+
export type EvidenceKind = "test" | "command" | "artifact" | "change" | "review" | "observation";
|
|
25
|
+
export type EvidenceStatus = "passed" | "failed" | "observed" | "unknown";
|
|
26
|
+
export type EvidenceSource = "workflow" | "engine";
|
|
27
|
+
export type AcceptanceStatus = "satisfied" | "unsatisfied" | "unknown";
|
|
28
|
+
export type WorkflowRunStatus = "succeeded" | "failed";
|
|
29
|
+
|
|
30
|
+
export interface AcceptanceCriterion {
|
|
31
|
+
/** Stable identifier referenced by evidence, for example `tests-pass`. */
|
|
32
|
+
id: string;
|
|
33
|
+
statement: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface WorkflowEvidenceInput {
|
|
37
|
+
kind: EvidenceKind;
|
|
38
|
+
status: EvidenceStatus;
|
|
39
|
+
label: string;
|
|
40
|
+
summary?: string;
|
|
41
|
+
/** Inspectable local path, URL, command name, or other bounded reference. */
|
|
42
|
+
ref?: string;
|
|
43
|
+
/** Declared acceptance criteria this evidence bears on. */
|
|
44
|
+
acceptanceIds?: string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface WorkflowEvidenceRecord {
|
|
48
|
+
id: string;
|
|
49
|
+
source: EvidenceSource;
|
|
50
|
+
recorded_at: string;
|
|
51
|
+
kind: EvidenceKind;
|
|
52
|
+
status: EvidenceStatus;
|
|
53
|
+
label: string;
|
|
54
|
+
summary?: string;
|
|
55
|
+
ref?: string;
|
|
56
|
+
stage?: string;
|
|
57
|
+
acceptance_ids: string[];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface AcceptanceResult extends AcceptanceCriterion {
|
|
61
|
+
status: AcceptanceStatus;
|
|
62
|
+
evidence_ids: string[];
|
|
63
|
+
/** Sources behind the decisive evidence. Empty when status is unknown. */
|
|
64
|
+
sources: EvidenceSource[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface AcceptanceSummary {
|
|
68
|
+
satisfied: number;
|
|
69
|
+
unsatisfied: number;
|
|
70
|
+
unknown: number;
|
|
71
|
+
total: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface ResultDigest {
|
|
75
|
+
kind: "text" | "json";
|
|
76
|
+
sha256: string;
|
|
77
|
+
bytes: number;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface WorkflowAgentProof {
|
|
81
|
+
id: string;
|
|
82
|
+
label: string;
|
|
83
|
+
stage?: string;
|
|
84
|
+
harness: HarnessName;
|
|
85
|
+
model?: string;
|
|
86
|
+
status: "succeeded" | "failed" | "cached";
|
|
87
|
+
attempts: number;
|
|
88
|
+
duration_ms: number;
|
|
89
|
+
cost_usd?: number;
|
|
90
|
+
session_id?: string;
|
|
91
|
+
result?: ResultDigest;
|
|
92
|
+
error?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface WorkflowRepoSnapshot {
|
|
96
|
+
cwd: string;
|
|
97
|
+
root?: string;
|
|
98
|
+
branch?: string;
|
|
99
|
+
head?: string;
|
|
100
|
+
dirty_paths: string[];
|
|
101
|
+
dirty_paths_truncated?: boolean;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface WorkflowRepoEvidence {
|
|
105
|
+
source: "engine";
|
|
106
|
+
before: WorkflowRepoSnapshot;
|
|
107
|
+
after: WorkflowRepoSnapshot;
|
|
108
|
+
drift: {
|
|
109
|
+
branch_changed: boolean;
|
|
110
|
+
head_changed: boolean;
|
|
111
|
+
dirty_paths_added: string[];
|
|
112
|
+
dirty_paths_cleared: string[];
|
|
113
|
+
dirty_paths_retained: string[];
|
|
114
|
+
/** True when snapshots cannot prove whether every retained dirty path changed. */
|
|
115
|
+
incomplete: boolean;
|
|
116
|
+
note?: string;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface HarnessEvidenceCoverage {
|
|
121
|
+
harness: HarnessName;
|
|
122
|
+
tool_evidence: {
|
|
123
|
+
support: "supported" | "partial" | "unsupported" | "unknown";
|
|
124
|
+
note?: string;
|
|
125
|
+
};
|
|
126
|
+
observed: {
|
|
127
|
+
final_results: number;
|
|
128
|
+
session_ids: number;
|
|
129
|
+
costs: number;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface WorkflowProofUnknown {
|
|
134
|
+
code:
|
|
135
|
+
| "tool_evidence_unavailable"
|
|
136
|
+
| "harness_capability_unregistered"
|
|
137
|
+
| "agent_cost_unreported"
|
|
138
|
+
| "agent_session_unreported"
|
|
139
|
+
| "repository_drift_incomplete";
|
|
140
|
+
message: string;
|
|
141
|
+
harness?: HarnessName;
|
|
142
|
+
agent_id?: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface WorkflowProof {
|
|
146
|
+
schema_version: typeof WORKFLOW_PROOF_SCHEMA_VERSION;
|
|
147
|
+
run: {
|
|
148
|
+
id: string;
|
|
149
|
+
name: string;
|
|
150
|
+
status: WorkflowRunStatus;
|
|
151
|
+
started_at: string;
|
|
152
|
+
ended_at: string;
|
|
153
|
+
duration_ms: number;
|
|
154
|
+
objective?: string;
|
|
155
|
+
error?: string;
|
|
156
|
+
result?: ResultDigest;
|
|
157
|
+
};
|
|
158
|
+
acceptance: {
|
|
159
|
+
criteria: AcceptanceResult[];
|
|
160
|
+
summary: AcceptanceSummary;
|
|
161
|
+
};
|
|
162
|
+
agents: WorkflowAgentProof[];
|
|
163
|
+
evidence: WorkflowEvidenceRecord[];
|
|
164
|
+
policy?: WorkflowPolicyProof;
|
|
165
|
+
repository: WorkflowRepoEvidence;
|
|
166
|
+
harnesses: HarnessEvidenceCoverage[];
|
|
167
|
+
unknowns: WorkflowProofUnknown[];
|
|
168
|
+
integrity: {
|
|
169
|
+
journal: {
|
|
170
|
+
path: "journal.jsonl";
|
|
171
|
+
sha256: string;
|
|
172
|
+
bytes: number;
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface WorkflowPolicyProof {
|
|
178
|
+
schema_version: 1;
|
|
179
|
+
name: string;
|
|
180
|
+
sha256: string;
|
|
181
|
+
isolation: PolicyIsolation;
|
|
182
|
+
network_access: PolicyNetworkAccess;
|
|
183
|
+
config: NormalizedPolicy;
|
|
184
|
+
decisions: PolicyDecision[];
|
|
185
|
+
summary: {
|
|
186
|
+
allowed: number;
|
|
187
|
+
denied: number;
|
|
188
|
+
asked: number;
|
|
189
|
+
total: number;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface HarnessEvidenceCapability {
|
|
194
|
+
toolEvidence: HarnessEvidenceCoverage["tool_evidence"];
|
|
195
|
+
}
|
|
196
|
+
|
|
12
197
|
/** JSON-schema *subset* accepted by stage gates (see validate.ts). */
|
|
13
198
|
export interface StageSchema {
|
|
14
199
|
type: "object" | "array" | "string" | "number" | "boolean";
|
|
@@ -94,11 +279,17 @@ export interface WorkflowContext {
|
|
|
94
279
|
stage: (title: string) => void;
|
|
95
280
|
/** Narrate progress (stderr + journal). */
|
|
96
281
|
log: (message: string) => void;
|
|
282
|
+
/** Attach a bounded, sourced receipt to the run and optional acceptance criteria. */
|
|
283
|
+
evidence: (input: WorkflowEvidenceInput) => string;
|
|
284
|
+
/** Authorize one host-mediated external mutation before performing it. */
|
|
285
|
+
authorize: (input: ExternalMutationRequest) => Promise<PolicyDecision>;
|
|
97
286
|
}
|
|
98
287
|
|
|
99
288
|
export interface WorkflowMeta {
|
|
100
289
|
name: string;
|
|
101
290
|
description?: string;
|
|
291
|
+
objective?: string;
|
|
292
|
+
acceptance?: AcceptanceCriterion[];
|
|
102
293
|
}
|
|
103
294
|
|
|
104
295
|
/** Loaded script shape: `export const meta` + `export default async (ctx) => …`. */
|
|
@@ -138,6 +329,21 @@ export interface EngineOpts {
|
|
|
138
329
|
allowApiBilling?: boolean;
|
|
139
330
|
/** Billing-probe override for tests (default: the real probeBilling). */
|
|
140
331
|
probeBilling?: BillingProber;
|
|
332
|
+
/** Capability claims used to state whether adapter-native tool evidence was
|
|
333
|
+
* available. Missing claims remain unknown. */
|
|
334
|
+
harnessEvidence?: Readonly<Record<HarnessName, HarnessEvidenceCapability | undefined>>;
|
|
335
|
+
/** Immutable host policy. Workflow scripts and model prompts cannot replace it. */
|
|
336
|
+
policy?: PolicySpec | NormalizedPolicy;
|
|
337
|
+
/** Host callback for ASK. Missing, invalid, throwing, or timed-out resolution denies. */
|
|
338
|
+
resolvePolicyAsk?: PolicyAskResolver;
|
|
339
|
+
/** Host-owned cost projection. Required to allow budgeted dispatches with known pricing. */
|
|
340
|
+
estimateDispatchCost?: DispatchCostEstimator;
|
|
341
|
+
/** Maximum wait for an ASK resolver (default 60 seconds). */
|
|
342
|
+
policyAskTimeoutMs?: number;
|
|
343
|
+
/** Execution boundary created by the host (default shared). */
|
|
344
|
+
isolation?: PolicyIsolation;
|
|
345
|
+
/** Network state of spawned harness subprocesses (default unknown). */
|
|
346
|
+
networkAccess?: PolicyNetworkAccess;
|
|
141
347
|
}
|
|
142
348
|
|
|
143
349
|
export interface RunReport {
|
|
@@ -151,10 +357,14 @@ export interface RunReport {
|
|
|
151
357
|
costUsd: number;
|
|
152
358
|
durationMs: number;
|
|
153
359
|
journalPath: string;
|
|
360
|
+
proofPath: string;
|
|
361
|
+
acceptance: AcceptanceSummary;
|
|
154
362
|
/** Estimated tokens of repo instructions (CLAUDE.md/AGENTS.md at the child
|
|
155
363
|
* cwd) that EVERY child cache-writes on spawn — the fixed per-child context
|
|
156
364
|
* overhead a fan-out multiplies. bytes/4 heuristic; 0 when no such file. */
|
|
157
365
|
contextTokensPerChildEstimate: number;
|
|
158
366
|
/** Billing mode per harness actually used this run (probed on first use). */
|
|
159
367
|
billing: Array<{ harness: HarnessName; mode: BillingMode }>;
|
|
368
|
+
/** Policy verdict totals when the host supplied a policy. */
|
|
369
|
+
policy?: WorkflowPolicyProof["summary"];
|
|
160
370
|
}
|