create-walle 0.10.1 → 0.10.2

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 (341) hide show
  1. package/README.md +4 -0
  2. package/lib/owner-write-safety.js +135 -0
  3. package/lib/public-runtime.js +13 -5
  4. package/lib/release-schema.json +3 -2
  5. package/lib/runtime-closure-policy.json +6 -4
  6. package/package.json +1 -1
  7. package/template/bin/deps-doctor.js +1 -1
  8. package/template/bin/node-bin.sh +11 -0
  9. package/template/coding-task-manager/api-prompts.js +10 -22
  10. package/template/coding-task-manager/bin/claude-hook.js +7 -3
  11. package/template/coding-task-manager/bin/claude-table-parity.js +307 -0
  12. package/template/coding-task-manager/bin/conversation-storage-auto-migration-lib.js +16 -1
  13. package/template/coding-task-manager/bin/conversation-storage-generation-evidence.js +9 -2
  14. package/template/coding-task-manager/bin/conversation-storage-service-entry-lib.js +16 -1
  15. package/template/coding-task-manager/bin/conversation-storage-walle-owner.js +247 -0
  16. package/template/coding-task-manager/bin/ctm-machine-pair.js +160 -0
  17. package/template/coding-task-manager/bin/lead-wait-census.js +1348 -0
  18. package/template/coding-task-manager/bin/repair-foreign-clone.js +564 -0
  19. package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
  20. package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
  21. package/template/coding-task-manager/db.js +705 -286
  22. package/template/coding-task-manager/git-utils.js +44 -0
  23. package/template/coding-task-manager/lib/adopted-host-redial.js +4 -0
  24. package/template/coding-task-manager/lib/agent-presets.js +15 -0
  25. package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
  26. package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
  27. package/template/coding-task-manager/lib/api/host-stats.js +98 -0
  28. package/template/coding-task-manager/lib/api/ingress.js +35 -12
  29. package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
  30. package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
  31. package/template/coding-task-manager/lib/api/machines.js +461 -0
  32. package/template/coding-task-manager/lib/api/misc-ops.js +20 -5
  33. package/template/coding-task-manager/lib/api/providers.js +53 -6
  34. package/template/coding-task-manager/lib/api/resume-from-store.js +25 -0
  35. package/template/coding-task-manager/lib/api/sessions.js +160 -8
  36. package/template/coding-task-manager/lib/api/transcript-history.js +17 -4
  37. package/template/coding-task-manager/lib/api/worktrees.js +38 -37
  38. package/template/coding-task-manager/lib/approval-drift.js +16 -1
  39. package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
  40. package/template/coding-task-manager/lib/approval-scope.js +68 -4
  41. package/template/coding-task-manager/lib/auth-context.js +32 -2
  42. package/template/coding-task-manager/lib/auth-rate-limit.js +41 -1
  43. package/template/coding-task-manager/lib/auth-rules.js +186 -45
  44. package/template/coding-task-manager/lib/broadcast-serialize.js +2 -1
  45. package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
  46. package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
  47. package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
  48. package/template/coding-task-manager/lib/claude-session-title.js +6 -30
  49. package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
  50. package/template/coding-task-manager/lib/client-diag-handler.js +5 -0
  51. package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
  52. package/template/coding-task-manager/lib/codex-harness-qualification.js +12 -0
  53. package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
  54. package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
  55. package/template/coding-task-manager/lib/codex-paths.js +2 -1
  56. package/template/coding-task-manager/lib/coding-agent-models.js +21 -30
  57. package/template/coding-task-manager/lib/coding-session-model-adapters.js +27 -2
  58. package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
  59. package/template/coding-task-manager/lib/coding-session-model-runtime.js +1 -2
  60. package/template/coding-task-manager/lib/coding-session-model-state.js +10 -0
  61. package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
  62. package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -0
  63. package/template/coding-task-manager/lib/create/resolve-launch-params.js +8 -1
  64. package/template/coding-task-manager/lib/ctm-boot-lifecycle.js +17 -1
  65. package/template/coding-task-manager/lib/db-domain-tables.js +7 -0
  66. package/template/coding-task-manager/lib/db-domains.js +21 -2
  67. package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -0
  68. package/template/coding-task-manager/lib/db-schema-source-files.js +1 -0
  69. package/template/coding-task-manager/lib/feature-manifest.js +1 -1
  70. package/template/coding-task-manager/lib/fs-watcher.js +3 -2
  71. package/template/coding-task-manager/lib/harness-history-transition.js +3 -3
  72. package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
  73. package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
  74. package/template/coding-task-manager/lib/headless-term-service.js +55 -17
  75. package/template/coding-task-manager/lib/host-control-dial.js +167 -0
  76. package/template/coding-task-manager/lib/host-handoff-orchestrator.js +16 -2
  77. package/template/coding-task-manager/lib/host-handoff.js +51 -13
  78. package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
  79. package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
  80. package/template/coding-task-manager/lib/host-stats.js +328 -0
  81. package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
  82. package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
  83. package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
  84. package/template/coding-task-manager/lib/hosted-sync-worker.js +113 -5
  85. package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +4 -0
  86. package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
  87. package/template/coding-task-manager/lib/instance-manifest.js +13 -1
  88. package/template/coding-task-manager/lib/instance-sync-status.js +15 -0
  89. package/template/coding-task-manager/lib/launch-model-override.js +160 -1
  90. package/template/coding-task-manager/lib/launch-plan-worker.js +59 -2
  91. package/template/coding-task-manager/lib/lead-model-switch-runtime.js +57 -4
  92. package/template/coding-task-manager/lib/lead-model-switch.js +3 -2
  93. package/template/coding-task-manager/lib/lead-model-transition-store.js +61 -3
  94. package/template/coding-task-manager/lib/legacy-draft-cancellation-recovery.js +111 -0
  95. package/template/coding-task-manager/lib/login-tripwire.js +1 -0
  96. package/template/coding-task-manager/lib/machine-pairing.js +238 -0
  97. package/template/coding-task-manager/lib/machine-pool.js +409 -0
  98. package/template/coding-task-manager/lib/machine-registry.js +749 -0
  99. package/template/coding-task-manager/lib/machine-self.js +66 -0
  100. package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +52 -4
  101. package/template/coding-task-manager/lib/media-journal-control-reader.js +473 -0
  102. package/template/coding-task-manager/lib/media-journal.js +84 -27
  103. package/template/coding-task-manager/lib/media-store-options.js +43 -15
  104. package/template/coding-task-manager/lib/migrations/v56-host-samples-and-machine-pool.js +76 -0
  105. package/template/coding-task-manager/lib/mirror-feed-sanitize.js +12 -3
  106. package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
  107. package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
  108. package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
  109. package/template/coding-task-manager/lib/model-proxy/lead-worker-picks.js +25 -0
  110. package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
  111. package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
  112. package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -0
  113. package/template/coding-task-manager/lib/model-proxy/stream-accounting.js +205 -0
  114. package/template/coding-task-manager/lib/model-proxy/tokens.js +78 -0
  115. package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
  116. package/template/coding-task-manager/lib/native-history-control.js +2 -2
  117. package/template/coding-task-manager/lib/native-lead-settings-client.js +2 -1
  118. package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
  119. package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +628 -64
  120. package/template/coding-task-manager/lib/owner-action-manifest-data.json +14 -0
  121. package/template/coding-task-manager/lib/painted-row-recorder.js +9 -1
  122. package/template/coding-task-manager/lib/prompt-submission-contract.js +21 -1
  123. package/template/coding-task-manager/lib/provider-login-broker.js +192 -9
  124. package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
  125. package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
  126. package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
  127. package/template/coding-task-manager/lib/read-pool-client.js +5 -2
  128. package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
  129. package/template/coding-task-manager/lib/recent-catalog-query.js +26 -0
  130. package/template/coding-task-manager/lib/recent-session-catalog-response.js +9 -0
  131. package/template/coding-task-manager/lib/remote-command-context.js +12 -0
  132. package/template/coding-task-manager/lib/remote-command-runtime.js +13 -1
  133. package/template/coding-task-manager/lib/remote-machine-catalog.js +1062 -0
  134. package/template/coding-task-manager/lib/remote-machine-create.js +693 -0
  135. package/template/coding-task-manager/lib/remote-machine-link.js +939 -0
  136. package/template/coding-task-manager/lib/remote-machine-proxy.js +520 -0
  137. package/template/coding-task-manager/lib/remote-session-forward.js +306 -0
  138. package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
  139. package/template/coding-task-manager/lib/restart-outcome-truth.js +20 -3
  140. package/template/coding-task-manager/lib/restart-preflight.js +9 -2
  141. package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
  142. package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
  143. package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
  144. package/template/coding-task-manager/lib/resume-blocked-wire.js +62 -1
  145. package/template/coding-task-manager/lib/resume-cwd.js +13 -0
  146. package/template/coding-task-manager/lib/resume-from-store.js +12 -1
  147. package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
  148. package/template/coding-task-manager/lib/resume-preflight.js +21 -16
  149. package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
  150. package/template/coding-task-manager/lib/review-repo-registry.js +17 -0
  151. package/template/coding-task-manager/lib/root-delivery-runtime.js +72 -15
  152. package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
  153. package/template/coding-task-manager/lib/root-prompt-admission.js +33 -2
  154. package/template/coding-task-manager/lib/root-prompt-flow.js +167 -33
  155. package/template/coding-task-manager/lib/scrollback-archive-store.js +7 -4
  156. package/template/coding-task-manager/lib/session-analysis-memory.js +2 -0
  157. package/template/coding-task-manager/lib/session-create/codex-native-provider-gate.js +218 -0
  158. package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
  159. package/template/coding-task-manager/lib/session-create/delegate-worker.js +95 -6
  160. package/template/coding-task-manager/lib/session-create/identity.js +20 -1
  161. package/template/coding-task-manager/lib/session-create/prepared.js +69 -1
  162. package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
  163. package/template/coding-task-manager/lib/session-create/provider-process.js +34 -37
  164. package/template/coding-task-manager/lib/session-create/response.js +30 -12
  165. package/template/coding-task-manager/lib/session-create/transcript.js +13 -4
  166. package/template/coding-task-manager/lib/session-create/worker-continuation.js +43 -1
  167. package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
  168. package/template/coding-task-manager/lib/session-create/worker-observability.js +99 -7
  169. package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
  170. package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
  171. package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
  172. package/template/coding-task-manager/lib/session-host-manager.js +152 -206
  173. package/template/coding-task-manager/lib/session-jobs.js +17 -9
  174. package/template/coding-task-manager/lib/session-lifecycle.js +18 -0
  175. package/template/coding-task-manager/lib/session-model-action-preconditions.js +9 -0
  176. package/template/coding-task-manager/lib/session-resource-sampler.js +19 -9
  177. package/template/coding-task-manager/lib/session-standup.js +67 -4
  178. package/template/coding-task-manager/lib/session-status-ledger.js +42 -3
  179. package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
  180. package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
  181. package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
  182. package/template/coding-task-manager/lib/startup-pointer-write.js +57 -0
  183. package/template/coding-task-manager/lib/state-sync/painted-frame-field.js +11 -0
  184. package/template/coding-task-manager/lib/storage/coding-session-model-store.js +21 -22
  185. package/template/coding-task-manager/lib/surviving-owner-bootstrap.js +7 -2
  186. package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
  187. package/template/coding-task-manager/lib/terminal-draft-http-status.js +25 -0
  188. package/template/coding-task-manager/lib/transcript-archiver.js +229 -229
  189. package/template/coding-task-manager/lib/transcript-frame-cache.js +12 -2
  190. package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
  191. package/template/coding-task-manager/lib/transcript-link.js +77 -0
  192. package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
  193. package/template/coding-task-manager/lib/transcript-source.js +8 -3
  194. package/template/coding-task-manager/lib/transcript-store.js +40 -0
  195. package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
  196. package/template/coding-task-manager/lib/typing-interaction-trace.js +92 -0
  197. package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
  198. package/template/coding-task-manager/lib/visible-revision-watchdog.js +8 -12
  199. package/template/coding-task-manager/lib/wake-skip-reasons.js +46 -0
  200. package/template/coding-task-manager/lib/walle-supervisor.js +98 -14
  201. package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
  202. package/template/coding-task-manager/lib/ws/state-sync.js +19 -2
  203. package/template/coding-task-manager/lib/ws/terminal-attach.js +32 -1
  204. package/template/coding-task-manager/lib/ws-router.js +68 -1
  205. package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
  206. package/template/coding-task-manager/oauth-proxy.js +99 -55
  207. package/template/coding-task-manager/package-lock.json +24 -0
  208. package/template/coding-task-manager/package.json +3 -0
  209. package/template/coding-task-manager/providers/codex-mcp-extract.js +121 -19
  210. package/template/coding-task-manager/providers/codex-mcp.js +14 -5
  211. package/template/coding-task-manager/public/css/app.css +279 -1
  212. package/template/coding-task-manager/public/css/reviews.css +4 -0
  213. package/template/coding-task-manager/public/index.html +294 -223
  214. package/template/coding-task-manager/public/js/app/machines-page.js +1252 -0
  215. package/template/coding-task-manager/public/js/app/models-tab.js +546 -36
  216. package/template/coding-task-manager/public/js/app/worktrees-panel.js +7 -5
  217. package/template/coding-task-manager/public/js/background-work.js +13 -7
  218. package/template/coding-task-manager/public/js/coding-session-model-presentation.js +44 -4
  219. package/template/coding-task-manager/public/js/core/session-commands.js +676 -0
  220. package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
  221. package/template/coding-task-manager/public/js/history-app-seam.js +26 -2
  222. package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
  223. package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
  224. package/template/coding-task-manager/public/js/history-scroller.js +187 -9
  225. package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
  226. package/template/coding-task-manager/public/js/machine-pool-shared.js +436 -0
  227. package/template/coding-task-manager/public/js/private-state-scope.js +31 -3
  228. package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -8
  229. package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
  230. package/template/coding-task-manager/public/js/queue-panel-submission-reconcile.js +174 -1
  231. package/template/coding-task-manager/public/js/reviews.js +7 -3
  232. package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
  233. package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
  234. package/template/coding-task-manager/public/js/row-join.js +4 -2
  235. package/template/coding-task-manager/public/js/session-model-picker.js +1 -1
  236. package/template/coding-task-manager/public/js/session-search-utils.js +46 -19
  237. package/template/coding-task-manager/public/js/state-sync-client.js +4 -0
  238. package/template/coding-task-manager/public/js/terminal/runtime-02.js +16 -7
  239. package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
  240. package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
  241. package/template/coding-task-manager/public/js/terminal/runtime-12.js +52 -2
  242. package/template/coding-task-manager/public/js/terminal/runtime-16.js +12 -12
  243. package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
  244. package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
  245. package/template/coding-task-manager/public/js/terminal/runtime-20.js +210 -73
  246. package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
  247. package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
  248. package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -1
  249. package/template/coding-task-manager/public/js/terminal-wheel.js +39 -2
  250. package/template/coding-task-manager/public/js/walle/chat-conversation.js +11 -3
  251. package/template/coding-task-manager/public/js/walle-session.js +30 -7
  252. package/template/coding-task-manager/public/m/app.css +226 -8
  253. package/template/coding-task-manager/public/m/app.js +502 -9
  254. package/template/coding-task-manager/public/m/index.html +38 -1
  255. package/template/coding-task-manager/public/m/machines.js +1313 -0
  256. package/template/coding-task-manager/public/m/pool-failover.js +391 -0
  257. package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
  258. package/template/coding-task-manager/public/m/sw.js +5 -0
  259. package/template/coding-task-manager/queue-engine.js +13 -0
  260. package/template/coding-task-manager/server/approvals.js +5 -6
  261. package/template/coding-task-manager/server/boot.js +136 -17
  262. package/template/coding-task-manager/server.js +902 -239
  263. package/template/coding-task-manager/session-integrity.js +7 -9
  264. package/template/coding-task-manager/workers/db-owner-worker.js +53 -7
  265. package/template/coding-task-manager/workers/read-pool-worker.js +17 -6
  266. package/template/coding-task-manager/workers/session-host-pool-process.js +18 -4
  267. package/template/coding-task-manager/workers/session-host-process.js +14 -3
  268. package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
  269. package/template/coding-task-manager/workers/worktree-worker.js +34 -0
  270. package/template/package-lock.json +2 -2
  271. package/template/package.json +1 -1
  272. package/template/scripts/conversation-storage-v2-migration.js +78 -11
  273. package/template/shared/conversation-storage-v2-contract.js +42 -6
  274. package/template/shared/fixtures/worker-status-payloads.json +392 -0
  275. package/template/shared/git-remote-key.js +83 -0
  276. package/template/shared/host-identity.js +98 -2
  277. package/template/shared/owner-write-safety.js +135 -0
  278. package/template/shared/public-runtime.js +13 -5
  279. package/template/shared/release-schema.json +3 -2
  280. package/template/shared/report-citations.js +14 -0
  281. package/template/shared/sqlite-write-lock.js +361 -223
  282. package/template/shared/storage/contract.js +35 -3
  283. package/template/wall-e/agent.js +21 -0
  284. package/template/wall-e/api-walle.js +5 -0
  285. package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
  286. package/template/wall-e/bin/walle-mcp-stdio.js +12 -6
  287. package/template/wall-e/brain/helper-rules-schema.js +129 -0
  288. package/template/wall-e/brain/migrations.js +51 -22
  289. package/template/wall-e/brain/model-deployment-facts.js +31 -1
  290. package/template/wall-e/brain/owner-call-whitelist.js +16 -0
  291. package/template/wall-e/brain/schema-ensures.js +22 -0
  292. package/template/wall-e/brain.js +1 -1
  293. package/template/wall-e/coding/journal-dispatcher.js +51 -0
  294. package/template/wall-e/coding/session-journal.js +28 -40
  295. package/template/wall-e/coding-orchestrator.js +23 -26
  296. package/template/wall-e/http/auth.js +18 -1
  297. package/template/wall-e/http/blog-views-api.js +318 -0
  298. package/template/wall-e/http/helper-rules-api.js +321 -0
  299. package/template/wall-e/http/model-proxy-providers.js +3 -1
  300. package/template/wall-e/http/telemetry-api.js +12 -0
  301. package/template/wall-e/lib/blog-view-policy.js +88 -0
  302. package/template/wall-e/lib/blog-view-store.js +169 -0
  303. package/template/wall-e/lib/client-config-lock.js +2 -1
  304. package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
  305. package/template/wall-e/lib/error-kinds.js +10 -1
  306. package/template/wall-e/lib/feature-manifest.js +1 -1
  307. package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
  308. package/template/wall-e/lib/helper-rules/evaluate.js +357 -0
  309. package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
  310. package/template/wall-e/lib/helper-rules/grade.js +277 -0
  311. package/template/wall-e/lib/helper-rules/label.js +247 -0
  312. package/template/wall-e/lib/helper-rules/lead-call-hook.js +522 -0
  313. package/template/wall-e/lib/helper-rules/store.js +667 -0
  314. package/template/wall-e/lib/mcp-integration.js +5 -6
  315. package/template/wall-e/lib/runtime-worker-pool.js +1 -0
  316. package/template/wall-e/lib/scheduler-worker-jobs.js +6 -0
  317. package/template/wall-e/lib/telemetry-db-schema.js +37 -0
  318. package/template/wall-e/lib/telemetry-process-client.js +76 -1
  319. package/template/wall-e/llm/default-fallback.js +4 -0
  320. package/template/wall-e/llm/model-catalog.js +13 -4
  321. package/template/wall-e/llm/model-roles.js +6 -0
  322. package/template/wall-e/llm/portkey-http.js +150 -0
  323. package/template/wall-e/llm/portkey-sync.js +15 -145
  324. package/template/wall-e/llm/worker-mcp-routing.js +61 -0
  325. package/template/wall-e/llm/worker-route.js +43 -1
  326. package/template/wall-e/loops/brain-custom-writes.js +45 -0
  327. package/template/wall-e/mcp-protocol-contract.js +41 -1
  328. package/template/wall-e/mcp-server.js +13 -2
  329. package/template/wall-e/mcp-worker-schemas.js +20 -2
  330. package/template/wall-e/memory/ctm-context-client.js +25 -5
  331. package/template/wall-e/shared/release-schema.json +3 -2
  332. package/template/wall-e/shared/sqlite-write-lock.js +361 -223
  333. package/template/wall-e/shared/storage/contract.js +35 -3
  334. package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
  335. package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +6 -0
  336. package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +7 -2
  337. package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +7 -2
  338. package/template/wall-e/tools/local-tools.js +6 -4
  339. package/template/wall-e/workers/brain-owner-worker.js +9 -0
  340. package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
  341. package/template/wall-e/workers/telemetry-worker.js +8 -0
package/README.md CHANGED
@@ -73,6 +73,10 @@ CTM can park an eligible inactive session to stop its process and free resources
73
73
 
74
74
  A shared MCP gateway lets eligible tool servers reuse one process across sessions; tools needing session-specific state keep separate instances.
75
75
 
76
+ ### Use more than one machine
77
+
78
+ Pair another machine running CTM and its sessions join the same list, tagged by machine. Pick the machine when you start a session, open and type into it from the hub's browser, and sign that machine's coding agents in from the Machines page, on desktop or phone.
79
+
76
80
  ### Review changes in one place
77
81
 
78
82
  The Review page moves between rendered HTML or Markdown, source files and diffs, and new files appear before Git tracks them. Comments collect into one message for the session responsible for the change, keeping feedback beside the files that produced it.
@@ -0,0 +1,135 @@
1
+ 'use strict';
2
+
3
+ // Shared "no other account can write through this path" predicate for paths CTM and
4
+ // Wall-E did not create themselves (a Codex sessions root, an enrolled provider root,
5
+ // a data directory handed in by an installer, ~/.walle/data).
6
+ //
7
+ // The rule is Debian OpenSSH's `user-group-modes.patch` rule, adapted: world write is
8
+ // never acceptable, and group write is acceptable ONLY when the owning group is the
9
+ // current user's own one-member private group (the user-private-group scheme that
10
+ // `pam_umask(8)` sets up as umask 002 on every Debian/Ubuntu/Fedora login). On a shared
11
+ // group (`staff` on macOS, `users` on many hosts) the check is exactly as strict as
12
+ // before.
13
+ //
14
+ // Accepted gap (same as the Debian patch): a group password held in `/etc/gshadow`
15
+ // (usable through `newgrp`) and accounts that exist only in NSS (LDAP/SSSD) are invisible
16
+ // to the `/etc/group` + `/etc/passwd` parse this module performs, so a gid that cannot be
17
+ // proven from the local files is refused — the check always fails closed.
18
+
19
+ const fs = require('node:fs');
20
+ const os = require('node:os');
21
+
22
+ const MAX_DB_BYTES = 1024 * 1024;
23
+ const GROUP_PATH = '/etc/group';
24
+ const PASSWD_PATH = '/etc/passwd';
25
+
26
+ /** Default reader: one bounded read (≤ MAX_DB_BYTES), the fd always closed. */
27
+ function _readBoundedFile(filePath) {
28
+ const fd = fs.openSync(filePath, 'r');
29
+ try {
30
+ const stat = fs.fstatSync(fd);
31
+ if (Number(stat.size) > MAX_DB_BYTES) {
32
+ throw new Error(`${filePath} is larger than ${MAX_DB_BYTES} bytes`);
33
+ }
34
+ return fs.readFileSync(fd, 'utf8');
35
+ } finally {
36
+ fs.closeSync(fd);
37
+ }
38
+ }
39
+
40
+ // A seam explicitly passed as `null` means "this platform has no such call" (the Windows
41
+ // shape); `undefined` means "use the process default".
42
+ function _seam(deps, name, fallback) {
43
+ if (deps[name] === null) return null;
44
+ if (typeof deps[name] === 'function') return deps[name];
45
+ return typeof fallback === 'function' ? fallback : null;
46
+ }
47
+
48
+ // Split a local-database file into usable lines: blanks and `#` comments are skipped, and a
49
+ // `+`/`-` NIS compat line makes the whole file unprovable (return null).
50
+ function _usableLines(text) {
51
+ const lines = [];
52
+ for (const raw of String(text).split('\n')) {
53
+ const line = raw.trim();
54
+ if (!line || line.startsWith('#')) continue;
55
+ if (line.startsWith('+') || line.startsWith('-')) return null;
56
+ lines.push(line);
57
+ }
58
+ return lines;
59
+ }
60
+
61
+ function _numericField(value) {
62
+ return /^\d+$/.test(value || '') ? Number(value) : null;
63
+ }
64
+
65
+ /** D-2: `gid` is the current user's one-member private group. Any doubt ⇒ false. */
66
+ function isUserPrivateGroup(gid, deps = {}) {
67
+ try {
68
+ const getuid = _seam(deps, 'getuid', process.getuid);
69
+ const getgid = _seam(deps, 'getgid', process.getgid);
70
+ if (typeof getuid !== 'function' || typeof getgid !== 'function') return false;
71
+ const targetGid = _numericField(String(gid));
72
+ if (targetGid === null) return false;
73
+ if (Number(getgid()) !== targetGid) return false;
74
+ const uid = Number(getuid());
75
+ const usernameFn = _seam(deps, 'username', () => os.userInfo().username);
76
+ if (typeof usernameFn !== 'function') return false;
77
+ const username = String(usernameFn() || '');
78
+ if (!username) return false;
79
+ const readFile = _seam(deps, 'readFile', _readBoundedFile);
80
+ if (typeof readFile !== 'function') return false;
81
+
82
+ // (b) /etc/group: exactly one line with this gid, named after the login, members ⊆ {login}.
83
+ const groupLines = _usableLines(readFile(GROUP_PATH));
84
+ if (!groupLines) return false;
85
+ const groupEntries = [];
86
+ for (const line of groupLines) {
87
+ const fields = line.split(':');
88
+ const lineGid = fields.length >= 3 ? _numericField(fields[2]) : null;
89
+ if (lineGid === null || lineGid !== targetGid) continue;
90
+ if (fields.length !== 4) return false;
91
+ groupEntries.push({ name: fields[0], members: fields[3].split(',').map(m => m.trim()).filter(Boolean) });
92
+ }
93
+ if (groupEntries.length !== 1) return false;
94
+ const group = groupEntries[0];
95
+ if (group.name !== username) return false;
96
+ if (group.members.length > 1) return false;
97
+ if (group.members.length === 1 && group.members[0] !== username) return false;
98
+
99
+ // (c) /etc/passwd: every account whose primary gid is this gid is this uid, and one exists.
100
+ const passwdLines = _usableLines(readFile(PASSWD_PATH));
101
+ if (!passwdLines) return false;
102
+ let primaryAccounts = 0;
103
+ for (const line of passwdLines) {
104
+ const fields = line.split(':');
105
+ const lineGid = fields.length >= 4 ? _numericField(fields[3]) : null;
106
+ if (lineGid === null || lineGid !== targetGid) continue;
107
+ if (fields.length !== 7) return false;
108
+ primaryAccounts += 1;
109
+ const lineUid = _numericField(fields[2]);
110
+ if (lineUid === null || lineUid !== uid) return false;
111
+ }
112
+ if (primaryAccounts === 0) return false;
113
+ return true;
114
+ } catch {
115
+ /* expected: any unreadable or unparsable account database fails closed (D-3) */
116
+ return false;
117
+ }
118
+ }
119
+
120
+ /**
121
+ * True iff no account other than the current user can write through `stat`'s permission bits.
122
+ * Accepts fs.Stats (Number) and fs.BigIntStats (bigint) alike.
123
+ * @param {{ mode: number|bigint, gid: number|bigint }} stat
124
+ * @param {{ readFile?: (p: string) => string, getuid?: () => number, getgid?: () => number,
125
+ * username?: () => string }} [deps] test seams
126
+ * @returns {boolean}
127
+ */
128
+ function isWritableOnlyByOwner(stat, deps = {}) {
129
+ const mode = Number(stat.mode);
130
+ if ((mode & 0o002) !== 0) return false; // world write is never acceptable
131
+ if ((mode & 0o020) === 0) return true; // no group write: no file is read
132
+ return isUserPrivateGroup(Number(stat.gid), deps);
133
+ }
134
+
135
+ module.exports = { isWritableOnlyByOwner, isUserPrivateGroup, MAX_DB_BYTES, _readBoundedFile };
@@ -36,6 +36,11 @@ const os = require('node:os');
36
36
  const path = require('node:path');
37
37
  const { execFileSync } = require('node:child_process');
38
38
 
39
+ // The ONE "no other account can write through this path" predicate, shared with CTM and Wall-E. It
40
+ // is a relative SIBLING require on purpose: the mirror is byte-identical, so the same bytes resolve it
41
+ // from `shared/` and from `create-walle/lib/`.
42
+ const { isWritableOnlyByOwner } = require('./owner-write-safety');
43
+
39
44
  const {
40
45
  parseReleaseRuntimePolicy,
41
46
  releaseRuntimeArchive,
@@ -187,10 +192,13 @@ function publicRuntimeNpmEnv(nodeBin) {
187
192
 
188
193
  // ── the one cache-directory admission ───────────────────────────────────────────────────────────
189
194
  /**
190
- * Assert that `dir` is a REAL directory (never a link), owned by the current user, and not
191
- * group/other writable. Ancestors ABOVE the owned cache boundary are deliberately not inspected: a
192
- * system path or a sticky ancestor is not this installer's ownership requirement, and pretending
193
- * otherwise would refuse every legitimate `~/.walle` under a shared parent.
195
+ * Assert that `dir` is a REAL directory (never a link), owned by the current user, and writable only
196
+ * by its owner (a user-private group counts as the owner: world write is never acceptable, and group
197
+ * write is acceptable only when the owning group is the user's own one-member private group, the
198
+ * umask-002 scheme of a Debian/Ubuntu/Fedora login). Ancestors ABOVE the owned cache boundary are
199
+ * deliberately not inspected: a system path or a sticky ancestor is not this installer's ownership
200
+ * requirement, and pretending otherwise would refuse every legitimate `~/.walle` under a shared
201
+ * parent.
194
202
  */
195
203
  function assertOwnedCacheDirectory(fsOps, dir, phase) {
196
204
  let stat;
@@ -202,7 +210,7 @@ function assertOwnedCacheDirectory(fsOps, dir, phase) {
202
210
  if (stat.isSymbolicLink() || !stat.isDirectory()) {
203
211
  throw refuse(phase, 'public runtime cache directory is not a real directory');
204
212
  }
205
- if ((Number(stat.mode) & 0o022) !== 0) {
213
+ if (!isWritableOnlyByOwner(stat)) {
206
214
  throw refuse(phase, 'public runtime cache directory is group or other writable');
207
215
  }
208
216
  if (typeof process.getuid === 'function' && Number(stat.uid) !== process.getuid()) {
@@ -9,7 +9,7 @@
9
9
  21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
10
10
  31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
11
11
  41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
12
- 51, 52, 53, 54, 55
12
+ 51, 52, 53, 54, 55, 56
13
13
  ]
14
14
  },
15
15
  "walle": {
@@ -24,7 +24,8 @@
24
24
  61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
25
25
  71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
26
26
  81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
27
- 97, 98, 99
27
+ 97, 98, 99, 100,
28
+ 101
28
29
  ]
29
30
  }
30
31
  }
@@ -39,7 +39,9 @@
39
39
  "coding-task-manager/bin/seam-replay.js",
40
40
  "coding-task-manager/bin/session-access-lint.js",
41
41
  "coding-task-manager/bin/session-create-fanout-lint.js",
42
+ "coding-task-manager/bin/session-host-kill-lint.js",
42
43
  "coding-task-manager/bin/session-runtime-evidence-lint.js",
44
+ "coding-task-manager/bin/startup-pointer-writer-lint.js",
43
45
  "coding-task-manager/bin/status-verdict-lint.js",
44
46
  "coding-task-manager/bin/term-container-band-lint.js",
45
47
  "coding-task-manager/bin/terminal-write-lint.js",
@@ -1785,12 +1787,12 @@
1785
1787
  "coding-task-manager/lib/walle-deps-repair.js": "be85620d08795ea0fe9539820416d5cc50b654519abddab0811907fa3fe93a7f",
1786
1788
  "coding-task-manager/lib/walle-mcp-auto-config.js": "b978e9b15d9dac8179dde0feb5357c14957f7b4e36dab7e6779587bcde8faeff",
1787
1789
  "coding-task-manager/lib/walle-native-health.js": "9fdf7f17eb77837aac4ea16140a6f4e5a97d7a568945da30f29b9a7541c3d967",
1788
- "coding-task-manager/lib/walle-supervisor.js": "04b924f16c9bd001ed505347202dbec2876b57fc427a32c93d23586530181f83",
1790
+ "coding-task-manager/lib/walle-supervisor.js": "1eb9971a2ede9735e595952404f467f6775ad9f99545137faad86e3c6fb38af9",
1789
1791
  "coding-task-manager/public/js/client-health-worker.js": "07e300113ee749ac7a6adaaa1461502d1562087af395b6c89cf1b885f1f5e00e",
1790
1792
  "coding-task-manager/public/js/image-normalize-worker.js": "37cb0758bddcf10c66060fae52088c1a842409f30e919988e789cfea7d05e2be",
1791
- "coding-task-manager/public/m/app.js": "483f777f57efd28d7796713c33df48ffba47e5bfb50597b446a37b961f53d585",
1792
- "coding-task-manager/server.js": "927a036ed5143c02b2c021e5b5c0a80def7f87d01524514108f90f438e48b776",
1793
- "scripts/conversation-storage-v2-migration.js": "80c66e41c9fb9b1d756fe21be17f3b07c6a65389712887043a86341fbf6a6879",
1793
+ "coding-task-manager/public/m/app.js": "8e4662e21c409003a2d61de3c044410055176b574d787b34f7ede776b62a7003",
1794
+ "coding-task-manager/server.js": "347578d2cab77abedb122df048f60415d8d392ed4caf4bd32fc92e91a9aa3f9a",
1795
+ "scripts/conversation-storage-v2-migration.js": "f2620ba24893c4d2ec6c594428ddb41dc098da38b4066f1df25fb87abbfaebfa",
1794
1796
  "shared/storage/schema-port.js": "e41cec8c075a6167fba2efd0177d9e20a11c0cd49ae176aaf36d5b9257409e67",
1795
1797
  "shared/storage/schema-sync.js": "7ca080e44e35e8178a0f74317023881f920ae75bde4f7431702ce1f9fa4a1d03",
1796
1798
  "wall-e/adapters/chatgpt.js": "8c0fa31ae65ed5c10776e50a1a26c131bc62cb1aa3d88eb4617e7b83b43789d9",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-walle",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "CTM + Wall-E: one workspace for coding agents, worktrees and review, with shared session context and a personal agent.",
5
5
  "homepage": "https://walle.sh",
6
6
  "bin": {
@@ -248,7 +248,7 @@ function checkDeps(pkgDir, opts = {}) {
248
248
  }
249
249
 
250
250
  // The package dirs a gate depends on, relative to a checkout root.
251
- const TREE_SUBS = ['', 'coding-task-manager', 'wall-e', 'shared', 'create-walle'];
251
+ const TREE_SUBS = ['', 'coding-task-manager', 'wall-e', 'shared', 'create-walle', 'ctm-relay'];
252
252
 
253
253
  // `npm --prefix <owner> install --no-save`: <owner> is the checkout that really
254
254
  // holds node_modules (a gate tree borrows it through a symlink). Never
@@ -56,6 +56,17 @@ bootstrap_candidates() {
56
56
  for cache_node in "$HOME"/.walle/runtimes/*/*/runtime/bin/node; do
57
57
  if [ -e "$cache_node" ]; then printf '%s\n' "$cache_node"; fi
58
58
  done
59
+ # Linux boxes (e.g. DGX Spark) install Node via nvm/fnm, so with a non-interactive ssh session
60
+ # that never sources the manager there is no `node` on PATH and none of the macOS Wall-E paths
61
+ # above exist. Any version found here only RUNS the fixed helper; the pin is still enforced by the
62
+ # candidate ladder below, so a version-globbed bootstrap can never select a mismatched ABI.
63
+ local manager_node
64
+ for manager_node in \
65
+ "$HOME"/.nvm/versions/node/*/bin/node \
66
+ "$HOME"/.local/share/fnm/node-versions/*/installation/bin/node \
67
+ "$HOME"/.fnm/node-versions/*/installation/bin/node; do
68
+ if [ -e "$manager_node" ]; then printf '%s\n' "$manager_node"; fi
69
+ done
59
70
  return 0
60
71
  }
61
72
 
@@ -5,8 +5,11 @@ const os = require('os');
5
5
  const { isMainThread } = require('node:worker_threads');
6
6
  const { classifySqliteError } = require('./lib/sqlite-driver');
7
7
  const { reportRouteError, routeError, tagRouteValidationError } = require('./lib/route-error');
8
+ const { terminalDraftHttpStatus: _terminalDraftStatus } = require('./lib/terminal-draft-http-status');
8
9
  // WP-2 (§9): the delivery-completion request projection lives with the image-protocol owners.
9
10
  const { buildDraftDeliveryCompletionRequest } = require('./lib/terminal-draft-publication-api');
11
+ const remoteSessionForward = require('./lib/remote-session-forward'); // WP-3 (§6/D-1..D-3): an image-draft request for a MIRROR id is answered by the owning box
12
+ const { overlayQueueDraftStatuses } = require('./lib/queue-draft-status-overlay'); // R-1 (§5): the queue-draft GET overlays durable engine status, never writes
10
13
  const db = require('./db-owner-client');
11
14
  const queueEngine = require('./queue-engine');
12
15
  const harvest = require('./prompt-harvest');
@@ -820,7 +823,10 @@ function handlePromptApi(req, res, url, deps = {}) {
820
823
  // --- Images ---
821
824
  if (p === '/api/images/upload' && m === 'POST') return handleUploadImage(req, res, url);
822
825
  if (/^\/api\/sessions\/[^/]+\/image-drafts(?:\/[^/]+(?:\/content|\/delivery|\/freeze|\/submit|\/retry)?)?$/.test(p)) {
823
- return handleTerminalImageDraft(req, res, url);
826
+ const route = _terminalDraftRoute(url); // WP-3: a MIRROR id is answered by the box; a local id takes the same-tick path
827
+ if (!route || !remoteSessionForward.isMirrorSessionRequest(req, url, route.sessionId)) return handleTerminalImageDraft(req, res, url);
828
+ return remoteSessionForward.maybeForwardSessionRequest(req, res, url, route.sessionId)
829
+ .then((forwarded) => (forwarded ? undefined : handleTerminalImageDraft(req, res, url)));
824
830
  }
825
831
  if (p === '/api/images/ingest-path' && m === 'POST') return handleIngestImagePath(req, res);
826
832
  if (p === '/api/mobile/attachments/upload' && m === 'POST') return handleUploadMobileAttachment(req, res, url);
@@ -1466,26 +1472,6 @@ function _terminalDraftRoute(url) {
1466
1472
  } catch { return null; }
1467
1473
  }
1468
1474
 
1469
- function _terminalDraftStatus(error) {
1470
- if (!error) return 500;
1471
- if (error.code === 'CTM_MAIN_DB_REQUEST_FORBIDDEN') return 501;
1472
- if (error.code === 'CTM_OWNERSHIP_UNAVAILABLE' || error.code === 'CTM_DB_OWNER_UNAVAILABLE' ||
1473
- error.code === 'CTM_MEDIA_JOURNAL_UNAVAILABLE') return 503;
1474
- if (error.code === 'CTM_DRAFT_NOT_FOUND' || error.code === 'CTM_DRAFT_SESSION_NOT_FOUND') return 404;
1475
- if (error.code === 'CTM_SESSION_OWNER_MISMATCH') return 409;
1476
- if (error.code === 'CTM_DRAFT_REVISION_CONFLICT') return 412;
1477
- // CTM_IMAGE_IDEMPOTENCY_CONFLICT is the legacy/mobile lanes' equivalent of the draft
1478
- // lane's idempotency conflict (media-store requestId dedupe) — same 409 semantic
1479
- // (WP-9 lane-parity: distinguishable from a malformed 400 without inspecting `code`).
1480
- if (error.code === 'CTM_DRAFT_IDEMPOTENCY_CONFLICT' || error.code === 'CTM_IMAGE_IDEMPOTENCY_CONFLICT' ||
1481
- error.code === 'CTM_DRAFT_DELIVERY_SUPERSEDED' ||
1482
- error.code === 'CTM_DRAFT_DELIVERY_STATE') return 409;
1483
- if (error.code === 'CTM_DRAFT_FROZEN' || error.code === 'CTM_DRAFT_REQUEST_CANCELLED') return 409;
1484
- if (error.code === 'CTM_DRAFT_IMAGE_INVALID' || error.code === 'CTM_DRAFT_SESSION_REQUIRED' ||
1485
- error.code === 'CTM_DRAFT_IDENTITY_INVALID' || error.code === 'CTM_DRAFT_DELIVERY_OUTCOME_INVALID') return 400;
1486
- return 500;
1487
- }
1488
-
1489
1475
  function _imageFailureStatus(error, fallbackStatus = 500) {
1490
1476
  const terminalStatus = _terminalDraftStatus(error);
1491
1477
  if (terminalStatus !== 500 || fallbackStatus === 500) return terminalStatus;
@@ -6891,7 +6877,9 @@ function mergeQueueDraftItemsByStatusTimestamp(existingItems, incomingItems) {
6891
6877
  function handleGetQueueDraft(req, res, sessionId) {
6892
6878
  const key = 'queue_draft_' + sessionId;
6893
6879
  const draft = _getPublishedSetting(key, { items: [], mode: 'manual' });
6894
- jsonResponse(res, 200, draft);
6880
+ // R-1 (§5): read-only projection. The engine is the authority for an item's
6881
+ // durable status; the stored snapshot is never rewritten on this route.
6882
+ jsonResponse(res, 200, overlayQueueDraftStatuses(draft, queueEngine.getItemStatusMap(sessionId)));
6895
6883
  }
6896
6884
 
6897
6885
  async function handleSaveQueueDraft(req, res, sessionId) {
@@ -15,16 +15,20 @@ const http = require('http');
15
15
  const crypto = require('crypto');
16
16
  const modelGeneration = require('../lib/env-flags').strFlag('CTM_MODEL_PROCESS_GENERATION', '');
17
17
 
18
- // Only these routes can carry a notice back to the model (Claude hook stdout JSON).
19
- const NOTICE_ROUTES = new Set(['PostToolUse', 'start']);
18
+ // Only these routes can carry a notice back to the model (Claude hook stdout JSON). `stop` is
19
+ // here for RC-1 (docs/session-stops-mid-job-2026-10-24.html D-1): the Stop hook is answered
20
+ // synchronously so a lead that still owns a live worker is told to keep waiting.
21
+ const NOTICE_ROUTES = new Set(['PostToolUse', 'start', 'stop']);
20
22
 
21
23
  // The hook stdout for a CTM response body: one JSON object when it carries notices, else ''.
24
+ // Against an OLD server that answers {"matched":true} there is no `notices` array, so nothing is
25
+ // printed (D-8, safe in either rollout order).
22
26
  function formatHookOutput(responseText, hookEventName) {
23
27
  let parsed;
24
28
  try { parsed = JSON.parse(responseText); } catch { return ''; }
25
29
  const notices = parsed && Array.isArray(parsed.notices) ? parsed.notices : [];
26
30
  const texts = notices.map((n) => (n && typeof n.text === 'string' ? n.text : '')).filter(Boolean);
27
- if (!texts.length || (hookEventName !== 'PostToolUse' && hookEventName !== 'UserPromptSubmit')) return '';
31
+ if (!texts.length || !['PostToolUse', 'UserPromptSubmit', 'Stop'].includes(hookEventName)) return '';
28
32
  return JSON.stringify({ hookSpecificOutput: { hookEventName, additionalContext: texts.join('\n') } });
29
33
  }
30
34