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,252 @@
1
+ 'use strict';
2
+ // WP-3 (docs/fleet-origin-main-sync-skill-2026-10-31.html §5 R-8, §6.5, §8 WP-3): the CTM origin
3
+ // follower.
4
+ //
5
+ // R-8: "the pull half runs itself". ONE unref'd interval per process; each tick runs the
6
+ // repository's OWN `land sync --pull-only --json` (§6.2), so there is never a second implementation
7
+ // of the fetch/fast-forward machine — and `land sync` itself schedules the idle restart (§6.4, via
8
+ // lib/fleet-update.js `scheduleLocalApply`) when it moves main. A tick that is still running when
9
+ // the next one fires is SKIPPED, never stacked; the timer callback never throws, so a failed child
10
+ // cannot kill the loop.
11
+ //
12
+ // The follower is a NO-OP (a handle carrying a `reason`, armed with no timer) whenever this process
13
+ // must not pull for this checkout:
14
+ // dev-<tag> a dev instance never touches the real repository's main;
15
+ // not_configured the target tree's `.ctm.json` has no `landing.publish` — R-1 is only in force
16
+ // where the repository opted in;
17
+ // follow_disabled `landing.publish.follow === false` — the box wants publish without the pull half;
18
+ // not_main repoRoot is not a git checkout whose current branch is `main` (a scratch repo, a
19
+ // release checkout, or a session worktree on a feature branch).
20
+ //
21
+ // Nothing here writes state: the verdict of every tick is already recorded by `land sync` in
22
+ // `<common>/landing/sync-state.json` (`recordSyncVerdict`), which is what the box's own
23
+ // `/api/fleet/status` reads back as `originSync.lastSync`.
24
+
25
+ const path = require('node:path');
26
+ const { spawn } = require('node:child_process');
27
+ const { loadTargetLandingConfig } = require('./landing/config');
28
+ const { runGitRaw } = require('./landing/git');
29
+
30
+ // §6.1 default cadence: 900 000 ms = 15 min. The normalized config always carries a positive
31
+ // integer, so this is only the defensive fallback for a caller that injects a hand-built config.
32
+ const DEFAULT_FOLLOW_INTERVAL_MS = 900000;
33
+ // §6.5: the pull is bounded — a fetch that has not finished in 120 s is killed (the child, not this
34
+ // process), and the next tick starts fresh.
35
+ const LAND_TIMEOUT_MS = 120000;
36
+ // The repo-relative path of the CLI this follower drives, from the repository root.
37
+ const LAND_SCRIPT_REL = path.join('coding-task-manager', 'bin', 'land.js');
38
+
39
+ /** Absolute path of the `land` CLI inside `repoRoot` — the process the follower spawns. */
40
+ function landScriptPath(repoRoot) {
41
+ return path.join(String(repoRoot || ''), LAND_SCRIPT_REL);
42
+ }
43
+
44
+ /**
45
+ * §6.2/§5 R-8: the follower's argv. `--pull-only` never merges and never pushes (a diverged box is
46
+ * reported `diverged` with `hint: land sync`, exit 1, for a human to run), and `--json` makes the
47
+ * verdict machine-readable instead of parsed out of a human line.
48
+ *
49
+ * §13.4 R-R1 (WP-8): when the resolver policy is `session` the follower runs the FULL `land sync`,
50
+ * which merges a clean divergence and pushes it itself — the resolver session only exists for the
51
+ * conflict/gate_failed case (see `start`).
52
+ */
53
+ function landArgv({ pullOnly = true } = {}) {
54
+ return pullOnly ? ['sync', '--pull-only', '--json'] : ['sync', '--json'];
55
+ }
56
+
57
+ /** The verdict out of `land sync --json`'s stdout; '' when it is not a payload we understand. */
58
+ function verdictOf(stdout) {
59
+ const text = String(stdout == null ? '' : stdout).trim();
60
+ if (!text) return '';
61
+ try {
62
+ const payload = JSON.parse(text);
63
+ return payload && typeof payload.verdict === 'string' ? payload.verdict : '';
64
+ } catch {
65
+ // HANDLE: a child killed mid-write (or a stray progress line on stdout) is not a verdict — the
66
+ // tick reports "unknown" and the next tick tries again.
67
+ return '';
68
+ }
69
+ }
70
+
71
+ /**
72
+ * The production tick body: `process.execPath <repoRoot>/coding-task-manager/bin/land.js sync
73
+ * [--pull-only] --json`, cwd `repoRoot`, no shell, killed after `timeoutMs`. Resolves (never rejects)
74
+ * with `{ verdict, code, error }` so a spawn failure is reported like any other bad verdict.
75
+ */
76
+ function runLandOnce({ repoRoot = '', timeoutMs = LAND_TIMEOUT_MS, env = process.env, pullOnly = true } = {}) {
77
+ return new Promise((resolve) => {
78
+ let child = null;
79
+ try {
80
+ child = spawn(process.execPath, [landScriptPath(repoRoot), ...landArgv({ pullOnly })], {
81
+ cwd: repoRoot, env, timeout: timeoutMs, shell: false, stdio: ['ignore', 'pipe', 'pipe'],
82
+ });
83
+ } catch (error) {
84
+ resolve({ verdict: '', code: null, error: (error && error.message) || String(error) });
85
+ return;
86
+ }
87
+ let stdout = '';
88
+ let stderr = '';
89
+ let settled = false;
90
+ const finish = (payload) => { if (!settled) { settled = true; resolve(payload); } };
91
+ child.stdout.on('data', (chunk) => { stdout += String(chunk); });
92
+ child.stderr.on('data', (chunk) => { stderr += String(chunk); });
93
+ child.on('error', (error) => finish({ verdict: '', code: null, error: (error && error.message) || String(error) }));
94
+ child.on('close', (code, signal) => finish({
95
+ verdict: verdictOf(stdout),
96
+ code: Number.isInteger(code) ? code : null,
97
+ signal: signal || null,
98
+ stderr: stderr.trim(),
99
+ }));
100
+ });
101
+ }
102
+
103
+ /**
104
+ * One log line per tick, stamped with the caller's clock (`now`) so a 15-minute cadence is readable
105
+ * in a long log: the verdict when the child produced one, else why it did not.
106
+ */
107
+ function tickLine(at, result) {
108
+ const when = new Date(Number(at) || 0).toISOString();
109
+ const verdict = String((result && result.verdict) || '');
110
+ if (verdict) return `${when} origin-follow: sync ${verdict}`;
111
+ const detail = (result && result.error) || (result && result.signal) || `exit ${(result && result.code) == null ? '?' : result.code}`;
112
+ return `${when} origin-follow: sync unknown (${detail})`;
113
+ }
114
+
115
+ /** True iff `repoRoot` is a git work tree whose current branch is `main` (R-8: the fleet target). */
116
+ function isOnMain(repoRoot) {
117
+ try {
118
+ const inside = runGitRaw(repoRoot, ['rev-parse', '--is-inside-work-tree']);
119
+ if (inside.status !== 0 || inside.stdout.trim() !== 'true') return false;
120
+ const branch = runGitRaw(repoRoot, ['rev-parse', '--abbrev-ref', 'HEAD']);
121
+ return branch.status === 0 && branch.stdout.trim() === 'main';
122
+ } catch {
123
+ // HANDLE: no git on PATH, or a path that cannot be spawned in — "not a main checkout", which is
124
+ // the no-op answer, never a throw out of boot.
125
+ return false;
126
+ }
127
+ }
128
+
129
+ /**
130
+ * §6.5: arm the follower. Returns `{ stop(), started, reason, intervalMs }`; `started: false` with a
131
+ * `reason` means this process must not follow (see the module header). Never throws.
132
+ *
133
+ * Injected surfaces (all optional, production defaults in parentheses):
134
+ * loadConfig (lib/landing/config.js `loadTargetLandingConfig`) — read from the TARGET tree
135
+ * runLand (`runLandOnce`) — `({ repoRoot, timeoutMs, env, pullOnly }) -> Promise<{ verdict, code }>`
136
+ * resolverTick (lib/fleet-resolver-tick.js, WP-8) — `{ busy(), after() }`, both async
137
+ * setIntervalImpl (`setInterval`) — the ONE timer, unref'd when the host returns a Timeout
138
+ * now (`Date.now`) — the tick log's clock
139
+ * log (`console.log`) — one line per tick
140
+ */
141
+ function start({
142
+ repoRoot = '',
143
+ dataDir = '',
144
+ port = null,
145
+ env = process.env,
146
+ loadConfig = loadTargetLandingConfig,
147
+ runLand = runLandOnce,
148
+ resolverTick = null,
149
+ setIntervalImpl = setInterval,
150
+ now = Date.now,
151
+ log = (line) => console.log(line),
152
+ } = {}) {
153
+ const root = String(repoRoot || '');
154
+ // `land sync` schedules the idle restart only when its env names this CTM (CTM_DATA_DIR +
155
+ // CTM_PORT, lib/fleet-update.js scheduleLocalApply guard (a)). The process env cannot be trusted
156
+ // to carry them: the MacBook Pro's launchd plist sets CTM_PORT but not CTM_DATA_DIR (observed
157
+ // 2026-10-31; a `pulled` tick there ended restart.reason "no_env"). So the follower hands the child
158
+ // the values this server actually runs with. The follower keeps no state of its own: the verdict
159
+ // lives in the landing sync state, written by `land sync` itself.
160
+ const childEnv = { ...(env || {}) };
161
+ if (dataDir) childEnv.CTM_DATA_DIR = String(dataDir);
162
+ if (port != null && port !== '') childEnv.CTM_PORT = String(port);
163
+ const write = typeof log === 'function' ? log : () => {};
164
+
165
+ const noop = (reason) => ({ started: false, reason, intervalMs: 0, stop() {} });
166
+
167
+ const tag = String((env && env.CTM_INSTANCE_TAG) || '');
168
+ if (tag.startsWith('dev-')) return noop('dev_instance');
169
+
170
+ let config = null;
171
+ try {
172
+ config = loadConfig(root);
173
+ } catch (error) {
174
+ // HANDLE: not a repository, no target branch, or an unreadable/invalid `.ctm.json` — there is
175
+ // nothing to follow, and a boot must not fail over an optional background timer.
176
+ void error;
177
+ return noop('config_unreadable');
178
+ }
179
+ const publish = config && config.publish;
180
+ if (!publish) return noop('not_configured');
181
+ if (publish.follow !== true) return noop('follow_disabled');
182
+ if (!isOnMain(root)) return noop('not_main');
183
+
184
+ const intervalMs = Number.isInteger(publish.followIntervalMs) && publish.followIntervalMs > 0
185
+ ? publish.followIntervalMs
186
+ : DEFAULT_FOLLOW_INTERVAL_MS;
187
+
188
+ // §13.4 R-R1 (WP-8): `session` means this box's own resolver session handles a blocked sync, so the
189
+ // follower runs the FULL `land sync` (merge + gate + push a clean divergence) and arms the resolver
190
+ // hooks below. Anything else (including a missing `resolve` before WP-6 lands) keeps the rev-2
191
+ // `--pull-only` behaviour. The full sync is bounded by the gate's own timeout plus 10 min of slack,
192
+ // because it runs the configured gates inside the child.
193
+ const fullSync = publish.resolve === 'session';
194
+ const gate0 = Array.isArray(config.gates) ? config.gates[0] : null;
195
+ const gateTimeoutSeconds = (gate0 && Number(gate0.timeoutSeconds)) || 10800;
196
+ const timeoutMs = fullSync ? gateTimeoutSeconds * 1000 + 600000 : LAND_TIMEOUT_MS;
197
+ const ticker = resolverTick && typeof resolverTick === 'object' ? resolverTick : null;
198
+
199
+ let running = false;
200
+ let stopped = false;
201
+ const stamp = () => new Date(Number(now()) || 0).toISOString();
202
+
203
+ const tick = async () => {
204
+ if (stopped) return;
205
+ if (running) {
206
+ write(`${stamp()} origin-follow: skipped (previous tick still running)`);
207
+ return;
208
+ }
209
+ running = true;
210
+ try {
211
+ if (fullSync && ticker && typeof ticker.busy === 'function' && await ticker.busy()) {
212
+ // R-R7: a live resolver owns the slot — do not race it with a second land sync; still give
213
+ // it the same `after()` pass the ordinary path gets.
214
+ write(`${stamp()} origin-follow: skipped land sync (resolver active)`);
215
+ } else {
216
+ const result = await runLand({ repoRoot: root, timeoutMs, env: childEnv, pullOnly: !fullSync });
217
+ write(tickLine(Number(now()) || 0, result));
218
+ }
219
+ if (ticker && typeof ticker.after === 'function') await ticker.after();
220
+ } catch (error) {
221
+ // REPORT: a throwing runLand (or resolver hook) is one bad tick, logged with its verdict slot
222
+ // left empty; the timer keeps its cadence and the next tick retries.
223
+ write(`${stamp()} origin-follow: sync unknown (${(error && error.code) || 'error'}: ${(error && error.message) || error})`);
224
+ } finally {
225
+ running = false;
226
+ }
227
+ };
228
+
229
+ const timer = setIntervalImpl(() => { void tick(); }, intervalMs);
230
+ if (timer && typeof timer.unref === 'function') timer.unref();
231
+
232
+ return {
233
+ started: true,
234
+ reason: 'started',
235
+ intervalMs,
236
+ stop() {
237
+ stopped = true;
238
+ if (timer && typeof clearInterval === 'function') clearInterval(timer);
239
+ },
240
+ };
241
+ }
242
+
243
+ module.exports = {
244
+ DEFAULT_FOLLOW_INTERVAL_MS,
245
+ LAND_TIMEOUT_MS,
246
+ isOnMain,
247
+ landArgv,
248
+ landScriptPath,
249
+ runLandOnce,
250
+ start,
251
+ verdictOf,
252
+ };
@@ -0,0 +1,147 @@
1
+ 'use strict';
2
+ // WP-8 (docs/fleet-origin-main-sync-skill-2026-10-31.html §13.4 R-R2/R-R7/R-R8/R-R10, §13.7 S-R12) +
3
+ // WP-12 (§14.3 R-14.3/R-14.4/R-14.5): the resolver's EFFECTS — the four things lib/fleet-resolver.js
4
+ // `start()` needs to open a visible resolver session with its brief already submitted, plus
5
+ // `sessionAlive`. This is a new module on purpose: the wiring must not grow server.js past its
6
+ // file-size ceiling, so server.js only hands over the functions below.
7
+ //
8
+ // There is NO new session-create path here, and no queue:
9
+ //
10
+ // prepareWorkspace `_prepareCreatedSessionWorkspace` (server.js) — the same call best-of makes,
11
+ // plus a branch rename so the checkout lands on exactly `sync/origin-<tip12>`
12
+ // (the resolver lane the pre-commit hook matches on that string, WP-6).
13
+ // resolvePick `resolveSubagentPick` (lib/session-create/subagent-pick.js) — the delegate
14
+ // pick, i.e. the same model CTM would give a delegate worker, turned into argv
15
+ // (`--model <model>`; R-14.5).
16
+ // createSession `handleCreatePrepared(null, {…})` — the prepared-create entry point, with the
17
+ // brief as the CLI's POSITIONAL prompt argument (`args = [...argv, prompt]`,
18
+ // R-14.3). The rev-3 queue lane is gone: the queue engine writes text and never
19
+ // Enter (E-5), so a server-started session's prompt sat unsubmitted forever.
20
+ // No nudge, no queue, no timer, no race with TUI readiness (R-14.4).
21
+ // notify `dispatchMobileNotification(mobileNotifications.notifyWaitingInput(…))` — the
22
+ // R-R8 give-up ping.
23
+ //
24
+ // `server` is the object server.js passes in; every member is a function, so a test can supply
25
+ // fakes and never touch CTM.
26
+
27
+ const { runGitAsync } = require('./fleet-resolver-tick');
28
+ // R-15.5: the resolver and best-of share ONE launch-prompt shape (REPLACE IN PLACE) — the argv
29
+ // builder lives in lib/agent-capabilities.js beside the per-agent declaration it reads.
30
+ const { launchPromptArgv } = require('./agent-capabilities');
31
+
32
+ const WORKTREE_NAMESPACE = 'claude';
33
+ // §14.3 R-14.5: the model flag a Claude resolver gets when no native pick names a concrete model —
34
+ // the CLI's own "default" alias, which overrides a managed `opusplan` pin (E-6).
35
+ const CLAUDE_DEFAULT_MODEL_ARGV = Object.freeze(['--model', 'default']);
36
+ const CLAUDE_AGENT = 'claude';
37
+
38
+ function typedError(code, message) {
39
+ const error = new Error(message || code);
40
+ error.code = code;
41
+ return error;
42
+ }
43
+
44
+ /**
45
+ * Build the four effects (+ `sessionAlive`) from the server functions.
46
+ *
47
+ * `opts.runGit` is the async git runner used for the one branch check/rename; production omits it
48
+ * (lib/fleet-resolver-tick.js `runGitAsync`), a test injects a recorder.
49
+ */
50
+ function createResolverEffects(server = {}, { runGit = runGitAsync } = {}) {
51
+ const s = server || {};
52
+
53
+ /**
54
+ * R-R10: a fresh worktree based on `baseRef`, then force the branch name to EXACTLY `branchName`.
55
+ * The prepared-create path may pick its own name (or reuse a suffixed one); the resolver lane the
56
+ * pre-commit hook reads matches `sync/origin-*` literally, so a mismatch is renamed in place.
57
+ */
58
+ async function prepareWorkspace({ repoRoot, baseRef, worktreeName, branchName }) {
59
+ const id = s.randomUUID();
60
+ const workspace = await s.prepareCreatedSessionWorkspace(
61
+ { id, cwd: repoRoot, title: worktreeName },
62
+ { cwd: repoRoot, baseRef, worktreeName, branchName, namespace: WORKTREE_NAMESPACE },
63
+ );
64
+ const cwd = workspace && workspace.cwd ? workspace.cwd : '';
65
+ if (!cwd) throw typedError('workspace_failed', 'prepareWorkspace returned no worktree path');
66
+ if (branchName) {
67
+ const current = String(await runGit(['rev-parse', '--abbrev-ref', 'HEAD'], { cwd }) || '').trim();
68
+ if (current !== branchName) {
69
+ // `git -C <cwd> branch -m <branchName>` — an exact-match rename, never a checkout (the
70
+ // worktree is brand new, so the branch is not checked out anywhere else).
71
+ await runGit(['branch', '-m', branchName], { cwd });
72
+ }
73
+ }
74
+ return { cwd, branch: branchName || (workspace && workspace.branch) || '' };
75
+ }
76
+
77
+ /**
78
+ * OQ-R1 (decided) + §14.3 R-14.5: ONLY a native pick with a concrete model is honoured, and it
79
+ * rides the launch argv as `--model <model>`. A routed pick (or any error, or no pick) falls back
80
+ * to the agent's own default: for Claude that is the CLI's `default` alias — an EMPTY model id
81
+ * lets a managed `opusplan` pin win (E-6) — and for every other agent (codex et al.) no model flag
82
+ * at all, so the CLI's own config decides.
83
+ */
84
+ async function resolvePick({ agent }) {
85
+ try {
86
+ const pick = await s.resolveSubagentPick({ agent, ctmSessionId: '' });
87
+ if (pick && pick.kind === 'native' && pick.model) {
88
+ return { model: pick.model, source: pick.source || 'session', argv: ['--model', pick.model] };
89
+ }
90
+ } catch (error) {
91
+ /* REPORT: a failed pick read is not a reason to skip the resolver — the default model is fine */
92
+ void error;
93
+ }
94
+ if (String(agent || '') === CLAUDE_AGENT) {
95
+ return { model: '', source: 'cli_default_alias', argv: [...CLAUDE_DEFAULT_MODEL_ARGV] };
96
+ }
97
+ return { model: '', source: 'agent_default', argv: [] };
98
+ }
99
+
100
+ /**
101
+ * §14.3 R-14.3: the prepared-create entry point (same call best-of makes), then assert the session
102
+ * exists. `args` is `[...argv, prompt]`: the brief is the CLI's positional prompt operand, LAST,
103
+ * and it is never preceded by `--` (lib/create/resolve-launch-params.js declines its approval-hook
104
+ * injection for an argv whose real terminator is not last, :327). An empty prompt is a caller bug,
105
+ * not a session to open, so it throws `prompt_required`.
106
+ */
107
+ async function createSession({ cwd, agent, model, title, argv, prompt }) {
108
+ if (!prompt) throw typedError('prompt_required', 'a resolver session needs its brief as the launch prompt');
109
+ const id = s.randomUUID();
110
+ await s.handleCreatePrepared(null, {
111
+ id,
112
+ title,
113
+ label: title,
114
+ titleIntent: 'default',
115
+ cmd: agent,
116
+ args: [...(argv || []), ...launchPromptArgv(agent, prompt)],
117
+ cwd,
118
+ agentType: agent,
119
+ model_id: model || '',
120
+ });
121
+ if (!s.getSession(id)) throw typedError('session_start_failed', `session ${id} was not created`);
122
+ return { sessionId: id };
123
+ }
124
+
125
+ /** R-R8: one mobile "needs you" ping, plus a stderr line an operator reading the log sees. */
126
+ async function notify({ title, body, sessionId }) {
127
+ console.warn(`[fleet-resolver] ${title}: ${body}`);
128
+ if (!s.mobileNotifications || typeof s.dispatchMobileNotification !== 'function') return;
129
+ s.dispatchMobileNotification(s.mobileNotifications.notifyWaitingInput({
130
+ sessionId,
131
+ source: 'fleet-resolver',
132
+ privatePreview: `${title}: ${body}`,
133
+ stateKey: `fleet-resolver:${sessionId}`,
134
+ }));
135
+ }
136
+
137
+ /** R-R7: "is the resolver's session still in CTM's map" — the ONE liveness fact `decide()` reads. */
138
+ function sessionAlive(id) {
139
+ return Boolean(id && s.getSession(id));
140
+ }
141
+
142
+ return { prepareWorkspace, resolvePick, createSession, notify, sessionAlive };
143
+ }
144
+
145
+ module.exports = {
146
+ createResolverEffects,
147
+ };
@@ -0,0 +1,148 @@
1
+ 'use strict';
2
+ // WP-8 (docs/fleet-origin-main-sync-skill-2026-10-31.html §13.4 R-R1/R-R7/R-R8, §13.7 S-R10/S-R11):
3
+ // the CTM-side half of the fleet-sync resolver — the two hooks the origin follower calls on every
4
+ // tick: `busy()` (is a resolver already running on this box?) and `after()` (read the verdict the
5
+ // tick just wrote and act on it).
6
+ //
7
+ // This module owns NO decisions: `decide()`/`start()`/`apply()` live in lib/fleet-resolver.js and are
8
+ // pure/injected there (WP-7). Everything here is I/O — resolve the git common dir, read
9
+ // `<common>/landing/sync-state.json` and the job record it names, read `resolver.json`, and hand the
10
+ // three to `decide()`.
11
+ //
12
+ // Async I/O only, on purpose: this runs on CTM's main thread, so bin/main-thread-lint.js must never
13
+ // see a sync fs/child_process call here. The one git call (`rev-parse --git-common-dir`) goes through
14
+ // execFile promisified to a local alias, the same shape lib/codesign-identity.js uses.
15
+
16
+ const fsp = require('node:fs/promises');
17
+ const path = require('node:path');
18
+ const { execFile } = require('node:child_process');
19
+ const { promisify } = require('node:util');
20
+ const resolver = require('./fleet-resolver');
21
+
22
+ const execFileAsync = promisify(execFile);
23
+ // A rev-parse is local and instant; anything slower is a broken repo, not a slow one.
24
+ const GIT_TIMEOUT_MS = 5000;
25
+ // §13.4 R-R7: a `current` record in one of these states owns the box's resolver slot. Mirrors
26
+ // lib/fleet-resolver.js's own LIVE_STATES (not exported there — repeated rather than widening WP-7).
27
+ const LIVE_STATES = Object.freeze(['starting', 'resolving']);
28
+ // Queue/job ids are Crockford-base32 (`lib/landing/queue.js`); this only keeps a corrupt sync-state
29
+ // file from pointing the read at a path outside `<common>/landing/jobs/`.
30
+ const JOB_ID_RE = /^[A-Za-z0-9_-]+$/;
31
+
32
+ /** The one async git read this module needs: stdout, trimmed. Throws on a non-zero exit. */
33
+ async function runGitAsync(args, { cwd, timeout = GIT_TIMEOUT_MS } = {}) {
34
+ const { stdout } = await execFileAsync('git', args, { cwd, timeout, encoding: 'utf8' });
35
+ return String(stdout == null ? '' : stdout).trim();
36
+ }
37
+
38
+ // `--git-common-dir` cannot change while this process runs; memoize only successes, like
39
+ // lib/landing/git.js `commonDir`. Keyed by resolved repoRoot so a test can hand over a temp dir.
40
+ const COMMON_DIR_CACHE = new Map();
41
+
42
+ async function resolveCommonDir(repoRoot, runGit) {
43
+ const key = path.resolve(String(repoRoot || ''));
44
+ const cached = COMMON_DIR_CACHE.get(key);
45
+ if (cached !== undefined) return cached;
46
+ const value = await runGit(['rev-parse', '--path-format=absolute', '--git-common-dir'], { cwd: repoRoot });
47
+ const resolved = String(value == null ? '' : value).trim();
48
+ if (resolved) COMMON_DIR_CACHE.set(key, resolved);
49
+ return resolved;
50
+ }
51
+
52
+ /** Read and parse one JSON file; a missing or unreadable one is `null`, never a throw. */
53
+ async function readJson(file) {
54
+ let raw;
55
+ try {
56
+ raw = await fsp.readFile(file, 'utf8');
57
+ } catch (error) {
58
+ /* expected: the file has not been written yet (or is mid-rename) -> "nothing to read" */
59
+ void error;
60
+ return null;
61
+ }
62
+ try {
63
+ return JSON.parse(raw);
64
+ } catch (error) {
65
+ /* REPORT: a torn/corrupt state file must never stop the tick; the next write heals it */
66
+ void error;
67
+ return null;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * The follower's per-tick resolver hooks (injected into lib/fleet-origin-follower.js `start`).
73
+ *
74
+ * repoRoot the checkout whose `<common>/landing/` holds sync-state.json, resolver.json and jobs/;
75
+ * publish the normalized `config.publish` (`resolve`, `resolveAgent`, `resolveMaxMinutes`);
76
+ * deps the effects lib/fleet-resolver.js `start`/`apply` call, plus `sessionAlive(id)`;
77
+ * now the tick's clock (ms epoch), so `decide()` stays pure;
78
+ * log one line per resolver action;
79
+ * runGit injectable async git (`(args, { cwd }) -> stdout`) — production is `runGitAsync`.
80
+ *
81
+ * Returns `{ busy, after }`. Both resolve; a git/fs failure inside `busy()` reads as "not busy"
82
+ * (the tick then runs `land sync`, which is where the truth comes from), and a throw out of `after()`
83
+ * is caught by the follower and reported in its tick line.
84
+ */
85
+ function createResolverTick({ repoRoot = '', publish = null, deps = {}, now = Date.now, log = (line) => console.log(line), runGit = runGitAsync } = {}) {
86
+ const effects = deps || {};
87
+ let commonPromise = null;
88
+ const commonDir = () => {
89
+ if (!commonPromise) commonPromise = resolveCommonDir(repoRoot, runGit).catch((error) => {
90
+ /* HANDLE: an unresolvable common dir reads as "no landing state" — the tick just runs land sync */
91
+ void error;
92
+ return '';
93
+ });
94
+ return commonPromise;
95
+ };
96
+
97
+ /** R-R7: a live resolver (state `starting|resolving`) with a session CTM still holds owns the slot. */
98
+ async function busy() {
99
+ const common = await commonDir();
100
+ if (!common) return false;
101
+ const state = await resolver.readState(common);
102
+ const current = state && state.current;
103
+ if (!current || !LIVE_STATES.includes(current.state)) return false;
104
+ // WP-13: a /fleet-sync session that claimed this key is resolving it; the tick must not run land sync under it.
105
+ if (resolver.claimedBySession(current)) return true;
106
+ try {
107
+ return Boolean(await effects.sessionAlive(current.sessionId));
108
+ } catch (error) {
109
+ /* HANDLE: an unreadable session map reads as "not alive" -> not busy, so the tick runs land sync */
110
+ void error;
111
+ return false;
112
+ }
113
+ }
114
+
115
+ /** §13.4 R-R1/R-R7/R-R8: read the tick's verdict and execute whatever `decide()` says. */
116
+ async function after() {
117
+ const common = await commonDir();
118
+ if (!common) return;
119
+ const syncState = await readJson(path.join(common, 'landing', 'sync-state.json'));
120
+ if (!syncState || typeof syncState !== 'object') return; // no sync has run yet -> nothing to decide
121
+ const jobId = syncState.lastSync && syncState.lastSync.jobId ? String(syncState.lastSync.jobId) : '';
122
+ const job = jobId && JOB_ID_RE.test(jobId)
123
+ ? await readJson(path.join(common, 'landing', 'jobs', `${jobId}.json`))
124
+ : null;
125
+ const resolverState = await resolver.readState(common);
126
+ const decision = resolver.decide({
127
+ syncState,
128
+ resolverState,
129
+ job,
130
+ publish,
131
+ now: now(),
132
+ sessionAlive: effects.sessionAlive,
133
+ });
134
+ if (!decision || decision.action === 'none') return;
135
+ await resolver.apply({ decision, repoRoot, commonDir: common, deps: effects });
136
+ log(`origin-follow: resolver ${decision.action} (${decision.reason})`);
137
+ }
138
+
139
+ return { busy, after };
140
+ }
141
+
142
+ module.exports = {
143
+ GIT_TIMEOUT_MS,
144
+ LIVE_STATES,
145
+ createResolverTick,
146
+ resolveCommonDir,
147
+ runGitAsync,
148
+ };