v0.9.0 — track aicodebox v0.8.1, schema validation on OAI + per-attempt usage

This release bumps the base image to aicodebox v0.8.1 and surfaces the
two meaningful changes the v0.8.x stream brought:

  1. /openai/v1/chat/completions with x-aicodebox-json-schema now
     ACTUALLY validates (v0.7.0 plumbed the header but never read
     result.parsed). Success → message.content is canonical
     re-serialized JSON, no fences. Schema-exhaustion → 422.
     Agent crash → 500. stream:true + schema header → 400.
  2. Per-attempt breakdown on /run (.attempts) and OAI envelope
     (.aicodebox_attempts) — caller can bill per-attempt or debug
     which retry failed which way. Top-level .usage is summed
     across attempts so the billable total reflects every retry.

Base image
- BASE_IMAGE pinned to
  psyb0t/aicodebox:v0.8.1@sha256:3a234d49d348b3182897c781be6b364e6b5d17784c4b70ac12df132e066d6dac
  in both Dockerfile + Makefile. Digest pin guards against tag-rebuild
  drift — :latest and :v0.8.1 currently resolve to different image IDs
  on Docker Hub.

PiAdapter
- Zero code changes. The base widened RunResult with .attempts but the
  adapter only populates text/session_id/usage; the base writes the
  per-attempt array after run_with_json_retry.

Tests
- Three updates to surface the v0.8.x contract end-to-end through pibox:
  schema-mode .attempts shape on /run, canonical content + envelope
  vendor extension on OAI schema header, and the new stream+schema 400
  rejection rule.

Doc sync
- README.md /run body field list rewritten — removes the long-stale
  ``outputFormat`` mention (gone at the base since v0.6.0) and
  documents the current jsonSchema-only contract + previously-missing
  ``includeRaw`` / ``async`` / ``fireAndForget`` knobs.
- CHANGELOG.md added (full backfill from v0.1.0).

Built against psyb0t/aicodebox:v0.8.1 (digest pinned). Older base
images are incompatible — the new tests assert behavior that doesn't
exist below aicodebox v0.8.0.