Isnād–Rijāl Framework: Concept → Code Mapping
This document maps each concept from the paper "Grading the Narrators" (Raja, 2026)
to its implementation in this repository.
Full architecture diagram: ARCHITECTURE.drawio — 3 tabs:
1. System Architecture (all modules, layers, relationships)
2. Claim Lifecycle (end-to-end data flow & decision routing)
3. Validation Matrix (what's proven, partial, and not yet done)
Architecture overview
The framework has five core components, plus the decision matrix that combines them:
┌──────────────────────────┐
│ Decision Matrix │
│ (core/decision.py) │
│ chain_grade × verdict │
│ → Action │
└──────────┬─────┬──────────┘
│ │
┌──────────────┘ └──────────────┐
▼ ▼
┌───────────────────┐ ┌───────────────────┐
│ Chain Grading │ │ Matn Criticism │
│ (core/grading.py) │ │ (matn.py, │
│ RefinedWeakestLink │ │ critics/*.py) │
└─────────┬─────────┘ └───────────────────┘
│
┌────────────┼────────────────┐
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌─────────────────┐
│ Chain │ │Registry │ │ Corroboration │
│ Engine │ │ (rijāl) │ │ (mutābaʿāt) │
│(core/ │ │(core/ │ │(core/corroborati│
│chain.py)│ │registry. │ │on.py) │
└─────────┘ │py) │ └─────────────────┘
└──────────┘
Paper section → module mapping
§4.1 Narrators and Chains
| Concept |
Module |
Key classes/functions |
| Narrator types (source, scraper, model, human) |
isnad/types.py |
NarratorType enum |
| Transmission chain |
isnad/core/chain.py |
Chain, ChainLinkSpec |
| Transform type (destructive/generative/pass-through) |
isnad/types.py |
TransformType enum |
| Completeness (ittiṣāl) |
isnad/core/chain.py |
Chain.is_complete, Chain.chain_status |
| Chain storage |
isnad/core/chain.py |
store_claim(), get_chain_from_db() |
| Claim normalization + hashing |
isnad/core/chain.py |
normalize_claim_text(), make_claim_id() |
§4.2 Narrator Registry & jarḥ–taʿdīl
| Concept |
Module |
Key classes/functions |
| Narrator grade (ordinal tiers) |
isnad/types.py |
NarratorGrade enum |
| Domain-conditioned key |
isnad/core/registry.py |
Registry — key is (narrator_id, domain) |
| ʿAdālah (integrity axis) |
isnad/types.py |
AdalahGrade enum |
| Ḍabṭ (precision axis) |
isnad/types.py |
DabtGrade enum |
| jarḥ–taʿdīl state machine |
isnad/core/registry.py |
Registry.record_evidence() |
| Bayesian transition policy (DEFAULT) |
isnad/core/registry.py |
BayesianTransitionPolicy (Beta posterior → grade) |
| Threshold transition policy (legacy fallback) |
isnad/core/registry.py |
ThresholdTransitionPolicy |
| Calibrated threshold policy |
isnad/core/registry.py |
CalibratedThresholdPolicy |
| Pluggable transition protocol |
isnad/types.py |
TransitionPolicy protocol |
| Evidence log (immutable) |
isnad/core/registry.py |
Narrator.evidence_log, NarratorEvidence (ORM) |
| Version bump reset |
isnad/core/registry.py |
Registry.bump_version() |
| Quarantine (mawḍūʿ containment) |
isnad/core/registry.py |
Registry.quarantine() |
§4.3 Corroboration (mutābaʿāt)
| Concept |
Module |
Key classes/functions |
| Independent-chain upgrade |
isnad/core/corroboration.py |
evaluate_corroboration() |
| CorroborationEngine |
isnad/core/corroboration.py |
.evaluate(), .evaluate_direct() |
| Capped upgrade policy (info-theoretic) |
isnad/core/corroboration.py |
CappedCorroborationPolicy |
| Minimum-grade gate |
isnad/core/corroboration.py |
CappedCorroborationPolicy.MIN_GATE_GRADE |
| Correlation detection (madār) |
isnad/core/corroboration.py |
SharedLineageDetector |
| Independence score |
isnad/core/corroboration.py |
SharedLineageDetector.compute_independence_score() |
| Finding corroborating claims |
isnad/core/corroboration.py |
find_corroborating_claims() |
§4.4 Dual Criticism & Decision Matrix
| Concept |
Module |
Key classes/functions |
| Content criticism protocol |
isnad/critics/base.py |
ContentCritic protocol |
| Deterministic critic (reference stub) |
isnad/matn.py |
DeterministicRuleCritic |
| EmbeddingCritic (TF-IDF — DEFAULT) |
isnad/critics/embedding.py |
EmbeddingCritic, TFIDFIndex |
| LocalNLICritic (DeBERTa cross-encoder) |
isnad/critics/nli.py |
LocalNLICritic |
| HybridCritic (MiniLM → NLI, 2-stage) |
isnad/critics/nli.py |
HybridCritic |
| LLMCritic (provider-agnostic: OpenRouter / OpenAI / DeepSeek / Anthropic / Gemini / …) |
isnad/critics/llm.py |
LLMCritic |
| Decision matrix |
isnad/core/decision.py |
decide(), describe_action() |
| Action routing |
isnad/types.py |
Action enum |
| Review queue |
isnad/models.py |
ReviewQueue (ORM) |
§5 Reference Schema
| Concept |
Module |
Key classes/functions |
| rijal_claims table |
isnad/models.py |
RijalClaim (ORM) |
| narrator_registry table |
isnad/models.py |
NarratorRegistry (ORM) |
| chain_links (normalized) |
isnad/models.py |
ChainLink (ORM) |
| narrator_evidence table |
isnad/models.py |
NarratorEvidence (ORM) |
| review_queue table |
isnad/models.py |
ReviewQueue (ORM) |
| JSONB narrator_chain |
isnad/models.py |
RijalClaim.narrator_chain |
| Lifecycle (supersession) |
isnad/models.py |
RijalClaim.valid_from/valid_until/superseded_by |
| Database session |
isnad/storage/sqlalchemy.py |
get_session(), init_db(), get_engine() |
| Persistence protocol |
isnad/storage/base.py |
RegistryPersistence protocol |
| Alembic migrations |
alembic/ |
Initial migration: all 5 tables + indexes |
Pluggable strategy extension points
Each open parameter from the paper (§4.2/§4.3) maps to a Python protocol:
| Paper concept |
Protocol |
Default implementation |
| Chain grading strategy |
GradingStrategy |
RefinedWeakestLink |
| Transition policy (jarḥ–taʿdīl) |
TransitionPolicy |
BayesianTransitionPolicy |
| Corroboration policy |
CorroborationPolicy |
CappedCorroborationPolicy |
| Correlation detection |
CorrelationDetector |
SharedLineageDetector |
| Content criticism |
ContentCritic |
EmbeddingCritic (TF-IDF) |
To provide a custom implementation, create a class implementing the protocol and pass it:
from isnad.core.grading import grade_chain
from isnad.types import NarratorGrade, TransformType
class MyGradingStrategy:
def compute_chain_grade(self, link_narrator_grades, link_transform_types,
is_complete, *, corroboration_support=False):
# custom logic here
...
result = grade_chain(
grades, transforms, is_complete=True,
strategy=MyGradingStrategy(),
)
Data flow
1. Claim ingested → Chain built (core/chain.py)
→ normalize_claim_text() + SHA-256 → claim_id
→ ChainLinkSpec per link (narrator_id, step, transform_type, trace_id)
→ store_claim() → DB
2. Chain links looked up in Registry (core/registry.py)
→ Registry.get_grade(narrator_id, domain) per link
→ BayesianTransitionPolicy (Beta posterior → grade)
3. Chain grade computed (core/grading.py) ← Registry grades
→ RefinedWeakestLink walks chain link-by-link
→ DESTRUCTIVE → hard floor | GENERATIVE → can repair | PASS_THROUGH → min
4. Content criticized independently (critics/*.py) ← Corpus
→ EmbeddingCritic (TF-IDF cosine) or HybridCritic (MiniLM → NLI)
→ ContentVerdict: CONSISTENT | CONTRADICTION | UNVERIFIABLE
5. Corroboration evaluated (core/corroboration.py) ← Other claims
→ CorroborationEngine checks independence, min grade gate, effective weight
→ DAIF → HASAN (capped, never reaches SAHIH)
6. Decision matrix routes action (core/decision.py) ← chain_grade + content_verdict
→ 4×3 matrix → Action: SERVE | SERVE_WITH_CAVEAT | REVIEW | QUARANTINE | REJECT
7. Action executed: serve / review / quarantine
8. Evidence logged back to Registry (jarḥ–taʿdīl loop closes)
→ POST /v1/evidence → Registry.record_evidence()
→ Narrator grades evolve with evidence over time
Module structure (src/isnad/)
isnad/
├── __init__.py Public API re-exports
├── types.py All enums, protocols, ordinal types
├── models.py SQLAlchemy ORM (5 tables)
├── matn.py DeterministicRuleCritic (reference stub)
├── core/ Core engine
│ ├── chain.py Chain, ChainLinkSpec, store_claim()
│ ├── registry.py Registry, RegistryDB, BayesianTransitionPolicy
│ ├── grading.py RefinedWeakestLink, grade_chain()
│ ├── corroboration.py CorroborationEngine, SharedLineageDetector
│ └── decision.py decide(), describe_action() (4×3 matrix)
├── critics/ Content criticism
│ ├── base.py ContentCritic protocol
│ ├── embedding.py EmbeddingCritic (TF-IDF — DEFAULT, zero-deps)
│ ├── nli.py LocalNLICritic, HybridCritic (DeBERTa + MiniLM)
│ ├── llm.py LLMCritic (Anthropic Claude, retrieval-augmented)
│ └── eval.py Critic evaluation harness
├── api/ FastAPI service
│ ├── app.py create_app() factory
│ ├── auth.py API key authentication
│ ├── dependencies.py DI: get_db(), get_registry(), get_critic()
│ └── endpoints/
│ ├── claims.py POST/GET /v1/claims
│ ├── narrators.py POST/GET /v1/narrators, POST /v1/evidence
│ └── health.py /v1/health, /metrics (Prometheus)
├── cli/ CLI entry point
│ └── main.py isnad serve | isnad seed
├── storage/ Persistence layer
│ ├── base.py RegistryPersistence protocol
│ └── sqlalchemy.py SQLAlchemy engine, session, init_db()
└── integrations/
└── langchain/ LangChain integration
├── tracer.py IsnadTracer (callback handler)
├── decorator.py @isnad_track decorator
└── helpers.py seed_registry(), CriticAdapter