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,495 @@
1
+ 'use strict';
2
+
3
+ // Landing-throughput WP-6 shard S16 (design doc §5 D-10 "move-only", §6 "Shard module
4
+ // seam"): the Wall-E row-history cluster moves out of server.js VERBATIM into this module
5
+ // behind the same configure(deps) seam as lib/api/session-attach.js and
6
+ // lib/terminal-attach-geometry.js (S6), lib/walle-history-serve.js (S8),
7
+ // lib/codex-rollout-history.js (S9), lib/terminal-input-prepared.js (S10), lib/idle-notify.js
8
+ // (S11), lib/session-park.js (S12), lib/terminal-draft-operation.js (S13) and
9
+ // lib/conversation-freshness-diagnostics.js (S14). It registers NO route and NO socket handler:
10
+ // server.js keeps the call sites as walleRowHistory.<name>(...) and this configure() seam.
11
+ // Bodies are identical to the server.js declarations except for the `_deps.` prefix on every
12
+ // identifier that used to resolve to a server.js top-level binding (D-10 rule 1), proven by
13
+ // `node bin/move-only-check.js`. Three inline `require('./lib/...')` calls are rebased to this
14
+ // module's own `require('./...')` (S8 precedent: one move-only DIFF per rebased require -- the
15
+ // remainder is proven by re-running against a copy with
16
+ // `sed "s#require('\./#require('./lib/#g"` applied).
17
+ //
18
+ // The module deliberately lives at lib/walle-row-history.js and NOT under lib/ws/: these are the
19
+ // durable per-message row store readers/shaper, not ws-router handlers.
20
+ //
21
+ // Injected deps, per function:
22
+ // _walleRowHistoryForCtmId: CTM_SESSION_ROWS_ENABLED, _fetchSessionMessagesArrayOffThread, _fetchWalleHistoryMetaOffThread, _handleWalleProjectionReadResult, _loadWalleHistoryOffThread, _noteWalleHistoryReadMiss, _offthreadRead, _resolveWalleHistorySource, _scheduleWalleSessionRowsCatchUp, _walleHistoryMigrationRuntime, _walleHistoryWindowBreaker, _walleSessionRowsFreshness, catchUpKind, classifyReadPoolMiss, dbModule, errorSink, isRenderableWalleHistoryWindow, recordSessionDiagnostic, rowCursorRegistry, walleConversationCacheFreshness
23
+ // _walleHistoryForReview: (none)
24
+ // _appendWalleUserRowAtSubmit: _notifyConversationUpdated, _runCtmDbWorkerOp, walleTranscript
25
+ // _walleProgressTranscriptPart: redactSecrets
26
+ //
27
+ // Mutable module state (D-10 rule 2 / S9 lesson 7): _walleHistoryMigrationRuntime is a server.js
28
+ // `let` reassigned during boot, so it is injected as a GETTER -- never a copy. No moved body
29
+ // ASSIGNS a server.js top-level binding, so this seam carries no get/set pair. Every other dep is
30
+ // a by-value reference (all declared before the seam's configure() call). Calls between the moved
31
+ // functions stay direct (no `_deps.`): _appendWalleUserRowAtSubmit calls _walleHistoryForReview.
32
+
33
+ let _deps = null;
34
+
35
+ function configure(deps = {}) {
36
+ _deps = deps;
37
+ }
38
+
39
+ // Wall-E chat history from CTM's durable per-message store (session_message_rows), keyed on the
40
+ // CANONICAL ctmSessionId (one id; no agentSessionId/ctmSessionId split that drifts). Returns the
41
+ // review-shaped messages when rows are present and fresh vs the live JSONL (a cheap file-size
42
+ // metadata check on the same canonical id; no provider JSONL body parse). Projection admission
43
+ // controls branch mode only: stale/invalid manifests still return complete row pages for audit-mode
44
+ // rendering. This is the post-blob-retirement display source of truth.
45
+ async function _walleRowHistoryForCtmId(source, {
46
+ offset = 0,
47
+ limit = 0,
48
+ before = '',
49
+ afterCursor = '',
50
+ around = '',
51
+ after = '',
52
+ projectionEpoch = 0,
53
+ orderingEpoch = 0,
54
+ allowStale = false,
55
+ budget = null,
56
+ budgetRung = 'window',
57
+ } = {}) {
58
+ if (!_deps.CTM_SESSION_ROWS_ENABLED || !source?.ctmSessionId) return { __miss: 'meta_unavailable' };
59
+ try {
60
+ const id = source.ctmSessionId;
61
+ const rowFreshness = _deps._walleSessionRowsFreshness(source);
62
+ _deps._walleHistoryMigrationRuntime?.raisePriority(id, 0);
63
+ let selectedWindow = null;
64
+ if (limit > 0) {
65
+ const windowTimeoutMs = budget ? budget.timeoutFor(budgetRung) : 8_000;
66
+ if (windowTimeoutMs <= 0) return { __miss: 'budget_exhausted' };
67
+ selectedWindow = await _deps._offthreadRead({
68
+ breaker: _deps._walleHistoryWindowBreaker,
69
+ op: 'getWalleHistoryWindow',
70
+ timeoutMs: windowTimeoutMs,
71
+ requestClass: 'interactive',
72
+ strictTimeout: true,
73
+ payload: {
74
+ dbPath: _deps.dbModule.getDbPath(),
75
+ sessionId: id,
76
+ offset,
77
+ limit,
78
+ before,
79
+ afterCursor,
80
+ around,
81
+ after,
82
+ projectionEpoch,
83
+ orderingEpoch,
84
+ // This is an authority grant, not a display preference: only the exact source-cursor
85
+ // proof may let the rich structured projection supersede the canonical text view.
86
+ preferRichProjection: rowFreshness.fresh,
87
+ telemetryReason: 'walle-history-window',
88
+ },
89
+ onSuccess: (result) => result,
90
+ onFail: (error) => {
91
+ const reason = _deps.classifyReadPoolMiss(error);
92
+ _deps._noteWalleHistoryReadMiss(error);
93
+ _deps.errorSink.report('walle-history:window-read', error, { sessionId: id, reason });
94
+ return { __miss: reason };
95
+ },
96
+ });
97
+ if (selectedWindow?.__miss) return selectedWindow;
98
+ // Active, partial-v2, AND active structured-projection pages are self-proving through the
99
+ // cutover ledger and exact v2 cursor. They bypass legacy row/file freshness, which is no
100
+ // longer an authority after activation, but a measured source-cursor lag still keeps the
101
+ // page in catch-up lifecycle. 'structured-projection' (walle-history-source-selection.js)
102
+ // is granted ONLY when the cutover is 'active' and the exact v2 cursor already proved
103
+ // coverage (options.preferRichProjection === true), so it is exactly as self-proving as a
104
+ // plain 'v2' window -- review round 2: it was falling through to the legacy gates below,
105
+ // which compare a row-store byte count against the growing jsonl and false-positive
106
+ // 'freshness_gate' during any running turn.
107
+ if (selectedWindow?.sourceAuthority === 'v2'
108
+ || selectedWindow?.sourceAuthority === 'v2-partial'
109
+ || selectedWindow?.sourceAuthority === 'structured-projection') {
110
+ // D-1/S-2 (WP-0): a v2 window still importing (kind 'partial') is a real miss and
111
+ // falls to the stale lane exactly as before. A merely LAGGING v2 window (kind 'lag')
112
+ // is not a miss -- it is complete-to-its-cursor history that carries its own
113
+ // catch-up lifecycle markers so the caller can serve it from THIS read, without a
114
+ // second stale-lane read, an unconditional catch-up import, or a degraded diagnostic.
115
+ // catchUpKind returns 'none' for 'structured-projection' (it only classifies 'v2'/
116
+ // 'v2-partial'), so it is always served as a normal settled page here -- correct, since
117
+ // the rich projection is only granted when rows are already proven fresh.
118
+ const kind = _deps.catchUpKind(selectedWindow, rowFreshness);
119
+ if (kind === 'partial' && !allowStale) return { __miss: 'freshness_gate' };
120
+ if (kind === 'lag') {
121
+ selectedWindow.catchingUp = true;
122
+ selectedWindow.lag = {
123
+ bytes: rowFreshness.lagBytes,
124
+ seconds: rowFreshness.lagSeconds,
125
+ state: 'rows_behind_cursor',
126
+ };
127
+ }
128
+ // A structured-projection window is where the inline repair manifest / forced
129
+ // structural rebuild lives (_handleWalleProjectionReadResult) -- the legacy path below
130
+ // used to call it for every serve; preserve that here since this window no longer
131
+ // reaches the legacy path at all. A plain v2 window never called it and still doesn't.
132
+ if (selectedWindow?.sourceAuthority === 'structured-projection') {
133
+ await _deps._handleWalleProjectionReadResult(id, selectedWindow);
134
+ }
135
+ // D-1 (WP-1, walle-history-source-selection.js): a proven-empty v2 window vs a non-empty transcript is the wedge this design fixes.
136
+ if (require('./env-flags').boolFlag('CTM_WALLE_SOURCE_AUTHORITY', true)) { const emptyMiss = await require('./walle-history-source-selection').detectWalleProjectionEmptyMiss(selectedWindow, source, _deps._resolveWalleHistorySource, _deps._scheduleWalleSessionRowsCatchUp, _deps.recordSessionDiagnostic, allowStale ? _deps._loadWalleHistoryOffThread : null); if (emptyMiss) return emptyMiss; }
137
+ // D-6 (WP-0): this early v2/structured-projection branch's own non-renderable label --
138
+ // NOT the legacy meta_unavailable sites below, which stay untouched.
139
+ return _deps.isRenderableWalleHistoryWindow(selectedWindow)
140
+ ? selectedWindow : { __miss: 'window_unrenderable' };
141
+ }
142
+ }
143
+ // S-3 (review round 2): this legacy row/file-size freshness gate only runs for a session
144
+ // whose v2 cutover is NOT active (sourceAuthority 'legacy' or no v2 authority at all) --
145
+ // that is import-incomplete, not lag, and is unaffected by D-1's catch-up kinds. Once
146
+ // cutover is active, the v2 cursor (or structured-projection's cursor-proven coverage,
147
+ // above) is the sole authority; this file_size-vs-jsonlSize comparison is stale evidence
148
+ // that would false-positive 'freshness_gate' while the jsonl keeps growing mid-turn.
149
+ const cursor = _deps.rowCursorRegistry.get(source.agentSessionId || source.chatSessionId || id)
150
+ || _deps.rowCursorRegistry.get(id);
151
+ if (!allowStale && (!cursor || !rowFreshness.fresh)) return { __miss: 'freshness_gate' };
152
+ const fileStat = cursor
153
+ ? { size: Math.max(0, Number(cursor.jsonlSize || 0)), mtimeMs: Number(cursor.jsonlMtimeMs || 0) }
154
+ : null;
155
+ const metaTimeoutMs = budget ? budget.timeoutFor('meta') : 2_500;
156
+ const meta = await _deps._fetchWalleHistoryMetaOffThread(id, metaTimeoutMs);
157
+ if (meta?.__miss) return meta;
158
+ if (!meta) return { __miss: 'meta_unavailable' };
159
+ if (!allowStale && !_deps.walleConversationCacheFreshness(meta, source, fileStat).fresh) {
160
+ return { __miss: 'freshness_gate' };
161
+ }
162
+ if (limit > 0) {
163
+ await _deps._handleWalleProjectionReadResult(id, selectedWindow);
164
+ return _deps.isRenderableWalleHistoryWindow(selectedWindow)
165
+ ? selectedWindow : { __miss: 'meta_unavailable' };
166
+ }
167
+ // Legacy callers still request a full array. Probe projection truth through the same
168
+ // off-thread reader before serving it so this path participates in read repair without
169
+ // unconditionally spending a repair-budget slot for healthy sessions.
170
+ const projectionProbe = await _deps._offthreadRead({
171
+ breaker: _deps._walleHistoryWindowBreaker,
172
+ op: 'getWalleHistoryWindow',
173
+ timeoutMs: budget ? Math.max(250, budget.timeoutFor(budgetRung)) : 2500,
174
+ requestClass: 'interactive',
175
+ strictTimeout: true,
176
+ payload: {
177
+ dbPath: _deps.dbModule.getDbPath(),
178
+ sessionId: id,
179
+ offset: 0,
180
+ limit: 1,
181
+ telemetryReason: 'walle-history-full-array-projection-probe',
182
+ },
183
+ onSuccess: (result) => result,
184
+ onFail: (error) => {
185
+ const reason = _deps.classifyReadPoolMiss(error);
186
+ _deps.errorSink.report('walle-history:full-array-projection-probe', error, {
187
+ sessionId: id,
188
+ reason,
189
+ });
190
+ return { __miss: reason };
191
+ },
192
+ });
193
+ if (!projectionProbe?.__miss) await _deps._handleWalleProjectionReadResult(id, projectionProbe);
194
+ const rows = await _deps._fetchSessionMessagesArrayOffThread(id, {
195
+ allowMainFallback: false,
196
+ reason: 'walle-row-history',
197
+ // D-3 (WP-2 item 5): this is the Wall-E resume/attach path -- a live-connected
198
+ // viewer is waiting on this exact array. Background readers of the same helper
199
+ // (standup summary's cursor-local-store/direct-conversation/cache-detailed
200
+ // reasons) intentionally do not pass this.
201
+ requestClass: 'interactive',
202
+ });
203
+ return Array.isArray(rows) && rows.length > 0 ? rows : { __miss: 'meta_unavailable' };
204
+ } catch (error) {
205
+ _deps._noteWalleHistoryReadMiss(error);
206
+ return { __miss: _deps.classifyReadPoolMiss(error) };
207
+ }
208
+ }
209
+
210
+ function _walleHistoryForReview(history) {
211
+ // Shared lib shaper: the targeted walle importer (api-prompts) writes rows
212
+ // through the SAME projection, so the render store has a single schema.
213
+ return require('./walle-ctm-history').walleHistoryForReview(history);
214
+ }
215
+
216
+ // WI-1 (RC-1 fix): append ONE review-shaped user row to session_message_rows, under the
217
+ // canonical ctm id, at Wall-E prompt SUBMIT time — before the turn runs. Without this the
218
+ // durable row store has no trace of the current turn (and, after a restart, no trace of the
219
+ // session at all — RC-1) until the turn-close sync (_syncWalleDurableRowsAfterTurn) or a cold
220
+ // rebuild runs, so a client that (re)attaches mid-turn sees nothing even after the turn
221
+ // finishes. Projects the just-appended user JSONL record through the SAME
222
+ // _walleHistoryForReview shaper every other rows-writer uses, so identity (message_uuid) and
223
+ // shape match a later full re-projection and the two writes dedupe cleanly. The DB-owner
224
+ // worker is the only commit path; failure records freshness debt and the turn-close sync heals it.
225
+ function _appendWalleUserRowAtSubmit(session, userAppend) {
226
+ if (!session || !session.id || !userAppend || !userAppend.record) return;
227
+ const record = userAppend.record;
228
+ const historyItem = {
229
+ role: 'user',
230
+ content: _deps.walleTranscript.extractText(record.message && record.message.content),
231
+ timestamp: record.timestamp || 0,
232
+ uuid: record.uuid || undefined,
233
+ parentUuid: record.parentUuid != null ? record.parentUuid : undefined,
234
+ };
235
+ if (record.branchEdit === true || record.forkedFromMessageId || record.branchId) {
236
+ historyItem.metadata = {
237
+ branchEdit: record.branchEdit === true,
238
+ forkedFromMessageId: String(record.forkedFromMessageId || ''),
239
+ branchId: String(record.branchId || ''),
240
+ };
241
+ }
242
+ if (record.attachments) historyItem.attachments = record.attachments;
243
+ let reviewRows;
244
+ try {
245
+ reviewRows = _walleHistoryForReview([historyItem]);
246
+ } catch (e) {
247
+ console.error('[walle-session] user-row projection error:', e.message);
248
+ return;
249
+ }
250
+ if (!Array.isArray(reviewRows) || reviewRows.length === 0) return;
251
+ const sessionId = session.id;
252
+ const row = reviewRows[0];
253
+ const appendEvidence = {
254
+ locator: String(userAppend.filePath || ''),
255
+ byteStart: Math.max(0, Number(userAppend.offset || 0)),
256
+ byteEnd: Math.max(0, Number(userAppend.offset || 0) + Number(userAppend.bytes || 0)),
257
+ uuid: String(userAppend.uuid || record.uuid || ''),
258
+ };
259
+ const afterAppend = (res) => {
260
+ if (res && res.ok && !res.skipped) {
261
+ _deps._notifyConversationUpdated(sessionId, { reason: 'walle-user-submit', inserted: 1 });
262
+ }
263
+ };
264
+ _deps._runCtmDbWorkerOp('appendWalleUserRow', {
265
+ sessionId,
266
+ logicalSessionKey: session.chatSessionId || session.agentSessionId || sessionId,
267
+ row,
268
+ appendEvidence,
269
+ }, { priority: 'urgent', timeoutMs: 15 * 1000 })
270
+ .then(afterAppend)
271
+ .catch((err) => {
272
+ // Worker unavailability creates durable catch-up debt; never activate a main-thread writer.
273
+ if (err && err.code !== 'CTM_DB_OWNER_WORKER_DEGRADED') {
274
+ console.error('[walle-session] off-thread user-row append failed:', err.message);
275
+ }
276
+ });
277
+ }
278
+
279
+ function _walleProgressTranscriptPart(event) {
280
+ if (!event || typeof event !== 'object') return null;
281
+ if (event.type === 'thinking') {
282
+ return {
283
+ partType: 'thinking',
284
+ data: { turn: event.turn || null, text: typeof event.text === 'string' ? event.text : '' },
285
+ };
286
+ }
287
+ // text_delta/reasoning_delta are durably written by Wall-E's embedded stream
288
+ // processor. This mirror must not add a second writer for those event types.
289
+ if (event.type === 'model_selected') {
290
+ return {
291
+ partType: 'model',
292
+ data: {
293
+ model: event.model || event.model_id || '',
294
+ provider: event.provider || '',
295
+ },
296
+ };
297
+ }
298
+ if (event.type === 'tool_call') {
299
+ // The stream processor re-emits raw events whose call fields live under
300
+ // event.data — reading only the top level wrote one EMPTY tool_call twin
301
+ // per narration/thinking part (junk "tool" rows on reload).
302
+ const call = event.data && typeof event.data === 'object' ? event.data : {};
303
+ const id = event.id || event.tool_call_id || event.toolCallId
304
+ || call.id || call.tool_call_id || call.toolCallId || '';
305
+ const name = event.name || event.tool || call.name || call.tool || '';
306
+ const input = event.input || event.arguments || call.input || call.args || null;
307
+ const summary = event.summary || call.summary || '';
308
+ if (!id && !name && input == null && !summary) return null;
309
+ return {
310
+ partType: 'tool_call',
311
+ data: { id, name, input, summary },
312
+ };
313
+ }
314
+ if (event.type === 'tool_result') {
315
+ const call = event.data && typeof event.data === 'object' ? event.data : {};
316
+ return {
317
+ partType: 'tool_result',
318
+ data: {
319
+ id: event.id || event.tool_call_id || event.toolCallId
320
+ || call.id || call.tool_call_id || call.toolCallId || '',
321
+ name: event.name || event.tool || call.name || call.tool || '',
322
+ result: event.result || event.output || call.result || call.output || '',
323
+ summary: event.summary || call.summary || '',
324
+ error: event.error || call.error || null,
325
+ },
326
+ };
327
+ }
328
+ if (event.type === 'skill_loaded' || event.type === 'skill_load_failed') {
329
+ return {
330
+ partType: event.type,
331
+ data: {
332
+ skill: event.skill || event.input?.skill_name || '',
333
+ input: event.input || event.args || null,
334
+ summary: event.summary || '',
335
+ source: event.source || '',
336
+ prefix: event.prefix || '',
337
+ agentType: event.agentType || event.agent_type || '',
338
+ error: event.error || '',
339
+ },
340
+ };
341
+ }
342
+ if (event.type === 'coding_summary') {
343
+ const activity = event.activity && typeof event.activity === 'object'
344
+ ? {
345
+ toolCount: Number(event.activity.toolCount || 0),
346
+ sources: Array.isArray(event.activity.sources)
347
+ ? event.activity.sources.slice(0, 12).map((source) => ({
348
+ tool: String(source && source.tool || ''),
349
+ detail: String(source && source.detail || ''),
350
+ })).filter((source) => source.tool || source.detail)
351
+ : [],
352
+ }
353
+ : null;
354
+ // Deterministic actionable summary (status · changed files · preview URLs
355
+ // and read-only activity/source evidence).
356
+ // Persisted so the pinned summary card survives a reload — attached to the
357
+ // turn's assistant message during history assembly (walle-ctm-history.js).
358
+ return {
359
+ partType: 'coding_summary',
360
+ data: {
361
+ status: event.status || '',
362
+ reason: event.reason || '',
363
+ verified: !!event.verified,
364
+ cwd: event.cwd || '',
365
+ changedFiles: Array.isArray(event.changedFiles) ? event.changedFiles : [],
366
+ previewUrls: Array.isArray(event.previewUrls) ? event.previewUrls : [],
367
+ activity,
368
+ },
369
+ };
370
+ }
371
+ if (event.type === 'retry') {
372
+ const detail = event.detail && typeof event.detail === 'object' ? event.detail : {};
373
+ return {
374
+ partType: 'status',
375
+ data: {
376
+ type: 'retry',
377
+ status: 'retrying',
378
+ message: event.message || '',
379
+ step: event.step,
380
+ channel: detail.channel || event.channel || '',
381
+ attempt: Number(detail.attempt || event.attempt || 0),
382
+ stepMax: Number(detail.stepMax || 0),
383
+ runRetries: Number(detail.runRetries || 0),
384
+ runMax: Number(detail.runMax || 0),
385
+ delayMs: Number(detail.delayMs || 0),
386
+ deadlineMs: Number(detail.deadlineMs || 0),
387
+ },
388
+ };
389
+ }
390
+ if (event.type === 'slow_provider') {
391
+ const detail = event.detail && typeof event.detail === 'object' ? event.detail : {};
392
+ return {
393
+ partType: 'status',
394
+ data: {
395
+ type: 'slow_provider',
396
+ status: 'waiting',
397
+ message: event.message || '',
398
+ provider: event.provider || '',
399
+ model: event.model || '',
400
+ kind: detail.kind || '',
401
+ elapsedMs: Number(detail.elapsedMs || 0),
402
+ thresholdMs: Number(detail.thresholdMs || 0),
403
+ timeoutMs: Number(detail.timeoutMs || 0),
404
+ },
405
+ };
406
+ }
407
+ if (event.type === 'provider_attempt_error') {
408
+ return {
409
+ partType: 'provider_attempt_error',
410
+ data: {
411
+ attempt: Number(event.attempt || 0),
412
+ message: event.message || event.error || 'Provider attempt failed',
413
+ rawError: event.rawError || '',
414
+ providerError: event.providerError || null,
415
+ messageId: event.messageId || '',
416
+ threadId: event.threadId || '',
417
+ turnId: event.turnId || '',
418
+ },
419
+ };
420
+ }
421
+ if (event.type === 'cancelled') return { partType: 'cancelled', data: {} };
422
+ // WP-2 (walle-silent-cli-turn-and-history-source-livelock, 2026-09-05): the codex
423
+ // CLI-fallback lane (wall-e/agent-runners/codex.js) now streams its own progress
424
+ // during the run instead of staying silent until exit — without a mapping here
425
+ // those events were broadcast live (see emitWalleProgress's unconditional
426
+ // broadcastToSession above) but never durably written, so a reload lost them.
427
+ // Reuse the SAME tool_call/tool_result partTypes the 'tool_call'/'tool_result'
428
+ // branches above already render, rather than inventing a parallel card shape.
429
+ if (event.type === 'cli_fallback_tool') {
430
+ const toolCall = event.toolCall && typeof event.toolCall === 'object' ? event.toolCall : {};
431
+ const id = String(toolCall.toolCallId || toolCall.id || '');
432
+ const name = String(toolCall.name || 'cli.tool');
433
+ if (toolCall.status === 'in_progress') {
434
+ return { partType: 'tool_call', data: { id, name, input: toolCall.input || null, summary: `Running ${name}` } };
435
+ }
436
+ const failed = toolCall.status === 'failed';
437
+ // Security follow-up (review round 1): raw CLI tool output can echo back
438
+ // credentials (a captured header, a token the tool was passed) — scrub
439
+ // before this reaches the durable transcript, same as the failureDetail
440
+ // sink already does on the wall-e side.
441
+ const output = _deps.redactSecrets(toolCall.result && typeof toolCall.result === 'object' ? String(toolCall.result.output || '') : '');
442
+ return {
443
+ partType: 'tool_result',
444
+ data: {
445
+ id,
446
+ name,
447
+ result: output,
448
+ summary: `${failed ? 'Failed' : 'Completed'} ${name}`,
449
+ error: failed ? output : null,
450
+ },
451
+ };
452
+ }
453
+ // A "Reconnecting..." notice is a transient CLI-transport retry, not a failure
454
+ // (see the codex `exec --json` contract note in agent-runners/codex.js) — surface
455
+ // it via the same 'status' partType the existing 'retry'/'slow_provider' branches
456
+ // above already use. Security follow-up: the notice text is raw CLI error
457
+ // output (the live incident this WP closes was a 401 quoted verbatim in one)
458
+ // — scrub before slicing/persisting.
459
+ if (event.type === 'cli_fallback_notice') {
460
+ return {
461
+ partType: 'status',
462
+ data: {
463
+ type: 'cli_fallback_notice',
464
+ status: 'waiting',
465
+ message: _deps.redactSecrets(String(event.message || '')).slice(0, 500),
466
+ phase: event.phase || '',
467
+ },
468
+ };
469
+ }
470
+ // The CLI-fallback lane's final agent_message, narrated as it arrives. This is
471
+ // NOT the durable answer-writing path (the coding turn's normal completion
472
+ // machinery still writes the turn's actual assistant message/coding_summary) —
473
+ // it is a live narration marker so the UI stops looking silent for the whole
474
+ // run, matching what the in-process (text_delta) lane already provides.
475
+ // Security follow-up: scrub before slicing/persisting, same reasoning as above.
476
+ if (event.type === 'cli_fallback_message') {
477
+ return {
478
+ partType: 'status',
479
+ data: {
480
+ type: 'cli_fallback_message',
481
+ status: 'done',
482
+ message: _deps.redactSecrets(String(event.text || '')).slice(0, 2000),
483
+ phase: event.phase || '',
484
+ },
485
+ };
486
+ }
487
+ return null;
488
+ }
489
+ module.exports = {
490
+ configure,
491
+ _walleRowHistoryForCtmId,
492
+ _walleHistoryForReview,
493
+ _appendWalleUserRowAtSubmit,
494
+ _walleProgressTranscriptPart,
495
+ };
@@ -22,6 +22,7 @@ const { isPrimaryInstance: isPrimaryCtmInstance } = require('./ctm-boot-lifecycl
22
22
  // D-3/D-4: a same-title ps row is never enough on its own — see
23
23
  // lib/walle-kill-authority.js for why (untagged non-primary instances share
24
24
  // the primary's exact "Wall-E" title).
25
+ const { orphanParentPids } = require('../../shared/orphan-parents'); // WP-12 (S-29)
25
26
  const { isOwnedRow, indexRowsByPid, logSkippedForeignPids } = require('./walle-kill-authority');
26
27
  const {
27
28
  checkWalleNativeDeps,
@@ -234,6 +235,7 @@ function commandInvokesScriptUnderRoot(command, rootMarker) {
234
235
 
235
236
  const defaultProcessOps = {
236
237
  pid: process.pid,
238
+ orphanParentPids,
237
239
  kill: (pid, signal) => process.kill(pid, signal),
238
240
  findListeningPidsByExactCommand,
239
241
  getProcessUptime,
@@ -1583,6 +1585,8 @@ function createWalleSupervisor({
1583
1585
  // D-3/D-4 (kill authority): a same-title process is only ever signalled
1584
1586
  // when it's OURS — spawned by this supervisor (ppid===myPid) or reparented
1585
1587
  // to init after a crash (ppid===1). Never by title alone; never myPid.
1588
+ // WP-12 (S-29): pids an orphan is re-parented to ({1} on macOS; + the systemd --user subreaper on Linux).
1589
+ const orphanParentSet = () => (typeof processOps.orphanParentPids === 'function' ? processOps.orphanParentPids() : orphanParentPids());
1586
1590
  async function collectManagedPids() {
1587
1591
  const myPid = processOps.pid || process.pid;
1588
1592
  const pidSet = new Set();
@@ -1603,7 +1607,8 @@ function createWalleSupervisor({
1603
1607
 
1604
1608
  const titles = new Set(processTitles());
1605
1609
  const byPid = indexRowsByPid(rows);
1606
- const owned = (row) => isOwnedRow(row, { titles, myPid });
1610
+ const orphanParents = orphanParentSet();
1611
+ const owned = (row) => isOwnedRow(row, { titles, myPid, orphanParents });
1607
1612
  const skippedByPid = new Map();
1608
1613
 
1609
1614
  let savedPid = null;
@@ -1663,6 +1668,7 @@ function createWalleSupervisor({
1663
1668
  const myPid = processOps.pid || process.pid;
1664
1669
  const rootMarker = path.resolve(walleDir());
1665
1670
  const titles = new Set(processTitles());
1671
+ const orphanParents = orphanParentSet();
1666
1672
  const gatewaySurviveOn = String(process.env['WALLE_MCP_GATEWAY_SURVIVE'] ?? '') !== '0';
1667
1673
  // adoptedPid included as defense-in-depth (B11): an adopted daemon has
1668
1674
  // ppid==1 and matches the instance signature — never casually reap it while
@@ -1693,7 +1699,7 @@ function createWalleSupervisor({
1693
1699
  const command = String(row.command || '');
1694
1700
  if (!Number.isInteger(pid) || pid <= 1) continue;
1695
1701
  if (excluded.has(pid)) continue;
1696
- if (!Number.isInteger(ppid) || ppid !== 1) continue;
1702
+ if (!Number.isInteger(ppid) || !orphanParents.has(ppid)) continue;
1697
1703
  if (!(titles.has(command) || commandInvokesScriptUnderRoot(command, rootMarker))) continue;
1698
1704
  // WP-3/S-9 (docs/mcp-startup-blackout-restart-storm-2026-08-21.html): the
1699
1705
  // gateway worker deliberately outlives its parent for adoption under this
@@ -2033,6 +2039,22 @@ function createWalleSupervisor({
2033
2039
  scheduleRestart(delayMs, 'auto-restart');
2034
2040
  }
2035
2041
 
2042
+ // WP-2 (D-5): the exec the daemon runs as — pure + synchronous, so it answers identically
2043
+ // whether the daemon was spawned by us or adopted from a pid file. The FDA hint must name
2044
+ // the real exec on both paths (see walleExecPath in the returned object).
2045
+ function resolveWalleExec() {
2046
+ // Spawn from the Wall-E .app bundle's node exec when present so the daemon shows
2047
+ // its icon + name in macOS Activity Monitor (the bundle's node is an ABI-matched
2048
+ // clone created by create-walle). Falls back to process.execPath otherwise.
2049
+ let walleExec = process.execPath;
2050
+ if (process.platform === 'darwin') {
2051
+ const bundleRoot = process.env.WALLE_BUNDLE_DIR || path.join(os.homedir(), '.walle', 'bundles');
2052
+ const bundleExec = path.join(bundleRoot, 'Wall-E.app', 'Contents', 'MacOS', 'Wall-E');
2053
+ try { if (fs.existsSync(bundleExec)) walleExec = bundleExec; } catch { /* expected: best-effort bundled-binary probe; any fs error leaves walleExec at its already-resolved default */ }
2054
+ }
2055
+ return walleExec;
2056
+ }
2057
+
2036
2058
  function spawnWalle(source) {
2037
2059
  // WP-S3 (B11): a real spawn always supersedes/ends any adopted-daemon
2038
2060
  // tracking — childPid (set below) takes over as the sole supervision
@@ -2105,15 +2127,9 @@ function createWalleSupervisor({
2105
2127
  delete childEnv.CTM_PROCESS_ROLE;
2106
2128
  if (walleToken) childEnv.WALL_E_API_TOKEN = walleToken;
2107
2129
 
2108
- // Spawn from the Wall-E .app bundle's node exec when present so the daemon shows
2109
- // its icon + name in macOS Activity Monitor (the bundle's node is an ABI-matched
2110
- // clone created by create-walle). Falls back to process.execPath otherwise.
2111
- let walleExec = process.execPath;
2112
- if (process.platform === 'darwin') {
2113
- const bundleRoot = process.env.WALLE_BUNDLE_DIR || path.join(os.homedir(), '.walle', 'bundles');
2114
- const bundleExec = path.join(bundleRoot, 'Wall-E.app', 'Contents', 'MacOS', 'Wall-E');
2115
- try { if (fs.existsSync(bundleExec)) walleExec = bundleExec; } catch { /* expected: best-effort bundled-binary probe; any fs error leaves walleExec at its already-resolved default */ }
2116
- }
2130
+ // WP-2 (D-5): one resolution shared with walleExecPath() below, so the spawn and the
2131
+ // FDA hint can never name different execs.
2132
+ const walleExec = resolveWalleExec();
2117
2133
 
2118
2134
  let nextChild;
2119
2135
  try {
@@ -2496,7 +2512,7 @@ function createWalleSupervisor({
2496
2512
  ? (await processOps.listPidsWithPpid() || []).filter((row) => row.pid === savedPid) : await listPidRow(savedPid);
2497
2513
  } catch { /* expected: best-effort per-pid ownership probe; a failure leaves savedRows=null, so the saved pid is never (wrongly) adopted */ }
2498
2514
  const savedRow = Array.isArray(savedRows) ? indexRowsByPid(savedRows).get(savedPid) : undefined;
2499
- if (isOwnedRow(savedRow, { titles, myPid })) {
2515
+ if (isOwnedRow(savedRow, { titles, myPid, orphanParents: orphanParentSet() })) {
2500
2516
  // WP-S3 (B11): this pid was NOT spawned by us this process lifetime —
2501
2517
  // adopt it into the same supervision the interval monitor gives a real
2502
2518
  // child (arm the monitor if it isn't already, and start tracking it so
@@ -2517,7 +2533,8 @@ function createWalleSupervisor({
2517
2533
  // A null snapshot is a FAILED probe, not "no Wall-E process" (nothing can be owned, so
2518
2534
  // only the not-running return below can see it) — report it instead of reading as empty.
2519
2535
  const psFailedFlag = Array.isArray(rows) ? {} : { ps_snapshot_failed: true };
2520
- const owned = (pid) => isOwnedRow(byPid.get(pid), { titles, myPid });
2536
+ const orphanParents = orphanParentSet();
2537
+ const owned = (pid) => isOwnedRow(byPid.get(pid), { titles, myPid, orphanParents });
2521
2538
 
2522
2539
  let discovered = [];
2523
2540
  try {
@@ -2678,7 +2695,7 @@ function createWalleSupervisor({
2678
2695
  rows = processOps.listPidsWithPpid ? await processOps.listPidsWithPpid() : await listPidsWithPpid();
2679
2696
  } catch { /* expected: best-effort ownership snapshot; a failed ps leaves rows=null (below), so the saved pid is never (wrongly) treated as our orphan */ }
2680
2697
  const row = Array.isArray(rows) ? indexRowsByPid(rows).get(saved) : undefined;
2681
- if (isOwnedRow(row, { titles, myPid })) {
2698
+ if (isOwnedRow(row, { titles, myPid, orphanParents: orphanParentSet() })) {
2682
2699
  orphanPid = saved;
2683
2700
  } else {
2684
2701
  staleForeignPid = saved;
@@ -2941,6 +2958,8 @@ function createWalleSupervisor({
2941
2958
  stopMcpReadinessMonitor,
2942
2959
  stopForProcessExit,
2943
2960
  spawnWalle,
2961
+ // WP-2 (D-5): the exec identity an FDA grant must name (pure; no spawn required).
2962
+ walleExecPath: resolveWalleExec,
2944
2963
  waitForMcpReady,
2945
2964
  };
2946
2965
  }