Dependencies

Dependencies connect claims to their sources and to other claims. When a source changes, TruthKeeper uses these dependencies to identify all affected claims.

Dependency Types

TruthKeeper uses a three-tier dependency model:

HARD

The claim is invalid if the source changes. Use for direct factual dependencies.

Example: “Function X calls function Y” depends on both functions existing.

SOFT

The claim may need review if the source changes. Use for contextual dependencies.

Example: “The API uses REST conventions” depends on API design docs.

DERIVED

The claim was computed from the source. Use for aggregated knowledge.

Example: “The codebase has 42 API endpoints” is derived from scanning all routes.

Dependency Targets

Dependencies can point to:

External Sources

{
  "target": "file://src/services/user.py",
  "type": "HARD"
}

{
  "target": "git://main/src/api/routes.py@abc123",
  "type": "HARD"
}

{
  "target": "https://api.example.com/v1/schema",
  "type": "SOFT"
}

Other Claims

{
  "target": "claim://clm_abc123",
  "type": "DERIVED"
}

Cascade Propagation

When a source changes, TruthKeeper walks the dependency graph to identify all affected claims. The cascade algorithm:

  1. Source watcher detects change
  2. Find all claims with direct dependencies on that source
  3. Mark direct dependents as STALE
  4. Find claims that depend on those claims
  5. Mark transitive dependents based on dependency type
  6. Calculate blast radius for each affected claim
  7. Queue high-impact claims for human review
Source Change: file://src/auth.py modified
       │
       ▼
┌──────────────────────────────────────────────┐
│ Direct Dependencies (HARD)                   │
├──────────────────────────────────────────────┤
│ Claim: "AuthService validates tokens"        │ → STALE
│ Claim: "JWT tokens expire after 1 hour"      │ → STALE
└──────────────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────────────┐
│ Transitive Dependencies                      │
├──────────────────────────────────────────────┤
│ Claim: "API requires authentication"         │ → SUSPECT (SOFT)
│ Claim: "42 endpoints use auth"               │ → SUSPECT (DERIVED)
└──────────────────────────────────────────────┘

Cascade Rules

Parent StateDependency TypeChild State
STALEHARDSTALE
STALESOFTSUSPECT
STALEDERIVEDSUSPECT
OUTDATEDHARDOUTDATED
OUTDATEDSOFTCONTESTED
OUTDATEDDERIVEDSTALE

Source Watchers

Source watchers monitor external sources and notify TruthKeeper when they change.

File Watcher

from truthkeeper.watchers import FileSourceWatcher

watcher = FileSourceWatcher(
    client=client,
    paths=["src/", "lib/"],
    patterns=["**/*.py", "**/*.ts"],
    ignore=["**/__pycache__/**", "**/node_modules/**"]
)

await watcher.start()

Git Watcher

from truthkeeper.watchers import GitSourceWatcher

watcher = GitSourceWatcher(
    client=client,
    repo_path=".",
    branch="main",
    poll_interval=60  # seconds
)

await watcher.start()

Webhook Receiver

# In your CI/CD pipeline
curl -X POST http://truthkeeper:8000/api/v1/sources/changed \
  -H "Content-Type: application/json" \
  -d '{
    "uri": "file://src/api/routes.py",
    "change_type": "MODIFIED",
    "commit": "abc123"
  }'

Stale Claims Cache

For efficient cascade resolution, TruthKeeper maintains a cache of stale claims indexed by source. This allows O(1) lookup of affected claims when a source changes.

# Get all stale claims efficiently
stale = await client.get_stale_claims()

# Get stale claims for a specific source
stale = await client.get_stale_claims(
    source="file://src/auth.py"
)

# Batch reverify
results = await client.reverify_claims([c.id for c in stale])

Best Practices

Choosing Dependency Types

  • HARD: Use when the claim directly quotes or references specific code/data
  • SOFT: Use when the claim is about patterns, conventions, or design decisions
  • DERIVED: Use when the claim summarizes or aggregates information

Avoiding Dependency Cycles

TruthKeeper detects and prevents circular dependencies. If you need bidirectional relationships, use DERIVED dependencies which don't cascade infinitely.

Dependency Granularity

  • Too coarse: “depends on src/” triggers on any file change
  • Too fine: “depends on line 42” breaks on any edit
  • Just right: “depends on src/auth.py:AuthService.validate”

Next Steps