git-compass 0.2.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 (74) hide show
  1. package/README.md +114 -0
  2. package/dist/__tests__/commands.test.d.ts +2 -0
  3. package/dist/__tests__/commands.test.d.ts.map +1 -0
  4. package/dist/__tests__/commands.test.js +26 -0
  5. package/dist/__tests__/commands.test.js.map +1 -0
  6. package/dist/__tests__/sanity.test.d.ts +2 -0
  7. package/dist/__tests__/sanity.test.d.ts.map +1 -0
  8. package/dist/__tests__/sanity.test.js +7 -0
  9. package/dist/__tests__/sanity.test.js.map +1 -0
  10. package/dist/bin/git-compass.d.ts +3 -0
  11. package/dist/bin/git-compass.d.ts.map +1 -0
  12. package/dist/bin/git-compass.js +4 -0
  13. package/dist/bin/git-compass.js.map +1 -0
  14. package/dist/commands/analyze-all.d.ts +3 -0
  15. package/dist/commands/analyze-all.d.ts.map +1 -0
  16. package/dist/commands/analyze-all.js +136 -0
  17. package/dist/commands/analyze-all.js.map +1 -0
  18. package/dist/commands/analyze.d.ts +3 -0
  19. package/dist/commands/analyze.d.ts.map +1 -0
  20. package/dist/commands/analyze.js +202 -0
  21. package/dist/commands/analyze.js.map +1 -0
  22. package/dist/commands/config.d.ts +3 -0
  23. package/dist/commands/config.d.ts.map +1 -0
  24. package/dist/commands/config.js +78 -0
  25. package/dist/commands/config.js.map +1 -0
  26. package/dist/commands/query.d.ts +3 -0
  27. package/dist/commands/query.d.ts.map +1 -0
  28. package/dist/commands/query.js +78 -0
  29. package/dist/commands/query.js.map +1 -0
  30. package/dist/commands/watch.d.ts +3 -0
  31. package/dist/commands/watch.d.ts.map +1 -0
  32. package/dist/commands/watch.js +49 -0
  33. package/dist/commands/watch.js.map +1 -0
  34. package/dist/config/__tests__/config.test.d.ts +2 -0
  35. package/dist/config/__tests__/config.test.d.ts.map +1 -0
  36. package/dist/config/__tests__/config.test.js +45 -0
  37. package/dist/config/__tests__/config.test.js.map +1 -0
  38. package/dist/config/index.d.ts +10 -0
  39. package/dist/config/index.d.ts.map +1 -0
  40. package/dist/config/index.js +82 -0
  41. package/dist/config/index.js.map +1 -0
  42. package/dist/constants/index.d.ts +15 -0
  43. package/dist/constants/index.d.ts.map +1 -0
  44. package/dist/constants/index.js +15 -0
  45. package/dist/constants/index.js.map +1 -0
  46. package/dist/formatters/__tests__/console.test.d.ts +2 -0
  47. package/dist/formatters/__tests__/console.test.d.ts.map +1 -0
  48. package/dist/formatters/__tests__/console.test.js +40 -0
  49. package/dist/formatters/__tests__/console.test.js.map +1 -0
  50. package/dist/formatters/console.d.ts +3 -0
  51. package/dist/formatters/console.d.ts.map +1 -0
  52. package/dist/formatters/console.js +148 -0
  53. package/dist/formatters/console.js.map +1 -0
  54. package/dist/formatters/report-gen.d.ts +3 -0
  55. package/dist/formatters/report-gen.d.ts.map +1 -0
  56. package/dist/formatters/report-gen.js +8 -0
  57. package/dist/formatters/report-gen.js.map +1 -0
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +47 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/utils/__tests__/cache.test.d.ts +2 -0
  63. package/dist/utils/__tests__/cache.test.d.ts.map +1 -0
  64. package/dist/utils/__tests__/cache.test.js +38 -0
  65. package/dist/utils/__tests__/cache.test.js.map +1 -0
  66. package/dist/utils/cache.d.ts +12 -0
  67. package/dist/utils/cache.d.ts.map +1 -0
  68. package/dist/utils/cache.js +47 -0
  69. package/dist/utils/cache.js.map +1 -0
  70. package/dist/utils/gitignore.d.ts +5 -0
  71. package/dist/utils/gitignore.d.ts.map +1 -0
  72. package/dist/utils/gitignore.js +36 -0
  73. package/dist/utils/gitignore.js.map +1 -0
  74. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # git-compass
2
+
3
+ [![npm version](https://img.shields.io/npm/v/git-compass.svg)](https://www.npmjs.com/package/git-compass)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Build Status](https://img.shields.io/badge/build-passing-brightgreen.svg)]()
6
+
7
+ **Git Compass** is a local-first, AI-augmented analytics engine that delivers deep insights into your code's evolution directly from your terminal. No cloud required, no privacy compromises.
8
+
9
+ It helps developers and teams understand their codebases better by analyzing Git history to reveal **hotspots**, **risk areas**, **contributor trends**, and **potential knowledge silos**.
10
+
11
+ ---
12
+
13
+ ## Key Features
14
+
15
+ ### Deep Repository Intelligence
16
+ - **Hotspot Detection**: Automatically bridge the gap between "frequently changed" and "risky" by analyzing churn velocity and author diversity.
17
+ - **Architectural Risk Scoring**: Real-time risk assessment for every file, Helping you prioritize refactors based on where technical debt is actually growing.
18
+ - **Temporal Coupling**: Surface hidden dependencies between files that always change together but aren't explicitly linked in code.
19
+ - **Code Health Monitoring**: Track code rot (abandoned files) and average impact (blast radius).
20
+
21
+ ### Team Dynamics & Health
22
+ - **Bus Factor Analysis**: Identify critical knowledge silos where a single person is the primary author of a component.
23
+ - **Burnout Mitigation**: Heatmaps of after-hours and weekend commit patterns to help teams maintain a healthy pace.
24
+ - **Contributor DNA**: Understand how different perspectives contribute to your codebase over time.
25
+
26
+ ### AI-Powered Synthesis (Optional)
27
+ - **Natural Language Insights**: Generate human-readable summaries of complex Git history (powered by Anthropic Claude or OpenAI).
28
+ - **Interactive Queries**: Ask your repo questions: *"Who knows the most about the auth module?"* or *"Which files are most risky?"*
29
+
30
+ ---
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ # Global install (recommended)
36
+ npm install -g git-compass
37
+
38
+ # Or run instantly via npx
39
+ npx git-compass analyze
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Quick Start
45
+
46
+ ### 1. Simple Analysis
47
+ Generate a comprehensive report for your current repository:
48
+ ```bash
49
+ git-compass analyze
50
+ ```
51
+
52
+ ### 2. Time-Windowed Deep Dive
53
+ Analyze the last 90 days of history:
54
+ ```bash
55
+ git-compass analyze --window 90d
56
+ ```
57
+
58
+ ### 3. AI Insights (Requires API Key)
59
+ Unlock natural language summaries:
60
+ ```bash
61
+ # Set your key once
62
+ git-compass config set ai.openaiKey <your-openai-key>
63
+ # or
64
+ git-compass config set ai.anthropicKey <your-anthropic-key>
65
+
66
+ # Run with AI augmentation
67
+ git-compass analyze --ai
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Command Reference
73
+
74
+ ### `analyze`
75
+ The primary engine for generating repository insights.
76
+ - `-p, --path <path>`: Path to Git repository (default: `.`)
77
+ - `-b, --branch <branch>`: Branch to analyze (default: `HEAD`)
78
+ - `-w, --window <window>`: Time window (`7d`, `30d`, `90d`, `1y`, `all`)
79
+ - `--max-commits <n>`: Cap the analysis scope
80
+ - `-o, --output <path>`: Export to JSON or HTML report
81
+
82
+ ### `query`
83
+ Interactive natural language interface for your repository.
84
+ ```bash
85
+ git-compass query "Show me the files with the highest churn in the last week"
86
+ ```
87
+
88
+ ### `watch`
89
+ Real-time monitoring mode. Automatically re-analyzes your repo as you commit.
90
+
91
+ ---
92
+
93
+ ## Configuration
94
+
95
+ Git Compass stores settings in a local config file. You can manage them via:
96
+ ```bash
97
+ git-compass config list
98
+ git-compass config set <key> <value>
99
+ ```
100
+
101
+ **Available Keys:**
102
+ - `ai.provider`: LLM provider (`openai`, `anthropic`, `gemini`)
103
+ - `ai.openaiKey`: Your OpenAI API key.
104
+ - `ai.anthropicKey`: Your Anthropic API key.
105
+
106
+ ---
107
+
108
+ ## Privacy & Safety
109
+
110
+ Git Compass is **local-first**. All repository parsing and traditional analytics happen entirely on your machine. If you choose to use the optional AI features, only the summarized metadata (never your full source code) is sent to the LLM provider for synthesis.
111
+
112
+ ---
113
+
114
+ Built with care for teams that value code health.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=commands.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/commands.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { configCommand } from "../commands/config.js";
3
+ import { analyzeCommand } from "../commands/analyze.js";
4
+ import { watchCommand } from "../commands/watch.js";
5
+ describe("Command Registration", () => {
6
+ it("should have correct names and descriptions", () => {
7
+ expect(configCommand.name()).toBe("config");
8
+ expect(analyzeCommand.name()).toBe("analyze");
9
+ expect(watchCommand.name()).toBe("watch");
10
+ expect(configCommand.description()).toContain("Manage");
11
+ expect(analyzeCommand.description()).toContain("Analyze");
12
+ });
13
+ it("should have expected subcommands for config", () => {
14
+ const subcommands = configCommand.commands.map(cmd => cmd.name());
15
+ expect(subcommands).toContain("set");
16
+ expect(subcommands).toContain("get");
17
+ expect(subcommands).toContain("list");
18
+ });
19
+ it("should have expected options for analyze", () => {
20
+ const optionFlags = analyzeCommand.options.map(opt => opt.flags);
21
+ expect(optionFlags.some(f => f.includes("--path"))).toBe(true);
22
+ expect(optionFlags.some(f => f.includes("--branch"))).toBe(true);
23
+ expect(optionFlags.some(f => f.includes("--output"))).toBe(true);
24
+ });
25
+ });
26
+ //# sourceMappingURL=commands.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.test.js","sourceRoot":"","sources":["../../src/__tests__/commands.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAM,MAAM,QAAQ,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE1C,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACxD,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sanity.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanity.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sanity.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ describe('cli', () => {
3
+ it('should pass a sanity check', () => {
4
+ expect(true).toBe(true);
5
+ });
6
+ });
7
+ //# sourceMappingURL=sanity.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanity.test.js","sourceRoot":"","sources":["../../src/__tests__/sanity.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE;IACnB,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=git-compass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-compass.d.ts","sourceRoot":"","sources":["../../src/bin/git-compass.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "../index.js";
3
+ run();
4
+ //# sourceMappingURL=git-compass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-compass.js","sourceRoot":"","sources":["../../src/bin/git-compass.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,GAAG,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const analyzeAllCommand: Command;
3
+ //# sourceMappingURL=analyze-all.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-all.d.ts","sourceRoot":"","sources":["../../src/commands/analyze-all.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0BpC,eAAO,MAAM,iBAAiB,SAmH1B,CAAC"}
@@ -0,0 +1,136 @@
1
+ import { Command } from "commander";
2
+ import ora from "ora";
3
+ import chalk from "chalk";
4
+ import path from "path";
5
+ import fs from "fs/promises";
6
+ import { createGitParser, getCommits, analyzeHotspots, computeRiskScores, getAIProvider, generateSummary, AIProviderType } from "@git-compass/core";
7
+ import { config } from "../config/index.js";
8
+ import { CONFIG_KEYS, ENV_VARS } from "../constants/index.js";
9
+ import { getCachePath, loadCache, getCachedResult, updateCache, saveCache } from "../utils/cache.js";
10
+ import { ensureGitIgnore } from "../utils/gitignore.js";
11
+ export const analyzeAllCommand = new Command("analyze-all")
12
+ .description("Scan a directory for Git repositories and analyze them all")
13
+ .argument("[path]", "directory to scan", process.cwd())
14
+ .option("-w, --window <window>", "time window: 7d, 30d, 90d, 1y, all", "30d")
15
+ .option("--max-commits <n>", "max commits to analyze per repo", "100")
16
+ .option("-d, --detail-level <level>", "detail level: summary, normal, verbose", "normal")
17
+ .option("--ai", "generate AI summaries (requires API key)")
18
+ .action(async (scanPath, options) => {
19
+ const rootPath = path.resolve(scanPath || process.cwd());
20
+ const spinner = ora(`Scanning for Git repositories in ${rootPath}...`).start();
21
+ try {
22
+ const repos = await findGitRepos(rootPath);
23
+ if (repos.length === 0) {
24
+ spinner.fail(chalk.red("No Git repositories found."));
25
+ return;
26
+ }
27
+ spinner.succeed(chalk.green(`Found ${repos.length} repositories.`));
28
+ const summaries = [];
29
+ for (const repoPath of repos) {
30
+ const repoName = path.basename(repoPath);
31
+ const repoSpinner = ora(`Analyzing ${repoName}...`).start();
32
+ try {
33
+ const git = createGitParser(repoPath);
34
+ const topLevel = await git.revparse(["--show-toplevel"]);
35
+ const repoRoot = path.resolve(topLevel);
36
+ const latestCommit = await git.revparse(["HEAD"]);
37
+ // Ensure .git-compass is ignored
38
+ await ensureGitIgnore(repoRoot, [".git-compass"]);
39
+ const cachePath = await getCachePath(repoRoot);
40
+ const cache = await loadCache(cachePath);
41
+ const cachedResult = getCachedResult(cache, repoRoot, latestCommit);
42
+ let result;
43
+ if (cachedResult && (!options.ai || cachedResult.aiSummary)) {
44
+ result = cachedResult;
45
+ repoSpinner.text = `Loaded ${repoName} from cache.`;
46
+ }
47
+ else {
48
+ const commits = await getCommits(git, {
49
+ maxCount: parseInt(options.maxCommits, 10),
50
+ since: options.window !== "all" ? options.window : undefined
51
+ });
52
+ const hotspots = analyzeHotspots(commits, options.window);
53
+ const riskScores = computeRiskScores(hotspots);
54
+ result = {
55
+ meta: {
56
+ repoPath: repoRoot,
57
+ branch: "HEAD",
58
+ window: options.window,
59
+ commitCount: commits.length,
60
+ generatedAt: new Date(),
61
+ },
62
+ hotspots,
63
+ riskScores,
64
+ churn: [],
65
+ contributors: [],
66
+ burnout: { flags: [], afterHoursCommits: 0, weekendCommits: 0, contributors: [] },
67
+ coupling: [],
68
+ knowledge: [],
69
+ impact: [],
70
+ rot: []
71
+ };
72
+ if (options.ai) {
73
+ const envProvider = process.env[ENV_VARS.AI_PROVIDER];
74
+ const configProvider = config.get(CONFIG_KEYS.AI_PROVIDER);
75
+ const providerType = envProvider || configProvider || AIProviderType.ANTHROPIC;
76
+ let apiKey;
77
+ if (providerType === "openai")
78
+ apiKey = process.env[ENV_VARS.OPENAI_API_KEY] || config.get("ai.openaiKey");
79
+ else if (providerType === "gemini")
80
+ apiKey = process.env[ENV_VARS.GEMINI_API_KEY] || config.get("ai.geminiKey");
81
+ else
82
+ apiKey = process.env[ENV_VARS.ANTHROPIC_API_KEY] || config.get("ai.anthropicKey") || config.get(CONFIG_KEYS.AI_KEY);
83
+ if (apiKey) {
84
+ try {
85
+ const aiProvider = getAIProvider(providerType, apiKey);
86
+ result.aiSummary = await generateSummary(aiProvider, result);
87
+ }
88
+ catch (e) { }
89
+ }
90
+ }
91
+ const updatedCache = updateCache(cache, repoRoot, latestCommit, result);
92
+ await saveCache(cachePath, updatedCache);
93
+ }
94
+ const highRiskCount = result.riskScores.filter(r => r.level === "high" || r.level === "critical").length;
95
+ summaries.push({
96
+ name: repoName,
97
+ commits: result.meta.commitCount,
98
+ hotspots: result.hotspots.length,
99
+ highRisk: highRiskCount
100
+ });
101
+ repoSpinner.succeed(chalk.cyan(`${repoName}: ${result.meta.commitCount} commits, ${highRiskCount} high-risk files.`));
102
+ }
103
+ catch (err) {
104
+ repoSpinner.fail(chalk.red(`Failed to analyze ${repoName}: ${err.message}`));
105
+ }
106
+ }
107
+ console.log("\n" + chalk.bold.underline("Organization Summary:"));
108
+ console.table(summaries);
109
+ }
110
+ catch (err) {
111
+ spinner.fail(chalk.red(`Scan failed: ${err.message}`));
112
+ }
113
+ });
114
+ async function findGitRepos(dir, depth = 0, maxDepth = 3) {
115
+ const repos = [];
116
+ try {
117
+ const entries = await fs.readdir(dir, { withFileTypes: true });
118
+ // Check if current dir is a git repo
119
+ if (entries.some(e => e.isDirectory() && e.name === ".git")) {
120
+ return [dir];
121
+ }
122
+ if (depth >= maxDepth)
123
+ return [];
124
+ for (const entry of entries) {
125
+ if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
126
+ const subRepos = await findGitRepos(path.join(dir, entry.name), depth + 1, maxDepth);
127
+ repos.push(...subRepos);
128
+ }
129
+ }
130
+ }
131
+ catch (err) {
132
+ // Ignore inaccessible directories
133
+ }
134
+ return repos;
135
+ }
136
+ //# sourceMappingURL=analyze-all.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-all.js","sourceRoot":"","sources":["../../src/commands/analyze-all.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const analyzeCommand: Command;
3
+ //# sourceMappingURL=analyze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6CpC,eAAO,MAAM,cAAc,SA4JvB,CAAC"}
@@ -0,0 +1,202 @@
1
+ import { Command } from "commander";
2
+ import ora from "ora";
3
+ import chalk from "chalk";
4
+ import { createGitParser, getCommits, analyzeHotspots, computeRiskScores, analyzeChurn, analyzeContributors, analyzeBurnout, analyzeCoupling, analyzeKnowledge, analyzeImpact, analyzeRot, getAIProvider, generateSummary, AIProviderType } from "@git-compass/core";
5
+ import { printConsoleReport } from "../formatters/console.js";
6
+ import { exportJson } from "../formatters/report-gen.js";
7
+ import { config } from "../config/index.js";
8
+ import { DEFAULT_BRANCH, DEFAULT_MAX_COMMITS, DEFAULT_WINDOW, CONFIG_KEYS, ENV_VARS } from "../constants/index.js";
9
+ import { getCachePath, loadCache, getCachedResult, updateCache, saveCache } from "../utils/cache.js";
10
+ import dotenv from "dotenv";
11
+ import path from "path";
12
+ import fs from "fs/promises";
13
+ import { ensureGitIgnore } from "../utils/gitignore.js";
14
+ dotenv.config();
15
+ export const analyzeCommand = new Command("analyze")
16
+ .description("Analyze a Git repository and surface insights")
17
+ .option("-p, --path <path>", "path to git repository", process.cwd())
18
+ .option("-b, --branch <branch>", "branch to analyze", DEFAULT_BRANCH)
19
+ .option("-w, --window <window>", `time window: 7d, 30d, 90d, 1y, all`, DEFAULT_WINDOW)
20
+ .option("--max-commits <n>", "max commits to analyze", DEFAULT_MAX_COMMITS.toString())
21
+ .option("-o, --output <path>", "path to save report (directory or filename)")
22
+ .option("-d, --detail-level <level>", "detail level: summary, normal, verbose", "normal")
23
+ .option("--ai", "generate AI summary (requires API key)")
24
+ .action(async (options) => {
25
+ const repoPath = path.resolve(options.path);
26
+ const spinner = ora("Initializing analysis...").start();
27
+ try {
28
+ const git = createGitParser(repoPath);
29
+ // Find repo root to place .git-compass folder
30
+ let repoRoot = repoPath;
31
+ try {
32
+ const topLevel = await git.revparse(["--show-toplevel"]);
33
+ if (topLevel)
34
+ repoRoot = path.resolve(topLevel);
35
+ }
36
+ catch (err) {
37
+ // Fallback to repoPath if not a git repo or other error
38
+ }
39
+ // Ensure .git-compass is ignored
40
+ await ensureGitIgnore(repoRoot, [".git-compass"]);
41
+ spinner.text = `Fetching commits from ${options.branch}...`;
42
+ // Get latest commit hash for caching
43
+ let latestCommit = "";
44
+ try {
45
+ latestCommit = await git.revparse([options.branch || "HEAD"]);
46
+ }
47
+ catch (err) {
48
+ // Fallback if branch is invalid or other error
49
+ }
50
+ // Check cache
51
+ const cachePath = await getCachePath(repoRoot);
52
+ const cache = await loadCache(cachePath);
53
+ const cachedResult = latestCommit ? getCachedResult(cache, repoRoot, latestCommit) : null;
54
+ if (cachedResult) {
55
+ if (!options.ai || (options.ai && cachedResult.aiSummary)) {
56
+ spinner.succeed(chalk.green(`Loaded from cache for ${latestCommit.slice(0, 7)}.`));
57
+ if (options.output) {
58
+ await handleReportExport(cachedResult, repoPath, repoRoot, options, spinner);
59
+ }
60
+ else {
61
+ printConsoleReport(cachedResult, options.detailLevel, !!options.ai);
62
+ }
63
+ return;
64
+ }
65
+ spinner.info(chalk.blue(`Found cached analysis for ${latestCommit.slice(0, 7)}, but AI summary is missing. Generating now...`));
66
+ }
67
+ const commits = cachedResult
68
+ ? [] // We won't re-fetch commits if we have a cached result and just need AI
69
+ : await getCommits(git, {
70
+ branch: options.branch,
71
+ maxCount: parseInt(options.maxCommits, 10)
72
+ });
73
+ if (!cachedResult && commits.length === 0) {
74
+ spinner.fail(chalk.red("No commits found in the specified window/branch."));
75
+ return;
76
+ }
77
+ const result = cachedResult || {
78
+ meta: {
79
+ repoPath,
80
+ branch: options.branch,
81
+ window: options.window,
82
+ commitCount: commits.length,
83
+ generatedAt: new Date(),
84
+ },
85
+ hotspots: analyzeHotspots(commits, options.window),
86
+ riskScores: computeRiskScores(analyzeHotspots(commits, options.window)), // Simplified for rebuild
87
+ churn: analyzeChurn(commits, options.window),
88
+ contributors: analyzeContributors(commits),
89
+ burnout: analyzeBurnout(commits),
90
+ coupling: analyzeCoupling(commits),
91
+ knowledge: analyzeKnowledge(commits),
92
+ impact: analyzeImpact(commits),
93
+ rot: analyzeRot(commits)
94
+ };
95
+ // Re-calculate hotspots/risk if we don't have cached result (above logic is a bit messy, let's fix)
96
+ if (!cachedResult) {
97
+ spinner.text = `Analyzing ${commits.length} commits...`;
98
+ const h = analyzeHotspots(commits, options.window);
99
+ result.hotspots = h;
100
+ result.riskScores = computeRiskScores(h);
101
+ result.churn = analyzeChurn(commits, options.window);
102
+ result.contributors = analyzeContributors(commits);
103
+ result.burnout = analyzeBurnout(commits);
104
+ result.coupling = analyzeCoupling(commits);
105
+ result.knowledge = analyzeKnowledge(commits);
106
+ result.impact = analyzeImpact(commits);
107
+ result.rot = analyzeRot(commits);
108
+ }
109
+ if (options.ai) {
110
+ spinner.text = "Generating AI insights...";
111
+ // Resolve provider and key
112
+ const envProvider = process.env[ENV_VARS.AI_PROVIDER];
113
+ const configProvider = config.get(CONFIG_KEYS.AI_PROVIDER);
114
+ const providerType = envProvider || configProvider || AIProviderType.ANTHROPIC;
115
+ // Determine API key based on provider
116
+ let apiKey;
117
+ switch (providerType) {
118
+ case AIProviderType.OPENAI:
119
+ apiKey = process.env[ENV_VARS.OPENAI_API_KEY] || config.get("ai.openaiKey");
120
+ break;
121
+ case AIProviderType.GEMINI:
122
+ apiKey = process.env[ENV_VARS.GEMINI_API_KEY] || config.get("ai.geminiKey");
123
+ break;
124
+ case AIProviderType.ANTHROPIC:
125
+ default:
126
+ apiKey = process.env[ENV_VARS.ANTHROPIC_API_KEY] || config.get("ai.anthropicKey") || config.get(CONFIG_KEYS.AI_KEY);
127
+ break;
128
+ }
129
+ if (!apiKey) {
130
+ spinner.warn(chalk.yellow(`AI summary requested but no API key found for ${providerType}. Skipping AI layer.`));
131
+ spinner.info(chalk.blue(`Run 'git-compass config set ai.provider <type>' to configure your preferred provider.`));
132
+ }
133
+ else {
134
+ try {
135
+ const aiProvider = getAIProvider(providerType, apiKey);
136
+ result.aiSummary = await generateSummary(aiProvider, result);
137
+ }
138
+ catch (aiErr) {
139
+ spinner.warn(chalk.yellow("AI summary failed: " + aiErr.message));
140
+ }
141
+ }
142
+ }
143
+ spinner.succeed(chalk.green(`Analysis complete for ${commits.length} commits.`));
144
+ // Update cache
145
+ if (latestCommit) {
146
+ const updatedCache = updateCache(cache, repoRoot, latestCommit, result);
147
+ await saveCache(cachePath, updatedCache);
148
+ }
149
+ if (options.output) {
150
+ await handleReportExport(result, repoPath, repoRoot, options, spinner);
151
+ }
152
+ else {
153
+ printConsoleReport(result, options.detailLevel, !!options.ai);
154
+ }
155
+ }
156
+ catch (err) {
157
+ spinner.fail(chalk.red("Analysis failed: " + err.message));
158
+ console.error(err);
159
+ }
160
+ });
161
+ function generateReportFilename(repoPath, branch, format) {
162
+ const repoName = path.basename(repoPath);
163
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
164
+ const cleanBranch = branch.replace(/[/\\?%*:|"<>]/g, "-");
165
+ return `git-compass-report-${repoName}-${cleanBranch}-${timestamp}.${format}`;
166
+ }
167
+ async function handleReportExport(result, repoPath, repoRoot, options, spinner) {
168
+ const gitCompassDirPath = path.join(repoRoot, ".git-compass");
169
+ let finalPath = path.resolve(options.output);
170
+ // Normalize shorthand or relative paths
171
+ if (options.output === "json") {
172
+ finalPath = gitCompassDirPath;
173
+ }
174
+ else if (!path.isAbsolute(options.output)) {
175
+ finalPath = path.resolve(gitCompassDirPath, options.output);
176
+ }
177
+ // Ensure .git-compass directory exists
178
+ await fs.mkdir(gitCompassDirPath, { recursive: true });
179
+ // Handle directory vs file logic
180
+ try {
181
+ if (!path.extname(finalPath)) {
182
+ await fs.mkdir(finalPath, { recursive: true });
183
+ finalPath = path.join(finalPath, generateReportFilename(repoPath, options.branch, "json"));
184
+ }
185
+ else {
186
+ await fs.mkdir(path.dirname(finalPath), { recursive: true });
187
+ }
188
+ }
189
+ catch (err) {
190
+ spinner.fail(chalk.red("Failed to prepare output directory: " + err.message));
191
+ return;
192
+ }
193
+ spinner.start(`Exporting report...`);
194
+ try {
195
+ const outPath = await exportJson(result, finalPath);
196
+ spinner.succeed(chalk.green(`Report saved to ${outPath}`));
197
+ }
198
+ catch (err) {
199
+ spinner.fail(chalk.red("Export failed: " + err.message));
200
+ }
201
+ }
202
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const configCommand: Command;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,aAAa,SAC4B,CAAC"}