d6ba76e660
---ci---
project: ci
phase: 1
milestone: v0.8
status: in_progress
decisions:
- id: D-026
decision: Graceful drain on SIGTERM/SIGINT: dispose timers then exit
rationale: Prevents orphaned setTimeout timers from leaking when process is killed
confidence: 0.88
requirements:
covered: [FIX-07]
---/ci---
FIX-07: cli/index.ts registers SIGTERM/SIGINT handlers that call
escalationProtocol.dispose() before process.exit. OrchestratorAgent
registers its EscalationProtocol instance via registerEscalationProtocol().
SIGINT exits with code 130, SIGTERM with 143 (standard signal+128 convention).
68 lines
2.0 KiB
JavaScript
68 lines
2.0 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { Command } from "commander";
|
|
import { VERSION } from "../version.js";
|
|
import { CIAgentFiles } from "../core/ciagent-files.js";
|
|
import { isCIAgentInitialized } from "../core/config.js";
|
|
import {
|
|
createInitCommand,
|
|
createRunCommand,
|
|
createQuickCommand,
|
|
createDebugCommand,
|
|
createVerifyCommand,
|
|
createReviewCommand,
|
|
createStatusCommand,
|
|
createAuditCommand,
|
|
createClarifyCommand,
|
|
createRollbackCommand,
|
|
createShipCommand,
|
|
createProjectsCommand,
|
|
} from "./commands.js";
|
|
|
|
let activeEscalationProtocol: { dispose(): void } | null = null;
|
|
|
|
export function registerEscalationProtocol(protocol: { dispose(): void }): void {
|
|
activeEscalationProtocol = protocol;
|
|
}
|
|
|
|
function gracefulShutdown(signal: string): void {
|
|
if (activeEscalationProtocol) {
|
|
try {
|
|
activeEscalationProtocol.dispose();
|
|
} catch {}
|
|
activeEscalationProtocol = null;
|
|
}
|
|
process.exit(signal === "SIGINT" ? 130 : 143);
|
|
}
|
|
|
|
process.on("SIGINT", () => gracefulShutdown("SIGINT"));
|
|
process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
|
|
|
|
const program = new Command();
|
|
|
|
program
|
|
.name("ciagent")
|
|
.description("CIAgent — Continuous Intelligence: autonomous AI-driven software engineering harness")
|
|
.version(VERSION)
|
|
.option("--project <slug>", "Specify which project to operate on")
|
|
.hook("preAction", () => {
|
|
const opts = program.opts();
|
|
if (opts.project && isCIAgentInitialized(process.cwd())) {
|
|
const ciFiles = new CIAgentFiles(process.cwd());
|
|
ciFiles.setProjectSlug(opts.project);
|
|
}
|
|
})
|
|
.addCommand(createInitCommand())
|
|
.addCommand(createRunCommand())
|
|
.addCommand(createQuickCommand())
|
|
.addCommand(createDebugCommand())
|
|
.addCommand(createVerifyCommand())
|
|
.addCommand(createReviewCommand())
|
|
.addCommand(createStatusCommand())
|
|
.addCommand(createAuditCommand())
|
|
.addCommand(createClarifyCommand())
|
|
.addCommand(createRollbackCommand())
|
|
.addCommand(createShipCommand())
|
|
.addCommand(createProjectsCommand());
|
|
|
|
program.parse(); |