@inflexa-ai/harness 0.44.0 → 0.45.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 (187) hide show
  1. package/dist/agents/conversation-agent.d.ts +10 -0
  2. package/dist/agents/conversation-agent.js +19 -1
  3. package/dist/agents/sandbox/shared.d.ts +23 -2
  4. package/dist/agents/sandbox/shared.js +51 -18
  5. package/dist/agents/sandbox/translational-safety-agent.js +26 -0
  6. package/dist/agents/sandbox/types.d.ts +24 -1
  7. package/dist/agents/sandbox-catalog.d.ts +14 -0
  8. package/dist/agents/sandbox-catalog.js +19 -0
  9. package/dist/app/approve-plan.d.ts +51 -0
  10. package/dist/app/approve-plan.js +84 -0
  11. package/dist/app/chat-turn.js +6 -3
  12. package/dist/app/data-profile-view.d.ts +1 -1
  13. package/dist/app/run-activity.js +4 -6
  14. package/dist/config/environment-stores.d.ts +4 -2
  15. package/dist/contracts/chat-events.d.ts +14 -2
  16. package/dist/contracts/chat-events.js +1 -1
  17. package/dist/contracts/chat-frame.d.ts +7 -0
  18. package/dist/contracts/chat-frame.js +24 -6
  19. package/dist/contracts/chat-parts.d.ts +73 -2
  20. package/dist/contracts/chat-parts.js +3 -1
  21. package/dist/contracts/index.d.ts +4 -2
  22. package/dist/contracts/index.js +1 -0
  23. package/dist/contracts/part-registry.js +3 -0
  24. package/dist/contracts/schemas/chat-events.d.ts +38 -0
  25. package/dist/contracts/schemas/chat-events.js +8 -0
  26. package/dist/contracts/schemas/chat-parts.d.ts +239 -15
  27. package/dist/contracts/schemas/chat-parts.js +80 -12
  28. package/dist/contracts/schemas/index.d.ts +2 -2
  29. package/dist/contracts/schemas/index.js +2 -2
  30. package/dist/contracts/subagent-activity.d.ts +12 -0
  31. package/dist/contracts/subagent-activity.js +76 -0
  32. package/dist/execution/artifact-metadata.js +1 -3
  33. package/dist/execution/dbos-workflow-purger.d.ts +2 -0
  34. package/dist/execution/dbos-workflow-purger.js +21 -14
  35. package/dist/execution/run-canceler.d.ts +33 -11
  36. package/dist/execution/run-canceler.js +130 -28
  37. package/dist/execution/run-end-record.d.ts +30 -0
  38. package/dist/execution/run-end-record.js +27 -0
  39. package/dist/execution/run-event-parts.d.ts +6 -5
  40. package/dist/execution/run-event-parts.js +6 -5
  41. package/dist/execution/run-event-stream.d.ts +18 -6
  42. package/dist/execution/run-event-stream.js +67 -17
  43. package/dist/execution/run-synthesis.d.ts +21 -0
  44. package/dist/execution/run-synthesis.js +77 -3
  45. package/dist/index.d.ts +28 -10
  46. package/dist/index.js +26 -2
  47. package/dist/lib/hooks.d.ts +1 -1
  48. package/dist/lib/metrics.d.ts +2 -2
  49. package/dist/loop/call-guard.d.ts +50 -0
  50. package/dist/loop/call-guard.js +90 -0
  51. package/dist/loop/compaction.d.ts +5 -0
  52. package/dist/loop/compaction.js +17 -0
  53. package/dist/loop/run-agent.d.ts +9 -0
  54. package/dist/loop/run-agent.js +16 -1
  55. package/dist/loop/run-to-terminal.js +4 -1
  56. package/dist/loop/types.d.ts +8 -0
  57. package/dist/memory/card-builders.d.ts +11 -0
  58. package/dist/memory/card-builders.js +35 -21
  59. package/dist/memory/conversation-display-recorder.d.ts +2 -2
  60. package/dist/memory/conversation-display-recorder.js +38 -4
  61. package/dist/memory/conversation-display-storage.d.ts +9 -2
  62. package/dist/memory/conversation-display-storage.js +18 -3
  63. package/dist/memory/thread-history.d.ts +42 -8
  64. package/dist/memory/thread-history.js +164 -45
  65. package/dist/memory/thread-store.d.ts +13 -0
  66. package/dist/memory/thread-store.js +15 -1
  67. package/dist/prompts/briefing.d.ts +57 -3
  68. package/dist/prompts/briefing.js +129 -2
  69. package/dist/prompts/conversation.d.ts +1 -1
  70. package/dist/prompts/conversation.js +3 -1
  71. package/dist/prompts/planner.js +13 -2
  72. package/dist/provenance/seam.d.ts +39 -20
  73. package/dist/provenance/seam.js +7 -5
  74. package/dist/providers/ai-sdk.js +93 -11
  75. package/dist/providers/types.d.ts +6 -0
  76. package/dist/reference-data/catalog.js +141 -2
  77. package/dist/report-model/authoring-grammar.d.ts +26 -26
  78. package/dist/report-model/pin-snapshot.d.ts +1 -1
  79. package/dist/report-model/pin-snapshot.js +2 -50
  80. package/dist/runtime/assemble.d.ts +8 -1
  81. package/dist/runtime/assemble.js +11 -0
  82. package/dist/runtime/boot.d.ts +3 -0
  83. package/dist/runtime/boot.js +10 -1
  84. package/dist/sandbox/image-packages.d.ts +26 -4
  85. package/dist/sandbox/image-packages.js +18 -4
  86. package/dist/sandbox/sandbox-step-translate.d.ts +23 -0
  87. package/dist/sandbox/sandbox-step-translate.js +24 -0
  88. package/dist/schemas/artifact-manifest.d.ts +1 -1
  89. package/dist/schemas/artifact-manifest.js +11 -9
  90. package/dist/schemas/data-profile-schemas.d.ts +12 -12
  91. package/dist/schemas/plan-schemas.d.ts +75 -21
  92. package/dist/schemas/plan-schemas.js +1 -1
  93. package/dist/schemas/run-synthesis.d.ts +2 -2
  94. package/dist/schemas/workflow-state.d.ts +113 -0
  95. package/dist/schemas/workflow-state.js +54 -0
  96. package/dist/state/analyses-metrics.d.ts +79 -7
  97. package/dist/state/analyses-metrics.js +141 -6
  98. package/dist/state/artifacts.d.ts +66 -3
  99. package/dist/state/artifacts.js +85 -7
  100. package/dist/state/data-profile.d.ts +4 -2
  101. package/dist/state/data-profile.js +7 -5
  102. package/dist/state/index.d.ts +9 -8
  103. package/dist/state/index.js +5 -5
  104. package/dist/state/migrations/20261012120000_index_the_runs_by_start.d.ts +8 -0
  105. package/dist/state/migrations/20261012120000_index_the_runs_by_start.js +12 -0
  106. package/dist/state/migrations/20261013120000_index_the_ended_runs_and_the_recent_threads.d.ts +8 -0
  107. package/dist/state/migrations/20261013120000_index_the_ended_runs_and_the_recent_threads.js +13 -0
  108. package/dist/state/migrations/20261013180000_narrow_the_active_run_index.d.ts +8 -0
  109. package/dist/state/migrations/20261013180000_narrow_the_active_run_index.js +13 -0
  110. package/dist/state/migrations/20261014120000_index_the_plans_by_parent_and_the_runs_by_plan.d.ts +8 -0
  111. package/dist/state/migrations/20261014120000_index_the_plans_by_parent_and_the_runs_by_plan.js +13 -0
  112. package/dist/state/migrations/index.js +8 -0
  113. package/dist/state/plans.d.ts +21 -0
  114. package/dist/state/plans.js +25 -0
  115. package/dist/state/runs.d.ts +79 -14
  116. package/dist/state/runs.js +150 -33
  117. package/dist/state/schema.d.ts +2 -0
  118. package/dist/state/step-executions.d.ts +9 -0
  119. package/dist/state/step-executions.js +22 -0
  120. package/dist/tasks/data-profile-activity.d.ts +7 -1
  121. package/dist/tasks/data-profile-activity.js +18 -9
  122. package/dist/tasks/data-profile.d.ts +15 -1
  123. package/dist/tasks/data-profile.js +16 -11
  124. package/dist/tools/ad-hoc-router.d.ts +2 -0
  125. package/dist/tools/ad-hoc-router.js +18 -2
  126. package/dist/tools/approval/gateway.js +28 -5
  127. package/dist/tools/capability-data.d.ts +36 -0
  128. package/dist/tools/capability-data.js +73 -0
  129. package/dist/tools/display/show-user.d.ts +1 -1
  130. package/dist/tools/execute-analysis.d.ts +80 -1
  131. package/dist/tools/execute-analysis.js +352 -110
  132. package/dist/tools/knowledge/check.d.ts +60 -0
  133. package/dist/tools/knowledge/check.js +92 -0
  134. package/dist/tools/knowledge/client.d.ts +382 -0
  135. package/dist/tools/knowledge/client.js +302 -0
  136. package/dist/tools/knowledge/environment.d.ts +78 -0
  137. package/dist/tools/knowledge/environment.js +105 -0
  138. package/dist/tools/knowledge/index.d.ts +49 -0
  139. package/dist/tools/knowledge/index.js +70 -0
  140. package/dist/tools/knowledge/local-slots.d.ts +62 -0
  141. package/dist/tools/knowledge/local-slots.js +177 -0
  142. package/dist/tools/knowledge/pin.d.ts +14 -0
  143. package/dist/tools/knowledge/pin.js +17 -0
  144. package/dist/tools/knowledge/recommend.d.ts +92 -0
  145. package/dist/tools/knowledge/recommend.js +98 -0
  146. package/dist/tools/knowledge/situation.d.ts +143 -0
  147. package/dist/tools/knowledge/situation.js +164 -0
  148. package/dist/tools/knowledge/skeleton.d.ts +69 -0
  149. package/dist/tools/knowledge/skeleton.js +202 -0
  150. package/dist/tools/knowledge/template.d.ts +137 -0
  151. package/dist/tools/knowledge/template.js +267 -0
  152. package/dist/tools/research/generate-plan.d.ts +23 -0
  153. package/dist/tools/research/generate-plan.js +203 -12
  154. package/dist/tools/research/guarded-address.d.ts +20 -0
  155. package/dist/tools/research/guarded-address.js +148 -0
  156. package/dist/tools/research/inspect-data-profile.d.ts +1 -1
  157. package/dist/tools/research/inspect-run.d.ts +1 -1
  158. package/dist/tools/research/inspect-run.js +7 -7
  159. package/dist/tools/research/searxng-engine.d.ts +40 -0
  160. package/dist/tools/research/searxng-engine.js +120 -0
  161. package/dist/tools/research/web-fetch.d.ts +124 -0
  162. package/dist/tools/research/web-fetch.js +627 -0
  163. package/dist/tools/research/web-search.d.ts +75 -0
  164. package/dist/tools/research/web-search.js +112 -0
  165. package/dist/tools/sandbox/list-available-packages.d.ts +7 -4
  166. package/dist/tools/sandbox/list-available-packages.js +12 -4
  167. package/dist/tools/sandbox/list-available-refs.d.ts +21 -0
  168. package/dist/tools/sandbox/list-available-refs.js +60 -3
  169. package/dist/tools/sandbox/report-blocker.js +5 -1
  170. package/dist/tools/terminal-text.d.ts +11 -0
  171. package/dist/tools/terminal-text.js +19 -0
  172. package/dist/tools/workspace/decision-record.d.ts +81 -0
  173. package/dist/tools/workspace/decision-record.js +117 -0
  174. package/dist/tools/workspace/edit-file.d.ts +3 -1
  175. package/dist/tools/workspace/edit-file.js +20 -2
  176. package/dist/tools/workspace/execute-command.d.ts +17 -0
  177. package/dist/tools/workspace/execute-command.js +28 -1
  178. package/dist/tools/workspace/index.d.ts +1 -0
  179. package/dist/tools/workspace/index.js +1 -0
  180. package/dist/tools/workspace/mutator.d.ts +1 -1
  181. package/dist/workflows/execute-analysis.d.ts +62 -21
  182. package/dist/workflows/execute-analysis.js +307 -79
  183. package/dist/workflows/plan/graph.d.ts +16 -0
  184. package/dist/workflows/plan/graph.js +36 -0
  185. package/dist/workflows/sandbox-step.d.ts +12 -0
  186. package/dist/workflows/sandbox-step.js +14 -12
  187. package/package.json +5 -1
@@ -17,6 +17,7 @@ import { ok } from "neverthrow";
17
17
  import { z } from "zod";
18
18
  import { defineTool, withToolCallRecord } from "../define-tool.js";
19
19
  import { unwrapOrThrow } from "../../lib/result.js";
20
+ import { noteScriptChange, scriptSha256 } from "./decision-record.js";
20
21
  const EditFileInputSchema = z.object({
21
22
  path: z
22
23
  .string()
@@ -172,6 +173,19 @@ export function createEditFileTool(deps) {
172
173
  });
173
174
  if (write.status !== "ok")
174
175
  return ok(write);
176
+ // A rendered script carries a decision record. The edit is a change the curator did not vet, and the
177
+ // record keeps it with the digest after the change, thus an empty `unvetted_edits` stays a fact.
178
+ const noted = await noteScriptChange({
179
+ filesystem: deps.workspaceFilesystem,
180
+ mutator: deps.mutator,
181
+ session: ctx.session,
182
+ ...(deps.workingDir !== undefined ? { workingDir: deps.workingDir } : {}),
183
+ invocationId: ctx.invocationId,
184
+ toolName: "edit_file",
185
+ scriptPath: path,
186
+ note: `edit_file: ${replaced.replacements} replacement(s)`,
187
+ sha256: scriptSha256(replaced.content),
188
+ });
175
189
  const lines = replaced.lines;
176
190
  return ok(withToolCallRecord({
177
191
  status: "ok",
@@ -179,8 +193,12 @@ export function createEditFileTool(deps) {
179
193
  replacements: replaced.replacements,
180
194
  bytesWritten: write.bytesWritten,
181
195
  ...(lines === undefined ? {} : { lines }),
182
- }, write.record));
196
+ ...(noted.status === "noted" ? { decision_record_noted: true } : {}),
197
+ }, noted.status === "noted" ? [write.record, noted.write] : [write.record]));
198
+ },
199
+ foldCallRecord: (records) => {
200
+ for (const record of records)
201
+ deps.mutator.recordWrite(record);
183
202
  },
184
- foldCallRecord: (record) => deps.mutator.recordWrite(record),
185
203
  });
186
204
  }
@@ -18,12 +18,20 @@
18
18
  * `sandbox-provenance-tracking`), and artifact registration reconciles them.
19
19
  * The frame of each exec rides the call record, and the fold feeds it to the
20
20
  * lineage collector of the step.
21
+ *
22
+ * A script the command names that carries a decision record is compared
23
+ * with the digest the record expects before it runs. A difference is a
24
+ * change that no file tool recorded, and the record gets it with the digest
25
+ * of the bytes that run, thus the record connects the cited decision to the
26
+ * code that ran.
21
27
  */
22
28
  import { type WithToolCallRecord } from "../define-tool.js";
23
29
  import type { SandboxClient } from "../../sandbox/client.js";
24
30
  import type { ProvenanceFrame, SandboxRef } from "../../sandbox/types.js";
25
31
  import type { ProvenanceCollector } from "../../provenance/collector.js";
32
+ import type { WorkspaceMutator, WriteRecord } from "./mutator.js";
26
33
  import { type BoundedExecResult } from "./result-bounds.js";
34
+ import type { WorkspaceFilesystem } from "../../workspace/filesystem.js";
27
35
  import type { Logger } from "../../lib/logger.js";
28
36
  /** What one exec leaves for the lineage collector of the step. */
29
37
  interface ExecCallRecord {
@@ -31,6 +39,8 @@ interface ExecCallRecord {
31
39
  readonly exitCode: number | null;
32
40
  readonly durationMs: number | null;
33
41
  readonly provenance?: ProvenanceFrame;
42
+ /** The decision-record writes of the script check before the exec, for the mutator. */
43
+ readonly recordWrites?: readonly WriteRecord[];
34
44
  }
35
45
  type ExecuteCommandResult = {
36
46
  readonly status: "ok";
@@ -58,6 +68,13 @@ export interface ExecuteCommandDeps {
58
68
  readonly lineageCollector?: ProvenanceCollector;
59
69
  /** Analysis resource mount root (`/{resourceId}`) — strips frame paths to relative. */
60
70
  readonly mountRoot?: string;
71
+ /**
72
+ * The workspace filesystem and the mutator of the step, for the record check of a
73
+ * script the command runs. Both absent (a read-only agent), no record is
74
+ * read or written.
75
+ */
76
+ readonly workspaceFilesystem?: WorkspaceFilesystem;
77
+ readonly mutator?: WorkspaceMutator;
61
78
  }
62
79
  export declare function createExecuteCommandTool(deps: ExecuteCommandDeps): import("../define-tool.js").Tool<{
63
80
  command: string[];
@@ -18,12 +18,19 @@
18
18
  * `sandbox-provenance-tracking`), and artifact registration reconciles them.
19
19
  * The frame of each exec rides the call record, and the fold feeds it to the
20
20
  * lineage collector of the step.
21
+ *
22
+ * A script the command names that carries a decision record is compared
23
+ * with the digest the record expects before it runs. A difference is a
24
+ * change that no file tool recorded, and the record gets it with the digest
25
+ * of the bytes that run, thus the record connects the cited decision to the
26
+ * code that ran.
21
27
  */
22
28
  import { posix as posixPath } from "node:path";
23
29
  import { ok } from "neverthrow";
24
30
  import { z } from "zod";
25
31
  import { defineTool, withToolCallRecord } from "../define-tool.js";
26
32
  import { feedExecFrame } from "../../provenance/exec-frame.js";
33
+ import { reconcileScriptRecord } from "./decision-record.js";
27
34
  import { EXEC_STREAM_BYTE_CAP, boundExecResult } from "./result-bounds.js";
28
35
  import { runSandboxExec } from "./run-exec.js";
29
36
  import { createNoopLogger } from "../../lib/console-logger.js";
@@ -86,6 +93,23 @@ export function createExecuteCommandTool(deps) {
86
93
  describeCall: ({ command }) => scriptToken(command) ?? command.join(" "),
87
94
  execute: async ({ command, cwd, env, timeoutSeconds }, ctx) => {
88
95
  const effectiveCwd = cwd === undefined ? defaultCwd : cwd.startsWith("/") ? cwd : posixPath.join(defaultCwd, cwd);
96
+ // Each script the argv names, as the sandbox resolves it. A relative token resolves against the cwd of the
97
+ // command, which is a `/{analysisId}/...` path, thus the workspace filesystem resolves it the same way.
98
+ const recordWrites = [];
99
+ if (deps.workspaceFilesystem && deps.mutator) {
100
+ for (const token of command.filter((arg) => SCRIPT_EXTENSIONS.test(arg))) {
101
+ const noted = await reconcileScriptRecord({
102
+ filesystem: deps.workspaceFilesystem,
103
+ mutator: deps.mutator,
104
+ session: ctx.session,
105
+ invocationId: ctx.invocationId,
106
+ toolName: "execute_command",
107
+ scriptPath: token.startsWith("/") ? token : posixPath.join(effectiveCwd, token),
108
+ });
109
+ if (noted.status === "noted")
110
+ recordWrites.push(noted.write);
111
+ }
112
+ }
89
113
  const result = await runSandboxExec({
90
114
  sandboxClient,
91
115
  sandbox,
@@ -97,18 +121,21 @@ export function createExecuteCommandTool(deps) {
97
121
  emit: ctx.emit,
98
122
  });
99
123
  const bounded = { status: "ok", ...boundExecResult(result) };
100
- if (!lineageCollector || !mountRoot)
124
+ if ((!lineageCollector || !mountRoot) && recordWrites.length === 0)
101
125
  return ok(bounded);
102
126
  const record = {
103
127
  command,
104
128
  exitCode: result.exitCode,
105
129
  durationMs: result.durationMs,
106
130
  ...(result.provenance ? { provenance: result.provenance } : {}),
131
+ ...(recordWrites.length > 0 ? { recordWrites } : {}),
107
132
  };
108
133
  return ok(withToolCallRecord(bounded, record));
109
134
  },
110
135
  // Best-effort: a collector failure must never fail the exec.
111
136
  foldCallRecord: (record) => {
137
+ for (const write of record.recordWrites ?? [])
138
+ deps.mutator?.recordWrite(write);
112
139
  if (!lineageCollector || !mountRoot)
113
140
  return;
114
141
  try {
@@ -21,5 +21,6 @@ export * from "./mutator.js";
21
21
  export * from "./execute-command.js";
22
22
  export * from "./write-file.js";
23
23
  export * from "./edit-file.js";
24
+ export * from "./decision-record.js";
24
25
  export { EXEC_STREAM_BYTE_CAP, boundExecResult } from "./result-bounds.js";
25
26
  export type { BoundedExecResult } from "./result-bounds.js";
@@ -23,4 +23,5 @@ export * from "./mutator.js";
23
23
  export * from "./execute-command.js";
24
24
  export * from "./write-file.js";
25
25
  export * from "./edit-file.js";
26
+ export * from "./decision-record.js";
26
27
  export { EXEC_STREAM_BYTE_CAP, boundExecResult } from "./result-bounds.js";
@@ -80,7 +80,7 @@ export type WriteOutcome = {
80
80
  * (`inflexa:tool` in the signed document) — the seam records the write without
81
81
  * inspecting its caller.
82
82
  */
83
- export type MutateToolName = "write_file" | "edit_file";
83
+ export type MutateToolName = "write_file" | "edit_file" | "knowledge_template" | "execute_command";
84
84
  export interface WorkspaceMutatorDeps {
85
85
  /** Absolute host root of this analysis's workspace tree — used by the resolver. */
86
86
  readonly workspaceRoot: string;
@@ -50,20 +50,25 @@
50
50
  * the run before any step starts
51
51
  * - a `suspend` error of a synthesis model request suspends the run in
52
52
  * place of the synthesis failure
53
- * - the analysis flips to `suspended_insufficient_funds` in
54
- * `collectAndComplete`. The paused parent lands in `CANCELLED`, a
53
+ * - the run row and the analysis flip to `suspended_insufficient_funds` in
54
+ * `collectAndComplete`. The run status is terminal and does not block a
55
+ * new run of the plan. The paused parent lands in `CANCELLED`, a
55
56
  * durably reschedulable state; re-driving it is a future enhancement,
56
57
  * not yet wired here. The reason of the host rides to the run row, the
57
58
  * charge close, the metric, and the terminal part, unread.
58
59
  * 5. `synthesizeFindings` (single sequential block, no sandbox)
59
60
  * 6. `collectAndComplete` (terminal — runs on ALL paths)
60
61
  * - determine final status from completed/cancelled/failed counts
61
- * - update `cortex_runs.status` + `error`, and inside that same step record
62
- * the run outcome metric plus the outcome of every settled step whose
63
- * child never wrote its own terminal row (a cancelled child, or one that
64
- * died before `failStep`)
65
- * - close running charge with matching reason
66
- * - revoke run authorization via the injected `runAuthorizer` seam
62
+ * - update `cortex_runs.status` + `error`. When the write changes the row,
63
+ * the same step emits `run_completed` before the commit, records the run
64
+ * outcome metric plus the outcome of every settled step whose child never
65
+ * wrote its own terminal row (a cancelled child, or one that died before
66
+ * `failStep`), closes the running charge with the matching outcome, and
67
+ * revokes the run authorization through the injected `runAuthorizer`
68
+ * - the write retries with backoff on a failed transaction. When the write is
69
+ * refused, or fails on each attempt, close and revoke in their own steps, then
70
+ * emit `run_completed`. After a failed write the row stays `running`, so the
71
+ * body records its run end as a workflow event for the run canceler
67
72
  * - emit terminal stream part
68
73
  * - WRITES NOTHING to the conversation thread (results are pull-only
69
74
  * via `inspectRun`)
@@ -81,6 +86,8 @@ import type { WorkingMemoryStore } from "../memory/working-memory.js";
81
86
  import type { AnalysisStep } from "../schemas/workflow-state.js";
82
87
  import type { ChatProvider, EmbeddingProvider } from "../providers/types.js";
83
88
  import type { BioToolKeys } from "../tools/bio/keys.js";
89
+ import type { KnowledgeClient } from "../tools/knowledge/client.js";
90
+ import type { TemplateBinding } from "../tools/knowledge/template.js";
84
91
  import type { ProvenanceSeam } from "../provenance/seam.js";
85
92
  import type { ToolOutputStore } from "../loop/tool-output.js";
86
93
  import type { RunCharge } from "../billing/run-charge.js";
@@ -160,7 +167,7 @@ export interface ExecuteAnalysisInput {
160
167
  * path returns — the caller joined an in-flight run, no new workflow was
161
168
  * started. Every other variant is a terminal status the parent reached.
162
169
  */
163
- export type ExecuteAnalysisFinalStatus = "running" | "completed" | "partial" | "failed" | "canceled";
170
+ export type ExecuteAnalysisFinalStatus = "running" | "completed" | "partial" | "failed" | "canceled" | "suspended_insufficient_funds";
164
171
  export interface ExecuteAnalysisResult {
165
172
  readonly runId: string;
166
173
  readonly workflowId: string;
@@ -255,16 +262,27 @@ export interface ExecuteAnalysisDeps {
255
262
  * carries the goal and the constraints as they are at the dispatch of that step.
256
263
  */
257
264
  readonly workingMemory: WorkingMemoryStore;
265
+ /**
266
+ * The knowledge client of the composition, when the embedder binds one.
267
+ * The seed composition reads the contract of the template a grounded step
268
+ * renders through it, and binds the plan settings to that contract.
269
+ * Absent, the seed says the contract was not retrieved, and the step agent
270
+ * learns the slots from the render answers alone.
271
+ */
272
+ readonly knowledge?: KnowledgeClient;
258
273
  /**
259
274
  * The provenance seam of the composition. The body reads its run emit member,
260
275
  * and it reads no other member.
261
276
  *
262
- * The emit is deliberately invoked directly in the workflow body (NOT wrapped
263
- * in `DBOS.runStep`) so that body re-execution on DBOS recovery re-fires it —
264
- * a cached step would suppress the recovery re-emission, defeating the
265
- * point. Idempotency is the consumer's job, achieved via the deterministic
266
- * identifiers the events carry, not via step caching. Every call site is
267
- * guarded so a throwing observer never fails the run.
277
+ * `run_started` and `step_completed` are emitted directly in the workflow body
278
+ * (NOT wrapped in `DBOS.runStep`) so that body re-execution on DBOS recovery
279
+ * re-fires them — a cached step would suppress the recovery re-emission.
280
+ * `run_completed` is emitted by the won `persist-final-status` step, or by the
281
+ * body after that step when the step did not emit in this execution (a refused
282
+ * or failed write, or a won step served from the DBOS cache), so a recovery
283
+ * replay still fires it. Idempotency is the consumer's job, achieved via the
284
+ * deterministic identifiers the events carry, not via step caching. Every call
285
+ * site is guarded so a throwing observer never fails the run.
268
286
  *
269
287
  * Events arrive with the run's `RunSession` from durable workflow input — a
270
288
  * persisting realization needs its credential, scope, and identity.
@@ -306,6 +324,7 @@ export declare function buildChildInput(args: {
306
324
  runId: string;
307
325
  workflowId: string;
308
326
  prompt: string;
327
+ templateBinding?: TemplateBinding;
309
328
  }): Omit<SandboxStepInput, "runSession">;
310
329
  /**
311
330
  * Compose one step's seed — the user-content message its agent opens on.
@@ -316,17 +335,26 @@ export declare function buildChildInput(args: {
316
335
  * rendered any earlier (at plan submission, say) cannot mention them, and the
317
336
  * agent is left to rediscover its own upstream.
318
337
  *
319
- * REPLAY: the caller wraps this in a `DBOS.runStep`, so the composed string is
320
- * checkpointed and a replay returns it verbatim — the DB and disk are not read
321
- * again and cannot drift the seed under a recovered run. Never call it
322
- * unwrapped from the workflow body.
338
+ * The template contract of a grounded step is read with the package, and the
339
+ * plan settings are bound to it: the seed describes the binding, and the child
340
+ * input carries it, from one checkpoint. The child fetches nothing.
341
+ *
342
+ * REPLAY: the caller wraps this in a `DBOS.runStep`, so the composed seed is
343
+ * checkpointed and a replay returns it verbatim — the DB, the disk, and the
344
+ * knowledge service are not read again and cannot drift the seed under a
345
+ * recovered run. Never call it unwrapped from the workflow body.
323
346
  */
324
347
  export declare function composeStepSeed(args: {
325
348
  input: ExecuteAnalysisInput;
326
349
  stepId: string;
327
350
  runId: string;
328
351
  deps: ExecuteAnalysisDeps;
329
- }): Promise<string>;
352
+ }): Promise<StepSeed>;
353
+ /** What `gatherStepPackage` gives: the data of the seed, and the binding of the plan settings when one holds. */
354
+ export interface StepPackage {
355
+ readonly briefing: StepBriefing;
356
+ readonly templateBinding?: TemplateBinding;
357
+ }
330
358
  /**
331
359
  * Do every read of one step's package and give the data its seed is rendered
332
360
  * from. All reads live here, so `composeStepBriefing` stays a pure renderer.
@@ -339,6 +367,9 @@ export declare function composeStepSeed(args: {
339
367
  * so an edit during a run reaches each later step, and two steps of one run
340
368
  * can carry different copies.
341
369
  *
370
+ * The contract of the template a grounded step renders is read here too, from
371
+ * the knowledge client, and the plan settings are bound to it.
372
+ *
342
373
  * A read failure throws (house rules): a swallowed error would be frozen into
343
374
  * the checkpointed seed and served to every replay of this step.
344
375
  */
@@ -347,7 +378,17 @@ export declare function gatherStepPackage(args: {
347
378
  stepId: string;
348
379
  runId: string;
349
380
  deps: ExecuteAnalysisDeps;
350
- }): Promise<StepBriefing>;
381
+ }): Promise<StepPackage>;
382
+ /**
383
+ * What `composeStepSeed` checkpoints: the seed, and the binding of the plan
384
+ * settings to the template of the step when the contract was retrieved and
385
+ * its served version is the version the plan names. JSON-serialisable, as a
386
+ * durable step result must be.
387
+ */
388
+ export interface StepSeed {
389
+ readonly prompt: string;
390
+ readonly templateBinding?: TemplateBinding;
391
+ }
351
392
  /**
352
393
  * Project a classified synthesis outcome onto the run-phase `synthesis` ledger
353
394
  * row's terminal update (see the run-synthesis-outcome spec). The blocker keeps