mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-14 18:44:44 +08:00
feat: add markdown status snapshots
This commit is contained in:
parent
4449bc77ce
commit
d2760d0359
@ -94,6 +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.
|
- **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.
|
- **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.
|
- **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 active sessions, skill-run health, install health, and pending governance events.
|
||||||
- **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.
|
- **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)
|
### v1.9.0 — Selective Install & Language Expansion (Mar 2026)
|
||||||
|
|||||||
@ -108,6 +108,7 @@ Examples:
|
|||||||
ecc repair --dry-run
|
ecc repair --dry-run
|
||||||
ecc auto-update --dry-run
|
ecc auto-update --dry-run
|
||||||
ecc status --json
|
ecc status --json
|
||||||
|
ecc status --markdown --write status.md
|
||||||
ecc sessions
|
ecc sessions
|
||||||
ecc sessions session-active --json
|
ecc sessions session-active --json
|
||||||
ecc session-inspect claude:latest
|
ecc session-inspect claude:latest
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
const path = require('path');
|
||||||
const { createStateStore } = require('./lib/state-store');
|
const { createStateStore } = require('./lib/state-store');
|
||||||
|
|
||||||
function showHelp(exitCode = 0) {
|
function showHelp(exitCode = 0) {
|
||||||
console.log(`
|
console.log(`
|
||||||
Usage: node scripts/status.js [--db <path>] [--json] [--limit <n>]
|
Usage: node scripts/status.js [--db <path>] [--json|--markdown] [--write <path>] [--limit <n>]
|
||||||
|
|
||||||
Query the ECC SQLite state store for active sessions, recent skill runs,
|
Query the ECC SQLite state store for active sessions, recent skill runs,
|
||||||
install health, and pending governance events.
|
install health, and pending governance events.
|
||||||
@ -19,6 +21,8 @@ function parseArgs(argv) {
|
|||||||
const parsed = {
|
const parsed = {
|
||||||
dbPath: null,
|
dbPath: null,
|
||||||
json: false,
|
json: false,
|
||||||
|
markdown: false,
|
||||||
|
writePath: null,
|
||||||
help: false,
|
help: false,
|
||||||
limit: 5,
|
limit: 5,
|
||||||
};
|
};
|
||||||
@ -31,6 +35,11 @@ function parseArgs(argv) {
|
|||||||
index += 1;
|
index += 1;
|
||||||
} else if (arg === '--json') {
|
} else if (arg === '--json') {
|
||||||
parsed.json = true;
|
parsed.json = true;
|
||||||
|
} else if (arg === '--markdown') {
|
||||||
|
parsed.markdown = true;
|
||||||
|
} else if (arg === '--write') {
|
||||||
|
parsed.writePath = args[index + 1] || null;
|
||||||
|
index += 1;
|
||||||
} else if (arg === '--limit') {
|
} else if (arg === '--limit') {
|
||||||
parsed.limit = args[index + 1] || null;
|
parsed.limit = args[index + 1] || null;
|
||||||
index += 1;
|
index += 1;
|
||||||
@ -41,6 +50,22 @@ function parseArgs(argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parsed.json && parsed.markdown) {
|
||||||
|
throw new Error('Choose only one output format: --json or --markdown');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.includes('--db') && !parsed.dbPath) {
|
||||||
|
throw new Error('Missing value for --db');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.includes('--write') && !parsed.writePath) {
|
||||||
|
throw new Error('Missing value for --write');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.includes('--limit') && !parsed.limit) {
|
||||||
|
throw new Error('Missing value for --limit');
|
||||||
|
}
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,6 +154,108 @@ function printHuman(payload) {
|
|||||||
printGovernance(payload.governance);
|
printGovernance(payload.governance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatPercent(value) {
|
||||||
|
return value === null ? 'n/a' : `${value}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatCode(value) {
|
||||||
|
return `\`${String(value || '').replace(/`/g, '\\`')}\``;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderMarkdown(payload) {
|
||||||
|
const lines = [
|
||||||
|
'# ECC Status',
|
||||||
|
'',
|
||||||
|
`Generated: ${payload.generatedAt}`,
|
||||||
|
`Database: ${formatCode(payload.dbPath)}`,
|
||||||
|
'',
|
||||||
|
'## Active Sessions',
|
||||||
|
'',
|
||||||
|
`Active sessions: ${payload.activeSessions.activeCount}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (payload.activeSessions.sessions.length === 0) {
|
||||||
|
lines.push('- none');
|
||||||
|
} else {
|
||||||
|
for (const session of payload.activeSessions.sessions) {
|
||||||
|
lines.push(`- ${formatCode(session.id)} [${session.harness}/${session.adapterId}] ${session.state}`);
|
||||||
|
lines.push(` - Repo: ${session.repoRoot || '(unknown)'}`);
|
||||||
|
lines.push(` - Started: ${session.startedAt || '(unknown)'}`);
|
||||||
|
lines.push(` - Workers: ${session.workerCount}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const skillSummary = payload.skillRuns.summary;
|
||||||
|
lines.push(
|
||||||
|
'',
|
||||||
|
'## Skill Runs',
|
||||||
|
'',
|
||||||
|
`Window size: ${payload.skillRuns.windowSize}`,
|
||||||
|
`Success: ${skillSummary.successCount}`,
|
||||||
|
`Failure: ${skillSummary.failureCount}`,
|
||||||
|
`Unknown: ${skillSummary.unknownCount}`,
|
||||||
|
`Success rate: ${formatPercent(skillSummary.successRate)}`,
|
||||||
|
`Failure rate: ${formatPercent(skillSummary.failureRate)}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (payload.skillRuns.recent.length === 0) {
|
||||||
|
lines.push('', 'Recent runs: none');
|
||||||
|
} else {
|
||||||
|
lines.push('', 'Recent runs:');
|
||||||
|
for (const skillRun of payload.skillRuns.recent.slice(0, 5)) {
|
||||||
|
lines.push(`- ${formatCode(skillRun.id)} ${skillRun.outcome} ${skillRun.skillId}@${skillRun.skillVersion}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push(
|
||||||
|
'',
|
||||||
|
'## Install Health',
|
||||||
|
'',
|
||||||
|
`Install health: ${payload.installHealth.status}`,
|
||||||
|
`Targets recorded: ${payload.installHealth.totalCount}`,
|
||||||
|
`Healthy: ${payload.installHealth.healthyCount}`,
|
||||||
|
`Warning: ${payload.installHealth.warningCount}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (payload.installHealth.installations.length === 0) {
|
||||||
|
lines.push('', 'Installations: none');
|
||||||
|
} else {
|
||||||
|
lines.push('', 'Installations:');
|
||||||
|
for (const installation of payload.installHealth.installations.slice(0, 5)) {
|
||||||
|
lines.push(`- ${formatCode(installation.targetId)} ${installation.status}`);
|
||||||
|
lines.push(` - Root: ${installation.targetRoot}`);
|
||||||
|
lines.push(` - Profile: ${installation.profile || '(custom)'}`);
|
||||||
|
lines.push(` - Modules: ${installation.moduleCount}`);
|
||||||
|
lines.push(` - Source version: ${installation.sourceVersion || '(unknown)'}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push(
|
||||||
|
'',
|
||||||
|
'## Governance',
|
||||||
|
'',
|
||||||
|
`Pending governance events: ${payload.governance.pendingCount}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (payload.governance.events.length === 0) {
|
||||||
|
lines.push('- none');
|
||||||
|
} else {
|
||||||
|
for (const event of payload.governance.events) {
|
||||||
|
lines.push(`- ${formatCode(event.id)} ${event.eventType}`);
|
||||||
|
lines.push(` - Session: ${event.sessionId || '(none)'}`);
|
||||||
|
lines.push(` - Created: ${event.createdAt}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${lines.join('\n')}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeOutput(writePath, output) {
|
||||||
|
const absolutePath = path.resolve(writePath);
|
||||||
|
fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
|
||||||
|
fs.writeFileSync(absolutePath, output, 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
let store = null;
|
let store = null;
|
||||||
|
|
||||||
@ -153,8 +280,21 @@ async function main() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (options.json) {
|
if (options.json) {
|
||||||
console.log(JSON.stringify(payload, null, 2));
|
const output = `${JSON.stringify(payload, null, 2)}\n`;
|
||||||
|
if (options.writePath) {
|
||||||
|
writeOutput(options.writePath, output);
|
||||||
|
}
|
||||||
|
process.stdout.write(output);
|
||||||
|
} else if (options.markdown) {
|
||||||
|
const output = renderMarkdown(payload);
|
||||||
|
if (options.writePath) {
|
||||||
|
writeOutput(options.writePath, output);
|
||||||
|
}
|
||||||
|
process.stdout.write(output);
|
||||||
} else {
|
} else {
|
||||||
|
if (options.writePath) {
|
||||||
|
throw new Error('--write requires --json or --markdown');
|
||||||
|
}
|
||||||
printHuman(payload);
|
printHuman(payload);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -174,4 +314,5 @@ if (require.main === module) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
main,
|
main,
|
||||||
parseArgs,
|
parseArgs,
|
||||||
|
renderMarkdown,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -576,6 +576,31 @@ async function runTests() {
|
|||||||
}
|
}
|
||||||
})) passed += 1; else failed += 1;
|
})) 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');
|
||||||
|
const outputPath = path.join(testDir, 'status.md');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await seedStore(dbPath);
|
||||||
|
|
||||||
|
const result = runNode(STATUS_SCRIPT, ['--db', dbPath, '--markdown', '--write', outputPath]);
|
||||||
|
assert.strictEqual(result.status, 0, result.stderr);
|
||||||
|
assert.ok(fs.existsSync(outputPath));
|
||||||
|
|
||||||
|
const written = fs.readFileSync(outputPath, 'utf8');
|
||||||
|
assert.strictEqual(result.stdout, written);
|
||||||
|
assert.match(written, /^# ECC Status/m);
|
||||||
|
assert.match(written, /Database: `[^`]+state\.db`/);
|
||||||
|
assert.match(written, /- `session-active` \[claude\/dmux-tmux\] active/);
|
||||||
|
assert.match(written, /Success rate: 66\.7%/);
|
||||||
|
assert.match(written, /Install health: healthy/);
|
||||||
|
assert.match(written, /Pending governance events: 1/);
|
||||||
|
} finally {
|
||||||
|
cleanupTempDir(testDir);
|
||||||
|
}
|
||||||
|
})) passed += 1; else failed += 1;
|
||||||
|
|
||||||
if (await test('sessions CLI supports list and detail views in human-readable and --json output', async () => {
|
if (await test('sessions CLI supports list and detail views in human-readable and --json output', async () => {
|
||||||
const testDir = createTempDir('ecc-state-cli-');
|
const testDir = createTempDir('ecc-state-cli-');
|
||||||
const dbPath = path.join(testDir, 'state.db');
|
const dbPath = path.join(testDir, 'state.db');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user