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/cli/dist/args.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Constants
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.KNOWN_VERBS = exports.DEFAULT_PORT = void 0;
|
|
7
|
+
exports.parseArgs = parseArgs;
|
|
8
|
+
exports.DEFAULT_PORT = 4200;
|
|
9
|
+
exports.KNOWN_VERBS = new Set([
|
|
10
|
+
'implement',
|
|
11
|
+
'batch-implement',
|
|
12
|
+
'why',
|
|
13
|
+
'get-backlog-specs',
|
|
14
|
+
'auto-propose-backlog-specs',
|
|
15
|
+
'propose-spec',
|
|
16
|
+
'refactor-recommender',
|
|
17
|
+
'health-check',
|
|
18
|
+
'compat-check',
|
|
19
|
+
'enrich',
|
|
20
|
+
]);
|
|
21
|
+
function parseArgs(argv) {
|
|
22
|
+
// argv is process.argv.slice(2)
|
|
23
|
+
let port = exports.DEFAULT_PORT;
|
|
24
|
+
let projectOverride;
|
|
25
|
+
const args = [...argv];
|
|
26
|
+
// Extract --port <n> and --project <name|path> from any position
|
|
27
|
+
for (let i = 0; i < args.length; i++) {
|
|
28
|
+
if (args[i] === '--port' && i + 1 < args.length) {
|
|
29
|
+
const parsed = parseInt(args[i + 1], 10);
|
|
30
|
+
if (!isNaN(parsed)) {
|
|
31
|
+
port = parsed;
|
|
32
|
+
}
|
|
33
|
+
args.splice(i, 2);
|
|
34
|
+
i--;
|
|
35
|
+
}
|
|
36
|
+
else if (args[i] === '--project' && i + 1 < args.length) {
|
|
37
|
+
projectOverride = args[i + 1];
|
|
38
|
+
args.splice(i, 2);
|
|
39
|
+
i--;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (args[0] === '--version' || args[0] === '-v') {
|
|
43
|
+
return { mode: 'version' };
|
|
44
|
+
}
|
|
45
|
+
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
46
|
+
return { mode: 'help' };
|
|
47
|
+
}
|
|
48
|
+
if (args[0] === '--status') {
|
|
49
|
+
return { mode: 'status', port };
|
|
50
|
+
}
|
|
51
|
+
if (args[0] === '--jobs') {
|
|
52
|
+
return { mode: 'jobs', port };
|
|
53
|
+
}
|
|
54
|
+
if (args[0] === 'desktop') {
|
|
55
|
+
return { mode: 'desktop', subArgs: args.slice(1), port };
|
|
56
|
+
}
|
|
57
|
+
// Allow server-management subcommands directly without the 'desktop' prefix:
|
|
58
|
+
// specrails-desktop start → specrails-desktop desktop start
|
|
59
|
+
// specrails-desktop stop → specrails-desktop desktop stop
|
|
60
|
+
// specrails-desktop add → specrails-desktop desktop add
|
|
61
|
+
// etc.
|
|
62
|
+
const DESKTOP_SUBCOMMANDS = new Set(['start', 'stop', 'status', 'add', 'remove', 'list']);
|
|
63
|
+
if (DESKTOP_SUBCOMMANDS.has(args[0])) {
|
|
64
|
+
return { mode: 'desktop', subArgs: args, port };
|
|
65
|
+
}
|
|
66
|
+
const first = args[0];
|
|
67
|
+
// Slash-prefixed command: pass through unchanged
|
|
68
|
+
if (first.startsWith('/')) {
|
|
69
|
+
const resolved = args.join(' ');
|
|
70
|
+
return { mode: 'raw', resolved, port, projectOverride };
|
|
71
|
+
}
|
|
72
|
+
// Known verb: inject /specrails: prefix
|
|
73
|
+
if (exports.KNOWN_VERBS.has(first)) {
|
|
74
|
+
const resolved = `/specrails:${args.join(' ')}`;
|
|
75
|
+
return { mode: 'command', resolved, port, projectOverride };
|
|
76
|
+
}
|
|
77
|
+
// Unknown first token: treat as raw prompt
|
|
78
|
+
const resolved = args.join(' ');
|
|
79
|
+
return { mode: 'raw', resolved, port, projectOverride };
|
|
80
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HTTP_REQUEST_TIMEOUT_MS = exports.DETECTION_TIMEOUT_MS = void 0;
|
|
7
|
+
exports.detectWebManager = detectWebManager;
|
|
8
|
+
exports.loadDesktopToken = loadDesktopToken;
|
|
9
|
+
exports.requestTimeoutError = requestTimeoutError;
|
|
10
|
+
exports.httpGet = httpGet;
|
|
11
|
+
exports.httpPost = httpPost;
|
|
12
|
+
const http_1 = __importDefault(require("http"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
exports.DETECTION_TIMEOUT_MS = 500;
|
|
17
|
+
exports.HTTP_REQUEST_TIMEOUT_MS = 15_000;
|
|
18
|
+
function detectWebManager(port) {
|
|
19
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
const timer = setTimeout(() => {
|
|
22
|
+
req.destroy();
|
|
23
|
+
resolve({ running: false, baseUrl });
|
|
24
|
+
}, exports.DETECTION_TIMEOUT_MS);
|
|
25
|
+
const req = http_1.default.get(`${baseUrl}/api/health`, { timeout: exports.DETECTION_TIMEOUT_MS }, (res) => {
|
|
26
|
+
clearTimeout(timer);
|
|
27
|
+
res.resume(); // drain the response
|
|
28
|
+
if (res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 300) {
|
|
29
|
+
resolve({ running: true, baseUrl });
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
resolve({ running: false, baseUrl });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
req.on('error', () => {
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
resolve({ running: false, baseUrl });
|
|
38
|
+
});
|
|
39
|
+
req.on('timeout', () => {
|
|
40
|
+
req.destroy();
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
resolve({ running: false, baseUrl });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// HTTP helpers
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
function loadDesktopToken() {
|
|
50
|
+
const candidates = [
|
|
51
|
+
path_1.default.join(os_1.default.homedir(), '.specrails', 'desktop.token'),
|
|
52
|
+
// Legacy fallback: pre-rename installs keep the token at hub.token until the
|
|
53
|
+
// server migrates it on next startup. Compat only — do not extend.
|
|
54
|
+
path_1.default.join(os_1.default.homedir(), '.specrails', 'hub.token'),
|
|
55
|
+
];
|
|
56
|
+
for (const tokenPath of candidates) {
|
|
57
|
+
try {
|
|
58
|
+
const t = fs_1.default.readFileSync(tokenPath, 'utf-8').trim();
|
|
59
|
+
if (t.length >= 32)
|
|
60
|
+
return t;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// try next candidate
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
function requestTimeoutError(url, timeoutMs) {
|
|
69
|
+
return new Error(`Request to ${url} timed out after ${timeoutMs}ms`);
|
|
70
|
+
}
|
|
71
|
+
function httpGet(url, timeoutMs = exports.HTTP_REQUEST_TIMEOUT_MS) {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
const token = loadDesktopToken();
|
|
74
|
+
const parsed = new URL(url);
|
|
75
|
+
const headers = {};
|
|
76
|
+
if (token)
|
|
77
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
78
|
+
const options = {
|
|
79
|
+
hostname: parsed.hostname,
|
|
80
|
+
port: parsed.port,
|
|
81
|
+
path: parsed.pathname + parsed.search,
|
|
82
|
+
headers,
|
|
83
|
+
};
|
|
84
|
+
const req = http_1.default.get(options, (res) => {
|
|
85
|
+
let body = '';
|
|
86
|
+
res.on('data', (chunk) => { body += chunk; });
|
|
87
|
+
res.on('end', () => resolve({ status: res.statusCode ?? 0, body }));
|
|
88
|
+
});
|
|
89
|
+
req.setTimeout(timeoutMs, () => {
|
|
90
|
+
req.destroy(requestTimeoutError(url, timeoutMs));
|
|
91
|
+
});
|
|
92
|
+
req.on('error', reject);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function httpPost(url, payload, timeoutMs = exports.HTTP_REQUEST_TIMEOUT_MS) {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
const data = JSON.stringify(payload);
|
|
98
|
+
const urlObj = new URL(url);
|
|
99
|
+
const token = loadDesktopToken();
|
|
100
|
+
const headers = {
|
|
101
|
+
'Content-Type': 'application/json',
|
|
102
|
+
'Content-Length': Buffer.byteLength(data),
|
|
103
|
+
};
|
|
104
|
+
if (token)
|
|
105
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
106
|
+
const options = {
|
|
107
|
+
hostname: urlObj.hostname,
|
|
108
|
+
port: urlObj.port,
|
|
109
|
+
path: urlObj.pathname,
|
|
110
|
+
method: 'POST',
|
|
111
|
+
headers,
|
|
112
|
+
};
|
|
113
|
+
const req = http_1.default.request(options, (res) => {
|
|
114
|
+
let body = '';
|
|
115
|
+
res.on('data', (chunk) => { body += chunk; });
|
|
116
|
+
res.on('end', () => resolve({ status: res.statusCode ?? 0, body }));
|
|
117
|
+
});
|
|
118
|
+
req.setTimeout(timeoutMs, () => {
|
|
119
|
+
req.destroy(requestTimeoutError(url, timeoutMs));
|
|
120
|
+
});
|
|
121
|
+
req.on('error', reject);
|
|
122
|
+
req.write(data);
|
|
123
|
+
req.end();
|
|
124
|
+
});
|
|
125
|
+
}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DESKTOP_LOG_FILE = exports.DESKTOP_PID_FILE = void 0;
|
|
7
|
+
exports.isPortInUse = isPortInUse;
|
|
8
|
+
exports.readPid = readPid;
|
|
9
|
+
exports.isProcessRunning = isProcessRunning;
|
|
10
|
+
exports.desktopServerPath = desktopServerPath;
|
|
11
|
+
exports.desktopStart = desktopStart;
|
|
12
|
+
exports.desktopStop = desktopStop;
|
|
13
|
+
exports.desktopStatus = desktopStatus;
|
|
14
|
+
exports.desktopAdd = desktopAdd;
|
|
15
|
+
exports.desktopRemove = desktopRemove;
|
|
16
|
+
exports.desktopList = desktopList;
|
|
17
|
+
exports.handleDesktop = handleDesktop;
|
|
18
|
+
const http_1 = __importDefault(require("http"));
|
|
19
|
+
const net_1 = __importDefault(require("net"));
|
|
20
|
+
const path_1 = __importDefault(require("path"));
|
|
21
|
+
const os_1 = __importDefault(require("os"));
|
|
22
|
+
const win_spawn_1 = require("./win-spawn");
|
|
23
|
+
const fs_1 = __importDefault(require("fs"));
|
|
24
|
+
const output_1 = require("./output");
|
|
25
|
+
const desktop_client_1 = require("./desktop-client");
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Server-management subcommand group
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
exports.DESKTOP_PID_FILE = path_1.default.join(os_1.default.homedir(), '.specrails', 'manager.pid');
|
|
30
|
+
exports.DESKTOP_LOG_FILE = path_1.default.join(os_1.default.homedir(), '.specrails', 'desktop.log');
|
|
31
|
+
function isPortInUse(port) {
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
const srv = net_1.default.createServer();
|
|
34
|
+
srv.once('error', (err) => {
|
|
35
|
+
resolve(err.code === 'EADDRINUSE');
|
|
36
|
+
});
|
|
37
|
+
srv.once('listening', () => {
|
|
38
|
+
srv.close();
|
|
39
|
+
resolve(false);
|
|
40
|
+
});
|
|
41
|
+
srv.listen(port, '127.0.0.1');
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function readPid() {
|
|
45
|
+
try {
|
|
46
|
+
const raw = fs_1.default.readFileSync(exports.DESKTOP_PID_FILE, 'utf-8').trim();
|
|
47
|
+
const pid = parseInt(raw, 10);
|
|
48
|
+
return isNaN(pid) ? null : pid;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function isProcessRunning(pid) {
|
|
55
|
+
try {
|
|
56
|
+
process.kill(pid, 0);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function desktopServerPath() {
|
|
64
|
+
// __dirname differs by runtime:
|
|
65
|
+
// compiled (npm install): <root>/cli/dist/ → need ../../server/dist/index.js
|
|
66
|
+
// tsx dev: <root>/cli/ → need ../server/dist/index.js
|
|
67
|
+
// Try both, compiled path first.
|
|
68
|
+
const fromDist = path_1.default.resolve(__dirname, '..', '..', 'server', 'dist', 'index.js');
|
|
69
|
+
const fromSrc = path_1.default.resolve(__dirname, '..', 'server', 'dist', 'index.js');
|
|
70
|
+
const devTs = path_1.default.resolve(__dirname, '..', 'server', 'index.ts');
|
|
71
|
+
if (fs_1.default.existsSync(fromDist))
|
|
72
|
+
return fromDist;
|
|
73
|
+
if (fs_1.default.existsSync(fromSrc))
|
|
74
|
+
return fromSrc;
|
|
75
|
+
if (fs_1.default.existsSync(devTs))
|
|
76
|
+
return devTs;
|
|
77
|
+
return fromDist;
|
|
78
|
+
}
|
|
79
|
+
async function desktopStart(port) {
|
|
80
|
+
const pid = readPid();
|
|
81
|
+
if (pid !== null && isProcessRunning(pid)) {
|
|
82
|
+
(0, output_1.cliLog)(`server already running (pid ${pid}) on port ${port}`);
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
// Check if port is already in use by another process
|
|
86
|
+
const portBusy = await isPortInUse(port);
|
|
87
|
+
if (portBusy) {
|
|
88
|
+
(0, output_1.cliError)(`port ${port} is already in use by another process`);
|
|
89
|
+
(0, output_1.cliError)(`if a previous server is stale, run: specrails-desktop stop`);
|
|
90
|
+
(0, output_1.cliError)(`or use a different port: specrails-desktop --port <port> start`);
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
const serverPath = desktopServerPath();
|
|
94
|
+
const isTs = serverPath.endsWith('.ts');
|
|
95
|
+
const args = isTs
|
|
96
|
+
? ['tsx', serverPath, '--port', String(port)]
|
|
97
|
+
: ['node', serverPath, '--port', String(port)];
|
|
98
|
+
// Ensure log dir exists and open log file for server output
|
|
99
|
+
try {
|
|
100
|
+
fs_1.default.mkdirSync(path_1.default.dirname(exports.DESKTOP_LOG_FILE), { recursive: true });
|
|
101
|
+
}
|
|
102
|
+
catch { /* ignore */ }
|
|
103
|
+
let logFd;
|
|
104
|
+
try {
|
|
105
|
+
logFd = fs_1.default.openSync(exports.DESKTOP_LOG_FILE, 'a');
|
|
106
|
+
}
|
|
107
|
+
catch { /* ignore — fall back to silent */ }
|
|
108
|
+
const stdio = [
|
|
109
|
+
'ignore',
|
|
110
|
+
logFd ?? 'ignore',
|
|
111
|
+
logFd ?? 'ignore',
|
|
112
|
+
];
|
|
113
|
+
// spawnCli so a dev `tsx`(.cmd) launcher resolves on Windows and the env is
|
|
114
|
+
// SystemRoot-backfilled; for the packaged `node` path cross-spawn spawns the
|
|
115
|
+
// .exe directly (no cmd.exe wrapper), keeping `detached` clean.
|
|
116
|
+
const child = (0, win_spawn_1.spawnCli)(args[0], args.slice(1), {
|
|
117
|
+
detached: true,
|
|
118
|
+
stdio,
|
|
119
|
+
env: { ...process.env },
|
|
120
|
+
});
|
|
121
|
+
if (logFd !== undefined) {
|
|
122
|
+
try {
|
|
123
|
+
fs_1.default.closeSync(logFd);
|
|
124
|
+
}
|
|
125
|
+
catch { /* ignore */ }
|
|
126
|
+
}
|
|
127
|
+
child.unref();
|
|
128
|
+
// Poll until the server is ready (up to 15 seconds, checking every 300ms)
|
|
129
|
+
const pollTimeoutMs = 15000;
|
|
130
|
+
const pollIntervalMs = 300;
|
|
131
|
+
const startPoll = Date.now();
|
|
132
|
+
while (Date.now() - startPoll < pollTimeoutMs) {
|
|
133
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
134
|
+
const detection = await (0, desktop_client_1.detectWebManager)(port);
|
|
135
|
+
if (detection.running) {
|
|
136
|
+
(0, output_1.cliLog)(`server started on http://127.0.0.1:${port}`);
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
(0, output_1.cliError)(`server failed to start — logs: ${exports.DESKTOP_LOG_FILE}`);
|
|
141
|
+
return 1;
|
|
142
|
+
}
|
|
143
|
+
async function desktopStop() {
|
|
144
|
+
const pid = readPid();
|
|
145
|
+
if (pid === null) {
|
|
146
|
+
(0, output_1.cliLog)('server is not running (no pid file)');
|
|
147
|
+
return 0;
|
|
148
|
+
}
|
|
149
|
+
if (!isProcessRunning(pid)) {
|
|
150
|
+
(0, output_1.cliLog)('server is not running (stale pid file)');
|
|
151
|
+
try {
|
|
152
|
+
fs_1.default.unlinkSync(exports.DESKTOP_PID_FILE);
|
|
153
|
+
}
|
|
154
|
+
catch { /* ignore */ }
|
|
155
|
+
return 0;
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
process.kill(pid, 'SIGTERM');
|
|
159
|
+
(0, output_1.cliLog)(`server stopped (pid ${pid})`);
|
|
160
|
+
return 0;
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
(0, output_1.cliError)(`failed to stop server: ${err.message}`);
|
|
164
|
+
return 1;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function desktopStatus(port) {
|
|
168
|
+
const pid = readPid();
|
|
169
|
+
const detection = await (0, desktop_client_1.detectWebManager)(port);
|
|
170
|
+
if (!detection.running) {
|
|
171
|
+
process.stdout.write(`server: not running\n`);
|
|
172
|
+
return 1;
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
const res = await (0, desktop_client_1.httpGet)(`${detection.baseUrl}/api/state`);
|
|
176
|
+
const state = JSON.parse(res.body);
|
|
177
|
+
process.stdout.write(`server: running (pid ${pid ?? '?'}) on ${detection.baseUrl}\n`);
|
|
178
|
+
process.stdout.write(`projects: ${state.projectCount ?? 0}\n`);
|
|
179
|
+
if (state.projects) {
|
|
180
|
+
for (const p of state.projects) {
|
|
181
|
+
process.stdout.write(` - ${p.name}\n`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return 0;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
process.stdout.write(`server: running on ${detection.baseUrl}\n`);
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function desktopAdd(projectPath, port) {
|
|
192
|
+
const detection = await (0, desktop_client_1.detectWebManager)(port);
|
|
193
|
+
if (!detection.running) {
|
|
194
|
+
(0, output_1.cliError)('server is not running. Start it first with: specrails-desktop start');
|
|
195
|
+
return 1;
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
const res = await (0, desktop_client_1.httpPost)(`${detection.baseUrl}/api/projects`, {
|
|
199
|
+
path: path_1.default.resolve(projectPath),
|
|
200
|
+
});
|
|
201
|
+
if (res.status === 201) {
|
|
202
|
+
const data = JSON.parse(res.body);
|
|
203
|
+
(0, output_1.cliLog)(`added project: ${data.project?.name ?? projectPath}`);
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
else if (res.status === 409) {
|
|
207
|
+
(0, output_1.cliLog)('project already registered');
|
|
208
|
+
return 0;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
let errMsg = `HTTP ${res.status}`;
|
|
212
|
+
try {
|
|
213
|
+
errMsg = JSON.parse(res.body).error ?? errMsg;
|
|
214
|
+
}
|
|
215
|
+
catch { /* use default */ }
|
|
216
|
+
(0, output_1.cliError)(`failed to add project: ${errMsg}`);
|
|
217
|
+
return 1;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
(0, output_1.cliError)(`failed to connect to server: ${err.message}`);
|
|
222
|
+
return 1;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async function desktopRemove(projectId, port) {
|
|
226
|
+
const detection = await (0, desktop_client_1.detectWebManager)(port);
|
|
227
|
+
if (!detection.running) {
|
|
228
|
+
(0, output_1.cliError)('server is not running');
|
|
229
|
+
return 1;
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
const deleteRes = await new Promise((resolve, reject) => {
|
|
233
|
+
const urlObj = new URL(`${detection.baseUrl}/api/projects/${projectId}`);
|
|
234
|
+
const token = (0, desktop_client_1.loadDesktopToken)();
|
|
235
|
+
const headers = {};
|
|
236
|
+
if (token)
|
|
237
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
238
|
+
const options = {
|
|
239
|
+
hostname: urlObj.hostname,
|
|
240
|
+
port: urlObj.port,
|
|
241
|
+
path: urlObj.pathname,
|
|
242
|
+
method: 'DELETE',
|
|
243
|
+
headers,
|
|
244
|
+
};
|
|
245
|
+
const req = http_1.default.request(options, (res) => {
|
|
246
|
+
let body = '';
|
|
247
|
+
res.on('data', (chunk) => { body += chunk; });
|
|
248
|
+
res.on('end', () => resolve({ status: res.statusCode ?? 0, body }));
|
|
249
|
+
});
|
|
250
|
+
req.on('error', reject);
|
|
251
|
+
req.end();
|
|
252
|
+
});
|
|
253
|
+
if (deleteRes.status === 200) {
|
|
254
|
+
(0, output_1.cliLog)(`project removed`);
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
(0, output_1.cliError)(`failed to remove project: HTTP ${deleteRes.status}`);
|
|
259
|
+
return 1;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
(0, output_1.cliError)(`failed to connect to server: ${err.message}`);
|
|
264
|
+
return 1;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async function desktopList(port) {
|
|
268
|
+
const detection = await (0, desktop_client_1.detectWebManager)(port);
|
|
269
|
+
if (!detection.running) {
|
|
270
|
+
(0, output_1.cliError)('server is not running');
|
|
271
|
+
return 1;
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
const res = await (0, desktop_client_1.httpGet)(`${detection.baseUrl}/api/projects`);
|
|
275
|
+
const data = JSON.parse(res.body);
|
|
276
|
+
if (!data.projects || data.projects.length === 0) {
|
|
277
|
+
(0, output_1.cliLog)('no projects registered');
|
|
278
|
+
return 0;
|
|
279
|
+
}
|
|
280
|
+
const idW = 36;
|
|
281
|
+
const nameW = 24;
|
|
282
|
+
process.stdout.write(`${(0, output_1.bold)('ID'.padEnd(idW))} ${(0, output_1.bold)('NAME'.padEnd(nameW))} ${(0, output_1.bold)('PATH')}\n`);
|
|
283
|
+
for (const p of data.projects) {
|
|
284
|
+
process.stdout.write(`${p.id.padEnd(idW)} ${p.name.padEnd(nameW)} ${p.path}\n`);
|
|
285
|
+
}
|
|
286
|
+
return 0;
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
(0, output_1.cliError)(`failed to fetch projects: ${err.message}`);
|
|
290
|
+
return 1;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
async function handleDesktop(subArgs, port) {
|
|
294
|
+
const sub = subArgs[0];
|
|
295
|
+
if (!sub || sub === 'help' || sub === '--help' || sub === '-h') {
|
|
296
|
+
process.stdout.write(`
|
|
297
|
+
${(0, output_1.bold)('specrails-desktop')} — server management
|
|
298
|
+
|
|
299
|
+
${(0, output_1.bold)('Usage:')}
|
|
300
|
+
specrails-desktop start Start the Specrails server
|
|
301
|
+
specrails-desktop stop Stop the Specrails server
|
|
302
|
+
specrails-desktop status Show server status and registered projects
|
|
303
|
+
specrails-desktop add <path> Register a project by path
|
|
304
|
+
specrails-desktop remove <id> Unregister a project by ID
|
|
305
|
+
specrails-desktop list List all registered projects
|
|
306
|
+
`.trimStart());
|
|
307
|
+
return 0;
|
|
308
|
+
}
|
|
309
|
+
if (sub === 'start') {
|
|
310
|
+
return desktopStart(port);
|
|
311
|
+
}
|
|
312
|
+
if (sub === 'stop') {
|
|
313
|
+
return desktopStop();
|
|
314
|
+
}
|
|
315
|
+
if (sub === 'status') {
|
|
316
|
+
return desktopStatus(port);
|
|
317
|
+
}
|
|
318
|
+
if (sub === 'add') {
|
|
319
|
+
const projectPath = subArgs[1];
|
|
320
|
+
if (!projectPath) {
|
|
321
|
+
(0, output_1.cliError)('usage: specrails-desktop add <path>');
|
|
322
|
+
return 1;
|
|
323
|
+
}
|
|
324
|
+
return desktopAdd(projectPath, port);
|
|
325
|
+
}
|
|
326
|
+
if (sub === 'remove') {
|
|
327
|
+
const projectId = subArgs[1];
|
|
328
|
+
if (!projectId) {
|
|
329
|
+
(0, output_1.cliError)('usage: specrails-desktop remove <id>');
|
|
330
|
+
return 1;
|
|
331
|
+
}
|
|
332
|
+
return desktopRemove(projectId, port);
|
|
333
|
+
}
|
|
334
|
+
if (sub === 'list') {
|
|
335
|
+
return desktopList(port);
|
|
336
|
+
}
|
|
337
|
+
(0, output_1.cliError)(`unknown subcommand: ${sub}`);
|
|
338
|
+
return 1;
|
|
339
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Duration formatting
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatDuration = formatDuration;
|
|
7
|
+
exports.formatTokens = formatTokens;
|
|
8
|
+
exports.formatJobDuration = formatJobDuration;
|
|
9
|
+
exports.formatJobStarted = formatJobStarted;
|
|
10
|
+
function formatDuration(ms) {
|
|
11
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
12
|
+
if (totalSeconds < 60) {
|
|
13
|
+
return `${totalSeconds}s`;
|
|
14
|
+
}
|
|
15
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
16
|
+
const seconds = totalSeconds % 60;
|
|
17
|
+
return `${minutes}m ${seconds}s`;
|
|
18
|
+
}
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Token formatting
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
function formatTokens(n) {
|
|
23
|
+
return new Intl.NumberFormat('en-US', { useGrouping: true })
|
|
24
|
+
.format(n)
|
|
25
|
+
.replace(/,/g, ' ');
|
|
26
|
+
}
|
|
27
|
+
function formatJobDuration(ms) {
|
|
28
|
+
if (ms == null)
|
|
29
|
+
return '-';
|
|
30
|
+
return formatDuration(ms);
|
|
31
|
+
}
|
|
32
|
+
function formatJobStarted(isoStr) {
|
|
33
|
+
try {
|
|
34
|
+
const d = new Date(isoStr);
|
|
35
|
+
const year = d.getFullYear();
|
|
36
|
+
const month = String(d.getMonth() + 1).padStart(2, '0');
|
|
37
|
+
const day = String(d.getDate()).padStart(2, '0');
|
|
38
|
+
const hour = String(d.getHours()).padStart(2, '0');
|
|
39
|
+
const min = String(d.getMinutes()).padStart(2, '0');
|
|
40
|
+
return `${year}-${month}-${day} ${hour}:${min}`;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return isoStr.slice(0, 16);
|
|
44
|
+
}
|
|
45
|
+
}
|
package/cli/dist/help.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getVersion = getVersion;
|
|
7
|
+
exports.printVersion = printVersion;
|
|
8
|
+
exports.printHelp = printHelp;
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const output_1 = require("./output");
|
|
12
|
+
const args_1 = require("./args");
|
|
13
|
+
function getVersion() {
|
|
14
|
+
for (const rel of ['../package.json', '../../package.json']) {
|
|
15
|
+
try {
|
|
16
|
+
const pkgPath = path_1.default.join(__dirname, rel);
|
|
17
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf8'));
|
|
18
|
+
if (typeof pkg.version === 'string')
|
|
19
|
+
return pkg.version;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// try next
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return 'unknown';
|
|
26
|
+
}
|
|
27
|
+
function printVersion() {
|
|
28
|
+
process.stdout.write(`specrails-desktop v${getVersion()}\n`);
|
|
29
|
+
}
|
|
30
|
+
function printHelp() {
|
|
31
|
+
const version = getVersion();
|
|
32
|
+
process.stdout.write(`
|
|
33
|
+
${(0, output_1.bold)(`specrails-desktop v${version}`)} — specrails CLI bridge
|
|
34
|
+
|
|
35
|
+
${(0, output_1.bold)('Project Required:')}
|
|
36
|
+
Every command runs in the context of a project registered for the current
|
|
37
|
+
directory. Register your project once before running any commands:
|
|
38
|
+
|
|
39
|
+
${(0, output_1.dim)('# Register your project (run once per project):')}
|
|
40
|
+
specrails-desktop add .
|
|
41
|
+
|
|
42
|
+
${(0, output_1.dim)('# Then run commands from that directory:')}
|
|
43
|
+
specrails-desktop implement #42
|
|
44
|
+
|
|
45
|
+
${(0, output_1.bold)('Usage:')}
|
|
46
|
+
specrails-desktop implement #42 Run a known specrails verb (prepends /specrails:)
|
|
47
|
+
specrails-desktop batch-implement #40 #41 Batch implementation across issues
|
|
48
|
+
specrails-desktop why Explain recent changes
|
|
49
|
+
specrails-desktop get-backlog-specs View prioritized spec backlog
|
|
50
|
+
specrails-desktop auto-propose-backlog-specs Generate new spec ideas
|
|
51
|
+
specrails-desktop propose-spec Explore an idea and produce a spec
|
|
52
|
+
specrails-desktop refactor-recommender Find refactoring opportunities
|
|
53
|
+
specrails-desktop health-check Run codebase health check
|
|
54
|
+
specrails-desktop compat-check Check for breaking API changes
|
|
55
|
+
specrails-desktop "any raw prompt" Pass a raw prompt directly to claude
|
|
56
|
+
specrails-desktop --status Print manager status and exit
|
|
57
|
+
specrails-desktop --jobs Print recent job history and exit
|
|
58
|
+
specrails-desktop start|stop|add|remove|list Manage the server
|
|
59
|
+
specrails-desktop --project <name|path> Override project (default: current directory)
|
|
60
|
+
specrails-desktop --port <n> Override default port (${args_1.DEFAULT_PORT})
|
|
61
|
+
specrails-desktop --version, -v Print version and exit
|
|
62
|
+
specrails-desktop --help, -h Show this help text
|
|
63
|
+
|
|
64
|
+
${(0, output_1.bold)('Execution paths:')}
|
|
65
|
+
Manager running → POST /api/spawn + stream logs via WebSocket
|
|
66
|
+
Manager not running → spawn claude directly with stream-json output
|
|
67
|
+
`.trimStart());
|
|
68
|
+
}
|