@sema-agent/core 7.16.0 → 7.17.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 (193) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/dist/agents/builtin-agents.d.ts +3 -3
  3. package/dist/agents/cross-session-envelope.d.ts +0 -1
  4. package/dist/agents/cross-session-envelope.js +0 -1
  5. package/dist/agents/peer-notices.d.ts +0 -9
  6. package/dist/agents/peer-notices.js +0 -63
  7. package/dist/agents/subagent.js +7 -15
  8. package/dist/brain/request-params.d.ts +2 -2
  9. package/dist/config/defaults.d.ts +0 -7
  10. package/dist/config/defaults.js +0 -2
  11. package/dist/core/artifact-host.d.ts +218 -0
  12. package/dist/core/artifact-host.js +92 -0
  13. package/dist/core/ask-origin.d.ts +29 -3
  14. package/dist/core/ask-origin.js +17 -9
  15. package/dist/core/ask-question.d.ts +25 -0
  16. package/dist/core/ask-question.js +4 -0
  17. package/dist/core/ask-unresolvable-notice.d.ts +30 -21
  18. package/dist/core/ask-unresolvable-notice.js +16 -8
  19. package/dist/core/auto-compaction.d.ts +10 -10
  20. package/dist/core/auto-mode-arming.d.ts +2 -2
  21. package/dist/core/background-agent-store.d.ts +5 -5
  22. package/dist/core/background-shell.d.ts +1 -1
  23. package/dist/core/checkpoint-execution-record.d.ts +0 -3
  24. package/dist/core/checkpoint-execution-record.js +0 -4
  25. package/dist/core/checkpoint-store.d.ts +71 -99
  26. package/dist/core/checkpoint-store.js +9 -16
  27. package/dist/core/context-edit.d.ts +36 -104
  28. package/dist/core/context-edit.js +37 -60
  29. package/dist/core/effective-path-target.d.ts +68 -8
  30. package/dist/core/effective-path-target.js +42 -30
  31. package/dist/core/engine-notice.d.ts +46 -32
  32. package/dist/core/env-budget.d.ts +31 -0
  33. package/dist/core/env-budget.js +39 -0
  34. package/dist/core/exec-output-tail.d.ts +5 -5
  35. package/dist/core/file-history-store.js +3 -6
  36. package/dist/core/fs-write-gate-policy.d.ts +1 -1
  37. package/dist/core/fs-write-gate-policy.js +3 -3
  38. package/dist/core/gate-lanes.js +9 -15
  39. package/dist/core/governance-codes.d.ts +1 -1
  40. package/dist/core/governance-codes.js +2 -0
  41. package/dist/core/hands-band.d.ts +1 -1
  42. package/dist/core/hooks.d.ts +18 -17
  43. package/dist/core/lsp-session.d.ts +1 -1
  44. package/dist/core/lsp.d.ts +1 -1
  45. package/dist/core/lsp.js +5 -4
  46. package/dist/core/mcp.d.ts +5 -5
  47. package/dist/core/mcp.js +4 -48
  48. package/dist/core/memory-recall.d.ts +0 -8
  49. package/dist/core/memory.d.ts +1 -1
  50. package/dist/core/oracle-isolation.js +2 -2
  51. package/dist/core/parent-spec-seat.d.ts +66 -0
  52. package/dist/core/parent-spec-seat.js +47 -0
  53. package/dist/core/permission-rule-model.d.ts +11 -6
  54. package/dist/core/permission-rule-model.js +53 -37
  55. package/dist/core/permission-rules.js +8 -3
  56. package/dist/core/protocol-naming.d.ts +2 -2
  57. package/dist/core/remote-env.d.ts +1 -1
  58. package/dist/core/retired-keys.d.ts +19 -0
  59. package/dist/core/retired-keys.js +15 -0
  60. package/dist/core/runner/active-skill-scope.js +3 -3
  61. package/dist/core/runner/assemble-result.d.ts +15 -13
  62. package/dist/core/runner/assemble-result.js +5 -4
  63. package/dist/core/runner/compaction-call-options.d.ts +25 -89
  64. package/dist/core/runner/contracts.d.ts +10 -9
  65. package/dist/core/runner/gate-exit.js +15 -1
  66. package/dist/core/runner/halt-attribution.d.ts +35 -0
  67. package/dist/core/runner/halt-attribution.js +16 -0
  68. package/dist/core/runner/memory-consolidation.d.ts +0 -2
  69. package/dist/core/runner/memory-consolidation.js +0 -1
  70. package/dist/core/runner/prepare-artifact.d.ts +53 -0
  71. package/dist/core/runner/prepare-artifact.js +77 -0
  72. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  73. package/dist/core/runner/prepare-caps-and-workflow.js +2 -3
  74. package/dist/core/runner/prepare-config-doors.d.ts +3 -3
  75. package/dist/core/runner/prepare-config-doors.js +5 -2
  76. package/dist/core/runner/prepare-context-lane.d.ts +2 -2
  77. package/dist/core/runner/prepare-context-lane.js +2 -13
  78. package/dist/core/runner/prepare-file-history.d.ts +1 -1
  79. package/dist/core/runner/prepare-file-history.js +3 -52
  80. package/dist/core/runner/prepare-hands-readface.d.ts +4 -7
  81. package/dist/core/runner/prepare-hands-readface.js +3 -2
  82. package/dist/core/runner/prepare-inherited-gate.d.ts +5 -2
  83. package/dist/core/runner/prepare-inherited-gate.js +7 -8
  84. package/dist/core/runner/prepare-memory.d.ts +4 -6
  85. package/dist/core/runner/prepare-memory.js +4 -2
  86. package/dist/core/runner/prepare-policy-chain.d.ts +3 -3
  87. package/dist/core/runner/prepare-policy-chain.js +15 -30
  88. package/dist/core/runner/prepare-prompt-assembly.js +1 -1
  89. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  90. package/dist/core/runner/prepare-suspend-saga.js +0 -2
  91. package/dist/core/runner/prepare-task.js +10 -9
  92. package/dist/core/runner/prepare-wiring-manifest.js +9 -7
  93. package/dist/core/runner/resume-admission.js +2 -1
  94. package/dist/core/runner/resume-internals-and-config.js +4 -0
  95. package/dist/core/runner/retired-runner-deps.d.ts +3 -0
  96. package/dist/core/runner/retired-runner-deps.js +7 -0
  97. package/dist/core/runner/run-harness-handlers.js +2 -3
  98. package/dist/core/runner/run-settle-and-teardown.d.ts +1 -1
  99. package/dist/core/runner/run-settle-and-teardown.js +3 -1
  100. package/dist/core/runner/session-file-state-replay.js +3 -3
  101. package/dist/core/runner/session-rule-policy.js +3 -4
  102. package/dist/core/runner/stream-halt-verbs.js +1 -1
  103. package/dist/core/runner/stream-steer-verb.js +1 -4
  104. package/dist/core/runner/workspace-path.js +3 -0
  105. package/dist/core/runner-deps.d.ts +30 -49
  106. package/dist/core/safe-notify.d.ts +1 -1
  107. package/dist/core/sensitive-path-policy.d.ts +1 -1
  108. package/dist/core/sensitive-path-policy.js +4 -4
  109. package/dist/core/session.d.ts +2 -2
  110. package/dist/core/skill-tool-specifier.d.ts +1 -1
  111. package/dist/core/skills-directory.d.ts +1 -1
  112. package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
  113. package/dist/core/strategy-store.d.ts +8 -11
  114. package/dist/core/task-event.d.ts +20 -17
  115. package/dist/core/task-limits.d.ts +1 -1
  116. package/dist/core/task-notification.d.ts +5 -5
  117. package/dist/core/task-registry-agent.d.ts +5 -5
  118. package/dist/core/task-registry-monitor.d.ts +2 -2
  119. package/dist/core/task-registry-shared.d.ts +27 -27
  120. package/dist/core/task-registry-shared.js +3 -13
  121. package/dist/core/task-registry.d.ts +8 -8
  122. package/dist/core/task-result.d.ts +37 -37
  123. package/dist/core/task-spec.d.ts +5 -5
  124. package/dist/core/task-stream.d.ts +16 -11
  125. package/dist/core/tool-catalog-entries.d.ts +1 -0
  126. package/dist/core/tool-catalog-entries.js +5 -0
  127. package/dist/core/tool-conformance.d.ts +0 -2
  128. package/dist/core/tool-conformance.js +1 -3
  129. package/dist/core/tool-errors.d.ts +5 -0
  130. package/dist/core/tool-errors.js +1 -0
  131. package/dist/core/tool-policy.d.ts +51 -22
  132. package/dist/core/tool-policy.js +28 -5
  133. package/dist/core/tool-result-budget.d.ts +1 -1
  134. package/dist/core/tool-result-store.d.ts +11 -11
  135. package/dist/core/tool-spec.d.ts +34 -38
  136. package/dist/core/tools.d.ts +2 -2
  137. package/dist/core/trace.d.ts +12 -15
  138. package/dist/core/untrusted-text.d.ts +1 -1
  139. package/dist/core/wiring-manifest.d.ts +4 -3
  140. package/dist/core/workflow-journal-store.d.ts +11 -11
  141. package/dist/engine/execution-env/node-execution-env.d.ts +3 -2
  142. package/dist/engine/execution-env/node-execution-env.js +4 -2
  143. package/dist/engine/harness/agent-harness.d.ts +47 -4
  144. package/dist/engine/harness/agent-harness.js +52 -9
  145. package/dist/engine/loop/agent-loop.js +15 -8
  146. package/dist/engine/loop/types.d.ts +5 -0
  147. package/dist/index.d.ts +19 -14
  148. package/dist/index.js +15 -10
  149. package/dist/internal/harness.d.ts +1 -0
  150. package/dist/orchestration/run-spec.d.ts +3 -0
  151. package/dist/orchestration/run-spec.js +3 -3
  152. package/dist/orchestration/run-workflow-tool.d.ts +12 -6
  153. package/dist/orchestration/run-workflow-tool.js +23 -5
  154. package/dist/orchestration/workflow-primitives.d.ts +4 -2
  155. package/dist/orchestration/workflow-primitives.js +1 -4
  156. package/dist/orchestration/workflow-types.d.ts +34 -4
  157. package/dist/orchestration/workflow-types.js +2 -0
  158. package/dist/orchestration/workflow.d.ts +39 -7
  159. package/dist/orchestration/workflow.js +234 -113
  160. package/dist/prompt-assembly/assemble.d.ts +2 -2
  161. package/dist/prompt-assembly/assemble.js +9 -9
  162. package/dist/prompt-assembly/composer.d.ts +6 -7
  163. package/dist/prompt-assembly/composer.js +10 -10
  164. package/dist/prompt-assembly/epoch.js +1 -1
  165. package/dist/prompt-assembly/event-registry.d.ts +0 -21
  166. package/dist/prompt-assembly/packs/sema-default.js +30 -30
  167. package/dist/prompt-assembly/types.d.ts +14 -14
  168. package/dist/prompts/coordinator.d.ts +0 -13
  169. package/dist/prompts/coordinator.js +0 -3
  170. package/dist/stores/file/checkpoint-store.js +1 -5
  171. package/dist/stores/file/file-history-store.js +2 -2
  172. package/dist/stores/file/permission-rule-store.d.ts +4 -35
  173. package/dist/stores/file/permission-rule-store.js +4 -148
  174. package/dist/tools/artifact/artifact-text.d.ts +62 -0
  175. package/dist/tools/artifact/artifact-text.js +68 -0
  176. package/dist/tools/artifact/artifact-tool.d.ts +52 -0
  177. package/dist/tools/artifact/artifact-tool.js +351 -0
  178. package/dist/tools/artifact/local-stub.d.ts +26 -0
  179. package/dist/tools/artifact/local-stub.js +296 -0
  180. package/dist/tools/fs/bash-readonly-classifier.d.ts +74 -8
  181. package/dist/tools/fs/bash-readonly-classifier.js +171 -60
  182. package/dist/tools/fs/fs-bash.d.ts +14 -10
  183. package/dist/tools/fs/fs-bash.js +19 -27
  184. package/dist/tools/fs/fs-search-tools.js +5 -2
  185. package/dist/tools/fs/fs-shared.d.ts +2 -0
  186. package/dist/tools/fs/fs-shared.js +3 -11
  187. package/dist/tools/fs/index.d.ts +4 -0
  188. package/dist/tools/fs/index.js +4 -1
  189. package/dist/tools/fs/safety.d.ts +117 -1
  190. package/dist/tools/fs/safety.js +131 -31
  191. package/dist/tools/fs/search.js +8 -6
  192. package/package.json +2 -1
  193. package/test/export-surface.snapshot.json +115 -39
@@ -6,7 +6,15 @@ import { withDelegationProvenance } from "../core/tool-policy.js";
6
6
  import { LAUNCH_RECEIPT_OWN_WORDS_CLAUSE, launchReceiptNoQuoteClause } from "../agents/launch-receipt-contract.js";
7
7
  import { startWorkflow } from "./workflow.js";
8
8
  import { WORKFLOW_AGENT_PARKED_ERROR_CODE } from "./workflow-types.js";
9
+ import { checkpointStoreOfSeat } from "../core/checkpoint-seat.js";
9
10
  import { buildWorkflowPrimitives } from "./workflow-primitives.js";
11
+ import { stripSpawnTurnQuestionFace } from "../core/ask-question.js";
12
+ import { parentSpecSeatOfCtx } from "../core/parent-spec-seat.js";
13
+ import { assertNoRetiredKeys } from "../core/retired-keys.js";
14
+ const RETIRED_RUN_WORKFLOW_TOOL_DEPS_KEYS = {
15
+ principal: "the host run's principal rides `RunWorkflowToolDeps.parentSpecSeat.principal` (the parent SPEC seat the host's prepare mints), never a seat of its own",
16
+ oneShot: "the host run's one-shot fact rides `RunWorkflowToolDeps.parentSpecSeat.oneShot` (only `true` travels), never a seat of its own",
17
+ };
10
18
  import { parseWorkflowMeta, splitWorkflowMeta, workflowScriptReadsClockOrRandom } from "./workflow-meta.js";
11
19
  import { mergeWorkflowArgs, normalizeStringArg } from "./workflow-script-store.js";
12
20
  import { builtinWorkflowListings, canonicalWorkflowName, resolveBuiltinWorkflow, workflowNameProbeOrder } from "./builtin-workflows.js";
@@ -169,6 +177,7 @@ async function collectNamedWorkflowListings(store, builtinsEnabled) {
169
177
  return [...byName.values()];
170
178
  }
171
179
  export async function createRunWorkflowTool(d) {
180
+ assertNoRetiredKeys(d, RETIRED_RUN_WORKFLOW_TOOL_DEPS_KEYS, "RunWorkflowToolDeps");
172
181
  if (d.scriptRunner.safeForUntrustedScripts !== true) {
173
182
  throw new Error("createRunWorkflowTool: refusing to mount run_workflow on a runner that is not safeForUntrustedScripts (design/98 fail-closed)");
174
183
  }
@@ -304,7 +313,8 @@ export async function createRunWorkflowTool(d) {
304
313
  "concurrent agents WRITE THE SAME FILES/REPO and must not clobber each other — even as a parallel fan-out " +
305
314
  "(plain parallel would clobber); this takes precedence over plain parallel. A separate-working-copy need, " +
306
315
  "NOT merely 'several agents'.\n" +
307
- "• resumeFromRunId (this tool's arg): RESUME a prior/crashed run — replay its completed agents, run only new work.\n" +
316
+ "• resumeFromRunId (this tool's arg): RESUME a prior/crashed run — replay its completed agents, run only new work " +
317
+ "(a run that could park must have finished — a crashed park-capable run is decided through the deployment's approval channel, not resumed).\n" +
308
318
  "• scriptPath / name (this tool's args): when a script store is wired, every run persists its script and " +
309
319
  "returns its scriptPath — to iterate, EDIT that file and re-invoke with {scriptPath} instead of resending " +
310
320
  "the full script; {name} runs a saved workflow.\n" +
@@ -392,7 +402,10 @@ export async function createRunWorkflowTool(d) {
392
402
  const rawResume = rawArgs.resumeFromRunId;
393
403
  const resumeFromRunId = typeof rawResume === "string" && rawResume.length > 0 ? rawResume : undefined;
394
404
  const sourceTaskId = ctx.taskId ?? d.sourceTaskId;
395
- const principal = ctx.principal ?? d.principal;
405
+ const hostSeat = parentSpecSeatOfCtx(ctx) ?? d.parentSpecSeat;
406
+ const detachedSeat = hostSeat !== undefined ? stripSpawnTurnQuestionFace(hostSeat) : undefined;
407
+ const parentSpecSeat = detachedSeat?.spec;
408
+ const principal = parentSpecSeat?.principal;
396
409
  const taskScope = ctx.principal ?? d.scope;
397
410
  let script;
398
411
  let registeredDefaultArgs;
@@ -487,8 +500,10 @@ export async function createRunWorkflowTool(d) {
487
500
  },
488
501
  }
489
502
  : governance;
503
+ const childParkSeat = ctx.checkpointStoreForChildren ?? d.parentCheckpointStore;
504
+ const parkStore = checkpointStoreOfSeat(childParkSeat);
490
505
  const scriptFn = (wfCtx) => {
491
- const primitives = buildWorkflowPrimitives(wfCtx, runGovernance, d.onAgentSpawn, principal, ctx.checkpointStoreForChildren ?? d.parentCheckpointStore, d.parentReadFace, d.parentReadDenyPatterns, ctx.handsReadOnly === true || d.parentHandsReadOnly === true, ctx.interactiveTools === false || d.parentInteractiveTools === false);
506
+ const primitives = buildWorkflowPrimitives(wfCtx, runGovernance, d.onAgentSpawn, childParkSeat, d.parentReadFace, d.parentReadDenyPatterns, ctx.handsReadOnly === true || d.parentHandsReadOnly === true, ctx.interactiveTools === false || d.parentInteractiveTools === false);
492
507
  return d.scriptRunner.run({ scriptSource: script, primitives, scriptArgs: effectiveArgs, signal: wfCtx.signal }).then((r) => r.result);
493
508
  };
494
509
  if (ctx.signal?.aborted) {
@@ -503,6 +518,7 @@ export async function createRunWorkflowTool(d) {
503
518
  try {
504
519
  handle = startWorkflow(d.runner, scriptFn, {
505
520
  store: d.store,
521
+ ...(parkStore !== undefined ? { checkpointStore: parkStore } : {}),
506
522
  ...(d.agents !== undefined ? { agents: d.agents } : {}),
507
523
  ...(d.builtinAgents !== undefined ? { builtinAgents: d.builtinAgents } : {}),
508
524
  name: meta.name,
@@ -548,7 +564,9 @@ export async function createRunWorkflowTool(d) {
548
564
  ...(d.parentModel !== undefined ? { defaultModel: d.parentModel } : {}),
549
565
  ...(d.parentThinking !== undefined ? { defaultThinking: d.parentThinking } : {}),
550
566
  ...(d.parentGetApiKeyAndHeaders !== undefined ? { defaultGetApiKeyAndHeaders: d.parentGetApiKeyAndHeaders } : {}),
551
- ...(hostDurableApproval !== undefined && d.store !== undefined ? { defaultDurableApproval: { ...hostDurableApproval } } : {}),
567
+ ...(parentSpecSeat !== undefined ? { parentSpecSeat } : {}),
568
+ ...(detachedSeat?.internalsFlag.questionFaceStripped === true || ctx.questionFaceStripped === true || d.parentQuestionFaceStripped === true ? { questionFaceStripped: true } : {}),
569
+ ...(hostDurableApproval !== undefined && d.store !== undefined && parkStore !== undefined ? { defaultDurableApproval: { ...hostDurableApproval } } : {}),
552
570
  ...(resumeFromRunId !== undefined && d.parkedResume !== undefined && d.parkedResume(resumeFromRunId) !== undefined ? { parkedResume: d.parkedResume(resumeFromRunId) } : {}),
553
571
  ...(parentCenterArtifactDigest !== undefined ? { parentCenterArtifactDigest } : {}),
554
572
  ...(parentCenterSourceRevision !== undefined ? { parentCenterSourceRevision } : {}),
@@ -662,7 +680,7 @@ export async function createRunWorkflowTool(d) {
662
680
  const carries = pollExpr
663
681
  ? ` A terminal ${pollExpr} reply carries its result AND per-agent rows — read them${journalRef !== undefined ? ` (full journal: ${journalRef})` : ""} before assuming an empty or unexpected result.`
664
682
  : "";
665
- if (d.oneShot === true) {
683
+ if (parentSpecSeat?.oneShot === true) {
666
684
  return blockingPollExpr
667
685
  ? `This is a ONE-SHOT submission (e.g. headless \`-p\`) — there is no later turn for a background notification to land in, so do NOT end your turn expecting one. Actively wait instead: ${blockingPollExpr}. If it is still running after the wait, wait again (bounded) rather than ending the turn, or write out your best available answer now if you are near your own time budget.${carries}`
668
686
  : "This is a one-shot submission (e.g. headless `-p`) and no poll path is available — the workflow's outcome may not be recoverable after this turn ends.";
@@ -34,9 +34,11 @@ export interface WorkflowGovernance {
34
34
  * `agent` primitive is GOVERNED when `governance` is set (LLM-authored), else a trusted pass-through.
35
35
  * The host's model and thinking are NOT injected here: both are seats the launch site (`workflow.ts`,
36
36
  * `withWorkflowChildSeats`) fills AFTER the agentType fold, so a definition's own value is the explicit rung
37
- * — filling them here ran ahead of the fold and made the fold's "when unset" guard permanently false.
37
+ * — filling them here ran ahead of the fold and made the fold's "when unset" guard permanently false. The parent
38
+ * SPEC seat (principal, oneShot, clientContext, the question face, the fs-fence widening, envFacts, the persistence
39
+ * statement) is applied there for the same reason (`applyParentSpecSeat`).
38
40
  */
39
- export declare function buildWorkflowPrimitives(ctx: WorkflowRunContext, governance?: WorkflowGovernance, onAgentSpawn?: (handle: WorkflowAgentHandle) => void, parentPrincipal?: string,
41
+ export declare function buildWorkflowPrimitives(ctx: WorkflowRunContext, governance?: WorkflowGovernance, onAgentSpawn?: (handle: WorkflowAgentHandle) => void,
40
42
  /** The host run's RESOLVED checkpoint seat — the store object it parks in, else the word `"disabled"`.
41
43
  * Every agent this workflow spawns inherits it; see the injection below. */
42
44
  parentCheckpointStore?: CheckpointStore | "disabled",
@@ -65,7 +65,7 @@ function formatResourceClampNote(notes) {
65
65
  const parts = notes.map((n) => `${n.field}: requested ${n.requested === undefined ? "unset" : n.requested} → applied ${n.applied}`);
66
66
  return `workflow governance tightened this agent's resource limits (${parts.join("; ")})`;
67
67
  }
68
- export function buildWorkflowPrimitives(ctx, governance, onAgentSpawn, parentPrincipal, parentCheckpointStore, parentReadFace, parentReadDenyPatterns, parentHandsReadOnly, parentInteractiveToolsOff) {
68
+ export function buildWorkflowPrimitives(ctx, governance, onAgentSpawn, parentCheckpointStore, parentReadFace, parentReadDenyPatterns, parentHandsReadOnly, parentInteractiveToolsOff) {
69
69
  const agent = (spec, opts) => {
70
70
  if (typeof spec === "string")
71
71
  spec = { objective: spec };
@@ -74,9 +74,6 @@ export function buildWorkflowPrimitives(ctx, governance, onAgentSpawn, parentPri
74
74
  const childSpec = governance
75
75
  ? buildGovernedChildSpec(spec, effectiveBaseline(governance.baseline), governance.models, governance.caps, (notes) => ctx.log(formatResourceClampNote(notes)), governance.onNotice)
76
76
  : { ...spec };
77
- if (childSpec.principal === undefined && parentPrincipal !== undefined) {
78
- childSpec.principal = parentPrincipal;
79
- }
80
77
  if (parentCheckpointStore !== undefined && (parentCheckpointStore === "disabled" || childSpec.checkpointStore === undefined)) {
81
78
  childSpec.checkpointStore = parentCheckpointStore;
82
79
  }
@@ -4,6 +4,17 @@ export type WorkflowRunStatus = "running" | "completed" | "failed";
4
4
  * agent durably paused at an approval gate and the run suspended on it (the row carries the token, see
5
5
  * {@link WorkflowAgentRun.parkedCheckpointToken}); a phase or group never parks (a parked agent ends the run). */
6
6
  export type WorkflowItemStatus = "running" | "completed" | "failed" | "parked";
7
+ /** The arm a `workflow.park_truth_unreadable` resume refusal fired on (`detail.reason`): the prior run's record could not
8
+ * be read (`store_threw`), is absent under this scope (`record_missing`), is not terminal (`record_not_terminal`) or
9
+ * carries no `parks` array (`parks_unreadable`); a candidate's checkpoint could not be read (`checkpoint_store_threw`);
10
+ * or the record/journal name parks while this workflow holds no checkpoint seat to prove them (`capability_not_armed`).
11
+ * Registered in docs/CLOSED-SETS.md with a mint obligation: every throw site spells its word. */
12
+ export declare const PARK_TRUTH_UNREADABLE_REASONS: readonly ["store_threw", "record_missing", "record_not_terminal", "parks_unreadable", "checkpoint_store_threw", "capability_not_armed"];
13
+ export type ParkTruthUnreadableReason = (typeof PARK_TRUTH_UNREADABLE_REASONS)[number];
14
+ /** What the checkpoint store said about a parked ordinal's token when a resume carried no acknowledgement for it
15
+ * (`workflow.park_not_pending`, `detail.status`): the row's own word, or `absent` when the store holds no row. */
16
+ export declare const PARK_NOT_PENDING_STATUSES: readonly ["resolved", "expired", "absent"];
17
+ export type ParkNotPendingStatus = (typeof PARK_NOT_PENDING_STATUSES)[number];
7
18
  export interface WorkflowPhase {
8
19
  title: string;
9
20
  /** F7/B7 (CC pretty.js:446478): a phase PRE-REGISTERED from `meta.phases` starts as `"pending"` — the plan
@@ -125,10 +136,11 @@ export interface WorkflowAgentRun {
125
136
  * #642 — the durable-approval checkpoint token this agent is PARKED on (`status: "parked"` only): the child
126
137
  * durably paused at an approval gate under the host's forwarded `durableApproval`, the run recorded the
127
138
  * park here and suspended. The mirror of the background agent row's `parkedCheckpointToken`, and the
128
- * workflow-origin JOIN a host routes a parked approval by: a checkpoint whose `sourceTaskId` equals this
129
- * row's {@link sessionId} is a workflow child's park, and this token is the same row's redemption key —
130
- * the checkpoint row itself carries no workflow key. It is the resume CAPABILITY (never log it or put it
131
- * in a URL); a durable row is its home exactly as on the background lane. Absent on every other status.
139
+ * workflow-origin JOIN a host routes a parked approval by: the checkpoint row whose `sessionId` equals this
140
+ * row's {@link sessionId} and whose token equals this one is a workflow child's park (the engine's own
141
+ * truth read binds on the same two facts `WorkflowRun.parks`); the checkpoint row itself carries no
142
+ * workflow key. It is the resume CAPABILITY (never log it or put it in a URL); a durable row is its home
143
+ * exactly as on the background lane. Absent on every other status.
132
144
  */
133
145
  parkedCheckpointToken?: string;
134
146
  /**
@@ -374,6 +386,24 @@ export interface WorkflowRun {
374
386
  divergedAtOrdinal?: number;
375
387
  divergedReason?: string;
376
388
  };
389
+ /**
390
+ * Every park this run is RESPONSIBLE for: its own (written at the park) and the ones it inherited from the run
391
+ * it resumed and did not settle (written at resume admission). KEYS ONLY — the truth of a park is the checkpoint
392
+ * store (`get(token).status`), never this list: a listed token may be resolved, expired or reaped, and the next
393
+ * resume reads the store for every entry. Present on every record this engine writes (`[]` when there is none)
394
+ * EXCEPT a record whose resume admission refused before its inherited set was established (deliberately absent:
395
+ * not a resume base). It is an ADMISSION INPUT of the next resume, so a store must project it verbatim and keep
396
+ * it through any size degrade; a reader treats absence as a state (an older engine's record, a stripped
397
+ * projection), never as `[]`. `token` is the same capability as {@link WorkflowAgentRun.parkedCheckpointToken}
398
+ * (never log it, never put it in a URL); `originRunId` is the run whose journal holds the `parked` entry for
399
+ * `callKey` (the re-park material).
400
+ */
401
+ parks?: Array<{
402
+ callKey: string;
403
+ sessionId: string;
404
+ token: string;
405
+ originRunId: string;
406
+ }>;
377
407
  /** RB-243: how many agent results were NOT journaled because they exceeded the per-entry size
378
408
  * cap ({@link MAX_JOURNAL_RESULT_BYTES}) — each skip also logs and journals a tombstone. Additive
379
409
  * observation; absent when 0. */
@@ -1,3 +1,5 @@
1
+ export const PARK_TRUTH_UNREADABLE_REASONS = ["store_threw", "record_missing", "record_not_terminal", "parks_unreadable", "checkpoint_store_threw", "capability_not_armed"];
2
+ export const PARK_NOT_PENDING_STATUSES = ["resolved", "expired", "absent"];
1
3
  export class WorkflowBudgetExceededError extends Error {
2
4
  spent;
3
5
  total;
@@ -1,7 +1,8 @@
1
1
  import type { TSchema } from "typebox";
2
2
  import type { InheritedGate, RunnerSelfSeat } from "../core/runner/contracts.js";
3
- import type { CheckpointToken, ResumeOutcome } from "../core/checkpoint-store.js";
3
+ import type { CheckpointStore, CheckpointToken, ResumeOutcome } from "../core/checkpoint-store.js";
4
4
  import type { AgentDefinition, TaskEvent, TaskResult, TaskSpec, ThinkingLevel } from "../core/types.js";
5
+ import { type ParentSpecSeat } from "../core/parent-spec-seat.js";
5
6
  import type { WorkflowRunStore } from "../core/workflow-run-store.js";
6
7
  import type { WorkflowJournalStore, ResumeClaimArgs } from "../core/workflow-journal-store.js";
7
8
  import type { WorkflowRun, WorkflowEvent } from "./workflow-types.js";
@@ -123,9 +124,7 @@ export declare class WorkflowJournalIncompatibleError extends Error {
123
124
  readonly fromRunId: string;
124
125
  readonly ordinal: number;
125
126
  readonly code = "workflow.journal_incompatible";
126
- constructor(fromRunId: string, ordinal: number,
127
- /** #642: an alternative reason clause (the parked-row cross-check); absent ⇒ the no-terminal-cause wording. */
128
- reason?: string);
127
+ constructor(fromRunId: string, ordinal: number);
129
128
  }
130
129
  /**
131
130
  * A TRUSTED, run-scoped internal channel carrying the workflow **nesting depth** across a process boundary
@@ -292,11 +291,16 @@ export interface WorkflowRunContext {
292
291
  * the checkpoint token the wa* row is parked on (the row's `parkedCheckpointToken`, the redemption key), the
293
292
  * caller's decision for it (the same {@link ResumeOutcome} a top-level `runner.resume` takes), and the optional
294
293
  * cross-process re-supply of the checkpoint's opaque parent constraints. The token is matched by string equality
295
- * against the journaled parked entry — an entry whose token no decision names re-parks.
294
+ * against the parked ordinal's token — an ordinal whose token no entry names re-parks.
295
+ *
296
+ * `outcome` is OPTIONAL. `{ token, outcome }` is a DECISION: a pending checkpoint is driven with it; one the store no
297
+ * longer calls pending is settled (the acknowledgement is implied). `{ token }` alone is an ACKNOWLEDGEMENT: it settles an
298
+ * ordinal whose checkpoint is resolved / expired / absent as a failed row (`workflow.park_not_pending`) so the script
299
+ * continues; if the re-read finds the checkpoint pending again it RE-PARKS — an acknowledgement never authorizes a drive.
296
300
  */
297
301
  export interface WorkflowParkedResume {
298
302
  token: CheckpointToken;
299
- outcome: ResumeOutcome;
303
+ outcome?: ResumeOutcome;
300
304
  inheritedGate?: InheritedGate;
301
305
  }
302
306
  export interface RunWorkflowOptions {
@@ -468,9 +472,37 @@ export interface RunWorkflowOptions {
468
472
  * parked child on with the caller's decision ({@link parkedResume}). Tighten-only: a park capability,
469
473
  * never a widening — the decision stays with a person. REQUIRES {@link store} (the wa* row's durable home;
470
474
  * refused loudly at entry without it). Threaded by the Workflow tool from the host's trusted seat; a
471
- * directly-started workflow passes its own. NOT call identity.
475
+ * directly-started workflow passes its own. NOT call identity. REQUIRES {@link checkpointStore} as well: a
476
+ * durable approval whose checkpoint this workflow cannot read back is a park no resume can prove.
472
477
  */
473
478
  defaultDurableApproval?: TaskSpec["durableApproval"];
479
+ /**
480
+ * The HOST run's parent SPEC seat ({@link import("../core/parent-spec-seat.js").ParentSpecSeat}: principal / oneShot /
481
+ * clientContext / the frozen question face / the fs-fence widening / envFacts / the declared persistence statement),
482
+ * applied onto every spawned agent at the launch site AFTER the agentType fold by {@link applyParentSpecSeat} — the
483
+ * Task delegation lane's one law: a value the child spec carries (script, definition, baseline) WINS, the seat FILLS
484
+ * an unset one, the two removals (`oneShot: true`, `memoryPersistenceCapable: false`) land unconditionally. Threaded
485
+ * by the Workflow tool from the host's seat; a directly-started workflow passes its own. NOT call identity (host
486
+ * wiring, like the checkpoint seat). Absent ⇒ nothing is applied. The seat the Workflow tool threads carries NO
487
+ * `onQuestion`: the tool strips the host's per-request face (every agent it spawns outlives the launching request)
488
+ * and says so through {@link questionFaceStripped}; a directly-started workflow passes what its own lifetime allows.
489
+ */
490
+ parentSpecSeat?: ParentSpecSeat;
491
+ /** The engine stripped the spawn turn's per-request question face from the seat above (pair-produced with the strip,
492
+ * `stripSpawnTurnQuestionFace`); rides every spawned agent's internals as `RunInternals.questionFaceStripped` — the
493
+ * wiring manifest's `question.wired: "stripped_bg_lane"` and the posture door's exemption read it. */
494
+ questionFaceStripped?: true;
495
+ /**
496
+ * The checkpoint store this run's children park in — the RESOLVED seat object itself (the same value the Workflow
497
+ * tool injects onto every child spec; a directly-started workflow passes the store its children park in). Its
498
+ * presence ARMS the park lane: a resume then proves every parked ordinal against `get(token)` before anything is
499
+ * dispatched (`WorkflowRun.parks` supplies the keys), and a child whose effective `checkpointStore` is a DIFFERENT
500
+ * object is refused at spawn (`config.invalid_checkpoint_store` — identity, not duck-typing: a caller-built `{get}`
501
+ * wrapper is not the seat). REQUIRES {@link store} (the park's durable row). Absent ⇒ the lane is not armed: a
502
+ * resume of a run that recorded parks is refused (`workflow.park_truth_unreadable` / `capability_not_armed`), a run
503
+ * without parks resumes as before. NOT call identity (deployment wiring, like the store seats).
504
+ */
505
+ checkpointStore?: CheckpointStore;
474
506
  /**
475
507
  * #642 — the decisions a resume ({@link resumeFromRunId}) carries for PARKED ordinals of the prior run: at
476
508
  * an ordinal whose journal entry is `parked` (a matching call key), the run drives the parked child's own