@opengsd/gsd-pi 1.1.1-dev.9f86580 → 1.1.1-dev.b2556262
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/headless-recover.js +56 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/index.js +39 -22
- package/dist/resources/extensions/browser-tools/state.js +12 -0
- package/dist/resources/extensions/browser-tools/tools/session.js +3 -2
- package/dist/resources/extensions/browser-tools/utils.js +3 -3
- package/dist/resources/extensions/gsd/auto/loop.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +43 -10
- package/dist/resources/extensions/gsd/auto/session.js +20 -1
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +72 -12
- package/dist/resources/extensions/gsd/auto-model-selection.js +128 -9
- package/dist/resources/extensions/gsd/auto-post-unit.js +19 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -19
- package/dist/resources/extensions/gsd/auto-recovery.js +4 -2
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +14 -11
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +172 -65
- package/dist/resources/extensions/gsd/closeout-wizard.js +32 -9
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -9
- package/dist/resources/extensions/gsd/commands-maintenance.js +93 -15
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +2 -2
- package/dist/resources/extensions/gsd/db-writer.js +35 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +50 -1
- package/dist/resources/extensions/gsd/gsd-db.js +480 -172
- package/dist/resources/extensions/gsd/markdown-renderer.js +37 -53
- package/dist/resources/extensions/gsd/md-importer.js +38 -3
- package/dist/resources/extensions/gsd/migration-auto-check.js +126 -31
- package/dist/resources/extensions/gsd/parsers-legacy.js +23 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +22 -4
- package/dist/resources/extensions/gsd/pre-execution-checks.js +10 -2
- package/dist/resources/extensions/gsd/preferences-models.js +110 -43
- package/dist/resources/extensions/gsd/preferences-types.js +13 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +68 -3
- package/dist/resources/extensions/gsd/preferences.js +4 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -1
- package/dist/resources/extensions/gsd/safety/content-validator.js +6 -4
- package/dist/resources/extensions/gsd/source-observations.js +306 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +15 -8
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +33 -5
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +34 -13
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +39 -14
- package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +4 -4
- package/dist/resources/extensions/gsd/state.js +7 -3
- package/dist/resources/extensions/gsd/tool-contract.js +14 -0
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +1 -9
- package/dist/resources/extensions/gsd/tools/complete-slice.js +7 -6
- package/dist/resources/extensions/gsd/tools/plan-slice.js +42 -11
- package/dist/resources/extensions/gsd/tools/plan-task.js +7 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +57 -429
- package/dist/resources/extensions/gsd/uat-policy.js +130 -0
- package/dist/resources/extensions/gsd/uat-run.js +414 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +3 -4
- package/dist/resources/extensions/gsd/verdict-parser.js +3 -8
- package/dist/resources/extensions/gsd/workflow-manifest.js +132 -5
- package/dist/resources/extensions/gsd/workflow-projections.js +8 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +18 -17
- package/dist/resources/extensions/subagent/agents.js +1 -0
- package/dist/resources/extensions/subagent/index.js +27 -12
- package/dist/resources/extensions/subagent/launch.js +7 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- 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/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 +8 -8
- 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/web/standalone/node_modules/@gsd/native/dist/native.js +22 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +4 -4
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +21 -23
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +66 -12
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +18 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +16 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/dist/native.js +22 -0
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +30 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.js +30 -0
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +23 -17
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +25 -24
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/themes.js +1 -1
- package/packages/pi-coding-agent/dist/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/utils.d.ts +11 -0
- package/packages/pi-tui/dist/utils.d.ts.map +1 -1
- package/packages/pi-tui/dist/utils.js +119 -6
- package/packages/pi-tui/dist/utils.js.map +1 -1
- package/packages/pi-tui/package.json +2 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/themes.js +1 -1
- package/pkg/dist/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/index.ts +39 -22
- package/src/resources/extensions/browser-tools/state.ts +13 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +57 -0
- package/src/resources/extensions/browser-tools/tools/session.ts +4 -2
- package/src/resources/extensions/browser-tools/utils.ts +3 -3
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +42 -10
- package/src/resources/extensions/gsd/auto/session.ts +22 -1
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +85 -12
- package/src/resources/extensions/gsd/auto-model-selection.ts +164 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +20 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +23 -20
- package/src/resources/extensions/gsd/auto-recovery.ts +22 -3
- package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +13 -10
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +225 -72
- package/src/resources/extensions/gsd/closeout-wizard.ts +47 -13
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -17
- package/src/resources/extensions/gsd/commands-maintenance.ts +124 -13
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +2 -2
- package/src/resources/extensions/gsd/db-writer.ts +38 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +50 -1
- package/src/resources/extensions/gsd/gsd-db.ts +564 -186
- package/src/resources/extensions/gsd/markdown-renderer.ts +44 -66
- package/src/resources/extensions/gsd/md-importer.ts +49 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +154 -34
- package/src/resources/extensions/gsd/parsers-legacy.ts +20 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +22 -4
- package/src/resources/extensions/gsd/pre-execution-checks.ts +9 -2
- package/src/resources/extensions/gsd/preferences-models.ts +112 -43
- package/src/resources/extensions/gsd/preferences-types.ts +39 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +76 -2
- package/src/resources/extensions/gsd/preferences.ts +5 -0
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +6 -1
- package/src/resources/extensions/gsd/safety/content-validator.ts +8 -5
- package/src/resources/extensions/gsd/source-observations.ts +402 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +20 -8
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +44 -5
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +39 -11
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +45 -15
- package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +4 -4
- package/src/resources/extensions/gsd/state.ts +7 -4
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +299 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +75 -3
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/closeout-wizard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/content-validator.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +16 -2
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +1 -11
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +62 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +99 -2
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +162 -18
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/source-observations.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +76 -21
- package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +306 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +73 -6
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +511 -1
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +44 -0
- package/src/resources/extensions/gsd/tool-contract.ts +28 -0
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +1 -11
- package/src/resources/extensions/gsd/tools/complete-slice.ts +7 -6
- package/src/resources/extensions/gsd/tools/plan-slice.ts +54 -12
- package/src/resources/extensions/gsd/tools/plan-task.ts +8 -1
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +66 -526
- package/src/resources/extensions/gsd/types.ts +1 -0
- package/src/resources/extensions/gsd/uat-policy.ts +191 -0
- package/src/resources/extensions/gsd/uat-run.ts +550 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +3 -4
- package/src/resources/extensions/gsd/verdict-parser.ts +3 -10
- package/src/resources/extensions/gsd/workflow-manifest.ts +193 -7
- package/src/resources/extensions/gsd/workflow-projections.ts +9 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +22 -22
- package/src/resources/extensions/shared/tests/format-utils.test.ts +8 -3
- package/src/resources/extensions/subagent/agents.ts +4 -0
- package/src/resources/extensions/subagent/index.ts +28 -3
- package/src/resources/extensions/subagent/launch.ts +8 -0
- package/src/resources/extensions/subagent/tests/model-override.test.ts +31 -0
- /package/dist/web/standalone/.next/static/{zzYMrKpPGfRQRxSFO32Jr → tJOKQbQRO-9MiFDO8DIDS}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{zzYMrKpPGfRQRxSFO32Jr → tJOKQbQRO-9MiFDO8DIDS}/_ssgManifest.js +0 -0
|
@@ -1246,7 +1246,7 @@ export async function cleanupAfterLoopExit(ctx: ExtensionContext): Promise<void>
|
|
|
1246
1246
|
const preserveStepSurface = s.preserveStepSurfaceAfterLoopExit;
|
|
1247
1247
|
const preserveCompletionSurface = s.completionStopInProgress;
|
|
1248
1248
|
const preservePausedSurface = s.paused;
|
|
1249
|
-
s.
|
|
1249
|
+
s.clearCurrentUnit();
|
|
1250
1250
|
s.active = false;
|
|
1251
1251
|
deactivateGSD();
|
|
1252
1252
|
clearUnitTimeout();
|
|
@@ -1269,11 +1269,14 @@ export async function cleanupAfterLoopExit(ctx: ExtensionContext): Promise<void>
|
|
|
1269
1269
|
// A transient provider-error pause intentionally leaves the paused badge
|
|
1270
1270
|
// visible so the user still has a resumable auto-mode signal on screen.
|
|
1271
1271
|
if (!s.paused) {
|
|
1272
|
-
if (
|
|
1273
|
-
s.preserveStepSurfaceAfterLoopExit = false;
|
|
1274
|
-
} else if (preserveCompletionSurface) {
|
|
1272
|
+
if (preserveCompletionSurface) {
|
|
1275
1273
|
ctx.ui.setStatus("gsd-auto", undefined);
|
|
1276
1274
|
s.completionStopInProgress = false;
|
|
1275
|
+
if (preserveStepSurface) {
|
|
1276
|
+
s.preserveStepSurfaceAfterLoopExit = false;
|
|
1277
|
+
}
|
|
1278
|
+
} else if (preserveStepSurface) {
|
|
1279
|
+
s.preserveStepSurfaceAfterLoopExit = false;
|
|
1277
1280
|
} else {
|
|
1278
1281
|
ctx.ui.setStatus("gsd-auto", undefined);
|
|
1279
1282
|
ctx.ui.setWidget("gsd-progress", undefined);
|
|
@@ -1987,7 +1990,7 @@ export async function pauseAuto(
|
|
|
1987
1990
|
// Non-fatal — best-effort closeout on pause
|
|
1988
1991
|
logWarning("engine", `unit closeout on pause failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1989
1992
|
}
|
|
1990
|
-
s.
|
|
1993
|
+
s.clearCurrentUnit();
|
|
1991
1994
|
}
|
|
1992
1995
|
|
|
1993
1996
|
// Keep STATE.md aligned with the DB-backed state before releasing pause state.
|
|
@@ -3308,7 +3311,7 @@ export async function dispatchHookUnit(
|
|
|
3308
3311
|
s.stepMode = true;
|
|
3309
3312
|
s.cmdCtx = ctx as ExtensionCommandContext;
|
|
3310
3313
|
s.autoStartTime = Date.now();
|
|
3311
|
-
s.
|
|
3314
|
+
s.clearCurrentUnit();
|
|
3312
3315
|
s.pendingQuickTasks = [];
|
|
3313
3316
|
}
|
|
3314
3317
|
|
|
@@ -3325,12 +3328,12 @@ export async function dispatchHookUnit(
|
|
|
3325
3328
|
const hookUnitType = `hook/${hookName}`;
|
|
3326
3329
|
const hookStartedAt = Date.now();
|
|
3327
3330
|
|
|
3328
|
-
s.
|
|
3331
|
+
s.setCurrentUnit({
|
|
3329
3332
|
type: triggerUnitType,
|
|
3330
3333
|
id: triggerUnitId,
|
|
3331
3334
|
startedAt: hookStartedAt,
|
|
3332
3335
|
workspaceRoot: s.basePath,
|
|
3333
|
-
};
|
|
3336
|
+
});
|
|
3334
3337
|
|
|
3335
3338
|
const result = await s.cmdCtx!.newSession({ workspaceRoot: s.basePath });
|
|
3336
3339
|
if (result.cancelled) {
|
|
@@ -3338,12 +3341,12 @@ export async function dispatchHookUnit(
|
|
|
3338
3341
|
return false;
|
|
3339
3342
|
}
|
|
3340
3343
|
|
|
3341
|
-
s.
|
|
3344
|
+
s.setCurrentUnit({
|
|
3342
3345
|
type: hookUnitType,
|
|
3343
3346
|
id: triggerUnitId,
|
|
3344
3347
|
startedAt: hookStartedAt,
|
|
3345
3348
|
workspaceRoot: s.basePath,
|
|
3346
|
-
};
|
|
3349
|
+
});
|
|
3347
3350
|
|
|
3348
3351
|
if (hookModel) {
|
|
3349
3352
|
const availableModels = ctx.modelRegistry.getAvailable();
|
|
@@ -699,7 +699,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
699
699
|
files: Type.Array(Type.String(), { description: "Array<string> of files likely touched; pass [\"path\"] or [], never a single string" }),
|
|
700
700
|
verify: Type.String({ description: "Verification command or block" }),
|
|
701
701
|
inputs: Type.Array(Type.String(), { description: "Array<string> of input files or references; pass [\"path\"] or [], never a single string" }),
|
|
702
|
-
expectedOutput: Type.Array(Type.String(), { description: "Array<string> of
|
|
702
|
+
expectedOutput: Type.Array(Type.String(), { description: "Array<string> of files this task creates or overwrites; pass [\"path\"] or [], never prose or a single string" }),
|
|
703
703
|
observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
|
|
704
704
|
}), { description: "Planned tasks for the slice" }),
|
|
705
705
|
// ── Enrichment metadata (optional — defaults to empty) ────────────
|
|
@@ -779,7 +779,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
779
779
|
files: Type.Array(Type.String(), { description: "Array<string> of files likely touched; pass [\"path\"] or [], never a single string" }),
|
|
780
780
|
verify: Type.String({ description: "Verification command or block" }),
|
|
781
781
|
inputs: Type.Array(Type.String(), { description: "Array<string> of input files or references; pass [\"path\"] or [], never a single string" }),
|
|
782
|
-
expectedOutput: Type.Array(Type.String(), { description: "Array<string> of
|
|
782
|
+
expectedOutput: Type.Array(Type.String(), { description: "Array<string> of files this task creates or overwrites; pass [\"path\"] or [], never prose or a single string" }),
|
|
783
783
|
observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
|
|
784
784
|
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
785
785
|
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
@@ -1160,7 +1160,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1160
1160
|
files: Type.Array(Type.String(), { description: "Files likely touched" }),
|
|
1161
1161
|
verify: Type.String({ description: "Verification command or block" }),
|
|
1162
1162
|
inputs: Type.Array(Type.String(), { description: "Input files or references" }),
|
|
1163
|
-
expectedOutput: Type.Array(Type.String(), { description: "
|
|
1163
|
+
expectedOutput: Type.Array(Type.String(), { description: "Files this task creates or overwrites" }),
|
|
1164
1164
|
}),
|
|
1165
1165
|
{ description: "Tasks to upsert (update existing or insert new)" },
|
|
1166
1166
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Registers GSD extension runtime hooks and token-saving tool policies.
|
|
3
3
|
|
|
4
|
-
import { existsSync } from "node:fs";
|
|
4
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
|
|
@@ -12,12 +12,22 @@ import { ALWAYS_PRESERVED_SHIM_TOOL_NAMES } from "@gsd/pi-ai";
|
|
|
12
12
|
import type { GSDEcosystemBeforeAgentStartHandler } from "../ecosystem/gsd-extension-api.js";
|
|
13
13
|
import { updateSnapshot } from "../ecosystem/gsd-extension-api.js";
|
|
14
14
|
|
|
15
|
-
import { buildMilestoneFileName, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
|
|
15
|
+
import { buildMilestoneFileName, clearPathCache, milestonesDir, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
|
|
16
16
|
import { canonicalToolName, clearDiscussionFlowState, isDepthConfirmationAnswer, isMilestoneDepthVerified, isQueuePhaseActive, markApprovalGateVerified, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, shouldBlockWorktreeWrite, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
|
|
17
17
|
import { resolveManifest } from "../unit-context-manifest.js";
|
|
18
18
|
import { isBlockedStateFile, isBashWriteToStateFile, BLOCKED_WRITE_ERROR } from "../write-intercept.js";
|
|
19
19
|
import { loadFile, saveFile, formatContinue } from "../files.js";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
clearToolInvocationError,
|
|
22
|
+
getAutoRuntimeSnapshot,
|
|
23
|
+
getSourceObservationStore,
|
|
24
|
+
isAutoActive,
|
|
25
|
+
isAutoCompletionStopInProgress,
|
|
26
|
+
isAutoPaused,
|
|
27
|
+
markToolEnd,
|
|
28
|
+
markToolStart,
|
|
29
|
+
recordToolInvocationError,
|
|
30
|
+
} from "../auto-runtime-state.js";
|
|
21
31
|
|
|
22
32
|
import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
|
|
23
33
|
import { maybePauseAutoForApprovalGate, resetPendingGatePauseGuard } from "./pending-gate-pause.js";
|
|
@@ -39,6 +49,7 @@ import { registerPlanMilestoneSchemaRecovery } from "./plan-milestone-schema-rec
|
|
|
39
49
|
import { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, isWorkflowAliasTool } from "../auto-unit-tool-scope.js";
|
|
40
50
|
import { filterToolsForProvider } from "../model-router.js";
|
|
41
51
|
import { RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES } from "../tool-presentation-plan.js";
|
|
52
|
+
import { injectSourceContextBlockIntoPayload, supportsSourceObservationsForUnit } from "../source-observations.js";
|
|
42
53
|
|
|
43
54
|
let approvalQuestionAbortInFlight = false;
|
|
44
55
|
|
|
@@ -474,6 +485,55 @@ function contextBasePath(ctx?: { cwd?: string }): string {
|
|
|
474
485
|
return typeof ctx?.cwd === "string" ? ctx.cwd : process.cwd();
|
|
475
486
|
}
|
|
476
487
|
|
|
488
|
+
function beginSourceObservationStoreForCurrentUnit(
|
|
489
|
+
ctx?: { cwd?: string },
|
|
490
|
+
): ReturnType<typeof getSourceObservationStore> | null {
|
|
491
|
+
if (!isAutoActive()) return null;
|
|
492
|
+
const dash = getAutoRuntimeSnapshot();
|
|
493
|
+
if (!dash.currentUnit) return null;
|
|
494
|
+
if (!supportsSourceObservationsForUnit(dash.currentUnit.type)) return null;
|
|
495
|
+
|
|
496
|
+
const store = getSourceObservationStore();
|
|
497
|
+
store.beginUnit({
|
|
498
|
+
unitType: dash.currentUnit.type,
|
|
499
|
+
unitId: dash.currentUnit.id,
|
|
500
|
+
startedAt: dash.currentUnit.startedAt,
|
|
501
|
+
basePath: dash.currentUnit.workspaceRoot ?? (dash.basePath || contextBasePath(ctx)),
|
|
502
|
+
});
|
|
503
|
+
return store;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function refreshSourceObservationAfterMutation(
|
|
507
|
+
canonicalName: string,
|
|
508
|
+
input: unknown,
|
|
509
|
+
ctx?: { cwd?: string },
|
|
510
|
+
): void {
|
|
511
|
+
if (canonicalName !== "edit" && canonicalName !== "write") return;
|
|
512
|
+
if (!input || typeof input !== "object") return;
|
|
513
|
+
|
|
514
|
+
const store = beginSourceObservationStoreForCurrentUnit(ctx);
|
|
515
|
+
if (!store) return;
|
|
516
|
+
store.observeMutation(input as { path?: unknown; file_path?: unknown });
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function clearSourceObservationsAfterShell(
|
|
520
|
+
canonicalName: string,
|
|
521
|
+
): void {
|
|
522
|
+
if (!isAutoActive()) return;
|
|
523
|
+
if (!isShellExecutionTool(canonicalName)) return;
|
|
524
|
+
const dash = getAutoRuntimeSnapshot();
|
|
525
|
+
if (!dash.currentUnit || !supportsSourceObservationsForUnit(dash.currentUnit.type)) return;
|
|
526
|
+
getSourceObservationStore().clear();
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function isShellExecutionTool(canonicalName: string): boolean {
|
|
530
|
+
return canonicalName === "bash" ||
|
|
531
|
+
canonicalName === "bg_shell" ||
|
|
532
|
+
canonicalName === "async_bash" ||
|
|
533
|
+
canonicalName === "shell" ||
|
|
534
|
+
canonicalName === "powershell";
|
|
535
|
+
}
|
|
536
|
+
|
|
477
537
|
function activateDeferredApprovalGate(basePath: string): void {
|
|
478
538
|
if (deferredApprovalGate?.basePath !== basePath) return;
|
|
479
539
|
setPendingGate(deferredApprovalGate.gateId, basePath);
|
|
@@ -497,6 +557,109 @@ function isContextDraftSummarySave(toolName: string, input: unknown): boolean {
|
|
|
497
557
|
return (input as { artifact_type?: unknown }).artifact_type === "CONTEXT-DRAFT";
|
|
498
558
|
}
|
|
499
559
|
|
|
560
|
+
type StructuredQuestion = {
|
|
561
|
+
id?: string;
|
|
562
|
+
header?: string;
|
|
563
|
+
question?: string;
|
|
564
|
+
options?: Array<{ label?: string; description?: string }>;
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
type StructuredAnswer = {
|
|
568
|
+
selected?: unknown;
|
|
569
|
+
notes?: unknown;
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
function selectedAnswerLabel(selected: unknown): string {
|
|
573
|
+
if (Array.isArray(selected)) return selected.map(String).join(", ");
|
|
574
|
+
if (selected == null) return "";
|
|
575
|
+
return String(selected);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function formatQuestionExchange(
|
|
579
|
+
questions: StructuredQuestion[],
|
|
580
|
+
answers: Record<string, StructuredAnswer> | undefined,
|
|
581
|
+
): string {
|
|
582
|
+
const lines: string[] = [];
|
|
583
|
+
for (const question of questions) {
|
|
584
|
+
lines.push(`### ${question.header ?? "Question"}`, "", question.question ?? "");
|
|
585
|
+
if (Array.isArray(question.options)) {
|
|
586
|
+
lines.push("");
|
|
587
|
+
for (const opt of question.options) {
|
|
588
|
+
lines.push(`- **${opt.label ?? ""}** — ${opt.description ?? ""}`);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const answer = question.id ? answers?.[question.id] : undefined;
|
|
593
|
+
if (answer) {
|
|
594
|
+
lines.push("");
|
|
595
|
+
const selected = selectedAnswerLabel(answer.selected);
|
|
596
|
+
if (selected) lines.push(`**Selected:** ${selected}`);
|
|
597
|
+
if (answer.notes) lines.push(`**Notes:** ${String(answer.notes)}`);
|
|
598
|
+
}
|
|
599
|
+
lines.push("");
|
|
600
|
+
}
|
|
601
|
+
return lines.join("\n");
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
async function ensureMilestoneShell(basePath: string, milestoneId: string): Promise<string> {
|
|
605
|
+
const milestoneDir = resolveMilestonePath(basePath, milestoneId)
|
|
606
|
+
?? join(milestonesDir(basePath), milestoneId);
|
|
607
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
608
|
+
clearPathCache();
|
|
609
|
+
|
|
610
|
+
try {
|
|
611
|
+
const { ensureDbOpen } = await import("./dynamic-tools.js");
|
|
612
|
+
if (await ensureDbOpen(basePath)) {
|
|
613
|
+
const { getMilestone, insertMilestone } = await import("../gsd-db.js");
|
|
614
|
+
if (!getMilestone(milestoneId)) {
|
|
615
|
+
insertMilestone({
|
|
616
|
+
id: milestoneId,
|
|
617
|
+
title: `New milestone ${milestoneId}`,
|
|
618
|
+
status: "queued",
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
} catch (err) {
|
|
623
|
+
safetyLogWarning("guided", `failed to persist milestone shell for ${milestoneId}: ${(err as Error).message}`);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return milestoneDir;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
async function saveDiscussionQuestionRound(
|
|
630
|
+
basePath: string,
|
|
631
|
+
milestoneId: string,
|
|
632
|
+
questions: StructuredQuestion[],
|
|
633
|
+
details: any,
|
|
634
|
+
): Promise<void> {
|
|
635
|
+
const milestoneDir = await ensureMilestoneShell(basePath, milestoneId);
|
|
636
|
+
const answers = details?.response?.answers;
|
|
637
|
+
const timestamp = new Date().toISOString();
|
|
638
|
+
const exchange = formatQuestionExchange(questions, answers);
|
|
639
|
+
|
|
640
|
+
const discussionPath = join(milestoneDir, buildMilestoneFileName(milestoneId, "DISCUSSION"));
|
|
641
|
+
const existingDiscussion = await loadFile(discussionPath) ?? `# ${milestoneId} Discussion Log\n\n`;
|
|
642
|
+
await saveFile(
|
|
643
|
+
discussionPath,
|
|
644
|
+
`${existingDiscussion}## Exchange — ${timestamp}\n\n${exchange}---\n\n`,
|
|
645
|
+
);
|
|
646
|
+
|
|
647
|
+
const draftPath = join(milestoneDir, buildMilestoneFileName(milestoneId, "CONTEXT-DRAFT"));
|
|
648
|
+
const existingDraft = await loadFile(draftPath);
|
|
649
|
+
const draftHeader = existingDraft
|
|
650
|
+
?? [
|
|
651
|
+
`# ${milestoneId}: New milestone ${milestoneId}`,
|
|
652
|
+
"",
|
|
653
|
+
"This draft was captured automatically from structured question responses.",
|
|
654
|
+
"Use it so `/gsd` can resume the in-flight milestone discussion.",
|
|
655
|
+
"",
|
|
656
|
+
].join("\n");
|
|
657
|
+
await saveFile(
|
|
658
|
+
draftPath,
|
|
659
|
+
`${draftHeader.trimEnd()}\n\n## Captured Question Round — ${timestamp}\n\n${exchange}`,
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
|
|
500
663
|
function withDepthGateDisplayReason<T extends { block: boolean; reason?: string }>(
|
|
501
664
|
result: T,
|
|
502
665
|
displayReason = "Depth confirmation is waiting for your answer.",
|
|
@@ -1129,6 +1292,17 @@ export function registerHooks(
|
|
|
1129
1292
|
if (isAutoActive() && typeof event.toolCallId === "string") {
|
|
1130
1293
|
markToolEnd(event.toolCallId);
|
|
1131
1294
|
}
|
|
1295
|
+
const toolName = canonicalToolName(event.toolName);
|
|
1296
|
+
if (isAutoActive() && toolName === "read" && !event.isError) {
|
|
1297
|
+
const store = beginSourceObservationStoreForCurrentUnit(ctx);
|
|
1298
|
+
if (store) {
|
|
1299
|
+
store.observeRead(event.input);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
if (!event.isError) {
|
|
1303
|
+
refreshSourceObservationAfterMutation(toolName, event.input, ctx);
|
|
1304
|
+
clearSourceObservationsAfterShell(toolName);
|
|
1305
|
+
}
|
|
1132
1306
|
if (isAutoActive() && event.isError) {
|
|
1133
1307
|
const resultPayload = ("result" in event ? event.result : undefined) as any;
|
|
1134
1308
|
const errorText = typeof resultPayload === "string"
|
|
@@ -1144,11 +1318,9 @@ export function registerHooks(
|
|
|
1144
1318
|
} else if (isAutoActive()) {
|
|
1145
1319
|
clearToolInvocationError();
|
|
1146
1320
|
}
|
|
1147
|
-
const toolName = canonicalToolName(event.toolName);
|
|
1148
1321
|
if (toolName !== "ask_user_questions") return;
|
|
1149
1322
|
const basePath = contextBasePath(ctx);
|
|
1150
1323
|
const milestoneId = await getDiscussionMilestoneIdFor(basePath);
|
|
1151
|
-
const queueActive = isQueuePhaseActive(basePath);
|
|
1152
1324
|
|
|
1153
1325
|
const details = event.details as any;
|
|
1154
1326
|
|
|
@@ -1227,36 +1399,8 @@ export function registerHooks(
|
|
|
1227
1399
|
}
|
|
1228
1400
|
}
|
|
1229
1401
|
|
|
1230
|
-
if (!milestoneId && !queueActive) return;
|
|
1231
1402
|
if (!milestoneId) return;
|
|
1232
|
-
|
|
1233
|
-
if (!milestoneDir) return;
|
|
1234
|
-
|
|
1235
|
-
const discussionPath = join(milestoneDir, buildMilestoneFileName(milestoneId, "DISCUSSION"));
|
|
1236
|
-
const timestamp = new Date().toISOString();
|
|
1237
|
-
const lines: string[] = [`## Exchange — ${timestamp}`, ""];
|
|
1238
|
-
for (const question of questions) {
|
|
1239
|
-
lines.push(`### ${question.header ?? "Question"}`, "", question.question ?? "");
|
|
1240
|
-
if (Array.isArray(question.options)) {
|
|
1241
|
-
lines.push("");
|
|
1242
|
-
for (const opt of question.options) {
|
|
1243
|
-
lines.push(`- **${opt.label}** — ${opt.description ?? ""}`);
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
const answer = details.response?.answers?.[question.id];
|
|
1247
|
-
if (answer) {
|
|
1248
|
-
lines.push("");
|
|
1249
|
-
const selected = Array.isArray(answer.selected) ? answer.selected.join(", ") : answer.selected;
|
|
1250
|
-
lines.push(`**Selected:** ${selected}`);
|
|
1251
|
-
if (answer.notes) {
|
|
1252
|
-
lines.push(`**Notes:** ${answer.notes}`);
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
lines.push("");
|
|
1256
|
-
}
|
|
1257
|
-
lines.push("---", "");
|
|
1258
|
-
const existing = await loadFile(discussionPath) ?? `# ${milestoneId} Discussion Log\n\n`;
|
|
1259
|
-
await saveFile(discussionPath, existing + lines.join("\n"));
|
|
1403
|
+
await saveDiscussionQuestionRound(basePath, milestoneId, questions, details);
|
|
1260
1404
|
});
|
|
1261
1405
|
|
|
1262
1406
|
pi.on("tool_execution_start", async (event, ctx) => {
|
|
@@ -1310,48 +1454,57 @@ export function registerHooks(
|
|
|
1310
1454
|
const payload = event.payload as Record<string, unknown> | null;
|
|
1311
1455
|
if (!payload || typeof payload !== "object") return;
|
|
1312
1456
|
|
|
1313
|
-
// ──
|
|
1314
|
-
//
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
payload.messages = createObservationMask(keepTurns)(messages);
|
|
1334
|
-
}
|
|
1335
|
-
const input = payload.input;
|
|
1336
|
-
if (Array.isArray(input)) {
|
|
1337
|
-
payload.input = createResponsesInputObservationMask(keepTurns)(input);
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
// Tool result truncation: cap individual tool result content length.
|
|
1342
|
-
// In pi-ai format, toolResult messages have role: "toolResult" and content: TextContent[].
|
|
1343
|
-
// Creates new objects to avoid mutating shared conversation state.
|
|
1344
|
-
const maxChars = cmConfig?.tool_result_max_chars ?? 800;
|
|
1345
|
-
const msgs = payload.messages;
|
|
1346
|
-
if (Array.isArray(msgs)) {
|
|
1347
|
-
payload.messages = truncateContextResultMessages(msgs as any, maxChars);
|
|
1457
|
+
// ── Context Management ──────────────────────────────────────────────
|
|
1458
|
+
// Load preferences once for both masking and truncation.
|
|
1459
|
+
try {
|
|
1460
|
+
const { loadEffectiveGSDPreferences } = await import("../preferences.js");
|
|
1461
|
+
const {
|
|
1462
|
+
createObservationMask,
|
|
1463
|
+
createResponsesInputObservationMask,
|
|
1464
|
+
truncateContextResultMessages,
|
|
1465
|
+
truncateResponsesInputResultItems,
|
|
1466
|
+
} = await import("../context-masker.js");
|
|
1467
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
1468
|
+
const cmConfig = prefs?.preferences.context_management;
|
|
1469
|
+
|
|
1470
|
+
// Observation masking: replace old tool results with placeholders.
|
|
1471
|
+
// Only active during auto-mode when context_management.observation_masking is enabled.
|
|
1472
|
+
if (isAutoActive() && cmConfig?.observation_masking !== false) {
|
|
1473
|
+
const keepTurns = cmConfig?.observation_mask_turns ?? 8;
|
|
1474
|
+
const messages = payload.messages;
|
|
1475
|
+
if (Array.isArray(messages)) {
|
|
1476
|
+
payload.messages = createObservationMask(keepTurns)(messages);
|
|
1348
1477
|
}
|
|
1349
1478
|
const input = payload.input;
|
|
1350
1479
|
if (Array.isArray(input)) {
|
|
1351
|
-
payload.input =
|
|
1480
|
+
payload.input = createResponsesInputObservationMask(keepTurns)(input);
|
|
1352
1481
|
}
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
// Tool result truncation: cap individual tool result content length.
|
|
1485
|
+
// Applies in ALL modes (auto + interactive) to prevent context bloat.
|
|
1486
|
+
// In pi-ai format, toolResult messages have role: "toolResult" and content: TextContent[].
|
|
1487
|
+
// Creates new objects to avoid mutating shared conversation state.
|
|
1488
|
+
const maxChars = cmConfig?.tool_result_max_chars ?? 800;
|
|
1489
|
+
const msgs = payload.messages;
|
|
1490
|
+
if (Array.isArray(msgs)) {
|
|
1491
|
+
payload.messages = truncateContextResultMessages(msgs as any, maxChars);
|
|
1492
|
+
}
|
|
1493
|
+
const input = payload.input;
|
|
1494
|
+
if (Array.isArray(input)) {
|
|
1495
|
+
payload.input = truncateResponsesInputResultItems(input as any, maxChars);
|
|
1496
|
+
}
|
|
1497
|
+
} catch { /* non-fatal */ }
|
|
1498
|
+
|
|
1499
|
+
try {
|
|
1500
|
+
if (isAutoActive()) {
|
|
1501
|
+
const sourceContextBlock = getSourceObservationStore().renderActiveBlock();
|
|
1502
|
+
if (sourceContextBlock) {
|
|
1503
|
+
const nextPayload = injectSourceContextBlockIntoPayload(payload, sourceContextBlock);
|
|
1504
|
+
Object.assign(payload, nextPayload);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
} catch { /* non-fatal */ }
|
|
1355
1508
|
|
|
1356
1509
|
// ── Service Tier ────────────────────────────────────────────────────
|
|
1357
1510
|
const modelId = event.model?.id;
|
|
@@ -5,6 +5,7 @@ import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
|
5
5
|
|
|
6
6
|
import type { NextAction } from "../shared/next-action-ui.js";
|
|
7
7
|
import type { GSDState } from "./types.js";
|
|
8
|
+
import { setAutoOutcomeWidget } from "./auto-dashboard.js";
|
|
8
9
|
import { invalidateAllCaches } from "./cache.js";
|
|
9
10
|
import { mergeCompletedMilestone } from "./parallel-merge.js";
|
|
10
11
|
import { cleanupQuickBranch, detectStrandedQuickBranch, type StrandedQuickBranch } from "./quick.js";
|
|
@@ -21,6 +22,13 @@ export interface CloseoutContext {
|
|
|
21
22
|
unmergedMilestones: UnmergedMilestoneBlocker[];
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
const MILESTONE_MERGE_CLOSEOUT_COMMANDS = [
|
|
26
|
+
"/gsd status for overview",
|
|
27
|
+
"/gsd visualize to inspect",
|
|
28
|
+
"/gsd notifications for history",
|
|
29
|
+
"/gsd start for new work",
|
|
30
|
+
];
|
|
31
|
+
|
|
24
32
|
export async function loadCloseoutContext(basePath: string): Promise<CloseoutContext> {
|
|
25
33
|
const unmergedMilestones = await findUnmergedCompletedMilestones(basePath);
|
|
26
34
|
return {
|
|
@@ -91,6 +99,23 @@ export function buildIdleMenuSummary(state: GSDState, closeout: CloseoutContext)
|
|
|
91
99
|
return [state.nextAction || "No active milestone."];
|
|
92
100
|
}
|
|
93
101
|
|
|
102
|
+
export function showMilestoneMergeCloseout(
|
|
103
|
+
ctx: ExtensionCommandContext,
|
|
104
|
+
blocker: UnmergedMilestoneBlocker,
|
|
105
|
+
): void {
|
|
106
|
+
ctx.ui.setStatus?.("gsd-auto", undefined);
|
|
107
|
+
ctx.ui.setStatus?.("gsd-step", undefined);
|
|
108
|
+
ctx.ui.setWidget?.("gsd-progress", undefined);
|
|
109
|
+
|
|
110
|
+
setAutoOutcomeWidget(ctx, {
|
|
111
|
+
status: "complete",
|
|
112
|
+
title: `Milestone ${blocker.milestoneId} merged`,
|
|
113
|
+
detail: `Merged ${blocker.branch} into ${blocker.integrationBranch}. Product changes are now on ${blocker.integrationBranch}.`,
|
|
114
|
+
nextAction: "Review the closeout, then start the next milestone when ready.",
|
|
115
|
+
commands: MILESTONE_MERGE_CLOSEOUT_COMMANDS,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
94
119
|
export async function runMergeQuickTask(
|
|
95
120
|
ctx: ExtensionCommandContext,
|
|
96
121
|
basePath: string,
|
|
@@ -113,31 +138,23 @@ export async function runMergeQuickTask(
|
|
|
113
138
|
return false;
|
|
114
139
|
}
|
|
115
140
|
|
|
116
|
-
export async function
|
|
141
|
+
export async function runMergeMilestoneBlocker(
|
|
117
142
|
ctx: ExtensionCommandContext,
|
|
118
143
|
basePath: string,
|
|
119
|
-
|
|
144
|
+
blocker: UnmergedMilestoneBlocker,
|
|
120
145
|
): Promise<boolean> {
|
|
121
|
-
const blockers = await findUnmergedCompletedMilestones(basePath);
|
|
122
|
-
const blocker = milestoneId
|
|
123
|
-
? blockers.find((candidate) => candidate.milestoneId === milestoneId)
|
|
124
|
-
: blockers[0];
|
|
125
|
-
if (!blocker) {
|
|
126
|
-
ctx.ui.notify("No unmerged completed milestone found.", "warning");
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
146
|
ctx.ui.notify(
|
|
131
147
|
`Completing preserved milestone merge for ${blocker.milestoneId} from ${blocker.branch} into ${blocker.integrationBranch}.`,
|
|
132
148
|
"info",
|
|
133
149
|
);
|
|
134
150
|
const result = await mergeCompletedMilestone(basePath, blocker.milestoneId);
|
|
135
151
|
if (result.success) {
|
|
152
|
+
invalidateAllCaches();
|
|
153
|
+
showMilestoneMergeCloseout(ctx, blocker);
|
|
136
154
|
ctx.ui.notify(
|
|
137
|
-
`Milestone ${blocker.milestoneId} merged to ${blocker.integrationBranch}.
|
|
155
|
+
`Milestone ${blocker.milestoneId} merged to ${blocker.integrationBranch}. Closeout is complete.`,
|
|
138
156
|
"info",
|
|
139
157
|
);
|
|
140
|
-
invalidateAllCaches();
|
|
141
158
|
return true;
|
|
142
159
|
}
|
|
143
160
|
|
|
@@ -148,6 +165,23 @@ export async function runMergeMilestone(
|
|
|
148
165
|
return false;
|
|
149
166
|
}
|
|
150
167
|
|
|
168
|
+
export async function runMergeMilestone(
|
|
169
|
+
ctx: ExtensionCommandContext,
|
|
170
|
+
basePath: string,
|
|
171
|
+
milestoneId?: string,
|
|
172
|
+
): Promise<boolean> {
|
|
173
|
+
const blockers = await findUnmergedCompletedMilestones(basePath);
|
|
174
|
+
const blocker = milestoneId
|
|
175
|
+
? blockers.find((candidate) => candidate.milestoneId === milestoneId)
|
|
176
|
+
: blockers[0];
|
|
177
|
+
if (!blocker) {
|
|
178
|
+
ctx.ui.notify("No unmerged completed milestone found.", "warning");
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return runMergeMilestoneBlocker(ctx, basePath, blocker);
|
|
183
|
+
}
|
|
184
|
+
|
|
151
185
|
export async function handleCloseoutChoice(
|
|
152
186
|
ctx: ExtensionCommandContext,
|
|
153
187
|
basePath: string,
|
|
@@ -19,7 +19,7 @@ import { handleSessionReport } from "../../commands-session-report.js";
|
|
|
19
19
|
import { handlePrBranch } from "../../commands-pr-branch.js";
|
|
20
20
|
import { currentDirectoryRoot, projectRoot } from "../context.js";
|
|
21
21
|
import { findUnmergedCompletedMilestones } from "../../unmerged-milestone-guard.js";
|
|
22
|
-
import {
|
|
22
|
+
import { runMergeMilestoneBlocker } from "../../closeout-wizard.js";
|
|
23
23
|
|
|
24
24
|
async function handleCompletedMilestoneRecovery(
|
|
25
25
|
phase: string,
|
|
@@ -37,22 +37,7 @@ async function handleCompletedMilestoneRecovery(
|
|
|
37
37
|
: blockers[0];
|
|
38
38
|
if (!blocker) return false;
|
|
39
39
|
|
|
40
|
-
ctx
|
|
41
|
-
`Completing preserved milestone merge for ${blocker.milestoneId} from ${blocker.branch} into ${blocker.integrationBranch}.`,
|
|
42
|
-
"info",
|
|
43
|
-
);
|
|
44
|
-
const result = await mergeCompletedMilestone(basePath, blocker.milestoneId);
|
|
45
|
-
if (result.success) {
|
|
46
|
-
ctx.ui.notify(
|
|
47
|
-
`Milestone ${blocker.milestoneId} merged to ${blocker.integrationBranch}. Run /gsd again when ready.`,
|
|
48
|
-
"info",
|
|
49
|
-
);
|
|
50
|
-
} else {
|
|
51
|
-
ctx.ui.notify(
|
|
52
|
-
`Milestone ${blocker.milestoneId} merge recovery failed: ${result.error}`,
|
|
53
|
-
"error",
|
|
54
|
-
);
|
|
55
|
-
}
|
|
40
|
+
await runMergeMilestoneBlocker(ctx, basePath, blocker);
|
|
56
41
|
return true;
|
|
57
42
|
}
|
|
58
43
|
|