docs/ingest-recovery.md
Rama main · réplica de lectura del repositorio original.
# Saved cards and publication recovery
Source adapters generate cards and save them before publication. `gbrain_publish.py`
owns verification, repair receipts and batch completion for local files, GitHub,
YouTube and both bookmark workers.
For a saved card, the publisher first checks the **current** GBrain database in a
read-only transaction. A matching body, timeline, declared metadata and complete text chunks, with
embeddings on all stored chunks, skips `put` and `embed`. A confirmed mismatch permits repair; a failed
verification connection never authorizes a write. This check does not certify the
embedding model version or semantic retrieval quality.
The outbox stores the path, content hash and failed stage. Recovery reads that file
again, without generating a replacement:
```sh
python3 scripts/gbrain_publish.py --limit 20
```
Card-specific failures remain pending while the batch continues. Backend failures
(including unknown transport errors) stop new generation. A read-only database
probe and embedding credential check run before a generation batch; this cannot
guarantee that an embedding provider stays available later in the batch.
New-generation limits exclude saved-card recovery. Batch summaries distinguish
`generated`, `recovered`, `verified`, `failed`, and `deferred`. Explicit saved
inputs are all verified; background workers rotate up to 20 saved cards by their
last attempt, including cards without an outbox receipt. Pending publication is
recovered even when bookmark reconciliation already marked enrichment done. The local search
index is rebuilt once after saved cards were handled, even if publication failed.
A batch exits unsuccessfully when publication or index completion fails; saved
cards remain on disk. Failed index completion stays pending in the outbox. Local/GitHub exit code 2 continues to mean new cards were
generated, while recovery-only success returns 0.
## Recall quality
The structured recall packet and doctor share one quality interpretation.
`partial` and `no_text` are degraded, not fully ready. Strict `--require-judge`
requires complete judgment. Unknown judgments preserve candidates and do not add
negative usage history. `no_records` is an empty result rather than a judge outage,
but it cannot satisfy a strict requirement for completed judgment.