@caupulican/pi-adaptative 0.81.41 → 0.81.42

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 (237) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/bundled-resources/runtimes/pi-shell-engine/commands/text.py +5 -1
  3. package/dist/bundled-resources/runtimes/pi-shell-engine/context.py +3 -3
  4. package/dist/bundled-resources/runtimes/pi-shell-engine/errors.py +8 -0
  5. package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +26 -3
  6. package/dist/bundled-resources/runtimes/pi-shell-engine/expand.py +3 -0
  7. package/dist/bundled-resources/runtimes/pi-shell-engine/main.py +4 -1
  8. package/dist/bundled-resources/runtimes/pi-shell-engine/state.py +2 -1
  9. package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +2 -0
  10. package/dist/core/agent-paths.d.ts +32 -0
  11. package/dist/core/agent-paths.d.ts.map +1 -1
  12. package/dist/core/agent-paths.js +65 -0
  13. package/dist/core/agent-paths.js.map +1 -1
  14. package/dist/core/agent-session-contracts.d.ts +19 -1
  15. package/dist/core/agent-session-contracts.d.ts.map +1 -1
  16. package/dist/core/agent-session-contracts.js.map +1 -1
  17. package/dist/core/agent-session.d.ts.map +1 -1
  18. package/dist/core/agent-session.js +4 -9
  19. package/dist/core/agent-session.js.map +1 -1
  20. package/dist/core/autonomy/contracts.d.ts +2 -0
  21. package/dist/core/autonomy/contracts.d.ts.map +1 -1
  22. package/dist/core/autonomy/contracts.js.map +1 -1
  23. package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
  24. package/dist/core/autonomy/envelope-enforcement.js +4 -9
  25. package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
  26. package/dist/core/autonomy/lane-tool-surface.d.ts +3 -1
  27. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  28. package/dist/core/autonomy/lane-tool-surface.js +17 -4
  29. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  30. package/dist/core/autonomy/path-scope.d.ts +14 -0
  31. package/dist/core/autonomy/path-scope.d.ts.map +1 -1
  32. package/dist/core/autonomy/path-scope.js +37 -6
  33. package/dist/core/autonomy/path-scope.js.map +1 -1
  34. package/dist/core/background-lane-controller.d.ts +27 -1
  35. package/dist/core/background-lane-controller.d.ts.map +1 -1
  36. package/dist/core/background-lane-controller.js +32 -1
  37. package/dist/core/background-lane-controller.js.map +1 -1
  38. package/dist/core/delegation/managed-lane-controller.d.ts +11 -1
  39. package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -1
  40. package/dist/core/delegation/managed-lane-controller.js +84 -41
  41. package/dist/core/delegation/managed-lane-controller.js.map +1 -1
  42. package/dist/core/delegation/session-worker-claim.d.ts.map +1 -1
  43. package/dist/core/delegation/session-worker-claim.js +4 -3
  44. package/dist/core/delegation/session-worker-claim.js.map +1 -1
  45. package/dist/core/delegation/worker-action-journal.d.ts +73 -0
  46. package/dist/core/delegation/worker-action-journal.d.ts.map +1 -0
  47. package/dist/core/delegation/worker-action-journal.js +297 -0
  48. package/dist/core/delegation/worker-action-journal.js.map +1 -0
  49. package/dist/core/delegation/worker-actions.d.ts +36 -1
  50. package/dist/core/delegation/worker-actions.d.ts.map +1 -1
  51. package/dist/core/delegation/worker-actions.js +171 -46
  52. package/dist/core/delegation/worker-actions.js.map +1 -1
  53. package/dist/core/delegation/worker-agent-control-coordinator.d.ts +75 -0
  54. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -0
  55. package/dist/core/delegation/worker-agent-control-coordinator.js +218 -0
  56. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -0
  57. package/dist/core/delegation/worker-agent-control.d.ts +66 -0
  58. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -0
  59. package/dist/core/delegation/worker-agent-control.js +163 -0
  60. package/dist/core/delegation/worker-agent-control.js.map +1 -0
  61. package/dist/core/delegation/worker-attempt-executor.d.ts +80 -0
  62. package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -0
  63. package/dist/core/delegation/worker-attempt-executor.js +343 -0
  64. package/dist/core/delegation/worker-attempt-executor.js.map +1 -0
  65. package/dist/core/delegation/worker-claim.d.ts +30 -0
  66. package/dist/core/delegation/worker-claim.d.ts.map +1 -1
  67. package/dist/core/delegation/worker-claim.js +205 -53
  68. package/dist/core/delegation/worker-claim.js.map +1 -1
  69. package/dist/core/delegation/worker-conversation-store.d.ts +116 -0
  70. package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -0
  71. package/dist/core/delegation/worker-conversation-store.js +442 -0
  72. package/dist/core/delegation/worker-conversation-store.js.map +1 -0
  73. package/dist/core/delegation/worker-delegation-controller.d.ts +21 -5
  74. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  75. package/dist/core/delegation/worker-delegation-controller.js +386 -251
  76. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  77. package/dist/core/delegation/worker-delegation-request.d.ts +14 -0
  78. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
  79. package/dist/core/delegation/worker-delegation-request.js.map +1 -1
  80. package/dist/core/delegation/worker-dispatch-scheduler.d.ts +4 -2
  81. package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -1
  82. package/dist/core/delegation/worker-dispatch-scheduler.js +16 -6
  83. package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -1
  84. package/dist/core/delegation/worker-execution-policy.d.ts +2 -1
  85. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
  86. package/dist/core/delegation/worker-execution-policy.js +5 -7
  87. package/dist/core/delegation/worker-execution-policy.js.map +1 -1
  88. package/dist/core/delegation/worker-lifecycle.d.ts +44 -1
  89. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
  90. package/dist/core/delegation/worker-lifecycle.js +120 -0
  91. package/dist/core/delegation/worker-lifecycle.js.map +1 -1
  92. package/dist/core/delegation/worker-process-owner.d.ts +18 -0
  93. package/dist/core/delegation/worker-process-owner.d.ts.map +1 -0
  94. package/dist/core/delegation/worker-process-owner.js +54 -0
  95. package/dist/core/delegation/worker-process-owner.js.map +1 -0
  96. package/dist/core/delegation/worker-profile-resolver.d.ts +5 -1
  97. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
  98. package/dist/core/delegation/worker-profile-resolver.js +8 -0
  99. package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
  100. package/dist/core/delegation/worker-recovery-coordinator.d.ts +54 -0
  101. package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -0
  102. package/dist/core/delegation/worker-recovery-coordinator.js +181 -0
  103. package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -0
  104. package/dist/core/delegation/worker-resource-catalog.d.ts +32 -0
  105. package/dist/core/delegation/worker-resource-catalog.d.ts.map +1 -0
  106. package/dist/core/delegation/worker-resource-catalog.js +116 -0
  107. package/dist/core/delegation/worker-resource-catalog.js.map +1 -0
  108. package/dist/core/delegation/worker-resource-materializer.d.ts +47 -0
  109. package/dist/core/delegation/worker-resource-materializer.d.ts.map +1 -0
  110. package/dist/core/delegation/worker-resource-materializer.js +137 -0
  111. package/dist/core/delegation/worker-resource-materializer.js.map +1 -0
  112. package/dist/core/delegation/worker-runner.d.ts +3 -1
  113. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  114. package/dist/core/delegation/worker-runner.js +189 -54
  115. package/dist/core/delegation/worker-runner.js.map +1 -1
  116. package/dist/core/delegation/worker-terminal-finalizer.d.ts +23 -0
  117. package/dist/core/delegation/worker-terminal-finalizer.d.ts.map +1 -0
  118. package/dist/core/delegation/worker-terminal-finalizer.js +12 -0
  119. package/dist/core/delegation/worker-terminal-finalizer.js.map +1 -0
  120. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +38 -0
  121. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -0
  122. package/dist/core/delegation/worker-write-reservation-coordinator.js +107 -0
  123. package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -0
  124. package/dist/core/delegation/worker-write-reservation.d.ts +90 -0
  125. package/dist/core/delegation/worker-write-reservation.d.ts.map +1 -0
  126. package/dist/core/delegation/worker-write-reservation.js +348 -0
  127. package/dist/core/delegation/worker-write-reservation.js.map +1 -0
  128. package/dist/core/models/model-endpoint.d.ts +3 -0
  129. package/dist/core/models/model-endpoint.d.ts.map +1 -0
  130. package/dist/core/models/model-endpoint.js +11 -0
  131. package/dist/core/models/model-endpoint.js.map +1 -0
  132. package/dist/core/orchestration/agent-resume.d.ts +2 -0
  133. package/dist/core/orchestration/agent-resume.d.ts.map +1 -1
  134. package/dist/core/orchestration/agent-resume.js +7 -0
  135. package/dist/core/orchestration/agent-resume.js.map +1 -1
  136. package/dist/core/orchestration/attempt-usage.d.ts +28 -0
  137. package/dist/core/orchestration/attempt-usage.d.ts.map +1 -0
  138. package/dist/core/orchestration/attempt-usage.js +168 -0
  139. package/dist/core/orchestration/attempt-usage.js.map +1 -0
  140. package/dist/core/orchestration/capability-gateway.d.ts +19 -1
  141. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  142. package/dist/core/orchestration/capability-gateway.js +128 -28
  143. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  144. package/dist/core/orchestration/contracts.d.ts +35 -0
  145. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  146. package/dist/core/orchestration/contracts.js +17 -0
  147. package/dist/core/orchestration/contracts.js.map +1 -1
  148. package/dist/core/orchestration/delegation-ledger.d.ts +17 -2
  149. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
  150. package/dist/core/orchestration/delegation-ledger.js +78 -3
  151. package/dist/core/orchestration/delegation-ledger.js.map +1 -1
  152. package/dist/core/orchestration/event-store.d.ts +1 -0
  153. package/dist/core/orchestration/event-store.d.ts.map +1 -1
  154. package/dist/core/orchestration/event-store.js +78 -38
  155. package/dist/core/orchestration/event-store.js.map +1 -1
  156. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  157. package/dist/core/orchestration/profile-registry.js +81 -41
  158. package/dist/core/orchestration/profile-registry.js.map +1 -1
  159. package/dist/core/orchestration/profile-store.d.ts.map +1 -1
  160. package/dist/core/orchestration/profile-store.js +18 -4
  161. package/dist/core/orchestration/profile-store.js.map +1 -1
  162. package/dist/core/orchestration/risk-budget.d.ts +2 -0
  163. package/dist/core/orchestration/risk-budget.d.ts.map +1 -1
  164. package/dist/core/orchestration/risk-budget.js +26 -0
  165. package/dist/core/orchestration/risk-budget.js.map +1 -1
  166. package/dist/core/orchestration/task-runtime.d.ts +13 -1
  167. package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
  168. package/dist/core/orchestration/task-runtime.js +127 -16
  169. package/dist/core/orchestration/task-runtime.js.map +1 -1
  170. package/dist/core/orchestration/worker-execution-contract.d.ts +3 -1
  171. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
  172. package/dist/core/orchestration/worker-execution-contract.js +75 -23
  173. package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
  174. package/dist/core/orchestration/worker-result-adapter.d.ts +9 -3
  175. package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -1
  176. package/dist/core/orchestration/worker-result-adapter.js +167 -14
  177. package/dist/core/orchestration/worker-result-adapter.js.map +1 -1
  178. package/dist/core/reflection-controller.d.ts +1 -1
  179. package/dist/core/reflection-controller.d.ts.map +1 -1
  180. package/dist/core/reflection-controller.js +90 -54
  181. package/dist/core/reflection-controller.js.map +1 -1
  182. package/dist/core/research/evidence-bundle.d.ts +20 -0
  183. package/dist/core/research/evidence-bundle.d.ts.map +1 -1
  184. package/dist/core/research/evidence-bundle.js +173 -69
  185. package/dist/core/research/evidence-bundle.js.map +1 -1
  186. package/dist/core/runtime-builder.d.ts +7 -0
  187. package/dist/core/runtime-builder.d.ts.map +1 -1
  188. package/dist/core/runtime-builder.js +15 -1
  189. package/dist/core/runtime-builder.js.map +1 -1
  190. package/dist/core/session-artifact-bundle.d.ts +35 -0
  191. package/dist/core/session-artifact-bundle.d.ts.map +1 -0
  192. package/dist/core/session-artifact-bundle.js +61 -0
  193. package/dist/core/session-artifact-bundle.js.map +1 -0
  194. package/dist/core/tools/delegate-status.d.ts +6 -1
  195. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  196. package/dist/core/tools/delegate-status.js +100 -18
  197. package/dist/core/tools/delegate-status.js.map +1 -1
  198. package/dist/core/tools/delegate.d.ts +9 -1
  199. package/dist/core/tools/delegate.d.ts.map +1 -1
  200. package/dist/core/tools/delegate.js +323 -61
  201. package/dist/core/tools/delegate.js.map +1 -1
  202. package/dist/core/tools/run-process.d.ts +1 -1
  203. package/dist/core/tools/run-process.d.ts.map +1 -1
  204. package/dist/core/tools/run-process.js +69 -9
  205. package/dist/core/tools/run-process.js.map +1 -1
  206. package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
  207. package/dist/core/tools/shell-contract-router.js +12 -5
  208. package/dist/core/tools/shell-contract-router.js.map +1 -1
  209. package/dist/core/util/bounded-file.d.ts +15 -0
  210. package/dist/core/util/bounded-file.d.ts.map +1 -0
  211. package/dist/core/util/bounded-file.js +120 -0
  212. package/dist/core/util/bounded-file.js.map +1 -0
  213. package/dist/core/util/bounded-jsonl.d.ts.map +1 -1
  214. package/dist/core/util/bounded-jsonl.js +119 -9
  215. package/dist/core/util/bounded-jsonl.js.map +1 -1
  216. package/dist/core/util/bounded-value.d.ts +3 -0
  217. package/dist/core/util/bounded-value.d.ts.map +1 -0
  218. package/dist/core/util/bounded-value.js +12 -0
  219. package/dist/core/util/bounded-value.js.map +1 -0
  220. package/dist/core/util/value-guards.d.ts +2 -0
  221. package/dist/core/util/value-guards.d.ts.map +1 -1
  222. package/dist/core/util/value-guards.js +5 -0
  223. package/dist/core/util/value-guards.js.map +1 -1
  224. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  225. package/dist/modes/interactive/components/session-selector.js +27 -44
  226. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  227. package/docs/tool-repair.md +3 -0
  228. package/docs/windows.md +4 -2
  229. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  230. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  231. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  232. package/examples/extensions/sandbox/package-lock.json +2 -2
  233. package/examples/extensions/sandbox/package.json +1 -1
  234. package/examples/extensions/with-deps/package-lock.json +2 -2
  235. package/examples/extensions/with-deps/package.json +1 -1
  236. package/npm-shrinkwrap.json +12 -12
  237. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## [0.81.42] - 2026-07-27
2
+
3
+ ### Changed
4
+
5
+ - Rebuilt delegated workers around immutable owner-authored execution contracts, durable logical-agent identities, resumable conversations and mailboxes, fenced write reservations, bounded resource materialization, verified model-pinned compaction, and event-driven terminal handoffs.
6
+ - Consolidated session-owned orchestration events, actions, mailboxes, conversations, and deletion under one bounded artifact bundle while keeping cross-session write reservations globally coordinated.
7
+
8
+ ### Fixed
9
+
10
+ - Made the Windows shell engine preserve `$?`, support controlled `exit`, and accept `head`/`tail -N`, so diagnostic-capture command chains complete with a terminal result instead of losing status or treating `exit` as an external command.
11
+ - Added a provider- and tool-neutral WSL incident collector that packages the latest human session, recovery and orchestration records, explicitly requested command logs, TUI evidence, boot identity, installed-runtime hashes, bounded kernel diagnostics, and relevant Windows host events without collecting credential stores or emitting false missing-log warnings.
12
+ - Made pre-start worker failures publish exactly one durable terminal handoff, rejected malformed typed result envelopes, and handled null or Buffer filesystem watcher filenames on Windows.
13
+ - Made orchestration session paths portable across Windows and POSIX and bounded profile, process, event, result, and cumulative usage payloads at their owning contracts.
14
+ - Kept explicit empty worker tool surfaces inside the repair loop and persisted immediate or argument-repaired tool requests in durable execution order, preventing unavailable-tool calls from collapsing into completion errors or divergent transcripts.
15
+ - Preserved bounded host-observed changed-file progress when an agent-bound worker is suspended, so owner-session disposal remains resumable without fabricating terminal parent-session records.
16
+
1
17
  ## [0.81.41] - 2026-07-27
2
18
 
3
19
  ### Added
@@ -97,7 +97,7 @@ def cat(ctx: "BuiltinContext") -> int:
97
97
 
98
98
 
99
99
  def _parse_n_flag(name: str, argv: list[str]) -> tuple[int, list[str]]:
100
- """Parse `[-n N] [FILE]` only. Any other flag/form -> unsupported-flag."""
100
+ """Parse `[-n N|-N] [FILE]`. Any other flag/form -> unsupported-flag."""
101
101
  n = 10
102
102
  operands: list[str] = []
103
103
  args = argv[1:]
@@ -118,6 +118,10 @@ def _parse_n_flag(name: str, argv: list[str]) -> tuple[int, list[str]]:
118
118
  n = _parse_int_operand(name, a[2:])
119
119
  i += 1
120
120
  continue
121
+ if len(a) > 1 and a[0] == "-" and a[1:].isdigit():
122
+ n = int(a[1:])
123
+ i += 1
124
+ continue
121
125
  if a.startswith("-") and a != "-":
122
126
  _refuse_flag(name, a)
123
127
  operands.append(a)
@@ -46,7 +46,7 @@ class ExecContext:
46
46
  stderr: BinaryIO | int | None = None
47
47
 
48
48
 
49
- # Frozen inline sets: state mutators and the runner builtin are NOT in commands/REGISTRY;
50
- # exec.py handles them inline because they need ShellState / the executor.
51
- STATE_BUILTINS = {"cd", "export", "unset"}
49
+ # Executor-owned builtins are NOT in commands/REGISTRY: state mutators and `exit`
50
+ # need ShellState/control-flow access, while the runner needs the executor.
51
+ STATE_BUILTINS = {"cd", "export", "unset", "exit"}
52
52
  RUNNER_BUILTINS = {"xargs"}
@@ -47,3 +47,11 @@ class UnsupportedConstruct(Exception):
47
47
  self.code = "unsupported"
48
48
  self.construct = construct
49
49
  self.message = message
50
+
51
+
52
+ class ShellExit(Exception):
53
+ """Controlled `exit` request carried to the nearest shell boundary."""
54
+
55
+ def __init__(self, exit_code: int) -> None:
56
+ super().__init__(exit_code)
57
+ self.exit_code = exit_code
@@ -17,7 +17,7 @@ import parser as parser_module
17
17
  import proc
18
18
  import tokens as tokens_module
19
19
  from context import RUNNER_BUILTINS, STATE_BUILTINS, BuiltinContext, ExecContext
20
- from errors import UnsupportedConstruct
20
+ from errors import ShellExit, UnsupportedConstruct
21
21
  from state import ShellState
22
22
 
23
23
  DEVNULL = os.devnull
@@ -209,6 +209,7 @@ def execute(list_node: nodes.CommandList, ctx: ExecContext) -> int:
209
209
  exit_code = 0
210
210
  for entry in list_node.entries:
211
211
  exit_code = _execute_andor(entry, ctx)
212
+ ctx.state.last_exit_code = exit_code
212
213
  return exit_code
213
214
 
214
215
 
@@ -222,6 +223,7 @@ def _execute_andor(andor: nodes.AndOr, ctx: ExecContext) -> int:
222
223
  if operator == "||" and exit_code == 0:
223
224
  continue
224
225
  exit_code = _execute_pipeline(pipeline, ctx)
226
+ ctx.state.last_exit_code = exit_code
225
227
  return exit_code
226
228
 
227
229
 
@@ -310,6 +312,8 @@ def _run_pipeline_elements(elements: list, ctx: ExecContext) -> int:
310
312
  # fabricated exit-0/empty-output success.
311
313
  refusals[idx] = exc
312
314
  results[idx] = 1
315
+ except ShellExit as exc:
316
+ results[idx] = exc.exit_code
313
317
  except BaseException as exc: # noqa: BLE001 - any other stage failure must not crash the engine
314
318
  # Any OTHER exception is a real per-stage failure, not a refusal: it
315
319
  # gets a named, actionable one-line message on the merged sink (never
@@ -477,7 +481,10 @@ def _execute_subshell(node: nodes.Subshell, ctx: ExecContext, stdin_stream, stdo
477
481
  )
478
482
  isolated_state = ctx.state.copy()
479
483
  inner_ctx = _sub_ctx(ctx, isolated_state, r_in, r_out, r_err)
480
- return execute(node.body, inner_ctx)
484
+ try:
485
+ return execute(node.body, inner_ctx)
486
+ except ShellExit as exc:
487
+ return exc.exit_code
481
488
  finally:
482
489
  tracker.close()
483
490
 
@@ -569,6 +576,19 @@ def _as_stream(fd_or_stream: BinaryIO | int, mode: str) -> BinaryIO:
569
576
 
570
577
 
571
578
  def _run_state_builtin(name: str, argv: list[str], ctx: ExecContext, out_stream: BinaryIO | int) -> int:
579
+ if name == "exit":
580
+ if len(argv) > 2:
581
+ _write_merged(out_stream, b"exit: too many arguments\n", ctx)
582
+ raise ShellExit(1)
583
+ if len(argv) == 1:
584
+ raise ShellExit(ctx.state.last_exit_code)
585
+ try:
586
+ exit_code = int(argv[1], 10)
587
+ except ValueError:
588
+ _write_merged(out_stream, f"exit: {argv[1]}: numeric argument required\n".encode("utf-8"), ctx)
589
+ raise ShellExit(2)
590
+ raise ShellExit(exit_code & 0xFF)
591
+
572
592
  if name == "cd":
573
593
  target = argv[1] if len(argv) > 1 else ctx.state.env.get("HOME")
574
594
  print_new_cwd = argv[1:2] == ["-"]
@@ -729,6 +749,9 @@ def run_command_substitution(src: str, ctx: ExecContext) -> tuple[str, int]:
729
749
  deadline=ctx.deadline,
730
750
  stderr=ctx.stderr,
731
751
  )
732
- exit_code = execute(ast, sub_ctx)
752
+ try:
753
+ exit_code = execute(ast, sub_ctx)
754
+ except ShellExit as exc:
755
+ exit_code = exc.exit_code
733
756
  text = buffer.getvalue().decode("utf-8", errors="replace")
734
757
  return text.rstrip("\n"), exit_code
@@ -97,6 +97,9 @@ def _resolve_param(name: str, op: str | None, arg: Word | None, ctx: "ExecContex
97
97
  split_and_glob_eligible is False here always; callers decide splitting based on
98
98
  quoting context (Raw vs DQ), not on the parameter's own nature.
99
99
  """
100
+ if name == "?" and op is None:
101
+ return str(ctx.state.last_exit_code), False
102
+
100
103
  env = ctx.state.env
101
104
  if op == "#len":
102
105
  value = env.get(name, "")
@@ -17,7 +17,7 @@ import exec as exec_module
17
17
  import parser as parser_module
18
18
  import tokens as tokens_module
19
19
  from context import ExecContext
20
- from errors import UnsupportedConstruct
20
+ from errors import ShellExit, UnsupportedConstruct
21
21
  from expand import ParamExpansionError
22
22
  from state import ShellState
23
23
 
@@ -97,6 +97,9 @@ def main() -> int:
97
97
  tokens = tokens_module.tokenize(command)
98
98
  ast = parser_module.parse(tokens)
99
99
  exit_code = exec_module.execute(ast, ctx)
100
+ except ShellExit as exc:
101
+ _write_frame(exc.exit_code, state.cwd, state.delta(original_env), None)
102
+ return 0
100
103
  except UnsupportedConstruct as exc:
101
104
  output.write(exc.message.encode("utf-8", errors="replace"))
102
105
  _write_frame(
@@ -64,6 +64,7 @@ class ShellState:
64
64
 
65
65
  cwd: str
66
66
  env: ShellEnvironment = field(default_factory=ShellEnvironment)
67
+ last_exit_code: int = 0
67
68
 
68
69
  def __post_init__(self) -> None:
69
70
  if not isinstance(self.env, ShellEnvironment):
@@ -71,7 +72,7 @@ class ShellState:
71
72
 
72
73
  def copy(self) -> "ShellState":
73
74
  """Return an independent copy (used for subshell isolation)."""
74
- return ShellState(cwd=self.cwd, env=self.env.copy())
75
+ return ShellState(cwd=self.cwd, env=self.env.copy(), last_exit_code=self.last_exit_code)
75
76
 
76
77
  def chdir(self, path: str) -> None:
77
78
  """Validate `path` exists and is a directory, then update cwd + OLDPWD."""
@@ -294,6 +294,8 @@ def _scan_dollar_form(src: str, pos: int) -> tuple[Segment, int]:
294
294
  )
295
295
  close = _find_closing_paren(src, pos + 2)
296
296
  return CmdSub(src=src[pos + 2 : close]), close + 1
297
+ if nxt == "?":
298
+ return Param(name="?", op=None, arg=None), pos + 2
297
299
  if nxt and (_IDENT_START_RE.match(nxt)):
298
300
  m = _IDENT_RE.match(src, pos + 1)
299
301
  assert m is not None
@@ -39,6 +39,38 @@ export declare function runtimesDir(kind: string, agentDir: string): string;
39
39
  export declare function modelsDir(kind: string, agentDir: string): string;
40
40
  /** `<agentDir>/sessions` -- session transcript storage (large, established; not a "loose file"). */
41
41
  export declare function sessionsDir(agentDir: string): string;
42
+ /**
43
+ * `<agentDir>/state/orchestration/sessions/<session-key>` -- the one durable control-plane
44
+ * bundle owned by a foreground session. Event state, worker mailboxes, mutation journals, and
45
+ * worker transcripts must stay beneath this boundary so explicit session deletion can remove
46
+ * exactly its companion artifacts without scanning global state.
47
+ */
48
+ export declare function orchestrationSessionsDir(agentDir: string): string;
49
+ /**
50
+ * `<agentDir>/state/orchestration/sessions/<session-key>` -- the one durable control-plane
51
+ * bundle owned by a foreground session.
52
+ */
53
+ export declare function orchestrationSessionDir(agentDir: string, parentSessionId: string): string;
54
+ /** `<orchestrationSessionDir>/events` -- append-only event tail, snapshot, cursor, and idempotency state. */
55
+ export declare function orchestrationEventStoreDir(agentDir: string, parentSessionId: string): string;
56
+ /**
57
+ * `<orchestrationSessionDir>/worker-conversations` -- durable Pi worker transcripts owned by one
58
+ * foreground session. Worker conversations remain in SessionManager's established JSONL format,
59
+ * but are intentionally outside the foreground session picker namespace.
60
+ */
61
+ export declare function workerConversationSessionsDir(agentDir: string, parentSessionId: string): string;
62
+ /**
63
+ * `<orchestrationSessionDir>/worker-mailboxes/<scope-digest>.json` -- durable bounded control
64
+ * messages for one logical worker. Identity stays hashed so neither agent ids nor project paths
65
+ * become path segments.
66
+ */
67
+ export declare function workerAgentMailboxFile(agentDir: string, parentSessionId: string, scopeDigest: string): string;
68
+ /**
69
+ * `<orchestrationSessionDir>/worker-actions/<scope-digest>.json` -- durable, bounded mutation
70
+ * intents and receipts for one fenced worker attempt. The opaque digest intentionally keeps task
71
+ * identifiers out of filesystem path segments and works on Windows and WSL.
72
+ */
73
+ export declare function workerActionJournalFile(agentDir: string, parentSessionId: string, scopeDigest: string): string;
42
74
  /** `<agentDir>/npm` -- managed npm package installs. */
43
75
  export declare function npmDir(agentDir: string): string;
44
76
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"agent-paths.d.ts","sourceRoot":"","sources":["../../src/core/agent-paths.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Typed path SSOT for everything machine-managed under `<agentDir>` (`~/.pi/agent/` by default,\n * `getAgentDir()` in `../config.ts`). Every writer that persists machine data (stores, caches, managed\n * runtimes/models, cross-process coordination) MUST resolve its path through one of the accessors\n * below instead of hand-rolling `join(agentDir, …)` — that ad-hoc pattern is exactly how root-level\n * stragglers like `trust.json` accumulated, and nothing stopped the next writer from doing it again.\n *\n * Canonical layout:\n * ```\n * <agentDir>/\n * auth.json settings.json models.json keybindings.json MEMORY.md USER.md SYSTEM.md … user CONFIG/MEMORY (root, kept)\n * okf-memory/ authored memory (root, kept)\n * skills/ extensions/ prompts/ themes/ profiles/ user RESOURCES (root, kept)\n * profiles/directories/<workspace-hash>/settings.json directory overlays\n * state/ durable machine state (model adaptation/fitness, tool performance,\n * learning observations, trust decisions, config backups, …) -- stateDir/stateFile\n * cache/ rebuildable, safe to delete (tool-path probes, jiti transform cache, uv) -- cacheDir/cacheFile\n * work/ transient/scratch, delegated to work-directory.ts (tenant/run/lease),\n * including context/sessions/<session-id>/{gc,artifacts} -- re-exported below\n * runtimes/<kind> models/<kind> -- runtimesDir/modelsDir\n * npm/ git/ sessions/ -- npmDir/gitDir/sessionsDir\n * worktrees/<repo-slug>/<laneKey> durable lane checkouts (core/worktree-sync) -- worktreesDir\n * ```\n *\n * Every accessor takes `agentDir` as an explicit, required first argument -- deliberately mirroring\n * `work-directory.ts`'s existing `getWorkRoot(agentDir)` convention rather than defaulting to\n * `getAgentDir()` internally. Several real callers (stores' `forAgentDir`, test harnesses with a temp\n * agentDir) build paths for a NON-default agentDir; a hidden default would silently resolve the wrong\n * root for those callers instead of failing loudly. Callers operating on the process-wide default pass\n * `getAgentDir()` explicitly at the call site.\n *\n * These accessors are pure path builders -- no directory creation, no I/O. Every existing writer\n * already creates its parent directory at write time (see `util/atomic-file.ts`'s\n * `mkdirSync(dirname(filePath), { recursive: true })`), so duplicating that here would be redundant\n * and would blur the \"pure function\" contract readers rely on.\n */\nimport { join } from \"node:path\";\nimport {\n\tacquireWorkRun,\n\tassertPortablePathSegment,\n\tboundedWorkRetention,\n\tcreateWorkRunId,\n\tgetProcessWorkRun,\n\tgetWorkRoot,\n\tgetWorkRunDir,\n\tgetWorkTenantDir,\n\thasActiveWorkRunLease,\n\tpruneWorkTenant,\n} from \"../utils/work-directory.ts\";\nimport { getReloadCoordinationDir } from \"./reload-blockers.ts\";\n\n/** Root entries reserved for user-authored configuration and memory. */\nexport const AGENT_ROOT_FILE_NAMES = [\n\t\"auth.json\",\n\t\"settings.json\",\n\t\"models.json\",\n\t\"keybindings.json\",\n\t\"MEMORY.md\",\n\t\"USER.md\",\n\t\"SYSTEM.md\",\n\t\"APPEND_SYSTEM.md\",\n] as const;\n\n/** Root entries reserved for user resources and machine-managed storage classes. */\nexport const AGENT_ROOT_DIRECTORY_NAMES = [\n\t\"okf-memory\",\n\t\"skills\",\n\t\"extensions\",\n\t\"prompts\",\n\t\"themes\",\n\t\"profiles\",\n\t\"state\",\n\t\"cache\",\n\t\"bin\",\n\t\"work\",\n\t\"runtimes\",\n\t\"models\",\n\t\"sessions\",\n\t\"npm\",\n\t\"git\",\n\t\"worktrees\",\n] as const;\n\nconst AGENT_ROOT_ENTRY_NAMES = new Set<string>([...AGENT_ROOT_FILE_NAMES, ...AGENT_ROOT_DIRECTORY_NAMES]);\n\nexport function isCanonicalAgentRootEntry(name: string): boolean {\n\treturn AGENT_ROOT_ENTRY_NAMES.has(name);\n}\n\n/** `<agentDir>/<name>` -- a root-level user config/memory file (auth.json, settings.json, MEMORY.md, …). */\nexport function configFile(agentDir: string, name: string): string {\n\treturn join(agentDir, name);\n}\n\n/** `<agentDir>/okf-memory` -- user-authored durable OKF memory documents. */\nexport function okfMemoryDir(agentDir: string): string {\n\treturn join(agentDir, \"okf-memory\");\n}\n\n/** `<agentDir>/state` -- durable machine-managed state. Deleting it loses real history, not just cache. */\nexport function stateDir(agentDir: string): string {\n\treturn join(agentDir, \"state\");\n}\n\n/** `<agentDir>/state/<segments…>` */\nexport function stateFile(agentDir: string, ...segments: string[]): string {\n\treturn join(stateDir(agentDir), ...segments);\n}\n\n/** `<agentDir>/state/attachments` -- bounded, session-keyed clipboard image attachments. */\nexport function attachmentsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"attachments\");\n}\n\n/** `<agentDir>/state/secrets` -- encrypted credential vault and owner-approved materializations. */\nexport function secretsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"secrets\");\n}\n\n/** `<agentDir>/state/secrets/vault.json` -- encrypted, versioned generic credential vault. */\nexport function secretVaultFile(agentDir: string): string {\n\treturn join(secretsDir(agentDir), \"vault.json\");\n}\n\n/** `<agentDir>/state/secrets/materialized` -- private generated dotenv files, grouped by profile. */\nexport function managedSecretEnvDir(agentDir: string): string {\n\treturn join(secretsDir(agentDir), \"materialized\");\n}\n\n/** `<agentDir>/state/extensions/<namespace>` -- durable state owned by one extension. */\nexport function extensionStateDir(agentDir: string, namespace: string): string {\n\tassertPortablePathSegment(\"Extension namespace\", namespace);\n\treturn stateFile(agentDir, \"extensions\", namespace);\n}\n\n/** `<agentDir>/state/backups/config` -- explicit user-requested configuration snapshots. */\nexport function configBackupsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"backups\", \"config\");\n}\n\n/** `<agentDir>/cache` -- rebuildable; safe to delete (the next run just re-probes/recomputes). */\nexport function cacheDir(agentDir: string): string {\n\treturn join(agentDir, \"cache\");\n}\n\n/** `<agentDir>/cache/<segments…>` */\nexport function cacheFile(agentDir: string, ...segments: string[]): string {\n\treturn join(cacheDir(agentDir), ...segments);\n}\n\n/** `<agentDir>/cache/extensions/<namespace>` -- rebuildable cache owned by one extension. */\nexport function extensionCacheDir(agentDir: string, namespace: string): string {\n\tassertPortablePathSegment(\"Extension namespace\", namespace);\n\treturn cacheFile(agentDir, \"extensions\", namespace);\n}\n\n/** `<agentDir>/bin` -- managed executable helpers (fd, rg). */\nexport function binDir(agentDir: string): string {\n\treturn join(agentDir, \"bin\");\n}\n\n/** `<agentDir>/runtimes/<kind>` -- a managed runtime install (ollama, python, prism-llamacpp, needle, …). */\nexport function runtimesDir(kind: string, agentDir: string): string {\n\treturn join(agentDir, \"runtimes\", kind);\n}\n\n/** `<agentDir>/models/<kind>` -- downloaded model weights, grouped by provider/runtime. */\nexport function modelsDir(kind: string, agentDir: string): string {\n\treturn join(agentDir, \"models\", kind);\n}\n\n/** `<agentDir>/sessions` -- session transcript storage (large, established; not a \"loose file\"). */\nexport function sessionsDir(agentDir: string): string {\n\treturn join(agentDir, \"sessions\");\n}\n\n/** `<agentDir>/npm` -- managed npm package installs. */\nexport function npmDir(agentDir: string): string {\n\treturn join(agentDir, \"npm\");\n}\n\n/**\n * `<agentDir>/worktrees` -- lane worktree checkouts for the worktree-sync subsystem\n * (`core/worktree-sync/`), grouped as `worktrees/<repo-slug>/<laneKey>`. These hold REAL\n * uncommitted agent work, so they are durable like `state/` -- never under transient `work/`,\n * whose retention would silently eat in-progress code.\n */\nexport function worktreesDir(agentDir: string): string {\n\treturn join(agentDir, \"worktrees\");\n}\n\n/** `<agentDir>/git` -- managed git-sourced package installs. */\nexport function gitDir(agentDir: string): string {\n\treturn join(agentDir, \"git\");\n}\n\nexport type AgentResourceKind = \"skills\" | \"prompts\" | \"themes\" | \"extensions\" | \"profiles\";\n\n/** `<agentDir>/<kind>` -- a user-managed resource directory. Root, kept: moving it breaks users. */\nexport function resourceDir(kind: AgentResourceKind, agentDir: string): string {\n\treturn join(agentDir, kind);\n}\n\n/** `<agentDir>/profiles/directories` -- durable per-directory resource-profile overlays. */\nexport function directoryProfilesDir(agentDir: string): string {\n\treturn join(resourceDir(\"profiles\", agentDir), \"directories\");\n}\n\n/**\n * `work/` is a mature transient/scratch root with its own tenant/run/lease/retention machinery\n * (`utils/work-directory.ts`). The SSOT delegates to it wholesale instead of reimplementing -- these\n * are straight re-exports so every category (state/cache/work/runtimes/models/…) is reachable from one\n * module without duplicating `work-directory.ts`'s logic.\n */\nexport {\n\tgetWorkRoot,\n\tassertPortablePathSegment,\n\tboundedWorkRetention,\n\tgetWorkTenantDir,\n\tgetWorkRunDir,\n\tgetProcessWorkRun,\n\thasActiveWorkRunLease,\n\tacquireWorkRun,\n\tcreateWorkRunId,\n\tpruneWorkTenant,\n};\nexport type { AcquireWorkRunOptions, WorkRetentionOptions, WorkRunLease } from \"../utils/work-directory.ts\";\n\n/**\n * `work/reload-coordination` -- cross-process reload/live-op coordination state. Already correctly\n * work-scoped (defined in `reload-blockers.ts`, its natural home given the surrounding reload-gate\n * logic there); re-exported here under the taxonomy's canonical name for SSOT discoverability.\n */\nexport const reloadCoordinationDir = getReloadCoordinationDir;\n"]}
1
+ {"version":3,"file":"agent-paths.d.ts","sourceRoot":"","sources":["../../src/core/agent-paths.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Typed path SSOT for everything machine-managed under `<agentDir>` (`~/.pi/agent/` by default,\n * `getAgentDir()` in `../config.ts`). Every writer that persists machine data (stores, caches, managed\n * runtimes/models, cross-process coordination) MUST resolve its path through one of the accessors\n * below instead of hand-rolling `join(agentDir, …)` — that ad-hoc pattern is exactly how root-level\n * stragglers like `trust.json` accumulated, and nothing stopped the next writer from doing it again.\n *\n * Canonical layout:\n * ```\n * <agentDir>/\n * auth.json settings.json models.json keybindings.json MEMORY.md USER.md SYSTEM.md … user CONFIG/MEMORY (root, kept)\n * okf-memory/ authored memory (root, kept)\n * skills/ extensions/ prompts/ themes/ profiles/ user RESOURCES (root, kept)\n * profiles/directories/<workspace-hash>/settings.json directory overlays\n * state/ durable machine state (model adaptation/fitness, tool performance,\n * learning observations, trust decisions, config backups, …) -- stateDir/stateFile\n * cache/ rebuildable, safe to delete (tool-path probes, jiti transform cache, uv) -- cacheDir/cacheFile\n * work/ transient/scratch, delegated to work-directory.ts (tenant/run/lease),\n * including context/sessions/<session-id>/{gc,artifacts} -- re-exported below\n * runtimes/<kind> models/<kind> -- runtimesDir/modelsDir\n * npm/ git/ sessions/ -- npmDir/gitDir/sessionsDir\n * state/orchestration/sessions/<session-key>/ -- one foreground-session-owned\n * control-plane bundle\n * worktrees/<repo-slug>/<laneKey> durable lane checkouts (core/worktree-sync) -- worktreesDir\n * ```\n *\n * Every accessor takes `agentDir` as an explicit, required first argument -- deliberately mirroring\n * `work-directory.ts`'s existing `getWorkRoot(agentDir)` convention rather than defaulting to\n * `getAgentDir()` internally. Several real callers (stores' `forAgentDir`, test harnesses with a temp\n * agentDir) build paths for a NON-default agentDir; a hidden default would silently resolve the wrong\n * root for those callers instead of failing loudly. Callers operating on the process-wide default pass\n * `getAgentDir()` explicitly at the call site.\n *\n * These accessors are pure path builders -- no directory creation, no I/O. Every existing writer\n * already creates its parent directory at write time (see `util/atomic-file.ts`'s\n * `mkdirSync(dirname(filePath), { recursive: true })`), so duplicating that here would be redundant\n * and would blur the \"pure function\" contract readers rely on.\n */\nimport { createHash } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport {\n\tacquireWorkRun,\n\tassertPortablePathSegment,\n\tboundedWorkRetention,\n\tcreateWorkRunId,\n\tgetProcessWorkRun,\n\tgetWorkRoot,\n\tgetWorkRunDir,\n\tgetWorkTenantDir,\n\thasActiveWorkRunLease,\n\tpruneWorkTenant,\n} from \"../utils/work-directory.ts\";\nimport { getReloadCoordinationDir } from \"./reload-blockers.ts\";\nimport { requireBoundedTrimmedText } from \"./util/bounded-value.ts\";\n\n/** Root entries reserved for user-authored configuration and memory. */\nexport const AGENT_ROOT_FILE_NAMES = [\n\t\"auth.json\",\n\t\"settings.json\",\n\t\"models.json\",\n\t\"keybindings.json\",\n\t\"MEMORY.md\",\n\t\"USER.md\",\n\t\"SYSTEM.md\",\n\t\"APPEND_SYSTEM.md\",\n] as const;\n\n/** Root entries reserved for user resources and machine-managed storage classes. */\nexport const AGENT_ROOT_DIRECTORY_NAMES = [\n\t\"okf-memory\",\n\t\"skills\",\n\t\"extensions\",\n\t\"prompts\",\n\t\"themes\",\n\t\"profiles\",\n\t\"state\",\n\t\"cache\",\n\t\"bin\",\n\t\"work\",\n\t\"runtimes\",\n\t\"models\",\n\t\"sessions\",\n\t\"npm\",\n\t\"git\",\n\t\"worktrees\",\n] as const;\n\nconst AGENT_ROOT_ENTRY_NAMES = new Set<string>([...AGENT_ROOT_FILE_NAMES, ...AGENT_ROOT_DIRECTORY_NAMES]);\n\nexport function isCanonicalAgentRootEntry(name: string): boolean {\n\treturn AGENT_ROOT_ENTRY_NAMES.has(name);\n}\n\n/** `<agentDir>/<name>` -- a root-level user config/memory file (auth.json, settings.json, MEMORY.md, …). */\nexport function configFile(agentDir: string, name: string): string {\n\treturn join(agentDir, name);\n}\n\n/** `<agentDir>/okf-memory` -- user-authored durable OKF memory documents. */\nexport function okfMemoryDir(agentDir: string): string {\n\treturn join(agentDir, \"okf-memory\");\n}\n\n/** `<agentDir>/state` -- durable machine-managed state. Deleting it loses real history, not just cache. */\nexport function stateDir(agentDir: string): string {\n\treturn join(agentDir, \"state\");\n}\n\n/** `<agentDir>/state/<segments…>` */\nexport function stateFile(agentDir: string, ...segments: string[]): string {\n\treturn join(stateDir(agentDir), ...segments);\n}\n\n/** `<agentDir>/state/attachments` -- bounded, session-keyed clipboard image attachments. */\nexport function attachmentsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"attachments\");\n}\n\n/** `<agentDir>/state/secrets` -- encrypted credential vault and owner-approved materializations. */\nexport function secretsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"secrets\");\n}\n\n/** `<agentDir>/state/secrets/vault.json` -- encrypted, versioned generic credential vault. */\nexport function secretVaultFile(agentDir: string): string {\n\treturn join(secretsDir(agentDir), \"vault.json\");\n}\n\n/** `<agentDir>/state/secrets/materialized` -- private generated dotenv files, grouped by profile. */\nexport function managedSecretEnvDir(agentDir: string): string {\n\treturn join(secretsDir(agentDir), \"materialized\");\n}\n\n/** `<agentDir>/state/extensions/<namespace>` -- durable state owned by one extension. */\nexport function extensionStateDir(agentDir: string, namespace: string): string {\n\tassertPortablePathSegment(\"Extension namespace\", namespace);\n\treturn stateFile(agentDir, \"extensions\", namespace);\n}\n\n/** `<agentDir>/state/backups/config` -- explicit user-requested configuration snapshots. */\nexport function configBackupsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"backups\", \"config\");\n}\n\n/** `<agentDir>/cache` -- rebuildable; safe to delete (the next run just re-probes/recomputes). */\nexport function cacheDir(agentDir: string): string {\n\treturn join(agentDir, \"cache\");\n}\n\n/** `<agentDir>/cache/<segments…>` */\nexport function cacheFile(agentDir: string, ...segments: string[]): string {\n\treturn join(cacheDir(agentDir), ...segments);\n}\n\n/** `<agentDir>/cache/extensions/<namespace>` -- rebuildable cache owned by one extension. */\nexport function extensionCacheDir(agentDir: string, namespace: string): string {\n\tassertPortablePathSegment(\"Extension namespace\", namespace);\n\treturn cacheFile(agentDir, \"extensions\", namespace);\n}\n\n/** `<agentDir>/bin` -- managed executable helpers (fd, rg). */\nexport function binDir(agentDir: string): string {\n\treturn join(agentDir, \"bin\");\n}\n\n/** `<agentDir>/runtimes/<kind>` -- a managed runtime install (ollama, python, prism-llamacpp, needle, …). */\nexport function runtimesDir(kind: string, agentDir: string): string {\n\treturn join(agentDir, \"runtimes\", kind);\n}\n\n/** `<agentDir>/models/<kind>` -- downloaded model weights, grouped by provider/runtime. */\nexport function modelsDir(kind: string, agentDir: string): string {\n\treturn join(agentDir, \"models\", kind);\n}\n\n/** `<agentDir>/sessions` -- session transcript storage (large, established; not a \"loose file\"). */\nexport function sessionsDir(agentDir: string): string {\n\treturn join(agentDir, \"sessions\");\n}\n\nfunction orchestrationSessionKey(parentSessionId: string): string {\n\tconst normalized = requireBoundedTrimmedText(parentSessionId, 512, \"Parent session id\");\n\tconst readable =\n\t\tencodeURIComponent(normalized)\n\t\t\t.replaceAll(\"%\", \"_\")\n\t\t\t// encodeURIComponent deliberately leaves `*` unescaped, but Windows forbids it in paths.\n\t\t\t// Restrict the readable prefix to a portable ASCII subset; the digest retains exact identity.\n\t\t\t.replaceAll(/[^a-zA-Z0-9._~-]/g, \"_\")\n\t\t\t.slice(0, 80) || \"session\";\n\tconst digest = createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n\treturn `${readable}-${digest}`;\n}\n\n/**\n * `<agentDir>/state/orchestration/sessions/<session-key>` -- the one durable control-plane\n * bundle owned by a foreground session. Event state, worker mailboxes, mutation journals, and\n * worker transcripts must stay beneath this boundary so explicit session deletion can remove\n * exactly its companion artifacts without scanning global state.\n */\nexport function orchestrationSessionsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"orchestration\", \"sessions\");\n}\n\n/**\n * `<agentDir>/state/orchestration/sessions/<session-key>` -- the one durable control-plane\n * bundle owned by a foreground session.\n */\nexport function orchestrationSessionDir(agentDir: string, parentSessionId: string): string {\n\treturn join(orchestrationSessionsDir(agentDir), orchestrationSessionKey(parentSessionId));\n}\n\n/** `<orchestrationSessionDir>/events` -- append-only event tail, snapshot, cursor, and idempotency state. */\nexport function orchestrationEventStoreDir(agentDir: string, parentSessionId: string): string {\n\treturn join(orchestrationSessionDir(agentDir, parentSessionId), \"events\");\n}\n\n/**\n * `<orchestrationSessionDir>/worker-conversations` -- durable Pi worker transcripts owned by one\n * foreground session. Worker conversations remain in SessionManager's established JSONL format,\n * but are intentionally outside the foreground session picker namespace.\n */\nexport function workerConversationSessionsDir(agentDir: string, parentSessionId: string): string {\n\treturn join(orchestrationSessionDir(agentDir, parentSessionId), \"worker-conversations\");\n}\n\n/**\n * `<orchestrationSessionDir>/worker-mailboxes/<scope-digest>.json` -- durable bounded control\n * messages for one logical worker. Identity stays hashed so neither agent ids nor project paths\n * become path segments.\n */\nexport function workerAgentMailboxFile(agentDir: string, parentSessionId: string, scopeDigest: string): string {\n\tif (!/^[a-f0-9]{32,64}$/i.test(scopeDigest)) {\n\t\tthrow new TypeError(\"Worker agent mailbox scope digest must be a hexadecimal SHA-256 prefix.\");\n\t}\n\treturn join(\n\t\torchestrationSessionDir(agentDir, parentSessionId),\n\t\t\"worker-mailboxes\",\n\t\t`${scopeDigest.toLowerCase()}.json`,\n\t);\n}\n\n/**\n * `<orchestrationSessionDir>/worker-actions/<scope-digest>.json` -- durable, bounded mutation\n * intents and receipts for one fenced worker attempt. The opaque digest intentionally keeps task\n * identifiers out of filesystem path segments and works on Windows and WSL.\n */\nexport function workerActionJournalFile(agentDir: string, parentSessionId: string, scopeDigest: string): string {\n\tif (!/^[a-f0-9]{32,64}$/i.test(scopeDigest)) {\n\t\tthrow new TypeError(\"Worker action journal scope digest must be a hexadecimal SHA-256 prefix.\");\n\t}\n\treturn join(\n\t\torchestrationSessionDir(agentDir, parentSessionId),\n\t\t\"worker-actions\",\n\t\t`${scopeDigest.toLowerCase()}.json`,\n\t);\n}\n\n/** `<agentDir>/npm` -- managed npm package installs. */\nexport function npmDir(agentDir: string): string {\n\treturn join(agentDir, \"npm\");\n}\n\n/**\n * `<agentDir>/worktrees` -- lane worktree checkouts for the worktree-sync subsystem\n * (`core/worktree-sync/`), grouped as `worktrees/<repo-slug>/<laneKey>`. These hold REAL\n * uncommitted agent work, so they are durable like `state/` -- never under transient `work/`,\n * whose retention would silently eat in-progress code.\n */\nexport function worktreesDir(agentDir: string): string {\n\treturn join(agentDir, \"worktrees\");\n}\n\n/** `<agentDir>/git` -- managed git-sourced package installs. */\nexport function gitDir(agentDir: string): string {\n\treturn join(agentDir, \"git\");\n}\n\nexport type AgentResourceKind = \"skills\" | \"prompts\" | \"themes\" | \"extensions\" | \"profiles\";\n\n/** `<agentDir>/<kind>` -- a user-managed resource directory. Root, kept: moving it breaks users. */\nexport function resourceDir(kind: AgentResourceKind, agentDir: string): string {\n\treturn join(agentDir, kind);\n}\n\n/** `<agentDir>/profiles/directories` -- durable per-directory resource-profile overlays. */\nexport function directoryProfilesDir(agentDir: string): string {\n\treturn join(resourceDir(\"profiles\", agentDir), \"directories\");\n}\n\n/**\n * `work/` is a mature transient/scratch root with its own tenant/run/lease/retention machinery\n * (`utils/work-directory.ts`). The SSOT delegates to it wholesale instead of reimplementing -- these\n * are straight re-exports so every category (state/cache/work/runtimes/models/…) is reachable from one\n * module without duplicating `work-directory.ts`'s logic.\n */\nexport {\n\tgetWorkRoot,\n\tassertPortablePathSegment,\n\tboundedWorkRetention,\n\tgetWorkTenantDir,\n\tgetWorkRunDir,\n\tgetProcessWorkRun,\n\thasActiveWorkRunLease,\n\tacquireWorkRun,\n\tcreateWorkRunId,\n\tpruneWorkTenant,\n};\nexport type { AcquireWorkRunOptions, WorkRetentionOptions, WorkRunLease } from \"../utils/work-directory.ts\";\n\n/**\n * `work/reload-coordination` -- cross-process reload/live-op coordination state. Already correctly\n * work-scoped (defined in `reload-blockers.ts`, its natural home given the surrounding reload-gate\n * logic there); re-exported here under the taxonomy's canonical name for SSOT discoverability.\n */\nexport const reloadCoordinationDir = getReloadCoordinationDir;\n"]}
@@ -19,6 +19,8 @@
19
19
  * including context/sessions/<session-id>/{gc,artifacts} -- re-exported below
20
20
  * runtimes/<kind> models/<kind> -- runtimesDir/modelsDir
21
21
  * npm/ git/ sessions/ -- npmDir/gitDir/sessionsDir
22
+ * state/orchestration/sessions/<session-key>/ -- one foreground-session-owned
23
+ * control-plane bundle
22
24
  * worktrees/<repo-slug>/<laneKey> durable lane checkouts (core/worktree-sync) -- worktreesDir
23
25
  * ```
24
26
  *
@@ -34,9 +36,11 @@
34
36
  * `mkdirSync(dirname(filePath), { recursive: true })`), so duplicating that here would be redundant
35
37
  * and would blur the "pure function" contract readers rely on.
36
38
  */
39
+ import { createHash } from "node:crypto";
37
40
  import { join } from "node:path";
38
41
  import { acquireWorkRun, assertPortablePathSegment, boundedWorkRetention, createWorkRunId, getProcessWorkRun, getWorkRoot, getWorkRunDir, getWorkTenantDir, hasActiveWorkRunLease, pruneWorkTenant, } from "../utils/work-directory.js";
39
42
  import { getReloadCoordinationDir } from "./reload-blockers.js";
43
+ import { requireBoundedTrimmedText } from "./util/bounded-value.js";
40
44
  /** Root entries reserved for user-authored configuration and memory. */
41
45
  export const AGENT_ROOT_FILE_NAMES = [
42
46
  "auth.json",
@@ -141,6 +145,67 @@ export function modelsDir(kind, agentDir) {
141
145
  export function sessionsDir(agentDir) {
142
146
  return join(agentDir, "sessions");
143
147
  }
148
+ function orchestrationSessionKey(parentSessionId) {
149
+ const normalized = requireBoundedTrimmedText(parentSessionId, 512, "Parent session id");
150
+ const readable = encodeURIComponent(normalized)
151
+ .replaceAll("%", "_")
152
+ // encodeURIComponent deliberately leaves `*` unescaped, but Windows forbids it in paths.
153
+ // Restrict the readable prefix to a portable ASCII subset; the digest retains exact identity.
154
+ .replaceAll(/[^a-zA-Z0-9._~-]/g, "_")
155
+ .slice(0, 80) || "session";
156
+ const digest = createHash("sha256").update(normalized).digest("hex").slice(0, 16);
157
+ return `${readable}-${digest}`;
158
+ }
159
+ /**
160
+ * `<agentDir>/state/orchestration/sessions/<session-key>` -- the one durable control-plane
161
+ * bundle owned by a foreground session. Event state, worker mailboxes, mutation journals, and
162
+ * worker transcripts must stay beneath this boundary so explicit session deletion can remove
163
+ * exactly its companion artifacts without scanning global state.
164
+ */
165
+ export function orchestrationSessionsDir(agentDir) {
166
+ return stateFile(agentDir, "orchestration", "sessions");
167
+ }
168
+ /**
169
+ * `<agentDir>/state/orchestration/sessions/<session-key>` -- the one durable control-plane
170
+ * bundle owned by a foreground session.
171
+ */
172
+ export function orchestrationSessionDir(agentDir, parentSessionId) {
173
+ return join(orchestrationSessionsDir(agentDir), orchestrationSessionKey(parentSessionId));
174
+ }
175
+ /** `<orchestrationSessionDir>/events` -- append-only event tail, snapshot, cursor, and idempotency state. */
176
+ export function orchestrationEventStoreDir(agentDir, parentSessionId) {
177
+ return join(orchestrationSessionDir(agentDir, parentSessionId), "events");
178
+ }
179
+ /**
180
+ * `<orchestrationSessionDir>/worker-conversations` -- durable Pi worker transcripts owned by one
181
+ * foreground session. Worker conversations remain in SessionManager's established JSONL format,
182
+ * but are intentionally outside the foreground session picker namespace.
183
+ */
184
+ export function workerConversationSessionsDir(agentDir, parentSessionId) {
185
+ return join(orchestrationSessionDir(agentDir, parentSessionId), "worker-conversations");
186
+ }
187
+ /**
188
+ * `<orchestrationSessionDir>/worker-mailboxes/<scope-digest>.json` -- durable bounded control
189
+ * messages for one logical worker. Identity stays hashed so neither agent ids nor project paths
190
+ * become path segments.
191
+ */
192
+ export function workerAgentMailboxFile(agentDir, parentSessionId, scopeDigest) {
193
+ if (!/^[a-f0-9]{32,64}$/i.test(scopeDigest)) {
194
+ throw new TypeError("Worker agent mailbox scope digest must be a hexadecimal SHA-256 prefix.");
195
+ }
196
+ return join(orchestrationSessionDir(agentDir, parentSessionId), "worker-mailboxes", `${scopeDigest.toLowerCase()}.json`);
197
+ }
198
+ /**
199
+ * `<orchestrationSessionDir>/worker-actions/<scope-digest>.json` -- durable, bounded mutation
200
+ * intents and receipts for one fenced worker attempt. The opaque digest intentionally keeps task
201
+ * identifiers out of filesystem path segments and works on Windows and WSL.
202
+ */
203
+ export function workerActionJournalFile(agentDir, parentSessionId, scopeDigest) {
204
+ if (!/^[a-f0-9]{32,64}$/i.test(scopeDigest)) {
205
+ throw new TypeError("Worker action journal scope digest must be a hexadecimal SHA-256 prefix.");
206
+ }
207
+ return join(orchestrationSessionDir(agentDir, parentSessionId), "worker-actions", `${scopeDigest.toLowerCase()}.json`);
208
+ }
144
209
  /** `<agentDir>/npm` -- managed npm package installs. */
145
210
  export function npmDir(agentDir) {
146
211
  return join(agentDir, "npm");
@@ -1 +1 @@
1
- {"version":3,"file":"agent-paths.js","sourceRoot":"","sources":["../../src/core/agent-paths.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Typed path SSOT for everything machine-managed under `<agentDir>` (`~/.pi/agent/` by default,\n * `getAgentDir()` in `../config.ts`). Every writer that persists machine data (stores, caches, managed\n * runtimes/models, cross-process coordination) MUST resolve its path through one of the accessors\n * below instead of hand-rolling `join(agentDir, …)` — that ad-hoc pattern is exactly how root-level\n * stragglers like `trust.json` accumulated, and nothing stopped the next writer from doing it again.\n *\n * Canonical layout:\n * ```\n * <agentDir>/\n * auth.json settings.json models.json keybindings.json MEMORY.md USER.md SYSTEM.md … user CONFIG/MEMORY (root, kept)\n * okf-memory/ authored memory (root, kept)\n * skills/ extensions/ prompts/ themes/ profiles/ user RESOURCES (root, kept)\n * profiles/directories/<workspace-hash>/settings.json directory overlays\n * state/ durable machine state (model adaptation/fitness, tool performance,\n * learning observations, trust decisions, config backups, …) -- stateDir/stateFile\n * cache/ rebuildable, safe to delete (tool-path probes, jiti transform cache, uv) -- cacheDir/cacheFile\n * work/ transient/scratch, delegated to work-directory.ts (tenant/run/lease),\n * including context/sessions/<session-id>/{gc,artifacts} -- re-exported below\n * runtimes/<kind> models/<kind> -- runtimesDir/modelsDir\n * npm/ git/ sessions/ -- npmDir/gitDir/sessionsDir\n * worktrees/<repo-slug>/<laneKey> durable lane checkouts (core/worktree-sync) -- worktreesDir\n * ```\n *\n * Every accessor takes `agentDir` as an explicit, required first argument -- deliberately mirroring\n * `work-directory.ts`'s existing `getWorkRoot(agentDir)` convention rather than defaulting to\n * `getAgentDir()` internally. Several real callers (stores' `forAgentDir`, test harnesses with a temp\n * agentDir) build paths for a NON-default agentDir; a hidden default would silently resolve the wrong\n * root for those callers instead of failing loudly. Callers operating on the process-wide default pass\n * `getAgentDir()` explicitly at the call site.\n *\n * These accessors are pure path builders -- no directory creation, no I/O. Every existing writer\n * already creates its parent directory at write time (see `util/atomic-file.ts`'s\n * `mkdirSync(dirname(filePath), { recursive: true })`), so duplicating that here would be redundant\n * and would blur the \"pure function\" contract readers rely on.\n */\nimport { join } from \"node:path\";\nimport {\n\tacquireWorkRun,\n\tassertPortablePathSegment,\n\tboundedWorkRetention,\n\tcreateWorkRunId,\n\tgetProcessWorkRun,\n\tgetWorkRoot,\n\tgetWorkRunDir,\n\tgetWorkTenantDir,\n\thasActiveWorkRunLease,\n\tpruneWorkTenant,\n} from \"../utils/work-directory.ts\";\nimport { getReloadCoordinationDir } from \"./reload-blockers.ts\";\n\n/** Root entries reserved for user-authored configuration and memory. */\nexport const AGENT_ROOT_FILE_NAMES = [\n\t\"auth.json\",\n\t\"settings.json\",\n\t\"models.json\",\n\t\"keybindings.json\",\n\t\"MEMORY.md\",\n\t\"USER.md\",\n\t\"SYSTEM.md\",\n\t\"APPEND_SYSTEM.md\",\n] as const;\n\n/** Root entries reserved for user resources and machine-managed storage classes. */\nexport const AGENT_ROOT_DIRECTORY_NAMES = [\n\t\"okf-memory\",\n\t\"skills\",\n\t\"extensions\",\n\t\"prompts\",\n\t\"themes\",\n\t\"profiles\",\n\t\"state\",\n\t\"cache\",\n\t\"bin\",\n\t\"work\",\n\t\"runtimes\",\n\t\"models\",\n\t\"sessions\",\n\t\"npm\",\n\t\"git\",\n\t\"worktrees\",\n] as const;\n\nconst AGENT_ROOT_ENTRY_NAMES = new Set<string>([...AGENT_ROOT_FILE_NAMES, ...AGENT_ROOT_DIRECTORY_NAMES]);\n\nexport function isCanonicalAgentRootEntry(name: string): boolean {\n\treturn AGENT_ROOT_ENTRY_NAMES.has(name);\n}\n\n/** `<agentDir>/<name>` -- a root-level user config/memory file (auth.json, settings.json, MEMORY.md, …). */\nexport function configFile(agentDir: string, name: string): string {\n\treturn join(agentDir, name);\n}\n\n/** `<agentDir>/okf-memory` -- user-authored durable OKF memory documents. */\nexport function okfMemoryDir(agentDir: string): string {\n\treturn join(agentDir, \"okf-memory\");\n}\n\n/** `<agentDir>/state` -- durable machine-managed state. Deleting it loses real history, not just cache. */\nexport function stateDir(agentDir: string): string {\n\treturn join(agentDir, \"state\");\n}\n\n/** `<agentDir>/state/<segments…>` */\nexport function stateFile(agentDir: string, ...segments: string[]): string {\n\treturn join(stateDir(agentDir), ...segments);\n}\n\n/** `<agentDir>/state/attachments` -- bounded, session-keyed clipboard image attachments. */\nexport function attachmentsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"attachments\");\n}\n\n/** `<agentDir>/state/secrets` -- encrypted credential vault and owner-approved materializations. */\nexport function secretsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"secrets\");\n}\n\n/** `<agentDir>/state/secrets/vault.json` -- encrypted, versioned generic credential vault. */\nexport function secretVaultFile(agentDir: string): string {\n\treturn join(secretsDir(agentDir), \"vault.json\");\n}\n\n/** `<agentDir>/state/secrets/materialized` -- private generated dotenv files, grouped by profile. */\nexport function managedSecretEnvDir(agentDir: string): string {\n\treturn join(secretsDir(agentDir), \"materialized\");\n}\n\n/** `<agentDir>/state/extensions/<namespace>` -- durable state owned by one extension. */\nexport function extensionStateDir(agentDir: string, namespace: string): string {\n\tassertPortablePathSegment(\"Extension namespace\", namespace);\n\treturn stateFile(agentDir, \"extensions\", namespace);\n}\n\n/** `<agentDir>/state/backups/config` -- explicit user-requested configuration snapshots. */\nexport function configBackupsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"backups\", \"config\");\n}\n\n/** `<agentDir>/cache` -- rebuildable; safe to delete (the next run just re-probes/recomputes). */\nexport function cacheDir(agentDir: string): string {\n\treturn join(agentDir, \"cache\");\n}\n\n/** `<agentDir>/cache/<segments…>` */\nexport function cacheFile(agentDir: string, ...segments: string[]): string {\n\treturn join(cacheDir(agentDir), ...segments);\n}\n\n/** `<agentDir>/cache/extensions/<namespace>` -- rebuildable cache owned by one extension. */\nexport function extensionCacheDir(agentDir: string, namespace: string): string {\n\tassertPortablePathSegment(\"Extension namespace\", namespace);\n\treturn cacheFile(agentDir, \"extensions\", namespace);\n}\n\n/** `<agentDir>/bin` -- managed executable helpers (fd, rg). */\nexport function binDir(agentDir: string): string {\n\treturn join(agentDir, \"bin\");\n}\n\n/** `<agentDir>/runtimes/<kind>` -- a managed runtime install (ollama, python, prism-llamacpp, needle, …). */\nexport function runtimesDir(kind: string, agentDir: string): string {\n\treturn join(agentDir, \"runtimes\", kind);\n}\n\n/** `<agentDir>/models/<kind>` -- downloaded model weights, grouped by provider/runtime. */\nexport function modelsDir(kind: string, agentDir: string): string {\n\treturn join(agentDir, \"models\", kind);\n}\n\n/** `<agentDir>/sessions` -- session transcript storage (large, established; not a \"loose file\"). */\nexport function sessionsDir(agentDir: string): string {\n\treturn join(agentDir, \"sessions\");\n}\n\n/** `<agentDir>/npm` -- managed npm package installs. */\nexport function npmDir(agentDir: string): string {\n\treturn join(agentDir, \"npm\");\n}\n\n/**\n * `<agentDir>/worktrees` -- lane worktree checkouts for the worktree-sync subsystem\n * (`core/worktree-sync/`), grouped as `worktrees/<repo-slug>/<laneKey>`. These hold REAL\n * uncommitted agent work, so they are durable like `state/` -- never under transient `work/`,\n * whose retention would silently eat in-progress code.\n */\nexport function worktreesDir(agentDir: string): string {\n\treturn join(agentDir, \"worktrees\");\n}\n\n/** `<agentDir>/git` -- managed git-sourced package installs. */\nexport function gitDir(agentDir: string): string {\n\treturn join(agentDir, \"git\");\n}\n\nexport type AgentResourceKind = \"skills\" | \"prompts\" | \"themes\" | \"extensions\" | \"profiles\";\n\n/** `<agentDir>/<kind>` -- a user-managed resource directory. Root, kept: moving it breaks users. */\nexport function resourceDir(kind: AgentResourceKind, agentDir: string): string {\n\treturn join(agentDir, kind);\n}\n\n/** `<agentDir>/profiles/directories` -- durable per-directory resource-profile overlays. */\nexport function directoryProfilesDir(agentDir: string): string {\n\treturn join(resourceDir(\"profiles\", agentDir), \"directories\");\n}\n\n/**\n * `work/` is a mature transient/scratch root with its own tenant/run/lease/retention machinery\n * (`utils/work-directory.ts`). The SSOT delegates to it wholesale instead of reimplementing -- these\n * are straight re-exports so every category (state/cache/work/runtimes/models/…) is reachable from one\n * module without duplicating `work-directory.ts`'s logic.\n */\nexport {\n\tgetWorkRoot,\n\tassertPortablePathSegment,\n\tboundedWorkRetention,\n\tgetWorkTenantDir,\n\tgetWorkRunDir,\n\tgetProcessWorkRun,\n\thasActiveWorkRunLease,\n\tacquireWorkRun,\n\tcreateWorkRunId,\n\tpruneWorkTenant,\n};\nexport type { AcquireWorkRunOptions, WorkRetentionOptions, WorkRunLease } from \"../utils/work-directory.ts\";\n\n/**\n * `work/reload-coordination` -- cross-process reload/live-op coordination state. Already correctly\n * work-scoped (defined in `reload-blockers.ts`, its natural home given the surrounding reload-gate\n * logic there); re-exported here under the taxonomy's canonical name for SSOT discoverability.\n */\nexport const reloadCoordinationDir = getReloadCoordinationDir;\n"]}
1
+ {"version":3,"file":"agent-paths.js","sourceRoot":"","sources":["../../src/core/agent-paths.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Typed path SSOT for everything machine-managed under `<agentDir>` (`~/.pi/agent/` by default,\n * `getAgentDir()` in `../config.ts`). Every writer that persists machine data (stores, caches, managed\n * runtimes/models, cross-process coordination) MUST resolve its path through one of the accessors\n * below instead of hand-rolling `join(agentDir, …)` — that ad-hoc pattern is exactly how root-level\n * stragglers like `trust.json` accumulated, and nothing stopped the next writer from doing it again.\n *\n * Canonical layout:\n * ```\n * <agentDir>/\n * auth.json settings.json models.json keybindings.json MEMORY.md USER.md SYSTEM.md … user CONFIG/MEMORY (root, kept)\n * okf-memory/ authored memory (root, kept)\n * skills/ extensions/ prompts/ themes/ profiles/ user RESOURCES (root, kept)\n * profiles/directories/<workspace-hash>/settings.json directory overlays\n * state/ durable machine state (model adaptation/fitness, tool performance,\n * learning observations, trust decisions, config backups, …) -- stateDir/stateFile\n * cache/ rebuildable, safe to delete (tool-path probes, jiti transform cache, uv) -- cacheDir/cacheFile\n * work/ transient/scratch, delegated to work-directory.ts (tenant/run/lease),\n * including context/sessions/<session-id>/{gc,artifacts} -- re-exported below\n * runtimes/<kind> models/<kind> -- runtimesDir/modelsDir\n * npm/ git/ sessions/ -- npmDir/gitDir/sessionsDir\n * state/orchestration/sessions/<session-key>/ -- one foreground-session-owned\n * control-plane bundle\n * worktrees/<repo-slug>/<laneKey> durable lane checkouts (core/worktree-sync) -- worktreesDir\n * ```\n *\n * Every accessor takes `agentDir` as an explicit, required first argument -- deliberately mirroring\n * `work-directory.ts`'s existing `getWorkRoot(agentDir)` convention rather than defaulting to\n * `getAgentDir()` internally. Several real callers (stores' `forAgentDir`, test harnesses with a temp\n * agentDir) build paths for a NON-default agentDir; a hidden default would silently resolve the wrong\n * root for those callers instead of failing loudly. Callers operating on the process-wide default pass\n * `getAgentDir()` explicitly at the call site.\n *\n * These accessors are pure path builders -- no directory creation, no I/O. Every existing writer\n * already creates its parent directory at write time (see `util/atomic-file.ts`'s\n * `mkdirSync(dirname(filePath), { recursive: true })`), so duplicating that here would be redundant\n * and would blur the \"pure function\" contract readers rely on.\n */\nimport { createHash } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport {\n\tacquireWorkRun,\n\tassertPortablePathSegment,\n\tboundedWorkRetention,\n\tcreateWorkRunId,\n\tgetProcessWorkRun,\n\tgetWorkRoot,\n\tgetWorkRunDir,\n\tgetWorkTenantDir,\n\thasActiveWorkRunLease,\n\tpruneWorkTenant,\n} from \"../utils/work-directory.ts\";\nimport { getReloadCoordinationDir } from \"./reload-blockers.ts\";\nimport { requireBoundedTrimmedText } from \"./util/bounded-value.ts\";\n\n/** Root entries reserved for user-authored configuration and memory. */\nexport const AGENT_ROOT_FILE_NAMES = [\n\t\"auth.json\",\n\t\"settings.json\",\n\t\"models.json\",\n\t\"keybindings.json\",\n\t\"MEMORY.md\",\n\t\"USER.md\",\n\t\"SYSTEM.md\",\n\t\"APPEND_SYSTEM.md\",\n] as const;\n\n/** Root entries reserved for user resources and machine-managed storage classes. */\nexport const AGENT_ROOT_DIRECTORY_NAMES = [\n\t\"okf-memory\",\n\t\"skills\",\n\t\"extensions\",\n\t\"prompts\",\n\t\"themes\",\n\t\"profiles\",\n\t\"state\",\n\t\"cache\",\n\t\"bin\",\n\t\"work\",\n\t\"runtimes\",\n\t\"models\",\n\t\"sessions\",\n\t\"npm\",\n\t\"git\",\n\t\"worktrees\",\n] as const;\n\nconst AGENT_ROOT_ENTRY_NAMES = new Set<string>([...AGENT_ROOT_FILE_NAMES, ...AGENT_ROOT_DIRECTORY_NAMES]);\n\nexport function isCanonicalAgentRootEntry(name: string): boolean {\n\treturn AGENT_ROOT_ENTRY_NAMES.has(name);\n}\n\n/** `<agentDir>/<name>` -- a root-level user config/memory file (auth.json, settings.json, MEMORY.md, …). */\nexport function configFile(agentDir: string, name: string): string {\n\treturn join(agentDir, name);\n}\n\n/** `<agentDir>/okf-memory` -- user-authored durable OKF memory documents. */\nexport function okfMemoryDir(agentDir: string): string {\n\treturn join(agentDir, \"okf-memory\");\n}\n\n/** `<agentDir>/state` -- durable machine-managed state. Deleting it loses real history, not just cache. */\nexport function stateDir(agentDir: string): string {\n\treturn join(agentDir, \"state\");\n}\n\n/** `<agentDir>/state/<segments…>` */\nexport function stateFile(agentDir: string, ...segments: string[]): string {\n\treturn join(stateDir(agentDir), ...segments);\n}\n\n/** `<agentDir>/state/attachments` -- bounded, session-keyed clipboard image attachments. */\nexport function attachmentsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"attachments\");\n}\n\n/** `<agentDir>/state/secrets` -- encrypted credential vault and owner-approved materializations. */\nexport function secretsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"secrets\");\n}\n\n/** `<agentDir>/state/secrets/vault.json` -- encrypted, versioned generic credential vault. */\nexport function secretVaultFile(agentDir: string): string {\n\treturn join(secretsDir(agentDir), \"vault.json\");\n}\n\n/** `<agentDir>/state/secrets/materialized` -- private generated dotenv files, grouped by profile. */\nexport function managedSecretEnvDir(agentDir: string): string {\n\treturn join(secretsDir(agentDir), \"materialized\");\n}\n\n/** `<agentDir>/state/extensions/<namespace>` -- durable state owned by one extension. */\nexport function extensionStateDir(agentDir: string, namespace: string): string {\n\tassertPortablePathSegment(\"Extension namespace\", namespace);\n\treturn stateFile(agentDir, \"extensions\", namespace);\n}\n\n/** `<agentDir>/state/backups/config` -- explicit user-requested configuration snapshots. */\nexport function configBackupsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"backups\", \"config\");\n}\n\n/** `<agentDir>/cache` -- rebuildable; safe to delete (the next run just re-probes/recomputes). */\nexport function cacheDir(agentDir: string): string {\n\treturn join(agentDir, \"cache\");\n}\n\n/** `<agentDir>/cache/<segments…>` */\nexport function cacheFile(agentDir: string, ...segments: string[]): string {\n\treturn join(cacheDir(agentDir), ...segments);\n}\n\n/** `<agentDir>/cache/extensions/<namespace>` -- rebuildable cache owned by one extension. */\nexport function extensionCacheDir(agentDir: string, namespace: string): string {\n\tassertPortablePathSegment(\"Extension namespace\", namespace);\n\treturn cacheFile(agentDir, \"extensions\", namespace);\n}\n\n/** `<agentDir>/bin` -- managed executable helpers (fd, rg). */\nexport function binDir(agentDir: string): string {\n\treturn join(agentDir, \"bin\");\n}\n\n/** `<agentDir>/runtimes/<kind>` -- a managed runtime install (ollama, python, prism-llamacpp, needle, …). */\nexport function runtimesDir(kind: string, agentDir: string): string {\n\treturn join(agentDir, \"runtimes\", kind);\n}\n\n/** `<agentDir>/models/<kind>` -- downloaded model weights, grouped by provider/runtime. */\nexport function modelsDir(kind: string, agentDir: string): string {\n\treturn join(agentDir, \"models\", kind);\n}\n\n/** `<agentDir>/sessions` -- session transcript storage (large, established; not a \"loose file\"). */\nexport function sessionsDir(agentDir: string): string {\n\treturn join(agentDir, \"sessions\");\n}\n\nfunction orchestrationSessionKey(parentSessionId: string): string {\n\tconst normalized = requireBoundedTrimmedText(parentSessionId, 512, \"Parent session id\");\n\tconst readable =\n\t\tencodeURIComponent(normalized)\n\t\t\t.replaceAll(\"%\", \"_\")\n\t\t\t// encodeURIComponent deliberately leaves `*` unescaped, but Windows forbids it in paths.\n\t\t\t// Restrict the readable prefix to a portable ASCII subset; the digest retains exact identity.\n\t\t\t.replaceAll(/[^a-zA-Z0-9._~-]/g, \"_\")\n\t\t\t.slice(0, 80) || \"session\";\n\tconst digest = createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n\treturn `${readable}-${digest}`;\n}\n\n/**\n * `<agentDir>/state/orchestration/sessions/<session-key>` -- the one durable control-plane\n * bundle owned by a foreground session. Event state, worker mailboxes, mutation journals, and\n * worker transcripts must stay beneath this boundary so explicit session deletion can remove\n * exactly its companion artifacts without scanning global state.\n */\nexport function orchestrationSessionsDir(agentDir: string): string {\n\treturn stateFile(agentDir, \"orchestration\", \"sessions\");\n}\n\n/**\n * `<agentDir>/state/orchestration/sessions/<session-key>` -- the one durable control-plane\n * bundle owned by a foreground session.\n */\nexport function orchestrationSessionDir(agentDir: string, parentSessionId: string): string {\n\treturn join(orchestrationSessionsDir(agentDir), orchestrationSessionKey(parentSessionId));\n}\n\n/** `<orchestrationSessionDir>/events` -- append-only event tail, snapshot, cursor, and idempotency state. */\nexport function orchestrationEventStoreDir(agentDir: string, parentSessionId: string): string {\n\treturn join(orchestrationSessionDir(agentDir, parentSessionId), \"events\");\n}\n\n/**\n * `<orchestrationSessionDir>/worker-conversations` -- durable Pi worker transcripts owned by one\n * foreground session. Worker conversations remain in SessionManager's established JSONL format,\n * but are intentionally outside the foreground session picker namespace.\n */\nexport function workerConversationSessionsDir(agentDir: string, parentSessionId: string): string {\n\treturn join(orchestrationSessionDir(agentDir, parentSessionId), \"worker-conversations\");\n}\n\n/**\n * `<orchestrationSessionDir>/worker-mailboxes/<scope-digest>.json` -- durable bounded control\n * messages for one logical worker. Identity stays hashed so neither agent ids nor project paths\n * become path segments.\n */\nexport function workerAgentMailboxFile(agentDir: string, parentSessionId: string, scopeDigest: string): string {\n\tif (!/^[a-f0-9]{32,64}$/i.test(scopeDigest)) {\n\t\tthrow new TypeError(\"Worker agent mailbox scope digest must be a hexadecimal SHA-256 prefix.\");\n\t}\n\treturn join(\n\t\torchestrationSessionDir(agentDir, parentSessionId),\n\t\t\"worker-mailboxes\",\n\t\t`${scopeDigest.toLowerCase()}.json`,\n\t);\n}\n\n/**\n * `<orchestrationSessionDir>/worker-actions/<scope-digest>.json` -- durable, bounded mutation\n * intents and receipts for one fenced worker attempt. The opaque digest intentionally keeps task\n * identifiers out of filesystem path segments and works on Windows and WSL.\n */\nexport function workerActionJournalFile(agentDir: string, parentSessionId: string, scopeDigest: string): string {\n\tif (!/^[a-f0-9]{32,64}$/i.test(scopeDigest)) {\n\t\tthrow new TypeError(\"Worker action journal scope digest must be a hexadecimal SHA-256 prefix.\");\n\t}\n\treturn join(\n\t\torchestrationSessionDir(agentDir, parentSessionId),\n\t\t\"worker-actions\",\n\t\t`${scopeDigest.toLowerCase()}.json`,\n\t);\n}\n\n/** `<agentDir>/npm` -- managed npm package installs. */\nexport function npmDir(agentDir: string): string {\n\treturn join(agentDir, \"npm\");\n}\n\n/**\n * `<agentDir>/worktrees` -- lane worktree checkouts for the worktree-sync subsystem\n * (`core/worktree-sync/`), grouped as `worktrees/<repo-slug>/<laneKey>`. These hold REAL\n * uncommitted agent work, so they are durable like `state/` -- never under transient `work/`,\n * whose retention would silently eat in-progress code.\n */\nexport function worktreesDir(agentDir: string): string {\n\treturn join(agentDir, \"worktrees\");\n}\n\n/** `<agentDir>/git` -- managed git-sourced package installs. */\nexport function gitDir(agentDir: string): string {\n\treturn join(agentDir, \"git\");\n}\n\nexport type AgentResourceKind = \"skills\" | \"prompts\" | \"themes\" | \"extensions\" | \"profiles\";\n\n/** `<agentDir>/<kind>` -- a user-managed resource directory. Root, kept: moving it breaks users. */\nexport function resourceDir(kind: AgentResourceKind, agentDir: string): string {\n\treturn join(agentDir, kind);\n}\n\n/** `<agentDir>/profiles/directories` -- durable per-directory resource-profile overlays. */\nexport function directoryProfilesDir(agentDir: string): string {\n\treturn join(resourceDir(\"profiles\", agentDir), \"directories\");\n}\n\n/**\n * `work/` is a mature transient/scratch root with its own tenant/run/lease/retention machinery\n * (`utils/work-directory.ts`). The SSOT delegates to it wholesale instead of reimplementing -- these\n * are straight re-exports so every category (state/cache/work/runtimes/models/…) is reachable from one\n * module without duplicating `work-directory.ts`'s logic.\n */\nexport {\n\tgetWorkRoot,\n\tassertPortablePathSegment,\n\tboundedWorkRetention,\n\tgetWorkTenantDir,\n\tgetWorkRunDir,\n\tgetProcessWorkRun,\n\thasActiveWorkRunLease,\n\tacquireWorkRun,\n\tcreateWorkRunId,\n\tpruneWorkTenant,\n};\nexport type { AcquireWorkRunOptions, WorkRetentionOptions, WorkRunLease } from \"../utils/work-directory.ts\";\n\n/**\n * `work/reload-coordination` -- cross-process reload/live-op coordination state. Already correctly\n * work-scoped (defined in `reload-blockers.ts`, its natural home given the surrounding reload-gate\n * logic there); re-exported here under the taxonomy's canonical name for SSOT discoverability.\n */\nexport const reloadCoordinationDir = getReloadCoordinationDir;\n"]}
@@ -225,8 +225,10 @@ export interface SpawnedUsageTotals {
225
225
  }
226
226
  export interface IsolatedCompletionOptions {
227
227
  systemPrompt: string;
228
- /** Isolated conversation; foreground session history is never inherited. */
228
+ /** New child-owned prompt messages for this call; foreground session history is never inherited. */
229
229
  messages: Message[];
230
+ /** Previously persisted child history. Omission preserves fresh one-shot behavior. */
231
+ history?: Message[];
230
232
  model?: Model<Api>;
231
233
  thinkingLevel?: ThinkingLevel;
232
234
  maxTokens?: number;
@@ -240,6 +242,20 @@ export interface IsolatedCompletionOptions {
240
242
  beforeToolCall?: AgentLoopConfig["beforeToolCall"];
241
243
  /** Child-only result observer. */
242
244
  afterToolCall?: AgentLoopConfig["afterToolCall"];
245
+ /**
246
+ * Durable child transcript sink. Message-end ordering means an assistant tool request is recorded
247
+ * before execution starts and each tool result is recorded before the next provider request.
248
+ * Throwing aborts the child loop; continuing without durable history would make replay unsafe.
249
+ */
250
+ onMessage?: (message: Message) => Promise<void> | void;
251
+ /** Durable mid-run steering inbox owned by the child conversation. */
252
+ getSteeringMessages?: AgentLoopConfig["getSteeringMessages"];
253
+ /** Durable post-turn follow-up inbox owned by the child conversation. */
254
+ getFollowUpMessages?: AgentLoopConfig["getFollowUpMessages"];
255
+ /** Child-owned provider projection, invoked before every request without mutating raw history. */
256
+ transformContext?: AgentLoopConfig["transformContext"];
257
+ /** Request-local budget/authority check, invoked immediately before every child provider transport. */
258
+ requestPreflight?: AgentLoopConfig["requestPreflight"];
243
259
  signal?: AbortSignal;
244
260
  /** Required cache policy; isolated calls never inherit a provider default implicitly. */
245
261
  cacheRetention: CacheRetention;
@@ -252,6 +268,8 @@ export interface IsolatedCompletionResult {
252
268
  text: string;
253
269
  usage: Usage;
254
270
  stopReason: StopReason;
271
+ /** Complete child-owned conversation; isolated calls never expose foreground history. */
272
+ messages?: Message[];
255
273
  }
256
274
  export interface ResearchLaneRunOutcome {
257
275
  started: boolean;