gsd-pi 2.44.0-dev.73f2fd5 → 2.44.0-dev.8894d5b

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 (164) hide show
  1. package/dist/resources/extensions/gsd/auto/infra-errors.js +0 -3
  2. package/dist/resources/extensions/gsd/auto/phases.js +36 -36
  3. package/dist/resources/extensions/gsd/auto-prompts.js +1 -24
  4. package/dist/resources/extensions/gsd/auto-timers.js +3 -57
  5. package/dist/resources/extensions/gsd/auto-worktree-sync.js +0 -4
  6. package/dist/resources/extensions/gsd/auto-worktree.js +6 -9
  7. package/dist/resources/extensions/gsd/auto.js +3 -30
  8. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +0 -136
  9. package/dist/resources/extensions/gsd/commands/catalog.js +1 -6
  10. package/dist/resources/extensions/gsd/commands/handlers/core.js +0 -1
  11. package/dist/resources/extensions/gsd/commands/handlers/ops.js +0 -5
  12. package/dist/resources/extensions/gsd/db-writer.js +16 -34
  13. package/dist/resources/extensions/gsd/doctor.js +0 -8
  14. package/dist/resources/extensions/gsd/git-service.js +3 -8
  15. package/dist/resources/extensions/gsd/gsd-db.js +1 -12
  16. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  17. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +4 -2
  18. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  19. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  20. package/dist/resources/extensions/gsd/prompts/replan-slice.md +14 -3
  21. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +37 -7
  22. package/dist/resources/extensions/gsd/provider-error-pause.js +0 -7
  23. package/dist/resources/extensions/gsd/tools/plan-slice.js +0 -1
  24. package/dist/resources/extensions/gsd/tools/plan-task.js +0 -1
  25. package/dist/resources/extensions/gsd/tools/replan-slice.js +0 -2
  26. package/dist/resources/extensions/gsd/worktree-resolver.js +0 -6
  27. package/dist/resources/extensions/mcp-client/index.js +0 -14
  28. package/dist/web/standalone/.next/BUILD_ID +1 -1
  29. package/dist/web/standalone/.next/app-path-routes-manifest.json +20 -20
  30. package/dist/web/standalone/.next/build-manifest.json +2 -2
  31. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  32. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  33. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  46. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/index.html +1 -1
  49. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app-paths-manifest.json +20 -20
  56. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  57. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  58. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  59. package/package.json +1 -1
  60. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +1 -3
  61. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  62. package/packages/pi-coding-agent/dist/core/auth-storage.js +1 -15
  63. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  64. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +0 -11
  65. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  66. package/packages/pi-coding-agent/dist/core/model-registry.js +1 -20
  67. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  68. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +0 -3
  69. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  70. package/packages/pi-coding-agent/dist/core/settings-manager.js +0 -6
  71. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  72. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  73. package/packages/pi-coding-agent/dist/main.js +0 -17
  74. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  75. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -3
  76. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  77. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +1 -8
  78. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  79. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +0 -2
  80. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  81. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +0 -12
  82. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  83. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  84. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +1 -4
  85. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  86. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +2 -5
  87. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  88. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +2 -13
  89. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  90. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  91. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +8 -17
  92. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.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 -7
  95. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  96. package/packages/pi-coding-agent/src/core/auth-storage.ts +1 -15
  97. package/packages/pi-coding-agent/src/core/model-registry.ts +1 -21
  98. package/packages/pi-coding-agent/src/core/settings-manager.ts +0 -9
  99. package/packages/pi-coding-agent/src/main.ts +0 -19
  100. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +0 -10
  101. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +0 -15
  102. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1 -3
  103. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +3 -18
  104. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -16
  105. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +1 -8
  106. package/src/resources/extensions/gsd/auto/infra-errors.ts +0 -3
  107. package/src/resources/extensions/gsd/auto/phases.ts +48 -45
  108. package/src/resources/extensions/gsd/auto-prompts.ts +1 -24
  109. package/src/resources/extensions/gsd/auto-timers.ts +3 -64
  110. package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -5
  111. package/src/resources/extensions/gsd/auto-worktree.ts +6 -9
  112. package/src/resources/extensions/gsd/auto.ts +3 -37
  113. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +0 -129
  114. package/src/resources/extensions/gsd/commands/catalog.ts +1 -6
  115. package/src/resources/extensions/gsd/commands/handlers/core.ts +0 -1
  116. package/src/resources/extensions/gsd/commands/handlers/ops.ts +0 -5
  117. package/src/resources/extensions/gsd/db-writer.ts +17 -39
  118. package/src/resources/extensions/gsd/doctor.ts +1 -7
  119. package/src/resources/extensions/gsd/git-service.ts +2 -6
  120. package/src/resources/extensions/gsd/gsd-db.ts +1 -16
  121. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  122. package/src/resources/extensions/gsd/prompts/complete-milestone.md +4 -2
  123. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  124. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  125. package/src/resources/extensions/gsd/prompts/replan-slice.md +14 -3
  126. package/src/resources/extensions/gsd/prompts/validate-milestone.md +37 -7
  127. package/src/resources/extensions/gsd/provider-error-pause.ts +0 -9
  128. package/src/resources/extensions/gsd/tests/db-writer.test.ts +0 -79
  129. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -20
  130. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -11
  131. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -2
  132. package/src/resources/extensions/gsd/tools/plan-slice.ts +0 -2
  133. package/src/resources/extensions/gsd/tools/plan-task.ts +0 -2
  134. package/src/resources/extensions/gsd/tools/replan-slice.ts +0 -3
  135. package/src/resources/extensions/gsd/worktree-resolver.ts +0 -7
  136. package/src/resources/extensions/mcp-client/index.ts +0 -20
  137. package/dist/resources/extensions/gsd/commands-mcp-status.js +0 -187
  138. package/dist/resources/extensions/gsd/tools/validate-milestone.js +0 -88
  139. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +0 -15
  140. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +0 -1
  141. package/packages/pi-coding-agent/dist/core/local-model-check.js +0 -41
  142. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +0 -1
  143. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +0 -2
  144. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +0 -1
  145. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +0 -32
  146. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +0 -1
  147. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +0 -15
  148. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +0 -1
  149. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +0 -40
  150. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +0 -1
  151. package/packages/pi-coding-agent/src/core/local-model-check.ts +0 -45
  152. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +0 -38
  153. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +0 -48
  154. package/src/resources/extensions/gsd/commands-mcp-status.ts +0 -247
  155. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +0 -88
  156. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +0 -114
  157. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +0 -120
  158. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +0 -103
  159. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +0 -66
  160. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +0 -67
  161. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +0 -49
  162. package/src/resources/extensions/gsd/tools/validate-milestone.ts +0 -127
  163. /package/dist/web/standalone/.next/static/{kxxAA66bah_yhPYqLBHE2 → oZMtyM-zfu6Inx-S59cOl}/_buildManifest.js +0 -0
  164. /package/dist/web/standalone/.next/static/{kxxAA66bah_yhPYqLBHE2 → oZMtyM-zfu6Inx-S59cOl}/_ssgManifest.js +0 -0
@@ -16,8 +16,6 @@ All relevant context has been preloaded below — the roadmap, all slice summari
16
16
 
17
17
  {{inlinedContext}}
18
18
 
19
- {{skillActivation}}
20
-
21
19
  ## Validation Steps
22
20
 
23
21
  1. For each **success criterion** in `{{roadmapPath}}`, check whether slice summaries and UAT results provide evidence that it was met. Record pass/fail per criterion.
@@ -27,15 +25,47 @@ All relevant context has been preloaded below — the roadmap, all slice summari
27
25
  5. Determine a verdict:
28
26
  - `pass` — all criteria met, all slices delivered, no gaps
29
27
  - `needs-attention` — minor gaps that do not block completion (document them)
30
- - `needs-remediation` — material gaps found; remediation slices must be added to the roadmap
28
+ - `needs-remediation` — material gaps found; add remediation slices to the roadmap
29
+
30
+ ## Output
31
+
32
+ Write `{{validationPath}}` with this structure:
33
+
34
+ ```markdown
35
+ ---
36
+ verdict: <pass|needs-attention|needs-remediation>
37
+ remediation_round: {{remediationRound}}
38
+ ---
39
+
40
+ # Milestone Validation: {{milestoneId}}
31
41
 
32
- ## Persist Validation
42
+ ## Success Criteria Checklist
43
+ - [x] Criterion 1 — evidence: ...
44
+ - [ ] Criterion 2 — gap: ...
33
45
 
34
- **Persist validation results through `gsd_validate_milestone`.** Call it with: `milestoneId`, `verdict`, `remediationRound`, `successCriteriaChecklist`, `sliceDeliveryAudit`, `crossSliceIntegration`, `requirementCoverage`, `verdictRationale`, and `remediationPlan` (if verdict is `needs-remediation`). The tool writes the validation to the DB and renders VALIDATION.md to disk.
46
+ ## Slice Delivery Audit
47
+ | Slice | Claimed | Delivered | Status |
48
+ |-------|---------|-----------|--------|
49
+ | S01 | ... | ... | pass |
50
+
51
+ ## Cross-Slice Integration
52
+ (any boundary mismatches)
53
+
54
+ ## Requirement Coverage
55
+ (any unaddressed requirements)
56
+
57
+ ## Verdict Rationale
58
+ (why this verdict was chosen)
59
+
60
+ ## Remediation Plan
61
+ (only if verdict is needs-remediation — list new slices to add to the roadmap)
62
+ ```
35
63
 
36
64
  If verdict is `needs-remediation`:
37
- - After calling `gsd_validate_milestone`, use `gsd_reassess_roadmap` to add remediation slices. Pass `milestoneId`, a synthetic `completedSliceId` (e.g. "VALIDATION"), `verdict: "roadmap-adjusted"`, `assessment` text, and `sliceChanges` with the new slices in the `added` array. The tool persists the changes to the DB and re-renders ROADMAP.md.
38
- - These remediation slices will be planned and executed before validation re-runs.
65
+ - Add new slices to `{{roadmapPath}}` with unchecked `[ ]` status
66
+ - These slices will be planned and executed before validation re-runs
67
+
68
+ **You MUST write `{{validationPath}}` before finishing.**
39
69
 
40
70
  **File system safety:** When scanning milestone directories for evidence, use `ls` or `find` to list directory contents first — never pass a directory path (e.g. `tasks/`, `slices/`) directly to the `read` tool. The `read` tool only accepts file paths, not directories.
41
71
 
@@ -19,11 +19,6 @@ export function classifyProviderError(errorMsg: string): {
19
19
  const isRateLimit = /rate.?limit|too many requests|429/i.test(errorMsg);
20
20
  const isServerError = /internal server error|500|502|503|overloaded|server_error|api_error|service.?unavailable/i.test(errorMsg);
21
21
 
22
- // Connection/process errors — transient, auto-resume after brief backoff (#2309).
23
- // These indicate the process was killed, the connection was reset, or a network
24
- // blip occurred. They are NOT permanent failures.
25
- const isConnectionError = /terminated|connection.?reset|connection.?refused|other side closed|fetch failed|network.?(?:is\s+)?unavailable|ECONNREFUSED|ECONNRESET|EPIPE/i.test(errorMsg);
26
-
27
22
  // Permanent errors — never auto-resume
28
23
  const isPermanent = /auth|unauthorized|forbidden|invalid.*key|invalid.*api|billing|quota exceeded|account/i.test(errorMsg);
29
24
 
@@ -42,10 +37,6 @@ export function classifyProviderError(errorMsg: string): {
42
37
  return { isTransient: true, isRateLimit: false, suggestedDelayMs: 30_000 }; // 30s for server errors
43
38
  }
44
39
 
45
- if (isConnectionError) {
46
- return { isTransient: true, isRateLimit: false, suggestedDelayMs: 15_000 }; // 15s for connection errors
47
- }
48
-
49
40
  // Unknown error — treat as permanent (user reviews)
50
41
  return { isTransient: false, isRateLimit: false, suggestedDelayMs: 0 };
51
42
  }
@@ -483,85 +483,6 @@ describe('db-writer', () => {
483
483
  }
484
484
  });
485
485
 
486
- test('saveArtifactToDb — shrinkage guard preserves larger existing file', async () => {
487
- const tmpDir = makeTmpDir();
488
- const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
489
- openDatabase(dbPath);
490
-
491
- try {
492
- const fullContent = '# Full Research\n\n' + 'x'.repeat(20000) + '\n';
493
- const abbreviatedContent = '# Summary\n\nShort version.\n';
494
-
495
- // Pre-create the file with full content (simulating a prior `write` tool call)
496
- const relPath = 'milestones/M001/M001-RESEARCH.md';
497
- const filePath = path.join(tmpDir, '.gsd', relPath);
498
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
499
- fs.writeFileSync(filePath, fullContent);
500
-
501
- // Call saveArtifactToDb with abbreviated content — should trigger shrinkage guard
502
- await saveArtifactToDb({
503
- path: relPath,
504
- artifact_type: 'RESEARCH',
505
- content: abbreviatedContent,
506
- milestone_id: 'M001',
507
- }, tmpDir);
508
-
509
- // Disk file should be preserved (not overwritten)
510
- assert.deepStrictEqual(
511
- fs.readFileSync(filePath, 'utf-8'),
512
- fullContent,
513
- 'disk file preserved — shrinkage guard prevented overwrite',
514
- );
515
-
516
- // DB should contain the full disk content, not the abbreviated content
517
- const adapter = _getAdapter();
518
- const row = adapter!
519
- .prepare('SELECT full_content FROM artifacts WHERE path = ?')
520
- .get(relPath);
521
- assert.deepStrictEqual(
522
- row!['full_content'],
523
- fullContent,
524
- 'DB stores the richer disk content instead of abbreviated content',
525
- );
526
- } finally {
527
- closeDatabase();
528
- cleanupDir(tmpDir);
529
- }
530
- });
531
-
532
- test('saveArtifactToDb — allows overwrite when new content is similar size', async () => {
533
- const tmpDir = makeTmpDir();
534
- const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
535
- openDatabase(dbPath);
536
-
537
- try {
538
- const oldContent = '# Summary v1\n\nOriginal content here.\n';
539
- const newContent = '# Summary v2\n\nUpdated content here with more details.\n';
540
-
541
- const relPath = 'milestones/M001/M001-SUMMARY.md';
542
- const filePath = path.join(tmpDir, '.gsd', relPath);
543
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
544
- fs.writeFileSync(filePath, oldContent);
545
-
546
- await saveArtifactToDb({
547
- path: relPath,
548
- artifact_type: 'SUMMARY',
549
- content: newContent,
550
- milestone_id: 'M001',
551
- }, tmpDir);
552
-
553
- // Disk file should be updated (new content is >=50% of old size)
554
- assert.deepStrictEqual(
555
- fs.readFileSync(filePath, 'utf-8'),
556
- newContent,
557
- 'disk file updated when new content is similar size',
558
- );
559
- } finally {
560
- closeDatabase();
561
- cleanupDir(tmpDir);
562
- }
563
- });
564
-
565
486
  // ═══════════════════════════════════════════════════════════════════════════
566
487
  // Full Round-Trip: DB → Markdown → Parse → Compare
567
488
  // ═══════════════════════════════════════════════════════════════════════════
@@ -7,13 +7,10 @@ import { isInfrastructureError, INFRA_ERROR_CODES } from "../auto/infra-errors.j
7
7
  // ── INFRA_ERROR_CODES constant ───────────────────────────────────────────────
8
8
 
9
9
  test("INFRA_ERROR_CODES contains the expected codes", () => {
10
- for (const code of [
11
- "ENOSPC", "ENOMEM", "EROFS", "EDQUOT", "EMFILE", "ENFILE",
12
- "ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
13
- ]) {
10
+ for (const code of ["ENOSPC", "ENOMEM", "EROFS", "EDQUOT", "EMFILE", "ENFILE"]) {
14
11
  assert.ok(INFRA_ERROR_CODES.has(code), `missing ${code}`);
15
12
  }
16
- assert.equal(INFRA_ERROR_CODES.size, 9, "unexpected extra codes");
13
+ assert.equal(INFRA_ERROR_CODES.size, 6, "unexpected extra codes");
17
14
  });
18
15
 
19
16
  // ── isInfrastructureError: code property detection ───────────────────────────
@@ -48,21 +45,6 @@ test("detects ENFILE via code property", () => {
48
45
  assert.equal(isInfrastructureError(err), "ENFILE");
49
46
  });
50
47
 
51
- test("detects ECONNREFUSED via code property", () => {
52
- const err = Object.assign(new Error("connect ECONNREFUSED 127.0.0.1:3000"), { code: "ECONNREFUSED" });
53
- assert.equal(isInfrastructureError(err), "ECONNREFUSED");
54
- });
55
-
56
- test("detects ENOTFOUND via code property", () => {
57
- const err = Object.assign(new Error("getaddrinfo ENOTFOUND api.example.com"), { code: "ENOTFOUND" });
58
- assert.equal(isInfrastructureError(err), "ENOTFOUND");
59
- });
60
-
61
- test("detects ENETUNREACH via code property", () => {
62
- const err = Object.assign(new Error("connect ENETUNREACH 2607:f8b0:4004::"), { code: "ENETUNREACH" });
63
- assert.equal(isInfrastructureError(err), "ENETUNREACH");
64
- });
65
-
66
48
  // ── isInfrastructureError: message fallback ──────────────────────────────────
67
49
 
68
50
  test("falls back to message scanning when no code property", () => {
@@ -147,12 +147,12 @@ test("plan-slice prompt no longer frames direct PLAN writes as the source of tru
147
147
  assert.match(prompt, /Do \*\*not\*\* rely on direct `PLAN\.md` writes as the source of truth/i);
148
148
  });
149
149
 
150
- test("plan-slice prompt explicitly names gsd_plan_slice as DB-backed planning tool", () => {
150
+ test("plan-slice prompt explicitly names gsd_plan_slice and gsd_plan_task as DB-backed planning tools", () => {
151
151
  const prompt = readPrompt("plan-slice");
152
152
  assert.match(prompt, /gsd_plan_slice/);
153
153
  assert.match(prompt, /gsd_plan_task/);
154
- // The prompt should describe the DB-backed tool as the canonical write path
155
- assert.match(prompt, /DB-backed tool is the canonical write path/i);
154
+ // The prompt should describe these as the canonical write path
155
+ assert.match(prompt, /DB-backed tools are the canonical write path/i);
156
156
  });
157
157
 
158
158
  test("plan-slice prompt does not instruct direct file writes as a primary step", () => {
@@ -161,18 +161,14 @@ test("plan-slice prompt does not instruct direct file writes as a primary step",
161
161
  assert.doesNotMatch(prompt, /^\d+\.\s+Write `?\{\{outputPath\}\}`?\s*$/m);
162
162
  });
163
163
 
164
- test("plan-slice prompt clarifies gsd_plan_slice handles task persistence", () => {
164
+ test("plan-slice prompt instructs calling gsd_plan_task for each task", () => {
165
165
  const prompt = readPrompt("plan-slice");
166
- // gsd_plan_slice persists tasks in its transaction — no separate gsd_plan_task calls needed
167
- assert.match(prompt, /gsd_plan_task/);
168
- assert.match(prompt, /gsd_plan_slice` handles task persistence/i);
166
+ assert.match(prompt, /call `gsd_plan_task` for each task/i);
169
167
  });
170
168
 
171
- test("replan-slice prompt uses gsd_replan_slice as canonical DB-backed tool", () => {
169
+ test("replan-slice prompt requires DB-backed planning state when available", () => {
172
170
  const prompt = readPrompt("replan-slice");
173
- assert.match(prompt, /gsd_replan_slice/);
174
- // Degraded fallback (direct file writes) was removed — DB tools are always available
175
- assert.doesNotMatch(prompt, /Degraded fallback/i);
171
+ assert.match(prompt, /DB-backed planning tool exists for this phase, use it as the source of truth/i);
176
172
  });
177
173
 
178
174
  test("reassess-roadmap prompt references gsd_reassess_roadmap tool", () => {
@@ -34,7 +34,6 @@ const RENAME_MAP: Array<{ canonical: string; alias: string }> = [
34
34
  { canonical: "gsd_replan_slice", alias: "gsd_slice_replan" },
35
35
  { canonical: "gsd_reassess_roadmap", alias: "gsd_roadmap_reassess" },
36
36
  { canonical: "gsd_complete_milestone", alias: "gsd_milestone_complete" },
37
- { canonical: "gsd_validate_milestone", alias: "gsd_milestone_validate" },
38
37
  ];
39
38
 
40
39
  // ─── Registration count ──────────────────────────────────────────────────────
@@ -44,7 +43,7 @@ console.log('\n── Tool naming: registration count ──');
44
43
  const pi = makeMockPi();
45
44
  registerDbTools(pi);
46
45
 
47
- assert.deepStrictEqual(pi.tools.length, 26, 'Should register exactly 26 tools (13 canonical + 13 aliases)');
46
+ assert.deepStrictEqual(pi.tools.length, 24, 'Should register exactly 24 tools (12 canonical + 12 aliases)');
48
47
 
49
48
  // ─── Both names exist for each pair ──────────────────────────────────────────
50
49
 
@@ -20,7 +20,6 @@ export interface PlanSliceTaskInput {
20
20
  inputs: string[];
21
21
  expectedOutput: string[];
22
22
  observabilityImpact?: string;
23
- fullPlanMd?: string;
24
23
  }
25
24
 
26
25
  export interface PlanSliceParams {
@@ -168,7 +167,6 @@ export async function handlePlanSlice(
168
167
  inputs: task.inputs,
169
168
  expectedOutput: task.expectedOutput,
170
169
  observabilityImpact: task.observabilityImpact ?? "",
171
- fullPlanMd: task.fullPlanMd,
172
170
  });
173
171
  }
174
172
  });
@@ -15,7 +15,6 @@ export interface PlanTaskParams {
15
15
  inputs: string[];
16
16
  expectedOutput: string[];
17
17
  observabilityImpact?: string;
18
- fullPlanMd?: string;
19
18
  }
20
19
 
21
20
  export interface PlanTaskResult {
@@ -95,7 +94,6 @@ export async function handlePlanTask(
95
94
  inputs: params.inputs,
96
95
  expectedOutput: params.expectedOutput,
97
96
  observabilityImpact: params.observabilityImpact ?? "",
98
- fullPlanMd: params.fullPlanMd,
99
97
  });
100
98
  });
101
99
  } catch (err) {
@@ -21,7 +21,6 @@ export interface ReplanSliceTaskInput {
21
21
  verify: string;
22
22
  inputs: string[];
23
23
  expectedOutput: string[];
24
- fullPlanMd?: string;
25
24
  }
26
25
 
27
26
  export interface ReplanSliceParams {
@@ -137,7 +136,6 @@ export async function handleReplanSlice(
137
136
  verify: updatedTask.verify || "",
138
137
  inputs: updatedTask.inputs || [],
139
138
  expectedOutput: updatedTask.expectedOutput || [],
140
- fullPlanMd: updatedTask.fullPlanMd,
141
139
  });
142
140
  } else {
143
141
  // Insert new task then set planning fields
@@ -156,7 +154,6 @@ export async function handleReplanSlice(
156
154
  verify: updatedTask.verify || "",
157
155
  inputs: updatedTask.inputs || [],
158
156
  expectedOutput: updatedTask.expectedOutput || [],
159
- fullPlanMd: updatedTask.fullPlanMd,
160
157
  });
161
158
  }
162
159
  }
@@ -17,7 +17,6 @@ import { existsSync, unlinkSync } from "node:fs";
17
17
  import { join } from "node:path";
18
18
  import type { AutoSession } from "./auto/session.js";
19
19
  import { debugLog } from "./debug-logger.js";
20
- import { MergeConflictError } from "./git-service.js";
21
20
 
22
21
  // ─── Dependency Interface ──────────────────────────────────────────────────
23
22
 
@@ -434,12 +433,6 @@ export class WorktreeResolver {
434
433
  /* best-effort */
435
434
  }
436
435
  }
437
-
438
- // Re-throw MergeConflictError so the auto loop can detect real code
439
- // conflicts and stop instead of retrying forever (#2330).
440
- if (err instanceof MergeConflictError) {
441
- throw err;
442
- }
443
436
  }
444
437
 
445
438
  // Always restore basePath and rebuild — whether merge succeeded or failed
@@ -213,26 +213,6 @@ function formatToolList(serverName: string, tools: McpToolSchema[]): string {
213
213
  return lines.join("\n");
214
214
  }
215
215
 
216
- // ─── Status helper (consumed by /gsd mcp) ─────────────────────────────────────
217
-
218
- /**
219
- * Return the live connection status for a named MCP server.
220
- * Safe to call even when the server has never been connected.
221
- */
222
- export function getConnectionStatus(name: string): {
223
- connected: boolean;
224
- tools: string[];
225
- error?: string;
226
- } {
227
- const conn = connections.get(name);
228
- const cached = toolCache.get(name);
229
- return {
230
- connected: !!conn,
231
- tools: cached ? cached.map((t) => t.name) : [],
232
- error: undefined,
233
- };
234
- }
235
-
236
216
  // ─── Extension ────────────────────────────────────────────────────────────────
237
217
 
238
218
  export default function (pi: ExtensionAPI) {
@@ -1,187 +0,0 @@
1
- /**
2
- * MCP Status — `/gsd mcp` command handler.
3
- *
4
- * Shows configured MCP servers, their connection status, and available tools.
5
- *
6
- * Subcommands:
7
- * /gsd mcp — Overview of all servers (alias: /gsd mcp status)
8
- * /gsd mcp status — Same as bare /gsd mcp
9
- * /gsd mcp check <srv> — Detailed status for a specific server
10
- */
11
- import { existsSync, readFileSync } from "node:fs";
12
- import { join } from "node:path";
13
- function readMcpConfigs() {
14
- const servers = [];
15
- const seen = new Set();
16
- const configPaths = [
17
- join(process.cwd(), ".mcp.json"),
18
- join(process.cwd(), ".gsd", "mcp.json"),
19
- ];
20
- for (const configPath of configPaths) {
21
- try {
22
- if (!existsSync(configPath))
23
- continue;
24
- const raw = readFileSync(configPath, "utf-8");
25
- const data = JSON.parse(raw);
26
- const mcpServers = (data.mcpServers ?? data.servers);
27
- if (!mcpServers || typeof mcpServers !== "object")
28
- continue;
29
- for (const [name, config] of Object.entries(mcpServers)) {
30
- if (seen.has(name))
31
- continue;
32
- seen.add(name);
33
- const hasCommand = typeof config.command === "string";
34
- const hasUrl = typeof config.url === "string";
35
- const transport = hasCommand
36
- ? "stdio"
37
- : hasUrl
38
- ? "http"
39
- : "unknown";
40
- servers.push({
41
- name,
42
- transport,
43
- ...(hasCommand && {
44
- command: config.command,
45
- args: Array.isArray(config.args) ? config.args : undefined,
46
- }),
47
- ...(hasUrl && { url: config.url }),
48
- });
49
- }
50
- }
51
- catch {
52
- // Non-fatal — config file may not exist or be malformed
53
- }
54
- }
55
- return servers;
56
- }
57
- // ─── Formatters (exported for testing) ──────────────────────────────────────
58
- export function formatMcpStatusReport(servers) {
59
- if (servers.length === 0) {
60
- return [
61
- "No MCP servers configured.",
62
- "",
63
- "Add servers to .mcp.json or .gsd/mcp.json to enable MCP integrations.",
64
- "See: https://modelcontextprotocol.io/quickstart",
65
- ].join("\n");
66
- }
67
- const lines = [`MCP Server Status — ${servers.length} server(s)\n`];
68
- for (const s of servers) {
69
- const icon = s.error ? "✗" : s.connected ? "✓" : "○";
70
- const status = s.error
71
- ? `error: ${s.error}`
72
- : s.connected
73
- ? `connected — ${s.toolCount} tools`
74
- : "disconnected";
75
- lines.push(` ${icon} ${s.name} (${s.transport}) — ${status}`);
76
- }
77
- lines.push("");
78
- lines.push("Use /gsd mcp check <server> for details on a specific server.");
79
- lines.push("Use mcp_discover to connect and list tools for a server.");
80
- return lines.join("\n");
81
- }
82
- export function formatMcpServerDetail(server) {
83
- const lines = [`MCP Server: ${server.name}\n`];
84
- lines.push(` Transport: ${server.transport}`);
85
- if (server.error) {
86
- lines.push(` Status: error`);
87
- lines.push(` Error: ${server.error}`);
88
- }
89
- else if (server.connected) {
90
- lines.push(` Status: connected`);
91
- lines.push(` Tools: ${server.toolCount}`);
92
- if (server.tools.length > 0) {
93
- lines.push("");
94
- lines.push(" Available tools:");
95
- for (const tool of server.tools) {
96
- lines.push(` - ${tool}`);
97
- }
98
- }
99
- }
100
- else {
101
- lines.push(` Status: disconnected`);
102
- lines.push("");
103
- lines.push(` Run mcp_discover("${server.name}") to connect and list tools.`);
104
- }
105
- return lines.join("\n");
106
- }
107
- // ─── Command handler ────────────────────────────────────────────────────────
108
- /**
109
- * Handle `/gsd mcp [status|check <server>]`.
110
- */
111
- export async function handleMcpStatus(args, ctx) {
112
- const trimmed = args.trim().toLowerCase();
113
- const configs = readMcpConfigs();
114
- // /gsd mcp check <server>
115
- if (trimmed.startsWith("check ")) {
116
- const serverName = args.trim().slice("check ".length).trim();
117
- const config = configs.find((c) => c.name === serverName);
118
- if (!config) {
119
- const available = configs.map((c) => c.name).join(", ") || "(none)";
120
- ctx.ui.notify(`Unknown MCP server: "${serverName}"\n\nAvailable: ${available}`, "warning");
121
- return;
122
- }
123
- // Try to get connection/tool info from the mcp-client module if available
124
- let connected = false;
125
- let toolNames = [];
126
- let error;
127
- try {
128
- const mcpClient = await import("../mcp-client/index.js");
129
- // Access the module's connection state if exported; fall back gracefully
130
- const mod = mcpClient;
131
- if (typeof mod.getConnectionStatus === "function") {
132
- const status = mod.getConnectionStatus(serverName);
133
- connected = status.connected;
134
- toolNames = status.tools;
135
- error = status.error;
136
- }
137
- }
138
- catch {
139
- // mcp-client may not expose status helpers — that's fine
140
- }
141
- ctx.ui.notify(formatMcpServerDetail({
142
- name: config.name,
143
- transport: config.transport,
144
- connected,
145
- toolCount: toolNames.length,
146
- tools: toolNames,
147
- error,
148
- }), "info");
149
- return;
150
- }
151
- // /gsd mcp or /gsd mcp status
152
- if (!trimmed || trimmed === "status") {
153
- // Build status for each server
154
- const statuses = [];
155
- for (const config of configs) {
156
- let connected = false;
157
- let toolCount = 0;
158
- let error;
159
- try {
160
- const mcpClient = await import("../mcp-client/index.js");
161
- const mod = mcpClient;
162
- if (typeof mod.getConnectionStatus === "function") {
163
- const status = mod.getConnectionStatus(config.name);
164
- connected = status.connected;
165
- toolCount = status.tools.length;
166
- error = status.error;
167
- }
168
- }
169
- catch {
170
- // Fall back to unknown state
171
- }
172
- statuses.push({
173
- name: config.name,
174
- transport: config.transport,
175
- connected,
176
- toolCount,
177
- error,
178
- });
179
- }
180
- ctx.ui.notify(formatMcpStatusReport(statuses), "info");
181
- return;
182
- }
183
- // Unknown subcommand
184
- ctx.ui.notify("Usage: /gsd mcp [status|check <server>]\n\n" +
185
- " status Show all MCP server statuses (default)\n" +
186
- " check <server> Detailed status for a specific server", "warning");
187
- }
@@ -1,88 +0,0 @@
1
- /**
2
- * validate-milestone handler — the core operation behind gsd_validate_milestone.
3
- *
4
- * Persists milestone validation results to the assessments table,
5
- * renders VALIDATION.md to disk, and invalidates caches.
6
- */
7
- import { join } from "node:path";
8
- import { transaction, _getAdapter, } from "../gsd-db.js";
9
- import { resolveMilestonePath, clearPathCache } from "../paths.js";
10
- import { saveFile, clearParseCache } from "../files.js";
11
- import { invalidateStateCache } from "../state.js";
12
- function renderValidationMarkdown(params) {
13
- let md = `---
14
- verdict: ${params.verdict}
15
- remediation_round: ${params.remediationRound}
16
- ---
17
-
18
- # Milestone Validation: ${params.milestoneId}
19
-
20
- ## Success Criteria Checklist
21
- ${params.successCriteriaChecklist}
22
-
23
- ## Slice Delivery Audit
24
- ${params.sliceDeliveryAudit}
25
-
26
- ## Cross-Slice Integration
27
- ${params.crossSliceIntegration}
28
-
29
- ## Requirement Coverage
30
- ${params.requirementCoverage}
31
-
32
- ## Verdict Rationale
33
- ${params.verdictRationale}
34
- `;
35
- if (params.verdict === "needs-remediation" && params.remediationPlan) {
36
- md += `\n## Remediation Plan\n${params.remediationPlan}\n`;
37
- }
38
- return md;
39
- }
40
- export async function handleValidateMilestone(params, basePath) {
41
- if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
42
- return { error: "milestoneId is required and must be a non-empty string" };
43
- }
44
- const validVerdicts = ["pass", "needs-attention", "needs-remediation"];
45
- if (!validVerdicts.includes(params.verdict)) {
46
- return { error: `verdict must be one of: ${validVerdicts.join(", ")}` };
47
- }
48
- // ── Filesystem render ──────────────────────────────────────────────────
49
- const validationMd = renderValidationMarkdown(params);
50
- let validationPath;
51
- const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
52
- if (milestoneDir) {
53
- validationPath = join(milestoneDir, `${params.milestoneId}-VALIDATION.md`);
54
- }
55
- else {
56
- const gsdDir = join(basePath, ".gsd");
57
- const manualDir = join(gsdDir, "milestones", params.milestoneId);
58
- validationPath = join(manualDir, `${params.milestoneId}-VALIDATION.md`);
59
- }
60
- try {
61
- await saveFile(validationPath, validationMd);
62
- }
63
- catch (renderErr) {
64
- process.stderr.write(`gsd-db: validate_milestone — disk render failed: ${renderErr.message}\n`);
65
- return { error: `disk render failed: ${renderErr.message}` };
66
- }
67
- // ── DB write — store in assessments table ──────────────────────────────
68
- const validatedAt = new Date().toISOString();
69
- transaction(() => {
70
- const adapter = _getAdapter();
71
- adapter.prepare(`INSERT OR REPLACE INTO assessments (path, milestone_id, slice_id, task_id, status, scope, full_content, created_at)
72
- VALUES (:path, :mid, NULL, NULL, :verdict, 'milestone-validation', :content, :created_at)`).run({
73
- ":path": validationPath,
74
- ":mid": params.milestoneId,
75
- ":verdict": params.verdict,
76
- ":content": validationMd,
77
- ":created_at": validatedAt,
78
- });
79
- });
80
- invalidateStateCache();
81
- clearPathCache();
82
- clearParseCache();
83
- return {
84
- milestoneId: params.milestoneId,
85
- verdict: params.verdict,
86
- validationPath,
87
- };
88
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * local-model-check.ts — Utility to detect if a model baseUrl is local.
3
- *
4
- * Leaf module with zero transitive dependencies on TypeScript parameter properties.
5
- * Used by ModelRegistry and tests.
6
- */
7
- /**
8
- * Check if a model's baseUrl points to a local endpoint.
9
- * Returns true for localhost, 127.0.0.1, 0.0.0.0, ::1, or unix socket paths.
10
- * Returns false if baseUrl is empty (cloud provider) or points to a remote host.
11
- */
12
- export declare function isLocalModel(model: {
13
- baseUrl: string;
14
- }): boolean;
15
- //# sourceMappingURL=local-model-check.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"local-model-check.d.ts","sourceRoot":"","sources":["../../src/core/local-model-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAgChE"}