agent-gauntlet 0.10.0 → 0.11.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 +25 -23
- package/dist/index.js +9226 -0
- package/dist/index.js.map +65 -0
- package/dist/scripts/status.js +280 -0
- package/dist/scripts/status.js.map +10 -0
- package/package.json +22 -8
- package/src/built-in-reviews/code-quality.md +0 -25
- package/src/built-in-reviews/index.ts +0 -28
- package/src/bun-plugins.d.ts +0 -4
- package/src/cli-adapters/claude.ts +0 -327
- package/src/cli-adapters/codex.ts +0 -290
- package/src/cli-adapters/cursor.ts +0 -128
- package/src/cli-adapters/gemini.ts +0 -510
- package/src/cli-adapters/github-copilot.ts +0 -141
- package/src/cli-adapters/index.ts +0 -250
- package/src/cli-adapters/thinking-budget.ts +0 -23
- package/src/commands/check.ts +0 -311
- package/src/commands/ci/index.ts +0 -15
- package/src/commands/ci/init.ts +0 -96
- package/src/commands/ci/list-jobs.ts +0 -90
- package/src/commands/clean.ts +0 -54
- package/src/commands/detect.ts +0 -173
- package/src/commands/health.ts +0 -169
- package/src/commands/help.ts +0 -34
- package/src/commands/index.ts +0 -13
- package/src/commands/init.ts +0 -1878
- package/src/commands/list.ts +0 -33
- package/src/commands/review.ts +0 -311
- package/src/commands/run.ts +0 -29
- package/src/commands/shared.ts +0 -267
- package/src/commands/stop-hook.ts +0 -567
- package/src/commands/validate.ts +0 -20
- package/src/commands/wait-ci.ts +0 -518
- package/src/config/ci-loader.ts +0 -33
- package/src/config/ci-schema.ts +0 -28
- package/src/config/global.ts +0 -87
- package/src/config/loader.ts +0 -301
- package/src/config/schema.ts +0 -165
- package/src/config/stop-hook-config.ts +0 -130
- package/src/config/types.ts +0 -65
- package/src/config/validator.ts +0 -592
- package/src/core/change-detector.ts +0 -137
- package/src/core/diff-stats.ts +0 -442
- package/src/core/entry-point.ts +0 -190
- package/src/core/job.ts +0 -96
- package/src/core/run-executor.ts +0 -621
- package/src/core/runner.ts +0 -290
- package/src/gates/check.ts +0 -118
- package/src/gates/resolve-check-command.ts +0 -21
- package/src/gates/result.ts +0 -54
- package/src/gates/review.ts +0 -1333
- package/src/hooks/adapters/claude-stop-hook.ts +0 -99
- package/src/hooks/adapters/cursor-stop-hook.ts +0 -122
- package/src/hooks/adapters/types.ts +0 -94
- package/src/hooks/stop-hook-handler.ts +0 -748
- package/src/index.ts +0 -47
- package/src/output/app-logger.ts +0 -214
- package/src/output/console-log.ts +0 -168
- package/src/output/console.ts +0 -359
- package/src/output/logger.ts +0 -126
- package/src/output/sinks/console-sink.ts +0 -59
- package/src/output/sinks/file-sink.ts +0 -110
- package/src/scripts/status.ts +0 -433
- package/src/templates/workflow.yml +0 -79
- package/src/types/gauntlet-status.ts +0 -79
- package/src/utils/debug-log.ts +0 -392
- package/src/utils/diff-parser.ts +0 -103
- package/src/utils/execution-state.ts +0 -472
- package/src/utils/log-parser.ts +0 -696
- package/src/utils/sanitizer.ts +0 -3
- package/src/utils/session-ref.ts +0 -91
package/src/commands/detect.ts
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import type { Command } from "commander";
|
|
3
|
-
import { loadConfig } from "../config/loader.js";
|
|
4
|
-
import { ChangeDetector } from "../core/change-detector.js";
|
|
5
|
-
import { EntryPointExpander } from "../core/entry-point.js";
|
|
6
|
-
import { type Job, JobGenerator } from "../core/job.js";
|
|
7
|
-
import {
|
|
8
|
-
readExecutionState,
|
|
9
|
-
resolveFixBase,
|
|
10
|
-
} from "../utils/execution-state.js";
|
|
11
|
-
import {
|
|
12
|
-
hasExistingLogs,
|
|
13
|
-
performAutoClean,
|
|
14
|
-
shouldAutoClean,
|
|
15
|
-
} from "./shared.js";
|
|
16
|
-
|
|
17
|
-
interface ChangeOptions {
|
|
18
|
-
commit?: string;
|
|
19
|
-
uncommitted?: boolean;
|
|
20
|
-
fixBase?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function autoCleanIfNeeded(
|
|
24
|
-
logDir: string,
|
|
25
|
-
baseBranch: string,
|
|
26
|
-
): Promise<void> {
|
|
27
|
-
const result = await shouldAutoClean(logDir, baseBranch);
|
|
28
|
-
if (result.clean) {
|
|
29
|
-
await performAutoClean(logDir, result);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function resolveFreshFixBase(
|
|
34
|
-
logDir: string,
|
|
35
|
-
baseBranch: string,
|
|
36
|
-
): Promise<string | undefined> {
|
|
37
|
-
const state = await readExecutionState(logDir);
|
|
38
|
-
if (!state) return undefined;
|
|
39
|
-
return (await resolveFixBase(state, baseBranch)).fixBase ?? undefined;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Resolve change detection options using the same logic as run-executor.
|
|
44
|
-
* Handles rerun mode (existing logs → uncommitted-only diff) and fixBase resolution.
|
|
45
|
-
*/
|
|
46
|
-
async function resolveChangeOptions(
|
|
47
|
-
logDir: string,
|
|
48
|
-
baseBranch: string,
|
|
49
|
-
cliOptions: { commit?: string; uncommitted?: boolean },
|
|
50
|
-
): Promise<ChangeOptions> {
|
|
51
|
-
await autoCleanIfNeeded(logDir, baseBranch);
|
|
52
|
-
|
|
53
|
-
const logsExist = await hasExistingLogs(logDir);
|
|
54
|
-
const isRerun = logsExist && !cliOptions.commit;
|
|
55
|
-
|
|
56
|
-
const opts: ChangeOptions = {};
|
|
57
|
-
if (isRerun) {
|
|
58
|
-
const state = await readExecutionState(logDir);
|
|
59
|
-
opts.uncommitted = true;
|
|
60
|
-
opts.fixBase = state?.working_tree_ref;
|
|
61
|
-
} else if (!logsExist) {
|
|
62
|
-
const fixBase = await resolveFreshFixBase(logDir, baseBranch);
|
|
63
|
-
if (fixBase) opts.fixBase = fixBase;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (cliOptions.commit || cliOptions.uncommitted) {
|
|
67
|
-
return {
|
|
68
|
-
commit: cliOptions.commit,
|
|
69
|
-
uncommitted: cliOptions.uncommitted,
|
|
70
|
-
fixBase: opts.fixBase,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
return opts;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function registerDetectCommand(program: Command): void {
|
|
77
|
-
program
|
|
78
|
-
.command("detect")
|
|
79
|
-
.description(
|
|
80
|
-
"Show what gates would run for detected changes (without executing them)",
|
|
81
|
-
)
|
|
82
|
-
.option(
|
|
83
|
-
"-b, --base-branch <branch>",
|
|
84
|
-
"Override base branch for change detection",
|
|
85
|
-
)
|
|
86
|
-
.option("-c, --commit <sha>", "Use diff for a specific commit")
|
|
87
|
-
.option(
|
|
88
|
-
"-u, --uncommitted",
|
|
89
|
-
"Use diff for current uncommitted changes (staged and unstaged)",
|
|
90
|
-
)
|
|
91
|
-
.action(async (options) => {
|
|
92
|
-
try {
|
|
93
|
-
const config = await loadConfig();
|
|
94
|
-
|
|
95
|
-
// Priority: CLI override > CI env var > config
|
|
96
|
-
const effectiveBaseBranch =
|
|
97
|
-
options.baseBranch ||
|
|
98
|
-
(process.env.GITHUB_BASE_REF &&
|
|
99
|
-
(process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true")
|
|
100
|
-
? process.env.GITHUB_BASE_REF
|
|
101
|
-
: null) ||
|
|
102
|
-
config.project.base_branch;
|
|
103
|
-
|
|
104
|
-
const changeOptions = await resolveChangeOptions(
|
|
105
|
-
config.project.log_dir,
|
|
106
|
-
effectiveBaseBranch,
|
|
107
|
-
{ commit: options.commit, uncommitted: options.uncommitted },
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
const changeDetector = new ChangeDetector(
|
|
111
|
-
effectiveBaseBranch,
|
|
112
|
-
changeOptions,
|
|
113
|
-
);
|
|
114
|
-
const expander = new EntryPointExpander();
|
|
115
|
-
const jobGen = new JobGenerator(config);
|
|
116
|
-
|
|
117
|
-
console.log(chalk.dim("Detecting changes..."));
|
|
118
|
-
const changes = await changeDetector.getChangedFiles();
|
|
119
|
-
|
|
120
|
-
if (changes.length === 0) {
|
|
121
|
-
console.log(chalk.green("No changes detected."));
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
console.log(chalk.dim(`Found ${changes.length} changed files:`));
|
|
126
|
-
for (const file of changes) {
|
|
127
|
-
console.log(chalk.dim(` - ${file}`));
|
|
128
|
-
}
|
|
129
|
-
console.log();
|
|
130
|
-
|
|
131
|
-
const entryPoints = await expander.expand(
|
|
132
|
-
config.project.entry_points,
|
|
133
|
-
changes,
|
|
134
|
-
);
|
|
135
|
-
const jobs = jobGen.generateJobs(entryPoints);
|
|
136
|
-
|
|
137
|
-
if (jobs.length === 0) {
|
|
138
|
-
console.log(chalk.yellow("No applicable gates for these changes."));
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
console.log(chalk.bold(`Would run ${jobs.length} gate(s):\n`));
|
|
143
|
-
printJobsByWorkDir(jobs);
|
|
144
|
-
} catch (error: unknown) {
|
|
145
|
-
const err = error as { message?: string };
|
|
146
|
-
console.error(chalk.red("Error:"), err.message);
|
|
147
|
-
process.exit(1);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function groupByWorkDir(jobs: Job[]): Map<string, Job[]> {
|
|
153
|
-
const map = new Map<string, Job[]>();
|
|
154
|
-
for (const job of jobs) {
|
|
155
|
-
if (!map.has(job.workingDirectory)) {
|
|
156
|
-
map.set(job.workingDirectory, []);
|
|
157
|
-
}
|
|
158
|
-
map.get(job.workingDirectory)?.push(job);
|
|
159
|
-
}
|
|
160
|
-
return map;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function printJobsByWorkDir(jobs: Job[]): void {
|
|
164
|
-
for (const [workDir, wdJobs] of groupByWorkDir(jobs).entries()) {
|
|
165
|
-
console.log(chalk.cyan(`Working directory: ${workDir}`));
|
|
166
|
-
for (const job of wdJobs) {
|
|
167
|
-
const typeLabel =
|
|
168
|
-
job.type === "check" ? chalk.yellow("check") : chalk.blue("review");
|
|
169
|
-
console.log(` ${typeLabel} ${chalk.bold(job.name)}`);
|
|
170
|
-
}
|
|
171
|
-
console.log();
|
|
172
|
-
}
|
|
173
|
-
}
|
package/src/commands/health.ts
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import type { Command } from "commander";
|
|
4
|
-
import { getAdapter, getAllAdapters } from "../cli-adapters/index.js";
|
|
5
|
-
import { loadConfig } from "../config/loader.js";
|
|
6
|
-
import { validateConfig } from "../config/validator.js";
|
|
7
|
-
|
|
8
|
-
export function registerHealthCommand(program: Command): void {
|
|
9
|
-
program
|
|
10
|
-
.command("health")
|
|
11
|
-
.description("Check CLI tool availability")
|
|
12
|
-
.action(async () => {
|
|
13
|
-
// 1. Config validation
|
|
14
|
-
console.log(chalk.bold("Config validation:"));
|
|
15
|
-
const validationResult = await validateConfig();
|
|
16
|
-
|
|
17
|
-
if (validationResult.filesChecked.length === 0) {
|
|
18
|
-
console.log(chalk.yellow(" No config files found"));
|
|
19
|
-
} else {
|
|
20
|
-
// List all files checked
|
|
21
|
-
for (const file of validationResult.filesChecked) {
|
|
22
|
-
const relativePath = path.relative(process.cwd(), file);
|
|
23
|
-
console.log(chalk.dim(` ${relativePath}`));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Show validation results
|
|
27
|
-
if (validationResult.valid && validationResult.issues.length === 0) {
|
|
28
|
-
console.log(chalk.green(" ✓ All config files are valid"));
|
|
29
|
-
} else {
|
|
30
|
-
// Group issues by file
|
|
31
|
-
const issuesByFile = new Map<
|
|
32
|
-
string,
|
|
33
|
-
typeof validationResult.issues
|
|
34
|
-
>();
|
|
35
|
-
for (const issue of validationResult.issues) {
|
|
36
|
-
const relativeFile = path.relative(process.cwd(), issue.file);
|
|
37
|
-
if (!issuesByFile.has(relativeFile)) {
|
|
38
|
-
issuesByFile.set(relativeFile, []);
|
|
39
|
-
}
|
|
40
|
-
issuesByFile.get(relativeFile)?.push(issue);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Display issues
|
|
44
|
-
for (const [file, issues] of issuesByFile.entries()) {
|
|
45
|
-
for (const issue of issues) {
|
|
46
|
-
const icon =
|
|
47
|
-
issue.severity === "error" ? chalk.red("✗") : chalk.yellow("⚠");
|
|
48
|
-
const fieldInfo = issue.field
|
|
49
|
-
? chalk.dim(` (${issue.field})`)
|
|
50
|
-
: "";
|
|
51
|
-
console.log(` ${icon} ${file}${fieldInfo}`);
|
|
52
|
-
console.log(` ${issue.message}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
console.log();
|
|
59
|
-
|
|
60
|
-
// 2. CLI Tool Health Check
|
|
61
|
-
console.log(chalk.bold("CLI Tool Health Check:"));
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
const config = await loadConfig();
|
|
65
|
-
|
|
66
|
-
// Check for reviews configuration
|
|
67
|
-
const reviewEntries = Object.entries(config.reviews);
|
|
68
|
-
|
|
69
|
-
if (reviewEntries.length === 0) {
|
|
70
|
-
console.log(chalk.yellow(" No CLI tools configured"));
|
|
71
|
-
console.log(
|
|
72
|
-
chalk.dim(
|
|
73
|
-
" No review gates found. Add review gates with cli_preference to check tool availability.",
|
|
74
|
-
),
|
|
75
|
-
);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Collect all unique agent names from review gate cli_preference settings
|
|
80
|
-
const preferredAgents = new Set<string>();
|
|
81
|
-
const reviewsWithEmptyPreference: string[] = [];
|
|
82
|
-
|
|
83
|
-
reviewEntries.forEach(([reviewName, review]) => {
|
|
84
|
-
if (!review.cli_preference || review.cli_preference.length === 0) {
|
|
85
|
-
reviewsWithEmptyPreference.push(reviewName);
|
|
86
|
-
} else {
|
|
87
|
-
review.cli_preference.forEach((agent) => {
|
|
88
|
-
preferredAgents.add(agent);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Report Empty Preferences (Loader should handle this via default merging, but good to check)
|
|
94
|
-
if (reviewsWithEmptyPreference.length > 0) {
|
|
95
|
-
console.log(chalk.yellow(" ⚠️ Misconfiguration detected:"));
|
|
96
|
-
reviewsWithEmptyPreference.forEach((name) => {
|
|
97
|
-
console.log(
|
|
98
|
-
chalk.yellow(
|
|
99
|
-
` Review gate "${name}" has empty cli_preference`,
|
|
100
|
-
),
|
|
101
|
-
);
|
|
102
|
-
});
|
|
103
|
-
console.log();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// If no agents are configured, show message
|
|
107
|
-
if (preferredAgents.size === 0) {
|
|
108
|
-
console.log(chalk.yellow(" No CLI tools configured"));
|
|
109
|
-
console.log(
|
|
110
|
-
chalk.dim(
|
|
111
|
-
" All review gates have empty cli_preference. Add tools to cli_preference to check availability.",
|
|
112
|
-
),
|
|
113
|
-
);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Check the configured agents
|
|
118
|
-
for (const agentName of Array.from(preferredAgents).sort()) {
|
|
119
|
-
const adapter = getAdapter(agentName);
|
|
120
|
-
if (adapter) {
|
|
121
|
-
const health = await adapter.checkHealth();
|
|
122
|
-
let statusStr = "";
|
|
123
|
-
|
|
124
|
-
switch (health.status) {
|
|
125
|
-
case "healthy":
|
|
126
|
-
statusStr = chalk.green("Installed");
|
|
127
|
-
break;
|
|
128
|
-
case "missing":
|
|
129
|
-
statusStr = chalk.red("Missing");
|
|
130
|
-
break;
|
|
131
|
-
case "unhealthy":
|
|
132
|
-
statusStr = chalk.red(`${health.message || "Unhealthy"}`);
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
console.log(` ${adapter.name.padEnd(10)} : ${statusStr}`);
|
|
137
|
-
} else {
|
|
138
|
-
console.log(
|
|
139
|
-
` ${agentName.padEnd(10)} : ${chalk.yellow("Unknown")}`,
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
} catch (_error: unknown) {
|
|
144
|
-
// If config can't be loaded, fall back to checking all adapters
|
|
145
|
-
const adapters = getAllAdapters();
|
|
146
|
-
console.log(
|
|
147
|
-
chalk.dim(" (Config not found, checking all supported agents)"),
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
for (const adapter of adapters) {
|
|
151
|
-
const health = await adapter.checkHealth();
|
|
152
|
-
let statusStr = "";
|
|
153
|
-
|
|
154
|
-
switch (health.status) {
|
|
155
|
-
case "healthy":
|
|
156
|
-
statusStr = chalk.green("Installed");
|
|
157
|
-
break;
|
|
158
|
-
case "missing":
|
|
159
|
-
statusStr = chalk.red("Missing");
|
|
160
|
-
break;
|
|
161
|
-
case "unhealthy":
|
|
162
|
-
statusStr = chalk.red(`${health.message || "Unhealthy"}`);
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
console.log(` ${adapter.name.padEnd(10)} : ${statusStr}`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
}
|
package/src/commands/help.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import type { Command } from "commander";
|
|
3
|
-
|
|
4
|
-
export function registerHelpCommand(program: Command): void {
|
|
5
|
-
program
|
|
6
|
-
.command("help")
|
|
7
|
-
.description("Show help information")
|
|
8
|
-
.action(() => {
|
|
9
|
-
console.log(chalk.bold("Agent Gauntlet - AI-assisted quality gates\n"));
|
|
10
|
-
console.log(
|
|
11
|
-
"Agent Gauntlet runs quality gates (checks + AI reviews) for only the parts",
|
|
12
|
-
);
|
|
13
|
-
console.log(
|
|
14
|
-
"of your repo that changed, based on a configurable set of entry points.\n",
|
|
15
|
-
);
|
|
16
|
-
console.log(chalk.bold("Commands:\n"));
|
|
17
|
-
console.log(" run Run gates for detected changes");
|
|
18
|
-
console.log(" check Run only applicable checks");
|
|
19
|
-
console.log(" review Run only applicable reviews");
|
|
20
|
-
console.log(" clean Archive logs (move current logs into previous/)");
|
|
21
|
-
console.log(
|
|
22
|
-
" detect Show what gates would run (without executing them)",
|
|
23
|
-
);
|
|
24
|
-
console.log(" list List configured gates");
|
|
25
|
-
console.log(" health Check CLI tool availability");
|
|
26
|
-
console.log(" init Initialize .gauntlet configuration");
|
|
27
|
-
console.log(" ci CI integration commands (init, list-jobs)");
|
|
28
|
-
console.log(" help Show this help message\n");
|
|
29
|
-
console.log(
|
|
30
|
-
"For more information, see: https://github.com/your-repo/agent-gauntlet",
|
|
31
|
-
);
|
|
32
|
-
console.log("Or run: agent-gauntlet <command> --help");
|
|
33
|
-
});
|
|
34
|
-
}
|
package/src/commands/index.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export { registerCheckCommand } from "./check.js";
|
|
2
|
-
export { registerCICommand } from "./ci/index.js";
|
|
3
|
-
export { registerCleanCommand } from "./clean.js";
|
|
4
|
-
export { registerDetectCommand } from "./detect.js";
|
|
5
|
-
export { registerHealthCommand } from "./health.js";
|
|
6
|
-
export { registerHelpCommand } from "./help.js";
|
|
7
|
-
export { registerInitCommand } from "./init.js";
|
|
8
|
-
export { registerListCommand } from "./list.js";
|
|
9
|
-
export { registerReviewCommand } from "./review.js";
|
|
10
|
-
export { registerRunCommand } from "./run.js";
|
|
11
|
-
export { registerStopHookCommand } from "./stop-hook.js";
|
|
12
|
-
export { registerValidateCommand } from "./validate.js";
|
|
13
|
-
export { registerWaitCICommand } from "./wait-ci.js";
|