gsd-pi 2.59.0-dev.023bd39 → 2.59.0-dev.d77b3dd

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 (88) hide show
  1. package/dist/resources/extensions/gsd/auto/phases.js +54 -1
  2. package/dist/resources/extensions/gsd/auto-model-selection.js +8 -3
  3. package/dist/resources/extensions/gsd/auto-post-unit.js +40 -1
  4. package/dist/resources/extensions/gsd/auto-prompts.js +13 -0
  5. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +70 -0
  6. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +51 -5
  7. package/dist/resources/extensions/gsd/captures.js +54 -1
  8. package/dist/resources/extensions/gsd/complexity-classifier.js +1 -1
  9. package/dist/resources/extensions/gsd/context-masker.js +68 -0
  10. package/dist/resources/extensions/gsd/docs/preferences-reference.md +7 -0
  11. package/dist/resources/extensions/gsd/gsd-db.js +2 -2
  12. package/dist/resources/extensions/gsd/model-router.js +123 -4
  13. package/dist/resources/extensions/gsd/phase-anchor.js +56 -0
  14. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  15. package/dist/resources/extensions/gsd/preferences-validation.js +46 -0
  16. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
  17. package/dist/resources/extensions/gsd/prompts/rethink.md +7 -0
  18. package/dist/resources/extensions/gsd/prompts/triage-captures.md +6 -1
  19. package/dist/resources/extensions/gsd/rethink.js +5 -2
  20. package/dist/resources/extensions/gsd/state.js +1 -1
  21. package/dist/resources/extensions/gsd/status-guards.js +4 -3
  22. package/dist/resources/extensions/gsd/triage-resolution.js +128 -1
  23. package/dist/resources/extensions/gsd/triage-ui.js +12 -3
  24. package/dist/web/standalone/.next/BUILD_ID +1 -1
  25. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  26. package/dist/web/standalone/.next/build-manifest.json +2 -2
  27. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  28. package/dist/web/standalone/.next/required-server-files.json +1 -1
  29. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  30. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/index.html +1 -1
  46. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  53. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  54. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  55. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  56. package/dist/web/standalone/server.js +1 -1
  57. package/package.json +1 -1
  58. package/src/resources/extensions/gsd/auto/phases.ts +60 -1
  59. package/src/resources/extensions/gsd/auto-model-selection.ts +12 -3
  60. package/src/resources/extensions/gsd/auto-post-unit.ts +48 -1
  61. package/src/resources/extensions/gsd/auto-prompts.ts +17 -0
  62. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +78 -0
  63. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +53 -4
  64. package/src/resources/extensions/gsd/captures.ts +71 -2
  65. package/src/resources/extensions/gsd/complexity-classifier.ts +1 -1
  66. package/src/resources/extensions/gsd/context-masker.ts +74 -0
  67. package/src/resources/extensions/gsd/docs/preferences-reference.md +7 -0
  68. package/src/resources/extensions/gsd/gsd-db.ts +2 -2
  69. package/src/resources/extensions/gsd/model-router.ts +171 -8
  70. package/src/resources/extensions/gsd/phase-anchor.ts +71 -0
  71. package/src/resources/extensions/gsd/preferences-types.ts +9 -0
  72. package/src/resources/extensions/gsd/preferences-validation.ts +38 -0
  73. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
  74. package/src/resources/extensions/gsd/prompts/rethink.md +7 -0
  75. package/src/resources/extensions/gsd/prompts/triage-captures.md +6 -1
  76. package/src/resources/extensions/gsd/rethink.ts +5 -2
  77. package/src/resources/extensions/gsd/state.ts +1 -1
  78. package/src/resources/extensions/gsd/status-guards.ts +4 -3
  79. package/src/resources/extensions/gsd/tests/context-masker.test.ts +122 -0
  80. package/src/resources/extensions/gsd/tests/model-router.test.ts +87 -1
  81. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +83 -0
  82. package/src/resources/extensions/gsd/tests/status-guards.test.ts +4 -0
  83. package/src/resources/extensions/gsd/tests/stop-backtrack.test.ts +216 -0
  84. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -1
  85. package/src/resources/extensions/gsd/triage-resolution.ts +144 -1
  86. package/src/resources/extensions/gsd/triage-ui.ts +12 -3
  87. /package/dist/web/standalone/.next/static/{QlWL-8CXgQpzV3ehkNMzh → t_cBZAENjaOJIRST3dw08}/_buildManifest.js +0 -0
  88. /package/dist/web/standalone/.next/static/{QlWL-8CXgQpzV3ehkNMzh → t_cBZAENjaOJIRST3dw08}/_ssgManifest.js +0 -0
@@ -10,7 +10,7 @@
10
10
  * Also provides detectFileOverlap() for surfacing downstream impact on quick tasks.
11
11
  */
12
12
 
13
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
14
14
  import { join } from "node:path";
15
15
  import { createRequire } from "node:module";
16
16
  import { gsdRoot, milestonesDir } from "./paths.js";
@@ -129,6 +129,129 @@ export function executeReplan(
129
129
  }
130
130
  }
131
131
 
132
+ // ─── Backtrack (Milestone Regression) ────────────────────────────────────────
133
+
134
+ /**
135
+ * Execute a backtrack directive — user wants to abandon current milestone
136
+ * and return to a previous one (milestone regression).
137
+ *
138
+ * Writes a BACKTRACK-TRIGGER.md marker at `.gsd/BACKTRACK-TRIGGER.md` with
139
+ * the target milestone, reason, and timestamp. The state machine (deriveState)
140
+ * detects this and transitions the project to the target milestone, resetting
141
+ * its slices to allow re-planning.
142
+ *
143
+ * Returns the extracted target milestone ID, or null if extraction failed.
144
+ */
145
+ export function executeBacktrack(
146
+ basePath: string,
147
+ currentMilestoneId: string,
148
+ capture: CaptureEntry,
149
+ ): string | null {
150
+ try {
151
+ // Extract target milestone from capture text or resolution
152
+ const targetMatch = (capture.resolution ?? capture.text)
153
+ .match(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/);
154
+ const targetMilestoneId = targetMatch?.[1] ?? null;
155
+
156
+ const ts = new Date().toISOString();
157
+ const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
158
+ const content = [
159
+ `# Backtrack Trigger`,
160
+ ``,
161
+ `**Source:** Capture ${capture.id}`,
162
+ `**Capture:** ${capture.text}`,
163
+ `**Rationale:** ${capture.rationale ?? "User-initiated milestone backtrack"}`,
164
+ `**From:** ${currentMilestoneId}`,
165
+ `**Target:** ${targetMilestoneId ?? "(user to specify)"}`,
166
+ `**Triggered:** ${ts}`,
167
+ ``,
168
+ `Auto-mode was paused by this backtrack directive. The user directed`,
169
+ `that the current milestone (${currentMilestoneId}) be abandoned and work`,
170
+ `should return to ${targetMilestoneId ?? "a previous milestone"}.`,
171
+ ``,
172
+ `## Recovery Steps`,
173
+ ``,
174
+ `1. Review what went wrong in ${currentMilestoneId}`,
175
+ `2. Identify missing features/requirements from the target milestone`,
176
+ `3. Resume auto-mode — the state machine will re-enter discussion for the target`,
177
+ ].join("\n");
178
+
179
+ writeFileSync(triggerPath, content, "utf-8");
180
+
181
+ // If we have a valid target, also reset that milestone's completion status
182
+ // so deriveState() will re-enter it as the active milestone.
183
+ if (targetMilestoneId) {
184
+ try {
185
+ const targetDir = join(milestonesDir(basePath), targetMilestoneId);
186
+ if (existsSync(targetDir)) {
187
+ // Write a regression marker so the state machine knows this milestone
188
+ // needs re-discussion, not just re-execution
189
+ const regressionPath = join(targetDir, `${targetMilestoneId}-REGRESSION.md`);
190
+ writeFileSync(regressionPath, [
191
+ `# Milestone Regression`,
192
+ ``,
193
+ `**From:** ${currentMilestoneId}`,
194
+ `**Reason:** ${capture.text}`,
195
+ `**Triggered:** ${ts}`,
196
+ ``,
197
+ `This milestone is being revisited because downstream milestone`,
198
+ `${currentMilestoneId} failed or missed critical features that should`,
199
+ `have been part of this milestone's scope.`,
200
+ ``,
201
+ `The discuss phase should re-evaluate requirements and identify gaps.`,
202
+ ].join("\n"), "utf-8");
203
+ }
204
+ } catch { /* best-effort */ }
205
+ }
206
+
207
+ return targetMilestoneId;
208
+ } catch {
209
+ return null;
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Read the backtrack trigger file if it exists.
215
+ * Returns the parsed target milestone and metadata, or null.
216
+ */
217
+ export function readBacktrackTrigger(basePath: string): {
218
+ target: string | null;
219
+ from: string | null;
220
+ capture: string;
221
+ triggeredAt: string;
222
+ } | null {
223
+ const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
224
+ if (!existsSync(triggerPath)) return null;
225
+
226
+ try {
227
+ const content = readFileSync(triggerPath, "utf-8");
228
+ const target = content.match(/\*\*Target:\*\*\s*(.+)/)?.[1]?.trim() ?? null;
229
+ const from = content.match(/\*\*From:\*\*\s*(.+)/)?.[1]?.trim() ?? null;
230
+ const capture = content.match(/\*\*Capture:\*\*\s*(.+)/)?.[1]?.trim() ?? "";
231
+ const triggeredAt = content.match(/\*\*Triggered:\*\*\s*(.+)/)?.[1]?.trim() ?? "";
232
+ return {
233
+ target: target === "(user to specify)" ? null : target,
234
+ from,
235
+ capture,
236
+ triggeredAt,
237
+ };
238
+ } catch {
239
+ return null;
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Remove the backtrack trigger after it has been processed.
245
+ */
246
+ export function clearBacktrackTrigger(basePath: string): void {
247
+ const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
248
+ try {
249
+ if (existsSync(triggerPath)) {
250
+ unlinkSync(triggerPath);
251
+ }
252
+ } catch { /* best-effort */ }
253
+ }
254
+
132
255
  // ─── File Overlap Detection ───────────────────────────────────────────────────
133
256
 
134
257
  /**
@@ -298,6 +421,10 @@ export interface TriageExecutionResult {
298
421
  deferredMilestones: number;
299
422
  /** Captures classified as quick-task that need dispatch */
300
423
  quickTasks: CaptureEntry[];
424
+ /** Number of stop directives (will pause auto-mode via guard) */
425
+ stopped: number;
426
+ /** Backtrack captures (will trigger milestone regression via guard) */
427
+ backtracks: CaptureEntry[];
301
428
  /** Details of each action taken, for logging */
302
429
  actions: string[];
303
430
  }
@@ -326,6 +453,8 @@ export function executeTriageResolutions(
326
453
  replanned: 0,
327
454
  deferredMilestones: 0,
328
455
  quickTasks: [],
456
+ stopped: 0,
457
+ backtracks: [],
329
458
  actions: [],
330
459
  };
331
460
 
@@ -409,5 +538,19 @@ export function executeTriageResolutions(
409
538
  }
410
539
  }
411
540
 
541
+ // Count stop/backtrack captures — these are handled by the pre-dispatch guard
542
+ // in runGuards(), not here. We just report them for logging purposes.
543
+ const allCaptures = loadAllCaptures(basePath);
544
+ for (const cap of allCaptures) {
545
+ if (cap.status !== "resolved" || cap.executed) continue;
546
+ if (cap.classification === "stop") {
547
+ result.stopped++;
548
+ result.actions.push(`Stop directive from ${cap.id}: "${cap.text}" — will pause on next dispatch`);
549
+ } else if (cap.classification === "backtrack") {
550
+ result.backtracks.push(cap);
551
+ result.actions.push(`Backtrack directive from ${cap.id}: "${cap.text}" — will trigger milestone regression on next dispatch`);
552
+ }
553
+ }
554
+
412
555
  return result;
413
556
  }
@@ -49,10 +49,18 @@ const CLASSIFICATION_LABELS: Record<Classification, { label: string; description
49
49
  label: "Note",
50
50
  description: "Informational only — no action needed.",
51
51
  },
52
+ "stop": {
53
+ label: "Stop",
54
+ description: "Halt auto-mode immediately — user directive to cease execution.",
55
+ },
56
+ "backtrack": {
57
+ label: "Backtrack",
58
+ description: "Abandon current milestone and return to a previous one.",
59
+ },
52
60
  };
53
61
 
54
62
  const ALL_CLASSIFICATIONS: Classification[] = [
55
- "quick-task", "inject", "defer", "replan", "note",
63
+ "quick-task", "inject", "defer", "replan", "note", "stop", "backtrack",
56
64
  ];
57
65
 
58
66
  // ─── Public API ───────────────────────────────────────────────────────────────
@@ -83,8 +91,9 @@ export async function showTriageConfirmation(
83
91
  const capture = captureMap.get(result.captureId);
84
92
  if (!capture) continue;
85
93
 
86
- // Auto-confirm note and defer — low-impact, no plan modification
87
- if (result.classification === "note" || result.classification === "defer") {
94
+ // Auto-confirm note, defer, stop, and backtrack — low-impact or urgent directives
95
+ if (result.classification === "note" || result.classification === "defer"
96
+ || result.classification === "stop" || result.classification === "backtrack") {
88
97
  const resolution = result.classification === "note"
89
98
  ? "acknowledged as note"
90
99
  : `deferred${result.targetSlice ? ` to ${result.targetSlice}` : ""}`;