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.
Files changed (71) hide show
  1. package/README.md +25 -23
  2. package/dist/index.js +9226 -0
  3. package/dist/index.js.map +65 -0
  4. package/dist/scripts/status.js +280 -0
  5. package/dist/scripts/status.js.map +10 -0
  6. package/package.json +22 -8
  7. package/src/built-in-reviews/code-quality.md +0 -25
  8. package/src/built-in-reviews/index.ts +0 -28
  9. package/src/bun-plugins.d.ts +0 -4
  10. package/src/cli-adapters/claude.ts +0 -327
  11. package/src/cli-adapters/codex.ts +0 -290
  12. package/src/cli-adapters/cursor.ts +0 -128
  13. package/src/cli-adapters/gemini.ts +0 -510
  14. package/src/cli-adapters/github-copilot.ts +0 -141
  15. package/src/cli-adapters/index.ts +0 -250
  16. package/src/cli-adapters/thinking-budget.ts +0 -23
  17. package/src/commands/check.ts +0 -311
  18. package/src/commands/ci/index.ts +0 -15
  19. package/src/commands/ci/init.ts +0 -96
  20. package/src/commands/ci/list-jobs.ts +0 -90
  21. package/src/commands/clean.ts +0 -54
  22. package/src/commands/detect.ts +0 -173
  23. package/src/commands/health.ts +0 -169
  24. package/src/commands/help.ts +0 -34
  25. package/src/commands/index.ts +0 -13
  26. package/src/commands/init.ts +0 -1878
  27. package/src/commands/list.ts +0 -33
  28. package/src/commands/review.ts +0 -311
  29. package/src/commands/run.ts +0 -29
  30. package/src/commands/shared.ts +0 -267
  31. package/src/commands/stop-hook.ts +0 -567
  32. package/src/commands/validate.ts +0 -20
  33. package/src/commands/wait-ci.ts +0 -518
  34. package/src/config/ci-loader.ts +0 -33
  35. package/src/config/ci-schema.ts +0 -28
  36. package/src/config/global.ts +0 -87
  37. package/src/config/loader.ts +0 -301
  38. package/src/config/schema.ts +0 -165
  39. package/src/config/stop-hook-config.ts +0 -130
  40. package/src/config/types.ts +0 -65
  41. package/src/config/validator.ts +0 -592
  42. package/src/core/change-detector.ts +0 -137
  43. package/src/core/diff-stats.ts +0 -442
  44. package/src/core/entry-point.ts +0 -190
  45. package/src/core/job.ts +0 -96
  46. package/src/core/run-executor.ts +0 -621
  47. package/src/core/runner.ts +0 -290
  48. package/src/gates/check.ts +0 -118
  49. package/src/gates/resolve-check-command.ts +0 -21
  50. package/src/gates/result.ts +0 -54
  51. package/src/gates/review.ts +0 -1333
  52. package/src/hooks/adapters/claude-stop-hook.ts +0 -99
  53. package/src/hooks/adapters/cursor-stop-hook.ts +0 -122
  54. package/src/hooks/adapters/types.ts +0 -94
  55. package/src/hooks/stop-hook-handler.ts +0 -748
  56. package/src/index.ts +0 -47
  57. package/src/output/app-logger.ts +0 -214
  58. package/src/output/console-log.ts +0 -168
  59. package/src/output/console.ts +0 -359
  60. package/src/output/logger.ts +0 -126
  61. package/src/output/sinks/console-sink.ts +0 -59
  62. package/src/output/sinks/file-sink.ts +0 -110
  63. package/src/scripts/status.ts +0 -433
  64. package/src/templates/workflow.yml +0 -79
  65. package/src/types/gauntlet-status.ts +0 -79
  66. package/src/utils/debug-log.ts +0 -392
  67. package/src/utils/diff-parser.ts +0 -103
  68. package/src/utils/execution-state.ts +0 -472
  69. package/src/utils/log-parser.ts +0 -696
  70. package/src/utils/sanitizer.ts +0 -3
  71. package/src/utils/session-ref.ts +0 -91
@@ -1,99 +0,0 @@
1
- import type {
2
- StopHookAdapter,
3
- StopHookContext,
4
- StopHookResult,
5
- } from "./types.js";
6
-
7
- /**
8
- * Claude Code hook response format.
9
- */
10
- interface ClaudeHookResponse {
11
- decision: "block" | "approve";
12
- reason?: string;
13
- stopReason: string;
14
- systemMessage?: string;
15
- status: string;
16
- message: string;
17
- }
18
-
19
- /**
20
- * Adapter for Claude Code stop hook protocol.
21
- *
22
- * Claude Code protocol:
23
- * - Input: { cwd, stop_hook_active, session_id, transcript_path, hook_event_name, permission_mode }
24
- * - Output: { decision: "block"|"approve", reason?, stopReason, systemMessage?, status, message }
25
- * - Block mechanism: decision: "block" with reason (fed back to Claude as prompt)
26
- * - Allow mechanism: decision: "approve"
27
- */
28
- export class ClaudeStopHookAdapter implements StopHookAdapter {
29
- name = "claude";
30
-
31
- /**
32
- * Detect if this adapter should handle the given input.
33
- * Claude Code doesn't send cursor_version, so we detect by absence.
34
- */
35
- detect(raw: Record<string, unknown>): boolean {
36
- // Claude Code doesn't send cursor_version
37
- return !("cursor_version" in raw);
38
- }
39
-
40
- /**
41
- * Parse Claude Code input into normalized context.
42
- */
43
- parseInput(raw: Record<string, unknown>): StopHookContext {
44
- return {
45
- cwd: (raw.cwd as string) ?? process.cwd(),
46
- isNestedHook: raw.stop_hook_active === true,
47
- sessionId: raw.session_id as string | undefined,
48
- rawInput: raw,
49
- };
50
- }
51
-
52
- /**
53
- * Get the block reason for a given result based on status.
54
- */
55
- private getBlockReason(result: StopHookResult): string | undefined {
56
- const reasonMap: Record<string, string | undefined> = {
57
- failed: result.instructions,
58
- pr_push_required: result.pushPRReason,
59
- ci_failed: result.ciFixReason,
60
- ci_pending: result.ciPendingReason,
61
- };
62
- return reasonMap[result.status];
63
- }
64
-
65
- /**
66
- * Format handler result into Claude Code protocol output.
67
- */
68
- formatOutput(result: StopHookResult): string {
69
- const blockReason = this.getBlockReason(result);
70
- const stopReason =
71
- result.shouldBlock && blockReason ? blockReason : result.message;
72
-
73
- const response: ClaudeHookResponse = {
74
- decision: result.shouldBlock ? "block" : "approve",
75
- stopReason,
76
- systemMessage: result.message,
77
- status: result.status,
78
- message: result.message,
79
- };
80
-
81
- if (result.shouldBlock && blockReason) {
82
- response.reason = blockReason;
83
- }
84
-
85
- return JSON.stringify(response);
86
- }
87
-
88
- /**
89
- * Check if execution should be skipped based on Claude-specific conditions.
90
- * Note: stop_hook_active from stdin is currently disabled in the main entry point
91
- * because Claude Code sends it after blocking twice, but we need to re-run.
92
- */
93
- shouldSkipExecution(_ctx: StopHookContext): StopHookResult | null {
94
- // The isNestedHook check is handled at the entry point level
95
- // via the marker file mechanism, not here.
96
- // This method is available for future protocol-specific skip conditions.
97
- return null;
98
- }
99
- }
@@ -1,122 +0,0 @@
1
- import type {
2
- StopHookAdapter,
3
- StopHookContext,
4
- StopHookResult,
5
- } from "./types.js";
6
-
7
- /**
8
- * Cursor hook response format.
9
- * - Empty object {} = allow stop (no feedback)
10
- * - { systemMessage: "..." } = allow stop with user-visible message
11
- * - { followup_message: "..." } = block stop and continue with message
12
- */
13
- interface CursorHookResponse {
14
- followup_message?: string;
15
- systemMessage?: string;
16
- }
17
-
18
- /**
19
- * Default maximum loop count before allowing stop.
20
- * Cursor has built-in loop_limit (default 5, configurable in hooks.json),
21
- * but we provide defense-in-depth with our own check.
22
- */
23
- const DEFAULT_MAX_LOOPS = 10;
24
-
25
- /**
26
- * Adapter for Cursor IDE stop hook protocol.
27
- *
28
- * Cursor protocol:
29
- * - Input: { status, loop_count, cursor_version, workspace_roots, conversation_id, ... }
30
- * - Output: { followup_message?: "..." } or {}
31
- * - Block mechanism: { followup_message: "instructions" } - continues agent with message
32
- * - Allow mechanism: {} (empty object) - allows stop
33
- * - Loop prevention: loop_count field (Cursor has built-in loop_limit)
34
- */
35
- export class CursorStopHookAdapter implements StopHookAdapter {
36
- name = "cursor";
37
-
38
- /**
39
- * Maximum loop count before forcing stop.
40
- * Can be configured via hooks.json loop_limit.
41
- */
42
- private maxLoops: number;
43
-
44
- constructor(maxLoops: number = DEFAULT_MAX_LOOPS) {
45
- this.maxLoops = maxLoops;
46
- }
47
-
48
- /**
49
- * Detect if this adapter should handle the given input.
50
- * Cursor sends cursor_version in hook input.
51
- */
52
- detect(raw: Record<string, unknown>): boolean {
53
- return "cursor_version" in raw;
54
- }
55
-
56
- /**
57
- * Parse Cursor input into normalized context.
58
- */
59
- parseInput(raw: Record<string, unknown>): StopHookContext {
60
- const workspaceRoots = raw.workspace_roots;
61
- const loopCount = raw.loop_count as number | undefined;
62
-
63
- return {
64
- cwd:
65
- (Array.isArray(workspaceRoots) ? workspaceRoots[0] : null) ??
66
- process.cwd(),
67
- isNestedHook: false, // Cursor uses loop_count instead of nested hook flag
68
- loopCount,
69
- sessionId: raw.conversation_id as string | undefined,
70
- rawInput: raw,
71
- };
72
- }
73
-
74
- /**
75
- * Get the block message for a given result based on status.
76
- */
77
- private getBlockMessage(result: StopHookResult): string {
78
- const messageMap: Record<string, string | undefined> = {
79
- failed: result.instructions,
80
- pr_push_required: result.pushPRReason,
81
- ci_failed: result.ciFixReason,
82
- ci_pending: result.ciPendingReason,
83
- };
84
- return messageMap[result.status] || result.message;
85
- }
86
-
87
- /**
88
- * Format handler result into Cursor protocol output.
89
- */
90
- formatOutput(result: StopHookResult): string {
91
- if (result.shouldBlock) {
92
- const response: CursorHookResponse = {
93
- followup_message: this.getBlockMessage(result),
94
- };
95
- return JSON.stringify(response);
96
- }
97
-
98
- // Include systemMessage for user feedback even when not blocking
99
- const response: CursorHookResponse = {
100
- systemMessage: result.message,
101
- };
102
- return JSON.stringify(response);
103
- }
104
-
105
- /**
106
- * Check if execution should be skipped based on Cursor-specific conditions.
107
- * Returns early if loop_count exceeds threshold.
108
- */
109
- shouldSkipExecution(ctx: StopHookContext): StopHookResult | null {
110
- // Cursor has built-in loop_limit (default 5), but we can check here too
111
- // for defense-in-depth
112
- if (ctx.loopCount !== undefined && ctx.loopCount >= this.maxLoops) {
113
- return {
114
- status: "retry_limit_exceeded",
115
- shouldBlock: false,
116
- message:
117
- "Loop limit reached — run `agent-gauntlet clean` to archive and continue.",
118
- };
119
- }
120
- return null;
121
- }
122
- }
@@ -1,94 +0,0 @@
1
- import type { GauntletStatus, RunResult } from "../../types/gauntlet-status.js";
2
-
3
- /**
4
- * Protocol-agnostic context passed from adapter to handler.
5
- * Contains normalized fields from either Claude Code or Cursor input.
6
- */
7
- export interface StopHookContext {
8
- /** Working directory for the project */
9
- cwd: string;
10
- /** True if this is a nested hook invocation (Claude: stop_hook_active, Cursor: high loop_count) */
11
- isNestedHook: boolean;
12
- /** Cursor-specific: current loop iteration count */
13
- loopCount?: number;
14
- /** Session/conversation identifier for logging */
15
- sessionId?: string;
16
- /** Original parsed JSON input for diagnostics */
17
- rawInput: Record<string, unknown>;
18
- }
19
-
20
- /**
21
- * Protocol-agnostic result from handler to adapter.
22
- * Contains all information needed to format protocol-specific output.
23
- */
24
- export interface StopHookResult {
25
- /** Machine-readable status code */
26
- status: GauntletStatus;
27
- /** Whether the stop should be blocked */
28
- shouldBlock: boolean;
29
- /** Fix instructions when blocking due to failed gates */
30
- instructions?: string;
31
- /** PR push instructions when blocking due to pr_push_required */
32
- pushPRReason?: string;
33
- /** CI fix instructions when blocking due to ci_failed */
34
- ciFixReason?: string;
35
- /** CI pending instructions when blocking due to ci_pending */
36
- ciPendingReason?: string;
37
- /** Human-friendly status message */
38
- message: string;
39
- /** Interval minutes (when status is interval_not_elapsed) */
40
- intervalMinutes?: number;
41
- /** Individual gate results for detailed failure information */
42
- gateResults?: RunResult["gateResults"];
43
- }
44
-
45
- /**
46
- * Result from PR status check.
47
- */
48
- export interface PRStatusResult {
49
- /** Whether a PR exists for the current branch */
50
- prExists: boolean;
51
- /** Whether the PR is up to date with local HEAD */
52
- upToDate: boolean;
53
- /** Error message if check failed (graceful degradation) */
54
- error?: string;
55
- /** PR number if it exists */
56
- prNumber?: number;
57
- }
58
-
59
- /**
60
- * Adapter interface for protocol-specific stop hook handling.
61
- * Each adapter handles input parsing, output formatting, and protocol-specific behavior.
62
- */
63
- export interface StopHookAdapter {
64
- /** Human-readable name for logging */
65
- name: string;
66
-
67
- /**
68
- * Detect if this adapter should handle the given input.
69
- * @param raw Parsed JSON from stdin
70
- * @returns true if this adapter should handle the input
71
- */
72
- detect(raw: Record<string, unknown>): boolean;
73
-
74
- /**
75
- * Parse protocol-specific input into normalized context.
76
- * @param raw Parsed JSON from stdin
77
- * @returns Normalized context for the handler
78
- */
79
- parseInput(raw: Record<string, unknown>): StopHookContext;
80
-
81
- /**
82
- * Format handler result into protocol-specific output.
83
- * @param result Handler result
84
- * @returns JSON string to output to stdout
85
- */
86
- formatOutput(result: StopHookResult): string;
87
-
88
- /**
89
- * Check if execution should be skipped based on protocol-specific conditions.
90
- * @param ctx Parsed context
91
- * @returns Result to output immediately, or null to continue execution
92
- */
93
- shouldSkipExecution(ctx: StopHookContext): StopHookResult | null;
94
- }