@tekyzinc/gsd-t 2.30.10 → 2.31.10

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/README.md CHANGED
@@ -94,6 +94,7 @@ This will replace changed command files, back up your CLAUDE.md if customized, a
94
94
  | Command | Purpose | Auto |
95
95
  |---------|---------|------|
96
96
  | `/user:gsd {request}` | Describe what you need → auto-routes to the right command | Manual |
97
+ | _(any plain text)_ | Auto-routed via UserPromptSubmit hook — no leading `/` needed | Auto |
97
98
 
98
99
  ### Help & Onboarding
99
100
 
package/bin/gsd-t.js CHANGED
@@ -456,6 +456,66 @@ function configureUpdateCheckHook(scriptPath) {
456
456
  }
457
457
  }
458
458
 
459
+ // ─── Auto-Route Hook ─────────────────────────────────────────────────────────
460
+
461
+ const AUTO_ROUTE_SCRIPT = "gsd-t-auto-route.js";
462
+
463
+ function installAutoRoute() {
464
+ ensureDir(SCRIPTS_DIR);
465
+
466
+ const src = path.join(PKG_SCRIPTS, AUTO_ROUTE_SCRIPT);
467
+ const dest = path.join(SCRIPTS_DIR, AUTO_ROUTE_SCRIPT);
468
+
469
+ if (!fs.existsSync(src)) {
470
+ warn("Auto-route script not found in package — skipping");
471
+ return;
472
+ }
473
+
474
+ const srcContent = fs.readFileSync(src, "utf8");
475
+ const destContent = fs.existsSync(dest) ? fs.readFileSync(dest, "utf8") : "";
476
+
477
+ if (normalizeEol(srcContent) !== normalizeEol(destContent)) {
478
+ copyFile(src, dest, AUTO_ROUTE_SCRIPT);
479
+ } else {
480
+ info("Auto-route script unchanged");
481
+ }
482
+
483
+ configureAutoRouteHook(dest);
484
+ }
485
+
486
+ function configureAutoRouteHook(scriptPath) {
487
+ const parsed = readSettingsJson();
488
+ if (parsed === null && fs.existsSync(SETTINGS_JSON)) {
489
+ warn("settings.json has invalid JSON — cannot configure auto-route hook");
490
+ return;
491
+ }
492
+ const settings = parsed || {};
493
+ if (!settings.hooks) settings.hooks = {};
494
+ if (!settings.hooks.UserPromptSubmit) settings.hooks.UserPromptSubmit = [];
495
+
496
+ const cmd = `node "${scriptPath.replace(/\\/g, "\\\\")}"`;
497
+ const hasAutoRoute = settings.hooks.UserPromptSubmit.some((entry) =>
498
+ entry.hooks && entry.hooks.some((h) => h.command && h.command.includes(AUTO_ROUTE_SCRIPT))
499
+ );
500
+
501
+ if (hasAutoRoute) {
502
+ info("Auto-route hook already configured");
503
+ return;
504
+ }
505
+
506
+ settings.hooks.UserPromptSubmit.push({
507
+ matcher: "",
508
+ hooks: [{ type: "command", command: cmd }],
509
+ });
510
+
511
+ if (!isSymlink(SETTINGS_JSON)) {
512
+ fs.writeFileSync(SETTINGS_JSON, JSON.stringify(settings, null, 2));
513
+ success("Auto-route hook configured in settings.json");
514
+ } else {
515
+ warn("Skipping settings.json write — target is a symlink");
516
+ }
517
+ }
518
+
459
519
  // ─── Utility Scripts ─────────────────────────────────────────────────────────
460
520
 
461
521
  const UTILITY_SCRIPTS = ["gsd-t-tools.js", "gsd-t-statusline.js"];
@@ -597,6 +657,9 @@ function doInstall(opts = {}) {
597
657
  heading("Update Check (Session Start)");
598
658
  installUpdateCheck();
599
659
 
660
+ heading("Auto-Route (UserPromptSubmit)");
661
+ installAutoRoute();
662
+
600
663
  heading("Utility Scripts");
601
664
  installUtilityScripts();
602
665
  saveInstalledVersion();
@@ -135,11 +135,13 @@ Use these when user asks for help on a specific command:
135
135
 
136
136
  ### gsd (smart router)
137
137
  - **Summary**: Describe what you need in plain language — auto-routes to the right GSD-T command using semantic evaluation
138
- - **Auto-invoked**: No
138
+ - **Auto-invoked**: Yes — via UserPromptSubmit hook when prompt does not start with `/`
139
139
  - **Files**: Reads `CLAUDE.md`, `.gsd-t/progress.md`, command summaries from `gsd-t-help`
140
140
  - **How it works**: Evaluates your request against every command's purpose and "Use when" criteria. Commands that match get shortlisted, best fit is selected. Shows runner-up when close.
141
+ - **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.
141
142
  - **Use when**: You don't want to remember which command to use — just describe what you want
142
143
  - **Examples**: `/user:gsd Fix the login bug`, `/user:gsd Add dark mode`, `/user:gsd Scan for tech debt`
144
+ - **Auto-route examples**: `Fix the login bug` (no slash needed), `Add dark mode`, `Scan for tech debt`
143
145
 
144
146
  ### prompt
145
147
  - **Summary**: Help formulate project/feature/milestone prompts through guided questions
@@ -63,6 +63,7 @@ GSD-T reads all state files and tells you exactly where you left off.
63
63
  | Command | Purpose | Auto |
64
64
  |---------|---------|------|
65
65
  | `/user:gsd {request}` | Describe what you need → auto-routes to the right command | Manual |
66
+ | _(any plain text)_ | Auto-routed via UserPromptSubmit hook — no leading `/` needed | Auto |
66
67
 
67
68
  ### Help & Onboarding
68
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "2.30.10",
3
+ "version": "2.31.10",
4
4
  "description": "GSD-T: Contract-Driven Development for Claude Code — 46 slash commands with backlog management, impact analysis, test sync, milestone archival, and PRD generation",
5
5
  "author": "Tekyz, Inc.",
6
6
  "license": "MIT",
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * GSD-T UserPromptSubmit hook — auto-routes plain text prompts through /gsd.
4
+ *
5
+ * Receives JSON on stdin: { "prompt": "...", "cwd": "...", "session_id": "..." }
6
+ * Outputs to stdout: injected as system context before Claude processes the prompt.
7
+ *
8
+ * Logic:
9
+ * - Prompt starts with "/" → exit silently (user typed a command, pass through)
10
+ * - Prompt is plain text → emit [GSD-T AUTO-ROUTE] signal so Claude routes via /gsd
11
+ */
12
+
13
+ let input = "";
14
+ process.stdin.setEncoding("utf8");
15
+ process.stdin.on("data", (chunk) => { input += chunk; });
16
+ process.stdin.on("end", () => {
17
+ try {
18
+ const data = JSON.parse(input);
19
+ const prompt = (typeof data.prompt === "string" ? data.prompt : "").trimStart();
20
+ if (prompt.startsWith("/")) process.exit(0); // slash command — pass through
21
+ if (!prompt) process.exit(0); // empty prompt — pass through
22
+ // Plain text prompt — inject routing signal
23
+ process.stdout.write(
24
+ "[GSD-T AUTO-ROUTE] The user typed a plain text message (no leading /). " +
25
+ "Route it automatically through the /gsd smart router — execute the /user:gsd " +
26
+ "command with the user's full message as the argument."
27
+ );
28
+ } catch {
29
+ // JSON parse error or any other failure — never block the prompt
30
+ }
31
+ process.exit(0);
32
+ });
@@ -191,6 +191,8 @@ On session start, a version check hook auto-updates GSD-T and outputs a status m
191
191
 
192
192
  Only execute GSD-T workflow behavior when a `/gsd-t-*` command is invoked or when actively mid-phase (resumed via `/gsd-t-resume`). **Plain text messages — especially questions — should be answered conversationally.** Do not launch into workflow execution, file reading, or phase advancement from a question or comment. If the user wants work done, they will invoke a command.
193
193
 
194
+ **Exception — Auto-Route signal**: When `[GSD-T AUTO-ROUTE]` appears in your context (injected by the UserPromptSubmit hook), the user's plain text message should be treated as a `/user:gsd {message}` invocation. Execute the `/gsd` smart router with the user's full message as the argument instead of replying conversationally.
195
+
194
196
  ## Auto-Init Guard
195
197
 
196
198
  Before executing any GSD-T workflow command, check if **any** of these files are missing in the current project: