@tekyzinc/gsd-t 3.23.11 → 3.25.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/CHANGELOG.md +48 -0
- package/README.md +7 -0
- package/bin/cli-preflight-checks/branch-guard.cjs +110 -0
- package/bin/cli-preflight-checks/contracts-stable.cjs +128 -0
- package/bin/cli-preflight-checks/deps-installed.cjs +89 -0
- package/bin/cli-preflight-checks/manifest-fresh.cjs +98 -0
- package/bin/cli-preflight-checks/ports-free.cjs +110 -0
- package/bin/cli-preflight-checks/working-tree-state.cjs +149 -0
- package/bin/cli-preflight.cjs +265 -0
- package/bin/gsd-t-context-brief-kinds/design-verify.cjs +139 -0
- package/bin/gsd-t-context-brief-kinds/execute.cjs +205 -0
- package/bin/gsd-t-context-brief-kinds/qa.cjs +130 -0
- package/bin/gsd-t-context-brief-kinds/red-team.cjs +131 -0
- package/bin/gsd-t-context-brief-kinds/scan.cjs +118 -0
- package/bin/gsd-t-context-brief-kinds/verify.cjs +157 -0
- package/bin/gsd-t-context-brief.cjs +395 -0
- package/bin/gsd-t-ratelimit-probe-worker.cjs +236 -0
- package/bin/gsd-t-ratelimit-probe.cjs +648 -0
- package/bin/gsd-t-verify-gate-judge.cjs +224 -0
- package/bin/gsd-t-verify-gate.cjs +612 -0
- package/bin/gsd-t.js +45 -1
- package/bin/live-activity-report.cjs +615 -0
- package/bin/m55-substrate-proof.cjs +134 -0
- package/bin/parallel-cli-tee.cjs +206 -0
- package/bin/parallel-cli.cjs +478 -0
- package/commands/gsd-t-execute.md +31 -0
- package/commands/gsd-t-help.md +21 -0
- package/commands/gsd-t-verify.md +38 -0
- package/docs/architecture.md +194 -0
- package/docs/diagrams/.gsd-t/.context-meter-state.json +10 -0
- package/docs/diagrams/.gsd-t/context-meter.log +9 -0
- package/docs/diagrams/.gsd-t/events/2026-05-08.jsonl +45 -0
- package/docs/diagrams/.gsd-t/events/2026-05-09.jsonl +1 -0
- package/docs/diagrams/.gsd-t/heartbeat-cd9e7f59-ba5b-406a-9ed6-16762f039e81.jsonl +48 -0
- package/docs/diagrams/01-top-level-map-d2.png +0 -0
- package/docs/diagrams/01-top-level-map.d2 +77 -0
- package/docs/diagrams/01-top-level-map.mmd +48 -0
- package/docs/diagrams/01-top-level-map.png +0 -0
- package/docs/diagrams/01-top-level-map.svg +126 -0
- package/docs/diagrams/02-milestone-lifecycle-d2.png +0 -0
- package/docs/diagrams/02-milestone-lifecycle.d2 +38 -0
- package/docs/diagrams/02-milestone-lifecycle.mmd +36 -0
- package/docs/diagrams/02-milestone-lifecycle.png +0 -0
- package/docs/diagrams/02-milestone-lifecycle.svg +114 -0
- package/docs/diagrams/03-wave-mode-d2.png +0 -0
- package/docs/diagrams/03-wave-mode.d2 +33 -0
- package/docs/diagrams/03-wave-mode.mmd +21 -0
- package/docs/diagrams/03-wave-mode.png +0 -0
- package/docs/diagrams/03-wave-mode.svg +113 -0
- package/docs/diagrams/04-design-to-code-d2.png +0 -0
- package/docs/diagrams/04-design-to-code.d2 +35 -0
- package/docs/diagrams/04-design-to-code.mmd +29 -0
- package/docs/diagrams/04-design-to-code.png +0 -0
- package/docs/diagrams/04-design-to-code.svg +115 -0
- package/docs/diagrams/05-backlog-d2.png +0 -0
- package/docs/diagrams/05-backlog.d2 +40 -0
- package/docs/diagrams/05-backlog.mmd +20 -0
- package/docs/diagrams/05-backlog.png +0 -0
- package/docs/diagrams/05-backlog.svg +113 -0
- package/docs/diagrams/06-automation-utilities-d2.png +0 -0
- package/docs/diagrams/06-automation-utilities.d2 +48 -0
- package/docs/diagrams/06-automation-utilities.mmd +47 -0
- package/docs/diagrams/06-automation-utilities.png +0 -0
- package/docs/diagrams/06-automation-utilities.svg +110 -0
- package/docs/diagrams/_theme.d2 +86 -0
- package/docs/requirements.md +48 -0
- package/docs/workflow-diagram.md +338 -0
- package/package.json +1 -1
- package/scripts/gsd-t-dashboard-server.js +190 -0
- package/scripts/gsd-t-transcript.html +200 -0
- package/templates/CLAUDE-global.md +46 -0
- package/templates/prompts/design-verify-subagent.md +3 -0
- package/templates/prompts/qa-subagent.md +3 -0
- package/templates/prompts/red-team-subagent.md +3 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# GSD-T Workflow Diagram
|
|
2
|
+
|
|
3
|
+
Visual reference for every GSD-T command and how they connect. Generated 2026-05-08, GSD-T v3.24.10.
|
|
4
|
+
|
|
5
|
+
**Visual language** (consistent across all 6 diagrams):
|
|
6
|
+
|
|
7
|
+
| Shape / Color | Role |
|
|
8
|
+
|---|---|
|
|
9
|
+
| 🟦 Blue rectangle | GSD-T command |
|
|
10
|
+
| 🟪 Dashed purple rectangle | Auto-spawned subagent (qa, doc-ripple, debug-loop) |
|
|
11
|
+
| 🟥 Red rectangle | Quality gate (Red Team, Design Verify) |
|
|
12
|
+
| 🟧 Amber diamond | Decision point |
|
|
13
|
+
| 🟫 Pink hexagon | Smart router (`/gsd`) |
|
|
14
|
+
| ⬜ Oval | User input / output endpoint |
|
|
15
|
+
| 🟨 Cylinder | File / artifact |
|
|
16
|
+
| **Solid arrow** | Typical successor / auto-advance |
|
|
17
|
+
| **Dashed arrow** | Optional or conditional path / spawn |
|
|
18
|
+
|
|
19
|
+
The PNGs are rendered from D2 sources alongside each diagram. The Mermaid source is kept below each PNG as a fallback for environments that auto-render Mermaid (GitHub markdown).
|
|
20
|
+
|
|
21
|
+
To regenerate after editing a `.d2` source:
|
|
22
|
+
```sh
|
|
23
|
+
cd docs/diagrams
|
|
24
|
+
d2 --layout=elk --pad=40 NN-name.d2 NN-name.svg
|
|
25
|
+
# Then convert to PNG via headless Chrome (D2's native PNG export needs Playwright)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 1. Top-Level Map — Entry Points → Lifecycle
|
|
31
|
+
|
|
32
|
+

|
|
33
|
+
|
|
34
|
+
```mermaid
|
|
35
|
+
flowchart TD
|
|
36
|
+
USER([User input])
|
|
37
|
+
|
|
38
|
+
USER --> ROUTER{{"/gsd<br/>(smart router)"}}
|
|
39
|
+
|
|
40
|
+
ROUTER -->|"plain text<br/>(auto-route hook)"| ROUTER
|
|
41
|
+
ROUTER -->|continuation| RESUME["/gsd-t-resume"]
|
|
42
|
+
ROUTER -->|conversational| TALK["dialog-only<br/>no spawn"]
|
|
43
|
+
ROUTER -->|workflow| ENTRY{Entry kind?}
|
|
44
|
+
|
|
45
|
+
ENTRY -->|new greenfield| PROJ["/gsd-t-project"]
|
|
46
|
+
ENTRY -->|existing repo onboard| ISS["/gsd-t-init-scan-setup"]
|
|
47
|
+
ENTRY -->|new feature| FEAT["/gsd-t-feature"]
|
|
48
|
+
ENTRY -->|spec vs code| GAP["/gsd-t-gap-analysis"]
|
|
49
|
+
ENTRY -->|small task| QUICK["/gsd-t-quick"]
|
|
50
|
+
ENTRY -->|bug| DEBUG["/gsd-t-debug"]
|
|
51
|
+
ENTRY -->|design-to-code| DD["/gsd-t-design-decompose"]
|
|
52
|
+
ENTRY -->|backlog idea| BADD["/gsd-t-backlog-add"]
|
|
53
|
+
ENTRY -->|status check| STAT["/gsd-t-status"]
|
|
54
|
+
|
|
55
|
+
ISS --> INIT["/gsd-t-init"]
|
|
56
|
+
INIT --> SCAN["/gsd-t-scan"]
|
|
57
|
+
SCAN --> SETUP["/gsd-t-setup"]
|
|
58
|
+
SCAN -.->|techdebt found| PROMO["/gsd-t-promote-debt"]
|
|
59
|
+
|
|
60
|
+
PROJ --> MILE["/gsd-t-milestone"]
|
|
61
|
+
FEAT --> MILE
|
|
62
|
+
GAP -.->|gaps found| MILE
|
|
63
|
+
PROMO --> MILE
|
|
64
|
+
BADD --> BPROMO["/gsd-t-backlog-promote"]
|
|
65
|
+
BPROMO --> MILE
|
|
66
|
+
BPROMO -.->|small| QUICK
|
|
67
|
+
BPROMO -.->|bug| DEBUG
|
|
68
|
+
|
|
69
|
+
MILE --> WAVE_OR_MANUAL{Auto or manual?}
|
|
70
|
+
WAVE_OR_MANUAL -->|hands-off| WAVE["/gsd-t-wave<br/>(full cycle)"]
|
|
71
|
+
WAVE_OR_MANUAL -->|step-by-step| PART["/gsd-t-partition"]
|
|
72
|
+
|
|
73
|
+
DD --> DB["/gsd-t-design-build"]
|
|
74
|
+
DB --> DR["/gsd-t-design-review"]
|
|
75
|
+
DB -.-> DA["/gsd-t-design-audit"]
|
|
76
|
+
|
|
77
|
+
classDef entry fill:#e1f5ff,stroke:#0288d1
|
|
78
|
+
classDef milestone fill:#fff4e1,stroke:#f57c00
|
|
79
|
+
classDef router fill:#f3e5f5,stroke:#7b1fa2
|
|
80
|
+
class PROJ,ISS,FEAT,GAP,QUICK,DEBUG,DD,BADD,STAT entry
|
|
81
|
+
class MILE,WAVE,PART milestone
|
|
82
|
+
class ROUTER,ENTRY,WAVE_OR_MANUAL router
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 2. Milestone Lifecycle — The Core Workflow
|
|
88
|
+
|
|
89
|
+
This is the heart of GSD-T. Every milestone passes through these phases. `/gsd-t-wave` runs them all hands-off; manual mode advances one at a time.
|
|
90
|
+
|
|
91
|
+

|
|
92
|
+
|
|
93
|
+
```mermaid
|
|
94
|
+
flowchart TD
|
|
95
|
+
MILE["/gsd-t-milestone<br/>define deliverable"]
|
|
96
|
+
|
|
97
|
+
MILE --> PART["/gsd-t-partition<br/>milestone → domains + contracts"]
|
|
98
|
+
PART -.->|complex| DISC["conversational mode<br/>(via /gsd)"]
|
|
99
|
+
DISC --> PLAN
|
|
100
|
+
|
|
101
|
+
PART --> PLAN["/gsd-t-plan<br/>atomic task lists per domain"]
|
|
102
|
+
PLAN -.->|risky| IMPACT["/gsd-t-impact<br/>downstream effect analysis"]
|
|
103
|
+
PLAN --> EXEC
|
|
104
|
+
IMPACT --> EXEC["/gsd-t-execute<br/>run tasks (solo or team)"]
|
|
105
|
+
|
|
106
|
+
EXEC -.->|after code| TS["/gsd-t-test-sync<br/>tests ↔ code"]
|
|
107
|
+
EXEC -.->|spawned| QA["/gsd-t-qa<br/>(subagent)"]
|
|
108
|
+
EXEC -.->|spawned| DR2["doc-ripple<br/>(subagent)"]
|
|
109
|
+
EXEC -.->|2 fails| DBGLOOP["headless --debug-loop"]
|
|
110
|
+
|
|
111
|
+
TS --> INTEG["/gsd-t-integrate<br/>wire domains together"]
|
|
112
|
+
INTEG --> VERIFY["/gsd-t-verify<br/>quality gates"]
|
|
113
|
+
|
|
114
|
+
VERIFY --> RT["Red Team<br/>adversarial QA"]
|
|
115
|
+
VERIFY --> DV["Design Verification<br/>(if design contract)"]
|
|
116
|
+
|
|
117
|
+
RT --> CM["/gsd-t-complete-milestone<br/>archive + git tag"]
|
|
118
|
+
DV --> CM
|
|
119
|
+
|
|
120
|
+
CM --> NEXT{More milestones?}
|
|
121
|
+
NEXT -->|yes| MILE
|
|
122
|
+
NEXT -->|no| DONE([Project complete])
|
|
123
|
+
|
|
124
|
+
classDef phase fill:#e8f5e9,stroke:#388e3c
|
|
125
|
+
classDef sub fill:#fff9c4,stroke:#f9a825
|
|
126
|
+
classDef gate fill:#ffebee,stroke:#c62828
|
|
127
|
+
class MILE,PART,PLAN,EXEC,TS,INTEG,VERIFY,CM phase
|
|
128
|
+
class QA,DR2,DBGLOOP,RT,DV,DISC sub
|
|
129
|
+
class IMPACT,NEXT gate
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 3. Wave Mode — Hands-Off Full Cycle
|
|
135
|
+
|
|
136
|
+
`/gsd-t-wave` chains every phase automatically. This is what runs in unattended mode.
|
|
137
|
+
|
|
138
|
+

|
|
139
|
+
|
|
140
|
+
```mermaid
|
|
141
|
+
flowchart LR
|
|
142
|
+
START([wave triggered]) --> P1[partition]
|
|
143
|
+
P1 --> P2[plan]
|
|
144
|
+
P2 --> P3[impact]
|
|
145
|
+
P3 --> P4[execute]
|
|
146
|
+
P4 --> P5[test-sync]
|
|
147
|
+
P5 --> P6[integrate]
|
|
148
|
+
P6 --> P7[verify]
|
|
149
|
+
P7 --> P8[complete-milestone]
|
|
150
|
+
P8 --> END([milestone shipped])
|
|
151
|
+
|
|
152
|
+
P4 -.spawned.-> SUB1[qa]
|
|
153
|
+
P4 -.spawned.-> SUB2[doc-ripple]
|
|
154
|
+
P4 -.parallel.-> PAR[parallel<br/>task dispatch]
|
|
155
|
+
P7 -.gates.-> GATE1[Red Team]
|
|
156
|
+
P7 -.gates.-> GATE2[Design Verify]
|
|
157
|
+
|
|
158
|
+
classDef phase fill:#e8f5e9,stroke:#388e3c
|
|
159
|
+
classDef sub fill:#fff9c4,stroke:#f9a825
|
|
160
|
+
class P1,P2,P3,P4,P5,P6,P7,P8 phase
|
|
161
|
+
class SUB1,SUB2,PAR,GATE1,GATE2 sub
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 4. Design-to-Code Pipeline
|
|
167
|
+
|
|
168
|
+
Triggered when user provides a Figma URL, screenshots, or "build from this design".
|
|
169
|
+
|
|
170
|
+

|
|
171
|
+
|
|
172
|
+
```mermaid
|
|
173
|
+
flowchart TD
|
|
174
|
+
REQ([Design-to-code request])
|
|
175
|
+
|
|
176
|
+
REQ --> CHECK{Existing<br/>contracts?}
|
|
177
|
+
CHECK -->|"start over"| CLEAN[clean UI assets<br/>inline]
|
|
178
|
+
CHECK -->|none| DD
|
|
179
|
+
CHECK -->|present| DB
|
|
180
|
+
|
|
181
|
+
CLEAN --> DD["/gsd-t-design-decompose<br/>elements → widgets → pages"]
|
|
182
|
+
|
|
183
|
+
DD --> DDOUT[".gsd-t/contracts/design/<br/>elements/*.contract.md<br/>widgets/*.contract.md<br/>pages/*.contract.md<br/>INDEX.md"]
|
|
184
|
+
|
|
185
|
+
DDOUT --> DB["/gsd-t-design-build<br/>two-terminal review"]
|
|
186
|
+
|
|
187
|
+
DB --> T1[Term 1<br/>builder]
|
|
188
|
+
DB --> T2["/gsd-t-design-review<br/>Term 2 reviewer"]
|
|
189
|
+
|
|
190
|
+
T1 <-->|review loop| T2
|
|
191
|
+
|
|
192
|
+
T2 --> SHIP{All gates pass?}
|
|
193
|
+
SHIP -->|no| T1
|
|
194
|
+
SHIP -->|yes| DONE([UI shipped])
|
|
195
|
+
|
|
196
|
+
DONE -.optional.-> DA["/gsd-t-design-audit<br/>compare built vs Figma"]
|
|
197
|
+
|
|
198
|
+
classDef pipe fill:#e1f5ff,stroke:#0288d1
|
|
199
|
+
classDef art fill:#f3e5f5,stroke:#7b1fa2
|
|
200
|
+
class DD,DB,T1,T2,DA,CLEAN pipe
|
|
201
|
+
class DDOUT art
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## 5. Backlog Subsystem
|
|
207
|
+
|
|
208
|
+
Lightweight idea capture that feeds into the main workflow.
|
|
209
|
+
|
|
210
|
+

|
|
211
|
+
|
|
212
|
+
```mermaid
|
|
213
|
+
flowchart LR
|
|
214
|
+
IDEA([User has idea]) --> BADD["/gsd-t-backlog-add"]
|
|
215
|
+
BADD --> BL[".gsd-t/backlog.md"]
|
|
216
|
+
|
|
217
|
+
BL --> VIEW["/gsd-t-backlog-list<br/>filtered view"]
|
|
218
|
+
BL --> EDIT["/gsd-t-backlog-edit"]
|
|
219
|
+
BL --> MOVE["/gsd-t-backlog-move<br/>reorder priority"]
|
|
220
|
+
BL --> RM["/gsd-t-backlog-remove"]
|
|
221
|
+
BL --> PROMO["/gsd-t-backlog-promote"]
|
|
222
|
+
|
|
223
|
+
PROMO --> ROUTE{Classify}
|
|
224
|
+
ROUTE -->|big| MILE["/gsd-t-milestone"]
|
|
225
|
+
ROUTE -->|small| QUICK["/gsd-t-quick"]
|
|
226
|
+
ROUTE -->|bug| DEBUG["/gsd-t-debug"]
|
|
227
|
+
ROUTE -->|feature| FEAT["/gsd-t-feature"]
|
|
228
|
+
|
|
229
|
+
SETTINGS["/gsd-t-backlog-settings"] -.configures.-> BADD
|
|
230
|
+
|
|
231
|
+
classDef backlog fill:#fff3e0,stroke:#ef6c00
|
|
232
|
+
class BADD,VIEW,EDIT,MOVE,RM,PROMO,SETTINGS backlog
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 6. Automation, Observability & Utilities
|
|
238
|
+
|
|
239
|
+
Commands that operate alongside the main workflow rather than within it.
|
|
240
|
+
|
|
241
|
+

|
|
242
|
+
|
|
243
|
+
```mermaid
|
|
244
|
+
flowchart TD
|
|
245
|
+
subgraph UNATTENDED [Unattended supervision]
|
|
246
|
+
UN["/gsd-t-unattended<br/>detached supervisor"]
|
|
247
|
+
UNW["/gsd-t-unattended-watch<br/>live status (270s reschedule)"]
|
|
248
|
+
UNS["/gsd-t-unattended-stop<br/>graceful halt"]
|
|
249
|
+
UN -.feeds.-> UNW
|
|
250
|
+
UNS -.signals.-> UN
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
subgraph OBS [Observability]
|
|
254
|
+
VIZ["/gsd-t-visualize<br/>SSE + React Flow"]
|
|
255
|
+
MET["/gsd-t-metrics<br/>ELO + signal dist"]
|
|
256
|
+
STAT["/gsd-t-status<br/>cross-domain progress"]
|
|
257
|
+
HEALTH["/gsd-t-health<br/>validate .gsd-t/"]
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
subgraph SESSION [Session control]
|
|
261
|
+
RES["/gsd-t-resume"]
|
|
262
|
+
PAUSE["/gsd-t-pause"]
|
|
263
|
+
LOG["/gsd-t-log<br/>sync Decision Log"]
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
subgraph MAINT [Maintenance]
|
|
267
|
+
VU["/gsd-t-version-update"]
|
|
268
|
+
VUA["/gsd-t-version-update-all"]
|
|
269
|
+
GC["/gsd-t-global-change"]
|
|
270
|
+
TM["/gsd-t-triage-and-merge"]
|
|
271
|
+
POP["/gsd-t-populate<br/>docs from code"]
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
subgraph HEAD [Headless / CI]
|
|
275
|
+
HEX["headless exec"]
|
|
276
|
+
HQ["headless query"]
|
|
277
|
+
HDL["headless --debug-loop"]
|
|
278
|
+
PAR["parallel<br/>task dispatch"]
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
classDef u fill:#e3f2fd,stroke:#1565c0
|
|
282
|
+
classDef o fill:#f1f8e9,stroke:#558b2f
|
|
283
|
+
classDef s fill:#fce4ec,stroke:#ad1457
|
|
284
|
+
classDef m fill:#ede7f6,stroke:#4527a0
|
|
285
|
+
classDef h fill:#fff8e1,stroke:#ff6f00
|
|
286
|
+
class UN,UNW,UNS u
|
|
287
|
+
class VIZ,MET,STAT,HEALTH o
|
|
288
|
+
class RES,PAUSE,LOG s
|
|
289
|
+
class VU,VUA,GC,TM,POP m
|
|
290
|
+
class HEX,HQ,HDL,PAR h
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 7. Phase Successor Table
|
|
296
|
+
|
|
297
|
+
| Completed phase | Auto-advances to | Also available |
|
|
298
|
+
|-----------------|------------------|----------------|
|
|
299
|
+
| `project` / `feature` | `milestone` | — |
|
|
300
|
+
| `init` / `init-scan-setup` | `scan` / `milestone` | `setup` |
|
|
301
|
+
| `scan` | `promote-debt` | `milestone` |
|
|
302
|
+
| `gap-analysis` | `milestone` | `feature` |
|
|
303
|
+
| `milestone` | `partition` | `wave` (full auto) |
|
|
304
|
+
| `partition` | `plan` | conversational mode (if complex) |
|
|
305
|
+
| `plan` | `execute` | `impact` (if risky) |
|
|
306
|
+
| `impact` | `execute` | — |
|
|
307
|
+
| `execute` | `test-sync` | spawns `qa`, `doc-ripple` |
|
|
308
|
+
| `test-sync` | `verify` | `integrate` (multi-domain) |
|
|
309
|
+
| `integrate` | `verify` | — |
|
|
310
|
+
| `verify` | `complete-milestone` (auto) | spawns Red Team + Design Verify |
|
|
311
|
+
| `complete-milestone` | `status` / next milestone | — |
|
|
312
|
+
| `design-decompose` | `design-build` | `partition` (if domains needed) |
|
|
313
|
+
| `design-build` | (review loop with `design-review`) | `design-audit` |
|
|
314
|
+
|
|
315
|
+
Standalone commands (no successor): `quick`, `debug`, `status`, `help`, `resume`, `pause`, `log`, `health`, `metrics`, `visualize`, all `backlog-*`, `version-update*`, `global-change`, `triage-and-merge`, `populate`, `unattended*`.
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## 8. Auto-Spawned Subagents
|
|
320
|
+
|
|
321
|
+
These never need manual invocation — they fire as part of code-producing phases:
|
|
322
|
+
|
|
323
|
+
| Subagent | Spawned by | Purpose |
|
|
324
|
+
|----------|------------|---------|
|
|
325
|
+
| `qa` | partition, plan, execute, verify, quick, debug, integrate, complete-milestone | Test generation + gap reporting |
|
|
326
|
+
| `doc-ripple` | execute, integrate, quick, debug, wave | Update downstream docs |
|
|
327
|
+
| Red Team | verify (after QA passes) | Adversarial bug-finding |
|
|
328
|
+
| Design Verification | execute Step 5.25, verify (when design contract exists) | Browser-based pixel comparison |
|
|
329
|
+
| `headless --debug-loop` | execute, test-sync, verify, debug, wave (after 2 failed fix attempts) | Compaction-proof fix loop |
|
|
330
|
+
| `parallel` | execute, wave, integrate, quick, debug (when >1 task passes gates) | Task-level parallel dispatch |
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## 9. Source
|
|
335
|
+
|
|
336
|
+
- Canonical command list: `commands/` directory
|
|
337
|
+
- Per-command details: `/gsd-t-help {command}` or [commands/gsd-t-help.md](../commands/gsd-t-help.md)
|
|
338
|
+
- Command summaries section in help file is the source of truth — this diagram is derived from it.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekyzinc/gsd-t",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.10",
|
|
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",
|
|
@@ -699,6 +699,184 @@ function handleParallelismReport(req, res, projectDir) {
|
|
|
699
699
|
res.end(md);
|
|
700
700
|
}
|
|
701
701
|
|
|
702
|
+
// M54 D1 T3 — Live Activity endpoints (additive, read-only)
|
|
703
|
+
// Contract: .gsd-t/contracts/live-activity-contract.md v1.0.0
|
|
704
|
+
// Three endpoints: GET /api/live-activity (5s cache),
|
|
705
|
+
// GET /api/live-activity/<id>/tail (per-id 5s cache, path-traversal guard),
|
|
706
|
+
// GET /api/live-activity/<id>/stream (SSE, uncached, 15s heartbeat).
|
|
707
|
+
|
|
708
|
+
const LIVE_ACTIVITY_CACHE_MS = 5000;
|
|
709
|
+
const _liveActivityCache = { list: { at: 0, body: null }, tail: new Map() };
|
|
710
|
+
|
|
711
|
+
function _loadLiveActivityReporter() {
|
|
712
|
+
try {
|
|
713
|
+
return require(path.join(__dirname, "..", "bin", "live-activity-report.cjs"));
|
|
714
|
+
} catch (err) {
|
|
715
|
+
return { _loadError: err && err.message || String(err) };
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
function isValidActivityId(id) {
|
|
720
|
+
if (typeof id !== "string") return false;
|
|
721
|
+
if (id.length === 0 || id.length > 256) return false;
|
|
722
|
+
if (id.indexOf("..") !== -1) return false;
|
|
723
|
+
if (id.indexOf("/") !== -1) return false;
|
|
724
|
+
if (id.indexOf("\\") !== -1) return false;
|
|
725
|
+
if (id.indexOf("\0") !== -1) return false;
|
|
726
|
+
return true;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
function handleLiveActivity(req, res, projectDir) {
|
|
730
|
+
const now = Date.now();
|
|
731
|
+
const cache = _liveActivityCache.list;
|
|
732
|
+
if (cache.body && (now - cache.at) < LIVE_ACTIVITY_CACHE_MS) {
|
|
733
|
+
res.writeHead(200, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Cache-Control": "no-store", "X-Cache": "hit" });
|
|
734
|
+
res.end(cache.body);
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
const reporter = _loadLiveActivityReporter();
|
|
738
|
+
if (reporter._loadError) {
|
|
739
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
740
|
+
res.end(JSON.stringify({ error: "live-activity-report module unavailable", detail: reporter._loadError }));
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
let result;
|
|
744
|
+
try {
|
|
745
|
+
result = reporter.computeLiveActivities({ projectDir });
|
|
746
|
+
} catch (err) {
|
|
747
|
+
// Contract regression — computeLiveActivities must never throw
|
|
748
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
749
|
+
res.end(JSON.stringify({ error: "computeLiveActivities threw", detail: err && err.message || String(err) }));
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const body = JSON.stringify(result);
|
|
753
|
+
cache.at = now;
|
|
754
|
+
cache.body = body;
|
|
755
|
+
res.writeHead(200, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Cache-Control": "no-store", "X-Cache": "miss" });
|
|
756
|
+
res.end(body);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
function handleLiveActivityTail(req, res, projectDir, id) {
|
|
760
|
+
if (!isValidActivityId(id)) {
|
|
761
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
762
|
+
res.end(JSON.stringify({ error: "invalid_id" }));
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
const cacheKey = projectDir + "\0" + id;
|
|
766
|
+
const now = Date.now();
|
|
767
|
+
const cached = _liveActivityCache.tail.get(cacheKey);
|
|
768
|
+
if (cached && (now - cached.at) < LIVE_ACTIVITY_CACHE_MS) {
|
|
769
|
+
res.writeHead(cached.statusCode, cached.headers);
|
|
770
|
+
res.end(cached.body);
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// Find the activity to determine kind and tail path
|
|
775
|
+
const reporter = _loadLiveActivityReporter();
|
|
776
|
+
if (reporter._loadError) {
|
|
777
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
778
|
+
res.end(JSON.stringify({ error: "live-activity-report module unavailable" }));
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
let result;
|
|
782
|
+
try {
|
|
783
|
+
result = reporter.computeLiveActivities({ projectDir });
|
|
784
|
+
} catch (err) {
|
|
785
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
786
|
+
res.end(JSON.stringify({ error: "computeLiveActivities threw", detail: err && err.message || String(err) }));
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
const activity = result.activities.find((a) => a.id === id);
|
|
791
|
+
if (!activity) {
|
|
792
|
+
const notFound = { statusCode: 404, headers: { "Content-Type": "application/json", "Cache-Control": "no-store" }, body: JSON.stringify({ error: "not_found" }) };
|
|
793
|
+
_liveActivityCache.tail.set(cacheKey, Object.assign({ at: now }, notFound));
|
|
794
|
+
res.writeHead(404, notFound.headers);
|
|
795
|
+
res.end(notFound.body);
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// Read tail content by kind
|
|
800
|
+
let tailContent = "";
|
|
801
|
+
const kind = activity.kind;
|
|
802
|
+
if (kind === "bash" || kind === "spawn") {
|
|
803
|
+
// Last ~64 KB of process stdout — use _readFileTail pattern
|
|
804
|
+
// For bash: the log file path is not directly known without process inspection.
|
|
805
|
+
// Return a JSON snapshot of the activity as a fallback.
|
|
806
|
+
tailContent = JSON.stringify(activity, null, 2);
|
|
807
|
+
} else if (kind === "monitor") {
|
|
808
|
+
tailContent = JSON.stringify(activity, null, 2);
|
|
809
|
+
} else if (kind === "tool") {
|
|
810
|
+
tailContent = JSON.stringify(activity, null, 2);
|
|
811
|
+
} else {
|
|
812
|
+
tailContent = JSON.stringify(activity, null, 2);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
const hit = { statusCode: 200, headers: { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store", "Access-Control-Allow-Origin": "*" }, body: tailContent };
|
|
816
|
+
_liveActivityCache.tail.set(cacheKey, Object.assign({ at: now }, hit));
|
|
817
|
+
res.writeHead(200, hit.headers);
|
|
818
|
+
res.end(hit.body);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
function handleLiveActivityStream(req, res, projectDir, id) {
|
|
822
|
+
if (!isValidActivityId(id)) {
|
|
823
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
824
|
+
res.end(JSON.stringify({ error: "invalid_id" }));
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
res.writeHead(200, Object.assign({}, SSE_HEADERS, { "Access-Control-Allow-Origin": "*", "Cache-Control": "no-store" }));
|
|
828
|
+
|
|
829
|
+
// Send an initial data frame
|
|
830
|
+
res.write("data: " + JSON.stringify({ id, status: "stream_opened" }) + "\n\n");
|
|
831
|
+
|
|
832
|
+
// Heartbeat every 15s
|
|
833
|
+
const heartbeat = setInterval(() => {
|
|
834
|
+
if (!res.writableEnded) {
|
|
835
|
+
res.write(": heartbeat\n\n");
|
|
836
|
+
}
|
|
837
|
+
}, KEEPALIVE_MS);
|
|
838
|
+
|
|
839
|
+
// Poll for activity presence; close stream when activity disappears
|
|
840
|
+
const reporter = _loadLiveActivityReporter();
|
|
841
|
+
const poll = setInterval(() => {
|
|
842
|
+
if (res.writableEnded) {
|
|
843
|
+
clearInterval(poll);
|
|
844
|
+
clearInterval(heartbeat);
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
if (reporter._loadError) {
|
|
848
|
+
clearInterval(poll);
|
|
849
|
+
clearInterval(heartbeat);
|
|
850
|
+
res.write("data: " + JSON.stringify({ id, status: "reporter_unavailable" }) + "\n\n");
|
|
851
|
+
res.end();
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
let result;
|
|
855
|
+
try {
|
|
856
|
+
result = reporter.computeLiveActivities({ projectDir });
|
|
857
|
+
} catch (_) {
|
|
858
|
+
return; // silent — will retry next tick
|
|
859
|
+
}
|
|
860
|
+
const still = result.activities.find((a) => a.id === id);
|
|
861
|
+
if (!still) {
|
|
862
|
+
clearInterval(poll);
|
|
863
|
+
clearInterval(heartbeat);
|
|
864
|
+
if (!res.writableEnded) {
|
|
865
|
+
res.write("data: " + JSON.stringify({ id, status: "activity_ended" }) + "\n\n");
|
|
866
|
+
res.end();
|
|
867
|
+
}
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
// Emit a status frame
|
|
871
|
+
res.write("data: " + JSON.stringify({ id, durationMs: still.durationMs, alive: still.alive }) + "\n\n");
|
|
872
|
+
}, 1000);
|
|
873
|
+
|
|
874
|
+
req.on("close", () => {
|
|
875
|
+
clearInterval(poll);
|
|
876
|
+
clearInterval(heartbeat);
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
|
|
702
880
|
// POST /api/unattended-stop — proxies to the existing stop-sentinel flow so
|
|
703
881
|
// the transcript panel's "Stop Supervisor" button reuses the canonical
|
|
704
882
|
// kill path. Writes `.gsd-t/.unattended/stop` sentinel; supervisor polls
|
|
@@ -887,6 +1065,12 @@ function startServer(port, eventsDir, htmlPath, projectDir, transcriptHtmlPath,
|
|
|
887
1065
|
if (url === "/api/parallelism/report") return handleParallelismReport(req, res, projDir);
|
|
888
1066
|
// M44 D9 — stop-supervisor proxy (POST only; reuses existing sentinel flow)
|
|
889
1067
|
if (url === "/api/unattended-stop") return handleUnattendedStop(req, res, projDir);
|
|
1068
|
+
// M54 D1 T3 — live-activity endpoints (additive, read-only)
|
|
1069
|
+
if (url === "/api/live-activity") return handleLiveActivity(req, res, projDir);
|
|
1070
|
+
const laTailMatch = url.match(/^\/api\/live-activity\/([^/]+)\/tail$/);
|
|
1071
|
+
if (laTailMatch) return handleLiveActivityTail(req, res, projDir, decodeURIComponent(laTailMatch[1]));
|
|
1072
|
+
const laStreamMatch = url.match(/^\/api\/live-activity\/([^/]+)\/stream$/);
|
|
1073
|
+
if (laStreamMatch) return handleLiveActivityStream(req, res, projDir, decodeURIComponent(laStreamMatch[1]));
|
|
890
1074
|
// POST /transcript/:spawnId/kill — SIGTERM the recorded workerPid
|
|
891
1075
|
const killMatch = url.match(/^\/transcript\/([^/]+)\/kill$/);
|
|
892
1076
|
if (killMatch && req.method === "POST") return handleTranscriptKill(req, res, decodeURIComponent(killMatch[1]), projDir);
|
|
@@ -959,6 +1143,12 @@ module.exports = {
|
|
|
959
1143
|
handleParallelism,
|
|
960
1144
|
handleParallelismReport,
|
|
961
1145
|
handleUnattendedStop,
|
|
1146
|
+
// M54 D1 T3 — live-activity observability
|
|
1147
|
+
handleLiveActivity,
|
|
1148
|
+
handleLiveActivityTail,
|
|
1149
|
+
handleLiveActivityStream,
|
|
1150
|
+
isValidActivityId,
|
|
1151
|
+
_liveActivityCache,
|
|
962
1152
|
// M49 — idle-TTL exports for tests
|
|
963
1153
|
_activityTracker,
|
|
964
1154
|
_wrapSseHandler,
|