@su-record/vibe 2.9.20 → 2.9.22
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/CLAUDE.md +4 -3
- package/commands/vibe.contract.md +29 -29
- package/commands/vibe.regress.md +20 -20
- package/commands/vibe.run.md +6 -6
- package/commands/vibe.spec.md +6 -6
- package/commands/vibe.test.md +96 -0
- package/commands/vibe.verify.md +9 -9
- package/hooks/scripts/__tests__/pre-tool-guard.test.js +82 -1
- package/hooks/scripts/pre-tool-guard.js +60 -19
- package/package.json +1 -1
- package/skills/vibe-contract/SKILL.md +58 -58
- package/skills/vibe-regress/SKILL.md +94 -94
- package/skills/vibe-spec/SKILL.md +12 -12
- package/skills/vibe-test/SKILL.md +247 -0
|
@@ -9,18 +9,18 @@ chain-next: []
|
|
|
9
9
|
|
|
10
10
|
# vibe.contract — API Contract Drift Detection
|
|
11
11
|
|
|
12
|
-
**Purpose**:
|
|
12
|
+
**Purpose**: catch divergence between the SPEC's external contract and the actual implementation. Passing tests ≠ contract preserved.
|
|
13
13
|
|
|
14
14
|
## Why this exists
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Hidden vibe-coding weakness: as the implementation grows, response shapes drift away from what the SPEC documents. Scenario tests still pass — but **external consumers break**. Manual SPEC-vs-code review is high-friction, so mechanize it.
|
|
17
17
|
|
|
18
18
|
## Storage Contract
|
|
19
19
|
|
|
20
20
|
```
|
|
21
21
|
.claude/vibe/contracts/
|
|
22
|
-
<feature>.md #
|
|
23
|
-
<feature>.snapshot.md #
|
|
22
|
+
<feature>.md # contract SSOT (extracted from SPEC)
|
|
23
|
+
<feature>.snapshot.md # implementation snapshot (last check)
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
### Contract frontmatter schema
|
|
@@ -30,9 +30,9 @@ chain-next: []
|
|
|
30
30
|
feature: string
|
|
31
31
|
extracted-from: .claude/vibe/specs/<feature>.md
|
|
32
32
|
extracted-at: ISO-8601
|
|
33
|
-
source-spec-hash: sha256 #
|
|
33
|
+
source-spec-hash: sha256 # for change detection
|
|
34
34
|
endpoints:
|
|
35
|
-
- id: unique-kebab-id #
|
|
35
|
+
- id: unique-kebab-id # e.g. get-user-by-id
|
|
36
36
|
kind: http | graphql | event | function
|
|
37
37
|
# http
|
|
38
38
|
method: GET | POST | PUT | DELETE | PATCH
|
|
@@ -64,75 +64,75 @@ endpoints:
|
|
|
64
64
|
|
|
65
65
|
## Subcommands
|
|
66
66
|
|
|
67
|
-
### 1. `extract <feature>` —
|
|
67
|
+
### 1. `extract <feature>` — pull contract out of the SPEC
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
1. SPEC
|
|
71
|
-
2.
|
|
69
|
+
**Steps**:
|
|
70
|
+
1. Load SPEC file (single file or split folder)
|
|
71
|
+
2. Search sections in this order:
|
|
72
72
|
- `## API` / `## Endpoints` / `## Interface` / `## Contract`
|
|
73
|
-
- Markdown
|
|
74
|
-
-
|
|
75
|
-
3.
|
|
76
|
-
4.
|
|
77
|
-
5. `source-spec-hash`:
|
|
78
|
-
6. `.claude/vibe/contracts/<feature>.md`
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
### 2. `check <feature>` —
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
1. `.claude/vibe/contracts/<feature>.md
|
|
86
|
-
2.
|
|
87
|
-
- http:
|
|
88
|
-
- graphql: resolver
|
|
89
|
-
- event:
|
|
90
|
-
- function:
|
|
91
|
-
3.
|
|
92
|
-
4.
|
|
93
|
-
5.
|
|
94
|
-
|
|
95
|
-
### 3. `diff <feature>` —
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
1. `.snapshot.md
|
|
99
|
-
2.
|
|
100
|
-
3.
|
|
73
|
+
- Markdown tables (method/path/request/response headers)
|
|
74
|
+
- OpenAPI/JSON Schema snippets inside code blocks
|
|
75
|
+
3. Extraction failure (no such section) → **exit cleanly with `no-contract` state**. Not every feature has an API.
|
|
76
|
+
4. Success → convert to the frontmatter structure
|
|
77
|
+
5. `source-spec-hash`: sha256 of SPEC content (for next extract to detect change)
|
|
78
|
+
6. Save to `.claude/vibe/contracts/<feature>.md` (no-op if file exists with the same hash)
|
|
79
|
+
|
|
80
|
+
**Caveat**: extraction is LLM-driven. Mark low-confidence fields with `# unconfirmed` so the user can review.
|
|
81
|
+
|
|
82
|
+
### 2. `check <feature>` — contract vs implementation
|
|
83
|
+
|
|
84
|
+
**Steps**:
|
|
85
|
+
1. Load `.claude/vibe/contracts/<feature>.md`. If missing → **suggest extract first**.
|
|
86
|
+
2. For each endpoint, find implementation:
|
|
87
|
+
- http: detect framework (Express, Fastify, Next.js API routes, Hono, ...)
|
|
88
|
+
- graphql: locate resolver files
|
|
89
|
+
- event: producer/consumer code
|
|
90
|
+
- function: module export
|
|
91
|
+
3. Extract implementation signature/schema → compare against contract
|
|
92
|
+
4. Classify drift (severity table in command file)
|
|
93
|
+
5. Persist snapshot at `.claude/vibe/contracts/<feature>.snapshot.md` (current implementation state)
|
|
94
|
+
|
|
95
|
+
### 3. `diff <feature>` — changes since last snapshot
|
|
96
|
+
|
|
97
|
+
**Steps**:
|
|
98
|
+
1. If `.snapshot.md` does not exist → say "first run" and exit
|
|
99
|
+
2. Re-extract current implementation; compare to existing snapshot
|
|
100
|
+
3. Output **only changed fields** in ASCII diff form:
|
|
101
101
|
```
|
|
102
102
|
endpoints/get-user-by-id/response/200:
|
|
103
103
|
- email: string
|
|
104
|
-
+ email: string | null ← nullability
|
|
105
|
-
+ phoneNumber: string ←
|
|
104
|
+
+ email: string | null ← nullability added (P1 breaking)
|
|
105
|
+
+ phoneNumber: string ← new field (P3 safe)
|
|
106
106
|
```
|
|
107
|
-
4.
|
|
107
|
+
4. On any drift, auto-call `/vibe.regress register --from-contract`
|
|
108
108
|
|
|
109
109
|
## Drift Severity Matrix
|
|
110
110
|
|
|
111
|
-
(command file
|
|
111
|
+
(matches command file — keep both in sync on edits)
|
|
112
112
|
|
|
113
113
|
## Integration Points
|
|
114
114
|
|
|
115
115
|
### From /vibe.spec
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
Auto-invoke right after the SPEC is written:
|
|
118
118
|
```
|
|
119
119
|
Load skill `vibe-contract` with: extract <feature>
|
|
120
120
|
```
|
|
121
|
-
|
|
121
|
+
Failure does not stop `/vibe.spec` (extraction is optional). On success, `/vibe.run` references this contract.
|
|
122
122
|
|
|
123
123
|
### From /vibe.verify
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
After all scenarios pass:
|
|
126
126
|
```
|
|
127
127
|
Load skill `vibe-contract` with: check <feature>
|
|
128
128
|
```
|
|
129
|
-
- drift
|
|
130
|
-
- P1 drift → verify
|
|
131
|
-
- P2/P3 drift →
|
|
129
|
+
- no drift → verify still passes
|
|
130
|
+
- P1 drift → demote verify to fail; auto-register
|
|
131
|
+
- P2 / P3 drift → warning only; verify still passes
|
|
132
132
|
|
|
133
133
|
### To /vibe.regress
|
|
134
134
|
|
|
135
|
-
P1 drift
|
|
135
|
+
On P1 drift:
|
|
136
136
|
```
|
|
137
137
|
Load skill `vibe-regress` with:
|
|
138
138
|
subcommand: register --from-contract
|
|
@@ -143,15 +143,15 @@ Load skill `vibe-regress` with:
|
|
|
143
143
|
|
|
144
144
|
## Framework Detection Rules
|
|
145
145
|
|
|
146
|
-
HTTP framework
|
|
147
|
-
1. `package.json` dependencies
|
|
146
|
+
HTTP framework detection order:
|
|
147
|
+
1. `package.json` dependencies: `next` → Next.js API routes
|
|
148
148
|
2. `fastify` → Fastify
|
|
149
149
|
3. `express` → Express
|
|
150
150
|
4. `hono` → Hono
|
|
151
151
|
5. `@nestjs/core` → NestJS
|
|
152
|
-
6.
|
|
152
|
+
6. None detected → ask user for manual mapping
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
After detection, grep for each framework's **route definition pattern** to map endpoints:
|
|
155
155
|
- Next.js: `pages/api/**` or `app/api/**/route.ts`
|
|
156
156
|
- Express: `app.get|post|put|delete|patch\(`
|
|
157
157
|
- Fastify: `fastify.get|post|...` or route configuration
|
|
@@ -159,8 +159,8 @@ HTTP framework 감지 순서:
|
|
|
159
159
|
|
|
160
160
|
## Done Criteria
|
|
161
161
|
|
|
162
|
-
- [ ] `extract
|
|
163
|
-
- [ ] `source-spec-hash
|
|
164
|
-
- [ ] `check
|
|
165
|
-
- [ ] P1 drift
|
|
166
|
-
- [ ]
|
|
162
|
+
- [ ] `extract` does not error on SPEC without an API section
|
|
163
|
+
- [ ] `source-spec-hash`-based re-extract is a no-op when unchanged
|
|
164
|
+
- [ ] `check` reports each drift with severity + location (file:line)
|
|
165
|
+
- [ ] P1 drift always invokes `/vibe.regress`
|
|
166
|
+
- [ ] On framework detection failure, ask the user — do not silently skip
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vibe-regress
|
|
3
3
|
tier: core
|
|
4
|
-
description: "Regression test auto-evolution. Registers bugs (auto from /vibe.verify failures or manual), generates preventive vitest/jest files from bug records, clusters repeated patterns (3+ same root-cause-tag) into shared tests, and imports historical `fix:` commits from git log. Storage: .claude/vibe/regressions/<slug>.md. Must use this skill when user runs /vibe.regress, when /vibe.verify produces a failure, or when the user says 'don't let this happen again' / '
|
|
4
|
+
description: "Regression test auto-evolution. Registers bugs (auto from /vibe.verify failures or manual), generates preventive vitest/jest files from bug records, clusters repeated patterns (3+ same root-cause-tag) into shared tests, and imports historical `fix:` commits from git log. Storage: .claude/vibe/regressions/<slug>.md. Must use this skill when user runs /vibe.regress, when /vibe.verify produces a failure, or when the user says 'don't let this happen again' / 'regression test' / '회귀 테스트'."
|
|
5
5
|
triggers: [regress, regression, "회귀", "다시는", "반복 버그", "fix commit"]
|
|
6
6
|
priority: 70
|
|
7
7
|
chain-next: []
|
|
@@ -9,92 +9,92 @@ chain-next: []
|
|
|
9
9
|
|
|
10
10
|
# vibe.regress — Regression Auto-Evolution
|
|
11
11
|
|
|
12
|
-
**Purpose**:
|
|
12
|
+
**Purpose**: never fix the same bug twice. Each fix grows a preventive test.
|
|
13
13
|
|
|
14
14
|
## Why this exists
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
A classic vibe-coding weakness: LLMs reintroduce bugs of the same class. Regression tests are the only mechanical defense. But if the human has to write the test every time, it gets skipped — so automate.
|
|
17
17
|
|
|
18
18
|
## Storage Contract
|
|
19
19
|
|
|
20
20
|
```
|
|
21
21
|
.claude/vibe/regressions/
|
|
22
|
-
<bug-slug>.md #
|
|
23
|
-
_cluster-<tag>.md #
|
|
22
|
+
<bug-slug>.md # one file per bug
|
|
23
|
+
_cluster-<tag>.md # shared-test design produced by `cluster`
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
### Frontmatter schema (
|
|
26
|
+
### Frontmatter schema (strict)
|
|
27
27
|
|
|
28
28
|
```yaml
|
|
29
|
-
slug: string # kebab-case,
|
|
30
|
-
symptom: string #
|
|
31
|
-
root-cause-tag: enum #
|
|
32
|
-
fix-commit: string # git hash (
|
|
33
|
-
test-path: string #
|
|
29
|
+
slug: string # kebab-case, globally unique
|
|
30
|
+
symptom: string # one line, user-facing
|
|
31
|
+
root-cause-tag: enum # only the allowed tags below
|
|
32
|
+
fix-commit: string # git hash (or "pending")
|
|
33
|
+
test-path: string # generated test file path (or "pending")
|
|
34
34
|
status: open | test-generated | resolved
|
|
35
35
|
registered: YYYY-MM-DD
|
|
36
|
-
feature: string #
|
|
36
|
+
feature: string # related feature name (matches SPEC)
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
### Allowed `root-cause-tag` values
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
Clustering depends on this, so use **only the predefined set**:
|
|
42
42
|
|
|
43
|
-
- `timezone` —
|
|
44
|
-
- `nullability` — null/undefined/empty
|
|
45
|
-
- `concurrency` — race
|
|
46
|
-
- `boundary` — off-by-one, edge
|
|
47
|
-
- `encoding` — charset, URL encoding,
|
|
48
|
-
- `validation` —
|
|
49
|
-
- `auth` —
|
|
50
|
-
- `state-sync` —
|
|
51
|
-
- `integration` —
|
|
52
|
-
- `type-narrow` — TypeScript
|
|
53
|
-
- `other` —
|
|
43
|
+
- `timezone` — timezone / DST / off-by-one in time
|
|
44
|
+
- `nullability` — null / undefined / empty handling
|
|
45
|
+
- `concurrency` — race conditions
|
|
46
|
+
- `boundary` — off-by-one, edge values
|
|
47
|
+
- `encoding` — charset, URL encoding, escaping
|
|
48
|
+
- `validation` — missing input validation
|
|
49
|
+
- `auth` — authn/authz logic
|
|
50
|
+
- `state-sync` — client/server state mismatch
|
|
51
|
+
- `integration` — external API call failure
|
|
52
|
+
- `type-narrow` — TypeScript type narrowing mistake
|
|
53
|
+
- `other` — when nothing fits (add new tags later)
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
**Rule**: if a new tag is needed, do not force-fit into an existing one — register as `other`. Once `other` reaches 3 entries, propose adding a new tag.
|
|
56
56
|
|
|
57
57
|
## Subcommands
|
|
58
58
|
|
|
59
|
-
### 1. `register "<symptom>"` —
|
|
59
|
+
### 1. `register "<symptom>"` — manual registration
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
Most calls are automatic; manual use is rare (bugs found outside `/vibe.verify`, or production incidents).
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
1. `getCurrentTime
|
|
65
|
-
2. `git log -1 --format=%H
|
|
66
|
-
3.
|
|
63
|
+
**Steps**:
|
|
64
|
+
1. `getCurrentTime` for today's date
|
|
65
|
+
2. `git log -1 --format=%H` for current commit hash (fix-commit candidate)
|
|
66
|
+
3. Conversation extracts:
|
|
67
67
|
- Reproduction steps (Given/When/Then)
|
|
68
|
-
- Root
|
|
69
|
-
- Fix
|
|
70
|
-
4. `root-cause-tag
|
|
71
|
-
5. slug
|
|
72
|
-
6. `.claude/vibe/regressions/<slug>.md`
|
|
73
|
-
|
|
74
|
-
### 2. `generate <slug>` —
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
1. bug
|
|
78
|
-
2.
|
|
79
|
-
- `package.json
|
|
80
|
-
-
|
|
81
|
-
3.
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
4.
|
|
85
|
-
5.
|
|
86
|
-
6. bug
|
|
87
|
-
7.
|
|
88
|
-
|
|
89
|
-
### 3. `list` —
|
|
68
|
+
- Root-cause paragraph
|
|
69
|
+
- Fix description
|
|
70
|
+
4. `root-cause-tag` is **inferred from the allowed set, then confirmed with the user**. If unclear → `other`.
|
|
71
|
+
5. Generate slug: kebab-case keywords from the symptom; on collision append `-2`
|
|
72
|
+
6. Write `.claude/vibe/regressions/<slug>.md` (status: `open`)
|
|
73
|
+
|
|
74
|
+
### 2. `generate <slug>` — generate preventive test
|
|
75
|
+
|
|
76
|
+
**Steps**:
|
|
77
|
+
1. Read bug file
|
|
78
|
+
2. Detect test stack:
|
|
79
|
+
- From `package.json` `devDependencies`: prefer `vitest` over `jest`
|
|
80
|
+
- If neither → **ask user, then stop**
|
|
81
|
+
3. Decide test location:
|
|
82
|
+
- Sibling `__tests__/` next to the implementation file, OR
|
|
83
|
+
- The project's existing test dir (vitest config `test.include`)
|
|
84
|
+
4. File name: `<original-file>.regression.test.ts`
|
|
85
|
+
5. Body: render `templates/test-vitest.md` or `templates/test-jest.md`
|
|
86
|
+
6. Update bug frontmatter: `test-path`, `status: test-generated`
|
|
87
|
+
7. **Run the test immediately** — should fail (if not yet fixed) or pass (if fixed). Record outcome in frontmatter.
|
|
88
|
+
|
|
89
|
+
### 3. `list` — open items
|
|
90
90
|
|
|
91
91
|
```
|
|
92
|
-
/vibe.regress list # status != resolved
|
|
93
|
-
/vibe.regress list --feature login # feature
|
|
94
|
-
/vibe.regress list --tag timezone # tag
|
|
92
|
+
/vibe.regress list # status != resolved
|
|
93
|
+
/vibe.regress list --feature login # filter by feature
|
|
94
|
+
/vibe.regress list --tag timezone # filter by tag
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
Terminal table:
|
|
98
98
|
|
|
99
99
|
```
|
|
100
100
|
SLUG FEATURE TAG STATUS AGE
|
|
@@ -102,36 +102,36 @@ login-jwt-expiry-off-by-one login timezone test-generated 3d
|
|
|
102
102
|
cart-stock-race-double-deduct cart concurrency open 1d
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
### 4. `import` — git log
|
|
105
|
+
### 4. `import` — backfill from git log
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
**Steps**:
|
|
108
108
|
1. `git log --grep='^fix:' --format='%H|%s|%ci' --since=<last-import-date>`
|
|
109
|
-
- `last-import-date
|
|
110
|
-
2.
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
3.
|
|
115
|
-
4.
|
|
109
|
+
- `last-import-date` lives in `.claude/vibe/regressions/.import-cursor` (defaults to 90 days ago)
|
|
110
|
+
2. For each commit:
|
|
111
|
+
- If a bug file with the same `fix-commit` already exists → **skip**
|
|
112
|
+
- Otherwise infer symptom + root-cause-tag from message/diff (LLM call)
|
|
113
|
+
- Write a new bug file (status: `resolved` — already fixed)
|
|
114
|
+
3. Update `.import-cursor`
|
|
115
|
+
4. Suggest `generate` for newly imported entries
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
**Note**: only `fix:` commits are considered. Projects not using Conventional Commits can override with `--grep-pattern`.
|
|
118
118
|
|
|
119
|
-
### 5. `cluster` —
|
|
119
|
+
### 5. `cluster` — promote recurring patterns
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
1.
|
|
123
|
-
2.
|
|
124
|
-
3.
|
|
125
|
-
- 3
|
|
126
|
-
- `_cluster-<tag>.md`
|
|
127
|
-
-
|
|
128
|
-
4.
|
|
121
|
+
**Steps**:
|
|
122
|
+
1. Aggregate `root-cause-tag` across all bug files
|
|
123
|
+
2. **A tag with ≥3 entries** becomes a cluster candidate
|
|
124
|
+
3. For each candidate:
|
|
125
|
+
- Feed the 3 reproductions to an LLM to extract the common cause and shared test cases
|
|
126
|
+
- Write `_cluster-<tag>.md` (links to the original bug slugs)
|
|
127
|
+
- Propose a shared test skeleton at `<project-test-dir>/_cluster-<tag>.regression.test.ts` (create only with user approval)
|
|
128
|
+
4. Original bug files are **not deleted** — history preserved
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
**Important**: `cluster` is never automatic. Users invoke it explicitly to avoid premature abstraction.
|
|
131
131
|
|
|
132
132
|
## Integration with /vibe.verify
|
|
133
133
|
|
|
134
|
-
`/vibe.verify`
|
|
134
|
+
When `/vibe.verify` fails it calls:
|
|
135
135
|
|
|
136
136
|
```
|
|
137
137
|
Load skill `vibe-regress` with: register --from-verify
|
|
@@ -141,34 +141,34 @@ Load skill `vibe-regress` with: register --from-verify
|
|
|
141
141
|
<location>: {file:line}
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
`--from-verify`
|
|
144
|
+
`--from-verify` behavior:
|
|
145
145
|
- symptom = scenario name + error summary
|
|
146
|
-
- feature =
|
|
147
|
-
- root-cause-tag = error pattern
|
|
146
|
+
- feature = forwarded feature name
|
|
147
|
+
- root-cause-tag = inferred from error pattern (default `other` if unclear)
|
|
148
148
|
- status = `open`
|
|
149
|
-
-
|
|
149
|
+
- **Skip user confirmation** — the user is already attentive in a verify-failure context, and friction must be minimized
|
|
150
150
|
|
|
151
151
|
## Integration with /vibe.run
|
|
152
152
|
|
|
153
|
-
`/vibe.run "<feature>"
|
|
153
|
+
At the start of `/vibe.run "<feature>"`:
|
|
154
154
|
|
|
155
|
-
1.
|
|
156
|
-
2.
|
|
155
|
+
1. Filter `.claude/vibe/regressions/*.md` for `feature: <feature-name>` + `status != resolved`
|
|
156
|
+
2. If any open items:
|
|
157
157
|
```
|
|
158
158
|
⚠️ Open regressions for this feature:
|
|
159
159
|
- login-jwt-expiry-off-by-one (timezone, 3d old)
|
|
160
160
|
- login-session-leak (auth, 1w old)
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
Fix these before adding new behavior? [y/N]
|
|
163
163
|
```
|
|
164
|
-
3. `y` → `/vibe.regress generate
|
|
165
|
-
4. `N` →
|
|
164
|
+
3. `y` → chain to `/vibe.regress generate` for items not yet test-generated
|
|
165
|
+
4. `N` → continue (ultrawork mode auto-`N`, records TODO)
|
|
166
166
|
|
|
167
167
|
## Done Criteria
|
|
168
168
|
|
|
169
|
-
- [ ]
|
|
170
|
-
- [ ]
|
|
171
|
-
- [ ] `root-cause-tag
|
|
172
|
-
- [ ] `generate
|
|
173
|
-
- [ ] `import
|
|
174
|
-
- [ ] `cluster
|
|
169
|
+
- [ ] Subcommand-less invocation prints usage
|
|
170
|
+
- [ ] Frontmatter schema strictly enforced (missing fields rejected)
|
|
171
|
+
- [ ] `root-cause-tag` outside the allowed set → warn + force `other`
|
|
172
|
+
- [ ] After `generate`, the test is **actually run** to verify
|
|
173
|
+
- [ ] `import` deduplicates by `fix-commit` hash
|
|
174
|
+
- [ ] `cluster` does nothing under 3 entries (false-positive guard)
|
|
@@ -400,21 +400,21 @@ Read ~/.claude/vibe/languages/typescript-react.md
|
|
|
400
400
|
Before spawning any research agents, check for a prior persisted dataset:
|
|
401
401
|
|
|
402
402
|
```bash
|
|
403
|
-
# Slug = kebab-case of feature/topic, max 50 chars
|
|
403
|
+
# Slug = kebab-case of the feature/topic, max 50 chars
|
|
404
404
|
ls .claude/vibe/research/<slug>/paper.md 2>/dev/null
|
|
405
405
|
```
|
|
406
406
|
|
|
407
407
|
**If `paper.md` exists:**
|
|
408
408
|
1. Read `.claude/vibe/research/<slug>/paper.md`
|
|
409
409
|
2. Read `.claude/vibe/research/<slug>/awesome-list.md` (if present)
|
|
410
|
-
3. Inject the **Findings**, **Recommendation**, and **Security considerations** sections into SPEC Context
|
|
410
|
+
3. Inject the **Findings**, **Recommendation**, and **Security considerations** sections verbatim into SPEC Context, prefixed with `> Source: .claude/vibe/research/<slug>/paper.md (cached {{FILE_MTIME}})`
|
|
411
411
|
4. **Skip step 3** (parallel research) entirely — do not re-run GPT/Gemini/Claude agents
|
|
412
|
-
5.
|
|
412
|
+
5. Print: `✅ Research cache hit: <slug> (saved ~30s of LLM calls)`
|
|
413
413
|
|
|
414
414
|
**Cache invalidation:**
|
|
415
|
-
- User passes `--refresh-research` → delete dir,
|
|
416
|
-
- `paper.md` mtime older than 30 days → warn user, ask to refresh or reuse
|
|
417
|
-
-
|
|
415
|
+
- User passes `--refresh-research` → delete dir, rerun step 3 from scratch
|
|
416
|
+
- `paper.md` mtime older than 30 days → warn the user, ask to refresh or reuse
|
|
417
|
+
- `stack` in `paper.md` frontmatter differs from current stack → auto-refresh
|
|
418
418
|
|
|
419
419
|
**If `paper.md` does NOT exist:**
|
|
420
420
|
Proceed to step 3. After step 3 completes, the synthesizer **must** write the 3 artifacts (see `parallel-research/orchestrator.md` Phase 5) so the next `/vibe.spec` run on this topic hits the cache.
|
|
@@ -565,19 +565,19 @@ Task(subagent_type="ui-layout-architect",
|
|
|
565
565
|
|
|
566
566
|
### 3.9 Persist Research Cache (AFTER research completes, BEFORE SPEC write)
|
|
567
567
|
|
|
568
|
-
> The "no Write during research" rule
|
|
568
|
+
> The "no Write during research" rule from step 3 does **not** apply here — research is done; artifacts are safe to persist.
|
|
569
569
|
|
|
570
|
-
After parallel research + UI/UX intelligence complete
|
|
570
|
+
After parallel research + UI/UX intelligence complete, before writing the SPEC, save the merged research to `.claude/vibe/research/<slug>/`:
|
|
571
571
|
|
|
572
572
|
1. Compute slug: kebab-case of feature name, max 50 chars
|
|
573
573
|
2. Write **three files** using templates from `parallel-research/templates/`:
|
|
574
574
|
- `.claude/vibe/research/<slug>/synthesis.md` — raw merged findings (all agent outputs)
|
|
575
|
-
- `.claude/vibe/research/<slug>/awesome-list.md` — curated links/repos/patterns (
|
|
575
|
+
- `.claude/vibe/research/<slug>/awesome-list.md` — curated links/repos/patterns (every entry needs a one-line "why"; drop entries without one)
|
|
576
576
|
- `.claude/vibe/research/<slug>/paper.md` — structured survey (Abstract → Background → Method → Findings → Recommendation → Security → References)
|
|
577
|
-
3. Include a frontmatter header in `paper.md` with `stack:` field so step 2.9 can detect stack drift
|
|
578
|
-
4. If the directory already exists (user
|
|
577
|
+
3. Include a frontmatter header in `paper.md` with a `stack:` field so step 2.9 can detect stack drift
|
|
578
|
+
4. If the directory already exists (user passed `--refresh-research`), overwrite
|
|
579
579
|
|
|
580
|
-
This makes the next `/vibe.spec` or `/vibe.research` invocation on the same topic hit the cache at step 2.9.
|
|
580
|
+
This makes the next `/vibe.spec` (or future `/vibe.research`) invocation on the same topic hit the cache at step 2.9.
|
|
581
581
|
|
|
582
582
|
### 4. Write SPEC Document (PTCF Structure)
|
|
583
583
|
|