create-walle 0.10.1 → 0.10.2

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 (341) hide show
  1. package/README.md +4 -0
  2. package/lib/owner-write-safety.js +135 -0
  3. package/lib/public-runtime.js +13 -5
  4. package/lib/release-schema.json +3 -2
  5. package/lib/runtime-closure-policy.json +6 -4
  6. package/package.json +1 -1
  7. package/template/bin/deps-doctor.js +1 -1
  8. package/template/bin/node-bin.sh +11 -0
  9. package/template/coding-task-manager/api-prompts.js +10 -22
  10. package/template/coding-task-manager/bin/claude-hook.js +7 -3
  11. package/template/coding-task-manager/bin/claude-table-parity.js +307 -0
  12. package/template/coding-task-manager/bin/conversation-storage-auto-migration-lib.js +16 -1
  13. package/template/coding-task-manager/bin/conversation-storage-generation-evidence.js +9 -2
  14. package/template/coding-task-manager/bin/conversation-storage-service-entry-lib.js +16 -1
  15. package/template/coding-task-manager/bin/conversation-storage-walle-owner.js +247 -0
  16. package/template/coding-task-manager/bin/ctm-machine-pair.js +160 -0
  17. package/template/coding-task-manager/bin/lead-wait-census.js +1348 -0
  18. package/template/coding-task-manager/bin/repair-foreign-clone.js +564 -0
  19. package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
  20. package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
  21. package/template/coding-task-manager/db.js +705 -286
  22. package/template/coding-task-manager/git-utils.js +44 -0
  23. package/template/coding-task-manager/lib/adopted-host-redial.js +4 -0
  24. package/template/coding-task-manager/lib/agent-presets.js +15 -0
  25. package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
  26. package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
  27. package/template/coding-task-manager/lib/api/host-stats.js +98 -0
  28. package/template/coding-task-manager/lib/api/ingress.js +35 -12
  29. package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
  30. package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
  31. package/template/coding-task-manager/lib/api/machines.js +461 -0
  32. package/template/coding-task-manager/lib/api/misc-ops.js +20 -5
  33. package/template/coding-task-manager/lib/api/providers.js +53 -6
  34. package/template/coding-task-manager/lib/api/resume-from-store.js +25 -0
  35. package/template/coding-task-manager/lib/api/sessions.js +160 -8
  36. package/template/coding-task-manager/lib/api/transcript-history.js +17 -4
  37. package/template/coding-task-manager/lib/api/worktrees.js +38 -37
  38. package/template/coding-task-manager/lib/approval-drift.js +16 -1
  39. package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
  40. package/template/coding-task-manager/lib/approval-scope.js +68 -4
  41. package/template/coding-task-manager/lib/auth-context.js +32 -2
  42. package/template/coding-task-manager/lib/auth-rate-limit.js +41 -1
  43. package/template/coding-task-manager/lib/auth-rules.js +186 -45
  44. package/template/coding-task-manager/lib/broadcast-serialize.js +2 -1
  45. package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
  46. package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
  47. package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
  48. package/template/coding-task-manager/lib/claude-session-title.js +6 -30
  49. package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
  50. package/template/coding-task-manager/lib/client-diag-handler.js +5 -0
  51. package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
  52. package/template/coding-task-manager/lib/codex-harness-qualification.js +12 -0
  53. package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
  54. package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
  55. package/template/coding-task-manager/lib/codex-paths.js +2 -1
  56. package/template/coding-task-manager/lib/coding-agent-models.js +21 -30
  57. package/template/coding-task-manager/lib/coding-session-model-adapters.js +27 -2
  58. package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
  59. package/template/coding-task-manager/lib/coding-session-model-runtime.js +1 -2
  60. package/template/coding-task-manager/lib/coding-session-model-state.js +10 -0
  61. package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
  62. package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -0
  63. package/template/coding-task-manager/lib/create/resolve-launch-params.js +8 -1
  64. package/template/coding-task-manager/lib/ctm-boot-lifecycle.js +17 -1
  65. package/template/coding-task-manager/lib/db-domain-tables.js +7 -0
  66. package/template/coding-task-manager/lib/db-domains.js +21 -2
  67. package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -0
  68. package/template/coding-task-manager/lib/db-schema-source-files.js +1 -0
  69. package/template/coding-task-manager/lib/feature-manifest.js +1 -1
  70. package/template/coding-task-manager/lib/fs-watcher.js +3 -2
  71. package/template/coding-task-manager/lib/harness-history-transition.js +3 -3
  72. package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
  73. package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
  74. package/template/coding-task-manager/lib/headless-term-service.js +55 -17
  75. package/template/coding-task-manager/lib/host-control-dial.js +167 -0
  76. package/template/coding-task-manager/lib/host-handoff-orchestrator.js +16 -2
  77. package/template/coding-task-manager/lib/host-handoff.js +51 -13
  78. package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
  79. package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
  80. package/template/coding-task-manager/lib/host-stats.js +328 -0
  81. package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
  82. package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
  83. package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
  84. package/template/coding-task-manager/lib/hosted-sync-worker.js +113 -5
  85. package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +4 -0
  86. package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
  87. package/template/coding-task-manager/lib/instance-manifest.js +13 -1
  88. package/template/coding-task-manager/lib/instance-sync-status.js +15 -0
  89. package/template/coding-task-manager/lib/launch-model-override.js +160 -1
  90. package/template/coding-task-manager/lib/launch-plan-worker.js +59 -2
  91. package/template/coding-task-manager/lib/lead-model-switch-runtime.js +57 -4
  92. package/template/coding-task-manager/lib/lead-model-switch.js +3 -2
  93. package/template/coding-task-manager/lib/lead-model-transition-store.js +61 -3
  94. package/template/coding-task-manager/lib/legacy-draft-cancellation-recovery.js +111 -0
  95. package/template/coding-task-manager/lib/login-tripwire.js +1 -0
  96. package/template/coding-task-manager/lib/machine-pairing.js +238 -0
  97. package/template/coding-task-manager/lib/machine-pool.js +409 -0
  98. package/template/coding-task-manager/lib/machine-registry.js +749 -0
  99. package/template/coding-task-manager/lib/machine-self.js +66 -0
  100. package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +52 -4
  101. package/template/coding-task-manager/lib/media-journal-control-reader.js +473 -0
  102. package/template/coding-task-manager/lib/media-journal.js +84 -27
  103. package/template/coding-task-manager/lib/media-store-options.js +43 -15
  104. package/template/coding-task-manager/lib/migrations/v56-host-samples-and-machine-pool.js +76 -0
  105. package/template/coding-task-manager/lib/mirror-feed-sanitize.js +12 -3
  106. package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
  107. package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
  108. package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
  109. package/template/coding-task-manager/lib/model-proxy/lead-worker-picks.js +25 -0
  110. package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
  111. package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
  112. package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -0
  113. package/template/coding-task-manager/lib/model-proxy/stream-accounting.js +205 -0
  114. package/template/coding-task-manager/lib/model-proxy/tokens.js +78 -0
  115. package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
  116. package/template/coding-task-manager/lib/native-history-control.js +2 -2
  117. package/template/coding-task-manager/lib/native-lead-settings-client.js +2 -1
  118. package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
  119. package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +628 -64
  120. package/template/coding-task-manager/lib/owner-action-manifest-data.json +14 -0
  121. package/template/coding-task-manager/lib/painted-row-recorder.js +9 -1
  122. package/template/coding-task-manager/lib/prompt-submission-contract.js +21 -1
  123. package/template/coding-task-manager/lib/provider-login-broker.js +192 -9
  124. package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
  125. package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
  126. package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
  127. package/template/coding-task-manager/lib/read-pool-client.js +5 -2
  128. package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
  129. package/template/coding-task-manager/lib/recent-catalog-query.js +26 -0
  130. package/template/coding-task-manager/lib/recent-session-catalog-response.js +9 -0
  131. package/template/coding-task-manager/lib/remote-command-context.js +12 -0
  132. package/template/coding-task-manager/lib/remote-command-runtime.js +13 -1
  133. package/template/coding-task-manager/lib/remote-machine-catalog.js +1062 -0
  134. package/template/coding-task-manager/lib/remote-machine-create.js +693 -0
  135. package/template/coding-task-manager/lib/remote-machine-link.js +939 -0
  136. package/template/coding-task-manager/lib/remote-machine-proxy.js +520 -0
  137. package/template/coding-task-manager/lib/remote-session-forward.js +306 -0
  138. package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
  139. package/template/coding-task-manager/lib/restart-outcome-truth.js +20 -3
  140. package/template/coding-task-manager/lib/restart-preflight.js +9 -2
  141. package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
  142. package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
  143. package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
  144. package/template/coding-task-manager/lib/resume-blocked-wire.js +62 -1
  145. package/template/coding-task-manager/lib/resume-cwd.js +13 -0
  146. package/template/coding-task-manager/lib/resume-from-store.js +12 -1
  147. package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
  148. package/template/coding-task-manager/lib/resume-preflight.js +21 -16
  149. package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
  150. package/template/coding-task-manager/lib/review-repo-registry.js +17 -0
  151. package/template/coding-task-manager/lib/root-delivery-runtime.js +72 -15
  152. package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
  153. package/template/coding-task-manager/lib/root-prompt-admission.js +33 -2
  154. package/template/coding-task-manager/lib/root-prompt-flow.js +167 -33
  155. package/template/coding-task-manager/lib/scrollback-archive-store.js +7 -4
  156. package/template/coding-task-manager/lib/session-analysis-memory.js +2 -0
  157. package/template/coding-task-manager/lib/session-create/codex-native-provider-gate.js +218 -0
  158. package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
  159. package/template/coding-task-manager/lib/session-create/delegate-worker.js +95 -6
  160. package/template/coding-task-manager/lib/session-create/identity.js +20 -1
  161. package/template/coding-task-manager/lib/session-create/prepared.js +69 -1
  162. package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
  163. package/template/coding-task-manager/lib/session-create/provider-process.js +34 -37
  164. package/template/coding-task-manager/lib/session-create/response.js +30 -12
  165. package/template/coding-task-manager/lib/session-create/transcript.js +13 -4
  166. package/template/coding-task-manager/lib/session-create/worker-continuation.js +43 -1
  167. package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
  168. package/template/coding-task-manager/lib/session-create/worker-observability.js +99 -7
  169. package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
  170. package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
  171. package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
  172. package/template/coding-task-manager/lib/session-host-manager.js +152 -206
  173. package/template/coding-task-manager/lib/session-jobs.js +17 -9
  174. package/template/coding-task-manager/lib/session-lifecycle.js +18 -0
  175. package/template/coding-task-manager/lib/session-model-action-preconditions.js +9 -0
  176. package/template/coding-task-manager/lib/session-resource-sampler.js +19 -9
  177. package/template/coding-task-manager/lib/session-standup.js +67 -4
  178. package/template/coding-task-manager/lib/session-status-ledger.js +42 -3
  179. package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
  180. package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
  181. package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
  182. package/template/coding-task-manager/lib/startup-pointer-write.js +57 -0
  183. package/template/coding-task-manager/lib/state-sync/painted-frame-field.js +11 -0
  184. package/template/coding-task-manager/lib/storage/coding-session-model-store.js +21 -22
  185. package/template/coding-task-manager/lib/surviving-owner-bootstrap.js +7 -2
  186. package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
  187. package/template/coding-task-manager/lib/terminal-draft-http-status.js +25 -0
  188. package/template/coding-task-manager/lib/transcript-archiver.js +229 -229
  189. package/template/coding-task-manager/lib/transcript-frame-cache.js +12 -2
  190. package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
  191. package/template/coding-task-manager/lib/transcript-link.js +77 -0
  192. package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
  193. package/template/coding-task-manager/lib/transcript-source.js +8 -3
  194. package/template/coding-task-manager/lib/transcript-store.js +40 -0
  195. package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
  196. package/template/coding-task-manager/lib/typing-interaction-trace.js +92 -0
  197. package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
  198. package/template/coding-task-manager/lib/visible-revision-watchdog.js +8 -12
  199. package/template/coding-task-manager/lib/wake-skip-reasons.js +46 -0
  200. package/template/coding-task-manager/lib/walle-supervisor.js +98 -14
  201. package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
  202. package/template/coding-task-manager/lib/ws/state-sync.js +19 -2
  203. package/template/coding-task-manager/lib/ws/terminal-attach.js +32 -1
  204. package/template/coding-task-manager/lib/ws-router.js +68 -1
  205. package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
  206. package/template/coding-task-manager/oauth-proxy.js +99 -55
  207. package/template/coding-task-manager/package-lock.json +24 -0
  208. package/template/coding-task-manager/package.json +3 -0
  209. package/template/coding-task-manager/providers/codex-mcp-extract.js +121 -19
  210. package/template/coding-task-manager/providers/codex-mcp.js +14 -5
  211. package/template/coding-task-manager/public/css/app.css +279 -1
  212. package/template/coding-task-manager/public/css/reviews.css +4 -0
  213. package/template/coding-task-manager/public/index.html +294 -223
  214. package/template/coding-task-manager/public/js/app/machines-page.js +1252 -0
  215. package/template/coding-task-manager/public/js/app/models-tab.js +546 -36
  216. package/template/coding-task-manager/public/js/app/worktrees-panel.js +7 -5
  217. package/template/coding-task-manager/public/js/background-work.js +13 -7
  218. package/template/coding-task-manager/public/js/coding-session-model-presentation.js +44 -4
  219. package/template/coding-task-manager/public/js/core/session-commands.js +676 -0
  220. package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
  221. package/template/coding-task-manager/public/js/history-app-seam.js +26 -2
  222. package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
  223. package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
  224. package/template/coding-task-manager/public/js/history-scroller.js +187 -9
  225. package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
  226. package/template/coding-task-manager/public/js/machine-pool-shared.js +436 -0
  227. package/template/coding-task-manager/public/js/private-state-scope.js +31 -3
  228. package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -8
  229. package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
  230. package/template/coding-task-manager/public/js/queue-panel-submission-reconcile.js +174 -1
  231. package/template/coding-task-manager/public/js/reviews.js +7 -3
  232. package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
  233. package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
  234. package/template/coding-task-manager/public/js/row-join.js +4 -2
  235. package/template/coding-task-manager/public/js/session-model-picker.js +1 -1
  236. package/template/coding-task-manager/public/js/session-search-utils.js +46 -19
  237. package/template/coding-task-manager/public/js/state-sync-client.js +4 -0
  238. package/template/coding-task-manager/public/js/terminal/runtime-02.js +16 -7
  239. package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
  240. package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
  241. package/template/coding-task-manager/public/js/terminal/runtime-12.js +52 -2
  242. package/template/coding-task-manager/public/js/terminal/runtime-16.js +12 -12
  243. package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
  244. package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
  245. package/template/coding-task-manager/public/js/terminal/runtime-20.js +210 -73
  246. package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
  247. package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
  248. package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -1
  249. package/template/coding-task-manager/public/js/terminal-wheel.js +39 -2
  250. package/template/coding-task-manager/public/js/walle/chat-conversation.js +11 -3
  251. package/template/coding-task-manager/public/js/walle-session.js +30 -7
  252. package/template/coding-task-manager/public/m/app.css +226 -8
  253. package/template/coding-task-manager/public/m/app.js +502 -9
  254. package/template/coding-task-manager/public/m/index.html +38 -1
  255. package/template/coding-task-manager/public/m/machines.js +1313 -0
  256. package/template/coding-task-manager/public/m/pool-failover.js +391 -0
  257. package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
  258. package/template/coding-task-manager/public/m/sw.js +5 -0
  259. package/template/coding-task-manager/queue-engine.js +13 -0
  260. package/template/coding-task-manager/server/approvals.js +5 -6
  261. package/template/coding-task-manager/server/boot.js +136 -17
  262. package/template/coding-task-manager/server.js +902 -239
  263. package/template/coding-task-manager/session-integrity.js +7 -9
  264. package/template/coding-task-manager/workers/db-owner-worker.js +53 -7
  265. package/template/coding-task-manager/workers/read-pool-worker.js +17 -6
  266. package/template/coding-task-manager/workers/session-host-pool-process.js +18 -4
  267. package/template/coding-task-manager/workers/session-host-process.js +14 -3
  268. package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
  269. package/template/coding-task-manager/workers/worktree-worker.js +34 -0
  270. package/template/package-lock.json +2 -2
  271. package/template/package.json +1 -1
  272. package/template/scripts/conversation-storage-v2-migration.js +78 -11
  273. package/template/shared/conversation-storage-v2-contract.js +42 -6
  274. package/template/shared/fixtures/worker-status-payloads.json +392 -0
  275. package/template/shared/git-remote-key.js +83 -0
  276. package/template/shared/host-identity.js +98 -2
  277. package/template/shared/owner-write-safety.js +135 -0
  278. package/template/shared/public-runtime.js +13 -5
  279. package/template/shared/release-schema.json +3 -2
  280. package/template/shared/report-citations.js +14 -0
  281. package/template/shared/sqlite-write-lock.js +361 -223
  282. package/template/shared/storage/contract.js +35 -3
  283. package/template/wall-e/agent.js +21 -0
  284. package/template/wall-e/api-walle.js +5 -0
  285. package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
  286. package/template/wall-e/bin/walle-mcp-stdio.js +12 -6
  287. package/template/wall-e/brain/helper-rules-schema.js +129 -0
  288. package/template/wall-e/brain/migrations.js +51 -22
  289. package/template/wall-e/brain/model-deployment-facts.js +31 -1
  290. package/template/wall-e/brain/owner-call-whitelist.js +16 -0
  291. package/template/wall-e/brain/schema-ensures.js +22 -0
  292. package/template/wall-e/brain.js +1 -1
  293. package/template/wall-e/coding/journal-dispatcher.js +51 -0
  294. package/template/wall-e/coding/session-journal.js +28 -40
  295. package/template/wall-e/coding-orchestrator.js +23 -26
  296. package/template/wall-e/http/auth.js +18 -1
  297. package/template/wall-e/http/blog-views-api.js +318 -0
  298. package/template/wall-e/http/helper-rules-api.js +321 -0
  299. package/template/wall-e/http/model-proxy-providers.js +3 -1
  300. package/template/wall-e/http/telemetry-api.js +12 -0
  301. package/template/wall-e/lib/blog-view-policy.js +88 -0
  302. package/template/wall-e/lib/blog-view-store.js +169 -0
  303. package/template/wall-e/lib/client-config-lock.js +2 -1
  304. package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
  305. package/template/wall-e/lib/error-kinds.js +10 -1
  306. package/template/wall-e/lib/feature-manifest.js +1 -1
  307. package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
  308. package/template/wall-e/lib/helper-rules/evaluate.js +357 -0
  309. package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
  310. package/template/wall-e/lib/helper-rules/grade.js +277 -0
  311. package/template/wall-e/lib/helper-rules/label.js +247 -0
  312. package/template/wall-e/lib/helper-rules/lead-call-hook.js +522 -0
  313. package/template/wall-e/lib/helper-rules/store.js +667 -0
  314. package/template/wall-e/lib/mcp-integration.js +5 -6
  315. package/template/wall-e/lib/runtime-worker-pool.js +1 -0
  316. package/template/wall-e/lib/scheduler-worker-jobs.js +6 -0
  317. package/template/wall-e/lib/telemetry-db-schema.js +37 -0
  318. package/template/wall-e/lib/telemetry-process-client.js +76 -1
  319. package/template/wall-e/llm/default-fallback.js +4 -0
  320. package/template/wall-e/llm/model-catalog.js +13 -4
  321. package/template/wall-e/llm/model-roles.js +6 -0
  322. package/template/wall-e/llm/portkey-http.js +150 -0
  323. package/template/wall-e/llm/portkey-sync.js +15 -145
  324. package/template/wall-e/llm/worker-mcp-routing.js +61 -0
  325. package/template/wall-e/llm/worker-route.js +43 -1
  326. package/template/wall-e/loops/brain-custom-writes.js +45 -0
  327. package/template/wall-e/mcp-protocol-contract.js +41 -1
  328. package/template/wall-e/mcp-server.js +13 -2
  329. package/template/wall-e/mcp-worker-schemas.js +20 -2
  330. package/template/wall-e/memory/ctm-context-client.js +25 -5
  331. package/template/wall-e/shared/release-schema.json +3 -2
  332. package/template/wall-e/shared/sqlite-write-lock.js +361 -223
  333. package/template/wall-e/shared/storage/contract.js +35 -3
  334. package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
  335. package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +6 -0
  336. package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +7 -2
  337. package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +7 -2
  338. package/template/wall-e/tools/local-tools.js +6 -4
  339. package/template/wall-e/workers/brain-owner-worker.js +9 -0
  340. package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
  341. package/template/wall-e/workers/telemetry-worker.js +8 -0
@@ -16,10 +16,11 @@ const {
16
16
  } = require('./lifecycle-wake-experiment');
17
17
  const projectConfig = require('./project-config');
18
18
  const { resolveResumeCwdFallback } = require('./resume-cwd');
19
- const { validateResumeTarget, withTrashLocation } = require('./resume-preflight');
19
+ const { validateResumeTarget, withTrashLocation, findClaudeResumeTranscript, transcriptHasConversation } = require('./resume-preflight');
20
20
  const { findTrashedTranscript } = require('./session-transcript-trash');
21
21
  const sessionHistory = require('./session-history');
22
22
  const { extractResumeTarget, getCodexThreadResumeCwdInfo, locateCodexRollout } = sessionHistory;
23
+ const { ensureClaudeResumeTarget } = require('./launch-model-override');
23
24
  const walleMcpAutoConfig = require('./walle-mcp-auto-config');
24
25
  const { ensureWalleMcpForAgentSession } = walleMcpAutoConfig;
25
26
  const {
@@ -228,7 +229,15 @@ async function prepareLaunchPlan(spec = {}, progressPort = parentPort) {
228
229
  cwd = fallback.cwd || cwd;
229
230
 
230
231
  let agentType = agentTypeForCommand(cmd);
231
- let resumeResolution = resolveResumeAlias(agentType, args, metadata);
232
+ // WP-0 D-2: for the PRIVATE Claude model-target operation below, the recorded source argv must reach
233
+ // the native-history classification UNTOUCHED. resolveResumeAlias is a naive
234
+ // `indexOf('--resume')` + metadata rewrite, and an argument that merely SPELLS `--resume` while being
235
+ // another option's operand (e.g. `--append-system-prompt --resume`) would be rewritten before the
236
+ // canonical normalizer ever sees it. Ordinary create/restore callers and Codex keep today's order.
237
+ const defersClaudeResumeAlias = agentType === 'claude' && spec.claudeResumeThreadId !== undefined;
238
+ let resumeResolution = defersClaudeResumeAlias
239
+ ? { args, resume: extractResumeTarget(agentType, args) }
240
+ : resolveResumeAlias(agentType, args, metadata);
232
241
  args = resumeResolution.args;
233
242
  let resume = resumeResolution.resume;
234
243
 
@@ -283,6 +292,54 @@ async function prepareLaunchPlan(spec = {}, progressPort = parentPort) {
283
292
  const cliResolution = resolvePublishedCliCommand(cmd, spec, env);
284
293
  cmd = cliResolution.cmd;
285
294
  agentType = agentTypeForCommand(cmd);
295
+ // WP-0 D-2 (same-harness, early): the project config above may have just rewritten this launch to a
296
+ // DIFFERENT harness, and the Codex-specific MCP/profile rewrites and prepareCodexLaunch() run long
297
+ // before a plan is returned. The private Claude model-target field names a Claude thread, so a launch
298
+ // that resolved to another harness is refused HERE -- before any of that preparation -- instead of
299
+ // executing Codex preparation and only then refusing the produced plan.
300
+ // Ordinary callers never set the private field, and Codex callers never set it either, so their
301
+ // behavior is unchanged. The planner's post-plan same-harness guard remains as the outer defence.
302
+ if (spec.claudeResumeThreadId !== undefined && agentType !== 'claude') {
303
+ const error = new TypeError('spec.claudeResumeThreadId names a Claude thread but the launch resolved to another harness');
304
+ error.code = 'launch_claude_target_harness_changed';
305
+ throw error;
306
+ }
307
+ // WP-0 (docs/claude-routed-native-history-resume-2026-10-24.html §5 D-2, §6): a Claude
308
+ // MODEL-TARGET preparation names the canonical source thread through the PRIVATE spec field
309
+ // `claudeResumeThreadId`, which only the lead-transition target planner sets after its canonical
310
+ // source proof. Claude keeps its own native transcript, so the launch must RESUME that exact
311
+ // thread instead of starting the recorded `--session-id` again (which would collide with the
312
+ // conversation already on disk). The classification below is the EXISTING native preflight --
313
+ // findClaudeResumeTranscript + transcriptHasConversation -- never a second reader, and nothing is
314
+ // written, moved, deleted or materialized here.
315
+ //
316
+ // A source with no recorded conversation is left EXACTLY as it is (today's fresh-launch
317
+ // behavior): forcing `--resume` onto a metadata-only stub is what the CLI answers with
318
+ // "No conversation found". The field is private to this worker spec, so an ordinary
319
+ // create/restore caller -- which never sets it -- cannot reach this block at all.
320
+ if (agentType === 'claude' && spec.claudeResumeThreadId !== undefined) {
321
+ const canonicalThreadId = String(spec.claudeResumeThreadId || '').trim();
322
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(canonicalThreadId)) {
323
+ const error = new TypeError('spec.claudeResumeThreadId must be the canonical Claude thread id');
324
+ error.code = 'launch_claude_resume_target_invalid';
325
+ throw error;
326
+ }
327
+ const canonicalTranscript = findClaudeResumeTranscript({
328
+ resumeId: canonicalThreadId,
329
+ jsonlPath: metadata.resumeAgent?.jsonl_path || metadata.resolved?.jsonl_path || '',
330
+ homeDir,
331
+ claudeConfigDir: env.CLAUDE_CONFIG_DIR || spec.claudeConfigDir,
332
+ });
333
+ if (canonicalTranscript && transcriptHasConversation(canonicalTranscript.path)) {
334
+ const normalized = ensureClaudeResumeTarget(args, canonicalThreadId);
335
+ if (!normalized.ok) {
336
+ const error = new TypeError(`the recorded Claude launch arguments cannot name the canonical thread: ${normalized.reason}`);
337
+ error.code = normalized.reason;
338
+ throw error;
339
+ }
340
+ args = normalized.args;
341
+ }
342
+ }
286
343
  resumeResolution = resolveResumeAlias(agentType, args, metadata);
287
344
  args = resumeResolution.args;
288
345
  resume = resumeResolution.resume;
@@ -217,6 +217,13 @@ function createLeadTransitionTargetPlanner(deps = {}) {
217
217
  const cwd = task.cwd || session.cwd || '';
218
218
  const agentType = detectAgentType(cmd);
219
219
  const resume = extractResumeTarget(agentType, args);
220
+ // D-2 (docs/claude-routed-native-history-resume-2026-10-24.html §5 D-2, §6): a Claude target
221
+ // launch must name the canonical SOURCE thread -- never an old startup/parent selector still
222
+ // sitting in the recorded argv -- so the canonical owner's own provider thread is what the
223
+ // metadata read is keyed by, and the private spec field below is what the launch-plan worker
224
+ // classifies/normalizes against. Both are derived ONLY here, after the canonical source proof
225
+ // below; no client/API caller and no ordinary create/restore caller sets either.
226
+ const canonicalThreadId = String(source?.providerThreadId || '');
220
227
  // The canonical SOURCE proof: the injected model runtime's owner must name THIS session, agent and
221
228
  // provider thread at exactly the submitted generation — generation 0 included. A missing owner is
222
229
  // refused here, BEFORE any reservation, metadata read or plan.
@@ -241,12 +248,19 @@ function createLeadTransitionTargetPlanner(deps = {}) {
241
248
  const generation = reserved.generation;
242
249
  const launchMetadata = await runReadPoolOp('readLaunchMetadata', {
243
250
  dbPath: dbModule.getDbPath(), baseDbPath: dbModule.getDbPath(), sessionId,
244
- resumeId: resume?.sessionId || '', telemetryReason: 'lead-transition-target-preflight',
251
+ resumeId: agentType === 'claude' ? canonicalThreadId : (resume?.sessionId || ''),
252
+ telemetryReason: 'lead-transition-target-preflight',
245
253
  }, { timeoutMs: 10_000, signal });
246
254
  if (identityGone()) return { ok: false, reason: 'lead_source_generation_changed' };
247
255
  cacheSessionOwnershipProjection(sessionId, launchMetadata?.resolved || launchMetadata || null);
248
256
  const mcpProfile = sessionMcpProfileSetting(task);
249
- const warmPlanInputs = await launchPlanWarmInputs({ agentType, cwd, launchMetadata, mcpProfile });
257
+ // Only Codex gathers warm-plan inputs. A Claude model-target preparation opts out of that cache
258
+ // entirely, because its key (transcript freshness, cwd, codex config, CLI stamp) cannot describe
259
+ // the same-thread resume operation below -- and a value that is computed only to be discarded
260
+ // would still cost the read.
261
+ const warmPlanInputs = agentType === 'codex'
262
+ ? await launchPlanWarmInputs({ agentType, cwd, launchMetadata, mcpProfile })
263
+ : null;
250
264
  if (identityGone()) return { ok: false, reason: 'lead_source_generation_changed' };
251
265
  const capturedLaunch = session._modelTransitionLaunchContext || {};
252
266
  const launchHomeDir = session._launchEnvOverrides?.HOME || capturedLaunch.homeDir || serverConfig.HOME;
@@ -262,11 +276,36 @@ function createLeadTransitionTargetPlanner(deps = {}) {
262
276
  env: targetPlanEnv,
263
277
  homeDir: launchHomeDir, cliCacheFile: agentCliCacheFile, codexHome: launchCodexHome,
264
278
  codexTransportGuard: serverConfig.CTM_CODEX_MCP_TRANSPORT_GUARD !== '0', wallePort,
265
- isRestore: true, launchMetadata, mcpProfile, warmPlanInputs, lane: 'interactive',
279
+ isRestore: true, launchMetadata, mcpProfile,
280
+ warmPlanInputs,
281
+ lane: 'interactive',
266
282
  transcriptTrashRoot: sessionTranscriptTrashRoot,
283
+ // PRIVATE internal argument (never persisted, never published, never accepted from a client):
284
+ // the canonical source thread the produced plan must resume. Only this planner sets it.
285
+ ...(agentType === 'claude' ? { claudeResumeThreadId: canonicalThreadId } : {}),
267
286
  });
268
287
  if (identityGone()) return { ok: false, reason: 'lead_source_generation_changed' };
269
288
  if (!result?.plan || Number(result.plan.generation) !== generation) return { ok: false, reason: 'lead_target_plan_unavailable' };
289
+ // D-2/D-3: the produced plan must still name the canonical thread in its argv AND in its resume
290
+ // metadata, and the two must AGREE about whether there is a resume target at all.
291
+ // `resolveResumeAlias` may re-resolve a Claude resume id out of the metadata row, so a plan that
292
+ // ends up on ANOTHER thread is refused here -- before the controller ever parks the source. Both
293
+ // absent is the legitimate native no-history fresh launch; exactly one absent is an inconsistent
294
+ // plan (an argv the launcher will act on that the metadata denies, or the reverse).
295
+ if (agentType === 'claude') {
296
+ // Same-harness guard: project config's applyToSpec may substitute the live Claude `cmd`, so a
297
+ // plan for ANOTHER harness (or a plan that does not name its harness at all) is refused here
298
+ // rather than being accepted as this planner's fresh/both-absent result.
299
+ if (result.plan.agentType !== 'claude') return { ok: false, reason: 'lead_target_harness_changed' };
300
+ const planArgs = Array.isArray(result.plan.args) ? result.plan.args : [];
301
+ const argvResume = extractResumeTarget('claude', planArgs);
302
+ const argvId = argvResume ? String(argvResume.sessionId || '') : '';
303
+ const metadataId = String(result.plan.resume?.sessionId || '');
304
+ if (!!argvId !== !!metadataId) return { ok: false, reason: 'lead_target_resume_inconsistent' };
305
+ if (argvId && (argvId !== canonicalThreadId || metadataId !== canonicalThreadId)) {
306
+ return { ok: false, reason: 'lead_target_resume_changed' };
307
+ }
308
+ }
270
309
  noteLaunchPlanReadinessGeneration(result.plan);
271
310
  return { ok: true, generation, launchPlan: result.plan, sourceGeneration };
272
311
  };
@@ -670,7 +709,10 @@ function createLeadModelSwitchRuntime(host) {
670
709
  const targetRecipe = {
671
710
  id: targetRecipeId, sessionId, providerThreadId: source.providerThreadId, harness,
672
711
  providerId: target.routeId || 'unknown', origin: target.routeId ? 'routed-proxy' : 'unknown',
673
- controlAdapterVersion: target.routeId ? CODEX_CONTROL_ADAPTER : null,
712
+ // The marker names the Codex app-server conversion adapter. A Claude target -- routed or
713
+ // native -- has no conversion adapter at all, so recording the Codex one there would claim a
714
+ // conversion this operation never performs (same-harness native resume).
715
+ controlAdapterVersion: harness === 'codex-cli' && target.routeId ? CODEX_CONTROL_ADAPTER : null,
674
716
  programVersion: null, cyberAccessProgram: null,
675
717
  routeId: target.routeId || null,
676
718
  wireModelId: target.routeId ? (target.modelId || null) : null, processGeneration: targetPlan.generation,
@@ -758,6 +800,17 @@ function createLeadModelSwitchRuntime(host) {
758
800
  const rebound = require('./launch-model-override').ensureCodexResumeTarget(recoveryArgs, source.providerThreadId);
759
801
  if (!rebound.ok) return { ok: false, reason: rebound.reason };
760
802
  recoveryArgs = rebound.args;
803
+ } else if (source.agent === 'claude') {
804
+ // The SAME normalization for a native Claude source. A captured Claude argv may select its
805
+ // thread through `--resume` OR through an explicit `--session-id` (a fresh identity CTM
806
+ // injected at startup), and it may still carry that launch's own initial positional prompt.
807
+ // The existing pure normalizer produces exactly one canonical `--resume <source thread>`
808
+ // prefix: every permission/settings operand survives, while the selector that named the
809
+ // thread and the one-shot startup prompt do not -- so a rollback resumes the SAME
810
+ // conversation instead of replaying the original task as a new turn.
811
+ const rebound = require('./launch-model-override').ensureClaudeResumeTarget(recoveryArgs, source.providerThreadId);
812
+ if (!rebound.ok) return { ok: false, reason: rebound.reason };
813
+ recoveryArgs = rebound.args;
761
814
  }
762
815
  const selectedSourceThread = extractResumeTarget(source.agent, recoveryArgs)?.sessionId || '';
763
816
  if (selectedSourceThread !== sourceThreadId) return { ok: false, reason: 'source_launch_context_unavailable' };
@@ -393,6 +393,7 @@ function createLeadModelSwitch(deps) {
393
393
  entry.recovered = !!result?.ok;
394
394
  if (!entry.recovered) {
395
395
  entry.req.recovery_reason = 'source_recovery_failed';
396
+ diagnostic(entry.req.ctm_session_id, 'lead-transition-source-recovery-failed', { reason: String(result?.reason || 'unknown').slice(0, 120) });
396
397
  const cause = entry.failureOutcome?.detail || 'The requested target was not applied.';
397
398
  entry.req.detail = `${cause} The captured source provider could not be restored.`;
398
399
  } else {
@@ -480,7 +481,7 @@ function createLeadModelSwitch(deps) {
480
481
  return refuse(409, 'client_request_conflict');
481
482
  }
482
483
  if (existing?.confirmationPromise) return refuse(409, 'lead_transition_committing', { request: publicRequest(existing.req) });
483
- if (existing?.handoffStarted && !existing.recovered && ['cancelled', 'failed'].includes(existing.req.state)) {
484
+ if (existing?.handoffStarted && (existing.sourceParked || existing.targetStarted) && !existing.recovered && ['cancelled', 'failed'].includes(existing.req.state)) {
484
485
  return refuse(409, 'lead_switch_recovery_in_flight', { request: publicRequest(existing.req) });
485
486
  }
486
487
  if (existing?.req.state === 'awaiting_turn' && existing.handoffStarted && !existing.recovered) {
@@ -767,7 +768,7 @@ function createLeadModelSwitch(deps) {
767
768
  return refuse(500, 'lead_transition_persist_failed', { message: String(error?.message || error).slice(0, 200) });
768
769
  }
769
770
  }
770
- if (providerTransition) {
771
+ if (providerTransition && info.agent !== 'claude') {
771
772
  if (!entry.transition) { requestControllers.delete(id); fail(entry, 'lead_transition_owner_unavailable', 'The transition owner is not available.'); return refuse(409, 'lead_transition_owner_unavailable'); }
772
773
  try {
773
774
  historyPreparation = await prepareHistory({
@@ -261,11 +261,41 @@ function createLeadModelTransitionStore({
261
261
  const getActiveForSession = (ctmSessionId) => {
262
262
  const sessionId = String(ctmSessionId || '').trim();
263
263
  if (!sessionId || sessionId.length > 128) return null;
264
- const row = getCoreDb().prepare(`SELECT transition_id FROM coding_model_transitions
264
+ const db = getCoreDb();
265
+ // An explicit CTM_DB_DOMAIN_SPLIT=0 boot never stamps v18, so the v49 journal is never
266
+ // created there. A journal that does not exist holds no active transition: answer that
267
+ // truthfully instead of throwing, which made every deferred restore on such a boot refuse
268
+ // with lead-transition-reconciliation-unavailable.
269
+ if (!db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type='table' AND name='coding_model_transitions'").get()) return null;
270
+ const row = db.prepare(`SELECT transition_id FROM coding_model_transitions
265
271
  WHERE ctm_session_id=? AND state IN ('queued','preparing','compacting','verified','handing_off','awaiting_turn')
266
272
  ORDER BY updated_at DESC, transition_id DESC LIMIT 1`).get(sessionId);
267
273
  return row ? get(row.transition_id) : null;
268
274
  };
275
+ // WP-1 (docs/codex-routed-fork-cold-restore-guard-2026-10-22.html §5 D-3, §9 S-6): the journal
276
+ // reader the launch-time route reconciliation needs. `getActiveForSession` excludes terminal
277
+ // states, but the repair must find the fork a transition ACTUALLY launched even after it failed, so
278
+ // this reads ANY state, newest revision first, with the parsed target recipe beside the row
279
+ // identity. Read-only and bounded; a malformed recipe JSON is skipped, never surfaced.
280
+ const listForThread = (ctmSessionId, providerThreadId) => {
281
+ const sessionId = String(ctmSessionId || '').trim();
282
+ const threadId = String(providerThreadId || '').trim();
283
+ if (!sessionId || sessionId.length > 128 || !threadId || threadId.length > 512) return [];
284
+ const rows = getCoreDb().prepare(`SELECT transition_id, revision, state, target_recipe_json
285
+ FROM coding_model_transitions WHERE ctm_session_id = ? ORDER BY revision DESC, updated_at DESC, transition_id DESC`)
286
+ .all(sessionId);
287
+ const out = [];
288
+ for (const row of rows) {
289
+ let targetRecipe;
290
+ try { targetRecipe = JSON.parse(row.target_recipe_json); } catch { continue; /* expected: a corrupt recipe is not a route source */ }
291
+ out.push({
292
+ transition_id: row.transition_id, revision: Number(row.revision), state: row.state, target_recipe: targetRecipe,
293
+ provider_thread_id: targetRecipe?.providerThreadId || null, route_id: targetRecipe?.routeId || null,
294
+ model: targetRecipe?.wireModelId || null, harness: targetRecipe?.harness || null,
295
+ });
296
+ }
297
+ return out;
298
+ };
269
299
  function saveProfile(profile = {}) {
270
300
  const allowed = new Set(['fingerprint', 'harness', 'cliVersion', 'adapterVersion', 'deployment', 'artifactPath', 'evidenceReceipt']);
271
301
  if (Object.keys(profile).some((key) => !allowed.has(key))) throw new TypeError('profile contains an unapproved field');
@@ -690,11 +720,39 @@ function createLeadModelTransitionStore({
690
720
  if (!row) return null;
691
721
  try { return { ...row, bindings: JSON.parse(row.bindings_json) }; } catch { return null; }
692
722
  }
693
- return { get, getActiveForSession, getStagedToken, saveProfile, begin, advance, commit, stageToken, recordFork, clearStagedToken };
723
+ return { get, getActiveForSession, listForThread, getStagedToken, saveProfile, begin, advance, commit, stageToken, recordFork, clearStagedToken };
694
724
  }
695
725
 
696
726
  // `validateRecipe` is exported so the approved-intent store can reuse the ONE complete bounded
697
727
  // journal recipe validation instead of keeping a parallel whitelist that silently drops (or refuses)
698
728
  // the real producer's provider/context metadata. This module imports only the PURE intent contract,
699
729
  // so the store importing this export introduces no construction cycle.
700
- module.exports = { ACTIVE_STATES, createLeadModelTransitionStore, validateRecipe };
730
+ // The provider thread of a FORK the session's active transition is still trying, or null. Until
731
+ // commit() moves the startup pointer, that thread is a candidate: the startup row keeps the source so
732
+ // a cold start before the first confirmed target turn resumes the source. Every startup-pointer writer
733
+ // (db.js updateStartupTaskAgentSession) asks this on the same handle, inside its own transaction.
734
+ function activeCandidateForkThread(db, ctmSessionId) {
735
+ // A core schema without the journal (pre-migration fixtures) has no transitions, so no candidate.
736
+ if (!db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='coding_model_transitions'").get()) return null;
737
+ const row = db.prepare(`SELECT source_recipe_json, target_recipe_json FROM coding_model_transitions
738
+ WHERE ctm_session_id=? AND state IN (${[...ACTIVE_STATES].map(() => '?').join(',')})
739
+ ORDER BY updated_at DESC, transition_id DESC LIMIT 1`).get(String(ctmSessionId || ''), ...ACTIVE_STATES);
740
+ if (!row) return null;
741
+ let source, target;
742
+ try { source = JSON.parse(row.source_recipe_json); target = JSON.parse(row.target_recipe_json); }
743
+ catch { return null; } // expected: a malformed journal row is refused by every transition reader; it names no candidate
744
+ const thread = String(target?.providerThreadId || '');
745
+ return thread && thread !== String(source?.providerThreadId || '') ? thread : null;
746
+ }
747
+
748
+ // The startup-pointer writers' guard (db.js updateStartupTaskAgentSession). Live: a fork relaunch wrote
749
+ // `resume <target>` and the commit then refused "startup task does not point at the captured source
750
+ // provider thread".
751
+ function resumesCandidateFork(db, ctmSessionId, resumeArgs) {
752
+ const candidate = Array.isArray(resumeArgs) ? activeCandidateForkThread(db, ctmSessionId) : null;
753
+ if (!candidate || !resumeArgs.some((arg) => String(arg) === candidate)) return false;
754
+ console.warn(`[startup-task] kept the source pointer for ${String(ctmSessionId).slice(0, 8)}: ${candidate.slice(0, 8)} is an uncommitted fork`);
755
+ return true;
756
+ }
757
+
758
+ module.exports = { ACTIVE_STATES, createLeadModelTransitionStore, validateRecipe, activeCandidateForkThread, resumesCandidateFork };
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const { createMediaJournalControlReader } = require('./media-journal-control-reader');
5
+
6
+ function unavailable(cause) {
7
+ return Object.assign(new Error('Pending image cancellation recovery is unavailable', { cause }), {
8
+ code: 'CTM_MEDIA_JOURNAL_UNAVAILABLE',
9
+ });
10
+ }
11
+
12
+ // One recovery scope per logical DB handle and journal directory. No new SQL owner: the caller
13
+ // supplies the same worker projector used by the write-behind store. Neither journal nor cursor
14
+ // is advanced, because unrelated content must remain available to its ordinary replay owner.
15
+ function createLegacyDraftCancellationRecovery({ getDirectory, getContext, projectEntry }) {
16
+ for (const callback of [getDirectory, getContext, projectEntry]) {
17
+ if (typeof callback !== 'function') throw new TypeError('Cancellation recovery requires callbacks');
18
+ }
19
+ let scope = null;
20
+ let operation = null;
21
+ let retired = false;
22
+ let closing = null;
23
+
24
+ function binding() {
25
+ const context = getContext();
26
+ const directory = getDirectory();
27
+ if (!context || !directory) throw new Error('Cancellation recovery has no open storage context');
28
+ return { context, directory: path.resolve(directory) };
29
+ }
30
+
31
+ function assertCurrent(owner) {
32
+ if (retired || owner !== scope) throw new Error('Cancellation recovery scope is retired');
33
+ const current = binding();
34
+ if (current.context !== owner.context || current.directory !== owner.directory) {
35
+ throw new Error('Cancellation recovery storage context changed');
36
+ }
37
+ }
38
+
39
+ async function closeReader(owner) {
40
+ if (!owner?.reader) return;
41
+ await owner.reader.close();
42
+ owner.reader = null; // Retain an unconfirmed resource owner on failure, not just its descriptor.
43
+ }
44
+
45
+ async function recover(current) {
46
+ await closeReader(scope);
47
+ const owner = scope = { ...current, reader: null, ready: false };
48
+ assertCurrent(owner);
49
+ const reader = owner.reader = createMediaJournalControlReader({
50
+ directory: owner.directory, assertCurrent: () => assertCurrent(owner),
51
+ });
52
+ let records;
53
+ let failed = false;
54
+ let failure;
55
+ try { records = await reader.read(); }
56
+ catch (error) { failed = true; failure = error; }
57
+ try { await closeReader(owner); }
58
+ catch (error) {
59
+ throw failed
60
+ ? new AggregateError([failure, error], 'Cancellation recovery and reader cleanup failed', { cause: failure })
61
+ : error;
62
+ }
63
+ if (failed) throw failure;
64
+ // Close every read handle BEFORE the first SQL projection. A partial projection remains
65
+ // idempotently retryable through applyMediaJournalEntry; it is never a completed recovery.
66
+ for (const { entry } of records) {
67
+ assertCurrent(owner);
68
+ const result = await projectEntry(entry, { urgent: true });
69
+ assertCurrent(owner);
70
+ if (typeof result?.cancelled !== 'boolean' || typeof result?.sessionEnded !== 'boolean'
71
+ || result.cancelled === result.sessionEnded) {
72
+ throw new TypeError('Cancellation projection did not confirm a durable cancellation or ended session');
73
+ }
74
+ }
75
+ assertCurrent(owner);
76
+ owner.ready = true;
77
+ }
78
+
79
+ function prepare() {
80
+ try {
81
+ if (retired) throw new Error('Cancellation recovery is closed');
82
+ const current = binding();
83
+ if (operation) return operation;
84
+ if (scope?.ready && scope.context === current.context && scope.directory === current.directory) {
85
+ return Promise.resolve();
86
+ }
87
+ operation = recover(current).catch(error => { throw unavailable(error); })
88
+ .finally(() => { operation = null; });
89
+ return operation;
90
+ } catch (error) {
91
+ return Promise.reject(unavailable(error));
92
+ }
93
+ }
94
+
95
+ function close() {
96
+ retired = true;
97
+ if (closing) return closing;
98
+ closing = (async () => {
99
+ // Already delivered operational errors are not shutdown failures. Unconfirmed handles
100
+ // remain owned and closeReader must still report them. No race against a timeout here.
101
+ if (operation) await operation.catch(() => { /* expected: admitted caller receives the failure */ });
102
+ await closeReader(scope);
103
+ scope = null;
104
+ })().finally(() => { closing = null; });
105
+ return closing;
106
+ }
107
+
108
+ return { prepare, close };
109
+ }
110
+
111
+ module.exports = { createLegacyDraftCancellationRecovery };
@@ -187,6 +187,7 @@ function armSessionLoginTripwire({ proc, env, onBlocked } = {}) {
187
187
  module.exports = {
188
188
  LOGIN_PATTERNS,
189
189
  WINDOW_CHARS,
190
+ stripAnsi,
190
191
  createLoginTripwire,
191
192
  attachToPty,
192
193
  armSessionLoginTripwire,