Incremental extraction and refresh for changed artifacts
August 9, 2026 · View on GitHub
Status: design specification
Date: 2026-07-21
Strategy frame: perseus-vault-durable-cognition-strategy-2026-07-20
Resolves: #734
Related: provenance-classes-derived-facts.md (classes, pipeline),
structured-truth-retrieval-policy.md (retrieval order),
memory-provenance-and-external-refs.md (origin fields, refs),
source-anchors-corrections-retention.md (supersession, retention)
Structured truth goes stale when source artifacts change. Re-running full
extraction over every artifact on every change is too expensive, and
re-writing everything creates duplicate observations. This spec defines
source-artifact version tracking on extracted entities, selective
re-extraction, lineage preservation, duplicate avoidance, and the
invalidation policy for capture/extract pipelines. It is a conventions
spec: it composes existing fields and tools (derived_from,
perseus_vault_supersede, valid-time, write-time dedup) rather than adding a new
subsystem.
1. Source-artifact version tracking
Every fact_extracted entity (provenance spec §1) MUST record the version
of the artifact it was extracted from:
{
"source_artifact": {
"ref_type": "file | confluence_page | url | custom",
"ref_value": "canonical artifact id (anchor vocabulary)",
"source_hash": "sha256 of extracted content, hex",
"source_version": "optional external version (page version, etag)",
"extracted_at": "unix ms",
"extractor": "rule_based | llm | connector:<name>"
}
}
source_hashis computed over the same normalized text the extractor saw; it is the change-detection key.source_versionis advisory — used when the source system provides one, never required.- The artifact record itself (
source_human, pipeline stage 1) carries the same hash; entities derived from the extracted facts inherit the hash transitively through theirderived_fromchain, not by copying it. - Section-scoped extraction SHOULD record a
section_path(heading path, line range) so a small edit invalidates only its section (see §2).
2. Selective refresh on artifact change
Refresh flow when a watched artifact is re-ingested:
- Hash compare. New content hash vs stored
source_hash. Equal → no-op; nothing is re-extracted, nothing rewritten. This is the common case and must be O(1) per artifact. - Locate affected entities. Entities whose
derived_fromchain terminates at this artifact are the refresh set. Withsection_path, the set narrows to sections whose bytes changed. - Re-extract only the refresh set. Run the extractor over the changed sections; produce candidate replacement facts.
- Reconcile (see §3–§4). Unchanged facts are kept; changed facts are superseded, not edited; new facts are written; vanished facts are invalidated per §5.
- Propagate upward.
fact_derivedobservations whose evidence set intersects the refresh set are markedstale_evidence: true(metadata flag) and re-derived lazily on next consolidation pass — never eagerly recomputed on every artifact save.
Write-path placement: steps 1–2 belong in perseus_vault_ingest_file /
perseus_vault_capture / connector ingest; steps 3–5 are pipeline conventions the
caller (or a refresh helper) executes. Existing tools keep their semantics;
refresh is orchestration over them.
3. Lineage preservation
- Supersession, not mutation: a changed fact is replaced via
perseus_vault_supersede(new entitysupersedesold, old entity'svalid_toclosed). The old version stays queryable viaperseus_vault_as_of/valid_at; the audit trail from current observation to source version is the supersession chain plus thesource_hashrecorded on each link. - The new entity records the new
source_hash; comparing hashes along the chain shows exactly which artifact version each version of the fact came from. perseus_vault_traverseoverderived_from+supersedesrenders the full lineage: artifact v3 → fact v2 → observation (graph-first spec §3).
4. Duplicate avoidance
- Write-time near-duplicate merging (#531) already folds a re-extracted
identical fact into the existing entity (
action: deduped). Refresh MUST NOT passskip_dedup— unchanged sections re-extracting identical facts are the normal case and must collapse. - A fact that differs only by
extracted_at/source_hashmetadata is not new: reconcilers compare fact content (the same similarity the dedup path uses), updating only the source metadata in place when content is unchanged. - Observations re-derived after refresh reuse the existing
(category, key)soperseus_vault_rememberupdates in place rather than spawning a parallel observation.
5. Invalidation policy
- Fact vanished from source (section deleted): supersede the extracted
entity with a tombstone successor (
status: deprecated, reasonsource_removed) and close its valid period at refresh time. Never hard-delete; history stays auditable. - Artifact deleted or unreachable: mark its extracted entities
stale_evidenceand demote via decay; invalidate on the next successful fetch that confirms removal. - Hash unavailable (source system gives no stable content): fall back
to
source_version, else toextracted_atfreshness — and say so in the entity metadata so downstream trust scoring can discount it. - Invalidation never cascades past one hop automatically: derived observations are flagged, and consolidation decides whether the observation still holds from its remaining evidence.
6. Success criteria mapping (#734)
- Lower compute: hash-compare short-circuits unchanged artifacts; only the refresh set is re-extracted (§2 steps 1–3).
- Fresher truth: section-scoped refresh lands in minutes, not at the next full re-ingest; stale evidence is flagged until re-derived (§2 step 5).
- Fewer duplicates: dedup-on-refresh plus content-based reconciliation (§4).
- Audit trail: supersession chain + per-version
source_hashgives current-observation → source-version lineage (§3).
7. Implementation slice
- Add
source_artifactmetadata population toperseus_vault_ingest_file,perseus_vault_capture, and connector ingest (metadata only, no schema change). - Refresh helper: hash-compare + refresh-set enumeration over
derived_fromchains; reconciliation rules of §3–§5. stale_evidenceflag surfaced in served explanations until re-derived.- Golden test: edit one section of a two-section artifact → only that
section's facts superseded; unchanged fact returns
deduped.