@iowarp/clio-coder 0.3.3 → 0.3.4

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 (244) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +3 -3
  4. package/dist/{acp-P2AQILE2.js → acp-S5R4RR5B.js} +7 -6
  5. package/dist/{agents-72W3BI7I.js → agents-P6DMMVZY.js} +24 -21
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-5TWEIYDN.js → auth-2XCZLPKS.js} +12 -8
  8. package/dist/{chunk-GGXXDWE4.js → chunk-22NAGB7X.js} +2 -2
  9. package/dist/{chunk-2DJ2KNFG.js → chunk-2LZI5CAG.js} +133 -13
  10. package/dist/{chunk-OAO4GE4M.js → chunk-2TZWSW76.js} +2 -2
  11. package/dist/{chunk-OOJYHWRB.js → chunk-34475P3I.js} +2 -2
  12. package/dist/{chunk-4XUGQOHA.js → chunk-35MKKU5R.js} +4 -4
  13. package/dist/{chunk-LM5TQCJZ.js → chunk-3HZ5RWN2.js} +5 -5
  14. package/dist/{chunk-AGYYIBLL.js → chunk-3JLKSKD7.js} +2 -2
  15. package/dist/{chunk-KZWTDYJF.js → chunk-4JUF2NNX.js} +7 -7
  16. package/dist/{chunk-ZDOOVTXZ.js → chunk-4OC57DA6.js} +27 -4
  17. package/dist/chunk-5M54SPOL.js +926 -0
  18. package/dist/{chunk-STBPMHSX.js → chunk-7RXG6QRZ.js} +51 -11
  19. package/dist/{chunk-X6IAEBZR.js → chunk-A2GZF7DC.js} +5 -5
  20. package/dist/{chunk-A3CYT5EX.js → chunk-AD2SYQYC.js} +55 -2
  21. package/dist/chunk-AOCYTWAV.js +449 -0
  22. package/dist/chunk-BEY543CS.js +258 -0
  23. package/dist/{chunk-6N5PTWMY.js → chunk-BP4OYD6A.js} +32 -13
  24. package/dist/chunk-BPGS2WCQ.js +612 -0
  25. package/dist/{chunk-V6RTAOC2.js → chunk-BRXQQJFP.js} +8 -8
  26. package/dist/chunk-CFGTUFWB.js +67 -0
  27. package/dist/{chunk-CBCAPZAA.js → chunk-E25LMLRW.js} +2 -2
  28. package/dist/{chunk-DUYJ5IO6.js → chunk-EDRHSCIE.js} +4 -4
  29. package/dist/{chunk-XBXAASKX.js → chunk-EFADSJET.js} +2 -2
  30. package/dist/{chunk-M6SHUN7Q.js → chunk-FO5ZOVUY.js} +2 -2
  31. package/dist/chunk-FYYLNIL5.js +313 -0
  32. package/dist/{chunk-FNTMWMX5.js → chunk-HV5X7OR2.js} +14 -12
  33. package/dist/{chunk-TZTZS7QK.js → chunk-HXG4IURW.js} +5 -3
  34. package/dist/{chunk-5UFT4SUX.js → chunk-K6WL7QZT.js} +3 -3
  35. package/dist/chunk-K7VKOLQQ.js +15 -0
  36. package/dist/{chunk-BMEMKKIT.js → chunk-KOHPCX4K.js} +2 -2
  37. package/dist/{chunk-OC7FIQPC.js → chunk-KRPY7NTG.js} +10 -7
  38. package/dist/chunk-LL4KHSZI.js +22 -0
  39. package/dist/{chunk-DSELYM6W.js → chunk-MEQ45TQ4.js} +15 -9
  40. package/dist/{chunk-5UUP6MWO.js → chunk-MV3K5QF2.js} +5 -436
  41. package/dist/{chunk-6SGHMWE3.js → chunk-N4CZJQRK.js} +5 -5
  42. package/dist/{chunk-TZK7PACC.js → chunk-NILBFAPG.js} +14 -8
  43. package/dist/chunk-OZNBF4L3.js +23 -0
  44. package/dist/{verify-375KUB3Y.js → chunk-PCZJO5TI.js} +127 -42
  45. package/dist/chunk-QQK64KLB.js +1360 -0
  46. package/dist/{chunk-SRDMMSEP.js → chunk-QQL5RT5M.js} +979 -1619
  47. package/dist/{chunk-LZSJBIVT.js → chunk-QWU7ZBO7.js} +70 -720
  48. package/dist/{chunk-2TLUCQVG.js → chunk-RD5U66HV.js} +3 -3
  49. package/dist/{chunk-OKGUZO2U.js → chunk-SPULKLCF.js} +4 -3
  50. package/dist/{chunk-OQ33BKR3.js → chunk-TTNYS3EA.js} +3 -60
  51. package/dist/chunk-TW3WDMVS.js +677 -0
  52. package/dist/chunk-TZSKNMZG.js +434 -0
  53. package/dist/{chunk-7MNJORFF.js → chunk-UL3WSD3F.js} +6 -1
  54. package/dist/{chunk-PIWWS5BL.js → chunk-UZHIZC5S.js} +7 -7
  55. package/dist/{chunk-UFIIWP2H.js → chunk-VAWWTKDP.js} +8 -8
  56. package/dist/{chunk-COU2UHX6.js → chunk-VEZEGCGW.js} +170 -2
  57. package/dist/{chunk-LW6DSM3M.js → chunk-VMNQ6OZA.js} +98 -202
  58. package/dist/chunk-VSNATDE6.js +122 -0
  59. package/dist/chunk-W6GROXXM.js +69 -0
  60. package/dist/chunk-WPQLXFOZ.js +375 -0
  61. package/dist/{chunk-ORBHGJC5.js → chunk-WR67VIZY.js} +3 -3
  62. package/dist/{chunk-PAJK6MAQ.js → chunk-X6COSD2O.js} +5 -5
  63. package/dist/chunk-ZGVHUX3M.js +66 -0
  64. package/dist/{chunk-LWLEKMDQ.js → chunk-ZYKPLLNQ.js} +510 -547
  65. package/dist/cli/index.js +27 -23
  66. package/dist/{clio-JOU4FXVA.js → clio-J5JIOIDS.js} +7 -6
  67. package/dist/{code-nav-7AX6FYE6.js → code-nav-AXCXSBHX.js} +5 -3
  68. package/dist/{config-XCDVKR23.js → config-OEBMIN2U.js} +37 -27
  69. package/dist/{configure-4GAP54ZW.js → configure-PUQOSIXQ.js} +16 -13
  70. package/dist/{context-5VKGUVJJ.js → context-EKDCKUUZ.js} +82 -7
  71. package/dist/{context-4UOGGLQ5.js → context-MGSE4Z2T.js} +33 -23
  72. package/dist/{context-77FM5DV5.js → context-URSXPBCK.js} +17 -9
  73. package/dist/{context-clear-XXJRLCJJ.js → context-clear-KDAJRNUK.js} +33 -23
  74. package/dist/context-working-set-SBKMPPI2.js +1552 -0
  75. package/dist/{dispatch-runner-QPRDDBDX.js → dispatch-runner-MSWN72NK.js} +43 -29
  76. package/dist/{doctor-HR46URBJ.js → doctor-7BSE27PJ.js} +10 -10
  77. package/dist/{eval-XSSNATB4.js → eval-IZGDOO4H.js} +9 -8
  78. package/dist/{evidence-6HG2PY2B.js → evidence-SR7WXB5B.js} +51 -23
  79. package/dist/{evolve-K7YU3NCY.js → evolve-K7VE2CBX.js} +30 -20
  80. package/dist/{fleet-VY3HHKN6.js → fleet-7XMJNQNF.js} +48 -38
  81. package/dist/{fleet-preflight-DDN536IT.js → fleet-preflight-AQNAH644.js} +3 -3
  82. package/dist/{init-JYGXI3FK.js → init-JGNPAYXT.js} +41 -31
  83. package/dist/{memory-WFZMGYHX.js → memory-4ALKDJ4Q.js} +32 -22
  84. package/dist/{models-I5QWSEOM.js → models-ZMMLFJNN.js} +22 -19
  85. package/dist/{monitor-GE4ID3IA.js → monitor-2F3T5KHP.js} +55 -43
  86. package/dist/{orchestrator-EM5MC3HM.js → orchestrator-ORHT43JB.js} +572 -388
  87. package/dist/{reset-L2FQEE3E.js → reset-NXGTYNUO.js} +4 -3
  88. package/dist/{run-ZU3QMZPZ.js → run-RF4WJGMT.js} +51 -41
  89. package/dist/{share-S5BZQC5I.js → share-UT3W6E4M.js} +5 -4
  90. package/dist/{skills-X5VXCRNQ.js → skills-PSACKC5Q.js} +2 -2
  91. package/dist/{skills-eval-WKIHWTHR.js → skills-eval-WJSI55RZ.js} +34 -24
  92. package/dist/{targets-SNCPI2NR.js → targets-PIIRAOYS.js} +23 -20
  93. package/dist/{terminal-lease-BNAHVHBS.js → terminal-lease-ULWXWNVY.js} +4 -3
  94. package/dist/{upgrade-JQHHPQ4K.js → upgrade-346TZ6AV.js} +18 -17
  95. package/dist/{usage-OR4O5SMZ.js → usage-6KKXR32N.js} +34 -24
  96. package/dist/verifiers-4UUM6TEE.js +1214 -0
  97. package/dist/verify-X5HDROLA.js +25 -0
  98. package/dist/{wiki-generate-UEXP2ARI.js → wiki-generate-7STOCIFZ.js} +42 -31
  99. package/dist/worker/entry.js +33 -24
  100. package/docs/README.md +7 -6
  101. package/docs/acp.md +1 -1
  102. package/docs/alcf-provider.md +1 -1
  103. package/docs/architecture.md +2 -2
  104. package/docs/artifact-versions.md +1 -1
  105. package/docs/built-in-agents.md +1 -1
  106. package/docs/capacity-and-scheduling.md +1 -1
  107. package/docs/commands-and-modes.md +53 -21
  108. package/docs/config-knobs-audit.md +1 -2
  109. package/docs/configuration-and-targets.md +15 -1
  110. package/docs/context-engine.md +64 -12
  111. package/docs/context-working-set.md +194 -0
  112. package/docs/development-pipeline.md +1 -1
  113. package/docs/documentation-coverage.md +5 -5
  114. package/docs/documentation-guide.md +6 -5
  115. package/docs/environment-variables.md +2 -1
  116. package/docs/eval-runner.md +1 -1
  117. package/docs/evals-internal.md +14 -1
  118. package/docs/evidence-and-memory.md +74 -2
  119. package/docs/evolution.md +1 -1
  120. package/docs/exit-codes-and-output.md +1 -1
  121. package/docs/extensions-and-sharing.md +2 -2
  122. package/docs/fleet-dispatch.md +22 -7
  123. package/docs/glossary.md +21 -1
  124. package/docs/installation-and-lifecycle.md +2 -2
  125. package/docs/middleware-and-components.md +1 -1
  126. package/docs/model-catalog.md +7 -9
  127. package/docs/observability.md +4 -4
  128. package/docs/proactive-memory.md +1 -1
  129. package/docs/prompt-envelope-and-tools.md +4 -4
  130. package/docs/provider-adapter-cookbook.md +1 -1
  131. package/docs/release-cut-checklist.md +31 -31
  132. package/docs/safety-model.md +23 -4
  133. package/docs/scientific-validation.md +21 -3
  134. package/docs/session-lifecycle.md +3 -3
  135. package/docs/skills-marketplace.md +1 -1
  136. package/docs/tool-usage.md +79 -12
  137. package/docs/trace-store.md +1 -1
  138. package/docs/troubleshooting.md +1 -1
  139. package/docs/tui-design.md +1 -1
  140. package/docs/worker-dispatch-mechanics.md +11 -1
  141. package/package.json +8 -11
  142. package/skills/meta/clio-test/SKILL.md +20 -17
  143. package/skills/meta/clio-test/evals.md +3 -3
  144. package/skills/meta/clio-test/references/harness.md +35 -6
  145. package/skills/meta/clio-test/references/test-map.md +20 -10
  146. package/skills/registry.yaml +2 -2
  147. package/skills/skill-marketplace.json +1 -1
  148. package/src/cli/context-working-set.ts +513 -0
  149. package/src/cli/context.ts +8 -0
  150. package/src/cli/evidence.ts +20 -2
  151. package/src/cli/index.ts +4 -0
  152. package/src/cli/verifiers.ts +325 -0
  153. package/src/core/bash-exec.ts +39 -14
  154. package/src/core/bus-events.ts +19 -4
  155. package/src/core/config.ts +54 -0
  156. package/src/core/defaults.ts +50 -3
  157. package/src/core/verification-scripts.ts +6 -0
  158. package/src/domains/agents/builtins/verifier.md +3 -0
  159. package/src/domains/config/classify.ts +1 -0
  160. package/src/domains/context/working-set/contract.ts +161 -0
  161. package/src/domains/context/working-set/defaults.ts +28 -0
  162. package/src/domains/context/working-set/engine.ts +203 -0
  163. package/src/domains/context/working-set/fold.ts +62 -0
  164. package/src/domains/context/working-set/horizon.ts +38 -0
  165. package/src/domains/context/working-set/marker.ts +103 -0
  166. package/src/domains/context/working-set/path-index.ts +436 -0
  167. package/src/domains/context/working-set/payload.ts +152 -0
  168. package/src/domains/context/working-set/policies/age-horizon.ts +55 -0
  169. package/src/domains/context/working-set/policies/index.ts +21 -0
  170. package/src/domains/context/working-set/policies/structural.ts +160 -0
  171. package/src/domains/context/working-set/project.ts +132 -0
  172. package/src/domains/context/working-set/protect.ts +109 -0
  173. package/src/domains/context/working-set/recall.ts +177 -0
  174. package/src/domains/context/working-set/replay/controls.ts +112 -0
  175. package/src/domains/context/working-set/replay/load-clio.ts +199 -0
  176. package/src/domains/context/working-set/replay/metrics.ts +185 -0
  177. package/src/domains/context/working-set/replay/reference-graph.ts +79 -0
  178. package/src/domains/context/working-set/replay/report.ts +139 -0
  179. package/src/domains/context/working-set/replay/runner.ts +325 -0
  180. package/src/domains/context/working-set/replay/synthetic.ts +422 -0
  181. package/src/domains/context/working-set/replay/trace.ts +21 -0
  182. package/src/domains/context/working-set/visible.ts +54 -0
  183. package/src/domains/evidence/build.ts +112 -45
  184. package/src/domains/evidence/eval.ts +24 -7
  185. package/src/domains/evidence/index.ts +53 -0
  186. package/src/domains/evidence/ordering.ts +12 -0
  187. package/src/domains/evidence/run-trust.ts +221 -0
  188. package/src/domains/evidence/store.ts +46 -6
  189. package/src/domains/evidence/trust-status.ts +854 -0
  190. package/src/domains/evidence/types.ts +26 -0
  191. package/src/domains/middleware/memory-intervention.ts +3 -0
  192. package/src/domains/middleware/stalled-turn.ts +165 -4
  193. package/src/domains/safety/autonomy.ts +1 -1
  194. package/src/domains/safety/default-path-policy.ts +8 -0
  195. package/src/domains/safety/finish-contract.ts +4 -3
  196. package/src/domains/safety/policy-engine.ts +48 -6
  197. package/src/domains/session/compaction/compact.ts +23 -1
  198. package/src/domains/session/compaction/cut-point.ts +2 -0
  199. package/src/domains/session/compaction/tokens.ts +16 -1
  200. package/src/domains/session/context-ledger.ts +2 -0
  201. package/src/domains/session/entries.ts +107 -1
  202. package/src/domains/session/manager.ts +9 -2
  203. package/src/domains/session/migrations/index.ts +22 -3
  204. package/src/engine/acp/server.ts +3 -0
  205. package/src/engine/agent.ts +18 -1
  206. package/src/engine/session.ts +9 -3
  207. package/src/entry/orchestrator.ts +16 -4
  208. package/src/interactive/chat-loop-messages.ts +18 -6
  209. package/src/interactive/chat-panel.ts +17 -1
  210. package/src/interactive/chat-renderer.ts +30 -21
  211. package/src/interactive/context-meter.ts +10 -0
  212. package/src/interactive/context-overlay.ts +81 -6
  213. package/src/interactive/context-recall-command.ts +110 -0
  214. package/src/interactive/interactive-slash-runtime.ts +37 -1
  215. package/src/interactive/model-session-replay.ts +21 -0
  216. package/src/interactive/overlay-general-openers.ts +6 -0
  217. package/src/interactive/overlay-session-lifecycle.ts +8 -4
  218. package/src/interactive/renderers/tool-execution.ts +18 -2
  219. package/src/interactive/session-transcript.ts +2 -2
  220. package/src/interactive/slash-commands.ts +29 -2
  221. package/src/interactive/turn-context.ts +238 -88
  222. package/src/interactive/turn-middleware.ts +6 -6
  223. package/src/tools/agent-tools.ts +11 -4
  224. package/src/tools/bash.ts +144 -82
  225. package/src/tools/builtin-tool-catalog.ts +11 -5
  226. package/src/tools/context/index.ts +105 -3
  227. package/src/tools/context/surface.ts +3 -2
  228. package/src/tools/core-bootstrap.ts +21 -0
  229. package/src/tools/dispatch-runner.ts +9 -7
  230. package/src/tools/monitor.ts +28 -20
  231. package/src/tools/registry.ts +59 -7
  232. package/src/tools/result-disposition.ts +550 -0
  233. package/src/tools/result-shaping.ts +262 -19
  234. package/src/tools/safe-exec.ts +2 -0
  235. package/src/tools/verify/authoring.ts +1119 -0
  236. package/src/tools/verify/catalog.ts +346 -0
  237. package/src/tools/verify/index.ts +13 -3
  238. package/src/tools/verify/scripts.ts +135 -37
  239. package/src/tools/verify/surface.ts +9 -5
  240. package/src/tools/worker-evidence.ts +35 -12
  241. package/dist/chunk-J7CWMCQD.js +0 -255
  242. package/dist/chunk-T6YILFSB.js +0 -80
  243. package/dist/chunk-VAKQQHWR.js +0 -434
  244. package/dist/chunk-VPAYEGVX.js +0 -184
@@ -6,7 +6,7 @@ import {
6
6
  isAutonomyLevel,
7
7
  mapAutonomy,
8
8
  typedValidationSummary
9
- } from "./chunk-STBPMHSX.js";
9
+ } from "./chunk-7RXG6QRZ.js";
10
10
  import {
11
11
  ROUTE_POLICY_VERSION,
12
12
  deriveExecutionRole,
@@ -15,36 +15,40 @@ import {
15
15
  isRoutingIntent,
16
16
  routePriorForLatencyClass,
17
17
  sameRouteIdentity
18
- } from "./chunk-GGXXDWE4.js";
18
+ } from "./chunk-22NAGB7X.js";
19
19
  import {
20
20
  AGENT_AUTOMATION_AUTHORITIES,
21
- agentSpecFingerprint,
21
+ agentSpecFingerprint
22
+ } from "./chunk-AOCYTWAV.js";
23
+ import {
22
24
  detectValidationCommand,
23
25
  extractCommandDeleteTargets,
24
26
  extractCommandWriteTargets,
25
27
  tokenizeShellLike,
26
28
  toolMutationPaths
27
- } from "./chunk-5UUP6MWO.js";
29
+ } from "./chunk-MV3K5QF2.js";
28
30
  import {
31
+ expandPath,
29
32
  resolveReadPath
30
33
  } from "./chunk-OQE5J4C6.js";
31
- import {
32
- isSkillActivation
33
- } from "./chunk-T6YILFSB.js";
34
34
  import {
35
35
  DEFAULT_MAX_LINES,
36
36
  OBSERVATION_POLICY_SLACK_BYTES,
37
37
  OBSERVE_SELF_CAPS,
38
+ deterministicDiagnosticSummary,
38
39
  finalizeObservation,
39
- formatSize,
40
40
  isSessionOffloadPath,
41
41
  observationBudgetExhausted,
42
42
  reserveObservation,
43
43
  splitLinesForCounting,
44
44
  truncateHead,
45
45
  truncateTail
46
- } from "./chunk-VAKQQHWR.js";
46
+ } from "./chunk-5M54SPOL.js";
47
47
  import {
48
+ formatSize
49
+ } from "./chunk-OZNBF4L3.js";
50
+ import {
51
+ byteLength,
48
52
  truncateUtf8
49
53
  } from "./chunk-6XLNIQDB.js";
50
54
  import {
@@ -56,12 +60,24 @@ import {
56
60
  } from "./chunk-CGKSTWHD.js";
57
61
  import {
58
62
  THINKING_LEVELS
59
- } from "./chunk-ZDOOVTXZ.js";
63
+ } from "./chunk-4OC57DA6.js";
64
+ import {
65
+ gitCommitAttributionEnabled,
66
+ reportCommitAttributionDiagnostic,
67
+ resolveSafeCwd,
68
+ withManagedGitCommitAttributionEnvironment
69
+ } from "./chunk-VEZEGCGW.js";
70
+ import {
71
+ clampTimerDelayMs
72
+ } from "./chunk-FQ4SKYE4.js";
60
73
  import {
61
74
  GUARDRAIL_DEFAULTS,
62
75
  GUARDRAIL_ENV_VARS,
63
76
  resolveGuardrail
64
77
  } from "./chunk-4ZG3XFUR.js";
78
+ import {
79
+ AI_AGENT_NAME
80
+ } from "./chunk-6EJMN2Y3.js";
65
81
  import {
66
82
  init_esm_shims
67
83
  } from "./chunk-3R73A4XB.js";
@@ -137,6 +153,255 @@ function applyCodewikiWorkerPolicy(tools, context) {
137
153
  return tools.filter((tool) => !isCodewikiTool(tool));
138
154
  }
139
155
 
156
+ // src/core/bash-exec.ts
157
+ init_esm_shims();
158
+ import { spawn } from "node:child_process";
159
+ import { StringDecoder } from "node:string_decoder";
160
+ var BASH_HARD_CAP_BYTES = 16 * 1024 * 1024;
161
+ var CLIO_CONTROL_ENV_KEYS = ["CLIO_CODER_INTERACTIVE", "CLIO_CODER_RESUME_SESSION_ID"];
162
+ var BASH_UPDATE_THROTTLE_MS = 100;
163
+ function buildToolEnv() {
164
+ const env = { ...process.env };
165
+ env.AI_AGENT = AI_AGENT_NAME;
166
+ for (const key of CLIO_CONTROL_ENV_KEYS) {
167
+ Reflect.deleteProperty(env, key);
168
+ }
169
+ return env;
170
+ }
171
+ var LOGIN_ENV_CAPTURE_TIMEOUT_MS = 1e4;
172
+ var loginEnvCapture = null;
173
+ function parseNullDelimitedEnv(raw) {
174
+ const env = {};
175
+ for (const entry of raw.split("\0")) {
176
+ if (entry.length === 0) continue;
177
+ const eq = entry.indexOf("=");
178
+ if (eq <= 0) continue;
179
+ env[entry.slice(0, eq)] = entry.slice(eq + 1);
180
+ }
181
+ return typeof env.PATH === "string" && env.PATH.length > 0 ? env : null;
182
+ }
183
+ function captureLoginEnv() {
184
+ return new Promise((resolve) => {
185
+ let stdout = "";
186
+ let settled = false;
187
+ const finish = (value) => {
188
+ if (settled) return;
189
+ settled = true;
190
+ clearTimeout(timer);
191
+ resolve(value);
192
+ };
193
+ const child = spawn("/bin/bash", ["-lc", "env -0"], {
194
+ env: buildToolEnv(),
195
+ stdio: ["ignore", "pipe", "ignore"]
196
+ });
197
+ const timer = setTimeout(() => {
198
+ child.kill("SIGKILL");
199
+ finish(null);
200
+ }, LOGIN_ENV_CAPTURE_TIMEOUT_MS);
201
+ child.stdout?.on("data", (chunk) => {
202
+ stdout += chunk.toString("utf8");
203
+ });
204
+ child.on("error", () => finish(null));
205
+ child.on("close", (code) => finish(code === 0 ? parseNullDelimitedEnv(stdout) : null));
206
+ });
207
+ }
208
+ async function bashSpawnPlan() {
209
+ loginEnvCapture ??= captureLoginEnv();
210
+ const captured = await loginEnvCapture;
211
+ if (captured === null) return { mode: "-lc", env: buildToolEnv() };
212
+ const env = { ...process.env, ...captured };
213
+ env.AI_AGENT = AI_AGENT_NAME;
214
+ for (const key of CLIO_CONTROL_ENV_KEYS) {
215
+ Reflect.deleteProperty(env, key);
216
+ }
217
+ return { mode: "-c", env };
218
+ }
219
+ function combineBashOutput(result) {
220
+ const { stdout, stderr } = result;
221
+ return stderr.length > 0 ? `${stdout}${stdout.endsWith("\n") || stdout.length === 0 ? "" : "\n"}${stderr}` : stdout;
222
+ }
223
+ async function runBashCommand(command, options = {}) {
224
+ const plan = await bashSpawnPlan();
225
+ const attribution = withManagedGitCommitAttributionEnvironment(plan.env, {
226
+ cwd: options.cwd ?? process.cwd(),
227
+ enabled: gitCommitAttributionEnabled(process.env)
228
+ });
229
+ reportCommitAttributionDiagnostic(attribution.diagnostic);
230
+ return new Promise((resolve) => {
231
+ const timeout = clampTimerDelayMs(options.timeoutMs ?? 3e5);
232
+ let aborted = false;
233
+ let timedOut = false;
234
+ let settled = false;
235
+ let timeoutId = null;
236
+ let killGraceTimer = null;
237
+ let killSent = false;
238
+ let stdout = "";
239
+ let stderr = "";
240
+ const stdoutDecoder = new StringDecoder("utf8");
241
+ const stderrDecoder = new StringDecoder("utf8");
242
+ let decodersFinished = false;
243
+ let outputBytes = 0;
244
+ let outputCapped = false;
245
+ let updateTimer = null;
246
+ let updateDirty = false;
247
+ let lastUpdateAt = 0;
248
+ const child = spawn("/bin/bash", [plan.mode, command], {
249
+ ...options.cwd === void 0 ? {} : { cwd: options.cwd },
250
+ env: attribution.env,
251
+ detached: process.platform !== "win32",
252
+ stdio: ["ignore", "pipe", "pipe"]
253
+ });
254
+ const finishDecoders = () => {
255
+ if (decodersFinished) return;
256
+ decodersFinished = true;
257
+ if (outputCapped) return;
258
+ stdout += stdoutDecoder.end();
259
+ stderr += stderrDecoder.end();
260
+ };
261
+ const emitUpdate = () => {
262
+ if (options.onUpdate === void 0 || !updateDirty) return;
263
+ updateDirty = false;
264
+ lastUpdateAt = Date.now();
265
+ try {
266
+ options.onUpdate({ stdout, stderr, outputBytes: Math.min(outputBytes, BASH_HARD_CAP_BYTES) });
267
+ } catch {
268
+ }
269
+ };
270
+ const clearUpdateTimer = () => {
271
+ if (updateTimer === null) return;
272
+ clearTimeout(updateTimer);
273
+ updateTimer = null;
274
+ };
275
+ const scheduleUpdate = () => {
276
+ if (options.onUpdate === void 0) return;
277
+ updateDirty = true;
278
+ const delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);
279
+ if (delay <= 0) {
280
+ clearUpdateTimer();
281
+ emitUpdate();
282
+ return;
283
+ }
284
+ updateTimer ??= setTimeout(() => {
285
+ updateTimer = null;
286
+ emitUpdate();
287
+ }, delay);
288
+ };
289
+ const finishUpdates = () => {
290
+ clearUpdateTimer();
291
+ emitUpdate();
292
+ };
293
+ if (options.onUpdate !== void 0) {
294
+ updateDirty = true;
295
+ emitUpdate();
296
+ }
297
+ const clearKillGraceTimer = () => {
298
+ if (!killGraceTimer) return;
299
+ clearTimeout(killGraceTimer);
300
+ killGraceTimer = null;
301
+ };
302
+ const sendSignal = (signalName) => {
303
+ const pid = child.pid;
304
+ if (pid && process.platform !== "win32") {
305
+ try {
306
+ process.kill(-pid, signalName);
307
+ return;
308
+ } catch {
309
+ }
310
+ }
311
+ child.kill(signalName);
312
+ };
313
+ const killChild = () => {
314
+ if (killSent) return;
315
+ killSent = true;
316
+ sendSignal("SIGTERM");
317
+ killGraceTimer = setTimeout(() => {
318
+ sendSignal("SIGKILL");
319
+ }, 5e3);
320
+ };
321
+ function onAbort() {
322
+ aborted = true;
323
+ killChild();
324
+ }
325
+ if (timeout > 0) {
326
+ timeoutId = setTimeout(() => {
327
+ timedOut = true;
328
+ killChild();
329
+ }, timeout);
330
+ }
331
+ if (options.signal?.aborted) {
332
+ onAbort();
333
+ } else {
334
+ options.signal?.addEventListener("abort", onAbort, { once: true });
335
+ }
336
+ const appendChunk = (target, chunk) => {
337
+ if (outputCapped) return;
338
+ const remaining = BASH_HARD_CAP_BYTES - outputBytes;
339
+ const accepted = chunk.byteLength <= remaining ? chunk : chunk.subarray(0, Math.max(0, remaining));
340
+ outputBytes += accepted.byteLength;
341
+ if (accepted.byteLength > 0) {
342
+ const decoded = target === "stdout" ? stdoutDecoder.write(accepted) : stderrDecoder.write(accepted);
343
+ if (target === "stdout") stdout += decoded;
344
+ else stderr += decoded;
345
+ }
346
+ if (accepted.byteLength < chunk.byteLength) {
347
+ outputCapped = true;
348
+ scheduleUpdate();
349
+ killChild();
350
+ return;
351
+ }
352
+ scheduleUpdate();
353
+ };
354
+ child.stdout?.on("data", (chunk) => appendChunk("stdout", chunk));
355
+ child.stderr?.on("data", (chunk) => appendChunk("stderr", chunk));
356
+ child.on("error", (error) => {
357
+ if (settled) return;
358
+ settled = true;
359
+ if (timeoutId) clearTimeout(timeoutId);
360
+ clearKillGraceTimer();
361
+ finishDecoders();
362
+ finishUpdates();
363
+ options.signal?.removeEventListener("abort", onAbort);
364
+ resolve({
365
+ error,
366
+ stdout,
367
+ stderr,
368
+ exitCode: null,
369
+ signal: null,
370
+ aborted,
371
+ timedOut,
372
+ outputCapped,
373
+ outputBytes
374
+ });
375
+ });
376
+ child.on("close", (code, signalName) => {
377
+ if (settled) return;
378
+ settled = true;
379
+ if (timeoutId) clearTimeout(timeoutId);
380
+ clearKillGraceTimer();
381
+ finishDecoders();
382
+ finishUpdates();
383
+ options.signal?.removeEventListener("abort", onAbort);
384
+ const error = code === 0 && signalName === null ? null : {
385
+ name: "Error",
386
+ message: signalName ? `command terminated by ${signalName}` : `command exited with code ${code ?? "?"}`,
387
+ code: code ?? void 0,
388
+ signal: signalName ?? void 0
389
+ };
390
+ resolve({
391
+ error,
392
+ stdout,
393
+ stderr,
394
+ exitCode: code,
395
+ signal: signalName,
396
+ aborted,
397
+ timedOut,
398
+ outputCapped,
399
+ outputBytes
400
+ });
401
+ });
402
+ });
403
+ }
404
+
140
405
  // src/tools/network-policy.ts
141
406
  init_esm_shims();
142
407
  var NO_NETWORK_TOOLS_ENV = "CLIO_CODER_NO_NETWORK_TOOLS";
@@ -831,525 +1096,9 @@ function runKindSupportsLiveSteering(kind) {
831
1096
  return kind === "http" || kind === "sdk";
832
1097
  }
833
1098
 
834
- // src/domains/session/task-board.ts
835
- init_esm_shims();
836
- import { randomUUID } from "node:crypto";
837
-
838
- // src/domains/session/entries.ts
839
- init_esm_shims();
840
- var SESSION_ENTRY_KINDS = [
841
- "message",
842
- "bashExecution",
843
- "custom",
844
- "modelChange",
845
- "thinkingLevelChange",
846
- "fileEntry",
847
- "branchSummary",
848
- "compactionSummary",
849
- "sessionInfo",
850
- "label",
851
- "protectedArtifact",
852
- "skillActivation",
853
- "taskLedger",
854
- "decisionLedger",
855
- "workerRun"
856
- ];
857
- function isRecord(value) {
858
- return !!value && typeof value === "object";
859
- }
860
- function isString(value) {
861
- return typeof value === "string";
862
- }
863
- function isOptionalString(value) {
864
- return value === void 0 || typeof value === "string";
865
- }
866
- function isOptionalBoolean(value) {
867
- return value === void 0 || typeof value === "boolean";
868
- }
869
- function isNumber(value) {
870
- return typeof value === "number" && Number.isFinite(value);
871
- }
872
- function isPositiveInteger(value) {
873
- return isNumber(value) && Number.isInteger(value) && value > 0;
874
- }
875
- function isOptionalNumber(value) {
876
- return value === void 0 || isNumber(value);
877
- }
878
- function isNullableString(value) {
879
- return value === null || typeof value === "string";
880
- }
881
- function isOneOf(value, allowed) {
882
- return typeof value === "string" && allowed.includes(value);
883
- }
884
- function isStringArray(value) {
885
- return Array.isArray(value) && value.every((item) => typeof item === "string");
886
- }
887
- function hasBaseSessionEntryFields(v) {
888
- return isString(v.turnId) && isNullableString(v.parentTurnId) && isString(v.timestamp);
889
- }
890
- var MESSAGE_ROLES = ["user", "assistant", "tool_call", "tool_result", "system", "checkpoint"];
891
- var FILE_OPERATIONS = ["read", "write", "edit", "create", "delete"];
892
- var COMPACTION_TRIGGERS = ["auto", "force", "overflow"];
893
- var PROTECTED_ARTIFACT_SOURCES = [
894
- "validation",
895
- "middleware",
896
- "user",
897
- "session"
898
- ];
899
- var TASK_LEDGER_STATUSES = ["pending", "active", "completed", "blocked", "cancelled"];
900
- var TASK_LEDGER_EVIDENCE_STATUSES = [
901
- "required",
902
- "pending",
903
- "passed",
904
- "failed",
905
- "missing"
906
- ];
907
- var DECISION_STATUSES = ["active", "superseded"];
908
- var DECISION_INTERVIEW_STATUSES = ["complete", "cancelled"];
909
- var WORKER_RUN_ORIGINS = ["user", "agent"];
910
- var WORKER_RUN_RUNTIME_KINDS = ["clio", "acp", "claude-sdk", "claude-code"];
911
- function isWorkerRunRuntime(value) {
912
- if (!isRecord(value)) return false;
913
- return isOneOf(value.kind, WORKER_RUN_RUNTIME_KINDS) && isOptionalString(value.targetId) && isOptionalString(value.wireModelId) && isOptionalString(value.peerId);
914
- }
915
- function isTaskLedgerGoal(value) {
916
- if (!isRecord(value)) return false;
917
- if (!isString(value.id) || !isString(value.title)) return false;
918
- if (!isOneOf(value.status, TASK_LEDGER_STATUSES)) return false;
919
- if (value.parentGoalId !== void 0 && !isNullableString(value.parentGoalId)) return false;
920
- const hasPairedProvenance = value.origin === "user" ? isString(value.userTaskId) && /^u[1-9]\d*$/.test(value.userTaskId) : (value.origin === void 0 || value.origin === "agent") && value.userTaskId === void 0;
921
- return isOptionalString(value.description) && hasPairedProvenance;
922
- }
923
- function isTaskLedgerEvidence(value) {
924
- if (!isRecord(value)) return false;
925
- if (!isString(value.id) || !isString(value.description)) return false;
926
- if (!isOneOf(value.status, TASK_LEDGER_EVIDENCE_STATUSES)) return false;
927
- return isOptionalString(value.command) && isOptionalString(value.artifactPath) && isOptionalString(value.observedAt) && isOptionalString(value.notes);
928
- }
929
- function isDecisionRecord(value) {
930
- if (!isRecord(value)) return false;
931
- if (!isString(value.key) || !/^[a-z0-9]+(?:_[a-z0-9]+)*$/.test(value.key)) return false;
932
- if (!isString(value.value) || !isOneOf(value.status, DECISION_STATUSES) || !isString(value.decidedAt)) return false;
933
- if (!isOptionalString(value.label) || !isOptionalString(value.source_question)) return false;
934
- if (!isOptionalString(value.revisedAt) || !isOptionalString(value.correction)) return false;
935
- return value.status === "superseded" ? isString(value.revisedAt) : value.revisedAt === void 0 && value.correction === void 0;
936
- }
937
- function isOptionalCompactionUsage(value) {
938
- if (value === void 0) return true;
939
- if (!isRecord(value)) return false;
940
- const cost = value.cost;
941
- return isNumber(value.input) && isNumber(value.output) && isNumber(value.cacheRead) && isNumber(value.cacheWrite) && isNumber(value.reasoning) && isNumber(value.totalTokens) && isNumber(value.apiCalls) && isRecord(cost) && isNumber(cost.total);
942
- }
943
- function isProtectedArtifact(value) {
944
- if (!isRecord(value)) return false;
945
- return isString(value.path) && isString(value.protectedAt) && isString(value.reason) && isOneOf(value.source, PROTECTED_ARTIFACT_SOURCES) && isOptionalString(value.validationCommand) && isOptionalNumber(value.validationExitCode);
946
- }
947
- function isSessionHeader(value) {
948
- if (!isRecord(value)) return false;
949
- return value.type === "session" && isPositiveInteger(value.version) && isString(value.id) && isString(value.timestamp) && isString(value.cwd) && isOptionalString(value.parentSession) && isOptionalString(value.parentTurnId);
950
- }
951
- function isSessionEntry(value) {
952
- if (!value || typeof value !== "object") return false;
953
- const v = value;
954
- if (!hasBaseSessionEntryFields(v)) return false;
955
- if (!isOneOf(v.kind, SESSION_ENTRY_KINDS)) return false;
956
- switch (v.kind) {
957
- case "message":
958
- return Object.hasOwn(v, "payload") && isOneOf(v.role, MESSAGE_ROLES);
959
- case "bashExecution":
960
- return isString(v.command) && isString(v.output) && (v.exitCode === null || isNumber(v.exitCode)) && typeof v.cancelled === "boolean" && typeof v.truncated === "boolean" && isOptionalString(v.fullOutputPath) && isOptionalBoolean(v.excludeFromContext);
961
- case "custom":
962
- return isString(v.customType) && isOptionalBoolean(v.display);
963
- case "modelChange":
964
- return isString(v.provider) && isString(v.modelId) && isOptionalString(v.target);
965
- case "thinkingLevelChange":
966
- return isString(v.thinkingLevel);
967
- case "fileEntry":
968
- return isString(v.path) && isOneOf(v.operation, FILE_OPERATIONS) && isOptionalNumber(v.bytes) && isOptionalString(v.hash);
969
- case "branchSummary":
970
- return isString(v.fromTurnId) && isString(v.summary);
971
- case "compactionSummary":
972
- return isString(v.summary) && isNumber(v.tokensBefore) && isString(v.firstKeptTurnId) && isOptionalCompactionUsage(v.usage) && (v.trigger === void 0 || isOneOf(v.trigger, COMPACTION_TRIGGERS)) && isOptionalNumber(v.tokensAfter) && isOptionalNumber(v.messagesSummarized) && isOptionalBoolean(v.isSplitTurn);
973
- case "sessionInfo":
974
- return isOptionalString(v.name) && isOptionalString(v.targetTurnId) && isOptionalString(v.label);
975
- case "label":
976
- return isString(v.targetTurnId) && isOptionalString(v.label);
977
- case "protectedArtifact":
978
- return v.action === "protect" && isProtectedArtifact(v.artifact) && isOptionalString(v.toolName) && isOptionalString(v.toolCallId) && isOptionalString(v.runId) && isOptionalString(v.correlationId);
979
- case "skillActivation":
980
- return isSkillActivation(v.activation);
981
- case "taskLedger":
982
- return isOptionalString(v.boardId) && Array.isArray(v.goals) && v.goals.every(isTaskLedgerGoal) && Array.isArray(v.subgoals) && v.subgoals.every(isTaskLedgerGoal) && isStringArray(v.activeRunIds) && Array.isArray(v.requiredValidationEvidence) && v.requiredValidationEvidence.every(isTaskLedgerEvidence);
983
- case "decisionLedger":
984
- return isString(v.interviewId) && isOneOf(v.interviewStatus, DECISION_INTERVIEW_STATUSES) && isString(v.startedAt) && isString(v.endedAt) && isNumber(v.roundCount) && Number.isInteger(v.roundCount) && v.roundCount >= 0 && isOptionalString(v.summary) && isOptionalString(v.transcriptPath) && Array.isArray(v.decisions) && v.decisions.every(isDecisionRecord);
985
- case "workerRun":
986
- return isString(v.assignmentId) && isString(v.runId) && isOneOf(v.origin, WORKER_RUN_ORIGINS) && isString(v.agentId) && isWorkerRunRuntime(v.runtime) && isOptionalString(v.parentToolCallId);
987
- }
988
- return false;
989
- }
990
-
991
- // src/domains/session/task-board.ts
992
- var TASK_BOARD_GOAL_ID = "board";
993
- var LEGACY_TASK_BOARD_ID = "legacy";
994
- function isOpenUserTask(task) {
995
- return task.origin === "user" && (task.status === "pending" || task.status === "active");
996
- }
997
- function taskBoardCounts(board) {
998
- const counts = {
999
- total: board.tasks.length,
1000
- completed: 0,
1001
- active: 0,
1002
- pending: 0,
1003
- blocked: 0,
1004
- cancelled: 0,
1005
- open: 0
1006
- };
1007
- for (const task of board.tasks) {
1008
- if (task.status === "completed") counts.completed += 1;
1009
- else if (task.status === "active") counts.active += 1;
1010
- else if (task.status === "pending") counts.pending += 1;
1011
- else if (task.status === "blocked") counts.blocked += 1;
1012
- else counts.cancelled += 1;
1013
- }
1014
- counts.open = counts.pending + counts.active;
1015
- return counts;
1016
- }
1017
- function boardStatus(tasks) {
1018
- const counts = taskBoardCounts({ tasks });
1019
- if (counts.total === 0) return "pending";
1020
- if (counts.active > 0) return "active";
1021
- if (counts.open === 0 && counts.blocked === 0) return "completed";
1022
- if (counts.blocked > 0 && counts.open === 0) return "blocked";
1023
- return "pending";
1024
- }
1025
- function toTaskLedgerEntryFields(board, now) {
1026
- const evidence = [];
1027
- const subgoals = board.tasks.map((task) => {
1028
- if (task.status === "completed" && task.evidence) {
1029
- evidence.push({
1030
- id: `${task.id}.evidence`,
1031
- description: task.evidence,
1032
- status: "passed",
1033
- observedAt: now.toISOString()
1034
- });
1035
- }
1036
- const goal = {
1037
- id: task.id,
1038
- title: task.title,
1039
- status: task.status,
1040
- parentGoalId: TASK_BOARD_GOAL_ID
1041
- };
1042
- if (task.origin) goal.origin = task.origin;
1043
- if (task.userTaskId) goal.userTaskId = task.userTaskId;
1044
- if (task.reason) goal.description = task.reason;
1045
- return goal;
1046
- });
1047
- return {
1048
- kind: "taskLedger",
1049
- parentTurnId: null,
1050
- boardId: board.boardId,
1051
- goals: [{ id: TASK_BOARD_GOAL_ID, title: board.title, status: boardStatus(board.tasks) }],
1052
- subgoals,
1053
- activeRunIds: [...board.activeRunIds],
1054
- requiredValidationEvidence: evidence
1055
- };
1056
- }
1057
- function isTaskLedgerShaped(value) {
1058
- return isSessionEntry(value) && value.kind === "taskLedger";
1059
- }
1060
- function foldTaskBoard(entries) {
1061
- let last = null;
1062
- for (const raw of entries) {
1063
- if (isTaskLedgerShaped(raw)) last = toEntryView(raw);
1064
- }
1065
- return last;
1066
- }
1067
- function foldSessionTaskHistory(entries) {
1068
- const boards = /* @__PURE__ */ new Map();
1069
- for (const [index, raw] of entries.entries()) {
1070
- if (!isTaskLedgerShaped(raw)) continue;
1071
- const view = toEntryView(raw);
1072
- if (!view) continue;
1073
- const boardId = typeof raw.boardId === "string" && raw.boardId.length > 0 ? raw.boardId : LEGACY_TASK_BOARD_ID;
1074
- const timestamp = typeof raw.timestamp === "string" ? raw.timestamp : "";
1075
- if (boardId === LEGACY_TASK_BOARD_ID) {
1076
- boards.set(boardId, {
1077
- boardId,
1078
- title: view.title,
1079
- tasks: new Map(view.tasks.map((task) => [task.id, task])),
1080
- lastSnapshotAt: timestamp,
1081
- lastIndex: index
1082
- });
1083
- continue;
1084
- }
1085
- const existing = boards.get(boardId);
1086
- if (!existing) {
1087
- boards.set(boardId, {
1088
- boardId,
1089
- title: view.title,
1090
- tasks: new Map(view.tasks.map((task) => [task.id, task])),
1091
- lastSnapshotAt: timestamp,
1092
- lastIndex: index
1093
- });
1094
- continue;
1095
- }
1096
- existing.title = view.title;
1097
- for (const task of view.tasks) existing.tasks.set(task.id, task);
1098
- existing.lastSnapshotAt = timestamp;
1099
- existing.lastIndex = index;
1100
- }
1101
- return [...boards.values()].sort((left, right) => right.lastIndex - left.lastIndex).map(({ lastIndex: _lastIndex, tasks, ...board }) => ({ ...board, tasks: [...tasks.values()] }));
1102
- }
1103
- function toEntryView(entry) {
1104
- const boardGoal = entry.goals[0];
1105
- if (!boardGoal) return null;
1106
- const evidenceByTask = /* @__PURE__ */ new Map();
1107
- for (const item of entry.requiredValidationEvidence) {
1108
- const taskId = item.id.endsWith(".evidence") ? item.id.slice(0, -".evidence".length) : item.id;
1109
- evidenceByTask.set(taskId, item.description);
1110
- }
1111
- return {
1112
- boardId: entry.boardId ?? LEGACY_TASK_BOARD_ID,
1113
- title: boardGoal.title,
1114
- tasks: entry.subgoals.map((goal) => {
1115
- const task = {
1116
- id: goal.id,
1117
- title: goal.title,
1118
- status: goal.status,
1119
- origin: goal.origin ?? "agent"
1120
- };
1121
- if (goal.userTaskId) task.userTaskId = goal.userTaskId;
1122
- if (goal.description) task.reason = goal.description;
1123
- const evidence = evidenceByTask.get(goal.id);
1124
- if (evidence) task.evidence = evidence;
1125
- return task;
1126
- }),
1127
- // Run linkage is process-live: the runs recorded in old entries ended
1128
- // with the process that dispatched them, so a refold starts empty and
1129
- // the historical linkage stays readable in the earlier entries.
1130
- activeRunIds: []
1131
- };
1132
- }
1133
- function nextTaskId(tasks) {
1134
- let max = 0;
1135
- for (const task of tasks) {
1136
- const match = /^t(\d+)$/.exec(task.id);
1137
- if (match) max = Math.max(max, Number(match[1]));
1138
- }
1139
- return max + 1;
1140
- }
1141
- function normalizeTitles(titles) {
1142
- return titles.map((title) => title.trim()).filter((title) => title.length > 0);
1143
- }
1144
- function applyMutation(board, mutation) {
1145
- if (mutation.op === "plan") {
1146
- const titles = normalizeTitles(mutation.tasks);
1147
- if (mutation.title.trim().length === 0) return { error: "plan requires a non-empty title" };
1148
- if (titles.length === 0) return { error: "plan requires at least one task" };
1149
- const retained = board?.tasks.filter(isOpenUserTask) ?? [];
1150
- const notes2 = [];
1151
- const replacedOpen = board ? taskBoardCounts(board).open - retained.length : 0;
1152
- if (board && replacedOpen > 0) {
1153
- notes2.push(`replaced board "${board.title}" with ${replacedOpen} agent task(s) still open`);
1154
- }
1155
- if (retained.length > 0) notes2.push(`preserved ${retained.length} open operator task(s)`);
1156
- const start = nextTaskId(retained);
1157
- return {
1158
- board: {
1159
- boardId: "",
1160
- title: mutation.title.trim(),
1161
- tasks: [
1162
- ...retained,
1163
- ...titles.map((title, index) => ({
1164
- id: `t${start + index}`,
1165
- title,
1166
- status: "pending",
1167
- origin: "agent"
1168
- }))
1169
- ],
1170
- // Runs in flight outlive a board swap: they belong to the session,
1171
- // so the fresh board inherits the linkage until the runs finish.
1172
- activeRunIds: board?.activeRunIds ?? []
1173
- },
1174
- notes: notes2
1175
- };
1176
- }
1177
- if (mutation.op === "pick") {
1178
- const title = mutation.title.trim();
1179
- if (title.length === 0) return { error: "pick requires a non-empty operator task title" };
1180
- if (!/^u[1-9]\d*$/.test(mutation.userTaskId)) return { error: "pick requires an operator task id like u3" };
1181
- if (board?.tasks.some(
1182
- (task) => task.userTaskId === mutation.userTaskId && (task.status === "pending" || task.status === "active" || task.status === "completed")
1183
- )) {
1184
- return { error: `operator task ${mutation.userTaskId} is already linked to durable board work` };
1185
- }
1186
- const tasks2 = board?.tasks ?? [];
1187
- const picked = {
1188
- id: `t${nextTaskId(tasks2)}`,
1189
- title,
1190
- status: "pending",
1191
- origin: "user",
1192
- userTaskId: mutation.userTaskId
1193
- };
1194
- return {
1195
- board: {
1196
- boardId: board?.boardId ?? "",
1197
- title: board?.title ?? "Operator tasks",
1198
- tasks: [...tasks2, picked],
1199
- activeRunIds: board?.activeRunIds ?? []
1200
- },
1201
- notes: []
1202
- };
1203
- }
1204
- if (board === null) return { error: 'no task board yet; declare one with action="plan" first' };
1205
- if (mutation.op === "add") {
1206
- const titles = normalizeTitles(mutation.tasks);
1207
- if (titles.length === 0) return { error: "add requires at least one task" };
1208
- const start = nextTaskId(board.tasks);
1209
- const added = titles.map((title, index) => ({
1210
- id: `t${start + index}`,
1211
- title,
1212
- status: "pending",
1213
- origin: "agent"
1214
- }));
1215
- return { board: { ...board, tasks: [...board.tasks, ...added] }, notes: [] };
1216
- }
1217
- const target = board.tasks.find((task) => task.id === mutation.id);
1218
- if (!target) return { error: `task ${mutation.id} not found on the board` };
1219
- if (mutation.op === "block" && mutation.reason.trim().length === 0) {
1220
- return { error: "block requires a reason so the ledger records why work stopped" };
1221
- }
1222
- if (mutation.op === "done") {
1223
- if (mutation.evidence.trim().length === 0) {
1224
- return {
1225
- error: "done requires note as the evidence that the task actually finished (the command you ran, the file:line you verified). If the work did not happen, use block with a reason or drop it."
1226
- };
1227
- }
1228
- if (target.status === "pending") {
1229
- return {
1230
- error: `task ${target.id} was never started, so it cannot be completed. Start it and do the work, or record the truth with block (reason) or drop.`
1231
- };
1232
- }
1233
- }
1234
- const notes = [];
1235
- const tasks = board.tasks.map((task) => {
1236
- if (task.id !== target.id) {
1237
- if (mutation.op === "start" && task.status === "active") {
1238
- notes.push(`parked ${task.id} back to pending (one task active at a time)`);
1239
- return { ...task, status: "pending" };
1240
- }
1241
- return task;
1242
- }
1243
- return applyStatusMutation(task, mutation);
1244
- });
1245
- return { board: { ...board, tasks }, notes };
1246
- }
1247
- function applyStatusMutation(task, mutation) {
1248
- switch (mutation.op) {
1249
- case "start":
1250
- return { ...task, status: "active" };
1251
- case "done": {
1252
- const done = { ...task, status: "completed", evidence: mutation.evidence.trim() };
1253
- delete done.reason;
1254
- return done;
1255
- }
1256
- case "block":
1257
- return { ...task, status: "blocked", reason: mutation.reason.trim() };
1258
- case "drop": {
1259
- const dropped = { ...task, status: "cancelled" };
1260
- if (mutation.reason?.trim()) dropped.reason = mutation.reason.trim();
1261
- return dropped;
1262
- }
1263
- }
1264
- }
1265
- function createTaskBoardStore(deps = {}) {
1266
- let cachedSessionId;
1267
- let dirty = true;
1268
- let board = null;
1269
- const syncToSession = () => {
1270
- const sessionId = deps.getSessionId?.() ?? null;
1271
- if (!dirty && cachedSessionId === sessionId) return;
1272
- dirty = false;
1273
- cachedSessionId = sessionId;
1274
- try {
1275
- board = deps.readEntries ? foldTaskBoard(deps.readEntries()) : null;
1276
- } catch {
1277
- board = null;
1278
- }
1279
- };
1280
- const persist = (next) => {
1281
- try {
1282
- deps.appendEntry?.(toTaskLedgerEntryFields(next, deps.now?.() ?? /* @__PURE__ */ new Date()));
1283
- } catch {
1284
- }
1285
- };
1286
- const mutationRequiresAcknowledgement = (current, mutation) => {
1287
- if (mutation.op === "pick") return true;
1288
- if (mutation.op === "plan") return current?.tasks.some(isOpenUserTask) ?? false;
1289
- if (mutation.op !== "done") return false;
1290
- return current?.tasks.some((task) => task.id === mutation.id && task.origin === "user") ?? false;
1291
- };
1292
- return {
1293
- snapshot() {
1294
- syncToSession();
1295
- return board;
1296
- },
1297
- cachedSnapshot() {
1298
- const sessionId = deps.getSessionId?.() ?? null;
1299
- return !dirty && cachedSessionId === sessionId ? board : null;
1300
- },
1301
- historySnapshot() {
1302
- syncToSession();
1303
- try {
1304
- return deps.readEntries ? foldSessionTaskHistory(deps.readEntries()) : [];
1305
- } catch {
1306
- return [];
1307
- }
1308
- },
1309
- apply(mutation) {
1310
- syncToSession();
1311
- const result = applyMutation(board, mutation);
1312
- if ("error" in result) return { ok: false, message: result.error };
1313
- const needsBoardId = mutation.op === "plan" || result.board.boardId.length === 0;
1314
- const nextBoard = needsBoardId ? { ...result.board, boardId: deps.createBoardId?.() ?? randomUUID() } : result.board;
1315
- if (mutationRequiresAcknowledgement(board, mutation)) {
1316
- if (!deps.appendEntry) {
1317
- return { ok: false, message: "durable task-ledger persistence is unavailable for operator-linked work" };
1318
- }
1319
- try {
1320
- deps.appendEntry(toTaskLedgerEntryFields(nextBoard, deps.now?.() ?? /* @__PURE__ */ new Date()));
1321
- } catch (error) {
1322
- const message = error instanceof Error ? error.message : String(error);
1323
- return { ok: false, message: `could not persist operator-linked task board: ${message}` };
1324
- }
1325
- board = nextBoard;
1326
- return { ok: true, board: nextBoard, notes: result.notes };
1327
- }
1328
- board = nextBoard;
1329
- persist(nextBoard);
1330
- return { ok: true, board: nextBoard, notes: result.notes };
1331
- },
1332
- attachRun(runId) {
1333
- syncToSession();
1334
- if (board === null || runId.length === 0 || board.activeRunIds.includes(runId)) return;
1335
- board = { ...board, activeRunIds: [...board.activeRunIds, runId] };
1336
- persist(board);
1337
- },
1338
- detachRun(runId) {
1339
- syncToSession();
1340
- if (board === null || !board.activeRunIds.includes(runId)) return;
1341
- board = { ...board, activeRunIds: board.activeRunIds.filter((id) => id !== runId) };
1342
- persist(board);
1343
- },
1344
- invalidate() {
1345
- dirty = true;
1346
- }
1347
- };
1348
- }
1349
-
1350
1099
  // src/engine/antigravity/subprocess-runtime.ts
1351
1100
  init_esm_shims();
1352
- import { spawn } from "node:child_process";
1101
+ import { spawn as spawn2 } from "node:child_process";
1353
1102
 
1354
1103
  // src/engine/external-subprocess.ts
1355
1104
  init_esm_shims();
@@ -1464,7 +1213,7 @@ async function readStdout(child, emit, state) {
1464
1213
  }
1465
1214
  function startAntigravityWorkerRun(input, emit) {
1466
1215
  const args = buildAgyArgs(input);
1467
- const child = spawn(ANTIGRAVITY_BINARY, args, {
1216
+ const child = spawn2(ANTIGRAVITY_BINARY, args, {
1468
1217
  cwd: process.cwd(),
1469
1218
  env: process.env,
1470
1219
  stdio: ["ignore", "pipe", "pipe"]
@@ -1519,7 +1268,7 @@ function startAntigravityWorkerRun(input, emit) {
1519
1268
 
1520
1269
  // src/engine/claude/subprocess-runtime.ts
1521
1270
  init_esm_shims();
1522
- import { spawn as spawn2 } from "node:child_process";
1271
+ import { spawn as spawn3 } from "node:child_process";
1523
1272
  import { createInterface } from "node:readline";
1524
1273
 
1525
1274
  // src/engine/claude/session-id.ts
@@ -1712,7 +1461,7 @@ async function readJsonLines(child, emit, state) {
1712
1461
  }
1713
1462
  function startClaudeCodeWorkerRun(input, emit) {
1714
1463
  const args = buildClaudeCodeArgs(input);
1715
- const child = spawn2("claude", args, {
1464
+ const child = spawn3("claude", args, {
1716
1465
  cwd: process.cwd(),
1717
1466
  env: process.env,
1718
1467
  stdio: ["ignore", "pipe", "pipe"]
@@ -1775,6 +1524,12 @@ function startClaudeCodeWorkerRun(input, emit) {
1775
1524
  init_esm_shims();
1776
1525
  var WORKER_RUNTIME_MEDIATES_CLIO_DISPATCH = false;
1777
1526
 
1527
+ // src/tools/builtin-tool-catalog.ts
1528
+ init_esm_shims();
1529
+
1530
+ // src/tools/bash.ts
1531
+ init_esm_shims();
1532
+
1778
1533
  // src/tools/presentation.ts
1779
1534
  init_esm_shims();
1780
1535
  var FOLDED = { foldDefault: "folded", showDiffWhenFolded: false, failureExcerpt: true };
@@ -1827,8 +1582,215 @@ function toolPresentationPolicy(toolName, args) {
1827
1582
  return TOOL_PRESENTATION[toolName] ?? FOLDED;
1828
1583
  }
1829
1584
 
1830
- // src/tools/builtin-tool-catalog.ts
1831
- init_esm_shims();
1585
+ // src/tools/bash.ts
1586
+ var BASH_DISPLAY_MAX_BYTES = 16 * 1024;
1587
+ var BASH_OUTPUT_POLICIES = /* @__PURE__ */ new Set(["full", "bounded", "summary", "metadata-only"]);
1588
+ function bashContextDisposition(policy) {
1589
+ if (policy === "full") {
1590
+ return { mode: "full", maxBytes: BASH_DISPLAY_MAX_BYTES, downgradeExcerpt: "tail" };
1591
+ }
1592
+ if (policy === "summary") {
1593
+ return {
1594
+ mode: "summary",
1595
+ maxBytes: BASH_DISPLAY_MAX_BYTES,
1596
+ strategy: "diagnostic",
1597
+ redact: true
1598
+ };
1599
+ }
1600
+ if (policy === "metadata-only") return { mode: "metadata-only", maxBytes: BASH_DISPLAY_MAX_BYTES };
1601
+ return { mode: "bounded", maxBytes: BASH_DISPLAY_MAX_BYTES, excerpt: "tail" };
1602
+ }
1603
+ var BASH_DEFAULT_RESULT_DISPOSITION = {
1604
+ presentation: {
1605
+ ...toolPresentationPolicy(ToolNames.Bash, void 0),
1606
+ maxBytes: BASH_DISPLAY_MAX_BYTES,
1607
+ overflow: "tail"
1608
+ },
1609
+ context: bashContextDisposition("bounded")
1610
+ };
1611
+ function normalizeBashArguments(args) {
1612
+ return args.output_policy === void 0 ? { ...args, output_policy: "bounded" } : args;
1613
+ }
1614
+ function bashOutputPolicy(args) {
1615
+ const value = args.output_policy;
1616
+ return typeof value === "string" && BASH_OUTPUT_POLICIES.has(value) ? value : null;
1617
+ }
1618
+ function resolveBashResultDisposition(args, declared = BASH_DEFAULT_RESULT_DISPOSITION) {
1619
+ const policy = bashOutputPolicy(args) ?? "bounded";
1620
+ const base = declared ?? BASH_DEFAULT_RESULT_DISPOSITION;
1621
+ return { presentation: base.presentation, context: bashContextDisposition(policy) };
1622
+ }
1623
+ function normalizedBashDisposition(policy) {
1624
+ return {
1625
+ presentation: { ...BASH_DEFAULT_RESULT_DISPOSITION.presentation, maxBytes: BASH_DISPLAY_MAX_BYTES },
1626
+ context: bashContextDisposition(policy)
1627
+ };
1628
+ }
1629
+ function shapeBashProgress(rawOutput, outputBytes, policy) {
1630
+ const disposition = normalizedBashDisposition(policy);
1631
+ let output;
1632
+ if (policy === "metadata-only") {
1633
+ output = `bash: running; captured ${outputBytes} bytes; stdout/stderr omitted by metadata-only policy`;
1634
+ } else if (policy === "summary") {
1635
+ output = deterministicDiagnosticSummary(rawOutput, BASH_DISPLAY_MAX_BYTES, true).text;
1636
+ } else {
1637
+ output = truncateTail(rawOutput, {
1638
+ maxLines: DEFAULT_MAX_LINES,
1639
+ maxBytes: disposition.context.maxBytes
1640
+ }).content;
1641
+ }
1642
+ return {
1643
+ kind: "ok",
1644
+ output,
1645
+ details: {
1646
+ resultSize: {
1647
+ bytes: outputBytes,
1648
+ shownBytes: byteLength(output),
1649
+ maxBytes: BASH_DISPLAY_MAX_BYTES,
1650
+ truncated: byteLength(rawOutput) > byteLength(output),
1651
+ policy
1652
+ }
1653
+ }
1654
+ };
1655
+ }
1656
+ function bashResultDetails(result, rawOutput, outcome) {
1657
+ return {
1658
+ outcome,
1659
+ exitCode: result.exitCode,
1660
+ signal: result.signal,
1661
+ timedOut: result.timedOut,
1662
+ aborted: result.aborted,
1663
+ outputCapped: result.outputCapped,
1664
+ outputBytes: result.outputBytes,
1665
+ retainedBytes: byteLength(rawOutput),
1666
+ stdoutBytes: byteLength(result.stdout),
1667
+ stderrBytes: byteLength(result.stderr)
1668
+ };
1669
+ }
1670
+ var OBSERVE_COMMAND_PATTERN = /^\s*(?:cat|head|tail|ls|grep|rg|find)\b/;
1671
+ var OBSERVE_NUDGE_SESSION_LIMIT = 64;
1672
+ var observeNudgeSeenSessions = /* @__PURE__ */ new Set();
1673
+ function observeToolsNudge(command, sessionId) {
1674
+ if (!OBSERVE_COMMAND_PATTERN.test(command)) return "";
1675
+ const key = sessionId ?? "no-session";
1676
+ if (observeNudgeSeenSessions.has(key)) return "";
1677
+ if (observeNudgeSeenSessions.size >= OBSERVE_NUDGE_SESSION_LIMIT) {
1678
+ const oldest = observeNudgeSeenSessions.values().next().value;
1679
+ if (oldest !== void 0) observeNudgeSeenSessions.delete(oldest);
1680
+ }
1681
+ observeNudgeSeenSessions.add(key);
1682
+ return "\n\n[note: prefer the structured observe tools over shell file inspection: read pages files with offset/limit, ls lists directories, grep and find search, code_nav maps symbols. Their results are capped and continuable; keep bash for builds, git, and scripts.]";
1683
+ }
1684
+ var bashTool = {
1685
+ name: ToolNames.Bash,
1686
+ description: "Execute a bash command inside the session workspace. output_policy controls model context: bounded keeps the diagnostic tail and is the default; summary keeps deterministic redacted diagnostics; metadata-only keeps facts and retrieval; full is admitted only within the result budget.",
1687
+ parameters: typebox_exports.Object({
1688
+ command: typebox_exports.String({ description: "Bash command to execute." }),
1689
+ cwd: typebox_exports.Optional(
1690
+ typebox_exports.String({
1691
+ description: "Omit this. The command already runs at the session workspace root. Set it only to run in a subdirectory of that root, as a relative path; an absolute path outside the root is blocked."
1692
+ })
1693
+ ),
1694
+ timeout_ms: typebox_exports.Optional(typebox_exports.Number({ description: "Timeout in milliseconds." })),
1695
+ output_policy: typebox_exports.Optional(
1696
+ typebox_exports.Union([typebox_exports.Literal("full"), typebox_exports.Literal("bounded"), typebox_exports.Literal("summary"), typebox_exports.Literal("metadata-only")], {
1697
+ description: "Model-context disposition. Omit for bounded tail output. Use summary for noisy runs, metadata-only when only status and retrieval matter, and full only for known-small output."
1698
+ })
1699
+ )
1700
+ }),
1701
+ baseActionClass: "execute",
1702
+ executionMode: "sequential",
1703
+ prepareArguments: normalizeBashArguments,
1704
+ resolveResultDisposition: resolveBashResultDisposition,
1705
+ async run(args, options) {
1706
+ args = normalizeBashArguments(args);
1707
+ if (typeof args.command !== "string" || args.command.length === 0) {
1708
+ return { kind: "error", message: "bash: missing command argument" };
1709
+ }
1710
+ const outputPolicy = bashOutputPolicy(args);
1711
+ if (outputPolicy === null) {
1712
+ return {
1713
+ kind: "error",
1714
+ message: "bash: output_policy must be one of full, bounded, summary, or metadata-only (omit it for bounded)",
1715
+ details: { outcome: "invalid-arguments", exitCode: null }
1716
+ };
1717
+ }
1718
+ const cwdArg = typeof args.cwd === "string" && args.cwd.length > 0 ? args.cwd : void 0;
1719
+ let cwd;
1720
+ try {
1721
+ cwd = resolveSafeCwd(cwdArg === void 0 ? void 0 : expandPath(cwdArg), process.cwd());
1722
+ } catch {
1723
+ return {
1724
+ kind: "error",
1725
+ message: `bash: cwd '${cwdArg}' escapes workspace root '${process.cwd()}'; use a typed tool or a project policy entry with explicit cwd`
1726
+ };
1727
+ }
1728
+ const timeout = typeof args.timeout_ms === "number" && args.timeout_ms > 0 ? args.timeout_ms : 3e5;
1729
+ try {
1730
+ const runOptions = {
1731
+ cwd,
1732
+ timeoutMs: timeout,
1733
+ ...options?.signal === void 0 ? {} : { signal: options.signal }
1734
+ };
1735
+ if (options?.onUpdate !== void 0) {
1736
+ runOptions.onUpdate = (progress) => {
1737
+ options.onUpdate?.(shapeBashProgress(combineBashOutput(progress), progress.outputBytes, outputPolicy));
1738
+ };
1739
+ }
1740
+ const result = await runBashCommand(args.command, runOptions);
1741
+ const { error, aborted, timedOut, outputCapped } = result;
1742
+ const rawOutput = combineBashOutput(result);
1743
+ const output = rawOutput.trim();
1744
+ if (aborted) {
1745
+ const status = "bash: command aborted";
1746
+ return {
1747
+ kind: "error",
1748
+ message: output.length > 0 ? `${output}
1749
+
1750
+ ${status}` : status,
1751
+ details: bashResultDetails(result, rawOutput, "abort")
1752
+ };
1753
+ }
1754
+ if (timedOut) {
1755
+ const status = `bash: command timed out after ${timeout}ms`;
1756
+ return {
1757
+ kind: "error",
1758
+ message: output.length > 0 ? `${output}
1759
+
1760
+ ${status}` : status,
1761
+ details: bashResultDetails(result, rawOutput, "timeout")
1762
+ };
1763
+ }
1764
+ if (outputCapped) {
1765
+ const status = `bash: command output exceeded ${BASH_HARD_CAP_BYTES} bytes and was stopped`;
1766
+ return {
1767
+ kind: "error",
1768
+ message: output.length > 0 ? `${output}
1769
+
1770
+ ${status}` : status,
1771
+ details: bashResultDetails(result, rawOutput, "output-cap")
1772
+ };
1773
+ }
1774
+ if (error) {
1775
+ const code = typeof error.code === "number" ? error.code : error.code;
1776
+ const status = `bash: command failed (exit ${code ?? "?"})`;
1777
+ const message = output.length > 0 ? `${output}
1778
+
1779
+ ${status}` : `${status}: ${error.message}`;
1780
+ return { kind: "error", message, details: bashResultDetails(result, rawOutput, "nonzero") };
1781
+ }
1782
+ const body = rawOutput.length > 0 ? rawOutput : "(no output)";
1783
+ return {
1784
+ kind: "ok",
1785
+ output: `${body}${observeToolsNudge(args.command, options?.sessionId)}`,
1786
+ details: bashResultDetails(result, rawOutput, "success")
1787
+ };
1788
+ } catch (err) {
1789
+ const msg = err instanceof Error ? err.message : String(err);
1790
+ return { kind: "error", message: `bash: ${msg}` };
1791
+ }
1792
+ }
1793
+ };
1832
1794
 
1833
1795
  // src/tools/read.ts
1834
1796
  init_esm_shims();
@@ -2031,7 +1993,7 @@ var TOOL_METADATA = {
2031
1993
  "Use a narrower query or scope to inspect omitted content."
2032
1994
  ),
2033
1995
  costLatency: "local_fast",
2034
- promptHint: 'Call context with scope="skills" to list installed and marketplace skills; when one matches the task, or the operator names a skill or asks how one works, suggest the operator run /skill <name> (a marketplace skill is offered for install) and never load it uninvited. When the user message carries a skill request, first load that skill via context (scope="skills", name=<skill>) before doing anything else.'
1996
+ promptHint: 'Call context with scope="skills" to list installed and marketplace skills; when one matches the task, or the operator names a skill or asks how one works, suggest the operator run /skill <name> (a marketplace skill is offered for install) and never load it uninvited. When the user message carries a skill request, first load that skill via context (scope="skills", name=<skill>) before doing anything else. When an [evicted ...] marker names content you need, recall it with context(scope="recall", ref=...); re-read the file only when the marker says it changed.'
2035
1997
  },
2036
1998
  [ToolNames.CredentialPresent]: {
2037
1999
  objective: "Check whether a credential key is present without returning its value.",
@@ -2059,15 +2021,18 @@ var TOOL_METADATA = {
2059
2021
  resultSizePolicy: exactMutationPolicy,
2060
2022
  costLatency: "local_fast"
2061
2023
  },
2062
- // EXECUTE: the safe-exec spine (bash offloads its own overflow).
2024
+ // EXECUTE: the safe-exec spine (canonical shaping offloads Bash overflow).
2063
2025
  [ToolNames.Bash]: {
2064
2026
  objective: "Execute an explicit shell command when narrower tools are insufficient.",
2065
2027
  uiLabel: "Shell",
2066
2028
  retrySafety: "unknown",
2067
- resultSizePolicy: summaryPolicy(
2068
- "Use a narrower command or a dedicated verification/read/search tool to inspect omitted output."
2069
- ),
2070
- costLatency: "local_slow"
2029
+ resultSizePolicy: {
2030
+ ...summaryPolicy("Use a narrower command or a dedicated verification/read/search tool to inspect omitted output."),
2031
+ offloadMaxBytes: BASH_HARD_CAP_BYTES
2032
+ },
2033
+ resultDisposition: BASH_DEFAULT_RESULT_DISPOSITION,
2034
+ costLatency: "local_slow",
2035
+ promptHint: "Bash output_policy defaults to bounded diagnostic tail. Use summary for noisy commands, metadata-only when only outcome and retrieval matter, and full only when output is known to fit the bounded result budget."
2071
2036
  },
2072
2037
  [ToolNames.Git]: {
2073
2038
  objective: "Read-only git inspection: status, diff, or log.",
@@ -2976,7 +2941,7 @@ function isValidLineage(value) {
2976
2941
  // src/engine/claude/tool-safety.ts
2977
2942
  init_esm_shims();
2978
2943
  import { performance } from "node:perf_hooks";
2979
- function isRecord2(value) {
2944
+ function isRecord(value) {
2980
2945
  return typeof value === "object" && value !== null && !Array.isArray(value);
2981
2946
  }
2982
2947
  function stringField(record2, ...keys) {
@@ -3242,7 +3207,7 @@ function emitClaudeToolPermissionDecision(input) {
3242
3207
  return decision;
3243
3208
  }
3244
3209
  function coerceToolInput(value) {
3245
- return isRecord2(value) ? value : {};
3210
+ return isRecord(value) ? value : {};
3246
3211
  }
3247
3212
 
3248
3213
  // src/domains/dispatch/agent-candidates.ts
@@ -3433,8 +3398,11 @@ export {
3433
3398
  emitClaudeToolPermissionDecision,
3434
3399
  coerceToolInput,
3435
3400
  WORKER_RUNTIME_MEDIATES_CLIO_DISPATCH,
3401
+ combineBashOutput,
3402
+ runBashCommand,
3436
3403
  classifyResourceRead,
3437
3404
  toolPresentationPolicy,
3405
+ bashTool,
3438
3406
  readMaxBytes,
3439
3407
  readTool,
3440
3408
  toolPromptHintsForNames,
@@ -3472,11 +3440,6 @@ export {
3472
3440
  runKindSupportsLiveSteering,
3473
3441
  projectExecutionHandoffs,
3474
3442
  DISPATCH_BRIEFING_MAX_BYTES,
3475
- validateJobSpec,
3476
- isSessionHeader,
3477
- isSessionEntry,
3478
- taskBoardCounts,
3479
- foldSessionTaskHistory,
3480
- createTaskBoardStore
3443
+ validateJobSpec
3481
3444
  };
3482
- //# sourceMappingURL=chunk-LWLEKMDQ.js.map
3445
+ //# sourceMappingURL=chunk-ZYKPLLNQ.js.map