gsd-pi 2.80.0-dev.cf9433f56 → 2.80.0-dev.d4fc28e6b
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/cli.js +0 -19
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
- package/dist/resources/extensions/gsd/auto/loop.js +71 -8
- package/dist/resources/extensions/gsd/auto/phases.js +150 -94
- package/dist/resources/extensions/gsd/auto/resolve.js +12 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +10 -30
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
- package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
- 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-start.js +197 -6
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +18 -22
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +86 -19
- 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 +298 -54
- 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/db/unit-dispatches.js +53 -0
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
- package/dist/resources/extensions/gsd/guided-flow.js +47 -28
- 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 +15 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- 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/workflow-protocol.js +131 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +35 -4
- 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 +12 -12
- 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 +12 -12
- 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/welcome-screen.d.ts +2 -0
- package/dist/welcome-screen.js +9 -7
- package/package.json +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-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 +36 -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-tool-refresh.test.ts +25 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +40 -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/claude-code-cli/stream-adapter.ts +30 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -2
- package/src/resources/extensions/gsd/auto/loop.ts +84 -8
- package/src/resources/extensions/gsd/auto/phases.ts +218 -154
- package/src/resources/extensions/gsd/auto/resolve.ts +19 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -29
- package/src/resources/extensions/gsd/auto/session.ts +8 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
- package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
- 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-start.ts +230 -9
- package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
- package/src/resources/extensions/gsd/auto.ts +18 -18
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +100 -18
- 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 +347 -54
- 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/db/unit-dispatches.ts +66 -0
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
- package/src/resources/extensions/gsd/guided-flow.ts +52 -35
- 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 +16 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- 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 +361 -10
- 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/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-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/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/isolation-none-branch-guard.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +5 -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/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 +7 -5
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -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/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -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 +50 -1
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
- 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 +104 -3
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +49 -4
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
- /package/dist/web/standalone/.next/static/{-5nHJWzSdG-WkPMul_khA → cWaxzf-sdbSSbbwYu8q7a}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{-5nHJWzSdG-WkPMul_khA → cWaxzf-sdbSSbbwYu8q7a}/_ssgManifest.js +0 -0
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Registers GSD extension runtime hooks and token-saving tool policies.
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
2
6
|
import { isToolCallEventType } from "@gsd/pi-coding-agent";
|
|
3
7
|
import { updateSnapshot } from "../ecosystem/gsd-extension-api.js";
|
|
4
8
|
import { buildMilestoneFileName, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
|
|
@@ -19,10 +23,202 @@ import { initNotificationWidget } from "../notification-widget.js";
|
|
|
19
23
|
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
20
24
|
import { extractSubagentAgentClasses } from "./subagent-input.js";
|
|
21
25
|
import { approvalGateIdForUnit, isExplicitApprovalResponse, shouldPauseForUserApprovalQuestion } from "../user-input-boundary.js";
|
|
22
|
-
|
|
23
|
-
// printed it before the TUI launched. Only re-print on /clear (subsequent sessions).
|
|
24
|
-
let isFirstSession = true;
|
|
26
|
+
import { resolveSkillManifest } from "../skill-manifest.js";
|
|
25
27
|
let approvalQuestionAbortInFlight = false;
|
|
28
|
+
async function loadWelcomeScreenModule() {
|
|
29
|
+
const candidates = [];
|
|
30
|
+
const gsdBinPath = process.env.GSD_BIN_PATH;
|
|
31
|
+
if (gsdBinPath) {
|
|
32
|
+
candidates.push(join(dirname(gsdBinPath), "welcome-screen.js"));
|
|
33
|
+
}
|
|
34
|
+
const packageRoot = process.env.GSD_PKG_ROOT;
|
|
35
|
+
if (packageRoot) {
|
|
36
|
+
candidates.push(join(packageRoot, "dist", "welcome-screen.js"));
|
|
37
|
+
candidates.push(join(packageRoot, "src", "welcome-screen.ts"));
|
|
38
|
+
}
|
|
39
|
+
for (const candidate of candidates) {
|
|
40
|
+
try {
|
|
41
|
+
if (!existsSync(candidate))
|
|
42
|
+
continue;
|
|
43
|
+
const mod = await import(pathToFileURL(candidate).href);
|
|
44
|
+
if (typeof mod.buildWelcomeScreenLines === "function") {
|
|
45
|
+
return mod;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Try the next package layout.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
async function installWelcomeHeader(ctx) {
|
|
55
|
+
if (!ctx.hasUI || typeof ctx.ui?.setHeader !== "function")
|
|
56
|
+
return;
|
|
57
|
+
try {
|
|
58
|
+
const welcome = await loadWelcomeScreenModule();
|
|
59
|
+
if (!welcome)
|
|
60
|
+
return;
|
|
61
|
+
let remoteChannel;
|
|
62
|
+
try {
|
|
63
|
+
const { resolveRemoteConfig } = await import("../../remote-questions/config.js");
|
|
64
|
+
const rc = resolveRemoteConfig();
|
|
65
|
+
if (rc)
|
|
66
|
+
remoteChannel = rc.channel;
|
|
67
|
+
}
|
|
68
|
+
catch { /* non-fatal */ }
|
|
69
|
+
ctx.ui.setHeader(() => ({
|
|
70
|
+
render(width) {
|
|
71
|
+
return welcome.buildWelcomeScreenLines({
|
|
72
|
+
version: process.env.GSD_VERSION || "0.0.0",
|
|
73
|
+
remoteChannel,
|
|
74
|
+
width,
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
invalidate() { },
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* non-fatal */
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
let deferredApprovalGate = null;
|
|
85
|
+
export const MINIMAL_GSD_TOOL_NAMES = [
|
|
86
|
+
"gsd_exec",
|
|
87
|
+
"gsd_exec_search",
|
|
88
|
+
"gsd_resume",
|
|
89
|
+
"gsd_milestone_status",
|
|
90
|
+
"gsd_checkpoint_db",
|
|
91
|
+
"memory_query",
|
|
92
|
+
"capture_thought",
|
|
93
|
+
];
|
|
94
|
+
export const MINIMAL_AUTO_BASE_TOOL_NAMES = [
|
|
95
|
+
"ask_user_questions",
|
|
96
|
+
"bash",
|
|
97
|
+
"bg_shell",
|
|
98
|
+
"edit",
|
|
99
|
+
"glob",
|
|
100
|
+
"grep",
|
|
101
|
+
"ls",
|
|
102
|
+
"read",
|
|
103
|
+
"write",
|
|
104
|
+
];
|
|
105
|
+
const AUTO_UNIT_SCOPED_TOOLS = {
|
|
106
|
+
"research-milestone": ["gsd_summary_save", "gsd_decision_save"],
|
|
107
|
+
"plan-milestone": ["gsd_plan_milestone", "gsd_decision_save", "gsd_requirement_update"],
|
|
108
|
+
"discuss-milestone": ["gsd_summary_save", "gsd_decision_save", "gsd_requirement_save"],
|
|
109
|
+
"validate-milestone": ["gsd_validate_milestone", "gsd_reassess_roadmap", "subagent"],
|
|
110
|
+
"complete-milestone": ["gsd_complete_milestone", "subagent"],
|
|
111
|
+
"research-slice": ["gsd_summary_save", "gsd_decision_save"],
|
|
112
|
+
"plan-slice": ["gsd_plan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
113
|
+
"refine-slice": ["gsd_plan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
114
|
+
"replan-slice": ["gsd_replan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
115
|
+
"complete-slice": ["gsd_slice_complete", "gsd_decision_save", "gsd_requirement_update", "subagent"],
|
|
116
|
+
"reassess-roadmap": ["gsd_reassess_roadmap"],
|
|
117
|
+
"execute-task": ["gsd_task_complete", "gsd_decision_save"],
|
|
118
|
+
"execute-task-simple": ["gsd_task_complete", "gsd_decision_save"],
|
|
119
|
+
"reactive-execute": ["gsd_task_complete", "gsd_decision_save"],
|
|
120
|
+
"run-uat": ["gsd_summary_save"],
|
|
121
|
+
"gate-evaluate": ["gsd_save_gate_result"],
|
|
122
|
+
"rewrite-docs": ["gsd_summary_save", "gsd_decision_save"],
|
|
123
|
+
"workflow-preferences": ["gsd_summary_save"],
|
|
124
|
+
"discuss-project": ["gsd_summary_save", "gsd_decision_save", "gsd_requirement_save"],
|
|
125
|
+
"discuss-requirements": ["gsd_requirement_save", "gsd_summary_save"],
|
|
126
|
+
"research-decision": ["gsd_summary_save"],
|
|
127
|
+
"research-project": ["gsd_summary_save", "gsd_decision_save"],
|
|
128
|
+
};
|
|
129
|
+
const WORKFLOW_GSD_TOOL_NAMES = [
|
|
130
|
+
...MINIMAL_GSD_TOOL_NAMES,
|
|
131
|
+
...Object.values(AUTO_UNIT_SCOPED_TOOLS).flat(),
|
|
132
|
+
].filter(isGsdManagedTool);
|
|
133
|
+
function isGsdManagedTool(name) {
|
|
134
|
+
return name.startsWith("gsd_") || name === "memory_query" || name === "capture_thought" || name === "gsd_graph";
|
|
135
|
+
}
|
|
136
|
+
export function buildMinimalGsdToolSet(activeToolNames) {
|
|
137
|
+
const active = new Set(activeToolNames);
|
|
138
|
+
const preserved = activeToolNames.filter((name) => !isGsdManagedTool(name));
|
|
139
|
+
const minimal = MINIMAL_GSD_TOOL_NAMES.filter((name) => active.has(name));
|
|
140
|
+
return [...new Set([...preserved, ...minimal])];
|
|
141
|
+
}
|
|
142
|
+
export function buildMinimalAutoGsdToolSet(activeToolNames, unitType) {
|
|
143
|
+
const active = new Set(activeToolNames);
|
|
144
|
+
const unitTools = unitType ? AUTO_UNIT_SCOPED_TOOLS[unitType] ?? [] : [];
|
|
145
|
+
const autoBaseTools = new Set(MINIMAL_AUTO_BASE_TOOL_NAMES);
|
|
146
|
+
const preserved = activeToolNames.filter((name) => autoBaseTools.has(name));
|
|
147
|
+
const scoped = [...MINIMAL_GSD_TOOL_NAMES, ...unitTools].filter((name) => active.has(name));
|
|
148
|
+
return [...new Set([...preserved, ...scoped])];
|
|
149
|
+
}
|
|
150
|
+
export function buildMinimalGsdWorkflowToolSet(activeToolNames) {
|
|
151
|
+
const active = new Set(activeToolNames);
|
|
152
|
+
const autoBaseTools = new Set(MINIMAL_AUTO_BASE_TOOL_NAMES);
|
|
153
|
+
const preserved = activeToolNames.filter((name) => autoBaseTools.has(name));
|
|
154
|
+
const scoped = WORKFLOW_GSD_TOOL_NAMES.filter((name) => active.has(name));
|
|
155
|
+
return [...new Set([...preserved, ...scoped])];
|
|
156
|
+
}
|
|
157
|
+
export function buildRequestScopedGsdToolSet(activeToolNames, requestCustomMessages) {
|
|
158
|
+
for (let index = (requestCustomMessages?.length ?? 0) - 1; index >= 0; index--) {
|
|
159
|
+
const currentCustomType = requestCustomMessages?.[index]?.customType;
|
|
160
|
+
if (currentCustomType === "gsd-run" ||
|
|
161
|
+
currentCustomType === "gsd-discuss" ||
|
|
162
|
+
currentCustomType === "gsd-doctor-heal" ||
|
|
163
|
+
currentCustomType === "gsd-triage") {
|
|
164
|
+
return buildMinimalGsdWorkflowToolSet(activeToolNames);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
export function isFullGsdToolSurfaceRequested() {
|
|
170
|
+
return process.env.PI_GSD_FULL_TOOLS === "1";
|
|
171
|
+
}
|
|
172
|
+
function isGeneralGsdToolScopingRequested() {
|
|
173
|
+
return process.env.PI_GSD_MINIMAL_TOOLS === "1";
|
|
174
|
+
}
|
|
175
|
+
function applyMinimalGsdToolSurface(pi) {
|
|
176
|
+
if (isFullGsdToolSurfaceRequested())
|
|
177
|
+
return;
|
|
178
|
+
const dash = getAutoRuntimeSnapshot();
|
|
179
|
+
if (dash.active && dash.currentUnit) {
|
|
180
|
+
pi.setActiveTools(buildMinimalAutoGsdToolSet(pi.getActiveTools(), dash.currentUnit.type));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (!isGeneralGsdToolScopingRequested())
|
|
184
|
+
return;
|
|
185
|
+
pi.setActiveTools(buildMinimalGsdToolSet(pi.getActiveTools()));
|
|
186
|
+
}
|
|
187
|
+
export function scopeGsdWorkflowToolsForDispatch(pi, unitType) {
|
|
188
|
+
if (isFullGsdToolSurfaceRequested())
|
|
189
|
+
return null;
|
|
190
|
+
const current = pi.getActiveTools();
|
|
191
|
+
const scoped = unitType
|
|
192
|
+
? buildMinimalAutoGsdToolSet(current, unitType)
|
|
193
|
+
: buildMinimalGsdWorkflowToolSet(current);
|
|
194
|
+
const toolsChanged = !(scoped.length === current.length && scoped.every((name, index) => name === current[index]));
|
|
195
|
+
const skillManifest = resolveSkillManifest(unitType);
|
|
196
|
+
const canScopeSkills = skillManifest !== null && pi.getVisibleSkills && pi.setVisibleSkills;
|
|
197
|
+
if (!toolsChanged && !canScopeSkills) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
if (toolsChanged) {
|
|
201
|
+
pi.setActiveTools(scoped);
|
|
202
|
+
}
|
|
203
|
+
const visibleSkills = canScopeSkills ? pi.getVisibleSkills() : undefined;
|
|
204
|
+
if (canScopeSkills) {
|
|
205
|
+
pi.setVisibleSkills(skillManifest);
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
tools: toolsChanged ? current : null,
|
|
209
|
+
visibleSkills,
|
|
210
|
+
restoreVisibleSkills: Boolean(canScopeSkills),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
export function restoreGsdWorkflowTools(pi, savedState) {
|
|
214
|
+
if (!savedState)
|
|
215
|
+
return;
|
|
216
|
+
if (savedState.tools)
|
|
217
|
+
pi.setActiveTools(savedState.tools);
|
|
218
|
+
if (savedState.restoreVisibleSkills && pi.setVisibleSkills) {
|
|
219
|
+
pi.setVisibleSkills(savedState.visibleSkills);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
26
222
|
async function deriveGsdState(basePath) {
|
|
27
223
|
const { deriveState } = await import("../state.js");
|
|
28
224
|
return deriveState(basePath);
|
|
@@ -71,11 +267,51 @@ async function applyCompactionThresholdOverride(ctx) {
|
|
|
71
267
|
// Non-fatal: leave any existing override in place.
|
|
72
268
|
}
|
|
73
269
|
}
|
|
74
|
-
|
|
75
|
-
|
|
270
|
+
function clearDeferredApprovalGate(basePath) {
|
|
271
|
+
if (!basePath || deferredApprovalGate?.basePath === basePath) {
|
|
272
|
+
deferredApprovalGate = null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function deferApprovalGate(gateId, basePath) {
|
|
276
|
+
deferredApprovalGate = { gateId, basePath };
|
|
277
|
+
}
|
|
278
|
+
function contextBasePath(ctx) {
|
|
279
|
+
return typeof ctx?.cwd === "string" ? ctx.cwd : process.cwd();
|
|
280
|
+
}
|
|
281
|
+
function activateDeferredApprovalGate(basePath) {
|
|
282
|
+
if (deferredApprovalGate?.basePath !== basePath)
|
|
283
|
+
return;
|
|
284
|
+
setPendingGate(deferredApprovalGate.gateId, basePath);
|
|
285
|
+
deferredApprovalGate = null;
|
|
286
|
+
}
|
|
287
|
+
function isContextDraftSummarySave(toolName, input) {
|
|
288
|
+
if (toolName !== "gsd_summary_save" && toolName !== "summary_save")
|
|
289
|
+
return false;
|
|
290
|
+
if (!input || typeof input !== "object")
|
|
291
|
+
return false;
|
|
292
|
+
return input.artifact_type === "CONTEXT-DRAFT";
|
|
293
|
+
}
|
|
294
|
+
function shouldBlockDeferredApprovalTool(toolName, input, basePath) {
|
|
295
|
+
if (deferredApprovalGate?.basePath !== basePath)
|
|
296
|
+
return { block: false };
|
|
297
|
+
if (toolName === "ask_user_questions")
|
|
298
|
+
return { block: false };
|
|
299
|
+
if (isContextDraftSummarySave(toolName, input))
|
|
300
|
+
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
|
+
export function resolveNotificationStoreBasePath(basePath) {
|
|
311
|
+
return resolveWorktreeProjectRoot(basePath);
|
|
76
312
|
}
|
|
77
313
|
function initSessionNotifications(ctx) {
|
|
78
|
-
initNotificationStore(resolveNotificationStoreBasePath());
|
|
314
|
+
initNotificationStore(resolveNotificationStoreBasePath(contextBasePath(ctx)));
|
|
79
315
|
installNotifyInterceptor(ctx);
|
|
80
316
|
initNotificationWidget(ctx);
|
|
81
317
|
}
|
|
@@ -109,64 +345,47 @@ async function writeContextModeCompactionSnapshot(basePath) {
|
|
|
109
345
|
}
|
|
110
346
|
export function registerHooks(pi, ecosystemHandlers) {
|
|
111
347
|
pi.on("session_start", async (_event, ctx) => {
|
|
348
|
+
const basePath = contextBasePath(ctx);
|
|
112
349
|
initSessionNotifications(ctx);
|
|
113
350
|
if (!isAutoActive()) {
|
|
114
351
|
const { initHealthWidget } = await import("../health-widget.js");
|
|
115
352
|
initHealthWidget(ctx);
|
|
116
353
|
}
|
|
117
|
-
resetWriteGateState(
|
|
354
|
+
resetWriteGateState(basePath);
|
|
118
355
|
resetToolCallLoopGuard();
|
|
119
356
|
approvalQuestionAbortInFlight = false;
|
|
357
|
+
clearDeferredApprovalGate();
|
|
120
358
|
await resetAskUserQuestionsTurnCache();
|
|
121
359
|
await syncServiceTierStatus(ctx);
|
|
122
360
|
await applyDisabledModelProviderPolicy(ctx);
|
|
123
361
|
await applyCompactionThresholdOverride(ctx);
|
|
124
362
|
// Skip MCP auto-prep when running inside an auto-worktree (see session_switch below).
|
|
125
363
|
const { isInAutoWorktree } = await import("../auto-worktree.js");
|
|
126
|
-
if (!isInAutoWorktree(
|
|
364
|
+
if (!isInAutoWorktree(basePath)) {
|
|
127
365
|
const { prepareWorkflowMcpForProject } = await import("../workflow-mcp-auto-prep.js");
|
|
128
|
-
prepareWorkflowMcpForProject(ctx,
|
|
366
|
+
prepareWorkflowMcpForProject(ctx, basePath);
|
|
129
367
|
}
|
|
130
368
|
// Apply show_token_cost preference (#1515)
|
|
131
369
|
try {
|
|
132
370
|
const { loadEffectiveGSDPreferences } = await import("../preferences.js");
|
|
133
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
371
|
+
const prefs = loadEffectiveGSDPreferences(basePath);
|
|
134
372
|
process.env.GSD_SHOW_TOKEN_COST = prefs?.preferences.show_token_cost ? "1" : "";
|
|
135
373
|
}
|
|
136
374
|
catch { /* non-fatal */ }
|
|
137
|
-
|
|
138
|
-
isFirstSession = false;
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
try {
|
|
142
|
-
const gsdBinPath = process.env.GSD_BIN_PATH;
|
|
143
|
-
if (gsdBinPath) {
|
|
144
|
-
const { dirname } = await import("node:path");
|
|
145
|
-
const { printWelcomeScreen } = await import(join(dirname(gsdBinPath), "welcome-screen.js"));
|
|
146
|
-
let remoteChannel;
|
|
147
|
-
try {
|
|
148
|
-
const { resolveRemoteConfig } = await import("../../remote-questions/config.js");
|
|
149
|
-
const rc = resolveRemoteConfig();
|
|
150
|
-
if (rc)
|
|
151
|
-
remoteChannel = rc.channel;
|
|
152
|
-
}
|
|
153
|
-
catch { /* non-fatal */ }
|
|
154
|
-
printWelcomeScreen({ version: process.env.GSD_VERSION || "0.0.0", remoteChannel });
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
catch { /* non-fatal */ }
|
|
158
|
-
}
|
|
375
|
+
await installWelcomeHeader(ctx);
|
|
159
376
|
await loadToolApiKeysForSession();
|
|
160
377
|
if (isAutoActive()) {
|
|
161
378
|
ctx.ui.setWidget("gsd-health", undefined);
|
|
162
379
|
}
|
|
163
380
|
});
|
|
164
381
|
pi.on("session_switch", async (_event, ctx) => {
|
|
382
|
+
const basePath = contextBasePath(ctx);
|
|
165
383
|
initSessionNotifications(ctx);
|
|
166
|
-
resetWriteGateState(
|
|
384
|
+
resetWriteGateState(basePath);
|
|
167
385
|
resetToolCallLoopGuard();
|
|
386
|
+
clearDeferredApprovalGate();
|
|
168
387
|
await resetAskUserQuestionsTurnCache();
|
|
169
|
-
clearDiscussionFlowState(
|
|
388
|
+
clearDiscussionFlowState(basePath);
|
|
170
389
|
await syncServiceTierStatus(ctx);
|
|
171
390
|
await applyDisabledModelProviderPolicy(ctx);
|
|
172
391
|
await applyCompactionThresholdOverride(ctx);
|
|
@@ -175,9 +394,9 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
175
394
|
// post-chdir rewrites the file mid-run (non-idempotent due to cwd-relative
|
|
176
395
|
// CLI path resolution), dirtying the tree and breaking the milestone merge.
|
|
177
396
|
const { isInAutoWorktree } = await import("../auto-worktree.js");
|
|
178
|
-
if (!isInAutoWorktree(
|
|
397
|
+
if (!isInAutoWorktree(basePath)) {
|
|
179
398
|
const { prepareWorkflowMcpForProject } = await import("../workflow-mcp-auto-prep.js");
|
|
180
|
-
prepareWorkflowMcpForProject(ctx,
|
|
399
|
+
prepareWorkflowMcpForProject(ctx, basePath);
|
|
181
400
|
}
|
|
182
401
|
await loadToolApiKeysForSession();
|
|
183
402
|
if (!isAutoActive()) {
|
|
@@ -189,10 +408,11 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
189
408
|
}
|
|
190
409
|
});
|
|
191
410
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
411
|
+
applyMinimalGsdToolSurface(pi);
|
|
192
412
|
// Wait for ecosystem loader to finish (no-op after first turn).
|
|
193
413
|
const { getEcosystemReadyPromise } = await import("../ecosystem/loader.js");
|
|
194
414
|
await getEcosystemReadyPromise();
|
|
195
|
-
const beforeAgentBasePath =
|
|
415
|
+
const beforeAgentBasePath = contextBasePath(ctx);
|
|
196
416
|
const pendingApprovalGate = getPendingGate(beforeAgentBasePath);
|
|
197
417
|
if (pendingApprovalGate && isExplicitApprovalResponse(event.prompt, pendingApprovalGate)) {
|
|
198
418
|
markApprovalGateVerified(pendingApprovalGate, beforeAgentBasePath);
|
|
@@ -201,13 +421,14 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
201
421
|
markDepthVerified(milestoneId, beforeAgentBasePath);
|
|
202
422
|
clearPendingGate(beforeAgentBasePath);
|
|
203
423
|
}
|
|
424
|
+
clearDeferredApprovalGate(beforeAgentBasePath);
|
|
204
425
|
// GSD's own context injection (existing behavior — unchanged).
|
|
205
426
|
const { buildBeforeAgentStartResult } = await import("./system-context.js");
|
|
206
427
|
const gsdResult = await buildBeforeAgentStartResult(event, ctx);
|
|
207
428
|
// Refresh the snapshot used by ecosystem getPhase()/getActiveUnit().
|
|
208
429
|
// deriveState has its own ~100ms cache so this is cheap on repeat calls.
|
|
209
430
|
try {
|
|
210
|
-
const state = await deriveGsdState(
|
|
431
|
+
const state = await deriveGsdState(beforeAgentBasePath);
|
|
211
432
|
updateSnapshot(state);
|
|
212
433
|
}
|
|
213
434
|
catch {
|
|
@@ -244,7 +465,12 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
244
465
|
resetToolCallLoopGuard();
|
|
245
466
|
await resetAskUserQuestionsTurnCache();
|
|
246
467
|
const { handleAgentEnd } = await import("./agent-end-recovery.js");
|
|
247
|
-
|
|
468
|
+
try {
|
|
469
|
+
await handleAgentEnd(pi, event, ctx);
|
|
470
|
+
}
|
|
471
|
+
finally {
|
|
472
|
+
activateDeferredApprovalGate(contextBasePath(ctx));
|
|
473
|
+
}
|
|
248
474
|
});
|
|
249
475
|
// Squash-merge quick-task branch back to the original branch after the
|
|
250
476
|
// agent turn completes (#2668). cleanupQuickBranch is a no-op when no
|
|
@@ -258,8 +484,8 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
258
484
|
// Best-effort: don't break the turn lifecycle if cleanup fails.
|
|
259
485
|
}
|
|
260
486
|
});
|
|
261
|
-
pi.on("session_before_compact", async () => {
|
|
262
|
-
const basePath =
|
|
487
|
+
pi.on("session_before_compact", async (_event, ctx) => {
|
|
488
|
+
const basePath = contextBasePath(ctx);
|
|
263
489
|
// Context Mode is default-on. Write the resumable snapshot before any
|
|
264
490
|
// active-auto cancel return so auto sessions still leave re-entry context.
|
|
265
491
|
await writeContextModeCompactionSnapshot(basePath);
|
|
@@ -323,7 +549,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
323
549
|
if (!unitType) {
|
|
324
550
|
try {
|
|
325
551
|
const { getPendingDeepProjectSetupUnitForContext } = await import("../guided-flow.js");
|
|
326
|
-
const pending = getPendingDeepProjectSetupUnitForContext(ctx,
|
|
552
|
+
const pending = getPendingDeepProjectSetupUnitForContext(ctx, contextBasePath(ctx));
|
|
327
553
|
unitType = pending?.unitType;
|
|
328
554
|
unitId = pending?.unitId;
|
|
329
555
|
}
|
|
@@ -332,7 +558,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
332
558
|
}
|
|
333
559
|
}
|
|
334
560
|
if (!unitType) {
|
|
335
|
-
const milestoneId = await getDiscussionMilestoneIdFor(
|
|
561
|
+
const milestoneId = await getDiscussionMilestoneIdFor(contextBasePath(ctx));
|
|
336
562
|
if (milestoneId) {
|
|
337
563
|
unitType = "discuss-milestone";
|
|
338
564
|
unitId = milestoneId;
|
|
@@ -342,11 +568,12 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
342
568
|
return;
|
|
343
569
|
const gateId = approvalGateIdForUnit(unitType, unitId);
|
|
344
570
|
if (gateId)
|
|
345
|
-
|
|
571
|
+
deferApprovalGate(gateId, contextBasePath(ctx));
|
|
346
572
|
approvalQuestionAbortInFlight = true;
|
|
347
573
|
ctx.ui.notify(`${unitType}${unitId ? ` ${unitId}` : ""} is waiting for your approval - pausing before more tool calls run.`, "info");
|
|
348
|
-
// The pending gate
|
|
349
|
-
//
|
|
574
|
+
// The durable pending gate is activated at agent_end so same-turn
|
|
575
|
+
// CONTEXT-DRAFT persistence can finish after the text boundary streams.
|
|
576
|
+
// The tool_call hook below still blocks non-draft tools in this turn.
|
|
350
577
|
// Aborting mid-stream eats the model's question text on external CLI
|
|
351
578
|
// providers (Claude Code SDK) because lastTextContent isn't populated
|
|
352
579
|
// from in-flight builder state — the user only ever sees "Claude Code
|
|
@@ -356,7 +583,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
356
583
|
const { isParallelActive, shutdownParallel } = await import("../parallel-orchestrator.js");
|
|
357
584
|
if (isParallelActive()) {
|
|
358
585
|
try {
|
|
359
|
-
await shutdownParallel(
|
|
586
|
+
await shutdownParallel(contextBasePath(ctx));
|
|
360
587
|
}
|
|
361
588
|
catch {
|
|
362
589
|
// best-effort
|
|
@@ -369,14 +596,17 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
369
596
|
saveActivityLog(ctx, dash.basePath, dash.currentUnit.type, dash.currentUnit.id);
|
|
370
597
|
}
|
|
371
598
|
});
|
|
372
|
-
pi.on("tool_call", async (event) => {
|
|
373
|
-
const discussionBasePath =
|
|
599
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
600
|
+
const discussionBasePath = contextBasePath(ctx);
|
|
374
601
|
const toolName = canonicalToolName(event.toolName);
|
|
375
602
|
// ── Loop guard: block repeated identical tool calls ──
|
|
376
603
|
const loopCheck = checkToolCallLoop(toolName, event.input);
|
|
377
604
|
if (loopCheck.block) {
|
|
378
605
|
return { block: true, reason: loopCheck.reason };
|
|
379
606
|
}
|
|
607
|
+
const deferredGateGuard = shouldBlockDeferredApprovalTool(toolName, event.input, discussionBasePath);
|
|
608
|
+
if (deferredGateGuard.block)
|
|
609
|
+
return deferredGateGuard;
|
|
380
610
|
// ── Discussion gate enforcement: track pending gate questions ─────────
|
|
381
611
|
// Only gate-shaped ask_user_questions calls should block execution.
|
|
382
612
|
// The gate stays pending until the user selects the approval option.
|
|
@@ -515,7 +745,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
515
745
|
}
|
|
516
746
|
}
|
|
517
747
|
});
|
|
518
|
-
pi.on("tool_result", async (event) => {
|
|
748
|
+
pi.on("tool_result", async (event, ctx) => {
|
|
519
749
|
if (isAutoActive() && typeof event.toolCallId === "string") {
|
|
520
750
|
markToolEnd(event.toolCallId);
|
|
521
751
|
}
|
|
@@ -535,7 +765,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
535
765
|
const toolName = canonicalToolName(event.toolName);
|
|
536
766
|
if (toolName !== "ask_user_questions")
|
|
537
767
|
return;
|
|
538
|
-
const basePath =
|
|
768
|
+
const basePath = contextBasePath(ctx);
|
|
539
769
|
const milestoneId = await getDiscussionMilestoneIdFor(basePath);
|
|
540
770
|
const queueActive = isQueuePhaseActive(basePath);
|
|
541
771
|
const details = event.details;
|
|
@@ -737,8 +967,22 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
737
967
|
// Tool set adaptation hook (ADR-005 Phase 4)
|
|
738
968
|
// Extensions can override tool set after model selection by returning { toolNames: [...] }
|
|
739
969
|
// Return undefined to let the built-in provider compatibility filtering proceed.
|
|
740
|
-
pi.on("adjust_tool_set", async (
|
|
741
|
-
|
|
970
|
+
pi.on("adjust_tool_set", async (event) => {
|
|
971
|
+
if (isFullGsdToolSurfaceRequested())
|
|
972
|
+
return undefined;
|
|
973
|
+
const removed = new Set(event.filteredTools);
|
|
974
|
+
const providerCompatible = event.activeToolNames.filter((name) => !removed.has(name));
|
|
975
|
+
const requestScoped = buildRequestScopedGsdToolSet(providerCompatible, event.requestCustomMessages);
|
|
976
|
+
if (requestScoped) {
|
|
977
|
+
return { toolNames: requestScoped };
|
|
978
|
+
}
|
|
979
|
+
const dash = getAutoRuntimeSnapshot();
|
|
980
|
+
if (dash.active && dash.currentUnit) {
|
|
981
|
+
return { toolNames: buildMinimalAutoGsdToolSet(providerCompatible, dash.currentUnit.type) };
|
|
982
|
+
}
|
|
983
|
+
if (isGeneralGsdToolScopingRequested()) {
|
|
984
|
+
return { toolNames: buildMinimalGsdToolSet(providerCompatible) };
|
|
985
|
+
}
|
|
742
986
|
return undefined;
|
|
743
987
|
});
|
|
744
988
|
}
|