# formulas/run-resources.toml
#
# Infrastructure resource snapshot — collect disk usage, RAM trends,
# Anthropic API call counts and budget burn, and Woodpecker CI queue depth.
# Write a structured JSON evidence file for planner and predictor consumption.
#
# Type: sense.  Read-only — produces metrics only, no git artifacts.
#
# Staleness threshold: 1 day (matches evidence/resources/ schema).
# Cron: daily at 06:00 UTC.

[formula]
id          = "run-resources"
name        = "Infrastructure Resource Snapshot"
description = "Collect disk, RAM, API usage, Anthropic budget burn, and CI queue depth; write evidence/resources/{date}.json."
type        = "sense"
# "sense"  → read-only, produces metrics only
# "act"    → produces git artifacts (cf. run-evolution, run-red-team)

# ── Cron ───────────────────────────────────────────────────────────────────────

[cron]
schedule    = "0 6 * * *"   # daily at 06:00 UTC
description = "Matches 1-day staleness threshold — one snapshot per day keeps the record fresh."

# ── Inputs ─────────────────────────────────────────────────────────────────────

[inputs.disk_path]
type        = "string"
required    = false
default     = "/"
description = "Filesystem path to measure disk usage for (passed to df)."

[inputs.anthropic_budget_usd_limit]
type        = "number"
required    = false
default     = 50.0
description = "Configured Anthropic budget ceiling in USD. Used to compute budget_pct in the evidence record."

[inputs.woodpecker_api_url]
type        = "string"
required    = false
default     = "http://localhost:8090"
description = "Base URL of the Woodpecker CI API. Set to empty string to skip CI metrics."

# ── Execution ──────────────────────────────────────────────────────────────────

[execution]
script     = "scripts/harb-evaluator/run-resources.sh"
invocation = "DISK_PATH={disk_path} ANTHROPIC_BUDGET_USD_LIMIT={anthropic_budget_usd_limit} WOODPECKER_API_URL={woodpecker_api_url} bash scripts/harb-evaluator/run-resources.sh"

# Exit codes:
#   0  snapshot written successfully
#   2  infrastructure error (disk command unavailable, JSON write failed, etc.)

# ── Steps ──────────────────────────────────────────────────────────────────────

[[steps]]
id          = "collect-disk"
description = """
Measure disk usage on {disk_path} via `df -B1 {disk_path}`.
Extract used_bytes, total_bytes, and used_pct.
"""

[[steps]]
id          = "collect-ram"
description = """
Measure RAM usage via `free -b` (Linux) or `vm_stat` (macOS).
Extract used_bytes, total_bytes, and used_pct.
"""

[[steps]]
id          = "collect-api"
description = """
Collect Anthropic API metrics:
  - anthropic_calls_24h: count of API calls in the past 24 hours (read from
    tmp/anthropic-call-log.jsonl if present; 0 if absent).
  - anthropic_budget_usd_used: sum of cost_usd entries in the call log for
    the current calendar day (UTC); 0 if log absent.
  - anthropic_budget_usd_limit: from {anthropic_budget_usd_limit} input.
  - anthropic_budget_pct: used / limit * 100 (0 if limit = 0).
"""
call_log    = "tmp/anthropic-call-log.jsonl"

[[steps]]
id          = "collect-ci"
description = """
Query Woodpecker CI API for queue state.
GET {woodpecker_api_url}/api/queue/info:
  - woodpecker_queue_depth: length of the waiting queue.
  - woodpecker_running: count of currently running jobs.
Skipped gracefully (fields set to null) when {woodpecker_api_url} is empty
or the endpoint is unreachable.
"""

[[steps]]
id          = "collect"
description = """
Assemble all collected metrics into evidence/resources/{date}.json.
Compute verdict:
  - "critical" if disk_used_pct ≥ 95, ram_used_pct ≥ 95,
    or anthropic_budget_pct ≥ 95.
  - "warn"     if disk_used_pct ≥ 80, ram_used_pct ≥ 80,
    or anthropic_budget_pct ≥ 80.
  - "ok"       otherwise.
Write the file conforming to the schema in evidence/README.md
## Schema: resources/YYYY-MM-DD.json.
"""
output = "evidence/resources/{date}.json"
schema = "evidence/README.md"   # see ## Schema: resources/YYYY-MM-DD.json

[[steps]]
id          = "deliver"
description = """
Commit evidence/resources/{date}.json to main.
Post a one-line summary comment to the originating issue (if any):
  verdict, disk_used_pct, ram_used_pct, anthropic_budget_pct, ci queue depth.
On "warn" or "critical": highlight the breaching dimensions.
"""

# ── Products ───────────────────────────────────────────────────────────────────

[products.evidence_file]
path     = "evidence/resources/{date}.json"
delivery = "commit to main"
schema   = "evidence/README.md"   # see ## Schema: resources/YYYY-MM-DD.json

[products.issue_comment]
delivery   = "post to originating issue (if any)"
content    = "verdict, disk_used_pct, ram_used_pct, anthropic_budget_pct, ci queue depth"
on_warn    = "highlight breaching dimensions and current values"

# ── Resources ──────────────────────────────────────────────────────────────────

[resources]
profile     = "light"
compute     = "local — shell commands only (df, free, curl); no Docker or Anvil required"
concurrency = "safe to run in parallel with other formulas"

# ── Notes ──────────────────────────────────────────────────────────────────────

[notes]
call_log = """
tmp/anthropic-call-log.jsonl is expected to have one JSON object per line,
each with at minimum:
  { "ts": "<ISO timestamp>", "cost_usd": <number> }
The file is written by the dark-factory agent loop.  When absent the API
metrics default to 0 — the snapshot is still written rather than failing.
"""

disk_warn = """
Planner MEMORY.md (2026-03-20) notes disk at 79%.  The "warn" threshold
(≥80%) will fire on the first run-resources pass.  Monitor trajectory;
evidence pipeline data accumulation will increase disk pressure.
"""
