Add ingestHtml and ingestMarkdown with ADR-0003 pageless offset semantics, PDF intrinsic metadata extraction with caller-wins merge (WP-0003), and citation recovery primitives including re-ingest reconcile, local quote search, and pluggable discovery hooks (ADR-0004). Mark all three workplans finished with contract tests (80 passing).
2.1 KiB
2.1 KiB
ADR-0004 — Citation recovery boundary
- Status: accepted
- Date: 2026-07-09
- Workplan: ESRC-WP-0004 (T01)
Context
evidence-source owns ingestion and representation generation. Citation
recovery spans stale-selector detection, local quote search, external source
discovery, and human confirmation — but selector resolution algorithms live in
evidence-anchor, and the CitationRecoveryAttempt type vocabulary lives in
citation-engine.
Decision
Owned by evidence-source
| Capability | Module | Notes |
|---|---|---|
| Re-ingest + re-fingerprint | src/recovery/re-ingest.ts |
Compare prior vs. fresh Document.fingerprint; flag requiresReanchor |
| Local canonical quote search | src/recovery/local-search.ts |
Search DocumentRepresentation.canonicalText |
| Recovery attempt scaffold | src/recovery/attempt.ts |
Local record using SharedContracts state vocabulary |
| Discovery hook interface | src/recovery/discovery.ts |
Pluggable providers; no network in core |
Owned elsewhere
| Capability | Owner |
|---|---|
| Stale selector detection / resolution order | evidence-anchor |
CitationRecoveryAttempt canonical type |
citation-engine (future) |
| Human confirmation UX | citation-work / umbrella |
| External HTTP/API lookup implementations | Deployment-specific providers registered on the hook |
Recovery flow
CitationClue
→ createRecoveryAttempt (evidence-source)
→ local library search via searchCanonicalQuote (evidence-source)
→ optional SourceDiscoveryHook providers (registered by host)
→ reIngestAndCompare when fresh bytes arrive (evidence-source)
→ anchor layer re-resolves selectors when requiresReanchor is true
evidence-source does not decide whether a selector is stale. It supplies
primitives the anchor layer calls after it detects mismatch.
Consequences
- No network coupling in the recovery core.
- Host apps register discovery providers explicitly (local-first default).
- Recovery state enum mirrors
wiki/SharedContracts.md§2.6 locally until the engine exports a sharedCitationRecoveryAttempttype.