@sema-agent/core 7.49.5 → 7.50.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 (200) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/dist/agents/observer.js +3 -10
  3. package/dist/agents/subagent-steps.d.ts +6 -14
  4. package/dist/agents/subagent-steps.js +3 -17
  5. package/dist/brain/stream-shared.d.ts +1 -1
  6. package/dist/core/allow-entry.d.ts +1 -1
  7. package/dist/core/allow-entry.js +1 -1
  8. package/dist/core/ask-origin.d.ts +15 -11
  9. package/dist/core/ask-origin.js +6 -14
  10. package/dist/core/auto-mode-prompt.js +6 -2
  11. package/dist/core/checkpoint-store.d.ts +6 -4
  12. package/dist/core/checkpoint-store.js +1 -1
  13. package/dist/core/context-edit.d.ts +2 -2
  14. package/dist/core/decision-receipt.d.ts +2 -2
  15. package/dist/core/decision-receipt.js +30 -11
  16. package/dist/core/delegation-frames.d.ts +66 -18
  17. package/dist/core/delegation-frames.js +22 -0
  18. package/dist/core/engine-notice.d.ts +7 -5
  19. package/dist/core/frame-settlement.d.ts +6 -1
  20. package/dist/core/gate-fold.js +34 -19
  21. package/dist/core/gate-lanes.js +15 -13
  22. package/dist/core/gate-outcome.d.ts +2 -2
  23. package/dist/core/governance-codes.js +2 -0
  24. package/dist/core/hooks.d.ts +28 -20
  25. package/dist/core/human-input-projection.js +2 -0
  26. package/dist/core/lsp-diagnostics.d.ts +3 -0
  27. package/dist/core/lsp-diagnostics.js +6 -0
  28. package/dist/core/lsp-session.d.ts +39 -17
  29. package/dist/core/lsp-session.js +118 -58
  30. package/dist/core/lsp.d.ts +83 -3
  31. package/dist/core/lsp.js +146 -16
  32. package/dist/core/mcp.js +2 -1
  33. package/dist/core/media-byte-cap.d.ts +14 -0
  34. package/dist/core/media-byte-cap.js +15 -3
  35. package/dist/core/memory-engine/consolidation-driver.d.ts +23 -1
  36. package/dist/core/memory-engine/consolidation-driver.js +54 -6
  37. package/dist/core/memory-engine/consolidation-write-gate.d.ts +46 -0
  38. package/dist/core/memory-engine/consolidation-write-gate.js +82 -0
  39. package/dist/core/memory-engine/consolidation.d.ts +17 -0
  40. package/dist/core/memory-engine/consolidation.js +1 -0
  41. package/dist/core/memory-engine/distiller.d.ts +8 -2
  42. package/dist/core/memory-engine/distiller.js +8 -6
  43. package/dist/core/memory-engine/engine.d.ts +37 -4
  44. package/dist/core/memory-engine/engine.js +127 -38
  45. package/dist/core/memory-engine/file-backend.d.ts +8 -3
  46. package/dist/core/memory-engine/file-backend.js +44 -16
  47. package/dist/core/memory-engine/index.d.ts +2 -2
  48. package/dist/core/memory-engine/index.js +1 -1
  49. package/dist/core/memory-engine/landing-admission.d.ts +65 -0
  50. package/dist/core/memory-engine/landing-admission.js +68 -0
  51. package/dist/core/memory-engine/types.d.ts +23 -0
  52. package/dist/core/mode-policy.d.ts +3 -2
  53. package/dist/core/mode-policy.js +2 -0
  54. package/dist/core/permission-rule-model.d.ts +19 -13
  55. package/dist/core/permission-rule-model.js +7 -4
  56. package/dist/core/permission-rule-provider.d.ts +11 -0
  57. package/dist/core/permission-rules.d.ts +1 -1
  58. package/dist/core/permission-rules.js +5 -2
  59. package/dist/core/persisted-rule-arms.d.ts +15 -7
  60. package/dist/core/persisted-rule-arms.js +13 -6
  61. package/dist/core/reminder-mint.d.ts +5 -0
  62. package/dist/core/reminder-mint.js +1 -0
  63. package/dist/core/retired-keys.d.ts +8 -0
  64. package/dist/core/retired-keys.js +4 -0
  65. package/dist/core/rule-lane-reads.d.ts +4 -4
  66. package/dist/core/rule-lane-reads.js +10 -1
  67. package/dist/core/runner/construction-doors.d.ts +10 -4
  68. package/dist/core/runner/construction-doors.js +25 -2
  69. package/dist/core/runner/contracts.d.ts +20 -3
  70. package/dist/core/runner/env-capability-census.js +1 -1
  71. package/dist/core/runner/gate-exit.js +2 -1
  72. package/dist/core/runner/memory-consolidation-driver.d.ts +6 -4
  73. package/dist/core/runner/memory-consolidation-driver.js +5 -2
  74. package/dist/core/runner/memory-consolidation-write-judge.d.ts +17 -0
  75. package/dist/core/runner/memory-consolidation-write-judge.js +14 -0
  76. package/dist/core/runner/permission-rule-lanes.d.ts +16 -22
  77. package/dist/core/runner/permission-rule-lanes.js +13 -43
  78. package/dist/core/runner/person-path-rows.d.ts +244 -0
  79. package/dist/core/runner/person-path-rows.js +387 -0
  80. package/dist/core/runner/policy-throw.d.ts +34 -0
  81. package/dist/core/runner/policy-throw.js +25 -0
  82. package/dist/core/runner/prepare-acquire-reconcile.js +8 -1
  83. package/dist/core/runner/prepare-artifact.d.ts +5 -3
  84. package/dist/core/runner/prepare-artifact.js +2 -8
  85. package/dist/core/runner/prepare-ask-lane.d.ts +2 -1
  86. package/dist/core/runner/prepare-ask-lane.js +14 -16
  87. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -3
  88. package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
  89. package/dist/core/runner/prepare-context-lane.js +2 -2
  90. package/dist/core/runner/prepare-gate-stations.d.ts +3 -3
  91. package/dist/core/runner/prepare-gate-stations.js +1 -1
  92. package/dist/core/runner/prepare-hands-readface.d.ts +19 -10
  93. package/dist/core/runner/prepare-hands-readface.js +57 -43
  94. package/dist/core/runner/prepare-lsp.d.ts +15 -13
  95. package/dist/core/runner/prepare-lsp.js +11 -11
  96. package/dist/core/runner/prepare-policy-chain.d.ts +8 -4
  97. package/dist/core/runner/prepare-policy-chain.js +11 -10
  98. package/dist/core/runner/prepare-run-refs.js +1 -1
  99. package/dist/core/runner/prepare-task.js +24 -16
  100. package/dist/core/runner/prepare-turn-wiring.d.ts +13 -6
  101. package/dist/core/runner/prepare-turn-wiring.js +19 -8
  102. package/dist/core/runner/read-root-grant.d.ts +1 -25
  103. package/dist/core/runner/read-root-grant.js +1 -17
  104. package/dist/core/runner/retired-runner-deps.d.ts +2 -2
  105. package/dist/core/runner/run-brain-sinks.d.ts +1 -5
  106. package/dist/core/runner/run-brain-sinks.js +2 -4
  107. package/dist/core/runner/run-harness-handlers.js +5 -4
  108. package/dist/core/runner/run-identity-wiring.d.ts +4 -4
  109. package/dist/core/runner/run-identity-wiring.js +10 -1
  110. package/dist/core/runner/run-leg.d.ts +1 -1
  111. package/dist/core/runner/run-leg.js +22 -9
  112. package/dist/core/runner/run-settle-and-teardown.d.ts +0 -4
  113. package/dist/core/runner/run-settle-and-teardown.js +7 -4
  114. package/dist/core/runner/run-terminal-adoption.d.ts +1 -1
  115. package/dist/core/runner/run-terminal-adoption.js +1 -1
  116. package/dist/core/runner/run-turn-boundary.js +2 -2
  117. package/dist/core/runner/runtask.js +8 -8
  118. package/dist/core/runner/session-file-state-replay.d.ts +14 -4
  119. package/dist/core/runner/session-file-state-replay.js +8 -0
  120. package/dist/core/runner/stream-steer-verb.js +3 -0
  121. package/dist/core/runner/tool-end-body.d.ts +5 -4
  122. package/dist/core/runner/tool-end-body.js +4 -4
  123. package/dist/core/runner/tool-output-projection.d.ts +6 -4
  124. package/dist/core/runner/tool-output-projection.js +66 -47
  125. package/dist/core/runner-deps.d.ts +6 -3
  126. package/dist/core/shared-memory/types.d.ts +2 -2
  127. package/dist/core/shell-read-silence.d.ts +23 -0
  128. package/dist/core/shell-read-silence.js +18 -0
  129. package/dist/core/synthetic-read-verdict.d.ts +80 -21
  130. package/dist/core/synthetic-read-verdict.js +89 -18
  131. package/dist/core/task-event.d.ts +113 -25
  132. package/dist/core/task-spec.d.ts +44 -0
  133. package/dist/core/task-tool-shape.d.ts +1 -1
  134. package/dist/core/tool-catalog-entries.js +16 -2
  135. package/dist/core/tool-policy.d.ts +25 -15
  136. package/dist/core/tool-policy.js +9 -13
  137. package/dist/core/trace.d.ts +3 -2
  138. package/dist/core/types.d.ts +3 -3
  139. package/dist/core/types.js +1 -1
  140. package/dist/core/untrusted-text.d.ts +2 -2
  141. package/dist/core/user-attachment.d.ts +164 -0
  142. package/dist/core/user-attachment.js +437 -0
  143. package/dist/engine/compaction/compaction.js +10 -3
  144. package/dist/engine/compaction/utils.js +6 -0
  145. package/dist/engine/execution-env/node-execution-env.d.ts +19 -1
  146. package/dist/engine/execution-env/node-execution-env.js +125 -0
  147. package/dist/engine/harness/agent-harness.d.ts +12 -2
  148. package/dist/engine/harness/agent-harness.js +15 -3
  149. package/dist/engine/harness/types.d.ts +21 -0
  150. package/dist/engine/llm/content-block-render.d.ts +15 -0
  151. package/dist/engine/llm/content-block-render.js +10 -0
  152. package/dist/engine/llm/index.d.ts +1 -0
  153. package/dist/engine/llm/index.js +1 -0
  154. package/dist/engine/llm/types.d.ts +80 -4
  155. package/dist/engine/llm/types.js +43 -1
  156. package/dist/engine/session/import-validate.js +2 -0
  157. package/dist/index.d.ts +6 -4
  158. package/dist/index.js +2 -1
  159. package/dist/internal/harness-types.d.ts +1 -1
  160. package/dist/internal/llm.d.ts +2 -2
  161. package/dist/internal/llm.js +1 -1
  162. package/dist/orchestration/workflow.d.ts +4 -5
  163. package/dist/orchestration/workflow.js +2 -2
  164. package/dist/prompts/default.d.ts +1 -1
  165. package/dist/tools/artifact/artifact-tool.js +1 -1
  166. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  167. package/dist/tools/fs/dir-entries.d.ts +4 -10
  168. package/dist/tools/fs/dir-entries.js +4 -11
  169. package/dist/tools/fs/file-read-check.js +3 -3
  170. package/dist/tools/fs/fs-pdf.js +2 -4
  171. package/dist/tools/fs/fs-read.d.ts +47 -4
  172. package/dist/tools/fs/fs-read.js +63 -19
  173. package/dist/tools/fs/fs-search-tools.d.ts +3 -3
  174. package/dist/tools/fs/fs-search-tools.js +7 -2
  175. package/dist/tools/fs/fs-write.d.ts +1 -1
  176. package/dist/tools/fs/fs-write.js +7 -6
  177. package/dist/tools/fs/index.d.ts +7 -1
  178. package/dist/tools/fs/index.js +56 -34
  179. package/dist/tools/fs/read-deny-home.d.ts +19 -1
  180. package/dist/tools/fs/read-deny-home.js +32 -22
  181. package/dist/tools/fs/read-deny.d.ts +14 -0
  182. package/dist/tools/fs/read-deny.js +8 -0
  183. package/dist/tools/fs/repo-map.d.ts +3 -2
  184. package/dist/tools/fs/repo-map.js +11 -3
  185. package/dist/tools/fs/safety.d.ts +41 -2
  186. package/dist/tools/fs/safety.js +12 -3
  187. package/dist/tools/fs/shell-read-check.d.ts +12 -3
  188. package/dist/tools/fs/shell-read-check.js +44 -24
  189. package/dist/tools/fs/shell-read-device.d.ts +1 -1
  190. package/dist/tools/fs/shell-read-face.d.ts +15 -0
  191. package/dist/tools/fs/shell-read-face.js +5 -0
  192. package/dist/tools/fs/shell-read-judge.d.ts +9 -4
  193. package/dist/tools/fs/shell-read-judge.js +1 -1
  194. package/dist/tools/loop-tick.d.ts +2 -2
  195. package/package.json +3 -1
  196. package/test/export-surface.snapshot.json +39 -1
  197. package/wire-changes/core@7.50.0.json +1699 -0
  198. package/wire-changes/core@7.50.1.json +65 -0
  199. package/dist/core/runner/persisted-path-rows.d.ts +0 -88
  200. package/dist/core/runner/persisted-path-rows.js +0 -108
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * PrepareTask's LSP phase, verbatim from the driver: the manager fold (spec > deps), the
3
- * LSP tool mount over the per-task env with its git-ignore filter, the diagnostics lane behind its four
4
- * preconditions (a manager whose sessions feed a registry, write-capable hands, not opted out), the run-scoped
3
+ * LSP tool mount over the per-task env with its git-ignore filter and the leg's read face, the diagnostics lane behind its
4
+ * four preconditions (a manager whose sessions feed a registry, write-capable hands, not opted out), the run-scoped
5
5
  * registry key, and the edit nudge (raw path → the SAME resolution the tool leg uses → registry reset +
6
- * session didChange). No manager, or no hands (the manifest still reports the seat, `mounted: false`), ⇒ nothing mounts and
7
- * both lane seats are undefined. The interface is the dependency list the segment had implicitly.
6
+ * session didChange through the read face). No manager, or no read face (a hands-less leg; the manifest still reports the
7
+ * seat, `mounted: false`), ⇒ nothing mounts and both lane seats are undefined. The interface is the dependency list the
8
+ * segment had implicitly.
8
9
  *
9
10
  * SYNCHRONOUS FUNCTION, SYNCHRONOUS CALL: the stretch has no await, so the phase adds no yield between the
10
11
  * fork-governance note before it and the memory trio's occupancy read after it (a stretch
@@ -12,9 +13,9 @@
12
13
  * Read-stability of the host handles for the call: {@link RunInternals} (`@contract prepare.deps-read-stable`).
13
14
  */
14
15
  import type { ExecutionEnv } from "../../internal/harness.js";
16
+ import { type LspListedWithholding, type LspReadFace } from "../lsp.js";
15
17
  import type { LspDiagnosticsRegistry } from "../lsp-diagnostics.js";
16
18
  import type { RunnerDeps, TaskSpec } from "../types.js";
17
- import type { Prepared } from "./contracts.js";
18
19
  import { RosterBuilder } from "../tool-roster.js";
19
20
  export interface PrepareLspInput {
20
21
  /** borrowed-readonly — the REBOUND spec. Read: `lspManager` (the per-task manager, outranks the deployment's),
@@ -25,18 +26,16 @@ export interface PrepareLspInput {
25
26
  /** borrowed-readonly — the run's resolved env: the tool's in-env server and git-ignore filter, and the
26
27
  * session lookup the nudge performs. */
27
28
  executionEnv: ExecutionEnv;
28
- /** borrowed-readonly — the SETTLED task root: the tool's git-ignore root, and the nudge's resolution base when
29
- * no cwd is tracked. */
29
+ /** borrowed-readonly — the SETTLED task root: the tool's git-ignore root. */
30
30
  taskRootFinal: string;
31
- /** borrowed-readonly — whether a real fs env is present (the tool mount's and the lane's hands precondition). */
32
- handsEnabled: boolean;
31
+ /** borrowed-readonly — the leg's read face (the hands phase's root, read roots, deny table, containment face, tracked
32
+ * cwd and file read station admission), present exactly when hands mounted: LSP mounts only under it, and the tool,
33
+ * the nudge and the diagnostics lane read every file through it. */
34
+ readFace: LspReadFace | undefined;
33
35
  /** borrowed-readonly — the acquired session id: the run's key into the deployment-shared registry. */
34
36
  sessionId: string;
35
- /** borrowed-readonly — the tracked-cwd cell the hands band writes; the nudge READS `current` per call as its
36
- * resolution base (identity is the contract — the band's `cd` handling writes this exact cell). */
37
- handsCwdRef: Prepared["cwdRef"];
38
37
  /** borrowed-mutable — the run's roster builder (identity is the contract). Writer here: ONE mount (the LSP tool)
39
- * when a manager exists and the leg has hands. */
38
+ * when a manager and a read face exist. */
40
39
  roster: RosterBuilder;
41
40
  /** borrowed-mutable — the env-hand membership set the read-posture observer projects; writer here: `add("LSP")`
42
41
  * on the mount. */
@@ -48,6 +47,9 @@ export interface PrepareLspResult {
48
47
  lspDiagnostics: LspDiagnosticsRegistry | undefined;
49
48
  /** owned — the edit nudge (raw path in), or undefined when the lane is not live. */
50
49
  nudgeLspOnEdit: ((rawPath: string) => void) | undefined;
50
+ /** owned — the files of a drain the read face withholds (`lspListedWithheld`: every view, fail-closed; kept files
51
+ * absent), or undefined when the lane is not live. */
52
+ withheldDiagnosticsOf: ((uris: readonly string[]) => Promise<ReadonlyMap<string, LspListedWithholding>>) | undefined;
51
53
  /** borrowed-readonly — the run's registry key (= the session id): one run per session, released at the terminal. */
52
54
  lspRunIdent: string;
53
55
  /** Did a MANAGER seat resolve? The manifest's LSP-section presence condition, from the ONE fold that decided the mount. */ managerWired: boolean;
@@ -1,28 +1,28 @@
1
- import { createLspTool, gitCheckIgnoreFilter, resolveLspPath } from "../lsp.js";
1
+ import { createLspTool, gitCheckIgnoreFilter, lspBaseOf, lspListedWithheld, lspReadGateOf, resolveLspPath } from "../lsp.js";
2
2
  import { pathToUri } from "../lsp-protocol.js";
3
3
  import { RosterBuilder } from "../tool-roster.js";
4
4
  export function prepareLsp(input) {
5
- const { spec, deps, executionEnv, taskRootFinal, handsEnabled, sessionId, handsCwdRef, roster, envHandToolNames } = input;
5
+ const { spec, deps, executionEnv, taskRootFinal, readFace, sessionId, roster, envHandToolNames } = input;
6
6
  const lspManager = spec.lspManager ?? deps.lspManager;
7
- if (lspManager && handsEnabled) {
8
- const lspRoot = taskRootFinal;
9
- roster.mount(createLspTool(lspManager, { isPathIgnored: gitCheckIgnoreFilter(executionEnv, lspRoot), env: executionEnv }), { source: "builtin", mountedBy: "hands" });
7
+ if (lspManager && readFace) {
8
+ roster.mount(createLspTool(lspManager, { isPathIgnored: gitCheckIgnoreFilter(executionEnv, taskRootFinal), env: executionEnv, readFace }), { source: "builtin", mountedBy: "hands" });
10
9
  envHandToolNames.add("LSP");
11
10
  }
12
- const lspDiagnostics = spec.lspDiagnostics !== false && lspManager?.diagnostics !== undefined && handsEnabled && spec.handsReadOnly !== true
11
+ const lspDiagnostics = spec.lspDiagnostics !== false && lspManager?.diagnostics !== undefined && readFace !== undefined && spec.handsReadOnly !== true
13
12
  ? lspManager.diagnostics
14
13
  : undefined;
15
14
  const lspRunIdent = sessionId;
16
- const nudgeLspOnEdit = lspDiagnostics
15
+ const nudgeLspOnEdit = lspDiagnostics && readFace
17
16
  ? (rawPath) => {
18
- const baseDir = handsCwdRef?.current ?? taskRootFinal;
19
- const filePath = resolveLspPath(rawPath, baseDir);
17
+ const filePath = resolveLspPath(rawPath, lspBaseOf(readFace));
20
18
  lspDiagnostics.fileEdited(lspRunIdent, pathToUri(filePath));
19
+ const gate = lspReadGateOf(executionEnv, readFace);
21
20
  void lspManager
22
21
  .sessionFor(filePath, undefined, executionEnv)
23
- .then((session) => session?.notifyFileChanged?.(filePath))
22
+ .then((session) => session?.notifyFileChanged?.(filePath, undefined, gate))
24
23
  .catch(() => undefined);
25
24
  }
26
25
  : undefined;
27
- return { lspDiagnostics, nudgeLspOnEdit, lspRunIdent, managerWired: lspManager !== undefined };
26
+ const withheldDiagnosticsOf = lspDiagnostics && readFace ? (uris) => lspListedWithheld(executionEnv, readFace, uris) : undefined;
27
+ return { lspDiagnostics, nudgeLspOnEdit, withheldDiagnosticsOf, lspRunIdent, managerWired: lspManager !== undefined };
28
28
  }
@@ -104,10 +104,11 @@ export interface PreparePolicyChainInput {
104
104
  handsCwdRef: CwdRef | undefined;
105
105
  /** borrowed-readonly — the compiled read-deny judge, or undefined (the offer factory's directory negative control). */
106
106
  readDenyMatcher: ReadDenyMatcher | undefined;
107
- /** borrowed-readonly — the run's one notice for a person's rule store that could not be read (`ruleStoreUnreadableNotice`). */
108
- announceRuleStoreSkipped: (at: "prepare" | "call") => void;
109
- /** borrowed-readonly — the run's one notice for rows the person's store served that were left out (`ruleRowsDroppedNotice`). */
110
- announceRuleRowsDropped: (rows: import("../permission-rule-provider.js").EffectivePermissionRules["droppedRows"]) => void;
107
+ /** borrowed-readonly — the run's one reader of the person's rules (`person-path-rows.ts`): the lanes take each call's
108
+ * pinned read from it. */
109
+ personRows: import("./person-path-rows.js").PersonPathRows;
110
+ /** borrowed-readonly — a reader of the same rows the run's cut does not end (the same notices), for the lane asked after the run. */
111
+ personRowsBeyondRun: import("./person-path-rows.js").PersonPathRows;
111
112
  /** borrowed-readonly — whether the question tool mounted (the lanes' question-tool exclusion). */
112
113
  questionToolMounted: boolean;
113
114
  /** borrowed-readonly — the resolved per-principal entitlements; only `forceDurableGate` (the mandate-park facility and
@@ -240,6 +241,9 @@ export interface PreparePolicyChainResult {
240
241
  grantBindingOf: GrantBindingOf;
241
242
  /** owned — the personal permission-rule lane, or undefined. */
242
243
  permissionRuleLane: PermissionRuleLanes["personal"];
244
+ /** owned — the same two lanes (personal and org) over the reader the run's cut does not end, for the one judgment asked after the
245
+ * run has ended (the synthetic write face). */
246
+ ruleLanesBeyondRun: PermissionRuleLanes;
243
247
  /** owned — the org permission-rule lane (`Prepared.permissionRuleOrg`), or undefined. */
244
248
  permissionRuleOrgLane: PermissionRuleLanes["org"];
245
249
  /** owned — whether the sandbox-admission mode armed (declared isolation with its park prerequisites). */
@@ -23,10 +23,10 @@ import { settleReadRootGrant } from "./read-root-grant.js";
23
23
  import { askGrantShapeOf } from "./inherited-ask-grants.js";
24
24
  import { createPermissionRuleLanes, inheritedAskRuleEvidence, createRuleOffersOf } from "./permission-rule-lanes.js";
25
25
  import { createLiveSessionRules, createSessionRulePolicy } from "./session-rule-policy.js";
26
- import { thrownText } from "../thrown-value.js";
26
+ import { policyThrowLine, reportPolicyThrow } from "./policy-throw.js";
27
27
  import { heldBy, heldValues, seatOf, wireOf } from "../tool-name-readings.js";
28
28
  export async function preparePolicyChain(input) {
29
- const { spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, pathRuleAnchors, headLeads, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, announceRuleRowsDropped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, readFace, permissionMode, scratchpadDir, toolRosterDeltas, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef } = input;
29
+ const { spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, pathRuleAnchors, headLeads, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, personRows, personRowsBeyondRun, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, readFace, permissionMode, scratchpadDir, toolRosterDeltas, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef } = input;
30
30
  const ancestorArbitrations = new Map();
31
31
  const arbitrateInherited = (ask, toolCallId, judged) => {
32
32
  const verdict = arbitrateByMode(permissionMode.current, judged.classification, { origin: judged.origin, ...askMandateMember(ancestorFacts(judged.ask.action === "ask" ? judged.ask : undefined)) });
@@ -321,7 +321,7 @@ export async function preparePolicyChain(input) {
321
321
  const listFacts = { root: taskRootFinal, sessionId, liveCwd: () => handsCwdRef?.current, anchors: pathRuleAnchors.leg };
322
322
  const skillGrantLane = skillGrants.lane(listFacts);
323
323
  const allowEntryLanes = { request: allowedToolTables.request.lane(listFacts), deployment: allowedToolTables.deployment.lane(listFacts) };
324
- const { personal: permissionRuleLane, org: permissionRuleOrgLane } = createPermissionRuleLanes({
324
+ const ruleLaneConfig = {
325
325
  provider: deps.permissionRuleStore,
326
326
  localOwnerDeclared: deps.localOwnerRules === true,
327
327
  principal: spec.principal,
@@ -336,11 +336,10 @@ export async function preparePolicyChain(input) {
336
336
  questionToolName: ASK_USER_QUESTION_TOOL_NAME,
337
337
  onRevisionDefect: (message) => deps.onError?.(new Error(message), { phase: "config", sessionId }),
338
338
  onDisclosure: (message) => emitTrace(deps.tracer, () => ({ kind: "permission.rule_store_unreadable", version: 1, taskId: hostTaskId, message, ts: Date.now() })),
339
- onStoreUnreadable: announceRuleStoreSkipped,
340
- onRowsDropped: announceRuleRowsDropped,
341
- signal: abortController.signal,
342
339
  stripsAllow: (rule, req) => permissionMode.current === "auto" && autoStrippedRule(rule, req),
343
- });
340
+ };
341
+ const { personal: permissionRuleLane, org: permissionRuleOrgLane } = createPermissionRuleLanes({ ...ruleLaneConfig, rows: personRows });
342
+ const ruleLanesBeyondRun = createPermissionRuleLanes({ ...ruleLaneConfig, rows: personRowsBeyondRun });
344
343
  const ruleOffersOf = createRuleOffersOf({
345
344
  laneArmed: permissionRuleLane !== undefined,
346
345
  principal: spec.principal,
@@ -373,9 +372,10 @@ export async function preparePolicyChain(input) {
373
372
  re = refuseOutOfContractDecision(await pol.check(editReq !== undefined ? await editReq : { ...creq, args: editArgs }, csignal ?? abortController.signal));
374
373
  }
375
374
  catch (err) {
375
+ reportPolicyThrow(notifyOwnHookCrash, "an inherited parent policy's re-check of the approved edit", creq, err, csignal ?? abortController.signal);
376
376
  return vetoed({
377
377
  action: "deny",
378
- message: `inherited parent policy re-check of the approved edit errored for "${creq.toolName}": ${thrownText(err)}`,
378
+ message: `inherited parent policy re-check of the approved edit errored for "${creq.toolName}": ${policyThrowLine(err)}`,
379
379
  });
380
380
  }
381
381
  if (re.action === "deny")
@@ -514,9 +514,10 @@ export async function preparePolicyChain(input) {
514
514
  decision = refuseOutOfContractDecision(await pc.policy.check(creq, csignal ?? abortController.signal));
515
515
  }
516
516
  catch (err) {
517
+ reportPolicyThrow(notifyOwnHookCrash, "an inherited parent policy", creq, err, csignal ?? abortController.signal);
517
518
  return {
518
519
  action: "deny",
519
- message: `inherited parent policy errored for "${creq.toolName}": ${thrownText(err)}`,
520
+ message: `inherited parent policy errored for "${creq.toolName}": ${policyThrowLine(err)}`,
520
521
  };
521
522
  }
522
523
  if (decision.action !== "ask")
@@ -678,7 +679,7 @@ export async function preparePolicyChain(input) {
678
679
  return decision;
679
680
  })
680
681
  : foldedPolicy;
681
- return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations };
682
+ return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, ruleLanesBeyondRun, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations };
682
683
  }
683
684
  const advisedPolicyNames = new WeakMap();
684
685
  const ADVISED_KEYS_CAP = 64;
@@ -19,7 +19,7 @@ export function prepareRunRefs(input) {
19
19
  const sinkWired = internals?.onForwardEvent !== undefined;
20
20
  const forwardEvent = sinkWired
21
21
  ? (e) => {
22
- if (e.type === "task_progress")
22
+ if (e.type === "task_progress" || e.type === "task_started")
23
23
  forwardSafely(internals, e);
24
24
  else if (spec.forwardSubagentEvents === true &&
25
25
  (e.type === "text_delta" || e.type === "text_end" || e.type === "reasoning_delta" || e.type === "tool_start" || e.type === "tool_progress" || e.type === "tool_end")) {
@@ -20,7 +20,7 @@ import { modePolicyOf, modeRequestAfterResume, refusePermissionModeDoors } from
20
20
  import { resolveOutputStyleFrame } from "../output-style.js";
21
21
  import { recordedModeSeed } from "../checkpoint-store.js";
22
22
  import { emitTrace } from "../trace.js";
23
- import { persistedPathRowsOfTask, ruleRowsDroppedNotice, ruleStoreUnreadableNotice } from "./persisted-path-rows.js";
23
+ import { personPathRowsOfTask, ruleRowsDroppedNotice, ruleStoreUnreadableNotice } from "./person-path-rows.js";
24
24
  import { STALL_FIRST_BYTE_MS, STALL_FIRST_TOKEN_MS, STALL_IDLE_MS, withBrainCallGuardrail } from "../../brain/timeout.js";
25
25
  import { OFFLOAD_TOOL_NAME } from "../tool-result-store.js";
26
26
  import { OUTPUT_TOOL_NAME, SKILL_TOOL_NAME, createOutputTool } from "./synthetic-tools.js";
@@ -102,6 +102,7 @@ import { AdvertisedWritableDirs } from "./advertised-writable-dirs.js";
102
102
  import { resolveTaskRootCanonical } from "./task-root-canonical.js";
103
103
  import { createStructuredProjector } from "./tool-output-projection.js";
104
104
  import { asThrownError, thrownText } from "../thrown-value.js";
105
+ import { createAttachmentDelivery, refuseUserAttachmentPathsWithoutWorkspace, screenUserAttachments } from "../user-attachment.js";
105
106
  function warnCompactionWindowHazard(tracer, spec, model, compModel, hostTaskId, overlay) {
106
107
  if (compModel === undefined)
107
108
  return;
@@ -291,6 +292,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
291
292
  const permissionModeSeat = refusePermissionModeDoors(spec);
292
293
  const outputStyleFrame = resolveOutputStyleFrame(spec.outputStyle);
293
294
  const allowedTools = screenAllowedToolsValue(spec.allowedTools, "TaskSpec.allowedTools");
295
+ const userAttachmentsSeat = screenUserAttachments(spec.userAttachments, { resumeLeg: resume !== undefined });
294
296
  const declaredModeAtDoor = (() => {
295
297
  const requested = modeRequestAfterResume(permissionModeSeat, recordedModeSeed(resume?.seed.inheritedGate), resume?.outcome);
296
298
  const ceiling = internals?.inheritedGate?.permissionModeCeiling?.current ?? internals?.inheritedGate?.permissionMode;
@@ -369,6 +371,8 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
369
371
  }
370
372
  const rollback = createRollbackStack((e) => deps.onError?.(e, { phase: "config", sessionId }));
371
373
  const { executionEnv, ownedEnvSeat, ownedEnvObservedAt, handsEnabled, taskRootInitial, placement } = await prepareExecutionEnv({ deps, spec, internals, resume, placementRootResolved, sessionId, forgetOnThrow, rollback });
374
+ if (!handsEnabled)
375
+ refuseUserAttachmentPathsWithoutWorkspace(userAttachmentsSeat);
372
376
  const externalContentTargetActive = executionEnv.externalContentTarget === true || resume?.seed.externalContentTarget === true;
373
377
  const abortController = new AbortController();
374
378
  if (spec.signal?.aborted)
@@ -443,19 +447,22 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
443
447
  const mountedMcpNow = mcpPool !== undefined ? () => mountedMcpOf({ declared: installedPreflight.mcp, roster: roster.tools, aggregateNames: new Set(mcp.tools.filter((t) => t.mcpRemoteName === undefined).map((t) => t.name)), pool: mcpPool.pool }) : undefined;
444
448
  const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, runClampSource, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, askSeat: doors.askSeat, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { chainTop, onLeg: onLeg.chained }, checkpointSeat, checkpointScope, toolFaceSnapshot, mountsCallerTool, ...(mountedMcpNow !== undefined ? { mountedMcp: mountedMcpNow } : {}), promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
445
449
  bindPermissionModeSeat(permissionMode);
446
- const announceRuleStoreSkipped = ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId });
447
- const announceRuleRowsDropped = ruleRowsDroppedNotice(deps.onNotice, { sessionId, runId });
448
- const persistedPathRowsRead = persistedPathRowsOfTask({ deps, principal: spec.principal, sessionId, root: taskRootFinal, rootCanonical: taskRootCanonical, leads: headLeads, chainTop, taskId: hostTaskId, handsEnabled, onRowsDropped: announceRuleRowsDropped, signals: [abortController.signal, ...(spec.signal !== undefined ? [spec.signal] : [])], onUnread: announceRuleStoreSkipped });
449
- const persistedPathRows = persistedPathRowsRead === undefined ? { readDirectories: [], denyRows: [] } : await persistedPathRowsRead;
450
+ const personRowNotices = { onUnread: ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId }), onRowsDropped: ruleRowsDroppedNotice(deps.onNotice, { sessionId, runId }) };
451
+ const readerOf = (signals) => personPathRowsOfTask({ deps, notices: personRowNotices, principal: spec.principal, ids: { sessionId, runId, taskId: hostTaskId }, root: taskRootFinal, rootCanonical: taskRootCanonical, leads: headLeads, chainTop, occurrences: toolOccurrences, signals });
452
+ const personRows = readerOf([abortController.signal, ...(spec.signal !== undefined ? [spec.signal] : [])]);
453
+ const personRowsBeyondRun = readerOf([]);
454
+ const primed = handsEnabled ? personRows.prime() : undefined;
455
+ if (primed !== undefined)
456
+ await primed;
450
457
  const policyDenyRows = toolPolicyPathRules([installedToolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)], legAnchors).filter((r) => r.faces.length > 0 && r.behavior === "deny");
451
458
  for (const r of policyDenyRows)
452
459
  if (r.unanchored !== undefined)
453
460
  emitTrace(deps.tracer, () => ({ kind: "permission.rule_store_unreadable", version: 1, taskId: hostTaskId, message: `the deny rule ${r.rule} needs a ${r.unanchored.join(" / ")} base this task does not declare — the shell's file commands and the search tools do not judge it on this leg (the gate asks)`, ts: Date.now() }));
454
- const effectivePathDenyRules = [...policyDenyRows.filter((r) => r.unanchored === undefined), ...persistedPathRows.denyRows];
461
+ const effectivePathDenyRules = policyDenyRows.filter((r) => r.unanchored === undefined);
455
462
  const writeTargetJudgeRef = {};
456
463
  const legExemptRoots = Object.freeze(dataRootSpellings(deps.memoryEngineDir));
457
464
  const legWriteGuard = { exemptRoots: legExemptRoots, rows: toolPolicyWriteGuardRows([installedToolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]) };
458
- const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, askSeat: doors.askSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, parentSpecSeat, runClampSource, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: effectivePathDenyRules }), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, delegated: delegation.isDelegatedChild });
465
+ const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, askSeat: doors.askSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, parentSpecSeat, runClampSource, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => personRows.tablesReady().then(() => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: pathTables?.ruleRows() ?? effectivePathDenyRules })), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, delegated: delegation.isDelegatedChild });
459
466
  const tools = roster.tools;
460
467
  const pausedRef = {};
461
468
  const undeliveredContinuationRef = { current: { parkedSteers: [], orphanTasks: [] } };
@@ -594,9 +601,10 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
594
601
  if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
595
602
  internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
596
603
  }
597
- const handsReadFaceInput = { permissionMode, denyRuleRows: effectivePathDenyRules, headLeads, writeTargetJudge: () => writeTargetJudgeRef.current, persistedReadDirectories: persistedPathRows.readDirectories, handsEnabled, executionEnv, taskRootFinal, taskRootCanonical, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), onFileEdited: noteFileEdited, harnessRef, toolProgressRef, toolOccurrences, ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
604
+ const modelFileReaderSeat = {};
605
+ const handsReadFaceInput = { permissionMode, denyRuleRows: effectivePathDenyRules, headLeads, writeTargetJudge: () => writeTargetJudgeRef.current, personRows, handsEnabled, executionEnv, taskRootFinal, taskRootCanonical, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, modelFileReaderSeat, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), onFileEdited: noteFileEdited, harnessRef, toolProgressRef, toolOccurrences, ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
598
606
  const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
599
- const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, shellReadCheck, shellReadAdmission, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher, envHandToolNames, sealReadStateSeat } = handsReadFace;
607
+ const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, shellReadCheck, shellReadAdmission, additionalRootsCanonical, attachmentRootCanonical, readDenyMatcher, readRoots, pathTables, envHandToolNames, sealReadStateSeat } = handsReadFace;
600
608
  resolvedReadFace = handsReadFace.resolvedReadFace;
601
609
  resolvedWriteFace = handsReadFace.resolvedWriteFace;
602
610
  readDenyAdditionsNormalized = handsReadFace.readDenyAdditionsNormalized;
@@ -623,8 +631,8 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
623
631
  deps.onError?.(new Error(`Fork DENIED for principal "${spec.principal ?? ""}" by runtimeCaps.allowFork=false ` +
624
632
  `(per-principal entitlement governance, not a misconfiguration — Agent(subagent_type:"fork") will refuse honestly)`), { phase: "config", sessionId });
625
633
  }
626
- const { lspDiagnostics, nudgeLspOnEdit, lspRunIdent, managerWired: lspManagerWired } = prepareLsp({ spec, deps, executionEnv, taskRootFinal, handsEnabled, sessionId, handsCwdRef, roster, envHandToolNames });
627
- prepareArtifact({ deps, runId, taskId: hostTaskId, sessionId, agentName: internals?.explicitAgentName, onAsk: frozenOnAsk, toolOccurrences, permissionMode, executionEnv, rootCanonical: attachmentRootCanonical, additionalRootsCanonical: () => [...additionalRootsCanonical, ...additionalReadRootsCanonical], readDenyMatcher, resolvedReadFace, handsCwdRef, roster, firstPartyOffload, envHandToolNames, ...(handsReadFace.artifactStoreRef !== undefined ? { artifactStoreRef: handsReadFace.artifactStoreRef } : {}) });
634
+ const { lspDiagnostics, nudgeLspOnEdit, withheldDiagnosticsOf, lspRunIdent, managerWired: lspManagerWired } = prepareLsp({ spec, deps, executionEnv, taskRootFinal, readFace: attachmentRootCanonical !== undefined ? { rootCanonical: attachmentRootCanonical, roots: readRoots, ready: personRows.tablesReady, ...(handsCwdRef !== undefined ? { cwdRef: handsCwdRef } : {}), ...(readDenyMatcher !== undefined ? { readDeny: readDenyMatcher } : {}), ...(resolvedReadFace !== undefined ? { face: resolvedReadFace } : {}), ...(handsReadFace.readAdmission !== undefined ? { admitted: handsReadFace.readAdmission } : {}) } : undefined, sessionId, roster, envHandToolNames });
635
+ prepareArtifact({ deps, runId, taskId: hostTaskId, sessionId, agentName: internals?.explicitAgentName, onAsk: frozenOnAsk, toolOccurrences, permissionMode, executionEnv, rootCanonical: attachmentRootCanonical, additionalRootsCanonical: readRoots, readDenyMatcher, resolvedReadFace, handsCwdRef, roster, firstPartyOffload, envHandToolNames, ...(handsReadFace.artifactStoreRef !== undefined ? { artifactStoreRef: handsReadFace.artifactStoreRef } : {}) });
628
636
  if (internals?.delegationProvenance !== undefined && resume !== undefined) {
629
637
  const live = internals.delegationProvenance.ref.current;
630
638
  const seed = resume.seed.delegationProvenance;
@@ -650,7 +658,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
650
658
  }
651
659
  const projectContext = await prepareProjectContext({ deps, spec, internals, session, sessionId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine, skillGrants, allowedTools, allowedToolTables, roster, toolFaceSnapshot, onceLedger, memoryTools, memoryEngineSession, memorySearchToolsPlanned, memoryPairExcludedName, memoryPairOccupiedName, resume, skillListingBudget: doors.skillListingBudget });
652
660
  const { memoryBlock: memoryBlockWithProject, instructionSources, projectInstructionContent, skillSpecs, skillSeatOf, skillsListing, sharedMemoryPairMounted, memoryEnginePairMounted } = projectContext;
653
- const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef } = await preparePromptInputs({ spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace: resolvedWriteFace?.inForce(), toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, session, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
661
+ const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef } = await preparePromptInputs({ spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace: resolvedWriteFace?.inForce(), toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical: (await readRoots.ready().then(readRoots)).filter((r) => !additionalRootsCanonical.includes(r)), sessionId, session, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
654
662
  judgeRunToolLists({ spec, tools: roster.tools, declaredPeers: { mcp: lockedPreflight.mcp, a2a: a2a.statuses }, own: { allow: toolFaceLists.allow, exclude: toolFaceLists.exclude }, layers: toolFaceSnapshot.selector.layers, legs: toolLegs, judgedUpstream: toolListsJudged !== undefined, ownWhere: internals?.ownToolListsWhere, onceLedger, sessionId });
655
663
  const { deferred, memoryBlock, toolSearch: toolSearchPolicy } = prepareDeferClassify({ spec, deps, roster, toolFaceSnapshot, handsEnabled, fullShellReachable, promptProfile, model, mcp, a2a, sharedMemoryPairMounted, memoryEnginePairMounted, memoryBlock: memoryBlockWithProject, memoryRecallSegment, onceLedger, sessionId });
656
664
  prepareMemoryEngineSession({ memoryEngineSession, internals, memoryDelegationEvidence, externalContentTargetActive, lockedPreflight, mcp, ...(mountedMcpNow !== undefined ? { mountedMcp: mountedMcpNow } : {}), sessionId, runId, deps, provenanceForChildrenRef, delegationSettlementRef, spec, envHandToolNames, roster, contentOriginWrapRef });
@@ -763,7 +771,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
763
771
  releaseSignal = () => sig.removeEventListener("abort", onExternalAbort);
764
772
  }
765
773
  }
766
- const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { leg: legAnchors, chainTop }, headLeads, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, announceRuleRowsDropped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider: () => autoModeDeciderRef.current, readFace: () => resolvedReadFace, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
774
+ const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, ruleLanesBeyondRun, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { leg: legAnchors, chainTop }, headLeads, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, personRows, personRowsBeyondRun, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider: () => autoModeDeciderRef.current, readFace: () => resolvedReadFace, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
767
775
  const { onAsk, preToolContexts, blockedToolCalls, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, askSeat: doors.askSeat, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, shellReadStationArmed: handsReadFace.shellReadStationArmed, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox, checkpointScope });
768
776
  const writeProtectionCheck = writeProtection.mount?.check;
769
777
  writeTargetJudgeRef.current = writeProtection.judgeWriteTarget;
@@ -781,13 +789,13 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
781
789
  const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, checkpointScope, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
782
790
  const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, checkpointScope, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, handsRoot: attachmentRootCanonical, stampCallTarget, advertisedWritableDirs, exemptRoots: legExemptRoots, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, ruleOffersOf, grantBindingOf, now, humanReviewRef, abortController, harness, pausedRef });
783
791
  const seatInputsFor = skillGateWiring({ tools, skillToolName: SKILL_TOOL_NAME, seatOf: skillSeatOf, mode: () => permissionMode.current, lane: skillGrantLane, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.skill_allowed", version: 1, taskId: hostTaskId, ...info, entries: [...info.entries], ts: Date.now() })), allowEntries: { deploymentAllows: { ...allowEntryLanes.deployment, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "deployment", ...info, entries: [...info.entries], ts: Date.now() })) }, requestAllows: { ...allowEntryLanes.request, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "request", ...info, entries: [...info.entries], ts: Date.now() })) } } });
784
- const { approvedCallScreen } = prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, toolOccurrences, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, stampCallTarget, readDenyInForce: () => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...handsReadFaceInput.denyRuleRows.filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, readFace: () => resolvedReadFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: { ...wiringManifest.ask, effective: askSeatEffective(wiringManifest) }, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, seatInputsFor, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash, frameSettlement });
792
+ const { approvedCallScreen } = prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, toolOccurrences, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, stampCallTarget, readDenyInForce: (toolCallId) => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...(pathTables?.forCall(toolCallId).ruleRows ?? handsReadFaceInput.denyRuleRows).filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, readFace: () => resolvedReadFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: { ...wiringManifest.ask, effective: askSeatEffective(wiringManifest) }, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, seatInputsFor, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash, frameSettlement });
785
793
  const postureFrameRef = { report: (err) => deps.onError?.(err, { phase: "degraded", sessionId }) };
786
794
  const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, toolRosterDeltas: rosterSeat, microCompactKnob, harness, batchHaltRef, gitStatusRef, postureFrameRef, requestLossyRef, trimPressureRef, contextOverlay: legContextOverlay, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}) });
787
795
  const preparedHolder = {};
788
- const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants: skillGrantLane, callerPolicy: installedToolPolicy, inheritedPolicies: (inheritedParentConstraints ?? []).map((c) => c.policy), persistedRuleLane: permissionRuleLane, orgRuleLane: permissionRuleOrgLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
796
+ const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, syntheticWriteVerdict, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants: skillGrantLane, callerPolicy: installedToolPolicy, inheritedPolicies: (inheritedParentConstraints ?? []).map((c) => c.policy), persistedRuleLane: permissionRuleLane, ruleLanesBeyondRun, orgRuleLane: permissionRuleOrgLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
789
797
  await onceLedger.settle(session, announcedListingsRef);
790
- const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: askSeatEffective(wiringManifest) }, ...(outputStyleFrame !== undefined ? { outputStyleFrame } : {}), permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, toolOccurrences, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(attachmentRootCanonical !== undefined ? { handsRoot: attachmentRootCanonical } : {}), ...(stampCallTarget !== undefined ? { stampCallTarget } : {}), toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), exemptRoots: legExemptRoots, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, skillGrants: skillGrantLane, skillSpecs, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, frameSettlement, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}), ...(approvedCallScreen !== undefined ? { approvedCallScreen } : {}) });
798
+ const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: askSeatEffective(wiringManifest) }, ...(outputStyleFrame !== undefined ? { outputStyleFrame } : {}), permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, toolOccurrences, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(attachmentRootCanonical !== undefined ? { handsRoot: attachmentRootCanonical } : {}), ...(stampCallTarget !== undefined ? { stampCallTarget } : {}), toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), exemptRoots: legExemptRoots, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, skillGrants: skillGrantLane, skillSpecs, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), syntheticWriteVerdict, ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit && withheldDiagnosticsOf ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent, withheldOf: withheldDiagnosticsOf } } : {}), stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, frameSettlement, ...(userAttachmentsSeat !== undefined ? { userAttachments: userAttachmentsSeat } : {}), attachmentDelivery: createAttachmentDelivery(), ...(modelFileReaderSeat.current !== undefined ? { modelFileReader: modelFileReaderSeat.current } : {}), syntheticReadVerdict, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}), ...(approvedCallScreen !== undefined ? { approvedCallScreen } : {}) });
791
799
  refuseLateRosterChanges(callerRoster.roster);
792
800
  rollback.commit();
793
801
  commitModeSeats(abortController.signal);
@@ -7,11 +7,12 @@ import { type TurnPromptSnapshot } from "../../prompt-assembly/turn-snapshot.js"
7
7
  import type { PromptTextDeclaration } from "../../prompts/default.js";
8
8
  import { CacheBreakDetector, type ToolFingerprintInput } from "../cache-break-detector.js";
9
9
  import type { ToolPolicy } from "../tool-policy.js";
10
- import { type SyntheticReadJudge } from "../synthetic-read-verdict.js";
10
+ import { type SyntheticReadJudge, type SyntheticWriteJudge } from "../synthetic-read-verdict.js";
11
11
  import type { RunnerDeps, TaskSpec } from "../types.js";
12
12
  import type { CwdRef } from "../../tools/fs/fs-shared.js";
13
13
  import { type ContainmentFace } from "../../tools/fs/index.js";
14
14
  import type { PlacedReadDenyMatcher } from "../../tools/fs/read-deny-home.js";
15
+ import type { ReadRootsSeat } from "./person-path-rows.js";
15
16
  import { type ReadFileState } from "../../tools/fs/safety.js";
16
17
  import type { Prepared } from "./contracts.js";
17
18
  export interface PrepareTurnWiringInput {
@@ -66,11 +67,10 @@ export interface PrepareTurnWiringInput {
66
67
  executionEnv: ExecutionEnv;
67
68
  /** borrowed-readonly — the canonical attachment root, or undefined (the readers' containment fence). */
68
69
  attachmentRootCanonical: string | undefined;
69
- /** borrowed-readonly — the canonical extra write roots (the fence's root set). */
70
- additionalRootsCanonical: ReadonlyArray<string>;
71
- /** borrowed-readonly — the canonical extra read roots (the fence's root set). */
72
- additionalReadRootsCanonical: ReadonlyArray<string>;
73
- /** borrowed-readonly — the compiled read-deny judge, or undefined (the reader's withheld arm). */
70
+ /** borrowed-readonly — the read face's root set beside the attachment root, read per use: the write roots, the read
71
+ * roots with the run's grants, the person's read directories as the run read them last (no call: `ready` first). */
72
+ readRoots: (() => readonly string[]) & Pick<ReadRootsSeat, "ready">;
73
+ /** borrowed-readonly — the run's read deny table (its latest; these readers are no call), or undefined (the reader's withheld arm). */
74
74
  readDenyMatcher: PlacedReadDenyMatcher | undefined;
75
75
  /** borrowed-readonly — the resolved read face, or undefined (the fence's ninth argument). */
76
76
  resolvedReadFace: ContainmentFace | undefined;
@@ -90,6 +90,11 @@ export interface PrepareTurnWiringInput {
90
90
  inheritedPolicies: readonly ToolPolicy[];
91
91
  /** borrowed-readonly — the person's persisted-rule lane, or undefined (a layer of the judge). */
92
92
  persistedRuleLane: Prepared["persistedRuleLane"];
93
+ /** borrowed-readonly — the person's and the org's lanes over the reader the run's cut does not end (the write face is asked after it). */
94
+ ruleLanesBeyondRun: {
95
+ readonly personal: Prepared["persistedRuleLane"];
96
+ readonly org: Prepared["permissionRuleOrg"];
97
+ };
93
98
  /** borrowed-readonly — the org rule lane, or undefined (a layer of the judge). */
94
99
  orgRuleLane: Prepared["permissionRuleOrg"];
95
100
  /** borrowed-readonly — the leg's target-reading stamp, or undefined (hands-less): the visibility judge stamps its request. */
@@ -157,6 +162,8 @@ export interface PrepareTurnWiringResult {
157
162
  /** owned — the run's ONE synthetic-Read deny judge over every layer that can refuse a model's `Read` (the
158
163
  * changed-files door reads it; a face that delivers a file the model did not ask for reads the same one). */
159
164
  syntheticReadVerdict: SyntheticReadJudge;
165
+ /** owned — the same layers' WRITE face (`Prepared.syntheticWriteVerdict`): an `ask` is an objection there. */
166
+ syntheticWriteVerdict: SyntheticWriteJudge;
160
167
  /** owned — the post-compact background-task listing (`Prepared.listBackgroundTasks`). */
161
168
  listBackgroundTasks: Prepared["listBackgroundTasks"];
162
169
  /** owned — the compaction-boundary center adoption candidate, or undefined (no source, or no adoption). */
@@ -4,7 +4,8 @@ import { artifactDeclarations } from "../../prompt-assembly/artifact.js";
4
4
  import { buildTurnPromptSnapshot } from "../../prompt-assembly/turn-snapshot.js";
5
5
  import { CacheBreakDetector, toolsToFingerprintInputs } from "../cache-break-detector.js";
6
6
  import { defaultTaskRegistry } from "../task-registry.js";
7
- import { createSyntheticReadJudge } from "../synthetic-read-verdict.js";
7
+ import { createSyntheticReadJudge, createSyntheticWriteJudge } from "../synthetic-read-verdict.js";
8
+ import { toolCallFaceOf } from "../tool-roster.js";
8
9
  import { ORG_ADJUDICATION_TIMEOUT_MS } from "../permission-rule-org.js";
9
10
  import { decodeTextBytes } from "../../tools/fs/encoding.js";
10
11
  import { applyContextShrinkToReadFileState, isReadDedupStubResult } from "../../tools/fs/index.js";
@@ -13,7 +14,7 @@ import { PROMPT_HASH_SALT } from "./prompt-hash-salt.js";
13
14
  import { CHANGED_FILES_MTIME_EPS_MS } from "./turn-attachments.js";
14
15
  import { thrownText } from "../thrown-value.js";
15
16
  export function prepareTurnWiring(input) {
16
- const { deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants, callerPolicy, inheritedPolicies, persistedRuleLane, orgRuleLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
17
+ const { deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants, callerPolicy, inheritedPolicies, persistedRuleLane, ruleLanesBeyondRun, orgRuleLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
17
18
  const cacheBreakDetector = deps.cacheBreakDetection === false ? undefined : new CacheBreakDetector();
18
19
  const cacheFingerprint = cacheBreakDetector
19
20
  ? { systemPrompt: systemPromptSeat.current, tools: toolsToFingerprintInputs(harnessTools) }
@@ -51,7 +52,10 @@ export function prepareTurnWiring(input) {
51
52
  try {
52
53
  let key = path;
53
54
  if (attachmentRootCanonical !== undefined) {
54
- const rk = await resolveKey(executionEnv, attachmentRootCanonical, path, undefined, undefined, [...additionalRootsCanonical, ...additionalReadRootsCanonical], undefined, readDenyMatcher, resolvedReadFace);
55
+ await readRoots.ready(abortController.signal);
56
+ if (abortController.signal.aborted)
57
+ return null;
58
+ const rk = await resolveKey(executionEnv, attachmentRootCanonical, path, abortController.signal, undefined, readRoots(), undefined, readDenyMatcher, resolvedReadFace);
55
59
  if (!rk.ok) {
56
60
  announceAttachmentSkip(path, rk.violation.message);
57
61
  if (rk.violation.code === "read_path_denied" && rk.violation.pattern !== undefined) {
@@ -61,7 +65,7 @@ export function prepareTurnWiring(input) {
61
65
  }
62
66
  key = rk.key;
63
67
  }
64
- const r = await executionEnv.readBinaryFile(key);
68
+ const r = await executionEnv.readBinaryFile(key, abortController.signal);
65
69
  if (!r.ok) {
66
70
  announceAttachmentSkip(path, r.error.message);
67
71
  return null;
@@ -84,7 +88,10 @@ export function prepareTurnWiring(input) {
84
88
  if (attachmentRootCanonical === undefined)
85
89
  return path;
86
90
  try {
87
- const rk = await resolveKey(executionEnv, attachmentRootCanonical, path, undefined, handsCwdRef?.current, [...additionalRootsCanonical, ...additionalReadRootsCanonical], undefined, undefined, resolvedReadFace);
91
+ await readRoots.ready(abortController.signal);
92
+ if (abortController.signal.aborted)
93
+ return path;
94
+ const rk = await resolveKey(executionEnv, attachmentRootCanonical, path, abortController.signal, handsCwdRef?.current, readRoots(), undefined, undefined, resolvedReadFace);
88
95
  return rk.ok ? rk.key : path;
89
96
  }
90
97
  catch {
@@ -102,7 +109,7 @@ export function prepareTurnWiring(input) {
102
109
  const onCompactionApplied = handsEnabled && readFileStateForCheckpoint
103
110
  ? (attachedComplete, preserveReadState) => applyContextShrinkToReadFileState(readFileStateForCheckpoint, { kind: "summarized", attachedComplete, ...(preserveReadState !== undefined ? { preserveKeys: preserveReadState } : {}) })
104
111
  : undefined;
105
- const syntheticReadVerdict = createSyntheticReadJudge({
112
+ const syntheticLayers = {
106
113
  skillGrants,
107
114
  ...(denyNarrowingPolicy !== undefined ? { denyNarrowingPolicy } : {}),
108
115
  ...(callerPolicy !== undefined ? { callerPolicy } : {}),
@@ -110,7 +117,11 @@ export function prepareTurnWiring(input) {
110
117
  ...(persistedRuleLane !== undefined ? { persistedRuleLane } : {}),
111
118
  ...(orgRuleLane !== undefined ? { orgRuleLane } : {}),
112
119
  ...(stampCallTarget !== undefined ? { stampCallTarget } : {}),
113
- signal: abortController.signal,
120
+ };
121
+ const syntheticReadVerdict = createSyntheticReadJudge({ ...syntheticLayers, signal: abortController.signal });
122
+ const syntheticWriteVerdict = createSyntheticWriteJudge({ ...syntheticLayers, ...(ruleLanesBeyondRun.personal !== undefined ? { persistedRuleLane: ruleLanesBeyondRun.personal } : {}), ...(ruleLanesBeyondRun.org !== undefined ? { orgRuleLane: ruleLanesBeyondRun.org } : {}) }, () => {
123
+ const p = preparedHolder.current;
124
+ return { face: toolCallFaceOf(p?.toolRoster, "Write"), cwd: p?.cwdRef?.current, root: p?.handsRoot, advertisedWritableDirs: p?.advertisedWritableDirs, exemptRoots: p?.exemptRoots };
114
125
  });
115
126
  const changedFilesReadDenied = async (paths) => {
116
127
  const deadlineAt = Date.now() + ORG_ADJUDICATION_TIMEOUT_MS;
@@ -204,5 +215,5 @@ export function prepareTurnWiring(input) {
204
215
  const effectiveReadFaceObserved = carrierReadFace();
205
216
  const effectiveWriteFaceObserved = carrierWriteFace();
206
217
  const effectiveReadDenyObserved = readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized.map((e) => ({ ...e })) : undefined;
207
- return { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved };
218
+ return { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, syntheticWriteVerdict, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved };
208
219
  }
@@ -1,40 +1,16 @@
1
1
  /** The run's IN-FLIGHT read-root grant: the one place a screened grant ({@link ReadRootGrantScreen}) widens this run's
2
2
  * read directories (through the hands phase's {@link GrantReadRoot}, built by {@link readRootGrantOver}), the one
3
- * composer of the two notices, and the home of the store-isolation rule both root admission points judge by (the
4
- * Artifact phase's mount and the grant) — machinery both phases reach down for. */
3
+ * composer of the two notices; the grant judges by the store-isolation rule ({@link rootAdmittingArtifactStore}). */
5
4
  import type { ExecutionEnv } from "../../internal/harness.js";
6
5
  import type { ReadRootGrantCandidate } from "../types.js";
7
6
  import type { ReadRootGrantScreen } from "../read-root-grant-screen.js";
8
7
  import { type RunnerDeps } from "../types.js";
9
- /**
10
- * THE store-isolation rule, one judgment for every root admission point (the Artifact mount over the prepare-time
11
- * roots, an in-flight read-root grant over the granted root): a root that CONTAINS the local artifact store, lies
12
- * INSIDE it, or IS it hands the file tools the store's ledger and stored files. Returns the first such root, or
13
- * undefined.
14
- *
15
- * `storePhysical` is the store's physical path on THIS process's filesystem (`physicalPathOfExisting`, resolved
16
- * once per run by the Artifact phase); a root is the execution env's canonical key. The judgment touches no
17
- * filesystem — the grant runs after the approver's wait under the call's cut, and a synchronous lookup on a stalled
18
- * store mount would block the event loop past that cut. The two are compared as identities only when both spell the
19
- * same family (`within` reads both under the root's family); a root of the other family names a filesystem the store
20
- * cannot be on, and no claim is made against it.
21
- */
22
- export declare function rootAdmittingArtifactStore(storePhysical: string, rootsCanonical: readonly string[]): string | undefined;
23
8
  /** The run's cell holding the local artifact store a granted root must never admit (its physical path, as the
24
9
  * Artifact phase resolved it): minted with the grant by the hands phase, written by the Artifact phase (the one
25
10
  * reader of the hosting seat) once the declaration validates. */
26
11
  export interface ArtifactStoreRef {
27
12
  current: string | undefined;
28
- /** The person's STANDING read grants — their persisted `Read(//dir/**)` rows, joined to the live read set at prepare —
29
- * held to the in-flight grant's store rule by {@link withdrawStandingGrantsAdmitting} once the store is known. */
30
- standing?: {
31
- readonly keys: readonly string[];
32
- readonly readRoots: string[];
33
- };
34
13
  }
35
- /** The store rule applied to the standing grants: each one that admits `storePhysical` leaves the live read set (so no
36
- * read face reaches the store through it); returns the withdrawn keys, for the caller to announce. */
37
- export declare function withdrawStandingGrantsAdmitting(storePhysical: string, ref: ArtifactStoreRef): string[];
38
14
  /** Why the run's station applied no grant: the spelling did not resolve (or its lookup was cut), it no longer
39
15
  * resolves to itself (a directory swapped for a link while the card waited), or it would admit the local artifact
40
16
  * store (the store-isolation rule the Artifact phase judges its mount by). */