agentbox-app 0.1.6

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 (302) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +176 -0
  3. package/bin/agentbox.mjs +103 -0
  4. package/briefs/adhd-mode.md +5 -0
  5. package/briefs/message-rules.md +95 -0
  6. package/briefs/worker.md +230 -0
  7. package/briefs/writing-rules.md +336 -0
  8. package/main/account-discovery.mjs +145 -0
  9. package/main/account-tooling.mjs +261 -0
  10. package/main/agent-activity.mjs +56 -0
  11. package/main/agent-files.mjs +422 -0
  12. package/main/agent-schedule.mjs +254 -0
  13. package/main/agent-sessions.mjs +435 -0
  14. package/main/agents.mjs +1095 -0
  15. package/main/analytics.mjs +206 -0
  16. package/main/answer-modes.mjs +206 -0
  17. package/main/approval-prompt-server.mjs +160 -0
  18. package/main/approvals.mjs +487 -0
  19. package/main/artifact-path.mjs +144 -0
  20. package/main/claude-bin.mjs +311 -0
  21. package/main/claude-input.mjs +117 -0
  22. package/main/claude-models.mjs +244 -0
  23. package/main/claude-plan.mjs +148 -0
  24. package/main/claude-usage.mjs +149 -0
  25. package/main/code-change.mjs +383 -0
  26. package/main/code-file.mjs +116 -0
  27. package/main/codex-account.mjs +146 -0
  28. package/main/codex-app-server.mjs +796 -0
  29. package/main/codex-approvals.mjs +712 -0
  30. package/main/codex-bin.mjs +261 -0
  31. package/main/codex-compaction.mjs +49 -0
  32. package/main/codex-models.mjs +194 -0
  33. package/main/codex-session.mjs +797 -0
  34. package/main/codex-threads.mjs +268 -0
  35. package/main/codex-usage-file.mjs +192 -0
  36. package/main/codex-usage.mjs +149 -0
  37. package/main/codex-watch.mjs +35 -0
  38. package/main/codex.mjs +757 -0
  39. package/main/config.mjs +345 -0
  40. package/main/copy-selection.mjs +55 -0
  41. package/main/crash-report.mjs +158 -0
  42. package/main/demo.mjs +254 -0
  43. package/main/dev-window.mjs +103 -0
  44. package/main/doc-file.mjs +99 -0
  45. package/main/doc-scheme.mjs +126 -0
  46. package/main/first-run.mjs +190 -0
  47. package/main/folders.mjs +91 -0
  48. package/main/fresh-user.mjs +120 -0
  49. package/main/git-change.mjs +323 -0
  50. package/main/img-scheme.mjs +90 -0
  51. package/main/instruction-settings.mjs +205 -0
  52. package/main/ipc.mjs +1558 -0
  53. package/main/live-replies.mjs +77 -0
  54. package/main/machine.mjs +113 -0
  55. package/main/main.mjs +972 -0
  56. package/main/menu.mjs +177 -0
  57. package/main/notify.mjs +155 -0
  58. package/main/open-source-file.mjs +8 -0
  59. package/main/project-identity.mjs +149 -0
  60. package/main/provider-commands.mjs +32 -0
  61. package/main/rail-note.mjs +74 -0
  62. package/main/repeats.mjs +261 -0
  63. package/main/row-label.mjs +185 -0
  64. package/main/screen-detail.mjs +44 -0
  65. package/main/serve.mjs +262 -0
  66. package/main/settings.mjs +912 -0
  67. package/main/staleness.mjs +76 -0
  68. package/main/store/chats.mjs +188 -0
  69. package/main/store/home.mjs +383 -0
  70. package/main/store/migrate.mjs +40 -0
  71. package/main/store/paths.mjs +82 -0
  72. package/main/store/pending-writes.mjs +122 -0
  73. package/main/store/project-lock.mjs +200 -0
  74. package/main/store/project.mjs +523 -0
  75. package/main/store/queues.mjs +31 -0
  76. package/main/store/work-items.mjs +299 -0
  77. package/main/store/write-queue.mjs +14 -0
  78. package/main/store-modules.mjs +23 -0
  79. package/main/store.mjs +1269 -0
  80. package/main/supervisor.mjs +6875 -0
  81. package/main/task-commands.mjs +161 -0
  82. package/main/task-folders-offthread.mjs +84 -0
  83. package/main/task-folders-thread.mjs +13 -0
  84. package/main/task-folders.mjs +409 -0
  85. package/main/task-remote-control.mjs +65 -0
  86. package/main/task-terminals.mjs +169 -0
  87. package/main/terminal-access.mjs +6 -0
  88. package/main/updater.mjs +240 -0
  89. package/main/zoom-keys.mjs +54 -0
  90. package/main/zoom-readout.mjs +20 -0
  91. package/mcp/agentbox-mcp.sh +34 -0
  92. package/mcp/core/account.mjs +77 -0
  93. package/mcp/core/chat.mjs +61 -0
  94. package/mcp/core/documents.mjs +238 -0
  95. package/mcp/core/page.mjs +152 -0
  96. package/mcp/core/products.mjs +110 -0
  97. package/mcp/core/skills.mjs +126 -0
  98. package/mcp/core/work.mjs +377 -0
  99. package/mcp/stdio.mjs +70 -0
  100. package/mcp/tools.mjs +257 -0
  101. package/package.json +186 -0
  102. package/renderer/dist/assets/Geist-Variable-Bj2R_7yk.woff2 +0 -0
  103. package/renderer/dist/assets/GeistMono-Variable-Dispecij.woff2 +0 -0
  104. package/renderer/dist/assets/addon-fit-YJmn1quW.js +12 -0
  105. package/renderer/dist/assets/addon-serialize-CsFQTvP_.js +13 -0
  106. package/renderer/dist/assets/cel-dusk-CS5I7kJS.webp +0 -0
  107. package/renderer/dist/assets/cel-dusk-DUslqS6B.webp +0 -0
  108. package/renderer/dist/assets/cel-dusk-Jt_xVGxp.webp +0 -0
  109. package/renderer/dist/assets/cel-dusk-sm-BBkV-tWT.webp +0 -0
  110. package/renderer/dist/assets/frost-haze-CxPSOBEg.webp +0 -0
  111. package/renderer/dist/assets/frost-haze-sm-C_w21qgd.webp +0 -0
  112. package/renderer/dist/assets/gouache-valley-ChSu14-t.webp +0 -0
  113. package/renderer/dist/assets/gouache-valley-d9qasI6k.webp +0 -0
  114. package/renderer/dist/assets/gouache-valley-sm-CdLjT5Ec.webp +0 -0
  115. package/renderer/dist/assets/ice-BC8luINc.webp +0 -0
  116. package/renderer/dist/assets/ice-CP9PrKHo.webp +0 -0
  117. package/renderer/dist/assets/ice-river-D6ziOhLY.webp +0 -0
  118. package/renderer/dist/assets/ice-river-UVM2-JY_.webp +0 -0
  119. package/renderer/dist/assets/ice-river-bErJwYWW.webp +0 -0
  120. package/renderer/dist/assets/ice-river-sm-Bg1U-SIj.webp +0 -0
  121. package/renderer/dist/assets/ice-sm-CbVcg3_D.webp +0 -0
  122. package/renderer/dist/assets/index-CwiDv5bL.css +32 -0
  123. package/renderer/dist/assets/index-D9hCAVPl.js +684 -0
  124. package/renderer/dist/assets/lake-C0WaW-6E.webp +0 -0
  125. package/renderer/dist/assets/lake-CSKjLC5K.webp +0 -0
  126. package/renderer/dist/assets/lake-ETGcOb25.webp +0 -0
  127. package/renderer/dist/assets/lake-harbour-BCQRbrHb.webp +0 -0
  128. package/renderer/dist/assets/lake-harbour-B_wfXTmE.webp +0 -0
  129. package/renderer/dist/assets/lake-harbour-Te1pEvBh.webp +0 -0
  130. package/renderer/dist/assets/lake-harbour-sm-Cme_ShEg.webp +0 -0
  131. package/renderer/dist/assets/lake-sm-CbG72Hbv.webp +0 -0
  132. package/renderer/dist/assets/lino-coast-CUZHcucI.webp +0 -0
  133. package/renderer/dist/assets/lino-coast-DP4J7cgd.webp +0 -0
  134. package/renderer/dist/assets/lino-coast-kOIAffr_.webp +0 -0
  135. package/renderer/dist/assets/lino-coast-sm-C1Mdbgit.webp +0 -0
  136. package/renderer/dist/assets/moon-pines-BskgnnXR.webp +0 -0
  137. package/renderer/dist/assets/moon-pines-CFSIIwt0.webp +0 -0
  138. package/renderer/dist/assets/moon-pines-PNhdOYww.webp +0 -0
  139. package/renderer/dist/assets/moon-pines-sm-C6K1NomK.webp +0 -0
  140. package/renderer/dist/assets/orbit-rings-2XV36Ch3.webp +0 -0
  141. package/renderer/dist/assets/orbit-rings-C4NrcYGQ.webp +0 -0
  142. package/renderer/dist/assets/orbit-rings-DGLk07dT.webp +0 -0
  143. package/renderer/dist/assets/orbit-rings-sm-Dky3YdvL.webp +0 -0
  144. package/renderer/dist/assets/peach-haze-2-C6f7xnWw.webp +0 -0
  145. package/renderer/dist/assets/peach-haze-2-sm-Dj_Ez_Sb.webp +0 -0
  146. package/renderer/dist/assets/pixel-harbour-DQjqMROg.webp +0 -0
  147. package/renderer/dist/assets/pixel-harbour-Dw71H_bc.webp +0 -0
  148. package/renderer/dist/assets/pixel-harbour-kOZfm-GM.webp +0 -0
  149. package/renderer/dist/assets/pixel-harbour-sm-Dturjuky.webp +0 -0
  150. package/renderer/dist/assets/pixel-orbit-C296JVMO.webp +0 -0
  151. package/renderer/dist/assets/pixel-orbit-C4oMRDSx.webp +0 -0
  152. package/renderer/dist/assets/pixel-orbit-CqVmQ4eh.webp +0 -0
  153. package/renderer/dist/assets/pixel-orbit-sm-CHagC_nO.webp +0 -0
  154. package/renderer/dist/assets/pixel-ridge-C6LYu6uE.webp +0 -0
  155. package/renderer/dist/assets/pixel-ridge-CIUCEESs.webp +0 -0
  156. package/renderer/dist/assets/pixel-ridge-sm-BnE0F_w-.webp +0 -0
  157. package/renderer/dist/assets/riso-hills-7heKVtry.webp +0 -0
  158. package/renderer/dist/assets/riso-hills-CIjAL3J6.webp +0 -0
  159. package/renderer/dist/assets/riso-hills-sm-DHsnbCfP.webp +0 -0
  160. package/renderer/dist/assets/slate-haze-BPWdkNsw.webp +0 -0
  161. package/renderer/dist/assets/slate-haze-sm-B0Cb5a2W.webp +0 -0
  162. package/renderer/dist/assets/source-sans-3-cyrillic-ext-wght-normal-DzyfIafT.woff2 +0 -0
  163. package/renderer/dist/assets/source-sans-3-cyrillic-wght-normal-BMDVbyM7.woff2 +0 -0
  164. package/renderer/dist/assets/source-sans-3-greek-ext-wght-normal-BWSLJLk6.woff2 +0 -0
  165. package/renderer/dist/assets/source-sans-3-greek-wght-normal-C9H9m1vD.woff2 +0 -0
  166. package/renderer/dist/assets/source-sans-3-latin-ext-wght-normal-C8iNium2.woff2 +0 -0
  167. package/renderer/dist/assets/source-sans-3-latin-wght-normal-BqRLTx4X.woff2 +0 -0
  168. package/renderer/dist/assets/source-sans-3-vietnamese-wght-normal-C1uRvKPU.woff2 +0 -0
  169. package/renderer/dist/assets/valley-haze-BDHPqoJy.webp +0 -0
  170. package/renderer/dist/assets/valley-haze-sm-CTyjmPAG.webp +0 -0
  171. package/renderer/dist/assets/vector-dunes-DzzWLdKo.webp +0 -0
  172. package/renderer/dist/assets/vector-dunes-Yr9NBQUy.webp +0 -0
  173. package/renderer/dist/assets/vector-dunes-sm-D8MYY6ms.webp +0 -0
  174. package/renderer/dist/assets/watercolour-mist-BCGKN4u4.webp +0 -0
  175. package/renderer/dist/assets/watercolour-mist-BF-jk5MC.webp +0 -0
  176. package/renderer/dist/assets/watercolour-mist-sm-Ds1xzTw9.webp +0 -0
  177. package/renderer/dist/assets/woodblock-sea-B1um67Z9.webp +0 -0
  178. package/renderer/dist/assets/woodblock-sea-DKQdYs32.webp +0 -0
  179. package/renderer/dist/assets/woodblock-sea-sm-BJzNq8xh.webp +0 -0
  180. package/renderer/dist/assets/xterm-BT7tBf8A.js +27 -0
  181. package/renderer/dist/emulator/audio-rules.mjs +74 -0
  182. package/renderer/dist/emulator/data/compression/README.md +11 -0
  183. package/renderer/dist/emulator/data/compression/extract7z.js +1 -0
  184. package/renderer/dist/emulator/data/compression/extractzip.js +1 -0
  185. package/renderer/dist/emulator/data/compression/libunrar.js +519 -0
  186. package/renderer/dist/emulator/data/compression/libunrar.wasm +0 -0
  187. package/renderer/dist/emulator/data/cores/README.md +22 -0
  188. package/renderer/dist/emulator/data/cores/mgba-legacy-wasm.data +0 -0
  189. package/renderer/dist/emulator/data/cores/mgba-thread-legacy-wasm.data +0 -0
  190. package/renderer/dist/emulator/data/cores/mgba-thread-wasm.data +0 -0
  191. package/renderer/dist/emulator/data/cores/mgba-wasm.data +0 -0
  192. package/renderer/dist/emulator/data/cores/package.json +65 -0
  193. package/renderer/dist/emulator/data/cores/reports/mgba.json +1 -0
  194. package/renderer/dist/emulator/data/emulator.css +1614 -0
  195. package/renderer/dist/emulator/data/loader.js +170 -0
  196. package/renderer/dist/emulator/data/localization/README.md +63 -0
  197. package/renderer/dist/emulator/data/localization/af-FR.json +339 -0
  198. package/renderer/dist/emulator/data/localization/ar-AR.json +301 -0
  199. package/renderer/dist/emulator/data/localization/ben-BEN.json +301 -0
  200. package/renderer/dist/emulator/data/localization/de-GER.json +301 -0
  201. package/renderer/dist/emulator/data/localization/el-GR.json +301 -0
  202. package/renderer/dist/emulator/data/localization/en-US.json +339 -0
  203. package/renderer/dist/emulator/data/localization/es-ES.json +310 -0
  204. package/renderer/dist/emulator/data/localization/fa-AF.json +310 -0
  205. package/renderer/dist/emulator/data/localization/hi-HI.json +301 -0
  206. package/renderer/dist/emulator/data/localization/it-IT.json +302 -0
  207. package/renderer/dist/emulator/data/localization/ja-JA.json +301 -0
  208. package/renderer/dist/emulator/data/localization/jv-JV.json +301 -0
  209. package/renderer/dist/emulator/data/localization/ko-KO.json +336 -0
  210. package/renderer/dist/emulator/data/localization/pt-BR.json +361 -0
  211. package/renderer/dist/emulator/data/localization/retroarch.json +617 -0
  212. package/renderer/dist/emulator/data/localization/ro-RO.json +310 -0
  213. package/renderer/dist/emulator/data/localization/ru-RU.json +301 -0
  214. package/renderer/dist/emulator/data/localization/tr-TR.json +310 -0
  215. package/renderer/dist/emulator/data/localization/vi-VN.json +302 -0
  216. package/renderer/dist/emulator/data/localization/zh-CN.json +351 -0
  217. package/renderer/dist/emulator/data/src/GameManager.js +464 -0
  218. package/renderer/dist/emulator/data/src/compression.js +142 -0
  219. package/renderer/dist/emulator/data/src/emulator.js +6158 -0
  220. package/renderer/dist/emulator/data/src/gamepad.js +167 -0
  221. package/renderer/dist/emulator/data/src/nipplejs.js +1 -0
  222. package/renderer/dist/emulator/data/src/shaders.js +236 -0
  223. package/renderer/dist/emulator/data/src/socket.io.min.js +7 -0
  224. package/renderer/dist/emulator/data/src/storage.js +125 -0
  225. package/renderer/dist/emulator/data/version.json +5 -0
  226. package/renderer/dist/emulator/host.js +299 -0
  227. package/renderer/dist/emulator/index.html +28 -0
  228. package/renderer/dist/emulator/provenance.json +6 -0
  229. package/renderer/dist/fixtures/onboard/designs/w-n13/the-first-row.html +1 -0
  230. package/renderer/dist/index.html +13 -0
  231. package/scripts/after-install.mjs +59 -0
  232. package/scripts/approval-server.sh +43 -0
  233. package/scripts/before-publish.mjs +133 -0
  234. package/shared/agent-import.d.mts +13 -0
  235. package/shared/agent-import.mjs +252 -0
  236. package/shared/agents.d.mts +190 -0
  237. package/shared/agents.mjs +937 -0
  238. package/shared/analytics-events.mjs +63 -0
  239. package/shared/answers.d.mts +12 -0
  240. package/shared/answers.mjs +80 -0
  241. package/shared/artifact-keys.d.mts +28 -0
  242. package/shared/artifact-keys.mjs +140 -0
  243. package/shared/bridge-map.mjs +128 -0
  244. package/shared/claude-commands.d.mts +20 -0
  245. package/shared/claude-commands.generated.mjs +149 -0
  246. package/shared/claude-commands.mjs +131 -0
  247. package/shared/claude-models.generated.d.mts +15 -0
  248. package/shared/claude-models.generated.mjs +26 -0
  249. package/shared/claude-usage.d.mts +16 -0
  250. package/shared/claude-usage.mjs +172 -0
  251. package/shared/codex-commands.d.mts +4 -0
  252. package/shared/codex-commands.mjs +17 -0
  253. package/shared/codex-import.d.mts +38 -0
  254. package/shared/codex-import.mjs +232 -0
  255. package/shared/codex-modes.mjs +159 -0
  256. package/shared/codex-usage.mjs +180 -0
  257. package/shared/contracts.mjs +412 -0
  258. package/shared/crash-scrub.mjs +182 -0
  259. package/shared/dashboard.mjs +481 -0
  260. package/shared/dead-run-trace.mjs +127 -0
  261. package/shared/demo-world.mjs +415 -0
  262. package/shared/effort-levels.d.mts +15 -0
  263. package/shared/effort-levels.mjs +76 -0
  264. package/shared/engines.d.mts +62 -0
  265. package/shared/engines.mjs +389 -0
  266. package/shared/first-run-examples.mjs +60 -0
  267. package/shared/first-run-line.mjs +149 -0
  268. package/shared/first-run-practice.d.mts +32 -0
  269. package/shared/first-run-practice.mjs +254 -0
  270. package/shared/first-run-shape.mjs +100 -0
  271. package/shared/fresh-user-home.mjs +189 -0
  272. package/shared/hook-failure.mjs +22 -0
  273. package/shared/install-id.mjs +39 -0
  274. package/shared/instruction-defaults.json +5 -0
  275. package/shared/library-folder.mjs +28 -0
  276. package/shared/notify-rules.mjs +120 -0
  277. package/shared/product-name.d.mts +6 -0
  278. package/shared/product-name.mjs +144 -0
  279. package/shared/project-folder-check.d.mts +22 -0
  280. package/shared/project-folder-check.mjs +152 -0
  281. package/shared/provider-commands.d.mts +8 -0
  282. package/shared/provider-commands.mjs +58 -0
  283. package/shared/rank.d.mts +19 -0
  284. package/shared/rank.mjs +146 -0
  285. package/shared/recovery.mjs +26 -0
  286. package/shared/referenced-files.d.mts +11 -0
  287. package/shared/referenced-files.mjs +122 -0
  288. package/shared/repeats.d.mts +45 -0
  289. package/shared/repeats.mjs +193 -0
  290. package/shared/schemes.mjs +33 -0
  291. package/shared/settings-terminal.d.mts +1 -0
  292. package/shared/settings-terminal.mjs +14 -0
  293. package/shared/side-build.mjs +57 -0
  294. package/shared/spawn-trouble.d.mts +8 -0
  295. package/shared/spawn-trouble.mjs +599 -0
  296. package/shared/terminal-state.d.mts +1 -0
  297. package/shared/terminal-state.mjs +58 -0
  298. package/shared/usage.d.mts +53 -0
  299. package/shared/usage.mjs +319 -0
  300. package/shared/work-items.mjs +561 -0
  301. package/shared/work-lines.mjs +360 -0
  302. package/worker-permissions.json +6 -0
@@ -0,0 +1,360 @@
1
+ // PURE. WHAT A TOOL CALL SAYS ON HER SCREEN —, 2026-08-20.
2
+ //
3
+ // WHAT MESSY ACTUALLY WAS, measured over her seven live imported sessions on
4
+ // 2026-08-20, off the drawn screen and not off the source:
5
+ //
6
+ // 535 work lines in 162 runs 328 of them (61%) ran past the end of their box
7
+ // and were cut by the ellipsis, so she could not read them at all 368 of them
8
+ // (69%) were over sixty characters the six worst showed 2% to 4% of
9
+ // themselves; every one of those was `cd /Users/you/Desktop/dev/... &&
10
+ // python3 - <<'PY' ...` 18 distinct raw tool names were printed as verbs, the
11
+ // worst being `mcp__plugin_paper-desktop_paper__write_html`, 31 times in one
12
+ // thread the longest unbroken run was 20 lines, and that happened three times
13
+ //
14
+ // So there are three separate defects wearing one word, and this file is the
15
+ // three answers.
16
+ //
17
+ // ONE. THE INTERESTING PART OF A COMMAND IS NEVER AT THE FRONT. Every one of
18
+ // the six worst lines was a real command hiding behind a `cd` into an absolute
19
+ // path, or an `export PATH=` prelude, or both. Truncating from the right, which
20
+ // is what an ellipsis does, therefore threw away the only part she wanted and
21
+ // kept the part every line shares. `plainCommand` drops the prelude instead, so
22
+ // the line STARTS at the thing that ran.
23
+ //
24
+ // TWO. A PATH IS SHOWN FROM THE END. `/Users/you/Desktop/dev/zero/
25
+ // renderer/src/components/Tweaks.tsx` is 63 characters of which the last 11 are
26
+ // the answer. Under the session's own folder it becomes
27
+ // `renderer/src/components/Tweaks.tsx`; deeper than that it keeps the last
28
+ // three segments behind a leading ellipsis. Nothing is invented and nothing is
29
+ // silently dropped: the whole string is one press away on the line itself.
30
+ //
31
+ // THREE. A RUN AGGREGATES, WHICH IS THE WORD SHE USED. Consecutive tool calls
32
+ // fold into one line that says how many and what kind. The threshold is three
33
+ // and it is measured, not chosen: her run-length histogram is
34
+ // {1:38, 2:42, 3:36, 4:18, 5:6, 6:6, 7:8, 8:2, 11:2, 13:1, 20:3}. Folding at
35
+ // two takes the screen down 70% and folding at three takes it down 62%, so the
36
+ // last eight points cost her the 42 pairs, and a pair read as two short clean
37
+ // lines says more than "2 things it ran" does. Three is where a wall starts.
38
+ //
39
+ // NOTHING HERE HIDES A FAILURE. A folded run says on its own line that
40
+ // something in it failed, in the same words and the same colour a single line
41
+ // would, because a fold she has to open to find bad news in is worse than the
42
+ // wall it replaced.
43
+
44
+ /* ------------------------------ WHAT IT DID ------------------------------- */
45
+ // HER WORDS AND NOT OUR TOOL NAMES. The design law forbids jargon in UI copy,
46
+ // so "Bash" and "Glob" are ours, not hers.
47
+ const VERBS = {
48
+ Bash: 'ran',
49
+ Read: 'read',
50
+ Write: 'wrote',
51
+ Edit: 'edited',
52
+ MultiEdit: 'edited',
53
+ NotebookEdit: 'edited',
54
+ Glob: 'looked for',
55
+ Grep: 'searched for',
56
+ WebFetch: 'fetched',
57
+ WebSearch: 'searched the web for',
58
+ Task: 'sent off a helper',
59
+ TodoWrite: 'kept its list',
60
+ ListAgents: 'listed the other sessions',
61
+ SendMessage: 'messaged',
62
+ ToolSearch: 'looked up a tool',
63
+ // Measured in her own threads on 2026-08-20 and printed raw until now:
64
+ // `skill` 3 times and `askuserquestion` twice, both as bare lowercase names.
65
+ Skill: 'used a skill',
66
+ AskUserQuestion: 'asked a question',
67
+ BashOutput: 'checked on a command',
68
+ KillShell: 'stopped a command',
69
+ ExitPlanMode: 'finished planning',
70
+ };
71
+
72
+ // THE PREFIX STRIP WAS BROKEN AND HER LONGEST THREAD IS WHERE IT SHOWED. The
73
+ // old pattern was `^mcp__[^_]+__`, which needs the server's name to hold no
74
+ // underscore. `mcp__plugin_paper-desktop_paper__write_html` went through
75
+ // untouched and she read that string 31 times in one afternoon. An MCP name is
76
+ // `mcp__<server>__<tool>` and a server may contain anything, so the tool is
77
+ // what follows the LAST double underscore.
78
+ export function workVerb(name) {
79
+ const n = String(name ?? '').trim();
80
+ if (!n) return 'did something';
81
+ if (VERBS[n]) return VERBS[n];
82
+ const mcp = n.startsWith('mcp__') ? n.slice(n.lastIndexOf('__') + 2) : n;
83
+ // Underscores are how a machine spells a space. She reads the result, so it
84
+ // gets the space: `list_work_items` is jargon and `list work items` is a
85
+ // name, which is all this line has ever claimed to be.
86
+ return mcp.replace(/_+/g, ' ').trim().toLowerCase() || 'did something';
87
+ }
88
+
89
+ /* ------------------------------ A PATH, SHORT ----------------------------- */
90
+ // From the END, because that is where the answer is. Three segments is the
91
+ // budget: measured over her 535 lines, three segments holds the whole of every
92
+ // path that sits inside a repo and the meaningful tail of every scratch path.
93
+ const PATH_SEGMENTS = 3;
94
+
95
+ // `home` IS THE MACHINE'S, AND IT HAS NO DEFAULT. It used to default to
96
+ // `/Users/you`, which meant every path this shortened was shortened correctly
97
+ // on exactly one Mac in the world. Agentbox is downloaded now: on anybody
98
+ // else's, `~/notes.md` came out as `/Users/leon/notes.md`, which is the
99
+ // prefix-only line this whole file exists to stop. Nothing is guessed when
100
+ // nobody says whose Mac it is; the path is shown whole, which is worse than a
101
+ // tilde and is at least true.
102
+ export function shortPath(raw, cwd = '', home = '') {
103
+ const s = String(raw ?? '').trim();
104
+ if (!s) return '';
105
+ if (!s.startsWith('/') && !s.startsWith('~')) return s;
106
+
107
+ let p = s;
108
+ // `/private/tmp` and `/tmp` are the same folder on a Mac and she has never
109
+ // typed either. Saying `/private` first is the filesystem talking.
110
+ p = p.replace(/^\/private\/tmp\//, '/tmp/');
111
+
112
+ // Inside the folder this session is running in, a path is what she would
113
+ // type: relative, with nothing above it.
114
+ const base = String(cwd ?? '').replace(/^\/private\/tmp\//, '/tmp/').replace(/\/+$/, '');
115
+ if (base && (p === base || p.startsWith(`${base}/`))) {
116
+ const rel = p === base ? '' : p.slice(base.length + 1);
117
+ return rel ? trimSegments(rel) : './';
118
+ }
119
+
120
+ const h = String(home ?? '').replace(/\/+$/, '');
121
+ if (h && p.startsWith(`${h}/`)) p = `~/${p.slice(h.length + 1)}`;
122
+
123
+ return trimSegments(p);
124
+ }
125
+
126
+ // Keep the last few segments and say, with an ellipsis, that there were more.
127
+ // The leading `…/` is the whole of the honesty here: a bare `components/
128
+ // Tweaks.tsx` would read as a path from the root of something.
129
+ function trimSegments(p) {
130
+ // The lead is kept whole when nothing is trimmed, because `/x/store.mjs` and
131
+ // `x/store.mjs` are two different files and dropping the slash would be this
132
+ // function quietly saying the wrong one.
133
+ const lead = p.startsWith('~/') ? '~/' : p.startsWith('/') ? '/' : '';
134
+ const body = p.slice(lead.length);
135
+ const parts = body.split('/').filter(Boolean);
136
+ if (parts.length <= PATH_SEGMENTS) return lead + parts.join('/');
137
+ return `…/${parts.slice(-PATH_SEGMENTS).join('/')}`;
138
+ }
139
+
140
+ /* --------------------------- A COMMAND, PLAIN ----------------------------- */
141
+ // THE PRELUDE COMES OFF THE FRONT. Every shape below was counted in her own
142
+ // sessions on 2026-08-20; none of it is hypothetical.
143
+ //
144
+ // `cd /Users/you/Desktop/dev/zero && …` the commonest by far
145
+ // `export PATH="$HOME/.nvm/versions/node/…" ; …` 29 times in one thread
146
+ // `SP=/private/tmp/claude-501/-Users-…/… ; …` a bare assignment
147
+ // `source ~/.zshrc && …`
148
+ //
149
+ // Each is scaffolding that says nothing about what the agent was doing, and
150
+ // each is long enough on its own to fill the line. They come off one at a time
151
+ // until what is left is a command.
152
+ //
153
+ // WHAT IT NEVER DOES IS INVENT. If stripping leaves nothing, the original
154
+ // stands: an agent that genuinely only ran `cd somewhere` did that, and a line
155
+ // reading empty would be this function lying about it.
156
+ const PRELUDE = [
157
+ // cd <path> && |; | \n
158
+ /^cd\s+(?:"[^"]*"|'[^']*'|[^\s;&|]+)\s*(?:&&|;|\n)\s*/,
159
+ // export NAME=<value> && |; | \n (value may be quoted and may hold; or &)
160
+ /^export\s+[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|[^\s;&]*)\s*(?:&&|;|\n)\s*/,
161
+ // NAME=<value> && |; | \n (a bare assignment, same shapes)
162
+ /^[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|[^\s;&]*)\s*(?:&&|;|\n)\s*/,
163
+ // source|. <file> && |; | \n
164
+ /^(?:source|\.)\s+(?:"[^"]*"|'[^']*'|[^\s;&|]+)\s*(?:&&|;|\n)\s*/,
165
+ // echo "=== a banner ===" && |; | \n
166
+ //
167
+ // ONLY A BANNER, and the `===` or `---` is what makes it one. An agent
168
+ // labelling its own terminal output is talking to itself, and four of the 31
169
+ // worst lines left on her screen after the preludes came off were exactly
170
+ // this. A plain `echo something` is a real command and is left alone, because
171
+ // it may be the whole of what ran.
172
+ /^echo\s+(?:"[^"]*(?:===|---)[^"]*"|'[^']*(?:===|---)[^']*')\s*(?:&&|;|\n)\s*/,
173
+ ];
174
+
175
+ // A heredoc is a whole script pretending to be an argument. The longest in her
176
+ // sessions was 84 lines of python inside one `ran`. Everything from the marker
177
+ // onward becomes an ellipsis, so the line says which program was fed a script
178
+ // without printing the script.
179
+ const HEREDOC = /<<-?\s*(['"]?)([A-Za-z_][A-Za-z0-9_]*)\1([\s\S]*)$/;
180
+
181
+ // EXCEPT WHEN THE PROGRAM IS THE WHOLE OF WHAT IS LEFT. Drawn over her own
182
+ // thread on 2026-08-20 the first cut put three `python3 - …` lines in a row
183
+ // inside one fold, which distinguishes nothing. In every one of those the file
184
+ // being worked on was named on the script's FIRST line, so when the command in
185
+ // front of the marker is this short the first line comes with it.
186
+ const HEREDOC_HEAD = 12;
187
+
188
+ function firstScriptLine(body, marker) {
189
+ for (const line of String(body ?? '').split('\n')) {
190
+ const t = line.trim();
191
+ // The marker itself closes the heredoc and is not a line of the script.
192
+ // Matched exactly, because a one-word line of script looks just like one.
193
+ if (!t || t === marker) continue;
194
+ if (t.startsWith('#') || t.startsWith('//')) continue;
195
+ return t;
196
+ }
197
+ return '';
198
+ }
199
+
200
+ export function plainCommand(raw) {
201
+ let s = String(raw ?? '').trim();
202
+ if (!s) return '';
203
+ const whole = s;
204
+
205
+ // Peel the scaffolding, repeatedly: `cd x && export Y=z && npm test` is all
206
+ // three of these in a row.
207
+ for (let i = 0; i < 6; i += 1) {
208
+ const before = s;
209
+ for (const re of PRELUDE) s = s.replace(re, '');
210
+ if (s === before) break;
211
+ }
212
+ const doc = s.match(HEREDOC);
213
+ if (doc) {
214
+ const head = s.slice(0, doc.index).trim();
215
+ const first = head.length <= HEREDOC_HEAD ? firstScriptLine(doc[3], doc[2]) : '';
216
+ s = first ? `${head} … ${first}` : `${head} …`;
217
+ }
218
+ s = s.replace(/\s+/g, ' ').trim();
219
+ return s || whole.replace(/\s+/g, ' ').trim();
220
+ }
221
+
222
+ /* ------------------------------- THE SUBJECT ------------------------------ */
223
+ // WHICH ONE THIS WAS, in as few characters as the truth allows. `cwd` is the
224
+ // folder the session is running in, which is what makes a path relative; it is
225
+ // optional so that nothing that calls this without one gets worse than before.
226
+ export function workSubject(input, cwd = '', home = '') {
227
+ const i = input ?? {};
228
+ if (i.command != null && String(i.command).trim()) {
229
+ return plainCommand(i.command);
230
+ }
231
+ const path = i.file_path ?? i.path ?? i.notebook_path;
232
+ if (path != null && String(path).trim()) return shortPath(path, cwd, home);
233
+ const raw = i.pattern ?? i.query ?? i.to ?? i.url ?? i.prompt ?? '';
234
+ return String(raw).replace(/\s+/g, ' ').trim();
235
+ }
236
+
237
+ // THE WHOLE OF IT, for the line she opened. Nothing this file shortens is
238
+ // lost: the full string goes back on the screen above the output, and this is
239
+ // the function that says whether there is anything to put there.
240
+ export function fullSubject(input) {
241
+ const i = input ?? {};
242
+ const raw = i.command ?? i.file_path ?? i.path ?? i.notebook_path
243
+ ?? i.pattern ?? i.query ?? i.to ?? i.url ?? i.prompt ?? '';
244
+ return String(raw).replace(/\s+$/, '');
245
+ }
246
+
247
+ /* -------------------------------- THE RUN --------------------------------- */
248
+ // AGGREGATE, HER WORD. Three or more consecutive tool calls fold into one line.
249
+ // Two do not, because two clean lines say more than a fold does and 42 of her
250
+ // 162 runs are exactly two.
251
+ export const RUN_MIN = 3;
252
+
253
+ export function groupWork(events, { min = RUN_MIN } = {}) {
254
+ const out = [];
255
+ let run = [];
256
+ const flush = () => {
257
+ if (!run.length) return;
258
+ if (run.length >= min) out.push({ kind: 'run', at: run[0].at ?? 0, items: run });
259
+ else out.push(...run);
260
+ run = [];
261
+ };
262
+ for (const e of events ?? []) {
263
+ if (e && e.kind === 'work') { run.push(e); continue; }
264
+ flush();
265
+ out.push(e);
266
+ }
267
+ flush();
268
+ return out;
269
+ }
270
+
271
+ // WHAT THE FOLDED LINE SAYS. It says the number first, because the number is
272
+ // the thing a fold owes her: her standing objection to every cap in this
273
+ // codebase is a total that was rounded off without saying so.
274
+ //
275
+ // one verb, and one we have a plain word for `20 things it ran`
276
+ // one verb we do not `31 things it did · write html 31`
277
+ // several `24 things it did · ran 18 · read 4 · edited 2`
278
+ //
279
+ // Three verbs is the tally's budget; past that the rest is one more count, so
280
+ // the line never grows past what fits.
281
+ //
282
+ // A COUNT OF ONE IS NOT PRINTED. Drawn over her own threads on 2026-08-20 the
283
+ // first cut read `8 things it did · ran 5 · read 2 · asked a question 1`, and
284
+ // that trailing 1 reads as part of the name rather than as a number. A bare
285
+ // verb already says once.
286
+ const PLAIN = new Set(['ran', 'read', 'wrote', 'edited', 'looked for', 'searched for', 'fetched', 'messaged']);
287
+ const TALLY_VERBS = 3;
288
+
289
+ export function runSummary(items) {
290
+ const list = (items ?? []).filter(Boolean);
291
+ if (!list.length) return '';
292
+ const counts = new Map();
293
+ for (const e of list) counts.set(e.verb, (counts.get(e.verb) ?? 0) + 1);
294
+ const byCount = [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
295
+
296
+ if (byCount.length === 1 && PLAIN.has(byCount[0][0])) {
297
+ return `${list.length} thing${list.length === 1 ? '' : 's'} it ${byCount[0][0]}`;
298
+ }
299
+ const shown = byCount.slice(0, TALLY_VERBS).map(([v, n]) => (n === 1 ? v : `${v} ${n}`));
300
+ const rest = byCount.slice(TALLY_VERBS).reduce((s, [, n]) => s + n, 0);
301
+ if (rest) shown.push(`${rest} more`);
302
+ return `${list.length} things it did · ${shown.join(' · ')}`;
303
+ }
304
+
305
+ // THE BAD NEWS IS NEVER BEHIND THE FOLD. Said in her words on the closed line,
306
+ // in the one colour this surface uses.
307
+ export function runFailures(items) {
308
+ const bad = (items ?? []).filter((e) => e && e.failed).length;
309
+ if (!bad) return '';
310
+ return `${bad} failed`;
311
+ }
312
+
313
+ /* --------------------------- THE FILE IT CHANGED -------------------------- */
314
+ // A WORK LINE THAT SAYS IT CHANGED A FILE HANDS THE FILE OVER, so the thread
315
+ // can make it a chip.
316
+ //
317
+ // The same four tools main/code-change.mjs reads, and they have to stay the
318
+ // same four: one list saying which calls become a diff and another saying which
319
+ // lines become a chip is two lists that drift, and the symptom of the drift is
320
+ // a chip that opens onto a file the change does not hold.
321
+ export const CHANGES_A_FILE = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit']);
322
+
323
+ /**
324
+ * The path a tool call changed, whole and unshortened, or '' when it changed
325
+ * nothing. Whole because it is matched against the change's own list, and the
326
+ * shortened form on screen has had its front thrown away.
327
+ */
328
+ export function changedFile(name, input) {
329
+ if (!CHANGES_A_FILE.has(String(name ?? ''))) return '';
330
+ const i = input ?? {};
331
+ return String(i.file_path ?? i.notebook_path ?? '').trim();
332
+ }
333
+
334
+ /**
335
+ * Which entry of a change a path on a work line is, or null.
336
+ *
337
+ * A transcript records the ABSOLUTE path it wrote; a change records the path
338
+ * relative to one of the run's roots when it sits under one, and the absolute
339
+ * path when it does not (main/code-change.mjs). So the two shapes have to meet,
340
+ * and matching on the tail is what makes them: the change's key is either the
341
+ * whole string or a suffix of it at a segment boundary.
342
+ *
343
+ * The LONGEST match wins. `src/a.ts` and `renderer/src/a.ts` are different
344
+ * files and both are suffixes of the second one's absolute path; taking the
345
+ * first match would open whichever the change happened to list first.
346
+ */
347
+ export function fileInChange(paths, raw) {
348
+ const p = String(raw ?? '').trim().replace(/^\/private\/tmp\//, '/tmp/');
349
+ if (!p) return null;
350
+ let best = null;
351
+ for (const key of paths ?? []) {
352
+ const k = String(key ?? '').trim();
353
+ if (!k) continue;
354
+ const hit = k === p || p.endsWith(`/${k}`)
355
+ || k.replace(/^\/private\/tmp\//, '/tmp/') === p;
356
+ if (!hit) continue;
357
+ if (!best || k.length > best.length) best = key;
358
+ }
359
+ return best;
360
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "//": "Worker settings, passed per-spawn via --settings. It carries NO permission rules of our own, on purpose: workers run on Claude Code's own defaults for whatever mode they are in, the way Codex workers run on the Codex app's own posture (main/codex-session.mjs). Her words, w-6ade63e1aa, 2026-09-27: 'We just want to match Claude Code's and Codex's default settings. We typically don't want to have our own settings for things like this.' This used to ship allow Bash plus a 28-entry ask list. In auto mode Claude Code drops a blanket Bash allow and still forces a prompt on every ask rule, so the list did nothing but add cards: on w-60f57bec36, 10 of 10 cards in nine minutes were `vercel` commands it named. additionalDirectories is EMPTY ON PURPOSE and is filled in at spawn time by Supervisor.writeWorkerSettings with this person's own store root: it used to name one developer's home folder, which shipped inside the download and granted every stranger's agents a directory that does not exist on their Mac (w-24fa146714, 2026-08-23).",
3
+ "permissions": {
4
+ "additionalDirectories": []
5
+ }
6
+ }