gsd-pi 2.35.0-dev.30eec3f → 2.35.0-dev.39eee32

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.
@@ -67,8 +67,9 @@ export function findMilestoneIds(basePath) {
67
67
  .filter((d) => d.isDirectory())
68
68
  .map((d) => {
69
69
  const match = d.name.match(/^(M\d+(?:-[a-z0-9]{6})?)/);
70
- return match ? match[1] : d.name;
71
- });
70
+ return match ? match[1] : null;
71
+ })
72
+ .filter((id) => id !== null);
72
73
  // Apply custom queue order if available, else fall back to numeric sort
73
74
  const customOrder = loadQueueOrder(basePath);
74
75
  return sortByQueueOrder(ids, customOrder);
@@ -33,11 +33,12 @@ export function isValidationTerminal(validationContent) {
33
33
  const verdict = match[1].match(/verdict:\s*(\S+)/);
34
34
  if (!verdict)
35
35
  return false;
36
+ const v = verdict[1] === 'passed' ? 'pass' : verdict[1];
36
37
  // 'pass' and 'needs-attention' are always terminal.
37
38
  // 'needs-remediation' is treated as terminal to prevent infinite loops
38
39
  // when no remediation slices exist in the roadmap (#832). The validation
39
40
  // report is preserved on disk for manual review.
40
- return verdict[1] === 'pass' || verdict[1] === 'needs-attention' || verdict[1] === 'needs-remediation';
41
+ return v === 'pass' || v === 'needs-attention' || v === 'needs-remediation';
41
42
  }
42
43
  const CACHE_TTL_MS = 100;
43
44
  let _stateCache = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gsd-pi",
3
- "version": "2.35.0-dev.30eec3f",
3
+ "version": "2.35.0-dev.39eee32",
4
4
  "description": "GSD — Get Shit Done coding agent",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -80,8 +80,9 @@ export function findMilestoneIds(basePath: string): string[] {
80
80
  .filter((d) => d.isDirectory())
81
81
  .map((d) => {
82
82
  const match = d.name.match(/^(M\d+(?:-[a-z0-9]{6})?)/);
83
- return match ? match[1] : d.name;
84
- });
83
+ return match ? match[1] : null;
84
+ })
85
+ .filter((id): id is string => id !== null);
85
86
 
86
87
  // Apply custom queue order if available, else fall back to numeric sort
87
88
  const customOrder = loadQueueOrder(basePath);
@@ -64,11 +64,12 @@ export function isValidationTerminal(validationContent: string): boolean {
64
64
  if (!match) return false;
65
65
  const verdict = match[1].match(/verdict:\s*(\S+)/);
66
66
  if (!verdict) return false;
67
+ const v = verdict[1] === 'passed' ? 'pass' : verdict[1];
67
68
  // 'pass' and 'needs-attention' are always terminal.
68
69
  // 'needs-remediation' is treated as terminal to prevent infinite loops
69
70
  // when no remediation slices exist in the roadmap (#832). The validation
70
71
  // report is preserved on disk for manual review.
71
- return verdict[1] === 'pass' || verdict[1] === 'needs-attention' || verdict[1] === 'needs-remediation';
72
+ return v === 'pass' || v === 'needs-attention' || v === 'needs-remediation';
72
73
  }
73
74
 
74
75
  // ─── State Derivation ──────────────────────────────────────────────────────
@@ -244,6 +244,32 @@ console.log('\n=== E2E: backward compat without QUEUE-ORDER.json ===');
244
244
  }
245
245
  }
246
246
 
247
+ // ═══════════════════════════════════════════════════════════════════════════
248
+ // Test: non-milestone directories are filtered out (#1494)
249
+ // ═══════════════════════════════════════════════════════════════════════════
250
+
251
+ console.log('\n=== E2E: non-milestone directories filtered from findMilestoneIds (#1494) ===');
252
+ {
253
+ const base = createFixtureBase();
254
+ try {
255
+ writeContext(base, 'M001', '', 'First');
256
+ writeContext(base, 'M002', '', 'Second');
257
+ // Create a rogue non-milestone directory
258
+ mkdirSync(join(base, '.gsd', 'milestones', 'slices'), { recursive: true });
259
+ mkdirSync(join(base, '.gsd', 'milestones', 'temp-backup'), { recursive: true });
260
+
261
+ invalidateStateCache();
262
+ const ids = findMilestoneIds(base);
263
+ assertEq(ids.length, 2, 'only M001 and M002 returned');
264
+ assertTrue(!ids.includes('slices'), 'slices directory excluded');
265
+ assertTrue(!ids.includes('temp-backup'), 'temp-backup directory excluded');
266
+ assertTrue(ids.includes('M001'), 'M001 included');
267
+ assertTrue(ids.includes('M002'), 'M002 included');
268
+ } finally {
269
+ cleanup(base);
270
+ }
271
+ }
272
+
247
273
  // ═══════════════════════════════════════════════════════════════════════════
248
274
  // Test: depends_on inline array format removal
249
275
  // ═══════════════════════════════════════════════════════════════════════════
@@ -104,6 +104,11 @@ test("isValidationTerminal returns true for verdict: needs-remediation (#832)",
104
104
  assert.equal(isValidationTerminal(content), true);
105
105
  });
106
106
 
107
+ test("isValidationTerminal returns true for verdict: passed (#1429)", () => {
108
+ const content = "---\nverdict: passed\nremediation_round: 0\n---\n\n# Validation";
109
+ assert.equal(isValidationTerminal(content), true);
110
+ });
111
+
107
112
  test("isValidationTerminal returns false for missing frontmatter", () => {
108
113
  const content = "# Validation\nNo frontmatter here.";
109
114
  assert.equal(isValidationTerminal(content), false);