create-walle 0.10.0 → 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 (381) hide show
  1. package/README.md +88 -41
  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 +7 -5
  6. package/package.json +10 -4
  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/capture-codex-rollout-records.js +417 -0
  11. package/template/coding-task-manager/bin/census-codex-lead-history.js +325 -0
  12. package/template/coding-task-manager/bin/claude-hook.js +7 -3
  13. package/template/coding-task-manager/bin/claude-table-parity.js +307 -0
  14. package/template/coding-task-manager/bin/conversation-storage-auto-migration-lib.js +16 -1
  15. package/template/coding-task-manager/bin/conversation-storage-generation-evidence.js +9 -2
  16. package/template/coding-task-manager/bin/conversation-storage-service-entry-lib.js +16 -1
  17. package/template/coding-task-manager/bin/conversation-storage-walle-owner.js +247 -0
  18. package/template/coding-task-manager/bin/ctm-machine-pair.js +160 -0
  19. package/template/coding-task-manager/bin/lead-wait-census.js +1348 -0
  20. package/template/coding-task-manager/bin/repair-foreign-clone.js +564 -0
  21. package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
  22. package/template/coding-task-manager/bin/seam-replay-codex.js +301 -0
  23. package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
  24. package/template/coding-task-manager/db.js +705 -286
  25. package/template/coding-task-manager/git-utils.js +44 -0
  26. package/template/coding-task-manager/lib/adopted-host-redial.js +4 -0
  27. package/template/coding-task-manager/lib/agent-presets.js +15 -0
  28. package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
  29. package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
  30. package/template/coding-task-manager/lib/api/host-stats.js +98 -0
  31. package/template/coding-task-manager/lib/api/ingress.js +35 -12
  32. package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
  33. package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
  34. package/template/coding-task-manager/lib/api/machines.js +461 -0
  35. package/template/coding-task-manager/lib/api/misc-ops.js +20 -5
  36. package/template/coding-task-manager/lib/api/providers.js +53 -6
  37. package/template/coding-task-manager/lib/api/resume-from-store.js +25 -0
  38. package/template/coding-task-manager/lib/api/sessions.js +160 -8
  39. package/template/coding-task-manager/lib/api/transcript-history.js +17 -4
  40. package/template/coding-task-manager/lib/api/worktrees.js +38 -37
  41. package/template/coding-task-manager/lib/approval-drift.js +16 -1
  42. package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
  43. package/template/coding-task-manager/lib/approval-scope.js +68 -4
  44. package/template/coding-task-manager/lib/auth-context.js +32 -2
  45. package/template/coding-task-manager/lib/auth-rate-limit.js +41 -1
  46. package/template/coding-task-manager/lib/auth-rules.js +186 -45
  47. package/template/coding-task-manager/lib/broadcast-serialize.js +2 -1
  48. package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
  49. package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
  50. package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
  51. package/template/coding-task-manager/lib/claude-session-title.js +6 -30
  52. package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
  53. package/template/coding-task-manager/lib/client-diag-handler.js +25 -0
  54. package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
  55. package/template/coding-task-manager/lib/codex-harness-qualification.js +12 -0
  56. package/template/coding-task-manager/lib/codex-history-terminal-renderer.js +33 -33
  57. package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
  58. package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
  59. package/template/coding-task-manager/lib/codex-local-links.js +267 -0
  60. package/template/coding-task-manager/lib/codex-markdown-lists.js +160 -0
  61. package/template/coding-task-manager/lib/codex-native-history-prefix.js +4 -0
  62. package/template/coding-task-manager/lib/codex-paths.js +2 -1
  63. package/template/coding-task-manager/lib/codex-source-handoff.js +186 -0
  64. package/template/coding-task-manager/lib/coding-agent-models.js +21 -30
  65. package/template/coding-task-manager/lib/coding-session-model-adapters.js +27 -2
  66. package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
  67. package/template/coding-task-manager/lib/coding-session-model-runtime.js +1 -2
  68. package/template/coding-task-manager/lib/coding-session-model-state.js +10 -0
  69. package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
  70. package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -0
  71. package/template/coding-task-manager/lib/create/resolve-launch-params.js +8 -1
  72. package/template/coding-task-manager/lib/ctm-boot-lifecycle.js +17 -1
  73. package/template/coding-task-manager/lib/db-domain-tables.js +7 -0
  74. package/template/coding-task-manager/lib/db-domains.js +21 -2
  75. package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -0
  76. package/template/coding-task-manager/lib/db-owner-worker-client.js +22 -0
  77. package/template/coding-task-manager/lib/db-schema-source-files.js +1 -0
  78. package/template/coding-task-manager/lib/feature-manifest.js +1 -3
  79. package/template/coding-task-manager/lib/fs-watcher.js +3 -2
  80. package/template/coding-task-manager/lib/harness-history-transition.js +41 -14
  81. package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
  82. package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
  83. package/template/coding-task-manager/lib/headless-term-service.js +60 -23
  84. package/template/coding-task-manager/lib/history-transition-read-op.js +179 -23
  85. package/template/coding-task-manager/lib/host-control-dial.js +167 -0
  86. package/template/coding-task-manager/lib/host-handoff-orchestrator.js +16 -2
  87. package/template/coding-task-manager/lib/host-handoff.js +51 -13
  88. package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
  89. package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
  90. package/template/coding-task-manager/lib/host-stats.js +328 -0
  91. package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
  92. package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
  93. package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
  94. package/template/coding-task-manager/lib/hosted-sync-worker.js +113 -5
  95. package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +4 -0
  96. package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
  97. package/template/coding-task-manager/lib/instance-manifest.js +13 -1
  98. package/template/coding-task-manager/lib/instance-sync-status.js +15 -0
  99. package/template/coding-task-manager/lib/kernel/diag-log.js +12 -0
  100. package/template/coding-task-manager/lib/launch-model-override.js +160 -1
  101. package/template/coding-task-manager/lib/launch-plan-worker.js +59 -2
  102. package/template/coding-task-manager/lib/lead-model-observer.js +17 -2
  103. package/template/coding-task-manager/lib/lead-model-switch-runtime.js +57 -4
  104. package/template/coding-task-manager/lib/lead-model-switch.js +11 -2
  105. package/template/coding-task-manager/lib/lead-model-transition-runtime.js +42 -4
  106. package/template/coding-task-manager/lib/lead-model-transition-store.js +61 -3
  107. package/template/coding-task-manager/lib/legacy-draft-cancellation-recovery.js +111 -0
  108. package/template/coding-task-manager/lib/login-tripwire.js +18 -0
  109. package/template/coding-task-manager/lib/machine-pairing.js +238 -0
  110. package/template/coding-task-manager/lib/machine-pool.js +409 -0
  111. package/template/coding-task-manager/lib/machine-registry.js +749 -0
  112. package/template/coding-task-manager/lib/machine-self.js +66 -0
  113. package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +56 -4
  114. package/template/coding-task-manager/lib/media-journal-control-reader.js +473 -0
  115. package/template/coding-task-manager/lib/media-journal.js +84 -27
  116. package/template/coding-task-manager/lib/media-store-options.js +43 -15
  117. package/template/coding-task-manager/lib/migrations/v56-host-samples-and-machine-pool.js +76 -0
  118. package/template/coding-task-manager/lib/mirror-feed-sanitize.js +12 -3
  119. package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +16 -3
  120. package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
  121. package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
  122. package/template/coding-task-manager/lib/model-proxy/collaboration-codec.js +94 -0
  123. package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
  124. package/template/coding-task-manager/lib/model-proxy/lead-worker-picks.js +25 -0
  125. package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
  126. package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
  127. package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -0
  128. package/template/coding-task-manager/lib/model-proxy/responses-face.js +24 -2
  129. package/template/coding-task-manager/lib/model-proxy/stream-accounting.js +205 -0
  130. package/template/coding-task-manager/lib/model-proxy/tokens.js +78 -0
  131. package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
  132. package/template/coding-task-manager/lib/native-history-control.js +62 -14
  133. package/template/coding-task-manager/lib/native-lead-settings-client.js +2 -1
  134. package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
  135. package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +628 -64
  136. package/template/coding-task-manager/lib/owner-action-manifest-data.json +14 -0
  137. package/template/coding-task-manager/lib/painted-row-recorder.js +9 -1
  138. package/template/coding-task-manager/lib/prompt-admission-trace.js +69 -0
  139. package/template/coding-task-manager/lib/prompt-submission-contract.js +21 -1
  140. package/template/coding-task-manager/lib/provider-login-broker.js +192 -9
  141. package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
  142. package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
  143. package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
  144. package/template/coding-task-manager/lib/raw-history-block.js +3 -1
  145. package/template/coding-task-manager/lib/read-pool-client.js +36 -24
  146. package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
  147. package/template/coding-task-manager/lib/read-pool-telemetry.js +14 -5
  148. package/template/coding-task-manager/lib/recent-catalog-query.js +26 -0
  149. package/template/coding-task-manager/lib/recent-session-catalog-response.js +9 -0
  150. package/template/coding-task-manager/lib/remote-command-context.js +12 -0
  151. package/template/coding-task-manager/lib/remote-command-runtime.js +18 -5
  152. package/template/coding-task-manager/lib/remote-machine-catalog.js +1062 -0
  153. package/template/coding-task-manager/lib/remote-machine-create.js +693 -0
  154. package/template/coding-task-manager/lib/remote-machine-link.js +939 -0
  155. package/template/coding-task-manager/lib/remote-machine-proxy.js +520 -0
  156. package/template/coding-task-manager/lib/remote-session-forward.js +306 -0
  157. package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
  158. package/template/coding-task-manager/lib/restart-outcome-truth.js +20 -3
  159. package/template/coding-task-manager/lib/restart-preflight.js +9 -2
  160. package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
  161. package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
  162. package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
  163. package/template/coding-task-manager/lib/resume-blocked-wire.js +62 -1
  164. package/template/coding-task-manager/lib/resume-cwd.js +13 -0
  165. package/template/coding-task-manager/lib/resume-from-store.js +12 -1
  166. package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
  167. package/template/coding-task-manager/lib/resume-preflight.js +21 -16
  168. package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
  169. package/template/coding-task-manager/lib/review-repo-registry.js +17 -0
  170. package/template/coding-task-manager/lib/root-delivery-runtime.js +72 -15
  171. package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
  172. package/template/coding-task-manager/lib/root-prompt-admission.js +43 -11
  173. package/template/coding-task-manager/lib/root-prompt-flow.js +175 -38
  174. package/template/coding-task-manager/lib/scrollback-archive-store.js +7 -4
  175. package/template/coding-task-manager/lib/server-memory-sampler-runtime.js +10 -0
  176. package/template/coding-task-manager/lib/server-memory-sampler.js +41 -2
  177. package/template/coding-task-manager/lib/session-analysis-memory.js +2 -0
  178. package/template/coding-task-manager/lib/session-create/codex-native-provider-gate.js +218 -0
  179. package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
  180. package/template/coding-task-manager/lib/session-create/delegate-worker.js +95 -6
  181. package/template/coding-task-manager/lib/session-create/identity.js +20 -1
  182. package/template/coding-task-manager/lib/session-create/prepared.js +69 -1
  183. package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
  184. package/template/coding-task-manager/lib/session-create/provider-process.js +38 -39
  185. package/template/coding-task-manager/lib/session-create/response.js +30 -12
  186. package/template/coding-task-manager/lib/session-create/transcript.js +13 -4
  187. package/template/coding-task-manager/lib/session-create/worker-continuation.js +43 -1
  188. package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
  189. package/template/coding-task-manager/lib/session-create/worker-observability.js +99 -7
  190. package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
  191. package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
  192. package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
  193. package/template/coding-task-manager/lib/session-host-manager.js +152 -206
  194. package/template/coding-task-manager/lib/session-jobs.js +17 -9
  195. package/template/coding-task-manager/lib/session-lifecycle.js +20 -50
  196. package/template/coding-task-manager/lib/session-model-action-preconditions.js +68 -3
  197. package/template/coding-task-manager/lib/session-resource-sampler.js +67 -9
  198. package/template/coding-task-manager/lib/session-standup.js +67 -4
  199. package/template/coding-task-manager/lib/session-status-ledger.js +42 -3
  200. package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
  201. package/template/coding-task-manager/lib/session-status.js +2 -2
  202. package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
  203. package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
  204. package/template/coding-task-manager/lib/startup-pointer-write.js +57 -0
  205. package/template/coding-task-manager/lib/state-sync/painted-frame-field.js +11 -0
  206. package/template/coding-task-manager/lib/storage/coding-session-model-store.js +21 -22
  207. package/template/coding-task-manager/lib/surviving-owner-bootstrap.js +7 -2
  208. package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
  209. package/template/coding-task-manager/lib/terminal-draft-http-status.js +25 -0
  210. package/template/coding-task-manager/lib/transcript-archiver.js +229 -229
  211. package/template/coding-task-manager/lib/transcript-frame-cache.js +12 -2
  212. package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
  213. package/template/coding-task-manager/lib/transcript-link.js +77 -0
  214. package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
  215. package/template/coding-task-manager/lib/transcript-source.js +8 -3
  216. package/template/coding-task-manager/lib/transcript-store.js +40 -0
  217. package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
  218. package/template/coding-task-manager/lib/typing-interaction-trace.js +136 -2
  219. package/template/coding-task-manager/lib/typing-worker-stages.js +208 -1
  220. package/template/coding-task-manager/lib/usage-ledger/claude-parse.js +53 -2
  221. package/template/coding-task-manager/lib/usage-ledger/ingest.js +13 -4
  222. package/template/coding-task-manager/lib/usage-ledger/read.js +14 -0
  223. package/template/coding-task-manager/lib/usage-ledger/schema.js +49 -1
  224. package/template/coding-task-manager/lib/usage-ledger/store.js +337 -6
  225. package/template/coding-task-manager/lib/usage-ledger/task-read.js +123 -5
  226. package/template/coding-task-manager/lib/visible-revision-watchdog.js +8 -12
  227. package/template/coding-task-manager/lib/wake-skip-reasons.js +46 -0
  228. package/template/coding-task-manager/lib/walle-supervisor.js +98 -14
  229. package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
  230. package/template/coding-task-manager/lib/ws/input.js +1 -0
  231. package/template/coding-task-manager/lib/ws/state-sync.js +19 -2
  232. package/template/coding-task-manager/lib/ws/terminal-attach.js +32 -1
  233. package/template/coding-task-manager/lib/ws-router.js +68 -1
  234. package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
  235. package/template/coding-task-manager/oauth-proxy.js +99 -55
  236. package/template/coding-task-manager/package-lock.json +24 -0
  237. package/template/coding-task-manager/package.json +3 -0
  238. package/template/coding-task-manager/protocol/message-table.json +0 -10
  239. package/template/coding-task-manager/protocol/messages.js +0 -10
  240. package/template/coding-task-manager/protocol/ws-schema.json +0 -20
  241. package/template/coding-task-manager/protocol/ws-schema.md +0 -2
  242. package/template/coding-task-manager/providers/codex-mcp-extract.js +121 -19
  243. package/template/coding-task-manager/providers/codex-mcp.js +14 -5
  244. package/template/coding-task-manager/public/css/app.css +279 -2
  245. package/template/coding-task-manager/public/css/reviews.css +4 -0
  246. package/template/coding-task-manager/public/index.html +297 -240
  247. package/template/coding-task-manager/public/js/app/machines-page.js +1252 -0
  248. package/template/coding-task-manager/public/js/app/models-tab.js +546 -36
  249. package/template/coding-task-manager/public/js/app/worktrees-panel.js +7 -5
  250. package/template/coding-task-manager/public/js/background-work.js +13 -7
  251. package/template/coding-task-manager/public/js/client-health-core.js +81 -0
  252. package/template/coding-task-manager/public/js/client-health-main.js +61 -0
  253. package/template/coding-task-manager/public/js/coding-session-model-presentation.js +44 -4
  254. package/template/coding-task-manager/public/js/core/session-commands.js +676 -0
  255. package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
  256. package/template/coding-task-manager/public/js/history-app-seam.js +26 -2
  257. package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
  258. package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
  259. package/template/coding-task-manager/public/js/history-scroller.js +187 -9
  260. package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
  261. package/template/coding-task-manager/public/js/machine-pool-shared.js +436 -0
  262. package/template/coding-task-manager/public/js/private-state-scope.js +31 -3
  263. package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -4
  264. package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
  265. package/template/coding-task-manager/public/js/protocol.js +0 -10
  266. package/template/coding-task-manager/public/js/queue-panel-submission-reconcile.js +174 -1
  267. package/template/coding-task-manager/public/js/reviews.js +7 -3
  268. package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
  269. package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
  270. package/template/coding-task-manager/public/js/row-join.js +18 -3
  271. package/template/coding-task-manager/public/js/session-model-picker.js +1 -1
  272. package/template/coding-task-manager/public/js/session-search-utils.js +46 -19
  273. package/template/coding-task-manager/public/js/session-usage-view.js +1 -0
  274. package/template/coding-task-manager/public/js/state-sync-client.js +4 -0
  275. package/template/coding-task-manager/public/js/terminal/runtime-02.js +16 -7
  276. package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
  277. package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
  278. package/template/coding-task-manager/public/js/terminal/runtime-12.js +52 -2
  279. package/template/coding-task-manager/public/js/terminal/runtime-16.js +12 -12
  280. package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
  281. package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
  282. package/template/coding-task-manager/public/js/terminal/runtime-20.js +210 -73
  283. package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
  284. package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
  285. package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -3
  286. package/template/coding-task-manager/public/js/terminal-wheel.js +39 -2
  287. package/template/coding-task-manager/public/js/walle/chat-conversation.js +11 -3
  288. package/template/coding-task-manager/public/js/walle-session.js +30 -7
  289. package/template/coding-task-manager/public/m/app.css +226 -8
  290. package/template/coding-task-manager/public/m/app.js +502 -9
  291. package/template/coding-task-manager/public/m/index.html +38 -1
  292. package/template/coding-task-manager/public/m/machines.js +1313 -0
  293. package/template/coding-task-manager/public/m/pool-failover.js +391 -0
  294. package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
  295. package/template/coding-task-manager/public/m/sw.js +5 -0
  296. package/template/coding-task-manager/queue-engine.js +13 -0
  297. package/template/coding-task-manager/server/approvals.js +5 -6
  298. package/template/coding-task-manager/server/boot.js +136 -17
  299. package/template/coding-task-manager/server.js +964 -425
  300. package/template/coding-task-manager/session-integrity.js +7 -9
  301. package/template/coding-task-manager/workers/db-owner-worker.js +53 -7
  302. package/template/coding-task-manager/workers/read-pool-worker.js +17 -6
  303. package/template/coding-task-manager/workers/session-host-pool-process.js +18 -4
  304. package/template/coding-task-manager/workers/session-host-process.js +14 -3
  305. package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
  306. package/template/coding-task-manager/workers/worktree-worker.js +34 -0
  307. package/template/package-lock.json +2 -2
  308. package/template/package.json +1 -1
  309. package/template/scripts/conversation-storage-v2-migration.js +78 -11
  310. package/template/shared/conversation-storage-v2-contract.js +42 -6
  311. package/template/shared/fixtures/worker-status-payloads.json +392 -0
  312. package/template/shared/git-remote-key.js +83 -0
  313. package/template/shared/host-identity.js +98 -2
  314. package/template/shared/owner-write-safety.js +135 -0
  315. package/template/shared/public-runtime.js +13 -5
  316. package/template/shared/release-schema.json +3 -2
  317. package/template/shared/report-citations.js +14 -0
  318. package/template/shared/sqlite-write-lock.js +361 -223
  319. package/template/shared/storage/contract.js +35 -3
  320. package/template/wall-e/agent.js +21 -0
  321. package/template/wall-e/api-walle.js +5 -0
  322. package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
  323. package/template/wall-e/bin/walle-mcp-stdio.js +12 -6
  324. package/template/wall-e/brain/helper-rules-schema.js +129 -0
  325. package/template/wall-e/brain/migrations.js +51 -22
  326. package/template/wall-e/brain/model-deployment-facts.js +31 -1
  327. package/template/wall-e/brain/owner-call-whitelist.js +16 -0
  328. package/template/wall-e/brain/schema-ensures.js +22 -0
  329. package/template/wall-e/brain.js +1 -1
  330. package/template/wall-e/coding/host-capabilities.js +2 -2
  331. package/template/wall-e/coding/journal-dispatcher.js +51 -0
  332. package/template/wall-e/coding/session-journal.js +28 -40
  333. package/template/wall-e/coding-orchestrator.js +23 -26
  334. package/template/wall-e/fly.toml +1 -1
  335. package/template/wall-e/http/auth.js +18 -1
  336. package/template/wall-e/http/blog-views-api.js +318 -0
  337. package/template/wall-e/http/helper-rules-api.js +321 -0
  338. package/template/wall-e/http/model-proxy-providers.js +3 -1
  339. package/template/wall-e/http/telemetry-api.js +12 -0
  340. package/template/wall-e/lib/blog-view-policy.js +88 -0
  341. package/template/wall-e/lib/blog-view-store.js +169 -0
  342. package/template/wall-e/lib/client-config-lock.js +2 -1
  343. package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
  344. package/template/wall-e/lib/error-kinds.js +10 -1
  345. package/template/wall-e/lib/feature-manifest.js +1 -1
  346. package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
  347. package/template/wall-e/lib/helper-rules/evaluate.js +357 -0
  348. package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
  349. package/template/wall-e/lib/helper-rules/grade.js +277 -0
  350. package/template/wall-e/lib/helper-rules/label.js +247 -0
  351. package/template/wall-e/lib/helper-rules/lead-call-hook.js +522 -0
  352. package/template/wall-e/lib/helper-rules/store.js +667 -0
  353. package/template/wall-e/lib/mcp-integration.js +5 -6
  354. package/template/wall-e/lib/runtime-worker-pool.js +1 -0
  355. package/template/wall-e/lib/scheduler-worker-jobs.js +6 -0
  356. package/template/wall-e/lib/telemetry-db-schema.js +37 -0
  357. package/template/wall-e/lib/telemetry-process-client.js +76 -1
  358. package/template/wall-e/llm/default-fallback.js +4 -0
  359. package/template/wall-e/llm/model-catalog.js +13 -4
  360. package/template/wall-e/llm/model-roles.js +6 -0
  361. package/template/wall-e/llm/portkey-http.js +150 -0
  362. package/template/wall-e/llm/portkey-sync.js +15 -145
  363. package/template/wall-e/llm/worker-mcp-routing.js +61 -0
  364. package/template/wall-e/llm/worker-route.js +43 -1
  365. package/template/wall-e/loops/brain-custom-writes.js +45 -0
  366. package/template/wall-e/mcp-protocol-contract.js +41 -1
  367. package/template/wall-e/mcp-server.js +13 -2
  368. package/template/wall-e/mcp-worker-schemas.js +20 -2
  369. package/template/wall-e/memory/ctm-context-client.js +25 -5
  370. package/template/wall-e/shared/release-schema.json +3 -2
  371. package/template/wall-e/shared/sqlite-write-lock.js +361 -223
  372. package/template/wall-e/shared/storage/contract.js +35 -3
  373. package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
  374. package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +6 -0
  375. package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +7 -2
  376. package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +7 -2
  377. package/template/wall-e/tools/local-tools.js +12 -5
  378. package/template/wall-e/workers/brain-owner-worker.js +9 -0
  379. package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
  380. package/template/wall-e/workers/telemetry-worker.js +8 -0
  381. package/template/coding-task-manager/lib/giant-freeze-park.js +0 -31
@@ -23,6 +23,7 @@ const MAX_CURSOR_BYTES = 16 * 1024;
23
23
  // A request keeps consuming blocks until it holds maxRows rows or has read maxBytes; this bounds
24
24
  // the work when many consecutive blocks hold only hidden record kinds.
25
25
  const MAX_FILL_BLOCKS = 16;
26
+ const MAX_EMPTY_RUN_BLOCKS = 256; // D-1: while no row is collected a fill keeps consuming up to 256 × BLOCK_BYTES = 8 MiB of hidden records before answering an empty page
26
27
  // leadPrompt: when no loaded unit before the page holds a prompt, scan this many EARLIER blocks (2 MiB) for one.
27
28
  const LEAD_SCAN_MAX_BLOCKS = 64;
28
29
  // Per-process LRU of scan answers. A page inside one long turn would otherwise re-scan the same blocks on every
@@ -323,7 +324,7 @@ function getRawCodexHistoryWindow(sources, options = {}, fileOps = transcriptSou
323
324
  // maxBytes budgets the source bytes CONSUMED (the logical blocks); readRawHistoryBlock also reads a
324
325
  // block of look-around each side to resolve record ownership, so counting raw reads would stop at ~3 blocks.
325
326
  const consumedBytes = () => segments.reduce((sum, one) => sum + (one.block.end - one.block.start), 0);
326
- while (all.length < maxRows && !(all.length && consumedBytes() >= maxBytes) && segments.length < MAX_FILL_BLOCKS) {
327
+ while (all.length < maxRows && !(all.length && consumedBytes() >= maxBytes) && segments.length < (all.length ? MAX_FILL_BLOCKS : MAX_EMPTY_RUN_BLOCKS)) {
327
328
  const at = forward ? nextBlockOf(seg, all.at(-1)) : prevBlockOf(seg);
328
329
  if (!at) break;
329
330
  seg = loadBlock(at.x, at.b);
@@ -466,7 +467,8 @@ function getRawCodexHistoryWindow(sources, options = {}, fileOps = transcriptSou
466
467
  // A block with only non-display records must still advance rather than claim an edge.
467
468
  if (!items.length && all.length) return base('retryable-error', generation, 'response-budget-too-small');
468
469
  if (!items.length) {
469
- // Every block consumed was hidden-only: hand back cursors just past the oldest/newest one read.
470
+ // Every block consumed (up to MAX_EMPTY_RUN_BLOCKS while no row was collected) was hidden-only: hand back
471
+ // cursors just past the oldest/newest one read, so the next request resumes after the hidden run it walked.
470
472
  const oldest = forward ? segments[0] : segments.at(-1); const newest = forward ? segments.at(-1) : segments[0];
471
473
  const older = prevBlockOf(oldest); const newer = nextBlockOf(newest, null);
472
474
  response.olderCursor = cursorAt(older && { ...older, u: Number.MAX_SAFE_INTEGER, f: Number.MAX_SAFE_INTEGER });
@@ -484,4 +486,4 @@ function getRawCodexHistoryWindow(sources, options = {}, fileOps = transcriptSou
484
486
  return response;
485
487
  }
486
488
 
487
- module.exports = { FAMILY, BLOCK_BYTES, encodeRawCodexHistoryCursor, decodeRawCodexHistoryCursor, isRawCodexHistoryCursor, getRawCodexHistoryWindow, historyRowKindOfRole };
489
+ module.exports = { FAMILY, BLOCK_BYTES, MAX_EMPTY_RUN_BLOCKS, encodeRawCodexHistoryCursor, decodeRawCodexHistoryCursor, isRawCodexHistoryCursor, getRawCodexHistoryWindow, historyRowKindOfRole };
@@ -412,8 +412,10 @@ function unitKind(unit) {
412
412
  function renderUnit(unit, render, lane = 'legacy') {
413
413
  const message = { role: unit.role, text: inertText(unit.text), timestamp: unit.timestamp,
414
414
  ...(unit.metadata ? { metadata: inertText(unit.metadata) } : {}) };
415
+ // D-4: the rollout's own session cwd reaches BOTH lanes — a legacy-lane local file link draws the
416
+ // same cwd-relative target Codex's screen draws; `shape`/`tzOffsetMinutes` stay items-only.
415
417
  const out = renderCodexHistoryAnsi([message], { cols: render.cols, cliVersion: render.cliVersion || '', fidelity: true,
416
- ...(lane === 'items' ? { shape: 'owned', cwd: render.cwd, tzOffsetMinutes: render.tzOffsetMinutes } : {}) });
418
+ cwd: render.cwd, ...(lane === 'items' ? { shape: 'owned', tzOffsetMinutes: render.tzOffsetMinutes } : {}) });
417
419
  if (out.fallbackCount > 0) return null;
418
420
  const lines = out.ansi.split('\r\n').map(line => line.replace(RENDERED_ROW_RE, (match, sgr) => (sgr ? match : '�')));
419
421
  while (lines.length && lines.at(-1) === '') lines.pop();
@@ -165,6 +165,7 @@ const {
165
165
  _cloneHistogram,
166
166
  buildRefusalSnapshot,
167
167
  formatRefusalLogLine,
168
+ oldestOccupied,
168
169
  } = require('./read-pool-telemetry');
169
170
 
170
171
  // One timeout code for every client-leg expiry (pool-side and worker-side expiry already carry it): retry, not blame.
@@ -1104,8 +1105,11 @@ class CtmReadPoolClient {
1104
1105
  const timer = setTimeout(resolve, 500);
1105
1106
  timer.unref?.();
1106
1107
  });
1107
- const results = await Promise.all(this._workers.map(worker => worker.requestReadonlyRecycle(reason)));
1108
- return { requested: this._workers.length, recycled: results.filter(Boolean).length };
1108
+ // Only a slot with an isolate can hold a read connection; a retired / never-started slot is
1109
+ // already in a reader gap (sqlite.org/wal.html "reader gaps").
1110
+ const live = this._workers.filter((worker) => worker.isLive);
1111
+ const results = await Promise.all(live.map((worker) => worker.requestReadonlyRecycle(reason)));
1112
+ return { requested: live.length, recycled: results.filter(Boolean).length, skippedNoIsolate: this._workers.length - live.length };
1109
1113
  }
1110
1114
 
1111
1115
  // `idleMs` (WP-4): when set, only workers idle (no completed op) at least this long
@@ -1274,28 +1278,36 @@ class CtmReadPoolClient {
1274
1278
  .filter((waiter) => waiter.active)
1275
1279
  .map((waiter) => Date.now() - waiter.enqueuedAt)),
1276
1280
  resourceLimits: { ...this.resourceLimits },
1277
- workers: this._workers.map((w) => ({
1278
- ready: w.ready,
1279
- retiring: w.retiring,
1280
- closing: w.closing,
1281
- idleMs: Date.now() - w.lastActiveAt,
1282
- retired: w.retired,
1283
- retiredAt: w.retiredAt,
1284
- inFlight: w.inFlight,
1285
- heavyInFlight: w.heavyInFlight,
1286
- responseCount: w.responseCount,
1287
- responseBytes: w.responseBytes,
1288
- peakResponseBytes: w.peakResponseBytes,
1289
- inputCount: w.inputCount,
1290
- inputBytes: w.inputBytes,
1291
- peakInputBytes: w.peakInputBytes,
1292
- memory: { ...w.memory },
1293
- heapStatistics: w.heapStatistics,
1294
- openConnections: w.openConnections,
1295
- connection: w.connection,
1296
- currentOpBytes: w.currentOpBytes,
1297
- errors: { ...w.errors },
1298
- })),
1281
+ workers: this._workers.map((w) => {
1282
+ // WP-A P-2 (freeze-probes): what this worker is running RIGHT NOW, so a memory step can be
1283
+ // read against the work in flight. Same "oldest occupied" helper buildRefusalSnapshot uses.
1284
+ const current = oldestOccupied(w.occupied);
1285
+ return {
1286
+ currentOp: current ? current.op : null,
1287
+ currentOpAgeMs: current ? Date.now() - current.startedAt : 0,
1288
+ occupiedCount: w.occupied.size,
1289
+ ready: w.ready,
1290
+ retiring: w.retiring,
1291
+ closing: w.closing,
1292
+ idleMs: Date.now() - w.lastActiveAt,
1293
+ retired: w.retired,
1294
+ retiredAt: w.retiredAt,
1295
+ inFlight: w.inFlight,
1296
+ heavyInFlight: w.heavyInFlight,
1297
+ responseCount: w.responseCount,
1298
+ responseBytes: w.responseBytes,
1299
+ peakResponseBytes: w.peakResponseBytes,
1300
+ inputCount: w.inputCount,
1301
+ inputBytes: w.inputBytes,
1302
+ peakInputBytes: w.peakInputBytes,
1303
+ memory: { ...w.memory },
1304
+ heapStatistics: w.heapStatistics,
1305
+ openConnections: w.openConnections,
1306
+ connection: w.connection,
1307
+ currentOpBytes: w.currentOpBytes,
1308
+ errors: { ...w.errors },
1309
+ };
1310
+ }),
1299
1311
  inFlight: this._workers.reduce((s, w) => s + w.inFlight, 0),
1300
1312
  responseCount: this._workers.reduce((s, w) => s + w.responseCount, 0),
1301
1313
  responseBytes: this._workers.reduce((s, w) => s + w.responseBytes, 0),
@@ -140,8 +140,10 @@ const READ_POOL_OP_DECLARATIONS = {
140
140
  maxInputBytes: 8 * 1024,
141
141
  maxOutputBytes: REMOTE_COMMAND_RECEIPT_WIRE_MAX_BYTES + 16 * 1024,
142
142
  },
143
+ // Accepted prompt delivery needs this bounded row read in reserved interactive capacity.
144
+ // Background scans must not hold delivery behind service admission.
143
145
  getAcceptedRootJobText: {
144
- class: 'service', expectedMs: 1000, maxRows: 1,
146
+ class: 'interactive', expectedMs: 1000, maxRows: 1,
145
147
  maxInputBytes: 8 * 1024, maxOutputBytes: 16 * 1024, resumable: false,
146
148
  },
147
149
  hasLegacyRemoteCommandPresence: {
@@ -372,6 +374,13 @@ const READ_POOL_OP_DECLARATIONS = {
372
374
  startupTasksScan: {
373
375
  class: 'service', expectedMs: 250, maxRows: 200, maxOutputBytes: 512 * 1024,
374
376
  },
377
+ // WP-6 (session-name-agent-title-precedence §§6/8): the one-shot agent-title backfill's read
378
+ // half — up to 20 candidate rows plus a ≤64 KiB positional tail read per row. Background
379
+ // maintenance (service class, not user-visible): it is dispatched by the boot job, never by a
380
+ // keystroke, and 20 rows × a 64 KiB window is the whole budget of one task.
381
+ backfillAgentTitles: {
382
+ class: 'service', expectedMs: 5000, maxRows: 20, maxOutputBytes: 2 * 1024 * 1024,
383
+ },
375
384
  drain: { class: 'interactive', expectedMs: 25 },
376
385
  // WP-5 (composer-typing-freeze doc §13): the 15s walle-permission-reconcile tick's
377
386
  // two plain reads (approval_decisions forwarding rows + non-terminal pty:
@@ -32,6 +32,17 @@ function countGhosts(occupied) {
32
32
  return count;
33
33
  }
34
34
 
35
+ // The worker's oldest occupied entry (insertion-order tie-break, matching the refusal snapshot's own
36
+ // loop), or null. Shared by buildRefusalSnapshot and ReadPoolClient.getStatus()'s per-worker rows
37
+ // (freeze-probes WP-A P-2) so "what is this worker running right now" has ONE implementation.
38
+ function oldestOccupied(occupied) {
39
+ let oldest = null;
40
+ for (const entry of occupied.values()) {
41
+ if (!oldest || entry.startedAt < oldest.startedAt) oldest = entry;
42
+ }
43
+ return oldest;
44
+ }
45
+
35
46
  // A ghost's deadline span: the caller's full timeout (fallbackSpanMs when it had none).
36
47
  function ghostSpanMs(entry, fallbackSpanMs) {
37
48
  return entry.deadline > 0 && entry.enqueuedAt > 0 ? entry.deadline - entry.enqueuedAt : fallbackSpanMs;
@@ -50,11 +61,8 @@ function findOverdueGhost(occupied, now, fallbackSpanMs, multiple = 2, floorMs =
50
61
  function buildRefusalSnapshot({ now, op, requestClass, reason, workers, liveSize, waitersByClass, running, lastEmptyAtInteractive }) {
51
62
  let ghosts = 0;
52
63
  const perWorker = workers.map((w) => {
53
- let oldest = null;
54
- for (const occupied of w.occupied.values()) {
55
- if (occupied.orphanedAt) ghosts += 1;
56
- if (!oldest || occupied.startedAt < oldest.startedAt) oldest = occupied;
57
- }
64
+ ghosts += countGhosts(w.occupied);
65
+ const oldest = oldestOccupied(w.occupied);
58
66
  return {
59
67
  index: w.index,
60
68
  ready: w.ready,
@@ -112,6 +120,7 @@ module.exports = {
112
120
  buildRefusalSnapshot,
113
121
  formatRefusalLogLine,
114
122
  countGhosts,
123
+ oldestOccupied,
115
124
  findOverdueGhost,
116
125
  ghostSpanMs,
117
126
  };
@@ -110,6 +110,29 @@ function mapAgent(agent, parentRow) {
110
110
  };
111
111
  }
112
112
 
113
+ /**
114
+ * WP-3 (remote-hub-followups D-10): the machine tag for a recent row — the row's EXECUTION host
115
+ * (falling back to its current owner) when that id names a REGISTERED machine and is not this host
116
+ * or its lineage (`machineTags.localIds`). `machineHealth` is deliberately not stamped on recents:
117
+ * they are history (D-10).
118
+ *
119
+ * `machineTags` is main's cheap registry snapshot (`{machines, localIds}`), passed through the
120
+ * read-pool op input. With NO machines the result is null, so the row gains no key at all and the
121
+ * response stays byte-identical to the pre-WP-3 projection (AC-3a).
122
+ */
123
+ function machineFactsForRecentRow(row, options = {}) {
124
+ const tags = options && options.machineTags;
125
+ const machines = Array.isArray(tags?.machines) ? tags.machines : null;
126
+ if (!machines || machines.length === 0) return null;
127
+ const id = String(row?.execution_host_instance_id || row?.current_owner_instance_id || '').trim();
128
+ if (!id) return null;
129
+ const localIds = Array.isArray(tags.localIds) ? tags.localIds : [];
130
+ if (localIds.includes(id)) return null;
131
+ const machine = machines.find((candidate) => candidate && String(candidate.instanceId || '') === id);
132
+ if (!machine) return null;
133
+ return { machine: id, machineName: String(machine.displayName || '') };
134
+ }
135
+
113
136
  function mapRecentSessionRow(row, options = {}) {
114
137
  const hostname = String(options.hostname || '');
115
138
  const agentSessions = (Array.isArray(row?.agent_sessions) ? row.agent_sessions : [])
@@ -179,6 +202,8 @@ function mapRecentSessionRow(row, options = {}) {
179
202
  parentAgentSessionId: row.parent_agent_session_id || primary?.parentAgentSessionId || '',
180
203
  agentNickname: row.agent_nickname || primary?.agentNickname || '',
181
204
  agentRole: row.agent_role || primary?.agentRole || '',
205
+ // WP-3 (D-10): the machine tag, only when this row's execution host is a registered box.
206
+ ...(machineFactsForRecentRow(row, options) || {}),
182
207
  };
183
208
  return sessionEmpty.applyRecentSessionEmptyState(session, row);
184
209
  }
@@ -228,6 +253,7 @@ function queryRecentCatalogSessions(db, options = {}) {
228
253
  module.exports = {
229
254
  isProviderChildAgentRow,
230
255
  isProviderChildSessionRow,
256
+ machineFactsForRecentRow,
231
257
  mapRecentSessionRow,
232
258
  mapRecentSessionRows,
233
259
  mapRecentSessionRowsCooperatively,
@@ -16,6 +16,9 @@ const RECENT_SESSION_FIELDS = Object.freeze([
16
16
  'jsonlPath', 'sourcePath', 'desktopCacheOnly', 'provisionalId', 'agentSessionId',
17
17
  'agentSessionIds', 'threadSource', 'parentAgentSessionId', 'parentThreadId',
18
18
  'agentNickname', 'agentRole',
19
+ // WP-3 (remote-hub-followups S-13/D-10): the box tag must survive the persisted cold-boot
20
+ // snapshot, or a warm restart would strip it and a box row would render as local.
21
+ 'machine', 'machineName',
19
22
  ]);
20
23
  const RECENT_AGENT_FIELDS = Object.freeze([
21
24
  'agentSessionId', 'providerResumeId', 'ctmSessionId', 'provider', 'agent',
@@ -83,6 +86,12 @@ function activityMs(session) {
83
86
  return Number.isFinite(parsed) ? parsed : 0;
84
87
  }
85
88
 
89
+ // S-5 (remote-machine-hub-sessions-2026-10-22.html §9): this function OVERWRITES every row's
90
+ // `hostname` with THIS host's hostname. That is display metadata for a local (pre-multi-machine)
91
+ // catalog and it stays that way — but it means a row's `hostname` says NOTHING about where the
92
+ // session lives. Machine labeling MUST therefore use the machine's minted instance id
93
+ // (`machine`/`machineName`, filled by lib/remote-machine-catalog.js) and NEVER a hostname: any
94
+ // hostname-based label would silently claim a box's session is on this host (D-3).
86
95
  function buildRecentSessionCatalogResponse(input = {}) {
87
96
  const shape = normalizeRecentCatalogShape(input.query);
88
97
  const hostname = String(input.hostname || '');
@@ -2,6 +2,7 @@
2
2
 
3
3
  const crypto = require('crypto');
4
4
  const { getResolvedEnvCredentialIdentity } = require('./auth-context');
5
+ const { hasPeerControlScope } = require('./auth-rules');
5
6
  const { isVerifiedOwner } = require('./owner-policy');
6
7
 
7
8
  function isValidIdentity(value) {
@@ -38,6 +39,17 @@ function deriveRemoteCommandNamespace(auth, actualInstanceId) {
38
39
  if (!digest || !/^[a-f0-9]{64}$/.test(digest)) return null;
39
40
  principalTuple = ['env', digest];
40
41
  principalKind = 'env';
42
+ } else if (auth.source === 'sync-peer-token' && hasPeerControlScope(auth)) {
43
+ // WP-3b (docs/remote-machine-hub-sessions-2026-10-22.html §6.2/D-7): a relayed root prompt
44
+ // arrives on the sync peer bearer, which is the only credential carrying the peer-control
45
+ // scope (lib/auth-rules.js). The peer's own identity is its `X-CTM-Sync-Peer` id
46
+ // (`peerInstanceId`); when the single-token form names no peer, the token's log hash is the
47
+ // only distinguishing label. Neither → no principal, no namespace.
48
+ const peerInstanceId = typeof auth.peerInstanceId === 'string' ? auth.peerInstanceId : '';
49
+ const tokenHint = typeof auth.tokenHashPrefix === 'string' ? auth.tokenHashPrefix : '';
50
+ if (!peerInstanceId && !tokenHint) return null;
51
+ principalTuple = ['peer', peerInstanceId || `token:${tokenHint}`];
52
+ principalKind = 'peer';
41
53
  } else if (auth.source === 'loopback' && auth.isLoopback === true) {
42
54
  principalTuple = ['local', 'loopback'];
43
55
  principalKind = 'local';
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  const crypto = require('crypto');
4
+ const promptAdmissionTrace = require('./prompt-admission-trace');
4
5
  const { AsyncLocalStorage } = require('node:async_hooks');
5
6
  const remoteRelayProtocol = require('./remote-relay-protocol');
6
7
  const { createRemoteCommandCoordinator, projectIdentity } = require('./remote-command-coordinator');
7
- const { authorize: authorizeByRule, getHttpAuthRule, getWsAuthRule } = require('./auth-rules');
8
+ const { authorize: authorizeByRule, getHttpAuthRule, getWsAuthRule, hasPeerControlScope } = require('./auth-rules');
8
9
  const { deriveRemoteCommandNamespace } = require('./remote-command-context');
9
10
  const { getDeviceCredentialProof } = require('./ws-device-credential-proof');
10
11
  const instanceIdentityAccess = require('./instance-identity-access');
@@ -82,12 +83,12 @@ function createRemoteCommandRuntime({
82
83
  reserve: (entry) => {
83
84
  const at = now();
84
85
  scopeForCoordinator(db);
85
- return relayStore.reserveRemoteCommand(db, entry, at);
86
+ return promptAdmissionTrace.time('receipt.reserve', () => relayStore.reserveRemoteCommand(db, entry, at));
86
87
  },
87
88
  complete: (entry, result) => {
88
89
  const at = now();
89
90
  scopeForCoordinator(db);
90
- return relayStore.completeRemoteCommand(db, entry, result, at);
91
+ return promptAdmissionTrace.time('receipt.complete', () => relayStore.completeRemoteCommand(db, entry, result, at));
91
92
  },
92
93
  markUnknown: (entry, reason) => {
93
94
  const at = now();
@@ -96,9 +97,9 @@ function createRemoteCommandRuntime({
96
97
  },
97
98
  lookupLegacyPresence: async (commandId) => {
98
99
  const scope = scopeForCoordinator(db);
99
- const found = await runReadPoolOp('hasLegacyRemoteCommandPresence', {
100
+ const found = await promptAdmissionTrace.time('legacy.presence', () => runReadPoolOp('hasLegacyRemoteCommandPresence', {
100
101
  dbPath: scope.dbPath, commandId,
101
- }, { telemetryReason: 'remote-command-legacy-presence' });
102
+ }, { telemetryReason: 'remote-command-legacy-presence' }));
102
103
  if (!scope.isCurrent()) throw new Error('remote command database lifetime unavailable');
103
104
  return found;
104
105
  },
@@ -334,6 +335,18 @@ function createRemoteCommandRuntime({
334
335
  || auth.source !== 'env-scoped-token' || auth.transport !== 'remote') return deny();
335
336
  const decision = authorizeByRule(auth, getWsAuthRule('submit-prompt'), { enforceStepUp: true });
336
337
  if (!decision.ok) return deny(decision.code, decision.status);
338
+ } else if (auth.source === 'sync-peer-token' && auth.authenticated === true && hasPeerControlScope(auth)) {
339
+ // WP-3b (docs/remote-machine-hub-sessions-2026-10-22.html §6.2/D-7, AC-3a): the hub relays a
340
+ // box-owned session's `submit-prompt` over the sync peer bearer (auth source
341
+ // `sync-peer-token`, scopes {'sync','peer-control'}; lib/auth-context.js resolveSyncPeerToken).
342
+ // The peer credential is env-configured (CTM_SYNC_PEER_TOKEN / CTM_SYNC_PEER_TOKENS) with no
343
+ // revocation store to re-read, so freshness is exactly the shared `guard()` — this socket is
344
+ // still open, `client.auth` is still this same object, and the instance id is unchanged.
345
+ // Peer-control rows short-circuit step-up by design (authorize(), lib/auth-rules.js), so this
346
+ // mirrors the env/loopback branches: authorize with step-up ENFORCED and let the flag decide.
347
+ if (!guard()) return deny();
348
+ const decision = authorizeByRule(auth, getWsAuthRule('submit-prompt'), { enforceStepUp: true });
349
+ if (!decision.ok) return deny(decision.code, decision.status);
337
350
  } else if (auth.authenticated === true && auth.source === 'loopback' && auth.isLoopback === true) {
338
351
  let isLocal = false;
339
352
  try { isLocal = typeof validateLoopbackSocket === 'function' && validateLoopbackSocket(client) === true; }