@fitchmultz/pi-subagents 0.49.1 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1069) hide show
  1. package/CHANGELOG.md +72 -1
  2. package/README.md +119 -94
  3. package/dist/agent/contracts.js +104 -0
  4. package/dist/agent/cwd.js +51 -0
  5. package/dist/agent/host.js +69 -0
  6. package/dist/agent/index.js +456 -0
  7. package/dist/agent/journal-tail.js +142 -0
  8. package/dist/agent/launch.js +99 -0
  9. package/dist/agent/legacy.js +183 -0
  10. package/dist/agent/notifications.js +210 -0
  11. package/dist/agent/observation-state.js +246 -0
  12. package/dist/agent/observation-view.js +258 -0
  13. package/dist/agent/observation.js +346 -0
  14. package/dist/agent/observe-card.js +243 -0
  15. package/dist/agent/observe-chrome.js +85 -0
  16. package/dist/agent/observe-client.js +285 -0
  17. package/dist/agent/observe-layout.js +65 -0
  18. package/dist/agent/observe-reading.js +84 -0
  19. package/dist/agent/observe-screen.js +436 -0
  20. package/dist/agent/observe-transcript.js +382 -0
  21. package/dist/agent/observe.js +441 -0
  22. package/dist/agent/process.js +346 -0
  23. package/dist/agent/receipts.js +147 -0
  24. package/dist/agent/runner.js +477 -0
  25. package/dist/agent/saved.js +195 -0
  26. package/dist/agent/shell.js +44 -0
  27. package/dist/agent/storage.js +130 -0
  28. package/dist/agent/tool-schemas.js +20 -0
  29. package/dist/agent/typebox.js +25 -0
  30. package/dist/agent/usage.js +117 -0
  31. package/dist/agent/view.js +194 -0
  32. package/dist/agent/wake.js +99 -0
  33. package/dist/build-info.js +1 -0
  34. package/dist/index.js +8 -0
  35. package/dist/intercom-client.d.ts +26 -0
  36. package/dist/intercom-client.js +45 -0
  37. package/dist/pi-intercom/agent-dir.d.ts +1 -0
  38. package/dist/pi-intercom/bridge-config.js +12 -19
  39. package/dist/pi-intercom/bridge-http.js +1 -2
  40. package/dist/pi-intercom/bridge-mailbox.js +2 -7
  41. package/dist/pi-intercom/bridge-protocol.js +3 -10
  42. package/dist/pi-intercom/bridge-routes.js +15 -186
  43. package/dist/pi-intercom/bridge-session.js +4 -97
  44. package/dist/pi-intercom/bridge.js +12 -35
  45. package/dist/pi-intercom/broker/broker.js +57 -56
  46. package/dist/pi-intercom/broker/client-last.d.ts +13 -0
  47. package/dist/pi-intercom/broker/client-last.js +60 -0
  48. package/dist/pi-intercom/broker/client.d.ts +60 -0
  49. package/dist/pi-intercom/broker/client.js +75 -4
  50. package/dist/pi-intercom/broker/connection.d.ts +29 -0
  51. package/dist/pi-intercom/broker/connection.js +5 -18
  52. package/dist/pi-intercom/broker/framing.d.ts +17 -0
  53. package/dist/pi-intercom/broker/framing.js +10 -7
  54. package/dist/pi-intercom/broker/guard.js +23 -0
  55. package/dist/pi-intercom/broker/last.d.ts +26 -0
  56. package/dist/pi-intercom/broker/last.js +198 -0
  57. package/dist/pi-intercom/broker/paths.d.ts +13 -0
  58. package/dist/pi-intercom/broker/paths.js +58 -16
  59. package/dist/pi-intercom/broker/pid.js +5 -1
  60. package/dist/pi-intercom/broker/server-connection.js +37 -0
  61. package/dist/pi-intercom/broker/snapshot-reader.d.ts +9 -0
  62. package/dist/pi-intercom/broker/snapshots.d.ts +29 -0
  63. package/dist/pi-intercom/broker/spawn.js +32 -16
  64. package/dist/pi-intercom/broker/targets.d.ts +9 -0
  65. package/dist/pi-intercom/broker/targets.js +24 -0
  66. package/dist/pi-intercom/config.js +0 -23
  67. package/dist/pi-intercom/connection.js +40 -72
  68. package/dist/pi-intercom/identity.js +15 -44
  69. package/dist/pi-intercom/inbound-delivery.js +20 -125
  70. package/dist/pi-intercom/inbound-journal.js +85 -73
  71. package/dist/pi-intercom/inbound-record.js +20 -49
  72. package/dist/pi-intercom/inbound.js +17 -90
  73. package/dist/pi-intercom/index.js +11 -47
  74. package/dist/pi-intercom/last-message.js +46 -0
  75. package/dist/pi-intercom/lifecycle.js +96 -36
  76. package/dist/pi-intercom/message-format.js +1 -32
  77. package/dist/pi-intercom/outbound.js +14 -16
  78. package/dist/pi-intercom/reply-tracker.js +9 -18
  79. package/dist/pi-intercom/reply-wait.js +17 -108
  80. package/dist/pi-intercom/runtime-types.js +0 -1
  81. package/dist/pi-intercom/session-events.js +5 -21
  82. package/dist/pi-intercom/session-targets.d.ts +24 -0
  83. package/dist/pi-intercom/tool-arguments.js +4 -0
  84. package/dist/pi-intercom/tool-registration.js +8 -86
  85. package/dist/pi-intercom/tool-results.js +5 -7
  86. package/dist/pi-intercom/tool-schemas.js +13 -67
  87. package/dist/pi-intercom/tools.js +55 -29
  88. package/dist/pi-intercom/types.d.ts +212 -0
  89. package/dist/pi-intercom/types.js +62 -4
  90. package/dist/pi-intercom/ui/session-format.js +3 -3
  91. package/dist/pi-intercom/validation.d.ts +12 -0
  92. package/dist/pi-intercom/validation.js +3 -0
  93. package/dist/shared/bounded-json.js +151 -0
  94. package/dist/shared/compact-cards.js +66 -0
  95. package/dist/shared/journal-frames.js +3 -6
  96. package/dist/shared/journal-projections.js +0 -31
  97. package/dist/shared/json-projection.js +267 -129
  98. package/dist/shared/native-journal.js +123 -56
  99. package/dist/shared/post-exit-stdio-guard.js +120 -7
  100. package/dist/shared/tui-action.js +29 -0
  101. package/dist/shared/types.js +0 -195
  102. package/dist/shared/unknown.d.ts +9 -0
  103. package/docs/code-quality.md +6 -3
  104. package/docs/development.md +93 -92
  105. package/docs/intercom-bridge.md +211 -415
  106. package/docs/intercom.md +362 -593
  107. package/docs/performance.md +185 -192
  108. package/docs/reference.md +282 -1458
  109. package/docs/retired-history-maintenance.md +252 -0
  110. package/package.json +33 -27
  111. package/scripts/archive-retired-history.mjs +464 -0
  112. package/scripts/build.mjs +49 -29
  113. package/scripts/intercom-bridge-credentials.mjs +1 -1
  114. package/scripts/intercom-remote.mjs +55 -272
  115. package/scripts/local-install-smoke.mjs +3 -1
  116. package/scripts/measure-size.mjs +64 -0
  117. package/scripts/native-package-smoke.mjs +409 -110
  118. package/scripts/package-smoke.mjs +184 -358
  119. package/scripts/prepare.mjs +2 -2
  120. package/scripts/real-pi-live.mjs +377 -0
  121. package/scripts/real-pi-processes.mjs +12 -39
  122. package/scripts/real-pi-smoke.mjs +39 -306
  123. package/scripts/run-tests.mjs +5 -2
  124. package/scripts/typescript.mjs +35 -0
  125. package/skills/pi-intercom/SKILL.md +54 -107
  126. package/skills/pi-subagents/SKILL.md +76 -72
  127. package/src/agent/contracts.ts +118 -0
  128. package/src/agent/cwd.ts +69 -0
  129. package/src/agent/host.ts +81 -0
  130. package/src/agent/index.ts +520 -0
  131. package/src/agent/journal-tail.ts +172 -0
  132. package/src/agent/launch.ts +136 -0
  133. package/src/agent/legacy.ts +221 -0
  134. package/src/agent/notifications.ts +256 -0
  135. package/src/agent/observation-state.ts +277 -0
  136. package/src/agent/observation-view.ts +267 -0
  137. package/src/agent/observation.ts +405 -0
  138. package/src/agent/observe-card.ts +304 -0
  139. package/src/agent/observe-chrome.ts +170 -0
  140. package/src/agent/observe-client.ts +318 -0
  141. package/src/agent/observe-layout.ts +79 -0
  142. package/src/agent/observe-reading.ts +97 -0
  143. package/src/agent/observe-screen.ts +481 -0
  144. package/src/agent/observe-transcript.ts +434 -0
  145. package/src/agent/observe.ts +473 -0
  146. package/src/agent/process.ts +385 -0
  147. package/src/agent/receipts.ts +178 -0
  148. package/src/agent/runner.ts +515 -0
  149. package/src/agent/saved.ts +220 -0
  150. package/src/agent/shell.ts +57 -0
  151. package/src/agent/storage.ts +139 -0
  152. package/src/agent/tool-schemas.ts +33 -0
  153. package/src/agent/typebox.ts +22 -0
  154. package/src/agent/usage.ts +133 -0
  155. package/src/agent/view.ts +296 -0
  156. package/src/agent/wake.ts +107 -0
  157. package/src/index.ts +10 -0
  158. package/src/intercom-client.ts +108 -0
  159. package/src/pi-intercom/bridge-config.ts +13 -24
  160. package/src/pi-intercom/bridge-http.ts +1 -2
  161. package/src/pi-intercom/bridge-mailbox.ts +8 -8
  162. package/src/pi-intercom/bridge-protocol.ts +7 -11
  163. package/src/pi-intercom/bridge-routes.ts +29 -277
  164. package/src/pi-intercom/bridge-session.ts +5 -116
  165. package/src/pi-intercom/bridge.ts +12 -35
  166. package/src/pi-intercom/broker/broker.ts +63 -74
  167. package/src/pi-intercom/broker/client-last.ts +78 -0
  168. package/src/pi-intercom/broker/client.ts +87 -23
  169. package/src/pi-intercom/broker/connection.ts +5 -17
  170. package/src/pi-intercom/broker/framing.ts +11 -8
  171. package/src/pi-intercom/broker/guard.ts +33 -0
  172. package/src/pi-intercom/broker/last.ts +275 -0
  173. package/src/pi-intercom/broker/paths.ts +65 -16
  174. package/src/pi-intercom/broker/pid.ts +6 -1
  175. package/src/pi-intercom/broker/server-connection.ts +63 -0
  176. package/src/pi-intercom/broker/spawn.ts +44 -16
  177. package/src/pi-intercom/broker/targets.ts +42 -0
  178. package/src/pi-intercom/config.ts +0 -27
  179. package/src/pi-intercom/connection.ts +60 -92
  180. package/src/pi-intercom/identity.ts +24 -49
  181. package/src/pi-intercom/inbound-delivery.ts +25 -154
  182. package/src/pi-intercom/inbound-journal.ts +105 -86
  183. package/src/pi-intercom/inbound-record.ts +23 -65
  184. package/src/pi-intercom/inbound.ts +24 -117
  185. package/src/pi-intercom/index.ts +13 -49
  186. package/src/pi-intercom/last-message.ts +64 -0
  187. package/src/pi-intercom/lifecycle.ts +126 -50
  188. package/src/pi-intercom/message-format.ts +1 -34
  189. package/src/pi-intercom/outbound.ts +23 -17
  190. package/src/pi-intercom/reply-tracker.ts +10 -25
  191. package/src/pi-intercom/reply-wait.ts +23 -129
  192. package/src/pi-intercom/runtime-types.ts +5 -59
  193. package/src/pi-intercom/session-events.ts +7 -35
  194. package/src/pi-intercom/tool-arguments.ts +6 -0
  195. package/src/pi-intercom/tool-registration.ts +12 -109
  196. package/src/pi-intercom/tool-results.ts +10 -9
  197. package/src/pi-intercom/tool-schemas.ts +13 -108
  198. package/src/pi-intercom/tools.ts +58 -44
  199. package/src/pi-intercom/transport.ts +1 -0
  200. package/src/pi-intercom/types.ts +156 -6
  201. package/src/pi-intercom/ui/session-format.ts +3 -3
  202. package/src/pi-intercom/validation.ts +4 -0
  203. package/src/shared/bounded-json.ts +162 -0
  204. package/src/shared/compact-cards.ts +118 -0
  205. package/src/shared/journal-frames.ts +3 -19
  206. package/src/shared/journal-projections.ts +0 -35
  207. package/src/shared/json-projection.ts +267 -147
  208. package/src/shared/native-journal.ts +157 -75
  209. package/src/shared/post-exit-stdio-guard.ts +172 -8
  210. package/src/shared/tui-action.ts +39 -0
  211. package/src/shared/types.ts +0 -257
  212. package/tsconfig.client.json +8 -0
  213. package/tsconfig.json +1 -0
  214. package/agents/context-builder.md +0 -115
  215. package/agents/debugger.md +0 -58
  216. package/agents/delegate.md +0 -14
  217. package/agents/fixer.md +0 -40
  218. package/agents/oracle.md +0 -82
  219. package/agents/planner.md +0 -83
  220. package/agents/researcher.md +0 -60
  221. package/agents/reviewer-claude.md +0 -78
  222. package/agents/reviewer-gpt.md +0 -78
  223. package/agents/reviewer-ponytail.md +0 -92
  224. package/agents/reviewer-security.md +0 -92
  225. package/agents/reviewer.md +0 -78
  226. package/agents/scout.md +0 -77
  227. package/agents/ui-designer.md +0 -58
  228. package/agents/watcher.md +0 -27
  229. package/agents/worker.md +0 -52
  230. package/agents/writer.md +0 -39
  231. package/dist/agents/agent-defaults.js +0 -9
  232. package/dist/agents/agent-definition.js +0 -196
  233. package/dist/agents/agent-management.js +0 -88
  234. package/dist/agents/agent-scope.js +0 -9
  235. package/dist/agents/agent-selection.js +0 -13
  236. package/dist/agents/agent-serializer.js +0 -88
  237. package/dist/agents/agents.js +0 -111
  238. package/dist/agents/builtin-overrides.js +0 -218
  239. package/dist/agents/chain-serializer.js +0 -3
  240. package/dist/agents/config-values.js +0 -52
  241. package/dist/agents/discovery-paths.js +0 -91
  242. package/dist/agents/frontmatter.js +0 -31
  243. package/dist/agents/identity.js +0 -46
  244. package/dist/agents/json-chain.js +0 -254
  245. package/dist/agents/management-config.js +0 -332
  246. package/dist/agents/management-format.js +0 -231
  247. package/dist/agents/management-persistence.js +0 -287
  248. package/dist/agents/management-targets.js +0 -136
  249. package/dist/agents/management-warnings.js +0 -81
  250. package/dist/agents/markdown-chain.js +0 -210
  251. package/dist/agents/package-agents.js +0 -154
  252. package/dist/agents/skill-files.js +0 -157
  253. package/dist/agents/skill-search-paths.js +0 -246
  254. package/dist/agents/skill-types.js +0 -1
  255. package/dist/agents/skills.js +0 -125
  256. package/dist/extension/acceptance-schema.js +0 -55
  257. package/dist/extension/build-info.js +0 -1
  258. package/dist/extension/chain-schema.js +0 -196
  259. package/dist/extension/child-runtime.js +0 -237
  260. package/dist/extension/compact-tools.js +0 -183
  261. package/dist/extension/config-schema.js +0 -29
  262. package/dist/extension/config.js +0 -38
  263. package/dist/extension/control-notice-schema.js +0 -37
  264. package/dist/extension/control-notices.js +0 -36
  265. package/dist/extension/delegation-bridges.js +0 -43
  266. package/dist/extension/doctor.js +0 -166
  267. package/dist/extension/everyday-schemas.js +0 -207
  268. package/dist/extension/fanout-child.js +0 -25
  269. package/dist/extension/index.js +0 -28
  270. package/dist/extension/message-renderers.js +0 -225
  271. package/dist/extension/nested-control-inbox.js +0 -154
  272. package/dist/extension/parent-runtime.js +0 -339
  273. package/dist/extension/primary-tool.js +0 -69
  274. package/dist/extension/result-snapshot.js +0 -4
  275. package/dist/extension/runtime-reload.js +0 -62
  276. package/dist/extension/runtime-storage.js +0 -43
  277. package/dist/extension/schema-overrides.js +0 -75
  278. package/dist/extension/schemas.js +0 -345
  279. package/dist/extension/tool-input.js +0 -35
  280. package/dist/extension/tool-result.js +0 -29
  281. package/dist/history/answer-texts.js +0 -57
  282. package/dist/history/canonical-result.js +0 -114
  283. package/dist/history/canonical-selection.js +0 -40
  284. package/dist/history/database-generation.js +0 -82
  285. package/dist/history/database.js +0 -96
  286. package/dist/history/entry-ingestion.js +0 -61
  287. package/dist/history/index.js +0 -344
  288. package/dist/history/ingest.js +0 -314
  289. package/dist/history/output-digests.js +0 -40
  290. package/dist/history/preview.js +0 -210
  291. package/dist/history/prune.js +0 -33
  292. package/dist/history/queries.js +0 -81
  293. package/dist/history/query-scope.js +0 -190
  294. package/dist/history/rows.js +0 -77
  295. package/dist/history/run-projection.js +0 -136
  296. package/dist/history/run-queries.js +0 -153
  297. package/dist/history/schema.js +0 -31
  298. package/dist/history/search-queries.js +0 -169
  299. package/dist/history/selected-record.js +0 -108
  300. package/dist/history/source-file.js +0 -45
  301. package/dist/history/source-watches.js +0 -141
  302. package/dist/history/store.js +0 -243
  303. package/dist/history/text-chunks.js +0 -168
  304. package/dist/history/text.js +0 -35
  305. package/dist/history/transcript-queries.js +0 -183
  306. package/dist/history/types.js +0 -8
  307. package/dist/history/values.js +0 -36
  308. package/dist/history/wire-inputs.js +0 -122
  309. package/dist/history/wire-models.js +0 -38
  310. package/dist/history/worker-runtime.js +0 -441
  311. package/dist/history/worker.js +0 -91
  312. package/dist/intercom/intercom-bridge.js +0 -140
  313. package/dist/intercom/live-intercom.js +0 -151
  314. package/dist/intercom/nested-result-tree.js +0 -163
  315. package/dist/intercom/result-delivery.js +0 -40
  316. package/dist/intercom/result-intercom.js +0 -216
  317. package/dist/pi-intercom/bridge-ask.js +0 -57
  318. package/dist/pi-intercom/bridge-broadcast.js +0 -60
  319. package/dist/pi-intercom/bridge-catalog.js +0 -372
  320. package/dist/pi-intercom/bridge-control.js +0 -104
  321. package/dist/pi-intercom/bridge-groups.js +0 -135
  322. package/dist/pi-intercom/bridge-launch-journal.js +0 -84
  323. package/dist/pi-intercom/bridge-launch-policy.js +0 -154
  324. package/dist/pi-intercom/bridge-launch.js +0 -327
  325. package/dist/pi-intercom/bridge-operations.js +0 -127
  326. package/dist/pi-intercom/bridge-rpc-process.js +0 -292
  327. package/dist/pi-intercom/interview.js +0 -236
  328. package/dist/pi-intercom/native-control-auth.js +0 -80
  329. package/dist/pi-intercom/native-control-protocol.js +0 -111
  330. package/dist/pi-intercom/native-control.js +0 -130
  331. package/dist/pi-intercom/peer-awareness.js +0 -66
  332. package/dist/pi-intercom/saved-transcript.js +0 -135
  333. package/dist/pi-intercom/subagent-events.js +0 -238
  334. package/dist/pi-intercom/subagent-live-events.js +0 -175
  335. package/dist/pi-intercom/supervisor.js +0 -282
  336. package/dist/pi-intercom/topic-actions.js +0 -177
  337. package/dist/pi-intercom/topics.js +0 -242
  338. package/dist/pi-intercom/transcript.js +0 -175
  339. package/dist/pi-intercom/ui/compose-paste.js +0 -93
  340. package/dist/pi-intercom/ui/compose.js +0 -247
  341. package/dist/pi-intercom/ui/inline-message.js +0 -80
  342. package/dist/pi-intercom/ui/message-renderers.js +0 -147
  343. package/dist/pi-intercom/ui/overlay.js +0 -181
  344. package/dist/pi-intercom/ui/session-list.js +0 -157
  345. package/dist/pi-intercom/ui/tool-renderers.js +0 -110
  346. package/dist/pi-intercom/ui/topic-view.js +0 -88
  347. package/dist/runs/background/async-chain-plan.js +0 -265
  348. package/dist/runs/background/async-control.js +0 -171
  349. package/dist/runs/background/async-execution.js +0 -179
  350. package/dist/runs/background/async-job-admission.js +0 -40
  351. package/dist/runs/background/async-job-projection.js +0 -169
  352. package/dist/runs/background/async-job-tracker.js +0 -353
  353. package/dist/runs/background/async-launch.js +0 -216
  354. package/dist/runs/background/async-plan.js +0 -116
  355. package/dist/runs/background/async-result-file.js +0 -82
  356. package/dist/runs/background/async-resume.js +0 -247
  357. package/dist/runs/background/async-run-discovery.js +0 -211
  358. package/dist/runs/background/async-run-location.js +0 -135
  359. package/dist/runs/background/async-run-record.js +0 -1
  360. package/dist/runs/background/async-run-repair.js +0 -223
  361. package/dist/runs/background/async-run-summary.js +0 -1
  362. package/dist/runs/background/async-single-plan.js +0 -105
  363. package/dist/runs/background/async-status-projection.js +0 -155
  364. package/dist/runs/background/async-status-render.js +0 -117
  365. package/dist/runs/background/async-status-validation.js +0 -181
  366. package/dist/runs/background/async-status.js +0 -3
  367. package/dist/runs/background/async-value.js +0 -21
  368. package/dist/runs/background/completion-dedupe.js +0 -42
  369. package/dist/runs/background/completion-delivery.js +0 -251
  370. package/dist/runs/background/completion-receipts.js +0 -237
  371. package/dist/runs/background/legacy-status-acceptance.js +0 -34
  372. package/dist/runs/background/notify.js +0 -111
  373. package/dist/runs/background/parallel-groups.js +0 -72
  374. package/dist/runs/background/result-payload.js +0 -178
  375. package/dist/runs/background/result-watcher.js +0 -435
  376. package/dist/runs/background/run-id-resolver.js +0 -84
  377. package/dist/runs/background/run-schemas.js +0 -189
  378. package/dist/runs/background/run-status-contracts.js +0 -14
  379. package/dist/runs/background/run-status-render.js +0 -270
  380. package/dist/runs/background/run-status.js +0 -274
  381. package/dist/runs/background/runner-attempt-output.js +0 -155
  382. package/dist/runs/background/runner-attempt.js +0 -263
  383. package/dist/runs/background/runner-child-executor.js +0 -166
  384. package/dist/runs/background/runner-child-observer.js +0 -197
  385. package/dist/runs/background/runner-completion-summary.js +0 -71
  386. package/dist/runs/background/runner-completion.js +0 -211
  387. package/dist/runs/background/runner-config.js +0 -1
  388. package/dist/runs/background/runner-contract.js +0 -1
  389. package/dist/runs/background/runner-dynamic.js +0 -121
  390. package/dist/runs/background/runner-finalization.js +0 -149
  391. package/dist/runs/background/runner-graph.js +0 -68
  392. package/dist/runs/background/runner-initial-status.js +0 -60
  393. package/dist/runs/background/runner-lifecycle.js +0 -142
  394. package/dist/runs/background/runner-monitor.js +0 -311
  395. package/dist/runs/background/runner-parallel.js +0 -203
  396. package/dist/runs/background/runner-prepare-step.js +0 -86
  397. package/dist/runs/background/runner-reporting.js +0 -153
  398. package/dist/runs/background/runner-status.js +0 -148
  399. package/dist/runs/background/runner-step-output.js +0 -90
  400. package/dist/runs/background/runner-step-record.js +0 -45
  401. package/dist/runs/background/runner-step.js +0 -112
  402. package/dist/runs/background/runner-streaming.js +0 -173
  403. package/dist/runs/background/runner-workflow.js +0 -213
  404. package/dist/runs/background/stale-run-reconciler.js +0 -198
  405. package/dist/runs/background/subagent-runner-launcher.js +0 -75
  406. package/dist/runs/background/subagent-runner.js +0 -81
  407. package/dist/runs/background/top-level-async.js +0 -6
  408. package/dist/runs/foreground/chain-clarify.js +0 -428
  409. package/dist/runs/foreground/clarification-draft.js +0 -87
  410. package/dist/runs/foreground/clarify-contracts.js +0 -1
  411. package/dist/runs/foreground/clarify-invocation.js +0 -163
  412. package/dist/runs/foreground/clarify-text-editor.js +0 -210
  413. package/dist/runs/foreground/clarify-view.js +0 -167
  414. package/dist/runs/foreground/execution-input.js +0 -296
  415. package/dist/runs/foreground/execution-routing.js +0 -33
  416. package/dist/runs/foreground/execution-timeout.js +0 -81
  417. package/dist/runs/foreground/foreground-control.js +0 -276
  418. package/dist/runs/foreground/foreground-memory.js +0 -99
  419. package/dist/runs/foreground/invocation-context.js +0 -55
  420. package/dist/runs/foreground/invocation-execution.js +0 -331
  421. package/dist/runs/foreground/invocation-expansion.js +0 -48
  422. package/dist/runs/foreground/management-actions.js +0 -295
  423. package/dist/runs/foreground/nested-control.js +0 -179
  424. package/dist/runs/foreground/question-continuation.js +0 -78
  425. package/dist/runs/foreground/question-control.js +0 -193
  426. package/dist/runs/foreground/resume-target.js +0 -221
  427. package/dist/runs/foreground/revival-launch-policy.js +0 -58
  428. package/dist/runs/foreground/run-async-path.js +0 -217
  429. package/dist/runs/foreground/run-interrupt.js +0 -164
  430. package/dist/runs/foreground/run-nudge.js +0 -278
  431. package/dist/runs/foreground/saved-revival.js +0 -251
  432. package/dist/runs/foreground/subagent-executor.js +0 -153
  433. package/dist/runs/foreground/subagent-params.js +0 -202
  434. package/dist/runs/foreground/wait-observation.js +0 -104
  435. package/dist/runs/foreground/wait-registration.js +0 -17
  436. package/dist/runs/foreground/wait-run.js +0 -301
  437. package/dist/runs/shared/acceptance-contract.js +0 -347
  438. package/dist/runs/shared/acceptance-defaults.js +0 -1
  439. package/dist/runs/shared/acceptance-evaluation.js +0 -276
  440. package/dist/runs/shared/acceptance-finalization.js +0 -356
  441. package/dist/runs/shared/acceptance-outcome.js +0 -53
  442. package/dist/runs/shared/acceptance-reports.js +0 -212
  443. package/dist/runs/shared/acceptance-submission.js +0 -167
  444. package/dist/runs/shared/acceptance-verification.js +0 -100
  445. package/dist/runs/shared/acceptance.js +0 -4
  446. package/dist/runs/shared/chain-outputs.js +0 -138
  447. package/dist/runs/shared/child-attempt-types.js +0 -1
  448. package/dist/runs/shared/child-attempt.js +0 -340
  449. package/dist/runs/shared/child-boundaries.js +0 -173
  450. package/dist/runs/shared/child-context-filter.js +0 -44
  451. package/dist/runs/shared/child-event-observer.js +0 -390
  452. package/dist/runs/shared/child-execution-cwd.js +0 -126
  453. package/dist/runs/shared/child-execution-outcome.js +0 -72
  454. package/dist/runs/shared/child-invocation.js +0 -54
  455. package/dist/runs/shared/child-message-validation.js +0 -215
  456. package/dist/runs/shared/child-native-accounting.js +0 -106
  457. package/dist/runs/shared/child-native-observation.js +0 -69
  458. package/dist/runs/shared/child-observation-spool.js +0 -169
  459. package/dist/runs/shared/child-observations.js +0 -195
  460. package/dist/runs/shared/child-presence.js +0 -3
  461. package/dist/runs/shared/child-route-env.js +0 -119
  462. package/dist/runs/shared/child-stream-observer.js +0 -221
  463. package/dist/runs/shared/child-stream-projection.js +0 -137
  464. package/dist/runs/shared/child-structured-tool.js +0 -27
  465. package/dist/runs/shared/claude-code.js +0 -162
  466. package/dist/runs/shared/claude-model.js +0 -42
  467. package/dist/runs/shared/claude-session.js +0 -83
  468. package/dist/runs/shared/claude-types.js +0 -1
  469. package/dist/runs/shared/completion-guard.js +0 -31
  470. package/dist/runs/shared/control-event-policy.js +0 -8
  471. package/dist/runs/shared/control-notification-owner.js +0 -13
  472. package/dist/runs/shared/dynamic-fanout.js +0 -289
  473. package/dist/runs/shared/dynamic-item.js +0 -102
  474. package/dist/runs/shared/history-index.js +0 -98
  475. package/dist/runs/shared/legacy-async-recovery.js +0 -114
  476. package/dist/runs/shared/legacy-output-recovery.js +0 -148
  477. package/dist/runs/shared/mcp-config-schema.js +0 -36
  478. package/dist/runs/shared/mcp-direct-tool-allowlist.js +0 -365
  479. package/dist/runs/shared/model-fallback.js +0 -247
  480. package/dist/runs/shared/mutating-tool-guard.js +0 -210
  481. package/dist/runs/shared/native-finalization-types.js +0 -1
  482. package/dist/runs/shared/native-finalization.js +0 -180
  483. package/dist/runs/shared/native-usage.js +0 -293
  484. package/dist/runs/shared/nested-control-records.js +0 -128
  485. package/dist/runs/shared/nested-events.js +0 -8
  486. package/dist/runs/shared/nested-path.js +0 -52
  487. package/dist/runs/shared/nested-projection.js +0 -155
  488. package/dist/runs/shared/nested-protocol.js +0 -18
  489. package/dist/runs/shared/nested-registry.js +0 -191
  490. package/dist/runs/shared/nested-render.js +0 -156
  491. package/dist/runs/shared/nested-route.js +0 -220
  492. package/dist/runs/shared/nested-validation.js +0 -216
  493. package/dist/runs/shared/owned-child-evidence.js +0 -125
  494. package/dist/runs/shared/owned-run-list.js +0 -146
  495. package/dist/runs/shared/owned-run-observation.js +0 -267
  496. package/dist/runs/shared/owned-run-progress.js +0 -109
  497. package/dist/runs/shared/owned-run-read-state.js +0 -1
  498. package/dist/runs/shared/owned-run-results.js +0 -202
  499. package/dist/runs/shared/owned-run-status.js +0 -180
  500. package/dist/runs/shared/owned-run-view.js +0 -51
  501. package/dist/runs/shared/owned-workflow-details.js +0 -17
  502. package/dist/runs/shared/owner-output.js +0 -43
  503. package/dist/runs/shared/parallel-utils.js +0 -49
  504. package/dist/runs/shared/parent-receipts.js +0 -126
  505. package/dist/runs/shared/parent-usage.js +0 -233
  506. package/dist/runs/shared/pi-args.js +0 -217
  507. package/dist/runs/shared/pi-launch-input.js +0 -1
  508. package/dist/runs/shared/pi-session-launch.js +0 -86
  509. package/dist/runs/shared/pi-spawn.js +0 -66
  510. package/dist/runs/shared/run-history-queries.js +0 -136
  511. package/dist/runs/shared/run-history.js +0 -176
  512. package/dist/runs/shared/run-id-ambiguity.js +0 -4
  513. package/dist/runs/shared/run-metadata-paths.js +0 -14
  514. package/dist/runs/shared/run-metadata.js +0 -158
  515. package/dist/runs/shared/run-persistence.js +0 -131
  516. package/dist/runs/shared/run-records.js +0 -9
  517. package/dist/runs/shared/run-restoration.js +0 -337
  518. package/dist/runs/shared/run-state-owner.js +0 -26
  519. package/dist/runs/shared/session-cwd-preload.js +0 -42
  520. package/dist/runs/shared/single-output.js +0 -297
  521. package/dist/runs/shared/stable-value.js +0 -15
  522. package/dist/runs/shared/streaming-text.js +0 -26
  523. package/dist/runs/shared/structured-output.js +0 -67
  524. package/dist/runs/shared/subagent-control.js +0 -246
  525. package/dist/runs/shared/subagent-prompt-runtime.js +0 -94
  526. package/dist/runs/shared/subagent-tool-loop-guard.js +0 -95
  527. package/dist/runs/shared/supervisor-question-state.js +0 -145
  528. package/dist/runs/shared/supervisor-questions.js +0 -284
  529. package/dist/runs/shared/workflow-graph.js +0 -306
  530. package/dist/runs/shared/workflow-policy.js +0 -157
  531. package/dist/runs/shared/worktree-contract.js +0 -1
  532. package/dist/runs/shared/worktree-hook.js +0 -138
  533. package/dist/runs/shared/worktree-location.js +0 -47
  534. package/dist/runs/shared/worktree-preservation.js +0 -8
  535. package/dist/runs/shared/worktree-process.js +0 -107
  536. package/dist/runs/shared/worktree.js +0 -386
  537. package/dist/shared/agent-context-policy.js +0 -116
  538. package/dist/shared/agent-dir.js +0 -14
  539. package/dist/shared/artifacts.js +0 -114
  540. package/dist/shared/atomic-json.js +0 -16
  541. package/dist/shared/chain-files.js +0 -72
  542. package/dist/shared/concurrency.js +0 -18
  543. package/dist/shared/content-preview.js +0 -115
  544. package/dist/shared/execution-cwd.js +0 -22
  545. package/dist/shared/file-coalescer.js +0 -22
  546. package/dist/shared/fork-context.js +0 -47
  547. package/dist/shared/formatters.js +0 -111
  548. package/dist/shared/journal-reader.js +0 -6
  549. package/dist/shared/lazy-tools.js +0 -43
  550. package/dist/shared/message-output.js +0 -116
  551. package/dist/shared/model-info.js +0 -85
  552. package/dist/shared/native-import.js +0 -20
  553. package/dist/shared/native-session-loader.js +0 -17
  554. package/dist/shared/native-session.js +0 -4
  555. package/dist/shared/native-tui.js +0 -23
  556. package/dist/shared/native-typebox.js +0 -32
  557. package/dist/shared/prompt-sections.js +0 -10
  558. package/dist/shared/session-entries.js +0 -87
  559. package/dist/shared/session-identity.js +0 -16
  560. package/dist/shared/settings.js +0 -121
  561. package/dist/shared/status-format.js +0 -171
  562. package/dist/shared/task-file-policy.js +0 -24
  563. package/dist/shared/temp-root.js +0 -143
  564. package/dist/shared/types/acceptance.js +0 -1
  565. package/dist/shared/types/async.js +0 -1
  566. package/dist/shared/types/config.js +0 -1
  567. package/dist/shared/types/details.js +0 -1
  568. package/dist/shared/types/history.js +0 -1
  569. package/dist/shared/types/inputs.js +0 -1
  570. package/dist/shared/types/intercom.js +0 -1
  571. package/dist/shared/types/launch.js +0 -1
  572. package/dist/shared/types/messages.js +0 -1
  573. package/dist/shared/types/nested.js +0 -1
  574. package/dist/shared/types/owned-runs.js +0 -1
  575. package/dist/shared/types/progress.js +0 -1
  576. package/dist/shared/types/questions.js +0 -1
  577. package/dist/shared/types/results.js +0 -1
  578. package/dist/shared/types/state.js +0 -1
  579. package/dist/shared/types/usage.js +0 -1
  580. package/dist/shared/types/workflow.js +0 -1
  581. package/dist/shared/ui-mode.js +0 -3
  582. package/dist/shared/utils.js +0 -128
  583. package/dist/slash/command-discovery.js +0 -83
  584. package/dist/slash/command-input.js +0 -190
  585. package/dist/slash/prompt-template-bridge.js +0 -122
  586. package/dist/slash/prompt-template-contract.js +0 -77
  587. package/dist/slash/prompt-template-results.js +0 -125
  588. package/dist/slash/request-protocol.js +0 -68
  589. package/dist/slash/result-delivery.js +0 -237
  590. package/dist/slash/saved-chain.js +0 -78
  591. package/dist/slash/slash-bridge.js +0 -150
  592. package/dist/slash/slash-commands.js +0 -136
  593. package/dist/slash/slash-live-state.js +0 -267
  594. package/dist/tui/action-hints.js +0 -103
  595. package/dist/tui/activity-lines.js +0 -32
  596. package/dist/tui/agent-browser.js +0 -290
  597. package/dist/tui/agent-controls.js +0 -289
  598. package/dist/tui/agent-conversation.js +0 -444
  599. package/dist/tui/agent-dock.js +0 -171
  600. package/dist/tui/agent-history.js +0 -50
  601. package/dist/tui/agent-model.js +0 -62
  602. package/dist/tui/agent-picker.js +0 -262
  603. package/dist/tui/agent-view.js +0 -350
  604. package/dist/tui/compact-results.js +0 -193
  605. package/dist/tui/conversation-details.js +0 -190
  606. package/dist/tui/conversation-frame.js +0 -135
  607. package/dist/tui/conversation-history.js +0 -210
  608. package/dist/tui/conversation-menu.js +0 -78
  609. package/dist/tui/conversation-notices.js +0 -79
  610. package/dist/tui/conversation-selection.js +0 -58
  611. package/dist/tui/conversation-viewport.js +0 -129
  612. package/dist/tui/direction-message.js +0 -27
  613. package/dist/tui/display.js +0 -282
  614. package/dist/tui/editor-viewport.js +0 -18
  615. package/dist/tui/expanded-content.js +0 -87
  616. package/dist/tui/expanded-multi.js +0 -170
  617. package/dist/tui/expanded-single.js +0 -65
  618. package/dist/tui/history-cards.js +0 -202
  619. package/dist/tui/history-display.js +0 -238
  620. package/dist/tui/history-json.js +0 -16
  621. package/dist/tui/history-metadata.js +0 -152
  622. package/dist/tui/history-record.js +0 -251
  623. package/dist/tui/history-text.js +0 -34
  624. package/dist/tui/indexed-history.js +0 -116
  625. package/dist/tui/nested-widget.js +0 -120
  626. package/dist/tui/picker-page.js +0 -59
  627. package/dist/tui/render.js +0 -72
  628. package/dist/tui/result-facts.js +0 -64
  629. package/dist/tui/task-observation.js +0 -59
  630. package/dist/tui/task-store.js +0 -366
  631. package/dist/tui/text-values.js +0 -16
  632. package/dist/tui/view-connections.js +0 -47
  633. package/dist/tui/view-model.js +0 -94
  634. package/dist/tui/view-persistence.js +0 -51
  635. package/dist/tui/view-ports.js +0 -1
  636. package/dist/tui/view-session.js +0 -37
  637. package/dist/tui/widget-details.js +0 -144
  638. package/dist/tui/widget-status.js +0 -245
  639. package/dist/tui/widget.js +0 -145
  640. package/dist/tui/workflow-labels.js +0 -223
  641. package/dist/tui/workflow-outcomes.js +0 -124
  642. package/generated/RunValidators.d.ts +0 -28
  643. package/generated/RunValidators.js +0 -2
  644. package/prompts/gather-context-and-clarify.md +0 -14
  645. package/prompts/parallel-cleanup.md +0 -65
  646. package/prompts/parallel-context-build.md +0 -59
  647. package/prompts/parallel-handoff-plan.md +0 -68
  648. package/prompts/parallel-research.md +0 -55
  649. package/prompts/parallel-review.md +0 -61
  650. package/prompts/review-loop.md +0 -44
  651. package/scripts/generate-run-schemas.mjs +0 -210
  652. package/skills/pi-intercom/evals/evals.json +0 -29
  653. package/skills/pi-intercom/evals/trigger-evals.json +0 -47
  654. package/skills/pi-intercom/references/peer-sessions.md +0 -74
  655. package/skills/pi-subagents/evals/evals.json +0 -29
  656. package/skills/pi-subagents/evals/trigger-evals.json +0 -42
  657. package/skills/pi-subagents/references/full-orchestration-guide.md +0 -1005
  658. package/src/agents/agent-defaults.ts +0 -13
  659. package/src/agents/agent-definition.ts +0 -253
  660. package/src/agents/agent-management.ts +0 -120
  661. package/src/agents/agent-scope.ts +0 -11
  662. package/src/agents/agent-selection.ts +0 -22
  663. package/src/agents/agent-serializer.ts +0 -90
  664. package/src/agents/agents.ts +0 -214
  665. package/src/agents/builtin-overrides.ts +0 -297
  666. package/src/agents/chain-serializer.ts +0 -3
  667. package/src/agents/config-values.ts +0 -57
  668. package/src/agents/discovery-paths.ts +0 -134
  669. package/src/agents/frontmatter.ts +0 -39
  670. package/src/agents/identity.ts +0 -61
  671. package/src/agents/json-chain.ts +0 -305
  672. package/src/agents/management-config.ts +0 -342
  673. package/src/agents/management-format.ts +0 -243
  674. package/src/agents/management-persistence.ts +0 -408
  675. package/src/agents/management-targets.ts +0 -260
  676. package/src/agents/management-warnings.ts +0 -115
  677. package/src/agents/markdown-chain.ts +0 -237
  678. package/src/agents/package-agents.ts +0 -231
  679. package/src/agents/skill-files.ts +0 -182
  680. package/src/agents/skill-search-paths.ts +0 -289
  681. package/src/agents/skill-types.ts +0 -31
  682. package/src/agents/skills.ts +0 -179
  683. package/src/extension/acceptance-schema.ts +0 -88
  684. package/src/extension/build-info.ts +0 -2
  685. package/src/extension/chain-schema.ts +0 -276
  686. package/src/extension/child-runtime.ts +0 -302
  687. package/src/extension/compact-tools.ts +0 -271
  688. package/src/extension/config-schema.ts +0 -59
  689. package/src/extension/config.ts +0 -45
  690. package/src/extension/control-notice-schema.ts +0 -55
  691. package/src/extension/control-notices.ts +0 -71
  692. package/src/extension/delegation-bridges.ts +0 -59
  693. package/src/extension/doctor.ts +0 -207
  694. package/src/extension/everyday-schemas.ts +0 -252
  695. package/src/extension/fanout-child.ts +0 -33
  696. package/src/extension/index.ts +0 -31
  697. package/src/extension/message-renderers.ts +0 -334
  698. package/src/extension/nested-control-inbox.ts +0 -196
  699. package/src/extension/parent-runtime.ts +0 -405
  700. package/src/extension/primary-tool.ts +0 -130
  701. package/src/extension/result-snapshot.ts +0 -9
  702. package/src/extension/runtime-reload.ts +0 -72
  703. package/src/extension/runtime-storage.ts +0 -49
  704. package/src/extension/schema-overrides.ts +0 -114
  705. package/src/extension/schemas.ts +0 -477
  706. package/src/extension/tool-input.ts +0 -46
  707. package/src/extension/tool-result.ts +0 -47
  708. package/src/history/answer-texts.ts +0 -74
  709. package/src/history/canonical-result.ts +0 -138
  710. package/src/history/canonical-selection.ts +0 -54
  711. package/src/history/database-generation.ts +0 -86
  712. package/src/history/database.ts +0 -97
  713. package/src/history/entry-ingestion.ts +0 -129
  714. package/src/history/index.ts +0 -434
  715. package/src/history/ingest.ts +0 -387
  716. package/src/history/output-digests.ts +0 -41
  717. package/src/history/preview.ts +0 -235
  718. package/src/history/prune.ts +0 -48
  719. package/src/history/queries.ts +0 -125
  720. package/src/history/query-scope.ts +0 -278
  721. package/src/history/rows.ts +0 -118
  722. package/src/history/run-projection.ts +0 -162
  723. package/src/history/run-queries.ts +0 -199
  724. package/src/history/schema.ts +0 -34
  725. package/src/history/search-queries.ts +0 -223
  726. package/src/history/selected-record.ts +0 -140
  727. package/src/history/source-file.ts +0 -51
  728. package/src/history/source-watches.ts +0 -156
  729. package/src/history/store.ts +0 -332
  730. package/src/history/text-chunks.ts +0 -186
  731. package/src/history/text.ts +0 -43
  732. package/src/history/transcript-queries.ts +0 -257
  733. package/src/history/types.ts +0 -29
  734. package/src/history/values.ts +0 -36
  735. package/src/history/wire-inputs.ts +0 -141
  736. package/src/history/wire-models.ts +0 -51
  737. package/src/history/worker-runtime.ts +0 -502
  738. package/src/history/worker.ts +0 -99
  739. package/src/intercom/intercom-bridge.ts +0 -190
  740. package/src/intercom/live-intercom.ts +0 -209
  741. package/src/intercom/nested-result-tree.ts +0 -213
  742. package/src/intercom/result-delivery.ts +0 -56
  743. package/src/intercom/result-intercom.ts +0 -308
  744. package/src/pi-intercom/bridge-ask.ts +0 -64
  745. package/src/pi-intercom/bridge-broadcast.ts +0 -70
  746. package/src/pi-intercom/bridge-catalog.ts +0 -489
  747. package/src/pi-intercom/bridge-control.ts +0 -179
  748. package/src/pi-intercom/bridge-groups.ts +0 -169
  749. package/src/pi-intercom/bridge-launch-journal.ts +0 -122
  750. package/src/pi-intercom/bridge-launch-policy.ts +0 -190
  751. package/src/pi-intercom/bridge-launch.ts +0 -506
  752. package/src/pi-intercom/bridge-operations.ts +0 -169
  753. package/src/pi-intercom/bridge-rpc-process.ts +0 -330
  754. package/src/pi-intercom/interview.ts +0 -295
  755. package/src/pi-intercom/native-control-auth.ts +0 -89
  756. package/src/pi-intercom/native-control-protocol.ts +0 -180
  757. package/src/pi-intercom/native-control.ts +0 -160
  758. package/src/pi-intercom/peer-awareness.ts +0 -84
  759. package/src/pi-intercom/saved-transcript.ts +0 -175
  760. package/src/pi-intercom/subagent-events.ts +0 -299
  761. package/src/pi-intercom/subagent-live-events.ts +0 -236
  762. package/src/pi-intercom/supervisor.ts +0 -362
  763. package/src/pi-intercom/topic-actions.ts +0 -243
  764. package/src/pi-intercom/topics.ts +0 -271
  765. package/src/pi-intercom/transcript.ts +0 -226
  766. package/src/pi-intercom/ui/compose-paste.ts +0 -109
  767. package/src/pi-intercom/ui/compose.ts +0 -305
  768. package/src/pi-intercom/ui/inline-message.ts +0 -110
  769. package/src/pi-intercom/ui/message-renderers.ts +0 -182
  770. package/src/pi-intercom/ui/overlay.ts +0 -238
  771. package/src/pi-intercom/ui/session-list.ts +0 -222
  772. package/src/pi-intercom/ui/tool-renderers.ts +0 -148
  773. package/src/pi-intercom/ui/topic-view.ts +0 -107
  774. package/src/runs/background/async-chain-plan.ts +0 -451
  775. package/src/runs/background/async-control.ts +0 -219
  776. package/src/runs/background/async-execution.ts +0 -227
  777. package/src/runs/background/async-job-admission.ts +0 -54
  778. package/src/runs/background/async-job-projection.ts +0 -225
  779. package/src/runs/background/async-job-tracker.ts +0 -441
  780. package/src/runs/background/async-launch.ts +0 -319
  781. package/src/runs/background/async-plan.ts +0 -285
  782. package/src/runs/background/async-result-file.ts +0 -104
  783. package/src/runs/background/async-resume.ts +0 -386
  784. package/src/runs/background/async-run-discovery.ts +0 -264
  785. package/src/runs/background/async-run-location.ts +0 -194
  786. package/src/runs/background/async-run-record.ts +0 -14
  787. package/src/runs/background/async-run-repair.ts +0 -307
  788. package/src/runs/background/async-run-summary.ts +0 -71
  789. package/src/runs/background/async-single-plan.ts +0 -168
  790. package/src/runs/background/async-status-projection.ts +0 -188
  791. package/src/runs/background/async-status-render.ts +0 -164
  792. package/src/runs/background/async-status-validation.ts +0 -238
  793. package/src/runs/background/async-status.ts +0 -9
  794. package/src/runs/background/async-value.ts +0 -29
  795. package/src/runs/background/completion-dedupe.ts +0 -65
  796. package/src/runs/background/completion-delivery.ts +0 -321
  797. package/src/runs/background/completion-receipts.ts +0 -309
  798. package/src/runs/background/legacy-status-acceptance.ts +0 -38
  799. package/src/runs/background/notify.ts +0 -174
  800. package/src/runs/background/parallel-groups.ts +0 -102
  801. package/src/runs/background/result-payload.ts +0 -268
  802. package/src/runs/background/result-watcher.ts +0 -520
  803. package/src/runs/background/run-id-resolver.ts +0 -138
  804. package/src/runs/background/run-schemas.ts +0 -240
  805. package/src/runs/background/run-status-contracts.ts +0 -46
  806. package/src/runs/background/run-status-render.ts +0 -364
  807. package/src/runs/background/run-status.ts +0 -366
  808. package/src/runs/background/runner-attempt-output.ts +0 -281
  809. package/src/runs/background/runner-attempt.ts +0 -354
  810. package/src/runs/background/runner-child-executor.ts +0 -232
  811. package/src/runs/background/runner-child-observer.ts +0 -278
  812. package/src/runs/background/runner-completion-summary.ts +0 -106
  813. package/src/runs/background/runner-completion.ts +0 -274
  814. package/src/runs/background/runner-config.ts +0 -52
  815. package/src/runs/background/runner-contract.ts +0 -51
  816. package/src/runs/background/runner-dynamic.ts +0 -185
  817. package/src/runs/background/runner-finalization.ts +0 -203
  818. package/src/runs/background/runner-graph.ts +0 -91
  819. package/src/runs/background/runner-initial-status.ts +0 -72
  820. package/src/runs/background/runner-lifecycle.ts +0 -159
  821. package/src/runs/background/runner-monitor.ts +0 -401
  822. package/src/runs/background/runner-parallel.ts +0 -279
  823. package/src/runs/background/runner-prepare-step.ts +0 -128
  824. package/src/runs/background/runner-reporting.ts +0 -192
  825. package/src/runs/background/runner-status.ts +0 -220
  826. package/src/runs/background/runner-step-output.ts +0 -156
  827. package/src/runs/background/runner-step-record.ts +0 -76
  828. package/src/runs/background/runner-step.ts +0 -150
  829. package/src/runs/background/runner-streaming.ts +0 -220
  830. package/src/runs/background/runner-workflow.ts +0 -284
  831. package/src/runs/background/stale-run-reconciler.ts +0 -312
  832. package/src/runs/background/subagent-runner-launcher.ts +0 -88
  833. package/src/runs/background/subagent-runner.ts +0 -85
  834. package/src/runs/background/top-level-async.ts +0 -15
  835. package/src/runs/foreground/chain-clarify.ts +0 -505
  836. package/src/runs/foreground/clarification-draft.ts +0 -92
  837. package/src/runs/foreground/clarify-contracts.ts +0 -33
  838. package/src/runs/foreground/clarify-invocation.ts +0 -204
  839. package/src/runs/foreground/clarify-text-editor.ts +0 -229
  840. package/src/runs/foreground/clarify-view.ts +0 -222
  841. package/src/runs/foreground/execution-input.ts +0 -401
  842. package/src/runs/foreground/execution-routing.ts +0 -41
  843. package/src/runs/foreground/execution-timeout.ts +0 -92
  844. package/src/runs/foreground/foreground-control.ts +0 -342
  845. package/src/runs/foreground/foreground-memory.ts +0 -132
  846. package/src/runs/foreground/invocation-context.ts +0 -88
  847. package/src/runs/foreground/invocation-execution.ts +0 -465
  848. package/src/runs/foreground/invocation-expansion.ts +0 -58
  849. package/src/runs/foreground/management-actions.ts +0 -360
  850. package/src/runs/foreground/nested-control.ts +0 -248
  851. package/src/runs/foreground/question-continuation.ts +0 -112
  852. package/src/runs/foreground/question-control.ts +0 -309
  853. package/src/runs/foreground/resume-target.ts +0 -330
  854. package/src/runs/foreground/revival-launch-policy.ts +0 -112
  855. package/src/runs/foreground/run-async-path.ts +0 -327
  856. package/src/runs/foreground/run-interrupt.ts +0 -202
  857. package/src/runs/foreground/run-nudge.ts +0 -355
  858. package/src/runs/foreground/saved-revival.ts +0 -356
  859. package/src/runs/foreground/subagent-executor.ts +0 -203
  860. package/src/runs/foreground/subagent-params.ts +0 -392
  861. package/src/runs/foreground/wait-observation.ts +0 -160
  862. package/src/runs/foreground/wait-registration.ts +0 -18
  863. package/src/runs/foreground/wait-run.ts +0 -366
  864. package/src/runs/shared/acceptance-contract.ts +0 -458
  865. package/src/runs/shared/acceptance-defaults.ts +0 -1
  866. package/src/runs/shared/acceptance-evaluation.ts +0 -349
  867. package/src/runs/shared/acceptance-finalization.ts +0 -495
  868. package/src/runs/shared/acceptance-outcome.ts +0 -69
  869. package/src/runs/shared/acceptance-reports.ts +0 -246
  870. package/src/runs/shared/acceptance-submission.ts +0 -251
  871. package/src/runs/shared/acceptance-verification.ts +0 -118
  872. package/src/runs/shared/acceptance.ts +0 -31
  873. package/src/runs/shared/chain-outputs.ts +0 -206
  874. package/src/runs/shared/child-attempt-types.ts +0 -118
  875. package/src/runs/shared/child-attempt.ts +0 -387
  876. package/src/runs/shared/child-boundaries.ts +0 -217
  877. package/src/runs/shared/child-context-filter.ts +0 -53
  878. package/src/runs/shared/child-event-observer.ts +0 -496
  879. package/src/runs/shared/child-execution-cwd.ts +0 -162
  880. package/src/runs/shared/child-execution-outcome.ts +0 -103
  881. package/src/runs/shared/child-invocation.ts +0 -74
  882. package/src/runs/shared/child-message-validation.ts +0 -233
  883. package/src/runs/shared/child-native-accounting.ts +0 -154
  884. package/src/runs/shared/child-native-observation.ts +0 -79
  885. package/src/runs/shared/child-observation-spool.ts +0 -193
  886. package/src/runs/shared/child-observations.ts +0 -229
  887. package/src/runs/shared/child-presence.ts +0 -6
  888. package/src/runs/shared/child-route-env.ts +0 -142
  889. package/src/runs/shared/child-stream-observer.ts +0 -302
  890. package/src/runs/shared/child-stream-projection.ts +0 -160
  891. package/src/runs/shared/child-structured-tool.ts +0 -38
  892. package/src/runs/shared/claude-code.ts +0 -216
  893. package/src/runs/shared/claude-model.ts +0 -67
  894. package/src/runs/shared/claude-session.ts +0 -124
  895. package/src/runs/shared/claude-types.ts +0 -31
  896. package/src/runs/shared/completion-guard.ts +0 -44
  897. package/src/runs/shared/control-event-policy.ts +0 -15
  898. package/src/runs/shared/control-notification-owner.ts +0 -20
  899. package/src/runs/shared/dynamic-fanout.ts +0 -459
  900. package/src/runs/shared/dynamic-item.ts +0 -114
  901. package/src/runs/shared/history-index.ts +0 -130
  902. package/src/runs/shared/legacy-async-recovery.ts +0 -153
  903. package/src/runs/shared/legacy-output-recovery.ts +0 -214
  904. package/src/runs/shared/mcp-config-schema.ts +0 -46
  905. package/src/runs/shared/mcp-direct-tool-allowlist.ts +0 -465
  906. package/src/runs/shared/model-fallback.ts +0 -344
  907. package/src/runs/shared/mutating-tool-guard.ts +0 -295
  908. package/src/runs/shared/native-finalization-types.ts +0 -29
  909. package/src/runs/shared/native-finalization.ts +0 -252
  910. package/src/runs/shared/native-usage.ts +0 -396
  911. package/src/runs/shared/nested-control-records.ts +0 -178
  912. package/src/runs/shared/nested-events.ts +0 -45
  913. package/src/runs/shared/nested-path.ts +0 -65
  914. package/src/runs/shared/nested-projection.ts +0 -230
  915. package/src/runs/shared/nested-protocol.ts +0 -67
  916. package/src/runs/shared/nested-registry.ts +0 -273
  917. package/src/runs/shared/nested-render.ts +0 -217
  918. package/src/runs/shared/nested-route.ts +0 -292
  919. package/src/runs/shared/nested-validation.ts +0 -291
  920. package/src/runs/shared/owned-child-evidence.ts +0 -184
  921. package/src/runs/shared/owned-run-list.ts +0 -187
  922. package/src/runs/shared/owned-run-observation.ts +0 -368
  923. package/src/runs/shared/owned-run-progress.ts +0 -172
  924. package/src/runs/shared/owned-run-read-state.ts +0 -7
  925. package/src/runs/shared/owned-run-results.ts +0 -289
  926. package/src/runs/shared/owned-run-status.ts +0 -239
  927. package/src/runs/shared/owned-run-view.ts +0 -65
  928. package/src/runs/shared/owned-workflow-details.ts +0 -24
  929. package/src/runs/shared/owner-output.ts +0 -73
  930. package/src/runs/shared/parallel-utils.ts +0 -93
  931. package/src/runs/shared/parent-receipts.ts +0 -186
  932. package/src/runs/shared/parent-usage.ts +0 -344
  933. package/src/runs/shared/pi-args.ts +0 -280
  934. package/src/runs/shared/pi-launch-input.ts +0 -48
  935. package/src/runs/shared/pi-session-launch.ts +0 -94
  936. package/src/runs/shared/pi-spawn.ts +0 -76
  937. package/src/runs/shared/run-history-queries.ts +0 -195
  938. package/src/runs/shared/run-history.ts +0 -221
  939. package/src/runs/shared/run-id-ambiguity.ts +0 -8
  940. package/src/runs/shared/run-metadata-paths.ts +0 -17
  941. package/src/runs/shared/run-metadata.ts +0 -240
  942. package/src/runs/shared/run-persistence.ts +0 -181
  943. package/src/runs/shared/run-records.ts +0 -19
  944. package/src/runs/shared/run-restoration.ts +0 -455
  945. package/src/runs/shared/run-state-owner.ts +0 -31
  946. package/src/runs/shared/session-cwd-preload.ts +0 -47
  947. package/src/runs/shared/single-output.ts +0 -416
  948. package/src/runs/shared/stable-value.ts +0 -15
  949. package/src/runs/shared/streaming-text.ts +0 -45
  950. package/src/runs/shared/structured-output.ts +0 -98
  951. package/src/runs/shared/subagent-control.ts +0 -352
  952. package/src/runs/shared/subagent-prompt-runtime.ts +0 -119
  953. package/src/runs/shared/subagent-tool-loop-guard.ts +0 -139
  954. package/src/runs/shared/supervisor-question-state.ts +0 -221
  955. package/src/runs/shared/supervisor-questions.ts +0 -410
  956. package/src/runs/shared/workflow-graph.ts +0 -422
  957. package/src/runs/shared/workflow-policy.ts +0 -260
  958. package/src/runs/shared/worktree-contract.ts +0 -29
  959. package/src/runs/shared/worktree-hook.ts +0 -181
  960. package/src/runs/shared/worktree-location.ts +0 -61
  961. package/src/runs/shared/worktree-preservation.ts +0 -10
  962. package/src/runs/shared/worktree-process.ts +0 -132
  963. package/src/runs/shared/worktree.ts +0 -507
  964. package/src/shared/agent-context-policy.ts +0 -215
  965. package/src/shared/agent-dir.ts +0 -15
  966. package/src/shared/artifacts.ts +0 -126
  967. package/src/shared/atomic-json.ts +0 -19
  968. package/src/shared/chain-files.ts +0 -72
  969. package/src/shared/concurrency.ts +0 -27
  970. package/src/shared/content-preview.ts +0 -117
  971. package/src/shared/execution-cwd.ts +0 -39
  972. package/src/shared/file-coalescer.ts +0 -31
  973. package/src/shared/fork-context.ts +0 -72
  974. package/src/shared/formatters.ts +0 -125
  975. package/src/shared/journal-reader.ts +0 -18
  976. package/src/shared/lazy-tools.ts +0 -85
  977. package/src/shared/message-output.ts +0 -146
  978. package/src/shared/model-info.ts +0 -117
  979. package/src/shared/native-import.ts +0 -25
  980. package/src/shared/native-session-loader.ts +0 -13
  981. package/src/shared/native-session.ts +0 -6
  982. package/src/shared/native-tui.ts +0 -20
  983. package/src/shared/native-typebox.ts +0 -29
  984. package/src/shared/prompt-sections.ts +0 -16
  985. package/src/shared/session-entries.ts +0 -108
  986. package/src/shared/session-identity.ts +0 -25
  987. package/src/shared/settings.ts +0 -196
  988. package/src/shared/status-format.ts +0 -232
  989. package/src/shared/stream-json.d.ts +0 -10
  990. package/src/shared/task-file-policy.ts +0 -35
  991. package/src/shared/temp-root.ts +0 -158
  992. package/src/shared/types/acceptance.ts +0 -149
  993. package/src/shared/types/async.ts +0 -247
  994. package/src/shared/types/config.ts +0 -139
  995. package/src/shared/types/details.ts +0 -104
  996. package/src/shared/types/history.ts +0 -217
  997. package/src/shared/types/inputs.ts +0 -4
  998. package/src/shared/types/intercom.ts +0 -57
  999. package/src/shared/types/launch.ts +0 -39
  1000. package/src/shared/types/messages.ts +0 -104
  1001. package/src/shared/types/nested.ts +0 -153
  1002. package/src/shared/types/owned-runs.ts +0 -148
  1003. package/src/shared/types/progress.ts +0 -106
  1004. package/src/shared/types/questions.ts +0 -103
  1005. package/src/shared/types/results.ts +0 -119
  1006. package/src/shared/types/state.ts +0 -56
  1007. package/src/shared/types/usage.ts +0 -36
  1008. package/src/shared/types/workflow.ts +0 -187
  1009. package/src/shared/ui-mode.ts +0 -5
  1010. package/src/shared/utils.ts +0 -148
  1011. package/src/slash/command-discovery.ts +0 -110
  1012. package/src/slash/command-input.ts +0 -232
  1013. package/src/slash/prompt-template-bridge.ts +0 -161
  1014. package/src/slash/prompt-template-contract.ts +0 -152
  1015. package/src/slash/prompt-template-results.ts +0 -189
  1016. package/src/slash/request-protocol.ts +0 -87
  1017. package/src/slash/result-delivery.ts +0 -312
  1018. package/src/slash/saved-chain.ts +0 -115
  1019. package/src/slash/slash-bridge.ts +0 -224
  1020. package/src/slash/slash-commands.ts +0 -195
  1021. package/src/slash/slash-live-state.ts +0 -350
  1022. package/src/tui/action-hints.ts +0 -155
  1023. package/src/tui/activity-lines.ts +0 -40
  1024. package/src/tui/agent-browser.ts +0 -354
  1025. package/src/tui/agent-controls.ts +0 -355
  1026. package/src/tui/agent-conversation.ts +0 -514
  1027. package/src/tui/agent-dock.ts +0 -250
  1028. package/src/tui/agent-history.ts +0 -68
  1029. package/src/tui/agent-model.ts +0 -78
  1030. package/src/tui/agent-picker.ts +0 -325
  1031. package/src/tui/agent-view.ts +0 -403
  1032. package/src/tui/compact-results.ts +0 -342
  1033. package/src/tui/conversation-details.ts +0 -206
  1034. package/src/tui/conversation-frame.ts +0 -184
  1035. package/src/tui/conversation-history.ts +0 -260
  1036. package/src/tui/conversation-menu.ts +0 -119
  1037. package/src/tui/conversation-notices.ts +0 -116
  1038. package/src/tui/conversation-selection.ts +0 -66
  1039. package/src/tui/conversation-viewport.ts +0 -169
  1040. package/src/tui/direction-message.ts +0 -35
  1041. package/src/tui/display.ts +0 -409
  1042. package/src/tui/editor-viewport.ts +0 -19
  1043. package/src/tui/expanded-content.ts +0 -134
  1044. package/src/tui/expanded-multi.ts +0 -264
  1045. package/src/tui/expanded-single.ts +0 -92
  1046. package/src/tui/history-cards.ts +0 -298
  1047. package/src/tui/history-display.ts +0 -334
  1048. package/src/tui/history-json.ts +0 -17
  1049. package/src/tui/history-metadata.ts +0 -177
  1050. package/src/tui/history-record.ts +0 -321
  1051. package/src/tui/history-text.ts +0 -34
  1052. package/src/tui/indexed-history.ts +0 -149
  1053. package/src/tui/nested-widget.ts +0 -192
  1054. package/src/tui/picker-page.ts +0 -80
  1055. package/src/tui/render.ts +0 -104
  1056. package/src/tui/result-facts.ts +0 -99
  1057. package/src/tui/task-observation.ts +0 -96
  1058. package/src/tui/task-store.ts +0 -432
  1059. package/src/tui/text-values.ts +0 -20
  1060. package/src/tui/view-connections.ts +0 -64
  1061. package/src/tui/view-model.ts +0 -181
  1062. package/src/tui/view-persistence.ts +0 -57
  1063. package/src/tui/view-ports.ts +0 -55
  1064. package/src/tui/view-session.ts +0 -42
  1065. package/src/tui/widget-details.ts +0 -220
  1066. package/src/tui/widget-status.ts +0 -331
  1067. package/src/tui/widget.ts +0 -208
  1068. package/src/tui/workflow-labels.ts +0 -340
  1069. package/src/tui/workflow-outcomes.ts +0 -150
@@ -1,430 +1,226 @@
1
- # Secure remote Intercom bridge
2
-
3
- The bridge lets one authenticated remote agent, such as a Grok bot, work with Pi on your Mac unattended. It can message and ask any live Pi session, keep incoming messages and asks in a durable mailbox, wake the agent when mail sits unread, browse live and saved sessions, spawn and resume sessions, read recent transcripts, cancel or stop work, and broadcast to named groups.
4
-
5
- The bridge is a standalone Node HTTPS helper, `dist/pi-intercom/bridge.js`. Starting Pi never starts it. Pi-intercom's broker stays a same-machine Unix socket, and remote callers can't send raw broker frames.
6
-
7
- ## Design
8
-
9
- **Transport.** The helper listens only on `127.0.0.1`. Tailscale Serve exposes that port to your tailnet as a raw TCP forwarder, and the remote host reaches it through a forwarder on its own loopback. TLS runs end to end between the remote client and the helper; Tailscale carries encrypted bytes and never terminates TLS. Don't use Funnel, `--https` or `--tls-terminated-tcp` for this port. A Mac-initiated [SSH reverse forward](#ssh-alternative) also works.
10
-
11
- **Authentication.** TLS 1.2+ mutual authentication. A client presents a certificate issued by the bridge's private CA, and its SHA-256 fingerprint must be in the private allowlist. The client verifies the server against the same CA and its loopback SAN (`localhost`, `127.0.0.1`), so remote clients always use a loopback URL. Never use `curl -k` or disable verification.
12
-
13
- **Authority.** Each allowlisted certificate fixes one identity: its peer name, its Intercom ID (`remote-<fingerprint>`) and its home `cwd`. Request payloads can't change identity, and display names grant nothing. An authorized identity can use every bridge capability: list peers in any project, send text that agents treat as instructions, read transcripts, manage groups, spawn and resume sessions in any locally approved directory with any model, and cancel or stop work. Spawned sessions use your local tools, credentials and model budget. mTLS authenticates the caller; it doesn't sandbox the agents or make messages trustworthy. Issue certificates only to agents you trust with that authority. There is no broker-admin, raw RPC, shell or caller-supplied file-path endpoint.
14
-
15
- **Threat model.** The bridge denies unauthenticated callers on the tailnet or the Mac, revoked or expired certificates, identity spoofing, forged replies and control results, browser-origin requests and unbounded waits. It trusts the Mac user account, the OS, the broker, the private CA and the authorized remote host. Compromised endpoints and denial of service beyond the fixed connection and request limits are out of scope.
16
-
17
- **Broker.** The helper reuses Intercom's client, socket discovery and framing, so run it with Pi's `PI_CODING_AGENT_DIR` (default `~/.pi/agent`) and macOS per-user `TMPDIR`. It never restarts or replaces a live broker. Legacy messaging without `stateDir` never starts a broker. Persistent presence, spawn and resume use Pi's safe acquisition, including before any Pi session starts after reboot: reuse a healthy broker, start a detached broker only when none is running, and refuse a second broker while an unhealthy broker process may still own accepted work. Acquisition uses the normal PID-file/spawn-lock bookkeeping.
18
-
19
- **Availability.** The Mac must be awake, online and logged in, because the helper runs as a per-user LaunchAgent. Mail for the remote agent waits in its Mac mailbox while the agent is away. Nothing reaches Pi while the Mac is asleep, powered off or offline.
20
-
21
- **Audit.** stdout is JSONL metadata: identity, fingerprint, route, peer and message IDs, and outcomes, including wake and launch results. Message bodies, wake keys and private keys are never logged. Keep logs in a 0700 directory with 0600 files.
22
-
23
- ## Mac setup
24
-
25
- You need Node 24.21.0+, OpenSSL with `req -addext` (Homebrew OpenSSL works), Tailscale on both machines, and Pi with this package's Intercom extension. Examples use the identity `fitch-os` on port 9443. Replace `/Users/you` and other placeholders.
26
-
27
- ### 1. Install a release
28
-
29
- Install each helper version into a new directory and never edit it afterward. The service runs whatever `current` points to.
30
-
31
- ```bash
32
- RELEASES="$HOME/.pi/intercom-bridge-releases"
33
- NEW="$RELEASES/$(date +%Y%m%d-%H%M%S)"
34
- mkdir -p "$NEW"
35
- npm install --prefix "$NEW" --omit=dev @fitchmultz/pi-subagents
36
- PKG="$NEW/node_modules/@fitchmultz/pi-subagents"
37
- node "$PKG/dist/pi-intercom/bridge.js" --help
38
- ln -sfn "$NEW" "$RELEASES/current"
39
- ```
40
-
41
- ### 2. Create credentials
42
-
43
- ```bash
1
+ # Authenticated remote Intercom messaging
2
+
3
+ The optional standalone Node HTTPS helper lets a trusted remote Grok agent
4
+ exchange messages with reachable Pi peers. It preserves durable inbox transfer,
5
+ certificate-derived identity and unattended Grok wake/recovery. It does not start
6
+ or resume Pi sessions, inspect saved transcripts, control native processes,
7
+ manage groups, broadcast, or keep synchronous ask waiters.
8
+
9
+ Starting Pi never starts this helper. The broker remains a same-user Unix socket;
10
+ remote callers cannot send raw frames. Peer IDs and ambiguity handling belong to
11
+ the existing Intercom resolver. Discovery/target visibility follows the upstream
12
+ lineage owner; the helper does not infer agent roles or groups from names/cwd.
13
+ Remote Box identities register as standalone mains: they can reach local mains,
14
+ not delegated children. Children cannot address the Box, even by exact ID; their
15
+ main coordinates any remote exchange.
16
+
17
+ ## Transport and authority
18
+
19
+ - The helper binds only `127.0.0.1`, TLS 1.2+ with required client certificates.
20
+ The client verifies the server CA and loopback SAN. Never disable verification.
21
+ - A valid client certificate also needs its SHA-256 pin in private config. The
22
+ pin fixes its `remote-<fingerprint>` peer ID, display name and home cwd. A
23
+ request cannot supply another sender identity. Expiry/revocation deny new
24
+ requests, restored presence and wake delivery. Invalid reload denies everyone.
25
+ - Tailscale Serve may forward raw TCP to loopback; it must not terminate TLS.
26
+ Restrict the port to trusted remote hosts. Do not use Funnel or a wildcard bind.
27
+ An approved Mac-initiated SSH reverse loopback forward is also possible.
28
+ - Authenticated message text remains untrusted input. This is coordination, not
29
+ an OS sandbox: the receiving agent's ordinary tools/budget still apply.
30
+ - The Mac must be awake, logged in and online. Mail waits durably while Grok is
31
+ away; the helper cannot reach Pi while its Mac is asleep/offline.
32
+
33
+ stdout contains JSONL metadata only: identities, message/peer IDs and outcomes,
34
+ not message text or secrets. Keep logs private. Connections are capped at 128,
35
+ concurrent operations per identity at eight, request bodies at 64 KiB and ordinary
36
+ HTTP deadlines at 15 seconds. Browser-origin/fetch-metadata requests are denied.
37
+
38
+ ## Configuration
39
+
40
+ Use Node >=24.21.0 and the packaged `dist/pi-intercom/bridge.js`. Provision an
41
+ immutable reviewed release, keep the prior compiled release for rollback and
42
+ point a separately supervised service at it. Installation/restart is an explicit
43
+ operator gate, not an effect of editing this repository.
44
+
45
+ The credential script requires OpenSSL with `req -addext` support:
46
+
47
+ ```sh
44
48
  umask 077
45
- BRIDGE="$HOME/.pi/intercom-bridge"
46
- node "$PKG/scripts/intercom-bridge-credentials.mjs" init "$BRIDGE" fitch-os --cwd "$HOME" --port 9443 --days 3650
49
+ node scripts/intercom-bridge-credentials.mjs init /absolute/private/bridge grok-bot --cwd /home/you --port 9443 --days 3650
47
50
  ```
48
51
 
49
- `init` refuses an existing directory. It creates a ten-year CA, a one-year loopback server certificate, a client certificate whose CN is the identity name, and a private 0600 `config.json`. `--port` (default 9443) sets the helper port. `--days` (1–3650, default 7) sets the client certificate lifetime for `init` and `issue`. Authorization uses only the fingerprint. The last JSON line lists file paths and never secrets. `ca.key` and `server.key` stay on the Mac.
50
-
51
- ### 3. Configure
52
-
53
- ```bash
54
- mkdir -m 700 "$BRIDGE/state" "$BRIDGE/sessions" "$BRIDGE/wake" "$BRIDGE/logs"
55
- # Two lines in a 0600 file. Keep it out of Git, logs and shell history.
56
- (umask 077; printf 'GROK_WAKE_WEBHOOK_URL=%s\nGROK_WAKE_WEBHOOK_KEY=%s\n' "$WAKE_URL" "$WAKE_KEY" > "$BRIDGE/wake/fitch-os.env")
57
- ```
52
+ `init` refuses an existing directory. The script prints paths, not private values;
53
+ CA/server private keys remain on the Mac. Client lifetime defaults to seven days;
54
+ explicit unattended credentials may last up to 3650 days. `issue`, `revoke` and
55
+ `renew-server` preserve the existing storage/locking boundaries; see `--help`.
56
+ Only approved operators provision credentials through a secure channel.
58
57
 
59
- Add `stateDir`, `wake` and `launch` to the generated `config.json`. Keep the file 0600.
58
+ Config and secret files must be owned private regular files (0600), all paths
59
+ absolute. Public CA/certificate files need not be secret. `stateDir` must exist,
60
+ be owned 0700 and be symlink-free. Example:
60
61
 
61
62
  ```json
62
63
  {
63
64
  "port": 9443,
64
- "ca": "/Users/you/.pi/intercom-bridge/ca.crt",
65
- "cert": "/Users/you/.pi/intercom-bridge/server.crt",
66
- "key": "/Users/you/.pi/intercom-bridge/server.key",
67
- "stateDir": "/Users/you/.pi/intercom-bridge/state",
65
+ "ca": "/absolute/private/bridge/ca.crt",
66
+ "cert": "/absolute/private/bridge/server.crt",
67
+ "key": "/absolute/private/bridge/server.key",
68
+ "stateDir": "/absolute/private/bridge/state",
68
69
  "clients": [
69
70
  {
70
- "fingerprint256": "FINGERPRINT_FROM_INIT",
71
- "name": "fitch-os",
72
- "cwd": "/Users/you",
73
- "wake": { "envFile": "/Users/you/.pi/intercom-bridge/wake/fitch-os.env" },
74
- "launch": {
75
- "packageRoot": "/absolute/path/to/node_modules/@earendil-works/pi-coding-agent",
76
- "sessionDir": "/Users/you/.pi/intercom-bridge/sessions",
77
- "workspaceRoots": ["/"],
78
- "resumeDirs": ["/Users/you/.pi/agent/sessions"],
79
- "context": "You were started by the remote fitch-os agent through the Intercom bridge. Reply through Intercom.",
80
- "extensions": [
81
- "/absolute/path/to/pi-subagents/dist/pi-intercom/index.js",
82
- "/absolute/path/to/pi-subagents/dist/extension/index.js"
83
- ],
84
- "discoverResources": true,
85
- "trustProject": true,
86
- "maxSessions": 16
87
- }
71
+ "fingerprint256": "SHA256_FROM_ISSUE",
72
+ "name": "grok-bot",
73
+ "cwd": "/home/you",
74
+ "wake": { "envFile": "/absolute/private/bridge/grok-wake.env" }
88
75
  }
89
76
  ]
90
77
  }
91
78
  ```
92
79
 
93
- This example gives the agent full authority over every Mac path. The defaults stay restrictive for other identities.
94
-
95
- | Field | Purpose |
96
- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
97
- | `stateDir` | Owned 0700 directory, required for unattended use. Holds one 0600 SQLite mailbox per certificate fingerprint, a helper-wide wake ledger, presence proofs and groups. Symlinks, wrong owner or mode, and hard links are rejected. Change it only with a helper restart. Without it, the helper falls back to a legacy volatile inbox (256 messages, 4 MiB) with no wake or presence restore, and keeps groups in `$PI_CODING_AGENT_DIR/intercom/bridge-state`. |
98
- | `cwd` | The identity's presence and project association, the legacy `start` directory and the default spawn directory. It doesn't limit access. |
99
- | `wake.envFile` | Absolute path to an owned 0600 file defining `GROK_WAKE_WEBHOOK_URL` (HTTPS, without URL credentials or fragment) and `GROK_WAKE_WEBHOOK_KEY`. Requires `stateDir`. Reread on SIGHUP. |
100
- | `launch` | Enables saved-session browsing, spawn and resume. Omit it for a messaging-only identity. |
101
- | `packageRoot` | The installed Pi package for children. The helper runs that package's `bin.pi` with its own physical Node. Use the intended installed Pi, not a development SDK with the same version. |
102
- | `sessionDir` | Owned 0700 directory for new journals, written 0600. |
103
- | `workspaceRoots` | Up to 32 directories. Spawn and resume directories must be inside one. `["/"]` approves every path; the default empty list rejects spawn and resume. |
104
- | `resumeDirs` | Up to 32 owned directories searched, with `sessionDir`, for saved sessions. Every journal path component must be owned and symlink-free. |
105
- | `provider`, `model` | Optional default model; set both or neither. Omit them to use Pi's normal model selection. |
106
- | `extensions` | 1–32 absolute extension paths, including Intercom. With `discoverResources: true`, use the same physical Intercom path that native settings load, so a session never runs two Intercom copies. |
107
- | `discoverResources` | Default `false`. `true` keeps Pi's normal discovery of extensions, skills, prompts and context files. |
108
- | `trustProject` | Default `false`. Chooses native `--approve` or `--no-approve` for the selected directory. |
109
- | `offline` | Default `false`. `true` disables automatic catalog and network activity; requested inference still runs. |
110
- | `maxSessions`, `startupTimeoutMs` | Owned-session cap per identity, 1–16 (default 4; 32 per helper), and readiness deadline, 1–60000 ms (default 15000). |
111
-
112
- Children inherit the helper's environment, minus enclosing `PI_SUBAGENT_*` metadata, so set `PATH` in the service. A launch succeeds only when the exact saved session ID, name and file run idle in RPC mode and the session's own Intercom peer is published. That proves startup, not working provider credentials. A Pi dialog that needs a human is cancelled, and the session is stopped with `interaction_required`.
113
-
114
- ### 4. Run as a LaunchAgent
115
-
116
- Save as `~/Library/LaunchAgents/com.example.pi-intercom-bridge.fitch-os.plist`. Use your real Node path, and the output of `getconf DARWIN_USER_TEMP_DIR` for `TMPDIR`.
117
-
118
- ```xml
119
- <?xml version="1.0" encoding="UTF-8"?>
120
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
121
- <plist version="1.0">
122
- <dict>
123
- <key>Label</key><string>com.example.pi-intercom-bridge.fitch-os</string>
124
- <key>ProgramArguments</key>
125
- <array>
126
- <string>/absolute/path/to/node</string>
127
- <string>/Users/you/.pi/intercom-bridge-releases/current/node_modules/@fitchmultz/pi-subagents/dist/pi-intercom/bridge.js</string>
128
- <string>--config</string>
129
- <string>/Users/you/.pi/intercom-bridge/config.json</string>
130
- </array>
131
- <key>EnvironmentVariables</key>
132
- <dict>
133
- <key>PI_CODING_AGENT_DIR</key><string>/Users/you/.pi/agent</string>
134
- <key>TMPDIR</key><string>/var/folders/XX/YYYY/T/</string>
135
- <key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
136
- </dict>
137
- <key>RunAtLoad</key><true/>
138
- <key>KeepAlive</key><true/>
139
- <key>ExitTimeOut</key><integer>30</integer>
140
- <key>Umask</key><integer>63</integer>
141
- <key>StandardOutPath</key><string>/Users/you/.pi/intercom-bridge/logs/audit.jsonl</string>
142
- <key>StandardErrorPath</key><string>/Users/you/.pi/intercom-bridge/logs/stderr.log</string>
143
- </dict>
144
- </plist>
145
- ```
146
-
147
- ```bash
148
- LABEL=com.example.pi-intercom-bridge.fitch-os
149
- PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
150
- plutil -lint "$PLIST" && launchctl bootstrap "gui/$(id -u)" "$PLIST"
151
- lsof -nP -iTCP:9443 -sTCP:LISTEN # expect only 127.0.0.1:9443
152
- ```
153
-
154
- Wait for the `listening` audit record before making requests. Day-to-day control:
155
-
156
- ```bash
157
- launchctl kill SIGHUP "gui/$(id -u)/$LABEL" # reload allowlist, launch and wake policy
158
- launchctl kill SIGTERM "gui/$(id -u)/$LABEL" # graceful restart; KeepAlive starts the current release
159
- launchctl bootout "gui/$(id -u)" "$PLIST" # stop and stay stopped
160
- ```
161
-
162
- SIGHUP can't change the port, TLS files or `stateDir`; restart for those. With `KeepAlive`, killing the process only restarts it, so use `bootout` to stop access. SIGTERM stops owned sessions before exit, which is why `ExitTimeOut` allows 30 seconds.
163
-
164
- ### 5. Publish on the tailnet
165
-
166
- ```bash
167
- tailscale serve --bg --tcp=9443 tcp://localhost:9443
168
- tailscale serve status
169
- ```
170
-
171
- Restrict that port in your tailnet policy to the remote host. To withdraw it, run the same `serve` command with `off` appended.
172
-
173
- ### 6. Provision the remote host
174
-
175
- Copy only the client certificate and key printed by `init`, `ca.crt`, and `scripts/intercom-remote.mjs`, over an existing secure channel, into a 0700 directory with 0600 files. Then run a supervised loopback forwarder from `127.0.0.1:9443` to the Mac's tailnet name on port 9443. With kernel-mode Tailscale:
176
-
177
- ```bash
178
- socat TCP-LISTEN:9443,bind=127.0.0.1,reuseaddr,fork TCP:mac-name.example-tailnet.ts.net:9443
179
- ```
180
-
181
- Without root, run `tailscaled --tun=userspace-networking --socks5-server=127.0.0.1:1055` and relay the same loopback listener through that SOCKS5 proxy.
182
-
183
- ```bash
184
- export INTERCOM_BRIDGE_URL='https://127.0.0.1:9443'
185
- export INTERCOM_BRIDGE_CA="$HOME/.config/pi-intercom/ca.crt"
186
- export INTERCOM_BRIDGE_CERT="$HOME/.config/pi-intercom/client.crt"
187
- export INTERCOM_BRIDGE_KEY="$HOME/.config/pi-intercom/client.key"
188
- REMOTE="$HOME/.config/pi-intercom/intercom-remote.mjs"
189
- node "$REMOTE" register && node "$REMOTE" list
190
- ```
191
-
192
- The first authenticated connection establishes persistent presence (see [Mailbox, presence and wake](#mailbox-presence-and-wake)).
193
-
194
- ### More instances
195
-
196
- Prefer one helper per Mac with all remote agents in its `clients` allowlist. Each identity gets its own client name, key and optional wake webhook; all identities and webhook URLs share one 20-attempt/hour ledger. If separate listeners are necessary, share the same owned `stateDir` to retain one SQLite allowance, use disjoint client lists and separate ports/LaunchAgent labels, and retain the common CA. Separate state directories create independent budgets; do not use them to multiply the Mac's allocation.
197
-
198
- Helpers on the same Mac must share one CA; `init` always creates a new one. Pi sessions on the Mac check every native control (see [Stop and cancel](#stop-and-cancel)) against a single policy file: `PI_INTERCOM_BRIDGE_CONFIG`, else `$PI_CODING_AGENT_DIR/intercom/bridge.json`, else `~/.pi/intercom-bridge/config.json`. That file must name the common CA and list the current pin of every instance, so update it whenever you issue, rotate or revoke any instance's certificate. A different Mac has its own CA and policy file.
199
-
200
- ### SSH alternative
201
-
202
- A Mac-initiated SSH reverse forward can replace steps 5 and 6. Use an approved Linux account, keep host-key checking and don't forward your agent:
203
-
204
- ```bash
205
- ssh -NT -a -o BatchMode=yes -o StrictHostKeyChecking=yes -o ExitOnForwardFailure=yes \
206
- -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
207
- -R 127.0.0.1:9443:127.0.0.1:9443 user@linux-host
208
- ```
209
-
210
- On Linux, `ss -ltn '( sport = :9443 )'` must show only `127.0.0.1:9443`. `GatewayPorts=yes` forces a wildcard bind; require `no` or `clientspecified`. A dedicated tunnel key can be limited with `restrict,port-forwarding,permitlisten="127.0.0.1:9443",command="/bin/false"`. Never reuse the bridge client key as an SSH key.
211
-
212
- ## Remote API
213
-
214
- Every route requires mTLS and the allowlist. Bodies are JSON up to 64 KiB. Unknown routes, fields, query keys and browser-origin requests are rejected. Success is `{ "ok": true, ... }`; failure is `{ "ok": false, "error": { "code", "message", ... } }` with a non-2xx status. A failed certificate check can end the TLS handshake before any HTTP response. Nothing retries a mutation automatically. A lost response means the outcome is unknown, so inspect the inbox, sessions or peer before retrying.
215
-
216
- `intercom-remote.mjs` wraps the routes with the verbs `register`, `list`, `send`, `ask`, `inbox`, `reply`, `ack`, `start`, `spawn`, `resume`, `sessions`, `stop`, `cancel`, `capabilities`, `transcript`, `groups`, `group-upsert`, `broadcast` and `group-send` (broadcast that requires `--group`). Run it with `--help` for options. It prints JSON and exits 0 on success, 1 on an API, TLS or transport failure and 2 on invalid arguments. The examples below call routes directly:
217
-
218
- ```bash
219
- api() { # api METHOD PATH [JSON]
220
- curl --fail-with-body -sS --max-time 135 \
221
- --cacert "$INTERCOM_BRIDGE_CA" --cert "$INTERCOM_BRIDGE_CERT" --key "$INTERCOM_BRIDGE_KEY" \
222
- -X "$1" -H 'Content-Type: application/json' ${3+--data "$3"} "$INTERCOM_BRIDGE_URL$2"
223
- }
224
- ```
225
-
226
- | Route | Request | Result |
227
- | ----------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------- |
228
- | `POST /v1/register` | `{}` | `sessionId`, `name`; other routes register automatically |
229
- | `GET /v1/list` | — | live peers with unambiguous `target`s |
230
- | `POST /v1/send` | `{to,message,passive?,messageId?}` | `id`, `accepted`, `delivered` |
231
- | `POST /v1/ask` | `{to,message,timeoutMs?}` | send receipt and `reply:{from,message}` |
232
- | `POST /v1/reply` | `{replyTo,message}` | send receipt to the ask's saved sender |
233
- | `GET /v1/inbox` | `?after=CURSOR&limit=1..256&waitMs=0..10000` | `messages`, `nextCursor`, `hasMore`, `overflow`, `lostMessages`, `storageError` |
234
- | `POST /v1/ack` | `{ids:[...]}`, at most 256 | `acked`, `retained` |
235
- | `POST /v1/broadcast` | `{message,group?}` | `status`, per-target `receipts`, member `errors` |
236
- | `GET /v1/groups` | — | this identity's `groups` |
237
- | `POST /v1/groups` | `{name,members:[...]}` or `{name,match}` | upserted `groups` |
238
- | `GET /v1/sessions` | `?live=true&saved=true&q=&offset=&limit=` | `sessions`, `nextOffset?`, `liveTruncated?` |
239
- | `POST /v1/spawn` | `{name,cwd?,task?,model?}` | `session`, `id`, `reused`, `task?` |
240
- | `POST /v1/resume` | `{target,task?}` | `session`, `id`, `reused`, `task?` |
241
- | `POST /v1/stop` | one of `sessionId`, `target`, `to`; `mode?`, `timeoutMs?` | see [Stop and cancel](#stop-and-cancel) |
242
- | `POST /v1/cancel` | one of `sessionId`, `target`, `to`; `timeoutMs?` | same as `stop` with `mode:"cancel"` |
243
- | `GET /v1/transcript` | `?target=&limit=&maxBytes=&cursor=&timeoutMs=` | live or saved transcript page; see [Transcripts](#transcripts) |
244
- | `POST /v1/transcript` | `{to,limit?,maxBytes?,cursor?,timeoutMs?}` | same as `GET /v1/transcript` |
245
- | `POST /v1/capabilities` | `{to,timeoutMs?}` | native capabilities receipt |
246
- | `POST /v1/control` | `{to,verb,options?,timeoutMs?}` | native control receipt; `verb:"transcript"` behaves like `/v1/transcript` |
247
- | `POST /v1/start` | `{name}` | legacy idle launch in the identity `cwd` |
248
-
249
- Ask waits up to two minutes (`timeoutMs` 100–120000) for the exact recipient and `replyTo`; each identity has one outgoing ask at a time. A timeout doesn't retract a delivered ask, and a late answer arrives in the inbox. Spawn, resume and transcript lookup have a 75-second helper deadline (90 seconds in the CLI); ask has its timeout plus 15 seconds; other routes have 15 seconds. Live transcript controls keep their separate native response deadline; saved name lookup may scan the full catalog.
250
-
251
- Send defaults to active delivery (`steer`). Only `send` accepts the optional boolean `passive`; `true` maps to native `delivery:"passive"`, and `false` keeps the default. Use `node intercom-remote.mjs send --passive --to PEER --message TEXT` for mail without a model wake. Older helpers reject the unknown `passive` field before sending; the client never retries without it or redirects a failed mutation. Upgrade the receiving helper and consumer before relying on end-to-end no-wake delivery.
252
-
253
- Only `send` accepts an optional `messageId` (`--id ID` in the CLI): a nonblank string of at most 512 characters with no C0/C1 control characters or DEL. The ID is passed unchanged to the native recipient and returned as the receipt's `id`; omitting it still generates a random UUID. A stable ID does not guarantee deduplication, exactly-once delivery or a single provider run, and does not make retrying an unknown outcome safe. Older helpers reject the unknown field without sending; the client never retries without it.
254
-
255
- ### Mailbox, presence and wake
256
-
257
- **Intake.** Every message addressed to the identity is committed to its SQLite mailbox (full synchronous writes) before the helper surfaces it or completes a waiting ask. Unread mail and unanswered asks survive helper crashes, restarts and broker outages. There is no retention limit, so monitor disk space. If a write fails, the mailbox records `overflow`, `lostMessages` and `storageError`. If the loss itself can't be recorded, requests return 507 `mailbox_storage_failed` and the audit log shows `lossRecorded:false`.
258
-
259
- **Reading.** `GET /v1/inbox` returns a non-destructive page of at most 256 messages and 4 MiB. Keep reading with `after=nextCursor` while `hasMore` is true; start again from `0` to revisit unacked mail. The cursor is an opaque sequence number. Inbox and ack work while the broker is down.
260
-
261
- `waitMs` is an optional integer from 0 to 10000 (default 0, an immediate read). If the requested cursor page is empty, a positive wait returns as soon as matching mail is committed, a new admission loss is recorded, or the wait expires. Existing backlog returns immediately. Timeout returns a fresh empty page with the same cursor and current loss status; reads and waits never ack or consume mail. Use `node intercom-remote.mjs inbox --after CURSOR --wait-ms 10000`. Cancelling an inbox request cancels only that read, not other requests or the identity's broker connection. Revocation, certificate expiry, broker disconnect and helper shutdown still cancel the Session's outstanding requests. All requests, including waiting reads, share the eight-request cap per identity.
262
-
263
- **Acknowledging.** Ack an ordinary message to delete its payload; its ID stays as a tombstone so replays are ignored. Ack an ask to record that you've stored it: it appears in `retained`, stays in the inbox as a reply obligation and never triggers a fallback wake. A successful `reply` retires the ask. Reply goes to the ask's saved sender ID; if that sender is offline, it returns `peer_offline` and keeps the obligation. Ack is idempotent. In persistent mode, an answer returned by `ask` is also kept in the inbox; ack `reply.message.id` once you've consumed it.
264
-
265
- **Presence.** After the first authenticated connection, the helper writes a private presence proof (identity, `cwd` and certificate expiry) to `stateDir` and keeps the identity registered with the broker, refreshing every 15 seconds. It stays registered without remote polling until the certificate expires, the identity changes or is revoked, or the helper stops. A restarted helper restores presence from that proof without any remote request. A revoked identity is never restored.
266
-
267
- **Primary wake.** The remote consumer owns waking its agent. Reissue bounded inbox waits without a polling sleep; append each message to durable storage and fsync it; only then ack it. Advance an in-memory tail cursor only after durable intake, draining all `hasMore` pages immediately. Keep that cursor across waits so already-stored retained asks don't cause a busy loop; restart from `0` after a crash and deduplicate by `message.id`. Keep failed ack obligations for retry even after advancing the tail. Each identity needs its own outstanding wait so an empty inbox cannot delay another identity. A wait timeout or reconnect is not a reason to wake an agent. Intake ACK proves storage, not model completion. This notification path requires a running consumer; cold-consumer fallback remains separate.
268
-
269
- **Passive mail.** Native `delivery:"passive"` and legacy `passive:true` messages stay readable and ACKable in the mailbox, but never trigger the helper's fallback webhook, including after restart. Suppressing a notification does not acknowledge or consume the message. Consumers must also honor these flags: durably store and expose passive mail without invoking their own wake webhook. Passive backlogs do not prevent active mail on later pages from triggering fallback. Non-ask text beginning with the exact uppercase prefix `ACK`, `DUP-ACK`, `FYI`, `NOTE`, `RECEIPT` or `NOWAKE`, followed by whitespace, `:` or end of text, also retires notification intent only. Explicit `expectsReply:true` requests still wake regardless of these prefixes. Native passive intent always wins; there is no text-length cutoff.
270
-
271
- **Fallback wake.** The first observation after a successful mailbox commit durably schedules a two-second transport/fsync ACK grace. Time blocked on the mailbox's SQLite FULL write does not consume that grace. If actionable mail remains unacked, the helper POSTs one wake for the oldest such message to `GROK_WAKE_WEBHOOK_URL` with `Authorization: Bearer <GROK_WAKE_WEBHOOK_KEY>` and this body:
272
-
273
- ```json
274
- {
275
- "from": "sender name",
276
- "from_id": "pi-…",
277
- "to": "fitch-os",
278
- "message_id": "…",
279
- "ask_id": null,
280
- "text": "…"
281
- }
282
- ```
283
-
284
- `ask_id` is the message ID for asks. All retained, authorized certificate fingerprints targeting the same wake URL form one cold batch. Later messages join that batch without another POST before its retry deadline. A 2xx response is logged as `accepted`, but cannot prove durable intake: notification and payload remain pending until real inbox ACK (acking an ask counts). Deduplicate wakes by `message_id`.
285
-
286
- **Durable admission.** `wake-quota.sqlite` reserves every POST attempt before dispatch, including rejection, timeout and unknown outcomes, under SQLite `synchronous=FULL`. Each slot remains occupied until a full hour after the POST settles (response, error or abort), so COMMIT, connection and TLS latency cannot shorten the wire-attempt window. All identities, bots, keys and URLs share at most **20 attempts in a sliding hour** per ledger. Restart, SIGHUP and certificate/URL rotation do not reset it. Uncertainty and backoff are committed with each reservation: retry after 30 seconds, doubling through 60, 120 and 240 seconds to a five-minute ceiling while the batch remains unacknowledged. Real ACK retirement clears only that batch's retry state; fresh work receives the two-second grace immediately when quota remains. Redirects are refused and each request times out after ten seconds. Storage errors fail closed before POST; repair permissions/disk/corruption without deleting or replacing the ledger to reset usage.
287
-
288
- An open attempt has no expiry while its listener is alive. Private `wake-owner-*.lock` SQLite files hold OS locks for each listener's lifetime, including across process pauses; they are not PID or timed leases. Owner-file creation and lock acquisition are serialized with ledger recovery, so another listener cannot reap an initializing owner. After a listener exits, another listener conservatively counts its unfinished attempts for a full hour from recovery. Failed settlement writes remain counted and are retried before that listener dispatches again. Do not remove these files or any ledger to regain quota. Stop **all** old listeners before upgrading a version-1 ledger: its pre-dispatch timestamps cannot prove POST completion, so migration retains every recorded slot for a full hour from upgrade (or its recorded future time, if later), preserving retry state. Subsequent opens do not restart that migration hold.
289
-
290
- Mailbox commits/ACKs, startup reconstruction and exact retry/budget deadlines drive fallback. There is no periodic intake scan. Presence maintenance's separate broker lease timer is not inbox polling. Pending mail recovers automatically after budget expiry, failures and helper restart. Revocation or certificate expiry stops that identity's fallback without deleting unread payload.
291
-
292
- **First upgrade and audit preflight.** Fresh empty installations start with an unused allowance. An installation with mailbox/presence state but no ledger has unknown legacy usage and conservatively reserves all 20 slots for one hour. This is a migration quota exception, not a first-wake latency policy. Native JSONL outcomes have timestamps, but omit crash-before-log attempts and may have `log_overflow` gaps. Do not treat them as a complete pre-dispatch ledger.
293
-
294
- Where immutable prior source/runtime and owned audit history prove complete coverage, stop every legacy writer (disable automatic restart) before preparing migration. Bound unconfirmed attempts independently from each prior worker's maximum in-flight dispatches; sum these across all identities. Do not assume zero merely because shutdown was requested. This preflight checks the supplied PID has exited, rejects audit overflow and existing ledger/history, and writes a private fsynced `wake-history.json`:
295
-
296
- ```bash
297
- node "$PKG/scripts/intercom-bridge-wake-preflight.mjs" \
298
- --state-dir "$BRIDGE/state" --audit "$BRIDGE/logs/audit.jsonl" \
299
- --complete-since 'ISO_TIME_AT_LEAST_ONE_HOUR_BEFORE_STOP' \
300
- --stopped-at 'ISO_TIME_AFTER_ALL_LEGACY_WRITERS_STOPPED' \
301
- --stopped-pid OLD_HELPER_PID --unknown-attempts PROVEN_BOUND_0_TO_20
302
- ```
303
-
304
- `--complete-since` attests verified coverage; outcomes alone cannot prove it. The operator must verify **all** previous writer processes are stopped, not just the checked PID, and no legacy writer may run after sealing history. If that proof or a bounded unknown count is unavailable, skip preflight and retain the conservative reservation. On first creation the helper seeds recorded attempts still within the sliding hour, plus unknown reservations at startup, preserving known remaining capacity. Existing ledgers never reseed; malformed, unreadable or corrupt state denies admission. Never manually edit/reset the database, switch state directories to gain quota, or roll back to a non-accounting helper without a new conservative reconciliation.
305
-
306
- **Distributed ceiling.** URL grouping is local coalescing, not provider-account identity or exactly-once execution. Two simultaneously cold Macs can each issue a wake before either sees intake. Literal cross-Mac single admission requires a neutral admission authority governing every writer; none is introduced here. A known controlled allocation of two Box senders at 20 each (including their offline-peer POSTs), plus Work Mac 20 and Personal Mac 20 across all bots, totals 80 attempts/hour. That neither governs unrelated account traffic nor proves the provider's whole-account 100/hour cap. Offline-peer communication remains the Box owners' responsibility when both Macs sleep/offline; sleeping Macs cannot deliver locally until online, and stored queues remain retained.
307
-
308
- ### Sessions
309
-
310
- `GET /v1/sessions?live=true&saved=true` returns rows of `id`, `sessionId`, `peerId`, `name`, `cwd`, `status`, `lastSeen`, `saved` and `owned`. `owned` is true only for this identity's current helper subprocesses. Saved rows require `launch` policy and come from `sessionDir` and `resumeDirs`; rows never include journal paths or transcript bodies. `q` filters ID, name and cwd. `limit` is 1–100 (default 50). `offset` and `nextOffset` are filesystem candidate cursors, with at most 1,000 candidates scanned per request, not row counts. `liveTruncated` means live-only peers didn't fit; page them with `live=true` alone. A bare `GET /v1/sessions` keeps the legacy list of this identity's owned processes, including PID and journal path.
311
-
312
- ```bash
313
- api GET '/v1/sessions?live=true&saved=true&limit=50'
314
- api POST /v1/spawn '{"name":"reviewer","cwd":"/Users/you/src/app","task":"Review the current branch and reply with findings.","model":"provider/model-id"}'
315
- api POST /v1/resume '{"target":"NATIVE_SESSION_ID","task":"Continue where you left off."}'
316
- ```
317
-
318
- **Spawn** creates a session named `remote:IDENTITY:NAME` in `cwd` (default: the identity `cwd`). `model` is `provider/id`, split at the first slash; you can also send `provider` and `model` separately. The helper writes a new 0600 journal containing the launch context without running inference, starts Pi idle in RPC mode, and waits for readiness. It then sends `task` as an ordinary Intercom message from the identity, so the session's replies land in the mailbox. `task:{id,accepted,delivered,completed:false}` is broker acceptance. A live session with the same name is reused (`reused:true`), or rejected with `cwd_conflict` or `model_conflict` when those differ. If the task send fails, the error includes the live `session`; deliver the task with `/v1/send` instead of spawning again. After a lost response, check sessions or repeat the same name.
319
-
320
- **Resume** takes `target` (or exactly one of `sessionId` or `name`) plus an optional `task`. A target matches an exact native session ID or peer ID first, then a unique saved name. Name lookups scan the whole catalog to prove uniqueness and fail rather than accept a partial match. Resume reuses a live owned process, then a live Intercom peer proven to own that journal, without reopening the journal. Otherwise it opens the original journal in place, with the same session ID, cwd, name and history, and restores the recorded model. If Pi falls back to a different model, resume fails with `model_restore_failed` and submits no task. It refuses with `active_session` when a live peer matches the name and cwd but can't be proven to own the journal. A process that resume starts is helper-owned.
321
-
322
- Duplicate-writer protection covers helper-owned startups and discoverable Intercom peers. Pi's `SessionManager` has no cross-process journal lock, so a Pi process without Intercom, or one that hasn't published its peer yet, is invisible to the bridge. The helper never adopts processes after a restart. A surviving child that is still a live Intercom peer is reused by resume rather than reopened.
323
-
324
- ### Stop and cancel
325
-
326
- Both routes take exactly one of `sessionId`, `target` or `to`. `stop` also takes `mode`: `kill` (default) or `cancel`. `POST /v1/cancel` is `stop` with `mode:"cancel"`. The helper first looks for this identity's helper-owned process by native session ID, peer ID or name. Only when the identity owns no match (`unknown_session`) does it send a native control to a live Pi, with `timeoutMs` 100–10000 (default 3000). Any other failure, including an unknown outcome, is returned as is and never redirected. Ownership decides what the bridge can guarantee:
327
-
328
- | Target | `mode: "cancel"` | `mode: "kill"` (default) |
329
- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
330
- | This identity's helper-owned process | Native RPC abort. Returns after observed idle with `queuesPreserved:true` and the pending count, or `cancel_unconfirmed`. Future Intercom tasks still run. | Closes stdin and signals the private process group (TERM after 1 s, KILL after 3 s). Returns `status:"exited"` only after observing exit within 8 seconds; otherwise `stop_timeout`, so retry. The journal is kept. |
331
- | Any other live Pi with the updated extension | Native control `cancel_requested`: the current operation is aborted and accepted queued input is kept (`queueCleared:false`). | Native shutdown request: `shutdown_requested`, or `unsupported` while still requesting shutdown and abort. Always `processExited:false`. |
332
-
333
- For other sessions, TUI shuts down in order, idle RPC waits for its next command, and print or JSON modes report `unsupported`. A disconnect doesn't prove exit, and detached background jobs keep their own lifecycle. The bridge never signals another process by PID and never stops the broker.
334
-
335
- **Native controls** travel as passive, typed Intercom messages. Before acting, the recipient checks that the sender is `remote-<fingerprint>` and that the TLS certificate chain supplied by the bridge is current, issued by the configured CA and pinned in its policy file, then replies with a correlated result. A Pi process still running older extension code receives only a short passive note; the request then fails with `control_unconfirmed` and `deliveryUnknown:true`. Don't retry automatically. Use `POST /v1/control` with `verb` `capabilities`, `cancel`, `stop` or `transcript` for the direct form; it skips the owned-process lookup. `timeoutMs` is 100–10000 (default 3000), with at most eight controls in flight per identity.
336
-
337
- ### Transcripts
338
-
339
- `GET /v1/transcript?target=TARGET&limit=20`, `POST /v1/transcript {to,...}` and `POST /v1/control` with `verb:"transcript"` read the same way. The helper first resolves the target against live Intercom peers:
340
-
341
- - **Live.** A live Pi with the updated extension answers through native control. The result is the control receipt plus `source:"live"` and `transcript`, the page (also still at `native.transcript`). A live Pi running older extension code fails with `control_unconfirmed`; the helper doesn't fall back to its journal.
342
- - **Saved.** Only when no live peer matches (`peer_offline`) does the helper read the saved journal. That requires `launch` policy (otherwise 403 `launch_disabled`). The target resolves through the saved catalog by stable ID or unique name, and the result is `{status:"ok", source:"saved", session, transcript}`. The journal is parsed read-only with the identity's `packageRoot` and is never opened for writing or migrated. Saved reads reject journals over 64 MiB or 50,000 entries, ignore an unfinished trailing record, and fail with 409 `session_changed` if the journal's session ID changes during the read.
343
-
344
- A page holds `records` (`id`, `timestamp`, `role`, `text`, `truncated`) in chronological order. Only finalized user, assistant, tool-result and custom text on the active branch is included; thinking, images, tool arguments, and system or provider data are not, and streaming output isn't available. Defaults are 50 records and 64 KiB, with maximums of 100 records and 128 KiB (`maxBytes` minimum 256). A read scans at most 1,024 entries and reports `scanLimitReached`. `cursor` continues to older output while the selected branch is unchanged.
345
-
346
- ### Groups and broadcast
347
-
348
- ```bash
349
- api POST /v1/groups '{"name":"app","members":["reviewer","pi-0123456789abcdef0123456789abcdef"]}'
350
- api POST /v1/groups '{"name":"workers","match":"remote:fitch-os:*"}'
351
- api POST /v1/broadcast '{"group":"workers","message":"Report status."}'
352
- ```
353
-
354
- Groups are upserted by name and private to the certificate fingerprint, stored in `stateDir` (or `$PI_CODING_AGENT_DIR/intercom/bridge-state`, created 0700, when `stateDir` is unset). Each identity can have 64 groups of up to 256 explicit members, within 1 MiB. `match` is a name glob or `{id?, nameglob?, cwd?}`; the canonical fields are `members`, `namePattern` and `cwdPattern`. Explicit members are unioned with glob matches, and when both globs are set a peer must match both. Globs use Node's `path.matchesGlob`.
355
-
356
- Broadcast resolves current live Pi sessions, excluding remote identities, and deduplicates them. Without `group` it targets every live Pi session. Each target is sent once, sequentially, with its own receipt or error. Offline or ambiguous members appear in `errors`, and any failure makes `status` `partial`.
357
-
358
- If the broker stalls or disconnects mid-broadcast, the HTTP request fails (`ok:false`) but retains `status:"partial"`, all per-target `receipts` and member `errors`. A receipt with `accepted:true` is confirmed; an in-flight failure carries its message `id` and `deliveryUnknown:true`; targets not sent have `attempted:false` and `deliveryUnknown:false`. Revocation or certificate expiry denies the response instead. Nothing is retried automatically. Resend only definite failures or unattempted targets; inspect unknown outcomes before deciding whether to resend.
359
-
360
- ## Update and roll back
361
-
362
- **Helper.** Install a new release (step 1), point `current` at it, then restart gracefully:
363
-
364
- ```bash
365
- ln -sfn "$RELEASES/NEW_RELEASE" "$RELEASES/current"
366
- launchctl kill SIGTERM "gui/$(id -u)/$LABEL"
367
- ```
368
-
369
- To roll back, point `current` at the previous release and restart the same way. A restart stops the helper's owned sessions; their journals remain, so resume them afterward. Mailboxes, presence proofs and groups persist. Delete an old release only when no helper or broker process still runs from it, because a broker started by the helper runs from that release.
370
-
371
- **Pi extension.** Update Pi's own installation by following the [installation guide](reference.md#installation), and never overwrite extension files that a running Pi has loaded. New Pi processes use the newly selected extension. Each existing process keeps the code it loaded and gains native controls only after it adopts the update at a safe boundary: finish or checkpoint its work, quit, and resume the same saved session with `pi --session PATH`. Until then it stays messageable and listed, but controls to it fail with `control_unconfirmed`. The bridge can't force old processes to reload and doesn't kill them.
372
-
373
- ## Credentials
374
-
375
- **Rotate a client.** `issue` always creates a new fingerprint, keeps the identity's `launch` and `wake` policy, and replaces the old pin. Don't run it for a long-lived certificate you mean to keep.
376
-
377
- ```bash
378
- node "$PKG/scripts/intercom-bridge-credentials.mjs" issue "$BRIDGE" fitch-os --days 3650
379
- launchctl kill SIGHUP "gui/$(id -u)/$LABEL"
380
- ```
381
-
382
- Copy the new certificate and key to the remote host. After the reload, the old certificate is denied and its owned sessions stop. Mailboxes, presence proofs and groups are keyed by fingerprint, so the new certificate starts empty; the old files stay on the Mac for local recovery.
383
-
384
- **Renew the server certificate.** The server certificate from `init` lasts one year. Before it expires, reissue it from the same CA and restart the helper, because SIGHUP can't change TLS files:
385
-
386
- ```bash
387
- node "$PKG/scripts/intercom-bridge-credentials.mjs" renew-server "$BRIDGE" --days 3650
388
- launchctl kill SIGTERM "gui/$(id -u)/$LABEL"
389
- ```
390
-
391
- `renew-server` takes no identity name or `--cwd`. `--days` is 1–3650 (default 365). It writes a new `server-<hex>` key and certificate and points `cert` and `key` in `config.json` at them. The CA, client certificates and pins don't change, so remote hosts need nothing new. Check any certificate with `openssl x509 -noout -enddate -in FILE`; the CA itself expires ten years after `init`.
392
-
393
- **Revoke.**
394
-
395
- ```bash
396
- node "$PKG/scripts/intercom-bridge-credentials.mjs" revoke "$BRIDGE" fitch-os
397
- launchctl kill SIGHUP "gui/$(id -u)/$LABEL"
398
- ```
399
-
400
- Confirm the `allowlist_reloaded` record, that the identity has left the peer list, and that its certificate can't call `/v1/list`. Revocation also stops its owned sessions and fallback wakes. For an immediate cut-off, `bootout` the helper or withdraw the Tailscale Serve port. If the CA key is compromised, start over with a new `init`.
401
-
402
- Credential commands hold `DIR/.credentials.lock` for the whole update and fail rather than overwrite each other. After a crash, confirm the PID in `DIR/.credentials.lock/owner` has exited before removing the lock.
403
-
404
- ## Recovery
405
-
406
- | Symptom | What to do |
407
- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
408
- | TLS handshake fails from the remote host | Check client, server and CA expiry; the remote forwarder; `tailscale serve status`; and the helper's `listening` record. |
409
- | Local peers get `peer_offline` for the remote identity | The helper is stopped or the certificate expired or was revoked. A restarted helper re-registers from a valid presence proof; otherwise one authenticated request does. |
410
- | `broker_unavailable`, or a refusal to start a second broker | Let the unhealthy broker exit, or start a normal Pi session, then retry. Don't delete broker files or kill a working broker. |
411
- | 507 `mailbox_storage_failed` | Fix disk space or `stateDir` permissions, then restart the helper. `lossRecorded:false` audit records mark uncounted losses. |
412
- | No fallback wakes | Check `wake_delivery` records (`http_rejected` with status, `transport_unconfirmed`, `storage_unavailable`) and the env file's mode and URL. Acked messages never wake. |
413
- | Repeated wakes for one `message_id` | Accepted-but-unacked batches retry on durable 30-second-to-five-minute backoff, within the shared quota. Fix the consumer's store-then-ack loop. |
414
- | Lost response, `task_unconfirmed` or `control_unconfirmed` | The outcome is unknown. Inspect the inbox, sessions or peer before retrying. |
415
- | `launch_in_progress` or `stop_timeout` | Inspect `GET /v1/sessions`; retry stop until it reports `exited`. |
416
- | `allowlist_reloaded` with `failed_closed` | The config is invalid; every identity is denied and owned sessions stopped. Fix the config and send SIGHUP again. |
417
-
418
- ## Verification
419
-
420
- The process-boundary tests use a private real broker, real certificates, real HTTPS and the remote CLI. Launch tests use the installed Pi dependency graph with a native faux provider, so no paid inference or external credentials are needed. Coverage includes cold SIGKILL restarts with mailbox and presence recovery, event-driven fallback, shared durable quota and ack suppression, bounded cursor drains, storage failures, spawn and resume identity and model preservation, owned cancel and observed exit, native control authorization and old-owner timeouts, live transcripts and the saved-journal reader, same-CA server renewal with an unchanged client key, and restart-persistent groups.
421
-
422
- ```bash
423
- node --test test/integration/intercom-bridge.test.ts test/integration/intercom-bridge-delivery.test.ts \
424
- test/integration/intercom-bridge-wake-budget.test.ts test/integration/intercom-bridge-wake-state.test.ts \
425
- test/integration/intercom-bridge-launch.test.ts test/integration/intercom-bridge-lifecycle.test.ts \
426
- test/integration/intercom-native-control.test.ts test/unit/intercom-transcript.test.ts
427
- env -u PI_TIMING -u PI_EXTENSION_PERFORMANCE npm run ci
428
- ```
429
-
430
- For a live smoke test from the remote host, run `list`, ask one deliberately chosen session to reply `bridge-smoke-ok`, and fetch `GET /v1/sessions?live=true&saved=true`. With quota available, pause remote intake and send a deliberate actionable message to confirm fallback just after the two-second ACK grace; restore intake and verify actual ACK retires retry intent. Keep only a redacted record: platform, route, accepted or delivered flags and the reply text. Never publish config, keys, wake URLs or raw inbox and list output.
80
+ The optional owned 0600 `wake.envFile` contains `GROK_WAKE_WEBHOOK_URL` (HTTPS,
81
+ no URL credentials/fragment) and `GROK_WAKE_WEBHOOK_KEY`. Wake requires durable
82
+ `stateDir`. Omit wake for a polling-only client. Omit `stateDir` only for legacy
83
+ volatile messaging: 256 messages / 4 MiB, no cold presence or wake recovery.
84
+ The retired client `launch` key is accepted but ignored, with one metadata warning
85
+ per configuration load. Its paths and policies are not read or executed and it
86
+ grants no capability; remove it when convenient. Other unknown fields still fail
87
+ closed, with a bounded, control-free field name in the diagnostic. No credentials
88
+ or configuration files are automatically rewritten.
89
+
90
+ Run with the same per-user broker environment as local Pi:
91
+
92
+ ```sh
93
+ PI_CODING_AGENT_DIR=/home/you/.pi/agent node dist/pi-intercom/bridge.js --config /absolute/private/bridge/config.json
94
+ ```
95
+
96
+ On macOS preserve the user's native `TMPDIR` for old-namespace detection (see
97
+ `getconf DARWIN_USER_TEMP_DIR`); it does not select the new shared broker.
98
+ Observe `listening` before requests. A per-user LaunchAgent can supervise this
99
+ command with private logs, RunAtLoad and KeepAlive. SIGTERM/SIGINT drain helper
100
+ requests and disconnect its own peers; they never stop the shared broker.
101
+ SIGHUP reloads client/wake policy. Listener/TLS/stateDir changes require restart.
102
+ KeepAlive restarts a terminated helper; boot out the service to stay stopped.
103
+
104
+ Durable presence safely acquires the existing broker after reboot/crash. It
105
+ never restarts/replaces a live or uncertain unhealthy owner. Legacy volatile
106
+ messaging does not start a broker. The existing native PID/spawn lock owner
107
+ retains that safety boundary.
108
+
109
+ ## Protocol and maintained client
110
+
111
+ Every operation requires mTLS and the current pin. Responses include
112
+ `{ok,requestId,...}`; non-2xx faults include `error:{code,message,...}`. TLS may
113
+ close before HTTP when authentication fails. There are no automatic mutation
114
+ retries. A lost response is **UNKNOWN**, not proof that a message was unsent.
115
+
116
+ | Route | Input | Result |
117
+ | ------------------- | --------------------------------------------------------- | ---------------------------------------------------------- |
118
+ | `POST /v1/register` | `{}` | credential-derived `sessionId`, `name` |
119
+ | `GET /v1/list` | none | `sessionId`, peers with exact IDs/unambiguous targets |
120
+ | `POST /v1/send` | `{to,message,messageId?,passive?,replyTo?,expectsReply?}` | real broker send receipt |
121
+ | `GET /v1/inbox` | `after`, `limit=1..256`, `waitMs=0..10000` | complete envelopes, `nextCursor`, `hasMore`, loss metadata |
122
+ | `POST /v1/ack` | `{ids}` (at most 256) | `acked`; durable intake ownership transferred |
123
+
124
+ `to` uses the existing exact-ID/name resolver; ambiguity never selects a peer.
125
+ Explicit message IDs survive byte-for-byte. Use a fresh `--id` / `messageId` for
126
+ each new logical message; reuse it only to retry that same message. Updated native
127
+ recipients ignore an already-admitted ID even if a retry changes its payload,
128
+ while the broker can still report transport acceptance. Do not reuse a previous
129
+ ID to send a different instruction.
130
+
131
+ `passive:true` is mailbox-only and never wakes. Acceptance means transport/broker
132
+ admission, not native journal persistence, model start, reply completion or task
133
+ completion. A bare `ok:true` is not an acceptance receipt.
134
+
135
+ The maintained client is `scripts/intercom-remote.mjs`. Copy it unchanged with
136
+ only the CA, client certificate and private key to a private remote directory.
137
+ Set `INTERCOM_BRIDGE_URL` to the local forwarder HTTPS origin and
138
+ `INTERCOM_BRIDGE_CA/CERT/KEY` to the appropriate files. It accepts only
139
+ `register`, `list`, `send`, `inbox` and `ack`; run `--help` for arguments.
140
+
141
+ ```sh
142
+ node intercom-remote.mjs list
143
+ node intercom-remote.mjs send --to EXACT_ID --id REQUEST_ID --expects-reply --message 'Status?'
144
+ node intercom-remote.mjs send --to ORIGINAL_SENDER_ID --reply-to REQUEST_ID --message 'Answer'
145
+ ```
146
+
147
+ Replies are ordinary correlated sends. The consumer must fsync the **complete
148
+ sender/message envelope**, including `replyTo`/`expectsReply`, before ACK. ACK
149
+ now tombstones all payloads, including requests expecting a reply. Pending work
150
+ and reply duties belong to the durable consumer mailbox after transfer; there
151
+ is no server `retained` ask or synchronous HTTP waiter. Failed/offline replies
152
+ must leave that local duty pending. Exact-ID tombstones prevent replay
153
+ resurrection. Cursor pages are bounded by count and 4 MiB; long-waits observe
154
+ post-commit changes and never consume messages. Durable reads/ACKs remain
155
+ available while the broker is unavailable.
156
+
157
+ ## Wake and cold recovery
158
+
159
+ Authenticated presence is durably recorded and restored only for current,
160
+ unexpired pins. Each private SQLite mailbox uses the proven FULL-sync owner.
161
+ Mailbox commits schedule fallback after a short durable postcommit ACK grace
162
+ (target two seconds), independent of consumer polling. Passive mail never wakes.
163
+ ACK retires notification intent; webhook HTTP acceptance alone does not.
164
+
165
+ Wake reservations persist before POST. One shared Mac ledger covers all
166
+ fingerprints/URLs: at most 20 attempts per sliding hour with persisted backoff,
167
+ uncertain-attempt recovery and clock-rollback protection. A live owner never
168
+ ages out an open attempt. Cold recovery conservatively retains a full hour for
169
+ an uncertain stopped owner. Invalid/unreadable state fails closed, never resets
170
+ usage. Separate state directories are independent budgets, not a way to multiply
171
+ an installation's allowance. Preserve quota/history through upgrades.
172
+
173
+ The companion Box worker independently ingests each profile, fsyncs before ACK,
174
+ deduplicates and recovers from cursor zero. Its wake owner separately tracks
175
+ accepted versus consumed/failed mail. This is bounded at-least-once notification,
176
+ not exactly-once model execution. Multiple Macs and slow ACKs can duplicate wakes.
177
+
178
+ ## Paired upgrade gate
179
+
180
+ Qualify this source and `grok-pi-bridge` together. Its bundled client must be
181
+ byte-identical to this maintained client; use real broker/mTLS tests as well as
182
+ mailbox/filesystem checks. Never pin a nonexistent future SHA. Select the actual
183
+ reviewed immutable upstream commit only after publication; an older pin/client
184
+ is not evidence for the new reply/ACK protocol.
185
+
186
+ The cutover is a coordinated boundary, not a rolling mixed-protocol upgrade:
187
+
188
+ 1. Obtain deployment GO; inventory the participating Pi sessions/agent directories,
189
+ helper services and both Box workers, including external wake/health routines.
190
+ Stop admission of new remote work and pause every worker starter. Checkpoint or
191
+ finish old synchronous asks and remotely owned work before changing versions.
192
+ 2. Preserve native journals, SQLite/presence/quota state and Box STORE ledgers, plus
193
+ the prior compiled helper, extension and client/worker pair. On each Box, run
194
+ the companion's offline `mail reconcile` dry run, review the exact obligations,
195
+ explicitly apply safe unambiguous scoped receipts, and verify the pending set.
196
+ Ambiguous IDs remain pending. Follow its RUNBOOK for old open wake reservations;
197
+ they are not completion evidence and must not be reset to obtain fresh budget.
198
+ 3. Load the approved extension in **every participating Pi session on each Mac**
199
+ before restarting helper traffic. Old and new namespaces cannot see or forward
200
+ to each other. The startup warning covers the current agent directory only;
201
+ neither `list` nor the warning inventories every OS process. Verify the expected
202
+ exact peer IDs from the new main sessions and the helper before proceeding.
203
+ 4. Swap the reviewed helper and Box client/worker pair while starters remain
204
+ paused. Update saved bot prompts/routines: remote `spawn`, `resume`, `sessions`,
205
+ `transcript`, groups and broadcast are retired; replace `ask`/`reply` with
206
+ correlated `send`. An existing client `launch` config is ignored, not a startup
207
+ blocker. Verify per-Box pending duties and authenticated discovery/delivery,
208
+ then resume starters. Do not leave an old worker reading new-client receipts.
209
+
210
+ The companion must pin the **final immutable upstream revision selected for
211
+ rollout**, with green paired CI; a merge/squash that changes the selected revision
212
+ requires refreshing that pin and qualification before deployment. A doc-only
213
+ change does not itself change the protocol, but it is still a different reviewed
214
+ source identity. Neither PR is permission to merge or activate the pair.
215
+
216
+ For rollback, pause starters/traffic again and enumerate transferred Box reply
217
+ duties from its durable mailbox. Complete and verify those replies before restoring
218
+ old server-owned reply tooling; receipt reconciliation is not proof that a reply
219
+ was sent. If duties cannot be resolved, retain the new pair rather than pretending
220
+ the old helper can recover already-ACKed payloads. The Box's newer-code guard
221
+ intentionally rejects ordinary downgrade copies. Reinstating prior behavior needs
222
+ a separately reviewed, version-aware paired recovery (for example, a qualified
223
+ forward-versioned recovery release), not falsifying version stamps or using normal
224
+ bootstrap to force old code. Preserve mail/quota/history throughout. Never reset
225
+ history, fabricate consumption or resurrect mail. No source check installs/restarts
226
+ a runtime or proves provider execution.