agent-gauntlet 0.1.10 → 0.1.11

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 (48) hide show
  1. package/README.md +1 -1
  2. package/package.json +4 -2
  3. package/src/cli-adapters/claude.ts +139 -108
  4. package/src/cli-adapters/codex.ts +141 -117
  5. package/src/cli-adapters/cursor.ts +152 -0
  6. package/src/cli-adapters/gemini.ts +171 -139
  7. package/src/cli-adapters/github-copilot.ts +153 -0
  8. package/src/cli-adapters/index.ts +77 -48
  9. package/src/commands/check.test.ts +24 -20
  10. package/src/commands/check.ts +65 -59
  11. package/src/commands/detect.test.ts +38 -32
  12. package/src/commands/detect.ts +74 -61
  13. package/src/commands/health.test.ts +67 -53
  14. package/src/commands/health.ts +167 -145
  15. package/src/commands/help.test.ts +37 -37
  16. package/src/commands/help.ts +30 -22
  17. package/src/commands/index.ts +9 -9
  18. package/src/commands/init.test.ts +118 -107
  19. package/src/commands/init.ts +514 -417
  20. package/src/commands/list.test.ts +87 -70
  21. package/src/commands/list.ts +28 -24
  22. package/src/commands/rerun.ts +142 -119
  23. package/src/commands/review.test.ts +26 -20
  24. package/src/commands/review.ts +65 -59
  25. package/src/commands/run.test.ts +22 -20
  26. package/src/commands/run.ts +64 -58
  27. package/src/commands/shared.ts +44 -35
  28. package/src/config/loader.test.ts +112 -90
  29. package/src/config/loader.ts +132 -123
  30. package/src/config/schema.ts +49 -47
  31. package/src/config/types.ts +15 -13
  32. package/src/config/validator.ts +521 -454
  33. package/src/core/change-detector.ts +122 -104
  34. package/src/core/entry-point.test.ts +60 -62
  35. package/src/core/entry-point.ts +76 -67
  36. package/src/core/job.ts +69 -59
  37. package/src/core/runner.ts +261 -230
  38. package/src/gates/check.ts +78 -69
  39. package/src/gates/result.ts +7 -7
  40. package/src/gates/review.test.ts +174 -138
  41. package/src/gates/review.ts +716 -561
  42. package/src/index.ts +16 -15
  43. package/src/output/console.ts +253 -214
  44. package/src/output/logger.ts +64 -52
  45. package/src/templates/run_gauntlet.template.md +18 -0
  46. package/src/utils/diff-parser.ts +64 -62
  47. package/src/utils/log-parser.ts +227 -206
  48. package/src/utils/sanitizer.ts +1 -1
@@ -1,117 +1,128 @@
1
- import { describe, it, expect, beforeEach, afterEach, beforeAll, afterAll, mock } from 'bun:test';
2
- import { Command } from 'commander';
3
- import fs from 'node:fs/promises';
4
- import path from 'node:path';
1
+ import {
2
+ afterAll,
3
+ afterEach,
4
+ beforeAll,
5
+ beforeEach,
6
+ describe,
7
+ expect,
8
+ it,
9
+ mock,
10
+ } from "bun:test";
11
+ import fs from "node:fs/promises";
12
+ import path from "node:path";
13
+ import { Command } from "commander";
5
14
 
6
- const TEST_DIR = path.join(process.cwd(), 'test-init-' + Date.now());
15
+ const TEST_DIR = path.join(process.cwd(), `test-init-${Date.now()}`);
7
16
 
8
17
  // Mock adapters
9
18
  const mockAdapters = [
10
- {
11
- name: 'mock-cli-1',
12
- isAvailable: async () => true,
13
- getProjectCommandDir: () => '.mock1',
14
- getUserCommandDir: () => null,
15
- getCommandExtension: () => '.sh',
16
- canUseSymlink: () => false,
17
- transformCommand: (content: string) => content,
18
- },
19
- {
20
- name: 'mock-cli-2',
21
- isAvailable: async () => false, // Not available
22
- getProjectCommandDir: () => '.mock2',
23
- getUserCommandDir: () => null,
24
- getCommandExtension: () => '.sh',
25
- canUseSymlink: () => false,
26
- transformCommand: (content: string) => content,
27
- }
19
+ {
20
+ name: "mock-cli-1",
21
+ isAvailable: async () => true,
22
+ getProjectCommandDir: () => ".mock1",
23
+ getUserCommandDir: () => null,
24
+ getCommandExtension: () => ".sh",
25
+ canUseSymlink: () => false,
26
+ transformCommand: (content: string) => content,
27
+ },
28
+ {
29
+ name: "mock-cli-2",
30
+ isAvailable: async () => false, // Not available
31
+ getProjectCommandDir: () => ".mock2",
32
+ getUserCommandDir: () => null,
33
+ getCommandExtension: () => ".sh",
34
+ canUseSymlink: () => false,
35
+ transformCommand: (content: string) => content,
36
+ },
28
37
  ];
29
38
 
30
- mock.module('../cli-adapters/index.js', () => ({
31
- getAllAdapters: () => mockAdapters,
32
- getProjectCommandAdapters: () => mockAdapters,
33
- getUserCommandAdapters: () => [],
39
+ mock.module("../cli-adapters/index.js", () => ({
40
+ getAllAdapters: () => mockAdapters,
41
+ getProjectCommandAdapters: () => mockAdapters,
42
+ getUserCommandAdapters: () => [],
34
43
  }));
35
44
 
36
45
  // Import after mocking
37
- const { registerInitCommand } = await import('./init.js');
38
-
39
- describe('Init Command', () => {
40
- let program: Command;
41
- const originalConsoleLog = console.log;
42
- const originalCwd = process.cwd();
43
- let logs: string[];
44
-
45
- beforeAll(async () => {
46
- await fs.mkdir(TEST_DIR, { recursive: true });
47
- });
48
-
49
- afterAll(async () => {
50
- await fs.rm(TEST_DIR, { recursive: true, force: true });
51
- });
52
-
53
- beforeEach(() => {
54
- program = new Command();
55
- registerInitCommand(program);
56
- logs = [];
57
- console.log = (...args: any[]) => {
58
- logs.push(args.join(' '));
59
- };
60
- process.chdir(TEST_DIR);
61
- });
62
-
63
- afterEach(() => {
64
- console.log = originalConsoleLog;
65
- process.chdir(originalCwd);
66
- // Cleanup any created .gauntlet directory
67
- return fs.rm(path.join(TEST_DIR, '.gauntlet'), { recursive: true, force: true }).catch(() => {});
68
- });
69
-
70
- it('should register the init command', () => {
71
- const initCmd = program.commands.find(cmd => cmd.name() === 'init');
72
- expect(initCmd).toBeDefined();
73
- expect(initCmd?.description()).toBe('Initialize .gauntlet configuration');
74
- expect(initCmd?.options.some(opt => opt.long === '--yes')).toBe(true);
75
- });
76
-
77
- it('should create .gauntlet directory structure with --yes flag', async () => {
78
- // We expect it to use the available mock-cli-1
79
- await program.parseAsync(['node', 'test', 'init', '--yes']);
80
-
81
- // Check that files were created
82
- const gauntletDir = path.join(TEST_DIR, '.gauntlet');
83
- const configFile = path.join(gauntletDir, 'config.yml');
84
- const reviewsDir = path.join(gauntletDir, 'reviews');
85
- const checksDir = path.join(gauntletDir, 'checks');
86
- const runGauntletFile = path.join(gauntletDir, 'run_gauntlet.md');
87
-
88
- expect(await fs.stat(gauntletDir)).toBeDefined();
89
- expect(await fs.stat(configFile)).toBeDefined();
90
- expect(await fs.stat(reviewsDir)).toBeDefined();
91
- expect(await fs.stat(checksDir)).toBeDefined();
92
- expect(await fs.stat(runGauntletFile)).toBeDefined();
93
-
94
- // Verify config content
95
- const configContent = await fs.readFile(configFile, 'utf-8');
96
- expect(configContent).toContain('base_branch');
97
- expect(configContent).toContain('log_dir');
98
- expect(configContent).toContain('mock-cli-1'); // Should be present
99
- expect(configContent).not.toContain('mock-cli-2'); // Should not be present (unavailable)
100
-
101
- // Verify review file content
102
- const reviewFile = path.join(reviewsDir, 'code-quality.md');
103
- const reviewContent = await fs.readFile(reviewFile, 'utf-8');
104
- expect(reviewContent).toContain('mock-cli-1');
105
- });
106
-
107
- it('should not create directory if .gauntlet already exists', async () => {
108
- // Create .gauntlet directory first
109
- const gauntletDir = path.join(TEST_DIR, '.gauntlet');
110
- await fs.mkdir(gauntletDir, { recursive: true });
111
-
112
- await program.parseAsync(['node', 'test', 'init', '--yes']);
113
-
114
- const output = logs.join('\n');
115
- expect(output).toContain('.gauntlet directory already exists');
116
- });
46
+ const { registerInitCommand } = await import("./init.js");
47
+
48
+ describe("Init Command", () => {
49
+ let program: Command;
50
+ const originalConsoleLog = console.log;
51
+ const originalCwd = process.cwd();
52
+ let logs: string[];
53
+
54
+ beforeAll(async () => {
55
+ await fs.mkdir(TEST_DIR, { recursive: true });
56
+ });
57
+
58
+ afterAll(async () => {
59
+ await fs.rm(TEST_DIR, { recursive: true, force: true });
60
+ });
61
+
62
+ beforeEach(() => {
63
+ program = new Command();
64
+ registerInitCommand(program);
65
+ logs = [];
66
+ console.log = (...args: unknown[]) => {
67
+ logs.push(args.join(" "));
68
+ };
69
+ process.chdir(TEST_DIR);
70
+ });
71
+
72
+ afterEach(() => {
73
+ console.log = originalConsoleLog;
74
+ process.chdir(originalCwd);
75
+ // Cleanup any created .gauntlet directory
76
+ return fs
77
+ .rm(path.join(TEST_DIR, ".gauntlet"), { recursive: true, force: true })
78
+ .catch(() => {});
79
+ });
80
+
81
+ it("should register the init command", () => {
82
+ const initCmd = program.commands.find((cmd) => cmd.name() === "init");
83
+ expect(initCmd).toBeDefined();
84
+ expect(initCmd?.description()).toBe("Initialize .gauntlet configuration");
85
+ expect(initCmd?.options.some((opt) => opt.long === "--yes")).toBe(true);
86
+ });
87
+
88
+ it("should create .gauntlet directory structure with --yes flag", async () => {
89
+ // We expect it to use the available mock-cli-1
90
+ await program.parseAsync(["node", "test", "init", "--yes"]);
91
+
92
+ // Check that files were created
93
+ const gauntletDir = path.join(TEST_DIR, ".gauntlet");
94
+ const configFile = path.join(gauntletDir, "config.yml");
95
+ const reviewsDir = path.join(gauntletDir, "reviews");
96
+ const checksDir = path.join(gauntletDir, "checks");
97
+ const runGauntletFile = path.join(gauntletDir, "run_gauntlet.md");
98
+
99
+ expect(await fs.stat(gauntletDir)).toBeDefined();
100
+ expect(await fs.stat(configFile)).toBeDefined();
101
+ expect(await fs.stat(reviewsDir)).toBeDefined();
102
+ expect(await fs.stat(checksDir)).toBeDefined();
103
+ expect(await fs.stat(runGauntletFile)).toBeDefined();
104
+
105
+ // Verify config content
106
+ const configContent = await fs.readFile(configFile, "utf-8");
107
+ expect(configContent).toContain("base_branch");
108
+ expect(configContent).toContain("log_dir");
109
+ expect(configContent).toContain("mock-cli-1"); // Should be present
110
+ expect(configContent).not.toContain("mock-cli-2"); // Should not be present (unavailable)
111
+
112
+ // Verify review file content
113
+ const reviewFile = path.join(reviewsDir, "code-quality.md");
114
+ const reviewContent = await fs.readFile(reviewFile, "utf-8");
115
+ expect(reviewContent).toContain("mock-cli-1");
116
+ });
117
+
118
+ it("should not create directory if .gauntlet already exists", async () => {
119
+ // Create .gauntlet directory first
120
+ const gauntletDir = path.join(TEST_DIR, ".gauntlet");
121
+ await fs.mkdir(gauntletDir, { recursive: true });
122
+
123
+ await program.parseAsync(["node", "test", "init", "--yes"]);
124
+
125
+ const output = logs.join("\n");
126
+ expect(output).toContain(".gauntlet directory already exists");
127
+ });
117
128
  });