@tekyzinc/gsd-t 2.16.5 → 2.18.0
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 +16 -0
- package/README.md +4 -3
- package/bin/gsd-t.js +86 -2
- package/commands/gsd-t-help.md +8 -0
- package/commands/gsd-t-log.md +87 -0
- package/docs/GSD-T-README.md +1 -0
- package/package.json +3 -2
- package/scripts/gsd-t-heartbeat.js +156 -0
- package/templates/CLAUDE-global.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to GSD-T are documented here. Updated with each release.
|
|
4
4
|
|
|
5
|
+
## [2.18.0] - 2026-02-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Heartbeat system — real-time event streaming from Claude Code sessions via async hooks
|
|
9
|
+
- `scripts/gsd-t-heartbeat.js` — hook handler that writes JSONL events to `.gsd-t/heartbeat-{session_id}.jsonl`
|
|
10
|
+
- 9 Claude Code hooks: SessionStart, PostToolUse, SubagentStart, SubagentStop, TaskCompleted, TeammateIdle, Notification, Stop, SessionEnd
|
|
11
|
+
- Installer auto-configures heartbeat hooks in settings.json (all async, zero performance impact)
|
|
12
|
+
- Event types: session lifecycle, tool calls with file/command summaries, agent spawn/stop/idle, task completions
|
|
13
|
+
|
|
14
|
+
## [2.17.0] - 2026-02-16
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- `/user:gsd-t-log` command — sync progress.md Decision Log with recent git activity by scanning commits since last logged entry
|
|
18
|
+
- Incremental updates (only new commits) and first-time full reconstruction from git history
|
|
19
|
+
- Total commands: 38 GSD-T + 3 utility = 41
|
|
20
|
+
|
|
5
21
|
## [2.16.5] - 2026-02-16
|
|
6
22
|
|
|
7
23
|
### Added
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ A methodology for reliable, parallelizable development using Claude Code with op
|
|
|
18
18
|
npx @tekyzinc/gsd-t install
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
This installs
|
|
21
|
+
This installs 38 GSD-T commands + 3 utility commands to `~/.claude/commands/` and the global CLAUDE.md to `~/.claude/CLAUDE.md`. Works on Windows, Mac, and Linux.
|
|
22
22
|
|
|
23
23
|
### Start Using It
|
|
24
24
|
|
|
@@ -142,6 +142,7 @@ This will replace changed command files, back up your CLAUDE.md if customized, a
|
|
|
142
142
|
| `/user:gsd-t-resume` | Restore context, continue | Manual |
|
|
143
143
|
| `/user:gsd-t-quick` | Fast task with GSD-T guarantees | Manual |
|
|
144
144
|
| `/user:gsd-t-debug` | Systematic debugging with state | Manual |
|
|
145
|
+
| `/user:gsd-t-log` | Sync progress Decision Log with recent git activity | Manual |
|
|
145
146
|
| `/user:gsd-t-version-update` | Update GSD-T to latest version | Manual |
|
|
146
147
|
| `/user:gsd-t-version-update-all` | Update GSD-T + all registered projects | Manual |
|
|
147
148
|
|
|
@@ -280,8 +281,8 @@ get-stuff-done-teams/
|
|
|
280
281
|
├── LICENSE
|
|
281
282
|
├── bin/
|
|
282
283
|
│ └── gsd-t.js # CLI installer
|
|
283
|
-
├── commands/ #
|
|
284
|
-
│ ├── gsd-t-*.md #
|
|
284
|
+
├── commands/ # 41 slash commands
|
|
285
|
+
│ ├── gsd-t-*.md # 38 GSD-T workflow commands
|
|
285
286
|
│ ├── branch.md # Git branch helper
|
|
286
287
|
│ ├── checkin.md # Auto-version + commit/push helper
|
|
287
288
|
│ └── Claude-md.md # Reload CLAUDE.md directives
|
package/bin/gsd-t.js
CHANGED
|
@@ -24,6 +24,7 @@ const { execSync } = require("child_process");
|
|
|
24
24
|
|
|
25
25
|
const CLAUDE_DIR = path.join(os.homedir(), ".claude");
|
|
26
26
|
const COMMANDS_DIR = path.join(CLAUDE_DIR, "commands");
|
|
27
|
+
const SCRIPTS_DIR = path.join(CLAUDE_DIR, "scripts");
|
|
27
28
|
const GLOBAL_CLAUDE_MD = path.join(CLAUDE_DIR, "CLAUDE.md");
|
|
28
29
|
const SETTINGS_JSON = path.join(CLAUDE_DIR, "settings.json");
|
|
29
30
|
const VERSION_FILE = path.join(CLAUDE_DIR, ".gsd-t-version");
|
|
@@ -33,6 +34,7 @@ const UPDATE_CHECK_FILE = path.join(CLAUDE_DIR, ".gsd-t-update-check");
|
|
|
33
34
|
// Where our package files live (relative to this script)
|
|
34
35
|
const PKG_ROOT = path.resolve(__dirname, "..");
|
|
35
36
|
const PKG_COMMANDS = path.join(PKG_ROOT, "commands");
|
|
37
|
+
const PKG_SCRIPTS = path.join(PKG_ROOT, "scripts");
|
|
36
38
|
const PKG_TEMPLATES = path.join(PKG_ROOT, "templates");
|
|
37
39
|
const PKG_EXAMPLES = path.join(PKG_ROOT, "examples");
|
|
38
40
|
|
|
@@ -144,6 +146,84 @@ function getInstalledCommands() {
|
|
|
144
146
|
}
|
|
145
147
|
}
|
|
146
148
|
|
|
149
|
+
// ─── Heartbeat ──────────────────────────────────────────────────────────────
|
|
150
|
+
|
|
151
|
+
const HEARTBEAT_SCRIPT = "gsd-t-heartbeat.js";
|
|
152
|
+
const HEARTBEAT_HOOKS = [
|
|
153
|
+
"SessionStart", "PostToolUse", "SubagentStart", "SubagentStop",
|
|
154
|
+
"TaskCompleted", "TeammateIdle", "Notification", "Stop", "SessionEnd"
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
function installHeartbeat() {
|
|
158
|
+
ensureDir(SCRIPTS_DIR);
|
|
159
|
+
|
|
160
|
+
// Copy heartbeat script
|
|
161
|
+
const src = path.join(PKG_SCRIPTS, HEARTBEAT_SCRIPT);
|
|
162
|
+
const dest = path.join(SCRIPTS_DIR, HEARTBEAT_SCRIPT);
|
|
163
|
+
|
|
164
|
+
if (!fs.existsSync(src)) {
|
|
165
|
+
warn("Heartbeat script not found in package — skipping");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const srcContent = fs.readFileSync(src, "utf8");
|
|
170
|
+
const destContent = fs.existsSync(dest) ? fs.readFileSync(dest, "utf8") : "";
|
|
171
|
+
|
|
172
|
+
if (srcContent !== destContent) {
|
|
173
|
+
copyFile(src, dest, HEARTBEAT_SCRIPT);
|
|
174
|
+
} else {
|
|
175
|
+
info("Heartbeat script unchanged");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Configure hooks in settings.json
|
|
179
|
+
const hooksAdded = configureHeartbeatHooks(dest);
|
|
180
|
+
if (hooksAdded > 0) {
|
|
181
|
+
success(`${hooksAdded} heartbeat hooks configured in settings.json`);
|
|
182
|
+
} else {
|
|
183
|
+
info("Heartbeat hooks already configured");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function configureHeartbeatHooks(scriptPath) {
|
|
188
|
+
let settings = {};
|
|
189
|
+
if (fs.existsSync(SETTINGS_JSON)) {
|
|
190
|
+
try {
|
|
191
|
+
settings = JSON.parse(fs.readFileSync(SETTINGS_JSON, "utf8"));
|
|
192
|
+
} catch {
|
|
193
|
+
warn("settings.json has invalid JSON — cannot configure hooks");
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!settings.hooks) settings.hooks = {};
|
|
199
|
+
|
|
200
|
+
const cmd = `node "${scriptPath.replace(/\\/g, "\\\\")}"`;
|
|
201
|
+
let added = 0;
|
|
202
|
+
|
|
203
|
+
for (const event of HEARTBEAT_HOOKS) {
|
|
204
|
+
if (!settings.hooks[event]) settings.hooks[event] = [];
|
|
205
|
+
|
|
206
|
+
// Check if heartbeat hook already exists for this event
|
|
207
|
+
const hasHeartbeat = settings.hooks[event].some((entry) =>
|
|
208
|
+
entry.hooks && entry.hooks.some((h) => h.command && h.command.includes(HEARTBEAT_SCRIPT))
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
if (!hasHeartbeat) {
|
|
212
|
+
settings.hooks[event].push({
|
|
213
|
+
matcher: "",
|
|
214
|
+
hooks: [{ type: "command", command: cmd, async: true }],
|
|
215
|
+
});
|
|
216
|
+
added++;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (added > 0) {
|
|
221
|
+
fs.writeFileSync(SETTINGS_JSON, JSON.stringify(settings, null, 2));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return added;
|
|
225
|
+
}
|
|
226
|
+
|
|
147
227
|
// ─── Commands ────────────────────────────────────────────────────────────────
|
|
148
228
|
|
|
149
229
|
function doInstall(opts = {}) {
|
|
@@ -226,10 +306,14 @@ function doInstall(opts = {}) {
|
|
|
226
306
|
copyFile(globalSrc, GLOBAL_CLAUDE_MD, "CLAUDE.md installed → ~/.claude/CLAUDE.md");
|
|
227
307
|
}
|
|
228
308
|
|
|
229
|
-
// 4.
|
|
309
|
+
// 4. Install heartbeat script + hooks
|
|
310
|
+
heading("Heartbeat (Real-time Events)");
|
|
311
|
+
installHeartbeat();
|
|
312
|
+
|
|
313
|
+
// 5. Save version
|
|
230
314
|
saveInstalledVersion();
|
|
231
315
|
|
|
232
|
-
//
|
|
316
|
+
// 6. Summary
|
|
233
317
|
heading("Installation Complete!");
|
|
234
318
|
log("");
|
|
235
319
|
log(` Commands: ${gsdtCommands.length} GSD-T + ${utilityCommands.length} utility commands in ~/.claude/commands/`);
|
package/commands/gsd-t-help.md
CHANGED
|
@@ -52,6 +52,7 @@ UTILITIES Manual
|
|
|
52
52
|
debug Systematic debugging with state
|
|
53
53
|
promote-debt Convert techdebt items to milestones
|
|
54
54
|
populate Auto-populate docs from existing codebase
|
|
55
|
+
log Sync progress Decision Log with recent git activity
|
|
55
56
|
version-update Update GSD-T package to latest version
|
|
56
57
|
version-update-all Update GSD-T package + all registered projects
|
|
57
58
|
|
|
@@ -295,6 +296,13 @@ Use these when user asks for help on a specific command:
|
|
|
295
296
|
- **Updates**: `docs/requirements.md`, `docs/architecture.md`, `docs/workflows.md`, `docs/infrastructure.md`, `.gsd-t/progress.md`
|
|
296
297
|
- **Use when**: You have an existing codebase and want to fill docs with real findings instead of placeholders
|
|
297
298
|
|
|
299
|
+
### log
|
|
300
|
+
- **Summary**: Sync progress.md Decision Log with recent git activity
|
|
301
|
+
- **Auto-invoked**: No
|
|
302
|
+
- **Files**: `.gsd-t/progress.md`, git history
|
|
303
|
+
- **Use when**: Progress.md Decision Log is behind — catches up by scanning git commits since the last logged entry
|
|
304
|
+
- **Features**: Incremental updates, first-time full reconstruction from git history, groups same-day changes
|
|
305
|
+
|
|
298
306
|
### backlog-add
|
|
299
307
|
- **Summary**: Capture a new backlog item with auto-categorization
|
|
300
308
|
- **Auto-invoked**: No
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# GSD-T: Log — Sync Progress Decision Log with Recent Activity
|
|
2
|
+
|
|
3
|
+
Update `.gsd-t/progress.md` Decision Log by scanning git history for commits not yet recorded. Works on any GSD-T project.
|
|
4
|
+
|
|
5
|
+
## Step 1: Load State
|
|
6
|
+
|
|
7
|
+
Read:
|
|
8
|
+
1. `.gsd-t/progress.md` — current Decision Log entries
|
|
9
|
+
2. Note the **last entry's timestamp** — this is the cutoff; only commits after this time need processing
|
|
10
|
+
|
|
11
|
+
If `.gsd-t/progress.md` doesn't exist, inform user: "No GSD-T state found. Run `/user:gsd-t-init` first."
|
|
12
|
+
|
|
13
|
+
## Step 2: Get Recent Commits
|
|
14
|
+
|
|
15
|
+
Run: `git log --reverse --format="%ai|%s" --after="{last entry date}"`
|
|
16
|
+
|
|
17
|
+
If no cutoff exists (empty Decision Log), get the full history:
|
|
18
|
+
`git log --reverse --format="%ai|%s"`
|
|
19
|
+
|
|
20
|
+
## Step 3: Filter and Format
|
|
21
|
+
|
|
22
|
+
For each commit since the last logged entry:
|
|
23
|
+
|
|
24
|
+
1. **Skip** merge commits, whitespace-only changes, and commits already in the Decision Log
|
|
25
|
+
2. **Group** multiple commits on the same day that cover the same logical change into one entry
|
|
26
|
+
3. **Format** each entry:
|
|
27
|
+
```
|
|
28
|
+
- YYYY-MM-DD HH:MM: {commit summary} — {brief context}
|
|
29
|
+
```
|
|
30
|
+
4. If the commit message includes a version tag like `(vX.Y.Z)`, append it to the entry
|
|
31
|
+
|
|
32
|
+
### What to include:
|
|
33
|
+
- Feature additions, bug fixes, refactors
|
|
34
|
+
- Config/dependency changes
|
|
35
|
+
- Documentation updates
|
|
36
|
+
- Version bumps and releases
|
|
37
|
+
- Any commit that modified documents, scripts, or code
|
|
38
|
+
|
|
39
|
+
### What to exclude:
|
|
40
|
+
- Pure merge commits with no additional context
|
|
41
|
+
- Commits that only change whitespace or formatting
|
|
42
|
+
- Entries already in the Decision Log (check by date+content match)
|
|
43
|
+
|
|
44
|
+
## Step 4: Append to Decision Log
|
|
45
|
+
|
|
46
|
+
Append the new entries chronologically at the end of the existing Decision Log section in `.gsd-t/progress.md`.
|
|
47
|
+
|
|
48
|
+
Do NOT modify or rewrite existing entries — only add new ones.
|
|
49
|
+
|
|
50
|
+
## Step 5: Report
|
|
51
|
+
|
|
52
|
+
Show a summary:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Progress Log Updated
|
|
56
|
+
|
|
57
|
+
Commits scanned: {N}
|
|
58
|
+
New entries added: {M}
|
|
59
|
+
Last entry: {date and summary of most recent entry}
|
|
60
|
+
|
|
61
|
+
Decision Log now has {total} entries covering {first date} to {last date}.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If no new commits were found:
|
|
65
|
+
```
|
|
66
|
+
Progress Log — already up to date
|
|
67
|
+
|
|
68
|
+
Last entry: {date and summary}
|
|
69
|
+
No new commits since last log entry.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Step 6: First-Time Reconstruction
|
|
73
|
+
|
|
74
|
+
If the Decision Log is empty or has fewer than 3 entries and git history has 5+ commits, offer full reconstruction:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
The Decision Log appears sparse but this project has {N} commits.
|
|
78
|
+
Reconstructing full history from git...
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Then run the full reconstruction (same as the populate command's git history reconstruction):
|
|
82
|
+
1. Parse all commits
|
|
83
|
+
2. Generate timestamped entries
|
|
84
|
+
3. Group by logical change
|
|
85
|
+
4. Mark reconstructed entries: `(Entries before {date} reconstructed from git history)`
|
|
86
|
+
|
|
87
|
+
$ARGUMENTS
|
package/docs/GSD-T-README.md
CHANGED
|
@@ -111,6 +111,7 @@ GSD-T reads all state files and tells you exactly where you left off.
|
|
|
111
111
|
| `/user:gsd-t-resume` | Restore context, continue | Manual |
|
|
112
112
|
| `/user:gsd-t-quick` | Fast task with GSD-T guarantees | Manual |
|
|
113
113
|
| `/user:gsd-t-debug` | Systematic debugging with state | Manual |
|
|
114
|
+
| `/user:gsd-t-log` | Sync progress Decision Log with recent git activity | Manual |
|
|
114
115
|
| `/user:gsd-t-version-update` | Update GSD-T to latest version | Manual |
|
|
115
116
|
| `/user:gsd-t-version-update-all` | Update GSD-T + all registered projects | Manual |
|
|
116
117
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekyzinc/gsd-t",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "GSD-T: Contract-Driven Development for Claude Code —
|
|
3
|
+
"version": "2.18.0",
|
|
4
|
+
"description": "GSD-T: Contract-Driven Development for Claude Code — 41 slash commands with backlog management, impact analysis, test sync, and milestone archival",
|
|
5
5
|
"author": "Tekyz, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"files": [
|
|
24
24
|
"bin/",
|
|
25
25
|
"commands/",
|
|
26
|
+
"scripts/",
|
|
26
27
|
"templates/",
|
|
27
28
|
"examples/",
|
|
28
29
|
"docs/",
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GSD-T Heartbeat — Claude Code Hook Event Writer
|
|
5
|
+
*
|
|
6
|
+
* Writes structured events to .gsd-t/heartbeat-{session_id}.jsonl
|
|
7
|
+
* Installed as an async hook for multiple Claude Code events.
|
|
8
|
+
*
|
|
9
|
+
* Events captured:
|
|
10
|
+
* SessionStart, PostToolUse, SubagentStart, SubagentStop,
|
|
11
|
+
* TaskCompleted, TeammateIdle, Notification, Stop, SessionEnd
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
const path = require("path");
|
|
16
|
+
|
|
17
|
+
let input = "";
|
|
18
|
+
process.stdin.setEncoding("utf8");
|
|
19
|
+
process.stdin.on("data", (d) => (input += d));
|
|
20
|
+
process.stdin.on("end", () => {
|
|
21
|
+
try {
|
|
22
|
+
const hook = JSON.parse(input);
|
|
23
|
+
const dir = hook.cwd || process.cwd();
|
|
24
|
+
const gsdtDir = path.join(dir, ".gsd-t");
|
|
25
|
+
|
|
26
|
+
if (!fs.existsSync(gsdtDir)) return;
|
|
27
|
+
|
|
28
|
+
const sid = hook.session_id || "unknown";
|
|
29
|
+
const file = path.join(gsdtDir, `heartbeat-${sid}.jsonl`);
|
|
30
|
+
|
|
31
|
+
const event = buildEvent(hook);
|
|
32
|
+
if (event) {
|
|
33
|
+
fs.appendFileSync(file, JSON.stringify(event) + "\n");
|
|
34
|
+
}
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// Silent failure — never interfere with Claude Code
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
function buildEvent(hook) {
|
|
41
|
+
const base = {
|
|
42
|
+
ts: new Date().toISOString(),
|
|
43
|
+
sid: hook.session_id,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
switch (hook.hook_event_name) {
|
|
47
|
+
case "SessionStart":
|
|
48
|
+
return {
|
|
49
|
+
...base,
|
|
50
|
+
evt: "session_start",
|
|
51
|
+
data: { source: hook.source, model: hook.model },
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
case "PostToolUse":
|
|
55
|
+
return {
|
|
56
|
+
...base,
|
|
57
|
+
evt: "tool",
|
|
58
|
+
tool: hook.tool_name,
|
|
59
|
+
data: summarize(hook.tool_name, hook.tool_input),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
case "SubagentStart":
|
|
63
|
+
return {
|
|
64
|
+
...base,
|
|
65
|
+
evt: "agent_spawn",
|
|
66
|
+
data: { agent_id: hook.agent_id, agent_type: hook.agent_type },
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
case "SubagentStop":
|
|
70
|
+
return {
|
|
71
|
+
...base,
|
|
72
|
+
evt: "agent_stop",
|
|
73
|
+
data: { agent_id: hook.agent_id, agent_type: hook.agent_type },
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
case "TaskCompleted":
|
|
77
|
+
return {
|
|
78
|
+
...base,
|
|
79
|
+
evt: "task_done",
|
|
80
|
+
data: { task: hook.task_subject, agent: hook.teammate_name },
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
case "TeammateIdle":
|
|
84
|
+
return {
|
|
85
|
+
...base,
|
|
86
|
+
evt: "agent_idle",
|
|
87
|
+
data: { agent: hook.teammate_name, team: hook.team_name },
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
case "Notification":
|
|
91
|
+
return {
|
|
92
|
+
...base,
|
|
93
|
+
evt: "notification",
|
|
94
|
+
data: { message: hook.message, title: hook.title },
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
case "Stop":
|
|
98
|
+
return { ...base, evt: "session_stop" };
|
|
99
|
+
|
|
100
|
+
case "SessionEnd":
|
|
101
|
+
return {
|
|
102
|
+
...base,
|
|
103
|
+
evt: "session_end",
|
|
104
|
+
data: { reason: hook.reason },
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
default:
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function summarize(tool, input) {
|
|
113
|
+
if (!tool || !input) return {};
|
|
114
|
+
switch (tool) {
|
|
115
|
+
case "Read":
|
|
116
|
+
return { file: shortPath(input.file_path) };
|
|
117
|
+
case "Edit":
|
|
118
|
+
return { file: shortPath(input.file_path) };
|
|
119
|
+
case "Write":
|
|
120
|
+
return { file: shortPath(input.file_path) };
|
|
121
|
+
case "Bash":
|
|
122
|
+
return {
|
|
123
|
+
cmd: (input.command || "").slice(0, 150),
|
|
124
|
+
desc: input.description,
|
|
125
|
+
};
|
|
126
|
+
case "Grep":
|
|
127
|
+
return { pattern: input.pattern, path: shortPath(input.path) };
|
|
128
|
+
case "Glob":
|
|
129
|
+
return { pattern: input.pattern };
|
|
130
|
+
case "Task":
|
|
131
|
+
return { desc: input.description, type: input.subagent_type };
|
|
132
|
+
case "WebSearch":
|
|
133
|
+
return { query: input.query };
|
|
134
|
+
case "WebFetch":
|
|
135
|
+
return { url: input.url };
|
|
136
|
+
case "NotebookEdit":
|
|
137
|
+
return { file: shortPath(input.notebook_path) };
|
|
138
|
+
default:
|
|
139
|
+
return {};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function shortPath(p) {
|
|
144
|
+
if (!p) return null;
|
|
145
|
+
// Convert absolute paths to relative for readability
|
|
146
|
+
const cwd = process.cwd();
|
|
147
|
+
if (p.startsWith(cwd)) {
|
|
148
|
+
return p.slice(cwd.length + 1).replace(/\\/g, "/");
|
|
149
|
+
}
|
|
150
|
+
// For home-dir paths, abbreviate
|
|
151
|
+
const home = require("os").homedir();
|
|
152
|
+
if (p.startsWith(home)) {
|
|
153
|
+
return "~" + p.slice(home.length).replace(/\\/g, "/");
|
|
154
|
+
}
|
|
155
|
+
return p.replace(/\\/g, "/");
|
|
156
|
+
}
|
|
@@ -54,6 +54,7 @@ PROJECT or FEATURE or SCAN
|
|
|
54
54
|
| `/user:gsd-t-debug` | Systematic debugging |
|
|
55
55
|
| `/user:gsd-t-quick` | Fast task, respects contracts |
|
|
56
56
|
| `/user:gsd-t-populate` | Auto-populate docs from existing codebase |
|
|
57
|
+
| `/user:gsd-t-log` | Sync progress Decision Log with recent git activity |
|
|
57
58
|
| `/user:gsd-t-resume` | Restore context, continue |
|
|
58
59
|
| `/user:gsd-t-version-update` | Update GSD-T to latest version |
|
|
59
60
|
| `/user:gsd-t-version-update-all` | Update GSD-T + all registered projects |
|