# Registry & Ledger Schemas

All state lives under `<project>/.pi/gpu/` (override with `GPU_STATE_DIR`).
Files are plain JSON (+ one JSONL ledger) so the state is inspectable,
diffable, and portable across Pi sessions.

## providers.json

```json
[
  {
    "id": "vast",
    "name": "Vast.ai",
    "kind": "instance",
    "cli": "vastai",
    "installed": true,
    "cliVersion": "0.3.14",
    "authenticated": true,
    "authHint": null,
    "detectedAt": "2026-08-12T10:00:00Z"
  }
]
```

## machines.json

```json
[
  {
    "id": "m_001",
    "provider": "vast",
    "instance_id": "6123456",
    "gpu": "RTX 5090",
    "gpu_count": 1,
    "status": "running",
    "cost_hr": 0.31,
    "region": "Texas, US",
    "created_at": "2026-08-12T10:00:00Z",
    "tags": ["wan-2.2-5b"]
  }
]
```

`status`: `running | stopped | error | destroyed`.

## deployments.json

```json
{
  "id": "dep_wan225b_01",
  "provider": "vast",
  "machine_id": "m_001",
  "instance_id": "6123456",
  "gpu": "RTX 5090",
  "gpu_count": 1,
  "runtime": "comfyui",
  "model": "wan-2.2-5b",
  "endpoint": "http://1.2.3.4:8188",
  "ssh": "root@1.2.3.4",
  "status": "ready",
  "cost_hr": 0.31,
  "region": "Texas, US",
  "created_at": "2026-08-12T10:00:00Z",
  "idle_since": "2026-08-12T11:00:00Z"
}
```

`status`: `provisioning | ready | stopped | error | destroyed`. A deployment
is only `ready` after a successful health-check (test generation). Destroyed
deployments stay in the list with history — never delete.

## models.json

```json
{
  "id": "wan-2.2-5b",
  "name": "Wan 2.2 5B (T2V)",
  "source_url": "https://huggingface.co/Wan-AI/Wan2.2-T2V-5B",
  "vram_gb_min": 16,
  "vram_gb_fp8": null,
  "gpu_class": "24GB class (RTX 4090/5090, L40S)",
  "runtime": "comfyui",
  "notes": "Fast cheap pass on 24GB cards.",
  "verified": false
}
```

`verified: false` = hypothesis, confirm from the model card before spending.

## workflows.json

```json
{
  "id": "h3-image-to-video",
  "model": "minimax-h3",
  "runtime": "comfyui",
  "description": "H3: image + prompt to video",
  "input_schema": { "image": "uri", "prompt": "string", "duration": "number" },
  "verified": false
}
```

## jobs.jsonl (append-only ledger)

```json
{"id":"J-000123","deployment_id":"dep_wan225b_01","provider":"vast","model":"wan-2.2-5b","workflow":"wan-t2v","workflow_version":2,"inputs":{"prompt":"slow push-in on the kitchen","duration":5},"status":"completed","started_at":"2026-08-12T11:00:00Z","completed_at":"2026-08-12T11:03:12Z","duration_s":192.4,"cost_usd":0.017,"gpu":"RTX 5090","instance_id":"6123456","artifacts":[{"name":"output.mp4","uri":"s3://video-factory/jobs/J-000123/output.mp4"}],"error":null,"ts":"2026-08-12T11:00:00Z"}
```

`status`: `queued | running | completed | failed | cancelled`. A completed job
without artifact URIs is a warning sign — outputs die with the pod.

## policy.json

```json
{
  "ceiling_per_job_usd": 5,
  "ceiling_daily_usd": 40,
  "ceiling_monthly_usd": 400,
  "confirm_above_usd": 1,
  "idle_shutdown_after_min": 30
}
```

Enforced in code: provisioning/actions above `confirm_above_usd` require user
confirmation; ceilings are hard stops the agent cannot silently override.
