Provenance & Context Drift
Project context is useful only while its claims fit the project. A document might say that the package uses one module system, the tests run through one command, or authentication begins at one entry point. Code changes can invalidate those statements even though the document still looks complete.
Provenance records where a claim came from. Drift detection identifies recorded source bytes that no longer match. Neither one proves that the claim was correct in the first place.
HTML-knowledge repositories record this per claim instead: each source-observed record cites
its files, each document keeps the commit it was last checked against, and knowledge.py stale
lists exactly the records whose cited files changed since then. That check is advisory and never
blocks a commit. The rest of this page describes the Markdown-format provenance records.
This is not a promise that every sentence has a provenance record. The mechanism covers the
entries actually recorded under .codearbiter/.provenance/, and routine drift alarms consider
only entries whose drift_trigger is explicitly true.
Follow one claim back to its source
Section titled “Follow one claim back to its source”A derived document and its provenance record have different jobs. The document teaches the project’s conventions. The JSON record identifies the document, its creation date, whether it came from an interview, and the backing entries. An entry can name a repository-relative path, its recorded Git content hash, claims and their source lines, and whether changes should trigger a drift alarm.
For example, a claim in tech-stack.md might be backed by package.json. If the package changes
from module syntax to commonjs, the old hash differs and the old statement may now be wrong.
If only whitespace changes, the hash also differs, but the statement might still hold. The
hash tells you to inspect the relationship; it does not choose the interpretation.
Follow the evidence into a read
A pointer is a selection, not a verdict
Actual Python helper output over fixed local fixtures, not an installed-host run, approval, or validation of your repository.
The fixture uses real Git content hashes and the repository's read/provenance helpers. Choose an already-recorded case; these controls do not run a tool.
Several governing sources match
Fixture read: src/auth/session.py
1. Gather matching pointers
- security-controlsSecurity policy governs this file: use CTX-SECURITY-CONTROLS records in HTML context, or security-controls.md in Markdown context.
- decisionsADR-0042-session-boundary (Session boundary) governs this file — do not contradict it; route changes via /ca:reconcile or /ca:adr.
- specsspec session governs this file — implement to its acceptance criteria.
- Provenance · standardsstandards.md notes (lines 1-2): Session checks are explicit.
2. Assemble the bounded result
99 estimated tokens · 1 provenance hash call
Security policy governs this file: use CTX-SECURITY-CONTROLS records in HTML context, or security-controls.md in Markdown context.
ADR-0042-session-boundary (Session boundary) governs this file — do not contradict it; route changes via /ca:reconcile or /ca:adr.
spec session governs this file — implement to its acceptance criteria.
standards.md notes (lines 1-2): Session checks are explicit.Repeat in the same session: no additional context. The repeated call performs 0 provenance hash calls.
What this establishes: All four tiers contribute. Priority controls assembly order, not a first-match-only decision.
What you do next: Read the named documents. The pointer is not their complete contents or an approval.
The recorded source still matches
Fixture read: package.json
1. Gather matching pointers
- Provenance · standardstech-stack.md notes (lines 1): The package declares module syntax.
2. Assemble the bounded result
17 estimated tokens · 1 provenance hash call
tech-stack.md notes (lines 1): The package declares module syntax.Repeat in the same session: no additional context. The repeated call performs 0 provenance hash calls.
What this establishes: The recorded package bytes match their current hash, so the provenance claim can contribute a pointer.
What you do next: Inspect the actual claim as well as the hash. Matching bytes do not establish that an earlier interpretation was correct.
The source changed
Fixture read: package.json
1. Gather matching pointers
No matching pointer survives the selection and freshness checks in this fixture.
2. Assemble the bounded result
0 estimated tokens · 1 provenance hash call
Observed output: empty string. The helper did not supply additional context.
Repeat in the same session: no additional context. The repeated call performs 1 provenance hash call.
What this establishes: The package changed from module to commonjs. The old claim is suppressed, and drift detection identifies the dependent document.
What you do next: Review the changed behavior and re-scout or defer. Replacing a hash alone would conceal the now-false claim.
Separate drift output: tech-stack → package.json → changed. The mutation was confined to a disposable fixture.
No mapping exists
Fixture read: src/ui/view.py
1. Gather matching pointers
No matching pointer survives the selection and freshness checks in this fixture.
2. Assemble the bounded result
0 estimated tokens · 0 provenance hash calls
Observed output: empty string. The helper did not supply additional context.
Repeat in the same session: no additional context. The repeated call performs 0 provenance hash calls.
What this establishes: No candidate covers this file. The helper emits nothing and makes no provenance hash call.
What you do next: Do not treat silence as a safety verdict. Confirm activation, mapping, and relevant requirements before changing sensitive code.
The comparison above is actual helper output over a disposable example, not a claim that an installed agent examined your repository. Switch between fresh and changed source to see why a stale provenance pointer disappears rather than being injected as current knowledge.
Inspect the static relationship map
What happens when source changes
Section titled “What happens when source changes”At SessionStart, the shared provenance helper loads usable records and hashes the existing,
confined source paths marked as drift triggers. A mismatch is reported as changed; a genuinely
absent path can be reported as missing. It produces a concise advisory drift line, not a blocking
decision or a rewritten document.
Read that line as an invitation to investigate. No line can also mean no recorded sources, no eligible trigger, an unreadable or malformed record, or a hashing failure. The startup helper intentionally degrades to silence on those failures. A blank startup result is therefore not a certificate that all repository knowledge is current. One malformed record does not discard the remaining valid records, but the ordinary startup path does not promise a per-record warning.
Greenfield context may be interview-derived before source exists. An empty entry set does not make an interview answer false; it means this source-hash mechanism cannot yet validate it. Do not invent code citations merely to remove that distinction. See Plan a new project and Understand existing code.
Choose the correct disposition
Section titled “Choose the correct disposition”Re-scout when meaning may have changed. The incremental scout reads the changed paths and checks the dependent claims. If a claim no longer holds, review the proposed document change before the new baseline is recorded. This is a scoped update, not a reason to rescan the entire repository or rewrite its architecture.
Re-baseline when you can justify keeping the claim. This updates matching source hashes without changing the claim text. A cosmetic change can justify it after inspection. A missing source is not silently replaced: the helper preserves its old hash when there is no current one. Do not use re-baselining as a warning-dismissal button.
Defer when the work should remain open. The manual workflow leaves the document and mismatch alone so the next session can surface them. Record an owner and reopen condition when the work needs to survive this conversation, but do not pretend the defer operation creates a dedicated persistent debt record automatically. A defer is not a fresh result.
The choice belongs to the relationship between this document and these sources. One document can be safely re-baselined while another needs new claims. A global reset of all hashes would erase that distinction.
The commit path and manual audit are different
Section titled “The commit path and manual audit are different”During commit-gate Phase 5.5, before the commit lands, maintenance selects claims whose
recorded sources intersect staged paths. Legacy v1 records use heal_worklist; managed v2
pairs use v2_heal_worklist with a current bounded source and document snapshot. An empty
legacy worklist does not establish v2 freshness. Reinspect only selected claims. Unknown
evidence defers that document’s automatic update without blocking independent commit work.
If claims still hold, a managed pair uses native preview/apply for its selected owned fields, retaining document bytes and updating inspected source evidence. The writer rechecks source and target identities and writes the pair together. Legacy v1 re-baselining remains separate; it never writes v2 records. Stage the resulting paths explicitly with the required secrets re-scan. Changed claims enter normal diff review. Auto-heal does not silently rewrite conclusions or require another approval for maintenance already authorized by the commit request.
The manual context-check route is for drift outside that particular commit path: a merge you did
not author, an external edit, or a recorded source you are not staging now. Its compatibility
entry remains available as /ca:context-check, $ca-context-check, or /ca-context-check,
depending on the host. The catalog also advertises the canonical status-drift route; inspect the
installed command reference rather than inventing a new command.
For an audit-only request, the owner reports first and waits for a selected disposition. A direct request to refresh named documents or full context already authorizes that selection; it does not need repeated per-document permission. Inspection may be direct or use optional scoped agents. The writer previews selected changes and rechecks the source and target identities before applying the document/provenance pair; supported missing/v1 provenance can be explicitly adopted while its prior bytes are retained. Unowned content and initialization state stay intact. It does not stage or commit. Any revised provenance or document rides a later user-authorized commit. See the context-check reference and commit gate.
Inspect a real repository without changing its history
Section titled “Inspect a real repository without changing its history”Start by confirming the checkout, branch and current work. Read the affected document and its provenance JSON. Check that the named path exists inside this repository, the record has the expected shape, and the reported change concerns that path. Ask for the source diff and the claim it could invalidate. A number of commits since a change is not part of the hash-comparison report unless separately established from Git history.
Before accepting a re-baseline, explain why the statement remains true. Before accepting new text, inspect the supporting source and preserve unresolved questions. After either action, repeat the audit and inspect the actual file diff. A re-scouted document should have the intended claim and source relationship; a deferred document should still have its unresolved mismatch.
Do not delete markers, clear provenance directories or edit protected authority to manufacture a clean result. If a helper is missing or a record cannot be interpreted, preserve its path and the observed diagnostic, then use Troubleshooting. Redact secrets and private source content before sharing a diagnostic.
Freshness is one layer, not the whole authority model
Section titled “Freshness is one layer, not the whole authority model”A source hash, an ADR acceptance record, a typed artifact’s normative identity, and a fresh test result answer different questions. Updating provenance does not approve a feature, verify an ADR, or accept a task. Conversely, a passing feature test does not refresh an unrelated project claim.
Just-in-time context explains how a fresh claim can contribute a pointer at a read. Artifacts explains which records govern a change, and Auditability explains how to examine their evidence later.