witnessfield
Describes the external witness structure around a claim. Scoring is a swappable policy — not the protocol.
Institution role (Node 34539544): witness-structure library used by geniusflow-engine. Sister: helixhash. Full map: sangat-architecture/INSTITUTION_REPOSITORY_MAP.md.
v1.0 is a clean rewrite. In v0.x, scoring and priors were baked into the protocol, which created circular dependencies between the two libraries (HelixHash was a high-trust witness class inside witnessfield, and witnessfield-style credibility values leaked into HelixHash entries). v1.0 separates the protocol (what the library guarantees) from policy (opinions about how to weight things). HelixHash now only guarantees order and non-tampering. witnessfield now only describes witness structure. Scoring is a separate, swappable policy layer.
Install
pip install witnessfield
What it guarantees
witnessfield describes the external witness structure around a claim. The structure is the protocol. Scores are policy — one plausible policy ships as DefaultPolicy, but the priors, weights, and thresholds it uses are opinion, not measurement. Swap it for your own.
Quickstart
from witnessfield import Claim, Witness, CustodyHop, WitnessStructure
from witnessfield.policy import DefaultPolicy
# Describe the structure — no scoring needed
claim = Claim(
id="claim-001",
content="The Federal Reserve will issue tokenized-asset guidance by 2026-12-31.",
observed_at=1745000000.0,
)
journalist = Witness(
id="w1",
witness_class="journalist_primary", # caller-assigned — library makes no assumption
attested_content="WSJ reports Fed circulating draft guidance on tokenized settlement.",
observed_at=1745000000.0,
)
structure = WitnessStructure(claim=claim, witnesses=[journalist], hops=[])
# Structural summary — no policy required
desc = structure.describe()
print(desc["n_witnesses"]) # 1
print(desc["n_independent"]) # 1
print(desc["hop_count"]) # 0
# Score with any Policy implementation
policy = DefaultPolicy.from_legacy_priors() # loads v0.x calibration as a starting point
score = structure.score(policy)
print(f"V = {score:.4f}") # ~0.64 for a 1-year-old claim from a primary journalist
Protocol structure
The protocol defines four dataclasses and one constant.
FIDELITY_DIMS: tuple[str, ...] = (
"reversibility", # can the record be altered without detection?
"accountability", # is the witness identifiable and answerable?
"physical_trace", # does a tamper-evident physical record exist?
"independence", # is the witness free from the claim's beneficiary?
"specificity", # does the witness address this claim specifically?
"motivation_clean", # does the witness have clean motive (no conflict)?
"cross_referenceable", # can the claim be confirmed from an independent source?
)
@dataclass(frozen=True)
class Claim:
id: str
content: str
observed_at: float
@dataclass(frozen=True)
class Witness:
id: str
witness_class: str # free-form; policy decides meaning
attested_content: str
observed_at: float
signature: Optional[bytes] = None
@dataclass(frozen=True)
class CustodyHop:
source: str # witness id or "origin"
destination: str # witness id or "engine"
fidelity: dict[str, float] # subset of FIDELITY_DIMS; values in [0, 1]
@dataclass
class WitnessStructure:
claim: Claim
witnesses: list[Witness]
hops: list[CustodyHop]
def describe(self) -> dict: ... # structural summary, no scoring
def score(self, policy) -> float: # delegates to policy.score(self)
CustodyHop raises ValueError at construction if any fidelity key is not in
FIDELITY_DIMS, or if any value is outside [0.0, 1.0].
WitnessStructure raises ValueError at construction if the hop graph contains
a cycle (cycles are meaningless in a custody chain).
describe() — structural summary
desc = structure.describe()
# {
# "n_witnesses": 2,
# "n_independent": 1, # witnesses not receiving info from another witness
# "hop_count": 1,
# "age_seconds": 31557600.0, # time.time() - claim.observed_at
# "witness_class_counts": {"journalist_primary": 1, "licensed_professional": 1},
# "fidelity_profile": { # per FIDELITY_DIM across all hops
# "reversibility": {"min": 0.7, "mean": 0.7, "max": 0.7},
# ...
# }
# }
describe() is deterministic and policy-free. Calling it with no policy,
or calling it before any policy is loaded, always works.
Scoring is policy
from witnessfield.policy import Policy, DefaultPolicy
class Policy(Protocol):
def score(self, structure: WitnessStructure) -> float: ...
Implement the one-method Protocol with any callable to plug in your own scoring.
DefaultPolicy ships as a reference implementation. It uses:
w_base: prior credibility per witness classdecay_lambda: temporal decay rate per claim typefidelity_aggregator: how to aggregate hop fidelity dimensions (default: geometric mean)quantity_fn: how to aggregate witness count (default: log corroboration)
policy = DefaultPolicy(
w_base={"primary_source": 0.80, "secondary_report": 0.45},
decay_lambda={"prediction": 0.70, "default": 0.15},
)
score = structure.score(policy)
Migration from v0.x
# Load the old priors exactly — use as a starting point, not production calibration
policy = DefaultPolicy.from_legacy_priors()
The v0.x priors are stored in witnessfield/_legacy/legacy_priors.json as a
data file. They are opinion, not measurement. from_legacy_priors() is a
migration bridge; replace it with your own calibrated priors.
The archived v0.x tag is v0.1.0-archive.
Custody chain example
hop1 = CustodyHop(
source="origin",
destination="w1",
fidelity={
"reversibility": 0.95,
"accountability": 0.90,
"physical_trace": 1.00,
"independence": 0.85,
"specificity": 0.95,
"motivation_clean": 0.90,
"cross_referenceable": 1.00,
},
)
hop2 = CustodyHop(
source="w1",
destination="engine",
fidelity={"reversibility": 0.80, "physical_trace": 0.60},
)
structure = WitnessStructure(claim=claim, witnesses=[w1], hops=[hop1, hop2])
desc = structure.describe()
# fidelity_profile["reversibility"]["mean"] == 0.875
# fidelity_profile["physical_trace"]["mean"] == 0.80
Tests
pytest tests/test_witnessfield.py -v
Includes a grep test verifying that no blessed witness class names
("blockchain", "helix_anchored", "helixhash") appear in core.py
or policy.py. The library does not privilege any witness class.
Honest limitations
DefaultPolicyuses"default"lambda for all claims. Subclass it and overridescore()if you need per-claim-type decay.describe()usestime.time()forage_seconds. Mock it in tests for deterministic age values.- No cryptographic signature verification in the protocol layer. If a
Witness.signatureis present, a policy may verify it; the library does not.
License
MIT — Kirandeep Kaur, 2026
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file witnessfield-1.0.0.tar.gz.
File metadata
- Download URL: witnessfield-1.0.0.tar.gz
- Upload date:
- Size: 15.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5377926f44a8251e4c04480b9efa5b38ab8d4c3b9717051c3bbffaed5e76ccfa
|
|
| MD5 |
fec0c7867e0143aefadf4f1367ebc16b
|
|
| BLAKE2b-256 |
77217304b9bd294488f4e26812c6b1d2900ba10711cf5019c0c884916345e2e2
|
File details
Details for the file witnessfield-1.0.0-py3-none-any.whl.
File metadata
- Download URL: witnessfield-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
820ccf0f0f2d2817d8f7af6da8d9fecf0186327e75f8efa59147f2cda775f457
|
|
| MD5 |
6372c7398363f2dfee0264dc9c6d3919
|
|
| BLAKE2b-256 |
c438de50f9c7e8a4d36d15e30e0502bdd677c333910a8cabe15003eec08bbd8d
|