@tekyzinc/gsd-t 4.0.15 → 4.0.16

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,28 @@
2
2
 
3
3
  All notable changes to GSD-T are documented here. Updated with each release.
4
4
 
5
+ ## [4.0.16] - 2026-06-02 (M69 Workflow scriptPath Resolution — patch)
6
+
7
+ ### Fixed — workflow commands now run from any project, not just the GSD-T source repo
8
+
9
+ Every workflow-backed command (`gsd-t-scan`, `-execute`, `-verify`, `-wave`, `-integrate`, `-debug`, and the 6 `-phase`-runner commands) hard-coded a relative `scriptPath: "templates/workflows/..."`. That path only resolves when CWD is the GSD-T source repo; from any consumer project the workflow script (which ships inside the installed package, not the project) is unreachable, so `Workflow({scriptPath})` silently fails and the agent falls back to a hand-driven run. This is why a deep scan in a consumer project produced the register but not the 5 `.gsd-t/scan/*.md` dimension files — the M67 Document phase never executed.
10
+
11
+ - `bin/gsd-t.js`: new `gsd-t workflow-path <name>` subcommand — prints the ABSOLUTE path to `gsd-t-<name>.workflow.js` resolved from the CLI's own `PKG_ROOT`. Accepts name aliases (with/without `gsd-t-` prefix or `.workflow.js` suffix). Exit 0 + path; exit 4 + available list on unknown name; exit 64 on missing arg. Resolves from any CWD (works for global/local/npx installs since it follows the invoked binary).
12
+ - `commands/gsd-t-{scan,execute,verify,wave,integrate,debug,partition,plan,impact,milestone,prd,doc-ripple,design-decompose}.md` (13 files): replaced the relative `scriptPath` with an instruction to resolve the absolute path first via `gsd-t workflow-path <name>`.
13
+ - `templates/CLAUDE-global.md`, `commands/gsd-t-help.md`: documented the resolution requirement + the new subcommand.
14
+ - `test/m69-workflow-path.test.js`: +6 tests (resolves known/aliased/all-8 workflows, CWD-independence, exit 4 unknown, exit 64 usage).
15
+
16
+ Effect: `/gsd-t-scan` (and all workflow commands) now run correctly from any registered project with no special prompt or absolute-path workaround.
17
+
18
+ ### Added — `.gsd-t/techdebt_in_plain_english.md` scan output
19
+
20
+ The scan Document phase now also writes a non-technical companion to the tech-debt register: every TD item restated in layman's terms, why it matters in business/user consequences, and a concrete real-world analogy, with severity translated into plain urgency. For founders/PMs/stakeholders who need the findings without the jargon.
21
+
22
+ - `templates/workflows/gsd-t-scan.workflow.js`: +1 `docTargets` entry (`techdebt-plain-english`); included in the document-phase git commit.
23
+ - `commands/gsd-t-scan.md`: Document Ripple lists the new output.
24
+
25
+ Suite: 1278 pass / 0 fail / 4 skip — zero regressions.
26
+
5
27
  ## [4.0.15] - 2026-06-01 (M68 update-all Retired-Tool Prune — patch)
6
28
 
7
29
  ### Fixed — update-all now prunes bin tools retired in M61/M65
package/bin/gsd-t.js CHANGED
@@ -4446,6 +4446,43 @@ if (require.main === module) {
4446
4446
  const code = runParallelCli(args.slice(1), process.env);
4447
4447
  process.exit(code);
4448
4448
  }
4449
+ case "workflow-path": {
4450
+ // M69 — print the ABSOLUTE path to a GSD-T workflow script, resolved from
4451
+ // this CLI's own install root. Command files shell out to this instead of
4452
+ // hard-coding a relative `templates/workflows/...` scriptPath, which only
4453
+ // resolves when CWD is the GSD-T source repo — from any consumer project
4454
+ // the relative path is unresolvable and `Workflow({scriptPath})` silently
4455
+ // fails, forcing a hand-driven fallback (the HiloAviation scan incident).
4456
+ //
4457
+ // Usage: gsd-t workflow-path <name> (name with or without the
4458
+ // `gsd-t-` prefix / `.workflow.js` suffix). Exit 0 + path on stdout;
4459
+ // exit 4 + error on stderr if the workflow is unknown.
4460
+ const raw = (args[1] || "").trim();
4461
+ if (!raw) {
4462
+ process.stderr.write("usage: gsd-t workflow-path <name>\n");
4463
+ process.exit(64);
4464
+ }
4465
+ const wfDir = path.join(PKG_ROOT, "templates", "workflows");
4466
+ // Normalize: strip a leading "gsd-t-" and a trailing ".workflow.js"/".js",
4467
+ // then rebuild the canonical filename.
4468
+ const stem = raw
4469
+ .replace(/\.workflow\.js$/, "")
4470
+ .replace(/\.js$/, "")
4471
+ .replace(/^gsd-t-/, "");
4472
+ const file = path.join(wfDir, `gsd-t-${stem}.workflow.js`);
4473
+ if (!fs.existsSync(file)) {
4474
+ const avail = fs.existsSync(wfDir)
4475
+ ? fs.readdirSync(wfDir)
4476
+ .filter((f) => f.endsWith(".workflow.js"))
4477
+ .map((f) => f.replace(/^gsd-t-/, "").replace(/\.workflow\.js$/, ""))
4478
+ .join(", ")
4479
+ : "(workflows dir missing)";
4480
+ process.stderr.write(`gsd-t workflow-path: unknown workflow "${raw}". Available: ${avail}\n`);
4481
+ process.exit(4);
4482
+ }
4483
+ process.stdout.write(file + "\n");
4484
+ process.exit(0);
4485
+ }
4449
4486
  case "preflight": {
4450
4487
  // M55 D5 — `gsd-t preflight` thin dispatcher to bin/cli-preflight.cjs.
4451
4488
  const { spawnSync } = require("child_process");
@@ -22,7 +22,10 @@ Call the `Workflow` tool with:
22
22
 
23
23
  ```js
24
24
  {
25
- scriptPath: "templates/workflows/gsd-t-debug.workflow.js",
25
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path debug` (the
26
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
27
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
28
+ scriptPath: "<absolute path printed by `gsd-t workflow-path debug`>",
26
29
  args: {
27
30
  symptom: "describe the failing test or runtime error in one sentence",
28
31
  projectDir: "."
@@ -18,7 +18,10 @@ Capture the design reference from `$ARGUMENTS` (Figma URL / image path). If Figm
18
18
 
19
19
  ```js
20
20
  {
21
- scriptPath: "templates/workflows/gsd-t-phase.workflow.js",
21
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path phase` (the
22
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
23
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
24
+ scriptPath: "<absolute path printed by `gsd-t workflow-path phase`>",
22
25
  args: {
23
26
  phase: "design-decompose",
24
27
  projectDir: ".",
@@ -18,7 +18,10 @@ Read the recent commit range (or `$ARGUMENTS` if a specific scope is given) and
18
18
 
19
19
  ```js
20
20
  {
21
- scriptPath: "templates/workflows/gsd-t-phase.workflow.js",
21
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path phase` (the
22
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
23
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
24
+ scriptPath: "<absolute path printed by `gsd-t workflow-path phase`>",
22
25
  args: {
23
26
  phase: "doc-ripple",
24
27
  projectDir: ".",
@@ -22,7 +22,10 @@ Call the `Workflow` tool with:
22
22
 
23
23
  ```js
24
24
  {
25
- scriptPath: "templates/workflows/gsd-t-execute.workflow.js",
25
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path execute` (the
26
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
27
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
28
+ scriptPath: "<absolute path printed by `gsd-t workflow-path execute`>",
26
29
  args: {
27
30
  milestone: "M{NN}",
28
31
  domains: ["m{NN}-d1-...", "m{NN}-d2-...", ...],
@@ -432,6 +432,11 @@ Use these when user asks for help on a specific command:
432
432
  - **Files**: `.gsd-t/backlog-settings.md`
433
433
  - **Use when**: Customizing the classification dimensions for your project
434
434
 
435
+ ### workflow-path (M69)
436
+ - **Summary**: Prints the ABSOLUTE path to a GSD-T workflow script (`gsd-t-<name>.workflow.js`) resolved from the CLI's own install root. Command files shell out to this instead of hard-coding a relative `templates/workflows/...` scriptPath — which only resolves from the GSD-T source repo, so from any consumer project `Workflow({scriptPath})` would silently fail and fall back to a hand-driven scan (the HiloAviation incident).
437
+ - **Auto-invoked**: Yes — by every workflow-backed command (`gsd-t-scan`, `-execute`, `-verify`, `-wave`, `-integrate`, `-debug`, and the `-phase` runner) at Workflow-invocation time.
438
+ - **CLI**: `gsd-t workflow-path <name>` (name with or without the `gsd-t-` prefix / `.workflow.js` suffix). Exit 0 + absolute path on stdout; exit 4 + available list on unknown name; exit 64 on missing arg.
439
+
435
440
  ### preflight (M55)
436
441
  - **Summary**: Deterministic state-precondition check (`bin/cli-preflight.cjs`); 6 built-in checks (branch-guard, contracts-stable, deps-installed, manifest-fresh, ports-free, working-tree-state). Exit 0/4. Pluggable, zero-dep, captureSpawn-exempt.
437
442
  - **Auto-invoked**: Yes — by `gsd-t-execute` Step 1 and `gsd-t verify-gate` Track 1
@@ -18,7 +18,10 @@ Read `.gsd-t/progress.md`, the relevant domain `tasks.md`, and `docs/architectur
18
18
 
19
19
  ```js
20
20
  {
21
- scriptPath: "templates/workflows/gsd-t-phase.workflow.js",
21
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path phase` (the
22
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
23
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
24
+ scriptPath: "<absolute path printed by `gsd-t workflow-path phase`>",
22
25
  args: {
23
26
  phase: "impact",
24
27
  milestone: "M{NN}",
@@ -28,7 +28,10 @@ Call the `Workflow` tool with:
28
28
 
29
29
  ```js
30
30
  {
31
- scriptPath: "templates/workflows/gsd-t-integrate.workflow.js",
31
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path integrate` (the
32
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
33
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
34
+ scriptPath: "<absolute path printed by `gsd-t workflow-path integrate`>",
32
35
  args: {
33
36
  milestone: "M{NN}",
34
37
  domains: ["m{NN}-d1-...", "m{NN}-d2-..."], // domains that just completed
@@ -18,7 +18,10 @@ Read `.gsd-t/progress.md` (current version + completed milestones), `docs/requir
18
18
 
19
19
  ```js
20
20
  {
21
- scriptPath: "templates/workflows/gsd-t-phase.workflow.js",
21
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path phase` (the
22
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
23
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
24
+ scriptPath: "<absolute path printed by `gsd-t workflow-path phase`>",
22
25
  args: {
23
26
  phase: "milestone",
24
27
  projectDir: ".",
@@ -22,7 +22,10 @@ Call the `Workflow` tool with:
22
22
 
23
23
  ```js
24
24
  {
25
- scriptPath: "templates/workflows/gsd-t-phase.workflow.js",
25
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path phase` (the
26
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
27
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
28
+ scriptPath: "<absolute path printed by `gsd-t workflow-path phase`>",
26
29
  args: {
27
30
  phase: "partition",
28
31
  milestone: "M{NN}",
@@ -18,7 +18,10 @@ Read `.gsd-t/progress.md` and each domain's `scope.md`/`constraints.md`. The par
18
18
 
19
19
  ```js
20
20
  {
21
- scriptPath: "templates/workflows/gsd-t-phase.workflow.js",
21
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path phase` (the
22
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
23
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
24
+ scriptPath: "<absolute path printed by `gsd-t workflow-path phase`>",
22
25
  args: {
23
26
  phase: "plan",
24
27
  milestone: "M{NN}",
@@ -18,7 +18,10 @@ Read any existing `docs/requirements.md`, `docs/architecture.md`, and `.gsd-t/pr
18
18
 
19
19
  ```js
20
20
  {
21
- scriptPath: "templates/workflows/gsd-t-phase.workflow.js",
21
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path phase` (the
22
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
23
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
24
+ scriptPath: "<absolute path printed by `gsd-t workflow-path phase`>",
22
25
  args: {
23
26
  phase: "prd",
24
27
  projectDir: ".",
@@ -20,13 +20,19 @@ Each stage is a schema-validated `agent()` call (or deterministic CLI). Finders
20
20
 
21
21
  Read `CLAUDE.md`, `.gsd-t/progress.md`, `.gsd-t/contracts/`, and any existing `.gsd-t/techdebt.md` (the Workflow archives and continues from it). This tells the scan what's already known so it dedups rather than re-discovers.
22
22
 
23
- ## Step 2: Invoke the scan Workflow
23
+ ## Step 2: Resolve the workflow path, then invoke
24
24
 
25
- Call the `Workflow` tool with:
25
+ First resolve the ABSOLUTE path to the workflow script (the workflow ships inside the installed `@tekyzinc/gsd-t` package, NOT in the current project — a bare relative `templates/workflows/...` path only resolves when CWD is the GSD-T source repo, so from any other project `Workflow()` cannot find it). Run via Bash:
26
+
27
+ ```bash
28
+ gsd-t workflow-path scan
29
+ ```
30
+
31
+ It prints the absolute path (exit 0). Use that exact string as `scriptPath`. If `gsd-t` is not on PATH, fall back to `npx @tekyzinc/gsd-t workflow-path scan`, or derive it from the package: `node -e "const p=require('child_process').execSync('npm root -g').toString().trim(); console.log(p+'/@tekyzinc/gsd-t/templates/workflows/gsd-t-scan.workflow.js')"`. Do NOT fall back to a relative path or a hand-driven scan — that produces an incomplete result (the original bug). Then call the `Workflow` tool with:
26
32
 
27
33
  ```js
28
34
  {
29
- scriptPath: "templates/workflows/gsd-t-scan.workflow.js",
35
+ scriptPath: "<absolute path printed by `gsd-t workflow-path scan`>",
30
36
  args: {
31
37
  projectDir: ".", // the project to scan
32
38
  scanNumber: 12, // optional — for the register header
@@ -65,6 +71,7 @@ Present a summary: headline volume totals, findings by severity, the top critica
65
71
  The scan Workflow updates ALL of these deterministically (no manual follow-on):
66
72
 
67
73
  - `.gsd-t/techdebt.md` — fresh register (synthesis; prior one archived to `.gsd-t/techdebt_YYYY-MM-DD.md`)
74
+ - `.gsd-t/techdebt_in_plain_english.md` — non-technical companion to the register: every TD item in layman's terms, why it matters, and a real-world analogy (document phase)
68
75
  - `.gsd-t/scan/{architecture,security,quality,business-rules,contract-drift}.md` — dimension analysis files (document phase)
69
76
  - `docs/architecture.md`, `docs/workflows.md`, `docs/infrastructure.md`, `docs/requirements.md`, `README.md` — living docs, **merged not overwritten** (document phase)
70
77
  - HTML scan report via `bin/scan-report.js` (render phase)
@@ -31,7 +31,10 @@ Call the `Workflow` tool with:
31
31
 
32
32
  ```js
33
33
  {
34
- scriptPath: "templates/workflows/gsd-t-verify.workflow.js",
34
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path verify` (the
35
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
36
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
37
+ scriptPath: "<absolute path printed by `gsd-t workflow-path verify`>",
35
38
  args: {
36
39
  milestone: "M{NN}",
37
40
  projectDir: ".",
@@ -26,7 +26,10 @@ Call the `Workflow` tool with:
26
26
 
27
27
  ```js
28
28
  {
29
- scriptPath: "templates/workflows/gsd-t-wave.workflow.js",
29
+ // Resolve the ABSOLUTE path FIRST via Bash: `gsd-t workflow-path wave` (the
30
+ // workflow ships in the installed @tekyzinc/gsd-t package, not this project — a
31
+ // bare relative path only resolves from the GSD-T source repo). Use its stdout here:
32
+ scriptPath: "<absolute path printed by `gsd-t workflow-path wave`>",
30
33
  args: {
31
34
  milestone: "M{NN}",
32
35
  domains: ["m{NN}-d1-...", "m{NN}-d2-...", ...], // domains for this wave only, per integration-points
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "4.0.15",
3
+ "version": "4.0.16",
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",
@@ -319,7 +319,7 @@ Routine GSD-T actions (milestone → partition → plan → execute → verify
319
319
 
320
320
  ## GSD-T Workflows (M61 — v4.0.10+)
321
321
 
322
- GSD-T workflows live at `templates/workflows/`. Each workflow is a self-contained native Workflow script that handles one phase of the GSD-T lifecycle. Command files (`commands/gsd-t-*.md`) are thin invokers that call `Workflow({scriptPath, args})`.
322
+ GSD-T workflows live at `templates/workflows/`. Each workflow is a self-contained native Workflow script that handles one phase of the GSD-T lifecycle. Command files (`commands/gsd-t-*.md`) are thin invokers that call `Workflow({scriptPath, args})`. The `scriptPath` MUST be resolved to an absolute path at invoke time via `gsd-t workflow-path <name>` (M69) — the workflow ships inside the installed `@tekyzinc/gsd-t` package, not the consumer project, so a bare relative `templates/workflows/...` path only resolves from the GSD-T source repo and silently breaks `Workflow()` everywhere else.
323
323
 
324
324
  Canonical scripts:
325
325
  - `gsd-t-execute.workflow.js` — preflight → brief → file-disjointness → parallel(domain workers) → integrate → verify-gate
@@ -43,7 +43,7 @@ export const meta = {
43
43
  { title: "Probe", detail: "volume probe → derive per-area slice list", model: "haiku" },
44
44
  { title: "Deep Scan", detail: "pipeline: per-slice deep finder → single verify" },
45
45
  { title: "Synthesis", detail: "dedup / merge / re-rank into techdebt.md", model: "opus" },
46
- { title: "Document", detail: "deep living-doc + dimension-file cross-population (per-doc fan-out)" },
46
+ { title: "Document", detail: "deep living-doc + dimension-file + plain-English cross-population (per-doc fan-out)" },
47
47
  { title: "Render", detail: "schema extraction + diagrams + HTML report" },
48
48
  ],
49
49
  };
@@ -463,6 +463,13 @@ if (!fs.existsSync(registerPath)) {
463
463
  }
464
464
  log(`register written: ${JSON.stringify(synthesis.counts)}`);
465
465
 
466
+ // Read the synthesized register so the plain-English doc can mirror its EXACT
467
+ // TD-NNN ids / order (red-team HIGH-1: raw findings carry no TD ids, so a doc
468
+ // built only from findings would invent divergent numbering and break the
469
+ // cross-reference to techdebt.md). The register exists here (confirmed above).
470
+ let registerText = "";
471
+ try { registerText = fs.readFileSync(registerPath, "utf8"); } catch (_) {}
472
+
466
473
  // ─── Document — deep living-doc + dimension-file cross-population (M67) ───
467
474
  // M66 made the register deep but left doc cross-population as a non-deterministic
468
475
  // "lead agent follow-on" — effectively dropped. M67 fans out one agent PER DOCUMENT,
@@ -577,15 +584,51 @@ const docTargets = [
577
584
  id: "readme", label: "README.md", merge: true,
578
585
  prompt: `Update or create \`README.md\`: project name + description; tech stack + versions discovered; getting-started/setup (from infrastructure findings); brief architecture overview; link to \`docs/\` for detail. If it exists, MERGE — update tech-stack + setup sections but preserve the user's existing structure and custom content.`,
579
586
  },
587
+ {
588
+ id: "techdebt-plain-english", label: ".gsd-t/techdebt_in_plain_english.md",
589
+ needsRegister: true, // red-team HIGH-1: must receive the synthesized register (TD-NNN ids live there, not in findings)
590
+ prompt: `Write \`.gsd-t/techdebt_in_plain_english.md\` — a NON-TECHNICAL companion to the tech-debt register, written for a smart reader who is NOT an engineer (e.g. a founder, PM, or stakeholder). Cover EVERY item in the register (one entry per TD-NNN, in the same severity order), using the EXACT TD-NNN ids from the register provided below. For each item:\n` +
591
+ `- **Heading**: \`### TD-NNN — <the plain-English name of the problem>\` (keep the TD-NNN id so it cross-references the technical register, but rename the title into everyday language — no jargon).\n` +
592
+ `- **What it is** (1-2 sentences): explain the problem with ZERO technical terms. If a technical word is unavoidable, define it in parentheses the way you'd explain it to a friend.\n` +
593
+ `- **Why it matters** (1-2 sentences): the business/user consequence — what could go wrong, who is affected, what it costs.\n` +
594
+ `- **Real-world analogy**: a concrete everyday comparison that makes the risk intuitive (e.g. "This is like leaving the spare house key under the doormat — convenient, but anyone who thinks to look can get in." for a hardcoded secret). The analogy must genuinely map to THIS specific item, not be generic.\n` +
595
+ `- **Severity in plain terms**: translate CRITICAL/HIGH/MEDIUM/LOW into urgency a non-engineer feels ("fix before launch" / "schedule soon" / "clean up eventually").\n` +
596
+ `Open with a 2-3 sentence plain-English summary of the overall health of the codebase and the headline counts. Derive everything from the verified findings — do not invent items or analogies that don't fit. This file is the layman's lens on the same findings as \`.gsd-t/techdebt.md\`.`,
597
+ },
580
598
  ];
581
599
 
582
600
  const docResults = await parallel(
583
601
  docTargets.map((d) => async () => {
584
602
  const isLiving = !!d.merge;
603
+ // red-team HIGH-1: targets that mirror the register (plain-english) get the
604
+ // synthesized register text — the authoritative source of TD-NNN ids/order —
605
+ // not just the raw findings.
606
+ // red-team MEDIUM: do NOT silently truncate the register — a large register
607
+ // (e.g. 119 items ≈ 180KB) sliced to a small cap would drop the entire
608
+ // MEDIUM/LOW tail while the prompt says "cover EVERY item" (silent-cap
609
+ // anti-pattern the workflow forbids elsewhere). Cap generously, and if we DO
610
+ // hit it, tell the agent explicitly + log it so completeness loss is visible.
611
+ const REGISTER_CAP = 400000;
612
+ let registerBlock = "";
613
+ if (d.needsRegister) {
614
+ const truncated = registerText.length > REGISTER_CAP;
615
+ if (truncated) {
616
+ log(`⚠ register (${registerText.length} bytes) exceeds the ${REGISTER_CAP}-byte plain-english injection cap — the tail will be missing from techdebt_in_plain_english.md. Consider splitting the register.`);
617
+ }
618
+ registerBlock = [
619
+ "",
620
+ "Synthesized register (.gsd-t/techdebt.md) — use these EXACT TD-NNN ids/order:",
621
+ truncated ? "⚠ NOTE: the register was truncated to fit; cover every item you CAN see and end with a line noting that items beyond the last shown TD-NNN were omitted due to size." : "",
622
+ "```markdown",
623
+ registerText.slice(0, REGISTER_CAP),
624
+ "```",
625
+ ].join("\n");
626
+ }
585
627
  const prompt = [
586
628
  `You are the documentation agent for ONE document in a GSD-T deep scan.`,
587
629
  ``,
588
630
  baseCtx,
631
+ registerBlock,
589
632
  ``,
590
633
  d.prompt,
591
634
  ``,
@@ -680,7 +723,7 @@ if (render.ok) {
680
723
  // aren't versioned.
681
724
  const commit = spawnSync(
682
725
  "git",
683
- ["add", "-A", ".gsd-t/scan", "docs", "README.md", ":!.gsd-t/scan/.doc-backup"],
726
+ ["add", "-A", ".gsd-t/scan", ".gsd-t/techdebt_in_plain_english.md", "docs", "README.md", ":!.gsd-t/scan/.doc-backup"],
684
727
  { cwd: projectDir, stdio: "pipe" }
685
728
  );
686
729
  if (commit.status === 0) {