gsd-pi 2.80.0-dev.2be7caf18 → 2.80.0-dev.3065f7bfa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/phases.js +178 -108
- package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +20 -30
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +17 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +90 -15
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
- package/dist/resources/extensions/gsd/auto-start.js +197 -6
- package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +79 -24
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +42 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +9 -3
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +238 -28
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
- package/dist/resources/extensions/gsd/clean-root-preflight.js +24 -6
- package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
- package/dist/resources/extensions/gsd/context-budget.js +37 -2
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
- package/dist/resources/extensions/gsd/db-base-schema.js +4 -2
- package/dist/resources/extensions/gsd/db-migration-steps.js +6 -0
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
- package/dist/resources/extensions/gsd/git-service.js +36 -4
- package/dist/resources/extensions/gsd/gsd-db.js +46 -13
- package/dist/resources/extensions/gsd/guided-flow.js +66 -32
- package/dist/resources/extensions/gsd/memory-store.js +69 -12
- package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +16 -13
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
- package/dist/resources/extensions/gsd/unit-runtime.js +11 -0
- package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +68 -21
- 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 +15 -15
- 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 +15 -15
- 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/package.json +3 -3
- package/packages/mcp-server/src/workflow-tools.test.ts +9 -2
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +4 -1
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +2 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
- package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
- package/packages/pi-agent-core/dist/token-audit.js +221 -0
- package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
- package/packages/pi-agent-core/dist/types.d.ts +9 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
- package/packages/pi-agent-core/src/agent-loop.ts +4 -1
- package/packages/pi-agent-core/src/agent.ts +8 -0
- package/packages/pi-agent-core/src/index.ts +2 -0
- package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
- package/packages/pi-agent-core/src/token-audit.ts +287 -0
- package/packages/pi-agent-core/src/types.ts +14 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +18 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +41 -7
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +3 -6
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +3 -3
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +32 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +45 -7
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +3 -3
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +5 -5
- package/packages/pi-coding-agent/src/core/extensions/types.ts +35 -1
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
- package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
- package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -2
- package/src/resources/extensions/gsd/auto/phases.ts +251 -172
- package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +25 -30
- package/src/resources/extensions/gsd/auto/session.ts +8 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +95 -14
- package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
- package/src/resources/extensions/gsd/auto-start.ts +230 -9
- package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
- package/src/resources/extensions/gsd/auto.ts +87 -19
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +49 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +10 -3
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +283 -28
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
- package/src/resources/extensions/gsd/clean-root-preflight.ts +32 -7
- package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
- package/src/resources/extensions/gsd/context-budget.ts +44 -2
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +4 -2
- package/src/resources/extensions/gsd/db-migration-steps.ts +8 -0
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
- package/src/resources/extensions/gsd/git-service.ts +46 -8
- package/src/resources/extensions/gsd/gsd-db.ts +50 -13
- package/src/resources/extensions/gsd/guided-flow.ts +84 -39
- package/src/resources/extensions/gsd/memory-store.ts +77 -12
- package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
- package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +16 -13
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +417 -10
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +168 -6
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +15 -6
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +167 -4
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
- package/src/resources/extensions/gsd/unit-runtime.ts +11 -0
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +85 -19
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
- /package/dist/web/standalone/.next/static/{3EDDd9ULaybSupPoA_vf- → O2WvnXROue6l7nAp_4dhC}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{3EDDd9ULaybSupPoA_vf- → O2WvnXROue6l7nAp_4dhC}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Registers GSD extension runtime hooks and token-saving tool policies.
|
|
3
|
+
|
|
1
4
|
import { join } from "node:path";
|
|
2
5
|
|
|
3
6
|
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
@@ -25,12 +28,188 @@ import { initNotificationWidget } from "../notification-widget.js";
|
|
|
25
28
|
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
26
29
|
import { extractSubagentAgentClasses } from "./subagent-input.js";
|
|
27
30
|
import { approvalGateIdForUnit, isExplicitApprovalResponse, shouldPauseForUserApprovalQuestion } from "../user-input-boundary.js";
|
|
31
|
+
import { resolveSkillManifest } from "../skill-manifest.js";
|
|
28
32
|
|
|
29
33
|
// Skip the welcome screen on the very first session_start — cli.ts already
|
|
30
34
|
// printed it before the TUI launched. Only re-print on /clear (subsequent sessions).
|
|
31
35
|
let isFirstSession = true;
|
|
32
36
|
let approvalQuestionAbortInFlight = false;
|
|
33
37
|
|
|
38
|
+
interface DeferredApprovalGate {
|
|
39
|
+
gateId: string;
|
|
40
|
+
basePath: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let deferredApprovalGate: DeferredApprovalGate | null = null;
|
|
44
|
+
|
|
45
|
+
export const MINIMAL_GSD_TOOL_NAMES = [
|
|
46
|
+
"gsd_exec",
|
|
47
|
+
"gsd_exec_search",
|
|
48
|
+
"gsd_resume",
|
|
49
|
+
"gsd_milestone_status",
|
|
50
|
+
"gsd_checkpoint_db",
|
|
51
|
+
"memory_query",
|
|
52
|
+
"capture_thought",
|
|
53
|
+
] as const;
|
|
54
|
+
|
|
55
|
+
export const MINIMAL_AUTO_BASE_TOOL_NAMES = [
|
|
56
|
+
"ask_user_questions",
|
|
57
|
+
"bash",
|
|
58
|
+
"bg_shell",
|
|
59
|
+
"edit",
|
|
60
|
+
"glob",
|
|
61
|
+
"grep",
|
|
62
|
+
"ls",
|
|
63
|
+
"read",
|
|
64
|
+
"write",
|
|
65
|
+
] as const;
|
|
66
|
+
|
|
67
|
+
const AUTO_UNIT_SCOPED_TOOLS: Record<string, readonly string[]> = {
|
|
68
|
+
"research-milestone": ["gsd_summary_save", "gsd_decision_save"],
|
|
69
|
+
"plan-milestone": ["gsd_plan_milestone", "gsd_decision_save", "gsd_requirement_update"],
|
|
70
|
+
"discuss-milestone": ["gsd_summary_save", "gsd_decision_save", "gsd_requirement_save"],
|
|
71
|
+
"validate-milestone": ["gsd_validate_milestone", "gsd_reassess_roadmap", "subagent"],
|
|
72
|
+
"complete-milestone": ["gsd_complete_milestone", "subagent"],
|
|
73
|
+
"research-slice": ["gsd_summary_save", "gsd_decision_save"],
|
|
74
|
+
"plan-slice": ["gsd_plan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
75
|
+
"refine-slice": ["gsd_plan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
76
|
+
"replan-slice": ["gsd_replan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
77
|
+
"complete-slice": ["gsd_slice_complete", "gsd_decision_save", "gsd_requirement_update", "subagent"],
|
|
78
|
+
"reassess-roadmap": ["gsd_reassess_roadmap"],
|
|
79
|
+
"execute-task": ["gsd_task_complete", "gsd_decision_save"],
|
|
80
|
+
"execute-task-simple": ["gsd_task_complete", "gsd_decision_save"],
|
|
81
|
+
"reactive-execute": ["gsd_task_complete", "gsd_decision_save"],
|
|
82
|
+
"run-uat": ["gsd_summary_save"],
|
|
83
|
+
"gate-evaluate": ["gsd_save_gate_result"],
|
|
84
|
+
"rewrite-docs": ["gsd_summary_save", "gsd_decision_save"],
|
|
85
|
+
"workflow-preferences": ["gsd_summary_save"],
|
|
86
|
+
"discuss-project": ["gsd_summary_save", "gsd_decision_save", "gsd_requirement_save"],
|
|
87
|
+
"discuss-requirements": ["gsd_requirement_save", "gsd_summary_save"],
|
|
88
|
+
"research-decision": ["gsd_summary_save"],
|
|
89
|
+
"research-project": ["gsd_summary_save", "gsd_decision_save"],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const WORKFLOW_GSD_TOOL_NAMES = [
|
|
93
|
+
...MINIMAL_GSD_TOOL_NAMES,
|
|
94
|
+
...Object.values(AUTO_UNIT_SCOPED_TOOLS).flat(),
|
|
95
|
+
].filter(isGsdManagedTool);
|
|
96
|
+
|
|
97
|
+
function isGsdManagedTool(name: string): boolean {
|
|
98
|
+
return name.startsWith("gsd_") || name === "memory_query" || name === "capture_thought" || name === "gsd_graph";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function buildMinimalGsdToolSet(activeToolNames: readonly string[]): string[] {
|
|
102
|
+
const active = new Set(activeToolNames);
|
|
103
|
+
const preserved = activeToolNames.filter((name) => !isGsdManagedTool(name));
|
|
104
|
+
const minimal = MINIMAL_GSD_TOOL_NAMES.filter((name) => active.has(name));
|
|
105
|
+
return [...new Set([...preserved, ...minimal])];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function buildMinimalAutoGsdToolSet(
|
|
109
|
+
activeToolNames: readonly string[],
|
|
110
|
+
unitType: string | undefined,
|
|
111
|
+
): string[] {
|
|
112
|
+
const active = new Set(activeToolNames);
|
|
113
|
+
const unitTools = unitType ? AUTO_UNIT_SCOPED_TOOLS[unitType] ?? [] : [];
|
|
114
|
+
const autoBaseTools = new Set<string>(MINIMAL_AUTO_BASE_TOOL_NAMES);
|
|
115
|
+
const preserved = activeToolNames.filter((name) => autoBaseTools.has(name));
|
|
116
|
+
const scoped = [...MINIMAL_GSD_TOOL_NAMES, ...unitTools].filter((name) => active.has(name));
|
|
117
|
+
return [...new Set([...preserved, ...scoped])];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function buildMinimalGsdWorkflowToolSet(activeToolNames: readonly string[]): string[] {
|
|
121
|
+
const active = new Set(activeToolNames);
|
|
122
|
+
const autoBaseTools = new Set<string>(MINIMAL_AUTO_BASE_TOOL_NAMES);
|
|
123
|
+
const preserved = activeToolNames.filter((name) => autoBaseTools.has(name));
|
|
124
|
+
const scoped = WORKFLOW_GSD_TOOL_NAMES.filter((name) => active.has(name));
|
|
125
|
+
return [...new Set([...preserved, ...scoped])];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function buildRequestScopedGsdToolSet(
|
|
129
|
+
activeToolNames: readonly string[],
|
|
130
|
+
requestCustomMessages: readonly { customType?: string }[] | undefined,
|
|
131
|
+
): string[] | undefined {
|
|
132
|
+
for (let index = (requestCustomMessages?.length ?? 0) - 1; index >= 0; index--) {
|
|
133
|
+
const currentCustomType = requestCustomMessages?.[index]?.customType;
|
|
134
|
+
if (
|
|
135
|
+
currentCustomType === "gsd-run" ||
|
|
136
|
+
currentCustomType === "gsd-discuss" ||
|
|
137
|
+
currentCustomType === "gsd-doctor-heal" ||
|
|
138
|
+
currentCustomType === "gsd-triage"
|
|
139
|
+
) {
|
|
140
|
+
return buildMinimalGsdWorkflowToolSet(activeToolNames);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function isFullGsdToolSurfaceRequested(): boolean {
|
|
147
|
+
return process.env.PI_GSD_FULL_TOOLS === "1";
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function isGeneralGsdToolScopingRequested(): boolean {
|
|
151
|
+
return process.env.PI_GSD_MINIMAL_TOOLS === "1";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface ScopedGsdWorkflowState {
|
|
155
|
+
tools: string[] | null;
|
|
156
|
+
visibleSkills: string[] | undefined;
|
|
157
|
+
restoreVisibleSkills: boolean;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
type GsdWorkflowScopeApi = Pick<ExtensionAPI, "getActiveTools" | "setActiveTools"> & Partial<Pick<ExtensionAPI, "getVisibleSkills" | "setVisibleSkills">>;
|
|
161
|
+
|
|
162
|
+
function applyMinimalGsdToolSurface(pi: ExtensionAPI): void {
|
|
163
|
+
if (isFullGsdToolSurfaceRequested()) return;
|
|
164
|
+
const dash = getAutoRuntimeSnapshot();
|
|
165
|
+
if (dash.active && dash.currentUnit) {
|
|
166
|
+
pi.setActiveTools(buildMinimalAutoGsdToolSet(pi.getActiveTools(), dash.currentUnit.type));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (!isGeneralGsdToolScopingRequested()) return;
|
|
170
|
+
pi.setActiveTools(buildMinimalGsdToolSet(pi.getActiveTools()));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function scopeGsdWorkflowToolsForDispatch(
|
|
174
|
+
pi: GsdWorkflowScopeApi,
|
|
175
|
+
unitType?: string,
|
|
176
|
+
): ScopedGsdWorkflowState | null {
|
|
177
|
+
if (isFullGsdToolSurfaceRequested()) return null;
|
|
178
|
+
const current = pi.getActiveTools();
|
|
179
|
+
const scoped = unitType
|
|
180
|
+
? buildMinimalAutoGsdToolSet(current, unitType)
|
|
181
|
+
: buildMinimalGsdWorkflowToolSet(current);
|
|
182
|
+
const toolsChanged = !(scoped.length === current.length && scoped.every((name, index) => name === current[index]));
|
|
183
|
+
const skillManifest = resolveSkillManifest(unitType);
|
|
184
|
+
const canScopeSkills = skillManifest !== null && pi.getVisibleSkills && pi.setVisibleSkills;
|
|
185
|
+
if (!toolsChanged && !canScopeSkills) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
if (toolsChanged) {
|
|
189
|
+
pi.setActiveTools(scoped);
|
|
190
|
+
}
|
|
191
|
+
const visibleSkills = canScopeSkills ? pi.getVisibleSkills!() : undefined;
|
|
192
|
+
if (canScopeSkills) {
|
|
193
|
+
pi.setVisibleSkills!(skillManifest);
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
tools: toolsChanged ? current : null,
|
|
197
|
+
visibleSkills,
|
|
198
|
+
restoreVisibleSkills: Boolean(canScopeSkills),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function restoreGsdWorkflowTools(
|
|
203
|
+
pi: Pick<ExtensionAPI, "setActiveTools"> & Partial<Pick<ExtensionAPI, "setVisibleSkills">>,
|
|
204
|
+
savedState: ScopedGsdWorkflowState | null,
|
|
205
|
+
): void {
|
|
206
|
+
if (!savedState) return;
|
|
207
|
+
if (savedState.tools) pi.setActiveTools(savedState.tools);
|
|
208
|
+
if (savedState.restoreVisibleSkills && pi.setVisibleSkills) {
|
|
209
|
+
pi.setVisibleSkills(savedState.visibleSkills);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
34
213
|
async function deriveGsdState(basePath: string) {
|
|
35
214
|
const { deriveState } = await import("../state.js");
|
|
36
215
|
return deriveState(basePath);
|
|
@@ -85,12 +264,56 @@ async function applyCompactionThresholdOverride(ctx: ExtensionContext): Promise<
|
|
|
85
264
|
}
|
|
86
265
|
}
|
|
87
266
|
|
|
88
|
-
|
|
89
|
-
|
|
267
|
+
function clearDeferredApprovalGate(basePath?: string): void {
|
|
268
|
+
if (!basePath || deferredApprovalGate?.basePath === basePath) {
|
|
269
|
+
deferredApprovalGate = null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function deferApprovalGate(gateId: string, basePath: string): void {
|
|
274
|
+
deferredApprovalGate = { gateId, basePath };
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function contextBasePath(ctx?: { cwd?: string }): string {
|
|
278
|
+
return typeof ctx?.cwd === "string" ? ctx.cwd : process.cwd();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function activateDeferredApprovalGate(basePath: string): void {
|
|
282
|
+
if (deferredApprovalGate?.basePath !== basePath) return;
|
|
283
|
+
setPendingGate(deferredApprovalGate.gateId, basePath);
|
|
284
|
+
deferredApprovalGate = null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function isContextDraftSummarySave(toolName: string, input: unknown): boolean {
|
|
288
|
+
if (toolName !== "gsd_summary_save" && toolName !== "summary_save") return false;
|
|
289
|
+
if (!input || typeof input !== "object") return false;
|
|
290
|
+
return (input as { artifact_type?: unknown }).artifact_type === "CONTEXT-DRAFT";
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function shouldBlockDeferredApprovalTool(
|
|
294
|
+
toolName: string,
|
|
295
|
+
input: unknown,
|
|
296
|
+
basePath: string,
|
|
297
|
+
): { block: boolean; reason?: string } {
|
|
298
|
+
if (deferredApprovalGate?.basePath !== basePath) return { block: false };
|
|
299
|
+
if (toolName === "ask_user_questions") return { block: false };
|
|
300
|
+
if (isContextDraftSummarySave(toolName, input)) return { block: false };
|
|
301
|
+
return {
|
|
302
|
+
block: true,
|
|
303
|
+
reason: [
|
|
304
|
+
`HARD BLOCK: Approval question "${deferredApprovalGate.gateId}" has been shown to the user.`,
|
|
305
|
+
`Only CONTEXT-DRAFT persistence may finish in this same assistant turn.`,
|
|
306
|
+
`Wait for the user's answer before calling additional tools.`,
|
|
307
|
+
].join(" "),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export function resolveNotificationStoreBasePath(basePath: string): string {
|
|
312
|
+
return resolveWorktreeProjectRoot(basePath);
|
|
90
313
|
}
|
|
91
314
|
|
|
92
315
|
function initSessionNotifications(ctx: ExtensionContext): void {
|
|
93
|
-
initNotificationStore(resolveNotificationStoreBasePath());
|
|
316
|
+
initNotificationStore(resolveNotificationStoreBasePath(contextBasePath(ctx)));
|
|
94
317
|
installNotifyInterceptor(ctx);
|
|
95
318
|
initNotificationWidget(ctx);
|
|
96
319
|
}
|
|
@@ -132,29 +355,31 @@ export function registerHooks(
|
|
|
132
355
|
ecosystemHandlers: GSDEcosystemBeforeAgentStartHandler[],
|
|
133
356
|
): void {
|
|
134
357
|
pi.on("session_start", async (_event, ctx) => {
|
|
358
|
+
const basePath = contextBasePath(ctx);
|
|
135
359
|
initSessionNotifications(ctx);
|
|
136
360
|
if (!isAutoActive()) {
|
|
137
361
|
const { initHealthWidget } = await import("../health-widget.js");
|
|
138
362
|
initHealthWidget(ctx);
|
|
139
363
|
}
|
|
140
|
-
resetWriteGateState(
|
|
364
|
+
resetWriteGateState(basePath);
|
|
141
365
|
resetToolCallLoopGuard();
|
|
142
366
|
approvalQuestionAbortInFlight = false;
|
|
367
|
+
clearDeferredApprovalGate();
|
|
143
368
|
await resetAskUserQuestionsTurnCache();
|
|
144
369
|
await syncServiceTierStatus(ctx);
|
|
145
370
|
await applyDisabledModelProviderPolicy(ctx);
|
|
146
371
|
await applyCompactionThresholdOverride(ctx);
|
|
147
372
|
// Skip MCP auto-prep when running inside an auto-worktree (see session_switch below).
|
|
148
373
|
const { isInAutoWorktree } = await import("../auto-worktree.js");
|
|
149
|
-
if (!isInAutoWorktree(
|
|
374
|
+
if (!isInAutoWorktree(basePath)) {
|
|
150
375
|
const { prepareWorkflowMcpForProject } = await import("../workflow-mcp-auto-prep.js");
|
|
151
|
-
prepareWorkflowMcpForProject(ctx,
|
|
376
|
+
prepareWorkflowMcpForProject(ctx, basePath);
|
|
152
377
|
}
|
|
153
378
|
|
|
154
379
|
// Apply show_token_cost preference (#1515)
|
|
155
380
|
try {
|
|
156
381
|
const { loadEffectiveGSDPreferences } = await import("../preferences.js");
|
|
157
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
382
|
+
const prefs = loadEffectiveGSDPreferences(basePath);
|
|
158
383
|
process.env.GSD_SHOW_TOKEN_COST = prefs?.preferences.show_token_cost ? "1" : "";
|
|
159
384
|
} catch { /* non-fatal */ }
|
|
160
385
|
if (isFirstSession) {
|
|
@@ -186,11 +411,13 @@ export function registerHooks(
|
|
|
186
411
|
});
|
|
187
412
|
|
|
188
413
|
pi.on("session_switch", async (_event, ctx) => {
|
|
414
|
+
const basePath = contextBasePath(ctx);
|
|
189
415
|
initSessionNotifications(ctx);
|
|
190
|
-
resetWriteGateState(
|
|
416
|
+
resetWriteGateState(basePath);
|
|
191
417
|
resetToolCallLoopGuard();
|
|
418
|
+
clearDeferredApprovalGate();
|
|
192
419
|
await resetAskUserQuestionsTurnCache();
|
|
193
|
-
clearDiscussionFlowState(
|
|
420
|
+
clearDiscussionFlowState(basePath);
|
|
194
421
|
await syncServiceTierStatus(ctx);
|
|
195
422
|
await applyDisabledModelProviderPolicy(ctx);
|
|
196
423
|
await applyCompactionThresholdOverride(ctx);
|
|
@@ -199,9 +426,9 @@ export function registerHooks(
|
|
|
199
426
|
// post-chdir rewrites the file mid-run (non-idempotent due to cwd-relative
|
|
200
427
|
// CLI path resolution), dirtying the tree and breaking the milestone merge.
|
|
201
428
|
const { isInAutoWorktree } = await import("../auto-worktree.js");
|
|
202
|
-
if (!isInAutoWorktree(
|
|
429
|
+
if (!isInAutoWorktree(basePath)) {
|
|
203
430
|
const { prepareWorkflowMcpForProject } = await import("../workflow-mcp-auto-prep.js");
|
|
204
|
-
prepareWorkflowMcpForProject(ctx,
|
|
431
|
+
prepareWorkflowMcpForProject(ctx, basePath);
|
|
205
432
|
}
|
|
206
433
|
await loadToolApiKeysForSession();
|
|
207
434
|
if (!isAutoActive()) {
|
|
@@ -213,11 +440,13 @@ export function registerHooks(
|
|
|
213
440
|
});
|
|
214
441
|
|
|
215
442
|
pi.on("before_agent_start", async (event, ctx: ExtensionContext) => {
|
|
443
|
+
applyMinimalGsdToolSurface(pi);
|
|
444
|
+
|
|
216
445
|
// Wait for ecosystem loader to finish (no-op after first turn).
|
|
217
446
|
const { getEcosystemReadyPromise } = await import("../ecosystem/loader.js");
|
|
218
447
|
await getEcosystemReadyPromise();
|
|
219
448
|
|
|
220
|
-
const beforeAgentBasePath =
|
|
449
|
+
const beforeAgentBasePath = contextBasePath(ctx);
|
|
221
450
|
const pendingApprovalGate = getPendingGate(beforeAgentBasePath);
|
|
222
451
|
if (pendingApprovalGate && isExplicitApprovalResponse(event.prompt, pendingApprovalGate)) {
|
|
223
452
|
markApprovalGateVerified(pendingApprovalGate, beforeAgentBasePath);
|
|
@@ -225,6 +454,7 @@ export function registerHooks(
|
|
|
225
454
|
if (milestoneId) markDepthVerified(milestoneId, beforeAgentBasePath);
|
|
226
455
|
clearPendingGate(beforeAgentBasePath);
|
|
227
456
|
}
|
|
457
|
+
clearDeferredApprovalGate(beforeAgentBasePath);
|
|
228
458
|
|
|
229
459
|
// GSD's own context injection (existing behavior — unchanged).
|
|
230
460
|
const { buildBeforeAgentStartResult } = await import("./system-context.js");
|
|
@@ -233,7 +463,7 @@ export function registerHooks(
|
|
|
233
463
|
// Refresh the snapshot used by ecosystem getPhase()/getActiveUnit().
|
|
234
464
|
// deriveState has its own ~100ms cache so this is cheap on repeat calls.
|
|
235
465
|
try {
|
|
236
|
-
const state = await deriveGsdState(
|
|
466
|
+
const state = await deriveGsdState(beforeAgentBasePath);
|
|
237
467
|
updateSnapshot(state);
|
|
238
468
|
} catch {
|
|
239
469
|
updateSnapshot(null);
|
|
@@ -275,7 +505,11 @@ export function registerHooks(
|
|
|
275
505
|
resetToolCallLoopGuard();
|
|
276
506
|
await resetAskUserQuestionsTurnCache();
|
|
277
507
|
const { handleAgentEnd } = await import("./agent-end-recovery.js");
|
|
278
|
-
|
|
508
|
+
try {
|
|
509
|
+
await handleAgentEnd(pi, event, ctx);
|
|
510
|
+
} finally {
|
|
511
|
+
activateDeferredApprovalGate(contextBasePath(ctx));
|
|
512
|
+
}
|
|
279
513
|
});
|
|
280
514
|
|
|
281
515
|
// Squash-merge quick-task branch back to the original branch after the
|
|
@@ -290,8 +524,8 @@ export function registerHooks(
|
|
|
290
524
|
}
|
|
291
525
|
});
|
|
292
526
|
|
|
293
|
-
pi.on("session_before_compact", async () => {
|
|
294
|
-
const basePath =
|
|
527
|
+
pi.on("session_before_compact", async (_event, ctx) => {
|
|
528
|
+
const basePath = contextBasePath(ctx);
|
|
295
529
|
// Context Mode is default-on. Write the resumable snapshot before any
|
|
296
530
|
// active-auto cancel return so auto sessions still leave re-entry context.
|
|
297
531
|
await writeContextModeCompactionSnapshot(basePath);
|
|
@@ -358,7 +592,7 @@ export function registerHooks(
|
|
|
358
592
|
if (!unitType) {
|
|
359
593
|
try {
|
|
360
594
|
const { getPendingDeepProjectSetupUnitForContext } = await import("../guided-flow.js");
|
|
361
|
-
const pending = getPendingDeepProjectSetupUnitForContext(ctx,
|
|
595
|
+
const pending = getPendingDeepProjectSetupUnitForContext(ctx, contextBasePath(ctx));
|
|
362
596
|
unitType = pending?.unitType;
|
|
363
597
|
unitId = pending?.unitId;
|
|
364
598
|
} catch {
|
|
@@ -367,7 +601,7 @@ export function registerHooks(
|
|
|
367
601
|
}
|
|
368
602
|
|
|
369
603
|
if (!unitType) {
|
|
370
|
-
const milestoneId = await getDiscussionMilestoneIdFor(
|
|
604
|
+
const milestoneId = await getDiscussionMilestoneIdFor(contextBasePath(ctx));
|
|
371
605
|
if (milestoneId) {
|
|
372
606
|
unitType = "discuss-milestone";
|
|
373
607
|
unitId = milestoneId;
|
|
@@ -377,15 +611,16 @@ export function registerHooks(
|
|
|
377
611
|
if (!shouldPauseForUserApprovalQuestion(unitType, [event.message])) return;
|
|
378
612
|
|
|
379
613
|
const gateId = approvalGateIdForUnit(unitType, unitId);
|
|
380
|
-
if (gateId)
|
|
614
|
+
if (gateId) deferApprovalGate(gateId, contextBasePath(ctx));
|
|
381
615
|
|
|
382
616
|
approvalQuestionAbortInFlight = true;
|
|
383
617
|
ctx.ui.notify(
|
|
384
618
|
`${unitType}${unitId ? ` ${unitId}` : ""} is waiting for your approval - pausing before more tool calls run.`,
|
|
385
619
|
"info",
|
|
386
620
|
);
|
|
387
|
-
// The pending gate
|
|
388
|
-
//
|
|
621
|
+
// The durable pending gate is activated at agent_end so same-turn
|
|
622
|
+
// CONTEXT-DRAFT persistence can finish after the text boundary streams.
|
|
623
|
+
// The tool_call hook below still blocks non-draft tools in this turn.
|
|
389
624
|
// Aborting mid-stream eats the model's question text on external CLI
|
|
390
625
|
// providers (Claude Code SDK) because lastTextContent isn't populated
|
|
391
626
|
// from in-flight builder state — the user only ever sees "Claude Code
|
|
@@ -396,7 +631,7 @@ export function registerHooks(
|
|
|
396
631
|
const { isParallelActive, shutdownParallel } = await import("../parallel-orchestrator.js");
|
|
397
632
|
if (isParallelActive()) {
|
|
398
633
|
try {
|
|
399
|
-
await shutdownParallel(
|
|
634
|
+
await shutdownParallel(contextBasePath(ctx));
|
|
400
635
|
} catch {
|
|
401
636
|
// best-effort
|
|
402
637
|
}
|
|
@@ -408,8 +643,8 @@ export function registerHooks(
|
|
|
408
643
|
}
|
|
409
644
|
});
|
|
410
645
|
|
|
411
|
-
pi.on("tool_call", async (event) => {
|
|
412
|
-
const discussionBasePath =
|
|
646
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
647
|
+
const discussionBasePath = contextBasePath(ctx);
|
|
413
648
|
const toolName = canonicalToolName(event.toolName);
|
|
414
649
|
// ── Loop guard: block repeated identical tool calls ──
|
|
415
650
|
const loopCheck = checkToolCallLoop(toolName, event.input as Record<string, unknown>);
|
|
@@ -417,6 +652,13 @@ export function registerHooks(
|
|
|
417
652
|
return { block: true, reason: loopCheck.reason };
|
|
418
653
|
}
|
|
419
654
|
|
|
655
|
+
const deferredGateGuard = shouldBlockDeferredApprovalTool(
|
|
656
|
+
toolName,
|
|
657
|
+
event.input,
|
|
658
|
+
discussionBasePath,
|
|
659
|
+
);
|
|
660
|
+
if (deferredGateGuard.block) return deferredGateGuard;
|
|
661
|
+
|
|
420
662
|
// ── Discussion gate enforcement: track pending gate questions ─────────
|
|
421
663
|
// Only gate-shaped ask_user_questions calls should block execution.
|
|
422
664
|
// The gate stays pending until the user selects the approval option.
|
|
@@ -586,7 +828,7 @@ export function registerHooks(
|
|
|
586
828
|
}
|
|
587
829
|
});
|
|
588
830
|
|
|
589
|
-
pi.on("tool_result", async (event) => {
|
|
831
|
+
pi.on("tool_result", async (event, ctx) => {
|
|
590
832
|
if (isAutoActive() && typeof event.toolCallId === "string") {
|
|
591
833
|
markToolEnd(event.toolCallId);
|
|
592
834
|
}
|
|
@@ -605,7 +847,7 @@ export function registerHooks(
|
|
|
605
847
|
}
|
|
606
848
|
const toolName = canonicalToolName(event.toolName);
|
|
607
849
|
if (toolName !== "ask_user_questions") return;
|
|
608
|
-
const basePath =
|
|
850
|
+
const basePath = contextBasePath(ctx);
|
|
609
851
|
const milestoneId = await getDiscussionMilestoneIdFor(basePath);
|
|
610
852
|
const queueActive = isQueuePhaseActive(basePath);
|
|
611
853
|
|
|
@@ -811,8 +1053,21 @@ export function registerHooks(
|
|
|
811
1053
|
// Tool set adaptation hook (ADR-005 Phase 4)
|
|
812
1054
|
// Extensions can override tool set after model selection by returning { toolNames: [...] }
|
|
813
1055
|
// Return undefined to let the built-in provider compatibility filtering proceed.
|
|
814
|
-
pi.on("adjust_tool_set", async (
|
|
815
|
-
|
|
1056
|
+
pi.on("adjust_tool_set", async (event) => {
|
|
1057
|
+
if (isFullGsdToolSurfaceRequested()) return undefined;
|
|
1058
|
+
const removed = new Set(event.filteredTools);
|
|
1059
|
+
const providerCompatible = event.activeToolNames.filter((name) => !removed.has(name));
|
|
1060
|
+
const requestScoped = buildRequestScopedGsdToolSet(providerCompatible, event.requestCustomMessages);
|
|
1061
|
+
if (requestScoped) {
|
|
1062
|
+
return { toolNames: requestScoped };
|
|
1063
|
+
}
|
|
1064
|
+
const dash = getAutoRuntimeSnapshot();
|
|
1065
|
+
if (dash.active && dash.currentUnit) {
|
|
1066
|
+
return { toolNames: buildMinimalAutoGsdToolSet(providerCompatible, dash.currentUnit.type) };
|
|
1067
|
+
}
|
|
1068
|
+
if (isGeneralGsdToolScopingRequested()) {
|
|
1069
|
+
return { toolNames: buildMinimalGsdToolSet(providerCompatible) };
|
|
1070
|
+
}
|
|
816
1071
|
return undefined;
|
|
817
1072
|
});
|
|
818
1073
|
}
|