harnery 0.21.0 → 0.22.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.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/dist/core/work/index.d.ts +1 -1
  3. package/dist/core/work/index.d.ts.map +1 -1
  4. package/dist/core/work/read.d.ts +1 -1
  5. package/dist/core/work/read.d.ts.map +1 -1
  6. package/dist/core/work/runner.d.ts +1 -1
  7. package/dist/core/work/runner.d.ts.map +1 -1
  8. package/dist/core/work/runner.js +54 -1
  9. package/dist/core/work/state.d.ts +3 -0
  10. package/dist/core/work/state.d.ts.map +1 -1
  11. package/dist/core/work/state.js +19 -5
  12. package/dist/core/workflow/attempt-context.d.ts +5 -0
  13. package/dist/core/workflow/attempt-context.d.ts.map +1 -0
  14. package/dist/core/workflow/attempt-context.js +189 -0
  15. package/dist/core/workflow/engine.d.ts.map +1 -1
  16. package/dist/core/workflow/engine.js +20 -2
  17. package/dist/core/workflow/index.d.ts +3 -2
  18. package/dist/core/workflow/index.d.ts.map +1 -1
  19. package/dist/core/workflow/index.js +2 -1
  20. package/dist/core/workflow/proof.d.ts +2 -1
  21. package/dist/core/workflow/proof.d.ts.map +1 -1
  22. package/dist/core/workflow/proof.js +7 -1
  23. package/dist/core/workflow/run-state.d.ts +2 -1
  24. package/dist/core/workflow/run-state.d.ts.map +1 -1
  25. package/dist/core/workflow/run-state.js +5 -0
  26. package/dist/core/workflow/types.d.ts +27 -0
  27. package/dist/core/workflow/types.d.ts.map +1 -1
  28. package/dist/core/workflow/types.js +1 -0
  29. package/package.json +1 -1
  30. package/src/core/work/index.ts +1 -0
  31. package/src/core/work/read.ts +1 -0
  32. package/src/core/work/runner.ts +69 -3
  33. package/src/core/work/state.ts +36 -5
  34. package/src/core/workflow/attempt-context.ts +215 -0
  35. package/src/core/workflow/engine.ts +29 -1
  36. package/src/core/workflow/index.ts +10 -0
  37. package/src/core/workflow/proof.ts +9 -1
  38. package/src/core/workflow/run-state.ts +11 -1
  39. package/src/core/workflow/types.ts +35 -0
package/README.md CHANGED
@@ -22,7 +22,7 @@
22
22
  - **Multi-agent coordination:** per-agent heartbeats in `.harnery/active/`, claim-time and commit-time guards, the canonical event stream, councils, a decision docket, per-agent scratchpads, and harness adapters for Claude Code / Cursor / Codex.
23
23
  - **Cross-machine presence:** sessions on every machine that shares a repo see each other, labeled by machine. Zero-config over the repo's own git remote (presence refs), with an optional live-socket upgrade via an end-to-end-encrypted relay — the public `relay.harnery.com`, or self-host with `harn relay serve` / the bundled Cloudflare Worker (`relay/worker/`). The relay sees only ciphertext in opaquely-named rooms.
24
24
  - **Coordination-aware workflows:** `harn workflow run <script>` executes bounded, schema-gated multi-subagent workflow scripts — plain JS stages fanning out to headless harness-CLI subagents that are born coordination-registered (heartbeats, events, claim guards), with deterministic code deciding the routing between stages. An optional host-owned policy gates dispatch and declared external mutations with `ALLOW`, `ASK`, and `DENY`; CLI `ASK` requests park durably for an explicit approve/deny and same-run resume, while library callers remain fail-closed by default.
25
- - **Durable work above attempts:** `harn work` preserves an objective across bounded workflow attempts, dependencies, approval parks, failures, and review. Reusable workflow code receives the exact work ID, title, objective, and acceptance criteria as frozen typed context, preserved in the run manifest and proof. The one-shot reconciler derives state from append-only local evidence and reports the next explicit action without silently spawning, retrying, or accepting work.
25
+ - **Durable work above attempts:** `harn work` preserves an objective across bounded workflow attempts, dependencies, approval parks, failures, and review. Reusable workflow code receives the exact work ID, title, objective, acceptance criteria, and attempt identity as frozen typed context. A retry also receives the prior run's bounded error and unresolved proof criteria, while retry authority and attempt ceilings remain unchanged. The manifest, proof, and append-only ledger bind the same context, and the one-shot reconciler reports the next explicit action without silently spawning, retrying, or accepting work.
26
26
  - **Bounded goal supervision:** `harn supervisor` freezes a mission or existing root graph, specialist team, and safety limits, then runs scheduling cycles until reviewed mission success, human attention, no progress, or budget exhaustion. Its optional planner can create the first milestone, reassess accepted milestone proof, or recover a terminal graph using only a frozen workflow-template catalog. Plans can require independent bounded specialist review before ordinary approval or auto-apply authority, old generations remain immutable evidence, and all attempts still consume the goal budget. Use explicit foreground ticks or enroll goals in the optional heartbeat-backed background service.
27
27
  - **Standalone web UI:** `harn web up` boots a local Next.js dashboard for the coord layer, councils, per-project state, and a local coding-agent status view (Claude Code / Codex / Cursor usage, backed by `harn devtools`). Ships with the git clone, not the npm package (see [Install](#install)).
28
28
  - **Backup + sync:** `harn backup` snapshots `.harnery/` via [restic](https://restic.net/); `harn sync` keeps a curated subset live across machines via [rclone](https://rclone.org/) (Google Drive or any rclone remote).
@@ -1,3 +1,3 @@
1
1
  export { type RunWorkItemInput, runWorkItem } from "./runner.js";
2
- export { acceptWorkItem, assertWorkId, type CreateWorkItemInput, cancelWorkItem, createWorkItem, listWorkItems, newWorkId, readWorkItem, reconcileAllWorkItems, reconcileWorkItem, reopenWorkItem, WORK_EVENT_SCHEMA_VERSION, WORK_INTENT_SCHEMA_VERSION, type WorkAttempt, type WorkEvent, type WorkEventType, type WorkIntent, type WorkNextAction, type WorkProjection, type WorkRecord, type WorkState, } from "./state.js";
2
+ export { acceptWorkItem, assertWorkId, type CreateWorkItemInput, cancelWorkItem, createWorkItem, listWorkItems, newWorkId, readWorkItem, reconcileAllWorkItems, reconcileWorkItem, reopenWorkItem, WORK_EVENT_SCHEMA_VERSION, WORK_INTENT_SCHEMA_VERSION, type WorkAttempt, type WorkAttemptTrigger, type WorkEvent, type WorkEventType, type WorkIntent, type WorkNextAction, type WorkProjection, type WorkRecord, type WorkState, } from "./state.js";
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/work/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,cAAc,EACd,YAAY,EACZ,KAAK,mBAAmB,EACxB,cAAc,EACd,cAAc,EACd,aAAa,EACb,SAAS,EACT,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,SAAS,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/work/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,cAAc,EACd,YAAY,EACZ,KAAK,mBAAmB,EACxB,cAAc,EACd,cAAc,EACd,aAAa,EACb,SAAS,EACT,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,SAAS,GACf,MAAM,YAAY,CAAC"}
@@ -1,2 +1,2 @@
1
- export { assertWorkId, listWorkItems, readWorkItem, WORK_EVENT_SCHEMA_VERSION, WORK_INTENT_SCHEMA_VERSION, type WorkAttempt, type WorkEvent, type WorkEventType, type WorkIntent, type WorkNextAction, type WorkProjection, type WorkRecord, type WorkState, } from "./state.js";
1
+ export { assertWorkId, listWorkItems, readWorkItem, WORK_EVENT_SCHEMA_VERSION, WORK_INTENT_SCHEMA_VERSION, type WorkAttempt, type WorkAttemptTrigger, type WorkEvent, type WorkEventType, type WorkIntent, type WorkNextAction, type WorkProjection, type WorkRecord, type WorkState, } from "./state.js";
2
2
  //# sourceMappingURL=read.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/core/work/read.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,SAAS,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/core/work/read.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,SAAS,GACf,MAAM,YAAY,CAAC"}
@@ -2,7 +2,7 @@ import type { EngineOpts, RunReport } from "../workflow/types.js";
2
2
  export interface RunWorkItemInput {
3
3
  coordRoot: string;
4
4
  workId: string;
5
- engine: Omit<EngineOpts, "coordRoot" | "runId" | "resumeRunId" | "workItemId" | "workContext">;
5
+ engine: Omit<EngineOpts, "coordRoot" | "runId" | "resumeRunId" | "workItemId" | "workContext" | "attemptContext">;
6
6
  retry?: boolean;
7
7
  actor?: string;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/core/work/runner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAYlE,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,GAAG,aAAa,CAAC,CAAC;IAC/F,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAkE7E"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/core/work/runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EAGV,MAAM,sBAAsB,CAAC;AAgB9B,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,IAAI,CACV,UAAU,EACV,WAAW,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,GAAG,aAAa,GAAG,gBAAgB,CACxF,CAAC;IACF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAqF7E"}
@@ -1,6 +1,7 @@
1
1
  import { resolve } from "node:path";
2
2
  import { runWorkflow } from "../workflow/engine.js";
3
- import { WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION } from "../workflow/types.js";
3
+ import { readWorkflowProof } from "../workflow/proof.js";
4
+ import { WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION, WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION, } from "../workflow/types.js";
4
5
  import { acquireWorkLease, appendReconcileIfChanged, appendWorkEvent, assertWorkflowUnchanged, boundedActor, newWorkflowRunId, readWorkItemIgnoringLease, } from "./state.js";
5
6
  export async function runWorkItem(input) {
6
7
  const coordRoot = resolve(input.coordRoot);
@@ -30,6 +31,9 @@ export async function runWorkItem(input) {
30
31
  if (record.projection.state === "blocked" && !input.retry) {
31
32
  throw new Error(`work item ${input.workId} is blocked; use an explicit retry`);
32
33
  }
34
+ if (record.projection.state === "ready" && input.retry) {
35
+ throw new Error(`work item ${input.workId} is ready; retry requires a blocked prior attempt`);
36
+ }
33
37
  if (!(record.projection.state === "ready" || record.projection.state === "blocked")) {
34
38
  throw new Error(`work item ${input.workId} cannot run from state ${record.projection.state}`);
35
39
  }
@@ -37,6 +41,20 @@ export async function runWorkItem(input) {
37
41
  throw new Error(`work item ${input.workId} exhausted its ${record.intent.max_attempts} attempts`);
38
42
  }
39
43
  const attempt = record.projection.attempts_used + 1;
44
+ const trigger = input.retry ? "retry" : "initial";
45
+ let prior;
46
+ if (trigger === "retry") {
47
+ if (!latest) {
48
+ throw new Error(`work item ${input.workId} has no prior attempt to retry`);
49
+ }
50
+ prior = priorContext(coordRoot, latest);
51
+ }
52
+ const attemptContext = {
53
+ schema_version: WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION,
54
+ number: attempt,
55
+ trigger,
56
+ ...(prior ? { prior } : {}),
57
+ };
40
58
  const runId = newWorkflowRunId();
41
59
  appendWorkEvent(coordRoot, input.workId, {
42
60
  event: "attempt.started",
@@ -44,6 +62,7 @@ export async function runWorkItem(input) {
44
62
  reason: input.retry ? "explicit retry started" : "workflow attempt started",
45
63
  run_id: runId,
46
64
  attempt,
65
+ trigger,
47
66
  });
48
67
  return await runWorkflow(record.intent.workflow.path, {
49
68
  ...input.engine,
@@ -57,6 +76,7 @@ export async function runWorkItem(input) {
57
76
  objective: record.intent.objective,
58
77
  acceptance: [...record.intent.acceptance],
59
78
  },
79
+ attemptContext,
60
80
  });
61
81
  }
62
82
  finally {
@@ -69,3 +89,36 @@ export async function runWorkItem(input) {
69
89
  }
70
90
  }
71
91
  }
92
+ function priorContext(coordRoot, prior) {
93
+ if (!prior.proof_path) {
94
+ return {
95
+ run_id: prior.run_id,
96
+ causes: ["lost"],
97
+ unresolved: [],
98
+ };
99
+ }
100
+ const proof = readWorkflowProof(coordRoot, prior.run_id);
101
+ const causes = [];
102
+ if (proof.run.status === "failed")
103
+ causes.push("workflow_error");
104
+ if (proof.acceptance.summary.unsatisfied > 0)
105
+ causes.push("acceptance_unsatisfied");
106
+ if (proof.acceptance.summary.unknown > 0)
107
+ causes.push("acceptance_unknown");
108
+ if (causes.length === 0) {
109
+ throw new Error(`workflow proof ${prior.run_id} does not describe a retryable failure`);
110
+ }
111
+ return {
112
+ run_id: prior.run_id,
113
+ causes,
114
+ error: proof.run.error,
115
+ acceptance: { ...proof.acceptance.summary },
116
+ unresolved: proof.acceptance.criteria
117
+ .filter((criterion) => criterion.status !== "satisfied")
118
+ .map((criterion) => ({
119
+ id: criterion.id,
120
+ statement: criterion.statement,
121
+ status: criterion.status,
122
+ })),
123
+ };
124
+ }
@@ -2,6 +2,7 @@ export declare const WORK_INTENT_SCHEMA_VERSION: 1;
2
2
  export declare const WORK_EVENT_SCHEMA_VERSION: 1;
3
3
  export type WorkState = "waiting" | "ready" | "running" | "awaiting_approval" | "in_review" | "blocked" | "succeeded" | "cancelled";
4
4
  export type WorkNextAction = "wait_for_dependencies" | "run" | "wait_for_run" | "resolve_approval" | "resume" | "retry" | "review" | "none";
5
+ export type WorkAttemptTrigger = "initial" | "retry";
5
6
  export interface WorkIntent {
6
7
  schema_version: typeof WORK_INTENT_SCHEMA_VERSION;
7
8
  id: string;
@@ -31,6 +32,7 @@ export interface WorkEvent {
31
32
  reason?: string;
32
33
  run_id?: string;
33
34
  attempt?: number;
35
+ trigger?: WorkAttemptTrigger;
34
36
  state?: WorkState;
35
37
  next_action?: WorkNextAction;
36
38
  }
@@ -38,6 +40,7 @@ export interface WorkAttempt {
38
40
  number: number;
39
41
  run_id: string;
40
42
  started_at: string;
43
+ trigger?: WorkAttemptTrigger;
41
44
  status: "running" | "parked" | "succeeded" | "failed" | "lost";
42
45
  approval_id?: string;
43
46
  proof_path?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/core/work/state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/core/work/state.ts"],"names":[],"mappings":"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"}
@@ -156,7 +156,7 @@ function deriveWorkProjection(coordRoot, intent, events, ignoreLease = false) {
156
156
  .find((event) => ["work.accepted", "work.cancelled", "work.reopened"].includes(event.event));
157
157
  const terminal = latestGovernance?.event === "work.accepted" || latestGovernance?.event === "work.cancelled";
158
158
  const attemptEvents = events.filter((event) => event.event === "attempt.started");
159
- const attempts = attemptEvents.map((event) => inspectAttempt(coordRoot, event, intent));
159
+ const attempts = attemptEvents.map((event, index) => inspectAttempt(coordRoot, event, intent, attemptEvents[index - 1]?.run_id));
160
160
  const base = {
161
161
  id: intent.id,
162
162
  title: intent.title,
@@ -179,9 +179,7 @@ function deriveWorkProjection(coordRoot, intent, events, ignoreLease = false) {
179
179
  };
180
180
  }
181
181
  const reopenSeq = latestGovernance?.event === "work.reopened" ? latestGovernance.seq : 0;
182
- const currentAttempts = attemptEvents
183
- .filter((event) => event.seq > reopenSeq)
184
- .map((event) => inspectAttempt(coordRoot, event, intent));
182
+ const currentAttempts = attempts.filter((_, index) => attemptEvents[index].seq > reopenSeq);
185
183
  const unresolved = intent.dependencies.filter((dependency) => {
186
184
  try {
187
185
  return readWorkItem(coordRoot, dependency).projection.state !== "succeeded";
@@ -257,12 +255,13 @@ function deriveWorkProjection(coordRoot, intent, events, ignoreLease = false) {
257
255
  next_action: attemptsRemaining > 0 ? "retry" : "none",
258
256
  };
259
257
  }
260
- function inspectAttempt(coordRoot, event, intent) {
258
+ function inspectAttempt(coordRoot, event, intent, priorRunId) {
261
259
  const runId = event.run_id;
262
260
  const attempt = {
263
261
  number: event.attempt,
264
262
  run_id: runId,
265
263
  started_at: event.ts,
264
+ trigger: event.trigger,
266
265
  status: "lost",
267
266
  };
268
267
  const proofPath = join(coordRoot, ".harnery", "workflows", runId, "proof.json");
@@ -277,6 +276,13 @@ function inspectAttempt(coordRoot, event, intent) {
277
276
  JSON.stringify(manifest.work_context) !== JSON.stringify(workContextForIntent(intent))) {
278
277
  throw new Error(`workflow run ${runId} work context does not match work item ${event.work_id}`);
279
278
  }
279
+ if (manifest.attempt_context !== undefined &&
280
+ (manifest.attempt_context.number !== event.attempt ||
281
+ manifest.attempt_context.trigger !== event.trigger ||
282
+ (manifest.attempt_context.trigger === "retry" &&
283
+ manifest.attempt_context.prior?.run_id !== priorRunId))) {
284
+ throw new Error(`workflow run ${runId} attempt context does not match work item ${event.work_id}`);
285
+ }
280
286
  }
281
287
  if (existsSync(proofPath)) {
282
288
  if (!existsSync(manifestPath)) {
@@ -289,6 +295,9 @@ function inspectAttempt(coordRoot, event, intent) {
289
295
  if (JSON.stringify(proof.run.work_context) !== JSON.stringify(manifest?.work_context)) {
290
296
  throw new Error(`workflow proof ${runId} work context does not match its run manifest`);
291
297
  }
298
+ if (JSON.stringify(proof.run.attempt_context) !== JSON.stringify(manifest?.attempt_context)) {
299
+ throw new Error(`workflow proof ${runId} attempt context does not match its run manifest`);
300
+ }
292
301
  attempt.proof_path = proofPath;
293
302
  attempt.status =
294
303
  proof.run.status === "succeeded" &&
@@ -478,6 +487,11 @@ function validateWorkEvent(event, workId, seq) {
478
487
  throw new Error(`work item ${workId} event ${seq} has invalid attempt data`);
479
488
  }
480
489
  }
490
+ if (event.trigger !== undefined &&
491
+ (event.event !== "attempt.started" ||
492
+ (event.trigger !== "initial" && event.trigger !== "retry"))) {
493
+ throw new Error(`work item ${workId} event ${seq} has invalid attempt trigger`);
494
+ }
481
495
  if (event.event === "work.reconciled") {
482
496
  const states = [
483
497
  "waiting",
@@ -0,0 +1,5 @@
1
+ import type { WorkflowAttemptContext } from "./types.js";
2
+ export declare function normalizeWorkflowAttemptContext(value: unknown): WorkflowAttemptContext;
3
+ export declare function freezeWorkflowAttemptContext(value: unknown): Readonly<WorkflowAttemptContext>;
4
+ export declare function isCanonicalWorkflowAttemptContext(value: unknown): value is WorkflowAttemptContext;
5
+ //# sourceMappingURL=attempt-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attempt-context.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/attempt-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,sBAAsB,EAIvB,MAAM,YAAY,CAAC;AAoBpB,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CA8BtF;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,sBAAsB,CAAC,CAU7F;AAED,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAOjG"}
@@ -0,0 +1,189 @@
1
+ import { WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION } from "./types.js";
2
+ const RUN_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/;
3
+ const ACCEPTANCE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
4
+ const MAX_ATTEMPTS = 100;
5
+ const MAX_ERROR = 2_000;
6
+ const MAX_CRITERIA = 50;
7
+ const MAX_STATEMENT = 500;
8
+ const CONTEXT_FIELDS = new Set(["schema_version", "number", "trigger", "prior"]);
9
+ const PRIOR_FIELDS = new Set(["run_id", "causes", "error", "acceptance", "unresolved"]);
10
+ const SUMMARY_FIELDS = new Set(["satisfied", "unsatisfied", "unknown", "total"]);
11
+ const CRITERION_FIELDS = new Set(["id", "statement", "status"]);
12
+ const CAUSE_ORDER = [
13
+ "workflow_error",
14
+ "acceptance_unsatisfied",
15
+ "acceptance_unknown",
16
+ "lost",
17
+ ];
18
+ export function normalizeWorkflowAttemptContext(value) {
19
+ const input = objectValue(value, "workflow attempt context");
20
+ rejectExtraFields(input, CONTEXT_FIELDS, "workflow attempt context");
21
+ if (input.schema_version !== WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION) {
22
+ throw new Error("workflow attempt context has an unsupported schema");
23
+ }
24
+ const number = safeInteger(input.number, "workflow attempt context number", 1, MAX_ATTEMPTS);
25
+ if (input.trigger !== "initial" && input.trigger !== "retry") {
26
+ throw new Error('workflow attempt context trigger must be "initial" or "retry"');
27
+ }
28
+ if (input.trigger === "initial") {
29
+ if (input.prior !== undefined) {
30
+ throw new Error("initial workflow attempt context cannot contain prior evidence");
31
+ }
32
+ return {
33
+ schema_version: WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION,
34
+ number,
35
+ trigger: "initial",
36
+ };
37
+ }
38
+ if (number < 2)
39
+ throw new Error("retry workflow attempt context number must be at least 2");
40
+ if (input.prior === undefined) {
41
+ throw new Error("retry workflow attempt context requires prior evidence");
42
+ }
43
+ return {
44
+ schema_version: WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION,
45
+ number,
46
+ trigger: "retry",
47
+ prior: normalizePrior(input.prior),
48
+ };
49
+ }
50
+ export function freezeWorkflowAttemptContext(value) {
51
+ const normalized = normalizeWorkflowAttemptContext(value);
52
+ if (normalized.prior) {
53
+ for (const criterion of normalized.prior.unresolved)
54
+ Object.freeze(criterion);
55
+ Object.freeze(normalized.prior.causes);
56
+ Object.freeze(normalized.prior.acceptance);
57
+ Object.freeze(normalized.prior.unresolved);
58
+ Object.freeze(normalized.prior);
59
+ }
60
+ return Object.freeze(normalized);
61
+ }
62
+ export function isCanonicalWorkflowAttemptContext(value) {
63
+ try {
64
+ const normalized = normalizeWorkflowAttemptContext(value);
65
+ return JSON.stringify(normalized) === JSON.stringify(value);
66
+ }
67
+ catch {
68
+ return false;
69
+ }
70
+ }
71
+ function normalizePrior(value) {
72
+ const input = objectValue(value, "workflow attempt prior context");
73
+ rejectExtraFields(input, PRIOR_FIELDS, "workflow attempt prior context");
74
+ const runId = requiredString(input.run_id, "workflow attempt prior run id", 200);
75
+ if (!RUN_ID.test(runId)) {
76
+ throw new Error(`invalid workflow attempt prior run id ${JSON.stringify(runId)}`);
77
+ }
78
+ if (!Array.isArray(input.causes) || input.causes.length === 0) {
79
+ throw new Error("workflow attempt prior causes must be a non-empty array");
80
+ }
81
+ const seen = new Set();
82
+ for (const cause of input.causes) {
83
+ if (!CAUSE_ORDER.includes(cause)) {
84
+ throw new Error(`unsupported workflow attempt failure cause ${JSON.stringify(cause)}`);
85
+ }
86
+ if (seen.has(cause)) {
87
+ throw new Error(`duplicate workflow attempt failure cause ${JSON.stringify(cause)}`);
88
+ }
89
+ seen.add(cause);
90
+ }
91
+ const causes = CAUSE_ORDER.filter((cause) => seen.has(cause));
92
+ if (causes.includes("lost")) {
93
+ if (causes.length !== 1)
94
+ throw new Error("lost must be the only workflow attempt failure cause");
95
+ if (input.error !== undefined || input.acceptance !== undefined) {
96
+ throw new Error("lost workflow attempt evidence cannot contain proof-derived fields");
97
+ }
98
+ const unresolved = normalizeUnresolved(input.unresolved);
99
+ if (unresolved.length > 0) {
100
+ throw new Error("lost workflow attempt evidence cannot contain unresolved criteria");
101
+ }
102
+ return { run_id: runId, causes, unresolved };
103
+ }
104
+ const acceptance = normalizeAcceptanceSummary(input.acceptance);
105
+ const unresolved = normalizeUnresolved(input.unresolved);
106
+ const unsatisfied = unresolved.filter((criterion) => criterion.status === "unsatisfied").length;
107
+ const unknown = unresolved.filter((criterion) => criterion.status === "unknown").length;
108
+ if (unsatisfied !== acceptance.unsatisfied ||
109
+ unknown !== acceptance.unknown ||
110
+ causes.includes("acceptance_unsatisfied") !== acceptance.unsatisfied > 0 ||
111
+ causes.includes("acceptance_unknown") !== acceptance.unknown > 0) {
112
+ throw new Error("workflow attempt failure evidence does not match acceptance");
113
+ }
114
+ if (!causes.includes("workflow_error") && acceptance.unsatisfied + acceptance.unknown === 0) {
115
+ throw new Error("workflow attempt prior context does not describe a failure");
116
+ }
117
+ const error = input.error === undefined
118
+ ? undefined
119
+ : requiredString(input.error, "workflow attempt prior error", MAX_ERROR);
120
+ return {
121
+ run_id: runId,
122
+ causes,
123
+ ...(error === undefined ? {} : { error }),
124
+ acceptance,
125
+ unresolved,
126
+ };
127
+ }
128
+ function normalizeAcceptanceSummary(value) {
129
+ const input = objectValue(value, "workflow attempt acceptance summary");
130
+ rejectExtraFields(input, SUMMARY_FIELDS, "workflow attempt acceptance summary");
131
+ const satisfied = safeInteger(input.satisfied, "acceptance satisfied", 0, MAX_CRITERIA);
132
+ const unsatisfied = safeInteger(input.unsatisfied, "acceptance unsatisfied", 0, MAX_CRITERIA);
133
+ const unknown = safeInteger(input.unknown, "acceptance unknown", 0, MAX_CRITERIA);
134
+ const total = safeInteger(input.total, "acceptance total", 0, MAX_CRITERIA);
135
+ if (satisfied + unsatisfied + unknown !== total) {
136
+ throw new Error("workflow attempt acceptance summary total does not match its counts");
137
+ }
138
+ return { satisfied, unsatisfied, unknown, total };
139
+ }
140
+ function normalizeUnresolved(value) {
141
+ if (!Array.isArray(value) || value.length > MAX_CRITERIA) {
142
+ throw new Error(`workflow attempt unresolved criteria must contain at most ${MAX_CRITERIA} entries`);
143
+ }
144
+ const ids = new Set();
145
+ return value.map((candidate, index) => {
146
+ const input = objectValue(candidate, `workflow attempt unresolved[${index}]`);
147
+ rejectExtraFields(input, CRITERION_FIELDS, `workflow attempt unresolved[${index}]`);
148
+ const id = requiredString(input.id, `workflow attempt unresolved[${index}].id`, 64);
149
+ if (!ACCEPTANCE_ID.test(id)) {
150
+ throw new Error(`invalid workflow attempt acceptance id ${JSON.stringify(id)}`);
151
+ }
152
+ if (ids.has(id))
153
+ throw new Error(`duplicate workflow attempt acceptance id ${JSON.stringify(id)}`);
154
+ ids.add(id);
155
+ if (input.status !== "unsatisfied" && input.status !== "unknown") {
156
+ throw new Error(`workflow attempt unresolved[${index}].status is invalid`);
157
+ }
158
+ return {
159
+ id,
160
+ statement: requiredString(input.statement, `workflow attempt unresolved[${index}].statement`, MAX_STATEMENT),
161
+ status: input.status,
162
+ };
163
+ });
164
+ }
165
+ function objectValue(value, field) {
166
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
167
+ throw new Error(`${field} must be an object`);
168
+ }
169
+ return value;
170
+ }
171
+ function rejectExtraFields(value, allowed, field) {
172
+ const extra = Object.keys(value).find((key) => !allowed.has(key));
173
+ if (extra)
174
+ throw new Error(`${field} has unknown field ${JSON.stringify(extra)}`);
175
+ }
176
+ function requiredString(value, field, max) {
177
+ if (typeof value !== "string" || value.trim() === "")
178
+ throw new Error(`${field} is required`);
179
+ const normalized = value.trim();
180
+ if (normalized.length > max)
181
+ throw new Error(`${field} exceeds ${max} characters`);
182
+ return normalized;
183
+ }
184
+ function safeInteger(value, field, min, max) {
185
+ if (!Number.isSafeInteger(value) || value < min || value > max) {
186
+ throw new Error(`${field} must be an integer from ${min} to ${max}`);
187
+ }
188
+ return value;
189
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAqCH,OAAO,KAAK,EAEV,UAAU,EAEV,SAAS,EASV,MAAM,YAAY,CAAC;AAapB,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,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAOpF;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAyD1F"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAsCH,OAAO,KAAK,EAEV,UAAU,EAEV,SAAS,EAUV,MAAM,YAAY,CAAC;AAapB,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,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAOpF;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CA6E1F"}
@@ -31,6 +31,7 @@ import { pathToFileURL } from "node:url";
31
31
  import { snapshotRepo } from "../context/index.js";
32
32
  import { evaluatePolicy, normalizePolicy, PolicyDeniedError, policyDigest, summarizePolicyRequest, } from "../policy/index.js";
33
33
  import { assertWorkflowRunId, createWorkflowApproval } from "./approvals.js";
34
+ import { freezeWorkflowAttemptContext } from "./attempt-context.js";
34
35
  import { probeBilling } from "./billing.js";
35
36
  import { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, writeWorkflowProof, } from "./proof.js";
36
37
  import { acquireWorkflowResumeLease, assertWorkflowRunResumable, assertWorkflowScriptUnchanged, workflowScriptDigest, writeWorkflowRunManifest, } from "./run-state.js";
@@ -79,13 +80,22 @@ export async function runWorkflow(scriptPath, opts) {
79
80
  if (opts.resumeRunId && opts.workContext !== undefined) {
80
81
  throw new Error("parked workflow resume uses the frozen manifest work context");
81
82
  }
83
+ if (opts.resumeRunId && opts.attemptContext !== undefined) {
84
+ throw new Error("parked workflow resume uses the frozen manifest attempt context");
85
+ }
82
86
  const requestedWorkContext = opts.workContext === undefined ? undefined : freezeWorkflowWorkContext(opts.workContext);
87
+ const requestedAttemptContext = opts.attemptContext === undefined
88
+ ? undefined
89
+ : freezeWorkflowAttemptContext(opts.attemptContext);
83
90
  if (requestedWorkContext && !opts.workItemId) {
84
91
  throw new Error("workflow work context requires a work item id");
85
92
  }
86
93
  if (requestedWorkContext && requestedWorkContext.id !== opts.workItemId) {
87
94
  throw new Error(`workflow work context ${requestedWorkContext.id} does not match work item ${opts.workItemId}`);
88
95
  }
96
+ if (requestedAttemptContext && !requestedWorkContext) {
97
+ throw new Error("workflow attempt context requires work context");
98
+ }
89
99
  if (opts.resumeRunId && opts.resumeFrom) {
90
100
  throw new Error("resumeRunId and resumeFrom are mutually exclusive");
91
101
  }
@@ -100,6 +110,9 @@ export async function runWorkflow(scriptPath, opts) {
100
110
  const workContext = resumeState?.manifest.work_context
101
111
  ? freezeWorkflowWorkContext(resumeState.manifest.work_context)
102
112
  : requestedWorkContext;
113
+ const attemptContext = resumeState?.manifest.attempt_context
114
+ ? freezeWorkflowAttemptContext(resumeState.manifest.attempt_context)
115
+ : requestedAttemptContext;
103
116
  const absScript = isAbsolute(scriptPath) ? scriptPath : resolve(process.cwd(), scriptPath);
104
117
  if (resumeState) {
105
118
  if (resolve(resumeState.manifest.script.path) !== resolve(absScript)) {
@@ -116,13 +129,13 @@ export async function runWorkflow(scriptPath, opts) {
116
129
  // the run between the optimistic read and lease acquisition.
117
130
  assertWorkflowRunResumable(opts.coordRoot, resumeState.manifest.run_id);
118
131
  }
119
- return await executeWorkflow(scriptPath, absScript, opts, resumeState, workContext);
132
+ return await executeWorkflow(scriptPath, absScript, opts, resumeState, workContext, attemptContext);
120
133
  }
121
134
  finally {
122
135
  releaseResumeLease?.();
123
136
  }
124
137
  }
125
- async function executeWorkflow(scriptPath, absScript, opts, resumeState, workContext) {
138
+ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workContext, attemptContext) {
126
139
  const mod = (await import(__rewriteRelativeImportExtension(pathToFileURL(absScript).href)));
127
140
  if (typeof mod.default !== "function") {
128
141
  throw new Error(`${scriptPath}: workflow script must \`export default async (ctx) => …\``);
@@ -164,6 +177,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
164
177
  run_id: runId,
165
178
  work_item_id: opts.workItemId,
166
179
  work_context: workContext,
180
+ attempt_context: attemptContext,
167
181
  name,
168
182
  started_at: startedAt,
169
183
  script: { path: absScript, sha256: workflowScriptDigest(absScript) },
@@ -685,6 +699,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
685
699
  };
686
700
  const ctx = {
687
701
  work: workContext,
702
+ attempt: attemptContext,
688
703
  agent,
689
704
  parallel,
690
705
  stage,
@@ -705,6 +720,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
705
720
  name,
706
721
  work_item_id: opts.workItemId ?? null,
707
722
  work_context: workContext ?? null,
723
+ attempt_context: attemptContext ?? null,
708
724
  script: absScript,
709
725
  objective: meta.objective ?? null,
710
726
  acceptance: meta.acceptance,
@@ -732,6 +748,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
732
748
  runId,
733
749
  workItemId: opts.workItemId ?? resumeState?.manifest.work_item_id,
734
750
  workContext,
751
+ attemptContext,
735
752
  meta,
736
753
  status: "succeeded",
737
754
  startedAt,
@@ -797,6 +814,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
797
814
  runId,
798
815
  workItemId: opts.workItemId ?? resumeState?.manifest.work_item_id,
799
816
  workContext,
817
+ attemptContext,
800
818
  meta,
801
819
  status: "failed",
802
820
  startedAt,
@@ -1,9 +1,10 @@
1
1
  export type { CreateWorkflowApprovalInput, ResolveWorkflowApprovalInput, WorkflowApproval, WorkflowApprovalDecision, WorkflowApprovalRequest, WorkflowApprovalStatus, } from "./approvals.js";
2
2
  export { assertWorkflowRunId, createWorkflowApproval, listWorkflowApprovals, readWorkflowApproval, renderWorkflowApproval, resolveWorkflowApproval, WORKFLOW_APPROVAL_SCHEMA_VERSION, workflowApprovalId, } from "./approvals.js";
3
+ export { freezeWorkflowAttemptContext, isCanonicalWorkflowAttemptContext, normalizeWorkflowAttemptContext, } from "./attempt-context.js";
3
4
  export { runWorkflow, WorkflowParkedError, WorkflowRunError } from "./engine.js";
4
5
  export { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, readWorkflowProof, renderWorkflowProof, rollupAcceptance, writeWorkflowProof, } from "./proof.js";
5
6
  export type { WorkflowRunManifest } from "./run-state.js";
6
7
  export { acquireWorkflowResumeLease, assertWorkflowRunResumable, assertWorkflowScriptUnchanged, readWorkflowRunManifest, WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION, workflowRunManifestPath, workflowScriptDigest, writeWorkflowRunManifest, } from "./run-state.js";
7
- export type { AcceptanceCriterion, AcceptanceResult, AcceptanceStatus, AcceptanceSummary, AgentOpts, EngineOpts, EvidenceKind, EvidenceSource, EvidenceStatus, HarnessEvidenceCapability, HarnessEvidenceCoverage, HarnessName, ResultDigest, RunReport, Spawner, SpawnRequest, SpawnResult, StageSchema, WorkflowAgentProof, WorkflowApprovalMode, WorkflowContext, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowModule, WorkflowPolicyProof, WorkflowProof, WorkflowProofUnknown, WorkflowRepoEvidence, WorkflowRepoSnapshot, WorkflowRunStatus, WorkflowSpecialistProfile, WorkflowWorkContext, } from "./types.js";
8
- export { WORKFLOW_PROOF_SCHEMA_VERSION, WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION, } from "./types.js";
8
+ export type { AcceptanceCriterion, AcceptanceResult, AcceptanceStatus, AcceptanceSummary, AgentOpts, EngineOpts, EvidenceKind, EvidenceSource, EvidenceStatus, HarnessEvidenceCapability, HarnessEvidenceCoverage, HarnessName, ResultDigest, RunReport, Spawner, SpawnRequest, SpawnResult, StageSchema, WorkflowAgentProof, WorkflowApprovalMode, WorkflowAttemptContext, WorkflowAttemptFailureCause, WorkflowAttemptPriorContext, WorkflowAttemptUnresolvedCriterion, WorkflowContext, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowModule, WorkflowPolicyProof, WorkflowProof, WorkflowProofUnknown, WorkflowRepoEvidence, WorkflowRepoSnapshot, WorkflowRunStatus, WorkflowSpecialistProfile, WorkflowWorkContext, } from "./types.js";
9
+ export { WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION, WORKFLOW_PROOF_SCHEMA_VERSION, WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION, } from "./types.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,6BAA6B,EAC7B,uBAAuB,EACvB,oCAAoC,EACpC,uBAAuB,EACvB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AACxB,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,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,6BAA6B,EAC7B,oCAAoC,GACrC,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,4BAA4B,EAC5B,iCAAiC,EACjC,+BAA+B,GAChC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,6BAA6B,EAC7B,uBAAuB,EACvB,oCAAoC,EACpC,uBAAuB,EACvB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AACxB,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,oBAAoB,EACpB,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC3B,kCAAkC,EAClC,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,uCAAuC,EACvC,6BAA6B,EAC7B,oCAAoC,GACrC,MAAM,YAAY,CAAC"}
@@ -1,5 +1,6 @@
1
1
  export { assertWorkflowRunId, createWorkflowApproval, listWorkflowApprovals, readWorkflowApproval, renderWorkflowApproval, resolveWorkflowApproval, WORKFLOW_APPROVAL_SCHEMA_VERSION, workflowApprovalId, } from "./approvals.js";
2
+ export { freezeWorkflowAttemptContext, isCanonicalWorkflowAttemptContext, normalizeWorkflowAttemptContext, } from "./attempt-context.js";
2
3
  export { runWorkflow, WorkflowParkedError, WorkflowRunError } from "./engine.js";
3
4
  export { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, readWorkflowProof, renderWorkflowProof, rollupAcceptance, writeWorkflowProof, } from "./proof.js";
4
5
  export { acquireWorkflowResumeLease, assertWorkflowRunResumable, assertWorkflowScriptUnchanged, readWorkflowRunManifest, WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION, workflowRunManifestPath, workflowScriptDigest, writeWorkflowRunManifest, } from "./run-state.js";
5
- export { WORKFLOW_PROOF_SCHEMA_VERSION, WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION, } from "./types.js";
6
+ export { WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION, WORKFLOW_PROOF_SCHEMA_VERSION, WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION, } from "./types.js";
@@ -1,6 +1,6 @@
1
1
  import type { RepoSnapshot } from "../context/index.js";
2
2
  import type { NormalizedPolicy, PolicyDecision, PolicyIsolation, PolicyNetworkAccess } from "../policy/index.js";
3
- import type { AcceptanceCriterion, AcceptanceResult, AcceptanceSummary, HarnessEvidenceCapability, ResultDigest, WorkflowAgentProof, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowProof, WorkflowWorkContext } from "./types.js";
3
+ import type { AcceptanceCriterion, AcceptanceResult, AcceptanceSummary, HarnessEvidenceCapability, ResultDigest, WorkflowAgentProof, WorkflowAttemptContext, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowProof, WorkflowWorkContext } from "./types.js";
4
4
  export interface NormalizedWorkflowMeta {
5
5
  name: string;
6
6
  description?: string;
@@ -11,6 +11,7 @@ export interface BuildWorkflowProofInput {
11
11
  runId: string;
12
12
  workItemId?: string;
13
13
  workContext?: Readonly<WorkflowWorkContext>;
14
+ attemptContext?: Readonly<WorkflowAttemptContext>;
14
15
  meta: NormalizedWorkflowMeta;
15
16
  status: "succeeded" | "failed";
16
17
  startedAt: string;
@@ -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,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,EAIb,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAgBpB,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,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IAC5C,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,CA4ChF;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,CAyBjF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAoChE"}
1
+ {"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/proof.ts"],"names":[],"mappings":"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"}