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:
- System Architecture (all modules, layers, relationships)
- Claim Lifecycle (end-to-end data flow & decision routing)
- Validation Matrix (what’s proven, partial, and not yet done)
Architecture overview
Section titled “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
Section titled “Paper section → module mapping”§4.1 Narrators and Chains
Section titled “§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
Section titled “§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)
Section titled “§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
Section titled “§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
Section titled “§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
Section titled “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_chainfrom isnad.core.chain import adalah_grades_for_chainfrom isnad.types import NarratorGrade, TransformType
class MyGradingStrategy: def compute_chain_grade(self, link_narrator_grades, link_transform_types, is_complete, *, corroboration_support=False, link_adalah_grades=None): # custom logic here ...
result = grade_chain( grades, transforms, is_complete=True, strategy=MyGradingStrategy(), link_adalah_grades=adalah_grades_for_chain(reg, chain),)Data flow
Section titled “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() → DB2. 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 → min4. Content criticized independently (critics/*.py) ← Corpus → EmbeddingCritic (TF-IDF cosine) or HybridCritic (MiniLM → NLI) → ContentVerdict: CONSISTENT | CONTRADICTION | UNVERIFIABLE5. 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 → 5×3 matrix → Action: SERVE | SERVE_WITH_CAVEAT | REVIEW | QUARANTINE | REJECT7. Action executed: serve / review / quarantine8. Evidence logged back to Registry (jarḥ–taʿdīl loop closes) → POST /v1/evidence → Registry.record_evidence() → Narrator grades evolve with evidence over timeModule structure (src/isnad/)
Section titled “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() (5×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