@boshu2/vibe-check 2.2.0 → 2.3.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/.agents/plans/2025-12-28-ai-safety-integration-plan.md +326 -0
- package/.agents/research/2025-12-28-ai-platform-security-integration.md +295 -0
- package/.beads/README.md +81 -0
- package/.beads/config.yaml +62 -0
- package/.beads/interactions.jsonl +0 -0
- package/.beads/issues.jsonl +9 -0
- package/.beads/metadata.json +4 -0
- package/.gitattributes +3 -0
- package/AGENTS.md +40 -0
- package/CHANGELOG.md +43 -1
- package/CLAUDE.md +75 -0
- package/README.md +46 -1
- package/dist/ai-safety/contract-drift.d.ts +14 -0
- package/dist/ai-safety/contract-drift.d.ts.map +1 -0
- package/dist/ai-safety/contract-drift.js +230 -0
- package/dist/ai-safety/contract-drift.js.map +1 -0
- package/dist/ai-safety/index.d.ts +43 -0
- package/dist/ai-safety/index.d.ts.map +1 -0
- package/dist/ai-safety/index.js +177 -0
- package/dist/ai-safety/index.js.map +1 -0
- package/dist/ai-safety/scope-violation.d.ts +18 -0
- package/dist/ai-safety/scope-violation.d.ts.map +1 -0
- package/dist/ai-safety/scope-violation.js +150 -0
- package/dist/ai-safety/scope-violation.js.map +1 -0
- package/dist/ai-safety/secret-leakage.d.ts +18 -0
- package/dist/ai-safety/secret-leakage.d.ts.map +1 -0
- package/dist/ai-safety/secret-leakage.js +188 -0
- package/dist/ai-safety/secret-leakage.js.map +1 -0
- package/dist/ai-safety/token-spiral.d.ts +17 -0
- package/dist/ai-safety/token-spiral.d.ts.map +1 -0
- package/dist/ai-safety/token-spiral.js +183 -0
- package/dist/ai-safety/token-spiral.js.map +1 -0
- package/dist/ai-safety/types.d.ts +122 -0
- package/dist/ai-safety/types.d.ts.map +1 -0
- package/dist/ai-safety/types.js +32 -0
- package/dist/ai-safety/types.js.map +1 -0
- package/dist/commands/session.d.ts +9 -0
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +42 -0
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +59 -0
- package/dist/commands/watch.js.map +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Beads Configuration File
|
|
2
|
+
# This file configures default behavior for all bd commands in this repository
|
|
3
|
+
# All settings can also be set via environment variables (BD_* prefix)
|
|
4
|
+
# or overridden with command-line flags
|
|
5
|
+
|
|
6
|
+
# Issue prefix for this repository (used by bd init)
|
|
7
|
+
# If not set, bd init will auto-detect from directory name
|
|
8
|
+
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
|
|
9
|
+
# issue-prefix: ""
|
|
10
|
+
|
|
11
|
+
# Use no-db mode: load from JSONL, no SQLite, write back after each command
|
|
12
|
+
# When true, bd will use .beads/issues.jsonl as the source of truth
|
|
13
|
+
# instead of SQLite database
|
|
14
|
+
# no-db: false
|
|
15
|
+
|
|
16
|
+
# Disable daemon for RPC communication (forces direct database access)
|
|
17
|
+
# no-daemon: false
|
|
18
|
+
|
|
19
|
+
# Disable auto-flush of database to JSONL after mutations
|
|
20
|
+
# no-auto-flush: false
|
|
21
|
+
|
|
22
|
+
# Disable auto-import from JSONL when it's newer than database
|
|
23
|
+
# no-auto-import: false
|
|
24
|
+
|
|
25
|
+
# Enable JSON output by default
|
|
26
|
+
# json: false
|
|
27
|
+
|
|
28
|
+
# Default actor for audit trails (overridden by BD_ACTOR or --actor)
|
|
29
|
+
# actor: ""
|
|
30
|
+
|
|
31
|
+
# Path to database (overridden by BEADS_DB or --db)
|
|
32
|
+
# db: ""
|
|
33
|
+
|
|
34
|
+
# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON)
|
|
35
|
+
# auto-start-daemon: true
|
|
36
|
+
|
|
37
|
+
# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE)
|
|
38
|
+
# flush-debounce: "5s"
|
|
39
|
+
|
|
40
|
+
# Git branch for beads commits (bd sync will commit to this branch)
|
|
41
|
+
# IMPORTANT: Set this for team projects so all clones use the same sync branch.
|
|
42
|
+
# This setting persists across clones (unlike database config which is gitignored).
|
|
43
|
+
# Can also use BEADS_SYNC_BRANCH env var for local override.
|
|
44
|
+
# If not set, bd sync will require you to run 'bd config set sync.branch <branch>'.
|
|
45
|
+
# sync-branch: "beads-sync"
|
|
46
|
+
|
|
47
|
+
# Multi-repo configuration (experimental - bd-307)
|
|
48
|
+
# Allows hydrating from multiple repositories and routing writes to the correct JSONL
|
|
49
|
+
# repos:
|
|
50
|
+
# primary: "." # Primary repo (where this database lives)
|
|
51
|
+
# additional: # Additional repos to hydrate from (read-only)
|
|
52
|
+
# - ~/beads-planning # Personal planning repo
|
|
53
|
+
# - ~/work-planning # Work planning repo
|
|
54
|
+
|
|
55
|
+
# Integration settings (access with 'bd config get/set')
|
|
56
|
+
# These are stored in the database, not in this file:
|
|
57
|
+
# - jira.url
|
|
58
|
+
# - jira.project
|
|
59
|
+
# - linear.url
|
|
60
|
+
# - linear.api-key
|
|
61
|
+
# - github.org
|
|
62
|
+
# - github.repo
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{"id":"vibe-check-263","title":"Session end AI safety integration","description":"Integrate AI safety analysis into session end command. Add ai_safety section to JSON output. Show warnings in terminal output with recommendations.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-28T12:07:22.458246-05:00","created_by":"fullerbt","updated_at":"2025-12-28T12:32:10.15324-05:00","closed_at":"2025-12-28T12:32:10.15324-05:00","close_reason":"Completed: AI safety integrated into session end. JSON output includes ai_safety section. Terminal shows warnings and recommendations. Follows inner-loop pattern.","dependencies":[{"issue_id":"vibe-check-263","depends_on_id":"vibe-check-swh","type":"blocks","created_at":"2025-12-28T12:07:42.272223-05:00","created_by":"daemon"}],"comments":[{"id":6,"issue_id":"vibe-check-263","author":"fullerbt","text":"✅ Implementation complete:\n\nUpdated src/commands/session.ts:\n- Imported analyzeAISafety and formatAISafetyAnalysis from ai-safety module\n- Added ai_safety field to SessionMetricsOutput interface\n- Integrated AI safety analysis in runSessionEnd() (parallel with inner-loop)\n- Added ai_safety section to JSON output with:\n - health: 'healthy' | 'warning' | 'critical'\n - issues_detected, secrets_leaked, scope_violations counts\n - contract_drift_detected, token_spiral_detected booleans\n - recommendations array\n- Added terminal output showing:\n - Health status with emoji (🚨/⚠️/✅)\n - Individual detector messages (🔐/🎯/📉/💥)\n - Top 3 recommendations\n- Follows exact same pattern as inner-loop integration\n\nTesting:\n- Build passes ✅\n- Session start/end commands work ✅\n- JSON output structure confirmed (no commits = expected behavior)","created_at":"2025-12-28T17:32:04Z"}]}
|
|
2
|
+
{"id":"vibe-check-56v","title":"Contract drift detector","description":"Track commit message format compliance over time. Detect degradation from conventional commits. Report drift percentage and trend. Warning at \u003e30% drift.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-28T12:07:24.054553-05:00","created_by":"fullerbt","updated_at":"2025-12-28T13:21:58.451526-05:00","closed_at":"2025-12-28T13:21:58.451526-05:00","close_reason":"Contract drift detector with compliance scoring and trend detection","dependencies":[{"issue_id":"vibe-check-56v","depends_on_id":"vibe-check-ash","type":"blocks","created_at":"2025-12-28T12:07:42.336535-05:00","created_by":"daemon"}]}
|
|
3
|
+
{"id":"vibe-check-5s1","title":"Scope violation detector","description":"Detect commits touching files outside declared scope. Support scope config via .vibe-check/scope.yaml. Use glob patterns. Warning severity.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-28T12:07:23.888845-05:00","created_by":"fullerbt","updated_at":"2025-12-28T13:15:03.887086-05:00","closed_at":"2025-12-28T13:15:03.887086-05:00","close_reason":"Scope violation detector with YAML config and glob matching","dependencies":[{"issue_id":"vibe-check-5s1","depends_on_id":"vibe-check-ash","type":"blocks","created_at":"2025-12-28T12:07:42.3013-05:00","created_by":"daemon"}]}
|
|
4
|
+
{"id":"vibe-check-ash","title":"AI Safety types and orchestrator","description":"Create src/ai-safety/types.ts and src/ai-safety/index.ts. Define AISafetyAnalysis interface matching inner-loop pattern. Foundation for all other detectors.","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-12-28T12:07:20.710124-05:00","created_by":"fullerbt","updated_at":"2025-12-28T12:12:30.564652-05:00","closed_at":"2025-12-28T12:12:30.564652-05:00","close_reason":"Completed: AI Safety types and orchestrator foundation. Created types.ts with all interfaces and index.ts with orchestrator following inner-loop pattern. Build passes.","dependencies":[{"issue_id":"vibe-check-ash","depends_on_id":"vibe-check-lqb","type":"blocks","created_at":"2025-12-28T12:07:42.213339-05:00","created_by":"daemon"}],"comments":[{"id":2,"issue_id":"vibe-check-ash","author":"fullerbt","text":"Files to create:\n- src/ai-safety/types.ts\n- src/ai-safety/index.ts\n\nPattern: Follow src/inner-loop/ structure exactly","created_at":"2025-12-28T17:07:57Z"},{"id":4,"issue_id":"vibe-check-ash","author":"fullerbt","text":"✅ Implementation complete:\n\nCreated src/ai-safety/types.ts:\n- AISafetyAnalysis interface (matches inner-loop pattern)\n- 4 detector result types: SecretLeakageResult, ScopeViolationResult, ContractDriftResult, TokenSpiralResult\n- Config types with DEFAULT_AI_SAFETY_CONFIG\n- SECRET_PATTERNS constants for 8 secret types\n\nCreated src/ai-safety/index.ts:\n- analyzeAISafety() orchestrator function\n- generateRecommendations() helper\n- quickAISafetyCheck() fast check function\n- formatAISafetyAnalysis() terminal output formatter\n- Stub implementations for all detectors (to be filled by dependent issues)\n\nBuild verified: npm run build passes ✅","created_at":"2025-12-28T17:12:18Z"}]}
|
|
5
|
+
{"id":"vibe-check-gon","title":"Token spiral estimator","description":"Estimate token usage from commit size (~4 chars/token). Track cumulative session tokens. Detect explosion patterns (\u003e2x baseline). Advisory info severity.","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-12-28T12:07:25.111778-05:00","created_by":"fullerbt","updated_at":"2025-12-28T13:27:24.916118-05:00","closed_at":"2025-12-28T13:27:24.916118-05:00","close_reason":"Token spiral estimator with 3 estimation methods and explosion detection","dependencies":[{"issue_id":"vibe-check-gon","depends_on_id":"vibe-check-ash","type":"blocks","created_at":"2025-12-28T12:07:42.370654-05:00","created_by":"daemon"}]}
|
|
6
|
+
{"id":"vibe-check-gy2","title":"Watch command AI safety integration","description":"Add real-time secret detection alerts to watch mode. Red/bold for critical. Show file and pattern matched. Rate-limited alerts.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-28T12:07:26.399789-05:00","created_by":"fullerbt","updated_at":"2025-12-28T13:08:55.854894-05:00","closed_at":"2025-12-28T13:08:55.854894-05:00","close_reason":"Watch mode now detects secrets in real-time with rate-limited alerts","dependencies":[{"issue_id":"vibe-check-gy2","depends_on_id":"vibe-check-swh","type":"blocks","created_at":"2025-12-28T12:07:42.399267-05:00","created_by":"daemon"}]}
|
|
7
|
+
{"id":"vibe-check-lqb","title":"Epic: AI Safety Detection Module","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-28T12:07:01.674933-05:00","created_by":"fullerbt","updated_at":"2025-12-28T12:08:14.746447-05:00","closed_at":"2025-12-28T12:08:14.746447-05:00","close_reason":"Epic container - work tracked in child issues","comments":[{"id":1,"issue_id":"vibe-check-lqb","author":"fullerbt","text":"Research: .agents/research/2025-12-28-ai-platform-security-integration.md\nPlan: .agents/plans/2025-12-28-ai-safety-integration-plan.md\nSource patterns: ai-platform/tests/agents/test_agent_security.py","created_at":"2025-12-28T17:07:56Z"}]}
|
|
8
|
+
{"id":"vibe-check-swh","title":"Secret leakage detector","description":"Detect exposed secrets in commit diffs: OpenAI keys, GitHub PATs, GitLab PATs, AWS keys, Slack tokens. Port patterns from ai-platform test_agent_security.py. Critical severity.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-28T12:07:21.42346-05:00","created_by":"fullerbt","updated_at":"2025-12-28T12:18:57.212488-05:00","closed_at":"2025-12-28T12:18:57.212488-05:00","close_reason":"Completed: Secret leakage detector with 8 pattern types. Detects OpenAI, GitHub, GitLab, AWS, Slack tokens. Masks secrets, extracts file context. Tested and working.","dependencies":[{"issue_id":"vibe-check-swh","depends_on_id":"vibe-check-ash","type":"blocks","created_at":"2025-12-28T12:07:42.242965-05:00","created_by":"daemon"}],"comments":[{"id":3,"issue_id":"vibe-check-swh","author":"fullerbt","text":"Secret patterns to detect:\n- sk-[a-zA-Z0-9]{48} (OpenAI)\n- ghp_[a-zA-Z0-9]{36} (GitHub PAT)\n- glpat-[a-zA-Z0-9]{20} (GitLab PAT)\n- AKIA[0-9A-Z]{16} (AWS)\n- xox[baprs]-* (Slack)\n\nSource: ai-platform/tests/agents/test_agent_security.py:297-306","created_at":"2025-12-28T17:07:58Z"},{"id":5,"issue_id":"vibe-check-swh","author":"fullerbt","text":"✅ Implementation complete:\n\nCreated src/ai-safety/secret-leakage.ts:\n- detectSecretLeakage() - Async version that scans full commit diffs using simple-git\n- detectSecretLeakageFromMessages() - Sync version that scans commit messages only\n- Detects 8 secret patterns: OpenAI, GitHub PAT, GitLab PAT, AWS, Slack, Generic API keys, Secrets, Passwords\n- Masks secrets (shows first 8 chars + ***)\n- Extracts file context from diffs\n- Determines severity (critical vs warning)\n\nUpdated src/ai-safety/index.ts:\n- Imported and wired detectSecretLeakageFromMessages into orchestrator\n- Re-exported detector functions for external use\n- Replaced stub with real implementation\n\nTesting:\n- Build passes ✅\n- Verified with sample commit containing OpenAI key\n- Correctly detected, masked (sk-12345***), and marked as critical\n- Message-based detection working (1 secret found)","created_at":"2025-12-28T17:18:42Z"}]}
|
|
9
|
+
{"id":"vibe-check-vn7","title":"AI Safety tests and documentation","description":"Unit tests for each detector, integration test for orchestrator. Update CLAUDE.md and README.md with AI safety features. Target \u003e80% coverage.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T12:07:26.586099-05:00","created_by":"fullerbt","updated_at":"2025-12-28T13:35:48.191735-05:00","closed_at":"2025-12-28T13:35:48.191735-05:00","close_reason":"31 tests + documentation for AI Safety module","dependencies":[{"issue_id":"vibe-check-vn7","depends_on_id":"vibe-check-gon","type":"blocks","created_at":"2025-12-28T12:07:42.428834-05:00","created_by":"daemon"}]}
|
package/.gitattributes
ADDED
package/AGENTS.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Agent Instructions
|
|
2
|
+
|
|
3
|
+
This project uses **bd** (beads) for issue tracking. Run `bd onboard` to get started.
|
|
4
|
+
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bd ready # Find available work
|
|
9
|
+
bd show <id> # View issue details
|
|
10
|
+
bd update <id> --status in_progress # Claim work
|
|
11
|
+
bd close <id> # Complete work
|
|
12
|
+
bd sync # Sync with git
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Landing the Plane (Session Completion)
|
|
16
|
+
|
|
17
|
+
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
|
|
18
|
+
|
|
19
|
+
**MANDATORY WORKFLOW:**
|
|
20
|
+
|
|
21
|
+
1. **File issues for remaining work** - Create issues for anything that needs follow-up
|
|
22
|
+
2. **Run quality gates** (if code changed) - Tests, linters, builds
|
|
23
|
+
3. **Update issue status** - Close finished work, update in-progress items
|
|
24
|
+
4. **PUSH TO REMOTE** - This is MANDATORY:
|
|
25
|
+
```bash
|
|
26
|
+
git pull --rebase
|
|
27
|
+
bd sync
|
|
28
|
+
git push
|
|
29
|
+
git status # MUST show "up to date with origin"
|
|
30
|
+
```
|
|
31
|
+
5. **Clean up** - Clear stashes, prune remote branches
|
|
32
|
+
6. **Verify** - All changes committed AND pushed
|
|
33
|
+
7. **Hand off** - Provide context for next session
|
|
34
|
+
|
|
35
|
+
**CRITICAL RULES:**
|
|
36
|
+
- Work is NOT complete until `git push` succeeds
|
|
37
|
+
- NEVER stop before pushing - that leaves work stranded locally
|
|
38
|
+
- NEVER say "ready to push when you are" - YOU must push
|
|
39
|
+
- If push fails, resolve and retry until it succeeds
|
|
40
|
+
|
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
## [2.
|
|
10
|
+
## [2.3.0] - 2025-12-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **AI Safety Detection Module** - Detects LLM-specific security antipatterns in commit history
|
|
15
|
+
- **Secret Leakage Detector** - Scans commits for exposed credentials
|
|
16
|
+
- 8 patterns: OpenAI API keys, GitHub PATs, GitLab PATs, AWS keys, Slack tokens, generic secrets
|
|
17
|
+
- Two modes: full diff scanning (async) and message-only scanning (sync)
|
|
18
|
+
- Masks secrets in output (first 8 chars + `***`)
|
|
19
|
+
- Critical severity for high-value secrets (API keys, tokens)
|
|
20
|
+
- **Scope Violation Detector** - Detects files modified outside declared scope
|
|
21
|
+
- Configure via `.vibe-check/scope.yaml` with glob patterns
|
|
22
|
+
- Supports allowed patterns, directories, and exceptions
|
|
23
|
+
- Uses minimatch for flexible pattern matching
|
|
24
|
+
- **Contract Drift Detector** - Tracks commit message format compliance
|
|
25
|
+
- Scores commits against conventional commit format (0-100)
|
|
26
|
+
- Detects issues: missing_type, invalid_type, vague_message, too_short, etc.
|
|
27
|
+
- Calculates baseline vs current compliance with trend detection
|
|
28
|
+
- Configurable drift threshold (default: 30%)
|
|
29
|
+
- **Token Spiral Estimator** - Estimates token usage and detects explosions
|
|
30
|
+
- Three estimation methods: char_count, lines, diff_size
|
|
31
|
+
- Baseline from first 5 commits, explosion at >2x baseline
|
|
32
|
+
- Indicators: large_diff, many_files, massive_additions, bulk_additions
|
|
33
|
+
|
|
34
|
+
- **Watch Mode Integration** - Real-time secret detection with severity-based alerts
|
|
35
|
+
- Rate-limited alerts via commit:pattern:file tracking
|
|
36
|
+
- Red/bold for critical secrets, yellow for warnings
|
|
37
|
+
|
|
38
|
+
- **Session Integration** - AI Safety included in session end metrics
|
|
39
|
+
- New `ai_safety` section in JSON output
|
|
40
|
+
- Terminal output with health status and recommendations
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- `analyzeAISafety()` orchestrator runs all 4 detectors and aggregates results
|
|
45
|
+
- Added `minimatch` and `js-yaml` dependencies for scope configuration
|
|
46
|
+
|
|
47
|
+
### Developer
|
|
48
|
+
|
|
49
|
+
- 31 new unit and integration tests for AI Safety module
|
|
50
|
+
- Updated CLAUDE.md with AI Safety documentation and architecture
|
|
51
|
+
|
|
52
|
+
## [2.2.1] - 2025-12-27
|
|
11
53
|
|
|
12
54
|
### Added
|
|
13
55
|
|
package/CLAUDE.md
CHANGED
|
@@ -169,6 +169,13 @@ src/
|
|
|
169
169
|
│ ├── context-amnesia.ts # Context Amnesia detector
|
|
170
170
|
│ ├── instruction-drift.ts # Instruction Drift detector
|
|
171
171
|
│ └── logging-only.ts # Debug Loop Spiral detector
|
|
172
|
+
├── ai-safety/
|
|
173
|
+
│ ├── index.ts # AI Safety orchestrator
|
|
174
|
+
│ ├── types.ts # AI Safety types and config
|
|
175
|
+
│ ├── secret-leakage.ts # Secret/credential detection
|
|
176
|
+
│ ├── scope-violation.ts # Scope boundary detection
|
|
177
|
+
│ ├── contract-drift.ts # Commit format compliance
|
|
178
|
+
│ └── token-spiral.ts # Token usage estimation
|
|
172
179
|
├── analyzers/
|
|
173
180
|
│ ├── audit.ts # Codebase audit (monoliths, test gaps, TODOs)
|
|
174
181
|
│ ├── eldritch.ts # Eldritch horror detector (oversized functions)
|
|
@@ -337,6 +344,74 @@ EMERGENCY PROTOCOL: Multiple inner loop failures detected.
|
|
|
337
344
|
STOP → git status → backup → start simple
|
|
338
345
|
```
|
|
339
346
|
|
|
347
|
+
## AI Safety Detection
|
|
348
|
+
|
|
349
|
+
vibe-check detects LLM-specific security antipatterns in commit history:
|
|
350
|
+
|
|
351
|
+
| Detector | Detects | Severity |
|
|
352
|
+
|----------|---------|----------|
|
|
353
|
+
| **Secret Leakage** | API keys, tokens, credentials in commits | Critical |
|
|
354
|
+
| **Scope Violation** | Files modified outside declared scope | Warning |
|
|
355
|
+
| **Contract Drift** | Commit message format degrading | Warning |
|
|
356
|
+
| **Token Spiral** | Token usage explosion (>2x baseline) | Advisory |
|
|
357
|
+
|
|
358
|
+
### Secret Patterns Detected
|
|
359
|
+
|
|
360
|
+
- OpenAI API Keys (`sk-...`)
|
|
361
|
+
- GitHub Personal Access Tokens (`ghp_...`)
|
|
362
|
+
- GitLab Personal Access Tokens (`glpat-...`)
|
|
363
|
+
- AWS Access Keys (`AKIA...`)
|
|
364
|
+
- Slack Tokens (`xox...`)
|
|
365
|
+
- Generic API keys and passwords
|
|
366
|
+
|
|
367
|
+
### Scope Configuration
|
|
368
|
+
|
|
369
|
+
Define allowed scope in `.vibe-check/scope.yaml`:
|
|
370
|
+
|
|
371
|
+
```yaml
|
|
372
|
+
scope:
|
|
373
|
+
allowed_patterns:
|
|
374
|
+
- "src/feature/**"
|
|
375
|
+
- "tests/feature/**"
|
|
376
|
+
allowed_dirs:
|
|
377
|
+
- "src/feature"
|
|
378
|
+
description: "Only modify feature module"
|
|
379
|
+
exceptions:
|
|
380
|
+
- "package.json"
|
|
381
|
+
- "*.md"
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Integration Points
|
|
385
|
+
|
|
386
|
+
**Session End Output:**
|
|
387
|
+
```json
|
|
388
|
+
{
|
|
389
|
+
"ai_safety": {
|
|
390
|
+
"health": "healthy",
|
|
391
|
+
"issues_detected": 0,
|
|
392
|
+
"secrets_leaked": 0,
|
|
393
|
+
"scope_violations": 0,
|
|
394
|
+
"contract_drift_detected": false,
|
|
395
|
+
"token_spiral_detected": false,
|
|
396
|
+
"recommendations": []
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Watch Mode:** Real-time secret detection with severity-based alerts.
|
|
402
|
+
|
|
403
|
+
### Architecture
|
|
404
|
+
|
|
405
|
+
```
|
|
406
|
+
src/ai-safety/
|
|
407
|
+
├── index.ts # Orchestrator and exports
|
|
408
|
+
├── types.ts # Types, patterns, config
|
|
409
|
+
├── secret-leakage.ts # Secret/credential detection
|
|
410
|
+
├── scope-violation.ts # Scope boundary enforcement
|
|
411
|
+
├── contract-drift.ts # Commit format compliance
|
|
412
|
+
└── token-spiral.ts # Token usage estimation
|
|
413
|
+
```
|
|
414
|
+
|
|
340
415
|
---
|
|
341
416
|
|
|
342
417
|
# Vibe-Coding Methodology
|
package/README.md
CHANGED
|
@@ -73,12 +73,38 @@ npx @boshu2/vibe-check dashboard
|
|
|
73
73
|
|
|
74
74
|
## What It Measures
|
|
75
75
|
|
|
76
|
+
### Core Metrics
|
|
77
|
+
|
|
76
78
|
| Metric | Question | Target |
|
|
77
79
|
|--------|----------|--------|
|
|
78
80
|
| **Trust Pass Rate** | Does the code stick? | >95% |
|
|
79
81
|
| **Rework Ratio** | Building or debugging? | <30% |
|
|
80
82
|
| **Debug Spirals** | Are you stuck? | 0 active |
|
|
81
83
|
|
|
84
|
+
### Enhanced Metrics (v2.2.0)
|
|
85
|
+
|
|
86
|
+
Three deeper metrics for understanding development habits:
|
|
87
|
+
|
|
88
|
+
| Metric | Question | Target |
|
|
89
|
+
|--------|----------|--------|
|
|
90
|
+
| **Tracer Bullet Ratio** | Are you validating assumptions? | >20% |
|
|
91
|
+
| **Investigation Time** | How much hidden debugging? | 0 min |
|
|
92
|
+
| **Domain Cohesion** | Are changes focused? | >80% |
|
|
93
|
+
|
|
94
|
+
**Tracer Bullets** — Use `tracer:` or `tb:` prefix for validation commits:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
tracer(auth): validate OAuth token refresh
|
|
98
|
+
tb(api): test streaming endpoint response
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
- Tracers **before features** = proactive validation ✅
|
|
102
|
+
- Tracers **before fixes** = reactive debugging ❌ (too late!)
|
|
103
|
+
|
|
104
|
+
**Investigation Gaps** — Detects hidden debugging time (15-120 min gaps followed by fix commits).
|
|
105
|
+
|
|
106
|
+
**Domain Cohesion** — Measures how scattered changes are. Single-domain commits indicate clean vertical slices.
|
|
107
|
+
|
|
82
108
|
---
|
|
83
109
|
|
|
84
110
|
## The 12 Failure Patterns
|
|
@@ -190,12 +216,31 @@ vibe-check insights # Your spiral patterns
|
|
|
190
216
|
### Code Quality
|
|
191
217
|
|
|
192
218
|
```bash
|
|
193
|
-
vibe-check audit # Scan for monoliths, test gaps, TODOs
|
|
219
|
+
vibe-check audit # Scan for monoliths, test gaps, TODOs, eldritch horrors
|
|
194
220
|
vibe-check modularity # Pattern-aware modularity analysis
|
|
195
221
|
vibe-check modularity --verbose # Detailed breakdown with metrics
|
|
196
222
|
vibe-check modularity -f json # JSON output for CI integration
|
|
197
223
|
```
|
|
198
224
|
|
|
225
|
+
#### Audit Command (v2.2.0)
|
|
226
|
+
|
|
227
|
+
The `audit` command now includes **Eldritch Horror Detection**—identifying oversized functions that are symptomatic of AI-generated code gone wrong:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
👹 Eldritch Horrors (oversized functions):
|
|
231
|
+
src/services/auth.ts:45
|
|
232
|
+
handleAuthentication: 523 lines (CRITICAL)
|
|
233
|
+
src/api/routes.ts:120
|
|
234
|
+
processRequest: 287 lines (warning)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
| Severity | Threshold | What It Means |
|
|
238
|
+
|----------|-----------|---------------|
|
|
239
|
+
| Warning | >200 lines | Hard to understand |
|
|
240
|
+
| Critical | >500 lines | Impossible to maintain |
|
|
241
|
+
|
|
242
|
+
Supports: TypeScript, JavaScript, Python, Go
|
|
243
|
+
|
|
199
244
|
### Tools
|
|
200
245
|
|
|
201
246
|
```bash
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract Drift Detector
|
|
3
|
+
*
|
|
4
|
+
* Tracks commit message format compliance over time.
|
|
5
|
+
* Detects degradation from conventional commits format.
|
|
6
|
+
* Reports drift percentage and trend.
|
|
7
|
+
*/
|
|
8
|
+
import { Commit } from '../types.js';
|
|
9
|
+
import { ContractDriftResult, AISafetyConfig } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Detect contract drift in commit messages.
|
|
12
|
+
*/
|
|
13
|
+
export declare function detectContractDrift(commits: Commit[], config?: Partial<AISafetyConfig>): ContractDriftResult;
|
|
14
|
+
//# sourceMappingURL=contract-drift.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-drift.d.ts","sourceRoot":"","sources":["../../src/ai-safety/contract-drift.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EACL,mBAAmB,EAGnB,cAAc,EACf,MAAM,YAAY,CAAC;AA8IpB;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM,GACnC,mBAAmB,CAsHrB"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract Drift Detector
|
|
3
|
+
*
|
|
4
|
+
* Tracks commit message format compliance over time.
|
|
5
|
+
* Detects degradation from conventional commits format.
|
|
6
|
+
* Reports drift percentage and trend.
|
|
7
|
+
*/
|
|
8
|
+
// Valid conventional commit types
|
|
9
|
+
const VALID_TYPES = new Set([
|
|
10
|
+
'feat', 'fix', 'docs', 'style', 'refactor', 'perf',
|
|
11
|
+
'test', 'build', 'ci', 'chore', 'revert', 'tracer', 'tb',
|
|
12
|
+
]);
|
|
13
|
+
// Vague words that indicate low-quality commit messages
|
|
14
|
+
const VAGUE_WORDS = new Set([
|
|
15
|
+
'fix', 'update', 'change', 'modify', 'stuff', 'things',
|
|
16
|
+
'misc', 'wip', 'temp', 'test', 'debug', 'asdf', 'foo',
|
|
17
|
+
]);
|
|
18
|
+
/**
|
|
19
|
+
* Calculate compliance score for a single commit message.
|
|
20
|
+
* Returns 0-100 where 100 is perfect conventional commit format.
|
|
21
|
+
*/
|
|
22
|
+
function scoreCommitCompliance(message) {
|
|
23
|
+
const issues = [];
|
|
24
|
+
let score = 100;
|
|
25
|
+
// Check conventional commit format: type(scope): description
|
|
26
|
+
const conventionalMatch = message.match(/^(\w+)(?:\(([^)]+)\))?:\s*(.+)/);
|
|
27
|
+
if (!conventionalMatch) {
|
|
28
|
+
// No conventional format at all
|
|
29
|
+
if (!message.includes(':')) {
|
|
30
|
+
issues.push('missing_colon');
|
|
31
|
+
score -= 30;
|
|
32
|
+
}
|
|
33
|
+
// Try to detect if there's a type-like prefix
|
|
34
|
+
const words = message.split(/\s+/);
|
|
35
|
+
if (words.length > 0 && !VALID_TYPES.has(words[0].toLowerCase())) {
|
|
36
|
+
issues.push('missing_type');
|
|
37
|
+
score -= 25;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const [, type, , description] = conventionalMatch;
|
|
42
|
+
// Check if type is valid
|
|
43
|
+
if (!VALID_TYPES.has(type.toLowerCase())) {
|
|
44
|
+
issues.push('invalid_type');
|
|
45
|
+
score -= 20;
|
|
46
|
+
}
|
|
47
|
+
// Check description quality
|
|
48
|
+
if (!description || description.trim().length === 0) {
|
|
49
|
+
issues.push('no_description');
|
|
50
|
+
score -= 30;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// Check for vague descriptions
|
|
54
|
+
const descWords = description.toLowerCase().split(/\s+/);
|
|
55
|
+
const vagueCount = descWords.filter(w => VAGUE_WORDS.has(w)).length;
|
|
56
|
+
if (vagueCount > 0 && descWords.length <= 3) {
|
|
57
|
+
issues.push('vague_message');
|
|
58
|
+
score -= 15;
|
|
59
|
+
}
|
|
60
|
+
// Check for too short description
|
|
61
|
+
if (description.length < 10) {
|
|
62
|
+
issues.push('too_short');
|
|
63
|
+
score -= 10;
|
|
64
|
+
}
|
|
65
|
+
// Check for all caps (shouting)
|
|
66
|
+
if (description === description.toUpperCase() && description.length > 5) {
|
|
67
|
+
issues.push('all_caps');
|
|
68
|
+
score -= 10;
|
|
69
|
+
}
|
|
70
|
+
// Check for lowercase start (should be lowercase for conventional commits)
|
|
71
|
+
if (description[0] && description[0] === description[0].toUpperCase() &&
|
|
72
|
+
description[0] !== description[0].toLowerCase()) {
|
|
73
|
+
// Starts with uppercase - minor issue
|
|
74
|
+
issues.push('starts_with_lowercase');
|
|
75
|
+
score -= 5;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Ensure score stays in bounds
|
|
80
|
+
return {
|
|
81
|
+
score: Math.max(0, Math.min(100, score)),
|
|
82
|
+
issues,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Calculate entropy score for commit messages.
|
|
87
|
+
* Higher entropy (0-1) means more random/inconsistent messages.
|
|
88
|
+
*/
|
|
89
|
+
function calculateEntropy(commits) {
|
|
90
|
+
if (commits.length === 0)
|
|
91
|
+
return 0;
|
|
92
|
+
// Count type distribution
|
|
93
|
+
const typeCounts = new Map();
|
|
94
|
+
for (const commit of commits) {
|
|
95
|
+
const count = typeCounts.get(commit.type) || 0;
|
|
96
|
+
typeCounts.set(commit.type, count + 1);
|
|
97
|
+
}
|
|
98
|
+
// Calculate Shannon entropy
|
|
99
|
+
let entropy = 0;
|
|
100
|
+
const total = commits.length;
|
|
101
|
+
for (const count of typeCounts.values()) {
|
|
102
|
+
const p = count / total;
|
|
103
|
+
if (p > 0) {
|
|
104
|
+
entropy -= p * Math.log2(p);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Normalize to 0-1 range (max entropy = log2(n) for n categories)
|
|
108
|
+
const maxEntropy = Math.log2(Math.max(typeCounts.size, 1));
|
|
109
|
+
const normalizedEntropy = maxEntropy > 0 ? entropy / maxEntropy : 0;
|
|
110
|
+
// Invert: we want high entropy for BAD (inconsistent) commits
|
|
111
|
+
// Low variety in types is actually good for contract compliance
|
|
112
|
+
// So we measure "type consistency" inversely
|
|
113
|
+
// Actually, for contract drift, we want to measure message QUALITY entropy
|
|
114
|
+
// A mix of good and bad messages = medium entropy
|
|
115
|
+
// All bad messages = low entropy (consistently bad)
|
|
116
|
+
// All good messages = low entropy (consistently good)
|
|
117
|
+
// For our purposes, we'll measure the "other" type ratio as entropy proxy
|
|
118
|
+
const otherCount = typeCounts.get('other') || 0;
|
|
119
|
+
const otherRatio = otherCount / total;
|
|
120
|
+
return otherRatio; // 0 = all conventional, 1 = all non-conventional
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Detect contract drift in commit messages.
|
|
124
|
+
*/
|
|
125
|
+
export function detectContractDrift(commits, config = {}) {
|
|
126
|
+
// Check if contract checking is enabled
|
|
127
|
+
if (config.contractCheckEnabled === false) {
|
|
128
|
+
return {
|
|
129
|
+
detected: false,
|
|
130
|
+
driftMetrics: {
|
|
131
|
+
baselineCompliance: 0,
|
|
132
|
+
currentCompliance: 0,
|
|
133
|
+
driftPercentage: 0,
|
|
134
|
+
trend: 'stable',
|
|
135
|
+
entropyScore: 0,
|
|
136
|
+
},
|
|
137
|
+
degradingCommits: [],
|
|
138
|
+
totalDegradingCommits: 0,
|
|
139
|
+
message: 'Contract checking disabled',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (commits.length === 0) {
|
|
143
|
+
return {
|
|
144
|
+
detected: false,
|
|
145
|
+
driftMetrics: {
|
|
146
|
+
baselineCompliance: 100,
|
|
147
|
+
currentCompliance: 100,
|
|
148
|
+
driftPercentage: 0,
|
|
149
|
+
trend: 'stable',
|
|
150
|
+
entropyScore: 0,
|
|
151
|
+
},
|
|
152
|
+
degradingCommits: [],
|
|
153
|
+
totalDegradingCommits: 0,
|
|
154
|
+
message: 'No commits to analyze',
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const driftThreshold = config.driftThreshold ?? 30;
|
|
158
|
+
// Sort commits by date (oldest first)
|
|
159
|
+
const sortedCommits = [...commits].sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
160
|
+
// Calculate compliance for all commits
|
|
161
|
+
const complianceData = sortedCommits.map(commit => ({
|
|
162
|
+
commit,
|
|
163
|
+
...scoreCommitCompliance(commit.message),
|
|
164
|
+
}));
|
|
165
|
+
// Determine baseline window (first 20% or at least 3 commits)
|
|
166
|
+
const baselineSize = Math.max(3, Math.floor(commits.length * 0.2));
|
|
167
|
+
const currentSize = Math.max(3, Math.floor(commits.length * 0.2));
|
|
168
|
+
const baselineCommits = complianceData.slice(0, baselineSize);
|
|
169
|
+
const currentCommits = complianceData.slice(-currentSize);
|
|
170
|
+
// Calculate average compliance
|
|
171
|
+
const baselineCompliance = baselineCommits.length > 0
|
|
172
|
+
? baselineCommits.reduce((sum, c) => sum + c.score, 0) / baselineCommits.length
|
|
173
|
+
: 100;
|
|
174
|
+
const currentCompliance = currentCommits.length > 0
|
|
175
|
+
? currentCommits.reduce((sum, c) => sum + c.score, 0) / currentCommits.length
|
|
176
|
+
: 100;
|
|
177
|
+
// Calculate drift percentage (negative = improvement, positive = degradation)
|
|
178
|
+
const driftPercentage = baselineCompliance > 0
|
|
179
|
+
? ((baselineCompliance - currentCompliance) / baselineCompliance) * 100
|
|
180
|
+
: 0;
|
|
181
|
+
// Determine trend
|
|
182
|
+
let trend = 'stable';
|
|
183
|
+
if (driftPercentage > 10) {
|
|
184
|
+
trend = 'degrading';
|
|
185
|
+
}
|
|
186
|
+
else if (driftPercentage < -10) {
|
|
187
|
+
trend = 'improving';
|
|
188
|
+
}
|
|
189
|
+
// Calculate entropy score
|
|
190
|
+
const entropyScore = calculateEntropy(sortedCommits);
|
|
191
|
+
// Find degrading commits (score below 70)
|
|
192
|
+
const degradingCommits = complianceData
|
|
193
|
+
.filter(c => c.score < 70)
|
|
194
|
+
.map(c => ({
|
|
195
|
+
hash: c.commit.hash,
|
|
196
|
+
message: c.commit.message,
|
|
197
|
+
timestamp: c.commit.date,
|
|
198
|
+
issues: c.issues,
|
|
199
|
+
complianceScore: c.score,
|
|
200
|
+
}));
|
|
201
|
+
// Detect if contract drift is significant
|
|
202
|
+
const detected = driftPercentage > driftThreshold || degradingCommits.length > commits.length * 0.3;
|
|
203
|
+
// Generate message
|
|
204
|
+
let message = 'Commit format compliance stable';
|
|
205
|
+
if (detected) {
|
|
206
|
+
if (trend === 'degrading') {
|
|
207
|
+
message = `Commit format degrading: ${driftPercentage.toFixed(0)}% drift from baseline`;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
message = `${degradingCommits.length} commits below quality threshold`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else if (trend === 'improving') {
|
|
214
|
+
message = 'Commit format improving over time';
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
detected,
|
|
218
|
+
driftMetrics: {
|
|
219
|
+
baselineCompliance: Math.round(baselineCompliance),
|
|
220
|
+
currentCompliance: Math.round(currentCompliance),
|
|
221
|
+
driftPercentage: Math.round(driftPercentage),
|
|
222
|
+
trend,
|
|
223
|
+
entropyScore: Math.round(entropyScore * 100) / 100,
|
|
224
|
+
},
|
|
225
|
+
degradingCommits,
|
|
226
|
+
totalDegradingCommits: degradingCommits.length,
|
|
227
|
+
message,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=contract-drift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-drift.js","sourceRoot":"","sources":["../../src/ai-safety/contract-drift.ts"],"names":[],"mappings":"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"}
|