@tekyzinc/gsd-t 2.34.12 → 2.36.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
@@ -20,7 +20,7 @@ A methodology for reliable, parallelizable development using Claude Code with op
20
20
  npx @tekyzinc/gsd-t install
21
21
  ```
22
22
 
23
- This installs 44 GSD-T commands + 4 utility commands (48 total) to `~/.claude/commands/` and the global CLAUDE.md to `~/.claude/CLAUDE.md`. Works on Windows, Mac, and Linux.
23
+ This installs 44 GSD-T commands + 5 utility commands (49 total) to `~/.claude/commands/` and the global CLAUDE.md to `~/.claude/CLAUDE.md`. Works on Windows, Mac, and Linux.
24
24
 
25
25
  ### Start Using It
26
26
 
@@ -175,6 +175,7 @@ This will replace changed command files, back up your CLAUDE.md if customized, a
175
175
  | `/user:branch` | Create and switch to a new git branch | Manual |
176
176
  | `/user:checkin` | Auto-bump version, stage, commit, and push | Manual |
177
177
  | `/user:Claude-md` | Reload CLAUDE.md directives mid-session | Manual |
178
+ | `/global-change` | Apply file changes across all registered GSD-T projects | Manual |
178
179
 
179
180
  ---
180
181
 
@@ -0,0 +1,205 @@
1
+ # GSD-T: Global Change — Apply Changes Across All GSD-T Projects
2
+
3
+ You are applying a file-level change to every GSD-T project registered in `.claude/.gsd-t-projects`. This is a **global** slash command (installed to `~/.claude/commands/`) that enables bulk updates to project configuration, CLAUDE.md files, templates, and any other files that need to stay consistent across the GSD-T ecosystem.
4
+
5
+ ## Syntax
6
+
7
+ ```
8
+ /global-change <operation> <relative-path/filename> [arguments]
9
+ ```
10
+
11
+ ### Operations
12
+
13
+ | Operation | Arguments | Description |
14
+ |-----------|-----------|-------------|
15
+ | `copy` | `<relative-path/filename>` | Copy file from the GSD-T package directory to the same relative path in all projects |
16
+ | `insert` | `<relative-path/filename> <content>` | Append content to the specified file in all projects |
17
+ | `update` | `<relative-path/filename> <old_content> %%REPLACE_WITH%% <new_content>` | Find `old_content` in the file and replace it with `new_content` in all projects |
18
+ | `delete` | `<relative-path/filename>` | Delete the specified file from all projects |
19
+
20
+ ### Examples
21
+
22
+ ```
23
+ /global-change copy .gsd-t/templates/contract.md
24
+
25
+ /global-change insert .gsd-t/config.json {"newSetting": true}
26
+
27
+ /global-change update CLAUDE.md
28
+ - `model: haiku` — mechanical tasks
29
+ - `model: sonnet` (default) — reasoning tasks
30
+ %%REPLACE_WITH%%
31
+ - `model: haiku` — mechanical tasks (same as now)
32
+ - `model: sonnet` — mid-tier reasoning: routine code changes, standard refactors, test writing, straightforward synthesis
33
+ - `model: opus` — high-stakes reasoning: architecture decisions, security analysis, complex debugging, cross-module refactors, quality judgment on critical paths
34
+
35
+ /global-change delete .gsd-t/deprecated-template.md
36
+ ```
37
+
38
+ ## Step 1: Load the Project Registry
39
+
40
+ Read `~/.claude/.gsd-t-projects`. This file contains one absolute project path per line.
41
+
42
+ ```
43
+ # Example .gsd-t-projects
44
+ C:/Users/david/MyNextListen
45
+ C:/Users/david/TimeTracking
46
+ C:/Users/david/tekyz-ai-copilot
47
+ ```
48
+
49
+ If the file does not exist or is empty:
50
+ - STOP. Tell the user: "No GSD-T projects registered. Register projects by adding their absolute paths (one per line) to `~/.claude/.gsd-t-projects`."
51
+ - Do NOT proceed.
52
+
53
+ Parse the file:
54
+ - Skip blank lines
55
+ - Skip lines starting with `#` (comments)
56
+ - Trim whitespace from each path
57
+ - Store as `PROJECT_PATHS[]`
58
+
59
+ ## Step 2: Parse Arguments
60
+
61
+ Extract from $ARGUMENTS:
62
+ 1. **operation** — first word: `copy`, `insert`, `update`, or `delete`
63
+ 2. **relative-path/filename** — second token: the file path relative to each project root (e.g., `CLAUDE.md`, `.gsd-t/config.json`, `docs/architecture.md`)
64
+ 3. **Remaining arguments** depend on the operation:
65
+ - `copy` — no additional arguments
66
+ - `insert` — everything after the filename is the content to append
67
+ - `update` — everything after the filename is split by the `%%REPLACE_WITH%%` delimiter into **old_content** (before) and **new_content** (after)
68
+ - `delete` — no additional arguments
69
+
70
+ ### Parsing the `update` Delimiter
71
+
72
+ For `update` operations, the content portion (everything after the filename) MUST contain the literal string `%%REPLACE_WITH%%` on its own line. Split on this delimiter:
73
+ - **old_content** = trimmed text before `%%REPLACE_WITH%%` — the exact text to find in the target file
74
+ - **new_content** = trimmed text after `%%REPLACE_WITH%%` — the replacement text
75
+
76
+ If the delimiter is missing, STOP and show the user the correct syntax:
77
+ ```
78
+ Usage: /global-change update <file> <old content> %%REPLACE_WITH%% <new content>
79
+ ```
80
+
81
+ ### Validation Rules
82
+
83
+ - If operation is missing or not one of `copy|insert|update|delete` → STOP, show usage syntax
84
+ - If relative-path/filename is missing → STOP, show usage syntax
85
+ - If operation is `insert` and no content is provided → STOP, tell the user content is required
86
+ - If operation is `update` and `%%REPLACE_WITH%%` delimiter is missing → STOP, show correct syntax
87
+ - If operation is `update` and either old_content or new_content is empty → STOP, both sides of the delimiter are required
88
+ - If operation is `copy` and the source file does not exist in the GSD-T package directory → STOP, tell the user the source file was not found
89
+
90
+ ### Determine GSD-T Package Directory
91
+
92
+ The source directory for `copy` operations is the installed GSD-T package location. Resolve it by checking (in order):
93
+ 1. The directory containing this command file (walk up to the package root)
94
+ 2. `node_modules/@tekyz/gsd-t/` relative to the global npm prefix
95
+ 3. Ask the user if neither resolves
96
+
97
+ ## Step 3: Dry Run — Scan All Projects First
98
+
99
+ Before making any changes, scan every project to preview what will happen. For each project in `PROJECT_PATHS[]`:
100
+
101
+ ### For `copy`:
102
+ - Check if the target file already exists → note "will overwrite" or "will create"
103
+
104
+ ### For `insert`:
105
+ - Check if the target file exists → note "will append to existing" or "will create new file"
106
+
107
+ ### For `update`:
108
+ - Read the target file
109
+ - Search for `old_content` in the file contents
110
+ - If found → note "match found — will replace"
111
+ - If NOT found → note "⚠ NO MATCH — will skip" (do NOT modify files where the old content isn't found)
112
+ - If found multiple times → note "⚠ MULTIPLE MATCHES ([count]) — will replace all occurrences"
113
+
114
+ ### For `delete`:
115
+ - Check if the target file exists → note "will delete" or "will skip (not found)"
116
+
117
+ ### Display the dry run summary:
118
+
119
+ ```
120
+ Global Change — Pre-flight Summary
121
+ Operation: [operation]
122
+ Target: [relative-path/filename]
123
+ Projects: [N] registered
124
+
125
+ [For update — show old/new content preview]
126
+
127
+ Dry run results:
128
+ [status] [project-name] — [description]
129
+ [status] [project-name] — [description]
130
+ ```
131
+
132
+ **Level 3 (Full Auto)**: If ALL projects show clean matches (no warnings), auto-proceed to Step 4 without asking. If ANY project shows a warning (no match, multiple matches), pause and ask.
133
+
134
+ **Level 1-2**: Always pause and ask for confirmation.
135
+
136
+ ## Step 4: Execute Changes
137
+
138
+ For each project that passed the dry run:
139
+
140
+ ### `copy`
141
+ 1. Determine the target: `{PROJECT_PATH}/{relative-path/filename}`
142
+ 2. If the target directory does not exist → create it (including intermediate directories)
143
+ 3. Copy the source file to the target, overwriting if it exists
144
+
145
+ ### `insert`
146
+ 1. Determine the target: `{PROJECT_PATH}/{relative-path/filename}`
147
+ 2. If the target directory does not exist → create it (including intermediate directories)
148
+ 3. If the target file does not exist → create it with the provided content
149
+ 4. If the target file exists → append a newline + the provided content to the end
150
+
151
+ ### `update`
152
+ 1. Determine the target: `{PROJECT_PATH}/{relative-path/filename}`
153
+ 2. If the file does not exist → skip
154
+ 3. Read the file contents
155
+ 4. Search for `old_content` (exact string match, whitespace-sensitive)
156
+ 5. If NOT found → skip
157
+ 6. If found → replace ALL occurrences of `old_content` with `new_content`
158
+ 7. Write the modified contents back to the file
159
+
160
+ ### `delete`
161
+ 1. Determine the target: `{PROJECT_PATH}/{relative-path/filename}`
162
+ 2. If the target file does not exist → skip
163
+ 3. If the target file exists → delete it
164
+ 4. Do NOT delete the parent directory even if empty
165
+
166
+ ### Error Handling
167
+ - On failure, record: `FAILED: {error message}`
168
+ - Never abort the entire run because one project failed — continue to the next
169
+
170
+ ## Step 5: Report Results
171
+
172
+ Display the final summary:
173
+
174
+ ```
175
+ Global Change — Results
176
+ Operation: [operation] [relative-path/filename]
177
+ Succeeded: [N] / [total] projects
178
+ Failed: [N]
179
+ Skipped: [N]
180
+
181
+ [status] [project-name] — [result]
182
+ [status] [project-name] — [result]
183
+ ```
184
+
185
+ Status icons:
186
+ - `✓` — success
187
+ - `⊘` — skipped (file not found, no match, etc.)
188
+ - `✗` — failed with error
189
+
190
+ If there were failures, list them with actionable error messages.
191
+
192
+ ## Notes
193
+
194
+ - **Relative paths use forward slashes** regardless of OS
195
+ - **No glob patterns** — operates on a single file per invocation
196
+ - **Content for `insert`** can be provided inline or pasted in the user's message
197
+ - **Content for `update`** uses the `%%REPLACE_WITH%%` delimiter — old_content match is exact and whitespace-sensitive
198
+ - **Project names in logs** are derived from the last segment of the project path
199
+ - **The `.gsd-t-projects` file** is maintained by `gsd-t init` (auto-registers) and `gsd-t update-all` (reads)
200
+
201
+ $ARGUMENTS
202
+
203
+ ## Auto-Clear
204
+
205
+ All work is committed to project files. Execute `/clear` to free the context window for the next command.
@@ -22,6 +22,14 @@ Read everything:
22
22
 
23
23
  Build a mental model of: "How does this codebase work today?"
24
24
 
25
+ **Multi-Client Architecture Check**: Before moving to Step 2, identify whether the project has or will have multiple consumer surfaces:
26
+ - Look for directories: `web/`, `mobile/`, `app/`, `cli/`, `client/`, `frontend/`
27
+ - Look for split route files: `routes/web.js`, `routes/mobile.js`, `routes/api/v1/`, `routes/api/v2/`
28
+ - Check package.json scripts for `build:web`, `build:mobile`, `start:mobile`, etc.
29
+ - Check `.gsd-t/scan/quality.md` (if exists) for the "Consumer Surfaces Detected" table
30
+
31
+ Note what you find — this informs Step 3's Multi-Consumer Check and Step 4's milestone ordering.
32
+
25
33
  ## Step 2: Understand the Feature
26
34
 
27
35
  From $ARGUMENTS and conversation:
@@ -102,6 +110,14 @@ Produce a combined analysis:
102
110
  - {where this feature could break existing functionality}
103
111
  - {complex integration points}
104
112
  - {performance concerns}
113
+
114
+ ### Multi-Consumer Check
115
+ - Consumer surfaces that exist or will exist after this feature: {list}
116
+ - Does this feature add a new consumer surface? {yes/no}
117
+ - If yes: backend operations this new surface needs: {list}
118
+ - Of those, how many are already implemented for an existing surface? {list any matches}
119
+ - SharedCore extraction candidates (operations needed by 2+ surfaces): {list or "none found"}
120
+ - SharedCore milestone required? {yes — if 2+ candidates found | no — if none}
105
121
  ```
106
122
 
107
123
  ## Step 4: Decompose into Milestones
@@ -121,6 +137,7 @@ Apply these sequencing rules:
121
137
  3. **Existing contract updates early**: If existing contracts change, update and verify them before building new code against them
122
138
  4. **New functionality before integration**: Build the new thing, then wire it into existing flows
123
139
  5. **Migration/backfill as its own milestone**: If existing data needs transformation, isolate that work
140
+ 6. **SharedCore before new consumer surfaces**: If the feature adds a new consumer surface (web, mobile, CLI) AND SharedCore candidates were identified in Step 3's Multi-Consumer Check, add a SharedCore milestone BEFORE the new client's milestone. The SharedCore milestone extracts shared operations into a reusable backend domain — the new client's API calls SharedCore functions, it does not duplicate them.
124
141
 
125
142
  ### Write the Feature Roadmap
126
143
 
@@ -62,6 +62,7 @@ UTILITIES Manual
62
62
  version-update Update GSD-T package to latest version
63
63
  version-update-all Update GSD-T package + all registered projects
64
64
  triage-and-merge Auto-review, merge, and publish GitHub branches
65
+ global-change Apply file changes across all registered GSD-T projects
65
66
 
66
67
  BACKLOG Manual
67
68
  ───────────────────────────────────────────────────────────────────────────────
@@ -347,6 +348,14 @@ Use these when user asks for help on a specific command:
347
348
  - **Use when**: Collaborators have pushed branches and you want to batch-review, merge, and publish without manual per-branch ceremony
348
349
  - **Features**: 3-tier impact scoring (auto-merge / review / skip), publish gate (auto in Level 3, prompted otherwise), conflict detection, sensitive file detection
349
350
 
351
+ ### global-change
352
+ - **Summary**: Apply file changes (copy/insert/update/delete) across all registered GSD-T projects
353
+ - **Auto-invoked**: No
354
+ - **Files**: Reads `~/.claude/.gsd-t-projects`; modifies target file in each registered project
355
+ - **Use when**: You need to make the same change to CLAUDE.md, contracts, templates, or config across multiple projects at once
356
+ - **Operations**: `copy` (file from GSD-T package), `insert` (append content), `update` (find/replace with `%%REPLACE_WITH%%` delimiter), `delete` (remove file)
357
+ - **Features**: Dry run preview, per-project match validation, parallel execution, skip-on-no-match safety
358
+
350
359
  ### backlog-add
351
360
  - **Summary**: Capture a new backlog item with auto-categorization
352
361
  - **Auto-invoked**: No
@@ -8,6 +8,8 @@ Read these files in order:
8
8
  1. `CLAUDE.md` — project conventions and context
9
9
  2. `.gsd-t/progress.md` — current state (if exists)
10
10
  3. `docs/` — all available documentation (requirements, architecture, schema, design)
11
+ 4. `.gsd-t/scan/quality.md` (if exists) — extract the "Consumer Surfaces Detected" and "Shared Service Candidates" tables. These pre-populate Step 1.6 with scan-discovered data and eliminate re-research.
12
+ 5. `.gsd-t/contracts/shared-services-contract.md` (if exists) — a SharedCore domain was previously identified. Its listed operations are pre-confirmed shared and carry forward automatically to Step 1.6.2.
11
13
 
12
14
  If `.gsd-t/` doesn't exist, create the full directory structure:
13
15
  ```
@@ -98,7 +100,11 @@ For each surface that will consume this system, capture:
98
100
 
99
101
  **Surface types**: `web`, `mobile`, `cli`, `external-api`, `admin`, `background-worker`, `other`
100
102
 
101
- If only one surface exists mark "Single consumer SharedCore not needed" and proceed to Step 2.
103
+ **Existing System Check**: This milestone may be adding a NEW surface to a system that already has existing consumer surfaces. Before concluding surface enumeration, scan `.gsd-t/progress.md` completed milestones and look for directories or route files indicating prior client surfaces (`web/`, `mobile/`, `app/`, `cli/`, `client/`, `routes/web.js`, `routes/mobile.js`). Add any discovered existing surfaces to the table above.
104
+
105
+ > ⚠️ **New-client signal**: If this milestone adds a consumer surface to a system that already has one or more other consumer surfaces, SharedCore evaluation is MANDATORY regardless of shared operation count.
106
+
107
+ If only one surface exists and no prior surfaces were found → mark "Single consumer — SharedCore not needed" and proceed to Step 2.
102
108
 
103
109
  ---
104
110
 
@@ -123,7 +129,7 @@ Compare the "Operations Needed" column across all surfaces. Flag every operation
123
129
 
124
130
  ### 1.6.3 — Auto-Suggest SharedCore Domain
125
131
 
126
- **If 3 or more shared operations exist:**
132
+ **If 2 or more shared operations exist, OR if this milestone adds a new consumer surface to a system that already has other surfaces (detected in the Existing System Check above):**
127
133
 
128
134
  > ⚠️ **SharedCore recommended** — {N} operations are needed by {M} consumer surfaces.
129
135
  > A `shared-core` domain will be added to own these functions.
@@ -134,7 +140,7 @@ Add `shared-core` to the domain list before running Step 2. The `shared-core` do
134
140
  - Consumed by: all surface-specific adapter domains
135
141
  - Contract: `shared-services-contract.md` (use the template from `templates/shared-services-contract.md`)
136
142
 
137
- **If fewer than 3 shared operations exist:**
143
+ **If only 1 shared operation exists AND this is not a new-client-to-existing-system scenario:**
138
144
 
139
145
  > ℹ️ {N} shared operations found. Inline sharing is sufficient — no separate SharedCore domain needed. Document shared functions in the relevant domain's constraints.md.
140
146
 
@@ -18,6 +18,13 @@ Read ALL of these:
18
18
 
19
19
  ## Step 2: Create Task Lists Per Domain
20
20
 
21
+ ### SharedCore-First Pre-Check
22
+
23
+ Before writing any domain task lists:
24
+ 1. Does `.gsd-t/contracts/shared-services-contract.md` exist?
25
+ - **YES**: A `shared-core` domain has been identified. Plan its tasks first. All client-surface domains that consume SharedCore operations are BLOCKED BY shared-core until its tasks complete. Use `BLOCKED BY shared-core Task {N}` in the relevant client domain task lists.
26
+ - **NO**: Proceed. The Cross-Domain Duplicate Operation Scan (below) will catch any shared operations missed during partition.
27
+
21
28
  For each domain, write `.gsd-t/domains/{domain-name}/tasks.md`:
22
29
 
23
30
  ```markdown
@@ -81,6 +88,19 @@ For each operation in each domain's task list:
81
88
 
82
89
  > ✅ No duplicate operations detected across domains.
83
90
 
91
+ ### SharedCore Contract Compliance Check
92
+
93
+ If `.gsd-t/contracts/shared-services-contract.md` exists, run a second pass:
94
+
95
+ For each client-surface domain's task list, compare task operations against the SharedCore contract's "Shared Operations" table. Flag any task that implements an operation already owned by SharedCore:
96
+
97
+ > ⚠️ **SharedCore contract violation** — the following tasks reimplement operations owned by SharedCore:
98
+ > - {domain} Task {N}: implements `{operation}` — already owned by SharedCore per shared-services-contract.md
99
+ >
100
+ > Fix: Change these tasks to CALL the SharedCore function rather than implementing it independently.
101
+
102
+ If no violations: `✅ All client domains reference SharedCore correctly.`
103
+
84
104
  ---
85
105
 
86
106
  ### REQ Traceability
@@ -122,6 +122,7 @@ GSD-T reads all state files and tells you exactly where you left off.
122
122
  | `/user:gsd-t-version-update` | Update GSD-T to latest version | Manual |
123
123
  | `/user:gsd-t-version-update-all` | Update GSD-T + all registered projects | Manual |
124
124
  | `/user:gsd-t-triage-and-merge` | Auto-review, merge, and publish GitHub branches | Manual |
125
+ | `/global-change` | Apply file changes (copy/insert/update/delete) across all GSD-T projects | Manual |
125
126
 
126
127
  ### Backlog Management
127
128
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "2.34.12",
3
+ "version": "2.36.10",
4
4
  "description": "GSD-T: Contract-Driven Development for Claude Code — 48 slash commands with real-time agent dashboard, execution intelligence, backlog management, impact analysis, test sync, milestone archival, and PRD generation",
5
5
  "author": "Tekyz, Inc.",
6
6
  "license": "MIT",
@@ -23,43 +23,33 @@ body{background:var(--bg);color:var(--text);font-family:var(--font);font-size:12
23
23
  font-size:10px;border:1px solid;}
24
24
  .status.live{background:var(--green-bg);border-color:var(--green);color:var(--green);}
25
25
  .status.wait{background:var(--yellow-bg);border-color:var(--yellow);color:var(--yellow);}
26
- .dot{width:6px;height:6px;border-radius:50%;background:currentColor;
27
- animation:pdot 1.5s ease-in-out infinite;}
26
+ .dot{width:6px;height:6px;border-radius:50%;background:currentColor;animation:pdot 1.5s ease-in-out infinite;}
28
27
  @keyframes pdot{0%,100%{opacity:1}50%{opacity:.3}}
29
- .hright{margin-left:auto;color:var(--muted);font-size:11px;}
30
- .main{display:flex;flex:1;overflow:hidden;}
31
- .garea{flex:1;position:relative;background:var(--bg);}
32
- .rfwrap{width:100%;height:100%;}
33
- .react-flow__background{background:var(--bg);}
34
- .react-flow__node{font-family:var(--font);font-size:11px;}
28
+ .hright{margin-left:auto;color:var(--muted);font-size:11px;}.main{display:flex;flex:1;overflow:hidden;}
29
+ .garea{flex:1;position:relative;background:var(--bg);}.rfwrap{width:100%;height:100%;}
30
+ .react-flow__background{background:var(--bg);}.react-flow__node{font-family:var(--font);font-size:11px;}
35
31
  .agent-node{background:var(--surface);border:1px solid var(--border);border-radius:6px;
36
32
  padding:8px 12px;min-width:120px;text-align:center;}
37
- .agent-node.success{border-color:var(--green);background:var(--green-bg);}
38
- .agent-node.failure{border-color:var(--red);background:var(--red-bg);}
39
- .agent-node.learning,.agent-node.deferred{border-color:var(--yellow);background:var(--yellow-bg);}
40
- .agent-node.session{border-color:var(--blue);background:var(--blue-bg);}
41
- .node-id{color:var(--text);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:140px;}
42
- .node-cnt{color:var(--muted);font-size:9px;margin-top:2px;}
33
+ .agent-node.success{border-color:var(--green);background:var(--green-bg);}.agent-node.failure{border-color:var(--red);background:var(--red-bg);}
34
+ .agent-node.learning,.agent-node.deferred{border-color:var(--yellow);background:var(--yellow-bg);}.agent-node.session{border-color:var(--blue);background:var(--blue-bg);}
35
+ .node-id{color:var(--text);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:140px;}.node-cnt{color:var(--muted);font-size:9px;margin-top:2px;}
43
36
  .sidebar{width:300px;background:var(--surface);border-left:1px solid var(--border);
44
37
  display:flex;flex-direction:column;overflow:hidden;}
45
38
  .sb-hdr{padding:10px 12px;border-bottom:1px solid var(--border);color:var(--muted);
46
39
  font-size:10px;text-transform:uppercase;letter-spacing:.8px;flex-shrink:0;}
47
- .feed{flex:1;overflow-y:auto;padding:8px;}
48
- .feed::-webkit-scrollbar{width:4px;}
49
- .feed::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px;}
40
+ .feed{flex:1;overflow-y:auto;padding:8px;}.feed::-webkit-scrollbar{width:4px;}.feed::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px;}
50
41
  .ev{border-radius:4px;padding:6px 8px;margin-bottom:5px;border-left:3px solid var(--border);
51
42
  background:#1c2128;}
52
- .ev.success{border-left-color:var(--green);}
53
- .ev.failure{border-left-color:var(--red);}
54
- .ev.learning,.ev.deferred{border-left-color:var(--yellow);}
55
- .ev-type{font-weight:500;color:var(--text);font-size:11px;}
56
- .ev-cmd{color:var(--blue);font-size:10px;margin-top:1px;}
57
- .ev-ts{color:var(--muted);font-size:9px;margin-top:2px;}
43
+ .ev.success{border-left-color:var(--green);}.ev.failure{border-left-color:var(--red);}.ev.learning,.ev.deferred{border-left-color:var(--yellow);}
44
+ .ev-type{font-weight:500;color:var(--text);font-size:11px;}.ev-cmd{color:var(--blue);font-size:10px;margin-top:1px;}.ev-ts{color:var(--muted);font-size:9px;margin-top:2px;}
58
45
  .badge{display:inline-block;font-size:9px;padding:1px 5px;border-radius:3px;font-weight:bold;margin-left:4px;}
59
- .badge.success{background:var(--green-bg);color:var(--green);}
60
- .badge.failure{background:var(--red-bg);color:var(--red);}
61
- .badge.learning,.badge.deferred{background:var(--yellow-bg);color:var(--yellow);}
46
+ .badge.success{background:var(--green-bg);color:var(--green);}.badge.failure{background:var(--red-bg);color:var(--red);}.badge.learning,.badge.deferred{background:var(--yellow-bg);color:var(--yellow);}
62
47
  .noevents{color:var(--muted);font-size:11px;padding:12px;text-align:center;}
48
+ .models{padding:8px 12px;border-bottom:1px solid var(--border);flex-shrink:0;}
49
+ .model-row{display:flex;align-items:center;gap:8px;margin-bottom:4px;font-size:11px;}
50
+ .model-name{width:50px;color:var(--text);font-weight:500;}.model-bar-bg{flex:1;height:8px;background:var(--bg);border-radius:4px;overflow:hidden;}
51
+ .model-bar{height:100%;border-radius:4px;transition:width .3s ease;}.model-bar.opus{background:var(--blue);}.model-bar.sonnet{background:var(--green);}.model-bar.haiku{background:var(--yellow);}
52
+ .model-cnt{color:var(--muted);font-size:10px;min-width:20px;text-align:right;}
63
53
  </style>
64
54
  </head>
65
55
  <body>
@@ -71,6 +61,8 @@ body{background:var(--bg);color:var(--text);font-family:var(--font);font-size:12
71
61
  <div class="main">
72
62
  <div class="garea"><div id="rf-root" class="rfwrap"></div></div>
73
63
  <div class="sidebar">
64
+ <div class="sb-hdr">Models Invoked</div>
65
+ <div id="models" class="models"><div class="noevents">No model data yet</div></div>
74
66
  <div class="sb-hdr">Live Event Feed</div>
75
67
  <div id="feed" class="feed"><div class="noevents">Waiting for events...</div></div>
76
68
  </div>
@@ -109,12 +101,16 @@ function Dashboard(){
109
101
  const [edges,setEdges,onEdgesChange]=useEdgesState([]);
110
102
  const [events,setEvents]=useState([]);
111
103
  const agentMap=useRef({});
104
+ const modelCounts=useRef({});
112
105
 
113
106
  const processEvent=useCallback((ev)=>{
114
107
  setEvents(prev=>{
115
108
  const next=[ev,...prev];
116
109
  return next.length>MAX_EVENTS?next.slice(0,MAX_EVENTS):next;
117
110
  });
111
+ const m=ev.model||(ev.event_type==='session_start'&&ev.reasoning?ev.reasoning.match(/opus|sonnet|haiku/i):null);
112
+ const mName=m?(typeof m==='string'?m:m[0]).toLowerCase():null;
113
+ if(mName){modelCounts.current[mName]=(modelCounts.current[mName]||0)+1;}
118
114
  if(!ev.agent_id)return;
119
115
  const id=ev.agent_id;
120
116
  const prev=agentMap.current[id]||{count:0,outcome:null,parent:null,nodeType:null,firstTs:null};
@@ -167,14 +163,18 @@ function Dashboard(){
167
163
 
168
164
  useEffect(()=>{
169
165
  document.getElementById('ev-count').textContent=`${events.length} event${events.length!==1?'s':''}`;
166
+ const mp=document.getElementById('models'),mc=modelCounts.current,mEntries=Object.entries(mc).sort((a,b)=>b[1]-a[1]);
167
+ if(mEntries.length){const maxC=Math.max(...mEntries.map(e=>e[1]));
168
+ mp.innerHTML=mEntries.map(([n,c])=>`<div class="model-row"><span class="model-name">${n}</span><div class="model-bar-bg"><div class="model-bar ${n}" style="width:${Math.round((c/maxC)*100)}%"></div></div><span class="model-cnt">${c}</span></div>`).join('');}
170
169
  const feed=document.getElementById('feed');
171
170
  if(!events.length){feed.innerHTML='<div class="noevents">Waiting for events...</div>';return;}
172
171
  feed.innerHTML=events.slice(0,50).map(ev=>{
173
172
  const oc=outcomeClass(ev.outcome);
174
173
  const ts=ev.ts?new Date(ev.ts).toLocaleTimeString():'';
175
174
  const cmd=ev.command||ev.phase||'';
175
+ const evModel=ev.model||null;
176
176
  return`<div class="ev${oc?' '+oc:''}">
177
- <div class="ev-type">${ev.event_type||'event'}${oc?`<span class="badge ${oc}">${ev.outcome}</span>`:''}</div>
177
+ <div class="ev-type">${ev.event_type||'event'}${evModel?` <span style="color:var(--muted);font-size:9px">[${evModel}]</span>`:''}${oc?`<span class="badge ${oc}">${ev.outcome}</span>`:''}</div>
178
178
  ${cmd?`<div class="ev-cmd">${cmd}</div>`:''}
179
179
  ${ev.reasoning?`<div class="ev-ts" style="color:var(--muted)">${ev.reasoning.slice(0,60)}</div>`:''}
180
180
  <div class="ev-ts">${ts}</div>
@@ -78,6 +78,7 @@ function buildEvent(args) {
78
78
  trace_id: nullify(args["trace-id"]),
79
79
  reasoning: nullify(args["reasoning"]),
80
80
  outcome: nullify(args["outcome"]),
81
+ model: nullify(args["model"]),
81
82
  };
82
83
  }
83
84
 
@@ -76,6 +76,7 @@ PROJECT or FEATURE or SCAN
76
76
  | `/user:branch` | Create and switch to a new git branch |
77
77
  | `/user:checkin` | Auto-bump version, stage, commit, and push |
78
78
  | `/user:Claude-md` | Reload and apply CLAUDE.md directives |
79
+ | `/global-change` | Apply file changes across all registered GSD-T projects |
79
80
 
80
81
 
81
82
  # Living Documents
@@ -252,6 +253,13 @@ Report: pass/fail counts and any coverage gaps."
252
253
 
253
254
  **QA failure blocks phase completion.** Lead cannot proceed until QA reports PASS or user explicitly overrides.
254
255
 
256
+ ## Model Display (MANDATORY)
257
+
258
+ **Before every subagent spawn, display the model being used to the user:**
259
+ `⚙ [{model}] {command} → {brief description}` (e.g., `⚙ [sonnet] gsd-t-execute → domain: auth-service`, `⚙ [haiku] gsd-t-execute → QA validation`)
260
+
261
+ This gives the user real-time visibility into which model is handling each operation.
262
+
255
263
  ## API Documentation Guard (Swagger/OpenAPI)
256
264
 
257
265
  **Every API endpoint MUST be documented in a Swagger/OpenAPI spec. No exceptions.**