Skip to main content

sm-resolver — the corroboration kernel

A tiny, dependency-free kernel for detecting when independent sources disagree about the same subject. Point it at two or more sources, ask them the same question, and it reports any disagreement. It is the machinery under cross-registry / cross-method divergence detection, factored out so any layer can reuse it.

It is the reference implementation of the IETF draft Multi-Source Corroboration for AI Agent Discovery (draft-chandra-agent-registry-corroboration-00).

Five pieces, and only the resolvers know a wire format:

  • View — the contract a claim implements: comparable() → {field: value}. Those fields are what gets compared; a None value never participates.
  • Resolver[T] — a per-source adapter: a canonical id → (Status, View). It hides one source's format (an HTTP GET, a DID resolve, a DNS lookup) and MUST NOT raise — an unreachable source is error (no claim), never a false absent. It MAY expose a vantage — an observation context, class:value from a controlled vocabulary (SPEC.md §3a).
  • Claim — one source's answer from one vantage at one instant.
  • diff_claims — the pure diff: a sweep's claims → Finding list. It emits omission (present on one source, positively absent on another), source_equivocation (one source's vantages disagree with each other), and one finding per view field whose values disagree across sources. It never learns its layer.
  • Corroborator — resolve every (source, vantage), diff, apply confirmation, and return one SweepResult per subject: a verdict (AGREE / DIVERGENT / INSUFFICIENT), the claims, and the findings. Fewer than two decisive claims → INSUFFICIENT.

Install

pip install sm-resolver        # zero runtime dependencies

Use

Supply a view (its fields are what you compare) and a thin resolver per source:

import asyncio
from collections.abc import Mapping
from dataclasses import dataclass
from sm_resolver import Corroborator, Status

@dataclass(frozen=True)
class RecordView:                       # your layer's view
    endpoint: str | None = None
    def comparable(self) -> Mapping[str, str | None]:
        return {"endpoint": self.endpoint}

class MyResolver:                       # your thin per-source adapter
    def __init__(self, label): self.label = label
    async def resolve(self, agent_id) -> tuple[Status, RecordView | None]:
        ...                             # query this source; normalize to RecordView

results = asyncio.run(
    Corroborator([MyResolver("a"), MyResolver("b")]).check(["agent-1"])
)
for r in results:
    print(r.agent_id, r.verdict)             # agent-1 DIVERGENT
    for f in r.findings:
        print(" ", f.kind, f.confirmation, f.detail)
        # endpoint suspected {'field': 'endpoint', 'values': {'a': 'https://real', 'b': 'https://evil'}}

Long-running? Pass on_finding= — it fires once per distinct finding across the corroborator's lifetime — and staleness_window_s= to promote a re-observed finding from suspected to confirmed.

Who uses it

sm-divergence builds the reference layers on this kernel: a discovery layer (registries — NEST, the NANDA Index) and an identity layer (DID methods — did:key, did:web, Universal Resolver), each supplying its own view and thin resolvers. Capability and evidence layers are the same shape.

Design rules

  • A timeout is not a claim. An unreachable or erroring source is excluded, never counted as an omission.
  • Only present, comparable values disagree. A None field contributes nothing — an unverifiable value is not a disagreement.
  • The diff stays pure and generic — deterministic, no I/O, never raises, never learns its layer. All I/O lives in the resolvers.

Develop

make ci-local   # uv: sync → ruff → format → mypy --strict → pytest

License

MIT


First published: 2026-07-04 | Last modified: 2026-07-04

Personal research contributions aligned with Project NANDA standards. Stellarminds.ai

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sm_resolver-0.4.0.tar.gz (54.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sm_resolver-0.4.0-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

Details for the file sm_resolver-0.4.0.tar.gz.

File metadata

  • Download URL: sm_resolver-0.4.0.tar.gz
  • Upload date:
  • Size: 54.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for sm_resolver-0.4.0.tar.gz
Algorithm Hash digest
SHA256 af0ff7a0cb583d52c8d42473effbdf63cb4a53c3a50116e0ff7ef90f0ef13842
MD5 4daa3a35f3e11ad74237f72b5fe59acc
BLAKE2b-256 0257383deb9733c987d363bee71edf1d3e613285daf63a27029aa9033257f509

See more details on using hashes here.

Provenance

The following attestation bundles were made for sm_resolver-0.4.0.tar.gz:

Publisher: release.yml on Sharathvc23/sm-resolver

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sm_resolver-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: sm_resolver-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 16.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for sm_resolver-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7fefcf9bf4ed8f8b9a444315a5c70dc8859dcfb03b821c2bb6b66c774db308b2
MD5 b235bdeec5d33a4d4ee77f03e7765070
BLAKE2b-256 844348c360eab2deab4f3e1084073b3f5e2cfeb50c0f5f73dbcb5aa72fe94005

See more details on using hashes here.

Provenance

The following attestation bundles were made for sm_resolver-0.4.0-py3-none-any.whl:

Publisher: release.yml on Sharathvc23/sm-resolver

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.6.0

2 files

0.5.0

2 files

This release

0.4.0 This release

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page