ooda-status — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ooda-status (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Display the current state of the OODA-loop at a glance.
Check for the HALT file before anything else.
ls agent/safety/HALT 2>/dev/null && echo "HALT_ACTIVE" || echo "HALT_INACTIVE"If HALT exists, continue rendering the dashboard but mark HALT status as "ACTIVE". Do not abort — status must always be readable regardless of HALT state.
Read each file below. If a file is missing, note it and use a safe default value. If a file exists but contains invalid JSON (parse error), treat it the same as missing and append an alert: [WARN] Corrupt state file: <path> — skipped (parse error). Do not let a single corrupt file abort the entire dashboard.
config.json — project name, current level, cost limit, domain list, domain status fields
cat config.json 2>/dev/null || echo "MISSING"Also read config.mission (the project's purpose the loop drives toward) and each domain's mission_alignment.
Read each domain's status field from config.json to identify which domains are "available" (not yet configured) vs "active" vs "disabled".
agent/state/evolve/state.json — cycle_count, last_cycle timestamp
cat agent/state/evolve/state.json 2>/dev/null || echo "MISSING"agent/state/evolve/confidence.json — per-domain confidence scores (0.0–1.0)
cat agent/state/evolve/confidence.json 2>/dev/null || echo "MISSING"agent/state/evolve/action_queue.json — pending and proposed action counts, top action
cat agent/state/evolve/action_queue.json 2>/dev/null || echo "MISSING"agent/state/evolve/metrics.json — execution counters/streaks (under counters)
cat agent/state/evolve/metrics.json 2>/dev/null || echo "MISSING"Cost source: today's spend comes from agent/state/evolve/cost_ledger.json (total_estimated_usd, after confirming date == today UTC; stale date ⇒ $0.00 pending reset) and the limit from config.cost.daily_limit_usd. metrics.json has NO cost fields — never read cost from it.
Domain state files — for each domain in config.domains, read its state_file path:
# Example: cat agent/state/health/state.json 2>/dev/nullTime formatting — compute elapsed time from last_run or last_cycle to now:
XmXhXd—Domain status symbol:
✓ if status is healthy⚠ if status is degraded✗ if status is critical or error? if domain has never run or state file is missingScore — numeric value from domain state, formatted to 2 decimal places. Show — if unavailable.
Confidence — value from confidence.json for this domain (e.g. 0.9). Show — if unavailable.
Actions — count items in action_queue.json by status field: pending vs proposed. Top action: first item sorted by RICE score descending.
Alerts — collect all alerts arrays from domain state files. Count total. Show none if count is 0, otherwise show the count.
Cost — cost_ledger.json.total_estimated_usd (if date == today UTC, else $0.00) / config.cost.daily_limit_usd. Show —/— if unavailable.
Orient Health (v1.2.0) — parsed from the Orient layer state files:
episodes_count and last_episode_week — from episodes.json.episodes[].Show 0 and — if empty or missing.
principles_count and principles_high_conf — from principles.json.principles[],where high_conf is count(confidence >= 0.5).
lens_domains — number of agent/state/*/lens.json files that exist; denominatoris the count of active domains in config.domains.
chain_count_last_10 — in state.json.decision_log[-10:], count entrieswhere chain_executed exists and is non-empty.
active_interventions — length of memos.json.interventions[].skill_gaps_unaddressed — count(gap.resolved != true) in skill_gaps.json.gaps[].Break out learning_loop_break count separately since those flag internal evolve invariants (e.g., cost_ledger auto-patches).
reflections_count and last_lesson — from reflections.json.reflections[]:total count and the most recent entry's lesson (truncate to ~32 chars). Show 0 / — if the file is empty or missing. This shows whether the Reflexion self-critique loop (evolve Step 5-F / 2-F) is actually running.
Season + Focus (v1.2.0) — from config.json:
season_mode — config.season_modes.current_mode if enabled, else "disabled".season_overrides_count — length ofconfig.season_modes.modes[current_mode].weight_overrides.
Active context (v1.2.0) — from config.json.active_context.path:
<path> (age: <mtime>m); else none.Print the dashboard using box-drawing characters exactly as shown below. Replace {placeholders} with the computed values from Step 2.
╔══════════════════════════════════════════════════════╗
║ OODA-loop status ║
║ Mission: {mission_oneline_or_—} ║
╠══════════════════════════════════════════════════════╣
║ Cycle: #{N} Last: {ago} Level: {N} Vel: {N}/day ║
╠══════════════════════════════════════════════════════╣
║ Domain Score Conf Trend Last Status ║
║ {domain_name} {score} {conf} {↑↓→} {ago} {sym} ║
╠══════════════════════════════════════════════════════╣
║ Actions: {N} pending, {N} proposed Oldest: {age}d ║
║ Next: {top_action_title} (RICE {score}) ║
╠══════════════════════════════════════════════════════╣
║ Saturation: {N} observe-only cycles {bar} ║
║ Alerts: {count_or_none} ║
║ HALT: {ACTIVE / inactive} ║
║ Cost: ${spent}/${limit} today (${rate}/h) ║
╠══ Orient Health (v1.2.0) ═══════════════════════════╣
║ Episodes: {episodes_count} (last: {week}) ║
║ Principles: {principles_count} ({high_conf} conf≥0.5)║
║ Lens: {lens_domains}/{active_domain_count} domains ║
║ Chain exec: {chain_count_last_10}/10 cycles ║
║ Interventions: {active_interventions} active ║
║ Gaps: {skill_gaps_unaddressed} ({loop_break} break) ║
║ Reflections: {reflections_count} (last: {last_lesson})║
╠══ Season + Context (v1.2.0) ════════════════════════╣
║ Season: {season_mode} ({overrides_count} overrides) ║
║ Context: {context_path_or_none} ║
╚══════════════════════════════════════════════════════╝The --orient flag opens a detailed view of Orient Health only (useful when debugging whether the learning loop is actually running):
/ooda-status --orientOutput focuses on Episodes / Principles / Lens / Chain / Interventions / Skill gaps and omits the domain/cost/saturation rows.
--scorecard — is the loop actually WORKING?/ooda-status --scorecard (all recorded cycles)
/ooda-status --scorecard --window 20 (last 20 cycles)Renders the Loop Scorecard — the loop-engineering measurement view that answers "is the loop improving the project, or just running?". This is the deterministic reference scripts/loop_scorecard.py rendered verbatim; it reads outcomes.json (Step 6-C9), metrics.json counters, cost_ledger.json, and action_queue.json — no recomputation, no model call. KPIs (the measurement canon):
quality_multiplier across scored cycles (0–1).The single headline number: 1.0 = every cycle merged & held; 0.0 = all futile.
backlog is growing faster than the loop clears it).
goals.json done-conditions(the loop-engineering "run until a verifiable goal is met" signal).
self-diagnosed skill gaps closed, and are reflexion lessons re-applied?
Graceful degradation: with no outcomes.json yet (pre-v1.4.0 state or a fresh project), every KPI shows — and the verdict reads "no outcomes recorded yet."
--share — render the latest Cycle Card/ooda-status --share re-renders the most recent cycle's Cycle Card — the same shareable artifact evolve prints at the end of its Step 7 — so it can be screenshotted or pasted into X / Reddit / Slack without re-running a cycle. It is read-only.
/ooda-status --share#### --share --plain — emit only the text line
If the --plain flag is appended (/ooda-status --share --plain), this mode acts as a strict subset of --share that omits the Cycle Card rendering output. It reuses identical state reconstruction logic, LEARN-line selection priority, and all graceful degradation rules defined in --share. It emits only the single-sentence plain-text share line (as defined in evolve Step 7).
/ooda-status --share --plainReconstruct the card (or plain text) from existing state — no recomputation:
state.json.decision_log[-1] (cycle, timestamp,domain, skill, score, confidence, result, pr_number, risk_tier, orient_summary).
decision_log[-1].orient_summary and, if present, the**Orient** line of the latest entry in agent/state/evolve/CHANGELOG.md.
evolve Step 7 (human-decision confidence change > lens change > new intervention > micro-adjustment). Source it, in order, from the latest agent/state/*/lens_changelog.json entry, memos.json.interventions[] created this cycle, and the **Confidence** (trend / micro-adj) line of the latest CHANGELOG.md entry. If none is recoverable, render no new orientation recorded for cycle #{N}.
cost_ledger.json entry + config.cost.daily_limit_usd.Render byte-for-byte the same box and the plain-text share line as evolve Step 7, including the honesty rule on verbs (re-aimed / adjusted / deprioritized — never "trained" or "learned weights") and the same missing-field graceful degradation (render — for any absent field; on legacy pre-v1.2.0 state expect more —). If no cycle has run yet (decision_log empty), print: No cycle to share yet. Run /evolve first.
New columns and rows explained:
total_cycles / days_since_first_cycle. Helps detect runaway loops or idle periods.↑/↓/→ by delta); a domain with fewer than two appearances in the retained log renders →. Do not pretend a "5 cycles ago" per-domain snapshot exists — it doesn't.— if queue is empty. Highlights aging items that may need human review.consecutive_observe_only_cycles from state.json. Render as a progress bar toward saturation.halt_threshold (e.g., ████░░░░░░ 40%). Shows 0 if no saturation.cost_ledger.total_estimated_usd / hours_since_midnight_utc. Helps predict whether daily limit will be hit.One row per enabled domain. Pad domain names and numbers so columns align. If HALT is active, write HALT: ACTIVE (all caps, no color codes needed -- emphasis via caps).
Narrow terminal fallback — The box-drawing layout above assumes >= 50 columns. If the output environment is narrow (e.g. split pane, mobile terminal), fall back to a compact plain-text list without box-drawing characters:
OODA-loop status
Cycle #0 | Last — | Level 0
---
service_health — — — ?
test_coverage — — — ?
---
Actions: — pending, — proposed
Alerts: none | HALT: inactive | Cost: —/—After rendering the dashboard, check whether a suggestion should be shown:
cycle_count from state.json. If cycle_count >= 3, proceed.status: "available"."available" domains exist, show exactly one suggestion per status check: Suggestion: You've run {N} cycles. Consider adding
/scan-market for strategic insights.
Run: /ooda-skill create scan-marketReplace the domain name and description with the actual available domain being suggested.
"active" or "disabled" (none remain "available"), omit the Suggestions block entirely.| Condition | Behavior |
|---|---|
| config.json missing | Print: Not configured. Run /ooda-setup first. — stop. |
| state files missing (all) | Show dashboard with Cycle: #0 Last: — Level: 0 and domain rows as ?. Add note: No cycles run yet. Run /evolve to start. |
| Individual domain state file missing | Show ? for score, conf, last, status for that domain only. |
| Any state file contains invalid JSON | Treat as missing (use defaults), add [WARN] Corrupt state file: <path> to alerts section. |
| action_queue.json missing | Show Actions: — pending, — proposed and Next: —. |
| cost_ledger.json missing | Show Cost: —/— today. |
| HALT active | Show full dashboard. Mark HALT: ACTIVE. Do not suppress any data. |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.