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.
Files changed (237) hide show
  1. package/dist/cli.js +0 -19
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
  4. package/dist/resources/extensions/gsd/auto/loop.js +71 -8
  5. package/dist/resources/extensions/gsd/auto/phases.js +150 -94
  6. package/dist/resources/extensions/gsd/auto/resolve.js +12 -0
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +10 -30
  8. package/dist/resources/extensions/gsd/auto/session.js +8 -0
  9. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  10. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  11. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
  12. package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +17 -4
  14. package/dist/resources/extensions/gsd/auto-prompts.js +90 -15
  15. package/dist/resources/extensions/gsd/auto-start.js +197 -6
  16. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  17. package/dist/resources/extensions/gsd/auto.js +18 -22
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +86 -19
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
  20. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
  21. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +9 -3
  22. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
  23. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
  24. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +298 -54
  26. package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
  27. package/dist/resources/extensions/gsd/clean-root-preflight.js +24 -6
  28. package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
  29. package/dist/resources/extensions/gsd/db/unit-dispatches.js +53 -0
  30. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
  31. package/dist/resources/extensions/gsd/guided-flow.js +47 -28
  32. package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
  33. package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
  34. package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
  35. package/dist/resources/extensions/gsd/pre-execution-checks.js +15 -0
  36. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
  37. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  38. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  39. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  40. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  41. package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
  42. package/dist/resources/extensions/gsd/worktree-resolver.js +35 -4
  43. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  44. package/dist/web/standalone/.next/BUILD_ID +1 -1
  45. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  46. package/dist/web/standalone/.next/build-manifest.json +2 -2
  47. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  48. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  49. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  57. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/index.html +1 -1
  65. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  72. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  74. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  75. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  76. package/dist/welcome-screen.d.ts +2 -0
  77. package/dist/welcome-screen.js +9 -7
  78. package/package.json +1 -1
  79. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  80. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  81. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  82. package/packages/pi-agent-core/dist/agent.d.ts +5 -0
  83. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  84. package/packages/pi-agent-core/dist/agent.js +2 -0
  85. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  86. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  87. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  88. package/packages/pi-agent-core/dist/index.js +2 -0
  89. package/packages/pi-agent-core/dist/index.js.map +1 -1
  90. package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
  91. package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
  92. package/packages/pi-agent-core/dist/token-audit.js +221 -0
  93. package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
  94. package/packages/pi-agent-core/dist/types.d.ts +9 -0
  95. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  96. package/packages/pi-agent-core/dist/types.js.map +1 -1
  97. package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
  98. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  99. package/packages/pi-agent-core/src/agent.ts +8 -0
  100. package/packages/pi-agent-core/src/index.ts +2 -0
  101. package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
  102. package/packages/pi-agent-core/src/token-audit.ts +287 -0
  103. package/packages/pi-agent-core/src/types.ts +14 -0
  104. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  105. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +18 -0
  106. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  107. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
  108. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  109. package/packages/pi-coding-agent/dist/core/agent-session.js +36 -7
  110. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  111. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  112. package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
  113. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  114. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
  115. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  116. package/packages/pi-coding-agent/dist/core/extensions/runner.js +3 -6
  117. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  118. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +3 -3
  119. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  120. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +32 -1
  121. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  122. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  123. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
  124. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
  125. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
  126. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
  127. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
  128. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
  129. package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
  130. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  131. package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
  132. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  133. package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
  134. package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
  135. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
  136. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  137. package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
  138. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  139. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
  140. package/packages/pi-coding-agent/src/core/agent-session.ts +40 -7
  141. package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
  142. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +3 -3
  143. package/packages/pi-coding-agent/src/core/extensions/runner.ts +5 -5
  144. package/packages/pi-coding-agent/src/core/extensions/types.ts +35 -1
  145. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
  146. package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
  147. package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
  148. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
  149. package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
  150. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  151. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
  152. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
  153. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -2
  154. package/src/resources/extensions/gsd/auto/loop.ts +84 -8
  155. package/src/resources/extensions/gsd/auto/phases.ts +218 -154
  156. package/src/resources/extensions/gsd/auto/resolve.ts +19 -0
  157. package/src/resources/extensions/gsd/auto/run-unit.ts +10 -29
  158. package/src/resources/extensions/gsd/auto/session.ts +8 -0
  159. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  160. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  161. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
  162. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -0
  163. package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
  164. package/src/resources/extensions/gsd/auto-prompts.ts +95 -14
  165. package/src/resources/extensions/gsd/auto-start.ts +230 -9
  166. package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
  167. package/src/resources/extensions/gsd/auto.ts +18 -18
  168. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +100 -18
  169. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
  170. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
  171. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +10 -3
  172. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
  173. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
  174. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
  175. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +347 -54
  176. package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
  177. package/src/resources/extensions/gsd/clean-root-preflight.ts +32 -7
  178. package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
  179. package/src/resources/extensions/gsd/db/unit-dispatches.ts +66 -0
  180. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
  181. package/src/resources/extensions/gsd/guided-flow.ts +52 -35
  182. package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
  183. package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
  184. package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
  185. package/src/resources/extensions/gsd/pre-execution-checks.ts +16 -0
  186. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
  187. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  188. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  189. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  190. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  191. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
  192. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +361 -10
  193. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +168 -6
  194. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +15 -6
  195. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
  196. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
  197. package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
  198. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +5 -1
  199. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
  200. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
  201. package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
  202. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
  203. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +5 -1
  204. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
  205. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
  206. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
  207. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
  208. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
  209. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
  210. package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
  211. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
  212. package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
  213. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +7 -5
  214. package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
  215. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
  216. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
  217. package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
  218. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  219. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -0
  220. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  221. package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
  222. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
  223. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
  224. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +50 -1
  225. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
  226. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  227. package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
  228. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  229. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
  230. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
  231. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
  232. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +104 -3
  233. package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
  234. package/src/resources/extensions/gsd/worktree-resolver.ts +49 -4
  235. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
  236. /package/dist/web/standalone/.next/static/{-5nHJWzSdG-WkPMul_khA → cWaxzf-sdbSSbbwYu8q7a}/_buildManifest.js +0 -0
  237. /package/dist/web/standalone/.next/static/{-5nHJWzSdG-WkPMul_khA → cWaxzf-sdbSSbbwYu8q7a}/_ssgManifest.js +0 -0
@@ -1,4 +1,8 @@
1
- import { join } from "node:path";
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
- // Skip the welcome screen on the very first session_start — cli.ts already
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
- export function resolveNotificationStoreBasePath(cwd = process.cwd()) {
75
- return resolveWorktreeProjectRoot(cwd);
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(process.cwd());
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(process.cwd())) {
364
+ if (!isInAutoWorktree(basePath)) {
127
365
  const { prepareWorkflowMcpForProject } = await import("../workflow-mcp-auto-prep.js");
128
- prepareWorkflowMcpForProject(ctx, process.cwd());
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
- if (isFirstSession) {
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(process.cwd());
384
+ resetWriteGateState(basePath);
167
385
  resetToolCallLoopGuard();
386
+ clearDeferredApprovalGate();
168
387
  await resetAskUserQuestionsTurnCache();
169
- clearDiscussionFlowState(process.cwd());
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(process.cwd())) {
397
+ if (!isInAutoWorktree(basePath)) {
179
398
  const { prepareWorkflowMcpForProject } = await import("../workflow-mcp-auto-prep.js");
180
- prepareWorkflowMcpForProject(ctx, process.cwd());
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 = process.cwd();
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(process.cwd());
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
- await handleAgentEnd(pi, event, ctx);
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 = process.cwd();
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, process.cwd());
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(process.cwd());
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
- setPendingGate(gateId, process.cwd());
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 set above blocks subsequent non-read-only tool calls
349
- // via the tool_call hook below, so we do not abort the in-flight stream.
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(process.cwd());
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 = process.cwd();
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 = process.cwd();
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 (_event) => {
741
- // Default: no override — let provider capability filtering handle tool set
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
  }