specdacular 0.1.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/agents/specd-codebase-mapper.md +731 -0
- package/bin/install.js +356 -0
- package/commands/specd/help.md +50 -0
- package/commands/specd/map-codebase.md +69 -0
- package/package.json +35 -0
- package/specdacular/workflows/map-codebase.md +285 -0
package/bin/install.js
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const readline = require('readline');
|
|
7
|
+
|
|
8
|
+
// Colors
|
|
9
|
+
const cyan = '\x1b[36m';
|
|
10
|
+
const green = '\x1b[32m';
|
|
11
|
+
const yellow = '\x1b[33m';
|
|
12
|
+
const dim = '\x1b[2m';
|
|
13
|
+
const reset = '\x1b[0m';
|
|
14
|
+
|
|
15
|
+
// Get version from package.json
|
|
16
|
+
const pkg = require('../package.json');
|
|
17
|
+
|
|
18
|
+
// Parse args
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
const hasGlobal = args.includes('--global') || args.includes('-g');
|
|
21
|
+
const hasLocal = args.includes('--local') || args.includes('-l');
|
|
22
|
+
const hasUninstall = args.includes('--uninstall') || args.includes('-u');
|
|
23
|
+
const hasHelp = args.includes('--help') || args.includes('-h');
|
|
24
|
+
|
|
25
|
+
const banner = '\n' +
|
|
26
|
+
cyan + ' ███████╗██████╗ ███████╗ ██████╗\n' +
|
|
27
|
+
' ██╔════╝██╔══██╗██╔════╝██╔════╝\n' +
|
|
28
|
+
' ███████╗██████╔╝█████╗ ██║ \n' +
|
|
29
|
+
' ╚════██║██╔═══╝ ██╔══╝ ██║ \n' +
|
|
30
|
+
' ███████║██║ ███████╗╚██████╗\n' +
|
|
31
|
+
' ╚══════╝╚═╝ ╚══════╝ ╚═════╝' + reset + '\n' +
|
|
32
|
+
'\n' +
|
|
33
|
+
' Specdacular ' + dim + 'v' + pkg.version + reset + '\n' +
|
|
34
|
+
' Feature planning for existing codebases.\n';
|
|
35
|
+
|
|
36
|
+
console.log(banner);
|
|
37
|
+
|
|
38
|
+
// Show help if requested
|
|
39
|
+
if (hasHelp) {
|
|
40
|
+
console.log(` ${yellow}Usage:${reset} npx specdacular [options]\n
|
|
41
|
+
${yellow}Options:${reset}
|
|
42
|
+
${cyan}-g, --global${reset} Install globally (to ~/.claude/)
|
|
43
|
+
${cyan}-l, --local${reset} Install locally (to ./.claude/)
|
|
44
|
+
${cyan}-u, --uninstall${reset} Uninstall specdacular
|
|
45
|
+
${cyan}-h, --help${reset} Show this help message
|
|
46
|
+
|
|
47
|
+
${yellow}Examples:${reset}
|
|
48
|
+
${dim}# Interactive install${reset}
|
|
49
|
+
npx specdacular
|
|
50
|
+
|
|
51
|
+
${dim}# Install globally${reset}
|
|
52
|
+
npx specdacular --global
|
|
53
|
+
|
|
54
|
+
${dim}# Install to current project only${reset}
|
|
55
|
+
npx specdacular --local
|
|
56
|
+
|
|
57
|
+
${dim}# Uninstall${reset}
|
|
58
|
+
npx specdacular --global --uninstall
|
|
59
|
+
`);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get the global config directory
|
|
65
|
+
*/
|
|
66
|
+
function getGlobalDir() {
|
|
67
|
+
if (process.env.CLAUDE_CONFIG_DIR) {
|
|
68
|
+
return expandTilde(process.env.CLAUDE_CONFIG_DIR);
|
|
69
|
+
}
|
|
70
|
+
return path.join(os.homedir(), '.claude');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Expand ~ to home directory
|
|
75
|
+
*/
|
|
76
|
+
function expandTilde(filePath) {
|
|
77
|
+
if (filePath && filePath.startsWith('~/')) {
|
|
78
|
+
return path.join(os.homedir(), filePath.slice(2));
|
|
79
|
+
}
|
|
80
|
+
return filePath;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Read and parse settings.json
|
|
85
|
+
*/
|
|
86
|
+
function readSettings(settingsPath) {
|
|
87
|
+
if (fs.existsSync(settingsPath)) {
|
|
88
|
+
try {
|
|
89
|
+
return JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
90
|
+
} catch (e) {
|
|
91
|
+
return {};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Write settings.json with proper formatting
|
|
99
|
+
*/
|
|
100
|
+
function writeSettings(settingsPath, settings) {
|
|
101
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Recursively copy directory with path replacement in .md files
|
|
106
|
+
*/
|
|
107
|
+
function copyWithPathReplacement(srcDir, destDir, pathPrefix) {
|
|
108
|
+
if (fs.existsSync(destDir)) {
|
|
109
|
+
fs.rmSync(destDir, { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
112
|
+
|
|
113
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
114
|
+
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
117
|
+
const destPath = path.join(destDir, entry.name);
|
|
118
|
+
|
|
119
|
+
if (entry.isDirectory()) {
|
|
120
|
+
copyWithPathReplacement(srcPath, destPath, pathPrefix);
|
|
121
|
+
} else if (entry.name.endsWith('.md')) {
|
|
122
|
+
let content = fs.readFileSync(srcPath, 'utf8');
|
|
123
|
+
// Replace path references
|
|
124
|
+
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
125
|
+
fs.writeFileSync(destPath, content);
|
|
126
|
+
} else {
|
|
127
|
+
fs.copyFileSync(srcPath, destPath);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Verify a directory exists and contains files
|
|
134
|
+
*/
|
|
135
|
+
function verifyInstalled(dirPath, description) {
|
|
136
|
+
if (!fs.existsSync(dirPath)) {
|
|
137
|
+
console.error(` ${yellow}✗${reset} Failed to install ${description}`);
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
const entries = fs.readdirSync(dirPath);
|
|
142
|
+
if (entries.length === 0) {
|
|
143
|
+
console.error(` ${yellow}✗${reset} Failed to install ${description}: empty`);
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
} catch (e) {
|
|
147
|
+
console.error(` ${yellow}✗${reset} Failed to install ${description}: ${e.message}`);
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Uninstall specdacular
|
|
155
|
+
*/
|
|
156
|
+
function uninstall(isGlobal) {
|
|
157
|
+
const targetDir = isGlobal ? getGlobalDir() : path.join(process.cwd(), '.claude');
|
|
158
|
+
const locationLabel = isGlobal ? targetDir.replace(os.homedir(), '~') : './.claude';
|
|
159
|
+
|
|
160
|
+
console.log(` Uninstalling from ${cyan}${locationLabel}${reset}\n`);
|
|
161
|
+
|
|
162
|
+
if (!fs.existsSync(targetDir)) {
|
|
163
|
+
console.log(` ${yellow}⚠${reset} Directory does not exist: ${locationLabel}`);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let removedCount = 0;
|
|
168
|
+
|
|
169
|
+
// Remove specd commands
|
|
170
|
+
const specCommandsDir = path.join(targetDir, 'commands', 'specd');
|
|
171
|
+
if (fs.existsSync(specCommandsDir)) {
|
|
172
|
+
fs.rmSync(specCommandsDir, { recursive: true });
|
|
173
|
+
removedCount++;
|
|
174
|
+
console.log(` ${green}✓${reset} Removed commands/specd/`);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Remove specdacular directory
|
|
178
|
+
const specDir = path.join(targetDir, 'specdacular');
|
|
179
|
+
if (fs.existsSync(specDir)) {
|
|
180
|
+
fs.rmSync(specDir, { recursive: true });
|
|
181
|
+
removedCount++;
|
|
182
|
+
console.log(` ${green}✓${reset} Removed specdacular/`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Remove specd agents
|
|
186
|
+
const agentsDir = path.join(targetDir, 'agents');
|
|
187
|
+
if (fs.existsSync(agentsDir)) {
|
|
188
|
+
const files = fs.readdirSync(agentsDir);
|
|
189
|
+
let agentCount = 0;
|
|
190
|
+
for (const file of files) {
|
|
191
|
+
if (file.startsWith('specd-') && file.endsWith('.md')) {
|
|
192
|
+
fs.unlinkSync(path.join(agentsDir, file));
|
|
193
|
+
agentCount++;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (agentCount > 0) {
|
|
197
|
+
removedCount++;
|
|
198
|
+
console.log(` ${green}✓${reset} Removed ${agentCount} specd agents`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (removedCount === 0) {
|
|
203
|
+
console.log(` ${yellow}⚠${reset} No specdacular files found to remove.`);
|
|
204
|
+
} else {
|
|
205
|
+
console.log(`\n ${green}Done!${reset} Specdacular has been uninstalled.\n`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Install specdacular
|
|
211
|
+
*/
|
|
212
|
+
function install(isGlobal) {
|
|
213
|
+
const src = path.join(__dirname, '..');
|
|
214
|
+
const targetDir = isGlobal ? getGlobalDir() : path.join(process.cwd(), '.claude');
|
|
215
|
+
const locationLabel = isGlobal ? targetDir.replace(os.homedir(), '~') : './.claude';
|
|
216
|
+
const pathPrefix = isGlobal ? `${targetDir}/` : './.claude/';
|
|
217
|
+
|
|
218
|
+
console.log(` Installing to ${cyan}${locationLabel}${reset}\n`);
|
|
219
|
+
|
|
220
|
+
const failures = [];
|
|
221
|
+
|
|
222
|
+
// Install commands
|
|
223
|
+
const commandsDir = path.join(targetDir, 'commands');
|
|
224
|
+
fs.mkdirSync(commandsDir, { recursive: true });
|
|
225
|
+
|
|
226
|
+
const specSrc = path.join(src, 'commands', 'specd');
|
|
227
|
+
const specDest = path.join(commandsDir, 'specd');
|
|
228
|
+
if (fs.existsSync(specSrc)) {
|
|
229
|
+
copyWithPathReplacement(specSrc, specDest, pathPrefix);
|
|
230
|
+
if (verifyInstalled(specDest, 'commands/specd')) {
|
|
231
|
+
console.log(` ${green}✓${reset} Installed commands/specd`);
|
|
232
|
+
} else {
|
|
233
|
+
failures.push('commands/specd');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Install specdacular core
|
|
238
|
+
const coreSrc = path.join(src, 'specdacular');
|
|
239
|
+
const coreDest = path.join(targetDir, 'specdacular');
|
|
240
|
+
if (fs.existsSync(coreSrc)) {
|
|
241
|
+
copyWithPathReplacement(coreSrc, coreDest, pathPrefix);
|
|
242
|
+
if (verifyInstalled(coreDest, 'specdacular')) {
|
|
243
|
+
console.log(` ${green}✓${reset} Installed specdacular`);
|
|
244
|
+
} else {
|
|
245
|
+
failures.push('specdacular');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Install agents
|
|
250
|
+
const agentsSrc = path.join(src, 'agents');
|
|
251
|
+
if (fs.existsSync(agentsSrc)) {
|
|
252
|
+
const agentsDest = path.join(targetDir, 'agents');
|
|
253
|
+
fs.mkdirSync(agentsDest, { recursive: true });
|
|
254
|
+
|
|
255
|
+
// Remove old specd agents
|
|
256
|
+
if (fs.existsSync(agentsDest)) {
|
|
257
|
+
for (const file of fs.readdirSync(agentsDest)) {
|
|
258
|
+
if (file.startsWith('specd-') && file.endsWith('.md')) {
|
|
259
|
+
fs.unlinkSync(path.join(agentsDest, file));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Copy new agents
|
|
265
|
+
const agentEntries = fs.readdirSync(agentsSrc, { withFileTypes: true });
|
|
266
|
+
for (const entry of agentEntries) {
|
|
267
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
268
|
+
let content = fs.readFileSync(path.join(agentsSrc, entry.name), 'utf8');
|
|
269
|
+
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
270
|
+
fs.writeFileSync(path.join(agentsDest, entry.name), content);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (verifyInstalled(agentsDest, 'agents')) {
|
|
274
|
+
console.log(` ${green}✓${reset} Installed agents`);
|
|
275
|
+
} else {
|
|
276
|
+
failures.push('agents');
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Write VERSION file
|
|
281
|
+
const versionDest = path.join(targetDir, 'specdacular', 'VERSION');
|
|
282
|
+
fs.mkdirSync(path.dirname(versionDest), { recursive: true });
|
|
283
|
+
fs.writeFileSync(versionDest, pkg.version);
|
|
284
|
+
console.log(` ${green}✓${reset} Wrote VERSION (${pkg.version})`);
|
|
285
|
+
|
|
286
|
+
if (failures.length > 0) {
|
|
287
|
+
console.error(`\n ${yellow}Installation incomplete!${reset} Failed: ${failures.join(', ')}`);
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
console.log(`
|
|
292
|
+
${green}Done!${reset} Launch Claude Code and run ${cyan}/specd:help${reset}.
|
|
293
|
+
|
|
294
|
+
${yellow}Commands:${reset}
|
|
295
|
+
/specd:map-codebase - Analyze and document your codebase
|
|
296
|
+
/specd:help - Show all commands
|
|
297
|
+
`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Prompt for install location
|
|
302
|
+
*/
|
|
303
|
+
function promptLocation() {
|
|
304
|
+
if (!process.stdin.isTTY) {
|
|
305
|
+
console.log(` ${yellow}Non-interactive terminal, defaulting to global install${reset}\n`);
|
|
306
|
+
install(true);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const rl = readline.createInterface({
|
|
311
|
+
input: process.stdin,
|
|
312
|
+
output: process.stdout
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
let answered = false;
|
|
316
|
+
|
|
317
|
+
rl.on('close', () => {
|
|
318
|
+
if (!answered) {
|
|
319
|
+
answered = true;
|
|
320
|
+
console.log(`\n ${yellow}Installation cancelled${reset}\n`);
|
|
321
|
+
process.exit(0);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
const globalPath = getGlobalDir().replace(os.homedir(), '~');
|
|
326
|
+
|
|
327
|
+
console.log(` ${yellow}Where would you like to install?${reset}
|
|
328
|
+
|
|
329
|
+
${cyan}1${reset}) Global ${dim}(${globalPath})${reset} - available in all projects
|
|
330
|
+
${cyan}2${reset}) Local ${dim}(./.claude)${reset} - this project only
|
|
331
|
+
`);
|
|
332
|
+
|
|
333
|
+
rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
|
|
334
|
+
answered = true;
|
|
335
|
+
rl.close();
|
|
336
|
+
const choice = answer.trim() || '1';
|
|
337
|
+
const isGlobal = choice !== '2';
|
|
338
|
+
install(isGlobal);
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Main logic
|
|
343
|
+
if (hasGlobal && hasLocal) {
|
|
344
|
+
console.error(` ${yellow}Cannot specify both --global and --local${reset}`);
|
|
345
|
+
process.exit(1);
|
|
346
|
+
} else if (hasUninstall) {
|
|
347
|
+
if (!hasGlobal && !hasLocal) {
|
|
348
|
+
console.error(` ${yellow}--uninstall requires --global or --local${reset}`);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
uninstall(hasGlobal);
|
|
352
|
+
} else if (hasGlobal || hasLocal) {
|
|
353
|
+
install(hasGlobal);
|
|
354
|
+
} else {
|
|
355
|
+
promptLocation();
|
|
356
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specd:help
|
|
3
|
+
description: Show all specdacular commands and usage guide
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<objective>
|
|
9
|
+
Display available specdacular commands and usage guidance.
|
|
10
|
+
</objective>
|
|
11
|
+
|
|
12
|
+
<output>
|
|
13
|
+
# Specdacular
|
|
14
|
+
|
|
15
|
+
**Feature planning for existing codebases.**
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
| Command | Description |
|
|
20
|
+
|---------|-------------|
|
|
21
|
+
| `/specd:map-codebase` | Analyze codebase and generate documentation |
|
|
22
|
+
| `/specd:help` | Show this help |
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
1. **Map your codebase first:**
|
|
27
|
+
```
|
|
28
|
+
/specd:map-codebase
|
|
29
|
+
```
|
|
30
|
+
This spawns 4 parallel agents to analyze your codebase and creates 7 documents in `.specd/codebase/`.
|
|
31
|
+
|
|
32
|
+
2. **Review the generated docs:**
|
|
33
|
+
- `STACK.md` - Technologies and dependencies
|
|
34
|
+
- `ARCHITECTURE.md` - System design and patterns
|
|
35
|
+
- `STRUCTURE.md` - Directory layout
|
|
36
|
+
- `CONVENTIONS.md` - Code style and patterns
|
|
37
|
+
- `TESTING.md` - Test structure
|
|
38
|
+
- `INTEGRATIONS.md` - External services
|
|
39
|
+
- `CONCERNS.md` - Technical debt and issues
|
|
40
|
+
|
|
41
|
+
## Updating
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx specdacular@latest
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
*More commands coming soon for feature planning workflows.*
|
|
50
|
+
</output>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specd:map-codebase
|
|
3
|
+
description: Analyze codebase with parallel mapper agents to produce .specd/codebase/ documents
|
|
4
|
+
argument-hint: "[optional: specific area to map, e.g., 'api' or 'auth']"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<objective>
|
|
15
|
+
Analyze existing codebase using parallel specd-codebase-mapper agents to produce structured codebase documents.
|
|
16
|
+
|
|
17
|
+
Each mapper agent explores a focus area and **writes documents directly** to `.specd/codebase/`. The orchestrator only receives confirmations, keeping context usage minimal.
|
|
18
|
+
|
|
19
|
+
Output: .specd/codebase/ folder with 7 structured documents about the codebase state.
|
|
20
|
+
</objective>
|
|
21
|
+
|
|
22
|
+
<execution_context>
|
|
23
|
+
@~/.claude/specdacular/workflows/map-codebase.md
|
|
24
|
+
</execution_context>
|
|
25
|
+
|
|
26
|
+
<context>
|
|
27
|
+
Focus area: $ARGUMENTS (optional - if provided, tells agents to focus on specific subsystem)
|
|
28
|
+
|
|
29
|
+
**Load project state if exists:**
|
|
30
|
+
Check for .specd/codebase/STATE.md - loads context if project already initialized
|
|
31
|
+
|
|
32
|
+
**This command can run:**
|
|
33
|
+
- Before starting feature planning - understand the codebase first
|
|
34
|
+
- After major changes - refresh codebase understanding
|
|
35
|
+
- Anytime to update codebase documentation
|
|
36
|
+
</context>
|
|
37
|
+
|
|
38
|
+
<when_to_use>
|
|
39
|
+
**Use map-codebase for:**
|
|
40
|
+
- First time working with a codebase (understand what exists)
|
|
41
|
+
- Before planning a new feature (know the landscape)
|
|
42
|
+
- After significant refactoring (update documentation)
|
|
43
|
+
- Onboarding to an unfamiliar codebase
|
|
44
|
+
|
|
45
|
+
**Skip map-codebase for:**
|
|
46
|
+
- Trivial codebases (<5 files)
|
|
47
|
+
- When you already have recent codebase docs
|
|
48
|
+
</when_to_use>
|
|
49
|
+
|
|
50
|
+
<process>
|
|
51
|
+
1. Check if .specd/codebase/ already exists (offer to refresh or skip)
|
|
52
|
+
2. Create .specd/codebase/ directory structure
|
|
53
|
+
3. Spawn 4 parallel specd-codebase-mapper agents:
|
|
54
|
+
- Agent 1: tech focus → writes STACK.md, INTEGRATIONS.md
|
|
55
|
+
- Agent 2: arch focus → writes ARCHITECTURE.md, STRUCTURE.md
|
|
56
|
+
- Agent 3: quality focus → writes CONVENTIONS.md, TESTING.md
|
|
57
|
+
- Agent 4: concerns focus → writes CONCERNS.md
|
|
58
|
+
4. Wait for agents to complete, collect confirmations (NOT document contents)
|
|
59
|
+
5. Verify all 7 documents exist with line counts
|
|
60
|
+
6. Commit codebase map
|
|
61
|
+
7. Report completion
|
|
62
|
+
</process>
|
|
63
|
+
|
|
64
|
+
<success_criteria>
|
|
65
|
+
- [ ] .specd/codebase/ directory created
|
|
66
|
+
- [ ] All 7 codebase documents written by mapper agents
|
|
67
|
+
- [ ] Documents follow template structure
|
|
68
|
+
- [ ] Parallel agents completed without errors
|
|
69
|
+
</success_criteria>
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "specdacular",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Feature planning system for existing codebases. Map, understand, and plan features in large projects.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"specdacular": "bin/install.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"commands",
|
|
11
|
+
"agents",
|
|
12
|
+
"specdacular"
|
|
13
|
+
],
|
|
14
|
+
"keywords": [
|
|
15
|
+
"claude",
|
|
16
|
+
"claude-code",
|
|
17
|
+
"ai",
|
|
18
|
+
"codebase-analysis",
|
|
19
|
+
"feature-planning",
|
|
20
|
+
"spec-driven-development"
|
|
21
|
+
],
|
|
22
|
+
"author": "",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+ssh://git@github.com/victorbalan/specdacular.git"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/victorbalan/specdacular",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/victorbalan/specdacular/issues"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=16.7.0"
|
|
34
|
+
}
|
|
35
|
+
}
|