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,399 @@
1
+ 'use strict';
2
+
3
+ // WP-2 (design doc coding-task-manager/docs/fsevents-churn-followups-r2-2026-10-26.html
4
+ // §5 D-4..D-6, §6, §8 WP-2, §9 S-11): the host fseventsd sampler.
5
+ //
6
+ // Why it exists: fseventsd reached 2262 MB RSS on 2026-10-26 (§1.1) and nothing in this repo
7
+ // recorded it. The parent AC-8d ("< 100 MB on 10-28") was unmeasurable and is superseded by
8
+ // D-5: prove the sampler is alive (>= 1 row/hour of primary uptime), parse every JetsamEvent,
9
+ // and attach a producer attribution to every growth event so "our trees are not the producer"
10
+ // is a number instead of a feeling.
11
+ //
12
+ // Rules it obeys (§5 D-6, §11 anti-goals):
13
+ // * read-only instrumentation: it never starts, signals or heals fseventsd, never calls
14
+ // sudo/vmmap/sample/footprint, and never deletes anything;
15
+ // * every child process is ASYNC (execFile with a timeout, never execFileSync);
16
+ // * a metric is `top -l 1 -pid <pid> -stats pid,mem,cmprs` (no sudo; ~2.5 s wall) — chosen
17
+ // over vmmap (it suspends the target) and ps RSS (it excludes compressed pages);
18
+ // * every failure becomes an `error` row in the log; tick() never throws into the server.
19
+ //
20
+ // It runs inside the primary CTM process (launchd com.walle.server, survives reboot) — see
21
+ // server.js's registration block, gated by shouldRunSampler().
22
+
23
+ const fs = require('node:fs');
24
+ const path = require('node:path');
25
+ const os = require('node:os');
26
+ const { execFile: defaultExecFile } = require('node:child_process');
27
+
28
+ const SAMPLE_INTERVAL_MS = 30 * 60_000;
29
+ const GROWTH_ATTRIBUTION_BYTES = 256 * 1024 * 1024;
30
+ const ATTRIBUTION_MIN_GAP_MS = 6 * 60 * 60_000;
31
+ // D-6: one `top` per sample, async, bounded.
32
+ const TOP_TIMEOUT_MS = 10000;
33
+ // §6: the attribution child runs `fs-event-census.js --seconds 30`, bounded at 60 s.
34
+ const ATTRIBUTION_TIMEOUT_MS = 60000;
35
+ const ATTRIBUTION_SECONDS = 30;
36
+ const ATTRIBUTION_MAX_BUFFER = 8 * 1024 * 1024;
37
+ const JETSAM_DIR = '/Library/Logs/DiagnosticReports';
38
+ // §6: `memoryStatus.pageSize` (16384 on Apple silicon); 16384 is the documented fallback.
39
+ const FALLBACK_PAGE_SIZE = 16384;
40
+ const DEFAULT_LOG_PATH = path.join(os.homedir(), '.walle', 'logs', 'host-fseventsd.jsonl');
41
+ const STATE_FILE_NAME = 'host-fseventsd.state.json';
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Gating (D-4). server.js inlines this condition (the doc's §6 snippet); the predicate is
45
+ // exported so the gating itself is unit-testable without booting a server.
46
+ // ---------------------------------------------------------------------------
47
+ function shouldRunSampler({ platform = process.platform, devPort = '', flag = '1' } = {}) {
48
+ return platform === 'darwin' && !devPort && String(flag) !== '0';
49
+ }
50
+
51
+ // ---------------------------------------------------------------------------
52
+ // parseTopLine (pure): the last line of
53
+ // top -l 1 -pid <pid> -stats pid,mem,cmprs
54
+ // looks like `29548 2262M 637M`. Units may be B/K/M/G and may carry a +/- delta marker
55
+ // (either side; the magnitude is what the row is about). Returns
56
+ // { pid, memBytes, cmprsBytes } or null (e.g. for the `PID MEM CMPrS` header).
57
+ // ---------------------------------------------------------------------------
58
+ const TOP_ROW_RE = /^(\d+)\s+([+-]?[\d.]+)\s*([BKMG])?([+-])?\s+([+-]?[\d.]+)\s*([BKMG])?([+-])?$/;
59
+ const UNIT_MULTIPLIERS = { B: 1, K: 1024, M: 1024 ** 2, G: 1024 ** 3 };
60
+
61
+ function unitToBytes(value, unit) {
62
+ const n = Math.abs(Number(value));
63
+ if (!Number.isFinite(n)) return null;
64
+ const multiplier = UNIT_MULTIPLIERS[String(unit || '').toUpperCase()] || 1;
65
+ return Math.round(n * multiplier);
66
+ }
67
+
68
+ function parseTopLine(line) {
69
+ const s = String(line === null || line === undefined ? '' : line).trim();
70
+ if (s === '') return null;
71
+ const m = s.match(TOP_ROW_RE);
72
+ if (!m) return null;
73
+ const memBytes = unitToBytes(m[2], m[3]);
74
+ const cmprsBytes = unitToBytes(m[5], m[6]);
75
+ if (memBytes === null || cmprsBytes === null) return null;
76
+ return { pid: Number(m[1]), memBytes, cmprsBytes };
77
+ }
78
+
79
+ function lastNonEmptyLine(text) {
80
+ const lines = String(text === null || text === undefined ? '' : text).split('\n');
81
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
82
+ if (lines[i].trim() !== '') return lines[i];
83
+ }
84
+ return '';
85
+ }
86
+
87
+ // ---------------------------------------------------------------------------
88
+ // sampleOnce: pgrep the pid, then one bounded async `top`.
89
+ // Returns { at, pid, memBytes, cmprsBytes, raw } or { at, error } — never throws.
90
+ // ---------------------------------------------------------------------------
91
+ function runChild(execFile, file, args, options) {
92
+ return new Promise((resolve, reject) => {
93
+ let settled = false;
94
+ const settle = (fn, value) => {
95
+ if (settled) return;
96
+ settled = true;
97
+ fn(value);
98
+ };
99
+ const callback = (err, stdout, stderr) => {
100
+ if (err) settle(reject, err);
101
+ else settle(resolve, { stdout: String(stdout === null || stdout === undefined ? '' : stdout), stderr: String(stderr === null || stderr === undefined ? '' : stderr) });
102
+ };
103
+ let returned;
104
+ try {
105
+ returned = execFile(file, args, options, callback);
106
+ } catch (err) {
107
+ settle(reject, err);
108
+ return;
109
+ }
110
+ // HANDLE: an injected promise-style stand-in (a test fake) resolves instead of calling
111
+ // back; accept either shape so the fake needs no callback plumbing.
112
+ if (returned && typeof returned.then === 'function') {
113
+ returned.then(
114
+ (value) => settle(resolve, {
115
+ stdout: String(value && value.stdout !== undefined ? value.stdout : (value === undefined ? '' : value)),
116
+ stderr: String(value && value.stderr !== undefined ? value.stderr : ''),
117
+ }),
118
+ (err) => settle(reject, err),
119
+ );
120
+ }
121
+ });
122
+ }
123
+
124
+ async function sampleOnce({ execFile = defaultExecFile, now = Date.now } = {}) {
125
+ const at = now();
126
+ try {
127
+ const pidOut = await runChild(execFile, 'pgrep', ['-x', 'fseventsd'], { timeout: TOP_TIMEOUT_MS });
128
+ const pid = Number(String(pidOut.stdout).trim().split('\n')[0]);
129
+ if (!Number.isFinite(pid) || pid <= 0) return { at, error: 'pgrep -x fseventsd returned no pid' };
130
+ const topOut = await runChild(
131
+ execFile,
132
+ 'top',
133
+ ['-l', '1', '-pid', String(pid), '-stats', 'pid,mem,cmprs'],
134
+ { timeout: TOP_TIMEOUT_MS },
135
+ );
136
+ const raw = lastNonEmptyLine(topOut.stdout);
137
+ const parsed = parseTopLine(raw);
138
+ if (!parsed) return { at, error: `unparsable top row ${JSON.stringify(raw)}` };
139
+ return { at, pid, memBytes: parsed.memBytes, cmprsBytes: parsed.cmprsBytes, raw };
140
+ } catch (err) {
141
+ return { at, error: String((err && err.message) || err) };
142
+ }
143
+ }
144
+
145
+ // ---------------------------------------------------------------------------
146
+ // readNewJetsam: every JetsamEvent-*.ips newer than `lastSeen`, oldest first.
147
+ // Format (§6): line 1 is a JSON header, the rest is one JSON body carrying
148
+ // memoryStatus.pageSize, largestProcess, date and processes[] entries with name/rpages.
149
+ // Returns [{ file, date, largestProcess, fseventsdBytes, pageSize }] — plus `error` when a
150
+ // single file could not be read or parsed (the caller turns that into an `error` row).
151
+ // ---------------------------------------------------------------------------
152
+ async function readNewJetsam({ dir = JETSAM_DIR, lastSeen = '', fsImpl = fs } = {}) {
153
+ const io = fsImpl && fsImpl.promises ? fsImpl.promises : fsImpl;
154
+ let names;
155
+ try {
156
+ names = await io.readdir(dir);
157
+ } catch (err) {
158
+ // HANDLE: a host with no JetsamEvent directory (or no read permission) simply has no
159
+ // reports to ingest; that is not a sampler failure.
160
+ if (err && (err.code === 'ENOENT' || err.code === 'EACCES' || err.code === 'EPERM' || err.code === 'ENOTDIR')) return [];
161
+ throw err; // RETHROW: EMFILE/EIO are real problems worth an error row.
162
+ }
163
+ const since = String(lastSeen || '');
164
+ const files = names
165
+ .filter((name) => /^JetsamEvent-.*\.ips$/.test(name) && name > since)
166
+ .sort();
167
+ const rows = [];
168
+ for (const file of files) {
169
+ rows.push(await readJetsamFile(dir, file, io));
170
+ }
171
+ return rows;
172
+ }
173
+
174
+ async function readJetsamFile(dir, file, io) {
175
+ const pageSizeFallback = { file, date: null, largestProcess: null, fseventsdBytes: null, pageSize: FALLBACK_PAGE_SIZE };
176
+ let text;
177
+ try {
178
+ text = String(await io.readFile(path.join(dir, file), 'utf8'));
179
+ } catch (err) {
180
+ return { ...pageSizeFallback, error: `read failed: ${(err && err.message) || err}` };
181
+ }
182
+ const newline = text.indexOf('\n');
183
+ const headerText = newline === -1 ? text : text.slice(0, newline);
184
+ const bodyText = newline === -1 ? '' : text.slice(newline + 1);
185
+ let header = null;
186
+ let body = null;
187
+ try {
188
+ header = JSON.parse(headerText);
189
+ } catch {
190
+ /* expected: a truncated/foreign .ips header must not abort the remaining reports */
191
+ }
192
+ try {
193
+ body = JSON.parse(bodyText);
194
+ } catch {
195
+ /* expected: a truncated/foreign .ips body is reported as a per-file error below */
196
+ }
197
+ if (!body || typeof body !== 'object') {
198
+ return { ...pageSizeFallback, date: (header && header.timestamp) || null, error: 'body is not JSON' };
199
+ }
200
+ const pageSize = Number(body.memoryStatus && body.memoryStatus.pageSize) || FALLBACK_PAGE_SIZE;
201
+ const processes = Array.isArray(body.processes) ? body.processes : [];
202
+ const entry = processes.find((row) => row && row.name === 'fseventsd');
203
+ const rpages = entry && Number(entry.rpages);
204
+ return {
205
+ file,
206
+ date: body.date || (header && header.timestamp) || null,
207
+ largestProcess: body.largestProcess === undefined ? null : body.largestProcess,
208
+ fseventsdBytes: Number.isFinite(rpages) ? rpages * pageSize : null,
209
+ pageSize,
210
+ lifetimeMax: entry && entry.lifetimeMax !== undefined ? entry.lifetimeMax : null,
211
+ };
212
+ }
213
+
214
+ // ---------------------------------------------------------------------------
215
+ // createSampler: append-only JSONL rows + a sibling state file so a restart keeps the growth
216
+ // baseline (and does not re-ingest every JetsamEvent again).
217
+ // { kind: 'sample', at, pid, memBytes, cmprsBytes }
218
+ // { kind: 'jetsam', at, file, date, largestProcess, fseventsdBytes }
219
+ // { kind: 'attribution', at, memBytes, deltaBytes, census: { total, perSecond, categories, families } }
220
+ // { kind: 'error', at, stage, message }
221
+ // ---------------------------------------------------------------------------
222
+ function defaultState() {
223
+ return { version: 1, lastJetsam: '', lastSample: null, lastAttributionAt: null, updatedAt: null };
224
+ }
225
+
226
+ function createSampler({
227
+ logPath = DEFAULT_LOG_PATH,
228
+ repoRoot,
229
+ now = Date.now,
230
+ execFile = defaultExecFile,
231
+ homeDir = os.homedir(),
232
+ tmpDir = os.tmpdir(),
233
+ jetsamDir = JETSAM_DIR,
234
+ } = {}) {
235
+ const resolvedLogPath = logPath;
236
+ const statePath = path.join(path.dirname(resolvedLogPath), STATE_FILE_NAME);
237
+ const root = repoRoot || path.resolve(__dirname, '..', '..');
238
+ let state = null;
239
+
240
+ async function appendRow(row) {
241
+ await fs.promises.mkdir(path.dirname(resolvedLogPath), { recursive: true });
242
+ await fs.promises.appendFile(resolvedLogPath, `${JSON.stringify(row)}\n`, { mode: 0o600 });
243
+ }
244
+
245
+ // REPORT: an unwritable log must not stop the sampler from trying again next tick, so the
246
+ // caller sees the failure through console.warn in the server's timer callback.
247
+ async function appendRowSafe(row) {
248
+ try {
249
+ await appendRow(row);
250
+ } catch (err) {
251
+ process.stderr.write(`[fseventsd-sampler] log write failed: ${(err && err.message) || err}\n`);
252
+ }
253
+ }
254
+
255
+ async function loadState() {
256
+ if (state) return state;
257
+ try {
258
+ const parsed = JSON.parse(String(await fs.promises.readFile(statePath, 'utf8')));
259
+ state = { ...defaultState(), ...parsed };
260
+ return state;
261
+ } catch (err) {
262
+ if (err && err.code !== 'ENOENT') {
263
+ await appendRowSafe({ kind: 'error', at: now(), stage: 'state-read', message: String((err && err.message) || err) });
264
+ }
265
+ state = defaultState();
266
+ return state;
267
+ }
268
+ }
269
+
270
+ async function saveState() {
271
+ const tmp = `${statePath}.${process.pid}.tmp`;
272
+ state.updatedAt = new Date(now()).toISOString();
273
+ await fs.promises.writeFile(tmp, `${JSON.stringify(state)}\n`, { mode: 0o600 });
274
+ await fs.promises.rename(tmp, statePath);
275
+ }
276
+
277
+ // The attribution snapshot: one census run over the three producers we own (§6, §1.2).
278
+ async function runAttributionCensus() {
279
+ const args = [
280
+ path.join(root, 'bin', 'fs-event-census.js'),
281
+ '--seconds', String(ATTRIBUTION_SECONDS),
282
+ '--json',
283
+ '--families',
284
+ '--root', tmpDir,
285
+ '--root', path.join(homeDir, '.walle'),
286
+ '--root', path.join(homeDir, 'ws'),
287
+ ];
288
+ const { stdout } = await runChild(execFile, process.execPath, args, {
289
+ timeout: ATTRIBUTION_TIMEOUT_MS,
290
+ maxBuffer: ATTRIBUTION_MAX_BUFFER,
291
+ });
292
+ const parsed = JSON.parse(stdout);
293
+ return {
294
+ total: parsed.total,
295
+ perSecond: parsed.perSecond,
296
+ categories: (Array.isArray(parsed.categories) ? parsed.categories : []).map((row) => ({
297
+ name: row.name, count: row.count, share: row.share, newUnique: row.newUnique,
298
+ })),
299
+ families: Array.isArray(parsed.families)
300
+ ? parsed.families.map((row) => ({ name: row.name, count: row.count, newUnique: row.newUnique }))
301
+ : [],
302
+ };
303
+ }
304
+
305
+ async function ingestJetsam(current) {
306
+ let rows;
307
+ try {
308
+ rows = await readNewJetsam({ dir: jetsamDir, lastSeen: current.lastJetsam });
309
+ } catch (err) {
310
+ await appendRowSafe({ kind: 'error', at: now(), stage: 'jetsam', message: String((err && err.message) || err) });
311
+ return;
312
+ }
313
+ for (const row of rows) {
314
+ if (row.error) {
315
+ await appendRowSafe({ kind: 'error', at: now(), stage: 'jetsam-parse', message: `${row.file}: ${row.error}` });
316
+ } else {
317
+ await appendRowSafe({
318
+ kind: 'jetsam',
319
+ at: now(),
320
+ file: row.file,
321
+ date: row.date,
322
+ largestProcess: row.largestProcess,
323
+ fseventsdBytes: row.fseventsdBytes,
324
+ });
325
+ }
326
+ // HANDLE: the name advances even for an unparsable report — .ips files are immutable,
327
+ // so re-reading one every 30 min would only repeat the same error row forever.
328
+ current.lastJetsam = row.file;
329
+ }
330
+ }
331
+
332
+ async function maybeAttribute(current, sample) {
333
+ const prev = current.lastSample;
334
+ if (!prev || !Number.isFinite(prev.memBytes) || !Number.isFinite(sample.memBytes)) return;
335
+ const deltaBytes = sample.memBytes - prev.memBytes;
336
+ if (deltaBytes <= GROWTH_ATTRIBUTION_BYTES) return;
337
+ if (current.lastAttributionAt !== null && sample.at - current.lastAttributionAt < ATTRIBUTION_MIN_GAP_MS) return;
338
+ try {
339
+ const census = await runAttributionCensus();
340
+ await appendRowSafe({ kind: 'attribution', at: sample.at, memBytes: sample.memBytes, deltaBytes, census });
341
+ current.lastAttributionAt = sample.at;
342
+ } catch (err) {
343
+ // REPORT: no attribution time is recorded, so the next sample retries (the 6 h gap only
344
+ // bounds successes, §6). The absence is visible as an `error` row beside the growth.
345
+ await appendRowSafe({ kind: 'error', at: sample.at, stage: 'attribution', message: String((err && err.message) || err) });
346
+ }
347
+ }
348
+
349
+ async function tick() {
350
+ let current;
351
+ let sample;
352
+ try {
353
+ current = await loadState();
354
+ sample = await sampleOnce({ execFile, now });
355
+ if (sample.error) {
356
+ await appendRowSafe({ kind: 'error', at: sample.at, stage: 'sample', message: sample.error });
357
+ return;
358
+ }
359
+ await appendRowSafe({ kind: 'sample', at: sample.at, pid: sample.pid, memBytes: sample.memBytes, cmprsBytes: sample.cmprsBytes });
360
+ await ingestJetsam(current);
361
+ await maybeAttribute(current, sample);
362
+ current.lastSample = { at: sample.at, memBytes: sample.memBytes };
363
+ await saveState();
364
+ } catch (err) {
365
+ // REPORT: tick() is called from a named interval and from a boot timer; a rejection
366
+ // there would only be logged by the caller, so it is recorded here as an error row.
367
+ await appendRowSafe({
368
+ kind: 'error',
369
+ at: now(),
370
+ stage: 'tick',
371
+ message: String((err && err.message) || err),
372
+ });
373
+ }
374
+ }
375
+
376
+ return {
377
+ tick,
378
+ // Test/ops surface (read-only): where rows and state live.
379
+ logPath: resolvedLogPath,
380
+ statePath,
381
+ loadState,
382
+ };
383
+ }
384
+
385
+ module.exports = {
386
+ SAMPLE_INTERVAL_MS,
387
+ GROWTH_ATTRIBUTION_BYTES,
388
+ ATTRIBUTION_MIN_GAP_MS,
389
+ ATTRIBUTION_SECONDS,
390
+ DEFAULT_LOG_PATH,
391
+ JETSAM_DIR,
392
+ STATE_FILE_NAME,
393
+ FALLBACK_PAGE_SIZE,
394
+ createSampler,
395
+ parseTopLine,
396
+ readNewJetsam,
397
+ sampleOnce,
398
+ shouldRunSampler,
399
+ };
@@ -33,22 +33,14 @@ function modelProcessGenerationMetadata(value) {
33
33
  return validModelProcessGeneration(value) ? { modelProcessGeneration: value } : {};
34
34
  }
35
35
  const MODEL_STORAGE_ROOT_KEYS = Object.freeze(['HOME', 'CODEX_HOME', 'CTM_CODEX_SESSIONS_DIR', 'CLAUDE_CONFIG_DIR', 'GEMINI_CLI_HOME', 'OPENCODE_DATA_DIR', 'XDG_DATA_HOME']);
36
- // The keys a lead-model switch re-projects into the launch context (lib/lead-model-restore-reconciliation.js
37
- // projectDeferredRestoreLaunch: HOME / CODEX_HOME from the launch context, TMPDIR alongside them). They are
38
- // PROJECTED launch context, not per-session private overrides: a spawn still receives them, but their presence
39
- // must never turn an otherwise empty override set into a private environment that only a surviving owner can
40
- // reproduce. Anything else in the env is private and is captured by value.
41
- const PROJECTED_LAUNCH_CONTEXT_KEYS = Object.freeze(['HOME', 'CODEX_HOME', 'TMPDIR']);
42
- // Returns a NEW object holding only the non-projected entries of `env`; never mutates its input and maps a
43
- // non-object to `{}`.
44
- function privateOverridesFromEnv(env) {
45
- if (!env || typeof env !== 'object' || Array.isArray(env)) return {};
46
- const out = {};
47
- for (const [key, value] of Object.entries(env)) {
48
- if (!PROJECTED_LAUNCH_CONTEXT_KEYS.includes(key)) out[key] = value;
49
- }
50
- return out;
51
- }
36
+ // WP-0: the projected keys and the strip moved to lib/launch-environment.js (§5 D-1); re-exported from here so
37
+ // the existing importers are unchanged. The keys a lead-model switch re-projects into the launch context
38
+ // (lib/lead-model-restore-reconciliation.js projectDeferredRestoreLaunch: HOME / CODEX_HOME from the launch
39
+ // context, TMPDIR alongside them) are PROJECTED launch context, not per-session private overrides: a spawn
40
+ // still receives them, but their presence must never turn an otherwise empty override set into a private
41
+ // environment that only a surviving owner can reproduce. Anything else in the env is private and is captured
42
+ // by value.
43
+ const { PROJECTED_LAUNCH_CONTEXT_KEYS, privateOverridesFromEnv, launchEnvironmentMetadata } = require('./launch-environment');
52
44
  function modelStorageRootsFromEnv(env) {
53
45
  const roots = {};
54
46
  for (const key of MODEL_STORAGE_ROOT_KEYS) {
@@ -67,8 +59,8 @@ function writeHandoffManifest(dir, oldHostId, entries, { manifestPath } = {}) {
67
59
  const target = manifestPath || path.join(dir, `handoff-${oldHostId}-${++manifestCounter}.json`);
68
60
  const tmp = `${target}.tmp-${process.pid}`;
69
61
  entries = entries.map((entry) => {
70
- const { modelProcessGeneration, modelStorageRoots, modelExecutionRecipe, ...base } = entry;
71
- return { ...base, ...modelProcessGenerationMetadata(modelProcessGeneration), ...modelStorageRootsMetadata(modelStorageRoots), ...modelExecutionRecipeMetadata(modelExecutionRecipe, { sessionId: entry.sessionId, processGeneration: modelProcessGeneration }) };
62
+ const { modelProcessGeneration, modelStorageRoots, modelExecutionRecipe, launchEnvironment, ...base } = entry;
63
+ return { ...base, ...modelProcessGenerationMetadata(modelProcessGeneration), ...modelStorageRootsMetadata(modelStorageRoots), ...modelExecutionRecipeMetadata(modelExecutionRecipe, { sessionId: entry.sessionId, processGeneration: modelProcessGeneration }), ...launchEnvironmentMetadata(launchEnvironment, { manifest: true }) };
72
64
  });
73
65
  fs.writeFileSync(tmp, JSON.stringify({ version: 1, oldHostId, entries }), { mode: 0o600 });
74
66
  fs.renameSync(tmp, target);
@@ -100,6 +92,10 @@ function readHandoffManifest(manifestPath) {
100
92
  const recipe = modelExecutionRecipeMetadata(entry.modelExecutionRecipe, { sessionId: entry.sessionId, processGeneration: entry.modelProcessGeneration });
101
93
  if (recipe.modelExecutionRecipe) entry.modelExecutionRecipe = recipe.modelExecutionRecipe;
102
94
  else delete entry.modelExecutionRecipe;
95
+ // WP-1 (S-11): a manifest written by an older host has no field at all -- absent stays absent.
96
+ const launchEnv = launchEnvironmentMetadata(entry.launchEnvironment, { manifest: true });
97
+ if (launchEnv.launchEnvironment) entry.launchEnvironment = launchEnv.launchEnvironment;
98
+ else delete entry.launchEnvironment;
103
99
  });
104
100
  fs.unlinkSync(manifestPath);
105
101
  return { entries: parsed.entries };
@@ -228,6 +224,7 @@ function createHandoff({ hostId, workerPath, controlSocketPath, listSessions, se
228
224
  ...modelProcessGenerationMetadata(s.modelProcessGeneration),
229
225
  ...modelStorageRootsMetadata(s.modelStorageRoots),
230
226
  ...modelExecutionRecipeMetadata(s.modelExecutionRecipe),
227
+ ...launchEnvironmentMetadata(s.launchEnvironment, { manifest: true }),
231
228
  // Identity only: the context also carries the runtime render cache (Sets/Maps JSON turns into {}).
232
229
  workerDisplayContext: s.workerDisplayContext ? { agentRole: s.workerDisplayContext.agentRole, _workerAgent: s.workerDisplayContext._workerAgent, cwd: s.workerDisplayContext.cwd } : null,
233
230
  suppressPtyHeadlessUntilInput: !!s.suppressPtyHeadlessUntilInput,
@@ -344,4 +341,4 @@ function createHandoff({ hostId, workerPath, controlSocketPath, listSessions, se
344
341
  return { intercept, restore, resumeRestored, isActive: () => !!active };
345
342
  }
346
343
 
347
- module.exports = { HANDOFF_SEAL_TIMEOUT_MS, handoffManifestFromArgv, writeHandoffManifest, readHandoffManifest, spawnSuccessorHost, createHandoff, validModelProcessGeneration, modelProcessGenerationFromEnv, modelProcessGenerationMetadata, modelStorageRootsFromEnv, modelStorageRootsMetadata, PROJECTED_LAUNCH_CONTEXT_KEYS, privateOverridesFromEnv };
344
+ module.exports = { HANDOFF_SEAL_TIMEOUT_MS, handoffManifestFromArgv, writeHandoffManifest, readHandoffManifest, spawnSuccessorHost, createHandoff, validModelProcessGeneration, modelProcessGenerationFromEnv, modelProcessGenerationMetadata, modelStorageRootsFromEnv, modelStorageRootsMetadata, PROJECTED_LAUNCH_CONTEXT_KEYS, privateOverridesFromEnv, launchEnvironmentMetadata };