bigpowers 2.55.0 → 2.56.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/.pi/package.json +2 -2
- package/.pi/prompts/gate-trace.md +79 -0
- package/.pi/prompts/release-branch.md +12 -16
- package/.pi/prompts/verify-work.md +1 -0
- package/.pi/skills/gate-trace/SKILL.md +81 -0
- package/.pi/skills/release-branch/SKILL.md +12 -16
- package/.pi/skills/verify-work/SKILL.md +1 -0
- package/CHANGELOG.md +12 -0
- package/CLAUDE.md +3 -0
- package/CONVENTIONS.md +3 -0
- package/README.md +1 -1
- package/SKILL-INDEX.md +1 -1
- package/package.json +1 -1
- package/scripts/check-blind-spots.sh +349 -0
- package/scripts/trace-stories.sh +1 -0
- package/skills/build-epic/SKILL.md +1 -0
- package/skills/gate-trace/SKILL.md +82 -0
- package/skills/release-branch/SKILL.md +13 -16
- package/skills/verify-work/SKILL.md +2 -0
- package/skills-lock.json +8 -3
package/.pi/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bigpowers",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.56.0",
|
|
4
|
+
"description": "73 skills — 72 agent skills synthesizing 17 years of software engineering discipline into a prescriptive methodology for solo developers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
7
7
|
],
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Deterministic traceability quality gate — reads coverage matrix + blind-spot data, applies decision rules with oracle confidence downgrade, emits PASS/CONCERNS/FAIL/WAIVED verdict. Use before release-branch to gate merges on traceability."# story: e38s06
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Gate Trace
|
|
7
|
+
|
|
8
|
+
Deterministic quality gate that combines traceability coverage and blind-spot data into a single PASS/FAIL/CONCERNS/WAIVED decision before release.
|
|
9
|
+
|
|
10
|
+
## Decision Rules
|
|
11
|
+
|
|
12
|
+
| Rule | Condition | Verdict |
|
|
13
|
+
|------|-----------|---------|
|
|
14
|
+
| R1 | Any undone story with 0 code tags | FAIL |
|
|
15
|
+
| R2 | Any story done but no verify evidence | CONCERNS |
|
|
16
|
+
| R3 | P0 story (top WSJF quartile) with 0% coverage | FAIL |
|
|
17
|
+
| R4 | Overall coverage < 60% | CONCERNS |
|
|
18
|
+
| R5 | Overall ≥ 80% + no critical gaps + all verify → PASS | PASS |
|
|
19
|
+
|
|
20
|
+
## Oracle Confidence Downgrade
|
|
21
|
+
|
|
22
|
+
TEA-inspired: if trace links rely on heuristics rather than explicit tags, confidence drops.
|
|
23
|
+
|
|
24
|
+
| Heuristic Ratio | Downgrade |
|
|
25
|
+
|-----------------|-----------|
|
|
26
|
+
| > 50% links from heuristics (file-name or task-reference) | One level (PASS→CONCERNS, CONCERNS→FAIL) |
|
|
27
|
+
| > 80% links from heuristics | Two levels (PASS→FAIL, CONCERNS→FAIL) |
|
|
28
|
+
|
|
29
|
+
## Process
|
|
30
|
+
|
|
31
|
+
1. **Pre-flight:** Ensure `scripts/trace-stories.sh --json` has been run (produces `specs/traceability-matrix.json`). If not present, run it.
|
|
32
|
+
2. Ensure `scripts/check-blind-spots.sh` has been run (produces `specs/blind-spots.json`). If not present, run it.
|
|
33
|
+
3. Read `specs/traceability-matrix.json` and `specs/blind-spots.json`.
|
|
34
|
+
4. Apply decision rules R1–R5 in order (first match wins).
|
|
35
|
+
5. Apply oracle confidence downgrade based on the heuristic link ratio from the matrix's `oracle_stats`.
|
|
36
|
+
6. Output verdict + rationale to stdout.
|
|
37
|
+
7. Update `specs/execution-status.yaml` with gate-trace result.
|
|
38
|
+
|
|
39
|
+
## Verdict Semantics
|
|
40
|
+
|
|
41
|
+
| Verdict | Meaning | Action |
|
|
42
|
+
|---------|---------|--------|
|
|
43
|
+
| PASS | All gates satisfied | Proceed with merge |
|
|
44
|
+
| CONCERNS | Non-critical issues found | Requires explicit human override in `state.yaml` |
|
|
45
|
+
| FAIL | Critical traceability gap | Block merge — fix gap first |
|
|
46
|
+
| WAIVED | Cannot evaluate (missing inputs) | Skip gate — data not available |
|
|
47
|
+
|
|
48
|
+
## Output Format
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
gate_trace:
|
|
52
|
+
verdict: PASS|CONCERNS|FAIL|WAIVED
|
|
53
|
+
generated_at: "<ISO 8601>"
|
|
54
|
+
rationale: "<human-readable explanation>"
|
|
55
|
+
heuristic_ratio: <0.0–1.0>
|
|
56
|
+
downgrade_applied: <true|false>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Integration Points
|
|
60
|
+
|
|
61
|
+
- **release-branch SKILL.md** — pre-PR gate (FAIL blocks merge).
|
|
62
|
+
- **sync-skills.yml** — CI gate (FAIL blocks pipeline).
|
|
63
|
+
- **verify-work SKILL.md** — runs blind-spot checks; gate-trace consumes the result.
|
|
64
|
+
|
|
65
|
+
## References
|
|
66
|
+
|
|
67
|
+
- BMAD TEA traceability approach (market survey 2026-07-02).
|
|
68
|
+
- scripts/trace-stories.sh (e38s01) — produces traceability-matrix.json.
|
|
69
|
+
- scripts/check-blind-spots.sh (e38s04) — produces blind-spots.json.
|
|
70
|
+
- specs/execution-status.yaml — output target for gate result.
|
|
71
|
+
|
|
72
|
+
## Verify
|
|
73
|
+
|
|
74
|
+
→ verify: `test -f skills/gate-trace/SKILL.md && grep -q 'PASS.*CONCERNS.*FAIL.*WAIVED' skills/gate-trace/SKILL.md && echo "OK: gate-trace skill created" || echo "FAIL"`
|
|
75
|
+
|
|
76
|
+
## Handoff
|
|
77
|
+
|
|
78
|
+
Gate: READY → next: release-branch (final step before merge)
|
|
79
|
+
Writes: state.yaml handoff.next_skill = release-branch
|
|
@@ -11,21 +11,19 @@ Finalize a completed feature branch: verify coverage gates, integrate onto `main
|
|
|
11
11
|
|
|
12
12
|
## Additional modes
|
|
13
13
|
|
|
14
|
-
- `--hotfix`:
|
|
15
|
-
- `--squash-state`:
|
|
14
|
+
- `--hotfix`: Cherry-pick to main + tag. Skip PR in solo.
|
|
15
|
+
- `--squash-state`: Squash `chore(state):` commits before merge.
|
|
16
16
|
|
|
17
17
|
## Integrate mode
|
|
18
18
|
|
|
19
|
-
Read `specs/state.yaml` key `workflow_mode`
|
|
19
|
+
Read `specs/state.yaml` key `workflow_mode` (`team-pr` | `solo-git`). Fall back to `profiles/solo-git.md`.
|
|
20
20
|
|
|
21
21
|
| Mode | When | Ship path |
|
|
22
22
|
|------|------|-----------|
|
|
23
|
-
| **solo-local** | `workflow_mode: solo-git`
|
|
23
|
+
| **solo-local** | `workflow_mode: solo-git` | Auto: `scripts/land-branch.sh` if present, else fallback (Step 5) |
|
|
24
24
|
| **team-pr** | `workflow_mode: team-pr` (default) | `gh pr create` → `gh pr merge --squash` |
|
|
25
25
|
|
|
26
|
-
If unsure
|
|
27
|
-
|
|
28
|
-
> **Auto-detect note:** The solo-local path first checks if `scripts/land-branch.sh` exists and is executable. If present, the script handles the full squash-merge workflow. If absent, the built-in fallback sequence runs instead.
|
|
26
|
+
If unsure, prefer **solo-local**.
|
|
29
27
|
|
|
30
28
|
## Process
|
|
31
29
|
|
|
@@ -51,6 +49,10 @@ git log main...HEAD --oneline | grep -vE "^[a-f0-9]+ (feat|fix|docs|style|refact
|
|
|
51
49
|
|
|
52
50
|
If REVIEW.md is missing or stale → run `security-review` inline. Findings block the merge unless documented in EXCEPTIONS.md.
|
|
53
51
|
|
|
52
|
+
### 2b. Traceability gate
|
|
53
|
+
|
|
54
|
+
Run `gate-trace` before merge. FAIL blocks merge; CONCERNS requires explicit override in `specs/state.yaml` (`traceability_override: CONCERNS accepted, reason: <explanation>`). WAIVED if no matrix available.
|
|
55
|
+
|
|
54
56
|
### 3. Diff review
|
|
55
57
|
|
|
56
58
|
- [ ] All commits intentional, no secrets, CONVENTIONS.md compliance
|
|
@@ -61,20 +63,14 @@ Options: **Release (solo-local)** / **Open PR** / **Keep branch** / **Discard**
|
|
|
61
63
|
|
|
62
64
|
### 5. Solo-local integrate
|
|
63
65
|
|
|
64
|
-
Run `commit-message`
|
|
66
|
+
Run `commit-message` for the squash subject, then land:
|
|
65
67
|
|
|
66
|
-
**Path A — `scripts/land-branch.sh` exists (happy path):**
|
|
67
68
|
```bash
|
|
69
|
+
# Path A (preferred):
|
|
68
70
|
bash scripts/land-branch.sh <task-slug> "feat(scope): description"
|
|
71
|
+
# Path B (fallback if land-branch.sh missing): see REFERENCE.md
|
|
69
72
|
```
|
|
70
73
|
|
|
71
|
-
**Path B — `scripts/land-branch.sh` missing (fallback):**
|
|
72
|
-
See [REFERENCE.md](REFERENCE.md)
|
|
73
|
-
|
|
74
|
-
**Report which path was taken.** Print exactly:
|
|
75
|
-
- `"used land-branch.sh"` if Path A
|
|
76
|
-
- `"used fallback merge (land-branch.sh not found)"` if Path B
|
|
77
|
-
|
|
78
74
|
### 6. Create PR (team-pr only)
|
|
79
75
|
|
|
80
76
|
See [REFERENCE.md](REFERENCE.md) for the full PR body template and gh commands.
|
|
@@ -34,6 +34,7 @@ Review answers "is the code good?"; Verify answers "does the built thing do what
|
|
|
34
34
|
3. **AGENTS.md preflight** — before running default checks, call `bash scripts/bp-read-agents.sh` to detect project-specific commands. If `BP_PREFLIGHT` is set, run it instead of the default mechanical gates (or in addition to them if the project requires both). Output: `"Using preflight from AGENTS.md: <cmd>"`. Fall back to `CLAUDE.md` commands if AGENTS.md is absent.
|
|
35
35
|
4. Mechanical gates: build → typecheck → lint → tests (from `CLAUDE.md` or AGENTS.md).
|
|
36
36
|
5. **Security scan** — run `security-review` against the git diff (working tree vs merge-base). Parse findings report. If any HIGH findings with confidence ≥ 8 exist → **block the gate**. Write findings to `specs/security/REVIEW.md`. Allow documented exceptions via `specs/security/EXCEPTIONS.md`. MEDIUM/LOW findings warn but don't block.
|
|
37
|
+
5a. **Blind-spot check** — run `bash scripts/check-blind-spots.sh`. This detects structural quality gaps (verify-gap, test-gap, stale-tag, etc.) beyond percentage coverage. If any HIGH-severity findings exist → **block the verify-work PASS gate**. Findings are written to `specs/blind-spots.json`. MEDIUM/LOW findings warn but don't block.
|
|
37
38
|
6. **Step-by-step UAT** — one user-observable action at a time.
|
|
38
39
|
7. **Gaps loop** — failures → log → `plan-work` → re-verify. Unaddressed HIGH findings from step 5 feed into this loop alongside other quality gaps.
|
|
39
40
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gate-trace
|
|
3
|
+
description: "\"Deterministic traceability quality gate — reads coverage matrix + blind-spot data, applies decision rules with oracle confidence downgrade, emits PASS/CONCERNS/FAIL/WAIVED verdict. Use before release-branch to gate merges on traceability.\"# story: e38s06"
|
|
4
|
+
model: haiku
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Gate Trace
|
|
9
|
+
|
|
10
|
+
Deterministic quality gate that combines traceability coverage and blind-spot data into a single PASS/FAIL/CONCERNS/WAIVED decision before release.
|
|
11
|
+
|
|
12
|
+
## Decision Rules
|
|
13
|
+
|
|
14
|
+
| Rule | Condition | Verdict |
|
|
15
|
+
|------|-----------|---------|
|
|
16
|
+
| R1 | Any undone story with 0 code tags | FAIL |
|
|
17
|
+
| R2 | Any story done but no verify evidence | CONCERNS |
|
|
18
|
+
| R3 | P0 story (top WSJF quartile) with 0% coverage | FAIL |
|
|
19
|
+
| R4 | Overall coverage < 60% | CONCERNS |
|
|
20
|
+
| R5 | Overall ≥ 80% + no critical gaps + all verify → PASS | PASS |
|
|
21
|
+
|
|
22
|
+
## Oracle Confidence Downgrade
|
|
23
|
+
|
|
24
|
+
TEA-inspired: if trace links rely on heuristics rather than explicit tags, confidence drops.
|
|
25
|
+
|
|
26
|
+
| Heuristic Ratio | Downgrade |
|
|
27
|
+
|-----------------|-----------|
|
|
28
|
+
| > 50% links from heuristics (file-name or task-reference) | One level (PASS→CONCERNS, CONCERNS→FAIL) |
|
|
29
|
+
| > 80% links from heuristics | Two levels (PASS→FAIL, CONCERNS→FAIL) |
|
|
30
|
+
|
|
31
|
+
## Process
|
|
32
|
+
|
|
33
|
+
1. **Pre-flight:** Ensure `scripts/trace-stories.sh --json` has been run (produces `specs/traceability-matrix.json`). If not present, run it.
|
|
34
|
+
2. Ensure `scripts/check-blind-spots.sh` has been run (produces `specs/blind-spots.json`). If not present, run it.
|
|
35
|
+
3. Read `specs/traceability-matrix.json` and `specs/blind-spots.json`.
|
|
36
|
+
4. Apply decision rules R1–R5 in order (first match wins).
|
|
37
|
+
5. Apply oracle confidence downgrade based on the heuristic link ratio from the matrix's `oracle_stats`.
|
|
38
|
+
6. Output verdict + rationale to stdout.
|
|
39
|
+
7. Update `specs/execution-status.yaml` with gate-trace result.
|
|
40
|
+
|
|
41
|
+
## Verdict Semantics
|
|
42
|
+
|
|
43
|
+
| Verdict | Meaning | Action |
|
|
44
|
+
|---------|---------|--------|
|
|
45
|
+
| PASS | All gates satisfied | Proceed with merge |
|
|
46
|
+
| CONCERNS | Non-critical issues found | Requires explicit human override in `state.yaml` |
|
|
47
|
+
| FAIL | Critical traceability gap | Block merge — fix gap first |
|
|
48
|
+
| WAIVED | Cannot evaluate (missing inputs) | Skip gate — data not available |
|
|
49
|
+
|
|
50
|
+
## Output Format
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
gate_trace:
|
|
54
|
+
verdict: PASS|CONCERNS|FAIL|WAIVED
|
|
55
|
+
generated_at: "<ISO 8601>"
|
|
56
|
+
rationale: "<human-readable explanation>"
|
|
57
|
+
heuristic_ratio: <0.0–1.0>
|
|
58
|
+
downgrade_applied: <true|false>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Integration Points
|
|
62
|
+
|
|
63
|
+
- **release-branch SKILL.md** — pre-PR gate (FAIL blocks merge).
|
|
64
|
+
- **sync-skills.yml** — CI gate (FAIL blocks pipeline).
|
|
65
|
+
- **verify-work SKILL.md** — runs blind-spot checks; gate-trace consumes the result.
|
|
66
|
+
|
|
67
|
+
## References
|
|
68
|
+
|
|
69
|
+
- BMAD TEA traceability approach (market survey 2026-07-02).
|
|
70
|
+
- scripts/trace-stories.sh (e38s01) — produces traceability-matrix.json.
|
|
71
|
+
- scripts/check-blind-spots.sh (e38s04) — produces blind-spots.json.
|
|
72
|
+
- specs/execution-status.yaml — output target for gate result.
|
|
73
|
+
|
|
74
|
+
## Verify
|
|
75
|
+
|
|
76
|
+
→ verify: `test -f skills/gate-trace/SKILL.md && grep -q 'PASS.*CONCERNS.*FAIL.*WAIVED' skills/gate-trace/SKILL.md && echo "OK: gate-trace skill created" || echo "FAIL"`
|
|
77
|
+
|
|
78
|
+
## Handoff
|
|
79
|
+
|
|
80
|
+
Gate: READY → next: release-branch (final step before merge)
|
|
81
|
+
Writes: state.yaml handoff.next_skill = release-branch
|
|
@@ -13,21 +13,19 @@ Finalize a completed feature branch: verify coverage gates, integrate onto `main
|
|
|
13
13
|
|
|
14
14
|
## Additional modes
|
|
15
15
|
|
|
16
|
-
- `--hotfix`:
|
|
17
|
-
- `--squash-state`:
|
|
16
|
+
- `--hotfix`: Cherry-pick to main + tag. Skip PR in solo.
|
|
17
|
+
- `--squash-state`: Squash `chore(state):` commits before merge.
|
|
18
18
|
|
|
19
19
|
## Integrate mode
|
|
20
20
|
|
|
21
|
-
Read `specs/state.yaml` key `workflow_mode`
|
|
21
|
+
Read `specs/state.yaml` key `workflow_mode` (`team-pr` | `solo-git`). Fall back to `profiles/solo-git.md`.
|
|
22
22
|
|
|
23
23
|
| Mode | When | Ship path |
|
|
24
24
|
|------|------|-----------|
|
|
25
|
-
| **solo-local** | `workflow_mode: solo-git`
|
|
25
|
+
| **solo-local** | `workflow_mode: solo-git` | Auto: `scripts/land-branch.sh` if present, else fallback (Step 5) |
|
|
26
26
|
| **team-pr** | `workflow_mode: team-pr` (default) | `gh pr create` → `gh pr merge --squash` |
|
|
27
27
|
|
|
28
|
-
If unsure
|
|
29
|
-
|
|
30
|
-
> **Auto-detect note:** The solo-local path first checks if `scripts/land-branch.sh` exists and is executable. If present, the script handles the full squash-merge workflow. If absent, the built-in fallback sequence runs instead.
|
|
28
|
+
If unsure, prefer **solo-local**.
|
|
31
29
|
|
|
32
30
|
## Process
|
|
33
31
|
|
|
@@ -53,6 +51,10 @@ git log main...HEAD --oneline | grep -vE "^[a-f0-9]+ (feat|fix|docs|style|refact
|
|
|
53
51
|
|
|
54
52
|
If REVIEW.md is missing or stale → run `security-review` inline. Findings block the merge unless documented in EXCEPTIONS.md.
|
|
55
53
|
|
|
54
|
+
### 2b. Traceability gate
|
|
55
|
+
|
|
56
|
+
Run `gate-trace` before merge. FAIL blocks merge; CONCERNS requires explicit override in `specs/state.yaml` (`traceability_override: CONCERNS accepted, reason: <explanation>`). WAIVED if no matrix available.
|
|
57
|
+
|
|
56
58
|
### 3. Diff review
|
|
57
59
|
|
|
58
60
|
- [ ] All commits intentional, no secrets, CONVENTIONS.md compliance
|
|
@@ -63,20 +65,14 @@ Options: **Release (solo-local)** / **Open PR** / **Keep branch** / **Discard**
|
|
|
63
65
|
|
|
64
66
|
### 5. Solo-local integrate
|
|
65
67
|
|
|
66
|
-
Run `commit-message`
|
|
68
|
+
Run `commit-message` for the squash subject, then land:
|
|
67
69
|
|
|
68
|
-
**Path A — `scripts/land-branch.sh` exists (happy path):**
|
|
69
70
|
```bash
|
|
71
|
+
# Path A (preferred):
|
|
70
72
|
bash scripts/land-branch.sh <task-slug> "feat(scope): description"
|
|
73
|
+
# Path B (fallback if land-branch.sh missing): see REFERENCE.md
|
|
71
74
|
```
|
|
72
75
|
|
|
73
|
-
**Path B — `scripts/land-branch.sh` missing (fallback):**
|
|
74
|
-
See [REFERENCE.md](REFERENCE.md)
|
|
75
|
-
|
|
76
|
-
**Report which path was taken.** Print exactly:
|
|
77
|
-
- `"used land-branch.sh"` if Path A
|
|
78
|
-
- `"used fallback merge (land-branch.sh not found)"` if Path B
|
|
79
|
-
|
|
80
76
|
### 6. Create PR (team-pr only)
|
|
81
77
|
|
|
82
78
|
See [REFERENCE.md](REFERENCE.md) for the full PR body template and gh commands.
|
|
@@ -36,6 +36,7 @@ Review answers "is the code good?"; Verify answers "does the built thing do what
|
|
|
36
36
|
3. **AGENTS.md preflight** — before running default checks, call `bash scripts/bp-read-agents.sh` to detect project-specific commands. If `BP_PREFLIGHT` is set, run it instead of the default mechanical gates (or in addition to them if the project requires both). Output: `"Using preflight from AGENTS.md: <cmd>"`. Fall back to `CLAUDE.md` commands if AGENTS.md is absent.
|
|
37
37
|
4. Mechanical gates: build → typecheck → lint → tests (from `CLAUDE.md` or AGENTS.md).
|
|
38
38
|
5. **Security scan** — run `security-review` against the git diff (working tree vs merge-base). Parse findings report. If any HIGH findings with confidence ≥ 8 exist → **block the gate**. Write findings to `specs/security/REVIEW.md`. Allow documented exceptions via `specs/security/EXCEPTIONS.md`. MEDIUM/LOW findings warn but don't block.
|
|
39
|
+
5a. **Blind-spot check** — run `bash scripts/check-blind-spots.sh`. This detects structural quality gaps (verify-gap, test-gap, stale-tag, etc.) beyond percentage coverage. If any HIGH-severity findings exist → **block the verify-work PASS gate**. Findings are written to `specs/blind-spots.json`. MEDIUM/LOW findings warn but don't block.
|
|
39
40
|
6. **Step-by-step UAT** — one user-observable action at a time.
|
|
40
41
|
7. **Gaps loop** — failures → log → `plan-work` → re-verify. Unaddressed HIGH findings from step 5 feed into this loop alongside other quality gaps.
|
|
41
42
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [2.56.0](https://github.com/danielvm-git/bigpowers/compare/v2.55.0...v2.56.0) (2026-07-03)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* trim release-branch SKILL.md to 146 lines (cap 150) ([6c91813](https://github.com/danielvm-git/bigpowers/commit/6c91813012ce64b3e0fa90f3c11afa5b67559d9c))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **e38:** spec-to-code traceability gate — matrix, blind-spots, CI/CD integration ([ffeb843](https://github.com/danielvm-git/bigpowers/commit/ffeb8435a91ad2d278a490670bf2f1561df60135))
|
|
12
|
+
|
|
1
13
|
# [2.55.0](https://github.com/danielvm-git/bigpowers/compare/v2.54.0...v2.55.0) (2026-07-03)
|
|
2
14
|
|
|
3
15
|
|
package/CLAUDE.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# story: e38s08
|
|
2
|
+
|
|
1
3
|
# bigpowers — Claude Code
|
|
2
4
|
|
|
3
5
|
Read CONVENTIONS.md before any GitHub or git operation.
|
|
@@ -21,6 +23,7 @@ Stack: Markdown / Bash (documentation-based; skills integrate with Claude Code,
|
|
|
21
23
|
| CI platform | GitHub Actions (`.github/workflows/publish.yml`, `sync-skills.yml`) |
|
|
22
24
|
| Compliance | `npm run compliance` |
|
|
23
25
|
| Golden Suite | `bash scripts/run-golden-suite.sh` |
|
|
26
|
+
| Traceability | `bash scripts/trace-stories.sh --strict` | grep for story tags (traceability check) |
|
|
24
27
|
|
|
25
28
|
### Pre-Merge Checklist
|
|
26
29
|
|
package/CONVENTIONS.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# story: e38s08
|
|
2
|
+
|
|
1
3
|
# Conventions
|
|
2
4
|
|
|
3
5
|
## Conventional Commits & Semantic Versioning
|
|
@@ -51,6 +53,7 @@ You are operating within the `bigpowers` spec-driven development methodology.
|
|
|
51
53
|
- Use `investigate-bug` for bug reports before writing a fix.
|
|
52
54
|
- **Verification Mandate:** Every story implementation MUST end with a step-by-step manual verification script provided to the user. You must wait for the user to confirm behavioral correctness (UAT) before declaring the story done or moving to the next.
|
|
53
55
|
- **Verification:** You MUST verify every change with tests. Code generation without a corresponding plan in `specs/` is strictly forbidden.
|
|
56
|
+
- **Traceability Mandate:** Every story MUST have at least one `story: eNNsNN` tag in its implementing code or test file. `trace-stories.sh --strict` runs in CI to enforce this. Untagged stories fail the CI traceability gate.
|
|
54
57
|
- **Stream Continuity:** When writing large files or long documents, you MUST output continuously in chunks of ~200 lines. Do not pause between sections. Continue immediately until complete. If you need time to process, emit a placeholder comment or heading rather than going silent to prevent stream idle timeouts.
|
|
55
58
|
|
|
56
59
|
## specs/ — All Planning Output Goes Here
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|

|
|
5
|
-

|
|
6
6
|
|
|
7
7
|
**Agent skills synthesizing 17 years of software engineering discipline — from Clean Code to AI-native architecture — into a single, prescriptive methodology for solo developers.**
|
|
8
8
|
|
package/SKILL-INDEX.md
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# story: e38s04
|
|
3
|
+
# check-blind-spots.sh — TEA-inspired heuristic blind-spot detector
|
|
4
|
+
# Reads execution-status.yaml + traceability-matrix.json, runs 6 structural
|
|
5
|
+
# quality checks beyond percentage coverage, and emits specs/blind-spots.json.
|
|
6
|
+
#
|
|
7
|
+
# Checks:
|
|
8
|
+
# a. verify-gap — story done but no verification evidence
|
|
9
|
+
# b. test-gap — code tagged but no test file references
|
|
10
|
+
# c. epic-orphan — capsule task with no story tag anywhere
|
|
11
|
+
# d. stale-tag — story done but tag still in code
|
|
12
|
+
# e. double-tag — same file tagged with multiple stories
|
|
13
|
+
# f. bootstrap-testless — new story without test-related tag or files
|
|
14
|
+
#
|
|
15
|
+
# Severities: HIGH / MEDIUM / LOW
|
|
16
|
+
#
|
|
17
|
+
# Usage:
|
|
18
|
+
# bash scripts/check-blind-spots.sh # full scan, emit JSON
|
|
19
|
+
# bash scripts/check-blind-spots.sh --help # this message
|
|
20
|
+
#
|
|
21
|
+
# Exit codes:
|
|
22
|
+
# 0 — no HIGH-severity findings
|
|
23
|
+
# 1 — one or more HIGH-severity findings (or input files missing)
|
|
24
|
+
|
|
25
|
+
set -euo pipefail
|
|
26
|
+
|
|
27
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
28
|
+
BLIND_SPOTS_JSON="$REPO_ROOT/specs/blind-spots.json"
|
|
29
|
+
EXEC_STATUS="$REPO_ROOT/specs/execution-status.yaml"
|
|
30
|
+
MATRIX_JSON="$REPO_ROOT/specs/traceability-matrix.json"
|
|
31
|
+
VERIFICATIONS_DIR="$REPO_ROOT/specs/verifications"
|
|
32
|
+
EPICS_DIR="$REPO_ROOT/specs/epics"
|
|
33
|
+
|
|
34
|
+
while [[ $# -gt 0 ]]; do
|
|
35
|
+
case "$1" in
|
|
36
|
+
--help|-h)
|
|
37
|
+
cat <<'USAGE'
|
|
38
|
+
Usage: check-blind-spots.sh [flags]
|
|
39
|
+
|
|
40
|
+
Run 6 heuristic blind-spot checks on the codebase.
|
|
41
|
+
|
|
42
|
+
Flags:
|
|
43
|
+
--help Print this message and exit.
|
|
44
|
+
|
|
45
|
+
Checks:
|
|
46
|
+
verify-gap Story done, no verify evidence.
|
|
47
|
+
test-gap Code tagged, no test file references.
|
|
48
|
+
epic-orphan Capsule task with no story tag.
|
|
49
|
+
stale-tag Done story, tag still in code.
|
|
50
|
+
double-tag File tagged with multiple stories.
|
|
51
|
+
bootstrap-testless New story without test coverage.
|
|
52
|
+
|
|
53
|
+
Output: specs/blind-spots.json
|
|
54
|
+
|
|
55
|
+
Exit codes:
|
|
56
|
+
0 No HIGH-severity findings.
|
|
57
|
+
1 One or more HIGH-severity findings (or input files missing).
|
|
58
|
+
USAGE
|
|
59
|
+
exit 0
|
|
60
|
+
;;
|
|
61
|
+
*)
|
|
62
|
+
echo "check-blind-spots.sh: unknown flag: $1" >&2
|
|
63
|
+
echo "Try --help for usage." >&2
|
|
64
|
+
exit 1
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
# Input existence checks
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
if [[ ! -f "$EXEC_STATUS" ]]; then
|
|
73
|
+
echo "check-blind-spots.sh: execution-status.yaml: not found at $EXEC_STATUS" >&2
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# ---------------------------------------------------------------------------
|
|
78
|
+
# Detector logic (Python stdlib only)
|
|
79
|
+
# ---------------------------------------------------------------------------
|
|
80
|
+
python3 - "$REPO_ROOT" "$BLIND_SPOTS_JSON" "$EXEC_STATUS" "$MATRIX_JSON" "$VERIFICATIONS_DIR" "$EPICS_DIR" <<'PYEOF'
|
|
81
|
+
import json, os, re, sys
|
|
82
|
+
from pathlib import Path
|
|
83
|
+
from datetime import datetime, timezone
|
|
84
|
+
|
|
85
|
+
ROOT = Path(sys.argv[1])
|
|
86
|
+
BLIND_SPOTS_JSON = Path(sys.argv[2])
|
|
87
|
+
EXEC_STATUS = Path(sys.argv[3])
|
|
88
|
+
MATRIX_JSON = Path(sys.argv[4])
|
|
89
|
+
VERIFICATIONS_DIR = Path(sys.argv[5])
|
|
90
|
+
EPICS_DIR = Path(sys.argv[6])
|
|
91
|
+
|
|
92
|
+
findings: list[dict] = []
|
|
93
|
+
|
|
94
|
+
# -----------------------------------------------------------------------
|
|
95
|
+
# Parse execution-status.yaml → flat dict of story_id → status
|
|
96
|
+
# -----------------------------------------------------------------------
|
|
97
|
+
def parse_exec_status(path: Path) -> dict[str, str]:
|
|
98
|
+
status: dict[str, str] = {}
|
|
99
|
+
if not path.exists():
|
|
100
|
+
return status
|
|
101
|
+
text = path.read_text(encoding="utf-8")
|
|
102
|
+
lines = text.splitlines()
|
|
103
|
+
in_dev_status = False
|
|
104
|
+
for line in lines:
|
|
105
|
+
stripped = line.strip()
|
|
106
|
+
if stripped.startswith("development_status:"):
|
|
107
|
+
in_dev_status = True
|
|
108
|
+
continue
|
|
109
|
+
if not in_dev_status:
|
|
110
|
+
# Stop if we hit another top-level key
|
|
111
|
+
if stripped and not stripped.startswith(" ") and not stripped.startswith("#"):
|
|
112
|
+
if ":" in stripped:
|
|
113
|
+
in_dev_status = False
|
|
114
|
+
continue
|
|
115
|
+
if ":" in stripped and not stripped.startswith("#"):
|
|
116
|
+
# Lines like ' e38s04: "done"'
|
|
117
|
+
m = re.match(r'\s+(\S+):\s*"([^"]*)"', stripped)
|
|
118
|
+
if m:
|
|
119
|
+
status[m.group(1)] = m.group(2)
|
|
120
|
+
return status
|
|
121
|
+
|
|
122
|
+
dev_status = parse_exec_status(EXEC_STATUS)
|
|
123
|
+
|
|
124
|
+
# -----------------------------------------------------------------------
|
|
125
|
+
# Read traceability matrix (if available)
|
|
126
|
+
# -----------------------------------------------------------------------
|
|
127
|
+
matrix_data: dict | None = None
|
|
128
|
+
if MATRIX_JSON.exists():
|
|
129
|
+
matrix_data = json.loads(MATRIX_JSON.read_text(encoding="utf-8"))
|
|
130
|
+
|
|
131
|
+
# Build indexes from matrix
|
|
132
|
+
tagged_files: dict[str, list[str]] = {} # story_id → [files]
|
|
133
|
+
file_story_counts: dict[str, set[str]] = {} # file → set of story_ids
|
|
134
|
+
if matrix_data:
|
|
135
|
+
for s in matrix_data.get("stories", []):
|
|
136
|
+
sid = s["id"]
|
|
137
|
+
for link in s.get("links", []):
|
|
138
|
+
f = link["file"]
|
|
139
|
+
tagged_files.setdefault(sid, []).append(f)
|
|
140
|
+
file_story_counts.setdefault(f, set()).add(sid)
|
|
141
|
+
|
|
142
|
+
# Enumerate all tracked code files (skip .git, node_modules, specs/)
|
|
143
|
+
CODE_EXTENSIONS = {".sh", ".py", ".js", ".ts", ".jsx", ".tsx", ".md", ".yaml", ".yml", ".cjs", ".mjs", ".json"}
|
|
144
|
+
SKIP_DIRS = {".git", "node_modules", ".cursor", ".gemini", ".pi", "specs", "dist", "build", "__pycache__", ".bigpowers"}
|
|
145
|
+
|
|
146
|
+
def is_code_file(p: Path) -> bool:
|
|
147
|
+
return p.suffix in CODE_EXTENSIONS and not any(s in p.parts for s in SKIP_DIRS)
|
|
148
|
+
|
|
149
|
+
all_code_files: list[str] = []
|
|
150
|
+
for root, dirs, files in os.walk(str(ROOT)):
|
|
151
|
+
# Prune skip dirs
|
|
152
|
+
dirs[:] = [d for d in dirs if d not in SKIP_DIRS]
|
|
153
|
+
rel_root = str(Path(root).relative_to(ROOT))
|
|
154
|
+
for fname in files:
|
|
155
|
+
fpath = Path(root) / fname
|
|
156
|
+
if is_code_file(fpath):
|
|
157
|
+
all_code_files.append(str(fpath.relative_to(ROOT)))
|
|
158
|
+
|
|
159
|
+
# -----------------------------------------------------------------------
|
|
160
|
+
# Helper: find test files for a given code file
|
|
161
|
+
# -----------------------------------------------------------------------
|
|
162
|
+
TEST_PATTERNS = [
|
|
163
|
+
re.compile(r"(^|/)test(s)?/", re.IGNORECASE),
|
|
164
|
+
re.compile(r"(^|/)__tests__/", re.IGNORECASE),
|
|
165
|
+
re.compile(r"\.test\.", re.IGNORECASE),
|
|
166
|
+
re.compile(r"\.spec\.", re.IGNORECASE),
|
|
167
|
+
re.compile(r"_test\.", re.IGNORECASE),
|
|
168
|
+
re.compile(r"test_", re.IGNORECASE),
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
def has_test_files(code_files: list[str]) -> bool:
|
|
172
|
+
"""Check if any file in the repo looks like a test for the given code files."""
|
|
173
|
+
for cf in code_files:
|
|
174
|
+
cf_path = Path(cf)
|
|
175
|
+
cf_dir = cf_path.parent
|
|
176
|
+
cf_stem = cf_path.stem
|
|
177
|
+
for tf in all_code_files:
|
|
178
|
+
tp = Path(tf)
|
|
179
|
+
# Same directory test file
|
|
180
|
+
if tp.parent == cf_dir:
|
|
181
|
+
for pat in TEST_PATTERNS:
|
|
182
|
+
if pat.search(tp.name) and cf_stem in tp.name:
|
|
183
|
+
return True
|
|
184
|
+
# Tests dir sibling
|
|
185
|
+
test_dir_names = ["tests", "test", "__tests__"]
|
|
186
|
+
for tdn in test_dir_names:
|
|
187
|
+
test_dir = cf_dir / tdn
|
|
188
|
+
if str(test_dir) in tf:
|
|
189
|
+
if cf_stem in tp.name:
|
|
190
|
+
return True
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
# -----------------------------------------------------------------------
|
|
194
|
+
# Check A: verify-gap — story done but no verify evidence
|
|
195
|
+
# -----------------------------------------------------------------------
|
|
196
|
+
for sid, sstatus in dev_status.items():
|
|
197
|
+
if sstatus == "done":
|
|
198
|
+
verify_file = VERIFICATIONS_DIR / f"{sid}-verify.yaml"
|
|
199
|
+
if not verify_file.exists():
|
|
200
|
+
findings.append({
|
|
201
|
+
"check": "verify-gap",
|
|
202
|
+
"story_id": sid,
|
|
203
|
+
"severity": "HIGH",
|
|
204
|
+
"description": f"Story {sid} is marked done but no verification evidence exists at specs/verifications/{sid}-verify.yaml",
|
|
205
|
+
"remediation": f"Run verify-work for {sid} or create the verification evidence file"
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
# -----------------------------------------------------------------------
|
|
209
|
+
# Check B: test-gap — code tagged but no test file references
|
|
210
|
+
# -----------------------------------------------------------------------
|
|
211
|
+
for sid, files in tagged_files.items():
|
|
212
|
+
if dev_status.get(sid) in ("done", "active"):
|
|
213
|
+
if not has_test_files(files):
|
|
214
|
+
# Only flag if there are actual code files (not just docs)
|
|
215
|
+
code_only = [f for f in files if Path(f).suffix in {".sh", ".py", ".js", ".ts", ".jsx", ".tsx"} and "SKILL.md" not in f]
|
|
216
|
+
if code_only:
|
|
217
|
+
findings.append({
|
|
218
|
+
"check": "test-gap",
|
|
219
|
+
"story_id": sid,
|
|
220
|
+
"severity": "MEDIUM",
|
|
221
|
+
"description": f"Story {sid} has {len(code_only)} tagged code file(s) with no matching test files",
|
|
222
|
+
"remediation": f"Add test coverage for the tagged files: {', '.join(code_only[:3])}"
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
# -----------------------------------------------------------------------
|
|
226
|
+
# Check C: epic-orphan — capsule task with no story tag in any code file
|
|
227
|
+
# -----------------------------------------------------------------------
|
|
228
|
+
if EPICS_DIR.exists():
|
|
229
|
+
for epic_dir in sorted(EPICS_DIR.iterdir()):
|
|
230
|
+
if not epic_dir.is_dir() or epic_dir.name == "archive":
|
|
231
|
+
continue
|
|
232
|
+
epic_yaml = epic_dir / "epic.yaml"
|
|
233
|
+
if not epic_yaml.exists():
|
|
234
|
+
continue
|
|
235
|
+
# Extract story IDs from epic capsule task files
|
|
236
|
+
for task_file in sorted(epic_dir.glob("e*[0-9]-tasks.yaml")):
|
|
237
|
+
# e.g., e38s04-tasks.yaml → e38s04
|
|
238
|
+
sid_match = re.match(r"(e\d+s\d+)", task_file.name)
|
|
239
|
+
if not sid_match:
|
|
240
|
+
continue
|
|
241
|
+
sid = sid_match.group(1)
|
|
242
|
+
# Check if story has any tagged files (explicit or heuristic)
|
|
243
|
+
sstatus = dev_status.get(sid, "backlog")
|
|
244
|
+
if sstatus in ("done", "active") and sid not in tagged_files:
|
|
245
|
+
findings.append({
|
|
246
|
+
"check": "epic-orphan",
|
|
247
|
+
"story_id": sid,
|
|
248
|
+
"severity": "LOW",
|
|
249
|
+
"description": f"Story {sid} has capsule tasks but no story tags found in any code file",
|
|
250
|
+
"remediation": f"Add `// story: {sid}` tags to implementing files"
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
# -----------------------------------------------------------------------
|
|
254
|
+
# Check D: stale-tag — story done but tag still in code
|
|
255
|
+
# -----------------------------------------------------------------------
|
|
256
|
+
stale_from_matrix: set[str] = set()
|
|
257
|
+
if matrix_data:
|
|
258
|
+
stale_from_matrix = set(matrix_data.get("summary", {}).get("stale_tags", []))
|
|
259
|
+
|
|
260
|
+
for sid in stale_from_matrix:
|
|
261
|
+
findings.append({
|
|
262
|
+
"check": "stale-tag",
|
|
263
|
+
"story_id": sid,
|
|
264
|
+
"severity": "LOW",
|
|
265
|
+
"description": f"Story {sid} is marked done but still has story tags in code",
|
|
266
|
+
"remediation": f"Remove `// story: {sid}` tags from files or confirm the story should remain done"
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
# -----------------------------------------------------------------------
|
|
270
|
+
# Check E: double-tag — same file tagged with multiple stories
|
|
271
|
+
# -----------------------------------------------------------------------
|
|
272
|
+
for fpath, sids in file_story_counts.items():
|
|
273
|
+
if len(sids) > 1:
|
|
274
|
+
findings.append({
|
|
275
|
+
"check": "double-tag",
|
|
276
|
+
"file": fpath,
|
|
277
|
+
"severity": "MEDIUM",
|
|
278
|
+
"description": f"File '{fpath}' is tagged with multiple stories: {', '.join(sorted(sids))}",
|
|
279
|
+
"remediation": "Review whether this file genuinely implements multiple stories. If it's a shared utility, this is acceptable."
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
# -----------------------------------------------------------------------
|
|
283
|
+
# Check F: bootstrap-testless — new story (active/recent) without test evidence
|
|
284
|
+
# -----------------------------------------------------------------------
|
|
285
|
+
recent_threshold = 5 # flag active/done stories in the last 5 stories if no tests
|
|
286
|
+
active_and_recent = []
|
|
287
|
+
for sid in sorted(dev_status.keys()):
|
|
288
|
+
if dev_status[sid] in ("active",):
|
|
289
|
+
active_and_recent.append(sid)
|
|
290
|
+
|
|
291
|
+
for sid in active_and_recent:
|
|
292
|
+
# Check if story has tagged code AND no test files for those
|
|
293
|
+
if sid in tagged_files:
|
|
294
|
+
code_files = tagged_files[sid]
|
|
295
|
+
code_only = [f for f in code_files if Path(f).suffix in {".sh", ".py", ".js", ".ts", ".jsx", ".tsx"} and "SKILL.md" not in f]
|
|
296
|
+
if code_only and not has_test_files(code_files):
|
|
297
|
+
findings.append({
|
|
298
|
+
"check": "bootstrap-testless",
|
|
299
|
+
"story_id": sid,
|
|
300
|
+
"severity": "HIGH",
|
|
301
|
+
"description": f"Active story {sid} has {len(code_only)} tagged code file(s) but no test files detected",
|
|
302
|
+
"remediation": f"Add test files for: {', '.join(code_only[:3])}"
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
# -----------------------------------------------------------------------
|
|
306
|
+
# De-duplicate findings (same check + story_id)
|
|
307
|
+
# -----------------------------------------------------------------------
|
|
308
|
+
seen: set[tuple] = set()
|
|
309
|
+
deduped: list[dict] = []
|
|
310
|
+
for f in findings:
|
|
311
|
+
key = (f["check"], f.get("story_id", f.get("file", "")))
|
|
312
|
+
if key not in seen:
|
|
313
|
+
seen.add(key)
|
|
314
|
+
deduped.append(f)
|
|
315
|
+
findings = deduped
|
|
316
|
+
|
|
317
|
+
# -----------------------------------------------------------------------
|
|
318
|
+
# Emit blind-spots.json
|
|
319
|
+
# -----------------------------------------------------------------------
|
|
320
|
+
high_count = sum(1 for f in findings if f["severity"] == "HIGH")
|
|
321
|
+
medium_count = sum(1 for f in findings if f["severity"] == "MEDIUM")
|
|
322
|
+
low_count = sum(1 for f in findings if f["severity"] == "LOW")
|
|
323
|
+
|
|
324
|
+
blind_spots = {
|
|
325
|
+
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
326
|
+
"version": "1.0",
|
|
327
|
+
"summary": {
|
|
328
|
+
"total_findings": len(findings),
|
|
329
|
+
"high": high_count,
|
|
330
|
+
"medium": medium_count,
|
|
331
|
+
"low": low_count
|
|
332
|
+
},
|
|
333
|
+
"findings": findings
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
BLIND_SPOTS_JSON.parent.mkdir(parents=True, exist_ok=True)
|
|
337
|
+
BLIND_SPOTS_JSON.write_text(json.dumps(blind_spots, indent=2), encoding="utf-8")
|
|
338
|
+
|
|
339
|
+
# Print summary to stdout
|
|
340
|
+
print(f"check-blind-spots.sh: {len(findings)} findings ({high_count} HIGH, {medium_count} MEDIUM, {low_count} LOW)")
|
|
341
|
+
for f in findings:
|
|
342
|
+
print(f" [{f['severity']}] {f['check']}: {f['description'][:100]}")
|
|
343
|
+
|
|
344
|
+
if high_count > 0:
|
|
345
|
+
print(f"\n⚠️ {high_count} HIGH-severity finding(s) — review specs/blind-spots.json")
|
|
346
|
+
sys.exit(1)
|
|
347
|
+
|
|
348
|
+
sys.exit(0)
|
|
349
|
+
PYEOF
|
package/scripts/trace-stories.sh
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: build-epic
|
|
3
|
+
# story: e38s02
|
|
3
4
|
model: sonnet
|
|
4
5
|
effort: standard
|
|
5
6
|
description: Eight-step epic build cycle — reads state.yaml, execution-status.yaml, and one epic capsule; updates status via bp-yaml-set or direct edit. Resume mode runs one step per invocation. Use instead of ad-hoc execute-plan for release work.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gate-trace
|
|
3
|
+
description: "Deterministic traceability quality gate — reads coverage matrix + blind-spot data, applies decision rules with oracle confidence downgrade, emits PASS/CONCERNS/FAIL/WAIVED verdict. Use before release-branch to gate merges on traceability."
|
|
4
|
+
# story: e38s06
|
|
5
|
+
model: haiku
|
|
6
|
+
effort: light
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Gate Trace
|
|
10
|
+
|
|
11
|
+
Deterministic quality gate that combines traceability coverage and blind-spot data into a single PASS/FAIL/CONCERNS/WAIVED decision before release.
|
|
12
|
+
|
|
13
|
+
## Decision Rules
|
|
14
|
+
|
|
15
|
+
| Rule | Condition | Verdict |
|
|
16
|
+
|------|-----------|---------|
|
|
17
|
+
| R1 | Any undone story with 0 code tags | FAIL |
|
|
18
|
+
| R2 | Any story done but no verify evidence | CONCERNS |
|
|
19
|
+
| R3 | P0 story (top WSJF quartile) with 0% coverage | FAIL |
|
|
20
|
+
| R4 | Overall coverage < 60% | CONCERNS |
|
|
21
|
+
| R5 | Overall ≥ 80% + no critical gaps + all verify → PASS | PASS |
|
|
22
|
+
|
|
23
|
+
## Oracle Confidence Downgrade
|
|
24
|
+
|
|
25
|
+
TEA-inspired: if trace links rely on heuristics rather than explicit tags, confidence drops.
|
|
26
|
+
|
|
27
|
+
| Heuristic Ratio | Downgrade |
|
|
28
|
+
|-----------------|-----------|
|
|
29
|
+
| > 50% links from heuristics (file-name or task-reference) | One level (PASS→CONCERNS, CONCERNS→FAIL) |
|
|
30
|
+
| > 80% links from heuristics | Two levels (PASS→FAIL, CONCERNS→FAIL) |
|
|
31
|
+
|
|
32
|
+
## Process
|
|
33
|
+
|
|
34
|
+
1. **Pre-flight:** Ensure `scripts/trace-stories.sh --json` has been run (produces `specs/traceability-matrix.json`). If not present, run it.
|
|
35
|
+
2. Ensure `scripts/check-blind-spots.sh` has been run (produces `specs/blind-spots.json`). If not present, run it.
|
|
36
|
+
3. Read `specs/traceability-matrix.json` and `specs/blind-spots.json`.
|
|
37
|
+
4. Apply decision rules R1–R5 in order (first match wins).
|
|
38
|
+
5. Apply oracle confidence downgrade based on the heuristic link ratio from the matrix's `oracle_stats`.
|
|
39
|
+
6. Output verdict + rationale to stdout.
|
|
40
|
+
7. Update `specs/execution-status.yaml` with gate-trace result.
|
|
41
|
+
|
|
42
|
+
## Verdict Semantics
|
|
43
|
+
|
|
44
|
+
| Verdict | Meaning | Action |
|
|
45
|
+
|---------|---------|--------|
|
|
46
|
+
| PASS | All gates satisfied | Proceed with merge |
|
|
47
|
+
| CONCERNS | Non-critical issues found | Requires explicit human override in `state.yaml` |
|
|
48
|
+
| FAIL | Critical traceability gap | Block merge — fix gap first |
|
|
49
|
+
| WAIVED | Cannot evaluate (missing inputs) | Skip gate — data not available |
|
|
50
|
+
|
|
51
|
+
## Output Format
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
gate_trace:
|
|
55
|
+
verdict: PASS|CONCERNS|FAIL|WAIVED
|
|
56
|
+
generated_at: "<ISO 8601>"
|
|
57
|
+
rationale: "<human-readable explanation>"
|
|
58
|
+
heuristic_ratio: <0.0–1.0>
|
|
59
|
+
downgrade_applied: <true|false>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Integration Points
|
|
63
|
+
|
|
64
|
+
- **release-branch SKILL.md** — pre-PR gate (FAIL blocks merge).
|
|
65
|
+
- **sync-skills.yml** — CI gate (FAIL blocks pipeline).
|
|
66
|
+
- **verify-work SKILL.md** — runs blind-spot checks; gate-trace consumes the result.
|
|
67
|
+
|
|
68
|
+
## References
|
|
69
|
+
|
|
70
|
+
- BMAD TEA traceability approach (market survey 2026-07-02).
|
|
71
|
+
- scripts/trace-stories.sh (e38s01) — produces traceability-matrix.json.
|
|
72
|
+
- scripts/check-blind-spots.sh (e38s04) — produces blind-spots.json.
|
|
73
|
+
- specs/execution-status.yaml — output target for gate result.
|
|
74
|
+
|
|
75
|
+
## Verify
|
|
76
|
+
|
|
77
|
+
→ verify: `test -f skills/gate-trace/SKILL.md && grep -q 'PASS.*CONCERNS.*FAIL.*WAIVED' skills/gate-trace/SKILL.md && echo "OK: gate-trace skill created" || echo "FAIL"`
|
|
78
|
+
|
|
79
|
+
## Handoff
|
|
80
|
+
|
|
81
|
+
Gate: READY → next: release-branch (final step before merge)
|
|
82
|
+
Writes: state.yaml handoff.next_skill = release-branch
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- story: e38s07 -->
|
|
1
2
|
---
|
|
2
3
|
name: release-branch
|
|
3
4
|
model: haiku
|
|
@@ -13,21 +14,19 @@ Finalize a completed feature branch: verify coverage gates, integrate onto `main
|
|
|
13
14
|
|
|
14
15
|
## Additional modes
|
|
15
16
|
|
|
16
|
-
- `--hotfix`:
|
|
17
|
-
- `--squash-state`:
|
|
17
|
+
- `--hotfix`: Cherry-pick to main + tag. Skip PR in solo.
|
|
18
|
+
- `--squash-state`: Squash `chore(state):` commits before merge.
|
|
18
19
|
|
|
19
20
|
## Integrate mode
|
|
20
21
|
|
|
21
|
-
Read `specs/state.yaml` key `workflow_mode`
|
|
22
|
+
Read `specs/state.yaml` key `workflow_mode` (`team-pr` | `solo-git`). Fall back to `profiles/solo-git.md`.
|
|
22
23
|
|
|
23
24
|
| Mode | When | Ship path |
|
|
24
25
|
|------|------|-----------|
|
|
25
|
-
| **solo-local** | `workflow_mode: solo-git`
|
|
26
|
+
| **solo-local** | `workflow_mode: solo-git` | Auto: `scripts/land-branch.sh` if present, else fallback (Step 5) |
|
|
26
27
|
| **team-pr** | `workflow_mode: team-pr` (default) | `gh pr create` → `gh pr merge --squash` |
|
|
27
28
|
|
|
28
|
-
If unsure
|
|
29
|
-
|
|
30
|
-
> **Auto-detect note:** The solo-local path first checks if `scripts/land-branch.sh` exists and is executable. If present, the script handles the full squash-merge workflow. If absent, the built-in fallback sequence runs instead.
|
|
29
|
+
If unsure, prefer **solo-local**.
|
|
31
30
|
|
|
32
31
|
## Process
|
|
33
32
|
|
|
@@ -53,6 +52,10 @@ git log main...HEAD --oneline | grep -vE "^[a-f0-9]+ (feat|fix|docs|style|refact
|
|
|
53
52
|
|
|
54
53
|
If REVIEW.md is missing or stale → run `security-review` inline. Findings block the merge unless documented in EXCEPTIONS.md.
|
|
55
54
|
|
|
55
|
+
### 2b. Traceability gate
|
|
56
|
+
|
|
57
|
+
Run `gate-trace` before merge. FAIL blocks merge; CONCERNS requires explicit override in `specs/state.yaml` (`traceability_override: CONCERNS accepted, reason: <explanation>`). WAIVED if no matrix available.
|
|
58
|
+
|
|
56
59
|
### 3. Diff review
|
|
57
60
|
|
|
58
61
|
- [ ] All commits intentional, no secrets, CONVENTIONS.md compliance
|
|
@@ -63,20 +66,14 @@ Options: **Release (solo-local)** / **Open PR** / **Keep branch** / **Discard**
|
|
|
63
66
|
|
|
64
67
|
### 5. Solo-local integrate
|
|
65
68
|
|
|
66
|
-
Run `commit-message`
|
|
69
|
+
Run `commit-message` for the squash subject, then land:
|
|
67
70
|
|
|
68
|
-
**Path A — `scripts/land-branch.sh` exists (happy path):**
|
|
69
71
|
```bash
|
|
72
|
+
# Path A (preferred):
|
|
70
73
|
bash scripts/land-branch.sh <task-slug> "feat(scope): description"
|
|
74
|
+
# Path B (fallback if land-branch.sh missing): see REFERENCE.md
|
|
71
75
|
```
|
|
72
76
|
|
|
73
|
-
**Path B — `scripts/land-branch.sh` missing (fallback):**
|
|
74
|
-
See [REFERENCE.md](REFERENCE.md)
|
|
75
|
-
|
|
76
|
-
**Report which path was taken.** Print exactly:
|
|
77
|
-
- `"used land-branch.sh"` if Path A
|
|
78
|
-
- `"used fallback merge (land-branch.sh not found)"` if Path B
|
|
79
|
-
|
|
80
77
|
### 6. Create PR (team-pr only)
|
|
81
78
|
|
|
82
79
|
See [REFERENCE.md](REFERENCE.md) for the full PR body template and gh commands.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- story: e38s05 -->
|
|
1
2
|
---
|
|
2
3
|
name: verify-work
|
|
3
4
|
description: Multi-phase UAT gate — cold-start smoke, build, typecheck, lint, tests, step-by-step manual verification, gaps-closure loop. Use after execute-plan or develop-tdd, before audit-code.
|
|
@@ -36,6 +37,7 @@ Review answers "is the code good?"; Verify answers "does the built thing do what
|
|
|
36
37
|
3. **AGENTS.md preflight** — before running default checks, call `bash scripts/bp-read-agents.sh` to detect project-specific commands. If `BP_PREFLIGHT` is set, run it instead of the default mechanical gates (or in addition to them if the project requires both). Output: `"Using preflight from AGENTS.md: <cmd>"`. Fall back to `CLAUDE.md` commands if AGENTS.md is absent.
|
|
37
38
|
4. Mechanical gates: build → typecheck → lint → tests (from `CLAUDE.md` or AGENTS.md).
|
|
38
39
|
5. **Security scan** — run `security-review` against the git diff (working tree vs merge-base). Parse findings report. If any HIGH findings with confidence ≥ 8 exist → **block the gate**. Write findings to `specs/security/REVIEW.md`. Allow documented exceptions via `specs/security/EXCEPTIONS.md`. MEDIUM/LOW findings warn but don't block.
|
|
40
|
+
5a. **Blind-spot check** — run `bash scripts/check-blind-spots.sh`. This detects structural quality gaps (verify-gap, test-gap, stale-tag, etc.) beyond percentage coverage. If any HIGH-severity findings exist → **block the verify-work PASS gate**. Findings are written to `specs/blind-spots.json`. MEDIUM/LOW findings warn but don't block.
|
|
39
41
|
6. **Step-by-step UAT** — one user-observable action at a time.
|
|
40
42
|
7. **Gaps loop** — failures → log → `plan-work` → re-verify. Unaddressed HIGH findings from step 5 feed into this loop alongside other quality gaps.
|
|
41
43
|
|
package/skills-lock.json
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"build-epic": {
|
|
25
25
|
"description": "Eight-step epic build cycle — reads state.yaml, execution-status.yaml, and one epic capsule; updates status via bp-yaml-set or direct edit. Resume mode runs one step per invocation. Use instead of ad-hoc execute-plan for release work.",
|
|
26
|
-
"sha256": "
|
|
26
|
+
"sha256": "5abf6858c529996c",
|
|
27
27
|
"path": "skills/build-epic/SKILL.md"
|
|
28
28
|
},
|
|
29
29
|
"change-request": {
|
|
@@ -126,6 +126,11 @@
|
|
|
126
126
|
"sha256": "ce4781244b970a14",
|
|
127
127
|
"path": "skills/fix-bug/SKILL.md"
|
|
128
128
|
},
|
|
129
|
+
"gate-trace": {
|
|
130
|
+
"description": "\"Deterministic traceability quality gate — reads coverage matrix + blind-spot data, applies decision rules with oracle confidence downgrade, emits PASS/CONCERNS/FAIL/WAIVED verdict. Use before release-branch to gate merges on traceability.\"# story: e38s06",
|
|
131
|
+
"sha256": "15ca25acd70b90dd",
|
|
132
|
+
"path": "skills/gate-trace/SKILL.md"
|
|
133
|
+
},
|
|
129
134
|
"grill-me": {
|
|
130
135
|
"description": "Interactive assumption-surfacing Q&A that stress-tests a plan through relentless questioning until every decision is resolved. Use when user wants to challenge a plan, validate decisions from conversation/context, or mentions \"grill me\". For doc-grounded variant, use grill-with-docs.",
|
|
131
136
|
"sha256": "8ef90da0f127f2fd",
|
|
@@ -213,7 +218,7 @@
|
|
|
213
218
|
},
|
|
214
219
|
"release-branch": {
|
|
215
220
|
"description": "Make the merge/PR/keep/discard decision for a feature branch, verify coverage gates, create the PR with gh, and clean up the worktree. Use when a feature is done and ready to ship, or when user says \"release\", \"merge\", or \"open a PR\".",
|
|
216
|
-
"sha256": "
|
|
221
|
+
"sha256": "354267f0f4b593b5",
|
|
217
222
|
"path": "skills/release-branch/SKILL.md"
|
|
218
223
|
},
|
|
219
224
|
"request-review": {
|
|
@@ -338,7 +343,7 @@
|
|
|
338
343
|
},
|
|
339
344
|
"verify-work": {
|
|
340
345
|
"description": "Multi-phase UAT gate — cold-start smoke, build, typecheck, lint, tests, step-by-step manual verification, gaps-closure loop. Use after execute-plan or develop-tdd, before audit-code.",
|
|
341
|
-
"sha256": "
|
|
346
|
+
"sha256": "b2828b807467e5c7",
|
|
342
347
|
"path": "skills/verify-work/SKILL.md"
|
|
343
348
|
},
|
|
344
349
|
"visual-dashboard": {
|