draht-claude 2026.4.23
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/.claude-plugin/plugin.json +21 -0
- package/CHANGELOG.md +8 -0
- package/LICENSE +22 -0
- package/README.md +199 -0
- package/agents/architect.md +45 -0
- package/agents/debugger.md +57 -0
- package/agents/git-committer.md +52 -0
- package/agents/implementer.md +35 -0
- package/agents/reviewer.md +57 -0
- package/agents/security-auditor.md +109 -0
- package/agents/verifier.md +44 -0
- package/bin/draht-tools.cjs +1067 -0
- package/cli.mjs +348 -0
- package/commands/atomic-commit.md +61 -0
- package/commands/discuss-phase.md +54 -0
- package/commands/execute-phase.md +111 -0
- package/commands/fix.md +50 -0
- package/commands/init-project.md +65 -0
- package/commands/map-codebase.md +52 -0
- package/commands/new-project.md +73 -0
- package/commands/next-milestone.md +49 -0
- package/commands/orchestrate.md +58 -0
- package/commands/pause-work.md +38 -0
- package/commands/plan-phase.md +107 -0
- package/commands/progress.md +30 -0
- package/commands/quick.md +50 -0
- package/commands/resume-work.md +35 -0
- package/commands/review.md +55 -0
- package/commands/verify-work.md +72 -0
- package/hooks/hooks.json +26 -0
- package/package.json +50 -0
- package/scripts/gsd-post-phase.cjs +133 -0
- package/scripts/gsd-post-task.cjs +165 -0
- package/scripts/gsd-pre-execute.cjs +146 -0
- package/scripts/gsd-quality-gate.cjs +252 -0
- package/scripts/prompt-context.cjs +36 -0
- package/scripts/session-start.cjs +52 -0
- package/skills/ddd-workflow/SKILL.md +108 -0
- package/skills/gsd-workflow/SKILL.md +111 -0
- package/skills/tdd-workflow/SKILL.md +115 -0
package/cli.mjs
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* draht-claude CLI — installs this package as a Claude Code plugin via a local marketplace.
|
|
4
|
+
*
|
|
5
|
+
* Architecture:
|
|
6
|
+
* 1. Copy plugin files into a local marketplace at ~/.draht/claude-marketplace/
|
|
7
|
+
* 2. Write marketplace.json listing draht-claude as an available plugin
|
|
8
|
+
* 3. Shell out to `claude plugin marketplace add` and `claude plugin install`
|
|
9
|
+
* 4. Claude Code tracks the plugin in its own registries and enables it
|
|
10
|
+
*
|
|
11
|
+
* The install is reversible via `draht-claude uninstall`.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* npx draht-claude install [--path <dir>] [--force]
|
|
15
|
+
* npx draht-claude uninstall [--path <dir>]
|
|
16
|
+
* npx draht-claude update [--path <dir>]
|
|
17
|
+
* npx draht-claude status [--path <dir>]
|
|
18
|
+
* npx draht-claude --help
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
22
|
+
import * as fs from "node:fs";
|
|
23
|
+
import * as os from "node:os";
|
|
24
|
+
import * as path from "node:path";
|
|
25
|
+
import { fileURLToPath } from "node:url";
|
|
26
|
+
|
|
27
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const PACKAGE_ROOT = __dirname;
|
|
29
|
+
|
|
30
|
+
// Marketplace and plugin names
|
|
31
|
+
const MARKETPLACE_NAME = "draht";
|
|
32
|
+
const PLUGIN_NAME = "draht";
|
|
33
|
+
|
|
34
|
+
// Default location for the local marketplace we generate
|
|
35
|
+
const DEFAULT_MARKETPLACE_DIR = path.join(os.homedir(), ".draht", "claude-marketplace");
|
|
36
|
+
|
|
37
|
+
// Files in the npm package that must NOT be copied into the plugin tree
|
|
38
|
+
const IGNORE = new Set([
|
|
39
|
+
"node_modules",
|
|
40
|
+
"package.json",
|
|
41
|
+
"cli.mjs",
|
|
42
|
+
".npmignore",
|
|
43
|
+
".DS_Store",
|
|
44
|
+
"CHANGELOG.md",
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
// ─── args ───────────────────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
function parseArgs(argv) {
|
|
50
|
+
const args = argv.slice(2);
|
|
51
|
+
const command = args[0];
|
|
52
|
+
const flags = { path: null, force: false, help: false };
|
|
53
|
+
for (let i = 1; i < args.length; i++) {
|
|
54
|
+
const a = args[i];
|
|
55
|
+
if (a === "--path" || a === "-p") {
|
|
56
|
+
flags.path = args[++i];
|
|
57
|
+
} else if (a === "--force" || a === "-f") {
|
|
58
|
+
flags.force = true;
|
|
59
|
+
} else if (a === "--help" || a === "-h") {
|
|
60
|
+
flags.help = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!command || command === "--help" || command === "-h") flags.help = true;
|
|
64
|
+
return { command, flags };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function printHelp() {
|
|
68
|
+
console.log(`draht-claude — install the draht Claude Code plugin
|
|
69
|
+
|
|
70
|
+
Usage:
|
|
71
|
+
npx draht-claude install Install as a Claude Code plugin
|
|
72
|
+
npx draht-claude install --force Reinstall even if already present
|
|
73
|
+
npx draht-claude install --path DIR Custom marketplace directory
|
|
74
|
+
npx draht-claude uninstall Remove the plugin and marketplace
|
|
75
|
+
npx draht-claude update Reinstall (same as install --force)
|
|
76
|
+
npx draht-claude status Show install + enabled state
|
|
77
|
+
|
|
78
|
+
Options:
|
|
79
|
+
-p, --path <dir> Custom local marketplace directory
|
|
80
|
+
-f, --force Overwrite existing install
|
|
81
|
+
-h, --help Show this help
|
|
82
|
+
|
|
83
|
+
What this installs:
|
|
84
|
+
• Local Claude Code marketplace named "${MARKETPLACE_NAME}" at ~/.draht/claude-marketplace/
|
|
85
|
+
• Plugin "${PLUGIN_NAME}" inside that marketplace, registered and enabled
|
|
86
|
+
• 16 slash commands (/new-project, /plan-phase, /execute-phase, /orchestrate, ...)
|
|
87
|
+
• 7 specialist subagents (architect, implementer, reviewer, debugger, ...)
|
|
88
|
+
• 3 workflow skills (gsd-workflow, tdd-workflow, ddd-workflow)
|
|
89
|
+
• Workflow hook scripts (pre-execute, post-task, post-phase, quality-gate)
|
|
90
|
+
• Claude Code lifecycle hooks (SessionStart, UserPromptSubmit)
|
|
91
|
+
• Self-contained draht-tools CLI
|
|
92
|
+
|
|
93
|
+
After install, restart Claude Code. Commands appear in the slash command picker.
|
|
94
|
+
|
|
95
|
+
Docs: https://draht.dev
|
|
96
|
+
`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ─── helpers ────────────────────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
function log(msg) {
|
|
102
|
+
console.log(msg);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function err(msg) {
|
|
106
|
+
console.error(`error: ${msg}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function readPluginManifest() {
|
|
110
|
+
const manifestPath = path.join(PACKAGE_ROOT, ".claude-plugin", "plugin.json");
|
|
111
|
+
if (!fs.existsSync(manifestPath)) {
|
|
112
|
+
err(`Plugin manifest not found at ${manifestPath}`);
|
|
113
|
+
err("This usually means the package was installed incorrectly. Reinstall via 'npx draht-claude@latest install'.");
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function copyRecursive(src, dest) {
|
|
120
|
+
const stat = fs.statSync(src);
|
|
121
|
+
if (stat.isDirectory()) {
|
|
122
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
123
|
+
for (const entry of fs.readdirSync(src)) {
|
|
124
|
+
if (IGNORE.has(entry)) continue;
|
|
125
|
+
copyRecursive(path.join(src, entry), path.join(dest, entry));
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
fs.copyFileSync(src, dest);
|
|
129
|
+
// Preserve executable bit on bin/ and scripts/
|
|
130
|
+
const parentDir = path.basename(path.dirname(src));
|
|
131
|
+
if ((parentDir === "bin" || parentDir === "scripts") && (stat.mode & 0o111) !== 0) {
|
|
132
|
+
fs.chmodSync(dest, 0o755);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function removeRecursive(target) {
|
|
138
|
+
if (!fs.existsSync(target)) return;
|
|
139
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function hasClaudeCli() {
|
|
143
|
+
const which = spawnSync(process.platform === "win32" ? "where" : "which", ["claude"], { encoding: "utf-8" });
|
|
144
|
+
return which.status === 0 && which.stdout.trim().length > 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function runClaude(args, { allowFail = false } = {}) {
|
|
148
|
+
log(` $ claude ${args.join(" ")}`);
|
|
149
|
+
const res = spawnSync("claude", args, { stdio: "inherit" });
|
|
150
|
+
if (res.status !== 0 && !allowFail) {
|
|
151
|
+
err(`claude ${args[0]} ${args[1] || ""} failed with exit code ${res.status}`);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
return res.status === 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function writeMarketplaceManifest(marketplaceDir, pluginManifest) {
|
|
158
|
+
const manifest = {
|
|
159
|
+
$schema: "https://anthropic.com/claude-code/marketplace.schema.json",
|
|
160
|
+
name: MARKETPLACE_NAME,
|
|
161
|
+
description: "Local marketplace for draht-claude. Managed by the draht-claude CLI.",
|
|
162
|
+
owner: {
|
|
163
|
+
name: pluginManifest.author?.name || "draht",
|
|
164
|
+
url: pluginManifest.homepage || "https://draht.dev",
|
|
165
|
+
},
|
|
166
|
+
plugins: [
|
|
167
|
+
{
|
|
168
|
+
name: PLUGIN_NAME,
|
|
169
|
+
description: pluginManifest.description || "Draht GSD, multi-agent, TDD and DDD workflows as a Claude Code plugin",
|
|
170
|
+
source: `./plugins/${PLUGIN_NAME}`,
|
|
171
|
+
category: "workflow",
|
|
172
|
+
homepage: pluginManifest.homepage || "https://draht.dev",
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
};
|
|
176
|
+
const manifestDir = path.join(marketplaceDir, ".claude-plugin");
|
|
177
|
+
fs.mkdirSync(manifestDir, { recursive: true });
|
|
178
|
+
fs.writeFileSync(path.join(manifestDir, "marketplace.json"), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ─── commands ───────────────────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
function cmdInstall(flags) {
|
|
184
|
+
const marketplaceDir = flags.path || DEFAULT_MARKETPLACE_DIR;
|
|
185
|
+
const pluginDir = path.join(marketplaceDir, "plugins", PLUGIN_NAME);
|
|
186
|
+
const manifest = readPluginManifest();
|
|
187
|
+
|
|
188
|
+
log("draht-claude installer");
|
|
189
|
+
log(` plugin: ${manifest.name} v${manifest.version}`);
|
|
190
|
+
log(` source: ${PACKAGE_ROOT}`);
|
|
191
|
+
log(` marketplace: ${marketplaceDir}`);
|
|
192
|
+
log(` plugin dir: ${pluginDir}`);
|
|
193
|
+
log("");
|
|
194
|
+
|
|
195
|
+
// Check prerequisites
|
|
196
|
+
if (!hasClaudeCli()) {
|
|
197
|
+
err("claude CLI not found in PATH");
|
|
198
|
+
err("Install Claude Code first: https://claude.com/claude-code");
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Bail early if already installed and not forcing
|
|
203
|
+
if (fs.existsSync(pluginDir) && !flags.force) {
|
|
204
|
+
err(`plugin already installed at ${pluginDir}`);
|
|
205
|
+
err("use --force to reinstall, or 'draht-claude update' to refresh");
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Copy plugin files into marketplace dir
|
|
210
|
+
log("Copying plugin files...");
|
|
211
|
+
if (flags.force && fs.existsSync(pluginDir)) {
|
|
212
|
+
removeRecursive(pluginDir);
|
|
213
|
+
}
|
|
214
|
+
fs.mkdirSync(pluginDir, { recursive: true });
|
|
215
|
+
copyRecursive(PACKAGE_ROOT, pluginDir);
|
|
216
|
+
|
|
217
|
+
// Write marketplace manifest
|
|
218
|
+
log("Writing marketplace.json...");
|
|
219
|
+
writeMarketplaceManifest(marketplaceDir, manifest);
|
|
220
|
+
|
|
221
|
+
// Validate marketplace + plugin before registering
|
|
222
|
+
log("Validating manifest...");
|
|
223
|
+
runClaude(["plugin", "validate", pluginDir], { allowFail: true });
|
|
224
|
+
|
|
225
|
+
// Add marketplace to Claude Code (idempotent — will error if already added, so allow fail)
|
|
226
|
+
log("Registering marketplace with Claude Code...");
|
|
227
|
+
runClaude(["plugin", "marketplace", "add", marketplaceDir], { allowFail: true });
|
|
228
|
+
|
|
229
|
+
// Update marketplace so Claude Code picks up any changes to our plugin files on reinstall
|
|
230
|
+
runClaude(["plugin", "marketplace", "update", MARKETPLACE_NAME], { allowFail: true });
|
|
231
|
+
|
|
232
|
+
// Install the plugin
|
|
233
|
+
log("Installing plugin...");
|
|
234
|
+
const pluginSpec = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
|
|
235
|
+
runClaude(["plugin", "install", pluginSpec, "--scope", "user"]);
|
|
236
|
+
|
|
237
|
+
// Enable explicitly — install usually enables automatically, but be safe
|
|
238
|
+
runClaude(["plugin", "enable", pluginSpec], { allowFail: true });
|
|
239
|
+
|
|
240
|
+
log("");
|
|
241
|
+
log(`✓ installed ${PLUGIN_NAME}@${MARKETPLACE_NAME} v${manifest.version}`);
|
|
242
|
+
log("");
|
|
243
|
+
log("Next steps:");
|
|
244
|
+
log(" 1. Restart Claude Code so it picks up the plugin");
|
|
245
|
+
log(" 2. Check that commands appear: run `claude plugin list`");
|
|
246
|
+
log(" 3. Try /new-project or /orchestrate inside Claude Code");
|
|
247
|
+
log("");
|
|
248
|
+
log("Docs: https://draht.dev");
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function cmdUninstall(flags) {
|
|
252
|
+
const marketplaceDir = flags.path || DEFAULT_MARKETPLACE_DIR;
|
|
253
|
+
const pluginDir = path.join(marketplaceDir, "plugins", PLUGIN_NAME);
|
|
254
|
+
const pluginSpec = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
|
|
255
|
+
|
|
256
|
+
log("draht-claude uninstaller");
|
|
257
|
+
log(` marketplace: ${marketplaceDir}`);
|
|
258
|
+
log(` plugin: ${pluginSpec}`);
|
|
259
|
+
log("");
|
|
260
|
+
|
|
261
|
+
// Try to uninstall via claude CLI first (removes from settings.json + registries)
|
|
262
|
+
if (hasClaudeCli()) {
|
|
263
|
+
log("Disabling plugin in Claude Code...");
|
|
264
|
+
runClaude(["plugin", "disable", pluginSpec], { allowFail: true });
|
|
265
|
+
log("Uninstalling plugin...");
|
|
266
|
+
runClaude(["plugin", "uninstall", pluginSpec], { allowFail: true });
|
|
267
|
+
log("Removing marketplace...");
|
|
268
|
+
runClaude(["plugin", "marketplace", "remove", MARKETPLACE_NAME], { allowFail: true });
|
|
269
|
+
} else {
|
|
270
|
+
log("(claude CLI not found — skipping registry cleanup)");
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Remove local marketplace files
|
|
274
|
+
if (fs.existsSync(marketplaceDir)) {
|
|
275
|
+
log(`Removing ${marketplaceDir}...`);
|
|
276
|
+
removeRecursive(marketplaceDir);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
log("");
|
|
280
|
+
log("✓ uninstalled");
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function cmdUpdate(flags) {
|
|
284
|
+
cmdInstall({ ...flags, force: true });
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function cmdStatus(flags) {
|
|
288
|
+
const marketplaceDir = flags.path || DEFAULT_MARKETPLACE_DIR;
|
|
289
|
+
const pluginDir = path.join(marketplaceDir, "plugins", PLUGIN_NAME);
|
|
290
|
+
const pluginManifestPath = path.join(pluginDir, ".claude-plugin", "plugin.json");
|
|
291
|
+
|
|
292
|
+
log(`marketplace dir: ${marketplaceDir}`);
|
|
293
|
+
|
|
294
|
+
if (!fs.existsSync(pluginManifestPath)) {
|
|
295
|
+
log("status: not installed");
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
const manifest = JSON.parse(fs.readFileSync(pluginManifestPath, "utf-8"));
|
|
300
|
+
log("status: files present");
|
|
301
|
+
log(`plugin: ${manifest.name} v${manifest.version}`);
|
|
302
|
+
log(`description: ${manifest.description || "(none)"}`);
|
|
303
|
+
} catch (e) {
|
|
304
|
+
log(`status: files present (manifest unreadable: ${e.message})`);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Show claude's view if available
|
|
308
|
+
if (hasClaudeCli()) {
|
|
309
|
+
log("");
|
|
310
|
+
log("Claude Code plugin list:");
|
|
311
|
+
try {
|
|
312
|
+
const out = execSync("claude plugin list", { encoding: "utf-8" });
|
|
313
|
+
process.stdout.write(out);
|
|
314
|
+
} catch {
|
|
315
|
+
log(" (failed to run `claude plugin list`)");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ─── main ───────────────────────────────────────────────────────────────────
|
|
321
|
+
|
|
322
|
+
const { command, flags } = parseArgs(process.argv);
|
|
323
|
+
|
|
324
|
+
if (flags.help) {
|
|
325
|
+
printHelp();
|
|
326
|
+
process.exit(0);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
switch (command) {
|
|
330
|
+
case "install":
|
|
331
|
+
cmdInstall(flags);
|
|
332
|
+
break;
|
|
333
|
+
case "uninstall":
|
|
334
|
+
case "remove":
|
|
335
|
+
cmdUninstall(flags);
|
|
336
|
+
break;
|
|
337
|
+
case "update":
|
|
338
|
+
case "upgrade":
|
|
339
|
+
cmdUpdate(flags);
|
|
340
|
+
break;
|
|
341
|
+
case "status":
|
|
342
|
+
cmdStatus(flags);
|
|
343
|
+
break;
|
|
344
|
+
default:
|
|
345
|
+
err(`unknown command: ${command}`);
|
|
346
|
+
err("run 'draht-claude --help' for usage");
|
|
347
|
+
process.exit(1);
|
|
348
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Analyze uncommitted changes and create atomic conventional commits (one logical change per commit)
|
|
3
|
+
allowed-tools: Bash, Read, Task
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /atomic-commit
|
|
7
|
+
|
|
8
|
+
Analyze changes and create atomic commits.
|
|
9
|
+
|
|
10
|
+
## Atomic Reasoning
|
|
11
|
+
|
|
12
|
+
Before creating commits, decompose changes into atomic reasoning units:
|
|
13
|
+
|
|
14
|
+
**For each file change:**
|
|
15
|
+
1. **State the logical component** — What does this change do? What is its purpose? Does it complete a thought?
|
|
16
|
+
2. **Validate independence** — Can this change be applied independently? Does it depend on other changes? Does it break the build alone?
|
|
17
|
+
3. **Verify correctness** — Is this change logically complete? Does it mix concerns? Should it be split further?
|
|
18
|
+
|
|
19
|
+
**Synthesize commit strategy:**
|
|
20
|
+
- Group changes by logical concern (one commit = one idea)
|
|
21
|
+
- Order commits so each builds successfully
|
|
22
|
+
- Write clear commit messages that explain WHY, not just WHAT
|
|
23
|
+
- Ensure each commit is self-contained and reviewable
|
|
24
|
+
|
|
25
|
+
## Gathering Current State
|
|
26
|
+
|
|
27
|
+
First, gather the current state:
|
|
28
|
+
|
|
29
|
+
1. Run `git status` to see what changed
|
|
30
|
+
2. Run `git diff` to see unstaged changes
|
|
31
|
+
3. Run `git diff --cached` to see staged changes
|
|
32
|
+
|
|
33
|
+
## Strategy
|
|
34
|
+
|
|
35
|
+
Based on the changes, analyze and group them into logical, ATOMIC commits. Each commit should:
|
|
36
|
+
|
|
37
|
+
1. Contain ONE logical change only
|
|
38
|
+
2. Be self-contained and complete
|
|
39
|
+
3. Not break the build if applied independently
|
|
40
|
+
|
|
41
|
+
You may delegate this work to the `git-committer` subagent via the **Task tool** with `subagent_type: "git-committer"` if the change set is large or spans multiple areas. The git-committer will review diffs, group changes, and create commits with conventional commit messages.
|
|
42
|
+
|
|
43
|
+
For each group of changes you identify:
|
|
44
|
+
- List the specific files that belong together
|
|
45
|
+
- Generate a clear, descriptive commit message following conventional commits format
|
|
46
|
+
- Explain WHY these changes belong in one commit
|
|
47
|
+
|
|
48
|
+
Then execute the `git add <specific-files>` and `git commit` commands for each atomic commit in the order they should be applied.
|
|
49
|
+
|
|
50
|
+
Format each commit message as:
|
|
51
|
+
```
|
|
52
|
+
type(scope): brief description
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Common types: feat, fix, refactor, docs, test, chore, style, perf. For strict TDD cycles, also use `red:`, `green:`, `refactor:`.
|
|
56
|
+
|
|
57
|
+
## Rules
|
|
58
|
+
- NEVER use `git add -A` or `git add .` — always stage specific files
|
|
59
|
+
- NEVER use `git commit --no-verify`
|
|
60
|
+
- NEVER force push
|
|
61
|
+
- Review diffs before committing to ensure nothing unexpected is staged
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Capture implementation decisions before planning a phase
|
|
3
|
+
argument-hint: "<phase-number>"
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /discuss-phase
|
|
8
|
+
|
|
9
|
+
Capture implementation decisions before planning a phase.
|
|
10
|
+
|
|
11
|
+
Phase: $1
|
|
12
|
+
|
|
13
|
+
> **Tool note**: Invoke `draht-tools <subcommand>` as `node "${CLAUDE_PLUGIN_ROOT}/bin/draht-tools.cjs" <subcommand>` via the Bash tool.
|
|
14
|
+
|
|
15
|
+
## Atomic Reasoning
|
|
16
|
+
|
|
17
|
+
Before questioning, decompose this phase scope into atomic reasoning units:
|
|
18
|
+
|
|
19
|
+
**For each implementation decision:**
|
|
20
|
+
1. **State the logical component** — What gray area exists? What choice needs to be made? Why does this matter?
|
|
21
|
+
2. **Validate independence** — Can this decision be made independently, or does it depend on other choices? What downstream impacts does it have?
|
|
22
|
+
3. **Verify correctness** — What criteria determine the right answer? What trade-offs exist? What domain terms need clarification?
|
|
23
|
+
|
|
24
|
+
**Synthesize discussion strategy:**
|
|
25
|
+
- Identify critical decisions that block planning
|
|
26
|
+
- Group related decisions (e.g., all API decisions together)
|
|
27
|
+
- Sequence questions from foundational to detailed
|
|
28
|
+
- Ensure domain language is established first
|
|
29
|
+
|
|
30
|
+
## Steps
|
|
31
|
+
1. Run `draht-tools phase-info $1` to load phase context
|
|
32
|
+
2. Identify gray areas based on what's being built
|
|
33
|
+
3. Present 1-2 questions at a time about preferences
|
|
34
|
+
4. If `.planning/DOMAIN.md` exists, load it and validate discovered terms against the glossary. Add any new domain terms found during discussion.
|
|
35
|
+
5. Record decisions with `draht-tools save-context $1`
|
|
36
|
+
6. Commit: `draht-tools commit-docs "capture phase $1 context"`
|
|
37
|
+
|
|
38
|
+
## Workflow
|
|
39
|
+
This is one step in the per-phase cycle. Use fresh sessions (`/clear`) between steps:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
/discuss-phase N → /plan-phase N → /execute-phase N → /verify-work N → /discuss-phase N+1 → ...
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
After completing this command, tell the user to start a fresh session and run `/plan-phase $1`. Do NOT suggest `/next-milestone` — that is only after ALL phases in the milestone are verified.
|
|
46
|
+
|
|
47
|
+
## Gray Area Categories
|
|
48
|
+
- **Visual features** → Layout, density, interactions, empty states
|
|
49
|
+
- **APIs/CLIs** → Response format, error handling, auth
|
|
50
|
+
- **Data models** → Schema, relationships, validation
|
|
51
|
+
- **Content** → Structure, tone, depth, flow
|
|
52
|
+
- **Refactoring** → Grouping, naming, migration strategy
|
|
53
|
+
- **Testability** → What needs testing, test framework preference, coverage goals, integration vs unit boundaries
|
|
54
|
+
- **Domain boundaries** → What are the bounded contexts in play? Are there existing domain terms to respect? What aggregates/entities are involved?
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Execute all plans in a phase with atomic commits (parallel implementer subagents + TDD cycle)
|
|
3
|
+
argument-hint: "<phase-number> [--gaps-only]"
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, Task
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /execute-phase
|
|
8
|
+
|
|
9
|
+
Execute all plans in a phase with atomic commits, parallelizing independent plans via subagents.
|
|
10
|
+
|
|
11
|
+
Phase: $1
|
|
12
|
+
Arguments: $ARGUMENTS
|
|
13
|
+
|
|
14
|
+
> **Tool note**: Invoke `draht-tools <subcommand>` as `node "${CLAUDE_PLUGIN_ROOT}/bin/draht-tools.cjs" <subcommand>`. For subagent delegation, use the **Task tool** with `subagent_type: "implementer"`. Dispatch multiple parallel tasks in a single assistant turn by making multiple Task tool calls at once.
|
|
15
|
+
|
|
16
|
+
## Atomic Reasoning
|
|
17
|
+
|
|
18
|
+
Before executing, decompose this phase execution into atomic reasoning units:
|
|
19
|
+
|
|
20
|
+
**For each plan in the phase:**
|
|
21
|
+
1. **State the logical component** — What is this plan's singular purpose? What observable outcome does it produce?
|
|
22
|
+
2. **Validate independence** — Can this plan execute in parallel with others, or does it depend on their outputs? Which files does it touch?
|
|
23
|
+
3. **Verify correctness** — What tests will prove this plan works? What failure modes exist?
|
|
24
|
+
|
|
25
|
+
**Synthesize execution strategy:**
|
|
26
|
+
- Identify parallel execution groups (plans with no shared files/dependencies)
|
|
27
|
+
- Order dependent plans (plan B depends on plan A's outputs)
|
|
28
|
+
- Map each plan to a subagent task with clear success criteria
|
|
29
|
+
|
|
30
|
+
## Steps
|
|
31
|
+
0. Run the pre-execute check:
|
|
32
|
+
```bash
|
|
33
|
+
node "${CLAUDE_PLUGIN_ROOT}/scripts/gsd-pre-execute.cjs" $1
|
|
34
|
+
```
|
|
35
|
+
If it exits non-zero, STOP and report errors to the user. Do not proceed.
|
|
36
|
+
|
|
37
|
+
1. Run `draht-tools discover-plans $1` to find and order plans
|
|
38
|
+
2. Read each plan file yourself (from `.planning/phases/`) and analyze dependencies to identify which plans can run in parallel vs sequential
|
|
39
|
+
|
|
40
|
+
3. **Delegate execution to subagents via the Task tool:**
|
|
41
|
+
- For **independent plans** (no shared files, no dependency chain): dispatch multiple `Task` tool calls in parallel (single assistant turn), each with `subagent_type: "implementer"`, one per plan.
|
|
42
|
+
- For **dependent plans**: dispatch sequentially — one `Task` call at a time, waiting for the previous to complete before starting the next.
|
|
43
|
+
- Each implementer prompt must include:
|
|
44
|
+
- The full plan content (paste it inline — the subagent cannot run draht-tools)
|
|
45
|
+
- The TDD cycle instructions (see template below)
|
|
46
|
+
- Instructions to commit with `git add <files> && git commit -m "description"`
|
|
47
|
+
|
|
48
|
+
4. After all subagents complete, collect results and check for failures
|
|
49
|
+
5. For each completed task, run the post-task hook (record results + type check + test run):
|
|
50
|
+
```bash
|
|
51
|
+
node "${CLAUDE_PLUGIN_ROOT}/scripts/gsd-post-task.cjs" <phase> <plan> <task-num> <status> <commit-hash>
|
|
52
|
+
```
|
|
53
|
+
6. Run `draht-tools verify-phase $1` yourself (not the subagent)
|
|
54
|
+
7. Run the post-phase hook to generate the phase report:
|
|
55
|
+
```bash
|
|
56
|
+
node "${CLAUDE_PLUGIN_ROOT}/scripts/gsd-post-phase.cjs" $1
|
|
57
|
+
```
|
|
58
|
+
8. Run `draht-tools update-state` yourself
|
|
59
|
+
9. Final commit: `draht-tools commit-docs "complete phase $1 execution"`
|
|
60
|
+
10. Tell the user to start a fresh session (`/clear`) and run `/verify-work $1`
|
|
61
|
+
|
|
62
|
+
## Subagent Task Template
|
|
63
|
+
|
|
64
|
+
Each implementer Task call receives a prompt like:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Execute this plan. Here is the full plan content:
|
|
68
|
+
|
|
69
|
+
<paste full plan XML here>
|
|
70
|
+
|
|
71
|
+
For each <task> in the plan, follow this TDD cycle:
|
|
72
|
+
1. RED — Write failing tests from <test>. Run the test runner, confirm they FAIL. Commit with: git add <test-files> && git commit -m "red: <description>"
|
|
73
|
+
2. GREEN — Write minimal implementation from <action> to make tests pass. Run tests, confirm PASS. Commit with: git add <files> && git commit -m "green: <task name>"
|
|
74
|
+
3. REFACTOR — Apply <refactor> improvements if any. Tests must stay green after each change. Commit with: git add <files> && git commit -m "refactor: <description>"
|
|
75
|
+
4. VERIFY — Run the <verify> step, confirm <done> criteria are met.
|
|
76
|
+
|
|
77
|
+
Domain rules: Use ubiquitous language from .planning/DOMAIN.md (read it). Do not import across bounded context boundaries.
|
|
78
|
+
|
|
79
|
+
Checkpoint handling:
|
|
80
|
+
- type="auto" → execute silently.
|
|
81
|
+
- type="checkpoint:human-verify" → stop and report back what was built.
|
|
82
|
+
- type="checkpoint:decision" → stop and report the options.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Parallelization Rules
|
|
86
|
+
- Plans sharing no files and having no dependency edges can run in parallel
|
|
87
|
+
- If plan B depends on output of plan A, plan B must wait for A to complete
|
|
88
|
+
- If a parallel subagent fails, report which plan failed and continue with independent plans
|
|
89
|
+
|
|
90
|
+
## TDD Rules
|
|
91
|
+
- Never write implementation before a failing test exists
|
|
92
|
+
- If a test passes immediately after being written, it is not testing the right thing — fix it
|
|
93
|
+
- Red → Green → Refactor is not optional; skipping steps invalidates the safety net
|
|
94
|
+
- Each TDD phase gets its own commit so the history is auditable
|
|
95
|
+
|
|
96
|
+
## Domain Rules
|
|
97
|
+
- All identifiers (class names, method names, variables) must use the ubiquitous language from `.planning/DOMAIN.md`
|
|
98
|
+
- Do not import across bounded context boundaries directly — use domain events or ACL adapters
|
|
99
|
+
- If implementation reveals a missing domain term, stop and update DOMAIN.md before continuing
|
|
100
|
+
|
|
101
|
+
## Workflow
|
|
102
|
+
This is one step in the per-phase cycle:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
/discuss-phase N → /plan-phase N → /execute-phase N → /verify-work N
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
After completing this command, tell the user to start a fresh session (`/clear`) and run `/verify-work $1`. Do NOT suggest `/next-milestone`.
|
|
109
|
+
|
|
110
|
+
## Flags
|
|
111
|
+
- `--gaps-only` → only execute FIX-PLAN.md files from failed verification
|
package/commands/fix.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Diagnose and fix a bug with TDD discipline (debugger subagent → reproducing test → minimal fix)
|
|
3
|
+
argument-hint: "<description of what's broken>"
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, Task
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /fix
|
|
8
|
+
|
|
9
|
+
Diagnose and fix a specific bug or failing task with TDD discipline, using a subagent for diagnosis.
|
|
10
|
+
|
|
11
|
+
Issue: $ARGUMENTS
|
|
12
|
+
|
|
13
|
+
> **Tool note**: Invoke `draht-tools <subcommand>` as `node "${CLAUDE_PLUGIN_ROOT}/bin/draht-tools.cjs" <subcommand>`. For subagents, use the **Task tool** with `subagent_type: "debugger"` or `"implementer"`.
|
|
14
|
+
|
|
15
|
+
## Atomic Reasoning
|
|
16
|
+
|
|
17
|
+
Before diagnosing, decompose this bug into atomic reasoning units:
|
|
18
|
+
|
|
19
|
+
1. **State the logical component** — What is the observed failure? What should happen vs what actually happens?
|
|
20
|
+
2. **Validate independence** — Which components/files are involved? Can we isolate the failure? Are there related bugs that should be fixed separately?
|
|
21
|
+
3. **Verify correctness** — What test will reproduce this bug reliably? What would prove it's fixed? What regressions could the fix introduce?
|
|
22
|
+
|
|
23
|
+
**Synthesize fix strategy:**
|
|
24
|
+
- Trace the failure to root cause
|
|
25
|
+
- Write a minimal reproducing test
|
|
26
|
+
- Identify the smallest change that makes the test pass
|
|
27
|
+
- Plan regression checks
|
|
28
|
+
|
|
29
|
+
## Steps
|
|
30
|
+
1. **Diagnose via Task tool** with `subagent_type: "debugger"` and prompt:
|
|
31
|
+
"Diagnose this issue: $ARGUMENTS. Reproduce the bug by running the relevant test or command. Trace the root cause by reading the code. Identify the exact files and lines involved. Do NOT fix it yet — only report the diagnosis with: root cause, affected files, and a recommended fix approach."
|
|
32
|
+
|
|
33
|
+
2. **Write a reproducing test**: Based on the diagnosis, write a test that demonstrates the bug (it must fail)
|
|
34
|
+
- Commit: `git add <test-files> && git commit -m "red: reproduce <bug description>"`
|
|
35
|
+
|
|
36
|
+
3. **Minimal fix**: Write the smallest change that makes the test pass
|
|
37
|
+
- Do not refactor or add features — just fix the bug
|
|
38
|
+
- Run the full test suite to check for regressions
|
|
39
|
+
- Commit: `git add <files> && git commit -m "green: fix <bug description>"`
|
|
40
|
+
|
|
41
|
+
4. **Refactor** (if needed): Clean up without changing behavior
|
|
42
|
+
- Tests must stay green after every change
|
|
43
|
+
- Commit: `git add <files> && git commit -m "refactor: <description>"`
|
|
44
|
+
|
|
45
|
+
5. **Update state**: `draht-tools update-state`
|
|
46
|
+
|
|
47
|
+
## Rules
|
|
48
|
+
- Always reproduce before fixing — a fix without a test is a guess
|
|
49
|
+
- One bug, one fix, one commit series. Do not bundle unrelated changes.
|
|
50
|
+
- If the root cause spans multiple files, explain the chain in the commit message body
|