#!/usr/bin/env ts-node import * as path from 'path'; import { promises as fs } from 'fs'; type WorkflowOverallStatus = 'idle' | 'running' | 'blocked' | 'failed' | 'completed'; type WorkflowStatusFile = { overallStatus?: string; }; const DEFAULT_STATUS_PATH = path.join(process.cwd(), 'status', 'workflow-status.json'); const HEALTHY_STATES = new Set(['running', 'completed', 'idle']); const UNHEALTHY_STATES = new Set(['failed', 'blocked']); function getStatusPathFromArgs(argv: string[]): string { for (let i = 0; i < argv.length; i += 1) { if (argv[i] === '--status' && argv[i + 1]) { return argv[i + 1]; } } return DEFAULT_STATUS_PATH; } async function readOverallStatus(statusPath: string): Promise { const raw = await fs.readFile(statusPath, 'utf8'); const parsed = JSON.parse(raw) as WorkflowStatusFile; return String(parsed.overallStatus ?? '').trim(); } export async function checkWorkflowHealth(statusPath = DEFAULT_STATUS_PATH): Promise { try { const overallStatus = await readOverallStatus(statusPath); if (HEALTHY_STATES.has(overallStatus as WorkflowOverallStatus)) { console.log(JSON.stringify({ ok: true, status: overallStatus })); return 0; } if (UNHEALTHY_STATES.has(overallStatus as WorkflowOverallStatus)) { console.log(JSON.stringify({ ok: false, status: overallStatus })); return 1; } console.log(JSON.stringify({ ok: false, status: overallStatus || 'unknown', error: 'unknown_status' })); return 1; } catch (error) { const message = error instanceof Error ? error.message : String(error); console.log(JSON.stringify({ ok: false, error: 'status_read_failed', message })); return 1; } } if (import.meta.url === `file://${process.argv[1]}`) { const statusPath = getStatusPathFromArgs(process.argv.slice(2)); checkWorkflowHealth(statusPath).then((code) => { process.exitCode = code; }); }