@tekyzinc/gsd-t 3.16.11 → 3.16.12

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.
@@ -1489,16 +1489,35 @@ function isMilestoneComplete(projectDir, milestoneId) {
1489
1489
  if (!fs.existsSync(p)) return false;
1490
1490
  const body = fs.readFileSync(p, "utf8");
1491
1491
  const idEsc = milestoneId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1492
- // Form 1: "{id} COMPLETE" or "{id} COMPLETED"
1493
- const directRe = new RegExp(`\\b${idEsc}\\b[^\\n]*\\bCOMPLETED?\\b`, "i");
1494
- if (directRe.test(body)) return true;
1495
- // Form 2: "Status: complete" on a line mentioning the milestone id
1496
1492
  const lines = body.split(/\r?\n/);
1493
+ const COMPLETE_PHASES = new Set(["COMPLETE", "COMPLETED", "DONE", "VERIFIED"]);
1494
+
1495
+ // Authoritative signal #1: the top-of-file Status header.
1496
+ // `## Status: M43 PARTITIONED — Token Attribution & ...`
1497
+ // Match `## Status:` lines that name the active milestone id and read
1498
+ // the first ALL-CAPS phase keyword that follows. Anything outside the
1499
+ // keyword set (PARTITIONED, EXECUTING, VERIFYING, ...) is non-terminal.
1500
+ const statusRe = new RegExp(
1501
+ `^##\\s*Status:[^\\n]*\\b${idEsc}\\b\\s+([A-Z][A-Z-]+)`,
1502
+ );
1497
1503
  for (const ln of lines) {
1498
- if (new RegExp(`\\b${idEsc}\\b`).test(ln) && /\bcomplete(d)?\b/i.test(ln)) {
1499
- return true;
1500
- }
1504
+ const m = ln.match(statusRe);
1505
+ if (m && COMPLETE_PHASES.has(m[1])) return true;
1501
1506
  }
1507
+
1508
+ // Authoritative signal #2: the milestone's row in the Milestones table.
1509
+ // `| M43 | <name> | PARTITIONED | <version> | <domains> |`
1510
+ // The third pipe column is the milestone's status. Decision Log prose,
1511
+ // descriptive paragraphs, and "see also M43" mentions never satisfy
1512
+ // this — the row format is structural.
1513
+ const rowRe = new RegExp(
1514
+ `^\\|\\s*${idEsc}\\s*\\|[^|]*\\|\\s*([A-Z][A-Z-]+)\\s*\\|`,
1515
+ );
1516
+ for (const ln of lines) {
1517
+ const m = ln.match(rowRe);
1518
+ if (m && COMPLETE_PHASES.has(m[1])) return true;
1519
+ }
1520
+
1502
1521
  return false;
1503
1522
  } catch (_) {
1504
1523
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "3.16.11",
3
+ "version": "3.16.12",
4
4
  "description": "GSD-T: Contract-Driven Development for Claude Code — 54 slash commands with headless-by-default workflow spawning, unattended supervisor relay with event stream, graph-powered code analysis, real-time agent dashboard, task telemetry, doc-ripple enforcement, backlog management, impact analysis, test sync, milestone archival, and PRD generation",
5
5
  "author": "Tekyz, Inc.",
6
6
  "license": "MIT",