# The Agentic Codebase — companion repository task runner.
# nu-first per the book's shell mandate; bash fallback is the .sh script.
#
#   just stack-audit [path]   — score a repo 0–3 per STACK layer (default ".")
#   just stack-audit-sh [path]— same, via the portable bash fallback (no nu needed)
#   just stack-init <path>    — copy the templates into a target repo, then audit it
#   just stack-eval           — discover and shape-check the golden-task fixtures
#   just eval-suite [flags]   — Ch 15's real eval runner (eval-harness/)
#   just eval-gate [flags]    — CI blocking step: interval + cost + baseline regressions
#   just eval-comment [flags] — render the report as a PR-ready Markdown table
#   just eval-harness-test    — the harness's own golden tasks (run these first)
#   just demo                 — show the before/after audit contrast (the proof)

set shell := ["nu", "-c"]

_default:
    @just --list

# Score a repository against the five STACK layers (Nushell, primary).
stack-audit path=".":
    nu scripts/stack-audit.nu {{path}}

# Same audit via the portable bash fallback (use where nu is unavailable).
stack-audit-sh path=".":
    bash scripts/stack-audit.sh {{path}}

# Emit the machine-readable audit record (for scripting / CI).
stack-audit-json path=".":
    nu scripts/stack-audit.nu {{path}} --json

# Seed a target repo with STACK starter files, then audit it (non-destructive).
stack-init target:
    #!/usr/bin/env nu
    let target = ("{{target}}" | path expand)
    if not ($target | path exists) {
        print -e $"stack-init: target does not exist: ($target)"
        exit 1
    }
    print $"Seeding STACK starter files into ($target) ..."
    # (destination relative path) <- (template source)
    let plan = [
        { dst: "AGENTS.md",                                  src: "templates/AGENTS.md" }
        { dst: "mcp/example-tool.contract.yaml",             src: "templates/mcp-tool-contract.yaml" }
        { dst: "skills/example-skill/SKILL.md",              src: "templates/SKILL.md" }
        { dst: "agents/example-role.charter.md",             src: "templates/role-charter.md" }
        { dst: ".claude/hooks/block-destructive.sh",         src: "templates/hooks/block-destructive.sh" }
        { dst: ".claude/settings.hooks.json",                src: "templates/hooks/settings.hooks.json" }
        { dst: "evals/example.eval.yaml",                    src: "templates/evals/eval-spec.yaml" }
    ]
    for item in $plan {
        let dest = ($target | path join $item.dst)
        let destdir = ($dest | path dirname)
        if not ($destdir | path exists) { mkdir $destdir }
        if ($dest | path exists) {
            print $"  skip  ($item.dst)  \(already exists\)"
        } else {
            cp $item.src $dest
            print $"  copy  ($item.dst)"
        }
    }
    print ""
    print "Initial STACK audit of the seeded repo:"
    print ""
    nu scripts/stack-audit.nu $target

# Locate + validate golden-task specs (light check; the REAL runner is `just eval-suite`,
# implemented in eval-harness/ — see eval-harness/README.md).
stack-eval:
    #!/usr/bin/env nu
    print "Discovering golden tasks + eval specs (lightweight shape check)..."
    let specs = (do -i { glob "examples/**/*.eval.yaml" } | default [])
    let goldens = (do -i { glob "examples/**/eval/golden-*.md" } | default [])
    print $"  eval specs found:  ($specs | length)"
    for s in $specs { print $"    - ($s | path relative-to (pwd))" }
    print $"  golden tasks found: ($goldens | length)"
    for g in $goldens { print $"    - ($g | path relative-to (pwd))" }
    if (($specs | length) == 0) {
        print -e "No eval specs found. Add evals/<task>.eval.yaml (see templates/evals/)."
        exit 1
    }
    # Minimal validation: every spec parses as YAML-ish and declares a pass threshold.
    mut ok = 0
    for s in $specs {
        let txt = (open --raw $s)
        if ($txt | str contains "pass_threshold") and ($txt | str contains "runs_per_case") {
            $ok = $ok + 1
        } else {
            print -e $"  FAIL ($s): missing pass_threshold or runs_per_case"
        }
    }
    print ""
    print $"($ok)/($specs | length) eval specs are well-formed \(threshold + interval declared\)."
    print "For repeated execution and interval/cost gates, run `just eval-suite`."

# Show the before/after audit contrast — the companion's central proof.
demo:
    @print "===== BEFORE (drifted month-0 NexumOS) ====="
    nu scripts/stack-audit.nu examples/before
    @print ""
    @print "===== AFTER (STACK-implemented NexumOS) ====="
    nu scripts/stack-audit.nu examples/after


# --- Chapter 15 eval harness (reference implementation, eval-harness/) ---

# Run the golden eval suite: repeated runs, interval gate, cost budget, JSON report.
# Matches the CI invocation in Ch 15: `just eval-suite --runs 5 --report build/eval-report.json`.
eval-suite *args:
    #!/usr/bin/env nu
    let agent_cmd = ($env.EVAL_AGENT_CMD? | default "./eval-harness/examples/fake-agent.sh")
    with-env {EVAL_AGENT_CMD: $agent_cmd} {
        nu eval-harness/eval-run.nu --specs eval-harness/examples/refund-triage.eval.yaml {{args}}
    }

# Block the merge on any accuracy, cost, or baseline regression in the report.
eval-gate *args:
    nu eval-harness/eval-gate.nu {{args}}

# Post-ready Markdown: accuracy beside cost, always, plus failing assertions.
eval-comment *args:
    nu eval-harness/eval-comment.nu {{args}}

# Cost half of the gate alone (the `on_exceed: fail` budgets live in each spec).
eval-cost-gate *args:
    nu eval-harness/eval-gate.nu {{args}}

# The harness's own golden tasks: a passing double, the incident-reproducing
# double, the judge rung, dry-run validation. If these fail, fix the harness
# before trusting any number it prints.
eval-harness-test:
    nu eval-harness/tests/run-tests.nu
