@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.
- package/README.md +115 -0
- package/bin/vibe-check.js +2 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +90 -0
- package/dist/cli.js.map +1 -0
- package/dist/git.d.ts +4 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +64 -0
- package/dist/git.js.map +1 -0
- package/dist/metrics/flow.d.ts +3 -0
- package/dist/metrics/flow.d.ts.map +1 -0
- package/dist/metrics/flow.js +48 -0
- package/dist/metrics/flow.js.map +1 -0
- package/dist/metrics/index.d.ts +4 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +156 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/rework.d.ts +3 -0
- package/dist/metrics/rework.d.ts.map +1 -0
- package/dist/metrics/rework.js +45 -0
- package/dist/metrics/rework.js.map +1 -0
- package/dist/metrics/spirals.d.ts +9 -0
- package/dist/metrics/spirals.d.ts.map +1 -0
- package/dist/metrics/spirals.js +153 -0
- package/dist/metrics/spirals.js.map +1 -0
- package/dist/metrics/trust.d.ts +3 -0
- package/dist/metrics/trust.d.ts.map +1 -0
- package/dist/metrics/trust.js +71 -0
- package/dist/metrics/trust.js.map +1 -0
- package/dist/metrics/velocity.d.ts +4 -0
- package/dist/metrics/velocity.d.ts.map +1 -0
- package/dist/metrics/velocity.js +77 -0
- package/dist/metrics/velocity.js.map +1 -0
- package/dist/output/index.d.ts +6 -0
- package/dist/output/index.d.ts.map +1 -0
- package/dist/output/index.js +25 -0
- package/dist/output/index.js.map +1 -0
- package/dist/output/json.d.ts +3 -0
- package/dist/output/json.d.ts.map +1 -0
- package/dist/output/json.js +52 -0
- package/dist/output/json.js.map +1 -0
- package/dist/output/markdown.d.ts +3 -0
- package/dist/output/markdown.d.ts.map +1 -0
- package/dist/output/markdown.js +90 -0
- package/dist/output/markdown.js.map +1 -0
- package/dist/output/terminal.d.ts +3 -0
- package/dist/output/terminal.d.ts.map +1 -0
- package/dist/output/terminal.js +90 -0
- package/dist/output/terminal.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
- package/src/cli.ts +96 -0
- package/src/git.ts +72 -0
- package/src/metrics/flow.ts +53 -0
- package/src/metrics/index.ts +169 -0
- package/src/metrics/rework.ts +45 -0
- package/src/metrics/spirals.ts +173 -0
- package/src/metrics/trust.ts +80 -0
- package/src/metrics/velocity.ts +86 -0
- package/src/output/index.ts +20 -0
- package/src/output/json.ts +51 -0
- package/src/output/markdown.ts +111 -0
- package/src/output/terminal.ts +109 -0
- package/src/types.ts +68 -0
- 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
|
package/dist/cli.d.ts
ADDED
|
@@ -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
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,kDAA0B;AAC1B,+BAA8C;AAC9C,uCAA2C;AAC3C,qCAAwC;AAGxC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,gBAAgB,EAAE,4DAA4D,CAAC;KACtF,MAAM,CAAC,gBAAgB,EAAE,sCAAsC,CAAC;KAChE,MAAM,CACL,qBAAqB,EACrB,yCAAyC,EACzC,UAAU,CACX;KACA,MAAM,CAAC,mBAAmB,EAAE,8CAA8C,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC1F,MAAM,CAAC,eAAe,EAAE,qBAAqB,EAAE,KAAK,CAAC;KACrD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAExD,kBAAkB;QAClB,MAAM,YAAY,GAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;QACtE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC,CAAC;YACtD,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,IAAI,CAAC,kBAAkB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC,CAAC,MAAM,IAAA,eAAS,EAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,IAAI,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3D,IAAI,KAAK;gBAAE,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC;YACxD,IAAI,KAAK;gBAAE,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1D,CAAC;QAED,cAAc;QACd,MAAM,OAAO,GAAG,MAAM,IAAA,gBAAU,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAErD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,8CAA8C,CAAC,CAAC,CAAC;gBAC1E,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC;oBACxD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC;oBAC7D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;iBAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC7B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACzE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;YACjF,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC;QAC/D,CAAC;QAED,kBAAkB;QAClB,MAAM,MAAM,GAAG,IAAA,wBAAc,EAAC,OAAO,CAAC,CAAC;QAEvC,gBAAgB;QAChB,MAAM,MAAM,GAAG,IAAA,qBAAY,EAAC,MAAM,EAAE,MAAsB,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEpB,qDAAqD;QACrD,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACpD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/dist/git.d.ts
ADDED
|
@@ -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
|
package/dist/git.js.map
ADDED
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|