ralph-gate 0.1.1 → 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.
- package/dist/cli.js +68 -3
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -307,6 +307,50 @@ async function updateGitignore(cwd) {
|
|
|
307
307
|
return false;
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
+
var RALPH_GATE_HOOK_COMMAND = "npx ralph-gate --hook";
|
|
311
|
+
async function setupClaudeHook(cwd) {
|
|
312
|
+
const claudeDir = path2.join(cwd, ".claude");
|
|
313
|
+
const settingsPath = path2.join(claudeDir, "settings.local.json");
|
|
314
|
+
try {
|
|
315
|
+
await fs2.mkdir(claudeDir, { recursive: true });
|
|
316
|
+
let settings = {};
|
|
317
|
+
if (await fileExists(settingsPath)) {
|
|
318
|
+
try {
|
|
319
|
+
const content = await fs2.readFile(settingsPath, "utf8");
|
|
320
|
+
const parsed = JSON.parse(content);
|
|
321
|
+
if (parsed && typeof parsed === "object") {
|
|
322
|
+
settings = parsed;
|
|
323
|
+
}
|
|
324
|
+
} catch {
|
|
325
|
+
settings = {};
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (!settings.hooks) {
|
|
329
|
+
settings.hooks = {};
|
|
330
|
+
}
|
|
331
|
+
if (!settings.hooks.Stop) {
|
|
332
|
+
settings.hooks.Stop = [];
|
|
333
|
+
}
|
|
334
|
+
const hookExists = settings.hooks.Stop.some(
|
|
335
|
+
(hook) => hook.type === "command" && hook.command === RALPH_GATE_HOOK_COMMAND
|
|
336
|
+
);
|
|
337
|
+
if (hookExists) {
|
|
338
|
+
return { configured: false, alreadyExists: true };
|
|
339
|
+
}
|
|
340
|
+
settings.hooks.Stop.push({
|
|
341
|
+
type: "command",
|
|
342
|
+
command: RALPH_GATE_HOOK_COMMAND
|
|
343
|
+
});
|
|
344
|
+
await fs2.writeFile(
|
|
345
|
+
settingsPath,
|
|
346
|
+
JSON.stringify(settings, null, 2) + "\n",
|
|
347
|
+
"utf8"
|
|
348
|
+
);
|
|
349
|
+
return { configured: true, alreadyExists: false };
|
|
350
|
+
} catch {
|
|
351
|
+
return { configured: false, alreadyExists: false };
|
|
352
|
+
}
|
|
353
|
+
}
|
|
310
354
|
async function generateGateConfig(cwd) {
|
|
311
355
|
const warnings = [];
|
|
312
356
|
const detected = await detectProject(cwd);
|
|
@@ -377,13 +421,22 @@ async function initConfigFile(options = {}) {
|
|
|
377
421
|
};
|
|
378
422
|
}
|
|
379
423
|
const gitignoreUpdated = await updateGitignore(cwd);
|
|
424
|
+
let hookConfigured;
|
|
425
|
+
let hookAlreadyExists;
|
|
426
|
+
if (!options.skipHook) {
|
|
427
|
+
const hookResult = await setupClaudeHook(cwd);
|
|
428
|
+
hookConfigured = hookResult.configured;
|
|
429
|
+
hookAlreadyExists = hookResult.alreadyExists;
|
|
430
|
+
}
|
|
380
431
|
return {
|
|
381
432
|
config,
|
|
382
433
|
configPath,
|
|
383
434
|
created: true,
|
|
384
435
|
projectKind,
|
|
385
436
|
warnings,
|
|
386
|
-
gitignoreUpdated
|
|
437
|
+
gitignoreUpdated,
|
|
438
|
+
hookConfigured,
|
|
439
|
+
hookAlreadyExists
|
|
387
440
|
};
|
|
388
441
|
}
|
|
389
442
|
|
|
@@ -682,7 +735,8 @@ function parseArgs(args) {
|
|
|
682
735
|
function parseInitArgs(args) {
|
|
683
736
|
const options = {
|
|
684
737
|
force: false,
|
|
685
|
-
print: false
|
|
738
|
+
print: false,
|
|
739
|
+
skipHook: false
|
|
686
740
|
};
|
|
687
741
|
for (let i = 0; i < args.length; i += 1) {
|
|
688
742
|
const arg = args[i];
|
|
@@ -693,6 +747,9 @@ function parseInitArgs(args) {
|
|
|
693
747
|
case "--print":
|
|
694
748
|
options.print = true;
|
|
695
749
|
break;
|
|
750
|
+
case "--skip-hook":
|
|
751
|
+
options.skipHook = true;
|
|
752
|
+
break;
|
|
696
753
|
default:
|
|
697
754
|
return { options, error: `Unknown argument: ${arg}` };
|
|
698
755
|
}
|
|
@@ -761,7 +818,8 @@ async function main() {
|
|
|
761
818
|
}
|
|
762
819
|
const result = await initConfigFile({
|
|
763
820
|
force: options2.force,
|
|
764
|
-
print: options2.print
|
|
821
|
+
print: options2.print,
|
|
822
|
+
skipHook: options2.skipHook
|
|
765
823
|
});
|
|
766
824
|
if (result.error) {
|
|
767
825
|
console.error(result.error);
|
|
@@ -781,6 +839,13 @@ async function main() {
|
|
|
781
839
|
if (result.gitignoreUpdated) {
|
|
782
840
|
console.log("Updated .gitignore to exclude gate-results-*.json files.");
|
|
783
841
|
}
|
|
842
|
+
if (result.hookConfigured) {
|
|
843
|
+
console.log(
|
|
844
|
+
"Added Stop hook to .claude/settings.local.json for automatic gate runs."
|
|
845
|
+
);
|
|
846
|
+
} else if (result.hookAlreadyExists) {
|
|
847
|
+
console.log("Stop hook already exists in .claude/settings.local.json.");
|
|
848
|
+
}
|
|
784
849
|
return;
|
|
785
850
|
}
|
|
786
851
|
const { options, error } = parseArgs(argv);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/config.ts","../src/init.ts","../src/runner.ts","../src/output.ts","../src/hook.ts"],"sourcesContent":["#!/usr/bin/env node\nimport path from 'node:path';\nimport type { Gate, GateRunSummary } from './types.js';\nimport { loadConfig } from './config.js';\nimport { initConfigFile } from './init.js';\nimport { runGates, type RunGatesOptions } from './runner.js';\nimport { formatConsoleOutput, writeResultsFile } from './output.js';\nimport { generateHookResponse, outputHookResponse } from './hook.js';\n\ninterface CliOptions {\n hook: boolean;\n dryRun: boolean;\n only?: string;\n verbose: boolean;\n}\n\ninterface InitCliOptions {\n force: boolean;\n print: boolean;\n}\n\nfunction parseArgs(args: string[]): { options: CliOptions; error?: string } {\n const options: CliOptions = {\n hook: false,\n dryRun: false,\n verbose: false,\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i];\n switch (arg) {\n case '--hook':\n options.hook = true;\n break;\n case '--dry-run':\n options.dryRun = true;\n break;\n case '--verbose':\n options.verbose = true;\n break;\n case '--only': {\n const value = args[i + 1];\n if (!value) {\n return { options, error: 'Missing value for --only.' };\n }\n options.only = value;\n i += 1;\n break;\n }\n default:\n return { options, error: `Unknown argument: ${arg}` };\n }\n }\n\n return { options };\n}\n\nfunction parseInitArgs(args: string[]): {\n options: InitCliOptions;\n error?: string;\n} {\n const options: InitCliOptions = {\n force: false,\n print: false,\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i];\n switch (arg) {\n case '--force':\n options.force = true;\n break;\n case '--print':\n options.print = true;\n break;\n default:\n return { options, error: `Unknown argument: ${arg}` };\n }\n }\n\n return { options };\n}\n\nfunction defaultOutputPath(): string {\n return `gate-results-${process.pid}.json`;\n}\n\nfunction createEmptySummary(passed: boolean): GateRunSummary {\n return {\n passed,\n timestamp: new Date().toISOString(),\n totalDurationMs: 0,\n results: [],\n firstFailure: null,\n warnings: [],\n };\n}\n\nfunction formatDryRun(gates: Gate[], shell: string): string {\n const lines = [`SHELL: ${shell}`];\n if (gates.length === 0) {\n lines.push('No gates to run.');\n return lines.join('\\n');\n }\n for (const gate of gates) {\n const order = typeof gate.order === 'number' ? gate.order : 100;\n lines.push(`- ${gate.name} (order ${order}): ${gate.command}`);\n }\n return lines.join('\\n');\n}\n\nfunction createHookProgressReporter(\n enabled: boolean,\n): Partial<RunGatesOptions> {\n if (!enabled) {\n return {};\n }\n\n const prefix = '[ralph-gate]';\n const writeLine = (line: string) => {\n process.stderr.write(`${prefix} ${line}\\n`);\n };\n\n return {\n onGateStart: (gate) => {\n writeLine(`running ${gate.name}: ${gate.command}`);\n },\n onGateOutput: (_gate, _stream, text) => {\n process.stderr.write(text);\n },\n onGateComplete: (result) => {\n if (result.skipped) {\n writeLine(`${result.name} skipped`);\n return;\n }\n const status = result.passed\n ? `passed in ${result.durationMs}ms`\n : `failed (exit ${result.exitCode ?? 'null'}) in ${result.durationMs}ms`;\n writeLine(`${result.name} ${status}`);\n },\n };\n}\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n\n if (argv[0] === 'init') {\n const { options, error } = parseInitArgs(argv.slice(1));\n if (error) {\n console.error(error);\n process.exitCode = 1;\n return;\n }\n\n const result = await initConfigFile({\n force: options.force,\n print: options.print,\n });\n if (result.error) {\n console.error(result.error);\n process.exitCode = 1;\n return;\n }\n\n for (const warning of result.warnings) {\n console.error(`Warning: ${warning}`);\n }\n\n if (options.print) {\n console.log(JSON.stringify(result.config, null, 2));\n return;\n }\n\n console.log(\n `Created ${path.basename(result.configPath)} with ${result.config.gates.length} gate(s).`,\n );\n if (result.gitignoreUpdated) {\n console.log('Updated .gitignore to exclude gate-results-*.json files.');\n }\n return;\n }\n\n const { options, error } = parseArgs(argv);\n if (error) {\n console.error(error);\n process.exitCode = 1;\n return;\n }\n\n const configResult = await loadConfig();\n if (configResult.error) {\n const summary = createEmptySummary(false);\n const outputPath = defaultOutputPath();\n await writeResultsFile(summary, outputPath);\n\n if (options.hook) {\n outputHookResponse({ decision: 'block', reason: configResult.error });\n process.exitCode = 0;\n return;\n }\n\n console.error(configResult.error);\n process.exitCode = 1;\n return;\n }\n\n if (!configResult.config) {\n if (options.dryRun) {\n const shellLabel = process.env.SHELL ?? '(default)';\n console.log(formatDryRun([], shellLabel));\n }\n if (options.hook) {\n outputHookResponse({});\n process.exitCode = 0;\n }\n return;\n }\n\n const config = configResult.config;\n const shellLabel = process.env.SHELL ?? '(default)';\n\n if (options.dryRun) {\n console.log(formatDryRun(config.gates, shellLabel));\n return;\n }\n\n let gates = config.gates;\n if (options.only) {\n const match = gates.find((gate) => gate.name === options.only);\n if (!match) {\n console.error(`Gate not found: ${options.only}`);\n process.exitCode = 1;\n return;\n }\n gates = [match];\n }\n\n const outputPath = config.outputPath ?? defaultOutputPath();\n\n if (gates.length === 0) {\n const summary = createEmptySummary(true);\n await writeResultsFile(summary, outputPath);\n if (options.hook) {\n outputHookResponse({});\n process.exitCode = 0;\n return;\n }\n console.log(formatConsoleOutput(summary));\n return;\n }\n\n const hookProgress = createHookProgressReporter(options.hook);\n const summary = await runGates(gates, {\n failFast: config.failFast,\n verbose: options.verbose && !options.hook,\n ...hookProgress,\n });\n\n await writeResultsFile(summary, outputPath);\n\n if (options.hook) {\n outputHookResponse(generateHookResponse(summary));\n process.exitCode = 0;\n return;\n }\n\n console.log(formatConsoleOutput(summary));\n if (!summary.passed) {\n process.exitCode = 1;\n }\n}\n\nmain().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n});\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { Gate, GateConfig } from './types.js';\n\nconst CONFIG_FILES = ['gate.config.json', '.gaterc.json', '.gaterc'];\n\nexport interface LoadConfigResult {\n config: GateConfig | null;\n configPath?: string;\n error?: string;\n}\n\nfunction normalizeGate(gate: Gate): Gate {\n const order = typeof gate.order === 'number' ? gate.order : 100;\n const enabled = typeof gate.enabled === 'boolean' ? gate.enabled : true;\n const blocking = typeof gate.blocking === 'boolean' ? gate.blocking : true;\n\n return {\n ...gate,\n order,\n enabled,\n blocking,\n description:\n typeof gate.description === 'string' ? gate.description : undefined,\n name: gate.name,\n command: gate.command,\n } as Gate;\n}\n\nfunction validateGate(gate: unknown): string | null {\n if (!gate || typeof gate !== 'object') {\n return 'Gate entries must be objects.';\n }\n const maybeGate = gate as Gate;\n if (typeof maybeGate.name !== 'string' || maybeGate.name.trim() === '') {\n return 'Gate is missing required field: name.';\n }\n if (\n typeof maybeGate.command !== 'string' ||\n maybeGate.command.trim() === ''\n ) {\n return `Gate '${maybeGate.name}' is missing required field: command.`;\n }\n return null;\n}\n\nfunction sortGates(gates: Gate[]): Gate[] {\n const withIndex = gates.map((gate, index) => ({ gate, index }));\n withIndex.sort((a, b) => {\n const orderA = typeof a.gate.order === 'number' ? a.gate.order : 100;\n const orderB = typeof b.gate.order === 'number' ? b.gate.order : 100;\n if (orderA !== orderB) {\n return orderA - orderB;\n }\n return a.index - b.index;\n });\n return withIndex.map((entry) => entry.gate);\n}\n\nexport async function loadConfig(\n cwd: string = process.cwd(),\n): Promise<LoadConfigResult> {\n for (const filename of CONFIG_FILES) {\n const filePath = path.join(cwd, filename);\n try {\n await fs.access(filePath);\n } catch {\n continue;\n }\n\n let raw: string;\n try {\n raw = await fs.readFile(filePath, 'utf8');\n } catch (error) {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: unable to read ${filename}: ${(error as Error).message}`,\n };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: malformed JSON in ${filename}: ${(error as Error).message}`,\n };\n }\n\n if (!parsed || typeof parsed !== 'object') {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: expected object in ${filename}.`,\n };\n }\n\n const config = parsed as GateConfig;\n if (!Array.isArray(config.gates)) {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: missing required 'gates' array in ${filename}.`,\n };\n }\n\n const normalized: Gate[] = [];\n for (const gate of config.gates) {\n const gateError = validateGate(gate as Gate);\n if (gateError) {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: ${gateError}`,\n };\n }\n const normalizedGate = normalizeGate(gate as Gate);\n if (normalizedGate.enabled === false) {\n continue;\n }\n normalized.push(normalizedGate);\n }\n\n const failFast =\n typeof config.failFast === 'boolean' ? config.failFast : true;\n const outputPath =\n typeof config.outputPath === 'string' ? config.outputPath : undefined;\n\n const sorted = sortGates(normalized);\n\n return {\n config: {\n gates: sorted,\n failFast,\n outputPath,\n },\n configPath: filePath,\n };\n }\n\n return { config: null };\n}\n","import { promises as fs } from 'node:fs';\nimport { execSync } from 'node:child_process';\nimport path from 'node:path';\nimport type { Gate, GateConfig } from './types.js';\n\nexport const DEFAULT_CONFIG_FILENAME = 'gate.config.json';\n\ntype PackageManager = 'npm' | 'yarn' | 'pnpm';\n\ntype DetectedProject =\n | {\n kind: 'node';\n packageManager: PackageManager;\n packageJson: Record<string, unknown>;\n }\n | { kind: 'python'; requirements: Set<string> }\n | { kind: 'unknown' };\n\nexport interface InitOptions {\n cwd?: string;\n filename?: string;\n force?: boolean;\n print?: boolean;\n}\n\nexport interface InitResult {\n config: GateConfig;\n configPath: string;\n created: boolean;\n projectKind: DetectedProject['kind'];\n warnings: string[];\n error?: string;\n gitignoreUpdated?: boolean;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function detectPackageManager(cwd: string): Promise<PackageManager> {\n if (await fileExists(path.join(cwd, 'pnpm-lock.yaml'))) {\n return 'pnpm';\n }\n if (await fileExists(path.join(cwd, 'yarn.lock'))) {\n return 'yarn';\n }\n return 'npm';\n}\n\nfunction runScriptCommand(\n packageManager: PackageManager,\n scriptName: string,\n): string {\n switch (packageManager) {\n case 'yarn':\n return `yarn ${scriptName}`;\n case 'pnpm':\n return `pnpm run ${scriptName}`;\n default:\n return `npm run ${scriptName}`;\n }\n}\n\nasync function readJsonFile(filePath: string): Promise<unknown> {\n const raw = await fs.readFile(filePath, 'utf8');\n return JSON.parse(raw);\n}\n\nfunction extractRequirementName(line: string): string | null {\n const trimmed = line.trim();\n if (trimmed.length === 0 || trimmed.startsWith('#')) {\n return null;\n }\n const noEnvMarker = trimmed.split(';', 1)[0]?.trim() ?? '';\n if (noEnvMarker.length === 0) {\n return null;\n }\n const name = noEnvMarker.split(/[<>=\\[]/, 1)[0]?.trim();\n if (!name) {\n return null;\n }\n return name.toLowerCase();\n}\n\nasync function detectProject(cwd: string): Promise<DetectedProject> {\n const packageJsonPath = path.join(cwd, 'package.json');\n if (await fileExists(packageJsonPath)) {\n const pm = await detectPackageManager(cwd);\n const parsed = await readJsonFile(packageJsonPath);\n if (!parsed || typeof parsed !== 'object') {\n throw new Error('package.json is not a JSON object.');\n }\n return {\n kind: 'node',\n packageManager: pm,\n packageJson: parsed as Record<string, unknown>,\n };\n }\n\n const requirementsPath = path.join(cwd, 'requirements.txt');\n const pyprojectPath = path.join(cwd, 'pyproject.toml');\n\n if (\n (await fileExists(requirementsPath)) ||\n (await fileExists(pyprojectPath))\n ) {\n const requirements = new Set<string>();\n if (await fileExists(requirementsPath)) {\n const raw = await fs.readFile(requirementsPath, 'utf8');\n for (const line of raw.split(/\\r?\\n/)) {\n const name = extractRequirementName(line);\n if (name) {\n requirements.add(name);\n }\n }\n }\n return { kind: 'python', requirements };\n }\n\n return { kind: 'unknown' };\n}\n\nfunction getPackageJsonScripts(\n packageJson: Record<string, unknown>,\n): Record<string, string> {\n const scripts = packageJson.scripts;\n if (!scripts || typeof scripts !== 'object') {\n return {};\n }\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(\n scripts as Record<string, unknown>,\n )) {\n if (typeof value === 'string') {\n result[key] = value;\n }\n }\n return result;\n}\n\nfunction getPackageJsonDeps(packageJson: Record<string, unknown>): Set<string> {\n const deps = new Set<string>();\n const sections = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n ] as const;\n for (const section of sections) {\n const values = packageJson[section];\n if (!values || typeof values !== 'object') {\n continue;\n }\n for (const name of Object.keys(values as Record<string, unknown>)) {\n deps.add(name);\n }\n }\n return deps;\n}\n\nasync function inferNodeGates(\n cwd: string,\n packageManager: PackageManager,\n packageJson: Record<string, unknown>,\n warnings: string[],\n): Promise<Gate[]> {\n const gates: Gate[] = [];\n const scripts = getPackageJsonScripts(packageJson);\n const deps = getPackageJsonDeps(packageJson);\n\n const addIfScript = (name: string, order: number) => {\n if (!scripts[name]) {\n return;\n }\n gates.push({\n name,\n order,\n command: runScriptCommand(packageManager, name),\n });\n };\n\n addIfScript('lint', 10);\n addIfScript('typecheck', 20);\n addIfScript('test', 30);\n addIfScript('build', 40);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTypescript = deps.has('typescript');\n if (hasTypescript && (await fileExists(tsconfigPath)) && !scripts.typecheck) {\n warnings.push(\n \"No 'typecheck' script found; generating a default tsc gate.\",\n );\n gates.splice(1, 0, {\n name: 'typecheck',\n order: 20,\n command: 'npx tsc -p tsconfig.json --noEmit',\n });\n }\n\n return gates;\n}\n\nfunction inferPythonGates(\n requirements: Set<string>,\n warnings: string[],\n): Gate[] {\n const gates: Gate[] = [];\n\n if (requirements.has('ruff')) {\n gates.push({ name: 'lint', order: 10, command: 'python -m ruff check .' });\n }\n\n if (requirements.has('mypy')) {\n gates.push({ name: 'typecheck', order: 20, command: 'python -m mypy .' });\n }\n\n if (requirements.has('pytest')) {\n gates.push({ name: 'test', order: 30, command: 'python -m pytest -q' });\n } else {\n warnings.push(\n 'pytest not detected in requirements; no test gate generated.',\n );\n }\n\n return gates;\n}\n\nasync function updateGitignore(cwd: string): Promise<boolean> {\n const gitignorePath = path.join(cwd, '.gitignore');\n const pattern = 'gate-results-*.json';\n\n try {\n // Use git check-ignore to test if the pattern would already cover gate result files\n // This handles all edge cases: broader patterns, multiple patterns, etc.\n execSync('git check-ignore -q gate-results-test.json', {\n cwd,\n stdio: 'ignore',\n });\n // Exit code 0 means the file would be ignored - pattern already covered\n return false;\n } catch {\n // Not ignored or git not available - need to add the pattern\n }\n\n try {\n // Check if .gitignore exists and read it\n const exists = await fileExists(gitignorePath);\n const content = exists ? await fs.readFile(gitignorePath, 'utf8') : '';\n\n // Append the pattern with proper newline handling\n const newline = content && !content.endsWith('\\n') ? '\\n' : '';\n await fs.appendFile(gitignorePath, `${newline}${pattern}\\n`, 'utf8');\n return true;\n } catch {\n // Silently fail if we can't update .gitignore\n return false;\n }\n}\n\nexport async function generateGateConfig(cwd: string): Promise<{\n config: GateConfig;\n projectKind: DetectedProject['kind'];\n warnings: string[];\n}> {\n const warnings: string[] = [];\n const detected = await detectProject(cwd);\n\n let gates: Gate[] = [];\n\n if (detected.kind === 'node') {\n gates = await inferNodeGates(\n cwd,\n detected.packageManager,\n detected.packageJson,\n warnings,\n );\n } else if (detected.kind === 'python') {\n gates = inferPythonGates(detected.requirements, warnings);\n } else {\n warnings.push(\n 'No supported project markers found; creating an empty gate config.',\n );\n }\n\n return {\n config: {\n gates,\n failFast: true,\n },\n projectKind: detected.kind,\n warnings,\n };\n}\n\nexport async function initConfigFile(\n options: InitOptions = {},\n): Promise<InitResult> {\n const cwd = options.cwd ?? process.cwd();\n const filename = options.filename ?? DEFAULT_CONFIG_FILENAME;\n const configPath = path.join(cwd, filename);\n\n const { config, projectKind, warnings } = await generateGateConfig(cwd);\n\n if (options.print) {\n return {\n config,\n configPath,\n created: false,\n projectKind,\n warnings,\n };\n }\n\n const writeFlag = options.force ? 'w' : 'wx';\n\n try {\n await fs.writeFile(configPath, JSON.stringify(config, null, 2) + '\\n', {\n encoding: 'utf8',\n flag: writeFlag,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const code = (error as NodeJS.ErrnoException | null)?.code;\n if (!options.force && code === 'EEXIST') {\n return {\n config,\n configPath,\n created: false,\n projectKind,\n warnings,\n error: `Config already exists at ${configPath}. Use --force to overwrite.`,\n };\n }\n return {\n config,\n configPath,\n created: false,\n projectKind,\n warnings,\n error: `Unable to write config at ${configPath}: ${message}`,\n };\n }\n\n // Update .gitignore to include gate result files\n const gitignoreUpdated = await updateGitignore(cwd);\n\n return {\n config,\n configPath,\n created: true,\n projectKind,\n warnings,\n gitignoreUpdated,\n };\n}\n","import { spawn } from 'node:child_process';\nimport type { Gate, GateResult, GateRunSummary } from './types.js';\n\nexport interface RunGatesOptions {\n failFast?: boolean;\n verbose?: boolean;\n shell?: string;\n cwd?: string;\n onGateStart?: (gate: Gate) => void;\n onGateOutput?: (\n gate: Gate,\n stream: 'stdout' | 'stderr',\n text: string,\n ) => void;\n onGateComplete?: (result: GateResult) => void;\n}\n\nfunction resolveShell(shell?: string): string | boolean {\n if (typeof shell === 'string' && shell.length > 0) {\n return shell;\n }\n const envShell = process.env.SHELL;\n return envShell && envShell.length > 0 ? envShell : true;\n}\n\nasync function runGate(\n gate: Gate,\n options: RunGatesOptions,\n): Promise<GateResult> {\n const start = Date.now();\n const shell = resolveShell(options.shell);\n const env = process.env;\n\n return new Promise((resolve) => {\n options.onGateStart?.(gate);\n const child = spawn(gate.command, {\n shell,\n env,\n cwd: options.cwd,\n });\n\n let stdout = '';\n let stderr = '';\n let exitCode: number | null = null;\n let resolved = false;\n\n const finalize = () => {\n if (resolved) {\n return;\n }\n resolved = true;\n const durationMs = Date.now() - start;\n const result: GateResult = {\n name: gate.name,\n passed: exitCode === 0,\n exitCode,\n stdout,\n stderr,\n durationMs,\n skipped: false,\n blocking: gate.blocking !== false,\n timestamp: new Date().toISOString(),\n };\n options.onGateComplete?.(result);\n resolve(result);\n };\n\n child.stdout?.on('data', (chunk) => {\n const text = chunk.toString();\n stdout += text;\n if (options.verbose) {\n process.stdout.write(text);\n }\n options.onGateOutput?.(gate, 'stdout', text);\n });\n\n child.stderr?.on('data', (chunk) => {\n const text = chunk.toString();\n stderr += text;\n if (options.verbose) {\n process.stderr.write(text);\n }\n options.onGateOutput?.(gate, 'stderr', text);\n });\n\n child.on('error', (error) => {\n stderr += error.message;\n exitCode = null;\n finalize();\n });\n\n child.on('close', (code) => {\n exitCode = code;\n finalize();\n });\n });\n}\n\nexport async function runGates(\n gates: Gate[],\n options: RunGatesOptions = {},\n): Promise<GateRunSummary> {\n const results: GateResult[] = [];\n const warnings: string[] = [];\n const start = Date.now();\n let firstFailure: GateResult | null = null;\n\n for (const gate of gates) {\n const isBlocking = gate.blocking !== false;\n const shouldSkip =\n options.failFast !== false && firstFailure !== null && isBlocking;\n\n if (shouldSkip) {\n const skippedResult: GateResult = {\n name: gate.name,\n passed: true,\n exitCode: null,\n stdout: '',\n stderr: '',\n durationMs: 0,\n skipped: true,\n blocking: isBlocking,\n timestamp: new Date().toISOString(),\n };\n results.push(skippedResult);\n options.onGateComplete?.(skippedResult);\n continue;\n }\n\n const result = await runGate(gate, options);\n results.push(result);\n\n if (!result.passed) {\n if (result.blocking) {\n if (!firstFailure) {\n firstFailure = result;\n }\n } else {\n warnings.push(result.name);\n }\n }\n }\n\n const totalDurationMs = Date.now() - start;\n const passed = firstFailure === null;\n\n return {\n passed,\n timestamp: new Date().toISOString(),\n totalDurationMs,\n results,\n firstFailure,\n warnings,\n };\n}\n","import { promises as fs } from 'node:fs';\nimport type { GateResult, GateRunSummary } from './types.js';\n\nconst MAX_FAILURE_CHARS = 4000;\nconst HEAD_RATIO = 0.6;\n\nfunction truncateOutput(text: string, maxChars: number): string {\n const trimmed = text.trimEnd();\n if (maxChars <= 0 || trimmed.length === 0) {\n return '';\n }\n if (trimmed.length <= maxChars) {\n return trimmed;\n }\n const headChars = Math.max(1, Math.floor(maxChars * HEAD_RATIO));\n const tailChars = Math.max(0, maxChars - headChars);\n const omitted = trimmed.length - maxChars;\n const marker = `\\n...<${omitted} chars omitted>...\\n`;\n const head = trimmed.slice(0, headChars);\n const tail = tailChars > 0 ? trimmed.slice(-tailChars) : '';\n return `${head}${marker}${tail}`;\n}\n\nfunction splitBudget(\n stdoutLen: number,\n stderrLen: number,\n): {\n stdout: number;\n stderr: number;\n} {\n if (stdoutLen === 0 && stderrLen === 0) {\n return { stdout: 0, stderr: 0 };\n }\n if (stdoutLen === 0) {\n return { stdout: 0, stderr: MAX_FAILURE_CHARS };\n }\n if (stderrLen === 0) {\n return { stdout: MAX_FAILURE_CHARS, stderr: 0 };\n }\n\n const base = Math.floor(MAX_FAILURE_CHARS / 2);\n let stdout = Math.min(stdoutLen, base);\n let stderr = Math.min(stderrLen, base);\n let remaining = MAX_FAILURE_CHARS - stdout - stderr;\n\n if (remaining > 0) {\n const stdoutRemaining = stdoutLen - stdout;\n const stderrRemaining = stderrLen - stderr;\n if (stdoutRemaining === 0) {\n stderr += remaining;\n } else if (stderrRemaining === 0) {\n stdout += remaining;\n } else {\n const totalRemaining = stdoutRemaining + stderrRemaining;\n const stdoutExtra = Math.round(\n (stdoutRemaining / totalRemaining) * remaining,\n );\n stdout += stdoutExtra;\n stderr += remaining - stdoutExtra;\n }\n }\n\n return { stdout, stderr };\n}\n\nfunction colorize(text: string, code: string, enabled: boolean): string {\n if (!enabled) {\n return text;\n }\n return `\\u001b[${code}m${text}\\u001b[0m`;\n}\n\nfunction formatResultLine(result: GateResult, color: boolean): string {\n const statusSymbol = result.skipped ? '⊘' : result.passed ? '✓' : '✗';\n\n let symbolColor = '32';\n if (result.skipped) {\n symbolColor = '90';\n } else if (!result.passed) {\n symbolColor = '31';\n }\n\n const parts: string[] = [];\n if (result.skipped) {\n parts.push('skipped');\n } else if (!result.passed) {\n parts.push(`exit ${result.exitCode ?? 'null'}`);\n }\n parts.push(`${result.durationMs}ms`);\n\n const details = parts.length > 0 ? ` (${parts.join(', ')})` : '';\n const coloredSymbol = colorize(statusSymbol, symbolColor, color);\n return `${coloredSymbol} ${result.name}${details}`;\n}\n\nexport function formatFailureContext(stderr: string, stdout = ''): string {\n const trimmedStderr = stderr.trimEnd();\n const trimmedStdout = stdout.trimEnd();\n\n if (trimmedStderr.length === 0 && trimmedStdout.length === 0) {\n return 'No output captured.';\n }\n\n if (trimmedStderr.length > 0 && trimmedStdout.length > 0) {\n const budget = splitBudget(trimmedStdout.length, trimmedStderr.length);\n const stderrSection = truncateOutput(trimmedStderr, budget.stderr);\n const stdoutSection = truncateOutput(trimmedStdout, budget.stdout);\n return `STDERR:\\n${stderrSection}\\n\\nSTDOUT:\\n${stdoutSection}`;\n }\n\n if (trimmedStderr.length > 0) {\n return truncateOutput(trimmedStderr, MAX_FAILURE_CHARS);\n }\n\n return truncateOutput(trimmedStdout, MAX_FAILURE_CHARS);\n}\n\nexport function formatConsoleOutput(summary: GateRunSummary): string {\n const color = Boolean(process.stdout.isTTY);\n const lines: string[] = [];\n\n for (const result of summary.results) {\n lines.push(formatResultLine(result, color));\n }\n\n if (summary.warnings.length > 0) {\n const warningLine = `Warnings: ${summary.warnings.join(', ')}`;\n lines.push(colorize(warningLine, '33', color));\n }\n\n const finalLine = summary.passed\n ? colorize('All blocking gates passed.', '32', color)\n : colorize('Blocking gate failed.', '31', color);\n lines.push(finalLine);\n\n return lines.join('\\n');\n}\n\nexport async function writeResultsFile(\n summary: GateRunSummary,\n outputPath: string,\n): Promise<void> {\n const data = JSON.stringify(summary, null, 2);\n await fs.writeFile(outputPath, data, 'utf8');\n}\n","import type { GateRunSummary, HookOutput } from './types.js';\nimport { formatFailureContext } from './output.js';\n\nexport function generateHookResponse(summary: GateRunSummary): HookOutput {\n const warnings = summary.warnings.length > 0 ? summary.warnings : undefined;\n\n if (summary.passed) {\n return warnings ? { warnings } : {};\n }\n\n const failure = summary.firstFailure;\n if (failure) {\n const reason = `Gate '${failure.name}' failed (exit ${failure.exitCode ?? 'null'}):\\n${formatFailureContext(failure.stderr, failure.stdout)}`;\n return warnings\n ? { decision: 'block', reason, warnings }\n : { decision: 'block', reason };\n }\n\n const reason = 'Gate run failed without a blocking gate result.';\n return warnings\n ? { decision: 'block', reason, warnings }\n : { decision: 'block', reason };\n}\n\nexport function outputHookResponse(output: HookOutput): void {\n process.stdout.write(`${JSON.stringify(output)}\\n`);\n}\n"],"mappings":"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","names":["path","fs","path","fs","reason","options","error","path","summary","outputPath","shellLabel"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/config.ts","../src/init.ts","../src/runner.ts","../src/output.ts","../src/hook.ts"],"sourcesContent":["#!/usr/bin/env node\nimport path from 'node:path';\nimport type { Gate, GateRunSummary } from './types.js';\nimport { loadConfig } from './config.js';\nimport { initConfigFile } from './init.js';\nimport { runGates, type RunGatesOptions } from './runner.js';\nimport { formatConsoleOutput, writeResultsFile } from './output.js';\nimport { generateHookResponse, outputHookResponse } from './hook.js';\n\ninterface CliOptions {\n hook: boolean;\n dryRun: boolean;\n only?: string;\n verbose: boolean;\n}\n\ninterface InitCliOptions {\n force: boolean;\n print: boolean;\n skipHook: boolean;\n}\n\nfunction parseArgs(args: string[]): { options: CliOptions; error?: string } {\n const options: CliOptions = {\n hook: false,\n dryRun: false,\n verbose: false,\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i];\n switch (arg) {\n case '--hook':\n options.hook = true;\n break;\n case '--dry-run':\n options.dryRun = true;\n break;\n case '--verbose':\n options.verbose = true;\n break;\n case '--only': {\n const value = args[i + 1];\n if (!value) {\n return { options, error: 'Missing value for --only.' };\n }\n options.only = value;\n i += 1;\n break;\n }\n default:\n return { options, error: `Unknown argument: ${arg}` };\n }\n }\n\n return { options };\n}\n\nfunction parseInitArgs(args: string[]): {\n options: InitCliOptions;\n error?: string;\n} {\n const options: InitCliOptions = {\n force: false,\n print: false,\n skipHook: false,\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i];\n switch (arg) {\n case '--force':\n options.force = true;\n break;\n case '--print':\n options.print = true;\n break;\n case '--skip-hook':\n options.skipHook = true;\n break;\n default:\n return { options, error: `Unknown argument: ${arg}` };\n }\n }\n\n return { options };\n}\n\nfunction defaultOutputPath(): string {\n return `gate-results-${process.pid}.json`;\n}\n\nfunction createEmptySummary(passed: boolean): GateRunSummary {\n return {\n passed,\n timestamp: new Date().toISOString(),\n totalDurationMs: 0,\n results: [],\n firstFailure: null,\n warnings: [],\n };\n}\n\nfunction formatDryRun(gates: Gate[], shell: string): string {\n const lines = [`SHELL: ${shell}`];\n if (gates.length === 0) {\n lines.push('No gates to run.');\n return lines.join('\\n');\n }\n for (const gate of gates) {\n const order = typeof gate.order === 'number' ? gate.order : 100;\n lines.push(`- ${gate.name} (order ${order}): ${gate.command}`);\n }\n return lines.join('\\n');\n}\n\nfunction createHookProgressReporter(\n enabled: boolean,\n): Partial<RunGatesOptions> {\n if (!enabled) {\n return {};\n }\n\n const prefix = '[ralph-gate]';\n const writeLine = (line: string) => {\n process.stderr.write(`${prefix} ${line}\\n`);\n };\n\n return {\n onGateStart: (gate) => {\n writeLine(`running ${gate.name}: ${gate.command}`);\n },\n onGateOutput: (_gate, _stream, text) => {\n process.stderr.write(text);\n },\n onGateComplete: (result) => {\n if (result.skipped) {\n writeLine(`${result.name} skipped`);\n return;\n }\n const status = result.passed\n ? `passed in ${result.durationMs}ms`\n : `failed (exit ${result.exitCode ?? 'null'}) in ${result.durationMs}ms`;\n writeLine(`${result.name} ${status}`);\n },\n };\n}\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n\n if (argv[0] === 'init') {\n const { options, error } = parseInitArgs(argv.slice(1));\n if (error) {\n console.error(error);\n process.exitCode = 1;\n return;\n }\n\n const result = await initConfigFile({\n force: options.force,\n print: options.print,\n skipHook: options.skipHook,\n });\n if (result.error) {\n console.error(result.error);\n process.exitCode = 1;\n return;\n }\n\n for (const warning of result.warnings) {\n console.error(`Warning: ${warning}`);\n }\n\n if (options.print) {\n console.log(JSON.stringify(result.config, null, 2));\n return;\n }\n\n console.log(\n `Created ${path.basename(result.configPath)} with ${result.config.gates.length} gate(s).`,\n );\n if (result.gitignoreUpdated) {\n console.log('Updated .gitignore to exclude gate-results-*.json files.');\n }\n if (result.hookConfigured) {\n console.log(\n 'Added Stop hook to .claude/settings.local.json for automatic gate runs.',\n );\n } else if (result.hookAlreadyExists) {\n console.log('Stop hook already exists in .claude/settings.local.json.');\n }\n return;\n }\n\n const { options, error } = parseArgs(argv);\n if (error) {\n console.error(error);\n process.exitCode = 1;\n return;\n }\n\n const configResult = await loadConfig();\n if (configResult.error) {\n const summary = createEmptySummary(false);\n const outputPath = defaultOutputPath();\n await writeResultsFile(summary, outputPath);\n\n if (options.hook) {\n outputHookResponse({ decision: 'block', reason: configResult.error });\n process.exitCode = 0;\n return;\n }\n\n console.error(configResult.error);\n process.exitCode = 1;\n return;\n }\n\n if (!configResult.config) {\n if (options.dryRun) {\n const shellLabel = process.env.SHELL ?? '(default)';\n console.log(formatDryRun([], shellLabel));\n }\n if (options.hook) {\n outputHookResponse({});\n process.exitCode = 0;\n }\n return;\n }\n\n const config = configResult.config;\n const shellLabel = process.env.SHELL ?? '(default)';\n\n if (options.dryRun) {\n console.log(formatDryRun(config.gates, shellLabel));\n return;\n }\n\n let gates = config.gates;\n if (options.only) {\n const match = gates.find((gate) => gate.name === options.only);\n if (!match) {\n console.error(`Gate not found: ${options.only}`);\n process.exitCode = 1;\n return;\n }\n gates = [match];\n }\n\n const outputPath = config.outputPath ?? defaultOutputPath();\n\n if (gates.length === 0) {\n const summary = createEmptySummary(true);\n await writeResultsFile(summary, outputPath);\n if (options.hook) {\n outputHookResponse({});\n process.exitCode = 0;\n return;\n }\n console.log(formatConsoleOutput(summary));\n return;\n }\n\n const hookProgress = createHookProgressReporter(options.hook);\n const summary = await runGates(gates, {\n failFast: config.failFast,\n verbose: options.verbose && !options.hook,\n ...hookProgress,\n });\n\n await writeResultsFile(summary, outputPath);\n\n if (options.hook) {\n outputHookResponse(generateHookResponse(summary));\n process.exitCode = 0;\n return;\n }\n\n console.log(formatConsoleOutput(summary));\n if (!summary.passed) {\n process.exitCode = 1;\n }\n}\n\nmain().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n});\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { Gate, GateConfig } from './types.js';\n\nconst CONFIG_FILES = ['gate.config.json', '.gaterc.json', '.gaterc'];\n\nexport interface LoadConfigResult {\n config: GateConfig | null;\n configPath?: string;\n error?: string;\n}\n\nfunction normalizeGate(gate: Gate): Gate {\n const order = typeof gate.order === 'number' ? gate.order : 100;\n const enabled = typeof gate.enabled === 'boolean' ? gate.enabled : true;\n const blocking = typeof gate.blocking === 'boolean' ? gate.blocking : true;\n\n return {\n ...gate,\n order,\n enabled,\n blocking,\n description:\n typeof gate.description === 'string' ? gate.description : undefined,\n name: gate.name,\n command: gate.command,\n } as Gate;\n}\n\nfunction validateGate(gate: unknown): string | null {\n if (!gate || typeof gate !== 'object') {\n return 'Gate entries must be objects.';\n }\n const maybeGate = gate as Gate;\n if (typeof maybeGate.name !== 'string' || maybeGate.name.trim() === '') {\n return 'Gate is missing required field: name.';\n }\n if (\n typeof maybeGate.command !== 'string' ||\n maybeGate.command.trim() === ''\n ) {\n return `Gate '${maybeGate.name}' is missing required field: command.`;\n }\n return null;\n}\n\nfunction sortGates(gates: Gate[]): Gate[] {\n const withIndex = gates.map((gate, index) => ({ gate, index }));\n withIndex.sort((a, b) => {\n const orderA = typeof a.gate.order === 'number' ? a.gate.order : 100;\n const orderB = typeof b.gate.order === 'number' ? b.gate.order : 100;\n if (orderA !== orderB) {\n return orderA - orderB;\n }\n return a.index - b.index;\n });\n return withIndex.map((entry) => entry.gate);\n}\n\nexport async function loadConfig(\n cwd: string = process.cwd(),\n): Promise<LoadConfigResult> {\n for (const filename of CONFIG_FILES) {\n const filePath = path.join(cwd, filename);\n try {\n await fs.access(filePath);\n } catch {\n continue;\n }\n\n let raw: string;\n try {\n raw = await fs.readFile(filePath, 'utf8');\n } catch (error) {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: unable to read ${filename}: ${(error as Error).message}`,\n };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: malformed JSON in ${filename}: ${(error as Error).message}`,\n };\n }\n\n if (!parsed || typeof parsed !== 'object') {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: expected object in ${filename}.`,\n };\n }\n\n const config = parsed as GateConfig;\n if (!Array.isArray(config.gates)) {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: missing required 'gates' array in ${filename}.`,\n };\n }\n\n const normalized: Gate[] = [];\n for (const gate of config.gates) {\n const gateError = validateGate(gate as Gate);\n if (gateError) {\n return {\n config: null,\n configPath: filePath,\n error: `Invalid config: ${gateError}`,\n };\n }\n const normalizedGate = normalizeGate(gate as Gate);\n if (normalizedGate.enabled === false) {\n continue;\n }\n normalized.push(normalizedGate);\n }\n\n const failFast =\n typeof config.failFast === 'boolean' ? config.failFast : true;\n const outputPath =\n typeof config.outputPath === 'string' ? config.outputPath : undefined;\n\n const sorted = sortGates(normalized);\n\n return {\n config: {\n gates: sorted,\n failFast,\n outputPath,\n },\n configPath: filePath,\n };\n }\n\n return { config: null };\n}\n","import { promises as fs } from 'node:fs';\nimport { execSync } from 'node:child_process';\nimport path from 'node:path';\nimport type { Gate, GateConfig } from './types.js';\n\nexport const DEFAULT_CONFIG_FILENAME = 'gate.config.json';\n\ntype PackageManager = 'npm' | 'yarn' | 'pnpm';\n\ntype DetectedProject =\n | {\n kind: 'node';\n packageManager: PackageManager;\n packageJson: Record<string, unknown>;\n }\n | { kind: 'python'; requirements: Set<string> }\n | { kind: 'unknown' };\n\nexport interface InitOptions {\n cwd?: string;\n filename?: string;\n force?: boolean;\n print?: boolean;\n skipHook?: boolean;\n}\n\nexport interface InitResult {\n config: GateConfig;\n configPath: string;\n created: boolean;\n projectKind: DetectedProject['kind'];\n warnings: string[];\n error?: string;\n gitignoreUpdated?: boolean;\n hookConfigured?: boolean;\n hookAlreadyExists?: boolean;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function detectPackageManager(cwd: string): Promise<PackageManager> {\n if (await fileExists(path.join(cwd, 'pnpm-lock.yaml'))) {\n return 'pnpm';\n }\n if (await fileExists(path.join(cwd, 'yarn.lock'))) {\n return 'yarn';\n }\n return 'npm';\n}\n\nfunction runScriptCommand(\n packageManager: PackageManager,\n scriptName: string,\n): string {\n switch (packageManager) {\n case 'yarn':\n return `yarn ${scriptName}`;\n case 'pnpm':\n return `pnpm run ${scriptName}`;\n default:\n return `npm run ${scriptName}`;\n }\n}\n\nasync function readJsonFile(filePath: string): Promise<unknown> {\n const raw = await fs.readFile(filePath, 'utf8');\n return JSON.parse(raw);\n}\n\nfunction extractRequirementName(line: string): string | null {\n const trimmed = line.trim();\n if (trimmed.length === 0 || trimmed.startsWith('#')) {\n return null;\n }\n const noEnvMarker = trimmed.split(';', 1)[0]?.trim() ?? '';\n if (noEnvMarker.length === 0) {\n return null;\n }\n const name = noEnvMarker.split(/[<>=\\[]/, 1)[0]?.trim();\n if (!name) {\n return null;\n }\n return name.toLowerCase();\n}\n\nasync function detectProject(cwd: string): Promise<DetectedProject> {\n const packageJsonPath = path.join(cwd, 'package.json');\n if (await fileExists(packageJsonPath)) {\n const pm = await detectPackageManager(cwd);\n const parsed = await readJsonFile(packageJsonPath);\n if (!parsed || typeof parsed !== 'object') {\n throw new Error('package.json is not a JSON object.');\n }\n return {\n kind: 'node',\n packageManager: pm,\n packageJson: parsed as Record<string, unknown>,\n };\n }\n\n const requirementsPath = path.join(cwd, 'requirements.txt');\n const pyprojectPath = path.join(cwd, 'pyproject.toml');\n\n if (\n (await fileExists(requirementsPath)) ||\n (await fileExists(pyprojectPath))\n ) {\n const requirements = new Set<string>();\n if (await fileExists(requirementsPath)) {\n const raw = await fs.readFile(requirementsPath, 'utf8');\n for (const line of raw.split(/\\r?\\n/)) {\n const name = extractRequirementName(line);\n if (name) {\n requirements.add(name);\n }\n }\n }\n return { kind: 'python', requirements };\n }\n\n return { kind: 'unknown' };\n}\n\nfunction getPackageJsonScripts(\n packageJson: Record<string, unknown>,\n): Record<string, string> {\n const scripts = packageJson.scripts;\n if (!scripts || typeof scripts !== 'object') {\n return {};\n }\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(\n scripts as Record<string, unknown>,\n )) {\n if (typeof value === 'string') {\n result[key] = value;\n }\n }\n return result;\n}\n\nfunction getPackageJsonDeps(packageJson: Record<string, unknown>): Set<string> {\n const deps = new Set<string>();\n const sections = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n ] as const;\n for (const section of sections) {\n const values = packageJson[section];\n if (!values || typeof values !== 'object') {\n continue;\n }\n for (const name of Object.keys(values as Record<string, unknown>)) {\n deps.add(name);\n }\n }\n return deps;\n}\n\nasync function inferNodeGates(\n cwd: string,\n packageManager: PackageManager,\n packageJson: Record<string, unknown>,\n warnings: string[],\n): Promise<Gate[]> {\n const gates: Gate[] = [];\n const scripts = getPackageJsonScripts(packageJson);\n const deps = getPackageJsonDeps(packageJson);\n\n const addIfScript = (name: string, order: number) => {\n if (!scripts[name]) {\n return;\n }\n gates.push({\n name,\n order,\n command: runScriptCommand(packageManager, name),\n });\n };\n\n addIfScript('lint', 10);\n addIfScript('typecheck', 20);\n addIfScript('test', 30);\n addIfScript('build', 40);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTypescript = deps.has('typescript');\n if (hasTypescript && (await fileExists(tsconfigPath)) && !scripts.typecheck) {\n warnings.push(\n \"No 'typecheck' script found; generating a default tsc gate.\",\n );\n gates.splice(1, 0, {\n name: 'typecheck',\n order: 20,\n command: 'npx tsc -p tsconfig.json --noEmit',\n });\n }\n\n return gates;\n}\n\nfunction inferPythonGates(\n requirements: Set<string>,\n warnings: string[],\n): Gate[] {\n const gates: Gate[] = [];\n\n if (requirements.has('ruff')) {\n gates.push({ name: 'lint', order: 10, command: 'python -m ruff check .' });\n }\n\n if (requirements.has('mypy')) {\n gates.push({ name: 'typecheck', order: 20, command: 'python -m mypy .' });\n }\n\n if (requirements.has('pytest')) {\n gates.push({ name: 'test', order: 30, command: 'python -m pytest -q' });\n } else {\n warnings.push(\n 'pytest not detected in requirements; no test gate generated.',\n );\n }\n\n return gates;\n}\n\nasync function updateGitignore(cwd: string): Promise<boolean> {\n const gitignorePath = path.join(cwd, '.gitignore');\n const pattern = 'gate-results-*.json';\n\n try {\n // Use git check-ignore to test if the pattern would already cover gate result files\n // This handles all edge cases: broader patterns, multiple patterns, etc.\n execSync('git check-ignore -q gate-results-test.json', {\n cwd,\n stdio: 'ignore',\n });\n // Exit code 0 means the file would be ignored - pattern already covered\n return false;\n } catch {\n // Not ignored or git not available - need to add the pattern\n }\n\n try {\n // Check if .gitignore exists and read it\n const exists = await fileExists(gitignorePath);\n const content = exists ? await fs.readFile(gitignorePath, 'utf8') : '';\n\n // Append the pattern with proper newline handling\n const newline = content && !content.endsWith('\\n') ? '\\n' : '';\n await fs.appendFile(gitignorePath, `${newline}${pattern}\\n`, 'utf8');\n return true;\n } catch {\n // Silently fail if we can't update .gitignore\n return false;\n }\n}\n\ninterface ClaudeHook {\n type: string;\n command: string;\n}\n\ninterface ClaudeSettings {\n hooks?: {\n Stop?: ClaudeHook[];\n [key: string]: ClaudeHook[] | undefined;\n };\n [key: string]: unknown;\n}\n\nconst RALPH_GATE_HOOK_COMMAND = 'npx ralph-gate --hook';\n\nasync function setupClaudeHook(\n cwd: string,\n): Promise<{ configured: boolean; alreadyExists: boolean }> {\n const claudeDir = path.join(cwd, '.claude');\n const settingsPath = path.join(claudeDir, 'settings.local.json');\n\n try {\n // Ensure .claude directory exists\n await fs.mkdir(claudeDir, { recursive: true });\n\n let settings: ClaudeSettings = {};\n\n // Read existing settings if file exists\n if (await fileExists(settingsPath)) {\n try {\n const content = await fs.readFile(settingsPath, 'utf8');\n const parsed = JSON.parse(content);\n if (parsed && typeof parsed === 'object') {\n settings = parsed as ClaudeSettings;\n }\n } catch {\n // If we can't parse existing file, start fresh but warn\n settings = {};\n }\n }\n\n // Initialize hooks structure if needed\n if (!settings.hooks) {\n settings.hooks = {};\n }\n if (!settings.hooks.Stop) {\n settings.hooks.Stop = [];\n }\n\n // Check if ralph-gate hook already exists\n const hookExists = settings.hooks.Stop.some(\n (hook) =>\n hook.type === 'command' && hook.command === RALPH_GATE_HOOK_COMMAND,\n );\n\n if (hookExists) {\n return { configured: false, alreadyExists: true };\n }\n\n // Add the ralph-gate hook\n settings.hooks.Stop.push({\n type: 'command',\n command: RALPH_GATE_HOOK_COMMAND,\n });\n\n // Write updated settings\n await fs.writeFile(\n settingsPath,\n JSON.stringify(settings, null, 2) + '\\n',\n 'utf8',\n );\n\n return { configured: true, alreadyExists: false };\n } catch {\n // Silently fail if we can't setup hook\n return { configured: false, alreadyExists: false };\n }\n}\n\nexport async function generateGateConfig(cwd: string): Promise<{\n config: GateConfig;\n projectKind: DetectedProject['kind'];\n warnings: string[];\n}> {\n const warnings: string[] = [];\n const detected = await detectProject(cwd);\n\n let gates: Gate[] = [];\n\n if (detected.kind === 'node') {\n gates = await inferNodeGates(\n cwd,\n detected.packageManager,\n detected.packageJson,\n warnings,\n );\n } else if (detected.kind === 'python') {\n gates = inferPythonGates(detected.requirements, warnings);\n } else {\n warnings.push(\n 'No supported project markers found; creating an empty gate config.',\n );\n }\n\n return {\n config: {\n gates,\n failFast: true,\n },\n projectKind: detected.kind,\n warnings,\n };\n}\n\nexport async function initConfigFile(\n options: InitOptions = {},\n): Promise<InitResult> {\n const cwd = options.cwd ?? process.cwd();\n const filename = options.filename ?? DEFAULT_CONFIG_FILENAME;\n const configPath = path.join(cwd, filename);\n\n const { config, projectKind, warnings } = await generateGateConfig(cwd);\n\n if (options.print) {\n return {\n config,\n configPath,\n created: false,\n projectKind,\n warnings,\n };\n }\n\n const writeFlag = options.force ? 'w' : 'wx';\n\n try {\n await fs.writeFile(configPath, JSON.stringify(config, null, 2) + '\\n', {\n encoding: 'utf8',\n flag: writeFlag,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const code = (error as NodeJS.ErrnoException | null)?.code;\n if (!options.force && code === 'EEXIST') {\n return {\n config,\n configPath,\n created: false,\n projectKind,\n warnings,\n error: `Config already exists at ${configPath}. Use --force to overwrite.`,\n };\n }\n return {\n config,\n configPath,\n created: false,\n projectKind,\n warnings,\n error: `Unable to write config at ${configPath}: ${message}`,\n };\n }\n\n // Update .gitignore to include gate result files\n const gitignoreUpdated = await updateGitignore(cwd);\n\n // Setup Claude hook unless skipped\n let hookConfigured: boolean | undefined;\n let hookAlreadyExists: boolean | undefined;\n\n if (!options.skipHook) {\n const hookResult = await setupClaudeHook(cwd);\n hookConfigured = hookResult.configured;\n hookAlreadyExists = hookResult.alreadyExists;\n }\n\n return {\n config,\n configPath,\n created: true,\n projectKind,\n warnings,\n gitignoreUpdated,\n hookConfigured,\n hookAlreadyExists,\n };\n}\n","import { spawn } from 'node:child_process';\nimport type { Gate, GateResult, GateRunSummary } from './types.js';\n\nexport interface RunGatesOptions {\n failFast?: boolean;\n verbose?: boolean;\n shell?: string;\n cwd?: string;\n onGateStart?: (gate: Gate) => void;\n onGateOutput?: (\n gate: Gate,\n stream: 'stdout' | 'stderr',\n text: string,\n ) => void;\n onGateComplete?: (result: GateResult) => void;\n}\n\nfunction resolveShell(shell?: string): string | boolean {\n if (typeof shell === 'string' && shell.length > 0) {\n return shell;\n }\n const envShell = process.env.SHELL;\n return envShell && envShell.length > 0 ? envShell : true;\n}\n\nasync function runGate(\n gate: Gate,\n options: RunGatesOptions,\n): Promise<GateResult> {\n const start = Date.now();\n const shell = resolveShell(options.shell);\n const env = process.env;\n\n return new Promise((resolve) => {\n options.onGateStart?.(gate);\n const child = spawn(gate.command, {\n shell,\n env,\n cwd: options.cwd,\n });\n\n let stdout = '';\n let stderr = '';\n let exitCode: number | null = null;\n let resolved = false;\n\n const finalize = () => {\n if (resolved) {\n return;\n }\n resolved = true;\n const durationMs = Date.now() - start;\n const result: GateResult = {\n name: gate.name,\n passed: exitCode === 0,\n exitCode,\n stdout,\n stderr,\n durationMs,\n skipped: false,\n blocking: gate.blocking !== false,\n timestamp: new Date().toISOString(),\n };\n options.onGateComplete?.(result);\n resolve(result);\n };\n\n child.stdout?.on('data', (chunk) => {\n const text = chunk.toString();\n stdout += text;\n if (options.verbose) {\n process.stdout.write(text);\n }\n options.onGateOutput?.(gate, 'stdout', text);\n });\n\n child.stderr?.on('data', (chunk) => {\n const text = chunk.toString();\n stderr += text;\n if (options.verbose) {\n process.stderr.write(text);\n }\n options.onGateOutput?.(gate, 'stderr', text);\n });\n\n child.on('error', (error) => {\n stderr += error.message;\n exitCode = null;\n finalize();\n });\n\n child.on('close', (code) => {\n exitCode = code;\n finalize();\n });\n });\n}\n\nexport async function runGates(\n gates: Gate[],\n options: RunGatesOptions = {},\n): Promise<GateRunSummary> {\n const results: GateResult[] = [];\n const warnings: string[] = [];\n const start = Date.now();\n let firstFailure: GateResult | null = null;\n\n for (const gate of gates) {\n const isBlocking = gate.blocking !== false;\n const shouldSkip =\n options.failFast !== false && firstFailure !== null && isBlocking;\n\n if (shouldSkip) {\n const skippedResult: GateResult = {\n name: gate.name,\n passed: true,\n exitCode: null,\n stdout: '',\n stderr: '',\n durationMs: 0,\n skipped: true,\n blocking: isBlocking,\n timestamp: new Date().toISOString(),\n };\n results.push(skippedResult);\n options.onGateComplete?.(skippedResult);\n continue;\n }\n\n const result = await runGate(gate, options);\n results.push(result);\n\n if (!result.passed) {\n if (result.blocking) {\n if (!firstFailure) {\n firstFailure = result;\n }\n } else {\n warnings.push(result.name);\n }\n }\n }\n\n const totalDurationMs = Date.now() - start;\n const passed = firstFailure === null;\n\n return {\n passed,\n timestamp: new Date().toISOString(),\n totalDurationMs,\n results,\n firstFailure,\n warnings,\n };\n}\n","import { promises as fs } from 'node:fs';\nimport type { GateResult, GateRunSummary } from './types.js';\n\nconst MAX_FAILURE_CHARS = 4000;\nconst HEAD_RATIO = 0.6;\n\nfunction truncateOutput(text: string, maxChars: number): string {\n const trimmed = text.trimEnd();\n if (maxChars <= 0 || trimmed.length === 0) {\n return '';\n }\n if (trimmed.length <= maxChars) {\n return trimmed;\n }\n const headChars = Math.max(1, Math.floor(maxChars * HEAD_RATIO));\n const tailChars = Math.max(0, maxChars - headChars);\n const omitted = trimmed.length - maxChars;\n const marker = `\\n...<${omitted} chars omitted>...\\n`;\n const head = trimmed.slice(0, headChars);\n const tail = tailChars > 0 ? trimmed.slice(-tailChars) : '';\n return `${head}${marker}${tail}`;\n}\n\nfunction splitBudget(\n stdoutLen: number,\n stderrLen: number,\n): {\n stdout: number;\n stderr: number;\n} {\n if (stdoutLen === 0 && stderrLen === 0) {\n return { stdout: 0, stderr: 0 };\n }\n if (stdoutLen === 0) {\n return { stdout: 0, stderr: MAX_FAILURE_CHARS };\n }\n if (stderrLen === 0) {\n return { stdout: MAX_FAILURE_CHARS, stderr: 0 };\n }\n\n const base = Math.floor(MAX_FAILURE_CHARS / 2);\n let stdout = Math.min(stdoutLen, base);\n let stderr = Math.min(stderrLen, base);\n let remaining = MAX_FAILURE_CHARS - stdout - stderr;\n\n if (remaining > 0) {\n const stdoutRemaining = stdoutLen - stdout;\n const stderrRemaining = stderrLen - stderr;\n if (stdoutRemaining === 0) {\n stderr += remaining;\n } else if (stderrRemaining === 0) {\n stdout += remaining;\n } else {\n const totalRemaining = stdoutRemaining + stderrRemaining;\n const stdoutExtra = Math.round(\n (stdoutRemaining / totalRemaining) * remaining,\n );\n stdout += stdoutExtra;\n stderr += remaining - stdoutExtra;\n }\n }\n\n return { stdout, stderr };\n}\n\nfunction colorize(text: string, code: string, enabled: boolean): string {\n if (!enabled) {\n return text;\n }\n return `\\u001b[${code}m${text}\\u001b[0m`;\n}\n\nfunction formatResultLine(result: GateResult, color: boolean): string {\n const statusSymbol = result.skipped ? '⊘' : result.passed ? '✓' : '✗';\n\n let symbolColor = '32';\n if (result.skipped) {\n symbolColor = '90';\n } else if (!result.passed) {\n symbolColor = '31';\n }\n\n const parts: string[] = [];\n if (result.skipped) {\n parts.push('skipped');\n } else if (!result.passed) {\n parts.push(`exit ${result.exitCode ?? 'null'}`);\n }\n parts.push(`${result.durationMs}ms`);\n\n const details = parts.length > 0 ? ` (${parts.join(', ')})` : '';\n const coloredSymbol = colorize(statusSymbol, symbolColor, color);\n return `${coloredSymbol} ${result.name}${details}`;\n}\n\nexport function formatFailureContext(stderr: string, stdout = ''): string {\n const trimmedStderr = stderr.trimEnd();\n const trimmedStdout = stdout.trimEnd();\n\n if (trimmedStderr.length === 0 && trimmedStdout.length === 0) {\n return 'No output captured.';\n }\n\n if (trimmedStderr.length > 0 && trimmedStdout.length > 0) {\n const budget = splitBudget(trimmedStdout.length, trimmedStderr.length);\n const stderrSection = truncateOutput(trimmedStderr, budget.stderr);\n const stdoutSection = truncateOutput(trimmedStdout, budget.stdout);\n return `STDERR:\\n${stderrSection}\\n\\nSTDOUT:\\n${stdoutSection}`;\n }\n\n if (trimmedStderr.length > 0) {\n return truncateOutput(trimmedStderr, MAX_FAILURE_CHARS);\n }\n\n return truncateOutput(trimmedStdout, MAX_FAILURE_CHARS);\n}\n\nexport function formatConsoleOutput(summary: GateRunSummary): string {\n const color = Boolean(process.stdout.isTTY);\n const lines: string[] = [];\n\n for (const result of summary.results) {\n lines.push(formatResultLine(result, color));\n }\n\n if (summary.warnings.length > 0) {\n const warningLine = `Warnings: ${summary.warnings.join(', ')}`;\n lines.push(colorize(warningLine, '33', color));\n }\n\n const finalLine = summary.passed\n ? colorize('All blocking gates passed.', '32', color)\n : colorize('Blocking gate failed.', '31', color);\n lines.push(finalLine);\n\n return lines.join('\\n');\n}\n\nexport async function writeResultsFile(\n summary: GateRunSummary,\n outputPath: string,\n): Promise<void> {\n const data = JSON.stringify(summary, null, 2);\n await fs.writeFile(outputPath, data, 'utf8');\n}\n","import type { GateRunSummary, HookOutput } from './types.js';\nimport { formatFailureContext } from './output.js';\n\nexport function generateHookResponse(summary: GateRunSummary): HookOutput {\n const warnings = summary.warnings.length > 0 ? summary.warnings : undefined;\n\n if (summary.passed) {\n return warnings ? { warnings } : {};\n }\n\n const failure = summary.firstFailure;\n if (failure) {\n const reason = `Gate '${failure.name}' failed (exit ${failure.exitCode ?? 'null'}):\\n${formatFailureContext(failure.stderr, failure.stdout)}`;\n return warnings\n ? { decision: 'block', reason, warnings }\n : { decision: 'block', reason };\n }\n\n const reason = 'Gate run failed without a blocking gate result.';\n return warnings\n ? { decision: 'block', reason, warnings }\n : { decision: 'block', reason };\n}\n\nexport function outputHookResponse(output: HookOutput): void {\n process.stdout.write(`${JSON.stringify(output)}\\n`);\n}\n"],"mappings":"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","names":["path","fs","path","fs","reason","options","error","path","summary","outputPath","shellLabel"]}
|