Ooda status
Autonomous operations layer for Claude Code — opens small reviewable PRs for your live side project and re-orients from which ones you merge or reject. HALT file + hard cost cap; you stay in command.
npx -y skills add mataeil/OODA-loop --skill ooda-statusAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Display OODA-loop status dashboard. Shows cycle count, domain states, confidence scores, action queue, and alerts in a single view.
SKILL.md
15.7 KB, as published. Nobody here has run it
/ooda-status — Status Dashboard
Display the current state of the OODA-loop at a glance.
Step 0: Safety Check
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.
Step 1: Gather Data
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:
- last_run timestamp
- status field (healthy / degraded / critical / error)
- score value
- alerts array
# Example: cat agent/state/health/state.json 2>/dev/null
Step 2: Calculate Display Values
Time formatting — compute elapsed time from last_run or last_cycle to now:
- < 60 minutes →
Xm - < 24 hours →
Xh -
= 24 hours →
Xd - Never run →
—
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 missing
Score — 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_countandlast_episode_week— fromepisodes.json.episodes[]. Show0and—if empty or missing.principles_countandprinciples_high_conf— fromprinciples.json.principles[], wherehigh_confiscount(confidence >= 0.5).lens_domains— number ofagent/state/*/lens.jsonfiles that exist; denominator is the count of active domains in config.domains.chain_count_last_10— instate.json.decision_log[-10:], count entries wherechain_executedexists and is non-empty.active_interventions— length ofmemos.json.interventions[].skill_gaps_unaddressed—count(gap.resolved != true)inskill_gaps.json.gaps[]. Break outlearning_loop_breakcount separately since those flag internal evolve invariants (e.g., cost_ledger auto-patches).reflections_countandlast_lesson— fromreflections.json.reflections[]: total count and the most recent entry'slesson(truncate to ~32 chars). Show0/—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_modeif 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:
- if set and file readable:
<path> (age: <mtime>m); elsenone.
Step 3: Render Dashboard
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 --orient
Output 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):
- Loop Value Score — mean
quality_multiplieracross scored cycles (0–1). The single headline number: 1.0 = every cycle merged & held; 0.0 = all futile. - Task Completion Rate — % of cycles that merged and were accepted.
- Futile Cycle Rate — % of cycles that ran but changed nothing.
- PR Merge Rate + hold rate (merged that weren't reverted).
- Action Queue Resolution — resolved ÷ added (a value < 100% means the backlog is growing faster than the loop clears it).
- Cost per Successful Cycle — total cost ÷ accepted-value cycles.
- Goal Progress — mean progress of active
goals.jsondone-conditions (the loop-engineering "run until a verifiable goal is met" signal). - Gap Resolution / Lesson Application — learning-loop health: are self-diagnosed skill gaps closed, and are reflexion lessons re-applied?
- Verdict — working / partial / stalled, from the Loop Value Score.
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 --plain
Reconstruct the card (or plain text) from existing state — no recomputation:
- header / DECIDE / ACT —
state.json.decision_log[-1](cycle, timestamp, domain, skill, score, confidence, result, pr_number, risk_tier, orient_summary). - OBSERVE / ORIENT —
decision_log[-1].orient_summaryand, if present, the**Orient**line of the latest entry inagent/state/evolve/CHANGELOG.md. - LEARN — pick the highest-signal change using the SAME priority order as
evolve Step 7 (human-decision confidence change > lens change > new
intervention > micro-adjustment). Source it, in order, from the latest
agent/state/*/lens_changelog.jsonentry,memos.json.interventions[]created this cycle, and the**Confidence**(trend / micro-adj) line of the latest CHANGELOG.md entry. If none is recoverable, renderno new orientation recorded for cycle #{N}. - COST — latest
cost_ledger.jsonentry +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:
- Vel (Velocity): cycles per day =
total_cycles / days_since_first_cycle. Helps detect runaway loops or idle periods. - Trend: per-domain confidence direction. decision_log only snapshots the WINNER's confidence each cycle, so compare the domain's two most recent decision_log appearances (
↑/↓/→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. - Oldest: age of the oldest pending action in action_queue, in days. Shows
—if queue is empty. Highlights aging items that may need human review. - Saturation:
consecutive_observe_only_cyclesfrom state.json. Render as a progress bar towardsaturation.halt_threshold(e.g.,████░░░░░░ 40%). Shows0if no saturation. - $/h (Cost rate):
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: —/—
Step 4: Suggestions
After rendering the dashboard, check whether a suggestion should be shown:
- Read
cycle_countfrom state.json. Ifcycle_count >= 3, proceed. - Collect all domains from config.json where
status: "available". - If any
"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-market
Replace the domain name and description with the actual available domain being suggested.
- Rotate through available domains across successive status checks (use cycle_count mod available-domain-count to pick which one to show).
- Once all domains are either
"active"or"disabled"(none remain"available"), omit the Suggestions block entirely. - Never show more than 1 suggestion per status check.
Graceful Degradation
| 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. |