gsd-pi 2.80.0-dev.488219eb6 → 2.80.0-dev.4edec4620

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 (71) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -3
  3. package/dist/resources/extensions/gsd/auto-dashboard.js +18 -0
  4. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +21 -10
  5. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +19 -2
  6. package/dist/resources/extensions/gsd/guided-flow.js +6 -0
  7. package/dist/resources/extensions/gsd/health-widget.js +3 -0
  8. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  9. package/dist/web/standalone/.next/BUILD_ID +1 -1
  10. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  11. package/dist/web/standalone/.next/build-manifest.json +2 -2
  12. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  13. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  14. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  15. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  17. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  18. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  19. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  20. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/index.html +1 -1
  30. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  37. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  38. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  39. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  40. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  41. package/package.json +1 -1
  42. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  43. package/packages/pi-ai/dist/types.d.ts +2 -0
  44. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  45. package/packages/pi-ai/dist/types.js.map +1 -1
  46. package/packages/pi-ai/src/types.ts +3 -0
  47. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  48. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +12 -1
  49. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  50. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +5 -0
  51. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  52. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -0
  53. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  54. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  55. package/packages/pi-coding-agent/dist/core/sdk.js +7 -2
  56. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  57. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +15 -1
  58. package/packages/pi-coding-agent/src/core/agent-session.ts +11 -0
  59. package/packages/pi-coding-agent/src/core/sdk.ts +7 -1
  60. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  61. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +12 -3
  62. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +41 -0
  63. package/src/resources/extensions/gsd/auto-dashboard.ts +20 -0
  64. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +20 -10
  65. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -2
  66. package/src/resources/extensions/gsd/guided-flow.ts +6 -0
  67. package/src/resources/extensions/gsd/health-widget.ts +3 -0
  68. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +210 -0
  69. package/src/resources/extensions/gsd/tests/write-gate.test.ts +40 -1
  70. /package/dist/web/standalone/.next/static/{G68KoLv5claox_Dyd4pZn → eeMbUJZnoHp7l3SZHeXY9}/_buildManifest.js +0 -0
  71. /package/dist/web/standalone/.next/static/{G68KoLv5claox_Dyd4pZn → eeMbUJZnoHp7l3SZHeXY9}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- 186fe07f8b8d9487
1
+ ddf27c3bbbe27e53
@@ -1,3 +1,4 @@
1
+ // GSD2 - Claude Code CLI provider stream adapter
1
2
  /**
2
3
  * Stream adapter: bridges the Claude Agent SDK into GSD's streamSimple contract.
3
4
  *
@@ -16,6 +17,10 @@ import { dirname, join } from "node:path";
16
17
  import { PartialMessageBuilder, ZERO_USAGE, mapUsage } from "./partial-builder.js";
17
18
  import { buildWorkflowMcpServers } from "../gsd/workflow-mcp.js";
18
19
  import { showInterviewRound } from "../shared/tui.js";
20
+ /** Resolve the workspace root for local Claude Code process execution. */
21
+ export function resolveClaudeCodeCwd(options) {
22
+ return options?.cwd && options.cwd.trim().length > 0 ? options.cwd : process.cwd();
23
+ }
19
24
  /** Label used for the free-text fallback option in single-choice elicitation questions. */
20
25
  const OTHER_OPTION_LABEL = "None of the above";
21
26
  /** Regex pattern that identifies field names and descriptions that should be treated as sensitive/secure inputs. */
@@ -1051,8 +1056,9 @@ function mapThinkingLevelToAnthropicEffort(level, modelId) {
1051
1056
  * behaviour pass `permissionMode: "bypassPermissions"` explicitly.
1052
1057
  */
1053
1058
  export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
1054
- const { reasoning, ...sdkExtraOptions } = extraOptions;
1055
- const mcpServers = buildWorkflowMcpServers();
1059
+ const { reasoning, cwd, ...sdkExtraOptions } = extraOptions;
1060
+ const sdkCwd = typeof cwd === "string" && cwd.trim().length > 0 ? cwd : process.cwd();
1061
+ const mcpServers = buildWorkflowMcpServers(sdkCwd);
1056
1062
  const permissionMode = overrides?.permissionMode ?? "bypassPermissions";
1057
1063
  // Globally unblock the tools GSD expects Claude Code to run. When the
1058
1064
  // workflow MCP server is available, prefer its `ask_user_questions` tool over
@@ -1090,7 +1096,7 @@ export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
1090
1096
  model: modelId,
1091
1097
  includePartialMessages: true,
1092
1098
  persistSession: true,
1093
- cwd: process.cwd(),
1099
+ cwd: sdkCwd,
1094
1100
  permissionMode,
1095
1101
  allowDangerouslySkipPermissions: permissionMode === "bypassPermissions",
1096
1102
  settingSources: ["project"],
@@ -1352,12 +1358,14 @@ async function pumpSdkMessages(model, context, options, stream) {
1352
1358
  const queryPrompt = buildSdkQueryPrompt(context, prompt);
1353
1359
  const permissionMode = await resolveClaudePermissionMode();
1354
1360
  const uiContext = options?.extensionUIContext;
1361
+ const cwd = resolveClaudeCodeCwd(options);
1355
1362
  const canUseToolHandler = createClaudeCodeCanUseToolHandler(uiContext);
1356
1363
  // When no UI is available (headless / auto-mode), auto-approve all
1357
1364
  // tool requests. This replaces the old bypassPermissions workaround.
1358
1365
  const canUseToolFallback = canUseToolHandler
1359
1366
  ?? (async (_toolName, _input, opts) => ({ behavior: "allow", toolUseID: opts.toolUseID }));
1360
1367
  const sdkOpts = buildSdkOptions(modelId, prompt, { permissionMode }, {
1368
+ cwd,
1361
1369
  reasoning: options?.reasoning,
1362
1370
  canUseTool: canUseToolFallback,
1363
1371
  ...(uiContext
@@ -468,6 +468,20 @@ export function _resetWidgetModeForTests() {
468
468
  export function updateProgressWidget(ctx, unitType, unitId, state, accessors, tierBadge) {
469
469
  if (!ctx.hasUI)
470
470
  return;
471
+ // Welcome header is a startup-only banner — permanently suppress it once
472
+ // auto-mode activates. The dashboard widget owns all status from here.
473
+ // Note: setHeader(undefined) restores the built-in header (logo +
474
+ // instructions). To actually render zero lines, install an empty header.
475
+ if (typeof ctx.ui?.setHeader === "function") {
476
+ ctx.ui.setHeader(() => ({
477
+ render() { return []; },
478
+ invalidate() { },
479
+ }));
480
+ }
481
+ // Clear wizard step badge — auto-mode owns the UI from this point
482
+ if (typeof ctx.ui?.setStatus === "function") {
483
+ ctx.ui.setStatus("gsd-step", undefined);
484
+ }
471
485
  const verb = unitVerb(unitType);
472
486
  const phaseLabel = unitPhaseLabel(unitType);
473
487
  const mid = state.activeMilestone;
@@ -857,6 +871,10 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
857
871
  ? lastCommit.message.slice(0, maxCommitLen - 1) + "…"
858
872
  : lastCommit.message
859
873
  : "";
874
+ // Step-mode guidance — shown above keyboard hints when auto is paused
875
+ if (accessors.isStepMode()) {
876
+ lines.push(`${pad}${theme.fg("accent", "→")} ${theme.fg("dim", "Ctrl+N to advance to next step · /gsd status for overview")}`);
877
+ }
860
878
  // Hints line
861
879
  const hintParts = [];
862
880
  hintParts.push("esc pause");
@@ -66,16 +66,27 @@ async function installWelcomeHeader(ctx) {
66
66
  remoteChannel = rc.channel;
67
67
  }
68
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
- }));
69
+ ctx.ui.setHeader(() => {
70
+ let cachedLines;
71
+ let cachedWidth;
72
+ return {
73
+ render(width) {
74
+ if (cachedLines !== undefined && cachedWidth === width)
75
+ return cachedLines;
76
+ cachedLines = welcome.buildWelcomeScreenLines({
77
+ version: process.env.GSD_VERSION || "0.0.0",
78
+ remoteChannel,
79
+ width,
80
+ });
81
+ cachedWidth = width;
82
+ return cachedLines;
83
+ },
84
+ invalidate() {
85
+ cachedLines = undefined;
86
+ cachedWidth = undefined;
87
+ },
88
+ };
89
+ });
79
90
  }
80
91
  catch {
81
92
  /* non-fatal */
@@ -1,4 +1,5 @@
1
- import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
1
+ // GSD2 - Write gate runtime persistence and policy guards.
2
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, realpathSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
3
  import { isAbsolute, join, relative, resolve, sep } from "node:path";
3
4
  import { minimatch } from "minimatch";
4
5
  import { getIsolationMode } from "../preferences.js";
@@ -116,6 +117,22 @@ function shouldPersistWriteGateSnapshot(env = process.env) {
116
117
  function writeGateSnapshotPath(basePath) {
117
118
  return join(basePath, ".gsd", "runtime", "write-gate-state.json");
118
119
  }
120
+ function ensureWriteGateSnapshotDirectory(basePath) {
121
+ const gsdPath = join(basePath, ".gsd");
122
+ if (!existsSync(gsdPath)) {
123
+ try {
124
+ const stat = lstatSync(gsdPath);
125
+ if (stat.isSymbolicLink()) {
126
+ const target = readlinkSync(gsdPath);
127
+ mkdirSync(isAbsolute(target) ? target : resolve(basePath, target), { recursive: true });
128
+ }
129
+ }
130
+ catch {
131
+ // If .gsd truly does not exist, the runtime mkdir below will create it.
132
+ }
133
+ }
134
+ mkdirSync(join(gsdPath, "runtime"), { recursive: true });
135
+ }
119
136
  function currentWriteGateSnapshot(basePath = process.cwd()) {
120
137
  const state = getWriteGateState(basePath);
121
138
  return {
@@ -129,7 +146,7 @@ function persistWriteGateSnapshot(basePath) {
129
146
  if (!shouldPersistWriteGateSnapshot())
130
147
  return;
131
148
  const path = writeGateSnapshotPath(basePath);
132
- mkdirSync(join(basePath, ".gsd", "runtime"), { recursive: true });
149
+ ensureWriteGateSnapshotDirectory(basePath);
133
150
  const tempPath = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
134
151
  writeFileSync(tempPath, JSON.stringify(currentWriteGateSnapshot(basePath), null, 2), "utf-8");
135
152
  try {
@@ -1844,6 +1844,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
1844
1844
  const isFirst = milestoneIds.length === 0;
1845
1845
  if (isFirst) {
1846
1846
  // First ever — skip wizard, just ask directly
1847
+ ctx.ui.setStatus("gsd-step", "New Milestone · answer the questions above to plan");
1847
1848
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode });
1848
1849
  await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New project, milestone ${nextId}. Do NOT read or explore .gsd/ — it's empty scaffolding.`, basePath), "gsd-run", ctx, "discuss-milestone");
1849
1850
  }
@@ -1870,6 +1871,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
1870
1871
  await runQuickTaskChoice(ctx, pi);
1871
1872
  }
1872
1873
  else if (choice === "new_milestone") {
1874
+ ctx.ui.setStatus("gsd-step", "New Milestone · answer the questions above to plan");
1873
1875
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode });
1874
1876
  await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
1875
1877
  }
@@ -2042,6 +2044,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
2042
2044
  await runQuickTaskChoice(ctx, pi);
2043
2045
  }
2044
2046
  else if (choice === "plan") {
2047
+ ctx.ui.setStatus("gsd-step", "Planning Milestone · decomposing into slices");
2045
2048
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId, step: stepMode });
2046
2049
  await dispatchWorkflow(pi, await buildPlanMilestonePrompt(milestoneId, milestoneTitle, basePath), "gsd-run", ctx, "plan-milestone");
2047
2050
  }
@@ -2166,6 +2169,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
2166
2169
  notYetMessage: "Run /gsd when ready.",
2167
2170
  });
2168
2171
  if (choice === "plan") {
2172
+ ctx.ui.setStatus("gsd-step", "Slice Planning · answer the questions above");
2169
2173
  await dispatchWorkflow(pi, await buildPlanSlicePrompt(milestoneId, milestoneTitle, sliceId, sliceTitle, basePath), "gsd-run", ctx, "plan-slice");
2170
2174
  }
2171
2175
  else if (choice === "discuss") {
@@ -2225,6 +2229,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
2225
2229
  notYetMessage: "Run /gsd when ready.",
2226
2230
  });
2227
2231
  if (choice === "complete") {
2232
+ ctx.ui.setStatus("gsd-step", "Completing Slice · review changes above");
2228
2233
  await dispatchWorkflow(pi, await buildCompleteSlicePrompt(milestoneId, milestoneTitle, sliceId, sliceTitle, basePath), "gsd-run", ctx, "complete-slice");
2229
2234
  }
2230
2235
  else if (choice === "status") {
@@ -2285,6 +2290,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
2285
2290
  return;
2286
2291
  }
2287
2292
  if (choice === "execute") {
2293
+ ctx.ui.setStatus("gsd-step", "Executing Task · follow progress above");
2288
2294
  if (hasInterrupted) {
2289
2295
  await dispatchWorkflow(pi, loadPrompt("guided-resume-task", {
2290
2296
  milestoneId,
@@ -118,6 +118,9 @@ export function initHealthWidget(ctx) {
118
118
  render(width) {
119
119
  if (!cachedLines || cachedWidth !== width) {
120
120
  cachedLines = buildHealthLines(data, width);
121
+ if (data.projectState === "active") {
122
+ cachedLines = [...cachedLines, _theme.fg("dim", " /gsd auto to run · /gsd status for overview · /gsd help")];
123
+ }
121
124
  cachedWidth = width;
122
125
  }
123
126
  return cachedLines;