@boshu2/vibe-check 1.7.0 → 1.8.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/.agents/bundles/actionable-coaching-plan-2025-12-02.md +209 -0
- package/.agents/plans/git-forensics-enhancement-2025-12-05.md +493 -0
- package/.claude/skills/typescript-review.md +152 -0
- package/CHANGELOG.md +41 -5
- package/CLAUDE.md +85 -23
- package/Makefile +43 -19
- package/README.md +178 -172
- package/SECURITY.md +5 -1
- package/assets/logo-dark.svg +47 -0
- package/assets/logo.svg +47 -0
- package/claude-progress.json +28 -7
- package/claude-progress.txt +48 -0
- package/dist/analyzers/patterns.d.ts +62 -0
- package/dist/analyzers/patterns.d.ts.map +1 -0
- package/dist/analyzers/patterns.js +103 -0
- package/dist/analyzers/patterns.js.map +1 -0
- package/dist/analyzers/quality.d.ts +58 -0
- package/dist/analyzers/quality.d.ts.map +1 -0
- package/dist/analyzers/quality.js +114 -0
- package/dist/analyzers/quality.js.map +1 -0
- package/dist/analyzers/sessions.d.ts +45 -0
- package/dist/analyzers/sessions.d.ts.map +1 -0
- package/dist/analyzers/sessions.js +123 -0
- package/dist/analyzers/sessions.js.map +1 -0
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +5 -0
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/forensics.d.ts +29 -0
- package/dist/commands/forensics.d.ts.map +1 -0
- package/dist/commands/forensics.js +213 -0
- package/dist/commands/forensics.js.map +1 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +11 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/insights.d.ts +3 -0
- package/dist/commands/insights.d.ts.map +1 -0
- package/dist/commands/insights.js +120 -0
- package/dist/commands/insights.js.map +1 -0
- package/dist/commands/pipeline.d.ts +3 -0
- package/dist/commands/pipeline.d.ts.map +1 -0
- package/dist/commands/pipeline.js +485 -0
- package/dist/commands/pipeline.js.map +1 -0
- package/dist/commands/profile.d.ts +0 -1
- package/dist/commands/profile.d.ts.map +1 -1
- package/dist/commands/profile.js +0 -4
- package/dist/commands/profile.js.map +1 -1
- package/dist/commands/session.d.ts +9 -0
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +95 -0
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/sessions.d.ts +20 -0
- package/dist/commands/sessions.d.ts.map +1 -0
- package/dist/commands/sessions.js +201 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +124 -7
- package/dist/commands/watch.js.map +1 -1
- package/dist/inner-loop/context-amnesia.d.ts +20 -0
- package/dist/inner-loop/context-amnesia.d.ts.map +1 -0
- package/dist/inner-loop/context-amnesia.js +249 -0
- package/dist/inner-loop/context-amnesia.js.map +1 -0
- package/dist/inner-loop/index.d.ts +39 -0
- package/dist/inner-loop/index.d.ts.map +1 -0
- package/dist/inner-loop/index.js +208 -0
- package/dist/inner-loop/index.js.map +1 -0
- package/dist/inner-loop/instruction-drift.d.ts +28 -0
- package/dist/inner-loop/instruction-drift.d.ts.map +1 -0
- package/dist/inner-loop/instruction-drift.js +260 -0
- package/dist/inner-loop/instruction-drift.js.map +1 -0
- package/dist/inner-loop/logging-only.d.ts +30 -0
- package/dist/inner-loop/logging-only.d.ts.map +1 -0
- package/dist/inner-loop/logging-only.js +264 -0
- package/dist/inner-loop/logging-only.js.map +1 -0
- package/dist/inner-loop/tests-passing-lie.d.ts +34 -0
- package/dist/inner-loop/tests-passing-lie.d.ts.map +1 -0
- package/dist/inner-loop/tests-passing-lie.js +213 -0
- package/dist/inner-loop/tests-passing-lie.js.map +1 -0
- package/dist/inner-loop/types.d.ts +111 -0
- package/dist/inner-loop/types.d.ts.map +1 -0
- package/dist/inner-loop/types.js +29 -0
- package/dist/inner-loop/types.js.map +1 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +11 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/spiral-history.d.ts +62 -0
- package/dist/storage/spiral-history.d.ts.map +1 -0
- package/dist/storage/spiral-history.js +265 -0
- package/dist/storage/spiral-history.js.map +1 -0
- package/docs/ARCHITECTURE.md +2 -10
- package/docs/FEATURES.md +340 -0
- package/docs/GAMIFICATION.md +19 -266
- package/docs/VIBE-ECOSYSTEM.md +12 -78
- package/feature-list.json +140 -88
- package/package.json +1 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Actionable Coaching Enhancement Plan
|
|
2
|
+
|
|
3
|
+
**Goal:** Make vibe-check actively coach you to become a better vibe coder, not just display metrics.
|
|
4
|
+
|
|
5
|
+
**Created:** 2025-12-02
|
|
6
|
+
**Status:** Planning
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Problem Statement
|
|
11
|
+
|
|
12
|
+
Current vibe-check:
|
|
13
|
+
- Shows metrics (trust rate, rework ratio, spirals)
|
|
14
|
+
- Detects spirals in real-time (watch mode)
|
|
15
|
+
- Gives **generic** advice ("write a test", "take a break")
|
|
16
|
+
|
|
17
|
+
What's missing:
|
|
18
|
+
- **No memory** of what worked for YOU before
|
|
19
|
+
- **No personalization** based on YOUR patterns
|
|
20
|
+
- **No actionable next step** - just information
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Design Principles
|
|
25
|
+
|
|
26
|
+
1. **Lean** - ~200 lines, not 1700 (like the cut learning system)
|
|
27
|
+
2. **Actionable** - Tell user what to DO, not just what happened
|
|
28
|
+
3. **Personalized** - Based on YOUR history, not generic
|
|
29
|
+
4. **At decision time** - Surface advice when it matters (spiral detected, session end)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Architecture
|
|
34
|
+
|
|
35
|
+
### Data Model (append-only log)
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// ~/.vibe-check/spiral-history.ndjson
|
|
39
|
+
interface SpiralRecord {
|
|
40
|
+
date: string; // ISO date
|
|
41
|
+
pattern: string; // SECRETS_AUTH, VOLUME_CONFIG, etc.
|
|
42
|
+
component: string; // auth, database, api
|
|
43
|
+
duration: number; // minutes in spiral
|
|
44
|
+
resolution?: string; // What broke the spiral: TEST, BREAK, DOCS, HELP, ROLLBACK
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Why NDJSON:** Append-only, git-friendly diffs, easy to query last N records.
|
|
49
|
+
|
|
50
|
+
### Storage Location
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
~/.vibe-check/
|
|
54
|
+
├── profile.json # Existing - XP, streaks
|
|
55
|
+
└── spiral-history.ndjson # New - spiral log with resolutions
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Core Functions
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// Record a spiral (called from analyze/session end)
|
|
62
|
+
appendSpiral(pattern, component, duration): void
|
|
63
|
+
|
|
64
|
+
// Record what broke the spiral (user input or inferred)
|
|
65
|
+
resolveSpiral(resolution): void
|
|
66
|
+
|
|
67
|
+
// Get personalized advice for a pattern
|
|
68
|
+
getAdvice(pattern, component): {
|
|
69
|
+
yourHistory: { times: number, avgDuration: number },
|
|
70
|
+
whatWorked: { resolution: string, times: number }[],
|
|
71
|
+
suggestion: string
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Features
|
|
78
|
+
|
|
79
|
+
### Feature 1: Spiral History Tracking
|
|
80
|
+
|
|
81
|
+
**Automatic tracking** when spirals are detected:
|
|
82
|
+
- Pattern (SECRETS_AUTH, etc.)
|
|
83
|
+
- Component (auth, api, etc.)
|
|
84
|
+
- Duration (minutes)
|
|
85
|
+
- Timestamp
|
|
86
|
+
|
|
87
|
+
No user action required - happens during `analyze` and `session end`.
|
|
88
|
+
|
|
89
|
+
### Feature 2: Resolution Recording
|
|
90
|
+
|
|
91
|
+
After spiral detected, prompt for what broke it:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Spiral resolved. What worked?
|
|
95
|
+
[T] Wrote a test
|
|
96
|
+
[B] Took a break
|
|
97
|
+
[D] Read docs
|
|
98
|
+
[H] Asked for help
|
|
99
|
+
[R] Rolled back
|
|
100
|
+
[Enter] Skip
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Or infer from commit patterns:
|
|
104
|
+
- Test commit after fix commits → TEST
|
|
105
|
+
- >15 min gap → BREAK
|
|
106
|
+
- Revert commit → ROLLBACK
|
|
107
|
+
|
|
108
|
+
### Feature 3: Personalized Watch Alerts
|
|
109
|
+
|
|
110
|
+
When spiral detected in watch mode:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
⚠️ SPIRAL FORMING - auth component (SECRETS_AUTH pattern)
|
|
114
|
+
|
|
115
|
+
Your history: 4 auth spirals, avg 18 min
|
|
116
|
+
What worked: tracer test (3x), break (1x)
|
|
117
|
+
|
|
118
|
+
→ Write a test that validates your auth assumption
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Feature 4: Session End Coaching
|
|
122
|
+
|
|
123
|
+
At `vibe-check session end`:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
SESSION COMPLETE
|
|
127
|
+
|
|
128
|
+
Rating: HIGH (not ELITE because of 1 spiral)
|
|
129
|
+
|
|
130
|
+
🔄 You hit SECRETS_AUTH again (5th time)
|
|
131
|
+
Your go-to fix: tracer test
|
|
132
|
+
Consider: Add auth integration test to prevent recurrence
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Feature 5: Pattern Insights Command
|
|
136
|
+
|
|
137
|
+
New command or flag: `vibe-check insights`
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
YOUR SPIRAL PATTERNS (last 30 days)
|
|
141
|
+
|
|
142
|
+
Pattern Times Avg Duration Best Fix
|
|
143
|
+
SECRETS_AUTH 5 18 min tracer test
|
|
144
|
+
VOLUME_CONFIG 3 12 min docs
|
|
145
|
+
API_MISMATCH 2 25 min help
|
|
146
|
+
|
|
147
|
+
Top trigger: OAuth/token issues in auth component
|
|
148
|
+
|
|
149
|
+
Recommendation: Add tracer tests for auth flows before starting
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Implementation Order
|
|
155
|
+
|
|
156
|
+
| # | Feature | Effort | Files |
|
|
157
|
+
|---|---------|--------|-------|
|
|
158
|
+
| 1 | Spiral history storage | 1 hr | `src/storage/spiral-history.ts` |
|
|
159
|
+
| 2 | Auto-record spirals | 30 min | `src/commands/analyze.ts`, `session.ts` |
|
|
160
|
+
| 3 | Enhanced watch alerts | 1 hr | `src/commands/watch.ts` |
|
|
161
|
+
| 4 | Session end coaching | 1 hr | `src/commands/session.ts` |
|
|
162
|
+
| 5 | Insights command | 1 hr | `src/commands/insights.ts` |
|
|
163
|
+
|
|
164
|
+
**Total:** ~5 hours, ~300-400 lines of new code
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Success Criteria
|
|
169
|
+
|
|
170
|
+
1. After 5+ spirals, advice is personalized to user's history
|
|
171
|
+
2. Watch mode shows "what worked before" when spiral detected
|
|
172
|
+
3. Session end gives actionable coaching, not just metrics
|
|
173
|
+
4. User can see their patterns with `vibe-check insights`
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## What This Is NOT
|
|
178
|
+
|
|
179
|
+
- Not the bloated learning system (10 files, 1755 lines)
|
|
180
|
+
- Not ML/AI predictions
|
|
181
|
+
- Not nudges/cadences/synthesis
|
|
182
|
+
- Just: **record what happened, show what worked**
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Files to Create/Modify
|
|
187
|
+
|
|
188
|
+
### New Files
|
|
189
|
+
- `src/storage/spiral-history.ts` - NDJSON append/query
|
|
190
|
+
- `src/commands/insights.ts` - Pattern insights command
|
|
191
|
+
|
|
192
|
+
### Modified Files
|
|
193
|
+
- `src/commands/watch.ts` - Personalized alerts
|
|
194
|
+
- `src/commands/session.ts` - Session end coaching
|
|
195
|
+
- `src/commands/analyze.ts` - Record spirals to history
|
|
196
|
+
- `src/cli.ts` - Register insights command
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Open Questions
|
|
201
|
+
|
|
202
|
+
1. **Resolution input:** Interactive prompt vs infer from commits?
|
|
203
|
+
- Recommendation: Infer first, prompt as fallback
|
|
204
|
+
|
|
205
|
+
2. **History retention:** How many records to keep?
|
|
206
|
+
- Recommendation: Last 100 spirals (~3-6 months typical usage)
|
|
207
|
+
|
|
208
|
+
3. **Pattern display names:** Use technical (SECRETS_AUTH) or friendly (OAuth/Token Issues)?
|
|
209
|
+
- Recommendation: Friendly in output, technical internally
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
# vibe-check Enhancement Proposal
|
|
2
|
+
|
|
3
|
+
**Package:** @boshu2/vibe-check v1.7.0
|
|
4
|
+
**Purpose:** Add git forensics capabilities proven in release-engineering retrospective
|
|
5
|
+
**Date:** December 5, 2025
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Three proven algorithms from the release-engineering retrospective (475 commits, 60 days) should be integrated into vibe-check as new features:
|
|
12
|
+
|
|
13
|
+
1. **Git Forensics** - Repository analysis with pattern detection
|
|
14
|
+
2. **Session Detection** - Work session identification (90-min threshold)
|
|
15
|
+
3. **Era Evolution** - Track transformation phases over time
|
|
16
|
+
|
|
17
|
+
**Impact:** Transform vibe-check from real-time monitor → comprehensive retrospective tool
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Enhancement #1: Git Forensics Mode
|
|
22
|
+
|
|
23
|
+
### Command
|
|
24
|
+
```bash
|
|
25
|
+
npx @boshu2/vibe-check forensics [--since DATE] [--format json|markdown]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### What It Does
|
|
29
|
+
Analyzes git history to detect failure patterns and calculate quality metrics.
|
|
30
|
+
|
|
31
|
+
### Outputs
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"analysis_period": "2025-10-04 to 2025-12-05",
|
|
35
|
+
"total_commits": 475,
|
|
36
|
+
"patterns_detected": {
|
|
37
|
+
"debug_spirals": {
|
|
38
|
+
"count": 14,
|
|
39
|
+
"duration_minutes": 58.7,
|
|
40
|
+
"dates": ["2025-10-04"],
|
|
41
|
+
"commits": ["7b07068", "bb685a2", ...]
|
|
42
|
+
},
|
|
43
|
+
"vague_commits": {
|
|
44
|
+
"count": 282,
|
|
45
|
+
"percentage": 59.4,
|
|
46
|
+
"threshold": 20,
|
|
47
|
+
"examples": ["ci", "v3", "blah", "take 2"]
|
|
48
|
+
},
|
|
49
|
+
"context_amnesia": {
|
|
50
|
+
"scopes": [
|
|
51
|
+
{"name": "ci", "visits": 10},
|
|
52
|
+
{"name": "automation", "visits": 9},
|
|
53
|
+
{"name": "pipelines", "visits": 8}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"quality_metrics": {
|
|
58
|
+
"conventional_commits": 28.6,
|
|
59
|
+
"descriptive_quality": 30.7,
|
|
60
|
+
"vague_quality": 59.4
|
|
61
|
+
},
|
|
62
|
+
"recommendation": "sweep",
|
|
63
|
+
"sweep_targets": ["lib/common.sh", "harmonize.sh", "scaffold.sh"]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Implementation Algorithm
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
# Pseudocode from release-engineering analysis
|
|
71
|
+
def git_forensics(since_date):
|
|
72
|
+
# Extract commits
|
|
73
|
+
commits = git_log(format="%H|%h|%an|%ae|%ai|%at|%s", since=since_date)
|
|
74
|
+
|
|
75
|
+
# Parse each commit
|
|
76
|
+
parsed = []
|
|
77
|
+
for commit in commits:
|
|
78
|
+
hash, short, author, email, date_iso, timestamp, subject = commit.split('|')
|
|
79
|
+
|
|
80
|
+
# Detect patterns
|
|
81
|
+
is_take = re.match(r'^take [0-9]+$', subject)
|
|
82
|
+
is_vague = len(subject) < 20
|
|
83
|
+
is_conventional = re.match(r'^(feat|fix|docs|test|refactor|chore)', subject)
|
|
84
|
+
|
|
85
|
+
parsed.append({
|
|
86
|
+
'hash': short,
|
|
87
|
+
'subject': subject,
|
|
88
|
+
'is_take': is_take,
|
|
89
|
+
'is_vague': is_vague,
|
|
90
|
+
'is_conventional': is_conventional,
|
|
91
|
+
'timestamp': int(timestamp)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
# Detect debug spirals
|
|
95
|
+
take_commits = [c for c in parsed if c['is_take']]
|
|
96
|
+
if len(take_commits) >= 3:
|
|
97
|
+
first = min(take_commits, key=lambda c: c['timestamp'])
|
|
98
|
+
last = max(take_commits, key=lambda c: c['timestamp'])
|
|
99
|
+
duration_min = (last['timestamp'] - first['timestamp']) / 60
|
|
100
|
+
|
|
101
|
+
patterns['debug_spirals'] = {
|
|
102
|
+
'count': len(take_commits),
|
|
103
|
+
'duration_minutes': duration_min
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
# Calculate quality metrics
|
|
107
|
+
total = len(parsed)
|
|
108
|
+
vague_count = len([c for c in parsed if c['is_vague']])
|
|
109
|
+
conventional_count = len([c for c in parsed if c['is_conventional']])
|
|
110
|
+
|
|
111
|
+
quality_metrics = {
|
|
112
|
+
'conventional_commits': 100 * conventional_count / total,
|
|
113
|
+
'vague_quality': 100 * vague_count / total
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# Recommendation
|
|
117
|
+
if vague_count > total * 0.5 or len(take_commits) > 0:
|
|
118
|
+
recommendation = 'sweep'
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
'patterns_detected': patterns,
|
|
122
|
+
'quality_metrics': quality_metrics,
|
|
123
|
+
'recommendation': recommendation
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Files to Create
|
|
128
|
+
- `src/commands/forensics.js` - Main command
|
|
129
|
+
- `src/analyzers/patterns.js` - Pattern detection
|
|
130
|
+
- `src/analyzers/quality.js` - Quality metrics
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Enhancement #2: Session Detection
|
|
135
|
+
|
|
136
|
+
### Command
|
|
137
|
+
```bash
|
|
138
|
+
npx @boshu2/vibe-check sessions [--threshold MINUTES] [--format json]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### What It Does
|
|
142
|
+
Identifies work sessions from git history using configurable time gap threshold.
|
|
143
|
+
|
|
144
|
+
### Output
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"total_sessions": 46,
|
|
148
|
+
"total_commits": 475,
|
|
149
|
+
"avg_commits_per_session": 10.3,
|
|
150
|
+
"avg_duration_minutes": 79.4,
|
|
151
|
+
"median_duration_minutes": 33.1,
|
|
152
|
+
"longest_session_minutes": 413.2,
|
|
153
|
+
"sessions": [
|
|
154
|
+
{
|
|
155
|
+
"session_id": 1,
|
|
156
|
+
"start_date": "2025-10-04 11:59:47",
|
|
157
|
+
"end_date": "2025-10-04 16:53:29",
|
|
158
|
+
"duration_minutes": 293.7,
|
|
159
|
+
"num_commits": 50,
|
|
160
|
+
"commits": ["c83fea9", "de59b1c", ...]
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Implementation Algorithm
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
# Proven algorithm from release-engineering
|
|
170
|
+
def detect_sessions(commits, gap_threshold=90):
|
|
171
|
+
"""
|
|
172
|
+
Detect work sessions using time gap between commits.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
commits: List of commits sorted by timestamp
|
|
176
|
+
gap_threshold: Minutes between commits to start new session (default: 90)
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
List of sessions with metadata
|
|
180
|
+
"""
|
|
181
|
+
SESSION_GAP = gap_threshold * 60 # Convert to seconds
|
|
182
|
+
sessions = []
|
|
183
|
+
current_session = []
|
|
184
|
+
|
|
185
|
+
for commit in sorted(commits, key=lambda c: c['timestamp']):
|
|
186
|
+
if not current_session:
|
|
187
|
+
current_session = [commit]
|
|
188
|
+
elif commit['timestamp'] - current_session[-1]['timestamp'] > SESSION_GAP:
|
|
189
|
+
# Gap exceeded, save current session and start new
|
|
190
|
+
sessions.append({
|
|
191
|
+
'start': current_session[0],
|
|
192
|
+
'end': current_session[-1],
|
|
193
|
+
'commits': current_session,
|
|
194
|
+
'duration_min': (current_session[-1]['timestamp'] - current_session[0]['timestamp']) / 60
|
|
195
|
+
})
|
|
196
|
+
current_session = [commit]
|
|
197
|
+
else:
|
|
198
|
+
current_session.append(commit)
|
|
199
|
+
|
|
200
|
+
# Don't forget last session
|
|
201
|
+
if current_session:
|
|
202
|
+
sessions.append({
|
|
203
|
+
'start': current_session[0],
|
|
204
|
+
'end': current_session[-1],
|
|
205
|
+
'commits': current_session,
|
|
206
|
+
'duration_min': (current_session[-1]['timestamp'] - current_session[0]['timestamp']) / 60
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
return sessions
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Use Cases
|
|
213
|
+
- Productivity analysis (session duration trends)
|
|
214
|
+
- Work pattern identification (when do you work best?)
|
|
215
|
+
- Break analysis (gap between sessions)
|
|
216
|
+
- Integration with time tracking tools
|
|
217
|
+
|
|
218
|
+
### Files to Create
|
|
219
|
+
- `src/commands/sessions.js` - Main command
|
|
220
|
+
- `src/analyzers/sessions.js` - Session detection algorithm
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Enhancement #3: Era Evolution Tracking
|
|
225
|
+
|
|
226
|
+
### Command
|
|
227
|
+
```bash
|
|
228
|
+
npx @boshu2/vibe-check evolution [--eras CONFIG] [--format json]
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### What It Does
|
|
232
|
+
Classifies commits into user-defined eras and tracks quality evolution over time.
|
|
233
|
+
|
|
234
|
+
### Configuration
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"eras": [
|
|
238
|
+
{
|
|
239
|
+
"name": "genesis",
|
|
240
|
+
"start": "2025-10-04",
|
|
241
|
+
"end": "2025-10-05",
|
|
242
|
+
"description": "Initial chaos"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"name": "transformation",
|
|
246
|
+
"start": "2025-11-18",
|
|
247
|
+
"end": "2025-12-02",
|
|
248
|
+
"description": "Post-sweep discipline"
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Output
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"eras": [
|
|
258
|
+
{
|
|
259
|
+
"name": "genesis",
|
|
260
|
+
"commits": 154,
|
|
261
|
+
"sessions": 6,
|
|
262
|
+
"metrics": {
|
|
263
|
+
"conventional": 0.0,
|
|
264
|
+
"vague": 97.4,
|
|
265
|
+
"velocity": 10.79,
|
|
266
|
+
"rework_ratio": 6.5,
|
|
267
|
+
"debug_spirals": 14
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"name": "transformation",
|
|
272
|
+
"commits": 63,
|
|
273
|
+
"sessions": 10,
|
|
274
|
+
"metrics": {
|
|
275
|
+
"conventional": 85.7,
|
|
276
|
+
"vague": 0.0,
|
|
277
|
+
"velocity": 6.97,
|
|
278
|
+
"rework_ratio": 25.4,
|
|
279
|
+
"debug_spirals": 0
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
],
|
|
283
|
+
"transformation_summary": {
|
|
284
|
+
"conventional": "+85.7%",
|
|
285
|
+
"vague": "-97.4%",
|
|
286
|
+
"debug_spirals": "-14"
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Implementation Algorithm
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
# Era classification from release-engineering
|
|
295
|
+
def classify_eras(commits, era_config):
|
|
296
|
+
"""
|
|
297
|
+
Classify commits into eras and calculate per-era metrics.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
commits: List of parsed commits
|
|
301
|
+
era_config: Era definitions with start/end dates
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Metrics grouped by era
|
|
305
|
+
"""
|
|
306
|
+
commits_by_era = defaultdict(list)
|
|
307
|
+
|
|
308
|
+
for commit in commits:
|
|
309
|
+
commit_date = commit['date_iso'].split()[0]
|
|
310
|
+
|
|
311
|
+
# Find matching era
|
|
312
|
+
for era in era_config:
|
|
313
|
+
if era['start'] <= commit_date <= era['end']:
|
|
314
|
+
commits_by_era[era['name']].append(commit)
|
|
315
|
+
break
|
|
316
|
+
|
|
317
|
+
# Calculate metrics per era
|
|
318
|
+
results = []
|
|
319
|
+
for era_name, era_commits in commits_by_era.items():
|
|
320
|
+
total = len(era_commits)
|
|
321
|
+
|
|
322
|
+
metrics = {
|
|
323
|
+
'conventional': 100 * sum(1 for c in era_commits if c['is_conventional']) / total,
|
|
324
|
+
'vague': 100 * sum(1 for c in era_commits if c['is_vague']) / total,
|
|
325
|
+
'debug_spirals': sum(1 for c in era_commits if c['is_take'])
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
results.append({
|
|
329
|
+
'name': era_name,
|
|
330
|
+
'commits': total,
|
|
331
|
+
'metrics': metrics
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
return results
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Use Cases
|
|
338
|
+
- Transformation stories (before/after)
|
|
339
|
+
- Quarterly reviews (Q1, Q2, Q3, Q4)
|
|
340
|
+
- Migration tracking (pre-refactor, during, post)
|
|
341
|
+
- Team onboarding impact (before new dev, after)
|
|
342
|
+
|
|
343
|
+
### Files to Create
|
|
344
|
+
- `src/commands/evolution.js` - Main command
|
|
345
|
+
- `src/analyzers/eras.js` - Era classification
|
|
346
|
+
- `src/config/eras.schema.json` - Era config validation
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Integration Points
|
|
351
|
+
|
|
352
|
+
### Current vibe-check Commands
|
|
353
|
+
```bash
|
|
354
|
+
vibe-check analyze # Real-time metrics for current session
|
|
355
|
+
vibe-check history # Historical trend analysis
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### New Commands (Proposed)
|
|
359
|
+
```bash
|
|
360
|
+
vibe-check forensics # Git history pattern detection
|
|
361
|
+
vibe-check sessions # Work session analysis
|
|
362
|
+
vibe-check evolution # Era-based transformation tracking
|
|
363
|
+
vibe-check sweep-check # Quick check: is sweep needed?
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### sweep-check Integration
|
|
367
|
+
```bash
|
|
368
|
+
npx @boshu2/vibe-check sweep-check
|
|
369
|
+
|
|
370
|
+
# Combines forensics + pattern detection + recommendation
|
|
371
|
+
# Output:
|
|
372
|
+
⚠️ Sweep recommended
|
|
373
|
+
Detected patterns:
|
|
374
|
+
- 12 vague commits (threshold: >5)
|
|
375
|
+
- 2 debug spirals
|
|
376
|
+
- Context amnesia: ci (10 visits), automation (9 visits)
|
|
377
|
+
|
|
378
|
+
Targets for sweep:
|
|
379
|
+
- lib/common.sh (0% test coverage, 8 vague commits)
|
|
380
|
+
- harmonize.sh (no tests, spiral detected)
|
|
381
|
+
|
|
382
|
+
Run: npx @boshu2/vibe-check sweep --target lib/common.sh
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Implementation Priority
|
|
388
|
+
|
|
389
|
+
### Phase 1: Core Forensics (MVP)
|
|
390
|
+
- [ ] Git log parsing
|
|
391
|
+
- [ ] Pattern detection (vague commits, debug spirals)
|
|
392
|
+
- [ ] Basic quality metrics
|
|
393
|
+
- [ ] JSON output
|
|
394
|
+
- **Estimate:** 2-3 days
|
|
395
|
+
|
|
396
|
+
### Phase 2: Sessions & Evolution
|
|
397
|
+
- [ ] Session detection algorithm
|
|
398
|
+
- [ ] Era classification
|
|
399
|
+
- [ ] Comparative metrics
|
|
400
|
+
- [ ] Markdown/Terminal output
|
|
401
|
+
- **Estimate:** 2-3 days
|
|
402
|
+
|
|
403
|
+
### Phase 3: Integration
|
|
404
|
+
- [ ] sweep-check convenience command
|
|
405
|
+
- [ ] Integration with existing analyze command
|
|
406
|
+
- [ ] Historical storage
|
|
407
|
+
- [ ] Dashboard visualization
|
|
408
|
+
- **Estimate:** 2-3 days
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## Testing Strategy
|
|
413
|
+
|
|
414
|
+
### Unit Tests
|
|
415
|
+
```javascript
|
|
416
|
+
describe('forensics', () => {
|
|
417
|
+
it('detects debug spirals from take N pattern', () => {
|
|
418
|
+
const commits = [
|
|
419
|
+
{ subject: 'take 2', timestamp: 1000 },
|
|
420
|
+
{ subject: 'take 3', timestamp: 1300 },
|
|
421
|
+
{ subject: 'take 4', timestamp: 1600 }
|
|
422
|
+
];
|
|
423
|
+
const patterns = detectPatterns(commits);
|
|
424
|
+
expect(patterns.debug_spirals.count).toBe(3);
|
|
425
|
+
expect(patterns.debug_spirals.duration_minutes).toBe(10);
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('detects vague commits', () => {
|
|
429
|
+
const commits = [
|
|
430
|
+
{ subject: 'ci' },
|
|
431
|
+
{ subject: 'v3' },
|
|
432
|
+
{ subject: 'feat: proper commit message' }
|
|
433
|
+
];
|
|
434
|
+
const quality = calculateQuality(commits);
|
|
435
|
+
expect(quality.vague_percentage).toBe(66.7);
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Integration Tests
|
|
441
|
+
- Test against real repositories (release-engineering as reference)
|
|
442
|
+
- Validate against known metrics (475 commits → 46 sessions)
|
|
443
|
+
- Compare with manual analysis
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## Reference Implementation
|
|
448
|
+
|
|
449
|
+
All algorithms proven in:
|
|
450
|
+
- **Repository:** release-engineering (475 commits analyzed)
|
|
451
|
+
- **Files:** `/tmp/full_parse.py`, `/tmp/detect_sessions.py`, `/tmp/calc_vibe_metrics.py`
|
|
452
|
+
- **Story:** `THE-RELEASE-ENGINEERING-STORY.md`
|
|
453
|
+
|
|
454
|
+
**Results:**
|
|
455
|
+
- Successfully detected 14 debug spirals
|
|
456
|
+
- Calculated metrics across 5 eras
|
|
457
|
+
- Identified 46 work sessions
|
|
458
|
+
- Proved transformation: 97.4% vague → 0%
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## Benefits
|
|
463
|
+
|
|
464
|
+
**For Individual Developers:**
|
|
465
|
+
- Understand your coding patterns
|
|
466
|
+
- Identify when you're most productive
|
|
467
|
+
- Catch failure patterns before they compound
|
|
468
|
+
|
|
469
|
+
**For Teams:**
|
|
470
|
+
- Track transformation progress
|
|
471
|
+
- Identify training needs
|
|
472
|
+
- Celebrate improvements with data
|
|
473
|
+
|
|
474
|
+
**For Organizations:**
|
|
475
|
+
- Prove ROI of process improvements
|
|
476
|
+
- Benchmark across projects
|
|
477
|
+
- Make data-driven decisions
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## Next Steps
|
|
482
|
+
|
|
483
|
+
1. **Validate approach** with vibe-check maintainers
|
|
484
|
+
2. **Create GitHub issue** with this proposal
|
|
485
|
+
3. **Implement Phase 1** (forensics MVP)
|
|
486
|
+
4. **Get community feedback** on UX
|
|
487
|
+
5. **Iterate** based on real-world usage
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
**Contact:** Boden Fuller (boden.fuller@gdit.com)
|
|
492
|
+
**Reference:** release-engineering retrospective (Dec 5, 2025)
|
|
493
|
+
**Tags:** `#vibe-check` `#git-forensics` `#enhancement-proposal`
|