specrails-desktop 2.54.0 → 2.55.1
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-CEWktcV8.js → ActivityFeedPage-DmJcQpNe.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-Bnu8aoF2.js → AgentBrowserCapture-NxBHrU-V.js} +1 -1
- package/client/dist/assets/{AgentModeAnalyticsPane-N0k6nlj0.js → AgentModeAnalyticsPane-CGAKTJfU.js} +2 -2
- package/client/dist/assets/{AgentModeCodePane-7s6TnZGe.js → AgentModeCodePane-DNSs5_oe.js} +2 -2
- package/client/dist/assets/{AgentModeJobsPane-Btsb5Sq4.js → AgentModeJobsPane-DLoVYDnG.js} +1 -1
- package/client/dist/assets/{AgentsPage-BXgiO5qZ.js → AgentsPage-CAzMn9Gg.js} +1 -1
- package/client/dist/assets/{AnalyticsPage-CO8-ON4i.js → AnalyticsPage-C06KT4Y0.js} +1 -1
- package/client/dist/assets/{CodePage-CMSInNsE.js → CodePage-aX1mxGyT.js} +1 -1
- package/client/dist/assets/{DesktopAnalyticsPage-1ekD8Gob.js → DesktopAnalyticsPage-BtscfiQD.js} +1 -1
- package/client/dist/assets/{DocsDialog-CZ1QztVB.js → DocsDialog-CNOcXhp-.js} +1 -1
- package/client/dist/assets/{DocsPage-DHdvuLeh.js → DocsPage-C2BugxaI.js} +1 -1
- package/client/dist/assets/{ExportDropdown-ClahJdDn.js → ExportDropdown-BVGKEgkd.js} +1 -1
- package/client/dist/assets/{InteractiveJobComposer-DDYgxV10.js → InteractiveJobComposer-CCncBqNu.js} +1 -1
- package/client/dist/assets/{JobDetailModal-DSsX48Vu.js → JobDetailModal-Cn_k3-RM.js} +1 -1
- package/client/dist/assets/{JobDetailPage-DbzshFhr.js → JobDetailPage-BogJFBsk.js} +1 -1
- package/client/dist/assets/{JobsPage-DY4qRt9_.js → JobsPage-DL4E8ZyU.js} +1 -1
- package/client/dist/assets/{LoopBuilderPage-DTqzBtuf.js → LoopBuilderPage-9L6URQLY.js} +1 -1
- package/client/dist/assets/{LoopPreviewModal-C-NbAvIZ.js → LoopPreviewModal-CAPqTIgL.js} +1 -1
- package/client/dist/assets/{LoopsPage-C-RjiAxo.js → LoopsPage-aU8dYw7L.js} +1 -1
- package/client/dist/assets/{MinimizedChatsContext-BGtEjWsc.js → MinimizedChatsContext-D3QzgV0B.js} +1 -1
- package/client/dist/assets/{PluginsPage-BUdxGBro.js → PluginsPage-D_tsW9B5.js} +1 -1
- package/client/dist/assets/{ProjectSettingsDialog-e7y_uZIz.js → ProjectSettingsDialog-_ZbNuspP.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-CG-Dv0El.js +4 -0
- package/client/dist/assets/{TemplatePreviewModal-DoeJuvcY.js → TemplatePreviewModal-C19H2b2o.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-Cn-T8bgL.js → index-BcligJ3-.js} +29 -29
- package/client/dist/assets/index-C51x61Bz.css +2 -0
- 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/ci-cd.md +4 -0
- 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 +15 -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/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/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 +1354 -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/mcp-admin-router.js +1 -1
- package/server/dist/mcp/mcp-server.js +1 -1
- package/server/dist/mcp/tools/jobs.js +1 -1
- package/server/dist/mcp/tools/rails.js +2 -2
- package/server/dist/mcp/tools/specs.js +2 -2
- package/server/dist/mcp/tools/types.js +3 -3
- package/server/dist/mobile/mobile-code.js +100 -0
- package/server/dist/mobile/mobile-gateway.js +1 -1
- package/server/dist/mobile/mobile-missions.js +2 -2
- package/server/dist/mobile/mobile-router.js +12 -6
- package/server/dist/{desktop-analytics.js → modules/accounting/runtime/desktop-analytics.js} +2 -2
- package/server/dist/{pricing.js → modules/accounting/runtime/pricing.js} +1 -1
- 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.js → modules/agent-runtime/runtime/agent-runtime-controls.js} +7 -7
- 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/{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} +36 -26
- package/server/dist/{agent-chat-router.js → modules/missions/runtime/agent-chat-router.js} +7 -6
- package/server/dist/{agent-context-resolver.js → modules/missions/runtime/agent-context-resolver.js} +8 -8
- 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} +17 -7
- 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} +1 -1
- 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/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-Bs_jaLbJ.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-controls-router.js → modules/agent-runtime/runtime/agent-runtime-controls-router.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-failure-briefing.js → modules/missions/runtime/agent-failure-briefing.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
|
+
}
|