@tekyzinc/gsd-t 4.0.23 → 4.0.25

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to GSD-T are documented here. Updated with each release.
4
4
 
5
+ ## [4.0.25] - 2026-06-03 (M77 HTML Report Reads Deep-Scan Table Format - patch)
6
+
7
+ ### Fixed - scan report showed 0 critical/0 high on a 322-finding register
8
+
9
+ The HTML report renderer (`bin/scan-data-collector.js::parseDebtSummary`) parsed only the LEGACY breadth-scan prose format ("Critical items: N"). The deep-scan register uses a markdown severity TABLE (`| CRITICAL | 9 |`, emoji optional), so the report displayed 0 critical / 0 high. parseDebtSummary now reads both formats (prose first, then the table). +test/m77-renderer-table-summary.test.js (4 tests). Note: the per-item techDebt[] list section + the 10-finding sample still use legacy formats (secondary; headline cards are the fix).
10
+
11
+ Suite: 1315 pass / 0 fail / 4 skip.
12
+
13
+ ## [4.0.24] - 2026-06-03 (M76 revision — keep severity color bullets)
14
+
15
+ ### Fixed — over-correction: v4.0.23 stripped the severity color bullets too
16
+
17
+ v4.0.23 removed the severity emoji (🔴🟠🟡🟢) along with the em-dashes. But the emoji render fine and are wanted; the actual mojibake cause was only the em/en-dashes and smart quotes. Reverted the emoji strip:
18
+
19
+ - `templates/workflows/gsd-t-scan.workflow.js`: `ascii()` now normalizes em/en-dashes, smart quotes, and ellipsis ONLY — it no longer strips emoji. The severity color bullets are kept in the summary table + section headers. Doc-phase punctuation instruction updated to explicitly allow the severity bullets.
20
+ - `test/m76-ascii-clean-register.test.js`: updated to assert bullets are KEPT and dashes/quotes/ellipsis are normalized.
21
+ - One-off: restored the color bullets in the HiloAviation register (summary table + 4 severity section headers) while keeping the em-dash fix.
22
+
23
+ Suite: 1311 pass / 0 fail / 4 skip — zero regressions.
24
+
5
25
  ## [4.0.23] - 2026-06-03 (M76 ASCII-Clean Register Output — patch)
6
26
 
7
27
  ### Fixed — register/docs rendered as mojibake in non-UTF-8 terminals
@@ -8,11 +8,25 @@ function read(filePath) {
8
8
 
9
9
  function parseDebtSummary(text) {
10
10
  const n = (pattern) => { const m = text.match(pattern); return m ? parseInt(m[1], 10) : 0; };
11
- return {
11
+ // Legacy prose format ("Critical items: N").
12
+ let out = {
12
13
  debtCritical: n(/Critical items?:\s*(\d+)/i),
13
14
  debtHigh: n(/High priority:\s*(\d+)/i),
14
15
  debtMedium: n(/Medium priority:\s*(\d+)/i)
15
16
  };
17
+ // M77: deep-scan register uses a markdown SEVERITY TABLE instead, e.g.
18
+ // | 🔴 CRITICAL | 9 | / | HIGH | 90 | (emoji optional, case-insensitive).
19
+ // If the prose format yielded nothing, parse the table rows.
20
+ if (!out.debtCritical && !out.debtHigh && !out.debtMedium) {
21
+ const row = (label) => {
22
+ // a table row whose first cell contains the label and whose next cell is a number
23
+ const re = new RegExp("\\|[^|\\n]*\\b" + label + "\\b[^|\\n]*\\|\\s*\\**\\s*(\\d+)\\s*\\**\\s*\\|", "i");
24
+ const m = text.match(re);
25
+ return m ? parseInt(m[1], 10) : 0;
26
+ };
27
+ out = { debtCritical: row("CRITICAL"), debtHigh: row("HIGH"), debtMedium: row("MEDIUM") };
28
+ }
29
+ return out;
16
30
  }
17
31
 
18
32
  function parseTestCoverage(text) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "4.0.23",
3
+ "version": "4.0.25",
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",
@@ -494,21 +494,22 @@ counts.total = finalFindings.length;
494
494
  // of a 466KB register truncates at ~165KB — verified). Chunk 0 is the header+summary
495
495
  // (Write/create); the rest are appends. Items are grouped so a chunk never splits an
496
496
  // item, and the severity-section heading rides with its first item's chunk.
497
- // M76: register output must be ASCII-cleanno emoji, no em/en-dashes, no smart
498
- // quotes. They render as mojibake boxes in non-UTF-8 terminals/pagers (the
499
- // βPADCCH/πAPCCCH garbage a user saw). Finder text can also contain these, so sanitize
500
- // every user-supplied field, not just our own template strings.
497
+ // M76 (revised): the mojibake culprit was EM-DASHES () and smart quotes, NOT the
498
+ // severity color bullets (🔴🟠🟡🟢) those render fine and are intentional/wanted.
499
+ // So ascii() normalizes em/en-dashes, smart quotes, and ellipsis (and tidies trailing
500
+ // whitespace), but KEEPS emoji. It's applied to finder-supplied free-text fields so a
501
+ // stray dash in a description doesn't mojibake; the severity bullets live in the
502
+ // template below and are preserved.
501
503
  function ascii(s) {
502
504
  return String(s == null ? "" : s)
503
- .replace(/[\u{1F300}-\u{1FAFF}\u{2600}-\u{27BF}\u{2190}-\u{21FF}\u{2B00}-\u{2BFF}️]/gu, "") // emoji/symbols
504
- .replace(/[—–]/g, "-") // em/en dash -> hyphen
505
+ .replace(/[—–]/g, "-") // em/en dash -> hyphen (the actual mojibake cause)
505
506
  .replace(/[‘’]/g, "'") // smart single quotes
506
507
  .replace(/[“”]/g, '"') // smart double quotes
507
508
  .replace(/…/g, "...") // ellipsis
508
509
  .replace(/[ \t]+\n/g, "\n"); // tidy trailing whitespace
509
510
  }
510
511
  function fmtChunks(today) {
511
- const sevHead = { CRITICAL: "Critical", HIGH: "High", MEDIUM: "Medium", LOW: "Low" };
512
+ const sevHead = { CRITICAL: "🔴 Critical", HIGH: "🟠 High", MEDIUM: "🟡 Medium", LOW: "🟢 Low" };
512
513
  const head = [];
513
514
  head.push(`# Tech Debt Register - ${projectDir.split("/").pop()}`, "");
514
515
  if (scanNumber) head.push(`**Scan #${scanNumber}** - Deep codebase scan (runtime-native, ${coverageComplete ? "full coverage" : "PARTIAL coverage"})`);
@@ -517,10 +518,10 @@ function fmtChunks(today) {
517
518
  head.push(`**Verified findings:** ${counts.total}`, "");
518
519
  head.push(`> Effort estimates use GSD-T-native units (domain / wave / spawn / token-spend). Never human-hours.`);
519
520
  head.push(`> TD numbering continues from the prior register (if any, archived). This scan begins at **TD-${tdStart}**.`, "");
520
- if (!coverageComplete) head.push(`> [!] **PARTIAL COVERAGE - ${failedSlices.length} of ${slices.length} codebase areas were NOT scanned this pass** (failed to return findings): ${ascii(failedSlices.join(", "))}. Findings UNDER-COUNT the real debt. Re-run (resume) for full coverage.`, "");
521
+ if (!coverageComplete) head.push(`> ⚠️ **PARTIAL COVERAGE - ${failedSlices.length} of ${slices.length} codebase areas were NOT scanned this pass** (failed to return findings): ${ascii(failedSlices.join(", "))}. Findings UNDER-COUNT the real debt. Re-run (resume) for full coverage.`, "");
521
522
  head.push(`## Summary`, "", `| Severity | Count |`, `|----------|-------|`,
522
- `| CRITICAL | ${counts.critical} |`, `| HIGH | ${counts.high} |`,
523
- `| MEDIUM | ${counts.medium} |`, `| LOW | ${counts.low} |`,
523
+ `| 🔴 CRITICAL | ${counts.critical} |`, `| 🟠 HIGH | ${counts.high} |`,
524
+ `| 🟡 MEDIUM | ${counts.medium} |`, `| 🟢 LOW | ${counts.low} |`,
524
525
  `| **Total** | **${counts.total}** |`, "", "---", "");
525
526
 
526
527
  function itemMd(f, td) {
@@ -659,7 +660,7 @@ const docResults = await parallel(
659
660
  d.prompt,
660
661
  ``,
661
662
  isLiving ? mergeNote : `Write the file fresh in the format described (use Bash \`mkdir -p\` for parent dirs if needed).`,
662
- `ASCII ONLY: do NOT use emoji, em-dashes (use " - "), en-dashes, smart quotes, or other non-ASCII punctuation they render as garbage in non-UTF-8 terminals. Plain ASCII markdown only.`,
663
+ `PUNCTUATION: do NOT use em-dashes (use " - "), en-dashes, smart quotes, or ellipsis charactersthose render as garbage in non-UTF-8 terminals. Use plain ASCII hyphens and straight quotes. (Severity color bullets 🔴🟠🟡🟢 are fine to keep where used for severity.)`,
663
664
  `Read the actual code under the relevant slice paths for specifics - don't summarize only from findings. Use Write/Edit to write the file, then return JSON per the schema (status "written"/"merged"/"skipped"/"failed"). Do NOT commit - the workflow handles git at the end.`,
664
665
  ].filter(Boolean).join("\n");
665
666
  try {