specross 1.0.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/README.md +207 -0
- package/bin/cli.js +292 -0
- package/package.json +25 -0
- package/template/CLAUDE.md +106 -0
- package/template/_templates/bug-report.md +81 -0
- package/template/_templates/story.md +130 -0
- package/template/_templates/tech-spec.md +109 -0
- package/template/_templates/test-cases.md +80 -0
- package/template/agents/ba.md +73 -0
- package/template/agents/dev.md +93 -0
- package/template/agents/qc.md +122 -0
- package/template/commands/ba/impact.md +42 -0
- package/template/commands/ba/new-story.md +68 -0
- package/template/commands/ba/release.md +128 -0
- package/template/commands/ba/review.md +44 -0
- package/template/commands/dev/gen-scaffold.md +40 -0
- package/template/commands/dev/gen-tech-spec.md +39 -0
- package/template/commands/dev/review.md +52 -0
- package/template/commands/dev/status.md +51 -0
- package/template/commands/dev/sync.md +62 -0
- package/template/commands/help.md +77 -0
- package/template/commands/qc/bug-report.md +33 -0
- package/template/commands/qc/gen-scripts.md +42 -0
- package/template/commands/qc/gen-test-cases.md +41 -0
- package/template/commands/qc/status.md +51 -0
- package/template/commands/qc/sync.md +71 -0
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Specross
|
|
2
|
+
|
|
3
|
+
**Spec-driven AI collaboration for BA, Dev, and QC teams.**
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
BA writes story → Dev generates tech-spec + scaffold → ship
|
|
7
|
+
↘ QC generates test cases + scripts ↗
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
One story. Three roles. No drift.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## The problem
|
|
15
|
+
|
|
16
|
+
Specs live in Notion. Test cases live in Jira. Code lives in Git. Nobody's reading the same thing.
|
|
17
|
+
|
|
18
|
+
BA updates a story — Dev doesn't know. QC writes test cases from memory, not from AC. Tech spec drifts from the story the moment it's written.
|
|
19
|
+
|
|
20
|
+
Specross fixes this by making the story the single source of truth, and giving each role an AI command that reads directly from it.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## How it works
|
|
25
|
+
|
|
26
|
+
**BA** drafts a story in `ba/` — problem statement, actors, acceptance criteria, edge cases — and releases it to `stories/` when ready.
|
|
27
|
+
|
|
28
|
+
**Dev** runs `/dev:gen-tech-spec` — AI reads the story and generates a tech spec in the exact format your team uses. Then `/dev:gen-scaffold` to generate a code scaffold.
|
|
29
|
+
|
|
30
|
+
**QC** runs `/qc:gen-test-cases` — AI reads the same story and generates test cases covering every AC and edge case, with a coverage matrix.
|
|
31
|
+
|
|
32
|
+
**When BA updates the story** — `/ba:release` auto-diffs the new version against the previous one and tells Dev and QC exactly what changed. They run `/dev:sync` and `/qc:sync` to see what needs updating.
|
|
33
|
+
|
|
34
|
+
No meetings. No copy-paste. No guessing.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
**Option 1 — npx (no install needed):**
|
|
41
|
+
```bash
|
|
42
|
+
npx specross init
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Option 2 — global install:**
|
|
46
|
+
```bash
|
|
47
|
+
npm install -g specross
|
|
48
|
+
specross init
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Run in your project root. It asks which AI tool you're using, then copies commands and agents to the right place.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
Which AI tool are you using?
|
|
55
|
+
|
|
56
|
+
1. Claude Code → .claude/commands/ + .claude/agents/
|
|
57
|
+
2. Cursor → .cursor/rules/
|
|
58
|
+
3. Windsurf → .windsurf/rules/
|
|
59
|
+
4. Other → ai/commands/ + ai/agents/
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Update commands to latest version:**
|
|
63
|
+
```bash
|
|
64
|
+
npx specross update
|
|
65
|
+
# or
|
|
66
|
+
specross update
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Never overwrites your agent and template customizations.
|
|
70
|
+
|
|
71
|
+
**Requirements:** Node.js 16+
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## What gets installed
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
your-project/
|
|
79
|
+
├── {ai-folder}/ ← commands + agents (location depends on your AI tool)
|
|
80
|
+
│ ├── commands/
|
|
81
|
+
│ │ ├── ba/ ← /ba:new-story, /ba:review, /ba:release, /ba:impact
|
|
82
|
+
│ │ ├── dev/ ← /dev:gen-tech-spec, /dev:gen-scaffold, /dev:review, /dev:sync
|
|
83
|
+
│ │ └── qc/ ← /qc:gen-test-cases, /qc:gen-scripts, /qc:bug-report, /qc:sync
|
|
84
|
+
│ └── agents/
|
|
85
|
+
│ ├── ba.md ← HOW the AI thinks as BA
|
|
86
|
+
│ ├── dev.md ← HOW the AI thinks as Dev
|
|
87
|
+
│ └── qc.md ← HOW the AI thinks as QC
|
|
88
|
+
│
|
|
89
|
+
├── _templates/ ← WHAT format the AI outputs
|
|
90
|
+
│ ├── story.md
|
|
91
|
+
│ ├── tech-spec.md
|
|
92
|
+
│ ├── test-cases.md
|
|
93
|
+
│ └── bug-report.md
|
|
94
|
+
│
|
|
95
|
+
├── ba/ ← BA draft workspace (work in progress)
|
|
96
|
+
├── stories/ ← released stories (source of truth for Dev & QC)
|
|
97
|
+
└── CLAUDE.md ← fill in your tech stack, team conventions, architecture
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Workflow
|
|
103
|
+
|
|
104
|
+
### BA — write and release
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Create a feature and break it into specs
|
|
108
|
+
/ba:new-story order-management
|
|
109
|
+
/ba:new-story order-management/create-order
|
|
110
|
+
/ba:new-story order-management/list-orders
|
|
111
|
+
|
|
112
|
+
# Review for gaps before releasing
|
|
113
|
+
/ba:review order-management/create-order
|
|
114
|
+
|
|
115
|
+
# Release draft → stories/ (auto-diffs if update)
|
|
116
|
+
/ba:release order-management/create-order v1.0.0
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Story lives at `ba/order-management/create-order/story.md` while in draft. On release, it's promoted to `stories/` — that's the version Dev and QC work from.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### Dev — from story to code
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
/dev:gen-tech-spec order-management/create-order # story → tech spec
|
|
127
|
+
/dev:gen-scaffold order-management/create-order # tech spec → code scaffold
|
|
128
|
+
/dev:review order-management/create-order # check impl vs AC
|
|
129
|
+
/dev:sync order-management/create-order # story updated? see what changed
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Output: `stories/order-management/create-order/tech/tech-spec.md`
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
### QC — from story to tests
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
/qc:gen-test-cases order-management/create-order # story → test cases
|
|
140
|
+
/qc:gen-scripts order-management/create-order # test cases → automation scripts
|
|
141
|
+
/qc:bug-report order-management/create-order TC-003 # structured bug report
|
|
142
|
+
/qc:sync order-management/create-order # story updated? see what changed
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Output: `stories/order-management/create-order/test/test-cases.md`
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### Story update flow
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# BA edits ba/order-management/create-order/story.md
|
|
153
|
+
/ba:release order-management/create-order v1.1.0
|
|
154
|
+
# → auto-diffs vs stories/, summarizes what changed, estimates impact on Dev + QC
|
|
155
|
+
|
|
156
|
+
/dev:sync order-management/create-order # AI shows which parts of tech-spec need updating
|
|
157
|
+
/qc:sync order-management/create-order # AI shows which test cases are now invalid
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Story folder structure
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
stories/
|
|
166
|
+
└── order-management/
|
|
167
|
+
├── story.md ← overview spec
|
|
168
|
+
├── CHANGELOG.md
|
|
169
|
+
├── create-order/ ← sub-spec (one per flow)
|
|
170
|
+
│ ├── story.md ← source of truth
|
|
171
|
+
│ ├── CHANGELOG.md
|
|
172
|
+
│ ├── docs/
|
|
173
|
+
│ │ └── release-v1.0.0.md
|
|
174
|
+
│ ├── tech/
|
|
175
|
+
│ │ ├── tech-spec.md ← Dev output
|
|
176
|
+
│ │ └── .spec-lock ← which story version this is based on
|
|
177
|
+
│ └── test/
|
|
178
|
+
│ ├── test-cases.md ← QC output
|
|
179
|
+
│ └── .spec-lock
|
|
180
|
+
└── list-orders/
|
|
181
|
+
└── ...
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Customize
|
|
187
|
+
|
|
188
|
+
Two layers, both preserved on `npx specross update`:
|
|
189
|
+
|
|
190
|
+
**Agents** — change how the AI behaves per role (seniority, tone, rules, red flags):
|
|
191
|
+
```
|
|
192
|
+
agents/ba.md agents/dev.md agents/qc.md
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Templates** — change the output format for your team:
|
|
196
|
+
```
|
|
197
|
+
_templates/story.md _templates/tech-spec.md
|
|
198
|
+
_templates/test-cases.md _templates/bug-report.md
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Edit agents to change how the AI *thinks*. Edit templates to change what it *outputs*.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const readline = require('readline');
|
|
6
|
+
|
|
7
|
+
// ─── Colours ──────────────────────────────────────────────────────────────────
|
|
8
|
+
const c = {
|
|
9
|
+
reset: '\x1b[0m',
|
|
10
|
+
bold: '\x1b[1m',
|
|
11
|
+
dim: '\x1b[2m',
|
|
12
|
+
green: '\x1b[32m',
|
|
13
|
+
yellow: '\x1b[33m',
|
|
14
|
+
blue: '\x1b[34m',
|
|
15
|
+
cyan: '\x1b[36m',
|
|
16
|
+
red: '\x1b[31m',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const ok = (msg) => console.log(`${c.green}✓${c.reset} ${msg}`);
|
|
20
|
+
const skip = (msg) => console.log(`${c.yellow}→${c.reset} ${c.dim}${msg}${c.reset}`);
|
|
21
|
+
const info = (msg) => console.log(`${c.blue}ℹ${c.reset} ${msg}`);
|
|
22
|
+
const err = (msg) => console.log(`${c.red}✗${c.reset} ${msg}`);
|
|
23
|
+
const head = (msg) => console.log(`\n${c.bold}${c.cyan}${msg}${c.reset}`);
|
|
24
|
+
const rule = () => console.log(`${c.dim}${'─'.repeat(56)}${c.reset}`);
|
|
25
|
+
|
|
26
|
+
// ─── AI tool destinations ──────────────────────────────────────────────────────
|
|
27
|
+
const AI_TOOLS = {
|
|
28
|
+
'1': {
|
|
29
|
+
name: 'Claude Code',
|
|
30
|
+
commandsDir: '.claude/commands',
|
|
31
|
+
agentsDir: '.claude/agents',
|
|
32
|
+
hint: 'Slash commands auto-loaded. Run: claude .',
|
|
33
|
+
},
|
|
34
|
+
'2': {
|
|
35
|
+
name: 'Cursor',
|
|
36
|
+
commandsDir: '.cursor/rules',
|
|
37
|
+
agentsDir: '.cursor/rules',
|
|
38
|
+
hint: 'Rules auto-loaded by Cursor. Open your project in Cursor.',
|
|
39
|
+
},
|
|
40
|
+
'3': {
|
|
41
|
+
name: 'Windsurf',
|
|
42
|
+
commandsDir: '.windsurf/rules',
|
|
43
|
+
agentsDir: '.windsurf/rules',
|
|
44
|
+
hint: 'Rules auto-loaded by Windsurf. Open your project in Windsurf.',
|
|
45
|
+
},
|
|
46
|
+
'4': {
|
|
47
|
+
name: 'Other / Manual',
|
|
48
|
+
commandsDir: 'ai/commands',
|
|
49
|
+
agentsDir: 'ai/agents',
|
|
50
|
+
hint: 'Files copied to ai/. Load them manually into your AI tool.',
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
function ask(question) {
|
|
57
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
58
|
+
return new Promise(resolve => rl.question(question, ans => { rl.close(); resolve(ans.trim()); }));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function copyDir(src, dest, overwrite = false) {
|
|
62
|
+
const results = { copied: [], skipped: [] };
|
|
63
|
+
if (!fs.existsSync(src)) return results;
|
|
64
|
+
|
|
65
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
66
|
+
const srcPath = path.join(src, entry.name);
|
|
67
|
+
const destPath = path.join(dest, entry.name);
|
|
68
|
+
|
|
69
|
+
if (entry.isDirectory()) {
|
|
70
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
71
|
+
const sub = copyDir(srcPath, destPath, overwrite);
|
|
72
|
+
results.copied.push(...sub.copied);
|
|
73
|
+
results.skipped.push(...sub.skipped);
|
|
74
|
+
} else {
|
|
75
|
+
if (fs.existsSync(destPath) && !overwrite) {
|
|
76
|
+
results.skipped.push(destPath);
|
|
77
|
+
} else {
|
|
78
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
79
|
+
fs.copyFileSync(srcPath, destPath);
|
|
80
|
+
results.copied.push(destPath);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function ensureDir(dir) {
|
|
88
|
+
if (!fs.existsSync(dir)) {
|
|
89
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function rel(p) { return path.relative(process.cwd(), p); }
|
|
96
|
+
|
|
97
|
+
function readConfig(cwd) {
|
|
98
|
+
const cfgPath = path.join(cwd, '.specross.json');
|
|
99
|
+
if (fs.existsSync(cfgPath)) return JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function writeConfig(cwd, cfg) {
|
|
104
|
+
fs.writeFileSync(path.join(cwd, '.specross.json'), JSON.stringify(cfg, null, 2));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ─── init ─────────────────────────────────────────────────────────────────────
|
|
108
|
+
|
|
109
|
+
async function cmdInit() {
|
|
110
|
+
const cwd = process.cwd();
|
|
111
|
+
const tmpl = path.join(__dirname, '..', 'template');
|
|
112
|
+
|
|
113
|
+
console.log(`\n${c.bold}${c.cyan}Specross${c.reset} — installing into ${c.bold}${cwd}${c.reset}\n`);
|
|
114
|
+
rule();
|
|
115
|
+
|
|
116
|
+
// Ask which AI tool
|
|
117
|
+
head('Which AI tool are you using?');
|
|
118
|
+
console.log('');
|
|
119
|
+
Object.entries(AI_TOOLS).forEach(([key, tool]) => {
|
|
120
|
+
console.log(` ${c.bold}${key}${c.reset}. ${tool.name}`);
|
|
121
|
+
});
|
|
122
|
+
console.log('');
|
|
123
|
+
|
|
124
|
+
let toolKey = await ask(` ${c.yellow}Enter number (default: 1) ${c.reset}`);
|
|
125
|
+
if (!toolKey || !AI_TOOLS[toolKey]) toolKey = '1';
|
|
126
|
+
const tool = AI_TOOLS[toolKey];
|
|
127
|
+
|
|
128
|
+
console.log(`\n Installing for ${c.bold}${c.cyan}${tool.name}${c.reset}\n`);
|
|
129
|
+
rule();
|
|
130
|
+
|
|
131
|
+
// Save choice so `update` knows where to update
|
|
132
|
+
writeConfig(cwd, { aiTool: toolKey, commandsDir: tool.commandsDir, agentsDir: tool.agentsDir });
|
|
133
|
+
|
|
134
|
+
// 1. commands — always safe to overwrite
|
|
135
|
+
head('Step 1 — Commands');
|
|
136
|
+
const cmdRes = copyDir(path.join(tmpl, 'commands'), path.join(cwd, tool.commandsDir), true);
|
|
137
|
+
cmdRes.copied.forEach(f => ok(`Installed ${rel(f)}`));
|
|
138
|
+
|
|
139
|
+
// 2. agents — skip if already exist (user may have customized)
|
|
140
|
+
head('Step 2 — Role agents (yours if already customized)');
|
|
141
|
+
const agentRes = copyDir(path.join(tmpl, 'agents'), path.join(cwd, tool.agentsDir), false);
|
|
142
|
+
agentRes.copied.forEach(f => ok(`Installed ${rel(f)}`));
|
|
143
|
+
agentRes.skipped.forEach(f => skip(`Kept ${rel(f)} (your custom version)`));
|
|
144
|
+
|
|
145
|
+
// 3. templates — skip if already exist
|
|
146
|
+
head('Step 3 — Output templates (yours if already customized)');
|
|
147
|
+
const tmplRes = copyDir(path.join(tmpl, '_templates'), path.join(cwd, '_templates'), false);
|
|
148
|
+
tmplRes.copied.forEach(f => ok(`Installed ${rel(f)}`));
|
|
149
|
+
tmplRes.skipped.forEach(f => skip(`Kept ${rel(f)} (your custom version)`));
|
|
150
|
+
|
|
151
|
+
// 4. project folders
|
|
152
|
+
head('Step 4 — Project folders');
|
|
153
|
+
for (const folder of ['ba', 'stories']) {
|
|
154
|
+
const dir = path.join(cwd, folder);
|
|
155
|
+
if (ensureDir(dir)) {
|
|
156
|
+
fs.writeFileSync(path.join(dir, '.gitkeep'), '');
|
|
157
|
+
ok(`Created ${folder}/`);
|
|
158
|
+
} else {
|
|
159
|
+
skip(`Exists ${folder}/`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 5. CLAUDE.md
|
|
164
|
+
head('Step 5 — CLAUDE.md');
|
|
165
|
+
const mdDest = path.join(cwd, 'CLAUDE.md');
|
|
166
|
+
if (!fs.existsSync(mdDest)) {
|
|
167
|
+
fs.copyFileSync(path.join(tmpl, 'CLAUDE.md'), mdDest);
|
|
168
|
+
ok('Created CLAUDE.md');
|
|
169
|
+
} else {
|
|
170
|
+
skip('Kept CLAUDE.md (already exists)');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
rule();
|
|
174
|
+
console.log(`\n${c.green}${c.bold}Specross installed!${c.reset}\n`);
|
|
175
|
+
console.log(`${c.bold}Next steps:${c.reset}`);
|
|
176
|
+
console.log(` 1. Fill in ${c.bold}CLAUDE.md${c.reset} with your tech stack and team`);
|
|
177
|
+
console.log(` 2. Customize agents in: ${c.cyan}${tool.agentsDir}/${c.reset}`);
|
|
178
|
+
console.log(` 3. Customize templates in: ${c.cyan}_templates/${c.reset}`);
|
|
179
|
+
console.log(` 4. ${tool.hint}`);
|
|
180
|
+
console.log(` 5. First story: ${c.cyan}/ba:new-story my-feature${c.reset}\n`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ─── update ───────────────────────────────────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
async function cmdUpdate() {
|
|
186
|
+
const cwd = process.cwd();
|
|
187
|
+
const tmpl = path.join(__dirname, '..', 'template');
|
|
188
|
+
|
|
189
|
+
console.log(`\n${c.bold}${c.cyan}Specross${c.reset} — updating\n`);
|
|
190
|
+
rule();
|
|
191
|
+
|
|
192
|
+
// Read saved config to know where commands live
|
|
193
|
+
const cfg = readConfig(cwd);
|
|
194
|
+
let tool;
|
|
195
|
+
|
|
196
|
+
if (cfg) {
|
|
197
|
+
tool = AI_TOOLS[cfg.aiTool];
|
|
198
|
+
info(`Detected: ${tool.name} (from .specross.json)\n`);
|
|
199
|
+
} else {
|
|
200
|
+
head('Which AI tool are you using?');
|
|
201
|
+
console.log('');
|
|
202
|
+
Object.entries(AI_TOOLS).forEach(([key, t]) => {
|
|
203
|
+
console.log(` ${c.bold}${key}${c.reset}. ${t.name}`);
|
|
204
|
+
});
|
|
205
|
+
console.log('');
|
|
206
|
+
let toolKey = await ask(` ${c.yellow}Enter number (default: 1) ${c.reset}`);
|
|
207
|
+
if (!toolKey || !AI_TOOLS[toolKey]) toolKey = '1';
|
|
208
|
+
tool = AI_TOOLS[toolKey];
|
|
209
|
+
writeConfig(cwd, { aiTool: toolKey, commandsDir: tool.commandsDir, agentsDir: tool.agentsDir });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
info('Commands will be updated to the latest version.');
|
|
213
|
+
info('Agents and templates will NOT be touched — your customizations are safe.\n');
|
|
214
|
+
|
|
215
|
+
const ans = await ask(` ${c.yellow}Continue? (y/N) ${c.reset}`);
|
|
216
|
+
if (ans.toLowerCase() !== 'y') { console.log('\nCancelled.\n'); process.exit(0); }
|
|
217
|
+
|
|
218
|
+
// Only overwrite commands
|
|
219
|
+
head('Updating commands');
|
|
220
|
+
const cmdRes = copyDir(path.join(tmpl, 'commands'), path.join(cwd, tool.commandsDir), true);
|
|
221
|
+
cmdRes.copied.forEach(f => ok(`Updated ${rel(f)}`));
|
|
222
|
+
|
|
223
|
+
rule();
|
|
224
|
+
console.log(`\n${c.green}${c.bold}Commands updated!${c.reset}`);
|
|
225
|
+
console.log(`${c.dim}Agents and templates were not changed.${c.reset}\n`);
|
|
226
|
+
|
|
227
|
+
// Offer optional resets
|
|
228
|
+
const resetAgents = await ask(` ${c.yellow}Also reset agents to default? Overwrites customizations. (y/N) ${c.reset}`);
|
|
229
|
+
if (resetAgents.toLowerCase() === 'y') {
|
|
230
|
+
const res = copyDir(path.join(tmpl, 'agents'), path.join(cwd, tool.agentsDir), true);
|
|
231
|
+
res.copied.forEach(f => ok(`Reset ${rel(f)}`));
|
|
232
|
+
console.log('');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const resetTmpls = await ask(` ${c.yellow}Also reset templates to default? Overwrites customizations. (y/N) ${c.reset}`);
|
|
236
|
+
if (resetTmpls.toLowerCase() === 'y') {
|
|
237
|
+
const res = copyDir(path.join(tmpl, '_templates'), path.join(cwd, '_templates'), true);
|
|
238
|
+
res.copied.forEach(f => ok(`Reset ${rel(f)}`));
|
|
239
|
+
console.log('');
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log(`${c.green}${c.bold}Done!${c.reset}\n`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ─── help ─────────────────────────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
function cmdHelp() {
|
|
248
|
+
console.log(`
|
|
249
|
+
${c.bold}${c.cyan}specross${c.reset} — Spec-driven AI collaboration for BA, Dev & QC teams
|
|
250
|
+
|
|
251
|
+
${c.bold}Usage:${c.reset}
|
|
252
|
+
npx specross init Install Specross into the current project
|
|
253
|
+
npx specross update Update commands only (keeps your customizations)
|
|
254
|
+
npx specross help Show this help
|
|
255
|
+
|
|
256
|
+
${c.bold}Supported AI tools:${c.reset}
|
|
257
|
+
1. Claude Code → .claude/commands/ + .claude/agents/
|
|
258
|
+
2. Cursor → .cursor/rules/
|
|
259
|
+
3. Windsurf → .windsurf/rules/
|
|
260
|
+
4. Other → ai/commands/ + ai/agents/
|
|
261
|
+
|
|
262
|
+
${c.bold}What gets installed:${c.reset}
|
|
263
|
+
commands/ 12 slash commands for BA, Dev, QC
|
|
264
|
+
agents/ Role personas — customize per role (never overwritten by update)
|
|
265
|
+
_templates/ Output format — customize freely (never overwritten by update)
|
|
266
|
+
ba/ BA draft workspace
|
|
267
|
+
stories/ Released stories (source of truth for Dev & QC)
|
|
268
|
+
CLAUDE.md Project config — fill this in!
|
|
269
|
+
|
|
270
|
+
${c.bold}Commands available after install:${c.reset}
|
|
271
|
+
/help (list all commands with descriptions)
|
|
272
|
+
|
|
273
|
+
/ba:new-story /ba:review /ba:release /ba:impact
|
|
274
|
+
/dev:gen-tech-spec /dev:gen-scaffold /dev:review /dev:sync /dev:status
|
|
275
|
+
/qc:gen-test-cases /qc:gen-scripts /qc:bug-report /qc:sync /qc:status
|
|
276
|
+
|
|
277
|
+
${c.dim}Docs: https://github.com/ethandev147/specross${c.reset}
|
|
278
|
+
`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ─── Entry ────────────────────────────────────────────────────────────────────
|
|
282
|
+
|
|
283
|
+
const command = process.argv[2] || 'help';
|
|
284
|
+
switch (command) {
|
|
285
|
+
case 'init': cmdInit().catch(console.error); break;
|
|
286
|
+
case 'update': cmdUpdate().catch(console.error); break;
|
|
287
|
+
case 'help': case '--help': case '-h': cmdHelp(); break;
|
|
288
|
+
default:
|
|
289
|
+
err(`Unknown command: ${command}`);
|
|
290
|
+
cmdHelp();
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "specross",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Spec-driven AI collaboration for BA, Dev, and QC teams — built for Claude Code",
|
|
5
|
+
"keywords": ["claude", "claude-code", "ai", "agile", "ba", "dev", "qc", "specflow"],
|
|
6
|
+
"homepage": "https://github.com/ethandev147/specross",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/ethandev147/specross.git"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=16"
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"specross": "./bin/cli.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin/",
|
|
20
|
+
"template/"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"test": "node bin/cli.js --help"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Specross — Project Context for Claude
|
|
2
|
+
|
|
3
|
+
> This file tells Claude about your project. Fill in the sections below before your team starts using the commands.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What We're Building
|
|
8
|
+
|
|
9
|
+
<!-- Describe the product in 2–4 sentences. What is it? Who uses it? What problem does it solve? -->
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Tech Stack
|
|
14
|
+
|
|
15
|
+
<!-- List your languages, frameworks, and key libraries. Claude uses this when generating tech specs and scaffolds. -->
|
|
16
|
+
|
|
17
|
+
- **Language:** e.g. TypeScript / Python / Go
|
|
18
|
+
- **Frontend:** e.g. React, Next.js / Vue / None
|
|
19
|
+
- **Backend:** e.g. Node.js + Express / FastAPI / Rails
|
|
20
|
+
- **Database:** e.g. PostgreSQL / MongoDB / MySQL
|
|
21
|
+
- **Testing:** e.g. Jest + Playwright / pytest + Selenium / Cypress
|
|
22
|
+
- **Infrastructure:** e.g. AWS / GCP / Vercel
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Folder Conventions
|
|
27
|
+
|
|
28
|
+
<!-- Tell Claude where things live in your project. -->
|
|
29
|
+
|
|
30
|
+
- **Source code:** `src/`
|
|
31
|
+
- **Tests:** `tests/`
|
|
32
|
+
- **Stories:** `stories/`
|
|
33
|
+
|
|
34
|
+
### Naming conventions
|
|
35
|
+
- Files: `kebab-case` (e.g. `user-auth.service.ts`)
|
|
36
|
+
- Classes / Components: `PascalCase`
|
|
37
|
+
- Variables / Functions: `camelCase`
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Architecture Patterns
|
|
42
|
+
|
|
43
|
+
<!-- Describe how your codebase is structured so Claude generates consistent code. -->
|
|
44
|
+
|
|
45
|
+
- **Pattern:** e.g. MVC / Clean Architecture / Feature-based folders
|
|
46
|
+
- **API style:** e.g. REST / GraphQL / tRPC
|
|
47
|
+
- **Auth:** e.g. JWT in Authorization header / Session cookie / OAuth2
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Coding Standards
|
|
52
|
+
|
|
53
|
+
<!-- Any rules Claude should follow when generating code. -->
|
|
54
|
+
|
|
55
|
+
- Always add JSDoc / docstrings to public functions
|
|
56
|
+
- Prefer `const` over `let`; avoid `var`
|
|
57
|
+
- Use async/await over `.then()` chains
|
|
58
|
+
- Error responses use format: `{ error: { code: string, message: string } }`
|
|
59
|
+
- (Add your own standards here)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Team
|
|
64
|
+
|
|
65
|
+
<!-- Optional: list role names and owners so Claude can reference them in outputs. -->
|
|
66
|
+
|
|
67
|
+
| Role | Name |
|
|
68
|
+
|------|------|
|
|
69
|
+
| BA | |
|
|
70
|
+
| Dev Lead | |
|
|
71
|
+
| QC Lead | |
|
|
72
|
+
| Product Owner | |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Specross — How We Work
|
|
77
|
+
|
|
78
|
+
This repo uses Specross. Commands are available via Claude Code:
|
|
79
|
+
|
|
80
|
+
| Role | Command | Purpose |
|
|
81
|
+
|------|---------|---------|
|
|
82
|
+
| BA | `/ba:new-story [name]` | Create a new story |
|
|
83
|
+
| BA | `/ba:review [story]` | Review story for gaps |
|
|
84
|
+
| BA | `/ba:impact [story] [v-old] [v-new]` | Impact report on spec changes |
|
|
85
|
+
| Dev | `/dev:gen-tech-spec [story]` | Generate tech spec from story |
|
|
86
|
+
| Dev | `/dev:gen-scaffold [story]` | Generate code scaffold from tech spec |
|
|
87
|
+
| Dev | `/dev:review [story]` | Review implementation vs requirements |
|
|
88
|
+
| QC | `/qc:gen-test-cases [story]` | Generate test cases from story |
|
|
89
|
+
| QC | `/qc:gen-scripts [story]` | Generate automation scripts |
|
|
90
|
+
| QC | `/qc:bug-report [story] [TC-ID]` | Generate structured bug report |
|
|
91
|
+
|
|
92
|
+
### Story lifecycle
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
BA: /ba:new-story → fill in story.md → /ba:review
|
|
96
|
+
↓
|
|
97
|
+
Dev: /dev:gen-tech-spec → /dev:gen-scaffold → implement → /dev:review
|
|
98
|
+
QC: /qc:gen-test-cases → /qc:gen-scripts → test → /qc:bug-report
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### AI principles for this project
|
|
102
|
+
|
|
103
|
+
1. AI assists, humans decide. All AI output is a first draft.
|
|
104
|
+
2. Review all generated tech specs and test cases before treating them as final.
|
|
105
|
+
3. Prompts with more context produce better output — fill in this CLAUDE.md fully.
|
|
106
|
+
4. If output is wrong, refine and re-run the command. Don't accept poor output.
|