gsd-pi 2.14.1 → 2.14.2

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.
@@ -1520,7 +1520,7 @@ async function dispatchNextUnit(
1520
1520
  return; // Another dispatch is in progress — bail silently
1521
1521
  }
1522
1522
  _dispatching = true;
1523
-
1523
+ try {
1524
1524
  // Recursion depth guard: when many units are skipped in sequence (e.g., after
1525
1525
  // crash recovery with 10+ completed units), recursive dispatchNextUnit calls
1526
1526
  // can freeze the TUI or overflow the stack. Yield generously after MAX_SKIP_DEPTH.
@@ -2425,6 +2425,9 @@ async function dispatchNextUnit(
2425
2425
  );
2426
2426
  await pauseAuto(ctx, pi);
2427
2427
  }
2428
+ } finally {
2429
+ _dispatching = false;
2430
+ }
2428
2431
  }
2429
2432
 
2430
2433
  // ─── Skill Discovery ──────────────────────────────────────────────────────────
@@ -87,6 +87,28 @@ export function ensureGitignore(basePath: string): boolean {
87
87
  existing = readFileSync(gitignorePath, "utf-8");
88
88
  }
89
89
 
90
+ // Self-heal: remove blanket ".gsd/" lines from pre-v2.14.0 projects.
91
+ // The blanket ignore prevented planning artifacts (.gsd/milestones/) from
92
+ // being tracked in git, causing artifacts to vanish in worktrees and
93
+ // triggering loop detection failures. Replace with explicit runtime-only
94
+ // ignores so planning files are tracked naturally.
95
+ let modified = false;
96
+ const lines = existing.split("\n");
97
+ const filteredLines = lines.filter(line => {
98
+ const trimmed = line.trim();
99
+ // Remove standalone ".gsd/" lines (blanket ignore) but keep specific
100
+ // .gsd/ subpath patterns like ".gsd/activity/" or ".gsd/auto.lock"
101
+ if (trimmed === ".gsd/" || trimmed === ".gsd") {
102
+ modified = true;
103
+ return false;
104
+ }
105
+ return true;
106
+ });
107
+ if (modified) {
108
+ existing = filteredLines.join("\n");
109
+ writeFileSync(gitignorePath, existing, "utf-8");
110
+ }
111
+
90
112
  // Parse existing lines (trimmed, ignoring comments and blanks)
91
113
  const existingLines = new Set(
92
114
  existing
@@ -98,7 +120,7 @@ export function ensureGitignore(basePath: string): boolean {
98
120
  // Find patterns not yet present
99
121
  const missing = BASELINE_PATTERNS.filter((p) => !existingLines.has(p));
100
122
 
101
- if (missing.length === 0) return false;
123
+ if (missing.length === 0) return modified;
102
124
 
103
125
  // Build the block to append
104
126
  const block = [
@@ -91,13 +91,19 @@ Do not count the reflection step as a question round. Rounds start after reflect
91
91
 
92
92
  ## Depth Verification
93
93
 
94
- Before moving to the wrap-up gate, present a structured depth summary to the user via `ask_user_questions`. This is a checkpoint — show what you captured across the depth checklist dimensions, using the user's own terminology and framing.
94
+ Before moving to the wrap-up gate, present a structured depth summary as a checkpoint.
95
95
 
96
- The question should summarize: what you understood them to be building, what shaped your understanding most (their emphasis, constraints, concerns), and any areas where you're least confident in your understanding. Frame it as: "Before we move to planning, here's what I captured — did I get the depth right?"
96
+ **Print the summary as normal chat text first** — this is where the formatting renders properly. Structure the summary across the depth checklist dimensions using the user's own terminology and framing. Cover: what you understood them to be building, what shaped your understanding most (their emphasis, constraints, concerns), and any areas where you're least confident in your understanding.
97
97
 
98
- **Convention:** The question ID must contain `depth_verification` (e.g., `depth_verification_summary`). This naming convention enables downstream mechanical detection of this step.
98
+ **Then** use `ask_user_questions` with a short confirmation question NOT the summary itself. The question field is designed for single sentences, not multi-paragraph summaries.
99
99
 
100
- Offer two options: "Yes, you got it (Recommended)" and "Not quite let me clarify." If they clarify, absorb the correction and re-verify.
100
+ **Convention:** The question ID must contain `depth_verification` (e.g., `depth_verification_confirm`). This naming convention enables downstream mechanical detection of this step.
101
+
102
+ Example flow:
103
+ 1. Print in chat: the full depth summary with markdown formatting (headers, bold, bullets)
104
+ 2. Call `ask_user_questions` with: header "Depth Check", question "Did I capture the depth right?", options "Yes, you got it (Recommended)" and "Not quite — let me clarify"
105
+
106
+ If they clarify, absorb the correction and re-verify.
101
107
 
102
108
  ## Wrap-up Gate
103
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gsd-pi",
3
- "version": "2.14.1",
3
+ "version": "2.14.2",
4
4
  "description": "GSD — Get Shit Done coding agent",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1520,7 +1520,7 @@ async function dispatchNextUnit(
1520
1520
  return; // Another dispatch is in progress — bail silently
1521
1521
  }
1522
1522
  _dispatching = true;
1523
-
1523
+ try {
1524
1524
  // Recursion depth guard: when many units are skipped in sequence (e.g., after
1525
1525
  // crash recovery with 10+ completed units), recursive dispatchNextUnit calls
1526
1526
  // can freeze the TUI or overflow the stack. Yield generously after MAX_SKIP_DEPTH.
@@ -2425,6 +2425,9 @@ async function dispatchNextUnit(
2425
2425
  );
2426
2426
  await pauseAuto(ctx, pi);
2427
2427
  }
2428
+ } finally {
2429
+ _dispatching = false;
2430
+ }
2428
2431
  }
2429
2432
 
2430
2433
  // ─── Skill Discovery ──────────────────────────────────────────────────────────
@@ -87,6 +87,28 @@ export function ensureGitignore(basePath: string): boolean {
87
87
  existing = readFileSync(gitignorePath, "utf-8");
88
88
  }
89
89
 
90
+ // Self-heal: remove blanket ".gsd/" lines from pre-v2.14.0 projects.
91
+ // The blanket ignore prevented planning artifacts (.gsd/milestones/) from
92
+ // being tracked in git, causing artifacts to vanish in worktrees and
93
+ // triggering loop detection failures. Replace with explicit runtime-only
94
+ // ignores so planning files are tracked naturally.
95
+ let modified = false;
96
+ const lines = existing.split("\n");
97
+ const filteredLines = lines.filter(line => {
98
+ const trimmed = line.trim();
99
+ // Remove standalone ".gsd/" lines (blanket ignore) but keep specific
100
+ // .gsd/ subpath patterns like ".gsd/activity/" or ".gsd/auto.lock"
101
+ if (trimmed === ".gsd/" || trimmed === ".gsd") {
102
+ modified = true;
103
+ return false;
104
+ }
105
+ return true;
106
+ });
107
+ if (modified) {
108
+ existing = filteredLines.join("\n");
109
+ writeFileSync(gitignorePath, existing, "utf-8");
110
+ }
111
+
90
112
  // Parse existing lines (trimmed, ignoring comments and blanks)
91
113
  const existingLines = new Set(
92
114
  existing
@@ -98,7 +120,7 @@ export function ensureGitignore(basePath: string): boolean {
98
120
  // Find patterns not yet present
99
121
  const missing = BASELINE_PATTERNS.filter((p) => !existingLines.has(p));
100
122
 
101
- if (missing.length === 0) return false;
123
+ if (missing.length === 0) return modified;
102
124
 
103
125
  // Build the block to append
104
126
  const block = [
@@ -91,13 +91,19 @@ Do not count the reflection step as a question round. Rounds start after reflect
91
91
 
92
92
  ## Depth Verification
93
93
 
94
- Before moving to the wrap-up gate, present a structured depth summary to the user via `ask_user_questions`. This is a checkpoint — show what you captured across the depth checklist dimensions, using the user's own terminology and framing.
94
+ Before moving to the wrap-up gate, present a structured depth summary as a checkpoint.
95
95
 
96
- The question should summarize: what you understood them to be building, what shaped your understanding most (their emphasis, constraints, concerns), and any areas where you're least confident in your understanding. Frame it as: "Before we move to planning, here's what I captured — did I get the depth right?"
96
+ **Print the summary as normal chat text first** — this is where the formatting renders properly. Structure the summary across the depth checklist dimensions using the user's own terminology and framing. Cover: what you understood them to be building, what shaped your understanding most (their emphasis, constraints, concerns), and any areas where you're least confident in your understanding.
97
97
 
98
- **Convention:** The question ID must contain `depth_verification` (e.g., `depth_verification_summary`). This naming convention enables downstream mechanical detection of this step.
98
+ **Then** use `ask_user_questions` with a short confirmation question NOT the summary itself. The question field is designed for single sentences, not multi-paragraph summaries.
99
99
 
100
- Offer two options: "Yes, you got it (Recommended)" and "Not quite let me clarify." If they clarify, absorb the correction and re-verify.
100
+ **Convention:** The question ID must contain `depth_verification` (e.g., `depth_verification_confirm`). This naming convention enables downstream mechanical detection of this step.
101
+
102
+ Example flow:
103
+ 1. Print in chat: the full depth summary with markdown formatting (headers, bold, bullets)
104
+ 2. Call `ask_user_questions` with: header "Depth Check", question "Did I capture the depth right?", options "Yes, you got it (Recommended)" and "Not quite — let me clarify"
105
+
106
+ If they clarify, absorb the correction and re-verify.
101
107
 
102
108
  ## Wrap-up Gate
103
109