harnery 0.11.0 → 0.12.1

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.
Files changed (57) hide show
  1. package/README.md +1 -1
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +2 -0
  4. package/dist/commands/browse.js +1 -3
  5. package/dist/commands/eml.d.ts.map +1 -1
  6. package/dist/commands/eml.js +11 -50
  7. package/dist/commands/policy.d.ts +6 -0
  8. package/dist/commands/policy.d.ts.map +1 -0
  9. package/dist/commands/policy.js +42 -0
  10. package/dist/commands/workflow.d.ts.map +1 -1
  11. package/dist/commands/workflow.js +18 -1
  12. package/dist/core/agents/coord-client.d.ts +7 -0
  13. package/dist/core/agents/coord-client.d.ts.map +1 -1
  14. package/dist/core/agents/coord-client.js +27 -1
  15. package/dist/core/policy/evaluate.d.ts +14 -0
  16. package/dist/core/policy/evaluate.d.ts.map +1 -0
  17. package/dist/core/policy/evaluate.js +238 -0
  18. package/dist/core/policy/file.d.ts +3 -0
  19. package/dist/core/policy/file.d.ts.map +1 -0
  20. package/dist/core/policy/file.js +20 -0
  21. package/dist/core/policy/index.d.ts +5 -0
  22. package/dist/core/policy/index.d.ts.map +1 -0
  23. package/dist/core/policy/index.js +3 -0
  24. package/dist/core/policy/types.d.ts +91 -0
  25. package/dist/core/policy/types.d.ts.map +1 -0
  26. package/dist/core/policy/types.js +1 -0
  27. package/dist/core/scratch/index.d.ts.map +1 -1
  28. package/dist/core/scratch/index.js +14 -4
  29. package/dist/core/workflow/engine.d.ts.map +1 -1
  30. package/dist/core/workflow/engine.js +261 -35
  31. package/dist/core/workflow/index.d.ts +1 -1
  32. package/dist/core/workflow/index.d.ts.map +1 -1
  33. package/dist/core/workflow/proof.d.ts +7 -0
  34. package/dist/core/workflow/proof.d.ts.map +1 -1
  35. package/dist/core/workflow/proof.js +33 -0
  36. package/dist/core/workflow/types.d.ts +33 -0
  37. package/dist/core/workflow/types.d.ts.map +1 -1
  38. package/dist/lib/browser/client.d.ts +1 -1
  39. package/dist/lib/browser/client.d.ts.map +1 -1
  40. package/dist/lib/browser/client.js +7 -1
  41. package/package.json +9 -4
  42. package/src/commander.ts +2 -0
  43. package/src/commands/browse.ts +1 -5
  44. package/src/commands/eml.ts +11 -62
  45. package/src/commands/policy.ts +50 -0
  46. package/src/commands/workflow.ts +29 -1
  47. package/src/core/agents/coord-client.ts +28 -1
  48. package/src/core/policy/evaluate.ts +311 -0
  49. package/src/core/policy/file.ts +20 -0
  50. package/src/core/policy/index.ts +26 -0
  51. package/src/core/policy/types.ts +107 -0
  52. package/src/core/scratch/index.ts +20 -4
  53. package/src/core/workflow/engine.ts +283 -41
  54. package/src/core/workflow/index.ts +1 -0
  55. package/src/core/workflow/proof.ts +51 -0
  56. package/src/core/workflow/types.ts +43 -0
  57. package/src/lib/browser/client.ts +6 -1
@@ -0,0 +1,3 @@
1
+ export { evaluatePolicy, normalizePolicy, PolicyDeniedError, policyDigest, summarizePolicyRequest, } from "./evaluate.js";
2
+ export { loadPolicyFile } from "./file.js";
3
+ export { POLICY_SCHEMA_VERSION } from "./types.js";
@@ -0,0 +1,91 @@
1
+ export declare const POLICY_SCHEMA_VERSION: 1;
2
+ export type PolicyVerdict = "allow" | "ask" | "deny";
3
+ export type PolicyPhase = "dispatch" | "external_mutation";
4
+ export type PolicyIsolation = "shared" | "worktree" | "sandbox" | "remote";
5
+ export type PolicyNetworkAccess = "enabled" | "disabled" | "unknown";
6
+ /** Host-owned policy document. Workflow metadata cannot supply this value. */
7
+ export interface PolicySpec {
8
+ schema_version?: typeof POLICY_SCHEMA_VERSION;
9
+ name?: string;
10
+ max_cost_usd?: number;
11
+ /** Applied when a cost ceiling exists but the host cannot price a dispatch. */
12
+ unknown_cost?: Exclude<PolicyVerdict, "allow">;
13
+ allowed_harnesses?: readonly string[];
14
+ allowed_models?: readonly string[];
15
+ /** Absolute paths, or paths relative to the policy file. */
16
+ allowed_paths?: readonly string[];
17
+ network?: PolicyVerdict;
18
+ external_actions?: PolicyVerdict;
19
+ /** Allowed host-declared execution boundaries. No strength ordering is inferred. */
20
+ allowed_isolation?: readonly PolicyIsolation[];
21
+ }
22
+ export interface NormalizedPolicy {
23
+ schema_version: typeof POLICY_SCHEMA_VERSION;
24
+ name: string;
25
+ max_cost_usd?: number;
26
+ unknown_cost: Exclude<PolicyVerdict, "allow">;
27
+ allowed_harnesses?: readonly string[];
28
+ allowed_models?: readonly string[];
29
+ allowed_paths?: readonly string[];
30
+ network: PolicyVerdict;
31
+ external_actions: PolicyVerdict;
32
+ allowed_isolation?: readonly PolicyIsolation[];
33
+ }
34
+ export interface PolicyRequest {
35
+ phase: PolicyPhase;
36
+ action: string;
37
+ path?: string;
38
+ harness?: string;
39
+ model?: string;
40
+ effort?: string;
41
+ max_attempts?: number;
42
+ max_turns?: number;
43
+ timeout_ms?: number;
44
+ /** Prompt size for host estimation. Prompt content is never included. */
45
+ prompt_bytes?: number;
46
+ isolation: PolicyIsolation;
47
+ network_access: PolicyNetworkAccess;
48
+ service?: string;
49
+ target?: string;
50
+ current_cost_usd?: number;
51
+ projected_cost_usd?: number | null;
52
+ }
53
+ export type PolicyRequestSummary = PolicyRequest;
54
+ export interface PolicyRuleResult {
55
+ code: string;
56
+ verdict: PolicyVerdict;
57
+ reason: string;
58
+ }
59
+ export interface PolicyEvaluation {
60
+ verdict: PolicyVerdict;
61
+ reason: string;
62
+ rules: PolicyRuleResult[];
63
+ }
64
+ export interface PolicyAskResolution {
65
+ verdict: "allow" | "deny";
66
+ reason?: string;
67
+ }
68
+ export type PolicyAskResolver = (request: Readonly<PolicyRequestSummary>, evaluation: Readonly<PolicyEvaluation>) => Promise<PolicyAskResolution> | PolicyAskResolution;
69
+ export interface PolicyDecision {
70
+ id: string;
71
+ checked_at: string;
72
+ policy: string;
73
+ phase: PolicyPhase;
74
+ initial_verdict: PolicyVerdict;
75
+ verdict: "allow" | "deny";
76
+ resolved_by: "policy" | "host" | "fail_closed";
77
+ reason: string;
78
+ rule_codes: string[];
79
+ request: PolicyRequestSummary;
80
+ }
81
+ export interface ExternalMutationRequest {
82
+ /** Short verb phrase, for example "publish release" or "write report". */
83
+ action: string;
84
+ path?: string;
85
+ network?: boolean;
86
+ service?: string;
87
+ /** Bounded destination descriptor. Do not include credentials or payloads. */
88
+ target?: string;
89
+ }
90
+ export type DispatchCostEstimator = (request: Readonly<PolicyRequestSummary>) => Promise<number | null> | number | null;
91
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/policy/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export const POLICY_SCHEMA_VERSION = 1;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/scratch/index.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,kBAAkB,iFAQrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAC5C,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,6DAA6D;AAC7D,eAAO,MAAM,eAAe,QACyF,CAAC;AAEtH,mFAAmF;AACnF,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,UAAU,IAAI,MAAM,CAMnC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAInC;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtD;AAeD,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,CAAC,GAAE,IAAiB,GAAG,MAAM,CAW1D;AAID,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CA+DtE;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAkBxD;AAmBD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,SAAoB,GAAG,SAAS,EAAE,CA2DrF;AAID,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,MAAM,GACX,UAAU,CAgEZ;AAID,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOhE;AAED,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,IAAI,SAAyB,GAAG,MAAM,CAkBnE;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAajD;AAED,qDAAqD;AACrD,wBAAgB,YAAY,IAAI;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,EAAE,CAWF;AAID,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAIjE;AAED,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoB9D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/scratch/index.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,kBAAkB,iFAQrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAC5C,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,6DAA6D;AAC7D,eAAO,MAAM,eAAe,QACyF,CAAC;AAEtH,mFAAmF;AACnF,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,UAAU,IAAI,MAAM,CAMnC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAInC;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGtD;AAeD,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,CAAC,GAAE,IAAiB,GAAG,MAAM,CAW1D;AAID,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAwEtE;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAkBxD;AAmBD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,SAAoB,GAAG,SAAS,EAAE,CA2DrF;AAID,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,MAAM,GACX,UAAU,CAgEZ;AAID,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQhE;AAED,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,IAAI,SAAyB,GAAG,MAAM,CAkBnE;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAajD;AAED,qDAAqD;AACrD,wBAAgB,YAAY,IAAI;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,EAAE,CAWF;AAID,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAIjE;AAED,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoB9D"}
@@ -1,7 +1,7 @@
1
1
  import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
2
2
  import { dirname, resolve } from "node:path";
3
3
  import { resolveMachineLabel } from "../../lib/machine.js";
4
- import { monorepoRoot, readHeartbeat, resolveOwner } from "../agents/index.js";
4
+ import { assertSafeInstanceId, monorepoRoot, readHeartbeat, resolveOwner, } from "../agents/index.js";
5
5
  /**
6
6
  * Agent scratchpad: per-agent markdown journal at `.harnery/scratch/<instance_id>.md`.
7
7
  *
@@ -46,6 +46,7 @@ export function archiveDir() {
46
46
  return dir;
47
47
  }
48
48
  export function scratchPath(instanceId) {
49
+ assertSafeInstanceId(instanceId);
49
50
  return resolve(scratchDir(), `${instanceId}.md`);
50
51
  }
51
52
  // ─── Chicago time formatting ──────────────────────────────────────────────
@@ -96,9 +97,17 @@ export function parseScratch(path, content) {
96
97
  i++;
97
98
  break;
98
99
  }
99
- const m = line.match(/^(session_id|machine|started|last_updated):\s*(.+?)\s*$/);
100
- if (m) {
101
- header[m[1]] = m[2].trim();
100
+ const separator = line.indexOf(":");
101
+ if (separator > 0) {
102
+ const key = line.slice(0, separator);
103
+ if (key === "session_id" ||
104
+ key === "machine" ||
105
+ key === "started" ||
106
+ key === "last_updated") {
107
+ const value = line.slice(separator + 1).trim();
108
+ if (value)
109
+ header[key] = value;
110
+ }
102
111
  }
103
112
  }
104
113
  // ── entries ──
@@ -293,6 +302,7 @@ export function appendEntry(instanceId, category, body) {
293
302
  // ─── Archive lifecycle ────────────────────────────────────────────────────
294
303
  /** Move `<owner>.md` → `archived/<owner>-<ts>.md`. No-op if missing. Returns archive path (or null). */
295
304
  export function archiveScratch(instanceId) {
305
+ assertSafeInstanceId(instanceId);
296
306
  const src = scratchPath(instanceId);
297
307
  if (!existsSync(src))
298
308
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAeH,OAAO,KAAK,EAEV,UAAU,EAEV,SAAS,EAOV,MAAM,YAAY,CAAC;AAUpB,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM/E;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAqa1F"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAuBH,OAAO,KAAK,EAEV,UAAU,EAEV,SAAS,EAOV,MAAM,YAAY,CAAC;AAYpB,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM/E;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAsmB1F"}
@@ -29,6 +29,7 @@ import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync } from "n
29
29
  import { isAbsolute, join, resolve } from "node:path";
30
30
  import { pathToFileURL } from "node:url";
31
31
  import { snapshotRepo } from "../context/index.js";
32
+ import { evaluatePolicy, normalizePolicy, PolicyDeniedError, policyDigest, summarizePolicyRequest, } from "../policy/index.js";
32
33
  import { probeBilling } from "./billing.js";
33
34
  import { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, writeWorkflowProof, } from "./proof.js";
34
35
  import { WORKFLOW_PROOF_SCHEMA_VERSION } from "./types.js";
@@ -38,6 +39,8 @@ const DEFAULT_CONCURRENCY = 4;
38
39
  const DEFAULT_MAX_ATTEMPTS = 2;
39
40
  const DEFAULT_TIMEOUT_MS = 300_000;
40
41
  const DEFAULT_MAX_TURNS = 25;
42
+ const DEFAULT_POLICY_ASK_TIMEOUT_MS = 60_000;
43
+ const MAX_POLICY_DECISIONS = 50;
41
44
  export class WorkflowRunError extends Error {
42
45
  runId;
43
46
  proofPath;
@@ -67,6 +70,9 @@ export async function runWorkflow(scriptPath, opts) {
67
70
  const cwd = opts.cwd ?? opts.coordRoot;
68
71
  const log = opts.onLog ?? ((line) => process.stderr.write(`${line}\n`));
69
72
  const defaultHarness = opts.defaultHarness ?? "claude-code";
73
+ const isolation = opts.isolation ?? "shared";
74
+ const networkAccess = opts.networkAccess ?? "unknown";
75
+ const policy = opts.policy ? normalizePolicy(opts.policy, { baseDir: cwd }) : undefined;
70
76
  const repoBefore = snapshotRepo(cwd);
71
77
  // Per-child fixed context overhead: children spawn in `cwd` and load its
72
78
  // repo-instructions file into their system prompt, cache-writing it once
@@ -83,12 +89,15 @@ export async function runWorkflow(scriptPath, opts) {
83
89
  let agentsSpawned = 0;
84
90
  let agentsCached = 0;
85
91
  let costUsd = 0;
92
+ let reservedCostUsd = 0;
86
93
  let currentStage = "";
87
94
  let agentSeq = 0;
88
95
  let evidenceSeq = 0;
96
+ let policySeq = 0;
89
97
  const billingProbed = new Map();
90
98
  const agentProofs = new Map();
91
99
  const evidenceRecords = [];
100
+ const policyDecisions = [];
92
101
  const acceptanceIds = new Set(meta.acceptance.map((criterion) => criterion.id));
93
102
  const journal = (event, data) => {
94
103
  const line = JSON.stringify({
@@ -118,7 +127,90 @@ export async function runWorkflow(scriptPath, opts) {
118
127
  inFlight--;
119
128
  waiters.shift()?.();
120
129
  };
130
+ // Policy checks that affect the shared cost reservation ledger serialize.
131
+ // Spawns still run concurrently after authorization; only the last-moment
132
+ // check-and-reserve section is exclusive.
133
+ let policyGate = Promise.resolve();
134
+ const withDispatchPolicyGate = async (work) => {
135
+ const previous = policyGate;
136
+ let open;
137
+ policyGate = new Promise((resolveGate) => {
138
+ open = resolveGate;
139
+ });
140
+ await previous;
141
+ try {
142
+ return await work();
143
+ }
144
+ finally {
145
+ open();
146
+ }
147
+ };
148
+ const authorizePolicyRequest = async (rawRequest) => {
149
+ if (!policy) {
150
+ throw new Error("external mutation authorization requires a host policy");
151
+ }
152
+ if (policyDecisions.length >= MAX_POLICY_DECISIONS) {
153
+ throw new Error(`workflow policy decision cap reached (${MAX_POLICY_DECISIONS}); split the workflow or reduce protected actions`);
154
+ }
155
+ const request = summarizePolicyRequest(rawRequest);
156
+ const evaluation = evaluatePolicy(policy, request);
157
+ const id = `p${++policySeq}`;
158
+ const checkedAt = new Date().toISOString();
159
+ journal("policy.check", {
160
+ id,
161
+ policy: policy.name,
162
+ policy_sha256: policyDigest(policy),
163
+ request,
164
+ verdict: evaluation.verdict,
165
+ rules: evaluation.rules,
166
+ });
167
+ let verdict = evaluation.verdict === "allow" ? "allow" : "deny";
168
+ let resolvedBy = "policy";
169
+ let reason = evaluation.reason;
170
+ if (evaluation.verdict === "ask") {
171
+ resolvedBy = "fail_closed";
172
+ if (!opts.resolvePolicyAsk) {
173
+ reason = `${evaluation.reason}; no host approval resolver is configured`;
174
+ }
175
+ else {
176
+ try {
177
+ const resolution = await withTimeout(Promise.resolve(opts.resolvePolicyAsk(request, evaluation)), opts.policyAskTimeoutMs ?? DEFAULT_POLICY_ASK_TIMEOUT_MS);
178
+ if (!resolution || (resolution.verdict !== "allow" && resolution.verdict !== "deny")) {
179
+ reason = `${evaluation.reason}; host returned an invalid approval resolution`;
180
+ }
181
+ else {
182
+ verdict = resolution.verdict;
183
+ resolvedBy = "host";
184
+ reason = boundedPolicyReason(resolution.reason ?? evaluation.reason);
185
+ }
186
+ }
187
+ catch (error) {
188
+ reason = `${evaluation.reason}; approval failed closed: ${error.message}`;
189
+ }
190
+ }
191
+ }
192
+ const decision = {
193
+ id,
194
+ checked_at: checkedAt,
195
+ policy: policy.name,
196
+ phase: request.phase,
197
+ initial_verdict: evaluation.verdict,
198
+ verdict,
199
+ resolved_by: resolvedBy,
200
+ reason: boundedPolicyReason(reason),
201
+ rule_codes: evaluation.rules.map((rule) => rule.code),
202
+ request,
203
+ };
204
+ policyDecisions.push(decision);
205
+ journal("policy.resolve", { ...decision });
206
+ if (decision.verdict === "deny") {
207
+ throw new PolicyDeniedError(`policy ${JSON.stringify(policy.name)} denied ${request.phase} ${JSON.stringify(request.action)}: ${decision.reason}`, decision.id);
208
+ }
209
+ return decision;
210
+ };
121
211
  const agent = async (prompt, agentOpts = {}) => {
212
+ let reservedForDispatch = 0;
213
+ let spawnCountClaimed = false;
122
214
  const harness = agentOpts.harness ?? defaultHarness;
123
215
  const spawner = opts.spawners[harness];
124
216
  if (!spawner) {
@@ -158,50 +250,125 @@ export async function runWorkflow(scriptPath, opts) {
158
250
  log(`[${name}] ${currentStage || "(no stage)"} → ${id} ${label} (cached from ${opts.resumeFrom})`);
159
251
  return cached.value;
160
252
  }
161
- // Billing safeguard: on a harness's FIRST spawn this run, classify which
162
- // auth its children will use and refuse the silent-override state (an
163
- // exported API key shadowing a stored subscription login) unless the
164
- // caller explicitly opted into API billing. Cached agents never reach
165
- // this — no spawn, no billing.
166
- if (!billingProbed.has(harness)) {
167
- const probe = (opts.probeBilling ?? probeBilling)(harness);
168
- billingProbed.set(harness, probe);
169
- journal("billing.probe", {
253
+ if (policy) {
254
+ const estimateRequest = summarizePolicyRequest({
255
+ phase: "dispatch",
256
+ action: "spawn agent",
257
+ path: cwd,
170
258
  harness,
171
- mode: opts.subscriptionOnly ? "subscription" : probe.mode,
172
- api_key_source: probe.apiKeySource,
173
- login: probe.login,
174
- subscription_only: Boolean(opts.subscriptionOnly),
259
+ model: agentOpts.model,
260
+ effort: agentOpts.effort,
261
+ max_attempts: maxAttempts,
262
+ max_turns: agentOpts.maxTurns ?? DEFAULT_MAX_TURNS,
263
+ timeout_ms: agentOpts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
264
+ prompt_bytes: Buffer.byteLength(prompt),
265
+ isolation,
266
+ network_access: networkAccess,
267
+ current_cost_usd: round4(costUsd + reservedCostUsd),
268
+ projected_cost_usd: null,
175
269
  });
176
- if (opts.subscriptionOnly) {
177
- if (probe.login === "absent") {
178
- throw new Error(`subscription-only: no stored login detected for ${harness}; ` +
179
- `log the harness CLI in (or drop --subscription-only for a key-only host)`);
270
+ let projectedCost = null;
271
+ if (policy.max_cost_usd !== undefined && opts.estimateDispatchCost) {
272
+ try {
273
+ const candidate = await opts.estimateDispatchCost(estimateRequest);
274
+ if (candidate !== null && (!Number.isFinite(candidate) || candidate < 0)) {
275
+ throw new Error("cost estimator returned a non-finite or negative value");
276
+ }
277
+ projectedCost = candidate;
278
+ }
279
+ catch (error) {
280
+ journal("policy.cost_estimate_failed", {
281
+ harness,
282
+ model: agentOpts.model ?? null,
283
+ error: boundedPolicyReason(error.message),
284
+ });
180
285
  }
181
- log(`[billing] ${harness}: subscription-only (API-key vars scrubbed from child env)`);
182
286
  }
183
- else if (probe.mode === "api-key-override" && !opts.allowApiBilling) {
184
- throw new Error(`${probe.apiKeySource} is set AND a stored ${harness} login exists — the key silently ` +
185
- `overrides your subscription auth, so children would bill per-token API rates. ` +
186
- `Either unset ${probe.apiKeySource}, run with --subscription-only to scrub it from ` +
187
- `child envs, or pass --allow-api-billing if API billing is intended`);
287
+ try {
288
+ await withDispatchPolicyGate(async () => {
289
+ assertAgentCapacity(agentsSpawned, maxAgents);
290
+ const dispatchRequest = {
291
+ ...estimateRequest,
292
+ current_cost_usd: round4(costUsd + reservedCostUsd),
293
+ projected_cost_usd: projectedCost,
294
+ };
295
+ await authorizePolicyRequest(dispatchRequest);
296
+ if (policy.max_cost_usd !== undefined) {
297
+ reservedForDispatch =
298
+ projectedCost ?? Math.max(0, policy.max_cost_usd - dispatchRequest.current_cost_usd);
299
+ reservedCostUsd += reservedForDispatch;
300
+ }
301
+ agentsSpawned++;
302
+ spawnCountClaimed = true;
303
+ });
188
304
  }
189
- else if (probe.mode === "api-key") {
190
- log(`[billing] ${harness}: API-key billing (${probe.apiKeySource}; no stored login detected) — ` +
191
- `children bill per-token rates`);
305
+ catch (error) {
306
+ agentProof.error = error.message;
307
+ throw error;
192
308
  }
193
- else if (probe.mode === "api-key-override") {
194
- log(`[billing] ${harness}: API-key billing (--allow-api-billing; key overrides stored login)`);
309
+ }
310
+ else {
311
+ try {
312
+ assertAgentCapacity(agentsSpawned, maxAgents);
195
313
  }
196
- else {
197
- log(`[billing] ${harness}: subscription login`);
314
+ catch (error) {
315
+ agentProof.error = error.message;
316
+ throw error;
198
317
  }
199
318
  }
200
- if (agentsSpawned >= maxAgents) {
201
- agentProof.error = `workflow agent cap reached (${maxAgents})`;
202
- throw new Error(`workflow agent cap reached (${maxAgents}); raise --max-agents deliberately if the fan-out is intended`);
319
+ // Billing safeguard: on a harness's FIRST spawn this run, classify which
320
+ // auth its children will use and refuse the silent-override state (an
321
+ // exported API key shadowing a stored subscription login) unless the
322
+ // caller explicitly opted into API billing. Cached agents never reach
323
+ // this — no spawn, no billing.
324
+ try {
325
+ if (!billingProbed.has(harness)) {
326
+ const probe = (opts.probeBilling ?? probeBilling)(harness);
327
+ billingProbed.set(harness, probe);
328
+ journal("billing.probe", {
329
+ harness,
330
+ mode: opts.subscriptionOnly ? "subscription" : probe.mode,
331
+ api_key_source: probe.apiKeySource,
332
+ login: probe.login,
333
+ subscription_only: Boolean(opts.subscriptionOnly),
334
+ });
335
+ if (opts.subscriptionOnly) {
336
+ if (probe.login === "absent") {
337
+ throw new Error(`subscription-only: no stored login detected for ${harness}; ` +
338
+ `log the harness CLI in (or drop --subscription-only for a key-only host)`);
339
+ }
340
+ log(`[billing] ${harness}: subscription-only (API-key vars scrubbed from child env)`);
341
+ }
342
+ else if (probe.mode === "api-key-override" && !opts.allowApiBilling) {
343
+ throw new Error(`${probe.apiKeySource} is set AND a stored ${harness} login exists — the key silently ` +
344
+ `overrides your subscription auth, so children would bill per-token API rates. ` +
345
+ `Either unset ${probe.apiKeySource}, run with --subscription-only to scrub it from ` +
346
+ `child envs, or pass --allow-api-billing if API billing is intended`);
347
+ }
348
+ else if (probe.mode === "api-key") {
349
+ log(`[billing] ${harness}: API-key billing (${probe.apiKeySource}; no stored login detected) — ` +
350
+ `children bill per-token rates`);
351
+ }
352
+ else if (probe.mode === "api-key-override") {
353
+ log(`[billing] ${harness}: API-key billing (--allow-api-billing; key overrides stored login)`);
354
+ }
355
+ else {
356
+ log(`[billing] ${harness}: subscription login`);
357
+ }
358
+ }
203
359
  }
204
- agentsSpawned++;
360
+ catch (error) {
361
+ reservedCostUsd = Math.max(0, reservedCostUsd - reservedForDispatch);
362
+ reservedForDispatch = 0;
363
+ if (spawnCountClaimed) {
364
+ agentsSpawned--;
365
+ spawnCountClaimed = false;
366
+ }
367
+ agentProof.error = error.message;
368
+ throw error;
369
+ }
370
+ if (!spawnCountClaimed)
371
+ agentsSpawned++;
205
372
  await acquire();
206
373
  try {
207
374
  journal("agent.start", {
@@ -298,6 +465,7 @@ export async function runWorkflow(scriptPath, opts) {
298
465
  throw error;
299
466
  }
300
467
  finally {
468
+ reservedCostUsd = Math.max(0, reservedCostUsd - reservedForDispatch);
301
469
  release();
302
470
  }
303
471
  };
@@ -327,7 +495,22 @@ export async function runWorkflow(scriptPath, opts) {
327
495
  journal("evidence.recorded", { ...record });
328
496
  return record.id;
329
497
  };
330
- const ctx = { agent, parallel, stage, log, evidence };
498
+ const authorize = async (input) => {
499
+ const network = input.network === true || input.service !== undefined || input.target !== undefined
500
+ ? "enabled"
501
+ : "disabled";
502
+ return authorizePolicyRequest({
503
+ phase: "external_mutation",
504
+ action: input.action,
505
+ path: input.path ? resolve(cwd, input.path) : undefined,
506
+ isolation,
507
+ network_access: network,
508
+ service: input.service,
509
+ target: input.target,
510
+ current_cost_usd: round4(costUsd),
511
+ });
512
+ };
513
+ const ctx = { agent, parallel, stage, log, evidence, authorize };
331
514
  const t0 = Date.now();
332
515
  const startedAt = new Date(t0).toISOString();
333
516
  journal("run.start", {
@@ -337,6 +520,9 @@ export async function runWorkflow(scriptPath, opts) {
337
520
  acceptance: meta.acceptance,
338
521
  max_agents: maxAgents,
339
522
  concurrency,
523
+ policy: policy ? { name: policy.name, sha256: policyDigest(policy) } : null,
524
+ isolation,
525
+ network_access: networkAccess,
340
526
  });
341
527
  try {
342
528
  const result = await mod.default(ctx);
@@ -364,6 +550,9 @@ export async function runWorkflow(scriptPath, opts) {
364
550
  agents: Array.from(agentProofs.values()),
365
551
  evidence: evidenceRecords,
366
552
  harnessEvidence: opts.harnessEvidence,
553
+ policy: policy
554
+ ? { config: policy, decisions: policyDecisions, isolation, networkAccess }
555
+ : undefined,
367
556
  result,
368
557
  });
369
558
  writeWorkflowProof(proofPath, proof);
@@ -387,6 +576,7 @@ export async function runWorkflow(scriptPath, opts) {
387
576
  harness: p.harness,
388
577
  mode: opts.subscriptionOnly ? "subscription" : p.mode,
389
578
  })),
579
+ policy: proof.policy?.summary,
390
580
  };
391
581
  return report;
392
582
  }
@@ -417,6 +607,9 @@ export async function runWorkflow(scriptPath, opts) {
417
607
  agents: Array.from(agentProofs.values()),
418
608
  evidence: evidenceRecords,
419
609
  harnessEvidence: opts.harnessEvidence,
610
+ policy: policy
611
+ ? { config: policy, decisions: policyDecisions, isolation, networkAccess }
612
+ : undefined,
420
613
  error: err.message,
421
614
  });
422
615
  writeWorkflowProof(proofPath, proof);
@@ -486,3 +679,36 @@ function loadResumeCache(coordRoot, resumeFrom) {
486
679
  function round4(n) {
487
680
  return Math.round(n * 10_000) / 10_000;
488
681
  }
682
+ function assertAgentCapacity(agentsSpawned, maxAgents) {
683
+ if (agentsSpawned >= maxAgents) {
684
+ throw new Error(`workflow agent cap reached (${maxAgents}); raise --max-agents deliberately if the fan-out is intended`);
685
+ }
686
+ }
687
+ function boundedPolicyReason(value) {
688
+ const normalized = Array.from(value, (character) => {
689
+ const code = character.charCodeAt(0);
690
+ return code < 32 || code === 127 ? " " : character;
691
+ })
692
+ .join("")
693
+ .replace(/\s+/g, " ")
694
+ .trim();
695
+ return normalized.length > 2_000 ? `${normalized.slice(0, 1_999)}…` : normalized;
696
+ }
697
+ async function withTimeout(promise, timeoutMs) {
698
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
699
+ throw new Error("policyAskTimeoutMs must be a positive finite number");
700
+ }
701
+ let timer;
702
+ try {
703
+ return await Promise.race([
704
+ promise,
705
+ new Promise((_, reject) => {
706
+ timer = setTimeout(() => reject(new Error(`approval timed out after ${timeoutMs}ms`)), timeoutMs);
707
+ }),
708
+ ]);
709
+ }
710
+ finally {
711
+ if (timer)
712
+ clearTimeout(timer);
713
+ }
714
+ }
@@ -1,5 +1,5 @@
1
1
  export { runWorkflow, WorkflowRunError } from "./engine.js";
2
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";
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, WorkflowPolicyProof, WorkflowProof, WorkflowProofUnknown, WorkflowRepoEvidence, WorkflowRepoSnapshot, WorkflowRunStatus, } from "./types.js";
4
4
  export { WORKFLOW_PROOF_SCHEMA_VERSION } from "./types.js";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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"}
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,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { RepoSnapshot } from "../context/index.js";
2
+ import type { NormalizedPolicy, PolicyDecision, PolicyIsolation, PolicyNetworkAccess } from "../policy/index.js";
2
3
  import type { AcceptanceCriterion, AcceptanceResult, AcceptanceSummary, HarnessEvidenceCapability, ResultDigest, WorkflowAgentProof, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowProof } from "./types.js";
3
4
  export interface NormalizedWorkflowMeta {
4
5
  name: string;
@@ -19,6 +20,12 @@ export interface BuildWorkflowProofInput {
19
20
  agents: WorkflowAgentProof[];
20
21
  evidence: WorkflowEvidenceRecord[];
21
22
  harnessEvidence?: Readonly<Record<string, HarnessEvidenceCapability | undefined>>;
23
+ policy?: {
24
+ config: Readonly<NormalizedPolicy>;
25
+ decisions: readonly PolicyDecision[];
26
+ isolation: PolicyIsolation;
27
+ networkAccess: PolicyNetworkAccess;
28
+ };
22
29
  result?: unknown;
23
30
  error?: string;
24
31
  }
@@ -1 +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"}
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,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EAEzB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EAEZ,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;QACP,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACnC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;QACrC,SAAS,EAAE,eAAe,CAAC;QAC3B,aAAa,EAAE,mBAAmB,CAAC;KACpC,CAAC;IACF,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,CAyChF;AAgCD,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,CAoChE"}