create-walle 0.10.2 → 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 (488) hide show
  1. package/README.md +3 -1
  2. package/lib/release-schema.json +2 -2
  3. package/lib/runtime-closure-policy.json +8 -7
  4. package/package.json +1 -1
  5. package/template/coding-task-manager/api-prompts.js +45 -7
  6. package/template/coding-task-manager/bin/claude-hook.js +55 -1
  7. package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
  8. package/template/coding-task-manager/bin/land.js +2069 -0
  9. package/template/coding-task-manager/bin/memory-census.js +4 -2
  10. package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
  11. package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
  12. package/template/coding-task-manager/db.js +156 -32
  13. package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
  14. package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
  15. package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
  16. package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
  17. package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
  18. package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
  19. package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
  20. package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
  21. package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
  22. package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
  23. package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
  24. package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
  25. package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
  26. package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
  27. package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
  28. package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
  29. package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
  30. package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
  31. package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
  32. package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
  33. package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
  34. package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
  35. package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
  36. package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
  37. package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
  38. package/template/coding-task-manager/lib/agent-definitions.js +19 -0
  39. package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
  40. package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
  41. package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
  42. package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
  43. package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
  44. package/template/coding-task-manager/lib/agent-presets.js +84 -1
  45. package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
  46. package/template/coding-task-manager/lib/agent-version-service.js +74 -11
  47. package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
  48. package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
  49. package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
  50. package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
  51. package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
  52. package/template/coding-task-manager/lib/api/fleet.js +118 -0
  53. package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
  54. package/template/coding-task-manager/lib/api/ingress.js +9 -1
  55. package/template/coding-task-manager/lib/api/landing.js +403 -0
  56. package/template/coding-task-manager/lib/api/machines.js +691 -2
  57. package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
  58. package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
  59. package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
  60. package/template/coding-task-manager/lib/api/session-attach.js +623 -0
  61. package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
  62. package/template/coding-task-manager/lib/api/sessions.js +77 -51
  63. package/template/coding-task-manager/lib/api/setup-network.js +544 -16
  64. package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
  65. package/template/coding-task-manager/lib/api/setup.js +829 -10
  66. package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
  67. package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
  68. package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
  69. package/template/coding-task-manager/lib/auth-rules.js +292 -21
  70. package/template/coding-task-manager/lib/background-stop.js +369 -0
  71. package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
  72. package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
  73. package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
  74. package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
  75. package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
  76. package/template/coding-task-manager/lib/build-info.js +4 -2
  77. package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
  78. package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
  79. package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
  80. package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
  81. package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
  82. package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
  83. package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
  84. package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
  85. package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
  86. package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
  87. package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
  88. package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
  89. package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
  90. package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
  91. package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
  92. package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
  93. package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
  94. package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
  95. package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
  96. package/template/coding-task-manager/lib/conversation-sync.js +355 -0
  97. package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
  98. package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
  99. package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
  100. package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
  101. package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
  102. package/template/coding-task-manager/lib/db-domains.js +1 -0
  103. package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
  104. package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
  105. package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
  106. package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
  107. package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
  108. package/template/coding-task-manager/lib/feature-manifest.js +4 -0
  109. package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
  110. package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
  111. package/template/coding-task-manager/lib/fleet-hub.js +762 -0
  112. package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
  113. package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
  114. package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
  115. package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
  116. package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
  117. package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
  118. package/template/coding-task-manager/lib/fleet-update.js +798 -0
  119. package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
  120. package/template/coding-task-manager/lib/fs-watcher.js +58 -42
  121. package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
  122. package/template/coding-task-manager/lib/headless-term-service.js +84 -8
  123. package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
  124. package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
  125. package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
  126. package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
  127. package/template/coding-task-manager/lib/host-handoff.js +16 -19
  128. package/template/coding-task-manager/lib/host-stats.js +150 -3
  129. package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
  130. package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
  131. package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
  132. package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
  133. package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
  134. package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
  135. package/template/coding-task-manager/lib/hub-bridge.js +398 -0
  136. package/template/coding-task-manager/lib/idle-notify.js +491 -0
  137. package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
  138. package/template/coding-task-manager/lib/instance-manifest.js +5 -1
  139. package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
  140. package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
  141. package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
  142. package/template/coding-task-manager/lib/landing/config.js +536 -0
  143. package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
  144. package/template/coding-task-manager/lib/landing/gate.js +360 -0
  145. package/template/coding-task-manager/lib/landing/git.js +344 -0
  146. package/template/coding-task-manager/lib/landing/lease.js +247 -0
  147. package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
  148. package/template/coding-task-manager/lib/landing/proof.js +223 -0
  149. package/template/coding-task-manager/lib/landing/queue.js +998 -0
  150. package/template/coding-task-manager/lib/landing/radar.js +489 -0
  151. package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
  152. package/template/coding-task-manager/lib/landing/state.js +263 -0
  153. package/template/coding-task-manager/lib/landing/stop.js +49 -0
  154. package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
  155. package/template/coding-task-manager/lib/landing/sync.js +456 -0
  156. package/template/coding-task-manager/lib/landing/train.js +885 -0
  157. package/template/coding-task-manager/lib/landing/window.js +57 -0
  158. package/template/coding-task-manager/lib/launch-environment.js +121 -0
  159. package/template/coding-task-manager/lib/launch-model-override.js +36 -10
  160. package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
  161. package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
  162. package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
  163. package/template/coding-task-manager/lib/lead-model-options.js +160 -3
  164. package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
  165. package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
  166. package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
  167. package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
  168. package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
  169. package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
  170. package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
  171. package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
  172. package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
  173. package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
  174. package/template/coding-task-manager/lib/machine-registry.js +750 -5
  175. package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
  176. package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
  177. package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
  178. package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
  179. package/template/coding-task-manager/lib/memory-join.js +337 -0
  180. package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
  181. package/template/coding-task-manager/lib/memory-sync.js +565 -0
  182. package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
  183. package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
  184. package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
  185. package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
  186. package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
  187. package/template/coding-task-manager/lib/model-availability.js +727 -0
  188. package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
  189. package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
  190. package/template/coding-task-manager/lib/model-id-rule.js +19 -0
  191. package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
  192. package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
  193. package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
  194. package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
  195. package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
  196. package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
  197. package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
  198. package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
  199. package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
  200. package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
  201. package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
  202. package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
  203. package/template/coding-task-manager/lib/native-history-control.js +6 -4
  204. package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
  205. package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
  206. package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
  207. package/template/coding-task-manager/lib/opencode-cli.js +480 -0
  208. package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
  209. package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
  210. package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
  211. package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
  212. package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
  213. package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
  214. package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
  215. package/template/coding-task-manager/lib/perf-summary.js +7 -0
  216. package/template/coding-task-manager/lib/perf-tracker.js +63 -2
  217. package/template/coding-task-manager/lib/project-config.js +7 -0
  218. package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
  219. package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
  220. package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
  221. package/template/coding-task-manager/lib/read-pool-client.js +89 -2
  222. package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
  223. package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
  224. package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
  225. package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
  226. package/template/coding-task-manager/lib/relay-client.js +57 -3
  227. package/template/coding-task-manager/lib/relink-audit.js +34 -5
  228. package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
  229. package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
  230. package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
  231. package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
  232. package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
  233. package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
  234. package/template/coding-task-manager/lib/restart-guard.js +18 -6
  235. package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
  236. package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
  237. package/template/coding-task-manager/lib/resume-admission.js +17 -3
  238. package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
  239. package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
  240. package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
  241. package/template/coding-task-manager/lib/runtime-contract.js +3 -1
  242. package/template/coding-task-manager/lib/schema-indexes.js +1 -0
  243. package/template/coding-task-manager/lib/session-context-locator.js +742 -0
  244. package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
  245. package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
  246. package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
  247. package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
  248. package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
  249. package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
  250. package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
  251. package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
  252. package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
  253. package/template/coding-task-manager/lib/session-create/response.js +7 -7
  254. package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
  255. package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
  256. package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
  257. package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
  258. package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
  259. package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
  260. package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
  261. package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
  262. package/template/coding-task-manager/lib/session-empty.js +13 -10
  263. package/template/coding-task-manager/lib/session-host-manager.js +60 -0
  264. package/template/coding-task-manager/lib/session-jobs.js +3 -1
  265. package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
  266. package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
  267. package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
  268. package/template/coding-task-manager/lib/session-park.js +738 -0
  269. package/template/coding-task-manager/lib/session-path-grant.js +13 -4
  270. package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
  271. package/template/coding-task-manager/lib/session-transport.js +17 -0
  272. package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
  273. package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
  274. package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
  275. package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
  276. package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
  277. package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
  278. package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
  279. package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
  280. package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
  281. package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
  282. package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
  283. package/template/coding-task-manager/lib/submission-ack.js +90 -2
  284. package/template/coding-task-manager/lib/systemd-scope.js +115 -0
  285. package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
  286. package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
  287. package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
  288. package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
  289. package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
  290. package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
  291. package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
  292. package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
  293. package/template/coding-task-manager/lib/transcript-source.js +36 -4
  294. package/template/coding-task-manager/lib/transcript-store.js +9 -0
  295. package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
  296. package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
  297. package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
  298. package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
  299. package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
  300. package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
  301. package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
  302. package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
  303. package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
  304. package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
  305. package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
  306. package/template/coding-task-manager/lib/walle/turn.js +1 -1
  307. package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
  308. package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
  309. package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
  310. package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
  311. package/template/coding-task-manager/lib/walle-row-history.js +495 -0
  312. package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
  313. package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
  314. package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
  315. package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
  316. package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
  317. package/template/coding-task-manager/lib/ws/misc.js +1 -1
  318. package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
  319. package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
  320. package/template/coding-task-manager/oauth-proxy.js +112 -115
  321. package/template/coding-task-manager/package-lock.json +10 -94
  322. package/template/coding-task-manager/package.json +4 -3
  323. package/template/coding-task-manager/protocol/message-table.json +10 -0
  324. package/template/coding-task-manager/protocol/messages.js +10 -0
  325. package/template/coding-task-manager/protocol/ws-schema.json +20 -0
  326. package/template/coding-task-manager/protocol/ws-schema.md +2 -0
  327. package/template/coding-task-manager/public/css/app.css +170 -0
  328. package/template/coding-task-manager/public/css/walle-session.css +4 -0
  329. package/template/coding-task-manager/public/index.html +473 -243
  330. package/template/coding-task-manager/public/js/agent-command.js +86 -0
  331. package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
  332. package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
  333. package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
  334. package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
  335. package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
  336. package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
  337. package/template/coding-task-manager/public/js/background-work.js +196 -27
  338. package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
  339. package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
  340. package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
  341. package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
  342. package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
  343. package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
  344. package/template/coding-task-manager/public/js/document-review-links.js +9 -1
  345. package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
  346. package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
  347. package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
  348. package/template/coding-task-manager/public/js/message-renderer.js +4 -3
  349. package/template/coding-task-manager/public/js/model-picker.js +3 -1
  350. package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
  351. package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
  352. package/template/coding-task-manager/public/js/pasted-content.js +236 -0
  353. package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
  354. package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
  355. package/template/coding-task-manager/public/js/prompts.js +11 -10
  356. package/template/coding-task-manager/public/js/protocol.js +10 -0
  357. package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
  358. package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
  359. package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
  360. package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
  361. package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
  362. package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
  363. package/template/coding-task-manager/public/js/stream-view.js +6 -5
  364. package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
  365. package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
  366. package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
  367. package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
  368. package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
  369. package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
  370. package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
  371. package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
  372. package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
  373. package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
  374. package/template/coding-task-manager/public/js/walle.js +6 -0
  375. package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
  376. package/template/coding-task-manager/public/m/app.css +140 -0
  377. package/template/coding-task-manager/public/m/app.js +507 -68
  378. package/template/coding-task-manager/public/m/index.html +17 -0
  379. package/template/coding-task-manager/public/m/machines.js +838 -4
  380. package/template/coding-task-manager/public/m/private-api.js +31 -1
  381. package/template/coding-task-manager/public/usage.html +1 -0
  382. package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
  383. package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
  384. package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
  385. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
  386. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
  387. package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
  388. package/template/coding-task-manager/server.js +1950 -11679
  389. package/template/coding-task-manager/session-integrity.js +64 -4
  390. package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
  391. package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
  392. package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
  393. package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
  394. package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
  395. package/template/coding-task-manager/workers/session-host-process.js +5 -5
  396. package/template/coding-task-manager/workers/watch-worker.js +105 -0
  397. package/template/coding-task-manager/workers/worktree-worker.js +168 -33
  398. package/template/ctm-relay/lib/protocol.js +14 -1
  399. package/template/package-lock.json +2 -2
  400. package/template/package.json +1 -1
  401. package/template/shared/backup-retention.js +82 -0
  402. package/template/shared/conversation-admission.js +2 -0
  403. package/template/shared/conversation-provenance.js +3 -7
  404. package/template/shared/conversation-storage-v2-contract.js +5 -0
  405. package/template/shared/linked-worktree.js +51 -0
  406. package/template/shared/macos-fda-target.js +57 -0
  407. package/template/shared/orphan-parents.js +55 -0
  408. package/template/shared/release-schema.json +2 -2
  409. package/template/shared/storage/contract.js +3 -0
  410. package/template/wall-e/adapters/imessage.js +12 -0
  411. package/template/wall-e/agent.js +71 -4
  412. package/template/wall-e/api-walle.js +21 -1
  413. package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
  414. package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
  415. package/template/wall-e/brain/brain-join.js +859 -0
  416. package/template/wall-e/brain/brain-sync-membership.js +20 -0
  417. package/template/wall-e/brain/brain-sync-store.js +131 -77
  418. package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
  419. package/template/wall-e/brain/brain-sync-v2.js +578 -0
  420. package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
  421. package/template/wall-e/brain/deterministic-id.js +51 -0
  422. package/template/wall-e/brain/memories.js +2 -2
  423. package/template/wall-e/brain/migrations.js +40 -6
  424. package/template/wall-e/brain/model-identity-migration.js +1 -1
  425. package/template/wall-e/brain/owner-call-whitelist.js +23 -7
  426. package/template/wall-e/brain/schema.js +45 -85
  427. package/template/wall-e/brain.js +171 -35
  428. package/template/wall-e/chat.js +3 -3
  429. package/template/wall-e/coding/agent-shell-env.js +7 -2
  430. package/template/wall-e/coding/prompt-bundle.js +66 -21
  431. package/template/wall-e/config/main-loop-exemptions.json +2 -2
  432. package/template/wall-e/http/admin-api.js +37 -0
  433. package/template/wall-e/http/gws-api.js +4 -0
  434. package/template/wall-e/http/helper-rules-api.js +7 -1
  435. package/template/wall-e/http/model-admin.js +8 -1
  436. package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
  437. package/template/wall-e/http/model-proxy-providers.js +174 -1
  438. package/template/wall-e/http/model-route-health.js +157 -0
  439. package/template/wall-e/http/sync-api.js +278 -464
  440. package/template/wall-e/jobs/job-runner.js +28 -1
  441. package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
  442. package/template/wall-e/lib/ctm-data-dir.js +26 -0
  443. package/template/wall-e/lib/derivation-home.js +147 -0
  444. package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
  445. package/template/wall-e/lib/helper-rules/grade.js +51 -8
  446. package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
  447. package/template/wall-e/lib/helper-rules/store.js +4 -2
  448. package/template/wall-e/lib/landing-mcp-tools.js +170 -0
  449. package/template/wall-e/lib/mcp-client-config.js +133 -14
  450. package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
  451. package/template/wall-e/lib/mcp-integration.js +58 -13
  452. package/template/wall-e/lib/parent-death.js +7 -1
  453. package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
  454. package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
  455. package/template/wall-e/llm/delegate-vendor-default.js +12 -5
  456. package/template/wall-e/llm/model-roles.js +1 -1
  457. package/template/wall-e/llm/native-delegate-selection.js +56 -8
  458. package/template/wall-e/llm/worker-delegate-args.js +72 -7
  459. package/template/wall-e/llm/worker-mcp-routing.js +66 -17
  460. package/template/wall-e/loops/brain-custom-writes.js +19 -0
  461. package/template/wall-e/loops/ingest.js +17 -1
  462. package/template/wall-e/loops/think.js +19 -4
  463. package/template/wall-e/mcp-contract.js +222 -6
  464. package/template/wall-e/mcp-protocol-contract.js +40 -5
  465. package/template/wall-e/mcp-server.js +128 -29
  466. package/template/wall-e/mcp-worker-schemas.js +5 -5
  467. package/template/wall-e/memory/ctm-context-client.js +85 -0
  468. package/template/wall-e/memory/ctm-session-context.js +9 -3
  469. package/template/wall-e/memory/hub-bridge-client.js +388 -0
  470. package/template/wall-e/memory/replica-origin.js +56 -0
  471. package/template/wall-e/memory/session-pool.js +135 -0
  472. package/template/wall-e/runtime/live-capabilities.js +8 -3
  473. package/template/wall-e/server.js +4 -2
  474. package/template/wall-e/shared/release-schema.json +2 -2
  475. package/template/wall-e/shared/sqlite-file-set.js +39 -0
  476. package/template/wall-e/shared/storage/contract.js +3 -0
  477. package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
  478. package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
  479. package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
  480. package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
  481. package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
  482. package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
  483. package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
  484. package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
  485. package/template/wall-e/tools/chrome-automation.js +6 -0
  486. package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
  487. package/template/wall-e/workers/brain-owner-worker.js +18 -4
  488. package/template/wall-e/workers/mcp-gateway-process.js +5 -5
@@ -0,0 +1,393 @@
1
+ 'use strict';
2
+
3
+ // WP-6a (docs/shared-memory-every-machine-2026-10-31.html §6.5, gate E-3): the convergence verifier.
4
+ //
5
+ // verifyMemorySync(deps) -> { ok, hub: { instanceId, vector, counts }, members: [...], allEqual }
6
+ //
7
+ // Proves "exactly the same memory" the only way that survives a bucket collision: the bucketed
8
+ // content digest (§6.5) on the hub and on every enabled registry member, compared bucket by bucket.
9
+ // A bucket is equal when its row COUNTS match and — only for a non-empty bucket — its XOR fold
10
+ // matches; two empty buckets are equal whatever their xor string says, because the fold is over no
11
+ // rows at all.
12
+ //
13
+ // Three rules the caller depends on:
14
+ // * Read-only. This module never writes anywhere: no CTM row, no brain row, no file. It dials the
15
+ // local Wall-E (loopback + the CTM's own token), and each member's CTM front route.
16
+ // * A member that cannot be reached is REPORTED (`reachable:false`, `allEqual:false`) and the
17
+ // remaining members are still compared — one dead box must not hide the others' verdict.
18
+ // * The per-member `vectorLag` (hub max_seq − member max_seq, per origin) is the diagnosis the
19
+ // digest alone cannot give: a large positive lag means "still syncing", a NON-ZERO lag with an
20
+ // equal digest on every table means "diverged" (a row the hub holds and the member never will).
21
+ //
22
+ // Tier: this is the `bin/memory-sync-verify.js` core. The CLI owns arg parsing and the registry
23
+ // read; this module owns the comparison and the dials.
24
+ //
25
+ // NB (stabilization-lint): the two `setTimeout(` sites below (one in _localGet, one in _memberGet)
26
+ // are per-request abort deadlines, not recovery waits. Each is unref'd so a hung dial can never
27
+ // hold the process open. The lead registers the surfaces in release/ownership-registry.json — do
28
+ // not silence them here.
29
+
30
+ const machineRegistry = require('./machine-registry');
31
+ const { buildPeerControlHeaders } = require('./remote-machine-create');
32
+
33
+ // The hub's LOCAL Wall-E v2 routes (loopback + CTM token, exactly as lib/memory-sync.js reads them).
34
+ const LOCAL_PATHS = Object.freeze({
35
+ vector: '/api/walle/sync/v2/vector',
36
+ digest: '/api/walle/sync/v2/digest',
37
+ });
38
+
39
+ // The member's CTM front routes (§6.6), each of which forwards to the member's own Wall-E.
40
+ const MEMBER_PATHS = Object.freeze({
41
+ vector: '/api/sync/brain/v2/vector',
42
+ digest: '/api/sync/brain/v2/digest',
43
+ });
44
+
45
+ // D-11: the four tables "the same memory" means. `people` has no runtime writer today but is
46
+ // replicated and must still read equal (0/0) on every node rather than be silently skipped.
47
+ const DEFAULT_TABLES = Object.freeze(['memories', 'knowledge', 'entities', 'people']);
48
+
49
+ const DEFAULT_TIMEOUT_MS = 30_000;
50
+ const BUCKET_COUNT = 256;
51
+
52
+ function _string(value, max = 160) {
53
+ if (typeof value === 'string') return value.trim().slice(0, max);
54
+ return value == null ? '' : String(value).trim().slice(0, max);
55
+ }
56
+
57
+ function _normalizeTables(tables) {
58
+ const list = Array.isArray(tables) ? tables : DEFAULT_TABLES;
59
+ const seen = new Set();
60
+ for (const raw of list) {
61
+ const name = _string(raw, 40);
62
+ if (name) seen.add(name);
63
+ }
64
+ return [...seen];
65
+ }
66
+
67
+ // Dial order = `urls` first, then the pinned `url` (machine-registry D-3/_dialUrls). A row whose
68
+ // list is empty still gets one chance at its pinned URL.
69
+ function _memberUrls(member = {}) {
70
+ const list = (Array.isArray(member.urls) ? member.urls : []).map((u) => _string(u, 1000)).filter(Boolean);
71
+ if (list.length) return list;
72
+ const pinned = _string(member.url, 1000);
73
+ return pinned ? [pinned] : [];
74
+ }
75
+
76
+ function _joinUrl(base, pathname) {
77
+ return `${String(base).replace(/\/+$/, '')}${pathname}`;
78
+ }
79
+
80
+ /**
81
+ * The header builder for member dials. `deps.peerHeadersFor` wins (the hub-side production seam,
82
+ * the same one lib/memory-sync.js takes); with none, fall back to remote-machine-create's
83
+ * buildPeerControlHeaders so a bare caller still authenticates the way the probe does.
84
+ */
85
+ function _peerHeadersBuilder(deps, env) {
86
+ if (typeof deps.peerHeadersFor === 'function') {
87
+ const build = deps.peerHeadersFor;
88
+ return (instanceId) => {
89
+ try {
90
+ const built = build(instanceId);
91
+ return built && typeof built === 'object' ? built : {};
92
+ } catch {
93
+ return {}; // expected: a credential-builder fault degrades to an anonymous dial, reported as unreachable
94
+ }
95
+ };
96
+ }
97
+ const fallbackEnv = env && typeof env === 'object' ? env : process.env;
98
+ return (instanceId) => buildPeerControlHeaders(fallbackEnv, { instanceId }) || {};
99
+ }
100
+
101
+ /** One local Wall-E GET. Resolves { ok, json } — a transport fault is a verdict, never a throw. */
102
+ async function _localGet(walle, pathname, timeoutMs) {
103
+ if (!walle || typeof walle.requestJson !== 'function') return { ok: false, error: 'walle_client_missing' };
104
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
105
+ const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
106
+ if (timer && typeof timer.unref === 'function') timer.unref();
107
+ try {
108
+ const res = await walle.requestJson(pathname, {
109
+ method: 'GET',
110
+ signal: controller ? controller.signal : undefined,
111
+ });
112
+ const status = Number(res && res.status) || 0;
113
+ if (status < 200 || status >= 300 || !res || !res.json) return { ok: false, error: `walle_http_${status}` };
114
+ return { ok: true, json: res.json };
115
+ } catch (err) {
116
+ return { ok: false, error: `walle_request_failed: ${err && err.message ? err.message : String(err)}` };
117
+ } finally {
118
+ if (timer) clearTimeout(timer);
119
+ }
120
+ }
121
+
122
+ /** One member GET against one URL. Same deadline shape; status 0 means "nothing answered". */
123
+ async function _memberGet(fetchImpl, url, pathname, headers, timeoutMs) {
124
+ const fetchFn = fetchImpl || global.fetch;
125
+ if (typeof fetchFn !== 'function') return { ok: false, status: 0, error: 'fetch_unavailable' };
126
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
127
+ const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
128
+ if (timer && typeof timer.unref === 'function') timer.unref();
129
+ try {
130
+ const res = await fetchFn(_joinUrl(url, pathname), {
131
+ method: 'GET',
132
+ headers: { ...headers, Accept: 'application/json' },
133
+ signal: controller ? controller.signal : undefined,
134
+ });
135
+ let json = null;
136
+ try { json = await res.json(); } catch { json = null; /* expected: a non-JSON body is degraded to null and reported by status */ }
137
+ const status = Number(res && res.status) || 0;
138
+ if (status < 200 || status >= 300 || !json) return { ok: false, status, error: `member_http_${status}` };
139
+ return { ok: true, status, json };
140
+ } catch (err) {
141
+ return { ok: false, status: 0, error: err && err.message ? err.message : String(err) };
142
+ } finally {
143
+ if (timer) clearTimeout(timer);
144
+ }
145
+ }
146
+
147
+ async function _dialUrls(fetchImpl, urls, pathname, headers, timeoutMs) {
148
+ let last = { ok: false, status: 0, error: 'member_has_no_url' };
149
+ for (const url of urls) {
150
+ const res = await _memberGet(fetchImpl, url, pathname, headers, timeoutMs);
151
+ if (res.status > 0 || res.ok) return { ...res, url };
152
+ last = { ...res, url };
153
+ }
154
+ return last;
155
+ }
156
+
157
+ /** `buckets` as a 256-slot array; a malformed/short array reads as zero-count buckets. */
158
+ function _bucketArray(digest) {
159
+ const out = new Array(BUCKET_COUNT);
160
+ const list = digest && Array.isArray(digest.buckets) ? digest.buckets : [];
161
+ for (const entry of list) {
162
+ const b = Number(entry && entry.b) | 0;
163
+ if (b < 0 || b >= BUCKET_COUNT) continue;
164
+ out[b] = { count: Math.max(0, Number(entry && entry.count) || 0), xor: _string(entry && entry.xor, 64) };
165
+ }
166
+ for (let b = 0; b < BUCKET_COUNT; b += 1) if (!out[b]) out[b] = { count: 0, xor: '' };
167
+ return out;
168
+ }
169
+
170
+ // §6.5: equal when the counts match and — for a non-empty bucket — the xor folds match too. Two
171
+ // empty buckets are equal regardless of their xor string (the fold is over no rows).
172
+ function _bucketEqual(hub, member) {
173
+ if (hub.count !== member.count) return false;
174
+ if (hub.count === 0) return true;
175
+ return hub.xor === member.xor;
176
+ }
177
+
178
+ /** Compare one table's digests. Returns { equal, hubCount, memberCount, mismatchedBuckets }. */
179
+ function compareDigests(hubDigest, memberDigest) {
180
+ const hub = _bucketArray(hubDigest);
181
+ const member = _bucketArray(memberDigest);
182
+ const mismatchedBuckets = [];
183
+ for (let b = 0; b < BUCKET_COUNT; b += 1) {
184
+ if (!_bucketEqual(hub[b], member[b])) mismatchedBuckets.push(b);
185
+ }
186
+ return {
187
+ equal: mismatchedBuckets.length === 0,
188
+ hubCount: Number(hubDigest && hubDigest.count) || 0,
189
+ memberCount: Number(memberDigest && memberDigest.count) || 0,
190
+ mismatchedBuckets,
191
+ };
192
+ }
193
+
194
+ /**
195
+ * For every origin either side knows: hub max_seq − member max_seq. Positive = the hub holds
196
+ * updates the member has not applied; negative = the member is ahead (its rows have not reached
197
+ * the hub yet); 0 = this origin is level.
198
+ */
199
+ function vectorLag(hubVector, memberVector) {
200
+ const hub = hubVector && typeof hubVector === 'object' ? hubVector : {};
201
+ const member = memberVector && typeof memberVector === 'object' ? memberVector : {};
202
+ const origins = new Set([...Object.keys(hub), ...Object.keys(member)]);
203
+ const lag = {};
204
+ for (const origin of [...origins].sort()) {
205
+ lag[origin] = (Number(hub[origin]) || 0) - (Number(member[origin]) || 0);
206
+ }
207
+ return lag;
208
+ }
209
+
210
+ function _emptyTables(tables) {
211
+ const out = {};
212
+ for (const t of tables) out[t] = { equal: false, hubCount: null, memberCount: null, mismatchedBuckets: [] };
213
+ return out;
214
+ }
215
+
216
+ /** The enabled registry rows to check. `deps.machines` (a pre-fetched view) wins over `deps.db`. */
217
+ function _memberRows(deps) {
218
+ const source = Array.isArray(deps.machines)
219
+ ? deps.machines
220
+ : machineRegistry.listMachines({ db: deps.db }).machines;
221
+ return (source || []).filter((m) => m && m.enabled && _string(m.instanceId));
222
+ }
223
+
224
+ /**
225
+ * Compare the hub's digest against every enabled registry member.
226
+ *
227
+ * @param {object} deps { db, fetchImpl, walle, env, peerHeadersFor, tables, timeoutMs, machines }
228
+ * @returns {Promise<object>} { ok, error?, hub:{instanceId,vector,counts}, members:[...], allEqual }
229
+ */
230
+ async function verifyMemorySync(deps = {}) {
231
+ const walle = deps.walle || require('./walle-client');
232
+ const fetchImpl = deps.fetchImpl || global.fetch;
233
+ const env = deps.env || process.env;
234
+ const tables = _normalizeTables(deps.tables);
235
+ const requested = Number(deps.timeoutMs);
236
+ const timeoutMs = Number.isFinite(requested) && requested > 0 ? requested : DEFAULT_TIMEOUT_MS;
237
+ const peerHeadersFor = _peerHeadersBuilder(deps, env);
238
+
239
+ // 1. The hub. Its vector carries the identity every member's vector is compared against; without
240
+ // it there is no reference, so this is the one fatal leg.
241
+ const hubVectorRes = await _localGet(walle, LOCAL_PATHS.vector, timeoutMs);
242
+ if (!hubVectorRes.ok) {
243
+ return { ok: false, error: hubVectorRes.error, hub: null, members: [], allEqual: false };
244
+ }
245
+ const hubInstanceId = _string(hubVectorRes.json.instanceId);
246
+ const hubVector = hubVectorRes.json.vector && typeof hubVectorRes.json.vector === 'object'
247
+ ? { ...hubVectorRes.json.vector }
248
+ : {};
249
+
250
+ // 2. The hub digest per table. A table the hub cannot digest is a failed check, not a skipped one.
251
+ const hubDigests = {};
252
+ const hubCounts = {};
253
+ for (const table of tables) {
254
+ const res = await _localGet(walle, `${LOCAL_PATHS.digest}?table=${encodeURIComponent(table)}`, timeoutMs);
255
+ if (!res.ok) {
256
+ return {
257
+ ok: false,
258
+ error: `hub_digest_${table}: ${res.error}`,
259
+ hub: { instanceId: hubInstanceId, vector: hubVector, counts: null },
260
+ members: [],
261
+ allEqual: false,
262
+ };
263
+ }
264
+ hubDigests[table] = res.json;
265
+ hubCounts[table] = Number(res.json && res.json.count) || 0;
266
+ }
267
+
268
+ // 3. Every enabled member, sequentially: one comparison per table. A member that does not answer
269
+ // the vector is unreachable — reported, never fatal to the others.
270
+ const members = [];
271
+ for (const row of _memberRows(deps)) {
272
+ const instanceId = _string(row.instanceId);
273
+ const urls = _memberUrls(row);
274
+ const headers = peerHeadersFor(instanceId);
275
+ const vectorRes = await _dialUrls(fetchImpl, urls, MEMBER_PATHS.vector, headers, timeoutMs);
276
+ if (!vectorRes.ok) {
277
+ members.push({
278
+ instanceId,
279
+ reachable: false,
280
+ vector: null,
281
+ counts: null,
282
+ tables: _emptyTables(tables),
283
+ vectorLag: null,
284
+ error: vectorRes.error || 'member_unreachable',
285
+ });
286
+ continue;
287
+ }
288
+ const memberVector = vectorRes.json.vector && typeof vectorRes.json.vector === 'object'
289
+ ? { ...vectorRes.json.vector }
290
+ : {};
291
+ const memberTables = {};
292
+ const memberCounts = {};
293
+ for (const table of tables) {
294
+ const res = await _dialUrls(fetchImpl, urls, `${MEMBER_PATHS.digest}?table=${encodeURIComponent(table)}`, headers, timeoutMs);
295
+ if (!res.ok) {
296
+ memberTables[table] = { equal: false, hubCount: hubCounts[table], memberCount: null, mismatchedBuckets: [], error: res.error || 'member_digest_failed' };
297
+ memberCounts[table] = null;
298
+ continue;
299
+ }
300
+ const compared = compareDigests(hubDigests[table], res.json);
301
+ memberTables[table] = compared;
302
+ memberCounts[table] = compared.memberCount;
303
+ }
304
+ members.push({
305
+ instanceId,
306
+ reachable: true,
307
+ vector: memberVector,
308
+ counts: memberCounts,
309
+ tables: memberTables,
310
+ vectorLag: vectorLag(hubVector, memberVector),
311
+ });
312
+ }
313
+
314
+ const allEqual = members.length > 0
315
+ && members.every((m) => m.reachable && tables.every((t) => m.tables[t] && m.tables[t].equal));
316
+
317
+ return {
318
+ ok: true,
319
+ hub: { instanceId: hubInstanceId, vector: hubVector, counts: hubCounts },
320
+ members,
321
+ allEqual,
322
+ };
323
+ }
324
+
325
+ // ------------------------------------------------------------------------------------------------
326
+ // The CLI's pure half (bin/memory-sync-verify.js): one line per member, and the exit code.
327
+
328
+ /** One member's per-table cell: `memories =100/100` (equal) or `memories !100/99` (differs). */
329
+ function _tableCell(member, tables) {
330
+ return tables.map((t) => {
331
+ const row = member.tables && member.tables[t] ? member.tables[t] : null;
332
+ const hubCount = row && row.hubCount != null ? row.hubCount : '?';
333
+ const memberCount = row && row.memberCount != null ? row.memberCount : '?';
334
+ const mark = row && row.equal ? '=' : '!';
335
+ const extra = row && !row.equal && Array.isArray(row.mismatchedBuckets) && row.mismatchedBuckets.length
336
+ ? ` b[${row.mismatchedBuckets.join(',')}]`
337
+ : '';
338
+ return `${t} ${mark}${hubCount}/${memberCount}${extra}`;
339
+ }).join(' ');
340
+ }
341
+
342
+ function _lagCell(member) {
343
+ if (!member.vectorLag || typeof member.vectorLag !== 'object') return '-';
344
+ const entries = Object.entries(member.vectorLag);
345
+ if (!entries.length) return '-';
346
+ return entries.map(([origin, lag]) => `${origin}=${lag}`).join(',');
347
+ }
348
+
349
+ /**
350
+ * The human table: one row per member, then the verdict. Pure — no clock, no I/O.
351
+ *
352
+ * @param {object} result the verifyMemorySync result
353
+ * @param {object} [opts] { tables } — the table list to render in each row
354
+ */
355
+ function formatReport(result, opts = {}) {
356
+ const r = result && typeof result === 'object' ? result : {};
357
+ const hub = r.hub || {};
358
+ const members = Array.isArray(r.members) ? r.members : [];
359
+ const derived = members[0] && members[0].tables ? Object.keys(members[0].tables) : [];
360
+ const requested = Array.isArray(opts.tables) && opts.tables.length ? opts.tables : derived;
361
+ const tables = _normalizeTables(requested.length ? requested : DEFAULT_TABLES);
362
+ const lines = [];
363
+ lines.push(`memory sync verify — hub ${hub.instanceId || '(unknown)'}`);
364
+ lines.push(`tables: ${tables.join(', ')}`);
365
+ lines.push('');
366
+ for (const member of members) {
367
+ const state = member.reachable ? 'reachable ' : 'unreachable';
368
+ const detail = member.reachable ? _tableCell(member, tables) : (member.error || 'unreachable');
369
+ lines.push(`${member.instanceId || '(unknown)'} ${state} ${detail} lag: ${_lagCell(member)}`);
370
+ }
371
+ if (!members.length) lines.push('(no enabled members registered)');
372
+ lines.push('');
373
+ lines.push(`allEqual: ${r.allEqual === true}`);
374
+ if (r.error) lines.push(`error: ${r.error}`);
375
+ return `${lines.join('\n')}\n`;
376
+ }
377
+
378
+ /** Exit code: 0 only when every enabled member is reachable and every table matches. */
379
+ function exitCodeFor(result) {
380
+ return result && result.ok === true && result.allEqual === true ? 0 : 1;
381
+ }
382
+
383
+ module.exports = {
384
+ verifyMemorySync,
385
+ compareDigests,
386
+ vectorLag,
387
+ formatReport,
388
+ exitCodeFor,
389
+ DEFAULT_TABLES,
390
+ DEFAULT_TIMEOUT_MS,
391
+ LOCAL_PATHS,
392
+ MEMBER_PATHS,
393
+ };