create-walle 0.10.1 → 0.10.3

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 (681) hide show
  1. package/README.md +7 -1
  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 +11 -8
  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 +55 -29
  10. package/template/coding-task-manager/bin/claude-hook.js +62 -4
  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/ctm-relay-client.js +35 -12
  18. package/template/coding-task-manager/bin/land.js +2069 -0
  19. package/template/coding-task-manager/bin/lead-wait-census.js +1348 -0
  20. package/template/coding-task-manager/bin/memory-census.js +4 -2
  21. package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
  22. package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
  23. package/template/coding-task-manager/bin/repair-foreign-clone.js +564 -0
  24. package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
  25. package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
  26. package/template/coding-task-manager/db.js +860 -317
  27. package/template/coding-task-manager/git-utils.js +44 -0
  28. package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
  29. package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
  30. package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
  31. package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
  32. package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
  33. package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
  34. package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
  35. package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
  36. package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
  37. package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
  38. package/template/coding-task-manager/lib/adopted-host-redial.js +47 -7
  39. package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
  40. package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
  41. package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
  42. package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
  43. package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
  44. package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
  45. package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
  46. package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
  47. package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
  48. package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
  49. package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
  50. package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
  51. package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
  52. package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
  53. package/template/coding-task-manager/lib/agent-definitions.js +19 -0
  54. package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
  55. package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
  56. package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
  57. package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
  58. package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
  59. package/template/coding-task-manager/lib/agent-presets.js +99 -1
  60. package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
  61. package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
  62. package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
  63. package/template/coding-task-manager/lib/agent-version-service.js +74 -11
  64. package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
  65. package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
  66. package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
  67. package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
  68. package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
  69. package/template/coding-task-manager/lib/api/fleet.js +118 -0
  70. package/template/coding-task-manager/lib/api/host-stats.js +98 -0
  71. package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
  72. package/template/coding-task-manager/lib/api/ingress.js +43 -12
  73. package/template/coding-task-manager/lib/api/landing.js +403 -0
  74. package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
  75. package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
  76. package/template/coding-task-manager/lib/api/machines.js +1150 -0
  77. package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
  78. package/template/coding-task-manager/lib/api/misc-ops.js +25 -5
  79. package/template/coding-task-manager/lib/api/providers.js +53 -6
  80. package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
  81. package/template/coding-task-manager/lib/api/resume-from-store.js +25 -0
  82. package/template/coding-task-manager/lib/api/session-attach.js +623 -0
  83. package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
  84. package/template/coding-task-manager/lib/api/sessions.js +237 -59
  85. package/template/coding-task-manager/lib/api/setup-network.js +544 -16
  86. package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
  87. package/template/coding-task-manager/lib/api/setup.js +829 -10
  88. package/template/coding-task-manager/lib/api/transcript-history.js +17 -4
  89. package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
  90. package/template/coding-task-manager/lib/api/worktrees.js +38 -37
  91. package/template/coding-task-manager/lib/approval-drift.js +16 -1
  92. package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
  93. package/template/coding-task-manager/lib/approval-scope.js +68 -4
  94. package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
  95. package/template/coding-task-manager/lib/auth-context.js +32 -2
  96. package/template/coding-task-manager/lib/auth-rate-limit.js +64 -1
  97. package/template/coding-task-manager/lib/auth-rules.js +474 -62
  98. package/template/coding-task-manager/lib/background-stop.js +369 -0
  99. package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
  100. package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
  101. package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
  102. package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
  103. package/template/coding-task-manager/lib/broadcast-serialize.js +7 -1
  104. package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
  105. package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
  106. package/template/coding-task-manager/lib/build-info.js +4 -2
  107. package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
  108. package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
  109. package/template/coding-task-manager/lib/claude-session-title.js +6 -30
  110. package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
  111. package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
  112. package/template/coding-task-manager/lib/client-diag-handler.js +69 -2
  113. package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
  114. package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
  115. package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
  116. package/template/coding-task-manager/lib/codex-harness-qualification.js +55 -20
  117. package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
  118. package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
  119. package/template/coding-task-manager/lib/codex-paths.js +2 -1
  120. package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
  121. package/template/coding-task-manager/lib/coding-agent-models.js +48 -42
  122. package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
  123. package/template/coding-task-manager/lib/coding-session-model-adapters.js +70 -4
  124. package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
  125. package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
  126. package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
  127. package/template/coding-task-manager/lib/coding-session-model-runtime.js +24 -6
  128. package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
  129. package/template/coding-task-manager/lib/coding-session-model-state.js +17 -0
  130. package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
  131. package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
  132. package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -0
  133. package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
  134. package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
  135. package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
  136. package/template/coding-task-manager/lib/conversation-sync.js +355 -0
  137. package/template/coding-task-manager/lib/create/resolve-launch-params.js +104 -13
  138. package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
  139. package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
  140. package/template/coding-task-manager/lib/ctm-boot-lifecycle.js +17 -1
  141. package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
  142. package/template/coding-task-manager/lib/db-domain-tables.js +8 -0
  143. package/template/coding-task-manager/lib/db-domains.js +22 -2
  144. package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
  145. package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -0
  146. package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
  147. package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
  148. package/template/coding-task-manager/lib/db-schema-source-files.js +6 -0
  149. package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
  150. package/template/coding-task-manager/lib/feature-manifest.js +5 -1
  151. package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
  152. package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
  153. package/template/coding-task-manager/lib/fleet-hub.js +762 -0
  154. package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
  155. package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
  156. package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
  157. package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
  158. package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
  159. package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
  160. package/template/coding-task-manager/lib/fleet-update.js +798 -0
  161. package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
  162. package/template/coding-task-manager/lib/fs-watcher.js +61 -44
  163. package/template/coding-task-manager/lib/harness-history-transition.js +52 -11
  164. package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
  165. package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
  166. package/template/coding-task-manager/lib/headless-term-service.js +139 -25
  167. package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
  168. package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
  169. package/template/coding-task-manager/lib/host-control-dial.js +167 -0
  170. package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
  171. package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
  172. package/template/coding-task-manager/lib/host-handoff-orchestrator.js +16 -2
  173. package/template/coding-task-manager/lib/host-handoff.js +50 -15
  174. package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
  175. package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
  176. package/template/coding-task-manager/lib/host-stats.js +475 -0
  177. package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
  178. package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
  179. package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
  180. package/template/coding-task-manager/lib/hosted-sync-worker.js +141 -310
  181. package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
  182. package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
  183. package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
  184. package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
  185. package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
  186. package/template/coding-task-manager/lib/hub-bridge.js +398 -0
  187. package/template/coding-task-manager/lib/idle-notify.js +491 -0
  188. package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +12 -0
  189. package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
  190. package/template/coding-task-manager/lib/instance-manifest.js +18 -2
  191. package/template/coding-task-manager/lib/instance-sync-status.js +33 -8
  192. package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
  193. package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
  194. package/template/coding-task-manager/lib/landing/config.js +536 -0
  195. package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
  196. package/template/coding-task-manager/lib/landing/gate.js +360 -0
  197. package/template/coding-task-manager/lib/landing/git.js +344 -0
  198. package/template/coding-task-manager/lib/landing/lease.js +247 -0
  199. package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
  200. package/template/coding-task-manager/lib/landing/proof.js +223 -0
  201. package/template/coding-task-manager/lib/landing/queue.js +998 -0
  202. package/template/coding-task-manager/lib/landing/radar.js +489 -0
  203. package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
  204. package/template/coding-task-manager/lib/landing/state.js +263 -0
  205. package/template/coding-task-manager/lib/landing/stop.js +49 -0
  206. package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
  207. package/template/coding-task-manager/lib/landing/sync.js +456 -0
  208. package/template/coding-task-manager/lib/landing/train.js +885 -0
  209. package/template/coding-task-manager/lib/landing/window.js +57 -0
  210. package/template/coding-task-manager/lib/launch-environment.js +121 -0
  211. package/template/coding-task-manager/lib/launch-model-override.js +193 -8
  212. package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
  213. package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
  214. package/template/coding-task-manager/lib/launch-plan-worker.js +59 -2
  215. package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
  216. package/template/coding-task-manager/lib/lead-model-options.js +160 -3
  217. package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
  218. package/template/coding-task-manager/lib/lead-model-switch-runtime.js +409 -72
  219. package/template/coding-task-manager/lib/lead-model-switch.js +115 -10
  220. package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
  221. package/template/coding-task-manager/lib/lead-model-transition-store.js +85 -9
  222. package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
  223. package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
  224. package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
  225. package/template/coding-task-manager/lib/legacy-draft-cancellation-recovery.js +111 -0
  226. package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
  227. package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
  228. package/template/coding-task-manager/lib/login-tripwire.js +1 -0
  229. package/template/coding-task-manager/lib/machine-pairing.js +238 -0
  230. package/template/coding-task-manager/lib/machine-pool.js +409 -0
  231. package/template/coding-task-manager/lib/machine-registry.js +1494 -0
  232. package/template/coding-task-manager/lib/machine-self.js +66 -0
  233. package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
  234. package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +485 -57
  235. package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
  236. package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
  237. package/template/coding-task-manager/lib/media-journal-control-reader.js +473 -0
  238. package/template/coding-task-manager/lib/media-journal.js +84 -27
  239. package/template/coding-task-manager/lib/media-store-options.js +43 -15
  240. package/template/coding-task-manager/lib/memory-join.js +337 -0
  241. package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
  242. package/template/coding-task-manager/lib/memory-sync.js +565 -0
  243. package/template/coding-task-manager/lib/migrations/v56-host-samples-and-machine-pool.js +76 -0
  244. package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
  245. package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
  246. package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
  247. package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
  248. package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
  249. package/template/coding-task-manager/lib/mirror-feed-sanitize.js +12 -3
  250. package/template/coding-task-manager/lib/model-availability.js +727 -0
  251. package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
  252. package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
  253. package/template/coding-task-manager/lib/model-id-rule.js +19 -0
  254. package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +8 -0
  255. package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
  256. package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +6 -0
  257. package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
  258. package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
  259. package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
  260. package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
  261. package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
  262. package/template/coding-task-manager/lib/model-proxy/lead-worker-picks.js +25 -0
  263. package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
  264. package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
  265. package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -0
  266. package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
  267. package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
  268. package/template/coding-task-manager/lib/model-proxy/stream-accounting.js +205 -0
  269. package/template/coding-task-manager/lib/model-proxy/tokens.js +147 -5
  270. package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +18 -0
  271. package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
  272. package/template/coding-task-manager/lib/native-history-control.js +7 -5
  273. package/template/coding-task-manager/lib/native-lead-settings-client.js +46 -5
  274. package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
  275. package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +776 -75
  276. package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
  277. package/template/coding-task-manager/lib/opencode-cli.js +480 -0
  278. package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
  279. package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
  280. package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
  281. package/template/coding-task-manager/lib/owner-action-manifest-data.json +15 -1
  282. package/template/coding-task-manager/lib/painted-row-recorder.js +9 -1
  283. package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
  284. package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
  285. package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
  286. package/template/coding-task-manager/lib/perf-summary.js +7 -0
  287. package/template/coding-task-manager/lib/perf-tracker.js +63 -2
  288. package/template/coding-task-manager/lib/project-config.js +7 -0
  289. package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
  290. package/template/coding-task-manager/lib/prompt-submission-contract.js +21 -1
  291. package/template/coding-task-manager/lib/provider-login-broker.js +264 -24
  292. package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
  293. package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
  294. package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
  295. package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
  296. package/template/coding-task-manager/lib/read-pool-client.js +94 -4
  297. package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
  298. package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
  299. package/template/coding-task-manager/lib/recent-catalog-query.js +41 -0
  300. package/template/coding-task-manager/lib/recent-session-catalog-response.js +76 -10
  301. package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
  302. package/template/coding-task-manager/lib/relay-client.js +57 -3
  303. package/template/coding-task-manager/lib/relink-audit.js +34 -5
  304. package/template/coding-task-manager/lib/remote-command-context.js +12 -0
  305. package/template/coding-task-manager/lib/remote-command-runtime.js +13 -1
  306. package/template/coding-task-manager/lib/remote-machine-catalog.js +1357 -0
  307. package/template/coding-task-manager/lib/remote-machine-create.js +1233 -0
  308. package/template/coding-task-manager/lib/remote-machine-link.js +1426 -0
  309. package/template/coding-task-manager/lib/remote-machine-proxy.js +654 -0
  310. package/template/coding-task-manager/lib/remote-session-forward.js +364 -0
  311. package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
  312. package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
  313. package/template/coding-task-manager/lib/restart-guard.js +18 -6
  314. package/template/coding-task-manager/lib/restart-outcome-truth.js +20 -3
  315. package/template/coding-task-manager/lib/restart-preflight.js +9 -2
  316. package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
  317. package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
  318. package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
  319. package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
  320. package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
  321. package/template/coding-task-manager/lib/resume-admission.js +17 -3
  322. package/template/coding-task-manager/lib/resume-blocked-wire.js +62 -1
  323. package/template/coding-task-manager/lib/resume-cwd.js +13 -0
  324. package/template/coding-task-manager/lib/resume-from-store.js +12 -1
  325. package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
  326. package/template/coding-task-manager/lib/resume-preflight.js +21 -16
  327. package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
  328. package/template/coding-task-manager/lib/review-repo-registry.js +74 -18
  329. package/template/coding-task-manager/lib/root-delivery-runtime.js +74 -17
  330. package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
  331. package/template/coding-task-manager/lib/root-prompt-admission.js +33 -2
  332. package/template/coding-task-manager/lib/root-prompt-flow.js +168 -34
  333. package/template/coding-task-manager/lib/runtime-contract.js +3 -1
  334. package/template/coding-task-manager/lib/schema-indexes.js +1 -0
  335. package/template/coding-task-manager/lib/scrollback-archive-store.js +7 -4
  336. package/template/coding-task-manager/lib/session-analysis-memory.js +2 -0
  337. package/template/coding-task-manager/lib/session-context-locator.js +742 -0
  338. package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
  339. package/template/coding-task-manager/lib/session-create/codex-native-provider-gate.js +218 -0
  340. package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
  341. package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
  342. package/template/coding-task-manager/lib/session-create/delegate-worker.js +179 -20
  343. package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
  344. package/template/coding-task-manager/lib/session-create/identity.js +20 -1
  345. package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
  346. package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
  347. package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
  348. package/template/coding-task-manager/lib/session-create/prepared.js +201 -9
  349. package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
  350. package/template/coding-task-manager/lib/session-create/provider-process.js +193 -64
  351. package/template/coding-task-manager/lib/session-create/response.js +37 -19
  352. package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
  353. package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
  354. package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
  355. package/template/coding-task-manager/lib/session-create/transcript.js +14 -5
  356. package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
  357. package/template/coding-task-manager/lib/session-create/worker-continuation.js +50 -2
  358. package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
  359. package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
  360. package/template/coding-task-manager/lib/session-create/worker-observability.js +101 -9
  361. package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
  362. package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
  363. package/template/coding-task-manager/lib/session-empty.js +13 -10
  364. package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
  365. package/template/coding-task-manager/lib/session-host-manager.js +212 -206
  366. package/template/coding-task-manager/lib/session-jobs.js +20 -10
  367. package/template/coding-task-manager/lib/session-lifecycle.js +28 -4
  368. package/template/coding-task-manager/lib/session-model-action-preconditions.js +15 -2
  369. package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
  370. package/template/coding-task-manager/lib/session-park.js +738 -0
  371. package/template/coding-task-manager/lib/session-path-grant.js +13 -4
  372. package/template/coding-task-manager/lib/session-resource-sampler.js +19 -9
  373. package/template/coding-task-manager/lib/session-standup.js +67 -4
  374. package/template/coding-task-manager/lib/session-status-ledger.js +147 -6
  375. package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
  376. package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
  377. package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
  378. package/template/coding-task-manager/lib/session-transport.js +17 -0
  379. package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
  380. package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
  381. package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
  382. package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
  383. package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
  384. package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
  385. package/template/coding-task-manager/lib/startup-pointer-write.js +57 -0
  386. package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
  387. package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
  388. package/template/coding-task-manager/lib/state-sync/painted-frame-field.js +11 -0
  389. package/template/coding-task-manager/lib/storage/coding-session-model-store.js +25 -23
  390. package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
  391. package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
  392. package/template/coding-task-manager/lib/submission-ack.js +90 -2
  393. package/template/coding-task-manager/lib/surviving-owner-bootstrap.js +7 -2
  394. package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
  395. package/template/coding-task-manager/lib/systemd-scope.js +115 -0
  396. package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
  397. package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
  398. package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
  399. package/template/coding-task-manager/lib/terminal-draft-http-status.js +25 -0
  400. package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
  401. package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
  402. package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
  403. package/template/coding-task-manager/lib/transcript-archiver.js +229 -229
  404. package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
  405. package/template/coding-task-manager/lib/transcript-frame-cache.js +20 -5
  406. package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
  407. package/template/coding-task-manager/lib/transcript-link.js +77 -0
  408. package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
  409. package/template/coding-task-manager/lib/transcript-source.js +44 -7
  410. package/template/coding-task-manager/lib/transcript-store.js +49 -0
  411. package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
  412. package/template/coding-task-manager/lib/typing-interaction-trace.js +198 -3
  413. package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
  414. package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
  415. package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
  416. package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
  417. package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
  418. package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
  419. package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
  420. package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
  421. package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
  422. package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
  423. package/template/coding-task-manager/lib/visible-revision-watchdog.js +8 -12
  424. package/template/coding-task-manager/lib/wake-skip-reasons.js +47 -0
  425. package/template/coding-task-manager/lib/walle/turn.js +1 -1
  426. package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
  427. package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
  428. package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
  429. package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
  430. package/template/coding-task-manager/lib/walle-row-history.js +495 -0
  431. package/template/coding-task-manager/lib/walle-supervisor.js +130 -27
  432. package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
  433. package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
  434. package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
  435. package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
  436. package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
  437. package/template/coding-task-manager/lib/ws/misc.js +1 -1
  438. package/template/coding-task-manager/lib/ws/state-sync.js +125 -6
  439. package/template/coding-task-manager/lib/ws/terminal-attach.js +123 -1
  440. package/template/coding-task-manager/lib/ws-router.js +68 -1
  441. package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
  442. package/template/coding-task-manager/oauth-proxy.js +211 -170
  443. package/template/coding-task-manager/package-lock.json +34 -94
  444. package/template/coding-task-manager/package.json +7 -3
  445. package/template/coding-task-manager/protocol/message-table.json +10 -0
  446. package/template/coding-task-manager/protocol/messages.js +10 -0
  447. package/template/coding-task-manager/protocol/ws-schema.json +20 -0
  448. package/template/coding-task-manager/protocol/ws-schema.md +2 -0
  449. package/template/coding-task-manager/providers/codex-mcp-extract.js +121 -19
  450. package/template/coding-task-manager/providers/codex-mcp.js +14 -5
  451. package/template/coding-task-manager/public/css/app.css +449 -1
  452. package/template/coding-task-manager/public/css/reviews.css +4 -0
  453. package/template/coding-task-manager/public/css/walle-session.css +4 -0
  454. package/template/coding-task-manager/public/index.html +766 -465
  455. package/template/coding-task-manager/public/js/agent-command.js +86 -0
  456. package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
  457. package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
  458. package/template/coding-task-manager/public/js/app/machines-page.js +2572 -0
  459. package/template/coding-task-manager/public/js/app/models-tab.js +658 -73
  460. package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
  461. package/template/coding-task-manager/public/js/app/worktrees-panel.js +191 -7
  462. package/template/coding-task-manager/public/js/background-work.js +203 -28
  463. package/template/coding-task-manager/public/js/coding-session-model-presentation.js +181 -13
  464. package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
  465. package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
  466. package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
  467. package/template/coding-task-manager/public/js/core/session-commands.js +847 -5
  468. package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
  469. package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
  470. package/template/coding-task-manager/public/js/document-review-links.js +9 -1
  471. package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
  472. package/template/coding-task-manager/public/js/history-app-seam.js +48 -4
  473. package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
  474. package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
  475. package/template/coding-task-manager/public/js/history-scroller.js +187 -9
  476. package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
  477. package/template/coding-task-manager/public/js/machine-pool-shared.js +991 -0
  478. package/template/coding-task-manager/public/js/message-renderer.js +4 -3
  479. package/template/coding-task-manager/public/js/model-picker.js +3 -1
  480. package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
  481. package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
  482. package/template/coding-task-manager/public/js/pasted-content.js +236 -0
  483. package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
  484. package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
  485. package/template/coding-task-manager/public/js/private-state-scope.js +31 -3
  486. package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -8
  487. package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
  488. package/template/coding-task-manager/public/js/prompts.js +11 -10
  489. package/template/coding-task-manager/public/js/protocol.js +10 -0
  490. package/template/coding-task-manager/public/js/queue-panel-submission-reconcile.js +174 -1
  491. package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
  492. package/template/coding-task-manager/public/js/reviews.js +7 -3
  493. package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
  494. package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
  495. package/template/coding-task-manager/public/js/row-join.js +4 -2
  496. package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
  497. package/template/coding-task-manager/public/js/session-search-utils.js +64 -21
  498. package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
  499. package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
  500. package/template/coding-task-manager/public/js/state-sync-client.js +14 -1
  501. package/template/coding-task-manager/public/js/stream-view.js +6 -5
  502. package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
  503. package/template/coding-task-manager/public/js/terminal/runtime-02.js +16 -7
  504. package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
  505. package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
  506. package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
  507. package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
  508. package/template/coding-task-manager/public/js/terminal/runtime-12.js +60 -3
  509. package/template/coding-task-manager/public/js/terminal/runtime-16.js +16 -12
  510. package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
  511. package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
  512. package/template/coding-task-manager/public/js/terminal/runtime-20.js +211 -74
  513. package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
  514. package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
  515. package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
  516. package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -1
  517. package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
  518. package/template/coding-task-manager/public/js/terminal-wheel.js +62 -5
  519. package/template/coding-task-manager/public/js/walle/chat-conversation.js +15 -7
  520. package/template/coding-task-manager/public/js/walle-session.js +30 -7
  521. package/template/coding-task-manager/public/js/walle.js +6 -0
  522. package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
  523. package/template/coding-task-manager/public/m/app.css +366 -8
  524. package/template/coding-task-manager/public/m/app.js +1006 -74
  525. package/template/coding-task-manager/public/m/index.html +55 -1
  526. package/template/coding-task-manager/public/m/machines.js +2147 -0
  527. package/template/coding-task-manager/public/m/pool-failover.js +391 -0
  528. package/template/coding-task-manager/public/m/private-api.js +31 -1
  529. package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
  530. package/template/coding-task-manager/public/m/sw.js +5 -0
  531. package/template/coding-task-manager/public/usage.html +1 -0
  532. package/template/coding-task-manager/queue-engine.js +13 -0
  533. package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
  534. package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
  535. package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
  536. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
  537. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
  538. package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
  539. package/template/coding-task-manager/server/approvals.js +5 -6
  540. package/template/coding-task-manager/server/boot.js +136 -17
  541. package/template/coding-task-manager/server.js +2819 -11885
  542. package/template/coding-task-manager/session-integrity.js +71 -13
  543. package/template/coding-task-manager/workers/db-owner-worker.js +72 -9
  544. package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
  545. package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
  546. package/template/coding-task-manager/workers/read-pool-worker.js +93 -12
  547. package/template/coding-task-manager/workers/session-host-pool-process.js +24 -10
  548. package/template/coding-task-manager/workers/session-host-process.js +19 -8
  549. package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
  550. package/template/coding-task-manager/workers/watch-worker.js +105 -0
  551. package/template/coding-task-manager/workers/worktree-worker.js +202 -33
  552. package/template/ctm-relay/lib/protocol.js +14 -1
  553. package/template/package-lock.json +2 -2
  554. package/template/package.json +1 -1
  555. package/template/scripts/conversation-storage-v2-migration.js +78 -11
  556. package/template/shared/backup-retention.js +82 -0
  557. package/template/shared/conversation-admission.js +2 -0
  558. package/template/shared/conversation-provenance.js +3 -7
  559. package/template/shared/conversation-storage-v2-contract.js +47 -6
  560. package/template/shared/fixtures/worker-status-payloads.json +392 -0
  561. package/template/shared/git-remote-key.js +83 -0
  562. package/template/shared/host-identity.js +98 -2
  563. package/template/shared/linked-worktree.js +51 -0
  564. package/template/shared/macos-fda-target.js +57 -0
  565. package/template/shared/orphan-parents.js +55 -0
  566. package/template/shared/owner-write-safety.js +135 -0
  567. package/template/shared/public-runtime.js +13 -5
  568. package/template/shared/release-schema.json +3 -2
  569. package/template/shared/report-citations.js +14 -0
  570. package/template/shared/sqlite-write-lock.js +361 -223
  571. package/template/shared/storage/contract.js +38 -3
  572. package/template/wall-e/adapters/imessage.js +12 -0
  573. package/template/wall-e/agent.js +92 -4
  574. package/template/wall-e/api-walle.js +26 -1
  575. package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
  576. package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
  577. package/template/wall-e/bin/walle-mcp-stdio.js +14 -8
  578. package/template/wall-e/brain/brain-join.js +859 -0
  579. package/template/wall-e/brain/brain-sync-membership.js +20 -0
  580. package/template/wall-e/brain/brain-sync-store.js +131 -77
  581. package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
  582. package/template/wall-e/brain/brain-sync-v2.js +578 -0
  583. package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
  584. package/template/wall-e/brain/deterministic-id.js +51 -0
  585. package/template/wall-e/brain/helper-rules-schema.js +129 -0
  586. package/template/wall-e/brain/memories.js +2 -2
  587. package/template/wall-e/brain/migrations.js +91 -28
  588. package/template/wall-e/brain/model-deployment-facts.js +31 -1
  589. package/template/wall-e/brain/model-identity-migration.js +1 -1
  590. package/template/wall-e/brain/owner-call-whitelist.js +39 -7
  591. package/template/wall-e/brain/schema-ensures.js +22 -0
  592. package/template/wall-e/brain/schema.js +45 -85
  593. package/template/wall-e/brain.js +172 -36
  594. package/template/wall-e/chat.js +3 -3
  595. package/template/wall-e/coding/agent-shell-env.js +7 -2
  596. package/template/wall-e/coding/journal-dispatcher.js +51 -0
  597. package/template/wall-e/coding/prompt-bundle.js +66 -21
  598. package/template/wall-e/coding/session-journal.js +28 -40
  599. package/template/wall-e/coding-orchestrator.js +23 -26
  600. package/template/wall-e/config/main-loop-exemptions.json +2 -2
  601. package/template/wall-e/http/admin-api.js +37 -0
  602. package/template/wall-e/http/auth.js +18 -1
  603. package/template/wall-e/http/blog-views-api.js +318 -0
  604. package/template/wall-e/http/gws-api.js +4 -0
  605. package/template/wall-e/http/helper-rules-api.js +327 -0
  606. package/template/wall-e/http/model-admin.js +8 -1
  607. package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
  608. package/template/wall-e/http/model-proxy-providers.js +177 -2
  609. package/template/wall-e/http/model-route-health.js +157 -0
  610. package/template/wall-e/http/sync-api.js +278 -464
  611. package/template/wall-e/http/telemetry-api.js +12 -0
  612. package/template/wall-e/jobs/job-runner.js +28 -1
  613. package/template/wall-e/lib/blog-view-policy.js +88 -0
  614. package/template/wall-e/lib/blog-view-store.js +169 -0
  615. package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
  616. package/template/wall-e/lib/client-config-lock.js +2 -1
  617. package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
  618. package/template/wall-e/lib/ctm-data-dir.js +26 -0
  619. package/template/wall-e/lib/derivation-home.js +147 -0
  620. package/template/wall-e/lib/error-kinds.js +10 -1
  621. package/template/wall-e/lib/feature-manifest.js +1 -1
  622. package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
  623. package/template/wall-e/lib/helper-rules/evaluate.js +398 -0
  624. package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
  625. package/template/wall-e/lib/helper-rules/grade.js +320 -0
  626. package/template/wall-e/lib/helper-rules/label.js +247 -0
  627. package/template/wall-e/lib/helper-rules/lead-call-hook.js +555 -0
  628. package/template/wall-e/lib/helper-rules/store.js +669 -0
  629. package/template/wall-e/lib/landing-mcp-tools.js +170 -0
  630. package/template/wall-e/lib/mcp-client-config.js +133 -14
  631. package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
  632. package/template/wall-e/lib/mcp-integration.js +63 -19
  633. package/template/wall-e/lib/parent-death.js +7 -1
  634. package/template/wall-e/lib/runtime-worker-pool.js +1 -0
  635. package/template/wall-e/lib/scheduler-worker-jobs.js +12 -4
  636. package/template/wall-e/lib/telemetry-db-schema.js +37 -0
  637. package/template/wall-e/lib/telemetry-process-client.js +76 -1
  638. package/template/wall-e/llm/default-fallback.js +4 -0
  639. package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
  640. package/template/wall-e/llm/delegate-vendor-default.js +12 -5
  641. package/template/wall-e/llm/model-catalog.js +13 -4
  642. package/template/wall-e/llm/model-roles.js +7 -1
  643. package/template/wall-e/llm/native-delegate-selection.js +56 -8
  644. package/template/wall-e/llm/portkey-http.js +150 -0
  645. package/template/wall-e/llm/portkey-sync.js +15 -145
  646. package/template/wall-e/llm/worker-delegate-args.js +72 -7
  647. package/template/wall-e/llm/worker-mcp-routing.js +117 -7
  648. package/template/wall-e/llm/worker-route.js +43 -1
  649. package/template/wall-e/loops/brain-custom-writes.js +64 -0
  650. package/template/wall-e/loops/ingest.js +17 -1
  651. package/template/wall-e/loops/think.js +19 -4
  652. package/template/wall-e/mcp-contract.js +222 -6
  653. package/template/wall-e/mcp-protocol-contract.js +77 -2
  654. package/template/wall-e/mcp-server.js +141 -31
  655. package/template/wall-e/mcp-worker-schemas.js +25 -7
  656. package/template/wall-e/memory/ctm-context-client.js +110 -5
  657. package/template/wall-e/memory/ctm-session-context.js +9 -3
  658. package/template/wall-e/memory/hub-bridge-client.js +388 -0
  659. package/template/wall-e/memory/replica-origin.js +56 -0
  660. package/template/wall-e/memory/session-pool.js +135 -0
  661. package/template/wall-e/runtime/live-capabilities.js +8 -3
  662. package/template/wall-e/server.js +4 -2
  663. package/template/wall-e/shared/release-schema.json +3 -2
  664. package/template/wall-e/shared/sqlite-file-set.js +39 -0
  665. package/template/wall-e/shared/sqlite-write-lock.js +361 -223
  666. package/template/wall-e/shared/storage/contract.js +38 -3
  667. package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
  668. package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +13 -1
  669. package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +11 -6
  670. package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +13 -8
  671. package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
  672. package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
  673. package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
  674. package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
  675. package/template/wall-e/tools/chrome-automation.js +6 -0
  676. package/template/wall-e/tools/local-tools.js +6 -4
  677. package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
  678. package/template/wall-e/workers/brain-owner-worker.js +27 -4
  679. package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
  680. package/template/wall-e/workers/mcp-gateway-process.js +5 -5
  681. package/template/wall-e/workers/telemetry-worker.js +8 -0
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ // WP-0/WP-1 (docs/lead-switch-never-prompted-session-2026-10-30.html §5 D-1..D-4, §6): ONE history
4
+ // mode per transition — 'none' (this source lifetime has nothing to carry) or 'present' (today's
5
+ // behaviour) — decided ONCE before the switch claims its transition, carried on both recipes, and
6
+ // read back by every gate that used to re-derive (or silently assume) the answer.
7
+ //
8
+ // D-2, the rule that keeps this safe: 'none' is returned ONLY for a DEFINITE absence. The oracle is
9
+ // the same off-thread resume ladder park already consults (lib/park-fresh-relaunch.js
10
+ // `parkFindsNothingToResume`); a false answer, a thrown error, a timeout or an agent with no ladder
11
+ // all mean 'present'. "An unreadable store is not evidence that the conversation is gone"
12
+ // (superset-sh/superset#7144, adopted in §3 P-3), so a flaky ladder can only cost a refusal, never a
13
+ // lost conversation. A recipe written before this change carries no `historyMode` key and reads as
14
+ // 'present' — byte-for-byte today's path.
15
+
16
+ const { extractResumeTarget } = require('./session-history');
17
+ const { parkFindsNothingToResume } = require('./park-fresh-relaunch');
18
+
19
+ const HISTORY_MODES = Object.freeze(['none', 'present']);
20
+ // WP-2 D-6 (§5/§6): the only two spellings a source recipe's `modelOrigin` may carry.
21
+ const MODEL_ORIGINS = Object.freeze(['observed', 'cli-default']);
22
+
23
+ /**
24
+ * Resolve the SOURCE lifetime's history mode. NEVER throws (D-2): any error, rejection or timeout is
25
+ * 'present'.
26
+ *
27
+ * @param {object} input
28
+ * @param {'claude'|'codex'|string} input.agentType
29
+ * @param {string} input.ctmSessionId
30
+ * @param {string} input.jsonlPath claude: the transcript path park would stat; codex: the rollout path or ''
31
+ * @param {string} [input.resumeId] the source provider thread id
32
+ * @param {boolean} [input.resumeEvidence] true when park's own inputs already found a transcript/rollout ON DISK
33
+ * @param {(query: object) => Promise<{ rung?: string }>} input.resolveRung resolveResumeRungOffThread bound to dbPath
34
+ * @returns {Promise<'none'|'present'>}
35
+ */
36
+ async function resolveSourceHistoryMode({ agentType, ctmSessionId, jsonlPath, resumeId, resumeEvidence = false, resolveRung } = {}) {
37
+ try {
38
+ // A transcript/rollout file already on disk is proof there IS something to resume, so the ladder
39
+ // is never consulted for it (park short-circuits the same way, lib/park-fresh-relaunch.js).
40
+ if (resumeEvidence === true) return 'present';
41
+ const nothingToResume = await parkFindsNothingToResume({ agentType, ctmSessionId, jsonlPath, resumeId, resolveRung });
42
+ return nothingToResume === true ? 'none' : 'present';
43
+ } catch {
44
+ // HANDLE: D-2 — an unreadable store, a rejected ladder or a timeout is never evidence of absence,
45
+ // so the refusal side of every gate keeps today's behaviour.
46
+ return 'present';
47
+ }
48
+ }
49
+
50
+ /** Recipe read with the D-2 default: a missing or unknown key is 'present'. */
51
+ function recipeHistoryMode(recipe) {
52
+ return recipe?.historyMode === 'none' ? 'none' : 'present';
53
+ }
54
+
55
+ /**
56
+ * WP-2 D-6 (§5/§6): WHERE the source lifetime's model came from — recorded, never guessed.
57
+ *
58
+ * 'cli-default' means this source never named a model of its own: the mode is 'none' (nothing was
59
+ * ever prompted) AND `cliDefaultModel` (captured by the runtime's `getSessionInfo`) proved an empty
60
+ * `session.model_id`, no `--model`/`-m`/`--model=` in the captured launch argv and no
61
+ * `session_lead_model` pin row. Rolling such a source back must relaunch the ORIGINAL argv and pass
62
+ * NO one-shot model override at all, so the CLI's own default applies by construction (D-6 rejected
63
+ * both substituting `cli_default` as `--model` and re-reading the CLI's config file).
64
+ *
65
+ * Everything else is 'observed' — today's meaning: the model was read from the session/argv, and a
66
+ * rollback passes it as the one-shot override exactly as before. A recipe written before this change
67
+ * carries no `cliDefaultModel`, so it reads 'observed'.
68
+ */
69
+ function sourceModelOrigin(source) {
70
+ return recipeHistoryMode(source) === 'none' && source?.cliDefaultModel === true ? 'cli-default' : 'observed';
71
+ }
72
+
73
+ /** The value of a Claude argv's `--session-id <id>` / `--session-id=<id>`, or '' when absent. */
74
+ function claudeSessionIdArg(args) {
75
+ const list = Array.isArray(args) ? args.map(String) : [];
76
+ for (let i = 0; i < list.length; i += 1) {
77
+ if (list[i] === '--session-id') return String(list[i + 1] || '');
78
+ if (list[i].startsWith('--session-id=')) return list[i].slice('--session-id='.length);
79
+ }
80
+ return '';
81
+ }
82
+
83
+ /**
84
+ * The single thread clause shared by the pre-park planner check (D-4) and authorizeLiveTargetRestore
85
+ * (D-3) — one definition, so the two gates can never drift apart (§7).
86
+ *
87
+ * For 'present' it is EXACTLY the historical conjunct: the plan must resume the target recipe's own
88
+ * provider thread. For 'none' the plan must carry no resume selector at all, and a Claude plan's own
89
+ * `--session-id` must name the target recipe's thread: that argv is what the fresh process is given,
90
+ * so it is the thread its canonical owner will report.
91
+ *
92
+ * @returns {boolean}
93
+ */
94
+ function targetThreadClause({ source, target, launchPlan } = {}) {
95
+ const planThread = String(launchPlan?.resume?.sessionId || '');
96
+ const targetThread = String(target?.providerThreadId || '');
97
+ if (recipeHistoryMode(target) === 'present') return targetThread.length > 0 && planThread === targetThread;
98
+ // A 'none' target recipe is only meaningful with a 'none' SOURCE: the mode is one fact per
99
+ // transition, recorded twice.
100
+ if (recipeHistoryMode(source) !== 'none') return false;
101
+ if (planThread !== '') return false;
102
+ if (extractResumeTarget(launchPlan?.agentType, launchPlan?.args || [])) return false;
103
+ if (launchPlan?.agentType === 'claude') return targetThread.length > 0 && claudeSessionIdArg(launchPlan.args) === targetThread;
104
+ // codex: the new thread id is unknown until the thread links, so the owner check after launch
105
+ // binds it instead.
106
+ return true;
107
+ }
108
+
109
+ module.exports = { HISTORY_MODES, MODEL_ORIGINS, resolveSourceHistoryMode, recipeHistoryMode,
110
+ sourceModelOrigin, claudeSessionIdArg, targetThreadClause };
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+ // The CLI wire a lead agent speaks to CTM's model proxy. OpenCode leads and OpenCode's routed
3
+ // workers both use the Anthropic Messages face, so route servability is asked of 'claude'.
4
+ // This is the ONE rule: public/js/session-model-picker.js mirrors it as `leadWireAgent` for the
5
+ // Lead AND Delegate tabs, and tests pin the two bodies equal (docs/opencode-model-selection-round-2-shared-route-logic-2026-10-30.html §5 R-1, §6.1, §7).
6
+ function leadWireAgent(agent) { return agent === 'opencode' ? 'claude' : agent; }
7
+ module.exports = { leadWireAgent };
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const { createMediaJournalControlReader } = require('./media-journal-control-reader');
5
+
6
+ function unavailable(cause) {
7
+ return Object.assign(new Error('Pending image cancellation recovery is unavailable', { cause }), {
8
+ code: 'CTM_MEDIA_JOURNAL_UNAVAILABLE',
9
+ });
10
+ }
11
+
12
+ // One recovery scope per logical DB handle and journal directory. No new SQL owner: the caller
13
+ // supplies the same worker projector used by the write-behind store. Neither journal nor cursor
14
+ // is advanced, because unrelated content must remain available to its ordinary replay owner.
15
+ function createLegacyDraftCancellationRecovery({ getDirectory, getContext, projectEntry }) {
16
+ for (const callback of [getDirectory, getContext, projectEntry]) {
17
+ if (typeof callback !== 'function') throw new TypeError('Cancellation recovery requires callbacks');
18
+ }
19
+ let scope = null;
20
+ let operation = null;
21
+ let retired = false;
22
+ let closing = null;
23
+
24
+ function binding() {
25
+ const context = getContext();
26
+ const directory = getDirectory();
27
+ if (!context || !directory) throw new Error('Cancellation recovery has no open storage context');
28
+ return { context, directory: path.resolve(directory) };
29
+ }
30
+
31
+ function assertCurrent(owner) {
32
+ if (retired || owner !== scope) throw new Error('Cancellation recovery scope is retired');
33
+ const current = binding();
34
+ if (current.context !== owner.context || current.directory !== owner.directory) {
35
+ throw new Error('Cancellation recovery storage context changed');
36
+ }
37
+ }
38
+
39
+ async function closeReader(owner) {
40
+ if (!owner?.reader) return;
41
+ await owner.reader.close();
42
+ owner.reader = null; // Retain an unconfirmed resource owner on failure, not just its descriptor.
43
+ }
44
+
45
+ async function recover(current) {
46
+ await closeReader(scope);
47
+ const owner = scope = { ...current, reader: null, ready: false };
48
+ assertCurrent(owner);
49
+ const reader = owner.reader = createMediaJournalControlReader({
50
+ directory: owner.directory, assertCurrent: () => assertCurrent(owner),
51
+ });
52
+ let records;
53
+ let failed = false;
54
+ let failure;
55
+ try { records = await reader.read(); }
56
+ catch (error) { failed = true; failure = error; }
57
+ try { await closeReader(owner); }
58
+ catch (error) {
59
+ throw failed
60
+ ? new AggregateError([failure, error], 'Cancellation recovery and reader cleanup failed', { cause: failure })
61
+ : error;
62
+ }
63
+ if (failed) throw failure;
64
+ // Close every read handle BEFORE the first SQL projection. A partial projection remains
65
+ // idempotently retryable through applyMediaJournalEntry; it is never a completed recovery.
66
+ for (const { entry } of records) {
67
+ assertCurrent(owner);
68
+ const result = await projectEntry(entry, { urgent: true });
69
+ assertCurrent(owner);
70
+ if (typeof result?.cancelled !== 'boolean' || typeof result?.sessionEnded !== 'boolean'
71
+ || result.cancelled === result.sessionEnded) {
72
+ throw new TypeError('Cancellation projection did not confirm a durable cancellation or ended session');
73
+ }
74
+ }
75
+ assertCurrent(owner);
76
+ owner.ready = true;
77
+ }
78
+
79
+ function prepare() {
80
+ try {
81
+ if (retired) throw new Error('Cancellation recovery is closed');
82
+ const current = binding();
83
+ if (operation) return operation;
84
+ if (scope?.ready && scope.context === current.context && scope.directory === current.directory) {
85
+ return Promise.resolve();
86
+ }
87
+ operation = recover(current).catch(error => { throw unavailable(error); })
88
+ .finally(() => { operation = null; });
89
+ return operation;
90
+ } catch (error) {
91
+ return Promise.reject(unavailable(error));
92
+ }
93
+ }
94
+
95
+ function close() {
96
+ retired = true;
97
+ if (closing) return closing;
98
+ closing = (async () => {
99
+ // Already delivered operational errors are not shutdown failures. Unconfirmed handles
100
+ // remain owned and closeReader must still report them. No race against a timeout here.
101
+ if (operation) await operation.catch(() => { /* expected: admitted caller receives the failure */ });
102
+ await closeReader(scope);
103
+ scope = null;
104
+ })().finally(() => { closing = null; });
105
+ return closing;
106
+ }
107
+
108
+ return { prepare, close };
109
+ }
110
+
111
+ module.exports = { createLegacyDraftCancellationRecovery };
@@ -49,7 +49,13 @@ function readJsonFileSafe(filePath) {
49
49
  // that prompt entirely. Only a scope the USER wrote (top-level or `projects[cwd]` inside their
50
50
  // own ~/.claude.json) may ever supply a command here.
51
51
  function resolveCoreClaudeMcpServers(names, { homeDir = '', cwd = '' } = {}) {
52
- const claudeJson = homeDir ? readJsonFileSafe(path.join(homeDir, '.claude.json')) : null;
52
+ return selectClaudeMcpServers(homeDir ? readJsonFileSafe(path.join(homeDir, '.claude.json')) : null, names, { cwd });
53
+ }
54
+
55
+ // The pure half of resolveCoreClaudeMcpServers, shared with the async DeepSeek Harness reader
56
+ // (lib/session-create/dsh-session.js): the same two USER scopes, project scope winning. `names`
57
+ // null selects every declared server (the 'full' profile, which dsh must materialize itself).
58
+ function selectClaudeMcpServers(claudeJson, names, { cwd = '' } = {}) {
53
59
  const userScope = claudeJson && typeof claudeJson.mcpServers === 'object' && claudeJson.mcpServers ? claudeJson.mcpServers : {};
54
60
  const projectEntry = claudeJson && claudeJson.projects && typeof claudeJson.projects === 'object' && cwd
55
61
  ? claudeJson.projects[cwd]
@@ -57,7 +63,7 @@ function resolveCoreClaudeMcpServers(names, { homeDir = '', cwd = '' } = {}) {
57
63
  const projectScope = projectEntry && typeof projectEntry.mcpServers === 'object' && projectEntry.mcpServers ? projectEntry.mcpServers : {};
58
64
 
59
65
  const servers = {};
60
- for (const name of names) {
66
+ for (const name of names || [...new Set([...Object.keys(userScope), ...Object.keys(projectScope)])]) {
61
67
  const def = projectScope[name] || userScope[name];
62
68
  if (def) servers[name] = def;
63
69
  }
@@ -200,6 +206,7 @@ module.exports = {
200
206
  codexMcpDisableArgs,
201
207
  resolveMcpProfile,
202
208
  normalizeMcpProfile,
209
+ selectClaudeMcpServers,
203
210
  MCP_PROFILES,
204
211
  MCP_PROFILE_FULL,
205
212
  MCP_PROFILE_NONE,
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ // WP-2 (live-defer-wake-adopted-host-death-2026-10-28.html §5 R-3/R-4/R-6/R-8): a LIVE defer
4
+ // (the process died under an open tab) used to announce nothing to the attached clients -- only
5
+ // `broadcastSessionList(true)`. The tab therefore kept its "current route proof" for the same
6
+ // socket generation, so selecting it never sent a `terminal-bootstrap` and the server's deferred
7
+ // wake never ran. The idle-park path already does it right (server.js park loop: iterate the
8
+ // session's clients, readyState 1, sendDeferredRestoreStatus). These are the PURE helpers for
9
+ // that announcement -- no server state, no requires, so both the adopted exit handler and the
10
+ // session-create exit handler can share one implementation.
11
+
12
+ // Which defer this exit is. WP-3a's dead-host path stamps `hostClosed: true` on the exit event it
13
+ // synthesizes (lib/adopted-host-redial.js `_emitExitOnce`), so the evidence is the event itself --
14
+ // never a process-liveness probe reconstructed at the defer site.
15
+ function liveDeferSource(exitEvent) {
16
+ return exitEvent?.hostClosed === true ? 'host-death' : 'crash-defer';
17
+ }
18
+
19
+ // Announce the live defer to every client still attached. Returns the number of frames the caller's
20
+ // `send` accepted; a client that has gone away (readyState !== 1) is skipped, and a `send` that
21
+ // throws for one client must never stop the loop for the rest.
22
+ function announceLiveDefer({ clients, send } = {}) {
23
+ const list = clients || [];
24
+ let sent = 0;
25
+ for (const ws of list) {
26
+ if (ws?.readyState !== 1) continue;
27
+ try {
28
+ send(ws);
29
+ sent += 1;
30
+ } catch { /* expected: client disconnected during lifecycle broadcast */ }
31
+ }
32
+ return sent;
33
+ }
34
+
35
+ // WP-3b (R-8): the evidence a host death carries on its exit event, normalized for the diagnostic
36
+ // row. Booleans are strict, so an absent/undefined field reads as `false` -- never truthy garbage.
37
+ function hostDeathEvidence(exitEvent) {
38
+ return {
39
+ reason: String(exitEvent?.reason || ''),
40
+ hostRetired: exitEvent?.hostRetired === true,
41
+ hostPidAliveAtDeclare: exitEvent?.hostPidAliveAtDeclare === true,
42
+ };
43
+ }
44
+
45
+ module.exports = { liveDeferSource, announceLiveDefer, hostDeathEvidence };
@@ -187,6 +187,7 @@ function armSessionLoginTripwire({ proc, env, onBlocked } = {}) {
187
187
  module.exports = {
188
188
  LOGIN_PATTERNS,
189
189
  WINDOW_CHARS,
190
+ stripAnsi,
190
191
  createLoginTripwire,
191
192
  attachToPty,
192
193
  armSessionLoginTripwire,
@@ -0,0 +1,238 @@
1
+ 'use strict';
2
+
3
+ // WP-3 (docs/machine-pool-picker-pairing-dashboard-2026-10-24.html §6.3, D-6/D-9, §9 S-15/S-16/S-23):
4
+ // the pairing code — the BOX side.
5
+ //
6
+ // A machine that wants to join a pool shows an 8-character code. The joining member posts the code
7
+ // plus the pool token to the box's PRE-AUTH `POST /api/machine-pairing/join`; the box verifies the
8
+ // code, burns it, and adopts the token. Rules that shape this module:
9
+ //
10
+ // * §6.3 verbatim — alphabet, length, TTL, the 3-live-offer ceiling and the 5-wrong-redeem burn.
11
+ // * The code is a BEARER secret for one redemption. It is NEVER stored and NEVER logged: the only
12
+ // thing that reaches the database is `sha256(normalizeCode(code))` hex (D-6, §11 anti-goals).
13
+ // * `redeem` compares hashes with crypto.timingSafeEqual over EQUAL-LENGTH buffers — the digest is
14
+ // fixed-width, so a length mismatch is a malformed row, never a timing oracle.
15
+ // * Expired and already-used offers answer the SAME `pairing_code_invalid` code: a wrong code, a
16
+ // stale offer and a burned one must be indistinguishable to the caller, or the endpoint becomes
17
+ // an oracle for "was there ever an offer here".
18
+ //
19
+ // LEAF module: node built-ins only. Everything is injectable (`now`, `randomBytes`, `db`) so the
20
+ // unit test never touches the real clock, the real CSPRNG or a real database (clock-free rule).
21
+
22
+ const crypto = require('node:crypto');
23
+
24
+ const CODE_ALPHABET = 'BCDFGHJKLMNPQRSTVWXZ'; // RFC 8628 §6.1 — no vowels, no 0/1/I/O look-alikes
25
+ const CODE_LENGTH = 8; // shown (and typed) as XXXX-XXXX
26
+ const OFFER_TTL_MS = 600_000;
27
+ const MAX_LIVE_OFFERS = 3;
28
+ const MAX_FAILED_REDEEMS = 5;
29
+
30
+ // The container the box prints/paints once: `ctmpair1:` + base64url(JSON).
31
+ const PAIRING_STRING_PREFIX = 'ctmpair1:';
32
+
33
+ // |CODE_ALPHABET| = 20 and 256 is NOT a multiple of 20, so `byte % 20` would favour the first four
34
+ // letters roughly 13% of the time. 240 = floor(256/20)*20 is the largest multiple of 20 that fits in
35
+ // a byte: every byte >= 240 is discarded and re-drawn (RFC 8628 §6.1 rejection sampling).
36
+ const REJECT_AT = Math.floor(256 / CODE_ALPHABET.length) * CODE_ALPHABET.length; // 240
37
+ // A batch per draw, and a hard ceiling on batches so a broken/scripted `randomBytes` cannot spin
38
+ // this loop forever — 32 batches of 16 bytes is a 1-in-10^22 tail, never a real event.
39
+ const DRAW_BATCH = CODE_LENGTH * 2;
40
+ const MAX_DRAW_BATCHES = 32;
41
+
42
+ /**
43
+ * §6.3 verbatim: uppercase, then drop every character outside the alphabet. Hyphens and spaces are
44
+ * therefore formatting, not content — `wdjb-mjht`, `WDJB MJHT` and `WDJBMJHT` are one code.
45
+ */
46
+ function normalizeCode(value) {
47
+ return String(value || '').toUpperCase().replace(/[^BCDFGHJKLMNPQRSTVWXZ]/g, '');
48
+ }
49
+
50
+ /** The display form the offer response carries: XXXX-XXXX (empty in => empty out). */
51
+ function formatCode(value) {
52
+ const code = normalizeCode(value);
53
+ if (code.length !== CODE_LENGTH) return code;
54
+ return `${code.slice(0, 4)}-${code.slice(4)}`;
55
+ }
56
+
57
+ /** D-6: the ONLY representation of a code that is ever persisted. */
58
+ function hashCode(value) {
59
+ return crypto.createHash('sha256').update(normalizeCode(value), 'utf8').digest('hex');
60
+ }
61
+
62
+ /**
63
+ * Constant-time hash compare over equal-length buffers. Two sha256 digests are always 64 chars, so
64
+ * a mismatch in length means a malformed stored row — false, never a throw and never a compare.
65
+ */
66
+ function codeHashEquals(left, right) {
67
+ const a = Buffer.from(String(left == null ? '' : left), 'utf8');
68
+ const b = Buffer.from(String(right == null ? '' : right), 'utf8');
69
+ if (!a.length || a.length !== b.length) return false;
70
+ return crypto.timingSafeEqual(a, b);
71
+ }
72
+
73
+ /** `XXXX-XXXX` -> a batch of random letters, rejection-sampled (no modulo bias). */
74
+ function mintCode(randomBytes) {
75
+ const out = [];
76
+ for (let batch = 0; batch < MAX_DRAW_BATCHES && out.length < CODE_LENGTH; batch += 1) {
77
+ const bytes = randomBytes(DRAW_BATCH);
78
+ for (const byte of bytes) {
79
+ if (byte >= REJECT_AT) continue; // biased tail — re-draw, never fold
80
+ out.push(CODE_ALPHABET[byte % CODE_ALPHABET.length]);
81
+ if (out.length >= CODE_LENGTH) break;
82
+ }
83
+ }
84
+ if (out.length < CODE_LENGTH) throw new Error('machine-pairing: randomBytes did not yield an unbiased code');
85
+ return out.join('');
86
+ }
87
+
88
+ /**
89
+ * §6.3: `'ctmpair1:' + base64url(JSON{v:1,i:instanceId,n:displayName,u:candidates,c:code})`.
90
+ * `c` is the DISPLAY form (XXXX-XXXX); `normalizeCode` strips the hyphen on the way back in.
91
+ */
92
+ function encodePairingString({ instanceId, displayName, urls, code } = {}) {
93
+ const payload = JSON.stringify({
94
+ v: 1,
95
+ i: String(instanceId || ''),
96
+ n: String(displayName || ''),
97
+ u: (Array.isArray(urls) ? urls : []).map((url) => String(url || '')).filter(Boolean),
98
+ c: String(code || ''),
99
+ });
100
+ return `${PAIRING_STRING_PREFIX}${Buffer.from(payload, 'utf8').toString('base64url')}`;
101
+ }
102
+
103
+ /**
104
+ * The member side of the container. Returns null for anything that is not a v1 pairing string —
105
+ * a hand-edited or truncated string is a 400 (`pairing_string_invalid`), never a throw.
106
+ */
107
+ function decodePairingString(value) {
108
+ const raw = String(value == null ? '' : value).trim();
109
+ if (!raw.startsWith(PAIRING_STRING_PREFIX)) return null;
110
+ let parsed = null;
111
+ try {
112
+ parsed = JSON.parse(Buffer.from(raw.slice(PAIRING_STRING_PREFIX.length), 'base64url').toString('utf8'));
113
+ } catch {
114
+ return null; // expected: a corrupted container is a client error, not a server fault
115
+ }
116
+ if (!parsed || typeof parsed !== 'object' || parsed.v !== 1) return null;
117
+ const code = normalizeCode(parsed.c);
118
+ if (code.length !== CODE_LENGTH) return null;
119
+ const urls = (Array.isArray(parsed.u) ? parsed.u : [])
120
+ .map((url) => String(url || '').trim().replace(/\/+$/, ''))
121
+ .filter(Boolean);
122
+ const instanceId = String(parsed.i || '').trim();
123
+ if (!instanceId && !urls.length) return null;
124
+ return { version: 1, instanceId, displayName: String(parsed.n || ''), urls, code };
125
+ }
126
+
127
+ /**
128
+ * The box's pairing store.
129
+ *
130
+ * @param {{db: object, now?: () => number, randomBytes?: (n: number) => Buffer}} deps
131
+ * `db` must expose the four DB-owner ops: listLivePairingOffers, insertPairingOffer,
132
+ * markPairingOfferRedeemed, burnLivePairingOffers.
133
+ * @returns {{createOffer: () => Promise<object>, redeem: (code: string, options?: object) => Promise<object>,
134
+ * hasLiveOffers: () => Promise<boolean>, burnAll: () => Promise<object>}}
135
+ */
136
+ function createMachinePairing({ db, now = () => Date.now(), randomBytes = (n) => crypto.randomBytes(n) } = {}) {
137
+ if (!db || typeof db.listLivePairingOffers !== 'function') {
138
+ throw new TypeError('machine-pairing: db.listLivePairingOffers is required');
139
+ }
140
+ // §6.3: in memory on purpose — a restart clearing the counter is fine (the offers themselves are
141
+ // single-use and TTL-bounded), while persisting it would put an attacker-controlled number in the
142
+ // DB. Five CONSECUTIVE failures burn everything live; one success resets it.
143
+ let failedRedeems = 0;
144
+
145
+ function _now() {
146
+ return Math.trunc(Number(now()) || 0);
147
+ }
148
+
149
+ /**
150
+ * §6.3 `POST /api/machine-pairing/offers`. At most MAX_LIVE_OFFERS unspent offers exist at any
151
+ * moment, so a walked-away browser cannot leave an unbounded set of valid codes behind.
152
+ */
153
+ async function createOffer() {
154
+ const at = _now();
155
+ const live = await db.listLivePairingOffers({ at });
156
+ if (Array.isArray(live) && live.length >= MAX_LIVE_OFFERS) {
157
+ return { ok: false, code: 'pairing_offer_limit' };
158
+ }
159
+ const code = mintCode(randomBytes);
160
+ const expiresAt = at + OFFER_TTL_MS;
161
+ await db.insertPairingOffer({ id: crypto.randomUUID(), codeHash: hashCode(code), createdAt: at, expiresAt });
162
+ return { ok: true, code: formatCode(code), expiresAt };
163
+ }
164
+
165
+ /**
166
+ * §6.3 ordering: hash-compare against the live set, then burn the one that matched. `by` is the
167
+ * redeeming machine's instance id and is the only thing recorded — never the code.
168
+ *
169
+ * SINGLE USE IS THE UPDATE, NOT THE READ (F3). The candidate was found by reading the live set, but
170
+ * that read is not a claim: two joins holding the same code would both find the row and both return
171
+ * ok from a read-then-trust redeem. `markPairingOfferRedeemed` carries the `redeemed_at IS NULL`
172
+ * predicate in its WHERE clause and reports how many rows it changed, so exactly one of the two
173
+ * callers sees `changes === 1` and the loser is told `pairing_code_invalid` — the same answer an
174
+ * already-used code gets, which is what keeps the endpoint from being an oracle. A lost claim is NOT
175
+ * a failed guess (the caller was holding a real code), so it must not count toward the burn.
176
+ */
177
+ async function redeem(code, { by = '' } = {}) {
178
+ const at = _now();
179
+ const live = await db.listLivePairingOffers({ at });
180
+ const wanted = hashCode(code);
181
+ const offer = (Array.isArray(live) ? live : []).find((row) => codeHashEquals(row && row.codeHash, wanted));
182
+ if (!offer) {
183
+ failedRedeems += 1;
184
+ if (failedRedeems >= MAX_FAILED_REDEEMS) {
185
+ failedRedeems = 0;
186
+ // §6.3 AC-3c: the 5th consecutive miss burns EVERY live offer, so an attacker who is
187
+ // brute-forcing the 20^8 space loses the offers they were guessing against.
188
+ await db.burnLivePairingOffers({ at });
189
+ }
190
+ return { ok: false, code: 'pairing_code_invalid' };
191
+ }
192
+ const id = String(offer.id || '');
193
+ const changed = Number(await db.markPairingOfferRedeemed({
194
+ id,
195
+ at,
196
+ redeemedBy: String(by || '').slice(0, 200),
197
+ })) || 0;
198
+ if (changed !== 1) return { ok: false, code: 'pairing_code_invalid' };
199
+ // Only a claimed offer is a success, and only a success resets the consecutive-miss counter.
200
+ failedRedeems = 0;
201
+ return { ok: true, offer: { id, expiresAt: Number(offer.expiresAt) || 0 } };
202
+ }
203
+
204
+ /** §6.3/D-9: is this box showing a live code right now? (the identity probe's yes/no, never a code) */
205
+ async function hasLiveOffers() {
206
+ const live = await db.listLivePairingOffers({ at: _now() });
207
+ return Array.isArray(live) && live.length > 0;
208
+ }
209
+
210
+ /**
211
+ * F4: after a successful adopt this box belongs to somebody, so every OTHER live code must die —
212
+ * otherwise a second primary holding a code minted before the join could re-adopt the box and walk
213
+ * away with the pool secret. Also clears the failure counter: the box is no longer "unpaired".
214
+ */
215
+ async function burnAll() {
216
+ failedRedeems = 0;
217
+ return db.burnLivePairingOffers({ at: _now() });
218
+ }
219
+
220
+ return { createOffer, redeem, hasLiveOffers, burnAll };
221
+ }
222
+
223
+ module.exports = {
224
+ CODE_ALPHABET,
225
+ CODE_LENGTH,
226
+ OFFER_TTL_MS,
227
+ MAX_LIVE_OFFERS,
228
+ MAX_FAILED_REDEEMS,
229
+ PAIRING_STRING_PREFIX,
230
+ normalizeCode,
231
+ formatCode,
232
+ hashCode,
233
+ codeHashEquals,
234
+ mintCode,
235
+ encodePairingString,
236
+ decodePairingString,
237
+ createMachinePairing,
238
+ };