@boshu2/vibe-check 1.0.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.
Files changed (69) hide show
  1. package/README.md +115 -0
  2. package/bin/vibe-check.js +2 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +90 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/git.d.ts +4 -0
  8. package/dist/git.d.ts.map +1 -0
  9. package/dist/git.js +64 -0
  10. package/dist/git.js.map +1 -0
  11. package/dist/metrics/flow.d.ts +3 -0
  12. package/dist/metrics/flow.d.ts.map +1 -0
  13. package/dist/metrics/flow.js +48 -0
  14. package/dist/metrics/flow.js.map +1 -0
  15. package/dist/metrics/index.d.ts +4 -0
  16. package/dist/metrics/index.d.ts.map +1 -0
  17. package/dist/metrics/index.js +156 -0
  18. package/dist/metrics/index.js.map +1 -0
  19. package/dist/metrics/rework.d.ts +3 -0
  20. package/dist/metrics/rework.d.ts.map +1 -0
  21. package/dist/metrics/rework.js +45 -0
  22. package/dist/metrics/rework.js.map +1 -0
  23. package/dist/metrics/spirals.d.ts +9 -0
  24. package/dist/metrics/spirals.d.ts.map +1 -0
  25. package/dist/metrics/spirals.js +153 -0
  26. package/dist/metrics/spirals.js.map +1 -0
  27. package/dist/metrics/trust.d.ts +3 -0
  28. package/dist/metrics/trust.d.ts.map +1 -0
  29. package/dist/metrics/trust.js +71 -0
  30. package/dist/metrics/trust.js.map +1 -0
  31. package/dist/metrics/velocity.d.ts +4 -0
  32. package/dist/metrics/velocity.d.ts.map +1 -0
  33. package/dist/metrics/velocity.js +77 -0
  34. package/dist/metrics/velocity.js.map +1 -0
  35. package/dist/output/index.d.ts +6 -0
  36. package/dist/output/index.d.ts.map +1 -0
  37. package/dist/output/index.js +25 -0
  38. package/dist/output/index.js.map +1 -0
  39. package/dist/output/json.d.ts +3 -0
  40. package/dist/output/json.d.ts.map +1 -0
  41. package/dist/output/json.js +52 -0
  42. package/dist/output/json.js.map +1 -0
  43. package/dist/output/markdown.d.ts +3 -0
  44. package/dist/output/markdown.d.ts.map +1 -0
  45. package/dist/output/markdown.js +90 -0
  46. package/dist/output/markdown.js.map +1 -0
  47. package/dist/output/terminal.d.ts +3 -0
  48. package/dist/output/terminal.d.ts.map +1 -0
  49. package/dist/output/terminal.js +90 -0
  50. package/dist/output/terminal.js.map +1 -0
  51. package/dist/types.d.ts +63 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +3 -0
  54. package/dist/types.js.map +1 -0
  55. package/package.json +42 -0
  56. package/src/cli.ts +96 -0
  57. package/src/git.ts +72 -0
  58. package/src/metrics/flow.ts +53 -0
  59. package/src/metrics/index.ts +169 -0
  60. package/src/metrics/rework.ts +45 -0
  61. package/src/metrics/spirals.ts +173 -0
  62. package/src/metrics/trust.ts +80 -0
  63. package/src/metrics/velocity.ts +86 -0
  64. package/src/output/index.ts +20 -0
  65. package/src/output/json.ts +51 -0
  66. package/src/output/markdown.ts +111 -0
  67. package/src/output/terminal.ts +109 -0
  68. package/src/types.ts +68 -0
  69. package/tsconfig.json +19 -0
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # vibe-check
2
+
3
+ Measure vibe coding effectiveness with git commit analysis.
4
+
5
+ ## What is Vibe Coding?
6
+
7
+ Vibe coding is AI-assisted development where you collaborate with an AI coding assistant. This tool measures how effectively that collaboration is working by analyzing your git commit patterns.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install -g vibe-check
13
+ ```
14
+
15
+ Or run directly with npx:
16
+
17
+ ```bash
18
+ npx vibe-check
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ # Analyze current repository
25
+ vibe-check
26
+
27
+ # Analyze last week
28
+ vibe-check --since "1 week ago"
29
+
30
+ # JSON output for CI/automation
31
+ vibe-check --format json
32
+
33
+ # Markdown report
34
+ vibe-check --format markdown
35
+
36
+ # Analyze specific repo
37
+ vibe-check --repo /path/to/repo
38
+ ```
39
+
40
+ ## The 5 Core Metrics (FAAFO)
41
+
42
+ | Metric | What It Measures | Target |
43
+ |--------|------------------|--------|
44
+ | **Iteration Velocity** | Commits per hour | >5/hr = Elite |
45
+ | **Rework Ratio** | % commits that are fixes | <30% = Elite |
46
+ | **Trust Pass Rate** | % commits that stick (no immediate fix) | >95% = Elite |
47
+ | **Debug Spiral Duration** | Time spent in fix chains | <15m = Elite |
48
+ | **Flow Efficiency** | % time in productive work vs debugging | >90% = Elite |
49
+
50
+ ## Output Ratings
51
+
52
+ | Rating | Meaning |
53
+ |--------|---------|
54
+ | **ELITE** | Vibe coding working excellently |
55
+ | **HIGH** | Good effectiveness, minor improvements possible |
56
+ | **MEDIUM** | Room for improvement |
57
+ | **LOW** | Process issues, reassess approach |
58
+
59
+ ## Example Output
60
+
61
+ ```
62
+ ╔════════════════════════════════════════════════════════════╗
63
+ ║ VIBE CHECK RESULTS ║
64
+ ╠════════════════════════════════════════════════════════════╣
65
+ ║ Period: Nov 21 - Nov 28, 2025 ║
66
+ ║ Commits Analyzed: 47 ║
67
+ ╠════════════════════════════════════════════════════════════╣
68
+ ║ ║
69
+ ║ Iteration Velocity ████████████░░░░ 4.2/hr HIGH ║
70
+ ║ Rework Ratio ██████░░░░░░░░░░ 35% MEDIUM ║
71
+ ║ Trust Pass Rate ████████████████ 92% HIGH ║
72
+ ║ Debug Spiral Duration ██████████████░░ 18min HIGH ║
73
+ ║ Flow Efficiency ██████████████░░ 85% HIGH ║
74
+ ║ ║
75
+ ╠════════════════════════════════════════════════════════════╣
76
+ ║ Overall Rating: HIGH ║
77
+ ╚════════════════════════════════════════════════════════════╝
78
+ ```
79
+
80
+ ## Debug Spiral Detection
81
+
82
+ When the tool detects fix chains (multiple fix commits in a row), it identifies:
83
+ - Which component had issues
84
+ - Pattern category (e.g., `API_MISMATCH`, `SSL_TLS`, `VOLUME_CONFIG`)
85
+ - Duration of the spiral
86
+ - Suggested tracer test to prevent recurrence
87
+
88
+ ## Integration with Claude Code
89
+
90
+ This tool is designed to work with the RPI (Research-Plan-Implement) workflow:
91
+
92
+ 1. **Before implementation**: Run `vibe-check` to establish baseline
93
+ 2. **After implementation**: Run `vibe-check --since "<start-time>"` to measure session
94
+ 3. **Weekly review**: Run `vibe-check --since "1 week ago" --format markdown`
95
+
96
+ ## Options
97
+
98
+ ```
99
+ -V, --version Output version number
100
+ --since <date> Start date for analysis (e.g., "1 week ago", "2025-11-01")
101
+ --until <date> End date for analysis (default: now)
102
+ -f, --format <type> Output format: terminal, json, markdown (default: terminal)
103
+ -r, --repo <path> Repository path (default: current directory)
104
+ -v, --verbose Show verbose output
105
+ -h, --help Display help
106
+ ```
107
+
108
+ ## Requirements
109
+
110
+ - Node.js >= 18.0.0
111
+ - Git repository with commit history
112
+
113
+ ## License
114
+
115
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/cli.js');
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const git_1 = require("./git");
10
+ const metrics_1 = require("./metrics");
11
+ const output_1 = require("./output");
12
+ const program = new commander_1.Command();
13
+ program
14
+ .name('vibe-check')
15
+ .description('Measure vibe coding effectiveness with git commit analysis')
16
+ .version('1.0.0')
17
+ .option('--since <date>', 'Start date for analysis (e.g., "1 week ago", "2025-11-01")')
18
+ .option('--until <date>', 'End date for analysis (default: now)')
19
+ .option('-f, --format <type>', 'Output format: terminal, json, markdown', 'terminal')
20
+ .option('-r, --repo <path>', 'Repository path (default: current directory)', process.cwd())
21
+ .option('-v, --verbose', 'Show verbose output', false)
22
+ .action(async (options) => {
23
+ try {
24
+ const { since, until, format, repo, verbose } = options;
25
+ // Validate format
26
+ const validFormats = ['terminal', 'json', 'markdown'];
27
+ if (!validFormats.includes(format)) {
28
+ console.error(chalk_1.default.red(`Invalid format: ${format}`));
29
+ console.error(chalk_1.default.gray(`Valid formats: ${validFormats.join(', ')}`));
30
+ process.exit(1);
31
+ }
32
+ // Check if repo is valid
33
+ if (!(await (0, git_1.isGitRepo)(repo))) {
34
+ console.error(chalk_1.default.red(`Not a git repository: ${repo}`));
35
+ process.exit(1);
36
+ }
37
+ if (verbose) {
38
+ console.error(chalk_1.default.gray(`Analyzing repository: ${repo}`));
39
+ if (since)
40
+ console.error(chalk_1.default.gray(`Since: ${since}`));
41
+ if (until)
42
+ console.error(chalk_1.default.gray(`Until: ${until}`));
43
+ }
44
+ // Get commits
45
+ const commits = await (0, git_1.getCommits)(repo, since, until);
46
+ if (commits.length === 0) {
47
+ if (format === 'terminal') {
48
+ console.log(chalk_1.default.yellow('\nNo commits found in the specified range.\n'));
49
+ if (!since) {
50
+ console.log(chalk_1.default.gray('Try specifying a date range:'));
51
+ console.log(chalk_1.default.gray(' vibe-check --since "1 week ago"'));
52
+ console.log(chalk_1.default.gray(' vibe-check --since "2025-11-01"'));
53
+ }
54
+ }
55
+ else if (format === 'json') {
56
+ console.log(JSON.stringify({ error: 'No commits found', commits: 0 }));
57
+ }
58
+ else {
59
+ console.log('# Vibe-Check Report\n\nNo commits found in the specified range.');
60
+ }
61
+ process.exit(0);
62
+ }
63
+ if (verbose) {
64
+ console.error(chalk_1.default.gray(`Found ${commits.length} commits`));
65
+ }
66
+ // Analyze commits
67
+ const result = (0, metrics_1.analyzeCommits)(commits);
68
+ // Output result
69
+ const output = (0, output_1.formatOutput)(result, format);
70
+ console.log(output);
71
+ // Exit with appropriate code based on overall rating
72
+ if (result.overall === 'LOW') {
73
+ process.exit(1);
74
+ }
75
+ }
76
+ catch (error) {
77
+ if (error instanceof Error) {
78
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
79
+ if (options.verbose) {
80
+ console.error(chalk_1.default.gray(error.stack));
81
+ }
82
+ }
83
+ else {
84
+ console.error(chalk_1.default.red('An unexpected error occurred'));
85
+ }
86
+ process.exit(1);
87
+ }
88
+ });
89
+ program.parse();
90
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/git.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Commit } from './types';
2
+ export declare function getCommits(repoPath: string, since?: string, until?: string): Promise<Commit[]>;
3
+ export declare function isGitRepo(repoPath: string): Promise<boolean>;
4
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,EAAE,CAAC,CAuBnB;AA+BD,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQlE"}
package/dist/git.js ADDED
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getCommits = getCommits;
7
+ exports.isGitRepo = isGitRepo;
8
+ const simple_git_1 = __importDefault(require("simple-git"));
9
+ const COMMIT_TYPES = ['feat', 'fix', 'docs', 'chore', 'refactor', 'test', 'style'];
10
+ async function getCommits(repoPath, since, until) {
11
+ const git = (0, simple_git_1.default)(repoPath);
12
+ // Build options for git log
13
+ const options = {};
14
+ if (since) {
15
+ options['--since'] = since;
16
+ }
17
+ if (until) {
18
+ options['--until'] = until;
19
+ }
20
+ try {
21
+ const log = await git.log(options);
22
+ return log.all.map((entry) => parseCommit(entry));
23
+ }
24
+ catch (error) {
25
+ if (error instanceof Error) {
26
+ throw new Error(`Failed to read git log: ${error.message}`);
27
+ }
28
+ throw error;
29
+ }
30
+ }
31
+ function parseCommit(entry) {
32
+ const { hash, date, message, author_name } = entry;
33
+ // Parse conventional commit format: type(scope): description
34
+ const conventionalMatch = message.match(/^(\w+)(?:\(([^)]+)\))?:\s*(.+)/);
35
+ let type = 'other';
36
+ let scope = null;
37
+ if (conventionalMatch) {
38
+ const [, rawType, rawScope] = conventionalMatch;
39
+ const normalizedType = rawType.toLowerCase();
40
+ if (COMMIT_TYPES.includes(normalizedType)) {
41
+ type = normalizedType;
42
+ }
43
+ scope = rawScope || null;
44
+ }
45
+ return {
46
+ hash: hash.substring(0, 7),
47
+ date: new Date(date),
48
+ message: message.split('\n')[0], // First line only
49
+ type,
50
+ scope,
51
+ author: author_name,
52
+ };
53
+ }
54
+ async function isGitRepo(repoPath) {
55
+ const git = (0, simple_git_1.default)(repoPath);
56
+ try {
57
+ await git.status();
58
+ return true;
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ }
64
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":";;;;;AAKA,gCA2BC;AA+BD,8BAQC;AAvED,4DAA+E;AAG/E,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAErF,KAAK,UAAU,UAAU,CAC9B,QAAgB,EAChB,KAAc,EACd,KAAc;IAEd,MAAM,GAAG,GAAc,IAAA,oBAAS,EAAC,QAAQ,CAAC,CAAC;IAE3C,4BAA4B;IAC5B,MAAM,OAAO,GAA8C,EAAE,CAAC;IAE9D,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAC7B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAgC,MAAM,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEhE,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAuB;IAC1C,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IAEnD,6DAA6D;IAC7D,MAAM,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAE1E,IAAI,IAAI,GAAmB,OAAO,CAAC;IACnC,IAAI,KAAK,GAAkB,IAAI,CAAC;IAEhC,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,iBAAiB,CAAC;QAChD,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QAE7C,IAAI,YAAY,CAAC,QAAQ,CAAC,cAA6C,CAAC,EAAE,CAAC;YACzE,IAAI,GAAG,cAAgC,CAAC;QAC1C,CAAC;QACD,KAAK,GAAG,QAAQ,IAAI,IAAI,CAAC;IAC3B,CAAC;IAED,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC;QACpB,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,kBAAkB;QACnD,IAAI;QACJ,KAAK;QACL,MAAM,EAAE,WAAW;KACpB,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,SAAS,CAAC,QAAgB;IAC9C,MAAM,GAAG,GAAc,IAAA,oBAAS,EAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { FixChain, MetricResult } from '../types';
2
+ export declare function calculateFlowEfficiency(activeMinutes: number, spirals: FixChain[]): MetricResult;
3
+ //# sourceMappingURL=flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/metrics/flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAU,MAAM,UAAU,CAAC;AAE1D,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,QAAQ,EAAE,GAClB,YAAY,CAwBd"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateFlowEfficiency = calculateFlowEfficiency;
4
+ function calculateFlowEfficiency(activeMinutes, spirals) {
5
+ if (activeMinutes === 0) {
6
+ return {
7
+ value: 100,
8
+ unit: '%',
9
+ rating: 'elite',
10
+ description: 'No active time recorded',
11
+ };
12
+ }
13
+ const spiralMinutes = spirals
14
+ .filter((s) => s.isSpiral)
15
+ .reduce((sum, s) => sum + s.duration, 0);
16
+ const efficiency = ((activeMinutes - spiralMinutes) / activeMinutes) * 100;
17
+ const clampedEfficiency = Math.max(0, Math.min(100, efficiency));
18
+ const rating = getRating(clampedEfficiency);
19
+ return {
20
+ value: Math.round(clampedEfficiency),
21
+ unit: '%',
22
+ rating,
23
+ description: getDescription(rating, spiralMinutes),
24
+ };
25
+ }
26
+ function getRating(efficiency) {
27
+ if (efficiency > 90)
28
+ return 'elite';
29
+ if (efficiency >= 75)
30
+ return 'high';
31
+ if (efficiency >= 50)
32
+ return 'medium';
33
+ return 'low';
34
+ }
35
+ function getDescription(rating, spiralMinutes) {
36
+ const spiralText = spiralMinutes > 0 ? `${spiralMinutes}m spent in debug spirals` : 'No debug spirals';
37
+ switch (rating) {
38
+ case 'elite':
39
+ return `${spiralText}. Excellent productive flow`;
40
+ case 'high':
41
+ return `${spiralText}. Good balance`;
42
+ case 'medium':
43
+ return `${spiralText}. Significant debugging overhead`;
44
+ case 'low':
45
+ return `${spiralText}. More debugging than building`;
46
+ }
47
+ }
48
+ //# sourceMappingURL=flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/metrics/flow.ts"],"names":[],"mappings":";;AAEA,0DA2BC;AA3BD,SAAgB,uBAAuB,CACrC,aAAqB,EACrB,OAAmB;IAEnB,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,KAAK,EAAE,GAAG;YACV,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,yBAAyB;SACvC,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,OAAO;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;SACzB,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAE3C,MAAM,UAAU,GAAG,CAAC,CAAC,aAAa,GAAG,aAAa,CAAC,GAAG,aAAa,CAAC,GAAG,GAAG,CAAC;IAC3E,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAE5C,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;QACpC,IAAI,EAAE,GAAG;QACT,MAAM;QACN,WAAW,EAAE,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC;KACnD,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,UAAkB;IACnC,IAAI,UAAU,GAAG,EAAE;QAAE,OAAO,OAAO,CAAC;IACpC,IAAI,UAAU,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IACpC,IAAI,UAAU,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAC;IACtC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,aAAqB;IAC3D,MAAM,UAAU,GACd,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,0BAA0B,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAEtF,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,GAAG,UAAU,6BAA6B,CAAC;QACpD,KAAK,MAAM;YACT,OAAO,GAAG,UAAU,gBAAgB,CAAC;QACvC,KAAK,QAAQ;YACX,OAAO,GAAG,UAAU,kCAAkC,CAAC;QACzD,KAAK,KAAK;YACR,OAAO,GAAG,UAAU,gCAAgC,CAAC;IACzD,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Commit, VibeCheckResult } from '../types';
2
+ export declare function analyzeCommits(commits: Commit[]): VibeCheckResult;
3
+ export { calculateActiveHours } from './velocity';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AAW1E,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,eAAe,CAsDjE;AAuGD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateActiveHours = void 0;
4
+ exports.analyzeCommits = analyzeCommits;
5
+ const velocity_1 = require("./velocity");
6
+ const rework_1 = require("./rework");
7
+ const trust_1 = require("./trust");
8
+ const spirals_1 = require("./spirals");
9
+ const flow_1 = require("./flow");
10
+ function analyzeCommits(commits) {
11
+ if (commits.length === 0) {
12
+ return emptyResult();
13
+ }
14
+ // Sort commits by date
15
+ const sorted = [...commits].sort((a, b) => a.date.getTime() - b.date.getTime());
16
+ const from = sorted[0].date;
17
+ const to = sorted[sorted.length - 1].date;
18
+ const activeHours = (0, velocity_1.calculateActiveHours)(sorted);
19
+ // Count commit types
20
+ const commitCounts = countCommitTypes(sorted);
21
+ // Detect fix chains
22
+ const fixChains = (0, spirals_1.detectFixChains)(sorted);
23
+ // Calculate all metrics
24
+ const iterationVelocity = (0, velocity_1.calculateIterationVelocity)(sorted);
25
+ const reworkRatio = (0, rework_1.calculateReworkRatio)(sorted);
26
+ const trustPassRate = (0, trust_1.calculateTrustPassRate)(sorted);
27
+ const debugSpiralDuration = (0, spirals_1.calculateDebugSpiralDuration)(fixChains);
28
+ const flowEfficiency = (0, flow_1.calculateFlowEfficiency)(activeHours * 60, fixChains);
29
+ // Calculate pattern summary
30
+ const patterns = (0, spirals_1.calculatePatternSummary)(fixChains);
31
+ // Determine overall rating
32
+ const overall = calculateOverallRating([
33
+ iterationVelocity.rating,
34
+ reworkRatio.rating,
35
+ trustPassRate.rating,
36
+ debugSpiralDuration.rating,
37
+ flowEfficiency.rating,
38
+ ]);
39
+ return {
40
+ period: {
41
+ from,
42
+ to,
43
+ activeHours: Math.round(activeHours * 10) / 10,
44
+ },
45
+ commits: commitCounts,
46
+ metrics: {
47
+ iterationVelocity,
48
+ reworkRatio,
49
+ trustPassRate,
50
+ debugSpiralDuration,
51
+ flowEfficiency,
52
+ },
53
+ fixChains,
54
+ patterns,
55
+ overall,
56
+ };
57
+ }
58
+ function countCommitTypes(commits) {
59
+ const counts = {
60
+ total: commits.length,
61
+ feat: 0,
62
+ fix: 0,
63
+ docs: 0,
64
+ other: 0,
65
+ };
66
+ for (const commit of commits) {
67
+ switch (commit.type) {
68
+ case 'feat':
69
+ counts.feat++;
70
+ break;
71
+ case 'fix':
72
+ counts.fix++;
73
+ break;
74
+ case 'docs':
75
+ counts.docs++;
76
+ break;
77
+ default:
78
+ counts.other++;
79
+ }
80
+ }
81
+ return counts;
82
+ }
83
+ function calculateOverallRating(ratings) {
84
+ const scores = {
85
+ elite: 4,
86
+ high: 3,
87
+ medium: 2,
88
+ low: 1,
89
+ };
90
+ const avgScore = ratings.reduce((sum, r) => sum + scores[r], 0) / ratings.length;
91
+ if (avgScore >= 3.5)
92
+ return 'ELITE';
93
+ if (avgScore >= 2.5)
94
+ return 'HIGH';
95
+ if (avgScore >= 1.5)
96
+ return 'MEDIUM';
97
+ return 'LOW';
98
+ }
99
+ function emptyResult() {
100
+ return {
101
+ period: {
102
+ from: new Date(),
103
+ to: new Date(),
104
+ activeHours: 0,
105
+ },
106
+ commits: {
107
+ total: 0,
108
+ feat: 0,
109
+ fix: 0,
110
+ docs: 0,
111
+ other: 0,
112
+ },
113
+ metrics: {
114
+ iterationVelocity: {
115
+ value: 0,
116
+ unit: 'commits/hour',
117
+ rating: 'low',
118
+ description: 'No commits found',
119
+ },
120
+ reworkRatio: {
121
+ value: 0,
122
+ unit: '%',
123
+ rating: 'elite',
124
+ description: 'No commits found',
125
+ },
126
+ trustPassRate: {
127
+ value: 100,
128
+ unit: '%',
129
+ rating: 'elite',
130
+ description: 'No commits found',
131
+ },
132
+ debugSpiralDuration: {
133
+ value: 0,
134
+ unit: 'min',
135
+ rating: 'elite',
136
+ description: 'No debug spirals detected',
137
+ },
138
+ flowEfficiency: {
139
+ value: 100,
140
+ unit: '%',
141
+ rating: 'elite',
142
+ description: 'No active time recorded',
143
+ },
144
+ },
145
+ fixChains: [],
146
+ patterns: {
147
+ categories: {},
148
+ total: 0,
149
+ tracerAvailable: 0,
150
+ },
151
+ overall: 'HIGH',
152
+ };
153
+ }
154
+ var velocity_2 = require("./velocity");
155
+ Object.defineProperty(exports, "calculateActiveHours", { enumerable: true, get: function () { return velocity_2.calculateActiveHours; } });
156
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Commit, MetricResult } from '../types';
2
+ export declare function calculateReworkRatio(commits: Commit[]): MetricResult;
3
+ //# sourceMappingURL=rework.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rework.d.ts","sourceRoot":"","sources":["../../src/metrics/rework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAU,MAAM,UAAU,CAAC;AAExD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,CAoBpE"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateReworkRatio = calculateReworkRatio;
4
+ function calculateReworkRatio(commits) {
5
+ if (commits.length === 0) {
6
+ return {
7
+ value: 0,
8
+ unit: '%',
9
+ rating: 'elite',
10
+ description: 'No commits found',
11
+ };
12
+ }
13
+ const fixCommits = commits.filter((c) => c.type === 'fix').length;
14
+ const ratio = (fixCommits / commits.length) * 100;
15
+ const rating = getRating(ratio);
16
+ return {
17
+ value: Math.round(ratio),
18
+ unit: '%',
19
+ rating,
20
+ description: getDescription(rating, fixCommits, commits.length),
21
+ };
22
+ }
23
+ function getRating(ratio) {
24
+ if (ratio < 30)
25
+ return 'elite';
26
+ if (ratio < 50)
27
+ return 'high';
28
+ if (ratio < 70)
29
+ return 'medium';
30
+ return 'low';
31
+ }
32
+ function getDescription(rating, fixes, total) {
33
+ const fixText = `${fixes}/${total} commits are fixes`;
34
+ switch (rating) {
35
+ case 'elite':
36
+ return `${fixText}. Mostly forward progress`;
37
+ case 'high':
38
+ return `${fixText}. Normal for complex work`;
39
+ case 'medium':
40
+ return `${fixText}. Consider validating assumptions before coding`;
41
+ case 'low':
42
+ return `${fixText}. High rework, stop and reassess approach`;
43
+ }
44
+ }
45
+ //# sourceMappingURL=rework.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rework.js","sourceRoot":"","sources":["../../src/metrics/rework.ts"],"names":[],"mappings":";;AAEA,oDAoBC;AApBD,SAAgB,oBAAoB,CAAC,OAAiB;IACpD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,kBAAkB;SAChC,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;IAClE,MAAM,KAAK,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;IAClD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAEhC,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QACxB,IAAI,EAAE,GAAG;QACT,MAAM;QACN,WAAW,EAAE,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,OAAO,CAAC;IAC/B,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,MAAM,CAAC;IAC9B,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,QAAQ,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,KAAa,EAAE,KAAa;IAClE,MAAM,OAAO,GAAG,GAAG,KAAK,IAAI,KAAK,oBAAoB,CAAC;IAEtD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,GAAG,OAAO,2BAA2B,CAAC;QAC/C,KAAK,MAAM;YACT,OAAO,GAAG,OAAO,2BAA2B,CAAC;QAC/C,KAAK,QAAQ;YACX,OAAO,GAAG,OAAO,iDAAiD,CAAC;QACrE,KAAK,KAAK;YACR,OAAO,GAAG,OAAO,2CAA2C,CAAC;IACjE,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Commit, FixChain, MetricResult } from '../types';
2
+ export declare function detectFixChains(commits: Commit[]): FixChain[];
3
+ export declare function calculateDebugSpiralDuration(chains: FixChain[]): MetricResult;
4
+ export declare function calculatePatternSummary(chains: FixChain[]): {
5
+ categories: Record<string, number>;
6
+ total: number;
7
+ tracerAvailable: number;
8
+ };
9
+ //# sourceMappingURL=spirals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spirals.d.ts","sourceRoot":"","sources":["../../src/metrics/spirals.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAU,MAAM,UAAU,CAAC;AAclE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAyC7D;AA8CD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,CAsB7E;AAwBD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG;IAC3D,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;CACzB,CAoBA"}