@tekyzinc/gsd-t 3.12.12 → 3.12.14

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 (59) hide show
  1. package/CHANGELOG.md +103 -26
  2. package/README.md +76 -76
  3. package/bin/design-orchestrator.js +1 -1
  4. package/bin/gsd-t-unattended.cjs +15 -5
  5. package/bin/gsd-t-unattended.js +1 -1
  6. package/bin/gsd-t.js +114 -13
  7. package/bin/headless-auto-spawn.cjs +22 -3
  8. package/bin/headless-auto-spawn.js +12 -1
  9. package/bin/orchestrator.js +26 -0
  10. package/commands/gsd-t-backlog-promote.md +6 -6
  11. package/commands/gsd-t-complete-milestone.md +7 -7
  12. package/commands/gsd-t-design-audit.md +3 -3
  13. package/commands/gsd-t-design-build.md +1 -1
  14. package/commands/gsd-t-design-decompose.md +4 -4
  15. package/commands/gsd-t-execute.md +1 -1
  16. package/commands/gsd-t-feature.md +3 -3
  17. package/commands/gsd-t-gap-analysis.md +3 -3
  18. package/commands/gsd-t-health.md +3 -3
  19. package/commands/gsd-t-help.md +10 -10
  20. package/commands/gsd-t-impact.md +3 -3
  21. package/commands/gsd-t-init-scan-setup.md +5 -5
  22. package/commands/gsd-t-init.md +4 -4
  23. package/commands/gsd-t-log.md +1 -1
  24. package/commands/gsd-t-milestone.md +2 -2
  25. package/commands/gsd-t-pause.md +2 -2
  26. package/commands/gsd-t-prd.md +2 -2
  27. package/commands/gsd-t-project.md +1 -1
  28. package/commands/gsd-t-resume.md +4 -4
  29. package/commands/gsd-t-scan.md +3 -3
  30. package/commands/gsd-t-setup.md +2 -2
  31. package/commands/gsd-t-test-sync.md +1 -1
  32. package/commands/gsd-t-unattended-watch.md +5 -5
  33. package/commands/gsd-t-unattended.md +9 -9
  34. package/commands/gsd-t-wave.md +4 -4
  35. package/commands/gsd.md +17 -17
  36. package/docs/GSD-T-README.md +68 -68
  37. package/docs/architecture.md +8 -8
  38. package/docs/context-budget-recovery-plan.md +2 -2
  39. package/docs/infrastructure.md +7 -7
  40. package/docs/methodology.md +1 -1
  41. package/docs/neo4j-setup.md +2 -2
  42. package/docs/prd-gsd2-hybrid.md +1 -1
  43. package/docs/prd-harness-evolution.md +1 -1
  44. package/docs/requirements.md +2 -2
  45. package/docs/unattended-config.md +1 -1
  46. package/docs/unattended-windows-caveats.md +1 -1
  47. package/docs/workflows.md +1 -1
  48. package/package.json +1 -1
  49. package/scripts/context-meter/threshold.test.js +2 -2
  50. package/scripts/gsd-t-auto-route.js +1 -1
  51. package/scripts/gsd-t-context-meter.e2e.test.js +1 -1
  52. package/scripts/gsd-t-context-meter.test.js +1 -1
  53. package/scripts/gsd-t-design-review-server.js +11 -1
  54. package/scripts/gsd-t-event-writer.js +7 -4
  55. package/scripts/gsd-t-heartbeat.js +11 -1
  56. package/scripts/gsd-t-update-check.js +1 -1
  57. package/templates/CLAUDE-global.md +18 -163
  58. package/templates/stacks/_markdown.md +32 -0
  59. package/templates/stacks/design-to-code.md +1 -1
package/bin/gsd-t.js CHANGED
@@ -1294,9 +1294,9 @@ function showInstallSummary(gsdtCount, utilCount) {
1294
1294
  log(`${BOLD}Quick Start:${RESET}`);
1295
1295
  log(` ${DIM}$${RESET} cd your-project`);
1296
1296
  log(` ${DIM}$${RESET} claude`);
1297
- log(` ${DIM}>${RESET} /user:gsd-t-init my-project`);
1298
- log(` ${DIM}>${RESET} /user:gsd-t-milestone "First Feature"`);
1299
- log(` ${DIM}>${RESET} /user:gsd-t-wave`);
1297
+ log(` ${DIM}>${RESET} /gsd-t-init my-project`);
1298
+ log(` ${DIM}>${RESET} /gsd-t-milestone "First Feature"`);
1299
+ log(` ${DIM}>${RESET} /gsd-t-wave`);
1300
1300
  log("");
1301
1301
  log(`${BOLD}Other commands:${RESET}`);
1302
1302
  log(` ${DIM}$${RESET} npx @tekyzinc/gsd-t status ${DIM}— check installation${RESET}`);
@@ -1344,7 +1344,7 @@ function initClaudeMd(projectDir, projectName, today) {
1344
1344
  info("CLAUDE.md already contains GSD-T section — skipping");
1345
1345
  } else {
1346
1346
  warn("CLAUDE.md exists but doesn't reference GSD-T");
1347
- info("Run /user:gsd-t-init inside Claude Code to add GSD-T section");
1347
+ info("Run /gsd-t-init inside Claude Code to add GSD-T section");
1348
1348
  }
1349
1349
  } else { throw e; }
1350
1350
  }
@@ -1513,8 +1513,8 @@ function showInitTree(projectDir) {
1513
1513
  log(`${BOLD}Next steps:${RESET}`);
1514
1514
  log(` 1. Edit CLAUDE.md — add project overview and tech stack`);
1515
1515
  log(` 2. Start Claude Code: ${DIM}claude${RESET}`);
1516
- log(` 3. Run: ${DIM}/user:gsd-t-populate${RESET} ${DIM}(if existing codebase)${RESET}`);
1517
- log(` Or: ${DIM}/user:gsd-t-project${RESET} ${DIM}(if new project)${RESET}`);
1516
+ log(` 3. Run: ${DIM}/gsd-t-populate${RESET} ${DIM}(if existing codebase)${RESET}`);
1517
+ log(` Or: ${DIM}/gsd-t-project${RESET} ${DIM}(if new project)${RESET}`);
1518
1518
  log("");
1519
1519
  }
1520
1520
 
@@ -1687,7 +1687,7 @@ function showStatusProject() {
1687
1687
  }
1688
1688
  } else if (hasClaudeMd) {
1689
1689
  info("CLAUDE.md found but no .gsd-t/ directory");
1690
- info("Run /user:gsd-t-init inside Claude Code to set up");
1690
+ info("Run /gsd-t-init inside Claude Code to set up");
1691
1691
  } else {
1692
1692
  info("Not in a GSD-T project directory");
1693
1693
  info(`Run 'npx @tekyzinc/gsd-t init' to set up this directory`);
@@ -1945,6 +1945,19 @@ function exportUniversalRulesForNpm() {
1945
1945
  }
1946
1946
 
1947
1947
  async function doUpdateAll() {
1948
+ // Step 1: Upgrade the globally-installed npm package FIRST. Without this,
1949
+ // `update-all` would only propagate command files — but the global `gsd-t`
1950
+ // binary itself could stay pinned to an older version (e.g., user stuck
1951
+ // on v3.11.11 while npm registry has v3.12.12). See CHANGELOG v3.12.13.
1952
+ // Guard with an env flag to prevent re-exec loops.
1953
+ if (!process.env.GSDT_POST_UPGRADE) {
1954
+ const upgraded = await upgradeGlobalBinary();
1955
+ if (upgraded.reexec) {
1956
+ reexecUpdateAll();
1957
+ return;
1958
+ }
1959
+ }
1960
+
1948
1961
  await updateGlobalCommands();
1949
1962
  heading("Updating registered projects...");
1950
1963
  log("");
@@ -1969,6 +1982,65 @@ async function doUpdateAll() {
1969
1982
  showUpdateAllSummary(projects.length, counts, playwrightMissing, swaggerMissing, syncCount);
1970
1983
  }
1971
1984
 
1985
+ // Upgrade the globally-installed @tekyzinc/gsd-t to @latest. Returns
1986
+ // { upgraded: bool, reexec: bool, error?: string }.
1987
+ // - reexec=true when the on-disk version after `npm install -g` is newer than
1988
+ // the currently-running PKG_VERSION, meaning we need to hand off to the
1989
+ // freshly-installed binary so the new code drives propagation.
1990
+ // - reexec=false when already at latest, or when the install failed (we
1991
+ // continue with the current binary and still propagate command files).
1992
+ async function upgradeGlobalBinary() {
1993
+ heading("Upgrading global @tekyzinc/gsd-t to latest...");
1994
+ try {
1995
+ execFileSync("npm", ["install", "-g", "@tekyzinc/gsd-t@latest"], {
1996
+ stdio: "inherit",
1997
+ env: process.env,
1998
+ });
1999
+ } catch (e) {
2000
+ warn(`Global npm install failed: ${e.message || e}`);
2001
+ info("Continuing with current binary — command files will still be propagated.");
2002
+ return { upgraded: false, reexec: false, error: String(e.message || e) };
2003
+ }
2004
+
2005
+ // Read the freshly-installed global package's version. If it's newer than
2006
+ // the currently-running process, signal a re-exec.
2007
+ let newVersion = null;
2008
+ try {
2009
+ const prefix = execFileSync("npm", ["prefix", "-g"], { encoding: "utf8" }).trim();
2010
+ const globalPkgJson = path.join(prefix, "lib", "node_modules", "@tekyzinc", "gsd-t", "package.json");
2011
+ if (fs.existsSync(globalPkgJson)) {
2012
+ newVersion = JSON.parse(fs.readFileSync(globalPkgJson, "utf8")).version;
2013
+ }
2014
+ } catch {
2015
+ // Best-effort; fall through.
2016
+ }
2017
+
2018
+ if (newVersion && newVersion !== PKG_VERSION) {
2019
+ success(`Global binary upgraded: v${PKG_VERSION} → v${newVersion}`);
2020
+ info("Handing off to the newly-installed binary for propagation...");
2021
+ return { upgraded: true, reexec: true };
2022
+ }
2023
+ success(`Global binary already at latest (v${PKG_VERSION})`);
2024
+ return { upgraded: true, reexec: false };
2025
+ }
2026
+
2027
+ // Hand execution to the newly-installed global `gsd-t update-all`. Sets the
2028
+ // GSDT_POST_UPGRADE env flag so the child does not recurse into another
2029
+ // upgrade attempt.
2030
+ function reexecUpdateAll() {
2031
+ const env = Object.assign({}, process.env, { GSDT_POST_UPGRADE: "1" });
2032
+ try {
2033
+ execFileSync("gsd-t", ["update-all"], { stdio: "inherit", env });
2034
+ } catch (e) {
2035
+ // Surface the child's exit code; execFileSync throws with .status on
2036
+ // non-zero exit. Fall through to re-throw so the caller exits cleanly.
2037
+ if (e && typeof e.status === "number") {
2038
+ process.exit(e.status);
2039
+ }
2040
+ throw e;
2041
+ }
2042
+ }
2043
+
1972
2044
  async function updateGlobalCommands() {
1973
2045
  if (getInstalledVersion() !== PKG_VERSION) {
1974
2046
  await doInstall({ update: true });
@@ -2671,8 +2743,10 @@ function appendHeadlessTokenLog(projectDir, entry) {
2671
2743
  try {
2672
2744
  const logPath = path.join(projectDir, ".gsd-t", "token-log.md");
2673
2745
  const note = entry.exitCode === 0 ? "headless exec: ok" : `headless exec: exit ${entry.exitCode}`;
2746
+ // v3.12.14: prefer env-var model over hardcoded "unknown".
2747
+ const model = process.env.GSD_T_MODEL || "unknown";
2674
2748
  const row =
2675
- `| ${entry.dtStart} | ${entry.dtEnd} | ${entry.command} | headless | unknown | ${entry.durationS}s | ${note} | - | - | unknown |\n`;
2749
+ `| ${entry.dtStart} | ${entry.dtEnd} | ${entry.command} | headless | ${model} | ${entry.durationS}s | ${note} | - | - | unknown |\n`;
2676
2750
  const gsdtDir = path.join(projectDir, ".gsd-t");
2677
2751
  if (!fs.existsSync(gsdtDir)) fs.mkdirSync(gsdtDir, { recursive: true });
2678
2752
  if (!fs.existsSync(logPath)) {
@@ -2718,7 +2792,7 @@ function parseHeadlessFlags(args) {
2718
2792
  * Build the claude -p invocation string for a GSD-T command.
2719
2793
  *
2720
2794
  * Non-interactive `claude -p` mode requires the bare `/gsd-t-X` form — the
2721
- * `/user:gsd-t-X` namespace prefix is rejected as "Unknown command" even
2795
+ * `/gsd-t-X` namespace prefix is rejected as "Unknown command" even
2722
2796
  * though interactive mode accepts both. Verified by M36 Phase 0 Spike A
2723
2797
  * (2026-04-15). See .gsd-t/M36-spike-findings.md.
2724
2798
  */
@@ -2807,12 +2881,17 @@ function doHeadlessExec(command, cmdArgs, flags) {
2807
2881
  let output = "";
2808
2882
  let processExitCode = 0;
2809
2883
 
2810
- // Inject command/phase env vars so worker event-stream entries are tagged
2811
- // (Fix 2, v3.12.12).
2884
+ // Inject command/phase/trace/model/project-dir env vars so worker
2885
+ // event-stream entries (writer CLI + heartbeat hook) are tagged in the
2886
+ // child's context (Fix 2, v3.12.12; trace/model/project-dir added v3.12.14
2887
+ // for the null-telemetry regression fix).
2812
2888
  const workerEnv = Object.assign({}, process.env, {
2813
2889
  GSD_T_COMMAND: `gsd-t-${command}`,
2814
2890
  GSD_T_PHASE: process.env.GSD_T_PHASE || "execute",
2891
+ GSD_T_PROJECT_DIR: process.env.GSD_T_PROJECT_DIR || process.cwd(),
2815
2892
  });
2893
+ if (process.env.GSD_T_TRACE_ID) workerEnv.GSD_T_TRACE_ID = process.env.GSD_T_TRACE_ID;
2894
+ if (process.env.GSD_T_MODEL) workerEnv.GSD_T_MODEL = process.env.GSD_T_MODEL;
2816
2895
 
2817
2896
  try {
2818
2897
  const result = execFileSync("claude", ["-p", "--dangerously-skip-permissions", prompt], {
@@ -3097,9 +3176,22 @@ function getEscalationModel(iteration) {
3097
3176
  */
3098
3177
  function spawnClaudeSession(prompt, model) {
3099
3178
  try {
3179
+ // v3.12.14: propagate GSD_T_* env vars so the worker's heartbeat hook +
3180
+ // event-writer entries are tagged with the parent command/phase/trace and
3181
+ // this session's model. Without these, tool_call events from the debug
3182
+ // worker appear as command=null/phase=null.
3183
+ const env = Object.assign({}, process.env, {
3184
+ GSD_T_COMMAND: process.env.GSD_T_COMMAND || "gsd-t-debug",
3185
+ GSD_T_PHASE: process.env.GSD_T_PHASE || "debug",
3186
+ GSD_T_MODEL: model || process.env.GSD_T_MODEL || null,
3187
+ GSD_T_PROJECT_DIR: process.env.GSD_T_PROJECT_DIR || process.cwd(),
3188
+ });
3189
+ if (env.GSD_T_MODEL === null) delete env.GSD_T_MODEL;
3190
+ if (process.env.GSD_T_TRACE_ID) env.GSD_T_TRACE_ID = process.env.GSD_T_TRACE_ID;
3100
3191
  return execFileSync("claude", ["-p", prompt, "--model", model], {
3101
3192
  encoding: "utf8", timeout: 300000,
3102
3193
  stdio: ["pipe", "pipe", "pipe"],
3194
+ env,
3103
3195
  });
3104
3196
  } catch (e) {
3105
3197
  return (e.stdout || "") + (e.stderr || "") || null;
@@ -3136,8 +3228,17 @@ function runLedgerCompaction(projectDir, jsonMode) {
3136
3228
  JSON.stringify(entries, null, 2);
3137
3229
  let summary = "Compacted — see previous entries.";
3138
3230
  try {
3231
+ // v3.12.14: propagate GSD_T_* env for telemetry tagging.
3232
+ const env = Object.assign({}, process.env, {
3233
+ GSD_T_COMMAND: process.env.GSD_T_COMMAND || "gsd-t-debug",
3234
+ GSD_T_PHASE: process.env.GSD_T_PHASE || "debug",
3235
+ GSD_T_MODEL: "haiku",
3236
+ GSD_T_PROJECT_DIR: process.env.GSD_T_PROJECT_DIR || projectDir,
3237
+ });
3238
+ if (process.env.GSD_T_TRACE_ID) env.GSD_T_TRACE_ID = process.env.GSD_T_TRACE_ID;
3139
3239
  const out = execFileSync("claude", ["-p", compactPrompt, "--model", "haiku"], {
3140
3240
  encoding: "utf8", timeout: 120000, stdio: ["pipe", "pipe", "pipe"],
3241
+ env,
3141
3242
  });
3142
3243
  summary = (out || "").trim() || summary;
3143
3244
  } catch (e) {
@@ -3378,8 +3479,8 @@ function showHelp() {
3378
3479
  log(` ${DIM}$${RESET} npx @tekyzinc/gsd-t init my-saas-app`);
3379
3480
  log(` ${DIM}$${RESET} npx @tekyzinc/gsd-t update\n`);
3380
3481
  log(`${BOLD}After installing, use in Claude Code:${RESET}`);
3381
- log(` ${DIM}>${RESET} /user:gsd-t-project "Build a task management app"`);
3382
- log(` ${DIM}>${RESET} /user:gsd-t-wave\n`);
3482
+ log(` ${DIM}>${RESET} /gsd-t-project "Build a task management app"`);
3483
+ log(` ${DIM}>${RESET} /gsd-t-wave\n`);
3383
3484
  log(`${DIM}Docs: https://github.com/Tekyz-Inc/get-stuff-done-teams${RESET}\n`);
3384
3485
  }
3385
3486
 
@@ -135,12 +135,27 @@ function autoSpawnHeadless(opts) {
135
135
  const gsdtCli = path.join(projectDir, "bin", "gsd-t.js");
136
136
  const childArgs = [gsdtCli, "headless", stripGsdtPrefix(command), ...args, "--log"];
137
137
 
138
- // Inject command/phase into worker env so event-stream entries are tagged
139
- // (Fix 2, v3.12.12). GSD_T_PHASE defaults to "execute" for primary spawns.
138
+ // Inject command/phase/trace/model into worker env so event-stream entries
139
+ // (both the writer CLI and the heartbeat PostToolUse hook) are tagged in
140
+ // the child's context (Fix 2, v3.12.12; trace/model/project-dir added
141
+ // v3.12.14 to close the null-telemetry regression).
142
+ //
143
+ // GSD_T_PHASE defaults to "execute" for primary spawns.
144
+ // GSD_T_TRACE_ID / GSD_T_MODEL are inherited from parent env if set;
145
+ // parents (orchestrator, command files) should set them before spawning.
146
+ // GSD_T_PROJECT_DIR gives the writer a stable target when the child cwd
147
+ // drifts (e.g., temp dirs in subagents).
140
148
  const workerEnv = Object.assign({}, process.env, {
141
149
  GSD_T_COMMAND: command,
142
150
  GSD_T_PHASE: process.env.GSD_T_PHASE || "execute",
151
+ GSD_T_PROJECT_DIR: process.env.GSD_T_PROJECT_DIR || projectDir,
143
152
  });
153
+ if (process.env.GSD_T_TRACE_ID) {
154
+ workerEnv.GSD_T_TRACE_ID = process.env.GSD_T_TRACE_ID;
155
+ }
156
+ if (process.env.GSD_T_MODEL) {
157
+ workerEnv.GSD_T_MODEL = process.env.GSD_T_MODEL;
158
+ }
144
159
 
145
160
  const child = spawn("node", childArgs, {
146
161
  cwd: projectDir,
@@ -392,8 +407,12 @@ function appendTokenLog(projectDir, entry) {
392
407
  try {
393
408
  const logPath = path.join(projectDir, ".gsd-t", "token-log.md");
394
409
  const note = entry.exitCode === 0 ? "headless spawn: ok" : `headless spawn: exit ${entry.exitCode}`;
410
+ // v3.12.14: prefer env-var model over the old hardcoded "unknown". The
411
+ // parent session should have set GSD_T_MODEL before invoking spawn; fall
412
+ // back to "unknown" if not (graceful).
413
+ const model = process.env.GSD_T_MODEL || "unknown";
395
414
  const row =
396
- `| ${entry.dtStart} | ${entry.dtEnd} | ${entry.command} | headless | unknown | ${entry.durationS}s | ${note} | - | - | unknown |\n`;
415
+ `| ${entry.dtStart} | ${entry.dtEnd} | ${entry.command} | headless | ${model} | ${entry.durationS}s | ${note} | - | - | unknown |\n`;
397
416
  if (!fs.existsSync(logPath)) {
398
417
  // Create with header
399
418
  ensureDir(path.dirname(logPath));
@@ -135,11 +135,22 @@ function autoSpawnHeadless(opts) {
135
135
  const gsdtCli = path.join(projectDir, "bin", "gsd-t.js");
136
136
  const childArgs = [gsdtCli, "headless", stripGsdtPrefix(command), ...args, "--log"];
137
137
 
138
+ // v3.12.14 — env-var propagation for telemetry tagging (mirror of the
139
+ // authoritative .cjs variant). PRODUCTION consumers import the .cjs; this
140
+ // .js copy is retained only to keep the legacy test green.
141
+ const workerEnv = Object.assign({}, process.env, {
142
+ GSD_T_COMMAND: command,
143
+ GSD_T_PHASE: process.env.GSD_T_PHASE || "execute",
144
+ GSD_T_PROJECT_DIR: process.env.GSD_T_PROJECT_DIR || projectDir,
145
+ });
146
+ if (process.env.GSD_T_TRACE_ID) workerEnv.GSD_T_TRACE_ID = process.env.GSD_T_TRACE_ID;
147
+ if (process.env.GSD_T_MODEL) workerEnv.GSD_T_MODEL = process.env.GSD_T_MODEL;
148
+
138
149
  const child = spawn("node", childArgs, {
139
150
  cwd: projectDir,
140
151
  detached: true,
141
152
  stdio: ["ignore", logFd, logFd],
142
- env: process.env,
153
+ env: workerEnv,
143
154
  });
144
155
 
145
156
  child.unref();
@@ -82,6 +82,25 @@ function isPortInUse(port) {
82
82
  }
83
83
  }
84
84
 
85
+ /**
86
+ * Build the env block for orchestrator-spawned `claude -p` sessions.
87
+ * v3.12.14 — propagates GSD_T_COMMAND/PHASE/TRACE_ID/MODEL/PROJECT_DIR so the
88
+ * worker's heartbeat hook and event-writer entries are tagged. Accepts the
89
+ * opts object (for `label`) that callers already pass and defaults missing
90
+ * fields from the parent process env.
91
+ */
92
+ function _buildOrchestratorEnv(opts, projectDir) {
93
+ opts = opts || {};
94
+ const env = Object.assign({}, process.env, {
95
+ GSD_T_COMMAND: process.env.GSD_T_COMMAND || "gsd-t-orchestrator",
96
+ GSD_T_PHASE: process.env.GSD_T_PHASE || opts.label || "orchestrator",
97
+ GSD_T_PROJECT_DIR: process.env.GSD_T_PROJECT_DIR || projectDir,
98
+ });
99
+ if (process.env.GSD_T_TRACE_ID) env.GSD_T_TRACE_ID = process.env.GSD_T_TRACE_ID;
100
+ if (process.env.GSD_T_MODEL) env.GSD_T_MODEL = process.env.GSD_T_MODEL;
101
+ return env;
102
+ }
103
+
85
104
  // ─── Orchestrator Class ────────────────────────────────────────────────────
86
105
 
87
106
  class Orchestrator {
@@ -212,11 +231,15 @@ ${BOLD}Phases:${RESET} ${this.wf.phases.join(" → ")}
212
231
  const signalFile = path.join(this.getReviewDir(projectDir), `_sync-done-${Date.now()}.json`);
213
232
  let result = { output: "", exitCode: 1, duration: 0 };
214
233
 
234
+ // v3.12.14: propagate GSD_T_* env so the worker's heartbeat hook and
235
+ // event-writer entries are tagged. opts.label → phase/command hints.
236
+ const env = _buildOrchestratorEnv(opts, projectDir);
215
237
  const child = execFile("claude", args, {
216
238
  encoding: "utf8",
217
239
  timeout: effectiveTimeout,
218
240
  cwd: projectDir,
219
241
  maxBuffer: 10 * 1024 * 1024,
242
+ env,
220
243
  }, (err, stdout, stderr) => {
221
244
  this.untrackChild(child.pid);
222
245
  const raw = err ? ((err.stdout || "") + (err.stderr || "")) : (stdout || "");
@@ -264,12 +287,15 @@ ${BOLD}Phases:${RESET} ${this.wf.phases.join(" → ")}
264
287
  );
265
288
  }
266
289
 
290
+ // v3.12.14: propagate GSD_T_* env for telemetry tagging in the child.
291
+ const env = _buildOrchestratorEnv(opts, projectDir);
267
292
  return new Promise((resolve) => {
268
293
  const child = execFile("claude", args, {
269
294
  encoding: "utf8",
270
295
  timeout: timeout || 120_000,
271
296
  cwd: projectDir,
272
297
  maxBuffer: 10 * 1024 * 1024,
298
+ env,
273
299
  }, (err, stdout, stderr) => {
274
300
  this.untrackChild(child.pid);
275
301
  const raw = err ? ((err.stdout || "") + (err.stderr || "")) : (stdout || "");
@@ -13,14 +13,14 @@ Parse $ARGUMENTS to extract:
13
13
  - `<position>` — the entry number to promote
14
14
 
15
15
  If no position is provided, show an error:
16
- "Usage: `/user:gsd-t-backlog-promote <position>`"
16
+ "Usage: `/gsd-t-backlog-promote <position>`"
17
17
 
18
18
  ## Step 2: Find and Display Entry
19
19
 
20
20
  Find the entry at the specified position in `.gsd-t/backlog.md`.
21
21
 
22
22
  If the position doesn't exist, show an error:
23
- "No backlog entry at position {position}. Run `/user:gsd-t-backlog-list` to see available entries."
23
+ "No backlog entry at position {position}. Run `/gsd-t-backlog-list` to see available entries."
24
24
 
25
25
  Display the entry to the user:
26
26
  ```
@@ -88,10 +88,10 @@ After classification is confirmed:
88
88
 
89
89
  Based on the classification, present the command for the user to invoke:
90
90
 
91
- - **Milestone**: "Run `/user:gsd-t-milestone {refined description}`"
92
- - **Quick**: "Run `/user:gsd-t-quick {refined description}`"
93
- - **Debug**: "Run `/user:gsd-t-debug {refined description}`"
94
- - **Feature**: "Run `/user:gsd-t-feature {refined description}`"
91
+ - **Milestone**: "Run `/gsd-t-milestone {refined description}`"
92
+ - **Quick**: "Run `/gsd-t-quick {refined description}`"
93
+ - **Debug**: "Run `/gsd-t-debug {refined description}`"
94
+ - **Feature**: "Run `/gsd-t-feature {refined description}`"
95
95
 
96
96
  Display the full command with the refined description ready to copy.
97
97
 
@@ -3,8 +3,8 @@
3
3
  You are finalizing a completed milestone. Your job is to archive the milestone documentation, create a git tag, and prepare for the next milestone.
4
4
 
5
5
  This command is:
6
- - **Auto-invoked** by `/user:gsd-t-verify` (Step 8) after all quality gates pass — at ALL autonomy levels
7
- - **Auto-invoked** by `/user:gsd-t-wave` as part of the VERIFY+COMPLETE phase
6
+ - **Auto-invoked** by `/gsd-t-verify` (Step 8) after all quality gates pass — at ALL autonomy levels
7
+ - **Auto-invoked** by `/gsd-t-wave` as part of the VERIFY+COMPLETE phase
8
8
  - **Standalone** when user wants to manually close a milestone
9
9
 
10
10
  ## Step 1: Verify Completion
@@ -14,7 +14,7 @@ Read:
14
14
  2. `.gsd-t/verify-report.md` — confirm all checks passed
15
15
 
16
16
  If status is not VERIFIED:
17
- "⚠️ Milestone not yet verified. Run `/user:gsd-t-verify` first, or use `--force` to complete anyway."
17
+ "⚠️ Milestone not yet verified. Run `/gsd-t-verify` first, or use `--force` to complete anyway."
18
18
 
19
19
  If `--force` flag provided, proceed with warning in archive.
20
20
 
@@ -76,7 +76,7 @@ Refer to `.gsd-t/contracts/goal-backward-contract.md` for the full verification
76
76
  {findings table}
77
77
 
78
78
  Options:
79
- 1. Fix the findings and re-run /user:gsd-t-verify
79
+ 1. Fix the findings and re-run /gsd-t-verify
80
80
  2. Override with explicit acknowledgment: re-run this command with --force-goal-backward
81
81
 
82
82
  Proceed with option 1 (recommended) or acknowledge to force completion?
@@ -493,8 +493,8 @@ Summary:
493
493
 
494
494
  Next steps:
495
495
  - Push tags: git push origin v{version}
496
- - Start next milestone: /user:gsd-t-milestone "{next name}"
497
- - Or view roadmap: /user:gsd-t-status
496
+ - Start next milestone: /gsd-t-milestone "{next name}"
497
+ - Or view roadmap: /gsd-t-status
498
498
  ```
499
499
 
500
500
  ## Step 13: Update Roadmap (if exists)
@@ -510,7 +510,7 @@ If `.gsd-t/roadmap.md` exists:
510
510
  "Cannot complete — verification found issues. Address them first or use `--force`."
511
511
 
512
512
  ### If no milestone active:
513
- "No active milestone to complete. Run `/user:gsd-t-status` to see state."
513
+ "No active milestone to complete. Run `/gsd-t-status` to see state."
514
514
 
515
515
  ### If git operations fail:
516
516
  - Still create archive
@@ -400,7 +400,7 @@ If ANY CRITICAL or HIGH deviations were found, automatically prompt the fix work
400
400
  The audit report at `.gsd-t/design-audit-{page-name}-{YYYY-MM-DD}.md`
401
401
  has the exact Figma values for each deviation.
402
402
 
403
- `/user:gsd-t-quick fix all CRITICAL and HIGH deviations from .gsd-t/design-audit-{page-name}-{YYYY-MM-DD}.md — use the Figma values in the report as the source of truth`
403
+ `/gsd-t-quick fix all CRITICAL and HIGH deviations from .gsd-t/design-audit-{page-name}-{YYYY-MM-DD}.md — use the Figma values in the report as the source of truth`
404
404
 
405
405
  ───────────────────────────────────────────────────────────────
406
406
  ```
@@ -414,7 +414,7 @@ If ONLY MEDIUM or LOW deviations remain, show:
414
414
 
415
415
  **{N} MEDIUM + {N} LOW deviations.** These are minor — fix if you want pixel-perfect.
416
416
 
417
- `/user:gsd-t-quick fix MEDIUM and LOW deviations from .gsd-t/design-audit-{page-name}-{YYYY-MM-DD}.md`
417
+ `/gsd-t-quick fix MEDIUM and LOW deviations from .gsd-t/design-audit-{page-name}-{YYYY-MM-DD}.md`
418
418
 
419
419
  ───────────────────────────────────────────────────────────────
420
420
  ```
@@ -427,7 +427,7 @@ After fixes are applied, **re-run the audit automatically** to verify. Loop unti
427
427
 
428
428
  ## Rules
429
429
 
430
- - **You write ZERO code during the audit phase (Steps 1-5).** Report only. Code changes happen in Step 6 via `/user:gsd-t-quick`.
430
+ - **You write ZERO code during the audit phase (Steps 1-5).** Report only. Code changes happen in Step 6 via `/gsd-t-quick`.
431
431
  - **You do NOT "look close" at anything.** Every property gets an exact value from Figma and an exact value from the build. They match or they don't.
432
432
  - **You do NOT skip widgets.** Every widget in the Figma AND every widget in the build gets audited.
433
433
  - **You MUST call `get_design_context` per widget node — NOT `get_screenshot`.** `get_design_context` returns structured code, component properties, and design tokens. `get_screenshot` returns only a visual image that you cannot extract exact values from. Using `get_screenshot` for widget extraction defeats the entire purpose of structured comparison — you end up eyeballing instead of measuring. The ONLY acceptable use of `get_screenshot` is for the built page (Step 2) where you need to see what was actually rendered. For Figma source data, ALWAYS use `get_design_context`.
@@ -40,7 +40,7 @@ Pass any of these as `$ARGUMENTS`:
40
40
  ## Prerequisites
41
41
 
42
42
  - Design contracts must exist in `.gsd-t/contracts/design/` with an `INDEX.md`
43
- - If no contracts exist, run `/user:gsd-t-design-decompose` first
43
+ - If no contracts exist, run `/gsd-t-design-decompose` first
44
44
 
45
45
  ## Why a JS Orchestrator?
46
46
 
@@ -471,7 +471,7 @@ This domain owns the following design contracts:
471
471
  - Pages: (none — pages owned by page-assembly domain)
472
472
  ```
473
473
 
474
- If `.gsd-t/domains/` does NOT exist yet, suggest the user run `/user:gsd-t-partition` next, with a note that design contracts should be partitioned into domains:
474
+ If `.gsd-t/domains/` does NOT exist yet, suggest the user run `/gsd-t-partition` next, with a note that design contracts should be partitioned into domains:
475
475
  - **design-system domain** owns element contracts
476
476
  - **widgets domain** owns widget contracts
477
477
  - **pages domain** owns page assembly + routing
@@ -494,11 +494,11 @@ Display:
494
494
 
495
495
  **Design Build** — build UI from contracts with tiered review gates (elements → widgets → pages)
496
496
 
497
- `/user:gsd-t-design-build`
497
+ `/gsd-t-design-build`
498
498
 
499
499
  **Also available:**
500
- - `/user:gsd-t-partition` — if you need domain boundaries before building
501
- - `/user:gsd-t-plan` — if you need task lists before building
500
+ - `/gsd-t-partition` — if you need domain boundaries before building
501
+ - `/gsd-t-plan` — if you need task lists before building
502
502
 
503
503
  ───────────────────────────────────────────────────────────────
504
504
  ```
@@ -66,7 +66,7 @@ This calls `getSessionStatus()` (v2.0.0) which reads `.gsd-t/.context-meter-stat
66
66
 
67
67
  Use the returned `threshold` as the gate signal for the rest of this run. The gate logic is in Step 3.5; do NOT skip it. If the Context Meter hook isn't installed (`.gsd-t/.context-meter-state.json` missing and doctor reports it), run `gsd-t doctor` to diagnose — the gate still works via the heuristic fallback but real-time readings give much better guardrails.
68
68
 
69
- Why: every `/user:gsd-t-execute` invocation is a fresh orchestrator session and needs a current reading of context utilization before spawning any subagents. The authoritative source is the Context Meter state file; the fallback keeps the gate functional on projects that haven't installed the hook yet.
69
+ Why: every `/gsd-t-execute` invocation is a fresh orchestrator session and needs a current reading of context utilization before spawning any subagents. The authoritative source is the Context Meter state file; the fallback keeps the gate functional on projects that haven't installed the hook yet.
70
70
 
71
71
  ## Step 1: Load State
72
72
 
@@ -1,6 +1,6 @@
1
1
  # GSD-T: Feature — Add a Major Feature to an Existing Project
2
2
 
3
- You are the lead agent planning a significant new feature for an existing codebase. Unlike `/user:gsd-t-project` (greenfield), this command respects and builds on what already exists — existing patterns, schema, auth, conventions, and contracts.
3
+ You are the lead agent planning a significant new feature for an existing codebase. Unlike `/gsd-t-project` (greenfield), this command respects and builds on what already exists — existing patterns, schema, auth, conventions, and contracts.
4
4
 
5
5
  ## Step 0.5: Scan Freshness Auto-Refresh
6
6
 
@@ -154,7 +154,7 @@ The feature may be a single milestone or multiple, depending on scope:
154
154
  ### Single Milestone (if feature is focused):
155
155
  - 2-4 domains, < 15 tasks total
156
156
  - Minimal impact on existing contracts
157
- - Skip roadmap, go straight to: "Run `/user:gsd-t-partition` to begin"
157
+ - Skip roadmap, go straight to: "Run `/gsd-t-partition` to begin"
158
158
 
159
159
  ### Multiple Milestones (if feature is complex):
160
160
  Apply these sequencing rules:
@@ -267,7 +267,7 @@ Present:
267
267
  4. Any conflicts with existing work
268
268
  5. Recommended starting point
269
269
 
270
- Ask: "Ready to start? Run `/user:gsd-t-partition` for Milestone {N}."
270
+ Ask: "Ready to start? Run `/gsd-t-partition` for Milestone {N}."
271
271
 
272
272
  $ARGUMENTS
273
273
 
@@ -224,13 +224,13 @@ Show the recommended groupings and offer promotion paths:
224
224
  ## Recommended Next Steps
225
225
 
226
226
  1. {Milestone name} — {N} gaps ({critical} critical, {high} high)
227
- → /user:gsd-t-milestone "{name}"
227
+ → /gsd-t-milestone "{name}"
228
228
 
229
229
  2. {Feature name} — {N} gaps
230
- → /user:gsd-t-feature "{name}"
230
+ → /gsd-t-feature "{name}"
231
231
 
232
232
  3. Quick fixes — {N} items
233
- → /user:gsd-t-quick "{description}"
233
+ → /gsd-t-quick "{description}"
234
234
 
235
235
  Promote any of these now, or review the gap analysis first?
236
236
  ```
@@ -131,9 +131,9 @@ After repair, re-run the checks and report the final state.
131
131
  ## Step 6: Next Steps
132
132
 
133
133
  If HEALTHY → "✅ GSD-T structure is healthy — all required files present."
134
- If DEGRADED with --repair done → "✅ Repaired {N} missing files. Run /user:gsd-t-health again to confirm."
135
- If DEGRADED without --repair → "⚠ Run /user:gsd-t-health --repair to create {N} missing files."
136
- If BROKEN → "🔴 Project structure is broken. Run /user:gsd-t-health --repair or /user:gsd-t-init to rebuild."
134
+ If DEGRADED with --repair done → "✅ Repaired {N} missing files. Run /gsd-t-health again to confirm."
135
+ If DEGRADED without --repair → "⚠ Run /gsd-t-health --repair to create {N} missing files."
136
+ If BROKEN → "🔴 Project structure is broken. Run /gsd-t-health --repair or /gsd-t-init to rebuild."
137
137
 
138
138
  $ARGUMENTS
139
139
 
@@ -84,8 +84,8 @@ BACKLOG Manual
84
84
  backlog-settings Manage types, apps, categories, and defaults
85
85
 
86
86
  ───────────────────────────────────────────────────────────────────────────────
87
- Type /user:gsd-t-help {command} for detailed help on any command.
88
- Example: /user:gsd-t-help impact
87
+ Type /gsd-t-help {command} for detailed help on any command.
88
+ Example: /gsd-t-help impact
89
89
  ╚══════════════════════════════════════════════════════════════════════════════╝
90
90
  ```
91
91
 
@@ -94,7 +94,7 @@ Example: /user:gsd-t-help impact
94
94
  When user provides a command name, show detailed help:
95
95
 
96
96
  ```
97
- /user:gsd-t-help {command}
97
+ /gsd-t-help {command}
98
98
  ```
99
99
 
100
100
  ### Command Details Format:
@@ -108,7 +108,7 @@ SUMMARY
108
108
  {One-line description}
109
109
 
110
110
  USAGE
111
- /user:gsd-t-{command} [arguments]
111
+ /gsd-t-{command} [arguments]
112
112
 
113
113
  WHEN TO USE
114
114
  • {Use case 1}
@@ -131,8 +131,8 @@ FILES CREATED/UPDATED
131
131
  • {file 2}
132
132
 
133
133
  EXAMPLES
134
- /user:gsd-t-{command}
135
- /user:gsd-t-{command} "with argument"
134
+ /gsd-t-{command}
135
+ /gsd-t-{command} "with argument"
136
136
 
137
137
  RELATED COMMANDS
138
138
  • {related 1} — {why related}
@@ -149,10 +149,10 @@ Use these when user asks for help on a specific command:
149
149
  - **Summary**: Describe what you need in plain language — auto-routes to the right GSD-T command using semantic evaluation
150
150
  - **Auto-invoked**: Yes — via UserPromptSubmit hook when prompt does not start with `/`
151
151
  - **Files**: Reads `CLAUDE.md`, `.gsd-t/progress.md`, command summaries from `gsd-t-help`
152
- - **How it works**: First checks if this is a continuation of an ongoing command (mid-task follow-up, status report, or acknowledgment) — if so, outputs `→ /gsd ──▶ continue /user:gsd-t-{last-command}` and resumes. For new requests, evaluates against every command's purpose and "Use when" criteria. Commands that match get shortlisted, best fit is selected. Shows runner-up when close.
152
+ - **How it works**: First checks if this is a continuation of an ongoing command (mid-task follow-up, status report, or acknowledgment) — if so, outputs `→ /gsd ──▶ continue /gsd-t-{last-command}` and resumes. For new requests, evaluates against every command's purpose and "Use when" criteria. Commands that match get shortlisted, best fit is selected. Shows runner-up when close.
153
153
  - **Auto-route**: After `gsd-t install`, any plain text message (no leading `/`) is automatically routed through `/gsd`. Slash commands pass through unchanged. Binary detection — no heuristics.
154
154
  - **Use when**: You don't want to remember which command to use — just describe what you want
155
- - **Examples**: `/user:gsd Fix the login bug`, `/user:gsd Add dark mode`, `/user:gsd Scan for tech debt`
155
+ - **Examples**: `/gsd Fix the login bug`, `/gsd Add dark mode`, `/gsd Scan for tech debt`
156
156
  - **Auto-route examples**: `Fix the login bug` (no slash needed), `Add dark mode`, `Scan for tech debt`
157
157
 
158
158
  ### prd
@@ -228,7 +228,7 @@ Use these when user asks for help on a specific command:
228
228
  - **Use when**: Ready to define specific implementation tasks
229
229
  - **Note (M22)**: Tasks auto-split if estimated scope exceeds 70% context window — guarantees fresh dispatch works
230
230
  - **Note (M26)**: Pre-mortem step now also reads rules.jsonl for historical failure patterns via getPreMortemRules
231
- - **Note (M38)**: Conversational use cases (formerly `/user:gsd-t-prompt`, `/user:gsd-t-brainstorm`, `/user:gsd-t-discuss`) are now handled by the Smart Router's conversational mode — just describe what you want via `/user:gsd` or plain text.
231
+ - **Note (M38)**: Conversational use cases (formerly `/gsd-t-prompt`, `/gsd-t-brainstorm`, `/gsd-t-discuss`) are now handled by the Smart Router's conversational mode — just describe what you want via `/gsd` or plain text.
232
232
 
233
233
  ### impact
234
234
  - **Summary**: Analyze downstream effects of planned changes
@@ -433,7 +433,7 @@ Did you mean one of these?
433
433
  • {closest match 1}
434
434
  • {closest match 2}
435
435
 
436
- Run /user:gsd-t-help for full command list.
436
+ Run /gsd-t-help for full command list.
437
437
  ```
438
438
 
439
439
  $ARGUMENTS