gsd-pi 2.80.0-dev.0d763dc29 → 2.80.0-dev.1486c1899

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 (150) hide show
  1. package/README.md +4 -2
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/gsd/auto/phases.js +22 -15
  4. package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
  5. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -1
  6. package/dist/resources/extensions/gsd/auto-prompts.js +13 -1
  7. package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
  8. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  9. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  10. package/dist/resources/extensions/gsd/auto.js +52 -4
  11. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +21 -2
  12. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +27 -20
  13. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +21 -0
  14. package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
  15. package/dist/resources/extensions/gsd/guided-flow.js +19 -4
  16. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  17. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  18. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  19. package/dist/resources/extensions/gsd/quick.js +34 -2
  20. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  21. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  22. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  23. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  24. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  25. package/dist/resources/extensions/gsd/unit-runtime.js +11 -0
  26. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  27. package/dist/web/standalone/.next/BUILD_ID +1 -1
  28. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  29. package/dist/web/standalone/.next/build-manifest.json +2 -2
  30. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  31. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  32. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  46. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/index.html +1 -1
  48. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  55. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  57. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  58. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  59. package/package.json +3 -3
  60. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  61. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  62. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  63. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  64. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  65. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  66. package/packages/native/tsconfig.tsbuildinfo +1 -1
  67. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  68. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  69. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  70. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -0
  71. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  72. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  73. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  74. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  75. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  76. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  77. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  78. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  79. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  80. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -0
  81. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  82. package/packages/pi-coding-agent/dist/core/extensions/runner.js +3 -0
  83. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  84. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +2 -0
  85. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  86. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
  87. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  88. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  89. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
  90. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  91. package/packages/pi-coding-agent/dist/core/settings-manager.js +25 -0
  92. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  93. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  94. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +3 -0
  95. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  96. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  97. package/packages/pi-coding-agent/src/core/agent-session.ts +8 -0
  98. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  99. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  100. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +2 -0
  101. package/packages/pi-coding-agent/src/core/extensions/runner.ts +3 -0
  102. package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
  103. package/packages/pi-coding-agent/src/core/settings-manager.ts +39 -1
  104. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +3 -0
  105. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  106. package/packages/pi-tui/dist/tui.js +1 -1
  107. package/packages/pi-tui/dist/tui.js.map +1 -1
  108. package/packages/pi-tui/src/tui.ts +1 -1
  109. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  110. package/src/resources/extensions/gsd/auto/phases.ts +28 -20
  111. package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
  112. package/src/resources/extensions/gsd/auto/run-unit.ts +18 -1
  113. package/src/resources/extensions/gsd/auto-prompts.ts +17 -1
  114. package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
  115. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  116. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  117. package/src/resources/extensions/gsd/auto.ts +60 -3
  118. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -1
  119. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +27 -19
  120. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
  121. package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
  122. package/src/resources/extensions/gsd/guided-flow.ts +32 -4
  123. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  124. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  125. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  126. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  127. package/src/resources/extensions/gsd/quick.ts +37 -2
  128. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +71 -0
  129. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +14 -1
  130. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +11 -0
  131. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  132. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  133. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +234 -0
  134. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  135. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  136. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  137. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  138. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +55 -0
  139. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
  140. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  141. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
  142. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
  143. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  144. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  145. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  146. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  147. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  148. package/src/resources/extensions/gsd/unit-runtime.ts +11 -0
  149. /package/dist/web/standalone/.next/static/{1J8mL3ANp9jqY3SU5BbVW → O-2rnxSJki_W-2fkK3zIj}/_buildManifest.js +0 -0
  150. /package/dist/web/standalone/.next/static/{1J8mL3ANp9jqY3SU5BbVW → O-2rnxSJki_W-2fkK3zIj}/_ssgManifest.js +0 -0
@@ -51,6 +51,21 @@ export { showQueue, handleQueueReorder, showQueueAdd, buildExistingMilestonesCon
51
51
  import { logWarning } from "./workflow-logger.js";
52
52
  import { deleteRuntimeKv } from "./db/runtime-kv.js";
53
53
  import { PAUSED_SESSION_KV_KEY } from "./interrupted-session.js";
54
+ function scheduleAutoStartAfterIdle(ctx, pi, basePath, verboseMode, options, launch = startAutoDetached) {
55
+ const waitForIdle = typeof ctx.waitForIdle === "function"
56
+ ? ctx.waitForIdle.bind(ctx)
57
+ : async () => { };
58
+ void waitForIdle()
59
+ .then(() => {
60
+ setTimeout(() => launch(ctx, pi, basePath, verboseMode, options), 0);
61
+ })
62
+ .catch((err) => {
63
+ const message = err instanceof Error ? err.message : String(err);
64
+ ctx.ui.notify(`Auto-start failed while waiting for the prior turn to settle: ${message}`, "error");
65
+ logWarning("guided", `auto-start idle wait failed: ${message}`);
66
+ });
67
+ }
68
+ export const _scheduleAutoStartAfterIdleForTest = scheduleAutoStartAfterIdle;
54
69
  // ─── Scope-based validator wrappers ──────────────────────────────────────────
55
70
  // These thin wrappers accept a MilestoneScope so callers that already hold a
56
71
  // pinned scope never have to re-derive (basePath, milestoneId) separately.
@@ -325,7 +340,7 @@ async function dispatchNextDeepProjectSetupStage(entry) {
325
340
  const { DISPATCH_RULES, hasPendingDeepStage } = await import("./auto-dispatch.js");
326
341
  if (!hasPendingDeepStage(prefs, entry.basePath)) {
327
342
  pendingDeepProjectSetupMap.delete(entry.basePath);
328
- startAutoDetached(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
343
+ scheduleAutoStartAfterIdle(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
329
344
  return true;
330
345
  }
331
346
  const state = await deriveState(entry.basePath);
@@ -359,14 +374,14 @@ async function dispatchNextDeepProjectSetupStage(entry) {
359
374
  }
360
375
  else if (hasPendingDeepStage(prefs, entry.basePath)) {
361
376
  pendingDeepProjectSetupMap.delete(entry.basePath);
362
- startAutoDetached(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
377
+ scheduleAutoStartAfterIdle(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
363
378
  return true;
364
379
  }
365
380
  return false;
366
381
  }
367
382
  if (!USER_DRIVEN_DEEP_SETUP_UNITS.has(result.unitType)) {
368
383
  pendingDeepProjectSetupMap.delete(entry.basePath);
369
- startAutoDetached(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
384
+ scheduleAutoStartAfterIdle(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
370
385
  return true;
371
386
  }
372
387
  entry.currentUnitType = result.unitType;
@@ -544,7 +559,7 @@ export function checkAutoStartAfterDiscuss() {
544
559
  }
545
560
  pendingAutoStartMap.delete(basePath);
546
561
  ctx.ui.notify(`Milestone ${milestoneId} ready.`, "success");
547
- startAutoDetached(ctx, pi, basePath, false, { step });
562
+ scheduleAutoStartAfterIdle(ctx, pi, basePath, false, { step });
548
563
  return true;
549
564
  }
550
565
  /**
@@ -16,7 +16,7 @@ Dispatch ALL slices simultaneously using the `subagent` tool in **parallel mode*
16
16
 
17
17
  1. Call `subagent` with `tasks: [...]` containing one entry per slice below
18
18
  2. Wait for ALL subagents to complete
19
- 3. Verify each slice's RESEARCH file was written (check the `.gsd/{{mid}}/` directory)
19
+ 3. Verify each slice's RESEARCH file was written (check `.gsd/milestones/{{mid}}/slices/<slice-id>/`)
20
20
  4. If a subagent failed to write its RESEARCH file, retry it **once** individually
21
21
  5. If it fails a second time, write a partial RESEARCH file for that slice with a `## BLOCKER` section explaining the failure — do NOT retry again
22
22
  6. Report which slices completed research and which (if any) needed a blocker note
@@ -17,11 +17,7 @@ You are executing a GSD quick task — a lightweight, focused unit of work outsi
17
17
  5. Verify your work:
18
18
  - Run tests if applicable.
19
19
  - Verify both happy path and failure modes for non-trivial changes.
20
- 6. Commit your changes atomically:
21
- - Use conventional commit messages (feat:, fix:, refactor:, etc.)
22
- - Stage only relevant files — never commit secrets or runtime files.
23
- - Commit logical units separately if the task involves distinct changes.
24
- - Quick tasks run outside the auto-mode lifecycle — there is no system auto-commit, so commit directly here.
20
+ 6. {{commitInstruction}}
25
21
  7. Write a brief summary to `{{summaryPath}}`:
26
22
  - Quick tasks operate outside the milestone/slice/task DB structure, so `gsd_summary_save` (which requires a `milestone_id`) cannot be used here. Write the file directly.
27
23
 
@@ -27,13 +27,13 @@ Roadmap, slice summaries, assessments, requirements, decisions, and project cont
27
27
  Call `subagent` with `tasks: [...]` containing ALL THREE reviewers simultaneously:
28
28
 
29
29
  **Reviewer A - Requirements Coverage**
30
- Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Read `.gsd/{{milestoneId}}/REQUIREMENTS.md` or equivalent. For each requirement, check slice SUMMARY files in `.gsd/{{milestoneId}}/` and mark COVERED, PARTIAL, or MISSING. Output table: Requirement | Status | Evidence. End with one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."
30
+ Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Read `.gsd/REQUIREMENTS.md` or use the inlined requirements context. For each requirement, check slice SUMMARY files under `.gsd/milestones/{{milestoneId}}/slices/` and mark COVERED, PARTIAL, or MISSING. Output table: Requirement | Status | Evidence. End with one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."
31
31
 
32
32
  **Reviewer B - Cross-Slice Integration**
33
33
  Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Read `{{roadmapPath}}` and find the boundary map (produces/consumes contracts). For each boundary, confirm producer SUMMARY produced the artifact and consumer SUMMARY consumed it. Output table: Boundary | Producer Summary | Consumer Summary | Status. End with one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."
34
34
 
35
35
  **Reviewer C - Assessment & Acceptance Criteria**
36
- Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.gsd/{{milestoneId}}/CONTEXT.md` for criteria. Check slice ASSESSMENT files. Verify each criterion maps to a passing assessment or clear SUMMARY evidence. Then review inlined milestone verification classes. For each non-empty planned class, output table: Class | Planned Check | Evidence | Verdict. Use the exact class names `Contract`, `Integration`, `Operational`, and `UAT` whenever those classes are present. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered, NEEDS-ATTENTION if gaps exist."
36
+ Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.gsd/milestones/{{milestoneId}}/{{milestoneId}}-CONTEXT.md` for criteria. Check slice SUMMARY/UAT files under `.gsd/milestones/{{milestoneId}}/slices/`. Verify each criterion maps to passing evidence. Then review inlined milestone verification classes. For each non-empty planned class, output table: Class | Planned Check | Evidence | Verdict. Use the exact class names `Contract`, `Integration`, `Operational`, and `UAT` whenever those classes are present. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered, NEEDS-ATTENTION if gaps exist."
37
37
 
38
38
  ### Step 2 - Synthesize Findings
39
39
 
@@ -8,8 +8,8 @@
8
8
  * Quick tasks live in `.gsd/quick/` and are tracked in STATE.md's
9
9
  * "Quick Tasks Completed" table.
10
10
  */
11
- import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
12
- import { join } from "node:path";
11
+ import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
12
+ import { isAbsolute, join, relative } from "node:path";
13
13
  import { loadPrompt } from "./prompt-loader.js";
14
14
  import { gsdRoot } from "./paths.js";
15
15
  import { GitServiceImpl, runGit } from "./git-service.js";
@@ -64,6 +64,37 @@ function ensureQuickDir(basePath, taskNum, slug) {
64
64
  mkdirSync(taskDir, { recursive: true });
65
65
  return taskDir;
66
66
  }
67
+ function isPathInside(parent, child) {
68
+ const rel = relative(parent, child);
69
+ return rel === "" || (!!rel && !rel.startsWith("..") && !isAbsolute(rel));
70
+ }
71
+ function isExternalGsdRoot(basePath, root) {
72
+ try {
73
+ return !isPathInside(realpathSync(basePath), realpathSync(root));
74
+ }
75
+ catch {
76
+ return !isPathInside(basePath, root);
77
+ }
78
+ }
79
+ export function buildQuickCommitInstruction(basePath, root) {
80
+ const externalState = isExternalGsdRoot(basePath, root);
81
+ if (externalState) {
82
+ return [
83
+ "Commit repo changes atomically, but do not stage or commit `.gsd/quick/...`:",
84
+ " - `.gsd/` resolves outside this git repository, so Git cannot stage quick-task summary files from the project repo.",
85
+ " - Write the quick summary file directly at the requested path; that file is persisted by GSD external state.",
86
+ " - Stage and commit only implementation/test/docs files that live inside the repository.",
87
+ " - If the task only writes quick-task research/summary files and no repository files changed, do not run `git commit`; report that there was nothing in the project repo to commit.",
88
+ ].join("\n");
89
+ }
90
+ return [
91
+ "Commit your changes atomically:",
92
+ " - Use conventional commit messages (feat:, fix:, refactor:, etc.)",
93
+ " - Stage only relevant files — never commit secrets or runtime files.",
94
+ " - Commit logical units separately if the task involves distinct changes.",
95
+ " - Quick tasks run outside the auto-mode lifecycle — there is no system auto-commit, so commit directly here.",
96
+ ].join("\n");
97
+ }
67
98
  function quickReturnStatePath(basePath) {
68
99
  return join(gsdRoot(basePath), "runtime", "quick-return.json");
69
100
  }
@@ -198,6 +229,7 @@ export async function handleQuick(args, ctx, pi) {
198
229
  taskDir: taskDirRel,
199
230
  branch: actualBranch,
200
231
  summaryPath,
232
+ commitInstruction: buildQuickCommitInstruction(basePath, root),
201
233
  date,
202
234
  taskNum: String(taskNum),
203
235
  slug,
@@ -0,0 +1,15 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Shared Context Mode tool result helpers.
3
+ export function contextModeDisabledResult(operation) {
4
+ return {
5
+ content: [
6
+ {
7
+ type: "text",
8
+ text: `${operation} is disabled by \`context_mode.enabled: false\` in preferences. ` +
9
+ "Remove that override or set it to true to re-enable Context Mode tools.",
10
+ },
11
+ ],
12
+ details: { operation, error: "context_mode_disabled" },
13
+ isError: true,
14
+ };
15
+ }
@@ -3,7 +3,12 @@
3
3
  // Scans .gsd/exec/*.meta.json and returns a ranked summary so agents can
4
4
  // re-discover past runs without re-executing. Read-only; no DB writes.
5
5
  import { searchExecHistory } from "../exec-history.js";
6
+ import { isContextModeEnabled } from "../preferences-types.js";
7
+ import { contextModeDisabledResult } from "./context-mode-tool-result.js";
6
8
  export function executeExecSearch(params, opts) {
9
+ if (!isContextModeEnabled(opts.preferences)) {
10
+ return contextModeDisabledResult("gsd_exec_search");
11
+ }
7
12
  const searchOpts = {
8
13
  query: typeof params.query === "string" ? params.query : undefined,
9
14
  runtime: params.runtime,
@@ -5,6 +5,7 @@
5
5
  // for MCP return.
6
6
  import { EXEC_DEFAULTS, runExecSandbox, } from "../exec-sandbox.js";
7
7
  import { isContextModeEnabled } from "../preferences-types.js";
8
+ import { contextModeDisabledResult } from "./context-mode-tool-result.js";
8
9
  export function buildExecOptions(baseDir, cfg, extras) {
9
10
  const allowlist = Array.isArray(cfg?.exec_env_allowlist) ? cfg.exec_env_allowlist : EXEC_DEFAULTS.envAllowlist;
10
11
  const stdoutCap = clampNumber(cfg?.exec_stdout_cap_bytes, EXEC_DEFAULTS.stdoutCapBytes, 4_096, 16_777_216);
@@ -33,19 +34,6 @@ function clampNumber(value, fallback, min, max) {
33
34
  function isEnabled(prefs) {
34
35
  return isContextModeEnabled(prefs);
35
36
  }
36
- function disabledResult() {
37
- return {
38
- content: [
39
- {
40
- type: "text",
41
- text: "gsd_exec is disabled by `context_mode.enabled: false` in preferences. Remove that " +
42
- "override (or set it to true) to re-enable sandboxed tool-output execution.",
43
- },
44
- ],
45
- details: { operation: "gsd_exec", error: "context_mode_disabled" },
46
- isError: true,
47
- };
48
- }
49
37
  function paramError(message) {
50
38
  return {
51
39
  content: [{ type: "text", text: `Error: ${message}` }],
@@ -55,7 +43,7 @@ function paramError(message) {
55
43
  }
56
44
  export async function executeGsdExec(params, deps) {
57
45
  if (!isEnabled(deps.preferences))
58
- return disabledResult();
46
+ return contextModeDisabledResult("gsd_exec");
59
47
  const runtime = params.runtime;
60
48
  if (runtime !== "bash" && runtime !== "node" && runtime !== "python") {
61
49
  return paramError(`invalid runtime "${String(runtime)}" — must be bash | node | python`);
@@ -67,7 +55,7 @@ export async function executeGsdExec(params, deps) {
67
55
  if (Buffer.byteLength(script, "utf8") > 200_000) {
68
56
  return paramError("script exceeds the 200 KB length limit");
69
57
  }
70
- const opts = buildExecOptions(deps.baseDir, deps.preferences?.context_mode, { now: deps.now, generateId: deps.generateId });
58
+ const opts = buildExecOptions(deps.baseDir, deps.preferences?.context_mode, { env: deps.env, now: deps.now, generateId: deps.generateId });
71
59
  const run = deps.run ?? runExecSandbox;
72
60
  try {
73
61
  const result = await run({
@@ -2,7 +2,12 @@
2
2
  // agents can re-orient after compaction or session resume without
3
3
  // re-deriving project memory state.
4
4
  import { readCompactionSnapshot } from "../compaction-snapshot.js";
5
+ import { isContextModeEnabled } from "../preferences-types.js";
6
+ import { contextModeDisabledResult } from "./context-mode-tool-result.js";
5
7
  export function executeResume(_params, opts) {
8
+ if (!isContextModeEnabled(opts.preferences)) {
9
+ return contextModeDisabledResult("gsd_resume");
10
+ }
6
11
  const snapshot = readCompactionSnapshot(opts.baseDir);
7
12
  if (snapshot == null) {
8
13
  return {
@@ -80,7 +80,15 @@ const CONTEXT_MODE_LANE_LABELS = {
80
80
  orchestration: "orchestration",
81
81
  docs: "documentation",
82
82
  };
83
- const CONTEXT_MODE_GUIDANCE = "Use `gsd_exec` for noisy commands, `gsd_exec_search` before reruns, and `gsd_resume` after compaction or resume.";
83
+ const CONTEXT_MODE_GUIDANCE_BY_LANE = {
84
+ interview: "Use `gsd_resume` to restore prior discussion, `gsd_exec` for noisy discovery, and `gsd_exec_search` before repeating scans.",
85
+ research: "Use `gsd_exec` for noisy research scans, `gsd_exec_search` before reruns, and `gsd_resume` to restore prior findings.",
86
+ planning: "Use `gsd_resume` for planning continuity, `gsd_exec` for noisy checks, and `gsd_exec_search` before rerunning diagnostics.",
87
+ execution: "Use `gsd_exec` for builds, tests, and diagnostics, `gsd_exec_search` before reruns, and `gsd_resume` after compaction or resume.",
88
+ verification: "Use `gsd_exec` for verification commands, `gsd_exec_search` to reuse prior evidence, and `gsd_resume` after compaction or resume.",
89
+ orchestration: "Use `gsd_resume` before resuming orchestration, `gsd_exec_search` to reuse prior runs, and `gsd_exec` for noisy coordination checks.",
90
+ docs: "Use `gsd_resume` for prior context, `gsd_exec_search` for saved evidence, and `gsd_exec` for noisy doc validation commands.",
91
+ };
84
92
  /**
85
93
  * Render the Context Mode instruction lane for a unit type. Unknown unit
86
94
  * types, disabled config, and explicit `contextMode: "none"` all omit the
@@ -93,14 +101,15 @@ export function composeContextModeInstructions(unitType, opts) {
93
101
  if (!manifest || manifest.contextMode === "none")
94
102
  return "";
95
103
  const lane = CONTEXT_MODE_LANE_LABELS[manifest.contextMode];
104
+ const guidance = CONTEXT_MODE_GUIDANCE_BY_LANE[manifest.contextMode];
96
105
  if (opts.renderMode === "nested") {
97
- return `Context Mode (${lane} lane): ${CONTEXT_MODE_GUIDANCE}`;
106
+ return `Context Mode (${lane} lane): ${guidance}`;
98
107
  }
99
108
  return [
100
109
  "## Context Mode",
101
110
  "",
102
111
  `Lane: **${lane} lane**.`,
103
- CONTEXT_MODE_GUIDANCE,
112
+ guidance,
104
113
  ].join("\n");
105
114
  }
106
115
  const SECTION_SEPARATOR = "\n\n---\n\n";
@@ -4,6 +4,8 @@ import { atomicWriteSync } from "./atomic-write.js";
4
4
  import { gsdRoot, relSliceFile, relTaskFile, resolveSliceFile, resolveTaskFile, } from "./paths.js";
5
5
  import { loadFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
6
6
  import { parseUnitId } from "./unit-id.js";
7
+ import { getTask, isDbAvailable, refreshOpenDatabaseFromDisk } from "./gsd-db.js";
8
+ import { isClosedStatus } from "./status-guards.js";
7
9
  // Per-record advisory lock — prevents read-modify-write races between
8
10
  // concurrent writers updating disjoint fields of the same runtime record.
9
11
  // Within a single Node process this is moot (writeUnitRuntimeRecord is sync),
@@ -165,6 +167,12 @@ export async function inspectExecuteTaskDurability(basePath, unitId) {
165
167
  const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
166
168
  const taskChecked = !!planContent && new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m").test(planContent);
167
169
  const nextActionAdvanced = !new RegExp(`Execute ${tid}\\b`).test(stateContent);
170
+ let dbComplete = false;
171
+ if (isDbAvailable()) {
172
+ refreshOpenDatabaseFromDisk();
173
+ const task = getTask(mid, sid, tid);
174
+ dbComplete = !!task && isClosedStatus(task.status);
175
+ }
168
176
  // Must-have coverage: load task plan and count mentions in summary
169
177
  let mustHaveCount = 0;
170
178
  let mustHavesMentionedInSummary = 0;
@@ -188,11 +196,14 @@ export async function inspectExecuteTaskDurability(basePath, unitId) {
188
196
  summaryExists,
189
197
  taskChecked,
190
198
  nextActionAdvanced,
199
+ dbComplete,
191
200
  mustHaveCount,
192
201
  mustHavesMentionedInSummary,
193
202
  };
194
203
  }
195
204
  export function formatExecuteTaskRecoveryStatus(status) {
205
+ if (status.dbComplete)
206
+ return "DB task status is closed";
196
207
  const missing = [];
197
208
  if (!status.summaryExists)
198
209
  missing.push(`summary missing (${status.summaryPath})`);