# How Claims Are Tracked and Assessed in Claude-Obsidian's Claim Ledger

> Discover how Claude-Obsidian's claim ledger tracks and assesses falsifiable statements with metadata like risk levels and evidence links. Learn about its validation rules for integrity and freshness.

- Repository: [Agrici.Daniel/claude-obsidian](https://github.com/AgriciDaniel/claude-obsidian)
- Tags: how-to-guide
- Published: 2026-08-26

---

**The claim ledger stores falsifiable statements with structured metadata including risk levels, evidence links, and assessment states, enforcing strict validation rules for location integrity, source freshness, and evidentiary independence.**

The `AgriciDaniel/claude-obsidian` repository implements a rigorous provenance system through its claim ledger functionality. Every falsifiable statement is tracked in a JSON file located at [`wiki/meta/ledgers/claim-ledger.json`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/wiki/meta/ledgers/claim-ledger.json), following the schema `"claude-obsidian.claim-ledger.v1"`. This system ensures that factual assertions within your Obsidian vault remain traceable to verifiable evidence through automated validation and assessment logic.

## Claim Data Model and Core Fields

Each entry in the claim ledger is a dictionary keyed by a **safe claim identifier** (e.g., `clm-001`) and must conform to strict validation rules defined in [`claude_obsidian/ledgers.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/ledgers.py).

The claim data model requires the following fields:

| Field | Purpose | Validation Source |
|-------|---------|-------------------|
| `text` | The falsifiable statement as a non-empty Unicode scalar string. | Checked at lines 949-953 |
| `risk` | Either `"normal"` or `"high"`, determining independence requirements. | Validated at lines 955-958 |
| `assessment` | One of `"accepted"`, `"provisional"`, `"contested"`, `"unsupported"`, or `"deprecated"`. | Validated at lines 959-961 |
| `confidence` | `"high"`, `"medium"`, `"low"`, or `"unknown"`. | Validated at lines 962-964 |
| `location` | Object with `path` (vault-relative) and optional `anchor` (heading or block ID). | Path sanity at lines 965-981; anchor existence at lines 918-924 |
| `reviewed_at` | ISO date when formally reviewed; required for accepted claims. | Parsed at lines 930-934; future-date guard at lines 940-945 |
| `notes` | Optional free-form commentary; must be scalar text if present. | Checked at lines 946-950 |
| `supersedes` | Optional reference to a previous claim ID (`clm-…`). | Validated at lines 951-953 |
| `evidence` | Array of objects linking to source IDs (`src-…`) with relations `supports`, `contradicts`, or `context`. | Structure at lines 954-966; relation checks at lines 970-974 |

## Claim Identification and Location Integrity

### Safe Claim ID Format

Every claim identifier must match the regex `^clm-[A-Za-z0-9][A-Za-z0-9._-]*` as enforced by the `_safe_ledger_id` function (lines 659-664). The validator checks this pattern at the start of each record (line 944).

### Location Anchoring

The `location` field guarantees that claims appear on specific wiki pages:

- The `path` must be a canonical vault-relative wiki path (`wiki/...`). The validator rejects absolute paths, upward traversal (`..`), non-scalar characters, or illegal characters (lines 970-977).
- If an `anchor` is supplied, the target page is read via `read_vault_regular` and its headings or block IDs are extracted by `_markdown_anchor_sets`. The anchor must exist as a heading (`# Heading`) or a block (`^block-id`) (lines 918-924).

## Evidence-Based Assessment Logic

The `validate_claim_ledger` function implements sophisticated logic to determine claim validity based on linked evidence in the source ledger.

### Fresh Active Support Requirements

Supporting evidence must meet **fresh active support** criteria:

1. **Valid origin**: Passes `_source_origin_is_valid` (lines 661-686).
2. **Active status**: `review_status` equals `"active"` and not synthetic (`authority` ≠ `synthetic`, `content_kind` ≠ `synthetic`).
3. **Not stale**: Passes `source_is_stale` check (lines 752-758).
4. **Temporal validity**: The source's retrieval/ingestion date precedes the claim's `reviewed_at` date.

This collection is built at lines 1102-1111.

### Acceptance Rules

- **Accepted claims** require at least one fresh supporting source (lines 1121-1127).
- **High-risk claims** demand **two independent sources**. Independence is computed by `_independent_group_count`, which groups sources sharing the same origin, content hash, or declared `independence_key` (lines 897-903). Failure triggers an error at lines 1128-1132.

### Handling Contradictory Evidence

When fresh contradictory sources exist (`relation=="contradicts"`):

- An accepted claim must either be marked `"contested"` or provide explicit adjudication notes (lines 1136-1150).
- Conversely, a claim marked `"contested"` must have at least one contradictory source **or** non-empty notes (lines 1152-1164).

## Review Date Constraints and Migration

### Review Date Validation

Accepted claims carry strict temporal requirements:

- The `reviewed_at` field is mandatory when `assessment == "accepted"` (lines 935-939).
- The review date cannot be later than the audit date (`as_of` parameter) (lines 940-945).

### Legacy Migration

Legacy manifests are migrated to the new claim ledger format by `migrate_legacy_manifest`, which creates an empty claim ledger via `empty_claim_ledger` (lines 925-931) and validates the freshly built source ledger before returning both structures.

## Practical Implementation Examples

### Minimal Claim Ledger Structure

```json
{
  "schema": "claude-obsidian.claim-ledger.v1",
  "generated_at": "2026-07-11T12:00:00Z",
  "claims": {
    "clm-001": {
      "text": "The moon's orbital period is 27.3 days.",
      "risk": "normal",
      "assessment": "accepted",
      "confidence": "high",
      "location": { "path": "wiki/Astronomy.md", "anchor": "Moon-orbit" },
      "reviewed_at": "2026-07-10",
      "notes": "Verified against NASA data.",
      "supersedes": null,
      "evidence": [
        { "source_id": "src-abc123def4567890", "relation": "supports" }
      ]
    }
  }
}

```

The `src-…` identifier must match the canonical source ID generated by `stable_source_id` (lines 707-714).

### Validating Claims in Python

```python
from pathlib import Path
from claude_obsidian.ledgers import validate_claim_ledger, empty_claim_ledger

# Load source ledger (normally produced by the source‑ledger validator)

source_ledger = ...  # dict from source‑ledger.json

# Build a claim ledger (could be edited by the user)

claim_ledger = empty_claim_ledger()
claim_ledger["claims"]["clm-001"] = {
    "text": "The moon's orbital period is 27.3 days.",
    "risk": "normal",
    "assessment": "accepted",
    "confidence": "high",
    "location": {"path": "wiki/Astronomy.md", "anchor": "Moon-orbit"},
    "reviewed_at": "2026-07-10",
    "evidence": [{"source_id": "src-abc123def4567890", "relation": "supports"}],
}

# Run validation (raises LedgerValidationError on failure)

errors = validate_claim_ledger(claim_ledger, source_ledger, vault_root=Path("/my/vault"))
if errors:
    for err in errors:
        print(f"{err['path']}: {err['message']}")
else:
    print("All claims are valid!")

```

### Computing Stable Source IDs

```python
from claude_obsidian.ledgers import stable_source_id

source_id = stable_source_id(
    origin_kind="url",
    locator="https://example.com/data.json",
    content_sha256="3a7bd3e2360a7e5c5b9d4a0f4e1c92f6d5a5e8e7b2c6d4a9f2e1c3b4d5f6a7b8"
)
print(source_id)   # e.g., "src-1f2e3d4c5b6a7e8d9c0"

```

## Summary

- The **claim ledger** ([`wiki/meta/ledgers/claim-ledger.json`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/wiki/meta/ledgers/claim-ledger.json)) stores every falsifiable statement using the schema `"claude-obsidian.claim-ledger.v1"` with mandatory fields for text, risk, assessment, confidence, location, and evidence.
- **Claim IDs** must follow the regex `^clm-[A-Za-z0-9][A-Za-z0-9._-]*` and locations must reference valid vault paths and existing anchors.
- **Accepted claims** require at least one fresh supporting source, while **high-risk claims** demand two independent sources computed by `_independent_group_count`.
- The validator enforces **temporal constraints** ensuring `reviewed_at` dates exist for accepted claims and never exceed the audit date.
- **Contradictory evidence** triggers contested status requirements, ensuring claims with opposing sources are properly flagged or annotated.

## Frequently Asked Questions

### What file path does Claude-Obsidian use for the claim ledger?

The claim ledger is stored at [`wiki/meta/ledgers/claim-ledger.json`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/wiki/meta/ledgers/claim-ledger.json) relative to your vault root. This JSON file follows the schema `"claude-obsidian.claim-ledger.v1"` and contains all tracked claims keyed by their safe identifiers.

### How does the system validate that a claim's location actually exists?

The validator checks the `location.path` against canonical vault-relative wiki paths (rejecting absolute paths or traversal patterns) at lines 970-977. If an `anchor` is provided, the system reads the target page via `read_vault_regular` and extracts headings or block IDs using `_markdown_anchor_sets` to verify the anchor exists (lines 918-924).

### What constitutes a "fresh" supporting source for claim acceptance?

A fresh supporting source must have a valid origin per `_source_origin_is_valid`, carry `review_status == "active"`, be non-synthetic, not be stale according to `source_is_stale`, and have a retrieval date preceding the claim's `reviewed_at` date. These criteria are evaluated at lines 1102-1111.

### Why do high-risk claims require independent sources?

High-risk claims (where `risk == "high"`) require two independent sources to prevent circular verification. The `_independent_group_count` function groups sources sharing the same origin, content hash, or `independence_key` (lines 897-903), and the validator enforces this requirement at lines 1128-1132 to ensure robust evidentiary support.