# V8 Loom service

The Loom service runs the V8 case pipeline. Offline mode uses in-memory journal
and human-review queues. Production mode fails closed unless
`V8_JOURNAL_DATABASE_URL` (or the shared `YEMAYA_DATABASE_URL`) points to
PostgreSQL.

Apply the journal migrations before starting a production instance:

```bash
V8_JOURNAL_DATABASE_URL=postgresql://... \
  pnpm exec tsx apps/v8/loom-service/src/migrate-journal.ts
```

The migration command is idempotent and uses the shared migration runner with a
transaction-scoped advisory lock. Production `StageJournal` writes use a
separate transaction-scoped advisory lock per `(caseId, seed)` run, plus unique
database constraints on both `(caseId, seed, stage, attempt)` and
`(caseId, seed, seq)`. The same migration installs the database-owned HITL
allocation sequence and durable review queue; concurrent resolution is a
compare-and-set from `pending` to `resolved`. It also installs the immutable
case-revision store. `edit-and-approve` locks the review and current case
revision in one transaction, creates one successor revision, invalidates the
solver/quality/provenance/approval/release evidence ledger, and resolves the
review only if every write commits.

The guarded `editApplyReverifyResume` path retains that held edited revision,
requires fresh evidence for all five classes, verifies an Ed25519 release
signature and timestamp against the supplied trust policy, checks that mixed
lineage binds the human review and resumed artifact, then writes a published
successor and resolves the review in the same database transaction. A failed
gate, missing evidence class, stale review, or invalid signature rolls back the
entire edit/resume operation.

`GET /v8/cases/:caseId/provenance` is the operator read boundary. Production
reads the latest durable revision; offline mode reads the evaluated-run cache.
The response keeps every asset's locator-versus-byte hash scope, signed state,
C2PA verification, complete best-of-N candidate trajectory, and authenticated
release identity distinct. The projection fails closed if the aggregate and
asset manifest disagree or a published revision lacks its authenticated report.

Production best-of-N selection also requires exact active rights receipts for
the candidate output, model, and training dataset. Every selected, rejected,
held, and failed record retains its seed, prompt, provider/model identity,
scores, media probes, rights receipts, and disposition reasons.

Run the live concurrency/restart proof against a disposable or local test
database:

```bash
V8_TEST_DATABASE_URL=postgresql://... \
  pnpm exec vitest run src/postgres-journal-store.spec.ts \
    src/postgres-hitl-queue.spec.ts --reporter=dot
```

Run that command from `apps/v8/loom-service`. The test uses a process-unique
table and removes it afterward.
