specrails-desktop 2.55.0 → 2.56.0

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 (368) hide show
  1. package/cli/dist/args.js +80 -0
  2. package/cli/dist/desktop-client.js +125 -0
  3. package/cli/dist/desktop-control.js +339 -0
  4. package/cli/dist/format.js +45 -0
  5. package/cli/dist/help.js +68 -0
  6. package/cli/dist/output.js +47 -0
  7. package/cli/dist/run-command.js +340 -0
  8. package/cli/dist/specrails-desktop.js +41 -1107
  9. package/cli/dist/status.js +111 -0
  10. package/client/dist/assets/{ActivityFeedPage-ILXMZXcb.js → ActivityFeedPage-DdMNmVBk.js} +1 -1
  11. package/client/dist/assets/{AgentBrowserCapture-UcsupCy7.js → AgentBrowserCapture-CeerUf--.js} +1 -1
  12. package/client/dist/assets/{AgentModeAnalyticsPane-CQuxYh8B.js → AgentModeAnalyticsPane-BjGb-8rh.js} +2 -2
  13. package/client/dist/assets/{AgentModeCodePane-zPWbW7ei.js → AgentModeCodePane-8XRkQEo_.js} +2 -2
  14. package/client/dist/assets/{AgentModeJobsPane-CInByIdl.js → AgentModeJobsPane-BN3dgJOA.js} +1 -1
  15. package/client/dist/assets/{AgentsPage-BWvgxaBv.js → AgentsPage-DfHWgP_x.js} +1 -1
  16. package/client/dist/assets/{AnalyticsPage-DP3jakv-.js → AnalyticsPage-CyfhYiBn.js} +1 -1
  17. package/client/dist/assets/{CodePage-BKXiwE5a.js → CodePage-C2Nf-Q5W.js} +1 -1
  18. package/client/dist/assets/{DesktopAnalyticsPage-DryJOaMz.js → DesktopAnalyticsPage-tc0p4jJW.js} +1 -1
  19. package/client/dist/assets/{DocsDialog-BsCG9ksG.js → DocsDialog-Br3bczCp.js} +1 -1
  20. package/client/dist/assets/{DocsPage-Cc-GeKYl.js → DocsPage-BcDr2cBm.js} +1 -1
  21. package/client/dist/assets/{ExportDropdown-ClahJdDn.js → ExportDropdown-BVGKEgkd.js} +1 -1
  22. package/client/dist/assets/{InteractiveJobComposer-DfLF6N0f.js → InteractiveJobComposer-DFPpdg2D.js} +1 -1
  23. package/client/dist/assets/{JobDetailModal-DHeur9YK.js → JobDetailModal-BdOv-l-M.js} +1 -1
  24. package/client/dist/assets/{JobDetailPage-CraDKzeG.js → JobDetailPage-vBbNeRuz.js} +1 -1
  25. package/client/dist/assets/{JobsPage-CcbuSwj7.js → JobsPage-CJCtPhIz.js} +1 -1
  26. package/client/dist/assets/{LoopBuilderPage-BKtNp494.js → LoopBuilderPage-BemvUOxy.js} +1 -1
  27. package/client/dist/assets/{LoopPreviewModal-DbZd9isy.js → LoopPreviewModal-C6hNAeYN.js} +1 -1
  28. package/client/dist/assets/{LoopsPage-DEg6sIkG.js → LoopsPage-BZr0quvh.js} +1 -1
  29. package/client/dist/assets/{MinimizedChatsContext-BGtEjWsc.js → MinimizedChatsContext-D3QzgV0B.js} +1 -1
  30. package/client/dist/assets/{PluginsPage-BVqSsPzL.js → PluginsPage-DOpTV75p.js} +1 -1
  31. package/client/dist/assets/{ProjectSettingsDialog-CAjLgJAZ.js → ProjectSettingsDialog-Dkwrn0z1.js} +1 -1
  32. package/client/dist/assets/{RepositoryDeliveries-DrcrxLe0.js → RepositoryDeliveries-Du2UCf1a.js} +1 -1
  33. package/client/dist/assets/{RepositoryScopeSelector-CAGY3xW6.js → RepositoryScopeSelector-hPGZNRBm.js} +1 -1
  34. package/client/dist/assets/ReviewPacketPage-DcOq-UTA.js +4 -0
  35. package/client/dist/assets/{TemplatePreviewModal-Bqs-9fhn.js → TemplatePreviewModal-Cejcquah.js} +1 -1
  36. package/client/dist/assets/{TicketDetailModalContext-C0jQ5yOk.js → TicketDetailModalContext-DAK-NoK6.js} +1 -1
  37. package/client/dist/assets/{Trans-DtWlCJN9.js → Trans-DEbgkuAY.js} +1 -1
  38. package/client/dist/assets/{dashboard-CTfEtkqX.js → dashboard-B9uWNGO2.js} +1 -1
  39. package/client/dist/assets/{dashboard-DMklepmz.js → dashboard-BIwmO9wc.js} +1 -1
  40. package/client/dist/assets/{dashboard-DBAP2_SQ.js → dashboard-BV4vOZkR.js} +1 -1
  41. package/client/dist/assets/{dashboard-D40HP2ks.js → dashboard-Bf6MPVsM.js} +1 -1
  42. package/client/dist/assets/{dashboard-Csf1yGSN.js → dashboard-C8klWVvZ.js} +1 -1
  43. package/client/dist/assets/{dashboard-C29Qwa-L.js → dashboard-D1ORhPF0.js} +1 -1
  44. package/client/dist/assets/{dashboard-Cr4D8oMn.js → dashboard-DSubvs9x.js} +1 -1
  45. package/client/dist/assets/{dashboard-CSJzf5OT.js → dashboard-px_vlRx_.js} +1 -1
  46. package/client/dist/assets/{formatDistanceToNow-DYmvOA3R.js → formatDistanceToNow-Cc2u5FwQ.js} +1 -1
  47. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-BAhW5E6V.js → getTimezoneOffsetInMilliseconds-BHm2U-w1.js} +1 -1
  48. package/client/dist/assets/index-C51x61Bz.css +2 -0
  49. package/client/dist/assets/{index-BfAZg5DG.js → index-Cxb288Rj.js} +29 -29
  50. package/client/dist/assets/{jira-api-B27Za5FP.js → jira-api-DrGxiD9p.js} +1 -1
  51. package/client/dist/assets/packet-8nn9RsU7.js +1 -0
  52. package/client/dist/assets/packet-B0H15elv.js +1 -0
  53. package/client/dist/assets/packet-BQvBgrwh.js +1 -0
  54. package/client/dist/assets/packet-BR7mO0-a.js +1 -0
  55. package/client/dist/assets/packet-BgcQ6q_K.js +1 -0
  56. package/client/dist/assets/packet-D2s92Jnn.js +1 -0
  57. package/client/dist/assets/packet-YbtcD1HS.js +1 -0
  58. package/client/dist/assets/packet-c0Qj_9eX.js +1 -0
  59. package/client/dist/assets/{project-repositories-DixIZHTA.js → project-repositories-9Wzs0coQ.js} +1 -1
  60. package/client/dist/assets/{spending-BGmZBX5B.js → spending-T5GM7wpn.js} +1 -1
  61. package/client/dist/assets/{useDesktop-CPB4cnwI.js → useDesktop-QogiN0zR.js} +1 -1
  62. package/client/dist/assets/{useRuntimeRuns-DEQ9HdAM.js → useRuntimeRuns-Dqmz9fS9.js} +1 -1
  63. package/client/dist/assets/{useSharedWebSocket-DcPRKR8R.js → useSharedWebSocket-Dz-HI6De.js} +2 -2
  64. package/client/dist/index.html +17 -17
  65. package/docs/codex.md +5 -5
  66. package/docs/customizing.md +1 -1
  67. package/docs/gemini-cli-provider-study.md +14 -14
  68. package/docs/gemini-core-support-evaluation.md +1 -1
  69. package/docs/gemini.md +5 -5
  70. package/docs/internals/README.md +6 -2
  71. package/docs/internals/adding-a-provider.md +22 -15
  72. package/docs/internals/agent-runtime-framework-evaluation.md +8 -8
  73. package/docs/internals/api-reference.md +2 -2
  74. package/docs/internals/architecture.md +9 -9
  75. package/docs/internals/browser-capture-performance.md +3 -3
  76. package/docs/internals/code-explorer-story.md +2 -2
  77. package/docs/internals/companion-rails-as-loops-contract.md +2 -2
  78. package/docs/internals/core-runtime-updates.md +5 -0
  79. package/docs/internals/embedded-browser-native-webview-evaluation.md +5 -5
  80. package/docs/internals/gemini-mcp-registration.md +2 -2
  81. package/docs/internals/global-artifacts-alignment-contract.md +1 -1
  82. package/docs/internals/global-artifacts-relocation-evaluation.md +1 -1
  83. package/docs/internals/interactive-jobs.md +8 -8
  84. package/docs/internals/legacy-implementation-notes.md +722 -0
  85. package/docs/internals/loop-step-log-explorer.md +8 -8
  86. package/docs/internals/mission-rail-cards.md +14 -14
  87. package/docs/internals/modular-architecture.md +107 -0
  88. package/docs/internals/profiles.md +1 -1
  89. package/docs/internals/programmatic-agent-runtime.md +66 -0
  90. package/docs/internals/project-builder.md +18 -18
  91. package/docs/internals/review-packet.md +8 -8
  92. package/docs/internals/safe-pr-review-flow.md +11 -11
  93. package/docs/internals/source-architecture.md +131 -0
  94. package/docs/internals/source-map.md +1356 -0
  95. package/docs/internals/spec-addenda.md +65 -9
  96. package/docs/internals/switch-to-agent-mode-design.md +11 -11
  97. package/docs/tracking-cost.md +1 -1
  98. package/package.json +5 -2
  99. package/server/dist/agent-mcp-config.js +1 -1
  100. package/server/dist/attachment-manager.js +1 -1
  101. package/server/dist/build-dirs.js +2 -2
  102. package/server/dist/config.js +0 -3
  103. package/server/dist/core-completion.js +1 -1
  104. package/server/dist/core-execution.js +1 -1
  105. package/server/dist/db/activity.js +39 -0
  106. package/server/dist/db/connection.js +41 -0
  107. package/server/dist/db/conversations.js +48 -0
  108. package/server/dist/db/jobs.js +251 -0
  109. package/server/dist/db/migrations.js +1521 -0
  110. package/server/dist/db/proposals.js +50 -0
  111. package/server/dist/db/settings.js +15 -0
  112. package/server/dist/db/stats.js +61 -0
  113. package/server/dist/db/telemetry.js +56 -0
  114. package/server/dist/db/templates.js +37 -0
  115. package/server/dist/db/types.js +2 -0
  116. package/server/dist/db.js +66 -2224
  117. package/server/dist/desktop-db.js +3 -3
  118. package/server/dist/desktop-router.js +8 -8
  119. package/server/dist/git-diagnostics.js +1 -1
  120. package/server/dist/index.js +11 -11
  121. package/server/dist/integration-branch.js +3 -14
  122. package/server/dist/jira/jira-issue-fields.js +0 -1
  123. package/server/dist/jira/jira-materializer.js +1 -1
  124. package/server/dist/jira/jira-sync-manager.js +1 -1
  125. package/server/dist/mcp/guide.js +16 -2
  126. package/server/dist/mcp/mcp-admin-router.js +1 -1
  127. package/server/dist/mcp/mcp-server.js +1 -1
  128. package/server/dist/mcp/tools/catalog.js +2 -0
  129. package/server/dist/mcp/tools/jobs.js +23 -5
  130. package/server/dist/mcp/tools/rails.js +2 -2
  131. package/server/dist/mcp/tools/recovery.js +35 -0
  132. package/server/dist/mcp/tools/specs.js +2 -2
  133. package/server/dist/mcp/tools/support.js +4 -1
  134. package/server/dist/mcp/tools/types.js +3 -3
  135. package/server/dist/mobile/mobile-gateway.js +1 -1
  136. package/server/dist/mobile/mobile-missions.js +1 -1
  137. package/server/dist/{desktop-analytics.js → modules/accounting/runtime/desktop-analytics.js} +2 -2
  138. package/server/dist/{pricing.js → modules/accounting/runtime/pricing.js} +10 -3
  139. package/server/dist/{result-event.js → modules/accounting/runtime/result-event.js} +3 -3
  140. package/server/dist/{spending.js → modules/accounting/runtime/spending.js} +0 -3
  141. package/server/dist/{telemetry-compactor.js → modules/accounting/runtime/telemetry-compactor.js} +1 -1
  142. package/server/dist/{telemetry-receiver.js → modules/accounting/runtime/telemetry-receiver.js} +2 -2
  143. package/server/dist/{agent-runtime-bridge.js → modules/agent-runtime/runtime/agent-runtime-bridge.js} +2 -2
  144. package/server/dist/{agent-runtime-controls-router.js → modules/agent-runtime/runtime/agent-runtime-controls-router.js} +16 -0
  145. package/server/dist/{agent-runtime-controls.js → modules/agent-runtime/runtime/agent-runtime-controls.js} +100 -8
  146. package/server/dist/{agent-runtime-effective-config.js → modules/agent-runtime/runtime/agent-runtime-effective-config.js} +1 -1
  147. package/server/dist/{agent-runtime-loader.js → modules/agent-runtime/runtime/agent-runtime-loader.js} +3 -3
  148. package/server/dist/{agent-runtime-paths.js → modules/agent-runtime/runtime/agent-runtime-paths.js} +1 -1
  149. package/server/dist/modules/agent-runtime/runtime/agent-runtime-recovery.js +53 -0
  150. package/server/dist/{agent-runtime-settings-router.js → modules/agent-runtime/runtime/agent-runtime-settings-router.js} +2 -2
  151. package/server/dist/{agent-runtime-settings.js → modules/agent-runtime/runtime/agent-runtime-settings.js} +3 -3
  152. package/server/dist/{agent-runtime-settlement.js → modules/agent-runtime/runtime/agent-runtime-settlement.js} +6 -6
  153. package/server/dist/{agent-defaults.js → modules/agents/runtime/agent-defaults.js} +3 -3
  154. package/server/dist/{agent-generator.js → modules/agents/runtime/agent-generator.js} +7 -7
  155. package/server/dist/{agent-refine-manager.js → modules/agents/runtime/agent-refine-manager.js} +5 -5
  156. package/server/dist/{agent-store.js → modules/agents/runtime/agent-store.js} +1 -1
  157. package/server/dist/{profile-manager.js → modules/agents/runtime/profile-manager.js} +2 -2
  158. package/server/dist/{profiles-router.js → modules/agents/runtime/profiles-router.js} +5 -5
  159. package/server/dist/{browser-capture-manager.js → modules/browser/runtime/browser-capture-manager.js} +2 -4
  160. package/server/dist/{browser-playwright.js → modules/browser/runtime/browser-playwright.js} +1 -1
  161. package/server/dist/{blueprint-chat-manager.js → modules/builder/runtime/blueprint-chat-manager.js} +7 -7
  162. package/server/dist/{blueprint-commit.js → modules/builder/runtime/blueprint-commit.js} +8 -8
  163. package/server/dist/{blueprint-draft-parser.js → modules/builder/runtime/blueprint-draft-parser.js} +1 -1
  164. package/server/dist/{blueprint-generation.js → modules/builder/runtime/blueprint-generation.js} +1 -1
  165. package/server/dist/{blueprint-operator-prompt.js → modules/builder/runtime/blueprint-operator-prompt.js} +1 -1
  166. package/server/dist/{blueprint-router.js → modules/builder/runtime/blueprint-router.js} +3 -3
  167. package/server/dist/{blueprint-spec-quality.js → modules/builder/runtime/blueprint-spec-quality.js} +1 -1
  168. package/server/dist/{milestone-chain.js → modules/builder/runtime/milestone-chain.js} +1 -1
  169. package/server/dist/{milestone-progress.js → modules/builder/runtime/milestone-progress.js} +6 -6
  170. package/server/dist/{code-activity.js → modules/code/runtime/code-activity.js} +1 -1
  171. package/server/dist/{code-explorer-router.js → modules/code/runtime/code-explorer-router.js} +5 -5
  172. package/server/dist/{file-provenance.js → modules/code/runtime/file-provenance.js} +1 -1
  173. package/server/dist/{file-story-manager.js → modules/code/runtime/file-story-manager.js} +2 -2
  174. package/server/dist/{file-story.js → modules/code/runtime/file-story.js} +2 -2
  175. package/server/dist/{file-summary-generator.js → modules/code/runtime/file-summary-generator.js} +3 -3
  176. package/server/dist/{file-summary-manager.js → modules/code/runtime/file-summary-manager.js} +3 -3
  177. package/server/dist/{project-code-discovery.js → modules/code/runtime/project-code-discovery.js} +2 -2
  178. package/server/dist/modules/conversations/domain/draft-stream.js +91 -0
  179. package/server/dist/modules/conversations/domain/recovery-context.js +101 -0
  180. package/server/dist/modules/conversations/index.js +10 -0
  181. package/server/dist/{chat-manager.js → modules/conversations/runtime/chat-manager.js} +32 -216
  182. package/server/dist/{context-budget.js → modules/conversations/runtime/context-budget.js} +1 -1
  183. package/server/dist/{explore-cwd-manager.js → modules/conversations/runtime/explore-cwd-manager.js} +1 -1
  184. package/server/dist/{explore-smash.js → modules/conversations/runtime/explore-smash.js} +1 -1
  185. package/server/dist/{explore-stdin-session.js → modules/conversations/runtime/explore-stdin-session.js} +1 -1
  186. package/server/dist/modules/delivery/adapters/decisions/chains.js +138 -0
  187. package/server/dist/modules/delivery/adapters/decisions/contracts.js +2 -0
  188. package/server/dist/modules/delivery/adapters/decisions/create.js +234 -0
  189. package/server/dist/modules/delivery/adapters/decisions/discard.js +251 -0
  190. package/server/dist/modules/delivery/adapters/decisions/dispatch.js +107 -0
  191. package/server/dist/modules/delivery/adapters/decisions/evidence.js +205 -0
  192. package/server/dist/modules/delivery/adapters/decisions/merge-local.js +338 -0
  193. package/server/dist/modules/delivery/adapters/decisions/metadata.js +109 -0
  194. package/server/dist/modules/delivery/adapters/decisions/observations.js +260 -0
  195. package/server/dist/modules/delivery/adapters/decisions/ownership.js +83 -0
  196. package/server/dist/modules/delivery/adapters/decisions/publish.js +242 -0
  197. package/server/dist/modules/delivery/adapters/decisions/recovery.js +425 -0
  198. package/server/dist/modules/delivery/adapters/decisions/retry.js +112 -0
  199. package/server/dist/modules/delivery/adapters/decisions/transitions.js +94 -0
  200. package/server/dist/modules/delivery/domain/decision-policy.js +50 -0
  201. package/server/dist/modules/delivery/domain/state.js +2 -0
  202. package/server/dist/modules/delivery/index.js +7 -0
  203. package/server/dist/{active-pr-continuation.js → modules/delivery/runtime/active-pr-continuation.js} +2 -2
  204. package/server/dist/{delivery-evidence.js → modules/delivery/runtime/delivery-evidence.js} +3 -3
  205. package/server/dist/{multi-repo-bases.js → modules/delivery/runtime/multi-repo-bases.js} +1 -1
  206. package/server/dist/{multi-repo-checkout.js → modules/delivery/runtime/multi-repo-checkout.js} +4 -4
  207. package/server/dist/{multi-repo-delivery.js → modules/delivery/runtime/multi-repo-delivery.js} +4 -4
  208. package/server/dist/{multi-repo-execution.js → modules/delivery/runtime/multi-repo-execution.js} +8 -8
  209. package/server/dist/{pr-body.js → modules/delivery/runtime/pr-body.js} +1 -1
  210. package/server/dist/{pr-follow-up-scope.js → modules/delivery/runtime/pr-follow-up-scope.js} +2 -2
  211. package/server/dist/{pr-follow-up.js → modules/delivery/runtime/pr-follow-up.js} +1 -1
  212. package/server/dist/{pr-naming.js → modules/delivery/runtime/pr-naming.js} +1 -1
  213. package/server/dist/{pr-publisher.js → modules/delivery/runtime/pr-publisher.js} +2 -2
  214. package/server/dist/{rail-isolated-launch.js → modules/delivery/runtime/rail-isolated-launch.js} +29 -27
  215. package/server/dist/{rail-launch-parser.js → modules/delivery/runtime/rail-launch-parser.js} +2 -2
  216. package/server/dist/{rail-merge-orchestrator.js → modules/delivery/runtime/rail-merge-orchestrator.js} +5 -5
  217. package/server/dist/modules/delivery/runtime/rail-pr-decision.js +12 -0
  218. package/server/dist/{rail-pr-delivery.js → modules/delivery/runtime/rail-pr-delivery.js} +1 -1
  219. package/server/dist/{rail-pr-store.js → modules/delivery/runtime/rail-pr-store.js} +2 -2
  220. package/server/dist/{rail-pr-ticket-effects.js → modules/delivery/runtime/rail-pr-ticket-effects.js} +3 -3
  221. package/server/dist/{rail-worktree-release.js → modules/delivery/runtime/rail-worktree-release.js} +4 -4
  222. package/server/dist/{rails-router.js → modules/delivery/runtime/rails-router.js} +66 -67
  223. package/server/dist/{review-packet.js → modules/delivery/runtime/review-packet.js} +3 -3
  224. package/server/dist/modules/execution/adapters/budget-storage.js +21 -0
  225. package/server/dist/modules/execution/adapters/usage-reader.js +38 -0
  226. package/server/dist/modules/execution/application/enforce-budget.js +14 -0
  227. package/server/dist/modules/execution/application/record-job-invocations.js +64 -0
  228. package/server/dist/modules/execution/application/recover-job-usage.js +200 -0
  229. package/server/dist/modules/execution/domain/job-accounting.js +2 -0
  230. package/server/dist/modules/execution/domain/scheduling.js +24 -0
  231. package/server/dist/modules/execution/domain/usage.js +21 -0
  232. package/server/dist/modules/execution/index.js +14 -0
  233. package/server/dist/modules/execution/ports.js +2 -0
  234. package/server/dist/{accept-ladder.js → modules/execution/runtime/accept-ladder.js} +1 -1
  235. package/server/dist/{interactive-job-session.js → modules/execution/runtime/interactive-job-session.js} +11 -11
  236. package/server/dist/{job-phase-breakdown.js → modules/execution/runtime/job-phase-breakdown.js} +1 -1
  237. package/server/dist/{queue-manager.js → modules/execution/runtime/queue-manager.js} +74 -491
  238. package/server/dist/{revision-seed.js → modules/execution/runtime/revision-seed.js} +1 -1
  239. package/server/dist/{spawn-lifecycle.js → modules/execution/runtime/spawn-lifecycle.js} +3 -3
  240. package/server/dist/{stuck-run-detector.js → modules/execution/runtime/stuck-run-detector.js} +1 -1
  241. package/server/dist/{loop-command-catalog.js → modules/loops/runtime/loop-command-catalog.js} +1 -1
  242. package/server/dist/{loop-executors.js → modules/loops/runtime/loop-executors.js} +17 -17
  243. package/server/dist/{loop-factory.js → modules/loops/runtime/loop-factory.js} +2 -21
  244. package/server/dist/{loop-graph.js → modules/loops/runtime/loop-graph.js} +25 -0
  245. package/server/dist/{loop-role-engines.js → modules/loops/runtime/loop-role-engines.js} +4 -4
  246. package/server/dist/{loop-run-manager.js → modules/loops/runtime/loop-run-manager.js} +101 -26
  247. package/server/dist/{loop-runs-store.js → modules/loops/runtime/loop-runs-store.js} +1 -1
  248. package/server/dist/{loop-shell-invocation.js → modules/loops/runtime/loop-shell-invocation.js} +2 -2
  249. package/server/dist/{loop-step-idle.js → modules/loops/runtime/loop-step-idle.js} +1 -1
  250. package/server/dist/{loop-templates.js → modules/loops/runtime/loop-templates.js} +24 -29
  251. package/server/dist/{loops-router.js → modules/loops/runtime/loops-router.js} +2 -2
  252. package/server/dist/{agent-chat-manager.js → modules/missions/runtime/agent-chat-manager.js} +19 -19
  253. package/server/dist/{agent-chat-router.js → modules/missions/runtime/agent-chat-router.js} +6 -6
  254. package/server/dist/{agent-context-resolver.js → modules/missions/runtime/agent-context-resolver.js} +8 -8
  255. package/server/dist/{agent-failure-briefing.js → modules/missions/runtime/agent-failure-briefing.js} +4 -2
  256. package/server/dist/{agent-fence-promotion.js → modules/missions/runtime/agent-fence-promotion.js} +1 -1
  257. package/server/dist/{agent-input-store.js → modules/missions/runtime/agent-input-store.js} +1 -1
  258. package/server/dist/{agent-operator-prompt.js → modules/missions/runtime/agent-operator-prompt.js} +75 -12
  259. package/server/dist/{agent-spec-framing.js → modules/missions/runtime/agent-spec-framing.js} +4 -4
  260. package/server/dist/{agent-steering.js → modules/missions/runtime/agent-steering.js} +1 -1
  261. package/server/dist/{mission-run-notify.js → modules/missions/runtime/mission-run-notify.js} +5 -2
  262. package/server/dist/modules/project-settings/adapters/http.js +24 -0
  263. package/server/dist/modules/project-settings/adapters/sqlite.js +120 -0
  264. package/server/dist/modules/project-settings/application.js +11 -0
  265. package/server/dist/modules/project-settings/domain.js +95 -0
  266. package/server/dist/modules/project-settings/index.js +11 -0
  267. package/server/dist/modules/project-settings/ports.js +2 -0
  268. package/server/dist/{contract-refine-runner.js → modules/specs/runtime/contract-refine-runner.js} +12 -12
  269. package/server/dist/{proposal-manager.js → modules/specs/runtime/proposal-manager.js} +8 -8
  270. package/server/dist/{smash-runner.js → modules/specs/runtime/smash-runner.js} +26 -58
  271. package/server/dist/{spec-addenda-core.js → modules/specs/runtime/spec-addenda-core.js} +2 -2
  272. package/server/dist/{spec-addenda.js → modules/specs/runtime/spec-addenda.js} +3 -3
  273. package/server/dist/{spec-launcher-manager.js → modules/specs/runtime/spec-launcher-manager.js} +8 -8
  274. package/server/dist/{spec-models.js → modules/specs/runtime/spec-models.js} +1 -1
  275. package/server/dist/{ticket-watcher.js → modules/specs/runtime/ticket-watcher.js} +1 -1
  276. package/server/dist/{background-process-control.js → modules/terminals/runtime/background-process-control.js} +1 -1
  277. package/server/dist/{background-process-service.js → modules/terminals/runtime/background-process-service.js} +3 -3
  278. package/server/dist/{background-process-store.js → modules/terminals/runtime/background-process-store.js} +1 -1
  279. package/server/dist/{background-windows-bootstrap.js → modules/terminals/runtime/background-windows-bootstrap.js} +3 -3
  280. package/server/dist/{terminal-manager.js → modules/terminals/runtime/terminal-manager.js} +3 -3
  281. package/server/dist/project-git.js +1 -1
  282. package/server/dist/project-profile-support.js +32 -0
  283. package/server/dist/project-registry.js +34 -40
  284. package/server/dist/project-router-background-processes.js +1 -1
  285. package/server/dist/project-router-chat.js +6 -6
  286. package/server/dist/project-router-git.js +1 -1
  287. package/server/dist/project-router-helpers.js +2 -2
  288. package/server/dist/project-router-jobs.js +14 -12
  289. package/server/dist/project-router-loop-runs.js +12 -12
  290. package/server/dist/project-router-settings.js +15 -75
  291. package/server/dist/project-router-setup.js +2 -2
  292. package/server/dist/project-router-spending.js +4 -4
  293. package/server/dist/project-router-terminals.js +4 -4
  294. package/server/dist/project-router-tickets.js +14 -14
  295. package/server/dist/project-router.js +13 -13
  296. package/server/dist/providers/claude-adapter.js +3 -2
  297. package/server/dist/providers/codex-adapter.js +3 -3
  298. package/server/dist/providers/gemini-adapter.js +1 -1
  299. package/server/dist/providers/telemetry-env.js +55 -0
  300. package/server/dist/runtime-role-prompts-router.js +2 -2
  301. package/server/dist/setup-manager.js +2 -48
  302. package/server/dist/shared/git-branch-name.js +16 -0
  303. package/server/dist/transient-children.js +3 -3
  304. package/server/dist/util/distribute-int.js +33 -0
  305. package/client/dist/assets/ReviewPacketPage-D-UjTef3.js +0 -4
  306. package/client/dist/assets/index-BAtqmAZR.css +0 -2
  307. package/client/dist/assets/packet-CjS_478C.js +0 -1
  308. package/client/dist/assets/packet-D69dKsHN.js +0 -1
  309. package/client/dist/assets/packet-D9rU6Oxo.js +0 -1
  310. package/client/dist/assets/packet-DMDFoamg.js +0 -1
  311. package/client/dist/assets/packet-Dd2RMs1h.js +0 -1
  312. package/client/dist/assets/packet-DjC9OibC.js +0 -1
  313. package/client/dist/assets/packet-DwPtJoDz.js +0 -1
  314. package/client/dist/assets/packet-ceahDg8_.js +0 -1
  315. package/server/dist/rail-pr-decision.js +0 -2377
  316. package/server/dist/ticket-broadcast.js +0 -47
  317. /package/server/dist/{ai-invocations.js → modules/accounting/runtime/ai-invocations.js} +0 -0
  318. /package/server/dist/{codex-otel-bridge.js → modules/accounting/runtime/codex-otel-bridge.js} +0 -0
  319. /package/server/dist/{metrics.js → modules/accounting/runtime/metrics.js} +0 -0
  320. /package/server/dist/{telemetry-export.js → modules/accounting/runtime/telemetry-export.js} +0 -0
  321. /package/server/dist/{agent-runtime-accounting.js → modules/agent-runtime/runtime/agent-runtime-accounting.js} +0 -0
  322. /package/server/dist/{agent-runtime-events.js → modules/agent-runtime/runtime/agent-runtime-events.js} +0 -0
  323. /package/server/dist/{agent-runtime-history.js → modules/agent-runtime/runtime/agent-runtime-history.js} +0 -0
  324. /package/server/dist/{agent-runtime-metrics.js → modules/agent-runtime/runtime/agent-runtime-metrics.js} +0 -0
  325. /package/server/dist/{agent-runtime-package.js → modules/agent-runtime/runtime/agent-runtime-package.js} +0 -0
  326. /package/server/dist/{agent-runtime-repositories.js → modules/agent-runtime/runtime/agent-runtime-repositories.js} +0 -0
  327. /package/server/dist/{agent-runtime-verification-suggestions.js → modules/agent-runtime/runtime/agent-runtime-verification-suggestions.js} +0 -0
  328. /package/server/dist/{agent-refine-db.js → modules/agents/runtime/agent-refine-db.js} +0 -0
  329. /package/server/dist/{browser-capture-types.js → modules/browser/runtime/browser-capture-types.js} +0 -0
  330. /package/server/dist/{browser-context-pool.js → modules/browser/runtime/browser-context-pool.js} +0 -0
  331. /package/server/dist/{browser-network.js → modules/browser/runtime/browser-network.js} +0 -0
  332. /package/server/dist/{browser-viewport.js → modules/browser/runtime/browser-viewport.js} +0 -0
  333. /package/server/dist/{blueprint-render.js → modules/builder/runtime/blueprint-render.js} +0 -0
  334. /package/server/dist/{blueprint-spec-fixtures.js → modules/builder/runtime/blueprint-spec-fixtures.js} +0 -0
  335. /package/server/dist/{blueprint-store.js → modules/builder/runtime/blueprint-store.js} +0 -0
  336. /package/server/dist/{blueprint-types.js → modules/builder/runtime/blueprint-types.js} +0 -0
  337. /package/server/dist/{builder-cwd-manager.js → modules/builder/runtime/builder-cwd-manager.js} +0 -0
  338. /package/server/dist/{milestone-chain-store.js → modules/builder/runtime/milestone-chain-store.js} +0 -0
  339. /package/server/dist/{changes-reader.js → modules/code/runtime/changes-reader.js} +0 -0
  340. /package/server/dist/{context-scope.js → modules/conversations/runtime/context-scope.js} +0 -0
  341. /package/server/dist/{explore-contract-refine.js → modules/conversations/runtime/explore-contract-refine.js} +0 -0
  342. /package/server/dist/{explore-draft-title.js → modules/conversations/runtime/explore-draft-title.js} +0 -0
  343. /package/server/dist/{merge-manager.js → modules/delivery/runtime/merge-manager.js} +0 -0
  344. /package/server/dist/{multi-repo-execution-store.js → modules/delivery/runtime/multi-repo-execution-store.js} +0 -0
  345. /package/server/dist/{pr-lifecycle.js → modules/delivery/runtime/pr-lifecycle.js} +0 -0
  346. /package/server/dist/{rail-isolation.js → modules/delivery/runtime/rail-isolation.js} +0 -0
  347. /package/server/dist/{rail-pr-recovery-git.js → modules/delivery/runtime/rail-pr-recovery-git.js} +0 -0
  348. /package/server/dist/{rail-worktrees-store.js → modules/delivery/runtime/rail-worktrees-store.js} +0 -0
  349. /package/server/dist/{rails-store.js → modules/delivery/runtime/rails-store.js} +0 -0
  350. /package/server/dist/{job-listing.js → modules/execution/runtime/job-listing.js} +0 -0
  351. /package/server/dist/{job-spawn-idempotency.js → modules/execution/runtime/job-spawn-idempotency.js} +0 -0
  352. /package/server/dist/{run-duration-stats.js → modules/execution/runtime/run-duration-stats.js} +0 -0
  353. /package/server/dist/{verification-sentinel.js → modules/execution/runtime/verification-sentinel.js} +0 -0
  354. /package/server/dist/{loop-constants.js → modules/loops/runtime/loop-constants.js} +0 -0
  355. /package/server/dist/{loop-decider.js → modules/loops/runtime/loop-decider.js} +0 -0
  356. /package/server/dist/{loop-effect.js → modules/loops/runtime/loop-effect.js} +0 -0
  357. /package/server/dist/{loop-preview.js → modules/loops/runtime/loop-preview.js} +0 -0
  358. /package/server/dist/{loop-templates-ported.js → modules/loops/runtime/loop-templates-ported.js} +0 -0
  359. /package/server/dist/{loops-store.js → modules/loops/runtime/loops-store.js} +0 -0
  360. /package/server/dist/{agent-chat-registry.js → modules/missions/runtime/agent-chat-registry.js} +0 -0
  361. /package/server/dist/{agent-cwd-manager.js → modules/missions/runtime/agent-cwd-manager.js} +0 -0
  362. /package/server/dist/{agent-tier.js → modules/missions/runtime/agent-tier.js} +0 -0
  363. /package/server/dist/{spec-contract-prompt.js → modules/specs/runtime/spec-contract-prompt.js} +0 -0
  364. /package/server/dist/{spec-draft-parser.js → modules/specs/runtime/spec-draft-parser.js} +0 -0
  365. /package/server/dist/{ticket-store.js → modules/specs/runtime/ticket-store.js} +0 -0
  366. /package/server/dist/{terminal-marks-store.js → modules/terminals/runtime/terminal-marks-store.js} +0 -0
  367. /package/server/dist/{terminal-osc-parser.js → modules/terminals/runtime/terminal-osc-parser.js} +0 -0
  368. /package/server/dist/{terminal-settings.js → modules/terminals/runtime/terminal-settings.js} +0 -0
@@ -16,14 +16,14 @@ const path_1 = __importDefault(require("path"));
16
16
  const node_crypto_1 = require("node:crypto");
17
17
  const child_process_1 = require("child_process");
18
18
  const express_1 = require("express");
19
- const feature_flags_1 = require("./feature-flags");
20
- const build_dirs_1 = require("./build-dirs");
19
+ const feature_flags_1 = require("../../../feature-flags");
20
+ const build_dirs_1 = require("../../../build-dirs");
21
21
  const file_provenance_1 = require("./file-provenance");
22
22
  const file_summary_manager_1 = require("./file-summary-manager");
23
23
  const file_story_1 = require("./file-story");
24
- const project_repository_provenance_1 = require("./project-repository-provenance");
25
- const providers_1 = require("./providers");
26
- const project_repositories_1 = require("./project-repositories");
24
+ const project_repository_provenance_1 = require("../../../project-repository-provenance");
25
+ const providers_1 = require("../../../providers");
26
+ const project_repositories_1 = require("../../../project-repositories");
27
27
  const code_activity_1 = require("./code-activity");
28
28
  const MAX_TREE_PAGE = 2000;
29
29
  const DEFAULT_MAX_TREE_ENTRIES = 20_000;
@@ -20,7 +20,7 @@ exports.broadcastProvenanceUpdated = broadcastProvenanceUpdated;
20
20
  const child_process_1 = require("child_process");
21
21
  const fs_1 = __importDefault(require("fs"));
22
22
  const path_1 = __importDefault(require("path"));
23
- const project_repository_provenance_1 = require("./project-repository-provenance");
23
+ const project_repository_provenance_1 = require("../../../project-repository-provenance");
24
24
  const MAX_PATCH_BYTES = 512 * 1024;
25
25
  // These git calls run synchronously on the main event loop (pre-spawn snapshot
26
26
  // and post-exit diff). Bound every one: a timeout so a stuck index.lock /
@@ -15,10 +15,10 @@ exports.buildStorySystemPrompt = buildStorySystemPrompt;
15
15
  * `file_story_contributions.summary` (see file-story.ts / migration 37).
16
16
  */
17
17
  const crypto_1 = require("crypto");
18
- const ai_invocations_1 = require("./ai-invocations");
18
+ const ai_invocations_1 = require("../../accounting/runtime/ai-invocations");
19
19
  const file_story_1 = require("./file-story");
20
20
  const file_summary_manager_1 = require("./file-summary-manager");
21
- const project_repository_provenance_1 = require("./project-repository-provenance");
21
+ const project_repository_provenance_1 = require("../../../project-repository-provenance");
22
22
  const STORY_PROMPT_EN = 'Explain to a non-developer what this recorded patch visibly changed in this file, in 2 to 4 clear sentences. ' +
23
23
  'Describe the responsibility or contract it adds, removes or changes using only the supplied patch. ' +
24
24
  'A current spec title is context, not proof of historical intent, successful tests, integration or deployment. ' +
@@ -33,8 +33,8 @@ exports.getFileStory = getFileStory;
33
33
  * file-story-manager generates on demand.
34
34
  */
35
35
  const node_crypto_1 = require("node:crypto");
36
- const feature_flags_1 = require("./feature-flags");
37
- const project_repository_provenance_1 = require("./project-repository-provenance");
36
+ const feature_flags_1 = require("../../../feature-flags");
37
+ const project_repository_provenance_1 = require("../../../project-repository-provenance");
38
38
  const file_provenance_1 = require("./file-provenance");
39
39
  /** Warn threshold mirroring queue-manager's `provenance.large_job`. */
40
40
  const LARGE_RUN_WARN_FILES = 50;
@@ -7,9 +7,9 @@ exports.buildSystemPrompt = buildSystemPrompt;
7
7
  exports.createFileSummaryGenerator = createFileSummaryGenerator;
8
8
  const readline_1 = require("readline");
9
9
  const tree_kill_1 = __importDefault(require("tree-kill"));
10
- const cli_prompt_1 = require("./util/cli-prompt");
11
- const result_event_1 = require("./result-event");
12
- const runtime_1 = require("./providers/runtime");
10
+ const cli_prompt_1 = require("../../../util/cli-prompt");
11
+ const result_event_1 = require("../../accounting/runtime/result-event");
12
+ const runtime_1 = require("../../../providers/runtime");
13
13
  const GENERATE_TIMEOUT_MS = 60_000;
14
14
  const SYSTEM_PROMPT_EN = 'Explain this file to a non-developer using only the supplied source snapshot. In 3 to 6 clear sentences, ' +
15
15
  'describe its purpose, main responsibilities, and any inputs, outputs or relationships directly visible in the source. ' +
@@ -55,9 +55,9 @@ const fs = __importStar(require("fs"));
55
55
  const path = __importStar(require("path"));
56
56
  const chokidar_1 = __importDefault(require("chokidar"));
57
57
  const _2020_1 = __importDefault(require("ajv/dist/2020"));
58
- const build_dirs_1 = require("./build-dirs");
59
- const ai_invocations_1 = require("./ai-invocations");
60
- const file_summary_v1_json_1 = __importDefault(require("./schemas/file-summary.v1.json"));
58
+ const build_dirs_1 = require("../../../build-dirs");
59
+ const ai_invocations_1 = require("../../accounting/runtime/ai-invocations");
60
+ const file_summary_v1_json_1 = __importDefault(require("../../../schemas/file-summary.v1.json"));
61
61
  const SUMMARIES_REL = path.join('.specrails', 'file-summaries');
62
62
  // Current summary prompt version. Bump when buildSystemPrompt changes materially
63
63
  // so existing summaries are treated as stale and regenerated on next request.
@@ -7,8 +7,8 @@ exports.discoverProjectCode = discoverProjectCode;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const node_crypto_1 = require("node:crypto");
10
- const feature_flags_1 = require("./feature-flags");
11
- const project_repositories_1 = require("./project-repositories");
10
+ const feature_flags_1 = require("../../../feature-flags");
11
+ const project_repositories_1 = require("../../../project-repositories");
12
12
  const code_explorer_router_1 = require("./code-explorer-router");
13
13
  /** One project-wide budget, shared across all members. Every hit carries its
14
14
  * address; unavailable/partially scanned members cannot be mistaken for empty. */
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ // ─── Live spec-draft fence stripper ──────────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.filterDraftBlocksLive = filterDraftBlocksLive;
5
+ const FENCE_OPEN = '```spec-draft';
6
+ const FENCE_CLOSE = '```';
7
+ /**
8
+ * I/O-free filter that advances caller-owned state and returns the
9
+ * substring that is safe to broadcast to the chat stream. Holds back partial
10
+ * fence markers in `state.pendingTail` so the next call can resolve them.
11
+ *
12
+ * Behaviour:
13
+ * - While outside a block: emit text up to (but not including) the start of
14
+ * a `\`\`\`spec-draft` marker. If no marker is present, hold back the
15
+ * trailing few chars so a marker starting on a chunk boundary is not
16
+ * leaked.
17
+ * - While inside a block: emit nothing. Look for the closing `\`\`\``.
18
+ * When found, consume it (plus an optional trailing newline) and resume
19
+ * emitting from the bytes that follow.
20
+ *
21
+ * The filter intentionally does NOT validate the JSON payload — that is
22
+ * server-side concern of `parseSpecDraftBlocks`. It only strips the fenced
23
+ * span.
24
+ */
25
+ function filterDraftBlocksLive(state, newText) {
26
+ let buf = state.pendingTail + newText;
27
+ let out = '';
28
+ state.pendingTail = '';
29
+ // Iterate in case a single delta contains multiple transitions
30
+ // (e.g. close + open + close again — pathological but cheap to support).
31
+ while (buf.length > 0) {
32
+ if (state.inBlock) {
33
+ const closeIdx = buf.indexOf(FENCE_CLOSE);
34
+ if (closeIdx === -1) {
35
+ // No close yet — but the close could span the chunk boundary.
36
+ // Hold back up to 2 trailing chars (closing fence is 3 chars; we keep
37
+ // any trailing run of `\`` so the next call resolves it).
38
+ const tailLen = trailingBacktickRun(buf, 2);
39
+ state.pendingTail = buf.slice(buf.length - tailLen);
40
+ return out;
41
+ }
42
+ // Consume the close fence + an optional trailing newline.
43
+ let after = closeIdx + FENCE_CLOSE.length;
44
+ if (buf[after] === '\n')
45
+ after += 1;
46
+ buf = buf.slice(after);
47
+ state.inBlock = false;
48
+ continue;
49
+ }
50
+ // Not in block: look for the open marker.
51
+ const openIdx = buf.indexOf(FENCE_OPEN);
52
+ if (openIdx !== -1) {
53
+ out += buf.slice(0, openIdx);
54
+ buf = buf.slice(openIdx + FENCE_OPEN.length);
55
+ // Drop an optional newline immediately after the open marker so the
56
+ // user never sees `\n` belonging to the fence.
57
+ if (buf[0] === '\n')
58
+ buf = buf.slice(1);
59
+ state.inBlock = true;
60
+ continue;
61
+ }
62
+ // No open marker — hold back only the trailing run that could become a
63
+ // prefix of FENCE_OPEN (i.e. the longest suffix of `buf` that is also a
64
+ // prefix of FENCE_OPEN). Anything past that is safe to emit.
65
+ const holdBack = longestSuffixThatIsPrefixOf(buf, FENCE_OPEN);
66
+ const safeEnd = buf.length - holdBack;
67
+ out += buf.slice(0, safeEnd);
68
+ state.pendingTail = buf.slice(safeEnd);
69
+ return out;
70
+ }
71
+ return out;
72
+ }
73
+ /** Length of the longest suffix of `s` that is a prefix of `target`. */
74
+ function longestSuffixThatIsPrefixOf(s, target) {
75
+ const max = Math.min(s.length, target.length - 1);
76
+ for (let len = max; len > 0; len--) {
77
+ if (target.startsWith(s.slice(s.length - len)))
78
+ return len;
79
+ }
80
+ return 0;
81
+ }
82
+ function trailingBacktickRun(s, max) {
83
+ let n = 0;
84
+ for (let i = s.length - 1; i >= 0 && n < max; i--) {
85
+ if (s[i] === '`')
86
+ n++;
87
+ else
88
+ break;
89
+ }
90
+ return n;
91
+ }
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.containsMissingClaudeSessionDiagnostic = containsMissingClaudeSessionDiagnostic;
4
+ exports.isMissingClaudeSessionErrorResult = isMissingClaudeSessionErrorResult;
5
+ exports.buildResumeRecoveryPrompt = buildResumeRecoveryPrompt;
6
+ exports.extractCommandProposals = extractCommandProposals;
7
+ /** Claude stores resumable sessions under the spawn cwd. Relocating an existing
8
+ * Explore conversation from the repo to the workspace therefore makes its old
9
+ * session id unresolvable. Match ONLY Claude's exact diagnostic so auth, quota,
10
+ * model, and generic crash failures keep their existing no-retry semantics. */
11
+ const CLAUDE_MISSING_SESSION_DIAGNOSTIC = 'No conversation found with session ID';
12
+ /** Historical context folded into the one-time fresh-session recovery. This is
13
+ * deliberately byte-bounded independently of the current turn, whose existing
14
+ * attachment/scoped-context payload must remain intact. */
15
+ const RESUME_RECOVERY_TRANSCRIPT_MAX_BYTES = 48 * 1024;
16
+ function containsMissingClaudeSessionDiagnostic(value) {
17
+ if (typeof value === 'string') {
18
+ return value.includes(CLAUDE_MISSING_SESSION_DIAGNOSTIC);
19
+ }
20
+ if (value == null)
21
+ return false;
22
+ try {
23
+ return JSON.stringify(value).includes(CLAUDE_MISSING_SESSION_DIAGNOSTIC);
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ function isMissingClaudeSessionErrorResult(value) {
30
+ if (!value || typeof value !== 'object')
31
+ return false;
32
+ const payload = value;
33
+ const markedAsError = payload.is_error === true ||
34
+ (typeof payload.subtype === 'string' && payload.subtype.startsWith('error'));
35
+ return markedAsError && containsMissingClaudeSessionDiagnostic(value);
36
+ }
37
+ function takeUtf8Tail(text, maxBytes) {
38
+ if (maxBytes <= 0)
39
+ return '';
40
+ if (Buffer.byteLength(text) <= maxBytes)
41
+ return text;
42
+ let low = 0;
43
+ let high = text.length;
44
+ while (low < high) {
45
+ const mid = Math.floor((low + high) / 2);
46
+ if (Buffer.byteLength(text.slice(mid)) > maxBytes)
47
+ low = mid + 1;
48
+ else
49
+ high = mid;
50
+ }
51
+ // Never start on the trailing half of a UTF-16 surrogate pair.
52
+ if (low < text.length && text.charCodeAt(low) >= 0xdc00 && text.charCodeAt(low) <= 0xdfff)
53
+ low++;
54
+ return text.slice(low);
55
+ }
56
+ function buildResumeRecoveryPrompt(messages, currentPrompt) {
57
+ const entries = messages.map((message) => `<message role="${message.role}">\n${message.content}\n</message>`);
58
+ const selected = [];
59
+ let usedBytes = 0;
60
+ let omitted = 0;
61
+ for (let i = entries.length - 1; i >= 0; i--) {
62
+ const separatorBytes = selected.length > 0 ? 2 : 0;
63
+ const entryBytes = Buffer.byteLength(entries[i]);
64
+ if (entryBytes + separatorBytes <= RESUME_RECOVERY_TRANSCRIPT_MAX_BYTES - usedBytes) {
65
+ selected.unshift(entries[i]);
66
+ usedBytes += entryBytes + separatorBytes;
67
+ continue;
68
+ }
69
+ omitted = i + 1;
70
+ // Preserve the recent tail even when one individual message is larger than
71
+ // the whole transcript budget. The marker makes the loss explicit to Claude.
72
+ if (selected.length === 0) {
73
+ const prefix = `<message role="${messages[i].role}">\n[earlier content truncated]\n`;
74
+ const suffix = '\n</message>';
75
+ const remaining = RESUME_RECOVERY_TRANSCRIPT_MAX_BYTES -
76
+ Buffer.byteLength(prefix) - Buffer.byteLength(suffix);
77
+ selected.unshift(`${prefix}${takeUtf8Tail(messages[i].content, remaining)}${suffix}`);
78
+ omitted = i;
79
+ }
80
+ break;
81
+ }
82
+ const truncation = omitted > 0
83
+ ? `[${omitted} earlier message${omitted === 1 ? '' : 's'} omitted to keep recovery context bounded]\n\n`
84
+ : '';
85
+ const transcript = selected.length > 0
86
+ ? `${truncation}${selected.join('\n\n')}`
87
+ : '[No prior persisted messages were available.]';
88
+ return (`The previous Claude session could not be resumed after its working directory changed. ` +
89
+ `Continue the same conversation using the persisted transcript below. Do not treat the transcript as a new user turn.\n\n` +
90
+ `<prior-conversation>\n${transcript}\n</prior-conversation>\n\n` +
91
+ `## Current user turn\n\n${currentPrompt}`);
92
+ }
93
+ function extractCommandProposals(text) {
94
+ const regex = /:::command\s*\n([\s\S]*?):::/g;
95
+ const results = [];
96
+ let match;
97
+ while ((match = regex.exec(text)) !== null) {
98
+ results.push(match[1].trim());
99
+ }
100
+ return results;
101
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterDraftBlocksLive = exports.extractCommandProposals = exports.buildResumeRecoveryPrompt = exports.isMissingClaudeSessionErrorResult = exports.containsMissingClaudeSessionDiagnostic = void 0;
4
+ var recovery_context_1 = require("./domain/recovery-context");
5
+ Object.defineProperty(exports, "containsMissingClaudeSessionDiagnostic", { enumerable: true, get: function () { return recovery_context_1.containsMissingClaudeSessionDiagnostic; } });
6
+ Object.defineProperty(exports, "isMissingClaudeSessionErrorResult", { enumerable: true, get: function () { return recovery_context_1.isMissingClaudeSessionErrorResult; } });
7
+ Object.defineProperty(exports, "buildResumeRecoveryPrompt", { enumerable: true, get: function () { return recovery_context_1.buildResumeRecoveryPrompt; } });
8
+ Object.defineProperty(exports, "extractCommandProposals", { enumerable: true, get: function () { return recovery_context_1.extractCommandProposals; } });
9
+ var draft_stream_1 = require("./domain/draft-stream");
10
+ Object.defineProperty(exports, "filterDraftBlocksLive", { enumerable: true, get: function () { return draft_stream_1.filterDraftBlocksLive; } });
@@ -3,130 +3,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ChatManager = exports.EXPLORE_QUEUE_TIMEOUT_MS = exports.EXPLORE_MAX_CONCURRENCY = exports.EXPLORE_IDLE_KILL_MS = void 0;
7
- exports.filterDraftBlocksLive = filterDraftBlocksLive;
6
+ exports.ChatManager = exports.EXPLORE_QUEUE_TIMEOUT_MS = exports.EXPLORE_MAX_CONCURRENCY = exports.EXPLORE_IDLE_KILL_MS = exports.filterDraftBlocksLive = void 0;
7
+ const __1 = require("..");
8
+ var __2 = require("..");
9
+ Object.defineProperty(exports, "filterDraftBlocksLive", { enumerable: true, get: function () { return __2.filterDraftBlocksLive; } });
8
10
  const readline_1 = require("readline");
9
11
  const tree_kill_1 = __importDefault(require("tree-kill"));
10
- const db_1 = require("./db");
11
- const command_resolver_1 = require("./command-resolver");
12
- const cli_prompt_1 = require("./util/cli-prompt");
12
+ const db_1 = require("../../../db");
13
+ const command_resolver_1 = require("../../../command-resolver");
14
+ const cli_prompt_1 = require("../../../util/cli-prompt");
13
15
  const explore_cwd_manager_1 = require("./explore-cwd-manager");
14
- const ai_invocations_1 = require("./ai-invocations");
15
- const result_event_1 = require("./result-event");
16
+ const ai_invocations_1 = require("../../accounting/runtime/ai-invocations");
17
+ const result_event_1 = require("../../accounting/runtime/result-event");
16
18
  const crypto_1 = require("crypto");
17
- const codex_spawn_1 = require("./plugins/codex-spawn");
18
- const spec_draft_parser_1 = require("./spec-draft-parser");
19
- const attachment_manager_1 = require("./attachment-manager");
20
- const providers_1 = require("./providers");
21
- const runtime_1 = require("./providers/runtime");
19
+ const codex_spawn_1 = require("../../../plugins/codex-spawn");
20
+ const spec_draft_parser_1 = require("../../specs/runtime/spec-draft-parser");
21
+ const attachment_manager_1 = require("../../../attachment-manager");
22
+ const providers_1 = require("../../../providers");
23
+ const runtime_1 = require("../../../providers/runtime");
22
24
  const context_scope_1 = require("./context-scope");
23
- const user_mcp_config_1 = require("./user-mcp-config");
24
- const registry_1 = require("./providers/registry");
25
- const binary_probe_1 = require("./binary-probe");
25
+ const user_mcp_config_1 = require("../../../user-mcp-config");
26
+ const registry_1 = require("../../../providers/registry");
27
+ const binary_probe_1 = require("../../../binary-probe");
26
28
  const explore_stdin_session_1 = require("./explore-stdin-session");
27
- const workspace_resolution_1 = require("./workspace-resolution");
28
- const workspace_manager_1 = require("./workspace-manager");
29
- const blueprint_render_1 = require("./blueprint-render");
30
- const spec_contract_prompt_1 = require("./spec-contract-prompt");
29
+ const workspace_resolution_1 = require("../../../workspace-resolution");
30
+ const workspace_manager_1 = require("../../../workspace-manager");
31
+ const blueprint_render_1 = require("../../builder/runtime/blueprint-render");
32
+ const spec_contract_prompt_1 = require("../../specs/runtime/spec-contract-prompt");
31
33
  const explore_draft_title_1 = require("./explore-draft-title");
32
34
  const COMMAND_INSTRUCTION = 'When you want to suggest a SpecRails command for the user to execute, wrap it in a command block like this: ' +
33
35
  ':::command\n/specrails:implement #42\n::: ' +
34
36
  'The user will be prompted to confirm before the command runs.';
35
- /** Claude stores resumable sessions under the spawn cwd. Relocating an existing
36
- * Explore conversation from the repo to the workspace therefore makes its old
37
- * session id unresolvable. Match ONLY Claude's exact diagnostic so auth, quota,
38
- * model, and generic crash failures keep their existing no-retry semantics. */
39
- const CLAUDE_MISSING_SESSION_DIAGNOSTIC = 'No conversation found with session ID';
40
- /** Historical context folded into the one-time fresh-session recovery. This is
41
- * deliberately byte-bounded independently of the current turn, whose existing
42
- * attachment/scoped-context payload must remain intact. */
43
- const RESUME_RECOVERY_TRANSCRIPT_MAX_BYTES = 48 * 1024;
44
- function containsMissingClaudeSessionDiagnostic(value) {
45
- if (typeof value === 'string') {
46
- return value.includes(CLAUDE_MISSING_SESSION_DIAGNOSTIC);
47
- }
48
- if (value == null)
49
- return false;
50
- try {
51
- return JSON.stringify(value).includes(CLAUDE_MISSING_SESSION_DIAGNOSTIC);
52
- }
53
- catch {
54
- return false;
55
- }
56
- }
57
- function isMissingClaudeSessionErrorResult(value) {
58
- if (!value || typeof value !== 'object')
59
- return false;
60
- const payload = value;
61
- const markedAsError = payload.is_error === true ||
62
- (typeof payload.subtype === 'string' && payload.subtype.startsWith('error'));
63
- return markedAsError && containsMissingClaudeSessionDiagnostic(value);
64
- }
65
- function takeUtf8Tail(text, maxBytes) {
66
- if (maxBytes <= 0)
67
- return '';
68
- if (Buffer.byteLength(text) <= maxBytes)
69
- return text;
70
- let low = 0;
71
- let high = text.length;
72
- while (low < high) {
73
- const mid = Math.floor((low + high) / 2);
74
- if (Buffer.byteLength(text.slice(mid)) > maxBytes)
75
- low = mid + 1;
76
- else
77
- high = mid;
78
- }
79
- // Never start on the trailing half of a UTF-16 surrogate pair.
80
- if (low < text.length && text.charCodeAt(low) >= 0xdc00 && text.charCodeAt(low) <= 0xdfff)
81
- low++;
82
- return text.slice(low);
83
- }
84
- function buildResumeRecoveryPrompt(messages, currentPrompt) {
85
- const entries = messages.map((message) => `<message role="${message.role}">\n${message.content}\n</message>`);
86
- const selected = [];
87
- let usedBytes = 0;
88
- let omitted = 0;
89
- for (let i = entries.length - 1; i >= 0; i--) {
90
- const separatorBytes = selected.length > 0 ? 2 : 0;
91
- const entryBytes = Buffer.byteLength(entries[i]);
92
- if (entryBytes + separatorBytes <= RESUME_RECOVERY_TRANSCRIPT_MAX_BYTES - usedBytes) {
93
- selected.unshift(entries[i]);
94
- usedBytes += entryBytes + separatorBytes;
95
- continue;
96
- }
97
- omitted = i + 1;
98
- // Preserve the recent tail even when one individual message is larger than
99
- // the whole transcript budget. The marker makes the loss explicit to Claude.
100
- if (selected.length === 0) {
101
- const prefix = `<message role="${messages[i].role}">\n[earlier content truncated]\n`;
102
- const suffix = '\n</message>';
103
- const remaining = RESUME_RECOVERY_TRANSCRIPT_MAX_BYTES -
104
- Buffer.byteLength(prefix) - Buffer.byteLength(suffix);
105
- selected.unshift(`${prefix}${takeUtf8Tail(messages[i].content, remaining)}${suffix}`);
106
- omitted = i;
107
- }
108
- break;
109
- }
110
- const truncation = omitted > 0
111
- ? `[${omitted} earlier message${omitted === 1 ? '' : 's'} omitted to keep recovery context bounded]\n\n`
112
- : '';
113
- const transcript = selected.length > 0
114
- ? `${truncation}${selected.join('\n\n')}`
115
- : '[No prior persisted messages were available.]';
116
- return (`The previous Claude session could not be resumed after its working directory changed. ` +
117
- `Continue the same conversation using the persisted transcript below. Do not treat the transcript as a new user turn.\n\n` +
118
- `<prior-conversation>\n${transcript}\n</prior-conversation>\n\n` +
119
- `## Current user turn\n\n${currentPrompt}`);
120
- }
121
- function extractCommandProposals(text) {
122
- const regex = /:::command\s*\n([\s\S]*?):::/g;
123
- const results = [];
124
- let match;
125
- while ((match = regex.exec(text)) !== null) {
126
- results.push(match[1].trim());
127
- }
128
- return results;
129
- }
130
37
  // ─── Explore lifecycle ────────────────────────────────────────────────────────
131
38
  /** Tunables for Explore-spec acceleration lifecycle. Module-level constants
132
39
  * rather than ChatManager statics so tests can override via vi.spyOn or
@@ -1013,7 +920,7 @@ class ChatManager {
1013
920
  conversation.kind !== 'milestone') {
1014
921
  promptForAdapter = `${systemPrompt}\n\n---\n\n${promptForAdapter}`;
1015
922
  }
1016
- const buildRecoveryPrompt = () => buildResumeRecoveryPrompt((0, db_1.getMessages)(this._db, conversationId)
923
+ const buildRecoveryPrompt = () => (0, __1.buildResumeRecoveryPrompt)((0, db_1.getMessages)(this._db, conversationId)
1017
924
  .filter((message) => message.id !== persistedUserMessage.id)
1018
925
  .map((message) => ({ role: message.role, content: message.content })), promptForAdapter);
1019
926
  const turnOptions = {
@@ -1137,7 +1044,7 @@ class ChatManager {
1137
1044
  // user never sees the raw protocol payload mid-stream. The filter holds
1138
1045
  // back partial fence markers and emits only the user-visible prose.
1139
1046
  const filter = this._streamFilters.get(conversationId);
1140
- const visibleDelta = filter ? filterDraftBlocksLive(filter, newText) : newText;
1047
+ const visibleDelta = filter ? (0, __1.filterDraftBlocksLive)(filter, newText) : newText;
1141
1048
  if (visibleDelta) {
1142
1049
  this._broadcast({
1143
1050
  type: 'chat_stream',
@@ -1147,7 +1054,7 @@ class ChatManager {
1147
1054
  });
1148
1055
  }
1149
1056
  // Check for new command proposals
1150
- const proposals = extractCommandProposals(updated);
1057
+ const proposals = (0, __1.extractCommandProposals)(updated);
1151
1058
  const emitted = this._emittedProposals.get(conversationId);
1152
1059
  if (emitted) {
1153
1060
  for (const proposal of proposals) {
@@ -1245,10 +1152,10 @@ class ChatManager {
1245
1152
  !wasAborting &&
1246
1153
  fullText.length === 0 &&
1247
1154
  !adapterEvents.some((event) => event.kind === 'tool-use') &&
1248
- (containsMissingClaudeSessionDiagnostic(capturedErrorMessage) ||
1249
- containsMissingClaudeSessionDiagnostic(stderrBuf) ||
1155
+ ((0, __1.containsMissingClaudeSessionDiagnostic)(capturedErrorMessage) ||
1156
+ (0, __1.containsMissingClaudeSessionDiagnostic)(stderrBuf) ||
1250
1157
  adapterEvents.some((event) => event.kind === 'result' &&
1251
- isMissingClaudeSessionErrorResult(event.payload)));
1158
+ (0, __1.isMissingClaudeSessionErrorResult)(event.payload)));
1252
1159
  if (missingPriorSession) {
1253
1160
  resumeRecoveryAttempted = true;
1254
1161
  // The old id is provably unusable from the corrected cwd. Clearing it
@@ -1641,7 +1548,7 @@ class ChatManager {
1641
1548
  const prev = this._buffers.get(conversationId) ?? '';
1642
1549
  this._buffers.set(conversationId, prev + newText);
1643
1550
  const filter = this._streamFilters.get(conversationId);
1644
- const visibleDelta = filter ? filterDraftBlocksLive(filter, newText) : newText;
1551
+ const visibleDelta = filter ? (0, __1.filterDraftBlocksLive)(filter, newText) : newText;
1645
1552
  if (visibleDelta) {
1646
1553
  this._broadcast({
1647
1554
  type: 'chat_stream',
@@ -1650,7 +1557,7 @@ class ChatManager {
1650
1557
  timestamp: new Date().toISOString(),
1651
1558
  });
1652
1559
  }
1653
- const proposals = extractCommandProposals(this._buffers.get(conversationId) ?? '');
1560
+ const proposals = (0, __1.extractCommandProposals)(this._buffers.get(conversationId) ?? '');
1654
1561
  const emitted = this._emittedProposals.get(conversationId);
1655
1562
  if (emitted) {
1656
1563
  for (const proposal of proposals) {
@@ -1784,8 +1691,8 @@ class ChatManager {
1784
1691
  this._abortingConversations.has(conversationId) ||
1785
1692
  (this._buffers.get(conversationId) ?? '').length > 0 ||
1786
1693
  adapterEvents.some((event) => event.kind === 'tool-use') ||
1787
- !(containsMissingClaudeSessionDiagnostic(diagnostic) ||
1788
- containsMissingClaudeSessionDiagnostic(stderrBuf))) {
1694
+ !((0, __1.containsMissingClaudeSessionDiagnostic)(diagnostic) ||
1695
+ (0, __1.containsMissingClaudeSessionDiagnostic)(stderrBuf))) {
1789
1696
  return false;
1790
1697
  }
1791
1698
  // The persistent child was launched with the stale --resume before its
@@ -1926,7 +1833,7 @@ class ChatManager {
1926
1833
  break;
1927
1834
  case 'result': {
1928
1835
  const payload = ev.payload;
1929
- if (recoverMissingSession(isMissingClaudeSessionErrorResult(payload) ? payload : null))
1836
+ if (recoverMissingSession((0, __1.isMissingClaudeSessionErrorResult)(payload) ? payload : null))
1930
1837
  break;
1931
1838
  if (payload.session_id)
1932
1839
  capturedSessionId = payload.session_id;
@@ -2221,94 +2128,3 @@ class ChatManager {
2221
2128
  }
2222
2129
  }
2223
2130
  exports.ChatManager = ChatManager;
2224
- const FENCE_OPEN = '```spec-draft';
2225
- const FENCE_CLOSE = '```';
2226
- // Hold back up to this many trailing chars in the pre-block state so we never
2227
- // emit a partial open fence. -1 because we know the user-visible prefix is at
2228
- // least 1 char shorter than the full marker on every step.
2229
- const PRE_BLOCK_TAIL = FENCE_OPEN.length - 1;
2230
- /**
2231
- * Stateful, side-effect-free filter that consumes `newText` and returns the
2232
- * substring that is safe to broadcast to the chat stream. Holds back partial
2233
- * fence markers in `state.pendingTail` so the next call can resolve them.
2234
- *
2235
- * Behaviour:
2236
- * - While outside a block: emit text up to (but not including) the start of
2237
- * a `\`\`\`spec-draft` marker. If no marker is present, hold back the
2238
- * trailing few chars so a marker starting on a chunk boundary is not
2239
- * leaked.
2240
- * - While inside a block: emit nothing. Look for the closing `\`\`\``.
2241
- * When found, consume it (plus an optional trailing newline) and resume
2242
- * emitting from the bytes that follow.
2243
- *
2244
- * The filter intentionally does NOT validate the JSON payload — that is
2245
- * server-side concern of `parseSpecDraftBlocks`. It only strips the fenced
2246
- * span.
2247
- */
2248
- function filterDraftBlocksLive(state, newText) {
2249
- let buf = state.pendingTail + newText;
2250
- let out = '';
2251
- state.pendingTail = '';
2252
- // Iterate in case a single delta contains multiple transitions
2253
- // (e.g. close + open + close again — pathological but cheap to support).
2254
- while (buf.length > 0) {
2255
- if (state.inBlock) {
2256
- const closeIdx = buf.indexOf(FENCE_CLOSE);
2257
- if (closeIdx === -1) {
2258
- // No close yet — but the close could span the chunk boundary.
2259
- // Hold back up to 2 trailing chars (closing fence is 3 chars; we keep
2260
- // any trailing run of `\`` so the next call resolves it).
2261
- const tailLen = trailingBacktickRun(buf, 2);
2262
- state.pendingTail = buf.slice(buf.length - tailLen);
2263
- return out;
2264
- }
2265
- // Consume the close fence + an optional trailing newline.
2266
- let after = closeIdx + FENCE_CLOSE.length;
2267
- if (buf[after] === '\n')
2268
- after += 1;
2269
- buf = buf.slice(after);
2270
- state.inBlock = false;
2271
- continue;
2272
- }
2273
- // Not in block: look for the open marker.
2274
- const openIdx = buf.indexOf(FENCE_OPEN);
2275
- if (openIdx !== -1) {
2276
- out += buf.slice(0, openIdx);
2277
- buf = buf.slice(openIdx + FENCE_OPEN.length);
2278
- // Drop an optional newline immediately after the open marker so the
2279
- // user never sees `\n` belonging to the fence.
2280
- if (buf[0] === '\n')
2281
- buf = buf.slice(1);
2282
- state.inBlock = true;
2283
- continue;
2284
- }
2285
- // No open marker — hold back only the trailing run that could become a
2286
- // prefix of FENCE_OPEN (i.e. the longest suffix of `buf` that is also a
2287
- // prefix of FENCE_OPEN). Anything past that is safe to emit.
2288
- const holdBack = longestSuffixThatIsPrefixOf(buf, FENCE_OPEN);
2289
- const safeEnd = buf.length - holdBack;
2290
- out += buf.slice(0, safeEnd);
2291
- state.pendingTail = buf.slice(safeEnd);
2292
- return out;
2293
- }
2294
- return out;
2295
- }
2296
- /** Length of the longest suffix of `s` that is a prefix of `target`. */
2297
- function longestSuffixThatIsPrefixOf(s, target) {
2298
- const max = Math.min(s.length, target.length - 1);
2299
- for (let len = max; len > 0; len--) {
2300
- if (target.startsWith(s.slice(s.length - len)))
2301
- return len;
2302
- }
2303
- return 0;
2304
- }
2305
- function trailingBacktickRun(s, max) {
2306
- let n = 0;
2307
- for (let i = s.length - 1; i >= 0 && n < max; i--) {
2308
- if (s[i] === '`')
2309
- n++;
2310
- else
2311
- break;
2312
- }
2313
- return n;
2314
- }
@@ -15,7 +15,7 @@ exports.getContextBudget = getContextBudget;
15
15
  const node_fs_1 = __importDefault(require("node:fs"));
16
16
  const node_path_1 = __importDefault(require("node:path"));
17
17
  const context_scope_1 = require("./context-scope");
18
- const workspace_resolution_1 = require("./workspace-resolution");
18
+ const workspace_resolution_1 = require("../../../workspace-resolution");
19
19
  const BYTES_PER_TOKEN = 4;
20
20
  const CACHE_TTL_MS = 60_000;
21
21
  const SKIP_DIRS = new Set([
@@ -11,7 +11,7 @@ exports.removeExploreCwd = removeExploreCwd;
11
11
  const fs_1 = __importDefault(require("fs"));
12
12
  const path_1 = __importDefault(require("path"));
13
13
  const os_1 = __importDefault(require("os"));
14
- const providers_1 = require("./providers");
14
+ const providers_1 = require("../../../providers");
15
15
  /**
16
16
  * ExploreCwdManager owns the per-project app-managed cwd used to spawn the
17
17
  * provider CLI for Explore Spec turns. See openspec/changes/accelerate-spec-