bigpowers 1.5.1 → 2.0.1
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/CHANGELOG.md +35 -0
- package/CONVENTIONS.md +18 -2
- package/README.md +39 -13
- package/RELEASE.md +16 -1
- package/SKILL-INDEX.md +3 -3
- package/assess-impact/SKILL.md +2 -2
- package/build-epic/SKILL.md +5 -5
- package/change-request/SKILL.md +4 -4
- package/dashboard/src/loaders/reader.js +2 -1
- package/dashboard/src/tui/epic-queue.js +2 -0
- package/dashboard/src/tui/filesystem.js +5 -6
- package/dashboard/src/tui/index.js +39 -13
- package/dashboard/src/tui/ledger.js +3 -5
- package/dashboard/src/tui/metrics-bar.js +20 -3
- package/dashboard/src/tui/pipeline.js +9 -13
- package/dashboard/src/tui/state-yaml.js +6 -8
- package/deepen-architecture/SKILL.md +6 -6
- package/define-success/SKILL.md +1 -1
- package/develop-tdd/SKILL.md +3 -3
- package/elaborate-spec/SKILL.md +7 -7
- package/execute-plan/SKILL.md +4 -4
- package/investigate-bug/SKILL.md +1 -1
- package/kickoff-branch/SKILL.md +1 -1
- package/map-codebase/SKILL.md +4 -4
- package/migrate-spec/SKILL.md +8 -8
- package/model-domain/SKILL.md +8 -8
- package/orchestrate-project/REFERENCE.md +8 -4
- package/orchestrate-project/SKILL.md +2 -2
- package/package.json +1 -1
- package/plan-release/SKILL.md +73 -27
- package/plan-work/SKILL.md +23 -7
- package/release-branch/SKILL.md +15 -0
- package/research-first/SKILL.md +2 -2
- package/run-evals/SKILL.md +2 -2
- package/run-planning/SKILL.md +1 -1
- package/scope-work/SKILL.md +4 -4
- package/scripts/land-branch.sh +28 -0
- package/seed-conventions/SKILL.md +37 -6
- package/session-state/SKILL.md +34 -3
- package/slice-tasks/SKILL.md +4 -4
- package/survey-context/SKILL.md +2 -2
- package/trace-requirement/SKILL.md +6 -6
- package/verify-work/SKILL.md +35 -2
- package/write-document/SKILL.md +1 -1
- package/dashboard/src/data/gate-status.js +0 -32
- package/dashboard/src/data/metrics.js +0 -89
- package/dashboard/src/data/pipeline-map.js +0 -32
- package/dashboard/src/data/reader.js +0 -122
- package/dashboard/src/data/watcher.js +0 -108
package/run-evals/SKILL.md
CHANGED
|
@@ -20,8 +20,8 @@ model: sonnet
|
|
|
20
20
|
|
|
21
21
|
## Artefact
|
|
22
22
|
|
|
23
|
-
`specs/
|
|
23
|
+
`specs/verifications/eNNsYY-eval-report.md` — see [REFERENCE.md](REFERENCE.md) for template. Eval reports are stored alongside verification evidence in `specs/verifications/`, keyed by story ID for traceability.
|
|
24
24
|
|
|
25
25
|
## Verify
|
|
26
26
|
|
|
27
|
-
→ verify: `
|
|
27
|
+
→ verify: `find specs/verifications -name "*-eval-report.md" | wc -l | awk '{if($1>0) print "OK: "$1" eval reports"; else print "MISSING"}'`
|
package/run-planning/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: Advance discover-phase workflows and update specs/planning-status.y
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Run Planning
|
|
8
|
-
> **HARD GATE** — **HARD GATE** — Before running planning skills, confirm the epic
|
|
8
|
+
> **HARD GATE** — **HARD GATE** — Before running planning skills, confirm the epic capsule exists and the active story is clear. Planning without a target is noise.
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
Updates `specs/planning-status.yaml` as discover-phase skills complete.
|
package/scope-work/SKILL.md
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scope-work
|
|
3
|
-
description: Define what is in and out of scope for the current effort and save as specs/
|
|
3
|
+
description: Define what is in and out of scope for the current effort and save as specs/product/SCOPE_LATEST.yaml. Use when user wants a PRD, scope definition, or before plan-release on a new initiative.
|
|
4
4
|
model: sonnet
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Scope Work
|
|
8
8
|
|
|
9
|
-
Turn the current conversation into a bounded PRD at `specs/
|
|
9
|
+
Turn the current conversation into a bounded PRD at `specs/product/SCOPE_LATEST.yaml`.
|
|
10
10
|
|
|
11
11
|
## Process
|
|
12
12
|
|
|
13
13
|
1. Read existing `specs/` artifacts (`release-plan.yaml`, `plans/TECH_STACK_LATEST.md`, `requirements/VISION_LATEST.yaml` if any).
|
|
14
14
|
2. Interview (if needed): goal, users, in-scope, out-of-scope, constraints, success metrics.
|
|
15
|
-
3. Write `specs/
|
|
15
|
+
3. Write `specs/product/SCOPE_LATEST.yaml` with: `core_value`, `summary`, `in_scope[]`, `out_of_scope[]`, `constraints`, `success_criteria`, `references`.
|
|
16
16
|
4. Run `research-first` if external dependencies are proposed.
|
|
17
17
|
|
|
18
18
|
> **HARD GATE** — Every `in_scope` item must map to a future epic/story ID or explicit deferred note in `out_of_scope`.
|
|
19
19
|
|
|
20
20
|
## Verify
|
|
21
21
|
|
|
22
|
-
→ verify: `test -f specs/
|
|
22
|
+
→ verify: `test -f specs/product/SCOPE_LATEST.yaml && grep -c 'out_of_scope' specs/product/SCOPE_LATEST.yaml | awk '{if($1>0) print "OK"; else print "MISSING"}'`
|
package/scripts/land-branch.sh
CHANGED
|
@@ -143,6 +143,34 @@ if git remote get-url origin >/dev/null 2>&1; then
|
|
|
143
143
|
git push origin "$DEFAULT_BRANCH"
|
|
144
144
|
fi
|
|
145
145
|
|
|
146
|
+
# Epic capsule archival (evolved bigpowers v4.0.0+)
|
|
147
|
+
# Move completed epic capsules to archive when all stories are done
|
|
148
|
+
echo "==> Checking for completed epic capsules to archive..."
|
|
149
|
+
if [ -d specs/epics ] && [ -f specs/execution-status.yaml ]; then
|
|
150
|
+
for capsule in specs/epics/e[0-9]*-*/; do
|
|
151
|
+
[ -d "$capsule" ] || continue
|
|
152
|
+
capsule_name=$(basename "$capsule")
|
|
153
|
+
epic_id=$(echo "$capsule_name" | grep -o '^e[0-9]*' || true)
|
|
154
|
+
[ -n "$epic_id" ] || continue
|
|
155
|
+
# Check if all stories in this epic are done
|
|
156
|
+
ALL_DONE=true
|
|
157
|
+
if [ -f "$capsule/epic.yaml" ]; then
|
|
158
|
+
for story_id in $(grep -o 'e[0-9]*s[0-9]*' "$capsule/epic.yaml" 2>/dev/null || true); do
|
|
159
|
+
STATUS=$(grep "$story_id:" specs/execution-status.yaml 2>/dev/null | awk '{print $2}' || echo "todo")
|
|
160
|
+
if [ "$STATUS" != "done" ]; then
|
|
161
|
+
ALL_DONE=false
|
|
162
|
+
break
|
|
163
|
+
fi
|
|
164
|
+
done
|
|
165
|
+
fi
|
|
166
|
+
if [ "$ALL_DONE" = true ]; then
|
|
167
|
+
mkdir -p specs/epics/archive
|
|
168
|
+
echo " Archiving completed epic: $capsule_name → specs/epics/archive/"
|
|
169
|
+
mv "$capsule" "specs/epics/archive/"
|
|
170
|
+
fi
|
|
171
|
+
done
|
|
172
|
+
fi
|
|
173
|
+
|
|
146
174
|
# Worktree cleanup
|
|
147
175
|
WORKTREE_PATH="../$FEATURE_BRANCH"
|
|
148
176
|
if git worktree list --porcelain 2>/dev/null | grep -q "^worktree $WORKTREE_PATH$"; then
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: seed-conventions
|
|
3
3
|
model: sonnet
|
|
4
|
-
description: Generate CLAUDE.md and CONVENTIONS.md for a brand-new project through a brief interview, and create the specs/ directory. Entry point for greenfield projects. Use when starting a new project from scratch, when user asks to set up AI agent conventions, or when there is no CLAUDE.md yet.
|
|
4
|
+
description: Generate CLAUDE.md and CONVENTIONS.md for a brand-new project through a brief interview, and create the specs/ directory with evolved bigpowers structure (product/, tech-architecture/, verifications/, epics/archive/). Entry point for greenfield projects. Use when starting a new project from scratch, when user asks to set up AI agent conventions, or when there is no CLAUDE.md yet.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Seed Conventions
|
|
@@ -75,7 +75,7 @@ Stack: [language, framework, runtime]
|
|
|
75
75
|
## Agent Rules
|
|
76
76
|
- **Workflow Mandate:** You MUST use the bigpowers skills (e.g. `plan-work`, `develop-tdd`, `orchestrate-project`) to perform tasks. DO NOT write code directly in response to a user prompt like "build this feature".
|
|
77
77
|
- Read specs/ before writing code.
|
|
78
|
-
- All planning and specifications MUST be written to `specs/` (`
|
|
78
|
+
- All planning and specifications MUST be written to `specs/` (`product/SCOPE_LATEST.yaml`, `release-plan.yaml`, `epics/`) before any code is generated.
|
|
79
79
|
- Write the minimum code that solves the stated problem. Nothing extra.
|
|
80
80
|
- Never refactor, rename, or reorganize code outside the task scope.
|
|
81
81
|
- Run tests after every change. Show evidence before declaring done.
|
|
@@ -115,7 +115,7 @@ Stack: [language, framework, runtime]
|
|
|
115
115
|
## Agent Rules
|
|
116
116
|
- **Workflow Mandate:** You MUST use the bigpowers skills (e.g. `plan-work`, `develop-tdd`, `orchestrate-project`) to perform tasks. DO NOT write code directly in response to a user prompt like "build this feature".
|
|
117
117
|
- Read specs/ before writing code.
|
|
118
|
-
- All planning and specifications MUST be written to `specs/` (`
|
|
118
|
+
- All planning and specifications MUST be written to `specs/` (`product/SCOPE_LATEST.yaml`, `release-plan.yaml`, `epics/`) before any code is generated.
|
|
119
119
|
- Write the minimum code that solves the stated problem. Nothing extra.
|
|
120
120
|
- Never refactor, rename, or reorganize code outside the task scope.
|
|
121
121
|
- Run tests after every change. Show evidence before declaring done.
|
|
@@ -155,7 +155,7 @@ Stack: [language, framework, runtime]
|
|
|
155
155
|
## Agent Rules
|
|
156
156
|
- **Workflow Mandate:** You MUST use the bigpowers skills (e.g. `plan-work`, `develop-tdd`, `orchestrate-project`) to perform tasks. DO NOT write code directly in response to a user prompt like "build this feature".
|
|
157
157
|
- Read specs/ before writing code.
|
|
158
|
-
- All planning and specifications MUST be written to `specs/` (`
|
|
158
|
+
- All planning and specifications MUST be written to `specs/` (`product/SCOPE_LATEST.yaml`, `release-plan.yaml`, `epics/`) before any code is generated.
|
|
159
159
|
- Write the minimum code that solves the stated problem. Nothing extra.
|
|
160
160
|
- Never refactor, rename, or reorganize code outside the task scope.
|
|
161
161
|
- Run tests after every change. Show evidence before declaring done.
|
|
@@ -177,14 +177,45 @@ Use the standard bigpowers CONVENTIONS.md template, filling in the project-speci
|
|
|
177
177
|
|
|
178
178
|
### `specs/` directory
|
|
179
179
|
|
|
180
|
+
Create the evolved bigpowers directory structure:
|
|
181
|
+
|
|
180
182
|
```bash
|
|
181
|
-
mkdir -p specs
|
|
182
|
-
|
|
183
|
+
mkdir -p specs/product
|
|
184
|
+
mkdir -p specs/product/snapshots
|
|
185
|
+
mkdir -p specs/epics/archive
|
|
186
|
+
mkdir -p specs/tech-architecture
|
|
187
|
+
mkdir -p specs/adr
|
|
188
|
+
mkdir -p specs/verifications
|
|
189
|
+
mkdir -p specs/bugs
|
|
190
|
+
|
|
191
|
+
# Create empty placeholder files
|
|
192
|
+
touch specs/product/SCOPE_LATEST.yaml
|
|
193
|
+
touch specs/product/VISION_LATEST.yaml
|
|
194
|
+
touch specs/product/GLOSSARY_LATEST.yaml
|
|
195
|
+
touch specs/release-plan.yaml
|
|
196
|
+
touch specs/execution-status.yaml
|
|
197
|
+
touch specs/planning-status.yaml
|
|
198
|
+
touch specs/state.yaml
|
|
199
|
+
touch specs/tech-architecture/tech-stack.md
|
|
200
|
+
touch specs/tech-architecture/security.md
|
|
201
|
+
touch specs/tech-architecture/test.md
|
|
202
|
+
touch specs/tech-architecture/design.md
|
|
203
|
+
touch specs/tech-architecture/REFACTOR_LATEST.md
|
|
204
|
+
touch specs/tech-architecture/IMPACT_LATEST.md
|
|
205
|
+
touch specs/bugs/registry.yaml
|
|
206
|
+
echo "# Specs\n\nAll planning documents for this project. Evolved bigpowers structure (v2.0.0+)." > specs/README.md
|
|
183
207
|
```
|
|
184
208
|
|
|
209
|
+
**Note:** `specs/state.yaml.lock` is NOT pre-created — it is acquired and released dynamically during writes to prevent concurrency conflicts.
|
|
210
|
+
|
|
185
211
|
### Verify
|
|
186
212
|
|
|
187
213
|
- [ ] CLAUDE.md exists and is populated
|
|
188
214
|
- [ ] CONVENTIONS.md exists and includes specs/ output convention
|
|
189
215
|
- [ ] specs/ directory exists
|
|
216
|
+
- [ ] specs/product/ exists with SCOPE_LATEST.yaml, VISION_LATEST.yaml, GLOSSARY_LATEST.yaml
|
|
217
|
+
- [ ] specs/tech-architecture/ exists with tech-stack.md, security.md, test.md, design.md
|
|
218
|
+
- [ ] specs/verifications/ exists
|
|
219
|
+
- [ ] specs/epics/archive/ exists
|
|
220
|
+
- [ ] specs/bugs/registry.yaml exists
|
|
190
221
|
- [ ] Confirm with user: "Does CLAUDE.md accurately describe your project?"
|
package/session-state/SKILL.md
CHANGED
|
@@ -12,7 +12,7 @@ Track the current state of implementation, including decisions made, pending tas
|
|
|
12
12
|
|
|
13
13
|
## Goal
|
|
14
14
|
|
|
15
|
-
Maintain a single source of truth for the *current* session in `specs/state.yaml`. This complements long-term docs in `specs/
|
|
15
|
+
Maintain a single source of truth for the *current* session in `specs/state.yaml`. This complements long-term docs in `specs/tech-architecture/` and delivery detail in `specs/epics/` + `specs/release-plan.yaml`.
|
|
16
16
|
|
|
17
17
|
Legacy markdown (`specs/archive/STATE.md`, `RELEASE-PLAN.md`) is **not** SoT when YAML exists — use `specs/state.yaml` only.
|
|
18
18
|
|
|
@@ -45,7 +45,7 @@ handoff:
|
|
|
45
45
|
|
|
46
46
|
If `specs/state.yaml` does not exist, or if starting a new major phase:
|
|
47
47
|
|
|
48
|
-
- [ ] Read `specs/release-plan.yaml` and `specs/
|
|
48
|
+
- [ ] Read `specs/release-plan.yaml` and `specs/product/SCOPE_LATEST.yaml`.
|
|
49
49
|
- [ ] Get git metadata: `git branch --show-current` and `git rev-parse --short HEAD`.
|
|
50
50
|
- [ ] Create `specs/state.yaml` with active flow, git, handoff, and epic cycle if in build.
|
|
51
51
|
|
|
@@ -68,6 +68,32 @@ Whenever a significant decision is made or a milestone is reached:
|
|
|
68
68
|
|
|
69
69
|
→ verify: `bash scripts/validate-specs-yaml.sh`
|
|
70
70
|
|
|
71
|
+
## State Write-Lock Protocol
|
|
72
|
+
|
|
73
|
+
> **HARD GATE** — Before any write to `specs/state.yaml` or `specs/execution-status.yaml`, acquire `specs/state.yaml.lock`. Release it immediately after the write. A stale lock (>60s) may be force-released.
|
|
74
|
+
|
|
75
|
+
### Acquire
|
|
76
|
+
|
|
77
|
+
1. Check if `specs/state.yaml.lock` exists.
|
|
78
|
+
2. If it exists, read the agent ID and timestamp inside.
|
|
79
|
+
3. If the lock is stale (>60s old), remove it and proceed.
|
|
80
|
+
4. If the lock is fresh (<60s), wait 2s and retry (max 15 attempts = 30s).
|
|
81
|
+
5. Write `agent_id: <name>\nacquired_at: <ISO-8601>` to `specs/state.yaml.lock`.
|
|
82
|
+
|
|
83
|
+
### Release
|
|
84
|
+
|
|
85
|
+
1. After the write to `state.yaml` or `execution-status.yaml` completes:
|
|
86
|
+
2. `rm specs/state.yaml.lock`
|
|
87
|
+
|
|
88
|
+
### Lock format (`specs/state.yaml.lock`)
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
agent_id: session-state
|
|
92
|
+
acquired_at: "2026-06-11T14:30:00Z"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
71
97
|
## Operations
|
|
72
98
|
|
|
73
99
|
### show-state (absorbed)
|
|
@@ -80,7 +106,12 @@ Clear ephemeral session state. Set `active_epic_id`, `active_story_id`, and `epi
|
|
|
80
106
|
|
|
81
107
|
### compact-state (absorbed)
|
|
82
108
|
|
|
83
|
-
Archive verbose decisions before a context transition. Move all entries from `handoff.open_decisions` to
|
|
109
|
+
Archive verbose decisions before a context transition. Move all entries from `handoff.open_decisions` to their appropriate location:
|
|
110
|
+
|
|
111
|
+
- **System-wide decisions** → `specs/adr/NNNN-slug.md` (global Architectural Decision Records)
|
|
112
|
+
- **Epic-scoped decisions** → `specs/epics/<active_epic_id>-<slug>/adr/NNNN-slug.md` (epic-local ADRs, archived with epic)
|
|
113
|
+
|
|
114
|
+
After archiving, reset `handoff.open_decisions` to an empty list.
|
|
84
115
|
|
|
85
116
|
## File Format: specs/state.yaml
|
|
86
117
|
|
package/slice-tasks/SKILL.md
CHANGED
|
@@ -6,17 +6,17 @@ model: sonnet
|
|
|
6
6
|
|
|
7
7
|
# Slice Tasks
|
|
8
8
|
|
|
9
|
-
Produce **epic
|
|
9
|
+
Produce **epic capsule story tasks** in `specs/epics/eNN-slug/` — vertical slices, each independently deliverable and testable. Output: decoupled `eNNsYY-tasks.yaml` files with runnable verify commands. Legacy `specs/epics/ (see slice-tasks)` is deprecated; use capsule dirs + `execution-status.yaml`.
|
|
10
10
|
|
|
11
11
|
## Process
|
|
12
12
|
|
|
13
|
-
1. Read `specs/
|
|
13
|
+
1. Read `specs/product/SCOPE_LATEST.yaml` and/or `specs/release-plan.yaml`.
|
|
14
14
|
2. Cut **tracer-bullet slices** (thin end-to-end paths first, then depth).
|
|
15
|
-
3. Each story: `
|
|
15
|
+
3. Each story: writes `eNNsYY-tasks.yaml` with `story_id`, `title`, `status`, `bcps`, `tasks[]` (each with `id`, `description`, `verify`, `status`). Story spec `.md` files are written by `plan-work` and follow [countable-story-format.md](file:///Users/danielvm/Developer/bigpowers/countable-story-format.md).
|
|
16
16
|
4. Order by WSJF in `release-plan.yaml` epic list.
|
|
17
17
|
|
|
18
18
|
> **HARD GATE** — No horizontal-only slices ("add all models") without a vertical path that proves integration.
|
|
19
19
|
|
|
20
20
|
## Verify
|
|
21
21
|
|
|
22
|
-
→ verify: `
|
|
22
|
+
→ verify: `find specs/epics -name "*-tasks.yaml" | wc -l | awk '{if($1>0) print "OK: "$1" task files"; else print "MISSING"}'`
|
package/survey-context/SKILL.md
CHANGED
|
@@ -67,7 +67,7 @@ Based on what you've found, identify which PMBOK phase this project is currently
|
|
|
67
67
|
| **Design** | SCOPE exists but no `release-plan.yaml` |
|
|
68
68
|
| **Plan** | `release-plan.yaml` exists; on `main`/`master` branch |
|
|
69
69
|
| **Initiate** | On a feature branch; no code changes yet |
|
|
70
|
-
| **Execute** | `state.yaml` `active_flow: build_epic`; epic
|
|
70
|
+
| **Execute** | `state.yaml` `active_flow: build_epic`; epic capsule in progress |
|
|
71
71
|
| **Verify** | Implementation done; run `verify-work` or `run-evals` |
|
|
72
72
|
| **Bug** | `state.yaml` `active_flow: fix_bug` or open `specs/bugs/BUG-*.md` |
|
|
73
73
|
| **Review** | All code written; no PR yet |
|
|
@@ -116,7 +116,7 @@ At story start, write `metrics.story_start` with the current ISO 8601 timestamp
|
|
|
116
116
|
|
|
117
117
|
### list-epics (absorbed)
|
|
118
118
|
|
|
119
|
-
Loop through all `specs/epics
|
|
119
|
+
Loop through all `specs/epics/*/epic.yaml` files and print a summary of story counts per epic. Useful for understanding overall project scope and epic distribution.
|
|
120
120
|
|
|
121
121
|
### check-gates (absorbed)
|
|
122
122
|
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: trace-requirement
|
|
3
3
|
model: haiku
|
|
4
|
-
description: Link story IDs from specs/release-plan.yaml + epic
|
|
4
|
+
description: Link story IDs from specs/release-plan.yaml + epic capsule directories to the implementing code and tests. Produces specs/TRACEABILITY.md. Use when you want to verify coverage of a release plan, audit which stories are implemented, or find "dark" stories with no code.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Trace Requirement
|
|
8
8
|
|
|
9
|
-
Build a traceability matrix from `specs/release-plan.yaml + epic
|
|
9
|
+
Build a traceability matrix from `specs/release-plan.yaml + epic capsule directories` to implementing code and tests. Surfaces gaps in both directions: stories with no code, and code with no story.
|
|
10
10
|
|
|
11
11
|
## Pre-flight
|
|
12
12
|
|
|
13
|
-
> **HARD GATE** — `specs/release-plan.yaml + epic
|
|
13
|
+
> **HARD GATE** — `specs/release-plan.yaml + epic capsule directories` must exist. If it doesn't, run `plan-release` first.
|
|
14
14
|
|
|
15
|
-
→ verify: `[ -f specs/release-plan.yaml + epic
|
|
15
|
+
→ verify: `[ -f specs/release-plan.yaml + epic capsule directories ] && echo "ready" || echo "BLOCKED: run plan-release first"`
|
|
16
16
|
|
|
17
|
-
Read `specs/release-plan.yaml + epic
|
|
17
|
+
Read `specs/release-plan.yaml + epic capsule directories` fully before proceeding.
|
|
18
18
|
|
|
19
19
|
## Process
|
|
20
20
|
|
|
@@ -22,7 +22,7 @@ Read `specs/release-plan.yaml + epic shards` fully before proceeding.
|
|
|
22
22
|
|
|
23
23
|
From release-plan.yaml, collect all story IDs (e.g. `1.1`, `1.2`, `2.1`).
|
|
24
24
|
|
|
25
|
-
→ verify: `grep -o "Story [0-9]\+\.[0-9]\+" specs/release-plan.yaml + epic
|
|
25
|
+
→ verify: `grep -o "Story [0-9]\+\.[0-9]\+" specs/release-plan.yaml + epic capsule directories | sort -u`
|
|
26
26
|
|
|
27
27
|
### 2. Search for story tags in code
|
|
28
28
|
|
package/verify-work/SKILL.md
CHANGED
|
@@ -21,7 +21,7 @@ Review answers "is the code good?"; Verify answers "does the built thing do what
|
|
|
21
21
|
|
|
22
22
|
0. **Branch check** — must not be `main`/`master`.
|
|
23
23
|
|
|
24
|
-
1. Read active story tasks
|
|
24
|
+
1. Read active story tasks from `specs/epics/<capsule>/eNNsYY-tasks.yaml` and story spec from `specs/epics/<capsule>/eNNsYY-<slug>.md` (countable-story-format, Gherkin in §17).
|
|
25
25
|
2. **Cold-start smoke** (if app): stop server, clear caches, boot from scratch.
|
|
26
26
|
3. Mechanical gates: build → typecheck → lint → tests (from `CLAUDE.md`).
|
|
27
27
|
4. **Step-by-step UAT** — one user-observable action at a time.
|
|
@@ -55,9 +55,42 @@ After UAT, identify and close any gaps between promised behavior and actual beha
|
|
|
55
55
|
- Pass: user confirms per step.
|
|
56
56
|
- Fail: capture expected vs actual; do not mark done in `execution-status.yaml`.
|
|
57
57
|
|
|
58
|
+
## Persist verification evidence
|
|
59
|
+
|
|
60
|
+
After UAT passes, write structured evidence to `specs/verifications/eNNsYY-verify.yaml`:
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
story_id: e01s01
|
|
64
|
+
verified_at: "2026-06-11T14:30:00Z"
|
|
65
|
+
verifier: verify-work
|
|
66
|
+
phases:
|
|
67
|
+
smoke:
|
|
68
|
+
passed: true
|
|
69
|
+
build:
|
|
70
|
+
passed: true
|
|
71
|
+
command: "npm run build"
|
|
72
|
+
typecheck:
|
|
73
|
+
passed: true
|
|
74
|
+
lint:
|
|
75
|
+
passed: true
|
|
76
|
+
tests:
|
|
77
|
+
passed: true
|
|
78
|
+
coverage: "94.2%"
|
|
79
|
+
manual:
|
|
80
|
+
steps:
|
|
81
|
+
- step: "Open /login"
|
|
82
|
+
expected: "Login form renders"
|
|
83
|
+
actual: "Login form rendered correctly"
|
|
84
|
+
passed: true
|
|
85
|
+
gaps:
|
|
86
|
+
closed: true
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
> **HARD GATE** — Verification evidence MUST be persisted before marking the story done. No evidence = not verified.
|
|
90
|
+
|
|
58
91
|
## Verify
|
|
59
92
|
|
|
60
|
-
→ verify: `
|
|
93
|
+
→ verify: `test -f specs/verifications/<story_id>-verify.yaml && echo "Evidence persisted"`
|
|
61
94
|
|
|
62
95
|
See [REFERENCE.md](REFERENCE.md) for cold-start and gaps template.
|
|
63
96
|
|
package/write-document/SKILL.md
CHANGED
|
@@ -25,7 +25,7 @@ Create high-signal technical documentation that serves as an expert collaborator
|
|
|
25
25
|
|
|
26
26
|
Choose the correct BMAD-BigPowers artifact:
|
|
27
27
|
- **Decision Record (ADR)**: For "Why" decisions (saved to `specs/adr/`).
|
|
28
|
-
- **Context Map**: For system-wide architectural mapping (`specs/
|
|
28
|
+
- **Context Map**: For system-wide architectural mapping (`specs/tech-architecture/tech-stack.md`).
|
|
29
29
|
- **Technical Guide**: For "How-to" with verification (saved to `<module>/REFERENCE.md`).
|
|
30
30
|
- **Behavioral Feature**: Gherkin-style compliance specs (saved to `specs/audit/features/`).
|
|
31
31
|
- **Project README**: Project-facing documentation (saved to `README.md` at project root).
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const COLOR_MAP = {
|
|
2
|
-
ready: 'green',
|
|
3
|
-
blocked: 'red',
|
|
4
|
-
in_progress: 'yellow',
|
|
5
|
-
done: 'green',
|
|
6
|
-
pending: 'dim',
|
|
7
|
-
active: 'cyan'
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const ICON_MAP = {
|
|
11
|
-
ready: '●',
|
|
12
|
-
blocked: '✕',
|
|
13
|
-
in_progress: '◐',
|
|
14
|
-
done: '✓',
|
|
15
|
-
pending: '○',
|
|
16
|
-
active: '◐'
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function gateColor(gateStatus) {
|
|
20
|
-
return COLOR_MAP[gateStatus] || 'dim';
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function gateIcon(gateStatus) {
|
|
24
|
-
return ICON_MAP[gateStatus] || '-';
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
module.exports = {
|
|
28
|
-
gateColor,
|
|
29
|
-
gateIcon,
|
|
30
|
-
COLOR_MAP,
|
|
31
|
-
ICON_MAP
|
|
32
|
-
};
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* computeEpicMetrics(cycleTimes)
|
|
3
|
-
* Groups cycle times by epic prefix (e.g. e01 from e01s01)
|
|
4
|
-
* Returns Map of epicId to { avgCycleMin, totalBcps, avgBcpPerHour }
|
|
5
|
-
*/
|
|
6
|
-
function computeEpicMetrics(cycleTimes) {
|
|
7
|
-
if (!cycleTimes || cycleTimes.length === 0) {
|
|
8
|
-
return new Map();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const epicMap = new Map();
|
|
12
|
-
for (const story of cycleTimes) {
|
|
13
|
-
// Extract epic prefix: e01s01 -> e01
|
|
14
|
-
const epicId = story.id ? story.id.replace(/s\d+$/, '') : null;
|
|
15
|
-
if (!epicId) continue;
|
|
16
|
-
|
|
17
|
-
if (!epicMap.has(epicId)) {
|
|
18
|
-
epicMap.set(epicId, { stories: [] });
|
|
19
|
-
}
|
|
20
|
-
epicMap.get(epicId).stories.push(story);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const result = new Map();
|
|
24
|
-
for (const [epicId, data] of epicMap) {
|
|
25
|
-
const stories = data.stories;
|
|
26
|
-
const totalBcps = stories.reduce((sum, s) => sum + (s.bcps || 0), 0);
|
|
27
|
-
const totalMin = stories.reduce((sum, s) => sum + (s.cycleMin || 0), 0);
|
|
28
|
-
const avgCycleMin = stories.length > 0 ? totalMin / stories.length : 0;
|
|
29
|
-
const avgBcpPerHour = totalMin > 0 ? (totalBcps * 60) / totalMin : 0;
|
|
30
|
-
|
|
31
|
-
result.set(epicId, {
|
|
32
|
-
avgCycleMin,
|
|
33
|
-
totalBcps,
|
|
34
|
-
avgBcpPerHour
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return result;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* computeProjectMetrics(cycleTimes)
|
|
43
|
-
* Returns { totalBcps, totalMin, avgBcpPerHour } or null if no data
|
|
44
|
-
*/
|
|
45
|
-
function computeProjectMetrics(cycleTimes) {
|
|
46
|
-
if (!cycleTimes || cycleTimes.length === 0) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const totalBcps = cycleTimes.reduce((sum, s) => sum + (s.bcps || 0), 0);
|
|
51
|
-
const totalMin = cycleTimes.reduce((sum, s) => sum + (s.cycleMin || 0), 0);
|
|
52
|
-
const avgBcpPerHour = totalMin > 0 ? (totalBcps * 60) / totalMin : 0;
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
totalBcps,
|
|
56
|
-
totalMin,
|
|
57
|
-
avgBcpPerHour
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* computeCurrentVelocity(cycleTimes, windowStories=3)
|
|
63
|
-
* Rolling average of last N stories
|
|
64
|
-
* Returns { avgBcpPerHour, avgCycleMin } or null if no data
|
|
65
|
-
*/
|
|
66
|
-
function computeCurrentVelocity(cycleTimes, windowStories = 3) {
|
|
67
|
-
if (!cycleTimes || cycleTimes.length === 0) {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const window = Math.min(windowStories, cycleTimes.length);
|
|
72
|
-
const recentStories = cycleTimes.slice(-window);
|
|
73
|
-
|
|
74
|
-
const totalBcps = recentStories.reduce((sum, s) => sum + (s.bcps || 0), 0);
|
|
75
|
-
const totalMin = recentStories.reduce((sum, s) => sum + (s.cycleMin || 0), 0);
|
|
76
|
-
const avgCycleMin = recentStories.length > 0 ? totalMin / recentStories.length : 0;
|
|
77
|
-
const avgBcpPerHour = totalMin > 0 ? (totalBcps * 60) / totalMin : 0;
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
avgBcpPerHour,
|
|
81
|
-
avgCycleMin
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
module.exports = {
|
|
86
|
-
computeEpicMetrics,
|
|
87
|
-
computeProjectMetrics,
|
|
88
|
-
computeCurrentVelocity
|
|
89
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const STEPS = [
|
|
2
|
-
'survey-context',
|
|
3
|
-
'plan-work',
|
|
4
|
-
'kickoff-branch',
|
|
5
|
-
'develop-tdd',
|
|
6
|
-
'verify-work',
|
|
7
|
-
'audit-code',
|
|
8
|
-
'commit-message',
|
|
9
|
-
'release-branch'
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
function stepIndex(currentStep) {
|
|
13
|
-
return STEPS.indexOf(currentStep);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function stepLabel(index) {
|
|
17
|
-
if (index < 0 || index >= STEPS.length) {
|
|
18
|
-
return '-';
|
|
19
|
-
}
|
|
20
|
-
return STEPS[index];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function allSteps() {
|
|
24
|
-
return [...STEPS];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
module.exports = {
|
|
28
|
-
stepIndex,
|
|
29
|
-
stepLabel,
|
|
30
|
-
allSteps,
|
|
31
|
-
STEPS
|
|
32
|
-
};
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const yaml = require('js-yaml');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* readStateYaml(projectRoot)
|
|
7
|
-
* Reads specs/state.yaml and returns an object with mapped fields
|
|
8
|
-
* Returns null if file doesn't exist
|
|
9
|
-
*/
|
|
10
|
-
function readStateYaml(projectRoot) {
|
|
11
|
-
try {
|
|
12
|
-
const filePath = path.join(projectRoot, 'specs', 'state.yaml');
|
|
13
|
-
if (!fs.existsSync(filePath)) {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
17
|
-
const data = yaml.load(content);
|
|
18
|
-
return {
|
|
19
|
-
activeFlow: data.active_flow || null,
|
|
20
|
-
activeEpic: data.active_epic_id || null,
|
|
21
|
-
activeStory: data.active_story_id || null,
|
|
22
|
-
epicCycle: data.epic_cycle || {},
|
|
23
|
-
gitBranch: data.git?.branch || null,
|
|
24
|
-
metrics: data.metrics || null,
|
|
25
|
-
release: data.release || {},
|
|
26
|
-
handoff: data.handoff || {}
|
|
27
|
-
};
|
|
28
|
-
} catch (err) {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* readExecutionStatus(projectRoot)
|
|
35
|
-
* Reads specs/execution-status.yaml and returns { epics: Map }
|
|
36
|
-
* Map keys are story/epic IDs, values are status strings
|
|
37
|
-
* Returns null if file doesn't exist
|
|
38
|
-
*/
|
|
39
|
-
function readExecutionStatus(projectRoot) {
|
|
40
|
-
try {
|
|
41
|
-
const filePath = path.join(projectRoot, 'specs', 'execution-status.yaml');
|
|
42
|
-
if (!fs.existsSync(filePath)) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
46
|
-
const data = yaml.load(content);
|
|
47
|
-
const statusMap = new Map();
|
|
48
|
-
const devStatus = data.development_status || {};
|
|
49
|
-
for (const [key, value] of Object.entries(devStatus)) {
|
|
50
|
-
statusMap.set(key, value);
|
|
51
|
-
}
|
|
52
|
-
return { epics: statusMap };
|
|
53
|
-
} catch (err) {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* readEpicShards(projectRoot)
|
|
60
|
-
* Reads all files in specs/epics/*.yaml
|
|
61
|
-
* Returns array of { id, title, stories } objects or null
|
|
62
|
-
*/
|
|
63
|
-
function readEpicShards(projectRoot) {
|
|
64
|
-
try {
|
|
65
|
-
const epicsDir = path.join(projectRoot, 'specs', 'epics');
|
|
66
|
-
if (!fs.existsSync(epicsDir)) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
const files = fs.readdirSync(epicsDir)
|
|
70
|
-
.filter(f => f.endsWith('.yaml'))
|
|
71
|
-
.sort();
|
|
72
|
-
|
|
73
|
-
const epics = [];
|
|
74
|
-
for (const file of files) {
|
|
75
|
-
const filePath = path.join(epicsDir, file);
|
|
76
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
77
|
-
const data = yaml.load(content);
|
|
78
|
-
epics.push({
|
|
79
|
-
id: data.id || null,
|
|
80
|
-
title: data.title || null,
|
|
81
|
-
stories: data.stories || []
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
return epics.length > 0 ? epics : null;
|
|
85
|
-
} catch (err) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* readCycleTimes(projectRoot)
|
|
92
|
-
* Reads specs/metrics/cycle-times.yaml stories array
|
|
93
|
-
* Returns array of { id, bcps, start, end, cycleMin, bcpPerHour } or null
|
|
94
|
-
*/
|
|
95
|
-
function readCycleTimes(projectRoot) {
|
|
96
|
-
try {
|
|
97
|
-
const filePath = path.join(projectRoot, 'specs', 'metrics', 'cycle-times.yaml');
|
|
98
|
-
if (!fs.existsSync(filePath)) {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
102
|
-
const data = yaml.load(content);
|
|
103
|
-
const stories = data.stories || [];
|
|
104
|
-
return stories.map(s => ({
|
|
105
|
-
id: s.id || null,
|
|
106
|
-
bcps: s.bcps || 0,
|
|
107
|
-
start: s.start || null,
|
|
108
|
-
end: s.end || null,
|
|
109
|
-
cycleMin: s.cycle_min || 0,
|
|
110
|
-
bcpPerHour: s.bcp_per_hour || 0
|
|
111
|
-
}));
|
|
112
|
-
} catch (err) {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
module.exports = {
|
|
118
|
-
readStateYaml,
|
|
119
|
-
readExecutionStatus,
|
|
120
|
-
readEpicShards,
|
|
121
|
-
readCycleTimes
|
|
122
|
-
};
|