spec-starter 1.0.0 → 1.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.
@@ -1,26 +1,50 @@
1
1
  # <feature_title> — E2E Checklist
2
2
 
3
- Generated after implementation. Work through each scenario manually.
3
+ Generated after implementation. UI scenarios with a URL will run automatically via Playwright MCP if available; others require manual confirmation.
4
4
 
5
5
  ---
6
6
 
7
7
  ## Happy Path
8
8
 
9
- - [ ] <Scenario 1: exact steps to follow, expected outcome>
10
- - [ ] <Scenario 2>
9
+ - [ ] **<Scenario 1 title>**
10
+ - **URL:** `/<path>`
11
+ - **Steps:**
12
+ 1. <action using visible label or element description>
13
+ 2. <action>
14
+ - **Expected:** <what should be visible or true when done>
15
+
16
+ - [ ] **<Scenario 2 title>**
17
+ - **URL:** `/<path>`
18
+ - **Steps:**
19
+ 1. <action>
20
+ - **Expected:** <outcome>
11
21
 
12
22
  ## Edge Cases
13
23
 
14
- - [ ] <Edge case 1: what to do, what should happen>
15
- - [ ] <Edge case 2>
24
+ - [ ] **<Edge case 1 title>**
25
+ - **URL:** `/<path>`
26
+ - **Steps:**
27
+ 1. <how to trigger the edge case>
28
+ - **Expected:** <what the user should see>
29
+
30
+ - [ ] **<Non-browser check title>**
31
+ - <Describe what to run or check — no URL needed for non-browser scenarios>
16
32
 
17
33
  ## Error States
18
34
 
19
- - [ ] <Error scenario: how to trigger, what the user should see>
35
+ - [ ] **<Error scenario title>**
36
+ - **URL:** `/<path>`
37
+ - **Steps:**
38
+ 1. <how to trigger the error>
39
+ - **Expected:** <error message or fallback the user should see>
20
40
 
21
41
  ## Integration Points
22
42
 
23
- - [ ] <Cross-feature or external dependency check>
43
+ - [ ] **<Cross-feature or external dependency check>**
44
+ - **URL:** `/<path>`
45
+ - **Steps:**
46
+ 1. <check to perform>
47
+ - **Expected:** <expected integration behavior>
24
48
 
25
49
  ---
26
50
 
@@ -23,3 +23,7 @@
23
23
  - <Key point 1>
24
24
  - <Key point 2>
25
25
  - <Key point 3>
26
+
27
+ ## Diagram
28
+
29
+ <!-- Generated by /feature:blueprint -->
@@ -106,10 +106,33 @@ In `1-feature.md`, change `- [o] Blueprint` to `- [x] Blueprint`.
106
106
 
107
107
  **State update:** Do this immediately after blueprint.md is written.
108
108
 
109
+ ### Step 6: Generate Mermaid diagram and update 1-feature.md
110
+
111
+ Based on the blueprint you just wrote, generate a Mermaid architecture diagram that shows the key components or layers and data flow between them. Use `graph TD` orientation (top-down) unless the feature is a linear pipeline, in which case `graph LR` (left-right) is clearer.
112
+
113
+ Guidelines:
114
+ - 5 to 12 nodes is ideal — keep it concise
115
+ - Label edges with the action or data being passed: `-->|user input|`, `-->|SQL query|`, etc.
116
+ - Use subgraphs only if there are clearly distinct tiers (e.g. Frontend / Backend)
117
+ - No commentary inside the `## Diagram` section — only the fenced code block
118
+
119
+ Open `1-feature.md` for this feature. Find the `## Diagram` section. If the section is not present (feature created before this template update), append the `## Diagram` section to the end of the file instead. Replace from `## Diagram` to the end of the file with:
120
+
121
+ ````markdown
122
+ ## Diagram
123
+
124
+ ```mermaid
125
+ <your generated diagram here>
126
+ ```
127
+ ````
128
+
129
+ Use the Edit tool to make this replacement.
130
+
109
131
  Output:
110
132
 
111
133
  ```
112
- Blueprint written: .claude/_features/$ARGUMENTS/3-blueprint.md
134
+ Blueprint written: .claude/_features/$ARGUMENTS/3-blueprint.md
135
+ Diagram updated: .claude/_features/$ARGUMENTS/1-feature.md (## Diagram)
113
136
 
114
137
  Progress: [x] Brief [x] Blueprint [ ] Implement [ ] Review [ ] Done
115
138
  ```
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Run through the e2e checklist for a completed feature
3
3
  argument-hint: "<MM.DD-slug>"
4
- allowed-tools: Read, Edit, Glob, Bash
4
+ allowed-tools: Read, Edit, Glob, Bash, mcp__playwright__*
5
5
  ---
6
6
 
7
7
  Walk through the e2e checklist for a feature interactively. The feature must be marked `[x] Done` before testing is allowed.
@@ -89,6 +89,11 @@ Then stop.
89
89
 
90
90
  **Read shared testing instructions:** Check if `.claude/testing.md` exists. If it does, read it and use it throughout — it contains app-specific context like how to start the app, base URLs, test accounts, browser/device preferences, and any other setup needed to run scenarios correctly.
91
91
 
92
+ **Playwright check:** Use the Skill tool to invoke the `playwright-test` skill. It will check whether Playwright MCP tools are available and report back.
93
+
94
+ - If available → use Playwright automatically for all UI scenarios (those with a **URL** field). Note this as `playwright_available = true`.
95
+ - If not available → fall back to manual for all UI scenarios. Note this as `playwright_available = false`.
96
+
92
97
  ### Step 2: Present the checklist and run scenarios
93
98
 
94
99
  Output a summary of what you're about to test:
@@ -104,10 +109,16 @@ Then work through each section of the checklist in order:
104
109
 
105
110
  For each unchecked scenario (`- [ ]`):
106
111
  1. Present the scenario clearly — what to do and what to expect
107
- 2. For any scenario involving CLI commands or scripts, run them using Bash and report the result
108
- 3. For UI or manual scenarios, describe exactly what to check and ask the user to confirm: `Pass or fail?`
109
- 4. If the user confirms pass: mark the item `- [x]` in `e2e-checklist.md` using the Edit tool
110
- 5. If the user says fail: mark the item `- [!]` in `e2e-checklist.md`, note what failed, and continue to the next scenario
112
+ 2. For CLI/script scenarios: run with Bash and report the result
113
+ 3. For UI scenarios (those with **URL**, **Steps**, and **Expected** fields):
114
+ - If `playwright_available = true`: run the scenario automatically using the `playwright-test` skill.
115
+ - PASS mark the item `[x]`
116
+ - FAIL → mark the item `[!]`, note what failed, continue
117
+ - `[!] ERROR` → mark the item `[!]`, record the error evidence, continue
118
+ - If `playwright_available = false`: describe exactly what to check and ask the user: `Pass or fail?`
119
+ 4. For manual scenarios (no URL field): describe exactly what to check and ask the user: `Pass or fail?`
120
+ 5. If the user confirms pass: mark the item `- [x]` in `e2e-checklist.md` using the Edit tool
121
+ 6. If the user says fail: mark the item `- [!]` in `e2e-checklist.md`, note what failed, and continue to the next scenario
111
122
 
112
123
  Skip scenarios already marked `[x]` (previously passed) — report them as already passing.
113
124
 
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: playwright-test
3
+ description: Run UI scenarios automatically using Playwright MCP browser automation tools.
4
+ ---
5
+
6
+ # Playwright Test
7
+
8
+ Automate UI e2e scenario execution using Playwright MCP browser tools.
9
+
10
+ ## Availability check
11
+
12
+ Before using this skill, confirm that Playwright MCP tools are present in your tool list (look for tools prefixed with `mcp__playwright__` or similar browser automation tools). If they are available, proceed with this skill. If they are not available, stop immediately and report to the caller: "Playwright MCP not available." Do not execute any scenarios. The caller is responsible for handling unavailability (typically by asking the user to confirm each scenario manually).
13
+
14
+ ## Scenario structure
15
+
16
+ Each UI scenario in `4-e2e-checklist.md` follows this format:
17
+
18
+ ```
19
+ - [ ] **<Scenario title>**
20
+ - **URL:** `/<path>`
21
+ - **Steps:** numbered list of actions
22
+ - **Expected:** what should be visible/true when done
23
+ ```
24
+
25
+ Scenarios that have a URL, Steps, and Expected field are in scope for this skill. Scenarios without a URL (CLI checks, API checks, or manual-only verifications) are out of scope — the caller handles those via Bash or manual confirmation.
26
+
27
+ ## Building full URLs
28
+
29
+ The `## Base URL` section in `.claude/testing.md` provides the origin. If a scenario URL is relative (starts with `/`), prepend the base URL.
30
+
31
+ Example: base URL `http://localhost:3000` + scenario URL `/dashboard` = `http://localhost:3000/dashboard`.
32
+
33
+ If `testing.md` has no base URL, ask the user to provide it before proceeding.
34
+
35
+ ## Test accounts
36
+
37
+ If `.claude/testing.md` defines test credentials under `## Test accounts`, use them for any login flow before navigating to a protected route. Log in once at the start of the test run and reuse the session for subsequent scenarios where possible.
38
+
39
+ ## Running a scenario
40
+
41
+ For each in-scope scenario:
42
+
43
+ ### 1. Navigate
44
+
45
+ Navigate to the full URL using the Playwright navigation tool.
46
+
47
+ ### 2. Execute steps
48
+
49
+ Work through the numbered steps in order:
50
+
51
+ - **Clicks:** locate the element by its visible label, text, or ARIA role — not by CSS selector. Then click it.
52
+ - **Form inputs:** use fill tools to enter values into fields, identified by their visible label or placeholder text.
53
+ - **Keyboard actions** (Enter, Tab, Escape, etc.): use key press tools.
54
+
55
+ After all steps are complete, take a screenshot to capture the final state.
56
+
57
+ ### 3. Verify expected outcome
58
+
59
+ Use page content reading tools (accessibility tree or page text) to check whether the expected text or elements are present.
60
+
61
+ - If the expected outcome is present: **PASS**.
62
+ - If the expected outcome is absent or an error is visible: **FAIL**.
63
+
64
+ ## Result reporting format
65
+
66
+ After each scenario, report the result in this format:
67
+
68
+ ```
69
+ Scenario: <title>
70
+ Result: PASS
71
+ Evidence: <what was observed>
72
+ ```
73
+
74
+ or
75
+
76
+ ```
77
+ Scenario: <title>
78
+ Result: FAIL
79
+ Evidence: <what was observed>
80
+ ```
81
+
82
+ Include specific observed text, element presence, or error messages as evidence. Do not report vague evidence like "page loaded correctly."
83
+
84
+ This skill reports results to the conversation only. It does not modify `4-e2e-checklist.md`. The caller is responsible for marking scenarios `[x]` (pass) or `[!]` (fail) based on this skill's reported outcomes.
85
+
86
+ ## Error handling
87
+
88
+ If navigation fails or an element cannot be found, try once more using an alternate approach (e.g. a different locator strategy or a short wait before retrying).
89
+
90
+ If the scenario still cannot be completed after the second attempt, mark it with `[!]`, report the specific error and evidence, and continue to the next scenario. Never hang or retry infinitely.
91
+
92
+ ```
93
+ Scenario: <title>
94
+ Result: [!] ERROR
95
+ Evidence: <specific error message or what was observed>
96
+ ```
97
+
98
+ ## Output summary
99
+
100
+ After all scenarios are complete, output a summary table:
101
+
102
+ ```
103
+ ## E2E Results
104
+
105
+ | Scenario | Result |
106
+ |----------|--------|
107
+ | <title> | PASS |
108
+ | <title> | FAIL |
109
+ | <title> | [!] ERROR |
110
+ ```
111
+
112
+ Then list any FAIL or ERROR scenarios with their full evidence for follow-up.
@@ -34,6 +34,7 @@ Ask one question about manual/e2e testing setup:
34
34
  - Are there test accounts or credentials needed?
35
35
  - Any browser or device requirements?
36
36
  - Anything else needed to run through features manually?
37
+ - Is this a web app? If yes, what is the local dev base URL? (e.g. `http://localhost:3000`)
37
38
 
38
39
  ### 3. Update CLAUDE.md
39
40
 
@@ -57,7 +58,10 @@ Write `.claude/testing.md` with the manual testing setup gathered in Step 2. Thi
57
58
  # Testing
58
59
 
59
60
  ## How to start the app
60
- <dev server command and URL, or staging URL>
61
+ <dev server command>
62
+
63
+ ## Base URL
64
+ <base URL for the running app, e.g. http://localhost:3000 — or "N/A" if not a web app>
61
65
 
62
66
  ## Test accounts
63
67
  <credentials or "none required">
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # spec-starter
2
2
 
3
- A Claude Code project template for structured feature development. Drop the `.claude/` folder into any project to get a repeatable workflow for taking features from raw idea to tested implementation.
3
+ A Claude Code project template for structured feature development. Run `npx spec-starter` in any project to get a repeatable workflow for taking features from raw idea to tested implementation.
4
4
 
5
5
  ## How it works
6
6
 
@@ -21,7 +21,7 @@ Each stage has a matching slash command. Commands are interactive: called withou
21
21
  | Command | No args | With arg |
22
22
  |---|---|---|
23
23
  | `/task` | List backlog tasks | Add idea to `.claude/tasks.md` |
24
- | `/feature:start` | List backlog tasks | Create feature folder + `2-brief.md` |
24
+ | `/feature:start` | List backlog tasks | Create feature folder + `1-feature.md` + `2-brief.md` |
25
25
  | `/feature:review` | List `[?]` features | Review current state and take next action |
26
26
  | `/feature:blueprint` | List `[x]` Brief features ready to blueprint | Generate `3-blueprint.md` |
27
27
  | `/feature:implement` | List `[x]` Blueprint features ready to implement | Implement + generate `4-e2e-checklist.md` |
@@ -41,10 +41,11 @@ Backlog idea (.claude/tasks.md)
41
41
  /feature:blueprint <slug> → .claude/_features/<slug>/3-blueprint.md [x] Blueprint
42
42
 
43
43
  /feature:implement <slug> → writes code (TDD), generates 4-e2e-checklist.md [x] Implement
44
+ ↓ [o] Review
45
+ · manually work through 4-e2e-checklist.md
44
46
 
45
- Manual review work through 4-e2e-checklist.md [x] Review
46
-
47
- /feature:finish <slug> → push branch, PR into dev, merge, mark Done [x] Done
47
+ /feature:finish <slug> push branch, PR into dev, merge, mark Done [x] Review
48
+ [x] Done
48
49
 
49
50
  /feature:test <slug> → walk e2e checklist interactively (post-merge QA)
50
51
  ```
@@ -91,9 +92,23 @@ You can also create or edit `.claude/testing.md` by hand at any time.
91
92
 
92
93
  ## Getting started
93
94
 
94
- 1. Copy this repo's `.claude/` folder into your project root
95
- 2. Run `/project-init` to generate `CLAUDE.md` with project context and `.claude/testing.md` with testing setup
96
- 3. Add ideas to `.claude/tasks.md` (one per line), then run `/feature:start <idea>` to turn one into a feature
95
+ In your project root:
96
+
97
+ ```bash
98
+ npx spec-starter
99
+ ```
100
+
101
+ Then open Claude Code — `project-init` runs automatically on first open, generating `CLAUDE.md` and `.claude/testing.md`.
102
+
103
+ Add ideas to `.claude/tasks.md` (one per line), then run `/feature:start <idea>` to turn one into a feature.
104
+
105
+ ## Updating
106
+
107
+ Run the same command again to sync the latest engine files. Your project data (`_features/`, `tasks.md`, `testing.md`, `CLAUDE.md`) is never touched. Claude will announce the update next time you open the project.
108
+
109
+ ```bash
110
+ npx spec-starter
111
+ ```
97
112
 
98
113
  ## Design principle
99
114
 
package/bin/index.js CHANGED
@@ -3,32 +3,26 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
 
6
- const src = path.join(__dirname, '..');
7
- const dest = process.cwd();
6
+ const PKG_DIR = path.join(__dirname, '..');
7
+ const TARGET_DIR = process.cwd();
8
+ const VERSION = require('../package.json').version;
8
9
 
9
- // Always overwrite — these are the engine files
10
- const engineDirs = [
10
+ const SCAFFOLD_DIRS = [
11
11
  '.claude/commands',
12
12
  '.claude/skills',
13
13
  '.claude/_templates',
14
14
  '.claude/hooks',
15
15
  ];
16
- const engineFiles = [
17
- '.claude/settings.json',
18
- ];
19
16
 
20
- // Create only if missing — project seeds
21
- const seedFiles = [
22
- ['.claude/tasks.md', ''],
17
+ const SCAFFOLD_FILES = [
18
+ '.claude/settings.json',
23
19
  ];
24
20
 
25
- // Never touch: .claude/_features/, CLAUDE.md, .claude/testing.md
26
-
27
- function copyDir(srcDir, destDir) {
28
- fs.mkdirSync(destDir, { recursive: true });
29
- for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
30
- const srcPath = path.join(srcDir, entry.name);
31
- const destPath = path.join(destDir, entry.name);
21
+ function copyDir(src, dest) {
22
+ fs.mkdirSync(dest, { recursive: true });
23
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
24
+ const srcPath = path.join(src, entry.name);
25
+ const destPath = path.join(dest, entry.name);
32
26
  if (entry.isDirectory()) {
33
27
  copyDir(srcPath, destPath);
34
28
  } else {
@@ -37,33 +31,85 @@ function copyDir(srcDir, destDir) {
37
31
  }
38
32
  }
39
33
 
40
- const isUpdate = fs.existsSync(path.join(dest, '.claude'));
41
- console.log(isUpdate ? 'Syncing spec-starter...\n' : 'Installing spec-starter...\n');
34
+ // Copy scaffold
35
+ for (const dir of SCAFFOLD_DIRS) {
36
+ const src = path.join(PKG_DIR, dir);
37
+ const dest = path.join(TARGET_DIR, dir);
38
+ if (fs.existsSync(src)) copyDir(src, dest);
39
+ }
42
40
 
43
- fs.mkdirSync(path.join(dest, '.claude'), { recursive: true });
41
+ for (const file of SCAFFOLD_FILES) {
42
+ const src = path.join(PKG_DIR, file);
43
+ const dest = path.join(TARGET_DIR, file);
44
+ if (fs.existsSync(src)) {
45
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
46
+ fs.copyFileSync(src, dest);
47
+ }
48
+ }
44
49
 
45
- for (const dir of engineDirs) {
46
- copyDir(path.join(src, dir), path.join(dest, dir));
47
- console.log(` ✓ ${dir}`);
50
+ // Version tracking
51
+ const VERSION_FILE = path.join(TARGET_DIR, '.claude', '.spec-starter-version');
52
+ const CLAUDE_MD = path.join(TARGET_DIR, 'CLAUDE.md');
53
+
54
+ function readInstalledVersion() {
55
+ try {
56
+ return JSON.parse(fs.readFileSync(VERSION_FILE, 'utf8')).version;
57
+ } catch {
58
+ return null;
59
+ }
48
60
  }
49
61
 
50
- for (const file of engineFiles) {
51
- fs.mkdirSync(path.dirname(path.join(dest, file)), { recursive: true });
52
- fs.copyFileSync(path.join(src, file), path.join(dest, file));
53
- console.log(` ✓ ${file}`);
62
+ function writeInstalledVersion() {
63
+ fs.writeFileSync(VERSION_FILE, JSON.stringify({ version: VERSION }, null, 2));
54
64
  }
55
65
 
56
- for (const [file, content] of seedFiles) {
57
- const destFile = path.join(dest, file);
58
- if (!fs.existsSync(destFile)) {
59
- fs.writeFileSync(destFile, content);
60
- console.log(` ✓ ${file} (created)`);
66
+ // Bootstrap CLAUDE.md for fresh installs
67
+ function writeBootstrapClaudeMd() {
68
+ const content = `<!-- spec-starter:bootstrap -->
69
+ Run the \`project-init\` skill now. Do not do anything else first.
70
+ <!-- /spec-starter:bootstrap -->
71
+ `;
72
+ fs.writeFileSync(CLAUDE_MD, content);
73
+ }
74
+
75
+ // Inject update notice into existing CLAUDE.md
76
+ const NOTICE_START = '<!-- spec-starter:notice -->';
77
+ const NOTICE_END = '<!-- /spec-starter:notice -->';
78
+
79
+ function injectUpdateNotice() {
80
+ const notice = `${NOTICE_START}
81
+ spec-starter was updated to v${VERSION}. Let the user know what changed, then remove this notice block from CLAUDE.md.
82
+ ${NOTICE_END}`;
83
+
84
+ const existing = fs.readFileSync(CLAUDE_MD, 'utf8');
85
+
86
+ if (existing.includes(NOTICE_START)) {
87
+ // Replace existing notice
88
+ const updated = existing.replace(
89
+ new RegExp(`${NOTICE_START}[\\s\\S]*?${NOTICE_END}`),
90
+ notice
91
+ );
92
+ fs.writeFileSync(CLAUDE_MD, updated);
61
93
  } else {
62
- console.log(` - ${file} (kept existing)`);
94
+ // Prepend notice
95
+ fs.writeFileSync(CLAUDE_MD, notice + '\n\n' + existing);
63
96
  }
64
97
  }
65
98
 
66
- console.log(isUpdate
67
- ? '\nDone. Engine files updated, project data untouched.'
68
- : '\nDone. Run /project-init in Claude Code to set up your project.'
69
- );
99
+ // Main
100
+ const installedVersion = readInstalledVersion();
101
+ const claudeMdExists = fs.existsSync(CLAUDE_MD);
102
+
103
+ if (!claudeMdExists) {
104
+ writeBootstrapClaudeMd();
105
+ console.log(`spec-starter v${VERSION} installed.`);
106
+ console.log('Open Claude Code — project-init will run automatically.');
107
+ } else if (installedVersion !== VERSION) {
108
+ injectUpdateNotice();
109
+ console.log(`spec-starter updated to v${VERSION}.`);
110
+ console.log('Claude will announce the update next time you open this project.');
111
+ } else {
112
+ console.log(`spec-starter v${VERSION} refreshed.`);
113
+ }
114
+
115
+ writeInstalledVersion();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-starter",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Claude Code project template for structured feature development",
5
5
  "bin": {
6
6
  "spec-starter": "bin/index.js"