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
@@ -0,0 +1,78 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import { config } from "../config/index.js";
4
+ import { PROJECT_NAME } from "../constants/index.js";
5
+ export const configCommand = new Command("config")
6
+ .description(`Manage ${PROJECT_NAME} configuration`);
7
+ configCommand
8
+ .command("set <key> <value>")
9
+ .description("Set a configuration value (e.g., ai.key)")
10
+ .action((key, value) => {
11
+ config.set(key, value);
12
+ console.log(chalk.green(`${key} set successfully.`));
13
+ });
14
+ configCommand
15
+ .command("set-ai")
16
+ .description("Interactively configure AI provider and API key")
17
+ .action(async () => {
18
+ const { select, password } = await import("@inquirer/prompts");
19
+ const provider = await select({
20
+ message: "Select an AI provider:",
21
+ choices: [
22
+ { name: "Anthropic (Claude)", value: "anthropic" },
23
+ { name: "OpenAI (GPT-4o)", value: "openai" },
24
+ { name: "Google Gemini (1.5 Pro)", value: "gemini" }
25
+ ]
26
+ });
27
+ const apiKey = await password({
28
+ message: `Enter your ${provider} API Key:`,
29
+ mask: "*"
30
+ });
31
+ if (apiKey) {
32
+ config.set("ai.provider", provider);
33
+ config.set(`ai.${provider}Key`, apiKey);
34
+ // Also set the main ai.key for backward compatibility/simplicity
35
+ config.set("ai.key", apiKey);
36
+ console.log(chalk.green(`\nAI configured successfully with ${provider}!`));
37
+ }
38
+ });
39
+ configCommand
40
+ .command("get <key>")
41
+ .description("Get a configuration value")
42
+ .action((key) => {
43
+ const value = config.get(key);
44
+ if (key.toLowerCase().includes("key") && value) {
45
+ console.log(`${key}: ${maskKey(value)}`);
46
+ }
47
+ else {
48
+ console.log(`${key}: ${value ?? "not set"}`);
49
+ }
50
+ });
51
+ configCommand
52
+ .command("list")
53
+ .description("List all configuration")
54
+ .action(() => {
55
+ const all = config.store;
56
+ console.log(chalk.blue.bold(`\n--- ${PROJECT_NAME} Configuration ---`));
57
+ if (all.ai) {
58
+ console.log(`${chalk.yellow("AI Provider:")} ${all.ai.provider || "not set"}`);
59
+ if (all.ai.anthropicKey)
60
+ console.log(`${chalk.yellow("Anthropic Key:")} ${maskKey(all.ai.anthropicKey)}`);
61
+ if (all.ai.openaiKey)
62
+ console.log(`${chalk.yellow("OpenAI Key:")} ${maskKey(all.ai.openaiKey)}`);
63
+ if (all.ai.geminiKey)
64
+ console.log(`${chalk.yellow("Gemini Key:")} ${maskKey(all.ai.geminiKey)}`);
65
+ }
66
+ // List other top-level keys if any
67
+ for (const [key, val] of Object.entries(all)) {
68
+ if (key !== "ai") {
69
+ console.log(`${key}: ${JSON.stringify(val)}`);
70
+ }
71
+ }
72
+ });
73
+ function maskKey(key) {
74
+ if (key.length <= 8)
75
+ return "****";
76
+ return `${key.slice(0, 7)}...${key.slice(-4)}`;
77
+ }
78
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const queryCommand: Command;
3
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCpC,eAAO,MAAM,YAAY,SA4ErB,CAAC"}
@@ -0,0 +1,78 @@
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, queryAnalysis, getAIProvider, AIProviderType } from "@git-compass/core";
5
+ import { config } from "../config/index.js";
6
+ import { DEFAULT_BRANCH, DEFAULT_MAX_COMMITS, DEFAULT_WINDOW, CONFIG_KEYS, ENV_VARS } from "../constants/index.js";
7
+ import dotenv from "dotenv";
8
+ import path from "path";
9
+ dotenv.config();
10
+ export const queryCommand = new Command("query")
11
+ .description("Ask a natural language question about the repository")
12
+ .argument("<question>", "the question to ask")
13
+ .option("-p, --path <path>", "path to git repository", process.cwd())
14
+ .option("-b, --branch <branch>", "branch to analyze", DEFAULT_BRANCH)
15
+ .option("-w, --window <window>", "time window: 7d, 30d, 90d, 1y, all", DEFAULT_WINDOW)
16
+ .option("--max-commits <n>", "max commits to analyze", DEFAULT_MAX_COMMITS.toString())
17
+ .option("--ai", "generate AI summary")
18
+ .action(async (question, options) => {
19
+ const repoPath = path.resolve(options.path);
20
+ const spinner = ora("Setting up context...").start();
21
+ try {
22
+ const git = createGitParser(repoPath);
23
+ const commits = await getCommits(git, {
24
+ branch: options.branch,
25
+ maxCount: parseInt(options.maxCommits, 10),
26
+ since: options.window !== "all" ? options.window : undefined
27
+ });
28
+ if (commits.length === 0) {
29
+ spinner.fail(chalk.red("No commits found to build context."));
30
+ return;
31
+ }
32
+ spinner.text = "Analyzing repository state...";
33
+ const result = {
34
+ meta: { repoPath, branch: options.branch, commitCount: commits.length },
35
+ hotspots: analyzeHotspots(commits),
36
+ riskScores: computeRiskScores(analyzeHotspots(commits)),
37
+ churn: analyzeChurn(commits),
38
+ contributors: analyzeContributors(commits),
39
+ burnout: analyzeBurnout(commits),
40
+ coupling: analyzeCoupling(commits),
41
+ knowledge: analyzeKnowledge(commits),
42
+ impact: analyzeImpact(commits),
43
+ rot: analyzeRot(commits)
44
+ };
45
+ spinner.text = "Consulting AI...";
46
+ // Determine provider
47
+ const envProvider = process.env[ENV_VARS.AI_PROVIDER];
48
+ const configProvider = config.get(CONFIG_KEYS.AI_PROVIDER);
49
+ const providerType = envProvider || configProvider || AIProviderType.ANTHROPIC;
50
+ // Determine API key based on provider
51
+ let apiKey;
52
+ switch (providerType) {
53
+ case AIProviderType.OPENAI:
54
+ apiKey = process.env[ENV_VARS.OPENAI_API_KEY] || config.get("ai.openaiKey");
55
+ break;
56
+ case AIProviderType.GEMINI:
57
+ apiKey = process.env[ENV_VARS.GEMINI_API_KEY] || config.get("ai.geminiKey");
58
+ break;
59
+ case AIProviderType.ANTHROPIC:
60
+ default:
61
+ apiKey = process.env[ENV_VARS.ANTHROPIC_API_KEY] || config.get("ai.anthropicKey") || config.get(CONFIG_KEYS.AI_KEY);
62
+ break;
63
+ }
64
+ if (!apiKey) {
65
+ spinner.fail(chalk.red(`No API key found for ${providerType}. Use 'Git Compass config set' to configure.`));
66
+ return;
67
+ }
68
+ const aiClient = getAIProvider(providerType, apiKey);
69
+ const answer = await queryAnalysis(aiClient, question, result);
70
+ spinner.succeed(chalk.green("AI Query Complete."));
71
+ console.log(`\n${chalk.magenta.bold("Git Compass AI:")} ${answer}\n`);
72
+ }
73
+ catch (err) {
74
+ spinner.fail(chalk.red("Query failed: " + err.message));
75
+ console.error(err);
76
+ }
77
+ });
78
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const watchCommand: Command;
3
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,YAAY,SAkCrB,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { Command } from "commander";
2
+ import chokidar from "chokidar";
3
+ import path from "path";
4
+ import chalk from "chalk";
5
+ import { execSync } from "child_process";
6
+ import { DEFAULT_BRANCH, PROJECT_NAME } from "../constants/index.js";
7
+ export const watchCommand = new Command("watch")
8
+ .description(`Watch for repository changes and re-run analysis`)
9
+ .option("-p, --path <path>", "path to git repository", process.cwd())
10
+ .option("-b, --branch <branch>", "branch to analyze", DEFAULT_BRANCH)
11
+ .option("-w, --window <window>", "time window: 7d, 30d, 90d, 1y, all", "30d")
12
+ .option("--max-commits <n>", "max commits to analyze", "500")
13
+ .option("--ai", "generate AI summary")
14
+ .action((options) => {
15
+ const repoPath = path.resolve(options.path);
16
+ const gitDir = path.join(repoPath, ".git");
17
+ console.log(chalk.cyan.bold(`\n${PROJECT_NAME} is watching ${repoPath}...`));
18
+ console.log(chalk.gray("Analysis will re-run on every commit.\n"));
19
+ // Initial run
20
+ runAnalysis(options);
21
+ const watcher = chokidar.watch([
22
+ path.join(gitDir, "refs", "heads"),
23
+ path.join(gitDir, "index")
24
+ ], {
25
+ persistent: true,
26
+ ignoreInitial: true
27
+ });
28
+ watcher.on("change", (filePath) => {
29
+ console.log(chalk.yellow(`\nChange detected in ${path.basename(filePath)}. Re-analyzing...`));
30
+ runAnalysis(options);
31
+ });
32
+ process.on("SIGINT", () => {
33
+ watcher.close();
34
+ process.exit(0);
35
+ });
36
+ });
37
+ function runAnalysis(options) {
38
+ try {
39
+ const binPath = path.join(process.cwd(), "dist/bin/git-compass.js");
40
+ let cmd = `node ${binPath} analyze -p "${options.path}" -b "${options.branch}" -w "${options.window}" --max-commits ${options.maxCommits}`;
41
+ if (options.ai)
42
+ cmd += " --ai";
43
+ execSync(cmd, { stdio: "inherit" });
44
+ }
45
+ catch (err) {
46
+ console.error(chalk.red("Watch analysis failed. check your git state."));
47
+ }
48
+ }
49
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../../src/config/__tests__/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import { describe, it, expect, beforeEach, vi, afterEach } from "vitest";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { config } from "../index.js";
5
+ // Mock fs to avoid writing to actual .env
6
+ vi.mock("fs");
7
+ describe("EnvConfig", () => {
8
+ const mockEnvPath = path.resolve(process.cwd(), ".env");
9
+ beforeEach(() => {
10
+ vi.resetAllMocks();
11
+ });
12
+ afterEach(() => {
13
+ vi.restoreAllMocks();
14
+ });
15
+ it("should return undefined if key does not exist and .env is missing", () => {
16
+ vi.mocked(fs.existsSync).mockReturnValue(false);
17
+ expect(config.get("non-existent")).toBeUndefined();
18
+ });
19
+ it("should get value from process.env if .env is missing", () => {
20
+ vi.mocked(fs.existsSync).mockReturnValue(false);
21
+ process.env.TEST_KEY = "test-value";
22
+ expect(config.get("TEST_KEY")).toBe("test-value");
23
+ delete process.env.TEST_KEY;
24
+ });
25
+ it("should set value in .env file", () => {
26
+ vi.mocked(fs.existsSync).mockReturnValue(true);
27
+ vi.mocked(fs.readFileSync).mockReturnValue("");
28
+ config.set("ai.provider", "openai");
29
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining(".env"), expect.stringContaining("GIT_COMPASS_AI_PROVIDER=openai"), "utf-8");
30
+ });
31
+ it("should update existing value in .env file", () => {
32
+ vi.mocked(fs.existsSync).mockReturnValue(true);
33
+ vi.mocked(fs.readFileSync).mockReturnValue("GIT_COMPASS_AI_PROVIDER=anthropic\nOTHER_KEY=val");
34
+ config.set("ai.provider", "gemini");
35
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining(".env"), expect.stringContaining("GIT_COMPASS_AI_PROVIDER=gemini\nOTHER_KEY=val"), "utf-8");
36
+ });
37
+ it("should retrieve masked store accurately", () => {
38
+ vi.mocked(fs.existsSync).mockReturnValue(true);
39
+ vi.mocked(fs.readFileSync).mockReturnValue("GIT_COMPASS_AI_PROVIDER=openai\nOPENAI_API_KEY=sk-12345");
40
+ const store = config.store;
41
+ expect(store.ai.provider).toBe("openai");
42
+ expect(store.ai.openaiKey).toBe("sk-12345");
43
+ });
44
+ });
45
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../../src/config/__tests__/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ declare class EnvConfig {
2
+ private envPath;
3
+ constructor();
4
+ get(key: string): string | undefined;
5
+ set(key: string, value: string): void;
6
+ get store(): Record<string, any>;
7
+ }
8
+ export declare const config: EnvConfig;
9
+ export {};
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAyBA,cAAM,SAAS;IACb,OAAO,CAAC,OAAO,CAAS;;IAOxB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAWpC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IA6BrC,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAmB/B;CACF;AAED,eAAO,MAAM,MAAM,WAAkB,CAAC"}
@@ -0,0 +1,82 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import dotenv from "dotenv";
4
+ const CONFIG_MAP = {
5
+ "ai.provider": "GIT_COMPASS_AI_PROVIDER",
6
+ "ai.key": "GIT_COMPASS_AI_KEY",
7
+ "ai.anthropicKey": "ANTHROPIC_API_KEY",
8
+ "ai.openaiKey": "OPENAI_API_KEY",
9
+ "ai.geminiKey": "GEMINI_API_KEY"
10
+ };
11
+ function findGitRoot(startDir) {
12
+ let current = path.resolve(startDir);
13
+ const root = path.parse(current).root;
14
+ while (current !== root) {
15
+ if (fs.existsSync(path.join(current, ".git"))) {
16
+ return current;
17
+ }
18
+ current = path.dirname(current);
19
+ }
20
+ return startDir;
21
+ }
22
+ class EnvConfig {
23
+ envPath;
24
+ constructor() {
25
+ const root = findGitRoot(process.cwd());
26
+ this.envPath = path.resolve(root, ".env");
27
+ }
28
+ get(key) {
29
+ // Reload env to get latest values
30
+ if (fs.existsSync(this.envPath)) {
31
+ const envContent = fs.readFileSync(this.envPath);
32
+ const envConfig = dotenv.parse(envContent);
33
+ const envKey = CONFIG_MAP[key] || key;
34
+ return envConfig[envKey];
35
+ }
36
+ return process.env[CONFIG_MAP[key] || key];
37
+ }
38
+ set(key, value) {
39
+ const envKey = CONFIG_MAP[key] || key;
40
+ let content = "";
41
+ if (fs.existsSync(this.envPath)) {
42
+ content = fs.readFileSync(this.envPath, "utf-8");
43
+ }
44
+ const lines = content.split("\n");
45
+ let found = false;
46
+ const newLines = lines.map(line => {
47
+ if (line.trim().startsWith(`${envKey}=`)) {
48
+ found = true;
49
+ return `${envKey}=${value}`;
50
+ }
51
+ return line;
52
+ });
53
+ if (!found) {
54
+ newLines.push(`${envKey}=${value}`);
55
+ }
56
+ fs.writeFileSync(this.envPath, newLines.join("\n").trim() + "\n", "utf-8");
57
+ // Update process.env for current session
58
+ process.env[envKey] = value;
59
+ }
60
+ get store() {
61
+ if (fs.existsSync(this.envPath)) {
62
+ const data = dotenv.parse(fs.readFileSync(this.envPath, "utf-8"));
63
+ const result = { ai: {} };
64
+ // Map back to schema for compatibility
65
+ for (const [configKey, envKey] of Object.entries(CONFIG_MAP)) {
66
+ if (data[envKey]) {
67
+ const parts = configKey.split(".");
68
+ if (parts.length === 2 && parts[0] === "ai") {
69
+ result.ai[parts[1]] = data[envKey];
70
+ }
71
+ else {
72
+ result[configKey] = data[envKey];
73
+ }
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ return { ai: {} };
79
+ }
80
+ }
81
+ export const config = new EnvConfig();
82
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export declare const PROJECT_NAME = "Git Compass";
2
+ export declare const DEFAULT_BRANCH = "HEAD";
3
+ export declare const DEFAULT_WINDOW = "30d";
4
+ export declare const DEFAULT_MAX_COMMITS = 500;
5
+ export declare const CONFIG_KEYS: {
6
+ readonly AI_KEY: "ai.key";
7
+ readonly AI_PROVIDER: "ai.provider";
8
+ };
9
+ export declare const ENV_VARS: {
10
+ readonly ANTHROPIC_API_KEY: "ANTHROPIC_API_KEY";
11
+ readonly OPENAI_API_KEY: "OPENAI_API_KEY";
12
+ readonly GEMINI_API_KEY: "GEMINI_API_KEY";
13
+ readonly AI_PROVIDER: "GIT_COMPASS_AI_PROVIDER";
14
+ };
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,gBAAgB,CAAC;AAE1C,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,eAAO,MAAM,cAAc,QAAQ,CAAC;AACpC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX,eAAO,MAAM,QAAQ;;;;;CAKX,CAAC"}
@@ -0,0 +1,15 @@
1
+ export const PROJECT_NAME = "Git Compass";
2
+ export const DEFAULT_BRANCH = "HEAD";
3
+ export const DEFAULT_WINDOW = "30d";
4
+ export const DEFAULT_MAX_COMMITS = 500;
5
+ export const CONFIG_KEYS = {
6
+ AI_KEY: "ai.key",
7
+ AI_PROVIDER: "ai.provider"
8
+ };
9
+ export const ENV_VARS = {
10
+ ANTHROPIC_API_KEY: "ANTHROPIC_API_KEY",
11
+ OPENAI_API_KEY: "OPENAI_API_KEY",
12
+ GEMINI_API_KEY: "GEMINI_API_KEY",
13
+ AI_PROVIDER: "GIT_COMPASS_AI_PROVIDER"
14
+ };
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;AAE1C,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AACpC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,aAAa;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,iBAAiB,EAAE,mBAAmB;IACtC,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAChC,WAAW,EAAE,yBAAyB;CAC9B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=console.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.test.d.ts","sourceRoot":"","sources":["../../../src/formatters/__tests__/console.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { printConsoleReport } from "../console.js";
3
+ describe("Console Formatter", () => {
4
+ const mockResult = {
5
+ meta: {
6
+ repoPath: "/test/repo",
7
+ branch: "master",
8
+ window: "30d",
9
+ commitCount: 10,
10
+ generatedAt: new Date()
11
+ },
12
+ hotspots: [],
13
+ riskScores: [],
14
+ churn: [],
15
+ contributors: [],
16
+ burnout: [],
17
+ coupling: [],
18
+ knowledge: [],
19
+ impact: [],
20
+ rot: []
21
+ };
22
+ it("should output basic report structure", () => {
23
+ const logSpy = vi.spyOn(console, "log").mockImplementation(() => { });
24
+ printConsoleReport(mockResult, "summary", false);
25
+ expect(logSpy).toHaveBeenCalled();
26
+ const calls = logSpy.mock.calls.map(call => call[0]);
27
+ // console.log("DEBUG CALLS:", JSON.stringify(calls)); // Temporarily uncomment if needed
28
+ expect(calls.some(c => c && c.toLowerCase().includes("analysis"))).toBe(true);
29
+ logSpy.mockRestore();
30
+ });
31
+ it("should indicate AI summary presence", () => {
32
+ const logSpy = vi.spyOn(console, "log").mockImplementation(() => { });
33
+ const aiResult = { ...mockResult, aiSummary: { digest: "AI summary here", provider: "test", model: "test" } };
34
+ printConsoleReport(aiResult, "normal", true);
35
+ const calls = logSpy.mock.calls.map(call => call[0]);
36
+ expect(calls.some(c => c && c.toLowerCase().includes("ai"))).toBe(true);
37
+ logSpy.mockRestore();
38
+ });
39
+ });
40
+ //# sourceMappingURL=console.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.test.js","sourceRoot":"","sources":["../../../src/formatters/__tests__/console.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGnD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,MAAM,UAAU,GAAG;QACjB,IAAI,EAAE;YACJ,QAAQ,EAAE,YAAY;YACtB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,EAAE;YACf,WAAW,EAAE,IAAI,IAAI,EAAE;SACxB;QACD,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE;QACd,KAAK,EAAE,EAAE;QACT,YAAY,EAAE,EAAE;QAChB,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,EAAE;QACb,MAAM,EAAE,EAAE;QACV,GAAG,EAAE,EAAE;KACR,CAAC;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAErE,kBAAkB,CAAC,UAAiB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAExD,MAAM,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,yFAAyF;QAEzF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE9E,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACrE,MAAM,QAAQ,GAAG,EAAE,GAAG,UAAU,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;QAE9G,kBAAkB,CAAC,QAAe,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAEpD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAExE,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AnalysisResult } from "@git-compass/core";
2
+ export declare function printConsoleReport(result: AnalysisResult, detailLevel?: string, showAI?: boolean): void;
3
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/formatters/console.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,GAAE,MAAiB,EAAE,MAAM,GAAE,OAAe,QA4IjH"}