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.
- package/cli/dist/args.js +80 -0
- package/cli/dist/desktop-client.js +125 -0
- package/cli/dist/desktop-control.js +339 -0
- package/cli/dist/format.js +45 -0
- package/cli/dist/help.js +68 -0
- package/cli/dist/output.js +47 -0
- package/cli/dist/run-command.js +340 -0
- package/cli/dist/specrails-desktop.js +41 -1107
- package/cli/dist/status.js +111 -0
- package/client/dist/assets/{ActivityFeedPage-ILXMZXcb.js → ActivityFeedPage-DdMNmVBk.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-UcsupCy7.js → AgentBrowserCapture-CeerUf--.js} +1 -1
- package/client/dist/assets/{AgentModeAnalyticsPane-CQuxYh8B.js → AgentModeAnalyticsPane-BjGb-8rh.js} +2 -2
- package/client/dist/assets/{AgentModeCodePane-zPWbW7ei.js → AgentModeCodePane-8XRkQEo_.js} +2 -2
- package/client/dist/assets/{AgentModeJobsPane-CInByIdl.js → AgentModeJobsPane-BN3dgJOA.js} +1 -1
- package/client/dist/assets/{AgentsPage-BWvgxaBv.js → AgentsPage-DfHWgP_x.js} +1 -1
- package/client/dist/assets/{AnalyticsPage-DP3jakv-.js → AnalyticsPage-CyfhYiBn.js} +1 -1
- package/client/dist/assets/{CodePage-BKXiwE5a.js → CodePage-C2Nf-Q5W.js} +1 -1
- package/client/dist/assets/{DesktopAnalyticsPage-DryJOaMz.js → DesktopAnalyticsPage-tc0p4jJW.js} +1 -1
- package/client/dist/assets/{DocsDialog-BsCG9ksG.js → DocsDialog-Br3bczCp.js} +1 -1
- package/client/dist/assets/{DocsPage-Cc-GeKYl.js → DocsPage-BcDr2cBm.js} +1 -1
- package/client/dist/assets/{ExportDropdown-ClahJdDn.js → ExportDropdown-BVGKEgkd.js} +1 -1
- package/client/dist/assets/{InteractiveJobComposer-DfLF6N0f.js → InteractiveJobComposer-DFPpdg2D.js} +1 -1
- package/client/dist/assets/{JobDetailModal-DHeur9YK.js → JobDetailModal-BdOv-l-M.js} +1 -1
- package/client/dist/assets/{JobDetailPage-CraDKzeG.js → JobDetailPage-vBbNeRuz.js} +1 -1
- package/client/dist/assets/{JobsPage-CcbuSwj7.js → JobsPage-CJCtPhIz.js} +1 -1
- package/client/dist/assets/{LoopBuilderPage-BKtNp494.js → LoopBuilderPage-BemvUOxy.js} +1 -1
- package/client/dist/assets/{LoopPreviewModal-DbZd9isy.js → LoopPreviewModal-C6hNAeYN.js} +1 -1
- package/client/dist/assets/{LoopsPage-DEg6sIkG.js → LoopsPage-BZr0quvh.js} +1 -1
- package/client/dist/assets/{MinimizedChatsContext-BGtEjWsc.js → MinimizedChatsContext-D3QzgV0B.js} +1 -1
- package/client/dist/assets/{PluginsPage-BVqSsPzL.js → PluginsPage-DOpTV75p.js} +1 -1
- package/client/dist/assets/{ProjectSettingsDialog-CAjLgJAZ.js → ProjectSettingsDialog-Dkwrn0z1.js} +1 -1
- package/client/dist/assets/{RepositoryDeliveries-DrcrxLe0.js → RepositoryDeliveries-Du2UCf1a.js} +1 -1
- package/client/dist/assets/{RepositoryScopeSelector-CAGY3xW6.js → RepositoryScopeSelector-hPGZNRBm.js} +1 -1
- package/client/dist/assets/ReviewPacketPage-DcOq-UTA.js +4 -0
- package/client/dist/assets/{TemplatePreviewModal-Bqs-9fhn.js → TemplatePreviewModal-Cejcquah.js} +1 -1
- package/client/dist/assets/{TicketDetailModalContext-C0jQ5yOk.js → TicketDetailModalContext-DAK-NoK6.js} +1 -1
- package/client/dist/assets/{Trans-DtWlCJN9.js → Trans-DEbgkuAY.js} +1 -1
- package/client/dist/assets/{dashboard-CTfEtkqX.js → dashboard-B9uWNGO2.js} +1 -1
- package/client/dist/assets/{dashboard-DMklepmz.js → dashboard-BIwmO9wc.js} +1 -1
- package/client/dist/assets/{dashboard-DBAP2_SQ.js → dashboard-BV4vOZkR.js} +1 -1
- package/client/dist/assets/{dashboard-D40HP2ks.js → dashboard-Bf6MPVsM.js} +1 -1
- package/client/dist/assets/{dashboard-Csf1yGSN.js → dashboard-C8klWVvZ.js} +1 -1
- package/client/dist/assets/{dashboard-C29Qwa-L.js → dashboard-D1ORhPF0.js} +1 -1
- package/client/dist/assets/{dashboard-Cr4D8oMn.js → dashboard-DSubvs9x.js} +1 -1
- package/client/dist/assets/{dashboard-CSJzf5OT.js → dashboard-px_vlRx_.js} +1 -1
- package/client/dist/assets/{formatDistanceToNow-DYmvOA3R.js → formatDistanceToNow-Cc2u5FwQ.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-BAhW5E6V.js → getTimezoneOffsetInMilliseconds-BHm2U-w1.js} +1 -1
- package/client/dist/assets/index-C51x61Bz.css +2 -0
- package/client/dist/assets/{index-BfAZg5DG.js → index-Cxb288Rj.js} +29 -29
- package/client/dist/assets/{jira-api-B27Za5FP.js → jira-api-DrGxiD9p.js} +1 -1
- package/client/dist/assets/packet-8nn9RsU7.js +1 -0
- package/client/dist/assets/packet-B0H15elv.js +1 -0
- package/client/dist/assets/packet-BQvBgrwh.js +1 -0
- package/client/dist/assets/packet-BR7mO0-a.js +1 -0
- package/client/dist/assets/packet-BgcQ6q_K.js +1 -0
- package/client/dist/assets/packet-D2s92Jnn.js +1 -0
- package/client/dist/assets/packet-YbtcD1HS.js +1 -0
- package/client/dist/assets/packet-c0Qj_9eX.js +1 -0
- package/client/dist/assets/{project-repositories-DixIZHTA.js → project-repositories-9Wzs0coQ.js} +1 -1
- package/client/dist/assets/{spending-BGmZBX5B.js → spending-T5GM7wpn.js} +1 -1
- package/client/dist/assets/{useDesktop-CPB4cnwI.js → useDesktop-QogiN0zR.js} +1 -1
- package/client/dist/assets/{useRuntimeRuns-DEQ9HdAM.js → useRuntimeRuns-Dqmz9fS9.js} +1 -1
- package/client/dist/assets/{useSharedWebSocket-DcPRKR8R.js → useSharedWebSocket-Dz-HI6De.js} +2 -2
- package/client/dist/index.html +17 -17
- package/docs/codex.md +5 -5
- package/docs/customizing.md +1 -1
- package/docs/gemini-cli-provider-study.md +14 -14
- package/docs/gemini-core-support-evaluation.md +1 -1
- package/docs/gemini.md +5 -5
- package/docs/internals/README.md +6 -2
- package/docs/internals/adding-a-provider.md +22 -15
- package/docs/internals/agent-runtime-framework-evaluation.md +8 -8
- package/docs/internals/api-reference.md +2 -2
- package/docs/internals/architecture.md +9 -9
- package/docs/internals/browser-capture-performance.md +3 -3
- package/docs/internals/code-explorer-story.md +2 -2
- package/docs/internals/companion-rails-as-loops-contract.md +2 -2
- package/docs/internals/core-runtime-updates.md +5 -0
- package/docs/internals/embedded-browser-native-webview-evaluation.md +5 -5
- package/docs/internals/gemini-mcp-registration.md +2 -2
- package/docs/internals/global-artifacts-alignment-contract.md +1 -1
- package/docs/internals/global-artifacts-relocation-evaluation.md +1 -1
- package/docs/internals/interactive-jobs.md +8 -8
- package/docs/internals/legacy-implementation-notes.md +722 -0
- package/docs/internals/loop-step-log-explorer.md +8 -8
- package/docs/internals/mission-rail-cards.md +14 -14
- package/docs/internals/modular-architecture.md +107 -0
- package/docs/internals/profiles.md +1 -1
- package/docs/internals/programmatic-agent-runtime.md +66 -0
- package/docs/internals/project-builder.md +18 -18
- package/docs/internals/review-packet.md +8 -8
- package/docs/internals/safe-pr-review-flow.md +11 -11
- package/docs/internals/source-architecture.md +131 -0
- package/docs/internals/source-map.md +1356 -0
- package/docs/internals/spec-addenda.md +65 -9
- package/docs/internals/switch-to-agent-mode-design.md +11 -11
- package/docs/tracking-cost.md +1 -1
- package/package.json +5 -2
- package/server/dist/agent-mcp-config.js +1 -1
- package/server/dist/attachment-manager.js +1 -1
- package/server/dist/build-dirs.js +2 -2
- package/server/dist/config.js +0 -3
- package/server/dist/core-completion.js +1 -1
- package/server/dist/core-execution.js +1 -1
- package/server/dist/db/activity.js +39 -0
- package/server/dist/db/connection.js +41 -0
- package/server/dist/db/conversations.js +48 -0
- package/server/dist/db/jobs.js +251 -0
- package/server/dist/db/migrations.js +1521 -0
- package/server/dist/db/proposals.js +50 -0
- package/server/dist/db/settings.js +15 -0
- package/server/dist/db/stats.js +61 -0
- package/server/dist/db/telemetry.js +56 -0
- package/server/dist/db/templates.js +37 -0
- package/server/dist/db/types.js +2 -0
- package/server/dist/db.js +66 -2224
- package/server/dist/desktop-db.js +3 -3
- package/server/dist/desktop-router.js +8 -8
- package/server/dist/git-diagnostics.js +1 -1
- package/server/dist/index.js +11 -11
- package/server/dist/integration-branch.js +3 -14
- package/server/dist/jira/jira-issue-fields.js +0 -1
- package/server/dist/jira/jira-materializer.js +1 -1
- package/server/dist/jira/jira-sync-manager.js +1 -1
- package/server/dist/mcp/guide.js +16 -2
- package/server/dist/mcp/mcp-admin-router.js +1 -1
- package/server/dist/mcp/mcp-server.js +1 -1
- package/server/dist/mcp/tools/catalog.js +2 -0
- package/server/dist/mcp/tools/jobs.js +23 -5
- package/server/dist/mcp/tools/rails.js +2 -2
- package/server/dist/mcp/tools/recovery.js +35 -0
- package/server/dist/mcp/tools/specs.js +2 -2
- package/server/dist/mcp/tools/support.js +4 -1
- package/server/dist/mcp/tools/types.js +3 -3
- package/server/dist/mobile/mobile-gateway.js +1 -1
- package/server/dist/mobile/mobile-missions.js +1 -1
- package/server/dist/{desktop-analytics.js → modules/accounting/runtime/desktop-analytics.js} +2 -2
- package/server/dist/{pricing.js → modules/accounting/runtime/pricing.js} +10 -3
- package/server/dist/{result-event.js → modules/accounting/runtime/result-event.js} +3 -3
- package/server/dist/{spending.js → modules/accounting/runtime/spending.js} +0 -3
- package/server/dist/{telemetry-compactor.js → modules/accounting/runtime/telemetry-compactor.js} +1 -1
- package/server/dist/{telemetry-receiver.js → modules/accounting/runtime/telemetry-receiver.js} +2 -2
- package/server/dist/{agent-runtime-bridge.js → modules/agent-runtime/runtime/agent-runtime-bridge.js} +2 -2
- package/server/dist/{agent-runtime-controls-router.js → modules/agent-runtime/runtime/agent-runtime-controls-router.js} +16 -0
- package/server/dist/{agent-runtime-controls.js → modules/agent-runtime/runtime/agent-runtime-controls.js} +100 -8
- package/server/dist/{agent-runtime-effective-config.js → modules/agent-runtime/runtime/agent-runtime-effective-config.js} +1 -1
- package/server/dist/{agent-runtime-loader.js → modules/agent-runtime/runtime/agent-runtime-loader.js} +3 -3
- package/server/dist/{agent-runtime-paths.js → modules/agent-runtime/runtime/agent-runtime-paths.js} +1 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-recovery.js +53 -0
- package/server/dist/{agent-runtime-settings-router.js → modules/agent-runtime/runtime/agent-runtime-settings-router.js} +2 -2
- package/server/dist/{agent-runtime-settings.js → modules/agent-runtime/runtime/agent-runtime-settings.js} +3 -3
- package/server/dist/{agent-runtime-settlement.js → modules/agent-runtime/runtime/agent-runtime-settlement.js} +6 -6
- package/server/dist/{agent-defaults.js → modules/agents/runtime/agent-defaults.js} +3 -3
- package/server/dist/{agent-generator.js → modules/agents/runtime/agent-generator.js} +7 -7
- package/server/dist/{agent-refine-manager.js → modules/agents/runtime/agent-refine-manager.js} +5 -5
- package/server/dist/{agent-store.js → modules/agents/runtime/agent-store.js} +1 -1
- package/server/dist/{profile-manager.js → modules/agents/runtime/profile-manager.js} +2 -2
- package/server/dist/{profiles-router.js → modules/agents/runtime/profiles-router.js} +5 -5
- package/server/dist/{browser-capture-manager.js → modules/browser/runtime/browser-capture-manager.js} +2 -4
- package/server/dist/{browser-playwright.js → modules/browser/runtime/browser-playwright.js} +1 -1
- package/server/dist/{blueprint-chat-manager.js → modules/builder/runtime/blueprint-chat-manager.js} +7 -7
- package/server/dist/{blueprint-commit.js → modules/builder/runtime/blueprint-commit.js} +8 -8
- package/server/dist/{blueprint-draft-parser.js → modules/builder/runtime/blueprint-draft-parser.js} +1 -1
- package/server/dist/{blueprint-generation.js → modules/builder/runtime/blueprint-generation.js} +1 -1
- package/server/dist/{blueprint-operator-prompt.js → modules/builder/runtime/blueprint-operator-prompt.js} +1 -1
- package/server/dist/{blueprint-router.js → modules/builder/runtime/blueprint-router.js} +3 -3
- package/server/dist/{blueprint-spec-quality.js → modules/builder/runtime/blueprint-spec-quality.js} +1 -1
- package/server/dist/{milestone-chain.js → modules/builder/runtime/milestone-chain.js} +1 -1
- package/server/dist/{milestone-progress.js → modules/builder/runtime/milestone-progress.js} +6 -6
- package/server/dist/{code-activity.js → modules/code/runtime/code-activity.js} +1 -1
- package/server/dist/{code-explorer-router.js → modules/code/runtime/code-explorer-router.js} +5 -5
- package/server/dist/{file-provenance.js → modules/code/runtime/file-provenance.js} +1 -1
- package/server/dist/{file-story-manager.js → modules/code/runtime/file-story-manager.js} +2 -2
- package/server/dist/{file-story.js → modules/code/runtime/file-story.js} +2 -2
- package/server/dist/{file-summary-generator.js → modules/code/runtime/file-summary-generator.js} +3 -3
- package/server/dist/{file-summary-manager.js → modules/code/runtime/file-summary-manager.js} +3 -3
- package/server/dist/{project-code-discovery.js → modules/code/runtime/project-code-discovery.js} +2 -2
- package/server/dist/modules/conversations/domain/draft-stream.js +91 -0
- package/server/dist/modules/conversations/domain/recovery-context.js +101 -0
- package/server/dist/modules/conversations/index.js +10 -0
- package/server/dist/{chat-manager.js → modules/conversations/runtime/chat-manager.js} +32 -216
- package/server/dist/{context-budget.js → modules/conversations/runtime/context-budget.js} +1 -1
- package/server/dist/{explore-cwd-manager.js → modules/conversations/runtime/explore-cwd-manager.js} +1 -1
- package/server/dist/{explore-smash.js → modules/conversations/runtime/explore-smash.js} +1 -1
- package/server/dist/{explore-stdin-session.js → modules/conversations/runtime/explore-stdin-session.js} +1 -1
- package/server/dist/modules/delivery/adapters/decisions/chains.js +138 -0
- package/server/dist/modules/delivery/adapters/decisions/contracts.js +2 -0
- package/server/dist/modules/delivery/adapters/decisions/create.js +234 -0
- package/server/dist/modules/delivery/adapters/decisions/discard.js +251 -0
- package/server/dist/modules/delivery/adapters/decisions/dispatch.js +107 -0
- package/server/dist/modules/delivery/adapters/decisions/evidence.js +205 -0
- package/server/dist/modules/delivery/adapters/decisions/merge-local.js +338 -0
- package/server/dist/modules/delivery/adapters/decisions/metadata.js +109 -0
- package/server/dist/modules/delivery/adapters/decisions/observations.js +260 -0
- package/server/dist/modules/delivery/adapters/decisions/ownership.js +83 -0
- package/server/dist/modules/delivery/adapters/decisions/publish.js +242 -0
- package/server/dist/modules/delivery/adapters/decisions/recovery.js +425 -0
- package/server/dist/modules/delivery/adapters/decisions/retry.js +112 -0
- package/server/dist/modules/delivery/adapters/decisions/transitions.js +94 -0
- package/server/dist/modules/delivery/domain/decision-policy.js +50 -0
- package/server/dist/modules/delivery/domain/state.js +2 -0
- package/server/dist/modules/delivery/index.js +7 -0
- package/server/dist/{active-pr-continuation.js → modules/delivery/runtime/active-pr-continuation.js} +2 -2
- package/server/dist/{delivery-evidence.js → modules/delivery/runtime/delivery-evidence.js} +3 -3
- package/server/dist/{multi-repo-bases.js → modules/delivery/runtime/multi-repo-bases.js} +1 -1
- package/server/dist/{multi-repo-checkout.js → modules/delivery/runtime/multi-repo-checkout.js} +4 -4
- package/server/dist/{multi-repo-delivery.js → modules/delivery/runtime/multi-repo-delivery.js} +4 -4
- package/server/dist/{multi-repo-execution.js → modules/delivery/runtime/multi-repo-execution.js} +8 -8
- package/server/dist/{pr-body.js → modules/delivery/runtime/pr-body.js} +1 -1
- package/server/dist/{pr-follow-up-scope.js → modules/delivery/runtime/pr-follow-up-scope.js} +2 -2
- package/server/dist/{pr-follow-up.js → modules/delivery/runtime/pr-follow-up.js} +1 -1
- package/server/dist/{pr-naming.js → modules/delivery/runtime/pr-naming.js} +1 -1
- package/server/dist/{pr-publisher.js → modules/delivery/runtime/pr-publisher.js} +2 -2
- package/server/dist/{rail-isolated-launch.js → modules/delivery/runtime/rail-isolated-launch.js} +29 -27
- package/server/dist/{rail-launch-parser.js → modules/delivery/runtime/rail-launch-parser.js} +2 -2
- package/server/dist/{rail-merge-orchestrator.js → modules/delivery/runtime/rail-merge-orchestrator.js} +5 -5
- package/server/dist/modules/delivery/runtime/rail-pr-decision.js +12 -0
- package/server/dist/{rail-pr-delivery.js → modules/delivery/runtime/rail-pr-delivery.js} +1 -1
- package/server/dist/{rail-pr-store.js → modules/delivery/runtime/rail-pr-store.js} +2 -2
- package/server/dist/{rail-pr-ticket-effects.js → modules/delivery/runtime/rail-pr-ticket-effects.js} +3 -3
- package/server/dist/{rail-worktree-release.js → modules/delivery/runtime/rail-worktree-release.js} +4 -4
- package/server/dist/{rails-router.js → modules/delivery/runtime/rails-router.js} +66 -67
- package/server/dist/{review-packet.js → modules/delivery/runtime/review-packet.js} +3 -3
- package/server/dist/modules/execution/adapters/budget-storage.js +21 -0
- package/server/dist/modules/execution/adapters/usage-reader.js +38 -0
- package/server/dist/modules/execution/application/enforce-budget.js +14 -0
- package/server/dist/modules/execution/application/record-job-invocations.js +64 -0
- package/server/dist/modules/execution/application/recover-job-usage.js +200 -0
- package/server/dist/modules/execution/domain/job-accounting.js +2 -0
- package/server/dist/modules/execution/domain/scheduling.js +24 -0
- package/server/dist/modules/execution/domain/usage.js +21 -0
- package/server/dist/modules/execution/index.js +14 -0
- package/server/dist/modules/execution/ports.js +2 -0
- package/server/dist/{accept-ladder.js → modules/execution/runtime/accept-ladder.js} +1 -1
- package/server/dist/{interactive-job-session.js → modules/execution/runtime/interactive-job-session.js} +11 -11
- package/server/dist/{job-phase-breakdown.js → modules/execution/runtime/job-phase-breakdown.js} +1 -1
- package/server/dist/{queue-manager.js → modules/execution/runtime/queue-manager.js} +74 -491
- package/server/dist/{revision-seed.js → modules/execution/runtime/revision-seed.js} +1 -1
- package/server/dist/{spawn-lifecycle.js → modules/execution/runtime/spawn-lifecycle.js} +3 -3
- package/server/dist/{stuck-run-detector.js → modules/execution/runtime/stuck-run-detector.js} +1 -1
- package/server/dist/{loop-command-catalog.js → modules/loops/runtime/loop-command-catalog.js} +1 -1
- package/server/dist/{loop-executors.js → modules/loops/runtime/loop-executors.js} +17 -17
- package/server/dist/{loop-factory.js → modules/loops/runtime/loop-factory.js} +2 -21
- package/server/dist/{loop-graph.js → modules/loops/runtime/loop-graph.js} +25 -0
- package/server/dist/{loop-role-engines.js → modules/loops/runtime/loop-role-engines.js} +4 -4
- package/server/dist/{loop-run-manager.js → modules/loops/runtime/loop-run-manager.js} +101 -26
- package/server/dist/{loop-runs-store.js → modules/loops/runtime/loop-runs-store.js} +1 -1
- package/server/dist/{loop-shell-invocation.js → modules/loops/runtime/loop-shell-invocation.js} +2 -2
- package/server/dist/{loop-step-idle.js → modules/loops/runtime/loop-step-idle.js} +1 -1
- package/server/dist/{loop-templates.js → modules/loops/runtime/loop-templates.js} +24 -29
- package/server/dist/{loops-router.js → modules/loops/runtime/loops-router.js} +2 -2
- package/server/dist/{agent-chat-manager.js → modules/missions/runtime/agent-chat-manager.js} +19 -19
- package/server/dist/{agent-chat-router.js → modules/missions/runtime/agent-chat-router.js} +6 -6
- package/server/dist/{agent-context-resolver.js → modules/missions/runtime/agent-context-resolver.js} +8 -8
- package/server/dist/{agent-failure-briefing.js → modules/missions/runtime/agent-failure-briefing.js} +4 -2
- package/server/dist/{agent-fence-promotion.js → modules/missions/runtime/agent-fence-promotion.js} +1 -1
- package/server/dist/{agent-input-store.js → modules/missions/runtime/agent-input-store.js} +1 -1
- package/server/dist/{agent-operator-prompt.js → modules/missions/runtime/agent-operator-prompt.js} +75 -12
- package/server/dist/{agent-spec-framing.js → modules/missions/runtime/agent-spec-framing.js} +4 -4
- package/server/dist/{agent-steering.js → modules/missions/runtime/agent-steering.js} +1 -1
- package/server/dist/{mission-run-notify.js → modules/missions/runtime/mission-run-notify.js} +5 -2
- package/server/dist/modules/project-settings/adapters/http.js +24 -0
- package/server/dist/modules/project-settings/adapters/sqlite.js +120 -0
- package/server/dist/modules/project-settings/application.js +11 -0
- package/server/dist/modules/project-settings/domain.js +95 -0
- package/server/dist/modules/project-settings/index.js +11 -0
- package/server/dist/modules/project-settings/ports.js +2 -0
- package/server/dist/{contract-refine-runner.js → modules/specs/runtime/contract-refine-runner.js} +12 -12
- package/server/dist/{proposal-manager.js → modules/specs/runtime/proposal-manager.js} +8 -8
- package/server/dist/{smash-runner.js → modules/specs/runtime/smash-runner.js} +26 -58
- package/server/dist/{spec-addenda-core.js → modules/specs/runtime/spec-addenda-core.js} +2 -2
- package/server/dist/{spec-addenda.js → modules/specs/runtime/spec-addenda.js} +3 -3
- package/server/dist/{spec-launcher-manager.js → modules/specs/runtime/spec-launcher-manager.js} +8 -8
- package/server/dist/{spec-models.js → modules/specs/runtime/spec-models.js} +1 -1
- package/server/dist/{ticket-watcher.js → modules/specs/runtime/ticket-watcher.js} +1 -1
- package/server/dist/{background-process-control.js → modules/terminals/runtime/background-process-control.js} +1 -1
- package/server/dist/{background-process-service.js → modules/terminals/runtime/background-process-service.js} +3 -3
- package/server/dist/{background-process-store.js → modules/terminals/runtime/background-process-store.js} +1 -1
- package/server/dist/{background-windows-bootstrap.js → modules/terminals/runtime/background-windows-bootstrap.js} +3 -3
- package/server/dist/{terminal-manager.js → modules/terminals/runtime/terminal-manager.js} +3 -3
- package/server/dist/project-git.js +1 -1
- package/server/dist/project-profile-support.js +32 -0
- package/server/dist/project-registry.js +34 -40
- package/server/dist/project-router-background-processes.js +1 -1
- package/server/dist/project-router-chat.js +6 -6
- package/server/dist/project-router-git.js +1 -1
- package/server/dist/project-router-helpers.js +2 -2
- package/server/dist/project-router-jobs.js +14 -12
- package/server/dist/project-router-loop-runs.js +12 -12
- package/server/dist/project-router-settings.js +15 -75
- package/server/dist/project-router-setup.js +2 -2
- package/server/dist/project-router-spending.js +4 -4
- package/server/dist/project-router-terminals.js +4 -4
- package/server/dist/project-router-tickets.js +14 -14
- package/server/dist/project-router.js +13 -13
- package/server/dist/providers/claude-adapter.js +3 -2
- package/server/dist/providers/codex-adapter.js +3 -3
- package/server/dist/providers/gemini-adapter.js +1 -1
- package/server/dist/providers/telemetry-env.js +55 -0
- package/server/dist/runtime-role-prompts-router.js +2 -2
- package/server/dist/setup-manager.js +2 -48
- package/server/dist/shared/git-branch-name.js +16 -0
- package/server/dist/transient-children.js +3 -3
- package/server/dist/util/distribute-int.js +33 -0
- package/client/dist/assets/ReviewPacketPage-D-UjTef3.js +0 -4
- package/client/dist/assets/index-BAtqmAZR.css +0 -2
- package/client/dist/assets/packet-CjS_478C.js +0 -1
- package/client/dist/assets/packet-D69dKsHN.js +0 -1
- package/client/dist/assets/packet-D9rU6Oxo.js +0 -1
- package/client/dist/assets/packet-DMDFoamg.js +0 -1
- package/client/dist/assets/packet-Dd2RMs1h.js +0 -1
- package/client/dist/assets/packet-DjC9OibC.js +0 -1
- package/client/dist/assets/packet-DwPtJoDz.js +0 -1
- package/client/dist/assets/packet-ceahDg8_.js +0 -1
- package/server/dist/rail-pr-decision.js +0 -2377
- package/server/dist/ticket-broadcast.js +0 -47
- /package/server/dist/{ai-invocations.js → modules/accounting/runtime/ai-invocations.js} +0 -0
- /package/server/dist/{codex-otel-bridge.js → modules/accounting/runtime/codex-otel-bridge.js} +0 -0
- /package/server/dist/{metrics.js → modules/accounting/runtime/metrics.js} +0 -0
- /package/server/dist/{telemetry-export.js → modules/accounting/runtime/telemetry-export.js} +0 -0
- /package/server/dist/{agent-runtime-accounting.js → modules/agent-runtime/runtime/agent-runtime-accounting.js} +0 -0
- /package/server/dist/{agent-runtime-events.js → modules/agent-runtime/runtime/agent-runtime-events.js} +0 -0
- /package/server/dist/{agent-runtime-history.js → modules/agent-runtime/runtime/agent-runtime-history.js} +0 -0
- /package/server/dist/{agent-runtime-metrics.js → modules/agent-runtime/runtime/agent-runtime-metrics.js} +0 -0
- /package/server/dist/{agent-runtime-package.js → modules/agent-runtime/runtime/agent-runtime-package.js} +0 -0
- /package/server/dist/{agent-runtime-repositories.js → modules/agent-runtime/runtime/agent-runtime-repositories.js} +0 -0
- /package/server/dist/{agent-runtime-verification-suggestions.js → modules/agent-runtime/runtime/agent-runtime-verification-suggestions.js} +0 -0
- /package/server/dist/{agent-refine-db.js → modules/agents/runtime/agent-refine-db.js} +0 -0
- /package/server/dist/{browser-capture-types.js → modules/browser/runtime/browser-capture-types.js} +0 -0
- /package/server/dist/{browser-context-pool.js → modules/browser/runtime/browser-context-pool.js} +0 -0
- /package/server/dist/{browser-network.js → modules/browser/runtime/browser-network.js} +0 -0
- /package/server/dist/{browser-viewport.js → modules/browser/runtime/browser-viewport.js} +0 -0
- /package/server/dist/{blueprint-render.js → modules/builder/runtime/blueprint-render.js} +0 -0
- /package/server/dist/{blueprint-spec-fixtures.js → modules/builder/runtime/blueprint-spec-fixtures.js} +0 -0
- /package/server/dist/{blueprint-store.js → modules/builder/runtime/blueprint-store.js} +0 -0
- /package/server/dist/{blueprint-types.js → modules/builder/runtime/blueprint-types.js} +0 -0
- /package/server/dist/{builder-cwd-manager.js → modules/builder/runtime/builder-cwd-manager.js} +0 -0
- /package/server/dist/{milestone-chain-store.js → modules/builder/runtime/milestone-chain-store.js} +0 -0
- /package/server/dist/{changes-reader.js → modules/code/runtime/changes-reader.js} +0 -0
- /package/server/dist/{context-scope.js → modules/conversations/runtime/context-scope.js} +0 -0
- /package/server/dist/{explore-contract-refine.js → modules/conversations/runtime/explore-contract-refine.js} +0 -0
- /package/server/dist/{explore-draft-title.js → modules/conversations/runtime/explore-draft-title.js} +0 -0
- /package/server/dist/{merge-manager.js → modules/delivery/runtime/merge-manager.js} +0 -0
- /package/server/dist/{multi-repo-execution-store.js → modules/delivery/runtime/multi-repo-execution-store.js} +0 -0
- /package/server/dist/{pr-lifecycle.js → modules/delivery/runtime/pr-lifecycle.js} +0 -0
- /package/server/dist/{rail-isolation.js → modules/delivery/runtime/rail-isolation.js} +0 -0
- /package/server/dist/{rail-pr-recovery-git.js → modules/delivery/runtime/rail-pr-recovery-git.js} +0 -0
- /package/server/dist/{rail-worktrees-store.js → modules/delivery/runtime/rail-worktrees-store.js} +0 -0
- /package/server/dist/{rails-store.js → modules/delivery/runtime/rails-store.js} +0 -0
- /package/server/dist/{job-listing.js → modules/execution/runtime/job-listing.js} +0 -0
- /package/server/dist/{job-spawn-idempotency.js → modules/execution/runtime/job-spawn-idempotency.js} +0 -0
- /package/server/dist/{run-duration-stats.js → modules/execution/runtime/run-duration-stats.js} +0 -0
- /package/server/dist/{verification-sentinel.js → modules/execution/runtime/verification-sentinel.js} +0 -0
- /package/server/dist/{loop-constants.js → modules/loops/runtime/loop-constants.js} +0 -0
- /package/server/dist/{loop-decider.js → modules/loops/runtime/loop-decider.js} +0 -0
- /package/server/dist/{loop-effect.js → modules/loops/runtime/loop-effect.js} +0 -0
- /package/server/dist/{loop-preview.js → modules/loops/runtime/loop-preview.js} +0 -0
- /package/server/dist/{loop-templates-ported.js → modules/loops/runtime/loop-templates-ported.js} +0 -0
- /package/server/dist/{loops-store.js → modules/loops/runtime/loops-store.js} +0 -0
- /package/server/dist/{agent-chat-registry.js → modules/missions/runtime/agent-chat-registry.js} +0 -0
- /package/server/dist/{agent-cwd-manager.js → modules/missions/runtime/agent-cwd-manager.js} +0 -0
- /package/server/dist/{agent-tier.js → modules/missions/runtime/agent-tier.js} +0 -0
- /package/server/dist/{spec-contract-prompt.js → modules/specs/runtime/spec-contract-prompt.js} +0 -0
- /package/server/dist/{spec-draft-parser.js → modules/specs/runtime/spec-draft-parser.js} +0 -0
- /package/server/dist/{ticket-store.js → modules/specs/runtime/ticket-store.js} +0 -0
- /package/server/dist/{terminal-marks-store.js → modules/terminals/runtime/terminal-marks-store.js} +0 -0
- /package/server/dist/{terminal-osc-parser.js → modules/terminals/runtime/terminal-osc-parser.js} +0 -0
- /package/server/dist/{terminal-settings.js → modules/terminals/runtime/terminal-settings.js} +0 -0
package/client/dist/index.html
CHANGED
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
.specrails-splash__mark .pill { opacity: 1; }
|
|
205
205
|
}
|
|
206
206
|
</style>
|
|
207
|
-
<script type="module" crossorigin src="/assets/index-
|
|
207
|
+
<script type="module" crossorigin src="/assets/index-Cxb288Rj.js"></script>
|
|
208
208
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-CNC7AqOf.js">
|
|
209
209
|
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-zu2_FqZY.js">
|
|
210
210
|
<link rel="modulepreload" crossorigin href="/assets/react-dom-DiWzBDP9.js">
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
<link rel="modulepreload" crossorigin href="/assets/code-DaZ-ZwCT.js">
|
|
226
226
|
<link rel="modulepreload" crossorigin href="/assets/commands-BAWSYHjQ.js">
|
|
227
227
|
<link rel="modulepreload" crossorigin href="/assets/common-BrlwEnL7.js">
|
|
228
|
-
<link rel="modulepreload" crossorigin href="/assets/dashboard-
|
|
228
|
+
<link rel="modulepreload" crossorigin href="/assets/dashboard-BV4vOZkR.js">
|
|
229
229
|
<link rel="modulepreload" crossorigin href="/assets/explore-DgBACn39.js">
|
|
230
230
|
<link rel="modulepreload" crossorigin href="/assets/integrations-mB-7zoyT.js">
|
|
231
231
|
<link rel="modulepreload" crossorigin href="/assets/jira-CKJg3HZd.js">
|
|
@@ -234,22 +234,22 @@
|
|
|
234
234
|
<link rel="modulepreload" crossorigin href="/assets/mcp-CUAN6ORK.js">
|
|
235
235
|
<link rel="modulepreload" crossorigin href="/assets/narration-n3hOA7LY.js">
|
|
236
236
|
<link rel="modulepreload" crossorigin href="/assets/nav-DhPb-Isc.js">
|
|
237
|
-
<link rel="modulepreload" crossorigin href="/assets/packet-
|
|
237
|
+
<link rel="modulepreload" crossorigin href="/assets/packet-B0H15elv.js">
|
|
238
238
|
<link rel="modulepreload" crossorigin href="/assets/settings-HZSu-K4l.js">
|
|
239
239
|
<link rel="modulepreload" crossorigin href="/assets/setup-DpqzaEEA.js">
|
|
240
240
|
<link rel="modulepreload" crossorigin href="/assets/specs-DfIdoU5L.js">
|
|
241
241
|
<link rel="modulepreload" crossorigin href="/assets/terminal-BAzpHtpY.js">
|
|
242
242
|
<link rel="modulepreload" crossorigin href="/assets/tickets-D41ZMQpf.js">
|
|
243
243
|
<link rel="modulepreload" crossorigin href="/assets/createLucideIcon-Bjbbp_KS.js">
|
|
244
|
-
<link rel="modulepreload" crossorigin href="/assets/useSharedWebSocket-
|
|
245
|
-
<link rel="modulepreload" crossorigin href="/assets/Trans-
|
|
246
|
-
<link rel="modulepreload" crossorigin href="/assets/useDesktop-
|
|
244
|
+
<link rel="modulepreload" crossorigin href="/assets/useSharedWebSocket-Dz-HI6De.js">
|
|
245
|
+
<link rel="modulepreload" crossorigin href="/assets/Trans-DEbgkuAY.js">
|
|
246
|
+
<link rel="modulepreload" crossorigin href="/assets/useDesktop-QogiN0zR.js">
|
|
247
247
|
<link rel="modulepreload" crossorigin href="/assets/provider-capabilities-Vi1ZGvAK.js">
|
|
248
248
|
<link rel="modulepreload" crossorigin href="/assets/save-B6wGWwBR.js">
|
|
249
|
-
<link rel="modulepreload" crossorigin href="/assets/spending-
|
|
249
|
+
<link rel="modulepreload" crossorigin href="/assets/spending-T5GM7wpn.js">
|
|
250
250
|
<link rel="modulepreload" crossorigin href="/assets/sparkles-DrY8hb0X.js">
|
|
251
251
|
<link rel="modulepreload" crossorigin href="/assets/x-CBMI9ejn.js">
|
|
252
|
-
<link rel="modulepreload" crossorigin href="/assets/MinimizedChatsContext-
|
|
252
|
+
<link rel="modulepreload" crossorigin href="/assets/MinimizedChatsContext-D3QzgV0B.js">
|
|
253
253
|
<link rel="modulepreload" crossorigin href="/assets/zap-CUOlvtT1.js">
|
|
254
254
|
<link rel="modulepreload" crossorigin href="/assets/circle-x-CMYsN4ZH.js">
|
|
255
255
|
<link rel="modulepreload" crossorigin href="/assets/download-CFHyyHcw.js">
|
|
@@ -269,18 +269,18 @@
|
|
|
269
269
|
<link rel="modulepreload" crossorigin href="/assets/utils-BC4DHlz2.js">
|
|
270
270
|
<link rel="modulepreload" crossorigin href="/assets/dialog-xXB2q5HJ.js">
|
|
271
271
|
<link rel="modulepreload" crossorigin href="/assets/lib-CGdyxIWg.js">
|
|
272
|
-
<link rel="modulepreload" crossorigin href="/assets/getTimezoneOffsetInMilliseconds-
|
|
273
|
-
<link rel="modulepreload" crossorigin href="/assets/formatDistanceToNow-
|
|
272
|
+
<link rel="modulepreload" crossorigin href="/assets/getTimezoneOffsetInMilliseconds-BHm2U-w1.js">
|
|
273
|
+
<link rel="modulepreload" crossorigin href="/assets/formatDistanceToNow-Cc2u5FwQ.js">
|
|
274
274
|
<link rel="modulepreload" crossorigin href="/assets/button-Ccc9Dc-D.js">
|
|
275
|
-
<link rel="modulepreload" crossorigin href="/assets/jira-api-
|
|
276
|
-
<link rel="modulepreload" crossorigin href="/assets/project-repositories-
|
|
277
|
-
<link rel="modulepreload" crossorigin href="/assets/RepositoryScopeSelector-
|
|
278
|
-
<link rel="modulepreload" crossorigin href="/assets/TicketDetailModalContext-
|
|
275
|
+
<link rel="modulepreload" crossorigin href="/assets/jira-api-DrGxiD9p.js">
|
|
276
|
+
<link rel="modulepreload" crossorigin href="/assets/project-repositories-9Wzs0coQ.js">
|
|
277
|
+
<link rel="modulepreload" crossorigin href="/assets/RepositoryScopeSelector-hPGZNRBm.js">
|
|
278
|
+
<link rel="modulepreload" crossorigin href="/assets/TicketDetailModalContext-DAK-NoK6.js">
|
|
279
279
|
<link rel="modulepreload" crossorigin href="/assets/core-B3mKBIh5.js">
|
|
280
|
-
<link rel="modulepreload" crossorigin href="/assets/RepositoryDeliveries-
|
|
281
|
-
<link rel="modulepreload" crossorigin href="/assets/useRuntimeRuns-
|
|
280
|
+
<link rel="modulepreload" crossorigin href="/assets/RepositoryDeliveries-Du2UCf1a.js">
|
|
281
|
+
<link rel="modulepreload" crossorigin href="/assets/useRuntimeRuns-Dqmz9fS9.js">
|
|
282
282
|
<link rel="modulepreload" crossorigin href="/assets/event-Bt7f3wXe.js">
|
|
283
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
283
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C51x61Bz.css">
|
|
284
284
|
</head>
|
|
285
285
|
<body>
|
|
286
286
|
<div id="specrails-splash" aria-hidden="false" role="status" aria-label="Loading Specrails">
|
package/docs/codex.md
CHANGED
|
@@ -149,7 +149,7 @@ A few Codex-specific behaviours worth calling out:
|
|
|
149
149
|
|
|
150
150
|
Codex does not report `total_cost_usd` natively. The app computes an
|
|
151
151
|
estimate from the captured `usage` (input / output / cached input
|
|
152
|
-
tokens × the local rate-card in `server/pricing.ts`) and stores it in
|
|
152
|
+
tokens × the local rate-card in `server/modules/accounting/runtime/pricing.ts`) and stores it in
|
|
153
153
|
`ai_invocations.total_cost_usd` with `total_cost_usd_estimated = 1`.
|
|
154
154
|
|
|
155
155
|
The Analytics page surfaces this in two places:
|
|
@@ -168,7 +168,7 @@ The Analytics page surfaces this in two places:
|
|
|
168
168
|
|
|
169
169
|
The pricing table is reviewed quarterly. The reference date sits on
|
|
170
170
|
each entry as `lastReviewedAt`. If OpenAI raises prices mid-quarter,
|
|
171
|
-
ship an out-of-band update to `server/pricing.ts`.
|
|
171
|
+
ship an out-of-band update to `server/modules/accounting/runtime/pricing.ts`.
|
|
172
172
|
|
|
173
173
|
## Plugins and MCP on codex projects
|
|
174
174
|
|
|
@@ -198,7 +198,7 @@ adapter pins the minimum because earlier versions don't support
|
|
|
198
198
|
or set `OPENAI_API_KEY`. The app doesn't proxy auth.
|
|
199
199
|
|
|
200
200
|
**Cost shows as `—` for codex jobs even though tokens are non-zero**
|
|
201
|
-
— the spawned model isn't in `server/pricing.ts` (e.g. a brand-new
|
|
201
|
+
— the spawned model isn't in `server/modules/accounting/runtime/pricing.ts` (e.g. a brand-new
|
|
202
202
|
model OpenAI shipped after our last review). Update the pricing table
|
|
203
203
|
and reload the page.
|
|
204
204
|
|
|
@@ -243,8 +243,8 @@ The codex integration lives in:
|
|
|
243
243
|
- `server/providers/codex-adapter.ts` — `ProviderAdapter`
|
|
244
244
|
implementation for codex 0.128.0+. Fixtures under
|
|
245
245
|
`server/providers/__fixtures__/codex/0.128.0/`.
|
|
246
|
-
- `server/pricing.ts` — local pricing table + `estimateCostUsd`.
|
|
247
|
-
- `server/codex-otel-bridge.ts` — synthetic OTEL traces / metrics /
|
|
246
|
+
- `server/modules/accounting/runtime/pricing.ts` — local pricing table + `estimateCostUsd`.
|
|
247
|
+
- `server/modules/accounting/runtime/codex-otel-bridge.ts` — synthetic OTEL traces / metrics /
|
|
248
248
|
logs derived from JSONL events.
|
|
249
249
|
- `server/plugins/codex-mcp.ts` — `codex mcp add/remove/list` wrapper
|
|
250
250
|
with per-project `CODEX_HOME`.
|
package/docs/customizing.md
CHANGED
|
@@ -27,7 +27,7 @@ There's an inline anti-FOUC script in `client/index.html` so a page refresh neve
|
|
|
27
27
|
|
|
28
28
|
The active theme persists to `desktop_settings.ui_theme` on the server and mirrors to `localStorage` so the desktop app and browser stay in sync if you use both.
|
|
29
29
|
|
|
30
|
-
> Want a sixth theme? It's a small contribution — see `client/src/lib/themes.ts` and [internals/architecture.md](internals/architecture.md) for the contract.
|
|
30
|
+
> Want a sixth theme? It's a small contribution — see `client/src/features/settings/lib/themes.ts` and [internals/architecture.md](internals/architecture.md) for the contract.
|
|
31
31
|
|
|
32
32
|
## Sidebars
|
|
33
33
|
|
|
@@ -40,7 +40,7 @@ Decisión: **pinear ids GA concretos, no alias ni ids preview**, porque los ids
|
|
|
40
40
|
|
|
41
41
|
`[UNCERTAIN]`: el mapping alias→id-concreto no está byte-documentado; se resuelve NO usando alias.
|
|
42
42
|
|
|
43
|
-
**Filas para `server/pricing.ts` (clave `'gemini:<model>'`, USD por 1M tokens, Standard paid tier):**
|
|
43
|
+
**Filas para `server/modules/accounting/runtime/pricing.ts` (clave `'gemini:<model>'`, USD por 1M tokens, Standard paid tier):**
|
|
44
44
|
|
|
45
45
|
```ts
|
|
46
46
|
// Gemini (Google). Ref: ai.google.dev/gemini-api/docs/pricing (fetched 2026-06-16).
|
|
@@ -159,7 +159,7 @@ export { claudeAdapter, codexAdapter, geminiAdapter }
|
|
|
159
159
|
|
|
160
160
|
**Decisión: `nativeOtelEnv: true` — Gemini va por el path de claude (env-injection), NO por el bridge sintético de codex.** Evidencia `[confirmed]`: `packages/core/src/telemetry/config.ts` (PR #9113) lee de `process.env` con precedencia env>settings, emitiendo OTLP nativo de traces+metrics+logs.
|
|
161
161
|
|
|
162
|
-
**Cómo se inyecta** — en `server/queue-manager.ts`, con `nativeOtelEnv:true` el bloque del bridge (`queue-manager.ts:1197-1205`, gated `!adapter.capabilities.nativeOtelEnv`) **se salta automáticamente**, y Gemini fluye por `buildTelemetryEnv` (`queue-manager.ts:1042,1105`). El adapter/queue inyecta:
|
|
162
|
+
**Cómo se inyecta** — en `server/modules/execution/runtime/queue-manager.ts`, con `nativeOtelEnv:true` el bloque del bridge (`queue-manager.ts:1197-1205`, gated `!adapter.capabilities.nativeOtelEnv`) **se salta automáticamente**, y Gemini fluye por `buildTelemetryEnv` (`queue-manager.ts:1042,1105`). El adapter/queue inyecta:
|
|
163
163
|
```
|
|
164
164
|
GEMINI_TELEMETRY_ENABLED=true
|
|
165
165
|
GEMINI_TELEMETRY_TARGET=local
|
|
@@ -185,15 +185,15 @@ Mergeable independiente, no cambia comportamiento observable.
|
|
|
185
185
|
| Fichero:línea | Cambio | Bloq |
|
|
186
186
|
|---|---|---|
|
|
187
187
|
| `server/desktop-db.ts:10,50,167,268,388` | `CliProvider = 'claude'\|'codex'` → ensanchar a incluir `'gemini'` (o alias a `ProviderId`/string). Tipo DB central; todos heredan. `DEFAULT 'claude'` se mantiene. | **sí** |
|
|
188
|
-
| `server/spec-models.ts:1-37` | `SpecProvider` union + reemplazar ternario `provider==='codex'?CODEX:CLAUDE` en `getModelsForProvider` por **lookup `Record<provider, SpecModelOption[]>`** (fallback `adapter.defaultModel()`/`[]`). `PROVIDER_DEFAULT_MODEL` → record extensible. | **sí** |
|
|
188
|
+
| `server/modules/specs/runtime/spec-models.ts:1-37` | `SpecProvider` union + reemplazar ternario `provider==='codex'?CODEX:CLAUDE` en `getModelsForProvider` por **lookup `Record<provider, SpecModelOption[]>`** (fallback `adapter.defaultModel()`/`[]`). `PROVIDER_DEFAULT_MODEL` → record extensible. | **sí** |
|
|
189
189
|
| `server/desktop-router.ts:158-168` (`GET /available-providers`) | Dejar de destructurar `{claude,codex}` fijo; `detectAvailableCLIs()` ya devuelve `Record<string,boolean>` → **devolver el map entero (spread)**. `if(providers.claude\|\|providers.codex)` → `Object.values(providers).some(Boolean)`. | **sí** |
|
|
190
190
|
| `server/desktop-router.ts:265-266` | casts `as 'claude'\|'codex'` en addProject → ensanchar (registry valida con `hasAdapter`). | **sí** |
|
|
191
191
|
| `server/project-registry.ts:116` | `AddProjectInput.providers?: ('claude'\|'codex')[]` → `ProviderId[]`/`string[]`. | **sí** |
|
|
192
192
|
| `client/src/hooks/useDesktop.tsx:29,35,48,172` | 4 anotaciones `('claude'\|'codex')[]` → `string[]`/`ProviderId`. | **sí** |
|
|
193
|
-
| `client/src/lib/provider-capabilities.ts:11` | `ProviderId = 'claude'\|'codex'` → añadir `'gemini'`/string. | **sí** |
|
|
193
|
+
| `client/src/features/providers/lib/provider-capabilities.ts:11` | `ProviderId = 'claude'\|'codex'` → añadir `'gemini'`/string. | **sí** |
|
|
194
194
|
| `client/src/components/ModelSelector.tsx:20-55,80` | ternario `provider==='claude'?CLAUDE:CODEX` → map por id; `PRESET_DEFAULTS`/`MAX_OVERRIDES` literal → `Record<string,string>`; ensanchar prop union. **Bloqueante funcional**: sin esto Gemini mostraría modelos de Codex. | **sí** |
|
|
195
|
-
| `client/src/components/ChatInput.tsx:7-18,25` | selección por id-keyed map; ensanchar `provider?: 'claude'\|'codex'`. | **sí** |
|
|
196
|
-
| `client/src/components/AddProjectDialog.tsx:28,31,37,41,67-79,96,141,235-236` | `availableProviders` de `{claude;codex}` fijo → `Record<string,boolean>` iterado sobre `/available-providers`; `!claude && !codex` → iterar keys. | **sí** |
|
|
195
|
+
| `client/src/features/chat/components/ChatInput.tsx:7-18,25` | selección por id-keyed map; ensanchar `provider?: 'claude'\|'codex'`. | **sí** |
|
|
196
|
+
| `client/src/features/projects/components/AddProjectDialog.tsx:28,31,37,41,67-79,96,141,235-236` | `availableProviders` de `{claude;codex}` fijo → `Record<string,boolean>` iterado sobre `/available-providers`; `!claude && !codex` → iterar keys. | **sí** |
|
|
197
197
|
| `client/src/components/{AiEngineSelector:40,53, RailEngineSelector:33,38, CliLaunchMenu:52,55, explore-spec/SpecModelPicker:23,81, SetupWizard:563}` | casts inline `as 'claude'\|'codex'` → ensanchar union. Listas data-driven, Gemini aparece solo. | **sí** |
|
|
198
198
|
| `server/util/cli-prompt.ts:178-191` | `spawnAiCli` ya cae a `spawnCli` genérico para binarios desconocidos → **POSIX funciona sin cambio**. Windows multi-line argv (`transformClaudeArgsForWindows`/`transformCodexArgsForWindows`) NO cubre gemini. | cosmético (POSIX) / bloq Windows |
|
|
199
199
|
|
|
@@ -203,17 +203,17 @@ Mergeable independiente, no cambia comportamiento observable.
|
|
|
203
203
|
|---|---|---|
|
|
204
204
|
| `server/providers/gemini-adapter.ts` (nuevo) | El adapter completo (§3). | **sí** |
|
|
205
205
|
| `server/providers/index.ts:11-14,17` | import + `register(geminiAdapter)` + re-export. | **sí** |
|
|
206
|
-
| `server/pricing.ts:44-50` | 4 filas `'gemini:<model>'` (§2). Sin ellas coste=NULL. | **sí** |
|
|
206
|
+
| `server/modules/accounting/runtime/pricing.ts:44-50` | 4 filas `'gemini:<model>'` (§2). Sin ellas coste=NULL. | **sí** |
|
|
207
207
|
| `server/project-router-tickets.ts:1540-1556` (ai-edit) | dispatch hardcoded `if(provider==='codex'){binary='codex'...} else {binary='claude'...}` → **un proyecto gemini spawnearía 'claude' (binario equivocado)**. Reemplazar por `adapter.binary` + `adapter.buildArgs` (patrón ya usado en quick-spec línea 341). | **sí** |
|
|
208
208
|
| `server/project-router-tickets.ts:420,610,1022,1148` | bloques `if(provider==='codex')` sin hermano gemini → generalizar o añadir arm gemini. | **sí** |
|
|
209
209
|
| `server/setup-manager.ts:697-700,1306-1307` | regex allow-list `m[1]==='claude'\|\|m[1]==='codex'` **descarta 'gemini' silenciosamente** → install-config cae a claude. Añadir `'gemini'`. **Fallo silencioso de alto riesgo.** | **sí** |
|
|
210
210
|
| `server/setup-manager.ts:495-503` | `computeSummary` branch codex → hermano gemini si el summary difiere. | menor |
|
|
211
211
|
| `server/setup-prerequisites.ts:405-423` | switch de install-hint: añadir `case 'gemini':` (URL/comando install Gemini CLI). | menor |
|
|
212
|
-
| `server/agent-refine-manager.ts:73,79` | ensanchar `provider?: 'claude'\|'codex'`. (validateAgentBody ya skip non-claude). | **sí** (compile) |
|
|
213
|
-
| `server/chat-manager.ts:124,132,332` | ensanchar `provider?: 'claude'\|'codex'` ctor + cast persistido. Gates `adapter.id==='claude'` (scope/userMcp) ya rutean gemini como codex (OK). | **sí** (compile) |
|
|
214
|
-
| `server/result-event.ts:98-117` | `normaliseResultEvent` legacy shim: gemini cae al branch codex `else` (mis-parsea usage). **Preferir `adapter.extractResult`** (path moderno). Ensanchar union por si se usa. | menor |
|
|
215
|
-
| `client/src/types/context-scope.ts:62-67` | añadir filas de coste gemini (cliente). | menor |
|
|
216
|
-
| `client/src/
|
|
212
|
+
| `server/modules/agents/runtime/agent-refine-manager.ts:73,79` | ensanchar `provider?: 'claude'\|'codex'`. (validateAgentBody ya skip non-claude). | **sí** (compile) |
|
|
213
|
+
| `server/modules/conversations/runtime/chat-manager.ts:124,132,332` | ensanchar `provider?: 'claude'\|'codex'` ctor + cast persistido. Gates `adapter.id==='claude'` (scope/userMcp) ya rutean gemini como codex (OK). | **sí** (compile) |
|
|
214
|
+
| `server/modules/accounting/runtime/result-event.ts:98-117` | `normaliseResultEvent` legacy shim: gemini cae al branch codex `else` (mis-parsea usage). **Preferir `adapter.extractResult`** (path moderno). Ensanchar union por si se usa. | menor |
|
|
215
|
+
| `client/src/features/chat/types/context-scope.ts:62-67` | añadir filas de coste gemini (cliente). | menor |
|
|
216
|
+
| `client/src/features/analytics/components/ProviderBreakdownCard.tsx:9-17` | `PROVIDER_LABEL`/`PROVIDER_ACCENT`: añadir `gemini` (label + accent, p.ej. `bg-accent-success`). | menor |
|
|
217
217
|
| `client/src/components/Navbar.tsx:26-43` | badge: añadir `=== 'gemini'` (label/color), sino cae a 'no CLI' rojo. | menor |
|
|
218
218
|
| `client/src/components/SetupWizard.tsx:63-76` | heurísticas modelId sonnet/haiku/opus son claude-specific → branch gemini si el configure debe mostrar modelo. | menor |
|
|
219
219
|
| `server/desktop-router.ts:28-35,155-157,229-234` | gate beta: añadir `SPECRAILS_GEMINI_BETA` paralelo a `SPECRAILS_CODEX_BETA`. Generalizar el refuse hardcoded `providers.includes('codex')` (línea 229). | menor (necesario para el gate) |
|
|
@@ -273,7 +273,7 @@ CI exige **80% server** (lines/functions/statements, 70% branches) y **80% clien
|
|
|
273
273
|
- `parseStreamLine`: fixtures NDJSON bajo `server/providers/__fixtures__/gemini-*.ndjson` (init/message/tool_use/tool_result/error/result/línea-vacía/parse-fail), aserción del AdapterEvent[].
|
|
274
274
|
- `extractResult`: stats → tokens_in/out/cache_read, num_turns, session_id, `total_cost_usd` undefined.
|
|
275
275
|
- `detectInstalled`: mock de `execSync` (no instalado / version OK / version < min / probe-fail / timeout >3s → installed:false).
|
|
276
|
-
- `server/pricing.test.ts`: 4 filas `gemini:*`, `estimateCostUsd('gemini',model,usage)` correcto; clave ausente → null; semántica cached (no doble-conteo).
|
|
276
|
+
- `server/modules/accounting/runtime/pricing.test.ts`: 4 filas `gemini:*`, `estimateCostUsd('gemini',model,usage)` correcto; clave ausente → null; semántica cached (no doble-conteo).
|
|
277
277
|
- `server/provider-selection.test.ts`: `isProviderEnabled`/`resolveProvider`/`validateRequestedProvider` aceptan `'gemini'`; multi-provider claude+gemini.
|
|
278
278
|
- `server/providers/registry.test.ts`: `getAdapter('gemini')`/`hasAdapter`/`listAdapters` incluye gemini tras import de index.
|
|
279
279
|
|
|
@@ -296,6 +296,6 @@ CI exige **80% server** (lines/functions/statements, 70% branches) y **80% clien
|
|
|
296
296
|
3. **Beta-gated validation** — probar end-to-end: detect, add-project con gemini, Quick spec, Explore multi-turno (resume), Analytics coste, terminal launch. Validar exit 53/42, auth `GEMINI_API_KEY`. **NO** habilitar rails reales hasta resolver la traducción slash-command (§6, bloqueante) — gemini sirve para spec/explore/quick en esta fase.
|
|
297
297
|
4. **Docs** — crear `docs/adding-a-provider.md` (falta) con gemini como ejemplo, y `docs/gemini.md` (espejo de `docs/codex.md`) con setup de API key.
|
|
298
298
|
|
|
299
|
-
**Primer commit recomendado:** PR-A paso atómico — ensanchar `server/desktop-db.ts:10` `CliProvider` para incluir `'gemini'` y convertir el ternario de `server/spec-models.ts:1-37` `getModelsForProvider` en lookup `Record<provider, SpecModelOption[]>`. Desbloquea la cadena de tipos sin tocar comportamiento y deja la base lista para registrar el adapter.
|
|
299
|
+
**Primer commit recomendado:** PR-A paso atómico — ensanchar `server/desktop-db.ts:10` `CliProvider` para incluir `'gemini'` y convertir el ternario de `server/modules/specs/runtime/spec-models.ts:1-37` `getModelsForProvider` en lookup `Record<provider, SpecModelOption[]>`. Desbloquea la cadena de tipos sin tocar comportamiento y deja la base lista para registrar el adapter.
|
|
300
300
|
|
|
301
301
|
**Puntos `[UNCERTAIN]` pendientes (no inventados):** (a) `OTEL_RESOURCE_ATTRIBUTES` propagation en Gemini — validar empíricamente antes de confiar para correlación job/project; (b) semántica de `cachedContentTokenCount` como subconjunto de input — fijar por test de pricing; (c) `mcpRegistration` exacto en la versión bundleada — verificado que escribe a settings.json (`project-json`), confirmar en build. Ninguno bloquea v1 (spec/explore/quick); todos tienen fallback.
|
|
@@ -157,4 +157,4 @@ Un **spike de validación de orquestación**, ANTES de escribir el scaffold comp
|
|
|
157
157
|
- Core gap: `/Users/javi/repos/specrails-core/src/installer/phases/provider-detect.ts` (15, 33-36, 87-92), `/Users/javi/repos/specrails-core/src/installer/phases/install-config.ts` (13, 96), `/Users/javi/repos/specrails-core/src/installer/phases/scaffold.ts` (174-184, 244-250, 278-311, 666-747, 762-830), `/Users/javi/repos/specrails-core/src/installer/commands/init.ts` (86, 128, 204-218), `/Users/javi/repos/specrails-core/integration-contract.json` (3-26), `/Users/javi/repos/specrails-core/pinned-versions.json` (3).
|
|
158
158
|
- Templates a transformar: `/Users/javi/repos/specrails-core/templates/commands/specrails/implement.md`, `/Users/javi/repos/specrails-core/templates/commands/specrails/batch-implement.md`, `/Users/javi/repos/specrails-core/templates/agents/sr-{architect,developer,reviewer}.md`.
|
|
159
159
|
- Precedente de aplanamiento codex: `/Users/javi/repos/specrails-core/templates/codex-skills/batch-implement/SKILL.md` (5, 19-32), `/Users/javi/repos/specrails-core/templates/codex-skills/implement/SKILL.md` (24).
|
|
160
|
-
- Desktop (ya hecho): `/Users/javi/repos/specrails-desktop/server/providers/gemini-adapter.ts` (225-235), `/Users/javi/repos/specrails-desktop/server/providers/index.ts` (12, 16); a tocar: `/Users/javi/repos/specrails-desktop/server/queue-manager.ts` (command translation, `profile=null`), `/Users/javi/repos/specrails-desktop/client/src/lib/provider-capabilities.ts` (ocultar rails gemini).
|
|
160
|
+
- Desktop (ya hecho): `/Users/javi/repos/specrails-desktop/server/providers/gemini-adapter.ts` (225-235), `/Users/javi/repos/specrails-desktop/server/providers/index.ts` (12, 16); a tocar: `/Users/javi/repos/specrails-desktop/server/modules/execution/runtime/queue-manager.ts` (command translation, `profile=null`), `/Users/javi/repos/specrails-desktop/client/src/features/providers/lib/provider-capabilities.ts` (ocultar rails gemini).
|
package/docs/gemini.md
CHANGED
|
@@ -113,7 +113,7 @@ A few of these deserve a fuller explanation:
|
|
|
113
113
|
|
|
114
114
|
- **Cost is estimated, not native.** Gemini reports token counts (including
|
|
115
115
|
cached) but no USD cost in its stream, so Specrails estimates the cost from
|
|
116
|
-
a rate card (`server/pricing.ts`, keys `gemini:<model>`). Estimated rows
|
|
116
|
+
a rate card (`server/modules/accounting/runtime/pricing.ts`, keys `gemini:<model>`). Estimated rows
|
|
117
117
|
show a `~` prefix on the Analytics page.
|
|
118
118
|
- **OTEL is native.** Like Claude, Gemini honours the standard `OTEL_*`
|
|
119
119
|
telemetry env vars, so QueueManager injects the same telemetry env
|
|
@@ -167,7 +167,7 @@ Flash models; Pro/preview need billing.
|
|
|
167
167
|
|
|
168
168
|
> A few older ids (`gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-3-flash-preview`)
|
|
169
169
|
> are **not** selectable models. They survive only as historic pricing rows in
|
|
170
|
-
> `server/pricing.ts` so that already-recorded invocations on those models still
|
|
170
|
+
> `server/modules/accounting/runtime/pricing.ts` so that already-recorded invocations on those models still
|
|
171
171
|
> price correctly.
|
|
172
172
|
|
|
173
173
|
## Trusted folders (headless)
|
|
@@ -204,7 +204,7 @@ preview models; use a Flash model or enable billing.
|
|
|
204
204
|
**Cost shows `—`** — there's no `gemini:<model>` pricing row for the model
|
|
205
205
|
that ran (e.g. a brand-new model Google shipped after our last review). Cost
|
|
206
206
|
estimation fails soft (it returns nothing rather than guessing). Add a row to
|
|
207
|
-
`server/pricing.ts` and reload.
|
|
207
|
+
`server/modules/accounting/runtime/pricing.ts` and reload.
|
|
208
208
|
|
|
209
209
|
## Emergency rollback
|
|
210
210
|
|
|
@@ -231,7 +231,7 @@ are unaffected; the adapter stays registered but dormant.
|
|
|
231
231
|
`minCliVersion: '0.11.0'`). Registered in `server/providers/index.ts`.
|
|
232
232
|
- **Headless subagent ack:** `server/providers/gemini-agent-ack.ts`
|
|
233
233
|
(`acknowledgeGeminiProjectAgents`), wired as the adapter's
|
|
234
|
-
`prepareHeadlessSpawn` and called by `server/queue-manager.ts` before each
|
|
234
|
+
`prepareHeadlessSpawn` and called by `server/modules/execution/runtime/queue-manager.ts` before each
|
|
235
235
|
rail spawn.
|
|
236
236
|
- **Stream schema** (pinned to the gemini-cli 0.11 contract, locked by the
|
|
237
237
|
fixtures under `server/providers/__fixtures__/gemini-*.ndjson`):
|
|
@@ -241,7 +241,7 @@ are unaffected; the adapter stays registered but dormant.
|
|
|
241
241
|
- **Beta gate + provider list:** `server/desktop-router.ts`
|
|
242
242
|
(`isGeminiBetaDisabled` — returns `true` only when
|
|
243
243
|
`SPECRAILS_GEMINI_BETA === '0'`; `/available-providers`, `POST /projects`).
|
|
244
|
-
- **Pricing / cost estimation:** `server/pricing.ts` (`gemini:<model>` rows +
|
|
244
|
+
- **Pricing / cost estimation:** `server/modules/accounting/runtime/pricing.ts` (`gemini:<model>` rows +
|
|
245
245
|
`estimateCostUsd`, which returns `null` when no row matches).
|
|
246
246
|
- **Trust-folder env:** `server/util/cli-prompt.ts`, `spawnGemini`.
|
|
247
247
|
|
package/docs/internals/README.md
CHANGED
|
@@ -6,9 +6,13 @@ If you're a user looking for **how do I do X?** docs, head back to the [user gui
|
|
|
6
6
|
|
|
7
7
|
## Contents
|
|
8
8
|
|
|
9
|
+
Start with [the modular architecture decision](modular-architecture.md),
|
|
10
|
+
[the source map](source-map.md) and [the shared contributor/AI guide](../../AGENTS.md).
|
|
11
|
+
|
|
9
12
|
| Doc | What it covers |
|
|
10
13
|
|-----|----------------|
|
|
11
14
|
| [architecture.md](architecture.md) | Server modules, client layout, WebSocket protocol, process spawning, security model |
|
|
15
|
+
| [source-architecture.md](source-architecture.md) | Persistence boundaries, queue collaborators and unused-source audit |
|
|
12
16
|
| [api-reference.md](api-reference.md) | REST endpoint catalogue under `/api/*` and `/api/projects/:projectId/*` |
|
|
13
17
|
| [configuration.md](configuration.md) | Settings, env vars, kill switches, advanced flags |
|
|
14
18
|
| [operations-runbook.md](operations-runbook.md) | Start/stop, port conflicts, recovery procedures, backups |
|
|
@@ -17,7 +21,7 @@ If you're a user looking for **how do I do X?** docs, head back to the [user gui
|
|
|
17
21
|
| [programmatic-agent-runtime-validation.md](programmatic-agent-runtime-validation.md) | Paired implementation test results, packaging evidence and release limitations |
|
|
18
22
|
| [openspec-workflow.md](openspec-workflow.md) | `opsx:*` change lifecycle — used by the app itself for structured change management |
|
|
19
23
|
| [adding-a-provider.md](adding-a-provider.md) | How to add a new AI CLI: one adapter file plus one entry in the registry |
|
|
20
|
-
| [profiles.md](profiles.md) | Agent profiles quick start: open the Agents section, pick a profile per rail at launch, author custom agents in Agent Studio. For the true file-format and snapshotting internals, read `server/profile-manager.ts` and the profile-manager section of `CLAUDE.md` |
|
|
24
|
+
| [profiles.md](profiles.md) | Agent profiles quick start: open the Agents section, pick a profile per rail at launch, author custom agents in Agent Studio. For the true file-format and snapshotting internals, read `server/modules/agents/runtime/profile-manager.ts` and the profile-manager section of `CLAUDE.md` |
|
|
21
25
|
| [safe-pr-review-flow.md](safe-pr-review-flow.md) | The ask-first PR delivery: the `rail_pr_deliveries` row, decision state machine, the two synced decision surfaces (rail row + agent-chat card), the `on_review` ticket status and its Jira mapping |
|
|
22
26
|
| [interactive-jobs.md](interactive-jobs.md) | Interactive-by-default jobs: the persistent-stdin session model, `finalize` vs `auto` settle modes, loop-step turn routing, accounting reconciliation, kill-switch matrix |
|
|
23
27
|
| [loop-step-log-explorer.md](loop-step-log-explorer.md) | The step-grouped log surface for loop runs: the `loop_graph` / `loop_step` / `loop_step_end` event contract and seq guarantees, grouping + status model (interrupted rule, legacy fallback), follow mode, perf notes |
|
|
@@ -31,6 +35,6 @@ status is capability-aware: Kimi pure-output transforms fail closed.
|
|
|
31
35
|
|
|
32
36
|
## Contributing
|
|
33
37
|
|
|
34
|
-
For coding conventions, file naming, the coverage policy
|
|
38
|
+
For coding conventions, file naming, the coverage policy and WebSocket invariants, see [`AGENTS.md`](../../AGENTS.md). `CLAUDE.md` imports that shared guide; detailed history is kept in [optional reference notes](legacy-implementation-notes.md).
|
|
35
39
|
|
|
36
40
|
When adding a feature, follow the OpenSpec workflow: `/opsx:new → /opsx:ff → /opsx:apply → /opsx:verify → /opsx:archive`. The `/opsx:*` invocations resolve to command files under `.claude/commands/opsx/*.md` (the related skills under `.claude/skills/` are named `openspec-*`).
|
|
@@ -51,7 +51,7 @@ export const exampleAdapter: ProviderAdapter = {
|
|
|
51
51
|
capabilities: {
|
|
52
52
|
nativeResume: true,
|
|
53
53
|
nativeStreamJson: true,
|
|
54
|
-
nativeCostUsd: false, // if false, add the provider:model entries to server/pricing.ts
|
|
54
|
+
nativeCostUsd: false, // if false, add the provider:model entries to server/modules/accounting/runtime/pricing.ts
|
|
55
55
|
nativeOtelEnv: false, // if false, the app will synthesise OTEL via the bridge
|
|
56
56
|
profileEnvSupport: true,
|
|
57
57
|
systemPromptArg: false,
|
|
@@ -130,7 +130,7 @@ accordingly — don't assume null-only-on-empty.
|
|
|
130
130
|
|
|
131
131
|
The model catalog is **duplicated** by design: the adapter's `modelCatalog()`
|
|
132
132
|
drives the spawn-time UI, but spec-model validation reads a *second* copy in
|
|
133
|
-
`server/spec-models.ts` (`PROVIDER_MODELS` + `PROVIDER_DEFAULT_MODEL`, both
|
|
133
|
+
`server/modules/specs/runtime/spec-models.ts` (`PROVIDER_MODELS` + `PROVIDER_DEFAULT_MODEL`, both
|
|
134
134
|
`Record<string, …>` keyed by provider id). The file even comments that
|
|
135
135
|
`GEMINI_MODELS` "Mirrors GEMINI_MODELS in server/providers/gemini-adapter.ts".
|
|
136
136
|
If you add the catalog only to the adapter, your models won't validate in the
|
|
@@ -163,22 +163,22 @@ provider with zero edits):
|
|
|
163
163
|
(the only per-id touch on this route is an optional beta gate, below).
|
|
164
164
|
- `POST /api/projects` provider validation (`server/desktop-router.ts`,
|
|
165
165
|
via `hasAdapter` / `listAdapters`).
|
|
166
|
-
- `AddProjectDialog` (`client/src/components/AddProjectDialog.tsx`) — it
|
|
166
|
+
- `AddProjectDialog` (`client/src/features/projects/components/AddProjectDialog.tsx`) — it
|
|
167
167
|
fetches `/available-providers` generically (`Object.entries(data)`) and a
|
|
168
168
|
`providerRenderOrder()` helper appends **any** detected-but-unlisted
|
|
169
169
|
provider after the canonical-ordered known ones, with a neutral chip
|
|
170
170
|
fallback. A new provider appears in the Add Project UI automatically.
|
|
171
171
|
- `setup-prerequisites` provider rows (`server/setup-prerequisites.ts`,
|
|
172
172
|
iterates `listAdapters()`).
|
|
173
|
-
- Analytics `byProvider` (`server/spending.ts`) and the
|
|
174
|
-
`ProviderBreakdownCard` (`client/src/
|
|
173
|
+
- Analytics `byProvider` (`server/modules/accounting/runtime/spending.ts`) and the
|
|
174
|
+
`ProviderBreakdownCard` (`client/src/features/analytics/components/ProviderBreakdownCard.tsx`).
|
|
175
175
|
|
|
176
176
|
### `ProviderId` is `string` — no compile-time blocker
|
|
177
177
|
|
|
178
178
|
There is **no type-union to widen**. `ProviderId` is `export type ProviderId = string`
|
|
179
179
|
(`server/providers/types.ts`), and every provider-typed seam already aliases it:
|
|
180
|
-
`CliProvider` (`server/desktop-db.ts`), `SpecProvider` (`server/spec-models.ts`),
|
|
181
|
-
`EnqueueOptions.provider` and `_jobProviderSelection` (`server/queue-manager.ts`),
|
|
180
|
+
`CliProvider` (`server/desktop-db.ts`), `SpecProvider` (`server/modules/specs/runtime/spec-models.ts`),
|
|
181
|
+
`EnqueueOptions.provider` and `_jobProviderSelection` (`server/modules/execution/runtime/queue-manager.ts`),
|
|
182
182
|
`ChatManager`, `AgentRefineManager`, and `ProjectRegistry`. Adding a provider is
|
|
183
183
|
**not** a compile-time blocker — the old "widen ~8 unions" step is paid off (Gemini
|
|
184
184
|
is the proof it works). Any remaining `'claude' | 'codex'` literals live in test
|
|
@@ -210,16 +210,16 @@ makes it look first-class instead of falling back to a raw id:
|
|
|
210
210
|
### 3. (If `nativeCostUsd === false`) add pricing entries
|
|
211
211
|
|
|
212
212
|
For providers that don't report `total_cost_usd` in their terminal
|
|
213
|
-
event, append the rate card to `server/pricing.ts`:
|
|
213
|
+
event, append the rate card to `server/modules/accounting/runtime/pricing.ts`:
|
|
214
214
|
|
|
215
215
|
```ts
|
|
216
216
|
'example:flagship': { inputPer1M: 5.00, outputPer1M: 15.00, cacheReadPer1M: 0.50, lastReviewedAt: '2026-05-18' },
|
|
217
217
|
'example:fast': { inputPer1M: 0.50, outputPer1M: 1.50, cacheReadPer1M: 0.05, lastReviewedAt: '2026-05-18' },
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
The `finaliseInvocationResult` flow in `server/result-event.ts` falls
|
|
220
|
+
The `finaliseInvocationResult` flow in `server/modules/accounting/runtime/result-event.ts` falls
|
|
221
221
|
back to this table automatically and returns an `estimated` flag that
|
|
222
|
-
`recordInvocation` (`server/ai-invocations.ts`) persists as
|
|
222
|
+
`recordInvocation` (`server/modules/accounting/runtime/ai-invocations.ts`) persists as
|
|
223
223
|
`total_cost_usd_estimated = 1` on the `ai_invocations` row, which in
|
|
224
224
|
turn lights up the `~` tilde + Hero footnote on the AnalyticsPage.
|
|
225
225
|
|
|
@@ -233,7 +233,7 @@ Two paths, picked by your `nativeOtelEnv` capability flag:
|
|
|
233
233
|
is no `GEMINI_TELEMETRY_*` env var — Gemini honours the same `OTEL_*` vars as
|
|
234
234
|
Claude.
|
|
235
235
|
- **`nativeOtelEnv: false`** (Codex, Kimi) ⇒ the synthetic OTEL bridge at
|
|
236
|
-
`server/codex-otel-bridge.ts` fills the gap. It's provider-neutral despite its
|
|
236
|
+
`server/modules/accounting/runtime/codex-otel-bridge.ts` fills the gap. It's provider-neutral despite its
|
|
237
237
|
name — it consumes the canonical `AdapterEvent` stream. As long as your
|
|
238
238
|
adapter's `parseStreamLine` emits `text-delta`, `tool-use`, `session-started`,
|
|
239
239
|
and `result` events, the bridge synthesises traces / metrics / logs for free.
|
|
@@ -296,7 +296,7 @@ Two distinct version concepts — don't conflate them:
|
|
|
296
296
|
## Known gotchas
|
|
297
297
|
|
|
298
298
|
- **Legacy result path.** `normaliseResultEvent(event, provider)`
|
|
299
|
-
(`server/result-event.ts`) is still live for any callsite not yet
|
|
299
|
+
(`server/modules/accounting/runtime/result-event.ts`) is still live for any callsite not yet
|
|
300
300
|
migrated to `finaliseInvocationResult`. It only special-cases
|
|
301
301
|
`provider === 'claude'`; everything else falls into the non-claude
|
|
302
302
|
(codex-shaped) branch. A new provider hitting that path would be
|
|
@@ -363,15 +363,15 @@ Most of the old debt is **paid off** — and Gemini's addition is what paid it:
|
|
|
363
363
|
|
|
364
364
|
The genuine id-keyed sites that **remain** are:
|
|
365
365
|
|
|
366
|
-
- **`normaliseResultEvent` legacy branch** (`server/result-event.ts`) — the
|
|
366
|
+
- **`normaliseResultEvent` legacy branch** (`server/modules/accounting/runtime/result-event.ts`) — the
|
|
367
367
|
pre-`finaliseInvocationResult` path that special-cases `provider === 'claude'`.
|
|
368
|
-
- **Codex rail slash-command rewrite** (`server/queue-manager.ts`) —
|
|
368
|
+
- **Codex rail slash-command rewrite** (`server/modules/execution/runtime/queue-manager.ts`) —
|
|
369
369
|
`adapter.id === 'codex'`.
|
|
370
370
|
|
|
371
371
|
Plus a few cosmetic per-id sites that are *expected* edits, not drift: the
|
|
372
372
|
provider beta-gate env checks (`server/desktop-router.ts`), the install-hint
|
|
373
373
|
`switch` (`server/setup-prerequisites.ts`), the `PROVIDER_ORDER` / `PROVIDER_META`
|
|
374
|
-
chip, and the duplicated model catalog (`server/spec-models.ts`).
|
|
374
|
+
chip, and the duplicated model catalog (`server/modules/specs/runtime/spec-models.ts`).
|
|
375
375
|
|
|
376
376
|
The long-term goal is to delete the two remaining branches so adding a fourth
|
|
377
377
|
provider really is just the adapter file plus the registry entry. If you find a
|
|
@@ -397,3 +397,10 @@ bundled `local-runner` process, which speaks claude-shaped stream-json so the
|
|
|
397
397
|
spawn contract is unchanged. If you add another endpoint-backed provider, reuse
|
|
398
398
|
that adapter factory + the runner rather than teaching managers a new
|
|
399
399
|
transport. See `docs/internals/local-agent-runner.md`.
|
|
400
|
+
|
|
401
|
+
### Claude Opus generation
|
|
402
|
+
|
|
403
|
+
The `opus` catalog value selects Claude Opus 5.5 (`claude-opus-5-5`). Keep the
|
|
404
|
+
Claude adapter pin, selector labels, Core CLI executor and cost estimates aligned
|
|
405
|
+
when advancing this alias. Concrete historical model IDs in usage events retain
|
|
406
|
+
their existing estimates; provider-reported cost remains authoritative.
|
|
@@ -32,7 +32,7 @@ Los tres repositorios ya contienen ejecución programática, con responsabilidad
|
|
|
32
32
|
| Desktop | Adaptadores, procesos, streaming, colas, loops, SQLite, costes, worktrees, MCP y entrega | Control homogéneo por fase; reanudación durable del grafo; política de proveedor por rol |
|
|
33
33
|
| ai-agent-dev | Pipeline TypeScript con Claude Agent SDK, contexto preparado, JSON de análisis, herramientas y checks | Generalización, proveedores intercambiables, persistencia durable y garantías de ejecución |
|
|
34
34
|
|
|
35
|
-
En Desktop, el pipeline principal sigue empaquetado en un único paso de IA. Su propio código lo explica: architect → developer → reviewer ocurre dentro de la invocación completa de Core. Eso limita qué puede observar y controlar el host en cada fase. [Grafo de Implement](/Users/javi/repos/specrails-desktop/server/loop-factory.ts:42).
|
|
35
|
+
En Desktop, el pipeline principal sigue empaquetado en un único paso de IA. Su propio código lo explica: architect → developer → reviewer ocurre dentro de la invocación completa de Core. Eso limita qué puede observar y controlar el host en cada fase. [Grafo de Implement](/Users/javi/repos/specrails-desktop/server/modules/loops/runtime/loop-factory.ts:42).
|
|
36
36
|
|
|
37
37
|
La migración debe conservar los prompts que expresan conocimiento de arquitectura, desarrollo y revisión. Las decisiones mecánicas —routing, siguiente fase, reintento, validación, presupuesto— deben tener una implementación ejecutable única.
|
|
38
38
|
|
|
@@ -70,17 +70,17 @@ Core ya proporciona un contrato valioso: identidad de ejecución, specs congelad
|
|
|
70
70
|
|
|
71
71
|
Pero este helper no ejecuta agentes: la coordinación principal sigue en plantillas distintas para Claude, Codex y Gemini; Kimi tiene un runner específico considerable. Existe incluso deriva entre el perfil validado y el prompt: schema/CLI permiten routing vacío o sin default, mientras el prompt Claude exige routing y exactamente un default. Centralizar esa decisión en código elimina una fuente de divergencia. [Operaciones del helper](/Users/javi/repos/specrails-core/src/installer/runtime/pipeline-state.ts:670), [schema](/Users/javi/repos/specrails-core/schemas/profile.v1.json:74), [validador CLI](/Users/javi/repos/specrails-core/bin/specrails-core.mjs:516), [prompt](/Users/javi/repos/specrails-core/templates/commands/specrails/implement.md:93).
|
|
72
72
|
|
|
73
|
-
Desktop ya tiene contratos de capacidades y eventos para Claude, Codex, Gemini y Kimi. Hay transporte Codex app-server y Claude stream-json, además de ejecución por procesos. No hace falta reemplazar de golpe estos transportes para conseguir control programático. [ProviderAdapter](/Users/javi/repos/specrails-desktop/server/providers/types.ts:213), [ciclo común](/Users/javi/repos/specrails-desktop/server/spawn-lifecycle.ts:94), [sesiones vivas](/Users/javi/repos/specrails-desktop/server/providers/live-session.ts:5).
|
|
73
|
+
Desktop ya tiene contratos de capacidades y eventos para Claude, Codex, Gemini y Kimi. Hay transporte Codex app-server y Claude stream-json, además de ejecución por procesos. No hace falta reemplazar de golpe estos transportes para conseguir control programático. [ProviderAdapter](/Users/javi/repos/specrails-desktop/server/providers/types.ts:213), [ciclo común](/Users/javi/repos/specrails-desktop/server/modules/execution/runtime/spawn-lifecycle.ts:94), [sesiones vivas](/Users/javi/repos/specrails-desktop/server/providers/live-session.ts:5).
|
|
74
74
|
|
|
75
75
|
Sus límites actuales ayudan a definir el piloto:
|
|
76
76
|
|
|
77
|
-
- El motor de loops sigue un único sucesor; no implementa fan-out/join interno, aunque sí existe paralelismo entre ejecuciones aisladas. [Validación del grafo](/Users/javi/repos/specrails-desktop/server/loop-graph.ts:208).
|
|
78
|
-
- Al reiniciar, los loops activos o pausados se marcan fallidos. La recuperación contable y del outbox es útil, pero no reanuda la continuación en memoria. [Reconciliación](/Users/javi/repos/specrails-desktop/server/loop-runs-store.ts:545).
|
|
79
|
-
- En loops manda el proveedor/modelo del rail para todos los nodos. Core admite un proveedor global y modelos por agente dentro de él. Permitir proveedor distinto por rol requiere un contrato nuevo explícito. [Política del rail](/Users/javi/repos/specrails-desktop/server/loop-run-manager.ts:1465), [perfil v1](/Users/javi/repos/specrails-core/schemas/profile.v1.json:26).
|
|
80
|
-
- El cap de coste del loop se comprueba entre pasos: puede excederse por un paso completo. Si el paso contiene todo Implement, el control es muy grueso. [Contrato del cap](/Users/javi/repos/specrails-desktop/server/loop-graph.ts:57).
|
|
81
|
-
- El ledger ya diferencia consumo y estimaciones; el desglose por fase es principalmente reconstrucción de eventos Claude. Hay que medir desde cada invocación independiente. [Ledger](/Users/javi/repos/specrails-desktop/server/ai-invocations.ts:37), [desglose](/Users/javi/repos/specrails-desktop/server/job-phase-breakdown.ts:3).
|
|
77
|
+
- El motor de loops sigue un único sucesor; no implementa fan-out/join interno, aunque sí existe paralelismo entre ejecuciones aisladas. [Validación del grafo](/Users/javi/repos/specrails-desktop/server/modules/loops/runtime/loop-graph.ts:208).
|
|
78
|
+
- Al reiniciar, los loops activos o pausados se marcan fallidos. La recuperación contable y del outbox es útil, pero no reanuda la continuación en memoria. [Reconciliación](/Users/javi/repos/specrails-desktop/server/modules/loops/runtime/loop-runs-store.ts:545).
|
|
79
|
+
- En loops manda el proveedor/modelo del rail para todos los nodos. Core admite un proveedor global y modelos por agente dentro de él. Permitir proveedor distinto por rol requiere un contrato nuevo explícito. [Política del rail](/Users/javi/repos/specrails-desktop/server/modules/loops/runtime/loop-run-manager.ts:1465), [perfil v1](/Users/javi/repos/specrails-core/schemas/profile.v1.json:26).
|
|
80
|
+
- El cap de coste del loop se comprueba entre pasos: puede excederse por un paso completo. Si el paso contiene todo Implement, el control es muy grueso. [Contrato del cap](/Users/javi/repos/specrails-desktop/server/modules/loops/runtime/loop-graph.ts:57).
|
|
81
|
+
- El ledger ya diferencia consumo y estimaciones; el desglose por fase es principalmente reconstrucción de eventos Claude. Hay que medir desde cada invocación independiente. [Ledger](/Users/javi/repos/specrails-desktop/server/modules/accounting/runtime/ai-invocations.ts:37), [desglose](/Users/javi/repos/specrails-desktop/server/modules/execution/runtime/job-phase-breakdown.ts:3).
|
|
82
82
|
|
|
83
|
-
Mantendría worktrees, locks, alcance multirrepo, validación final de Core, MCP y entrega de PRs. [Preparación y finalización](/Users/javi/repos/specrails-desktop/server/core-execution.ts:48), [aislamiento](/Users/javi/repos/specrails-desktop/server/rail-isolation.ts:28), [control de herramientas](/Users/javi/repos/specrails-desktop/server/mcp/tools/types.ts:280).
|
|
83
|
+
Mantendría worktrees, locks, alcance multirrepo, validación final de Core, MCP y entrega de PRs. [Preparación y finalización](/Users/javi/repos/specrails-desktop/server/core-execution.ts:48), [aislamiento](/Users/javi/repos/specrails-desktop/server/modules/delivery/runtime/rail-isolation.ts:28), [control de herramientas](/Users/javi/repos/specrails-desktop/server/mcp/tools/types.ts:280).
|
|
84
84
|
|
|
85
85
|
**Comparativa de alternativas**
|
|
86
86
|
|
|
@@ -25,7 +25,7 @@ The CLI and the desktop client read the token automatically. The browser client
|
|
|
25
25
|
|
|
26
26
|
There is no UI to set or clear the token, and it is not an app setting.
|
|
27
27
|
|
|
28
|
-
This page is hand-maintained against the route declarations in `server/*-router.ts`, the per-domain `server/project-router-{jobs,spending,settings,terminals,tickets,chat,setup}.ts` family, `server/code-explorer-router.ts`, and `server/jira-router.ts`. If you spot a discrepancy, please file an issue.
|
|
28
|
+
This page is hand-maintained against the route declarations in `server/*-router.ts`, the per-domain `server/project-router-{jobs,spending,settings,terminals,tickets,chat,setup}.ts` family, `server/modules/code/runtime/code-explorer-router.ts`, and `server/jira-router.ts`. If you spot a discrepancy, please file an issue.
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
@@ -761,5 +761,5 @@ Error responses are `{ "error": "<message>" }`.
|
|
|
761
761
|
|
|
762
762
|
## Caveats
|
|
763
763
|
|
|
764
|
-
- **Surface drift**: this file is hand-maintained against the route declarations in `server/*-router.ts`, the per-domain `server/project-router-{jobs,spending,settings,terminals,tickets,chat,setup}.ts` family, `server/code-explorer-router.ts`, and `server/jira-router.ts`. The app adds endpoints regularly; if a route exists in code but not here, please open an issue.
|
|
764
|
+
- **Surface drift**: this file is hand-maintained against the route declarations in `server/*-router.ts`, the per-domain `server/project-router-{jobs,spending,settings,terminals,tickets,chat,setup}.ts` family, `server/modules/code/runtime/code-explorer-router.ts`, and `server/jira-router.ts`. The app adds endpoints regularly; if a route exists in code but not here, please open an issue.
|
|
765
765
|
- **Stability**: routes under `/api/*` and `/api/projects/:projectId/*` are considered stable. A few legacy setup endpoints (`setup/start`, `setup/message`, `enrich/*`) back a flow the UI does not expose and remain only for forward compatibility.
|
|
@@ -55,7 +55,7 @@ Tests use vitest with `:memory:` SQLite databases.
|
|
|
55
55
|
|
|
56
56
|
> **Artifact relocation + bundled framework (pre-release, branch `feat/relocate-artifacts-to-home`).** Relocated projects spawn AI-CLIs from `projects/<slug>/workspace` (with `SPECRAILS_REPO_DIR` pointing at the repo) instead of the repo, so imported repos stay pristine; the framework is bundled and symlinked instead of installed per-project via `npx`. See the **Artifact relocation + bundled framework** section in `CLAUDE.md` and the three internal docs: `global-artifacts-relocation-evaluation.md`, `global-artifacts-alignment-contract.md`, `bundled-framework-build-plan.md`.
|
|
57
57
|
|
|
58
|
-
The app SQLite (`desktop.sqlite`) stores only project metadata. All per-project data lives in an isolated `jobs.sqlite` under the project's slug directory — not just jobs and chat, but rails, tickets, agent profiles/versions, AI invocations (cost analytics), telemetry pointers, file provenance, terminal settings/marks, and more (see the `MIGRATIONS` array in `server/db.ts`). Projects can be removed and re-added without losing history, and the registry can be wiped without touching project data.
|
|
58
|
+
The app SQLite (`desktop.sqlite`) stores only project metadata. All per-project data lives in an isolated `jobs.sqlite` under the project's slug directory — not just jobs and chat, but rails, tickets, agent profiles/versions, AI invocations (cost analytics), telemetry pointers, file provenance, terminal settings/marks, and more (see the `MIGRATIONS` array in `server/db/migrations.ts`). Projects can be removed and re-added without losing history, and the registry can be wiped without touching project data.
|
|
59
59
|
|
|
60
60
|
> The data root is hardcoded to `os.homedir()/.specrails`. There is no environment override for the data directory.
|
|
61
61
|
>
|
|
@@ -109,7 +109,7 @@ The `boundBroadcast` closure injects `projectId` into all WebSocket messages, so
|
|
|
109
109
|
| `project-registry.ts` | `ProjectRegistry` class: load/unload per-project `ProjectContext` |
|
|
110
110
|
| `desktop-router.ts` | `/api/*` routes: projects, settings, themes, specrails-tech proxy, cross-project analytics |
|
|
111
111
|
| `project-router.ts` | `/api/projects/:id/*` routes: all project-scoped operations |
|
|
112
|
-
| `db.ts` |
|
|
112
|
+
| `db.ts`, `db/` | Stable persistence facade with separate connection, migrations and domain repositories; see [source boundaries](source-architecture.md) |
|
|
113
113
|
| `queue-manager.ts` | Job queue: spawn provider CLI processes serially per project |
|
|
114
114
|
| `chat-manager.ts` | Chat/Explore: spawn provider CLI for conversational turns |
|
|
115
115
|
| `setup-manager.ts` | Setup wizard: orchestrate `specrails-core` install + `/setup` chat |
|
|
@@ -265,14 +265,14 @@ The app is more than the job pipeline. Each subsystem owns its modules; this is
|
|
|
265
265
|
| Subsystem | Server modules | Notes |
|
|
266
266
|
|-----------|---------------|-------|
|
|
267
267
|
| **Multi-provider adapters** | `server/providers/{types,claude-adapter,codex-adapter,gemini-adapter,kimi-adapter,registry,index}.ts`, `server/provider-selection.ts` | **Four first-class providers — Claude, Codex, Gemini, and Kimi — enabled by default** behind a `ProviderAdapter` contract. Claude reports native cost and supports persistent stdin; Codex (`≥ 0.128.0`) and Gemini (`≥ 0.11.0`) expose estimated usage; Kimi (`≥ 0.27.0`) runs CLI-only prompt-mode JSONL, resumes through terminal hints, uses `.kimi-code` skills/MCP, and leaves absent cost/tokens unavailable. A project can install any subset; `providers[]` is a JSON column, the first entry is primary. Per-invocation provider is late-bound. Provider availability is gated by executable detection, Core target compatibility, and the existing Codex/Gemini emergency switches. See [`adding-a-provider.md`](adding-a-provider.md), [`../codex.md`](../codex.md), [`../gemini.md`](../gemini.md), and [`../kimi.md`](../kimi.md). |
|
|
268
|
-
| **Spending analytics** | `server/spending.ts`, `server/ai-invocations.ts`, `server/pricing.ts` | `recordInvocation` writes an `ai_invocations` row per AI CLI call across six surfaces (`job`, `quick-spec`, `explore-spec`, `ai-edit`, `smash`, `file-summary`); powers the Analytics page and `spending.invalidated`. |
|
|
269
|
-
| **Agent profiles** | `server/profile-manager.ts`, `server/profiles-router.ts` | Declarative JSON in `.specrails/profiles/*.json`, snapshot-per-job, `SPECRAILS_PROFILE_PATH` env injection. Requires `specrails-core ≥ 4.1.0` in general and the Core 4.12 Kimi target for Kimi roles (the app-wide install floor is `^4.12.0`). Claude and Kimi advertise profile support; other adapters force legacy/no-profile mode. |
|
|
268
|
+
| **Spending analytics** | `server/modules/accounting/runtime/spending.ts`, `server/modules/accounting/runtime/ai-invocations.ts`, `server/modules/accounting/runtime/pricing.ts` | `recordInvocation` writes an `ai_invocations` row per AI CLI call across six surfaces (`job`, `quick-spec`, `explore-spec`, `ai-edit`, `smash`, `file-summary`); powers the Analytics page and `spending.invalidated`. |
|
|
269
|
+
| **Agent profiles** | `server/modules/agents/runtime/profile-manager.ts`, `server/modules/agents/runtime/profiles-router.ts` | Declarative JSON in `.specrails/profiles/*.json`, snapshot-per-job, `SPECRAILS_PROFILE_PATH` env injection. Requires `specrails-core ≥ 4.1.0` in general and the Core 4.12 Kimi target for Kimi roles (the app-wide install floor is `^4.12.0`). Claude and Kimi advertise profile support; other adapters force legacy/no-profile mode. |
|
|
270
270
|
| **Plugins (Integrations)** | `server/plugin-manager.ts`, `server/plugins/` | Bundled-only, MCP-based, additivity invariant, surgical `.mcp.json` merge, `plugin.*` WS events. Serena ships today. |
|
|
271
|
-
| **Terminal panel** | `server/terminal-manager.ts` | `node-pty` sessions over the dedicated `/ws/terminal/:id` socket, OSC shell-integration marks. See [`../terminal.md`](../terminal.md). |
|
|
272
|
-
| **Code explorer** | `server/code-explorer-router.ts`, `server/file-provenance.ts`, `server/file-summary-manager.ts` | A non-developer-friendly file tree + Monaco viewer with plain-language AI summaries and *touched-by-AI* provenance chips per ticket/job, plus opt-in in-app editing of existing files (overwrite-only via `PUT /file` — no create/rename; refuses binaries `415`, enforces a 2 MB cap `413`, `404` on a missing path, respects deny-list/`.gitignore`). |
|
|
273
|
-
| **Pipeline telemetry** | `server/telemetry-receiver.ts` + QueueManager OTEL injection | Opt-in OTLP/JSON signals to `POST /otlp/v1/{traces,metrics,logs}`; blobs compacted after 7 days; diagnostic ZIP export. |
|
|
274
|
-
| **Explore acceleration + Contract Refine** | `server/explore-cwd-manager.ts`, `server/contract-refine-runner.ts` | App-managed Explore spawn cwd for fast first-token; optional post-commit Contract Layer enrichment. Kill switches: `SPECRAILS_EXPLORE_CONTRACT_REFINE`, `SPECRAILS_EXPLORE_LEGACY_CWD`. |
|
|
275
|
-
| **Tickets / drafts** | `server/ticket-store.ts` | Spec tickets (incl. `draft` status) backing the Specs board and Save-as-Draft flow. |
|
|
271
|
+
| **Terminal panel** | `server/modules/terminals/runtime/terminal-manager.ts` | `node-pty` sessions over the dedicated `/ws/terminal/:id` socket, OSC shell-integration marks. See [`../terminal.md`](../terminal.md). |
|
|
272
|
+
| **Code explorer** | `server/modules/code/runtime/code-explorer-router.ts`, `server/modules/code/runtime/file-provenance.ts`, `server/modules/code/runtime/file-summary-manager.ts` | A non-developer-friendly file tree + Monaco viewer with plain-language AI summaries and *touched-by-AI* provenance chips per ticket/job, plus opt-in in-app editing of existing files (overwrite-only via `PUT /file` — no create/rename; refuses binaries `415`, enforces a 2 MB cap `413`, `404` on a missing path, respects deny-list/`.gitignore`). |
|
|
273
|
+
| **Pipeline telemetry** | `server/modules/accounting/runtime/telemetry-receiver.ts` + QueueManager OTEL injection | Opt-in OTLP/JSON signals to `POST /otlp/v1/{traces,metrics,logs}`; blobs compacted after 7 days; diagnostic ZIP export. |
|
|
274
|
+
| **Explore acceleration + Contract Refine** | `server/modules/conversations/runtime/explore-cwd-manager.ts`, `server/modules/specs/runtime/contract-refine-runner.ts` | App-managed Explore spawn cwd for fast first-token; optional post-commit Contract Layer enrichment. Kill switches: `SPECRAILS_EXPLORE_CONTRACT_REFINE`, `SPECRAILS_EXPLORE_LEGACY_CWD`. |
|
|
275
|
+
| **Tickets / drafts** | `server/modules/specs/runtime/ticket-store.ts` | Spec tickets (incl. `draft` status) backing the Specs board and Save-as-Draft flow. |
|
|
276
276
|
| **Jira integration** | `server/jira/*` (`jira-sync-manager`, `jira-client`, `jira-materializer`, `jira-status-resolver`, `jira-db`, `jira-credential-store`), `server/jira-router.ts` | Optional per-project sync that backs a project's specs with a Jira board (Cloud or Data Center). Desktop is the sync layer — specrails-core reads the materialized cache unchanged and stays read-only. Inbound polling + a durable outbox handle write-back; the encrypted token lives on-device. Routes under `/api/projects/:id/jira/*` (gated by `SPECRAILS_JIRA_SECTION`, 404 when off); project-scoped WS events `jira.synced`, `jira.sync_error`, `jira.auth_expired`, `jira.outbox_changed`, `jira.degraded`. See [`../jira-integration-plan.md`](../jira-integration-plan.md). |
|
|
277
277
|
| **Theme system** | `server/desktop-router.ts` (`GET/PATCH /api/theme`) | Five built-in themes (`dracula`, `aurora-light`, `obsidian-dark`, `matrix`, `specrails`), default `specrails`, persisted app-wide with an anti-FOUC inline script. |
|
|
278
278
|
|
|
@@ -8,10 +8,10 @@ The Playwright capture engine backs **Add Spec → From a website** (`BrowserCap
|
|
|
8
8
|
Chromium (headless, persistent shared context — browser-context-pool.ts)
|
|
9
9
|
│ CDP Page.startScreencast (JPEG frames) Playwright input API
|
|
10
10
|
▼ ▲
|
|
11
|
-
PlaywrightPageHandle (server/browser-playwright.ts) │
|
|
11
|
+
PlaywrightPageHandle (server/modules/browser/runtime/browser-playwright.ts) │
|
|
12
12
|
│ ScreencastFrame (raw JPEG Buffer) │ dispatchInput
|
|
13
13
|
▼ │
|
|
14
|
-
BrowserCaptureManager (server/browser-capture-manager.ts)
|
|
14
|
+
BrowserCaptureManager (server/modules/browser/runtime/browser-capture-manager.ts)
|
|
15
15
|
│ binary WS frames (dedicated /ws/browser/:id) │ JSON control {type:'input'|'probe'}
|
|
16
16
|
▼ │
|
|
17
17
|
useBrowserCaptureSession (client) ───────────────────┘
|
|
@@ -119,7 +119,7 @@ Pop-ups now work end-to-end — the design:
|
|
|
119
119
|
|
|
120
120
|
## Verification
|
|
121
121
|
|
|
122
|
-
Unit coverage: `server/browser-capture-manager.test.ts` (deferred nav, conflation, full popup lifecycle), `server/browser-playwright.test.ts` (`screencastParams`), `server/project-router.browser.test.ts` (popup-view route), `client/src/lib/browser-frame-pipeline.test.ts` (latest-wins/drop/dispose/stats), `client/src/lib/browser-capture.test.ts` (coalescer, popup helpers).
|
|
122
|
+
Unit coverage: `server/modules/browser/runtime/browser-capture-manager.test.ts` (deferred nav, conflation, full popup lifecycle), `server/modules/browser/runtime/browser-playwright.test.ts` (`screencastParams`), `server/project-router.browser.test.ts` (popup-view route), `client/src/features/browser/lib/browser-frame-pipeline.test.ts` (latest-wins/drop/dispose/stats), `client/src/features/browser/lib/browser-capture.test.ts` (coalescer, popup helpers).
|
|
123
123
|
|
|
124
124
|
`node scripts/smoke-browser-rendering.mjs` exercises the real exported Playwright
|
|
125
125
|
handle using generated pages and temporary profiles, with no Specrails DB or
|
|
@@ -40,12 +40,12 @@ to the Code explorer.
|
|
|
40
40
|
| `summary_model`, `summary_generated_at` | generation metadata |
|
|
41
41
|
|
|
42
42
|
Stats rows are written **inside `recordProvenanceForJob`'s transaction**
|
|
43
|
-
(`server/file-provenance.ts`), for every provenance row that has a collected
|
|
43
|
+
(`server/modules/code/runtime/file-provenance.ts`), for every provenance row that has a collected
|
|
44
44
|
patch. That means every producer — QueueManager jobs AND the loop seam — gets
|
|
45
45
|
stats with zero extra calls. The prepare is guarded (like the migration-23
|
|
46
46
|
`insertPatch`) so a pre-37 DB degrades cleanly.
|
|
47
47
|
|
|
48
|
-
## The loop-run seam (`server/file-story.ts`)
|
|
48
|
+
## The loop-run seam (`server/modules/code/runtime/file-story.ts`)
|
|
49
49
|
|
|
50
50
|
`recordLoopRunProvenance({ db, projectId, runId, ticketId, repoDir, snapshot,
|
|
51
51
|
broadcast })` is the single chokepoint that mirrors QueueManager's
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
The single fact that scopes the whole gap, verified directly in code:
|
|
8
8
|
|
|
9
|
-
`server/rails-router.ts:301` — `if (isLoopsEnabled() && loopId) → LoopRunManager (loop.run_*, no jobId); else → QueueManager (jobId, rail.job_*)`.
|
|
9
|
+
`server/modules/delivery/runtime/rails-router.ts:301` — `if (isLoopsEnabled() && loopId) → LoopRunManager (loop.run_*, no jobId); else → QueueManager (jobId, rail.job_*)`.
|
|
10
10
|
|
|
11
11
|
- **Phone-initiated launches** send bare `{mode}` with **no `loopId`** (`desktop_repository.dart:116-123`) → fall to the **`else` / QueueManager** path → real `jobId` → `rail.job_*` → **the v1 companion mirrors them correctly (view + log tail + completion push). NO regression.**
|
|
12
|
-
- **Desktop-initiated launches** now **always** send a `loopId`: the loop picker uses `effectiveLoopId = selectedLoopId || factoryIdForMode(mode)` (`client/src/lib/rail-loops.ts:43-44`) so even a plain "Implement" rail sends `loopId='factory:implement'`, and `doLaunchRail` always passes it (`client/src/pages/DashboardPage.tsx:824,869`) → **LoopRunManager** → `loop.run_*` (no `jobId`) → **dropped at the mobile boundary** (`mobile-ws.ts topicFor` default→null).
|
|
12
|
+
- **Desktop-initiated launches** now **always** send a `loopId`: the loop picker uses `effectiveLoopId = selectedLoopId || factoryIdForMode(mode)` (`client/src/features/rails/lib/rail-loops.ts:43-44`) so even a plain "Implement" rail sends `loopId='factory:implement'`, and `doLaunchRail` always passes it (`client/src/features/dashboard/pages/DashboardPage.tsx:824,869`) → **LoopRunManager** → `loop.run_*` (no `jobId`) → **dropped at the mobile boundary** (`mobile-ws.ts topicFor` default→null).
|
|
13
13
|
|
|
14
14
|
**Net:** the mirror gap is NOT in the phone's own launches — it is in **mirroring rails the user launches from the desktop** (the normal case), which now emit `loop.run_*` the boundary never forwards. So a connected phone shows desktop-launched loop rails as **idle, with no live progress and no completion notification.** The frozen wire is untouched (additive only). Everything below stands with this scoping.
|
|
15
15
|
|