@eskoubar95/spec 0.1.4 → 0.1.5
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/dist/lib/copy-template.js +6 -6
- package/dist/lib/copy-template.js.map +1 -1
- package/package.json +2 -2
- package/template/.cursor/MCP-SETUP.md +16 -0
- package/template/.cursor/agents/batch-runner.md +52 -0
- package/template/.cursor/agents/verifier.md +40 -0
- package/template/.cursor/commands/_shared/branch-detection.md +78 -0
- package/template/.cursor/commands/_shared/git-workflow.md +3 -1
- package/template/.cursor/commands/_shared/github-workflows.md +7 -5
- package/template/.cursor/commands/_shared/helper-metadata.md +20 -0
- package/template/.cursor/commands/_shared/linear-automation.md +14 -6
- package/template/.cursor/commands/_shared/linear-helpers.md +26 -14
- package/template/.cursor/commands/_shared/pr-description.md +11 -2
- package/template/.cursor/commands/spec/init.md +33 -0
- package/template/.cursor/commands/spec/plan.md +43 -9
- package/template/.cursor/commands/spec/refine.md +7 -0
- package/template/.cursor/commands/task/batch.md +112 -0
- package/template/.cursor/commands/task/start.md +28 -6
- package/template/.cursor/commands/task/validate.md +19 -15
- package/template/.cursor/scripts/{validate-helpers.js → validate-helpers.cjs} +30 -32
- package/template/.cursor/skills/sdd-commit-unit/SKILL.md +42 -0
- package/template/.cursor/skills/sdd-design-system-bootstrap/SKILL.md +35 -0
- package/template/.cursor/skills/sdd-git-default-branch/SKILL.md +49 -0
- package/template/.cursor/skills/sdd-pr-create-or-update/SKILL.md +41 -0
- package/template/.cursor/skills/sdd-task-preflight/SKILL.md +47 -0
- package/template/.cursor/skills/sdd-validation-suite/SKILL.md +47 -0
- package/template/spec/00-root-spec.md +9 -0
- package/template/spec/templates/02-architecture.md +64 -0
- package/template/spec/templates/06-acceptance.md +59 -0
- package/template/spec/templates/07-design-system.md +145 -0
- package/template/spec/templates/08-infrastructure.md +76 -0
- package/template/spec/templates/09-sitemap.md +50 -0
- package/template/work/backlog/tasks.local.md +6 -0
- package/template/work/linear/FALLBACK-STRATEGY.md +84 -0
- package/template/work/linear/LABEL-MAPPING-GUIDE.md +72 -0
- package/template/work/linear/SETUP.md +75 -0
- package/template/work/linear/sync-config.md +86 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
You are an **Implementation Engineer** using Spec-Driven Development (SDD).
|
|
2
|
+
|
|
3
|
+
**Your role:** Implementation Engineer
|
|
4
|
+
**Your job:** Execute multiple tasks safely with clear scope, correctness, and discipline
|
|
5
|
+
**Your context:** Batch task execution (milestone or task list)
|
|
6
|
+
|
|
7
|
+
MODE: Execution / Batch
|
|
8
|
+
GOAL: Execute a batch of tasks sequentially while maintaining SDD discipline (one task at a time), Git hygiene, and validation evidence.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## State Assertion (REQUIRED)
|
|
13
|
+
|
|
14
|
+
**Before starting, output:**
|
|
15
|
+
|
|
16
|
+
**SDD MODE:** /task/batch
|
|
17
|
+
- **Mode:** Execution
|
|
18
|
+
- **Recommended Cursor Mode:** Agent
|
|
19
|
+
- **Why:** This command results in code changes across multiple tasks. Agent mode is optimal for multi-file changes and long runs.
|
|
20
|
+
- **Context:** [Milestone/task list, project detection summary, and batch policies]
|
|
21
|
+
- **Active Rule Sets:** [Will be populated after activation]
|
|
22
|
+
- **Implementation:** BLOCKED (until Step 3 confirmation)
|
|
23
|
+
- **Boundaries:**
|
|
24
|
+
- WILL: Execute tasks sequentially, validate each task, keep scope tight to the selected tasks
|
|
25
|
+
- WILL NOT: Expand scope beyond selected tasks, perform unrelated refactors, merge without validation evidence
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Step 0 — Project Detection and Rule Activation
|
|
30
|
+
|
|
31
|
+
Run detection and activation first (same as `/task/start`):
|
|
32
|
+
- Detect project type, size, phase, technologies (see `_shared/detection.md`)
|
|
33
|
+
- Activate relevant rules (see `_shared/activation.md`)
|
|
34
|
+
- Read tech stack from `spec/08-infrastructure.md` or `spec/02-architecture.md` if present
|
|
35
|
+
|
|
36
|
+
**If project is a monorepo (REQUIRED discipline):**
|
|
37
|
+
- Each task must have `**Workspace:** <path>` in `work/backlog/tasks.local.md`.
|
|
38
|
+
- If any selected task is missing `**Workspace:**` → **HARD STOP** before execution.
|
|
39
|
+
- Validate and build **per workspace**, not repo-wide.
|
|
40
|
+
|
|
41
|
+
## Step 1 — Select batch scope
|
|
42
|
+
|
|
43
|
+
Choose exactly one:
|
|
44
|
+
|
|
45
|
+
1) **Milestone batch**
|
|
46
|
+
- Read `work/backlog/milestones.md` and pick a milestone ID (e.g. `M3`)
|
|
47
|
+
- Collect its tasks from `work/backlog/tasks.local.md`
|
|
48
|
+
|
|
49
|
+
2) **Task list batch**
|
|
50
|
+
- Provide an ordered list of task IDs (e.g. `T1.1, T1.2, T1.3`)
|
|
51
|
+
- Verify each exists in `work/backlog/tasks.local.md`
|
|
52
|
+
|
|
53
|
+
## Step 2 — Define batch policies (must be explicit)
|
|
54
|
+
|
|
55
|
+
Set the following policies before execution:
|
|
56
|
+
|
|
57
|
+
- **Base branch**: resolve `defaultBranch` (do not assume `main`)
|
|
58
|
+
- Preferred: skill `/sdd-git-default-branch`
|
|
59
|
+
- Fallback: helper `_shared/branch-detection.md`
|
|
60
|
+
- **Branching**:
|
|
61
|
+
- One branch per task: `task/<task-id>-<short-description>`
|
|
62
|
+
- **Commit granularity**:
|
|
63
|
+
- Small logical units (recommended): skill `/sdd-commit-unit`
|
|
64
|
+
- Or: commit at task completion only
|
|
65
|
+
- **Validation**:
|
|
66
|
+
- Preferred: skill `/sdd-validation-suite`
|
|
67
|
+
- Or: project-specific scripts (lint/typecheck/tests/build) if present
|
|
68
|
+
- **PR strategy (optional)**:
|
|
69
|
+
- Preferred: skill `/sdd-pr-create-or-update` (with correct base branch)
|
|
70
|
+
- Or: manual PR creation after the batch
|
|
71
|
+
|
|
72
|
+
## Step 3 — Batch execution method (choose one)
|
|
73
|
+
|
|
74
|
+
### Option A (recommended): Use the `batch-runner` subagent
|
|
75
|
+
|
|
76
|
+
Launch the `batch-runner` subagent with:
|
|
77
|
+
|
|
78
|
+
- Batch scope (milestone ID or task list)
|
|
79
|
+
- Source-of-truth paths:
|
|
80
|
+
- `work/backlog/milestones.md`
|
|
81
|
+
- `work/backlog/tasks.local.md`
|
|
82
|
+
- `spec/tasks/**` (if present)
|
|
83
|
+
- Git policies:
|
|
84
|
+
- resolved `defaultBranch`
|
|
85
|
+
- branch naming rules
|
|
86
|
+
- commit policy
|
|
87
|
+
- Validation + PR policies
|
|
88
|
+
|
|
89
|
+
The subagent must return:
|
|
90
|
+
- completed task IDs
|
|
91
|
+
- blocked task IDs + reasons
|
|
92
|
+
- evidence (what ran; pass/fail)
|
|
93
|
+
- notes (risks/open questions discovered)
|
|
94
|
+
|
|
95
|
+
### Option B: Manual sequential execution (no subagent)
|
|
96
|
+
|
|
97
|
+
For each task in order:
|
|
98
|
+
1. Run `/task/start` for the task (preflight + branch)
|
|
99
|
+
2. Implement only what the task requires
|
|
100
|
+
3. Commit (per policy)
|
|
101
|
+
4. Run `/task/validate` for the task (per policy)
|
|
102
|
+
5. Record outcomes (what changed + evidence + next blocker)
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Completion criteria
|
|
107
|
+
|
|
108
|
+
This batch is complete when:
|
|
109
|
+
- Every task is either completed with validation evidence OR explicitly blocked with a reason
|
|
110
|
+
- No task is merged without validation evidence
|
|
111
|
+
- Any new risks/questions discovered are captured (`spec/03-risks.md`, `spec/04-open-questions.md`)
|
|
112
|
+
|
|
@@ -73,6 +73,24 @@ Inputs (source of truth):
|
|
|
73
73
|
- `spec/06-acceptance.md` (if it exists)
|
|
74
74
|
- `work/backlog/tasks.local.md`
|
|
75
75
|
|
|
76
|
+
## Step 0.9 — Workspace scope (REQUIRED for monorepos)
|
|
77
|
+
|
|
78
|
+
**ONLY EXECUTE IF:** detection indicates `projectType=monorepo`
|
|
79
|
+
|
|
80
|
+
Before selecting/implementing a task, ensure the task has an explicit workspace scope:
|
|
81
|
+
|
|
82
|
+
- If the task is local (from `tasks.local.md`):
|
|
83
|
+
- Read the task block and require `**Workspace:** <path>` (e.g. `apps/storefront`, `apps/backend`).
|
|
84
|
+
- If missing → **HARD STOP** and ask the user to add `**Workspace:**` to the task before continuing.
|
|
85
|
+
|
|
86
|
+
- If the task is a Linear issue:
|
|
87
|
+
- If the issue description contains a workspace path, use it.
|
|
88
|
+
- Otherwise → **HARD STOP** and ask the user to specify the workspace path for this task.
|
|
89
|
+
|
|
90
|
+
**Rules:**
|
|
91
|
+
- All commands (install/lint/typecheck/test/build) must be executed **scoped to the workspace**, not the repo root.
|
|
92
|
+
- If the monorepo uses pnpm/yarn/turbo/nx, prefer workspace-scoped commands (e.g., `pnpm -C <workspace> …` or `npm --prefix <workspace> …`).
|
|
93
|
+
|
|
76
94
|
Step 1 — Select the task
|
|
77
95
|
|
|
78
96
|
**Support for både local og Linear tasks:**
|
|
@@ -111,8 +129,9 @@ Step 1 — Select the task
|
|
|
111
129
|
- If status not found → guide user to create custom status
|
|
112
130
|
|
|
113
131
|
3. **Create Linear comment:**
|
|
114
|
-
- Add comment to Linear issue:
|
|
115
|
-
|
|
132
|
+
- Add a structured comment to Linear issue:
|
|
133
|
+
- “Started `<task-id>` via SDD. Branch: `<branch>`. Plan: `<1–3 bullets>`.”
|
|
134
|
+
- If task-level spec exists → add a second comment with a short spec summary + acceptance focus
|
|
116
135
|
|
|
117
136
|
**Error Handling:**
|
|
118
137
|
- If Linear MCP unavailable → continue with local mode only
|
|
@@ -230,10 +249,13 @@ Before implementation, ensure:
|
|
|
230
249
|
- If uncommitted changes exist → pause and ask: "Uncommitted changes detected. Commit, stash, or discard?"
|
|
231
250
|
- If untracked files exist → pause and ask: "Untracked files detected. Should they be committed?"
|
|
232
251
|
|
|
233
|
-
2. Ensure clean
|
|
234
|
-
-
|
|
235
|
-
|
|
236
|
-
|
|
252
|
+
2. Ensure clean base branch (project-agnostic):
|
|
253
|
+
- Resolve `defaultBranch` (do not assume `main`) using one of:
|
|
254
|
+
- Skill (Cursor 2.4+): `/sdd-git-default-branch`
|
|
255
|
+
- Helper: `.cursor/commands/_shared/branch-detection.md` (if present in the project)
|
|
256
|
+
- Checkout base branch: `git checkout <default-branch>`
|
|
257
|
+
- Pull latest changes (if remote exists): `git pull origin <default-branch>`
|
|
258
|
+
- Verify base is clean (no uncommitted changes)
|
|
237
259
|
|
|
238
260
|
3. Create task branch:
|
|
239
261
|
- Branch name format: `task/{task-id}-{short-description}` (e.g., `task/t1.2-setup-database`)
|
|
@@ -78,6 +78,14 @@ Ask what evidence exists:
|
|
|
78
78
|
- Manual verification steps
|
|
79
79
|
- Screenshots, logs, or other proof
|
|
80
80
|
|
|
81
|
+
## Workspace scope (REQUIRED for monorepos)
|
|
82
|
+
|
|
83
|
+
**ONLY EXECUTE IF:** detection indicates `projectType=monorepo`
|
|
84
|
+
|
|
85
|
+
- Require an explicit workspace scope for the task (from `work/backlog/tasks.local.md` `**Workspace:**` or from the Linear issue description).
|
|
86
|
+
- Run validation commands scoped to that workspace only.
|
|
87
|
+
- If workspace scope is missing → **HARD STOP** and require the user to define it (do not run repo-wide validation).
|
|
88
|
+
|
|
81
89
|
**Documentation Lookup (if framework-specific issue found):**
|
|
82
90
|
|
|
83
91
|
**ONLY READ IF framework/tool detected or documentation needed:**
|
|
@@ -177,21 +185,22 @@ Assess whether the task is:
|
|
|
177
185
|
1. Pre-merge checks:
|
|
178
186
|
- Verify all changes are committed
|
|
179
187
|
- Run build/test (if applicable)
|
|
180
|
-
-
|
|
188
|
+
- Resolve `defaultBranch` (do not assume `main`) using `/sdd-git-default-branch` or `branch-detection.md`
|
|
189
|
+
- Check for merge conflicts with base: `git fetch origin <default-branch> && git merge-base HEAD origin/<default-branch>`
|
|
181
190
|
|
|
182
|
-
2. Merge to
|
|
183
|
-
- Checkout
|
|
184
|
-
- Pull latest (if remote exists): `git pull origin
|
|
191
|
+
2. Merge to base branch:
|
|
192
|
+
- Checkout base (default branch): `git checkout <default-branch>`
|
|
193
|
+
- Pull latest (if remote exists): `git pull origin <default-branch>`
|
|
185
194
|
- Merge task branch: `git merge task/{task-id}-{short-description}`
|
|
186
|
-
- Push to remote (if configured): `git push origin
|
|
195
|
+
- Push to remote (if configured): `git push origin <default-branch>`
|
|
187
196
|
|
|
188
197
|
3. Post-merge cleanup:
|
|
189
198
|
- Delete local task branch (optional, ask first): `git branch -d task/{task-id}-{short-description}`
|
|
190
|
-
- Verify
|
|
199
|
+
- Verify base branch is clean
|
|
191
200
|
|
|
192
201
|
**Ask user preference:**
|
|
193
202
|
- "Should I auto-commit on task completion?" (if not already committed)
|
|
194
|
-
- "Should I auto-merge to
|
|
203
|
+
- "Should I auto-merge to the base branch on validation?" (if validated)
|
|
195
204
|
- "Should I delete task branch after merge?" (optional)
|
|
196
205
|
|
|
197
206
|
If follow-up is required:
|
|
@@ -226,14 +235,9 @@ Conclude with one of the following outcomes:
|
|
|
226
235
|
- If status not found → guide user to create custom status
|
|
227
236
|
|
|
228
237
|
3. **Create Linear comment with validation summary:**
|
|
229
|
-
- Add comment to Linear issue:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
Acceptance criteria: [summary]
|
|
233
|
-
Issues found: [list] (if any)
|
|
234
|
-
Next steps: [list] (if any)"
|
|
235
|
-
```
|
|
236
|
-
- Include relevant context from validation
|
|
238
|
+
- Add a structured comment to Linear issue (recommended format):
|
|
239
|
+
- “Validated `<task-id>` via SDD: `<pass/fail>`. Evidence: `<lint/tests/build>`. PR: `<url>` (if any).”
|
|
240
|
+
- Include acceptance summary (1–3 bullets) and any follow-up actions (if any)
|
|
237
241
|
|
|
238
242
|
**Error Handling:**
|
|
239
243
|
- If Linear MCP unavailable → continue without Linear update
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Helper Metadata Validation Script
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* Validates helper metadata for consistency and correctness:
|
|
7
7
|
* - All helpers have YAML frontmatter
|
|
8
8
|
* - Section line ranges match actual section markers
|
|
@@ -33,17 +33,17 @@ function log(message, color = 'reset') {
|
|
|
33
33
|
function parseYAMLFrontmatter(content) {
|
|
34
34
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
35
35
|
if (!frontmatterMatch) return null;
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
const frontmatter = {};
|
|
38
38
|
const lines = frontmatterMatch[1].split('\n');
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
let currentKey = null;
|
|
41
41
|
let currentValue = [];
|
|
42
42
|
let inArray = false;
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
for (const line of lines) {
|
|
45
45
|
if (line.trim() === '') continue;
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
// Check for array start
|
|
48
48
|
if (line.match(/^(\s*)([a-z_]+):\s*$/)) {
|
|
49
49
|
if (currentKey) {
|
|
@@ -54,13 +54,13 @@ function parseYAMLFrontmatter(content) {
|
|
|
54
54
|
inArray = true;
|
|
55
55
|
continue;
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
// Check for array item
|
|
59
59
|
if (inArray && line.match(/^\s*-\s*(.+)$/)) {
|
|
60
60
|
currentValue.push(line.match(/^\s*-\s*(.+)$/)[1]);
|
|
61
61
|
continue;
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
// Check for key-value
|
|
65
65
|
if (line.match(/^(\s*)([a-z_]+):\s*(.+)$/)) {
|
|
66
66
|
if (currentKey) {
|
|
@@ -72,25 +72,25 @@ function parseYAMLFrontmatter(content) {
|
|
|
72
72
|
inArray = false;
|
|
73
73
|
continue;
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
// Check for nested structure (sections)
|
|
77
77
|
if (line.match(/^\s+([a-z_]+):/)) {
|
|
78
78
|
// This is a nested key, skip for now (simplified parsing)
|
|
79
79
|
continue;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
if (currentKey) {
|
|
84
84
|
frontmatter[currentKey] = currentValue.length === 1 ? currentValue[0] : currentValue;
|
|
85
85
|
}
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
return frontmatter;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
function findSectionMarkers(content) {
|
|
91
91
|
const sections = [];
|
|
92
92
|
const lines = content.split('\n');
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
for (let i = 0; i < lines.length; i++) {
|
|
95
95
|
const line = lines[i];
|
|
96
96
|
const sectionMatch = line.match(/^## Section: (.+?) \(Lines (\d+)-(\d+)\)$/);
|
|
@@ -103,7 +103,7 @@ function findSectionMarkers(content) {
|
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
return sections;
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -111,14 +111,14 @@ function validateHelper(helperFile) {
|
|
|
111
111
|
const filePath = path.join(HELPERS_DIR, helperFile);
|
|
112
112
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
113
113
|
const issues = [];
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
// 1. Check frontmatter exists
|
|
116
116
|
const frontmatter = parseYAMLFrontmatter(content);
|
|
117
117
|
if (!frontmatter) {
|
|
118
118
|
issues.push({ type: 'error', message: 'Missing YAML frontmatter' });
|
|
119
119
|
return { file: helperFile, issues };
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
// 2. Check required fields
|
|
123
123
|
const requiredFields = ['helper_id', 'load_when', 'sections', 'always_load'];
|
|
124
124
|
for (const field of requiredFields) {
|
|
@@ -126,7 +126,7 @@ function validateHelper(helperFile) {
|
|
|
126
126
|
issues.push({ type: 'error', message: `Missing required field: ${field}` });
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
|
|
130
130
|
// 3. Check section markers match metadata
|
|
131
131
|
const sections = findSectionMarkers(content);
|
|
132
132
|
if (sections.length > 0 && frontmatter.sections) {
|
|
@@ -141,23 +141,22 @@ function validateHelper(helperFile) {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
-
|
|
144
|
+
|
|
145
145
|
return { file: helperFile, frontmatter, sections, issues };
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
function validateRegistry() {
|
|
149
149
|
const content = fs.readFileSync(METADATA_FILE, 'utf-8');
|
|
150
|
-
const helperFiles = fs.readdirSync(HELPERS_DIR)
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
const helperFiles = fs.readdirSync(HELPERS_DIR).filter((f) => f.endsWith('.md') && f !== 'helper-metadata.md');
|
|
151
|
+
|
|
153
152
|
const registryHelpers = [];
|
|
154
153
|
const registryMatch = content.match(/### ([a-z-]+)\.md/g);
|
|
155
154
|
if (registryMatch) {
|
|
156
|
-
registryHelpers.push(...registryMatch.map(m => m.replace('### ', '').replace('.md', '')));
|
|
155
|
+
registryHelpers.push(...registryMatch.map((m) => m.replace('### ', '').replace('.md', '')));
|
|
157
156
|
}
|
|
158
|
-
|
|
157
|
+
|
|
159
158
|
const issues = [];
|
|
160
|
-
|
|
159
|
+
|
|
161
160
|
// Check all helpers are in registry
|
|
162
161
|
for (const helperFile of helperFiles) {
|
|
163
162
|
const helperId = helperFile.replace('.md', '');
|
|
@@ -168,7 +167,7 @@ function validateRegistry() {
|
|
|
168
167
|
});
|
|
169
168
|
}
|
|
170
169
|
}
|
|
171
|
-
|
|
170
|
+
|
|
172
171
|
// Check registry has all helpers
|
|
173
172
|
for (const registryHelper of registryHelpers) {
|
|
174
173
|
if (!helperFiles.includes(`${registryHelper}.md`)) {
|
|
@@ -178,20 +177,19 @@ function validateRegistry() {
|
|
|
178
177
|
});
|
|
179
178
|
}
|
|
180
179
|
}
|
|
181
|
-
|
|
180
|
+
|
|
182
181
|
return { helperFiles, registryHelpers, issues };
|
|
183
182
|
}
|
|
184
183
|
|
|
185
184
|
function main() {
|
|
186
185
|
log('🔍 Validating Helper Metadata...\n', 'blue');
|
|
187
|
-
|
|
188
|
-
const helperFiles = fs.readdirSync(HELPERS_DIR)
|
|
189
|
-
|
|
190
|
-
|
|
186
|
+
|
|
187
|
+
const helperFiles = fs.readdirSync(HELPERS_DIR).filter((f) => f.endsWith('.md') && f !== 'helper-metadata.md');
|
|
188
|
+
|
|
191
189
|
let totalIssues = 0;
|
|
192
190
|
let totalErrors = 0;
|
|
193
191
|
let totalWarnings = 0;
|
|
194
|
-
|
|
192
|
+
|
|
195
193
|
// Validate each helper
|
|
196
194
|
for (const helperFile of helperFiles) {
|
|
197
195
|
const result = validateHelper(helperFile);
|
|
@@ -211,11 +209,11 @@ function main() {
|
|
|
211
209
|
log(`✅ ${helperFile}`, 'green');
|
|
212
210
|
}
|
|
213
211
|
}
|
|
214
|
-
|
|
212
|
+
|
|
215
213
|
// Validate registry
|
|
216
214
|
log('\n📋 Validating Helper Registry...\n', 'blue');
|
|
217
215
|
const registryResult = validateRegistry();
|
|
218
|
-
|
|
216
|
+
|
|
219
217
|
if (registryResult.issues.length > 0) {
|
|
220
218
|
for (const issue of registryResult.issues) {
|
|
221
219
|
if (issue.type === 'error') {
|
|
@@ -230,7 +228,7 @@ function main() {
|
|
|
230
228
|
} else {
|
|
231
229
|
log('✅ Helper registry is consistent', 'green');
|
|
232
230
|
}
|
|
233
|
-
|
|
231
|
+
|
|
234
232
|
// Summary
|
|
235
233
|
log('\n' + '='.repeat(50), 'blue');
|
|
236
234
|
if (totalIssues === 0) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-commit-unit
|
|
3
|
+
description: Create small, reviewable commits per logical unit of work with consistent messages tied to the task ID. Use during implementation and batch runs.
|
|
4
|
+
metadata:
|
|
5
|
+
sdd_category: git
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# SDD: Commit a Logical Unit
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
- After completing a coherent step (not after every file).
|
|
13
|
+
- Before switching focus or running validation.
|
|
14
|
+
- During batch runs after each “unit” completes.
|
|
15
|
+
|
|
16
|
+
## Inputs
|
|
17
|
+
|
|
18
|
+
- Task ID (from `work/backlog/tasks.local.md` or user input)
|
|
19
|
+
- Current diff (`git diff` and `git status`)
|
|
20
|
+
- Commit message style: concise, why-focused, task-linked
|
|
21
|
+
|
|
22
|
+
## Output contract
|
|
23
|
+
|
|
24
|
+
Return:
|
|
25
|
+
- `commitCreated`: yes/no
|
|
26
|
+
- `commitHash` (if created)
|
|
27
|
+
- `message`
|
|
28
|
+
- `filesChangedSummary`
|
|
29
|
+
|
|
30
|
+
## Rules
|
|
31
|
+
|
|
32
|
+
- Never commit secrets (`.env`, credential files, tokens).
|
|
33
|
+
- If there are no changes, do not create an empty commit.
|
|
34
|
+
- Keep commits small and reviewable; split if multiple concerns.
|
|
35
|
+
|
|
36
|
+
## Suggested commit message pattern
|
|
37
|
+
|
|
38
|
+
- Title: `<task-id>: <verb> <scope> (<why>)`
|
|
39
|
+
- Body (optional): 1–3 bullets explaining intent and risk
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
- `t1.2: add branch detection helper (avoid hardcoded main)`
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-design-system-bootstrap
|
|
3
|
+
description: Bootstrap a usable design system early (Tailwind + shadcn/ui) to avoid design babysitting later. Produces spec/07-design-system.md and a UI Definition of Done checklist.
|
|
4
|
+
metadata:
|
|
5
|
+
sdd_category: design
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# SDD: Design System Bootstrap (Tailwind + shadcn/ui)
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
- During `/spec/init` or `/spec/refine` when design direction is unclear or repeatedly causes rework.
|
|
13
|
+
- Before `/spec/plan` so design work can be turned into concrete, non-babysat tasks.
|
|
14
|
+
|
|
15
|
+
## Inputs (ask if missing)
|
|
16
|
+
|
|
17
|
+
- Product vibe / adjectives (3–5)
|
|
18
|
+
- Target surfaces (primary screens + whether data-dense)
|
|
19
|
+
- Brand constraints (logo, existing colors, typography)
|
|
20
|
+
- Accessibility target (default: WCAG AA)
|
|
21
|
+
|
|
22
|
+
## Output contract
|
|
23
|
+
|
|
24
|
+
Produce or update `spec/07-design-system.md` with:
|
|
25
|
+
- Style direction (do/don’t)
|
|
26
|
+
- Token table (semantic colors, typography, spacing, radius/shadows)
|
|
27
|
+
- Component conventions (shadcn/ui)
|
|
28
|
+
- UI patterns (nav/forms/tables/states)
|
|
29
|
+
- UI Definition of Done checklist
|
|
30
|
+
|
|
31
|
+
## Rules
|
|
32
|
+
|
|
33
|
+
- Make it usable, not aspirational.
|
|
34
|
+
- Prefer semantic tokens over raw colors.
|
|
35
|
+
- Keep it compatible with Tailwind + shadcn/ui defaults (can be overridden intentionally).
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-git-default-branch
|
|
3
|
+
description: Resolve default/development/production branches consistently across projects. Use before creating task branches, counting commits, creating PRs, or generating diffs.
|
|
4
|
+
metadata:
|
|
5
|
+
sdd_category: git
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# SDD: Resolve Git Default Branch
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
- You are about to create a task branch.
|
|
13
|
+
- You need to compute diffs/commit counts against the base branch.
|
|
14
|
+
- You are about to create or update a PR.
|
|
15
|
+
- You see any workflow text hardcoding `main`/`develop`/`staging` and need to make it project-agnostic.
|
|
16
|
+
|
|
17
|
+
## Inputs
|
|
18
|
+
|
|
19
|
+
- Optional: `.sdd/git-config.json` (project-specific config; preferred)
|
|
20
|
+
- Git remote metadata: `origin` HEAD branch (if available)
|
|
21
|
+
- Local/remote branch existence
|
|
22
|
+
|
|
23
|
+
## Output contract (what you must return)
|
|
24
|
+
|
|
25
|
+
Return a short structured result:
|
|
26
|
+
|
|
27
|
+
- `defaultBranch`: the branch to use as PR base and “clean base” checkout
|
|
28
|
+
- `developmentBranch`: optional; defaults to `defaultBranch` if not known
|
|
29
|
+
- `productionBranch`: optional; defaults to `defaultBranch` if not known
|
|
30
|
+
- `source`: `config` | `remoteHead` | `fallback`
|
|
31
|
+
|
|
32
|
+
## Algorithm (project-agnostic)
|
|
33
|
+
|
|
34
|
+
1. **Config (highest priority)**: If `.sdd/git-config.json` exists, read:
|
|
35
|
+
- `default_branch` OR `development_branch` as `defaultBranch`
|
|
36
|
+
- `development_branch` as `developmentBranch` (fallback: `defaultBranch`)
|
|
37
|
+
- `production_branch` as `productionBranch` (fallback: `defaultBranch`)
|
|
38
|
+
2. **Remote HEAD**: If `origin` exists, read the remote default branch (e.g., `git remote show origin` and parse `HEAD branch`).
|
|
39
|
+
3. **Fallback**: If remote HEAD is unavailable, pick the first existing branch in this order (local OR remote):
|
|
40
|
+
- `main`
|
|
41
|
+
- `master`
|
|
42
|
+
- `develop`
|
|
43
|
+
4. If nothing is detectable, return `defaultBranch: "main"` and include a warning in your explanation.
|
|
44
|
+
|
|
45
|
+
## Rules
|
|
46
|
+
|
|
47
|
+
- Do not assume `staging` exists. If a project uses `staging`, it should be configured in `.sdd/git-config.json`.
|
|
48
|
+
- Never hardcode `main` as “the” default branch in documentation. Use `defaultBranch` (resolved by this skill).
|
|
49
|
+
- If the project has `work/backlog/tasks.local.md`, include the task ID in downstream commit/PR titles (but this skill itself only resolves branches).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-pr-create-or-update
|
|
3
|
+
description: Create or update a PR with correct base branch, task-linked title, and a structured body (changes, testing, acceptance). Use after validation or at milestone boundaries.
|
|
4
|
+
metadata:
|
|
5
|
+
sdd_category: github
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# SDD: Create or Update Pull Request
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
- After `/task/validate` passes (or passes with known exceptions).
|
|
13
|
+
- During `/task/batch` when configured to open PRs per task or per milestone.
|
|
14
|
+
|
|
15
|
+
## Inputs
|
|
16
|
+
|
|
17
|
+
- Base branch: resolve via `/sdd-git-default-branch`
|
|
18
|
+
- Task ID + short title
|
|
19
|
+
- Git changes: commits since base branch, `git diff <base>...HEAD --stat`
|
|
20
|
+
- Validation result summary (lint/tests/build)
|
|
21
|
+
|
|
22
|
+
## Output contract
|
|
23
|
+
|
|
24
|
+
Return:
|
|
25
|
+
- `action`: created/updated/noop
|
|
26
|
+
- `prUrl` (if created/updated)
|
|
27
|
+
- `baseBranchUsed`
|
|
28
|
+
|
|
29
|
+
## Body template
|
|
30
|
+
|
|
31
|
+
Use a structured PR body:
|
|
32
|
+
|
|
33
|
+
- **Summary**: 1–3 bullets
|
|
34
|
+
- **Test plan**: checklist
|
|
35
|
+
- **Notes / risks**: optional
|
|
36
|
+
|
|
37
|
+
## Rules
|
|
38
|
+
|
|
39
|
+
- Never assume base is `main`.
|
|
40
|
+
- Prefer updating an existing PR over creating duplicates.
|
|
41
|
+
- Do not push unless user asked to push (or the workflow explicitly requires it).
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-task-preflight
|
|
3
|
+
description: Prepare a task workspace safely before implementation: clean working tree, correct base branch, and task branch naming. Use before /task/start execution work.
|
|
4
|
+
metadata:
|
|
5
|
+
sdd_category: git
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# SDD: Task Preflight (Git Safety)
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
- Right before starting implementation for a task (single task or batch task).
|
|
13
|
+
- When you suspect you’re on the wrong branch or have dirty state.
|
|
14
|
+
|
|
15
|
+
## Inputs
|
|
16
|
+
|
|
17
|
+
- Task context (ideally: `taskId`, short description)
|
|
18
|
+
- Repo state: `git status`, current branch, remotes
|
|
19
|
+
- Base branch: resolve via `/sdd-git-default-branch` (preferred) or helper `branch-detection.md`
|
|
20
|
+
|
|
21
|
+
## Output contract
|
|
22
|
+
|
|
23
|
+
Return:
|
|
24
|
+
- `baseBranch`
|
|
25
|
+
- `taskBranch`
|
|
26
|
+
- `actionsTaken` (bullets)
|
|
27
|
+
- `blockingIssues` (bullets; empty if none)
|
|
28
|
+
|
|
29
|
+
## Procedure
|
|
30
|
+
|
|
31
|
+
1. **Validate working tree is clean**
|
|
32
|
+
- If dirty/untracked: stop and report as `blockingIssues` (do not auto-stash).
|
|
33
|
+
2. **Resolve `baseBranch`**
|
|
34
|
+
- Use `/sdd-git-default-branch` to resolve `defaultBranch`.
|
|
35
|
+
3. **Ensure base branch is up to date**
|
|
36
|
+
- Checkout `baseBranch`
|
|
37
|
+
- If remote exists: pull latest (`git pull origin <baseBranch>`)
|
|
38
|
+
4. **Create/checkout task branch**
|
|
39
|
+
- Naming: `task/<task-id>-<short-description>` (kebab-case)
|
|
40
|
+
- If exists locally: checkout
|
|
41
|
+
- Else: create from `baseBranch`
|
|
42
|
+
|
|
43
|
+
## Rules
|
|
44
|
+
|
|
45
|
+
- Never merge/rebase in preflight.
|
|
46
|
+
- Never commit anything in preflight.
|
|
47
|
+
- Never assume `main`.
|