@opengsd/gsd-pi 1.5.0-dev.553dc518 → 1.5.0-dev.c4c8885f
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/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +114 -36
- package/dist/resources/extensions/gsd/activity-log.js +1 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +16 -10
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +14 -5
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +7 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +69 -17
- package/dist/resources/extensions/gsd/auto-model-selection.js +28 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +29 -117
- package/dist/resources/extensions/gsd/auto-recovery.js +50 -6
- package/dist/resources/extensions/gsd/auto-start.js +54 -31
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +12 -2
- package/dist/resources/extensions/gsd/auto-timers.js +9 -2
- package/dist/resources/extensions/gsd/auto.js +97 -31
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +67 -6
- package/dist/resources/extensions/gsd/codebase-generator.js +7 -1
- package/dist/resources/extensions/gsd/compat/compat-marker.js +44 -0
- package/dist/resources/extensions/gsd/config-overlay.js +7 -2
- package/dist/resources/extensions/gsd/db/engine.js +33 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +20 -2
- package/dist/resources/extensions/gsd/db-adapter.js +30 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +3 -3
- package/dist/resources/extensions/gsd/flat-phase-migration.js +18 -0
- package/dist/resources/extensions/gsd/gsd-db.js +12 -11
- package/dist/resources/extensions/gsd/guided-flow.js +16 -7
- package/dist/resources/extensions/gsd/journal.js +1 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +34 -91
- package/dist/resources/extensions/gsd/md-importer.js +89 -23
- package/dist/resources/extensions/gsd/metrics.js +2 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +30 -3
- package/dist/resources/extensions/gsd/paths.js +87 -52
- package/dist/resources/extensions/gsd/post-unit-hooks.js +27 -0
- package/dist/resources/extensions/gsd/preferences-models.js +66 -15
- package/dist/resources/extensions/gsd/preferences-skills.js +10 -16
- package/dist/resources/extensions/gsd/preferences-validation.js +66 -10
- package/dist/resources/extensions/gsd/preferences.js +20 -0
- package/dist/resources/extensions/gsd/rule-registry.js +106 -10
- package/dist/resources/extensions/gsd/skill-discovery.js +36 -23
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +1 -10
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +3 -24
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +10 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -5
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +16 -10
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +5 -0
- package/dist/resources/extensions/gsd/tools/reopen-task.js +13 -5
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -8
- package/dist/resources/extensions/gsd/uat-dispatch.js +94 -0
- package/dist/resources/extensions/gsd/uok/audit-toggle.js +31 -2
- package/dist/resources/extensions/gsd/uok/audit.js +3 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +22 -30
- package/dist/resources/extensions/gsd/uok/gitops.js +18 -15
- package/dist/resources/extensions/gsd/uok/kernel.js +120 -46
- package/dist/resources/extensions/gsd/uok/model-policy.js +17 -14
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +9 -26
- package/dist/resources/extensions/gsd/workspace.js +5 -14
- package/dist/resources/extensions/shared/gsd-browser-cli.js +29 -0
- package/dist/resources/extensions/shared/interview-ui.js +62 -9
- 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 +10 -10
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/chunks/{1128.js → 1991.js} +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- 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/worktree-cli-create.d.ts +10 -0
- package/dist/worktree-cli-create.js +11 -0
- package/dist/worktree-cli-format.d.ts +12 -0
- package/dist/worktree-cli-format.js +38 -0
- package/dist/worktree-cli-plan.d.ts +16 -0
- package/dist/worktree-cli-plan.js +19 -0
- package/dist/worktree-cli-session.d.ts +13 -0
- package/dist/worktree-cli-session.js +18 -0
- package/dist/worktree-cli-status.d.ts +35 -0
- package/dist/worktree-cli-status.js +54 -0
- package/dist/worktree-cli.d.ts +1 -16
- package/dist/worktree-cli.js +28 -122
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/orchestrator-agent.d.ts +21 -0
- package/packages/daemon/dist/orchestrator-agent.d.ts.map +1 -0
- package/packages/daemon/dist/orchestrator-agent.js +113 -0
- package/packages/daemon/dist/orchestrator-agent.js.map +1 -0
- package/packages/daemon/dist/orchestrator-tools.d.ts +12 -0
- package/packages/daemon/dist/orchestrator-tools.d.ts.map +1 -0
- package/packages/daemon/dist/orchestrator-tools.js +137 -0
- package/packages/daemon/dist/orchestrator-tools.js.map +1 -0
- package/packages/daemon/dist/orchestrator.d.ts +4 -56
- package/packages/daemon/dist/orchestrator.d.ts.map +1 -1
- package/packages/daemon/dist/orchestrator.js +13 -303
- package/packages/daemon/dist/orchestrator.js.map +1 -1
- package/packages/daemon/dist/orchestrator.test.js +11 -1
- package/packages/daemon/dist/orchestrator.test.js.map +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.js +74 -53
- package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +30 -2
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skill-directories.d.ts +66 -0
- package/packages/pi-coding-agent/dist/core/skill-directories.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/skill-directories.js +138 -0
- package/packages/pi-coding-agent/dist/core/skill-directories.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts +4 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +4 -1
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.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/extensions/ask-user-questions.ts +1 -1
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +146 -33
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +25 -0
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +93 -0
- package/src/resources/extensions/gsd/activity-log.ts +1 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +17 -11
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -4
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +9 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +77 -16
- package/src/resources/extensions/gsd/auto-model-selection.ts +33 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +53 -113
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -6
- package/src/resources/extensions/gsd/auto-start.ts +58 -29
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -2
- package/src/resources/extensions/gsd/auto-timers.ts +9 -2
- package/src/resources/extensions/gsd/auto.ts +103 -30
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +66 -6
- package/src/resources/extensions/gsd/codebase-generator.ts +7 -1
- package/src/resources/extensions/gsd/compat/compat-marker.ts +47 -0
- package/src/resources/extensions/gsd/config-overlay.ts +7 -1
- package/src/resources/extensions/gsd/db/engine.ts +36 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +23 -1
- package/src/resources/extensions/gsd/db-adapter.ts +29 -3
- package/src/resources/extensions/gsd/docs/preferences-reference.md +3 -3
- package/src/resources/extensions/gsd/flat-phase-migration.ts +20 -0
- package/src/resources/extensions/gsd/gsd-db.ts +20 -11
- package/src/resources/extensions/gsd/guided-flow.ts +19 -7
- package/src/resources/extensions/gsd/journal.ts +1 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +52 -103
- package/src/resources/extensions/gsd/md-importer.ts +93 -22
- package/src/resources/extensions/gsd/metrics.ts +2 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +32 -3
- package/src/resources/extensions/gsd/paths.ts +108 -51
- package/src/resources/extensions/gsd/post-unit-hooks.ts +32 -0
- package/src/resources/extensions/gsd/preferences-models.ts +74 -20
- package/src/resources/extensions/gsd/preferences-skills.ts +10 -16
- package/src/resources/extensions/gsd/preferences-types.ts +24 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +77 -9
- package/src/resources/extensions/gsd/preferences.ts +20 -0
- package/src/resources/extensions/gsd/rule-registry.ts +111 -9
- package/src/resources/extensions/gsd/skill-discovery.ts +47 -23
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +1 -9
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +2 -22
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +14 -0
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +169 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +41 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-timeout-recovery-supervisor-inflight-guard.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/db-adapter.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/db-writable-probe.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +72 -32
- package/src/resources/extensions/gsd/tests/import-completion-lost-update.test.ts +196 -0
- package/src/resources/extensions/gsd/tests/integration/paths.test.ts +88 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -15
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +269 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/preferences.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +95 -1
- package/src/resources/extensions/gsd/tests/sibling-model-fallbacks.test.ts +189 -0
- package/src/resources/extensions/gsd/tests/single-field-model-thinking.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/supervisor-model-swap-inflight-guard.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/supervisor-model-swap-thinking-clamp.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/uat-dispatch.test.ts +211 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +226 -2
- package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +213 -2
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +9 -5
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +19 -8
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +5 -0
- package/src/resources/extensions/gsd/tools/reopen-task.ts +13 -5
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +13 -9
- package/src/resources/extensions/gsd/types.ts +23 -4
- package/src/resources/extensions/gsd/uat-dispatch.ts +176 -0
- package/src/resources/extensions/gsd/uok/audit-toggle.ts +32 -2
- package/src/resources/extensions/gsd/uok/audit.ts +2 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +26 -36
- package/src/resources/extensions/gsd/uok/gitops.ts +21 -18
- package/src/resources/extensions/gsd/uok/kernel.ts +169 -48
- package/src/resources/extensions/gsd/uok/model-policy.ts +20 -17
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +9 -24
- package/src/resources/extensions/gsd/workspace.ts +5 -21
- package/src/resources/extensions/shared/gsd-browser-cli.ts +29 -0
- package/src/resources/extensions/shared/interview-ui.ts +58 -11
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +32 -0
- /package/dist/web/standalone/.next/static/{ZpFDazP-38PXBPiI_LdZf → NPMNi2HV8BuK3baQsEUhk}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{ZpFDazP-38PXBPiI_LdZf → NPMNi2HV8BuK3baQsEUhk}/_ssgManifest.js +0 -0
|
@@ -8,10 +8,16 @@ import type { AutoSession } from "../auto/session.js";
|
|
|
8
8
|
import type { LoopDeps } from "../auto/loop-deps.js";
|
|
9
9
|
import { gsdRoot } from "../paths.js";
|
|
10
10
|
import { buildAuditEnvelope, emitUokAuditEvent } from "./audit.js";
|
|
11
|
-
import {
|
|
12
|
-
|
|
11
|
+
import {
|
|
12
|
+
getUnifiedAuditOverride,
|
|
13
|
+
restoreUnifiedAuditOverride,
|
|
14
|
+
setUnifiedAuditEnabled,
|
|
15
|
+
setUnifiedAuditSuppressedForBasePath,
|
|
16
|
+
} from "./audit-toggle.js";
|
|
17
|
+
import { resolveUokFlags, type UokFlags } from "./flags.js";
|
|
13
18
|
import { createTurnObserver } from "./loop-adapter.js";
|
|
14
19
|
import { incrementLegacyTelemetry } from "../legacy-telemetry.js";
|
|
20
|
+
import { logWarning } from "../workflow-logger.js";
|
|
15
21
|
|
|
16
22
|
interface RunAutoLoopWithUokArgs {
|
|
17
23
|
ctx: ExtensionContext;
|
|
@@ -45,80 +51,195 @@ function writeParityEvent(basePath: string, event: Record<string, unknown>): voi
|
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
|
|
54
|
+
type UokKernelPathLabel = "uok-kernel" | "legacy-wrapper" | "legacy-fallback";
|
|
55
|
+
|
|
56
|
+
interface UokKernelRunPlan {
|
|
57
|
+
flags: UokFlags;
|
|
58
|
+
pathLabel: UokKernelPathLabel;
|
|
59
|
+
traceId: string;
|
|
60
|
+
useKernel: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
48
63
|
function resolveKernelPathLabel(
|
|
49
|
-
flags:
|
|
50
|
-
):
|
|
64
|
+
flags: UokFlags,
|
|
65
|
+
): UokKernelPathLabel {
|
|
51
66
|
if (flags.legacyFallback) return "legacy-fallback";
|
|
52
67
|
return flags.enabled ? "uok-kernel" : "legacy-wrapper";
|
|
53
68
|
}
|
|
54
69
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
function createUokKernelRunPlan(input: {
|
|
71
|
+
preferences: ReturnType<LoopDeps["loadEffectiveGSDPreferences"]> | undefined;
|
|
72
|
+
autoStartTime?: unknown;
|
|
73
|
+
}): UokKernelRunPlan {
|
|
74
|
+
const flags = resolveUokFlags(input.preferences?.preferences);
|
|
60
75
|
const pathLabel = resolveKernelPathLabel(flags);
|
|
61
|
-
|
|
62
|
-
incrementLegacyTelemetry("legacy.uokFallbackUsed");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
writeParityEvent(s.basePath, {
|
|
66
|
-
ts: new Date().toISOString(),
|
|
67
|
-
path: pathLabel,
|
|
76
|
+
return {
|
|
68
77
|
flags,
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
pathLabel,
|
|
79
|
+
traceId: `session:${String(input.autoStartTime || Date.now())}`,
|
|
80
|
+
useKernel: flags.enabled,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface KernelAuditStateController {
|
|
85
|
+
apply(enabled: boolean): void;
|
|
86
|
+
restore(): void;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function createKernelAuditStateController(basePath: string): KernelAuditStateController {
|
|
90
|
+
const previousAuditOverride = getUnifiedAuditOverride();
|
|
91
|
+
return {
|
|
92
|
+
apply(enabled): void {
|
|
93
|
+
setUnifiedAuditSuppressedForBasePath(basePath, !enabled);
|
|
94
|
+
setUnifiedAuditEnabled(enabled);
|
|
95
|
+
},
|
|
96
|
+
restore(): void {
|
|
97
|
+
restoreUnifiedAuditOverride(previousAuditOverride);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
71
101
|
|
|
72
|
-
|
|
102
|
+
function emitKernelEnterAudit(input: {
|
|
103
|
+
basePath: string;
|
|
104
|
+
plan: UokKernelRunPlan;
|
|
105
|
+
sessionId?: string;
|
|
106
|
+
}): boolean {
|
|
107
|
+
if (!input.plan.flags.auditUnified) return true;
|
|
108
|
+
|
|
109
|
+
try {
|
|
73
110
|
emitUokAuditEvent(
|
|
74
|
-
|
|
111
|
+
input.basePath,
|
|
75
112
|
buildAuditEnvelope({
|
|
76
|
-
traceId:
|
|
113
|
+
traceId: input.plan.traceId,
|
|
77
114
|
category: "orchestration",
|
|
78
115
|
type: "uok-kernel-enter",
|
|
79
116
|
payload: {
|
|
80
|
-
flags,
|
|
81
|
-
sessionId:
|
|
117
|
+
flags: input.plan.flags,
|
|
118
|
+
sessionId: input.sessionId,
|
|
82
119
|
},
|
|
83
120
|
}),
|
|
84
121
|
);
|
|
122
|
+
return true;
|
|
123
|
+
} catch (err) {
|
|
124
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
125
|
+
writeParityEvent(input.basePath, {
|
|
126
|
+
ts: new Date().toISOString(),
|
|
127
|
+
path: input.plan.pathLabel,
|
|
128
|
+
flags: input.plan.flags,
|
|
129
|
+
phase: "telemetry-error",
|
|
130
|
+
telemetry: "uok-kernel-enter",
|
|
131
|
+
error: errorMessage,
|
|
132
|
+
});
|
|
133
|
+
logWarning("db", `uok-kernel-enter audit emit failed (non-fatal): ${errorMessage}`);
|
|
134
|
+
return false;
|
|
85
135
|
}
|
|
136
|
+
}
|
|
86
137
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
138
|
+
function decorateLoopDepsForKernel(input: {
|
|
139
|
+
deps: LoopDeps;
|
|
140
|
+
basePath: string;
|
|
141
|
+
plan: UokKernelRunPlan;
|
|
142
|
+
auditHealthy: boolean;
|
|
143
|
+
}): LoopDeps {
|
|
144
|
+
if (!input.plan.useKernel) return input.deps;
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
...input.deps,
|
|
148
|
+
uokObserver: createTurnObserver({
|
|
149
|
+
basePath: input.basePath,
|
|
150
|
+
gitAction: input.plan.flags.gitopsTurnAction,
|
|
151
|
+
gitPush: input.plan.flags.gitopsTurnPush,
|
|
152
|
+
enableAudit: input.plan.flags.auditUnified && input.auditHealthy,
|
|
153
|
+
enableGitops: input.plan.flags.gitops,
|
|
154
|
+
}),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function executeKernelRunPlan(input: {
|
|
159
|
+
plan: UokKernelRunPlan;
|
|
160
|
+
ctx: ExtensionContext;
|
|
161
|
+
pi: ExtensionAPI;
|
|
162
|
+
s: AutoSession;
|
|
163
|
+
deps: LoopDeps;
|
|
164
|
+
kernelDeps: LoopDeps;
|
|
165
|
+
runKernelLoop: RunAutoLoopWithUokArgs["runKernelLoop"];
|
|
166
|
+
runLegacyLoop: RunAutoLoopWithUokArgs["runLegacyLoop"];
|
|
167
|
+
}): Promise<void> {
|
|
168
|
+
if (input.plan.useKernel) {
|
|
169
|
+
await input.runKernelLoop(input.ctx, input.pi, input.s, input.kernelDeps);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
await input.runLegacyLoop(input.ctx, input.pi, input.s, input.deps);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export async function runAutoLoopWithUok(args: RunAutoLoopWithUokArgs): Promise<void> {
|
|
176
|
+
const { ctx, pi, s, deps, runKernelLoop, runLegacyLoop } = args;
|
|
177
|
+
const auditState = createKernelAuditStateController(s.basePath);
|
|
178
|
+
let plan: UokKernelRunPlan | null = null;
|
|
99
179
|
|
|
100
180
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
181
|
+
plan = createUokKernelRunPlan({
|
|
182
|
+
preferences: deps.loadEffectiveGSDPreferences(),
|
|
183
|
+
autoStartTime: s.autoStartTime,
|
|
184
|
+
});
|
|
185
|
+
auditState.apply(plan.flags.auditUnified);
|
|
186
|
+
|
|
187
|
+
if (plan.pathLabel !== "uok-kernel") {
|
|
188
|
+
incrementLegacyTelemetry("legacy.uokFallbackUsed");
|
|
105
189
|
}
|
|
190
|
+
|
|
106
191
|
writeParityEvent(s.basePath, {
|
|
107
192
|
ts: new Date().toISOString(),
|
|
108
|
-
path: pathLabel,
|
|
109
|
-
flags,
|
|
110
|
-
phase: "
|
|
111
|
-
status: "ok",
|
|
193
|
+
path: plan.pathLabel,
|
|
194
|
+
flags: plan.flags,
|
|
195
|
+
phase: "enter",
|
|
112
196
|
});
|
|
113
|
-
|
|
197
|
+
|
|
198
|
+
const auditHealthy = emitKernelEnterAudit({
|
|
199
|
+
basePath: s.basePath,
|
|
200
|
+
plan,
|
|
201
|
+
sessionId: ctx.sessionManager?.getSessionId?.(),
|
|
202
|
+
});
|
|
203
|
+
auditState.apply(plan.flags.auditUnified && auditHealthy);
|
|
204
|
+
|
|
205
|
+
const kernelDeps = decorateLoopDepsForKernel({
|
|
206
|
+
deps,
|
|
207
|
+
basePath: s.basePath,
|
|
208
|
+
plan,
|
|
209
|
+
auditHealthy,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
await executeKernelRunPlan({
|
|
213
|
+
plan,
|
|
214
|
+
ctx,
|
|
215
|
+
pi,
|
|
216
|
+
s,
|
|
217
|
+
deps,
|
|
218
|
+
kernelDeps,
|
|
219
|
+
runKernelLoop,
|
|
220
|
+
runLegacyLoop,
|
|
221
|
+
});
|
|
222
|
+
|
|
114
223
|
writeParityEvent(s.basePath, {
|
|
115
224
|
ts: new Date().toISOString(),
|
|
116
|
-
path: pathLabel,
|
|
117
|
-
flags,
|
|
225
|
+
path: plan.pathLabel,
|
|
226
|
+
flags: plan.flags,
|
|
118
227
|
phase: "exit",
|
|
119
|
-
status: "
|
|
120
|
-
error: err instanceof Error ? err.message : String(err),
|
|
228
|
+
status: "ok",
|
|
121
229
|
});
|
|
230
|
+
} catch (err) {
|
|
231
|
+
if (plan) {
|
|
232
|
+
writeParityEvent(s.basePath, {
|
|
233
|
+
ts: new Date().toISOString(),
|
|
234
|
+
path: plan.pathLabel,
|
|
235
|
+
flags: plan.flags,
|
|
236
|
+
phase: "exit",
|
|
237
|
+
status: "error",
|
|
238
|
+
error: err instanceof Error ? err.message : String(err),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
122
241
|
throw err;
|
|
242
|
+
} finally {
|
|
243
|
+
auditState.restore();
|
|
123
244
|
}
|
|
124
245
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TaskMetadata } from "../complexity-classifier.js";
|
|
2
2
|
import { computeTaskRequirements, filterToolsForProvider } from "../model-router.js";
|
|
3
3
|
import { buildAuditEnvelope, emitUokAuditEvent } from "./audit.js";
|
|
4
|
+
import { isUnifiedAuditEnabled } from "./audit-toggle.js";
|
|
4
5
|
|
|
5
6
|
export interface ModelCandidate {
|
|
6
7
|
id: string;
|
|
@@ -83,23 +84,25 @@ export function applyModelPolicyFilter<T extends ModelCandidate>(
|
|
|
83
84
|
};
|
|
84
85
|
decisions.push(decision);
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
87
|
+
if (isUnifiedAuditEnabled(options.basePath)) {
|
|
88
|
+
emitUokAuditEvent(
|
|
89
|
+
options.basePath,
|
|
90
|
+
buildAuditEnvelope({
|
|
91
|
+
traceId: options.traceId,
|
|
92
|
+
turnId: options.turnId,
|
|
93
|
+
category: "model-policy",
|
|
94
|
+
type: allowed ? "model-policy-allow" : "model-policy-deny",
|
|
95
|
+
payload: {
|
|
96
|
+
modelId: model.id,
|
|
97
|
+
provider: model.provider,
|
|
98
|
+
api: model.api,
|
|
99
|
+
reason,
|
|
100
|
+
unitType: options.unitType,
|
|
101
|
+
requirements,
|
|
102
|
+
},
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
103
106
|
|
|
104
107
|
if (allowed) eligible.push(model);
|
|
105
108
|
}
|
|
@@ -105,7 +105,7 @@ export function writeWorktreeEventLog(
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
function emitWorkflowEventAudit(basePath: string, event: WorkflowEvent): void {
|
|
108
|
-
if (!isUnifiedAuditEnabled()) return;
|
|
108
|
+
if (!isUnifiedAuditEnabled(basePath)) return;
|
|
109
109
|
try {
|
|
110
110
|
const normalized = normalizeWorkflowEventCommand(event.cmd) ?? "unknown";
|
|
111
111
|
emitUokAuditEvent(
|
|
@@ -17,7 +17,7 @@ import type { MilestoneRow } from "./db-milestone-artifact-rows.js";
|
|
|
17
17
|
import type { SliceRow, TaskRow } from "./db-task-slice-rows.js";
|
|
18
18
|
import type { VerificationEvidenceRow } from "./db-verification-evidence-rows.js";
|
|
19
19
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
20
|
-
import { join } from "node:path";
|
|
20
|
+
import { dirname, join } from "node:path";
|
|
21
21
|
import { mkdirSync, existsSync } from "node:fs";
|
|
22
22
|
import { readFile } from "node:fs/promises";
|
|
23
23
|
import { logWarning } from "./workflow-logger.js";
|
|
@@ -26,7 +26,7 @@ import { deriveState } from "./state.js";
|
|
|
26
26
|
import type { GSDState } from "./types.js";
|
|
27
27
|
import { renderPlanFromDb, renderRoadmapFromDb } from "./markdown-renderer.js";
|
|
28
28
|
import { readManifest } from "./workflow-manifest.js";
|
|
29
|
-
import { gsdRoot,
|
|
29
|
+
import { gsdRoot, resolveMilestoneFile, resolveSliceFile, resolveTaskFile, relTaskFile } from "./paths.js";
|
|
30
30
|
|
|
31
31
|
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
32
32
|
|
|
@@ -329,24 +329,10 @@ export function renderSummaryProjection(basePath: string, milestoneId: string, s
|
|
|
329
329
|
const evidenceRows = getVerificationEvidence(milestoneId, sliceId, taskId);
|
|
330
330
|
const content = renderSummaryContent(taskRow, sliceId, milestoneId, evidenceRows);
|
|
331
331
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const phaseDir = resolveMilestonePath(basePath, milestoneId);
|
|
337
|
-
let dir: string;
|
|
338
|
-
if (slicePath && phaseDir && slicePath !== phaseDir) {
|
|
339
|
-
// Legacy layout: slice has its own slices/SID/ subdir → tasks/ subdir
|
|
340
|
-
dir = join(slicePath, "tasks");
|
|
341
|
-
} else if (phaseDir) {
|
|
342
|
-
// Flat-phase: task summaries go in the phase dir (no tasks/ subdir needed)
|
|
343
|
-
dir = phaseDir;
|
|
344
|
-
} else {
|
|
345
|
-
// Fallback: legacy hardcoded path (milestone dir not on disk yet)
|
|
346
|
-
dir = join(gsdProjectionRoot(basePath), "milestones", milestoneId, "slices", sliceId, "tasks");
|
|
347
|
-
}
|
|
348
|
-
mkdirSync(dir, { recursive: true });
|
|
349
|
-
atomicWriteSync(join(dir, `${taskId}-SUMMARY.md`), content);
|
|
332
|
+
const summaryPath = resolveTaskFile(basePath, milestoneId, sliceId, taskId, "SUMMARY")
|
|
333
|
+
?? join(basePath, relTaskFile(basePath, milestoneId, sliceId, taskId, "SUMMARY", getMilestone(milestoneId)?.title));
|
|
334
|
+
mkdirSync(dirname(summaryPath), { recursive: true });
|
|
335
|
+
atomicWriteSync(summaryPath, content);
|
|
350
336
|
}
|
|
351
337
|
|
|
352
338
|
// ─── STATE.md Projection ────────────────────────────────────────────────
|
|
@@ -536,7 +522,7 @@ export async function regenerateIfMissing(
|
|
|
536
522
|
filePath = resolveSliceFile(basePath, milestoneId, sliceId, "PLAN") ?? "";
|
|
537
523
|
break;
|
|
538
524
|
case "ROADMAP":
|
|
539
|
-
filePath =
|
|
525
|
+
filePath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP") ?? "";
|
|
540
526
|
break;
|
|
541
527
|
case "SUMMARY":
|
|
542
528
|
// For SUMMARY, we regenerate all task summaries in the slice
|
|
@@ -553,8 +539,7 @@ export async function regenerateIfMissing(
|
|
|
553
539
|
const doneTasks = taskRows.filter(t => t.status === "done" || t.status === "complete");
|
|
554
540
|
let regenerated = 0;
|
|
555
541
|
for (const task of doneTasks) {
|
|
556
|
-
|
|
557
|
-
if (!existsSync(summaryPath)) {
|
|
542
|
+
if (!resolveTaskFile(basePath, milestoneId, sliceId, task.id, "SUMMARY")) {
|
|
558
543
|
try {
|
|
559
544
|
renderSummaryProjection(basePath, milestoneId, sliceId, task.id);
|
|
560
545
|
regenerated++;
|
|
@@ -591,7 +576,7 @@ export async function regenerateIfMissing(
|
|
|
591
576
|
return !!(resolveSliceFile(basePath, milestoneId, sliceId, "PLAN"));
|
|
592
577
|
case "ROADMAP":
|
|
593
578
|
await renderRoadmapFromDb(basePath, milestoneId);
|
|
594
|
-
return
|
|
579
|
+
return !!resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
|
|
595
580
|
case "STATE":
|
|
596
581
|
await renderStateProjection(basePath);
|
|
597
582
|
return existsSync(filePath);
|
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import {
|
|
5
|
-
buildMilestoneFileName,
|
|
6
|
-
canonicalPhaseDirName,
|
|
7
|
-
isLegacyMilestonesLayout,
|
|
8
|
-
milestonesDir,
|
|
9
5
|
type GsdPathContract,
|
|
10
6
|
resolveGsdPathContract,
|
|
11
7
|
resolveMilestoneFile,
|
|
12
8
|
resolveMilestonePath,
|
|
9
|
+
targetMilestoneFile,
|
|
13
10
|
normalizeRealPath,
|
|
14
11
|
} from "./paths.js";
|
|
15
12
|
import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "./worktree-root.js";
|
|
@@ -41,27 +38,14 @@ function tryRealpath(p: string): string {
|
|
|
41
38
|
return normalizeRealPath(p);
|
|
42
39
|
}
|
|
43
40
|
|
|
44
|
-
function isLegacyMilestoneDirectory(dir: string): boolean {
|
|
45
|
-
const parent = dirname(dir);
|
|
46
|
-
return parent.endsWith("/milestones") || parent.endsWith("\\milestones");
|
|
47
|
-
}
|
|
48
|
-
|
|
49
41
|
function scopeMilestoneDir(basePath: string, milestoneId: string): string {
|
|
50
|
-
return resolveMilestonePath(basePath, milestoneId)
|
|
51
|
-
|
|
52
|
-
isLegacyMilestonesLayout(basePath) ? milestoneId : canonicalPhaseDirName(milestoneId),
|
|
53
|
-
);
|
|
42
|
+
return resolveMilestonePath(basePath, milestoneId)
|
|
43
|
+
?? dirname(targetMilestoneFile(basePath, milestoneId, "ROADMAP"));
|
|
54
44
|
}
|
|
55
45
|
|
|
56
46
|
function scopeMilestoneFile(basePath: string, milestoneId: string, suffix: string): string {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const dir = scopeMilestoneDir(basePath, milestoneId);
|
|
61
|
-
const filename = isLegacyMilestoneDirectory(dir)
|
|
62
|
-
? `${milestoneId}-${suffix}.md`
|
|
63
|
-
: buildMilestoneFileName(milestoneId, suffix);
|
|
64
|
-
return join(dir, filename);
|
|
47
|
+
return resolveMilestoneFile(basePath, milestoneId, suffix)
|
|
48
|
+
?? targetMilestoneFile(basePath, milestoneId, suffix);
|
|
65
49
|
}
|
|
66
50
|
|
|
67
51
|
/**
|
|
@@ -66,6 +66,30 @@ function splitCommandLine(commandLine: string): string[] {
|
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Extra gsd-browser CLI flags to forward verbatim to the launched daemon, from
|
|
71
|
+
* GSD_BROWSER_MCP_EXTRA_ARGS. Unlike GSD_BROWSER_MCP_ARGS (a full args override),
|
|
72
|
+
* these are *appended* to the default `mcp`/`daemon start` invocation so callers
|
|
73
|
+
* keep the managed session/identity flags. Accepts a JSON array (e.g.
|
|
74
|
+
* `["--stealth"]`) or a plain, optionally-quoted command-line string
|
|
75
|
+
* (e.g. `--stealth --browser-path /usr/bin/chromium`). This is the config-level
|
|
76
|
+
* knob for environments where Chrome needs extra launch flags — e.g. containers
|
|
77
|
+
* without unprivileged user namespaces, where `--stealth` supplies Chrome's
|
|
78
|
+
* `--no-sandbox`.
|
|
79
|
+
*/
|
|
80
|
+
function resolveExtraGsdBrowserArgs(env: NodeJS.ProcessEnv): string[] {
|
|
81
|
+
const raw = env.GSD_BROWSER_MCP_EXTRA_ARGS?.trim();
|
|
82
|
+
if (!raw) return [];
|
|
83
|
+
if (raw.startsWith("[")) {
|
|
84
|
+
const parsed = parseJsonEnv<unknown>(env, "GSD_BROWSER_MCP_EXTRA_ARGS");
|
|
85
|
+
if (!Array.isArray(parsed)) {
|
|
86
|
+
throw new Error("GSD_BROWSER_MCP_EXTRA_ARGS JSON must be an array of strings");
|
|
87
|
+
}
|
|
88
|
+
return parsed.map(String);
|
|
89
|
+
}
|
|
90
|
+
return splitCommandLine(raw);
|
|
91
|
+
}
|
|
92
|
+
|
|
69
93
|
function buildPathGsdBrowserVersionInvocation(platform: NodeJS.Platform): { command: string; args: string[] } {
|
|
70
94
|
if (platform === "win32") {
|
|
71
95
|
return { command: "cmd", args: ["/d", "/s", "/c", "gsd-browser", "--version"] };
|
|
@@ -297,6 +321,10 @@ export function resolveGsdBrowserMcpLaunchConfig(
|
|
|
297
321
|
|| (preferPathCli ? "gsd-browser" : undefined)
|
|
298
322
|
|| (bundledCliPath ? process.execPath : undefined)
|
|
299
323
|
|| "gsd-browser";
|
|
324
|
+
// Appended after the managed session/identity flags so they survive the
|
|
325
|
+
// daemon-start transformation (which forwards everything after `mcp`), letting
|
|
326
|
+
// callers add extra Chrome/gsd-browser launch flags via one config knob.
|
|
327
|
+
const extraArgs = resolveExtraGsdBrowserArgs(env);
|
|
300
328
|
const args = Array.isArray(explicitArgs) && explicitArgs.length > 0
|
|
301
329
|
? explicitArgs.map(String)
|
|
302
330
|
: [
|
|
@@ -311,6 +339,7 @@ export function resolveGsdBrowserMcpLaunchConfig(
|
|
|
311
339
|
identityKey,
|
|
312
340
|
"--identity-project",
|
|
313
341
|
identityProject,
|
|
342
|
+
...extraArgs,
|
|
314
343
|
];
|
|
315
344
|
const cwd = env.GSD_BROWSER_MCP_CWD?.trim() || resolvedProjectRoot;
|
|
316
345
|
|
|
@@ -244,6 +244,14 @@ export async function showInterviewRound(
|
|
|
244
244
|
let completed = false;
|
|
245
245
|
let removeAbortListener: (() => void) | undefined;
|
|
246
246
|
|
|
247
|
+
// Preview-panel scrolling. previewScroll is the first visible line of the
|
|
248
|
+
// side-by-side preview column; the viewport/total are captured on each
|
|
249
|
+
// render so PgUp/PgDn input can clamp against real bounds.
|
|
250
|
+
let previewScroll = 0;
|
|
251
|
+
let previewViewport = 0;
|
|
252
|
+
let previewTotal = 0;
|
|
253
|
+
function resetPreviewScroll() { previewScroll = 0; }
|
|
254
|
+
|
|
247
255
|
function finish(result: RoundResult) {
|
|
248
256
|
if (completed) return;
|
|
249
257
|
completed = true;
|
|
@@ -309,6 +317,7 @@ export async function showInterviewRound(
|
|
|
309
317
|
if (newIdx === currentIdx) return;
|
|
310
318
|
saveEditorToState();
|
|
311
319
|
currentIdx = newIdx;
|
|
320
|
+
resetPreviewScroll();
|
|
312
321
|
loadStateToEditor();
|
|
313
322
|
focusNotes = states[currentIdx].notesVisible && states[currentIdx].notes.length > 0;
|
|
314
323
|
refresh();
|
|
@@ -455,9 +464,20 @@ export async function showInterviewRound(
|
|
|
455
464
|
if (matchesKey(data, Key.right)) { switchQuestion((currentIdx + 1) % questions.length); return; }
|
|
456
465
|
}
|
|
457
466
|
|
|
467
|
+
// ── Preview scrolling ────────────────────────────────────────
|
|
468
|
+
if (matchesKey(data, Key.pageUp)) {
|
|
469
|
+
if (previewScroll > 0) { previewScroll = Math.max(0, previewScroll - previewViewport); refresh(); }
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
if (matchesKey(data, Key.pageDown)) {
|
|
473
|
+
const maxScroll = Math.max(0, previewTotal - previewViewport);
|
|
474
|
+
if (previewScroll < maxScroll) { previewScroll = Math.min(maxScroll, previewScroll + previewViewport); refresh(); }
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
458
478
|
// ── Cursor navigation ────────────────────────────────────────
|
|
459
|
-
if (matchesKey(data, Key.up)) { st.cursorIndex = (st.cursorIndex - 1 + optCount) % optCount; refresh(); return; }
|
|
460
|
-
if (matchesKey(data, Key.down)) { st.cursorIndex = (st.cursorIndex + 1) % optCount; refresh(); return; }
|
|
479
|
+
if (matchesKey(data, Key.up)) { st.cursorIndex = (st.cursorIndex - 1 + optCount) % optCount; resetPreviewScroll(); refresh(); return; }
|
|
480
|
+
if (matchesKey(data, Key.down)) { st.cursorIndex = (st.cursorIndex + 1) % optCount; resetPreviewScroll(); refresh(); return; }
|
|
461
481
|
|
|
462
482
|
if (multiSel) {
|
|
463
483
|
const doneI = noneOrDoneIdx(currentIdx);
|
|
@@ -562,6 +582,12 @@ export async function showInterviewRound(
|
|
|
562
582
|
|
|
563
583
|
// ── Preview helpers ──────────────────────────────────────────────
|
|
564
584
|
|
|
585
|
+
// Centered dim label between horizontal rules, used to mark hidden/scrollable rows.
|
|
586
|
+
function scrollIndicator(lbl: string, colWidth: number): string {
|
|
587
|
+
const d = "─".repeat(Math.max(0, Math.floor((colWidth - lbl.length - 2) / 2)));
|
|
588
|
+
return truncateToWidth(theme.fg("dim", ` ${d} ${lbl} ${d}`), colWidth);
|
|
589
|
+
}
|
|
590
|
+
|
|
565
591
|
let mdThemeCache: ReturnType<typeof getMarkdownTheme> | null = null;
|
|
566
592
|
let previewCache: { markdown: string; width: number; lines: string[] } | null = null;
|
|
567
593
|
|
|
@@ -666,6 +692,10 @@ export async function showInterviewRound(
|
|
|
666
692
|
const useSideBySide = questionHasAnyPreview()
|
|
667
693
|
&& contentWidth >= (MIN_OPTIONS_WIDTH + MIN_PREVIEW_WIDTH + DIVIDER_WIDTH);
|
|
668
694
|
|
|
695
|
+
// No scrollable preview unless the side-by-side path sets these below.
|
|
696
|
+
previewTotal = 0;
|
|
697
|
+
previewViewport = 0;
|
|
698
|
+
|
|
669
699
|
if (useSideBySide) {
|
|
670
700
|
// ── Preview path ──────────────────────────────────────
|
|
671
701
|
const ui = makeUI(theme, contentWidth);
|
|
@@ -707,19 +737,35 @@ export async function showInterviewRound(
|
|
|
707
737
|
const leftLines = fullLeft.slice(0, maxBody);
|
|
708
738
|
if (fullLeft.length > maxBody) {
|
|
709
739
|
const n = fullLeft.length - maxBody + 1;
|
|
710
|
-
|
|
711
|
-
const d = "─".repeat(Math.max(0, Math.floor((leftWidth - lbl.length - 2) / 2)));
|
|
712
|
-
leftLines[maxBody - 1] = truncateToWidth(theme.fg("dim", ` ${d} ${lbl} ${d}`), leftWidth);
|
|
740
|
+
leftLines[maxBody - 1] = scrollIndicator(`+${n} lines hidden`, leftWidth);
|
|
713
741
|
}
|
|
714
742
|
|
|
715
743
|
const preview = getCurrentPreview();
|
|
716
744
|
const fullRight = preview ? renderPreviewColumn(preview, previewWidth) : [];
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
745
|
+
// The first two lines are the pinned "Preview" header; the body
|
|
746
|
+
// below them scrolls via PgUp/PgDn so no content is unreachable.
|
|
747
|
+
const headerRows = fullRight.length > 0 ? 2 : 0;
|
|
748
|
+
const previewBody = fullRight.slice(headerRows);
|
|
749
|
+
const bodyViewport = Math.max(1, maxBody - headerRows);
|
|
750
|
+
previewTotal = previewBody.length;
|
|
751
|
+
previewViewport = bodyViewport;
|
|
752
|
+
const maxScroll = Math.max(0, previewBody.length - bodyViewport);
|
|
753
|
+
if (previewScroll > maxScroll) previewScroll = maxScroll;
|
|
754
|
+
|
|
755
|
+
const rightLines = fullRight.slice(0, headerRows);
|
|
756
|
+
if (previewBody.length <= bodyViewport) {
|
|
757
|
+
rightLines.push(...previewBody);
|
|
758
|
+
} else {
|
|
759
|
+
rightLines.push(...previewBody.slice(previewScroll, previewScroll + bodyViewport));
|
|
760
|
+
const hiddenAbove = previewScroll;
|
|
761
|
+
const hiddenBelow = previewBody.length - (previewScroll + bodyViewport);
|
|
762
|
+
// Overwrite the top/bottom visible rows with scroll indicators.
|
|
763
|
+
if (hiddenAbove > 0) {
|
|
764
|
+
rightLines[headerRows] = scrollIndicator(`▲ ${hiddenAbove} more`, previewWidth);
|
|
765
|
+
}
|
|
766
|
+
if (hiddenBelow > 0) {
|
|
767
|
+
rightLines[rightLines.length - 1] = scrollIndicator(`▼ ${hiddenBelow} more · PgUp/PgDn`, previewWidth);
|
|
768
|
+
}
|
|
723
769
|
}
|
|
724
770
|
|
|
725
771
|
while (leftLines.length < maxBody) leftLines.push("");
|
|
@@ -744,6 +790,7 @@ export async function showInterviewRound(
|
|
|
744
790
|
if (isMultiQuestion) hints.push("←/→ navigate");
|
|
745
791
|
hints.push(isLast && allAnswered() ? "enter to review" : "enter to next");
|
|
746
792
|
}
|
|
793
|
+
if (previewTotal > previewViewport) hints.push("pgup/pgdn scroll preview");
|
|
747
794
|
hints.push("esc to exit");
|
|
748
795
|
const footer = ui.hints(hints)[0] ?? "";
|
|
749
796
|
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
const ANSI_PATTERN = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
|
|
17
17
|
const ENTER = "\r";
|
|
18
18
|
const ESC = "\x1b";
|
|
19
|
+
const PAGE_DOWN = "\x1b[6~";
|
|
20
|
+
const PAGE_UP = "\x1b[5~";
|
|
19
21
|
|
|
20
22
|
before(() => { initTheme(); });
|
|
21
23
|
|
|
@@ -160,4 +162,34 @@ describe("interview-ui dialog borders", () => {
|
|
|
160
162
|
const widget = await captureWrapUpWidget();
|
|
161
163
|
assertFullOuterBorder(widget.render(80), 80);
|
|
162
164
|
});
|
|
165
|
+
|
|
166
|
+
it("makes an overflowing preview scrollable with PgUp/PgDn", async () => {
|
|
167
|
+
const longPreview = Array.from({ length: 60 }, (_, i) => `line ${i + 1}`).join("\n");
|
|
168
|
+
const widget = await captureInterviewWidget([{
|
|
169
|
+
...questions[0],
|
|
170
|
+
options: [
|
|
171
|
+
{ label: "Web App", description: "Frontend or full-stack", preview: longPreview },
|
|
172
|
+
],
|
|
173
|
+
}]);
|
|
174
|
+
|
|
175
|
+
// Initial render: content overflows, so a bottom "more" indicator and the
|
|
176
|
+
// scroll hint are shown, and the border stays intact.
|
|
177
|
+
const initial = stripAnsi(widget.render(100).join("\n"));
|
|
178
|
+
assertFullOuterBorder(widget.render(100), 100);
|
|
179
|
+
assert.match(initial, /▼ \d+ more/, "bottom scroll indicator should appear when preview overflows");
|
|
180
|
+
assert.match(initial, /pgup\/pgdn scroll preview/, "footer should hint at preview scrolling");
|
|
181
|
+
assert.doesNotMatch(initial, /▲ \d+ more/, "top indicator should be absent before scrolling");
|
|
182
|
+
|
|
183
|
+
// Scroll down: content below is now revealed and a top indicator appears.
|
|
184
|
+
widget.handleInput(PAGE_DOWN);
|
|
185
|
+
const scrolled = stripAnsi(widget.render(100).join("\n"));
|
|
186
|
+
assertFullOuterBorder(widget.render(100), 100);
|
|
187
|
+
assert.match(scrolled, /▲ \d+ more/, "top scroll indicator should appear after scrolling down");
|
|
188
|
+
assert.ok(scrolled !== initial, "scrolling should change the rendered preview");
|
|
189
|
+
|
|
190
|
+
// Scroll back up returns to the original view.
|
|
191
|
+
widget.handleInput(PAGE_UP);
|
|
192
|
+
const back = stripAnsi(widget.render(100).join("\n"));
|
|
193
|
+
assert.doesNotMatch(back, /▲ \d+ more/, "top indicator should disappear after scrolling back to top");
|
|
194
|
+
});
|
|
163
195
|
});
|