/**
* ROLE: INFRASTRUCTURE
* PURPOSE: Safe-halt protocol for catastrophic failures
* AUTHORITY: MCP CATASTROPHIC FAILURE SPEC
*
* Safe-halt routine:
* 1. Flush audit buffers
* 2. Seal current audit chain
* 3. Write a HALT REPORT with:
* - What failed
* - Why the system halted
* - What is safe to do next
* - What is explicitly forbidden
* 4. No auto-recovery
*/
import fs from "fs";
import path from "path";
import { readAuditLog, verifyAuditLogIntegrity } from "./audit-system.js";
import { getRepoRoot } from "./path-resolver.js";
const HALT_REPORTS_DIR = "docs/reports";
/**
* Generate halt report
*/
export function generateHaltReport(config = {}) {
const {
failure_ids = [],
failure_descriptions = [],
failure_summary = "Unknown failure",
invariant_ids = [],
trigger_reason = null,
triggered_by_role = null,
triggered_by_tool = null,
context = {}
} = config;
const timestamp = new Date().toISOString();
const filename = `HALT_REPORT_${timestamp.replace(/[:.]/g, "-")}.md`;
let report = `# HALT REPORT
**Generated:** ${timestamp}
## What Failed
${
failure_ids.length > 0
? `**Failure IDs:** ${failure_ids.join(", ")}\n`
: ""
}${
invariant_ids.length > 0
? `**Invariant IDs:** ${invariant_ids.join(", ")}\n`
: ""
}
**Summary:** ${failure_summary}
${
failure_descriptions.length > 0
? `### Details\n\n${failure_descriptions.map(d => `- ${d}`).join("\n")}\n`
: ""
}
## Why the System Halted
The system triggered a global kill-switch because:
1. One or more critical invariants were violated
2. The system cannot guarantee safe continued operation
3. Data integrity may be compromised
4. Manual human intervention is required
### Trigger Information
${triggered_by_tool ? `- **Triggered by Tool:** ${triggered_by_tool}\n` : ""}${
triggered_by_role ? `- **Triggered by Role:** ${triggered_by_role}\n` : ""
}${trigger_reason ? `- **Trigger Reason:** ${trigger_reason}\n` : ""}
## What is Safe to Do Next
✓ **SAFE OPERATIONS:**
- Read audit log (for forensic analysis)
- Read plan files
- Read workspace files
- Generate attestation bundles
- Run verification tools (read-only)
- Inspect workspace integrity
## What is Explicitly FORBIDDEN
✗ **FORBIDDEN OPERATIONS:**
- Writing to workspace files
- Creating new plans
- Executing plans
- Bootstrapping new plans
- Any mutation of state
**Reason:** Until all recovery verifications pass, the system is in an unsafe state.
## Recovery Path
To recover from this halt:
1. **Read the full audit log** to understand what went wrong
2. **Investigate the root cause** using forensic tools
3. **Fix the underlying issue** (code bug, corrupted file, policy violation, etc)
4. **Acknowledge this halt report** explicitly (human confirmation required)
5. **Run required verifications:**
- Verify audit log integrity (audit_verify)
- Run plan linting (plan_lint)
- Recompute maturity score (maturity_recompute)
6. **Only after all verifications pass,** unlock the kill-switch
## Evidence
### Audit Log Status
${context.auditStatus ? JSON.stringify(context.auditStatus, null, 2) : "Not available"}
### Workspace State
${
context.workspaceRoot
? `**Root:** ${context.workspaceRoot}\n`
: ""
}${
context.sessionId
? `**Session:** ${context.sessionId}\n`
: ""
}
---
**Do not edit this file.** It is evidence of a critical system event.
`;
return { filename, report, timestamp };
}
/**
* Write halt report to disk
*/
export function writeHaltReport(workspaceRoot, config = {}) {
const { filename, report } = generateHaltReport(config);
const reportsDir = path.join(workspaceRoot, HALT_REPORTS_DIR);
// Ensure directory exists
if (!fs.existsSync(reportsDir)) {
fs.mkdirSync(reportsDir, { recursive: true });
}
const filePath = path.join(reportsDir, filename);
try {
fs.writeFileSync(filePath, report, "utf8");
return {
success: true,
path: filePath,
filename,
url: `${reportsDir}/${filename}`
};
} catch (err) {
console.error(`[ERROR] Failed to write halt report: ${err.message}`);
// Re-throw for governance compliance - halt report write must not fail silently
throw new Error(`HALT_REPORT_WRITE_FAILED: ${err.message}`);
}
}
/**
* Execute safe-halt routine
*
* This should be called when a critical failure is detected.
*/
export function executeSafeHalt(workspaceRoot, config = {}) {
console.error("[SAFE-HALT] Beginning safe-halt routine...");
const auditLog = readAuditLog(workspaceRoot);
const auditStatus = verifyAuditLogIntegrity(workspaceRoot);
console.error(`[SAFE-HALT] Audit log: ${auditLog.count} entries`);
console.error(`[SAFE-HALT] Audit integrity: ${auditStatus.status}`);
// Write halt report
const reportResult = writeHaltReport(workspaceRoot, {
...config,
context: {
workspaceRoot,
sessionId: config.session_id,
auditStatus
}
});
if (!reportResult.success) {
console.error(`[SAFE-HALT] WARNING: Failed to write halt report: ${reportResult.error}`);
} else {
console.error(`[SAFE-HALT] Halt report written to: ${reportResult.path}`);
}
return {
halted: true,
timestamp: new Date().toISOString(),
audit_entries: auditLog.count,
audit_integrity: auditStatus,
halt_report: reportResult
};
}
/**
* List all halt reports
*/
export function listHaltReports(workspaceRoot) {
const reportsDir = path.join(workspaceRoot, HALT_REPORTS_DIR);
if (!fs.existsSync(reportsDir)) {
return [];
}
try {
const files = fs.readdirSync(reportsDir);
return files
.filter(f => f.startsWith("HALT_REPORT_"))
.sort()
.reverse();
} catch (err) {
console.error(`[ERROR] Failed to list halt reports: ${err.message}`);
// Re-throw for governance compliance - listing errors must propagate
throw new Error(`HALT_REPORTS_LIST_FAILED: ${err.message}`);
}
}
/**
* Read a halt report
*/
export function readHaltReport(workspaceRoot, filename) {
const filePath = path.join(workspaceRoot, HALT_REPORTS_DIR, filename);
if (!fs.existsSync(filePath)) {
return null;
}
try {
return fs.readFileSync(filePath, "utf8");
} catch (err) {
console.error(`[ERROR] Failed to read halt report: ${err.message}`);
// Re-throw for governance compliance - read errors must propagate
throw new Error(`HALT_REPORT_READ_FAILED: ${err.message}`);
}
}