@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.97ef11e3
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/README.md +10 -8
- package/dist/cli.js +5 -1
- package/dist/headless-events.d.ts +2 -1
- package/dist/headless-events.js +11 -3
- package/dist/headless-milestone-readiness.d.ts +29 -0
- package/dist/headless-milestone-readiness.js +161 -0
- package/dist/headless.js +27 -3
- package/dist/print-mode-exit.d.ts +12 -0
- package/dist/print-mode-exit.js +14 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +18 -49
- package/dist/resources/extensions/browser-tools/capture.js +2 -77
- package/dist/resources/extensions/browser-tools/screenshot-constraints.js +83 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -2
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +30 -2
- package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
- package/dist/resources/extensions/gsd/auto/loop.js +24 -4
- package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
- package/dist/resources/extensions/gsd/auto/unit-phase.js +37 -5
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +16 -10
- package/dist/resources/extensions/gsd/auto-dispatch.js +76 -19
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +137 -22
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -5
- package/dist/resources/extensions/gsd/auto-start.js +29 -9
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +40 -0
- package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
- package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +20 -6
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
- package/dist/resources/extensions/gsd/command-feedback.js +16 -12
- package/dist/resources/extensions/gsd/commands-verdict.js +10 -9
- package/dist/resources/extensions/gsd/compat/compat-marker.js +98 -6
- package/dist/resources/extensions/gsd/constants.js +12 -13
- package/dist/resources/extensions/gsd/context-masker.js +97 -21
- package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
- package/dist/resources/extensions/gsd/db/engine.js +56 -18
- package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
- package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
- package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
- package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +26 -4
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +24 -8
- package/dist/resources/extensions/gsd/error-classifier.js +12 -2
- package/dist/resources/extensions/gsd/exec-sandbox.js +1 -0
- package/dist/resources/extensions/gsd/flat-phase-migration.js +168 -21
- package/dist/resources/extensions/gsd/git-service.js +19 -7
- package/dist/resources/extensions/gsd/gsd-db.js +262 -76
- package/dist/resources/extensions/gsd/guided-flow.js +40 -15
- package/dist/resources/extensions/gsd/markdown-renderer.js +20 -22
- package/dist/resources/extensions/gsd/md-importer.js +107 -20
- package/dist/resources/extensions/gsd/migrate/command.js +19 -162
- package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
- package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
- package/dist/resources/extensions/gsd/migrate/planning-writer.js +12 -17
- package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
- package/dist/resources/extensions/gsd/model-router.js +11 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
- package/dist/resources/extensions/gsd/paths.js +70 -16
- package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
- package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
- package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
- package/dist/resources/extensions/gsd/preferences-types.js +5 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
- package/dist/resources/extensions/gsd/preferences.js +17 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
- package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
- package/dist/resources/extensions/gsd/skill-activation.js +17 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +125 -15
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +17 -4
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +5 -2
- package/dist/resources/extensions/gsd/stop-notice.js +24 -1
- package/dist/resources/extensions/gsd/sync-lock.js +13 -7
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
- package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
- package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
- package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
- package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
- package/dist/resources/extensions/gsd/unit-registry.js +4 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
- package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
- package/dist/resources/extensions/gsd/workspace.js +2 -1
- package/dist/resources/extensions/gsd/worktree-state-projection.js +26 -18
- package/dist/resources/extensions/mac-tools/index.js +31 -9
- package/dist/resources/extensions/shared/interview-ui.js +43 -6
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
- package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
- package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/package.json +0 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.js +31 -3
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +13 -10
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +14 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/cloud-config.d.ts +1 -1
- package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-config.js +5 -1
- package/packages/daemon/dist/cloud-config.js.map +1 -1
- package/packages/daemon/dist/cloud-config.test.js +51 -1
- package/packages/daemon/dist/cloud-config.test.js.map +1 -1
- package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
- package/packages/daemon/dist/local-tool-executor.js +2 -0
- package/packages/daemon/dist/local-tool-executor.js.map +1 -1
- package/packages/daemon/package.json +6 -6
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
- package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.js +1 -0
- package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/gsd-cloud/README.md +9 -3
- package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/background-cli.test.js +248 -0
- package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cli.d.ts +5 -0
- package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cli.js +266 -0
- package/packages/gsd-cloud/dist/cli.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
- package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.js +237 -0
- package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
- package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts +33 -0
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.js +260 -0
- package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
- package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-token.js +37 -0
- package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
- package/packages/gsd-cloud/dist/config.d.ts +17 -0
- package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/config.js +146 -0
- package/packages/gsd-cloud/dist/config.js.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
- package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.js +128 -0
- package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
- package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
- package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/executor.js +11 -0
- package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
- package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/index.js +29 -0
- package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
- package/packages/gsd-cloud/dist/index.d.ts +7 -0
- package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/index.js +8 -0
- package/packages/gsd-cloud/dist/index.js.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
- package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
- package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
- package/packages/gsd-cloud/dist/logger.d.ts +25 -0
- package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/logger.js +72 -0
- package/packages/gsd-cloud/dist/logger.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.d.ts +27 -0
- package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.js +272 -0
- package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.test.js +97 -0
- package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
- package/packages/gsd-cloud/dist/types.d.ts +51 -0
- package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/types.js +9 -0
- package/packages/gsd-cloud/dist/types.js.map +1 -0
- package/packages/gsd-cloud/package.json +3 -3
- package/packages/mcp-server/README.md +15 -2
- package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
- package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
- package/packages/mcp-server/dist/cli-runner.js +119 -33
- package/packages/mcp-server/dist/cli-runner.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +5 -5
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +64 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +136 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +124 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +25 -1
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +103 -0
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +18 -49
- package/src/resources/extensions/browser-tools/capture.ts +2 -86
- package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
- package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
- package/src/resources/extensions/gsd/auto/loop.ts +48 -4
- package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
- package/src/resources/extensions/gsd/auto/unit-phase.ts +41 -5
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
- package/src/resources/extensions/gsd/auto-dispatch.ts +87 -19
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +156 -20
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +12 -7
- package/src/resources/extensions/gsd/auto-start.ts +31 -8
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +56 -0
- package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
- package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +25 -8
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -12
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
- package/src/resources/extensions/gsd/command-feedback.ts +19 -12
- package/src/resources/extensions/gsd/commands-verdict.ts +16 -9
- package/src/resources/extensions/gsd/compat/compat-marker.ts +119 -8
- package/src/resources/extensions/gsd/constants.ts +14 -13
- package/src/resources/extensions/gsd/context-masker.ts +98 -2
- package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
- package/src/resources/extensions/gsd/db/engine.ts +58 -19
- package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
- package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
- package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
- package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +26 -4
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +30 -7
- package/src/resources/extensions/gsd/error-classifier.ts +13 -2
- package/src/resources/extensions/gsd/exec-sandbox.ts +1 -0
- package/src/resources/extensions/gsd/flat-phase-migration.ts +174 -19
- package/src/resources/extensions/gsd/git-service.ts +19 -6
- package/src/resources/extensions/gsd/gsd-db.ts +340 -85
- package/src/resources/extensions/gsd/guided-flow.ts +50 -14
- package/src/resources/extensions/gsd/markdown-renderer.ts +28 -30
- package/src/resources/extensions/gsd/md-importer.ts +114 -16
- package/src/resources/extensions/gsd/migrate/command.ts +21 -227
- package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
- package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
- package/src/resources/extensions/gsd/migrate/planning-writer.ts +12 -20
- package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
- package/src/resources/extensions/gsd/model-router.ts +12 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
- package/src/resources/extensions/gsd/paths.ts +77 -16
- package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
- package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
- package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
- package/src/resources/extensions/gsd/preferences.ts +25 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
- package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
- package/src/resources/extensions/gsd/skill-activation.ts +17 -3
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +162 -15
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +20 -4
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +4 -2
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
- package/src/resources/extensions/gsd/stop-notice.ts +29 -1
- package/src/resources/extensions/gsd/sync-lock.ts +14 -6
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +264 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
- package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +362 -1
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
- package/src/resources/extensions/gsd/tests/db-engine-cjs-compat.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -0
- package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
- package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
- package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
- package/src/resources/extensions/gsd/tests/planning-writer.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
- package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
- package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
- package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
- package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
- package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
- package/src/resources/extensions/gsd/types.ts +11 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
- package/src/resources/extensions/gsd/unit-registry.ts +4 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
- package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
- package/src/resources/extensions/gsd/workspace.ts +2 -1
- package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -24
- package/src/resources/extensions/mac-tools/index.ts +52 -9
- package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
- package/src/resources/extensions/shared/interview-ui.ts +47 -8
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +29 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
- package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
- /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → DXD9fZPnqtjZSlT5xdC3v}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → DXD9fZPnqtjZSlT5xdC3v}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { handleCloudCommand, formatUsage } from "./cli.js";
|
|
2
|
+
export { injectDefaultGateway, DEFAULT_GATEWAY } from "./inject-gateway.js";
|
|
3
|
+
export { CloudRuntime } from "./cloud-runtime.js";
|
|
4
|
+
export { runDeviceFlow } from "./device-flow.js";
|
|
5
|
+
export { selectExecutor, GsdPiExecutor, type Executor, type AdvertisedProject, type ExecutorKind, type SelectExecutorOptions, } from "./executors/index.js";
|
|
6
|
+
export type { DaemonConfig, LogLevel, LogEntry } from "./types.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EACL,cAAc,EACd,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Project/App: Open GSD
|
|
2
|
+
// File Purpose: Public entry for @opengsd/gsd-cloud — the standalone cloud agent.
|
|
3
|
+
export { handleCloudCommand, formatUsage } from "./cli.js";
|
|
4
|
+
export { injectDefaultGateway, DEFAULT_GATEWAY } from "./inject-gateway.js";
|
|
5
|
+
export { CloudRuntime } from "./cloud-runtime.js";
|
|
6
|
+
export { runDeviceFlow } from "./device-flow.js";
|
|
7
|
+
export { selectExecutor, GsdPiExecutor, } from "./executors/index.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,kFAAkF;AAElF,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EACL,cAAc,EACd,aAAa,GAKd,MAAM,sBAAsB,CAAC","sourcesContent":["// Project/App: Open GSD\n// File Purpose: Public entry for @opengsd/gsd-cloud — the standalone cloud agent.\n\nexport { handleCloudCommand, formatUsage } from \"./cli.js\";\nexport { injectDefaultGateway, DEFAULT_GATEWAY } from \"./inject-gateway.js\";\nexport { CloudRuntime } from \"./cloud-runtime.js\";\nexport { runDeviceFlow } from \"./device-flow.js\";\nexport {\n selectExecutor,\n GsdPiExecutor,\n type Executor,\n type AdvertisedProject,\n type ExecutorKind,\n type SelectExecutorOptions,\n} from \"./executors/index.js\";\nexport type { DaemonConfig, LogLevel, LogEntry } from \"./types.js\";\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The public GSD Cloud gateway. This default lives ONLY in @opengsd/gsd-cloud
|
|
3
|
+
* (D-01): the SaaS-branded wrapper is the one place the cloud.opengsd.net URL is
|
|
4
|
+
* intended to appear. The generic @opengsd/daemon requires --gateway explicitly.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_GATEWAY = "https://cloud.opengsd.net";
|
|
7
|
+
/**
|
|
8
|
+
* Insert `--gateway https://cloud.opengsd.net` for the `login` and `pair`
|
|
9
|
+
* commands when the caller has not supplied their own `--gateway`. Any other
|
|
10
|
+
* command (status/connect/disconnect) is returned unchanged, as is an explicit
|
|
11
|
+
* `--gateway` (the caller-supplied flag always wins) and empty argv.
|
|
12
|
+
*
|
|
13
|
+
* Pure function — no process.argv side effects — so the contract is unit-testable.
|
|
14
|
+
*/
|
|
15
|
+
export declare function injectDefaultGateway(argv: string[]): string[];
|
|
16
|
+
//# sourceMappingURL=inject-gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-gateway.d.ts","sourceRoot":"","sources":["../src/inject-gateway.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,eAAe,8BAA8B,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAW7D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Project/App: Open GSD
|
|
2
|
+
// File Purpose: Default the cloud gateway for login/pair when the caller omits --gateway.
|
|
3
|
+
/**
|
|
4
|
+
* The public GSD Cloud gateway. This default lives ONLY in @opengsd/gsd-cloud
|
|
5
|
+
* (D-01): the SaaS-branded wrapper is the one place the cloud.opengsd.net URL is
|
|
6
|
+
* intended to appear. The generic @opengsd/daemon requires --gateway explicitly.
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_GATEWAY = "https://cloud.opengsd.net";
|
|
9
|
+
/**
|
|
10
|
+
* Insert `--gateway https://cloud.opengsd.net` for the `login` and `pair`
|
|
11
|
+
* commands when the caller has not supplied their own `--gateway`. Any other
|
|
12
|
+
* command (status/connect/disconnect) is returned unchanged, as is an explicit
|
|
13
|
+
* `--gateway` (the caller-supplied flag always wins) and empty argv.
|
|
14
|
+
*
|
|
15
|
+
* Pure function — no process.argv side effects — so the contract is unit-testable.
|
|
16
|
+
*/
|
|
17
|
+
export function injectDefaultGateway(argv) {
|
|
18
|
+
const command = argv[0];
|
|
19
|
+
const gatewayAwareCommand = command === "login" || command === "pair";
|
|
20
|
+
// Respect both flag forms `parseArgs` accepts: `--gateway <url>` and
|
|
21
|
+
// `--gateway=<url>`. Matching only the bare token let an explicit
|
|
22
|
+
// `--gateway=<url>` slip through and get overridden by the appended default.
|
|
23
|
+
const hasGateway = argv.some((arg) => arg === "--gateway" || arg.startsWith("--gateway="));
|
|
24
|
+
if (!gatewayAwareCommand || hasGateway) {
|
|
25
|
+
return argv;
|
|
26
|
+
}
|
|
27
|
+
return [...argv, "--gateway", DEFAULT_GATEWAY];
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=inject-gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-gateway.js","sourceRoot":"","sources":["../src/inject-gateway.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,0FAA0F;AAE1F;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,2BAA2B,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAc;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,mBAAmB,GAAG,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,MAAM,CAAC;IACtE,qEAAqE;IACrE,kEAAkE;IAClE,6EAA6E;IAC7E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,WAAW,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,mBAAmB,IAAI,UAAU,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;AACjD,CAAC","sourcesContent":["// Project/App: Open GSD\n// File Purpose: Default the cloud gateway for login/pair when the caller omits --gateway.\n\n/**\n * The public GSD Cloud gateway. This default lives ONLY in @opengsd/gsd-cloud\n * (D-01): the SaaS-branded wrapper is the one place the cloud.opengsd.net URL is\n * intended to appear. The generic @opengsd/daemon requires --gateway explicitly.\n */\nexport const DEFAULT_GATEWAY = \"https://cloud.opengsd.net\";\n\n/**\n * Insert `--gateway https://cloud.opengsd.net` for the `login` and `pair`\n * commands when the caller has not supplied their own `--gateway`. Any other\n * command (status/connect/disconnect) is returned unchanged, as is an explicit\n * `--gateway` (the caller-supplied flag always wins) and empty argv.\n *\n * Pure function — no process.argv side effects — so the contract is unit-testable.\n */\nexport function injectDefaultGateway(argv: string[]): string[] {\n const command = argv[0];\n const gatewayAwareCommand = command === \"login\" || command === \"pair\";\n // Respect both flag forms `parseArgs` accepts: `--gateway <url>` and\n // `--gateway=<url>`. Matching only the bare token let an explicit\n // `--gateway=<url>` slip through and get overridden by the appended default.\n const hasGateway = argv.some((arg) => arg === \"--gateway\" || arg.startsWith(\"--gateway=\"));\n if (!gatewayAwareCommand || hasGateway) {\n return argv;\n }\n return [...argv, \"--gateway\", DEFAULT_GATEWAY];\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-gateway.test.d.ts","sourceRoot":"","sources":["../src/inject-gateway.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Project/App: Open GSD
|
|
2
|
+
// File Purpose: Unit tests locking the default-gateway injection contract.
|
|
3
|
+
import { test } from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import { injectDefaultGateway, DEFAULT_GATEWAY } from "./inject-gateway.js";
|
|
6
|
+
test("Test 1: login without --gateway injects the default gateway", () => {
|
|
7
|
+
const out = injectDefaultGateway(["login"]);
|
|
8
|
+
assert.ok(out.includes("--gateway"), "expected --gateway flag");
|
|
9
|
+
assert.ok(out.includes(DEFAULT_GATEWAY), "expected default gateway value");
|
|
10
|
+
assert.equal(DEFAULT_GATEWAY, "https://cloud.opengsd.net");
|
|
11
|
+
const idx = out.indexOf("--gateway");
|
|
12
|
+
assert.equal(out[idx + 1], DEFAULT_GATEWAY, "value must follow the flag");
|
|
13
|
+
});
|
|
14
|
+
test("Test 2: login with explicit --gateway is returned unchanged", () => {
|
|
15
|
+
const argv = ["login", "--gateway", "https://other.example"];
|
|
16
|
+
const out = injectDefaultGateway(argv);
|
|
17
|
+
assert.deepEqual(out, argv);
|
|
18
|
+
assert.equal(out.filter((a) => a === "--gateway").length, 1, "no double gateway");
|
|
19
|
+
});
|
|
20
|
+
test("Test 3: pair without --gateway injects the default gateway", () => {
|
|
21
|
+
const out = injectDefaultGateway(["pair", "--code", "X"]);
|
|
22
|
+
assert.ok(out.includes("--gateway"), "expected --gateway flag");
|
|
23
|
+
assert.ok(out.includes(DEFAULT_GATEWAY), "expected default gateway value");
|
|
24
|
+
});
|
|
25
|
+
test("Test 4: status/connect/disconnect are returned unchanged", () => {
|
|
26
|
+
for (const cmd of ["status", "connect", "disconnect"]) {
|
|
27
|
+
const out = injectDefaultGateway([cmd]);
|
|
28
|
+
assert.deepEqual(out, [cmd], `${cmd} must not inject a gateway`);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
test("Test 5: empty argv (no command) is returned unchanged", () => {
|
|
32
|
+
assert.deepEqual(injectDefaultGateway([]), []);
|
|
33
|
+
});
|
|
34
|
+
test("Test 6: login with equals-form --gateway=... is returned unchanged", () => {
|
|
35
|
+
const argv = ["login", "--gateway=https://other.example"];
|
|
36
|
+
const out = injectDefaultGateway(argv);
|
|
37
|
+
assert.deepEqual(out, argv);
|
|
38
|
+
assert.ok(!out.includes(DEFAULT_GATEWAY), "default gateway must not be appended");
|
|
39
|
+
assert.equal(out.filter((a) => a === "--gateway" || a.startsWith("--gateway=")).length, 1, "no double gateway");
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=inject-gateway.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-gateway.test.js","sourceRoot":"","sources":["../src/inject-gateway.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Project/App: Open GSD\n// File Purpose: Unit tests locking the default-gateway injection contract.\nimport { test } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { injectDefaultGateway, DEFAULT_GATEWAY } from \"./inject-gateway.js\";\n\ntest(\"Test 1: login without --gateway injects the default gateway\", () => {\n const out = injectDefaultGateway([\"login\"]);\n assert.ok(out.includes(\"--gateway\"), \"expected --gateway flag\");\n assert.ok(out.includes(DEFAULT_GATEWAY), \"expected default gateway value\");\n assert.equal(DEFAULT_GATEWAY, \"https://cloud.opengsd.net\");\n const idx = out.indexOf(\"--gateway\");\n assert.equal(out[idx + 1], DEFAULT_GATEWAY, \"value must follow the flag\");\n});\n\ntest(\"Test 2: login with explicit --gateway is returned unchanged\", () => {\n const argv = [\"login\", \"--gateway\", \"https://other.example\"];\n const out = injectDefaultGateway(argv);\n assert.deepEqual(out, argv);\n assert.equal(out.filter((a) => a === \"--gateway\").length, 1, \"no double gateway\");\n});\n\ntest(\"Test 3: pair without --gateway injects the default gateway\", () => {\n const out = injectDefaultGateway([\"pair\", \"--code\", \"X\"]);\n assert.ok(out.includes(\"--gateway\"), \"expected --gateway flag\");\n assert.ok(out.includes(DEFAULT_GATEWAY), \"expected default gateway value\");\n});\n\ntest(\"Test 4: status/connect/disconnect are returned unchanged\", () => {\n for (const cmd of [\"status\", \"connect\", \"disconnect\"]) {\n const out = injectDefaultGateway([cmd]);\n assert.deepEqual(out, [cmd], `${cmd} must not inject a gateway`);\n }\n});\n\ntest(\"Test 5: empty argv (no command) is returned unchanged\", () => {\n assert.deepEqual(injectDefaultGateway([]), []);\n});\n\ntest(\"Test 6: login with equals-form --gateway=... is returned unchanged\", () => {\n const argv = [\"login\", \"--gateway=https://other.example\"];\n const out = injectDefaultGateway(argv);\n assert.deepEqual(out, argv);\n assert.ok(!out.includes(DEFAULT_GATEWAY), \"default gateway must not be appended\");\n assert.equal(\n out.filter((a) => a === \"--gateway\" || a.startsWith(\"--gateway=\")).length,\n 1,\n \"no double gateway\",\n );\n});\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { LogLevel } from './types.js';
|
|
2
|
+
export interface LoggerOptions {
|
|
3
|
+
filePath: string;
|
|
4
|
+
level: LogLevel;
|
|
5
|
+
verbose?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Structured JSON-lines file logger.
|
|
9
|
+
* Writes LogEntry objects one per line in append mode.
|
|
10
|
+
* The open write stream keeps the Node event loop alive (daemon keepalive).
|
|
11
|
+
*/
|
|
12
|
+
export declare class Logger {
|
|
13
|
+
private readonly stream;
|
|
14
|
+
private readonly level;
|
|
15
|
+
private readonly verbose;
|
|
16
|
+
constructor(opts: LoggerOptions);
|
|
17
|
+
debug(msg: string, data?: Record<string, unknown>): void;
|
|
18
|
+
info(msg: string, data?: Record<string, unknown>): void;
|
|
19
|
+
warn(msg: string, data?: Record<string, unknown>): void;
|
|
20
|
+
error(msg: string, data?: Record<string, unknown>): void;
|
|
21
|
+
/** End the write stream. Resolves when the stream is fully flushed. */
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
private write;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,YAAY,CAAC;AASrD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEtB,IAAI,EAAE,aAAa;IAe/B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIvD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIvD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIxD,uEAAuE;IACvE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,OAAO,CAAC,KAAK;CAmBd"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createWriteStream, mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
const LEVEL_ORDER = {
|
|
4
|
+
debug: 0,
|
|
5
|
+
info: 1,
|
|
6
|
+
warn: 2,
|
|
7
|
+
error: 3,
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Structured JSON-lines file logger.
|
|
11
|
+
* Writes LogEntry objects one per line in append mode.
|
|
12
|
+
* The open write stream keeps the Node event loop alive (daemon keepalive).
|
|
13
|
+
*/
|
|
14
|
+
export class Logger {
|
|
15
|
+
stream;
|
|
16
|
+
level;
|
|
17
|
+
verbose;
|
|
18
|
+
constructor(opts) {
|
|
19
|
+
// Ensure parent directory exists
|
|
20
|
+
const dir = dirname(opts.filePath);
|
|
21
|
+
try {
|
|
22
|
+
mkdirSync(dir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
26
|
+
throw new Error(`Cannot create log directory ${dir}: ${msg}`);
|
|
27
|
+
}
|
|
28
|
+
this.stream = createWriteStream(opts.filePath, { flags: 'a' });
|
|
29
|
+
this.level = LEVEL_ORDER[opts.level] ?? LEVEL_ORDER.info;
|
|
30
|
+
this.verbose = opts.verbose ?? false;
|
|
31
|
+
}
|
|
32
|
+
debug(msg, data) {
|
|
33
|
+
this.write('debug', msg, data);
|
|
34
|
+
}
|
|
35
|
+
info(msg, data) {
|
|
36
|
+
this.write('info', msg, data);
|
|
37
|
+
}
|
|
38
|
+
warn(msg, data) {
|
|
39
|
+
this.write('warn', msg, data);
|
|
40
|
+
}
|
|
41
|
+
error(msg, data) {
|
|
42
|
+
this.write('error', msg, data);
|
|
43
|
+
}
|
|
44
|
+
/** End the write stream. Resolves when the stream is fully flushed. */
|
|
45
|
+
close() {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
// Attach listeners BEFORE triggering end() so a synchronous error
|
|
48
|
+
// from end() or an immediate 'close' cannot slip past the listener.
|
|
49
|
+
this.stream.once('close', () => resolve());
|
|
50
|
+
this.stream.once('error', reject);
|
|
51
|
+
this.stream.end();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
write(level, msg, data) {
|
|
55
|
+
if (LEVEL_ORDER[level] < this.level)
|
|
56
|
+
return;
|
|
57
|
+
const entry = {
|
|
58
|
+
ts: new Date().toISOString(),
|
|
59
|
+
level,
|
|
60
|
+
msg,
|
|
61
|
+
...(data !== undefined ? { data } : {}),
|
|
62
|
+
};
|
|
63
|
+
const line = JSON.stringify(entry) + '\n';
|
|
64
|
+
this.stream.write(line);
|
|
65
|
+
if (this.verbose) {
|
|
66
|
+
const prefix = `[${entry.ts}] ${level.toUpperCase()}`;
|
|
67
|
+
const suffix = data ? ` ${JSON.stringify(data)}` : '';
|
|
68
|
+
process.stderr.write(`${prefix}: ${msg}${suffix}\n`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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","sourcesContent":["import { createWriteStream, mkdirSync, type WriteStream } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { LogLevel, LogEntry } from './types.js';\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface LoggerOptions {\n filePath: string;\n level: LogLevel;\n verbose?: boolean;\n}\n\n/**\n * Structured JSON-lines file logger.\n * Writes LogEntry objects one per line in append mode.\n * The open write stream keeps the Node event loop alive (daemon keepalive).\n */\nexport class Logger {\n private readonly stream: WriteStream;\n private readonly level: number;\n private readonly verbose: boolean;\n\n constructor(opts: LoggerOptions) {\n // Ensure parent directory exists\n const dir = dirname(opts.filePath);\n try {\n mkdirSync(dir, { recursive: true });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Cannot create log directory ${dir}: ${msg}`);\n }\n\n this.stream = createWriteStream(opts.filePath, { flags: 'a' });\n this.level = LEVEL_ORDER[opts.level] ?? LEVEL_ORDER.info;\n this.verbose = opts.verbose ?? false;\n }\n\n debug(msg: string, data?: Record<string, unknown>): void {\n this.write('debug', msg, data);\n }\n\n info(msg: string, data?: Record<string, unknown>): void {\n this.write('info', msg, data);\n }\n\n warn(msg: string, data?: Record<string, unknown>): void {\n this.write('warn', msg, data);\n }\n\n error(msg: string, data?: Record<string, unknown>): void {\n this.write('error', msg, data);\n }\n\n /** End the write stream. Resolves when the stream is fully flushed. */\n close(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n // Attach listeners BEFORE triggering end() so a synchronous error\n // from end() or an immediate 'close' cannot slip past the listener.\n this.stream.once('close', () => resolve());\n this.stream.once('error', reject);\n this.stream.end();\n });\n }\n\n private write(level: LogLevel, msg: string, data?: Record<string, unknown>): void {\n if (LEVEL_ORDER[level] < this.level) return;\n\n const entry: LogEntry = {\n ts: new Date().toISOString(),\n level,\n msg,\n ...(data !== undefined ? { data } : {}),\n };\n\n const line = JSON.stringify(entry) + '\\n';\n this.stream.write(line);\n\n if (this.verbose) {\n const prefix = `[${entry.ts}] ${level.toUpperCase()}`;\n const suffix = data ? ` ${JSON.stringify(data)}` : '';\n process.stderr.write(`${prefix}: ${msg}${suffix}\\n`);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface RuntimeProcessStatus {
|
|
2
|
+
running: boolean;
|
|
3
|
+
pid: number | null;
|
|
4
|
+
projects: string[];
|
|
5
|
+
log_file: string;
|
|
6
|
+
}
|
|
7
|
+
interface StartRuntimeOptions {
|
|
8
|
+
binaryPath: string;
|
|
9
|
+
configPath: string;
|
|
10
|
+
projectDirs: string[];
|
|
11
|
+
readyTimeoutMs?: number;
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare const BACKGROUND_RUNTIME_READY_TIMEOUT_MS: number;
|
|
15
|
+
export declare function startBackgroundRuntime(opts: StartRuntimeOptions): Promise<RuntimeProcessStatus>;
|
|
16
|
+
/**
|
|
17
|
+
* Record a running runtime so a later launch can find and stop it. Used both by
|
|
18
|
+
* the detached launcher (child PID) and by a `--foreground` session (its own
|
|
19
|
+
* PID), so the two modes share one source of truth and never coexist on the
|
|
20
|
+
* same device token.
|
|
21
|
+
*/
|
|
22
|
+
export declare function writeRuntimeState(configPath: string, pid: number, projects: string[]): void;
|
|
23
|
+
export declare function clearRuntimeState(configPath: string): void;
|
|
24
|
+
export declare function stopBackgroundRuntime(configPath: string): Promise<boolean>;
|
|
25
|
+
export declare function backgroundRuntimeStatus(configPath: string): RuntimeProcessStatus;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=runtime-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-process.d.ts","sourceRoot":"","sources":["../src/runtime-process.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,mBAAmB;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAOD,eAAO,MAAM,mCAAmC,QACoB,CAAC;AAErE,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAoDrG;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAI3F;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAE1D;AAED,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMhF;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,CAoBhF"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// Project/App: Open GSD
|
|
2
|
+
// File Purpose: Detached cloud runtime process lifecycle and status persistence.
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { chmodSync, closeSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { CLOUD_RUNTIME_INITIAL_CONNECT_WINDOW_MS } from "./cloud-runtime.js";
|
|
7
|
+
const PROCESS_STARTUP_GRACE_MS = 5_000;
|
|
8
|
+
const FORCED_STOP_TIMEOUT_MS = 5_000;
|
|
9
|
+
const STOP_GRACE_PERIOD_MS = 5_000;
|
|
10
|
+
const STOP_POLL_INTERVAL_MS = 50;
|
|
11
|
+
export const BACKGROUND_RUNTIME_READY_TIMEOUT_MS = CLOUD_RUNTIME_INITIAL_CONNECT_WINDOW_MS + PROCESS_STARTUP_GRACE_MS;
|
|
12
|
+
export async function startBackgroundRuntime(opts) {
|
|
13
|
+
await acquireRuntimeStartLock(opts.configPath);
|
|
14
|
+
try {
|
|
15
|
+
await stopBackgroundRuntime(opts.configPath);
|
|
16
|
+
const logFile = runtimeLogPath(opts.configPath);
|
|
17
|
+
mkdirSync(dirname(runtimeStatePath(opts.configPath)), { recursive: true });
|
|
18
|
+
const logFd = openSync(logFile, "a", 0o600);
|
|
19
|
+
chmodSync(logFile, 0o600);
|
|
20
|
+
const runArgs = [opts.binaryPath, "_run", "--config", opts.configPath];
|
|
21
|
+
if (opts.verbose)
|
|
22
|
+
runArgs.push("--verbose");
|
|
23
|
+
let child;
|
|
24
|
+
try {
|
|
25
|
+
child = spawn(process.execPath, runArgs, {
|
|
26
|
+
cwd: opts.projectDirs[0] ?? process.cwd(),
|
|
27
|
+
detached: true,
|
|
28
|
+
env: process.env,
|
|
29
|
+
stdio: ["ignore", logFd, logFd, "ipc"],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
closeSync(logFd);
|
|
34
|
+
}
|
|
35
|
+
if (child.pid == null) {
|
|
36
|
+
child.kill();
|
|
37
|
+
throw new Error(`could not start the background runtime; see ${logFile}`);
|
|
38
|
+
}
|
|
39
|
+
const pid = child.pid;
|
|
40
|
+
writeRuntimeState(opts.configPath, pid, opts.projectDirs);
|
|
41
|
+
try {
|
|
42
|
+
await waitUntilReady(child, opts.readyTimeoutMs ?? BACKGROUND_RUNTIME_READY_TIMEOUT_MS);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (child.connected)
|
|
46
|
+
child.disconnect();
|
|
47
|
+
await terminateProcess(pid);
|
|
48
|
+
removeRuntimeState(opts.configPath);
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
if (child.connected)
|
|
52
|
+
child.disconnect();
|
|
53
|
+
child.unref();
|
|
54
|
+
return {
|
|
55
|
+
running: true,
|
|
56
|
+
pid,
|
|
57
|
+
projects: opts.projectDirs,
|
|
58
|
+
log_file: logFile,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
releaseRuntimeStartLock(opts.configPath);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Record a running runtime so a later launch can find and stop it. Used both by
|
|
67
|
+
* the detached launcher (child PID) and by a `--foreground` session (its own
|
|
68
|
+
* PID), so the two modes share one source of truth and never coexist on the
|
|
69
|
+
* same device token.
|
|
70
|
+
*/
|
|
71
|
+
export function writeRuntimeState(configPath, pid, projects) {
|
|
72
|
+
const statePath = runtimeStatePath(configPath);
|
|
73
|
+
mkdirSync(dirname(statePath), { recursive: true });
|
|
74
|
+
writePrivateJson(statePath, { pid, projects });
|
|
75
|
+
}
|
|
76
|
+
export function clearRuntimeState(configPath) {
|
|
77
|
+
removeRuntimeState(configPath);
|
|
78
|
+
}
|
|
79
|
+
export async function stopBackgroundRuntime(configPath) {
|
|
80
|
+
const state = readRuntimeState(configPath);
|
|
81
|
+
if (!state)
|
|
82
|
+
return false;
|
|
83
|
+
await terminateProcess(state.pid);
|
|
84
|
+
removeRuntimeState(configPath);
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
export function backgroundRuntimeStatus(configPath) {
|
|
88
|
+
const state = readRuntimeState(configPath);
|
|
89
|
+
if (!state) {
|
|
90
|
+
return { running: false, pid: null, projects: [], log_file: runtimeLogPath(configPath) };
|
|
91
|
+
}
|
|
92
|
+
if (!processIsRunning(state.pid)) {
|
|
93
|
+
removeRuntimeState(configPath);
|
|
94
|
+
return {
|
|
95
|
+
running: false,
|
|
96
|
+
pid: null,
|
|
97
|
+
projects: state.projects,
|
|
98
|
+
log_file: runtimeLogPath(configPath),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
running: true,
|
|
103
|
+
pid: state.pid,
|
|
104
|
+
projects: state.projects,
|
|
105
|
+
log_file: runtimeLogPath(configPath),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function waitUntilReady(child, timeoutMs) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
let timeout;
|
|
111
|
+
const cleanup = () => {
|
|
112
|
+
clearTimeout(timeout);
|
|
113
|
+
child.removeListener("error", onError);
|
|
114
|
+
child.removeListener("exit", onExit);
|
|
115
|
+
child.removeListener("message", onMessage);
|
|
116
|
+
};
|
|
117
|
+
const onError = (error) => {
|
|
118
|
+
cleanup();
|
|
119
|
+
reject(error);
|
|
120
|
+
};
|
|
121
|
+
const onExit = (code) => {
|
|
122
|
+
cleanup();
|
|
123
|
+
reject(new Error(`background runtime exited before connecting (exit ${code ?? "unknown"})`));
|
|
124
|
+
};
|
|
125
|
+
const onMessage = (message) => {
|
|
126
|
+
if (!message || typeof message !== "object" || message.type !== "ready")
|
|
127
|
+
return;
|
|
128
|
+
cleanup();
|
|
129
|
+
resolve();
|
|
130
|
+
};
|
|
131
|
+
timeout = setTimeout(() => {
|
|
132
|
+
cleanup();
|
|
133
|
+
reject(new Error(`background runtime did not connect within ${timeoutMs}ms`));
|
|
134
|
+
}, timeoutMs);
|
|
135
|
+
child.once("error", onError);
|
|
136
|
+
child.once("exit", onExit);
|
|
137
|
+
child.on("message", onMessage);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function runtimeStatePath(configPath) {
|
|
141
|
+
return join(dirname(configPath), "cloud-runtime.json");
|
|
142
|
+
}
|
|
143
|
+
function runtimeLogPath(configPath) {
|
|
144
|
+
return join(dirname(configPath), "cloud-runtime.log");
|
|
145
|
+
}
|
|
146
|
+
function runtimeStartLockPath(configPath) {
|
|
147
|
+
return join(dirname(configPath), "cloud-runtime.start.lock");
|
|
148
|
+
}
|
|
149
|
+
async function acquireRuntimeStartLock(configPath) {
|
|
150
|
+
const lockPath = runtimeStartLockPath(configPath);
|
|
151
|
+
mkdirSync(dirname(lockPath), { recursive: true });
|
|
152
|
+
// Match worst-case `startBackgroundRuntime` hold time: stop prior runtime, wait for
|
|
153
|
+
// ready, and tear down the child if ready fails, plus one poll interval.
|
|
154
|
+
const deadline = Date.now()
|
|
155
|
+
+ BACKGROUND_RUNTIME_READY_TIMEOUT_MS
|
|
156
|
+
+ 2 * (STOP_GRACE_PERIOD_MS + FORCED_STOP_TIMEOUT_MS)
|
|
157
|
+
+ STOP_POLL_INTERVAL_MS;
|
|
158
|
+
while (Date.now() < deadline) {
|
|
159
|
+
try {
|
|
160
|
+
const fd = openSync(lockPath, "wx");
|
|
161
|
+
writeFileSync(fd, `${process.pid}\n`, "utf8");
|
|
162
|
+
closeSync(fd);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
if (error.code !== "EEXIST")
|
|
167
|
+
throw error;
|
|
168
|
+
try {
|
|
169
|
+
const ownerPid = readRuntimeStartLockOwner(lockPath);
|
|
170
|
+
const incompleteLockIsStale = ownerPid === null
|
|
171
|
+
&& Date.now() - statSync(lockPath).mtimeMs > 1_000;
|
|
172
|
+
if ((ownerPid !== null && !processIsRunning(ownerPid)) || incompleteLockIsStale) {
|
|
173
|
+
unlinkSync(lockPath);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// Another process may have released the lock; retry.
|
|
179
|
+
}
|
|
180
|
+
await new Promise((resolve) => setTimeout(resolve, STOP_POLL_INTERVAL_MS));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
throw new Error("timed out waiting for the background runtime start lock");
|
|
184
|
+
}
|
|
185
|
+
function releaseRuntimeStartLock(configPath) {
|
|
186
|
+
const lockPath = runtimeStartLockPath(configPath);
|
|
187
|
+
if (readRuntimeStartLockOwner(lockPath) !== process.pid)
|
|
188
|
+
return;
|
|
189
|
+
try {
|
|
190
|
+
unlinkSync(lockPath);
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
if (error.code !== "ENOENT")
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function readRuntimeStartLockOwner(lockPath) {
|
|
198
|
+
try {
|
|
199
|
+
const pid = Number.parseInt(readFileSync(lockPath, "utf8").trim(), 10);
|
|
200
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
if (error.code === "ENOENT")
|
|
204
|
+
return null;
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function readRuntimeState(configPath) {
|
|
209
|
+
try {
|
|
210
|
+
const value = JSON.parse(readFileSync(runtimeStatePath(configPath), "utf8"));
|
|
211
|
+
const pid = value.pid;
|
|
212
|
+
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || !Array.isArray(value.projects))
|
|
213
|
+
return null;
|
|
214
|
+
return {
|
|
215
|
+
pid,
|
|
216
|
+
projects: value.projects.filter((project) => typeof project === "string"),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function processIsRunning(pid) {
|
|
224
|
+
try {
|
|
225
|
+
process.kill(pid, 0);
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
return error.code === "EPERM";
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function waitForProcessExit(pid, timeoutMs) {
|
|
233
|
+
const deadline = Date.now() + timeoutMs;
|
|
234
|
+
while (processIsRunning(pid)) {
|
|
235
|
+
if (Date.now() >= deadline)
|
|
236
|
+
return false;
|
|
237
|
+
await new Promise((resolve) => setTimeout(resolve, STOP_POLL_INTERVAL_MS));
|
|
238
|
+
}
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
async function terminateProcess(pid) {
|
|
242
|
+
signalProcess(pid, "SIGTERM");
|
|
243
|
+
if (await waitForProcessExit(pid, STOP_GRACE_PERIOD_MS))
|
|
244
|
+
return;
|
|
245
|
+
signalProcess(pid, "SIGKILL");
|
|
246
|
+
if (!await waitForProcessExit(pid, FORCED_STOP_TIMEOUT_MS)) {
|
|
247
|
+
throw new Error(`background runtime PID ${pid} did not stop`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function signalProcess(pid, signal) {
|
|
251
|
+
try {
|
|
252
|
+
process.kill(pid, signal);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
if (error.code !== "ESRCH")
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function removeRuntimeState(configPath) {
|
|
260
|
+
try {
|
|
261
|
+
unlinkSync(runtimeStatePath(configPath));
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
if (error.code !== "ENOENT")
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function writePrivateJson(path, value) {
|
|
269
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
270
|
+
chmodSync(path, 0o600);
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=runtime-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-process.js","sourceRoot":"","sources":["../src/runtime-process.ts"],"names":[],"mappings":"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","sourcesContent":["// Project/App: Open GSD\n// File Purpose: Detached cloud runtime process lifecycle and status persistence.\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport {\n chmodSync,\n closeSync,\n mkdirSync,\n openSync,\n readFileSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { CLOUD_RUNTIME_INITIAL_CONNECT_WINDOW_MS } from \"./cloud-runtime.js\";\n\ninterface RuntimeProcessState {\n pid: number;\n projects: string[];\n}\n\nexport interface RuntimeProcessStatus {\n running: boolean;\n pid: number | null;\n projects: string[];\n log_file: string;\n}\n\ninterface StartRuntimeOptions {\n binaryPath: string;\n configPath: string;\n projectDirs: string[];\n readyTimeoutMs?: number;\n verbose?: boolean;\n}\n\nconst PROCESS_STARTUP_GRACE_MS = 5_000;\nconst FORCED_STOP_TIMEOUT_MS = 5_000;\nconst STOP_GRACE_PERIOD_MS = 5_000;\nconst STOP_POLL_INTERVAL_MS = 50;\n\nexport const BACKGROUND_RUNTIME_READY_TIMEOUT_MS =\n CLOUD_RUNTIME_INITIAL_CONNECT_WINDOW_MS + PROCESS_STARTUP_GRACE_MS;\n\nexport async function startBackgroundRuntime(opts: StartRuntimeOptions): Promise<RuntimeProcessStatus> {\n await acquireRuntimeStartLock(opts.configPath);\n try {\n await stopBackgroundRuntime(opts.configPath);\n\n const logFile = runtimeLogPath(opts.configPath);\n mkdirSync(dirname(runtimeStatePath(opts.configPath)), { recursive: true });\n const logFd = openSync(logFile, \"a\", 0o600);\n chmodSync(logFile, 0o600);\n const runArgs = [opts.binaryPath, \"_run\", \"--config\", opts.configPath];\n if (opts.verbose) runArgs.push(\"--verbose\");\n let child: ChildProcess;\n try {\n child = spawn(process.execPath, runArgs, {\n cwd: opts.projectDirs[0] ?? process.cwd(),\n detached: true,\n env: process.env,\n stdio: [\"ignore\", logFd, logFd, \"ipc\"],\n });\n } finally {\n closeSync(logFd);\n }\n\n if (child.pid == null) {\n child.kill();\n throw new Error(`could not start the background runtime; see ${logFile}`);\n }\n const pid = child.pid;\n\n writeRuntimeState(opts.configPath, pid, opts.projectDirs);\n\n try {\n await waitUntilReady(child, opts.readyTimeoutMs ?? BACKGROUND_RUNTIME_READY_TIMEOUT_MS);\n } catch (error) {\n if (child.connected) child.disconnect();\n await terminateProcess(pid);\n removeRuntimeState(opts.configPath);\n throw error;\n }\n\n if (child.connected) child.disconnect();\n child.unref();\n\n return {\n running: true,\n pid,\n projects: opts.projectDirs,\n log_file: logFile,\n };\n } finally {\n releaseRuntimeStartLock(opts.configPath);\n }\n}\n\n/**\n * Record a running runtime so a later launch can find and stop it. Used both by\n * the detached launcher (child PID) and by a `--foreground` session (its own\n * PID), so the two modes share one source of truth and never coexist on the\n * same device token.\n */\nexport function writeRuntimeState(configPath: string, pid: number, projects: string[]): void {\n const statePath = runtimeStatePath(configPath);\n mkdirSync(dirname(statePath), { recursive: true });\n writePrivateJson(statePath, { pid, projects } satisfies RuntimeProcessState);\n}\n\nexport function clearRuntimeState(configPath: string): void {\n removeRuntimeState(configPath);\n}\n\nexport async function stopBackgroundRuntime(configPath: string): Promise<boolean> {\n const state = readRuntimeState(configPath);\n if (!state) return false;\n await terminateProcess(state.pid);\n removeRuntimeState(configPath);\n return true;\n}\n\nexport function backgroundRuntimeStatus(configPath: string): RuntimeProcessStatus {\n const state = readRuntimeState(configPath);\n if (!state) {\n return { running: false, pid: null, projects: [], log_file: runtimeLogPath(configPath) };\n }\n if (!processIsRunning(state.pid)) {\n removeRuntimeState(configPath);\n return {\n running: false,\n pid: null,\n projects: state.projects,\n log_file: runtimeLogPath(configPath),\n };\n }\n return {\n running: true,\n pid: state.pid,\n projects: state.projects,\n log_file: runtimeLogPath(configPath),\n };\n}\n\nfunction waitUntilReady(child: ChildProcess, timeoutMs: number): Promise<void> {\n return new Promise((resolve, reject) => {\n let timeout: ReturnType<typeof setTimeout>;\n const cleanup = (): void => {\n clearTimeout(timeout);\n child.removeListener(\"error\", onError);\n child.removeListener(\"exit\", onExit);\n child.removeListener(\"message\", onMessage);\n };\n const onError = (error: Error): void => {\n cleanup();\n reject(error);\n };\n const onExit = (code: number | null): void => {\n cleanup();\n reject(new Error(`background runtime exited before connecting (exit ${code ?? \"unknown\"})`));\n };\n const onMessage = (message: unknown): void => {\n if (!message || typeof message !== \"object\" || (message as { type?: unknown }).type !== \"ready\") return;\n cleanup();\n resolve();\n };\n timeout = setTimeout(() => {\n cleanup();\n reject(new Error(`background runtime did not connect within ${timeoutMs}ms`));\n }, timeoutMs);\n\n child.once(\"error\", onError);\n child.once(\"exit\", onExit);\n child.on(\"message\", onMessage);\n });\n}\n\nfunction runtimeStatePath(configPath: string): string {\n return join(dirname(configPath), \"cloud-runtime.json\");\n}\n\nfunction runtimeLogPath(configPath: string): string {\n return join(dirname(configPath), \"cloud-runtime.log\");\n}\n\nfunction runtimeStartLockPath(configPath: string): string {\n return join(dirname(configPath), \"cloud-runtime.start.lock\");\n}\n\nasync function acquireRuntimeStartLock(configPath: string): Promise<void> {\n const lockPath = runtimeStartLockPath(configPath);\n mkdirSync(dirname(lockPath), { recursive: true });\n // Match worst-case `startBackgroundRuntime` hold time: stop prior runtime, wait for\n // ready, and tear down the child if ready fails, plus one poll interval.\n const deadline = Date.now()\n + BACKGROUND_RUNTIME_READY_TIMEOUT_MS\n + 2 * (STOP_GRACE_PERIOD_MS + FORCED_STOP_TIMEOUT_MS)\n + STOP_POLL_INTERVAL_MS;\n while (Date.now() < deadline) {\n try {\n const fd = openSync(lockPath, \"wx\");\n writeFileSync(fd, `${process.pid}\\n`, \"utf8\");\n closeSync(fd);\n return;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n try {\n const ownerPid = readRuntimeStartLockOwner(lockPath);\n const incompleteLockIsStale = ownerPid === null\n && Date.now() - statSync(lockPath).mtimeMs > 1_000;\n if ((ownerPid !== null && !processIsRunning(ownerPid)) || incompleteLockIsStale) {\n unlinkSync(lockPath);\n continue;\n }\n } catch {\n // Another process may have released the lock; retry.\n }\n await new Promise((resolve) => setTimeout(resolve, STOP_POLL_INTERVAL_MS));\n }\n }\n throw new Error(\"timed out waiting for the background runtime start lock\");\n}\n\nfunction releaseRuntimeStartLock(configPath: string): void {\n const lockPath = runtimeStartLockPath(configPath);\n if (readRuntimeStartLockOwner(lockPath) !== process.pid) return;\n try {\n unlinkSync(lockPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n}\n\nfunction readRuntimeStartLockOwner(lockPath: string): number | null {\n try {\n const pid = Number.parseInt(readFileSync(lockPath, \"utf8\").trim(), 10);\n return Number.isInteger(pid) && pid > 0 ? pid : null;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n}\n\nfunction readRuntimeState(configPath: string): RuntimeProcessState | null {\n try {\n const value = JSON.parse(readFileSync(runtimeStatePath(configPath), \"utf8\")) as Partial<RuntimeProcessState>;\n const pid = value.pid;\n if (typeof pid !== \"number\" || !Number.isInteger(pid) || pid <= 0 || !Array.isArray(value.projects)) return null;\n return {\n pid,\n projects: value.projects.filter((project): project is string => typeof project === \"string\"),\n };\n } catch {\n return null;\n }\n}\n\nfunction processIsRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === \"EPERM\";\n }\n}\n\nasync function waitForProcessExit(pid: number, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (processIsRunning(pid)) {\n if (Date.now() >= deadline) return false;\n await new Promise((resolve) => setTimeout(resolve, STOP_POLL_INTERVAL_MS));\n }\n return true;\n}\n\nasync function terminateProcess(pid: number): Promise<void> {\n signalProcess(pid, \"SIGTERM\");\n if (await waitForProcessExit(pid, STOP_GRACE_PERIOD_MS)) return;\n signalProcess(pid, \"SIGKILL\");\n if (!await waitForProcessExit(pid, FORCED_STOP_TIMEOUT_MS)) {\n throw new Error(`background runtime PID ${pid} did not stop`);\n }\n}\n\nfunction signalProcess(pid: number, signal: NodeJS.Signals): void {\n try {\n process.kill(pid, signal);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ESRCH\") throw error;\n }\n}\n\nfunction removeRuntimeState(configPath: string): void {\n try {\n unlinkSync(runtimeStatePath(configPath));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n}\n\nfunction writePrivateJson(path: string, value: unknown): void {\n writeFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, { encoding: \"utf8\", mode: 0o600 });\n chmodSync(path, 0o600);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-process.test.d.ts","sourceRoot":"","sources":["../src/runtime-process.test.ts"],"names":[],"mappings":""}
|