feat: add status exit code gate

This commit is contained in:
Affaan Mustafa 2026-05-11 12:27:06 -04:00 committed by Affaan Mustafa
parent b1e67788f7
commit 9887ba6123
4 changed files with 40 additions and 2 deletions

View File

@ -94,7 +94,7 @@ This repo is the raw code only. The guides explain everything.
- **Media and launch tooling**`manim-video`, `remotion-video-creation`, and upgraded social publishing surfaces make technical explainers and launch content part of the same system.
- **Framework and product surface growth**`nestjs-patterns`, richer Codex/OpenCode install surfaces, and expanded cross-harness packaging keep the repo usable beyond Claude Code alone.
- **ECC 2.0 alpha is in-tree** — the Rust control-plane prototype in `ecc2/` now builds locally and exposes `dashboard`, `start`, `sessions`, `status`, `stop`, `resume`, and `daemon` commands. It is usable as an alpha, not yet a general release.
- **Operator status snapshots**`ecc status --markdown --write status.md` turns the local state store into a portable handoff covering readiness, active sessions, skill-run health, install health, pending governance events, and linked work items from Linear/GitHub/handoffs. Use `ecc work-items upsert ...` to add or update those linked work items from the CLI.
- **Operator status snapshots**`ecc status --markdown --write status.md` turns the local state store into a portable handoff covering readiness, active sessions, skill-run health, install health, pending governance events, and linked work items from Linear/GitHub/handoffs. Use `ecc work-items upsert ...` to add or update those linked work items from the CLI, and `ecc status --exit-code` to fail automation when readiness needs attention.
- **Ecosystem hardening** — AgentShield, ECC Tools cost controls, billing portal work, and website refreshes continue to ship around the core plugin instead of drifting into separate silos.
### v1.9.0 — Selective Install & Language Expansion (Mar 2026)

View File

@ -113,6 +113,7 @@ Examples:
ecc repair --dry-run
ecc auto-update --dry-run
ecc status --json
ecc status --exit-code
ecc status --markdown --write status.md
ecc sessions
ecc sessions session-active --json

View File

@ -8,10 +8,12 @@ const { createStateStore } = require('./lib/state-store');
function showHelp(exitCode = 0) {
console.log(`
Usage: node scripts/status.js [--db <path>] [--json|--markdown] [--write <path>] [--limit <n>]
Usage: node scripts/status.js [--db <path>] [--json|--markdown] [--write <path>] [--limit <n>] [--exit-code]
Query the ECC SQLite state store for active sessions, recent skill runs,
install health, pending governance events, and linked work items.
Use --exit-code to return 2 when readiness needs attention.
`);
process.exit(exitCode);
}
@ -23,6 +25,7 @@ function parseArgs(argv) {
json: false,
markdown: false,
writePath: null,
exitCode: false,
help: false,
limit: 5,
};
@ -37,6 +40,8 @@ function parseArgs(argv) {
parsed.json = true;
} else if (arg === '--markdown') {
parsed.markdown = true;
} else if (arg === '--exit-code') {
parsed.exitCode = true;
} else if (arg === '--write') {
parsed.writePath = args[index + 1] || null;
index += 1;
@ -364,6 +369,10 @@ async function main() {
}
printHuman(payload);
}
if (options.exitCode && payload.readiness.status !== 'ok') {
process.exitCode = 2;
}
} catch (error) {
console.error(`Error: ${error.message}`);
process.exit(1);

View File

@ -667,6 +667,34 @@ async function runTests() {
}
})) passed += 1; else failed += 1;
if (await test('status CLI --exit-code reports attention without suppressing output', async () => {
const attentionDir = createTempDir('ecc-state-attention-');
const okDir = createTempDir('ecc-state-ok-');
const attentionDbPath = path.join(attentionDir, 'state.db');
const okDbPath = path.join(okDir, 'state.db');
try {
await seedStore(attentionDbPath);
const attentionResult = runNode(STATUS_SCRIPT, ['--db', attentionDbPath, '--json', '--exit-code']);
assert.strictEqual(attentionResult.status, 2, attentionResult.stderr);
const attentionPayload = parseJson(attentionResult.stdout);
assert.strictEqual(attentionPayload.readiness.status, 'attention');
assert.strictEqual(attentionPayload.readiness.attentionCount, 2);
const okStore = await createStateStore({ dbPath: okDbPath });
okStore.close();
const okResult = runNode(STATUS_SCRIPT, ['--db', okDbPath, '--json', '--exit-code']);
assert.strictEqual(okResult.status, 0, okResult.stderr);
const okPayload = parseJson(okResult.stdout);
assert.strictEqual(okPayload.readiness.status, 'ok');
} finally {
cleanupTempDir(attentionDir);
cleanupTempDir(okDir);
}
})) passed += 1; else failed += 1;
if (await test('status CLI can emit and write markdown operator snapshots', async () => {
const testDir = createTempDir('ecc-state-cli-');
const dbPath = path.join(testDir, 'state.db');