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,20 @@
1
+ 'use strict';
2
+
3
+ // shared-memory D-5 (wall-e/docs/shared-memory-every-machine-2026-10-31.html): the READ side of the
4
+ // durable "this node is a member" marker. Kept apart from brain/brain-sync-v2.js (which writes it) so
5
+ // that placement checks inside scheduler worker jobs (lib/derivation-home.js) never pull write code
6
+ // into the worker-job module set (tests/worker-job-direct-write-gate.test.js). Host-local kv, never
7
+ // replicated.
8
+ const MEMBERSHIP_KEY = 'brain_sync.membership';
9
+
10
+ function readMembership(db) {
11
+ const row = db.prepare('SELECT value FROM kv_store WHERE key = ?').get(MEMBERSHIP_KEY);
12
+ if (!row || !row.value) return null;
13
+ try {
14
+ return JSON.parse(row.value);
15
+ } catch {
16
+ return null; // HANDLE: a corrupt marker reads as "no marker"; the next home round rewrites it
17
+ }
18
+ }
19
+
20
+ module.exports = { MEMBERSHIP_KEY, readMembership };
@@ -1,8 +1,9 @@
1
1
  'use strict';
2
2
 
3
- // multi-machine WP-5: the storage-layer half of the brain outbox (no DDL here — that is
4
- // brain/schema.js ensureBrainSyncSchema). The capture triggers record only (table, id, clock);
5
- // everything that reads a replicated ROW lives in this module so that raw SQL against the
3
+ // multi-machine WP-5: the storage-layer half of brain sync (no DDL here — that is
4
+ // brain/schema.js / brain/brain-sync-v2-schema.js). The v1 outbox transport is retired
5
+ // (WP-6); what remains is the replicated-row reader and the v2 clock host-local helpers.
6
+ // Everything that reads a replicated ROW lives in this module so that raw SQL against the
6
7
  // replicated tables stays in the storage layer (tests/knowledge-read-bounds.test.js).
7
8
 
8
9
  const REPLICATED_TABLES = Object.freeze(['memories', 'knowledge', 'entities', 'people']);
@@ -22,8 +23,8 @@ function knowledgeRowExists(db, id) {
22
23
  return !!db.prepare('SELECT 1 AS hit FROM knowledge WHERE id = ?').get(id);
23
24
  }
24
25
 
25
- // This brain's own instance id — the value the triggers could not stamp cheaply ('' in
26
- // brain_row_clock / brain_outbox means "this host"). Same precedence as
26
+ // This brain's own instance id — the value the capture trigger cannot stamp cheaply ('' in
27
+ // brain_row_clock means "this host"). Same precedence as
27
28
  // lib/brain-host-identity.js: the kv identity record, then the owner table.
28
29
  function localBrainInstanceId(db) {
29
30
  try {
@@ -40,110 +41,163 @@ function localBrainInstanceId(db) {
40
41
  }
41
42
  }
42
43
 
43
- // Follow-up #16: history backfill. Rows that predate the capture triggers (migration 89) never
44
- // had an outbox row; the outbox READ enqueues them a bounded page at a time (sync-api.js
45
- // listBrainOutbox), so there is no scheduler job, no boot work and no migration. The per-table
46
- // rowid cursor is host-local state in kv_store (no capture trigger exists on kv_store).
47
- //
48
- // Order: entities, people, knowledge, memories. knowledge walks rowid DESCENDING — every
49
- // superseded_by target has a higher rowid than the row pointing at it (measured on the live
50
- // brain), so a target always travels first and the receiver never drops the pointer
51
- // (brain_fk_dropped). `after` is the last rowid enqueued (for knowledge: the rows still to go
52
- // are BELOW it; null = not started).
53
- const BACKFILL_KEY = 'brain_sync.backfill';
54
- const BACKFILL_ORDER = Object.freeze(['entities', 'people', 'knowledge', 'memories']);
55
- const BACKFILL_DESCENDING = new Set(['knowledge']);
56
- // History loses to any real captured edit (LWW compares the clock first); two backfills of the
57
- // same id on two hosts tiebreak deterministically by origin id.
44
+ // WP-0 (§5 D-3/D-4/D-8, §6.3): the CLOCK seed walk — the v2 replacement for v1's history
45
+ // backfill (WP-6 deletes that walk). It exists because a row whose clock row is missing
46
+ // (written before the v2 triggers, or before this host knew its own instance id) is not
47
+ // ADDRESSABLE — a peer asks "everything from origin X after seq N" and never learns it exists.
48
+ // One clock row per replicated row, bounded page per call, host-local cursor in kv_store, one
49
+ // transaction per call. Nothing here fires a capture trigger — brain_row_clock,
50
+ // brain_local_seq, brain_vv and kv_store carry none — so the sentinel is not needed either.
51
+ const CLOCK_SEED_KEY = 'brain_sync.clock_seed';
52
+ // History loses to any real captured edit (LWW compares the clock first); two seeds of the
53
+ // same id on two hosts tiebreak deterministically by origin id. Shared with the seed walk.
58
54
  const BACKFILL_CLOCK = '1970-01-01T00:00:00.000Z';
55
+ // entities, people, knowledge, memories; knowledge walks rowid DESCENDING, because every
56
+ // superseded_by target has a higher rowid than the row pointing at it.
57
+ const CLOCK_SEED_ORDER = Object.freeze(['entities', 'people', 'knowledge', 'memories']);
58
+ const CLOCK_SEED_DESCENDING = new Set(['knowledge']);
59
59
 
60
- function readBackfillState(db) {
60
+ // Read side for WP-1 (and the job's own no-op check): where the walk is, and whether it is over.
61
+ function clockSeedState(db) {
62
+ const row = db.prepare('SELECT value FROM kv_store WHERE key = ?').get(CLOCK_SEED_KEY);
61
63
  let parsed = {};
62
- const row = db.prepare('SELECT value FROM kv_store WHERE key = ?').get(BACKFILL_KEY);
63
64
  if (row && row.value) {
64
65
  try {
65
66
  parsed = JSON.parse(row.value) || {};
66
67
  } catch {
67
- parsed = {}; // HANDLE: a corrupt cursor restarts the walk from the top — a re-send is idempotent on the receiver
68
+ parsed = {}; // HANDLE: a corrupt cursor restarts the walk from the top — every re-seed is idempotent (ON CONFLICT DO NOTHING)
68
69
  }
69
70
  }
70
- const state = {};
71
- for (const table of BACKFILL_ORDER) {
72
- const entry = parsed[table] && typeof parsed[table] === 'object' ? parsed[table] : {};
73
- state[table] = { after: Number.isInteger(entry.after) ? entry.after : null, done: entry.done === true };
74
- }
75
- return state;
71
+ return {
72
+ done: parsed.done === true,
73
+ table: CLOCK_SEED_ORDER.includes(parsed.table) ? parsed.table : CLOCK_SEED_ORDER[0],
74
+ after: Number.isInteger(parsed.after) ? parsed.after : null,
75
+ };
76
76
  }
77
77
 
78
- function _writeBackfillState(db, state) {
78
+ function _writeClockSeedState(db, state) {
79
79
  db.prepare(`
80
80
  INSERT INTO kv_store (key, value, updated_at) VALUES (?, ?, datetime('now'))
81
81
  ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at
82
- `).run(BACKFILL_KEY, JSON.stringify(state));
82
+ `).run(CLOCK_SEED_KEY, JSON.stringify(state));
83
+ }
84
+
85
+ // The same self-initialising counter the capture triggers use, so a seed and a live write can
86
+ // never mint the same seq for two different rows.
87
+ function _nextLocalSeq(db) {
88
+ db.prepare(`
89
+ INSERT INTO brain_local_seq (id, next_seq) VALUES (1, 1)
90
+ ON CONFLICT(id) DO UPDATE SET next_seq = next_seq + 1
91
+ `).run();
92
+ return Number(db.prepare('SELECT next_seq FROM brain_local_seq WHERE id = 1').get().next_seq);
93
+ }
94
+
95
+ function _bumpLocalVv(db, originInstanceId, seq) {
96
+ if (!(seq > 0)) return;
97
+ db.prepare(`
98
+ INSERT INTO brain_vv (origin_instance_id, max_seq) VALUES (?, ?)
99
+ ON CONFLICT(origin_instance_id) DO UPDATE SET max_seq = MAX(max_seq, excluded.max_seq)
100
+ `).run(originInstanceId, seq);
83
101
  }
84
102
 
85
- function _backfillRows(db, table, after, limit) {
86
- if (BACKFILL_DESCENDING.has(table)) {
87
- if (after == null) return db.prepare(`SELECT rowid AS rid, id FROM "${table}" ORDER BY rowid DESC LIMIT ?`).all(limit);
88
- return db.prepare(`SELECT rowid AS rid, id FROM "${table}" WHERE rowid < ? ORDER BY rowid DESC LIMIT ?`).all(after, limit);
103
+ // Up to `limit` rows of one replicated table that have NO clock row, in walk order.
104
+ function _clockSeedRows(db, table, after, limit) {
105
+ const missing = `NOT EXISTS (SELECT 1 FROM brain_row_clock c WHERE c.table_name = '${table}' AND c.row_id = t.id)`;
106
+ if (CLOCK_SEED_DESCENDING.has(table)) {
107
+ return db.prepare(`SELECT t.rowid AS rid, t.id AS id FROM "${table}" t WHERE ${missing} AND t.rowid < ? ORDER BY t.rowid DESC LIMIT ?`)
108
+ .all(after == null ? Number.MAX_SAFE_INTEGER : after, limit);
89
109
  }
90
- return db.prepare(`SELECT rowid AS rid, id FROM "${table}" WHERE rowid > ? ORDER BY rowid ASC LIMIT ?`).all(after == null ? 0 : after, limit);
110
+ return db.prepare(`SELECT t.rowid AS rid, t.id AS id FROM "${table}" t WHERE ${missing} AND t.rowid > ? ORDER BY t.rowid ASC LIMIT ?`)
111
+ .all(after == null ? 0 : after, limit);
91
112
  }
92
113
 
93
- // Enqueue at most `budget` historical rows into brain_outbox, in one transaction with the cursor.
94
- // A row with no brain_row_clock is stamped with the sentinel clock and origin '' (this host); a row
95
- // that already has a clock keeps it. Rows already captured live may be enqueued a second time —
96
- // the receiver's apply is idempotent, so there is deliberately no dedup scan. The writes here
97
- // touch only brain_outbox / brain_row_clock / kv_store, none of which carries a capture trigger.
98
- function enqueueBackfillPage(db, budget) {
99
- let remaining = Math.max(0, Math.floor(Number(budget) || 0));
100
- const state = readBackfillState(db);
101
- if (!remaining || BACKFILL_ORDER.every((table) => state[table].done)) return { enqueued: 0, backfill: state };
102
- let enqueued = 0;
114
+ // The v1 clock rows still carry '' ("this host") and often seq 0. Adopt them: once the origin is
115
+ // the local id the row is addressable, and the ones that already have a seq keep it (only a 0
116
+ // gets a fresh one). Bounded by the caller's budget, and resumable for free — an adopted row no
117
+ // longer matches `origin_instance_id = ''`, so the next call continues where this one stopped.
118
+ function _adoptUnknownOriginPage(db, localId, budget) {
119
+ const select = db.prepare(`
120
+ SELECT row_id AS rowId, origin_seq AS originSeq FROM brain_row_clock
121
+ WHERE table_name = ? AND origin_instance_id = '' ORDER BY rowid ASC LIMIT ?
122
+ `);
123
+ const adopt = db.prepare('UPDATE brain_row_clock SET origin_instance_id = ?, origin_seq = ? WHERE table_name = ? AND row_id = ?');
124
+ let adopted = 0;
125
+ let maxSeq = 0;
126
+ for (const table of REPLICATED_TABLES) {
127
+ if (adopted >= budget) break;
128
+ for (const row of select.all(table, budget - adopted)) {
129
+ const seq = Number(row.originSeq) > 0 ? Number(row.originSeq) : _nextLocalSeq(db);
130
+ adopt.run(localId, seq, table, row.rowId);
131
+ maxSeq = Math.max(maxSeq, seq);
132
+ adopted += 1;
133
+ }
134
+ }
135
+ _bumpLocalVv(db, localId, maxSeq);
136
+ return adopted;
137
+ }
138
+
139
+ // One bounded, resumable page of the clock seed walk. `limit` is the row budget for the WHOLE
140
+ // call (adoptions and seeds together), so a caller can bound the work it is about to do —
141
+ // job-driven, never boot-driven.
142
+ function seedClockPage(db, { limit = 2000 } = {}) {
143
+ const budget = Math.max(0, Math.floor(Number(limit) || 0));
144
+ const state = clockSeedState(db);
145
+ const localId = localBrainInstanceId(db);
146
+ // No identity yet: nothing can be addressed, and guessing one would fork this host's seq
147
+ // space. The job stays pending (done: false) until the boot write lands.
148
+ if (!localId) {
149
+ return { seeded: 0, rewritten: 0, done: false, table: state.table, reason: 'identity_unknown' };
150
+ }
151
+ if (state.done || budget === 0) return { seeded: 0, rewritten: 0, done: state.done, table: state.table };
152
+
153
+ const stamp = db.prepare(`
154
+ INSERT INTO brain_row_clock (table_name, row_id, updated_at, origin_instance_id, origin_seq, deleted)
155
+ VALUES (?, ?, ?, ?, ?, 0)
156
+ ON CONFLICT(table_name, row_id) DO NOTHING
157
+ `);
158
+ let seeded = 0;
159
+ let rewritten = 0;
160
+ let table = state.table;
161
+ let after = state.after;
162
+ let done = false;
103
163
  db.transaction(() => {
104
- const clockOf = db.prepare('SELECT updated_at, origin_instance_id FROM brain_row_clock WHERE table_name = ? AND row_id = ?');
105
- const stamp = db.prepare(`
106
- INSERT INTO brain_row_clock (table_name, row_id, updated_at, origin_instance_id) VALUES (?, ?, ?, '')
107
- ON CONFLICT(table_name, row_id) DO NOTHING
108
- `);
109
- const enqueue = db.prepare(`
110
- INSERT INTO brain_outbox (operation_id, table_name, row_id, op, updated_at, origin_instance_id)
111
- VALUES (lower(hex(randomblob(16))), ?, ?, 'upsert', ?, ?)
112
- `);
113
- for (const table of BACKFILL_ORDER) {
114
- if (!remaining) break;
115
- const cursor = state[table];
116
- if (cursor.done) continue;
164
+ rewritten = _adoptUnknownOriginPage(db, localId, budget);
165
+ let remaining = budget - rewritten;
166
+ let index = Math.max(0, CLOCK_SEED_ORDER.indexOf(table));
167
+ let maxSeq = 0;
168
+ while (remaining > 0 && index < CLOCK_SEED_ORDER.length) {
169
+ table = CLOCK_SEED_ORDER[index];
117
170
  const requested = remaining;
118
- const rows = _backfillRows(db, table, cursor.after, requested);
171
+ const rows = _clockSeedRows(db, table, after, requested);
119
172
  for (const row of rows) {
120
- cursor.after = Number(row.rid);
173
+ after = Number(row.rid);
121
174
  remaining -= 1;
122
- if (row.id == null || row.id === '') continue;
123
- const id = String(row.id);
124
- let clock = clockOf.get(table, id);
125
- if (!clock) {
126
- stamp.run(table, id, BACKFILL_CLOCK);
127
- clock = { updated_at: BACKFILL_CLOCK, origin_instance_id: '' };
128
- }
129
- enqueue.run(table, id, String(clock.updated_at || BACKFILL_CLOCK), String(clock.origin_instance_id || ''));
130
- enqueued += 1;
175
+ if (row.id == null || row.id === '') continue; // a rowid with no id is unreachable by a peer; the cursor still moves past it
176
+ const seq = _nextLocalSeq(db);
177
+ stamp.run(table, String(row.id), BACKFILL_CLOCK, localId, seq);
178
+ maxSeq = Math.max(maxSeq, seq);
179
+ seeded += 1;
180
+ }
181
+ if (rows.length < requested) {
182
+ index += 1;
183
+ after = null;
131
184
  }
132
- if (rows.length < requested) cursor.done = true;
133
185
  }
134
- _writeBackfillState(db, state);
186
+ done = index >= CLOCK_SEED_ORDER.length;
187
+ _bumpLocalVv(db, localId, maxSeq);
188
+ _writeClockSeedState(db, { table, after: done ? null : after, done });
135
189
  }).immediate();
136
- return { enqueued, backfill: state };
190
+ return { seeded, rewritten, done, table };
137
191
  }
138
192
 
139
193
  module.exports = {
140
194
  REPLICATED_TABLES,
141
- BACKFILL_KEY,
142
- BACKFILL_ORDER,
143
195
  BACKFILL_CLOCK,
196
+ CLOCK_SEED_KEY,
197
+ CLOCK_SEED_ORDER,
144
198
  readReplicatedRow,
145
199
  knowledgeRowExists,
146
200
  localBrainInstanceId,
147
- readBackfillState,
148
- enqueueBackfillPage,
201
+ clockSeedState,
202
+ seedClockPage,
149
203
  };
@@ -0,0 +1,203 @@
1
+ 'use strict';
2
+
3
+ // Sanctioned DDL module (lint/ddl-outside-runner.config.json): the WP-0 v2 brain-sync clock.
4
+ // Invoked only through brain/schema.js ensureBrainSyncSchemaV2 (createTables() and MIGRATIONS[104]).
5
+ // It never requires schema.js (schema.js -> this file is the only edge).
6
+
7
+ // --- WP-0 (shared-memory-every-machine-2026-10-31.html §5 D-3/D-4/D-8, §6.1) ------
8
+ // The v2 clock. v1's brain_row_clock held only (updated_at, origin_instance_id) —
9
+ // enough to decide WHO wins, not enough to ADDRESS a change: a peer asks "everything
10
+ // from origin X after seq N" (D-3). v2 adds origin_seq + deleted, so the clock row IS
11
+ // the compacted change log (one row per replicated row, latest state only) and a delete
12
+ // leaves a tombstone instead of vanishing (D-8: pruned only once every member's reported
13
+ // vector has passed it). The trigger also maintains brain_local_seq (this node's origin
14
+ // counter) and brain_vv (what this node holds, per origin).
15
+ //
16
+ // Idempotent BY INSPECTION, because createTables() runs it on EVERY boot (fresh and
17
+ // existing alike): the column adds are probed, and the triggers are dropped/recreated
18
+ // only while the installed SQL is still a v1 body (`brain_local_seq` absent). The
19
+ // statements below are shared verbatim by the fresh path (createTables) and migration
20
+ // 104, which is what tests-integration/migration-baseline-parity.test.js compares.
21
+ const BRAIN_SYNC_V2_COLUMNS = Object.freeze([
22
+ ['origin_seq', 'ALTER TABLE brain_row_clock ADD COLUMN origin_seq INTEGER NOT NULL DEFAULT 0'],
23
+ // No CHECK on `deleted`: a CHECK would have to be spelled identically on both paths
24
+ // (ALTER-added here, CREATE TABLE on a future rebuild) to keep the parity test green,
25
+ // and the only writer is this file's own trigger.
26
+ ['deleted', 'ALTER TABLE brain_row_clock ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0'],
27
+ ]);
28
+
29
+ // Host-local tables (D-7): never replicated, never taken from a join snapshot. brain_vv
30
+ // is the node's own vector; brain_member_vv is the hub's record of what each member last
31
+ // reported (empty on a member); brain_sync_conflicts is the WP-1 conflict ledger.
32
+ const BRAIN_SYNC_V2_TABLES = `
33
+ CREATE INDEX IF NOT EXISTS idx_brain_row_clock_origin ON brain_row_clock(origin_instance_id, origin_seq);
34
+ CREATE TABLE IF NOT EXISTS brain_local_identity (
35
+ id INTEGER PRIMARY KEY CHECK (id = 1),
36
+ instance_id TEXT NOT NULL
37
+ );
38
+ CREATE TABLE IF NOT EXISTS brain_local_seq (
39
+ id INTEGER PRIMARY KEY CHECK (id = 1),
40
+ next_seq INTEGER NOT NULL
41
+ );
42
+ CREATE TABLE IF NOT EXISTS brain_vv (
43
+ origin_instance_id TEXT PRIMARY KEY,
44
+ max_seq INTEGER NOT NULL
45
+ );
46
+ CREATE TABLE IF NOT EXISTS brain_member_vv (
47
+ member_instance_id TEXT NOT NULL,
48
+ origin_instance_id TEXT NOT NULL,
49
+ max_seq INTEGER NOT NULL,
50
+ reported_at TEXT NOT NULL,
51
+ PRIMARY KEY (member_instance_id, origin_instance_id)
52
+ );
53
+ CREATE TABLE IF NOT EXISTS brain_sync_conflicts (
54
+ id INTEGER PRIMARY KEY,
55
+ at TEXT NOT NULL,
56
+ reason TEXT NOT NULL CHECK (reason IN ('lww_lost','memory_identity_conflict','brain_fk_dropped','brain_table_unknown')),
57
+ table_name TEXT NOT NULL,
58
+ row_id TEXT NOT NULL,
59
+ origin_instance_id TEXT NOT NULL,
60
+ origin_seq INTEGER NOT NULL,
61
+ detail TEXT NOT NULL DEFAULT ''
62
+ );
63
+ `;
64
+
65
+ // The 12 capture triggers (ai / au / ad per replicated table), replacing v1's 8: same
66
+ // names, same WHEN sentinel, same watch columns for _au (a column a migration added is
67
+ // never named — ALTER TABLE DROP COLUMN dies while a trigger names it), plus the body
68
+ // that stamps the clock, bumps the sequence and maintains the vector. WP-6 (migration
69
+ // 105) removed the v1 outbox INSERT the ai/au bodies used to append.
70
+ //
71
+ // A trigger must never make a user write fail. The self-initialising `INSERT ... VALUES
72
+ // (1, 1) ON CONFLICT DO UPDATE SET next_seq = next_seq + 1` and the COALESCE to '' make
73
+ // every body legal even on a brain whose brain_local_identity row does not exist yet
74
+ // ('' keeps meaning "this host" — the v1 convention — until migration 104's boot write
75
+ // lands).
76
+ // The columns whose change is a replication event (the _au WATCH list). Also the columns the
77
+ // WP-1 digest compares: unwatched columns (read stamps, local classifier output) legitimately
78
+ // differ between machines and never replicate after the insert.
79
+ const BRAIN_SYNC_WATCH_COLUMNS = Object.freeze({
80
+ memories: Object.freeze(['content', 'content_raw', 'subject', 'metadata', 'importance', 'archived_at']),
81
+ knowledge: Object.freeze(['category', 'subject', 'predicate', 'object', 'confidence', 'source_memory_ids', 'status', 'superseded_by', 'valid_from', 'valid_to', 'last_confirmed', 'times_confirmed']),
82
+ entities: Object.freeze(['canonical_name', 'entity_type', 'aliases', 'properties', 'updated_at']),
83
+ people: Object.freeze(['name', 'aliases', 'identities', 'relationship', 'trust_level', 'trust_reason', 'interaction_freq', 'last_interaction', 'notes']),
84
+ });
85
+
86
+ function buildBrainSyncV2Triggers() {
87
+ const skipWhen = "NOT EXISTS (SELECT 1 FROM pragma_table_list WHERE name = 'brain_sync_applying')";
88
+ const watchColumns = BRAIN_SYNC_WATCH_COLUMNS;
89
+ let sql = '';
90
+ for (const table of Object.keys(watchColumns)) {
91
+ const watch = watchColumns[table].map((column) => `"${column}"`).join(', ');
92
+ const body = (row, deleted) => `
93
+ INSERT INTO brain_local_seq (id, next_seq) VALUES (1, 1)
94
+ ON CONFLICT(id) DO UPDATE SET next_seq = next_seq + 1;
95
+ INSERT INTO brain_row_clock (table_name, row_id, updated_at, origin_instance_id, origin_seq, deleted)
96
+ VALUES ('${table}', ${row}, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),
97
+ COALESCE((SELECT instance_id FROM brain_local_identity WHERE id = 1), ''),
98
+ (SELECT next_seq FROM brain_local_seq WHERE id = 1), ${deleted})
99
+ ON CONFLICT(table_name, row_id) DO UPDATE SET
100
+ updated_at = excluded.updated_at,
101
+ origin_instance_id = excluded.origin_instance_id,
102
+ origin_seq = excluded.origin_seq,
103
+ deleted = excluded.deleted;
104
+ INSERT INTO brain_vv (origin_instance_id, max_seq)
105
+ VALUES (COALESCE((SELECT instance_id FROM brain_local_identity WHERE id = 1), ''),
106
+ (SELECT next_seq FROM brain_local_seq WHERE id = 1))
107
+ ON CONFLICT(origin_instance_id) DO UPDATE SET max_seq = MAX(max_seq, excluded.max_seq);`;
108
+ // WP-6 (migration 105): the ai/au bodies stamp only the clock/seq/vv — the v1 outbox
109
+ // INSERT they used to append is gone, and so is the table it wrote to.
110
+ const live = body('new.id', '0');
111
+ sql += `
112
+ DROP TRIGGER IF EXISTS brain_outbox_${table}_ai;
113
+ CREATE TRIGGER IF NOT EXISTS brain_outbox_${table}_ai AFTER INSERT ON ${table}
114
+ WHEN ${skipWhen}
115
+ BEGIN${live}
116
+ END;
117
+ DROP TRIGGER IF EXISTS brain_outbox_${table}_au;
118
+ CREATE TRIGGER IF NOT EXISTS brain_outbox_${table}_au AFTER UPDATE OF ${watch} ON ${table}
119
+ WHEN ${skipWhen}
120
+ BEGIN${live}
121
+ END;
122
+ DROP TRIGGER IF EXISTS brain_outbox_${table}_ad;
123
+ CREATE TRIGGER IF NOT EXISTS brain_outbox_${table}_ad AFTER DELETE ON ${table}
124
+ WHEN ${skipWhen}
125
+ BEGIN${body('old.id', '1')}
126
+ END;
127
+ `;
128
+ }
129
+ return sql;
130
+ }
131
+
132
+ const BRAIN_SYNC_V2_TRIGGERS = buildBrainSyncV2Triggers();
133
+ // The one string a v1 trigger body does NOT contain — the installed-SQL probe below.
134
+ const BRAIN_SYNC_V2_MARKER = 'brain_local_seq';
135
+
136
+ // What the installed schema already has: the brain_row_clock columns and the capture
137
+ // trigger bodies. Asked through better-sqlite3's own APIs (pragma(), sqlite_master) —
138
+ // the same probe brain.js's `_columnExists` makes.
139
+ //
140
+ // The fallback matters: tests/brain-schema-module.test.js drives createTables() with a
141
+ // recording stub that implements only exec()/prepare(), so the probe throws there instead
142
+ // of answering, and "the v1 shape is installed" (columns missing, no triggers) is the
143
+ // right answer — the module then executes the fresh-install statements, each of which is
144
+ // IF NOT EXISTS / DROP IF EXISTS, and the DDL it records is the DDL a fresh install gets.
145
+ function _readBrainSyncInstalledSchema(d) {
146
+ try {
147
+ const columns = new Set((d.pragma('table_info(brain_row_clock)') || []).map((row) => row.name));
148
+ const triggers = d.prepare("SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name LIKE 'brain_outbox_%'")
149
+ .all().map((row) => String(row.sql || '')).join('\n');
150
+ return { columns, triggers };
151
+ } catch {
152
+ return { columns: null, triggers: '' }; // HANDLE: a handle that cannot answer queries — treat as an un-upgraded schema
153
+ }
154
+ }
155
+
156
+ // The v2 half of migration 104's body (schema.js ensureBrainSyncSchemaV2 runs the v1 DDL
157
+ // first, then this). createTables() runs it on every boot, so it must be a no-op on a
158
+ // database that already has the columns and the v2 triggers.
159
+ function applyBrainSyncSchemaV2(d) {
160
+ const installed = _readBrainSyncInstalledSchema(d);
161
+ for (const [column, sql] of BRAIN_SYNC_V2_COLUMNS) {
162
+ if (!installed.columns || !installed.columns.has(column)) d.exec(sql);
163
+ }
164
+ d.exec(BRAIN_SYNC_V2_TABLES);
165
+ if (!installed.triggers.includes(BRAIN_SYNC_V2_MARKER)) d.exec(BRAIN_SYNC_V2_TRIGGERS);
166
+ }
167
+
168
+ // --- WP-6 (migration 105): retire the v1 outbox transport -------------------------
169
+ // v1's outbox was the delivery mechanism until WP-1's version-vector feed replaced it;
170
+ // nothing drained it any more (observed 2026-10-31: hub 16,556 rows, box 35,526), and it
171
+ // was the only reason every brain write carried a second INSERT. Migration 105 deletes it
172
+ // completely: the three tables and the outbox INSERT the ai/au capture bodies used to
173
+ // append. v2 behaviour (clock/seq/vv) is untouched — the ai/au bodies are otherwise
174
+ // byte-identical.
175
+ //
176
+ // The one statement a v1/pre-105 trigger body has and the v2 body does not — the probe below.
177
+ const BRAIN_SYNC_OUTBOX_INSERT = 'INSERT INTO brain_outbox';
178
+ // DROP order matters only for readability; IF EXISTS makes a re-run (and a fresh install,
179
+ // where none of the three ever existed) a no-op.
180
+ const BRAIN_SYNC_V1_DROP_SQL = `
181
+ DROP TABLE IF EXISTS brain_outbox;
182
+ DROP TABLE IF EXISTS brain_sync_hwm;
183
+ DROP TABLE IF EXISTS brain_sync_applied;
184
+ `;
185
+
186
+ // Migration 105's body. createTables() runs it on every boot, so it must be a no-op on a
187
+ // database that already has outbox-free triggers and no v1 tables.
188
+ function applyBrainSyncSchemaV3(d) {
189
+ // Recreate the 8 ai/au triggers only while the installed SQL still carries the outbox
190
+ // INSERT. Dropping the tables first would leave a body that references a missing table
191
+ // (legal in SQLite until it fires, but a landmine), so the recreate comes first.
192
+ const installed = _readBrainSyncInstalledSchema(d);
193
+ if (installed.triggers.includes(BRAIN_SYNC_OUTBOX_INSERT)) d.exec(BRAIN_SYNC_V2_TRIGGERS);
194
+ d.exec(BRAIN_SYNC_V1_DROP_SQL);
195
+ }
196
+
197
+ module.exports = {
198
+ applyBrainSyncSchemaV2,
199
+ applyBrainSyncSchemaV3,
200
+ BRAIN_SYNC_V2_TRIGGERS,
201
+ BRAIN_SYNC_V2_MARKER,
202
+ BRAIN_SYNC_WATCH_COLUMNS,
203
+ };