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
@@ -5,13 +5,13 @@ const ids_1 = require("./ids");
5
5
  const db_1 = require("./db");
6
6
  const providers_1 = require("./providers");
7
7
  const runtime_1 = require("./providers/runtime");
8
- const context_scope_1 = require("./context-scope");
9
- const spec_models_1 = require("./spec-models");
8
+ const context_scope_1 = require("./modules/conversations/runtime/context-scope");
9
+ const spec_models_1 = require("./modules/specs/runtime/spec-models");
10
10
  const provider_selection_1 = require("./provider-selection");
11
- const ticket_store_1 = require("./ticket-store");
11
+ const ticket_store_1 = require("./modules/specs/runtime/ticket-store");
12
12
  const project_router_helpers_1 = require("./project-router-helpers");
13
13
  function registerChatRoutes(deps) {
14
- const { router, registry, ctx, ticketPath } = deps;
14
+ const { router, ctx, ticketPath } = deps;
15
15
  // ─── Chat routes ─────────────────────────────────────────────────────────────
16
16
  router.get('/:projectId/chat/conversations', (req, res) => {
17
17
  const conversations = (0, db_1.listConversations)(ctx(req).db);
@@ -94,7 +94,7 @@ function registerChatRoutes(deps) {
94
94
  res.status(201).json({ conversation });
95
95
  });
96
96
  router.get('/:projectId/chat/conversations/:id', (req, res) => {
97
- const { db, project } = ctx(req);
97
+ const { db } = ctx(req);
98
98
  const conversation = (0, db_1.getConversation)(db, req.params.id);
99
99
  if (!conversation) {
100
100
  res.status(404).json({ error: 'Conversation not found' });
@@ -104,7 +104,7 @@ function registerChatRoutes(deps) {
104
104
  res.json({ conversation, messages });
105
105
  });
106
106
  router.delete('/:projectId/chat/conversations/:id', (req, res) => {
107
- const { db, chatManager, broadcast, project, ticketWatcher } = ctx(req);
107
+ const { db, chatManager, ticketWatcher } = ctx(req);
108
108
  const convId = req.params.id;
109
109
  const conversation = (0, db_1.getConversation)(db, convId);
110
110
  if (!conversation) {
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.registerGitRoutes = registerGitRoutes;
7
7
  const project_git_1 = require("./project-git");
8
8
  const git_diagnostics_1 = require("./git-diagnostics");
9
- const pr_publisher_1 = require("./pr-publisher");
9
+ const pr_publisher_1 = require("./modules/delivery/runtime/pr-publisher");
10
10
  const repo_lock_1 = require("./repo-lock");
11
11
  const process_admission_1 = require("./process-admission");
12
12
  const project_repositories_1 = require("./project-repositories");
@@ -20,8 +20,8 @@ exports.serializeInstallConfigYaml = serializeInstallConfigYaml;
20
20
  const fs_1 = __importDefault(require("fs"));
21
21
  const path_1 = __importDefault(require("path"));
22
22
  const core_package_1 = require("./core-package");
23
- const spec_models_1 = require("./spec-models");
24
- const ticket_store_1 = require("./ticket-store");
23
+ const spec_models_1 = require("./modules/specs/runtime/spec-models");
24
+ const ticket_store_1 = require("./modules/specs/runtime/ticket-store");
25
25
  const install_config_path_1 = require("./install-config-path");
26
26
  const workspace_resolution_1 = require("./workspace-resolution");
27
27
  const TERMINAL_PANEL_ENABLED = process.env.SPECRAILS_TERMINAL_PANEL !== 'false';
@@ -1,27 +1,29 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerJobsRoutes = registerJobsRoutes;
4
- const agent_runtime_controls_router_1 = require("./agent-runtime-controls-router");
4
+ // Domain routes extracted from project-router.ts (jobs).
5
+ // Registered on the shared router by createProjectRouter — behaviour-preserving.
6
+ const agent_runtime_controls_router_1 = require("./modules/agent-runtime/runtime/agent-runtime-controls-router");
5
7
  const ids_1 = require("./ids");
6
8
  const db_1 = require("./db");
7
- const queue_manager_1 = require("./queue-manager");
9
+ const queue_manager_1 = require("./modules/execution/runtime/queue-manager");
8
10
  const feature_flags_1 = require("./feature-flags");
9
11
  const types_1 = require("./types");
10
- const job_phase_breakdown_1 = require("./job-phase-breakdown");
12
+ const job_phase_breakdown_1 = require("./modules/execution/runtime/job-phase-breakdown");
11
13
  const providers_1 = require("./providers");
12
14
  const hooks_1 = require("./hooks");
13
- const explore_smash_1 = require("./explore-smash");
14
- const job_spawn_idempotency_1 = require("./job-spawn-idempotency");
15
- const spec_models_1 = require("./spec-models");
15
+ const explore_smash_1 = require("./modules/conversations/runtime/explore-smash");
16
+ const job_spawn_idempotency_1 = require("./modules/execution/runtime/job-spawn-idempotency");
17
+ const spec_models_1 = require("./modules/specs/runtime/spec-models");
16
18
  const provider_selection_1 = require("./provider-selection");
17
- const loop_runs_store_1 = require("./loop-runs-store");
18
- const metrics_1 = require("./metrics");
19
- const job_listing_1 = require("./job-listing");
20
- const ticket_store_1 = require("./ticket-store");
19
+ const loop_runs_store_1 = require("./modules/loops/runtime/loop-runs-store");
20
+ const metrics_1 = require("./modules/accounting/runtime/metrics");
21
+ const job_listing_1 = require("./modules/execution/runtime/job-listing");
22
+ const ticket_store_1 = require("./modules/specs/runtime/ticket-store");
21
23
  const project_router_background_processes_1 = require("./project-router-background-processes");
22
24
  const project_router_helpers_1 = require("./project-router-helpers");
23
25
  function registerJobsRoutes(deps) {
24
- const { router, registry, ctx, ticketPath } = deps;
26
+ const { router, ctx, ticketPath } = deps;
25
27
  // ─── Queue / Spawn routes ────────────────────────────────────────────────────
26
28
  router.post('/:projectId/spawn', (req, res) => {
27
29
  const { command, priority, dependsOnJobId, pipelineId, profileName, aiEngine, model, rerunOfJobId, } = req.body ?? {};
@@ -204,7 +206,7 @@ function registerJobsRoutes(deps) {
204
206
  (0, project_router_background_processes_1.registerBackgroundProcessRoutes)(deps);
205
207
  // Returns the resolved default model for Add Spec + the full provider
206
208
  // allow-list so the modal can render its picker without maintaining its
207
- // own copy of the model lists. Source of truth is `server/spec-models.ts`.
209
+ // own copy of the model lists. Source of truth is `server/modules/specs/runtime/spec-models.ts`.
208
210
  router.get('/:projectId/default-spec-model', (req, res) => {
209
211
  const { project } = ctx(req);
210
212
  // Multi-provider: an optional ?provider= query selects which engine's models
@@ -1,25 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerLoopRunRoutes = registerLoopRunRoutes;
4
- const loop_graph_1 = require("./loop-graph");
4
+ const loop_graph_1 = require("./modules/loops/runtime/loop-graph");
5
5
  const feature_flags_1 = require("./feature-flags");
6
- const loops_store_1 = require("./loops-store");
7
- const loop_runs_store_1 = require("./loop-runs-store");
8
- const run_duration_stats_1 = require("./run-duration-stats");
9
- const loop_constants_1 = require("./loop-constants");
6
+ const loops_store_1 = require("./modules/loops/runtime/loops-store");
7
+ const loop_runs_store_1 = require("./modules/loops/runtime/loop-runs-store");
8
+ const run_duration_stats_1 = require("./modules/execution/runtime/run-duration-stats");
9
+ const loop_constants_1 = require("./modules/loops/runtime/loop-constants");
10
10
  const providers_1 = require("./providers");
11
11
  const runtime_1 = require("./providers/runtime");
12
- const agent_defaults_1 = require("./agent-defaults");
12
+ const agent_defaults_1 = require("./modules/agents/runtime/agent-defaults");
13
13
  const provider_selection_1 = require("./provider-selection");
14
- const spec_models_1 = require("./spec-models");
14
+ const spec_models_1 = require("./modules/specs/runtime/spec-models");
15
15
  const workspace_resolution_1 = require("./workspace-resolution");
16
- const loop_command_catalog_1 = require("./loop-command-catalog");
16
+ const loop_command_catalog_1 = require("./modules/loops/runtime/loop-command-catalog");
17
17
  const ids_1 = require("./ids");
18
18
  const project_repositories_1 = require("./project-repositories");
19
- const multi_repo_execution_1 = require("./multi-repo-execution");
20
- const rails_store_1 = require("./rails-store");
21
- const rail_pr_store_1 = require("./rail-pr-store");
22
- const rail_isolation_1 = require("./rail-isolation");
19
+ const multi_repo_execution_1 = require("./modules/delivery/runtime/multi-repo-execution");
20
+ const rails_store_1 = require("./modules/delivery/runtime/rails-store");
21
+ const rail_pr_store_1 = require("./modules/delivery/runtime/rail-pr-store");
22
+ const rail_isolation_1 = require("./modules/delivery/runtime/rail-isolation");
23
23
  const process_admission_1 = require("./process-admission");
24
24
  function registerLoopRunRoutes(deps) {
25
25
  const { router, ctx } = deps;
@@ -4,32 +4,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.registerSettingsRoutes = registerSettingsRoutes;
7
- // Domain routes extracted from project-router.ts (settings).
8
- // Registered on the shared router by createProjectRouter — behaviour-preserving.
7
+ // Composition for project settings and the remaining settings-related routes.
8
+ // The project-settings module owns its validation, use cases and HTTP adapter.
9
+ const project_settings_1 = require("./modules/project-settings");
10
+ const sqlite_1 = require("./modules/project-settings/adapters/sqlite");
11
+ const http_1 = require("./modules/project-settings/adapters/http");
9
12
  const fs_1 = __importDefault(require("fs"));
10
13
  const path_1 = __importDefault(require("path"));
11
14
  const db_1 = require("./db");
12
- const telemetry_export_1 = require("./telemetry-export");
15
+ const telemetry_export_1 = require("./modules/accounting/runtime/telemetry-export");
13
16
  const integration_branch_1 = require("./integration-branch");
14
17
  const worktree_manager_1 = require("./worktree-manager");
15
- const context_budget_1 = require("./context-budget");
16
- const context_scope_1 = require("./context-scope");
17
- const spec_models_1 = require("./spec-models");
18
- const terminal_settings_1 = require("./terminal-settings");
19
- const terminal_marks_store_1 = require("./terminal-marks-store");
18
+ const context_budget_1 = require("./modules/conversations/runtime/context-budget");
19
+ const context_scope_1 = require("./modules/conversations/runtime/context-scope");
20
+ const spec_models_1 = require("./modules/specs/runtime/spec-models");
21
+ const terminal_settings_1 = require("./modules/terminals/runtime/terminal-settings");
22
+ const terminal_marks_store_1 = require("./modules/terminals/runtime/terminal-marks-store");
20
23
  const project_router_helpers_1 = require("./project-router-helpers");
21
24
  const install_config_path_1 = require("./install-config-path");
22
- const agent_runtime_settings_router_1 = require("./agent-runtime-settings-router");
23
- const agent_runtime_controls_router_1 = require("./agent-runtime-controls-router");
25
+ const agent_runtime_settings_router_1 = require("./modules/agent-runtime/runtime/agent-runtime-settings-router");
26
+ const agent_runtime_controls_router_1 = require("./modules/agent-runtime/runtime/agent-runtime-controls-router");
24
27
  function registerSettingsRoutes(deps) {
25
28
  (0, agent_runtime_settings_router_1.registerAgentRuntimeSettingsRoutes)(deps);
26
29
  (0, agent_runtime_controls_router_1.registerAgentRuntimeControlRoutes)(deps);
27
- const { router, registry, ctx, ticketPath } = deps;
30
+ const { router, registry, ctx } = deps;
28
31
  // ─── Project settings (pipeline telemetry) ───────────────────────────────────
29
- router.get('/:projectId/settings', (req, res) => {
30
- const settings = (0, db_1.getProjectSettings)(ctx(req).db);
31
- res.json(settings);
32
- });
32
+ (0, http_1.registerProjectSettingsHttp)(router, req => (0, project_settings_1.createProjectSettingsService)((0, sqlite_1.createSqliteProjectSettingsRepository)(ctx(req).db)));
33
33
  // ─── Per-project Quick mode Contract Refine last-used value ─────────────────
34
34
  router.get('/:projectId/add-spec-quick-contract-refine-last', (req, res) => {
35
35
  res.json({
@@ -80,66 +80,6 @@ function registerSettingsRoutes(deps) {
80
80
  (0, context_scope_1.setLastContextScope)(ctx(req).db, merged);
81
81
  res.json({ scope: merged });
82
82
  });
83
- router.patch('/:projectId/settings', (req, res) => {
84
- const { pipelineTelemetryEnabled, orchestratorModel, prePrompt, freestylePrePrompt, worktreeEnvPassthrough } = req.body ?? {};
85
- const patch = {};
86
- if (pipelineTelemetryEnabled !== undefined) {
87
- patch.pipelineTelemetryEnabled = Boolean(pipelineTelemetryEnabled);
88
- }
89
- const VALID_MODELS = ['sonnet', 'opus', 'haiku'];
90
- if (orchestratorModel !== undefined) {
91
- if (typeof orchestratorModel !== 'string' || !VALID_MODELS.includes(orchestratorModel)) {
92
- res.status(400).json({ error: `orchestratorModel must be one of: ${VALID_MODELS.join(', ')}` });
93
- return;
94
- }
95
- patch.orchestratorModel = orchestratorModel;
96
- }
97
- if (prePrompt !== undefined) {
98
- if (typeof prePrompt !== 'string') {
99
- res.status(400).json({ error: 'prePrompt must be a string' });
100
- return;
101
- }
102
- patch.prePrompt = prePrompt;
103
- }
104
- if (freestylePrePrompt !== undefined) {
105
- if (typeof freestylePrePrompt !== 'string') {
106
- res.status(400).json({ error: 'freestylePrePrompt must be a string' });
107
- return;
108
- }
109
- patch.freestylePrePrompt = freestylePrePrompt;
110
- }
111
- if (worktreeEnvPassthrough !== undefined) {
112
- try {
113
- patch.worktreeEnvPassthrough = (0, db_1.normalizeWorktreeEnvPassthrough)(worktreeEnvPassthrough);
114
- }
115
- catch (err) {
116
- res.status(400).json({ error: err instanceof Error ? err.message : 'invalid worktreeEnvPassthrough' });
117
- return;
118
- }
119
- }
120
- if (req.body?.integrationBranch !== undefined) {
121
- const ib = req.body.integrationBranch;
122
- if (typeof ib !== 'string') {
123
- res.status(400).json({ error: 'integrationBranch must be a string' });
124
- return;
125
- }
126
- // Empty = clear (auto-resolve). A non-empty value flows into `git worktree
127
- // add … <base>`, so it must be a safe branch name (no arg-injection).
128
- if (ib.trim() !== '' && !(0, integration_branch_1.isValidBranchName)(ib)) {
129
- res.status(400).json({ error: 'integrationBranch is not a valid branch name' });
130
- return;
131
- }
132
- patch.integrationBranch = ib;
133
- }
134
- try {
135
- (0, db_1.updateProjectSettings)(ctx(req).db, patch);
136
- res.json({ ok: true, settings: (0, db_1.getProjectSettings)(ctx(req).db) });
137
- }
138
- catch (err) {
139
- console.error('[project-router] settings patch error:', err);
140
- res.status(500).json({ error: 'Failed to update settings' });
141
- }
142
- });
143
83
  // Resolve the effective integration branch (configured value + what it resolves
144
84
  // to right now + provenance) so the client can show the base before launch.
145
85
  router.get('/:projectId/integration-branch', async (req, res) => {
@@ -11,8 +11,8 @@ const path_1 = __importDefault(require("path"));
11
11
  const ids_1 = require("./ids");
12
12
  const db_1 = require("./db");
13
13
  const desktop_db_1 = require("./desktop-db");
14
- const queue_manager_1 = require("./queue-manager");
15
- const changes_reader_1 = require("./changes-reader");
14
+ const queue_manager_1 = require("./modules/execution/runtime/queue-manager");
15
+ const changes_reader_1 = require("./modules/code/runtime/changes-reader");
16
16
  const project_router_helpers_1 = require("./project-router-helpers");
17
17
  const install_config_path_1 = require("./install-config-path");
18
18
  const workspace_resolution_1 = require("./workspace-resolution");
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseTzOffsetMinutes = parseTzOffsetMinutes;
4
4
  exports.localDayBoundsUtc = localDayBoundsUtc;
5
5
  exports.registerSpendingRoutes = registerSpendingRoutes;
6
- const queue_manager_1 = require("./queue-manager");
6
+ const queue_manager_1 = require("./modules/execution/runtime/queue-manager");
7
7
  const config_1 = require("./config");
8
8
  const workspace_resolution_1 = require("./workspace-resolution");
9
- const ai_invocations_1 = require("./ai-invocations");
10
- const spending_1 = require("./spending");
11
- const ticket_store_1 = require("./ticket-store");
9
+ const ai_invocations_1 = require("./modules/accounting/runtime/ai-invocations");
10
+ const spending_1 = require("./modules/accounting/runtime/spending");
11
+ const ticket_store_1 = require("./modules/specs/runtime/ticket-store");
12
12
  /**
13
13
  * Parse + clamp a `tzOffsetMinutes` query param (minutes east of UTC, the value
14
14
  * `Date.prototype.getTimezoneOffset()` negates). Non-numeric / out-of-range
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerTerminalsRoutes = registerTerminalsRoutes;
4
- const terminal_settings_1 = require("./terminal-settings");
4
+ const terminal_settings_1 = require("./modules/terminals/runtime/terminal-settings");
5
5
  const feature_flags_1 = require("./feature-flags");
6
- const browser_capture_types_1 = require("./browser-capture-types");
7
- const terminal_manager_1 = require("./terminal-manager");
6
+ const browser_capture_types_1 = require("./modules/browser/runtime/browser-capture-types");
7
+ const terminal_manager_1 = require("./modules/terminals/runtime/terminal-manager");
8
8
  const project_router_helpers_1 = require("./project-router-helpers");
9
9
  function registerTerminalsRoutes(deps) {
10
- const { router, registry, ctx, ticketPath } = deps;
10
+ const { router, registry, ctx } = deps;
11
11
  // ─── Terminals ───────────────────────────────────────────────────────────────
12
12
  function requireTerminalsEnabled(_req, res, next) {
13
13
  if (!project_router_helpers_1.TERMINAL_PANEL_ENABLED) {
@@ -44,20 +44,20 @@ const project_repositories_1 = require("./project-repositories");
44
44
  const ids_1 = require("./ids");
45
45
  const db_1 = require("./db");
46
46
  const providers_1 = require("./providers");
47
- const contract_refine_runner_1 = require("./contract-refine-runner");
48
- const explore_contract_refine_1 = require("./explore-contract-refine");
49
- const smash_runner_1 = require("./smash-runner");
50
- const explore_smash_1 = require("./explore-smash");
51
- const ai_invocations_1 = require("./ai-invocations");
52
- const context_scope_1 = require("./context-scope");
53
- const result_event_1 = require("./result-event");
47
+ const contract_refine_runner_1 = require("./modules/specs/runtime/contract-refine-runner");
48
+ const explore_contract_refine_1 = require("./modules/conversations/runtime/explore-contract-refine");
49
+ const smash_runner_1 = require("./modules/specs/runtime/smash-runner");
50
+ const explore_smash_1 = require("./modules/conversations/runtime/explore-smash");
51
+ const ai_invocations_1 = require("./modules/accounting/runtime/ai-invocations");
52
+ const context_scope_1 = require("./modules/conversations/runtime/context-scope");
53
+ const result_event_1 = require("./modules/accounting/runtime/result-event");
54
54
  const runtime_1 = require("./providers/runtime");
55
55
  const crypto_1 = require("crypto");
56
- const spec_models_1 = require("./spec-models");
56
+ const spec_models_1 = require("./modules/specs/runtime/spec-models");
57
57
  const provider_selection_1 = require("./provider-selection");
58
- const ticket_store_1 = require("./ticket-store");
59
- const explore_draft_title_1 = require("./explore-draft-title");
60
- const spec_addenda_1 = require("./spec-addenda");
58
+ const ticket_store_1 = require("./modules/specs/runtime/ticket-store");
59
+ const explore_draft_title_1 = require("./modules/conversations/runtime/explore-draft-title");
60
+ const spec_addenda_1 = require("./modules/specs/runtime/spec-addenda");
61
61
  const cli_prompt_1 = require("./util/cli-prompt");
62
62
  const transient_children_1 = require("./transient-children");
63
63
  const process_admission_1 = require("./process-admission");
@@ -131,7 +131,7 @@ async function maybePromoteSpecToJira(c, ticketId, createLocal, broadcast) {
131
131
  }
132
132
  }
133
133
  function registerTicketsRoutes(deps) {
134
- const { router, registry, ctx, ticketPath } = deps;
134
+ const { router, ctx, ticketPath } = deps;
135
135
  // Validate scope at every authoring boundary before writes, uploads or AI.
136
136
  const validateRepositoryScope = (req, res, next) => {
137
137
  try {
@@ -1251,7 +1251,7 @@ function registerTicketsRoutes(deps) {
1251
1251
  // Validate the ticket exists.
1252
1252
  try {
1253
1253
  const filePath = ticketPath(req);
1254
- const { withLock } = await Promise.resolve().then(() => __importStar(require('./ticket-store')));
1254
+ const { withLock } = await Promise.resolve().then(() => __importStar(require('./modules/specs/runtime/ticket-store')));
1255
1255
  const ticket = withLock(filePath, (s) => s.tickets[String(ticketId)]);
1256
1256
  if (!ticket) {
1257
1257
  res.status(404).json({ error: 'ticket not found' });
@@ -1327,7 +1327,7 @@ function registerTicketsRoutes(deps) {
1327
1327
  const { project, db, broadcast } = ctx(req);
1328
1328
  try {
1329
1329
  const filePath = ticketPath(req);
1330
- const { readStore } = await Promise.resolve().then(() => __importStar(require('./ticket-store')));
1330
+ const { readStore } = await Promise.resolve().then(() => __importStar(require('./modules/specs/runtime/ticket-store')));
1331
1331
  const store = readStore(filePath);
1332
1332
  const gate = (0, smash_runner_1.checkSmashEligibility)(store, ticketId);
1333
1333
  if (!gate.ok) {
@@ -8,25 +8,25 @@ exports.createProjectRouter = createProjectRouter;
8
8
  const express_1 = require("express");
9
9
  const node_fs_1 = __importDefault(require("node:fs"));
10
10
  const project_repositories_1 = require("./project-repositories");
11
- const file_summary_manager_1 = require("./file-summary-manager");
12
- const project_code_discovery_1 = require("./project-code-discovery");
11
+ const file_summary_manager_1 = require("./modules/code/runtime/file-summary-manager");
12
+ const project_code_discovery_1 = require("./modules/code/runtime/project-code-discovery");
13
13
  const feature_flags_1 = require("./feature-flags");
14
14
  const hooks_1 = require("./hooks");
15
- const rails_router_1 = require("./rails-router");
16
- const profiles_router_1 = require("./profiles-router");
15
+ const rails_router_1 = require("./modules/delivery/runtime/rails-router");
16
+ const profiles_router_1 = require("./modules/agents/runtime/profiles-router");
17
17
  const plugins_router_1 = require("./plugins-router");
18
- const code_explorer_router_1 = require("./code-explorer-router");
19
- const code_activity_1 = require("./code-activity");
18
+ const code_explorer_router_1 = require("./modules/code/runtime/code-explorer-router");
19
+ const code_activity_1 = require("./modules/code/runtime/code-activity");
20
20
  const jira_router_1 = require("./jira-router");
21
- const ticket_store_1 = require("./ticket-store");
21
+ const ticket_store_1 = require("./modules/specs/runtime/ticket-store");
22
22
  const workspace_resolution_1 = require("./workspace-resolution");
23
23
  const workspace_manager_1 = require("./workspace-manager");
24
- const blueprint_render_1 = require("./blueprint-render");
25
- const milestone_progress_1 = require("./milestone-progress");
26
- const blueprint_draft_parser_1 = require("./blueprint-draft-parser");
27
- const blueprint_spec_quality_1 = require("./blueprint-spec-quality");
28
- const file_story_manager_1 = require("./file-story-manager");
29
- const file_summary_generator_1 = require("./file-summary-generator");
24
+ const blueprint_render_1 = require("./modules/builder/runtime/blueprint-render");
25
+ const milestone_progress_1 = require("./modules/builder/runtime/milestone-progress");
26
+ const blueprint_draft_parser_1 = require("./modules/builder/runtime/blueprint-draft-parser");
27
+ const blueprint_spec_quality_1 = require("./modules/builder/runtime/blueprint-spec-quality");
28
+ const file_story_manager_1 = require("./modules/code/runtime/file-story-manager");
29
+ const file_summary_generator_1 = require("./modules/code/runtime/file-summary-generator");
30
30
  const providers_1 = require("./providers");
31
31
  const desktop_db_1 = require("./desktop-db");
32
32
  const project_router_jobs_1 = require("./project-router-jobs");
@@ -21,7 +21,7 @@ const WHICH_CMD = process.platform === 'win32' ? 'where' : 'which';
21
21
  const CLAUDE_MODELS = [
22
22
  { value: 'sonnet', label: 'Claude Sonnet', default: true },
23
23
  { value: 'fable', label: 'Claude Fable' },
24
- { value: 'opus', label: 'Claude Opus' },
24
+ { value: 'opus', label: 'Claude Opus 5.5' },
25
25
  { value: 'haiku', label: 'Claude Haiku' },
26
26
  ];
27
27
  /** Mirror of ChatManager.normalizeClaudeCodeModel — pinned model strings the
@@ -36,6 +36,7 @@ function normaliseModel(model) {
36
36
  return 'sonnet';
37
37
  case 'claude-fable-5':
38
38
  return 'fable';
39
+ case 'claude-opus-5-5':
39
40
  case 'claude-opus-5':
40
41
  case 'claude-opus-4-8':
41
42
  case 'claude-opus-4-5':
@@ -61,7 +62,7 @@ function normaliseModel(model) {
61
62
  * bare `opus` alias currently points at.
62
63
  */
63
64
  const PINNED_ALIAS_MODEL_IDS = {
64
- opus: 'claude-opus-5',
65
+ opus: 'claude-opus-5-5',
65
66
  };
66
67
  /** Catalog value (or concrete id) in, spawn model id out. */
67
68
  function resolveSpawnModel(model) {
@@ -21,8 +21,8 @@
21
21
  // `mcp_tool_call`. The parser matches all four for forward/backward compat.
22
22
  //
23
23
  // Codex does not emit `total_cost_usd`; cost is estimated downstream via
24
- // server/pricing.ts. Codex does not honour Claude's OTEL env vars; signals are
25
- // synthesised by server/codex-otel-bridge.ts.
24
+ // server/modules/accounting/runtime/pricing.ts. Codex does not honour Claude's OTEL env vars; signals are
25
+ // synthesised by server/modules/accounting/runtime/codex-otel-bridge.ts.
26
26
  //
27
27
  // Spec: openspec/specs/multi-provider-architecture/spec.md
28
28
  var __importDefault = (this && this.__importDefault) || function (mod) {
@@ -37,7 +37,7 @@ const WHICH_CMD = process.platform === 'win32' ? 'where' : 'which';
37
37
  const CODEX_MIN_VERSION = '0.128.0';
38
38
  exports._CODEX_MIN_VERSION = CODEX_MIN_VERSION;
39
39
  const CODEX_MODELS = [
40
- // Newest first. gpt-6-astra has no rate card in `server/pricing.ts` yet, so
40
+ // Newest first. gpt-6-astra has no rate card in `server/modules/accounting/runtime/pricing.ts` yet, so
41
41
  // its turns show cost as unavailable (honest-metrics: never fabricated).
42
42
  { value: 'gpt-6-astra', label: 'GPT-6 Astra' },
43
43
  { value: 'gpt-5.6-sol', label: 'GPT-5.6 Sol' },
@@ -12,7 +12,7 @@
12
12
  // "cached":N,"total_tokens":N,"duration_ms":N}}
13
13
  //
14
14
  // Differences vs codex: Gemini reports tokens but NOT cost, so `nativeCostUsd`
15
- // is false and cost is estimated downstream via server/pricing.ts. Gemini DOES
15
+ // is false and cost is estimated downstream via server/modules/accounting/runtime/pricing.ts. Gemini DOES
16
16
  // emit OTLP natively via `GEMINI_TELEMETRY_*` env (set by QueueManager), so
17
17
  // `nativeOtelEnv` is true — no synthetic bridge. There is no `--system-prompt`
18
18
  // flag (the CLI uses the `GEMINI_SYSTEM_MD` env), so `systemPromptArg` is false
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTelemetryEnv = buildTelemetryEnv;
4
+ // ─── Telemetry env helpers ────────────────────────────────────────────────────
5
+ /** Build the OTLP/telemetry environment variable block for a spawned AI-CLI
6
+ * process. Extracted as a pure function so it is unit-testable without a full
7
+ * spawn.
8
+ *
9
+ * Provider-aware: claude and codex honour the standard `OTEL_*` env-var
10
+ * convention (plus claude's `CLAUDE_CODE_ENABLE_TELEMETRY=1` master switch),
11
+ * but the Gemini CLI does NOT — it reads its own `GEMINI_TELEMETRY_*` prefixed
12
+ * vars (verified against google-gemini/gemini-cli docs/cli/telemetry.md) and
13
+ * defaults to gRPC, so gemini rails need `GEMINI_TELEMETRY_OTLP_PROTOCOL=http`
14
+ * and the OTLP endpoint pointed at our loopback receiver. Resource attributes
15
+ * still flow via the standard `OTEL_RESOURCE_ATTRIBUTES` (read by the OTel JS
16
+ * SDK that the Gemini CLI uses), so the receiver can route by job/project id.
17
+ *
18
+ * The `providerId` argument defaults to `'claude'` so existing claude/codex
19
+ * call paths stay byte-identical. */
20
+ function buildTelemetryEnv(jobId, projectId, desktopPort, extraResourceAttributes = {}, providerId = 'claude') {
21
+ const baseAttrs = [
22
+ ['specrails.job_id', jobId],
23
+ ['specrails.project_id', projectId],
24
+ ];
25
+ for (const [k, v] of Object.entries(extraResourceAttributes)) {
26
+ baseAttrs.push([k, String(v)]);
27
+ }
28
+ const resourceAttributes = baseAttrs.map(([k, v]) => `${k}=${v}`).join(',');
29
+ const endpoint = `http://127.0.0.1:${desktopPort}/otlp`;
30
+ if (providerId === 'gemini') {
31
+ // Gemini CLI uses its own env contract (not OTEL_*). Defaults to gRPC, so we
32
+ // must force the http transport to reach our OTLP/HTTP JSON receiver, and
33
+ // target the `local` backend (not gcp). OTEL_RESOURCE_ATTRIBUTES is still
34
+ // honoured by the underlying OTel SDK for job/project routing.
35
+ return {
36
+ GEMINI_TELEMETRY_ENABLED: 'true',
37
+ GEMINI_TELEMETRY_TARGET: 'local',
38
+ GEMINI_TELEMETRY_OTLP_ENDPOINT: endpoint,
39
+ GEMINI_TELEMETRY_OTLP_PROTOCOL: 'http',
40
+ GEMINI_TELEMETRY_TRACES_ENABLED: 'true',
41
+ OTEL_RESOURCE_ATTRIBUTES: resourceAttributes,
42
+ };
43
+ }
44
+ // claude (master switch + OTEL_*) and codex (OTEL_* only) — byte-identical to
45
+ // the pre-fix block for both.
46
+ return {
47
+ CLAUDE_CODE_ENABLE_TELEMETRY: '1',
48
+ OTEL_EXPORTER_OTLP_ENDPOINT: endpoint,
49
+ OTEL_EXPORTER_OTLP_PROTOCOL: 'http/json',
50
+ OTEL_METRICS_EXPORTER: 'otlp',
51
+ OTEL_LOGS_EXPORTER: 'otlp',
52
+ OTEL_TRACES_EXPORTER: 'otlp',
53
+ OTEL_RESOURCE_ATTRIBUTES: resourceAttributes,
54
+ };
55
+ }
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerRuntimeRolePromptRoutes = registerRuntimeRolePromptRoutes;
4
- const agent_runtime_settings_1 = require("./agent-runtime-settings");
5
- const agent_runtime_loader_1 = require("./agent-runtime-loader");
4
+ const agent_runtime_settings_1 = require("./modules/agent-runtime/runtime/agent-runtime-settings");
5
+ const agent_runtime_loader_1 = require("./modules/agent-runtime/runtime/agent-runtime-loader");
6
6
  function registerRuntimeRolePromptRoutes(router) {
7
7
  router.get('/runtime-role-prompts', async (_req, res) => {
8
8
  try {
@@ -22,8 +22,8 @@ const core_package_1 = require("./core-package");
22
22
  const providers_1 = require("./providers");
23
23
  const registry_1 = require("./providers/registry");
24
24
  const runtime_1 = require("./providers/runtime");
25
- const result_event_1 = require("./result-event");
26
- const ai_invocations_1 = require("./ai-invocations");
25
+ const result_event_1 = require("./modules/accounting/runtime/result-event");
26
+ const ai_invocations_1 = require("./modules/accounting/runtime/ai-invocations");
27
27
  const crypto_1 = require("crypto");
28
28
  const artifact_registry_1 = require("./artifact-registry");
29
29
  const install_config_path_1 = require("./install-config-path");
@@ -180,52 +180,6 @@ function readInstallConfig(project, provider) {
180
180
  return null;
181
181
  }
182
182
  }
183
- // ─── Template deployment (post-install) ──────────────────────────────────────
184
- function deployTemplates(projectPath, selectedAgents) {
185
- const templatesDir = (0, path_1.join)(projectPath, '.specrails', 'setup-templates');
186
- const targetDir = (0, path_1.join)(projectPath, SPECRAILS_DIR);
187
- let agents = 0, commands = 0, personas = 0;
188
- // Deploy selected agent templates
189
- const agentTemplatesDir = (0, path_1.join)(templatesDir, 'agents');
190
- const agentTargetDir = (0, path_1.join)(targetDir, 'agents');
191
- if ((0, fs_1.existsSync)(agentTemplatesDir)) {
192
- (0, fs_1.mkdirSync)(agentTargetDir, { recursive: true });
193
- for (const file of (0, fs_1.readdirSync)(agentTemplatesDir)) {
194
- if (!file.endsWith('.md'))
195
- continue;
196
- const agentId = file.replace(/\.md$/, '');
197
- if (selectedAgents.length > 0 && !selectedAgents.includes(agentId))
198
- continue;
199
- (0, fs_1.copyFileSync)((0, path_1.join)(agentTemplatesDir, file), (0, path_1.join)(agentTargetDir, file));
200
- agents++;
201
- }
202
- }
203
- // Deploy persona templates
204
- const personaTemplatesDir = (0, path_1.join)(templatesDir, 'personas');
205
- const personaTargetDir = (0, path_1.join)(agentTargetDir, 'personas');
206
- if ((0, fs_1.existsSync)(personaTemplatesDir)) {
207
- (0, fs_1.mkdirSync)(personaTargetDir, { recursive: true });
208
- for (const file of (0, fs_1.readdirSync)(personaTemplatesDir)) {
209
- if (!file.endsWith('.md'))
210
- continue;
211
- (0, fs_1.copyFileSync)((0, path_1.join)(personaTemplatesDir, file), (0, path_1.join)(personaTargetDir, file));
212
- personas++;
213
- }
214
- }
215
- // Deploy command templates
216
- const cmdTemplatesDir = (0, path_1.join)(templatesDir, 'commands', 'specrails');
217
- const cmdTargetDir = (0, path_1.join)(targetDir, 'commands', 'specrails');
218
- if ((0, fs_1.existsSync)(cmdTemplatesDir)) {
219
- (0, fs_1.mkdirSync)(cmdTargetDir, { recursive: true });
220
- for (const file of (0, fs_1.readdirSync)(cmdTemplatesDir)) {
221
- if (!file.endsWith('.md'))
222
- continue;
223
- (0, fs_1.copyFileSync)((0, path_1.join)(cmdTemplatesDir, file), (0, path_1.join)(cmdTargetDir, file));
224
- commands++;
225
- }
226
- }
227
- return { agents, commands, personas };
228
- }
229
183
  // Full install: 7-phase enrichment flow (claude /specrails:enrich)
230
184
  exports.CHECKPOINTS = [
231
185
  { key: 'base_install', name: 'Base installation' },
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isValidBranchName = isValidBranchName;
4
+ /** Safe input subset for branch names passed to Git commands. */
5
+ function isValidBranchName(name) {
6
+ if (typeof name !== 'string')
7
+ return false;
8
+ const n = name.trim();
9
+ if (!n || n.length > 255)
10
+ return false;
11
+ if (n.startsWith('-') || n.startsWith('/') || n.endsWith('/'))
12
+ return false;
13
+ if (n.includes('..') || n.includes('//') || n.endsWith('.lock'))
14
+ return false;
15
+ return /^[A-Za-z0-9._/-]+$/.test(n);
16
+ }