Metadata-Version: 2.5
Name: evidence-gap-router
Version: 0.2.4
Summary: Route work by missing evidence, not by agent count.
Project-URL: Homepage, https://github.com/kadubon/evidence-gap-router
Project-URL: Repository, https://github.com/kadubon/evidence-gap-router
Project-URL: Issues, https://github.com/kadubon/evidence-gap-router/issues
Project-URL: Changelog, https://github.com/kadubon/evidence-gap-router/blob/main/CHANGELOG.md
Author: K. Takahashi
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: agents,data-quality,evidence,routing,verification
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: pydantic<3,>=2.12
Description-Content-Type: text/markdown

# evidence-gap-router

**Route work by missing evidence, not by agent count.**

A small Python SDK that chooses the next acquisition or verification from
missing evidence and unfinished checks in a finite, host-declared action set.

Python **3.12+** · Apache-2.0 · [日本語](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/README.ja.md) · [Documentation](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/index.md)

## When to use it

Use it when permitted work depends on the material already obtained, verification
results, prerequisites, costs or changed rules. It retains evidence, issued
checks, failures, expenses and unresolved requirements across explicit continuation.

A fixed pipeline is usually sufficient when every input and step is already
known. The SDK does not supply agents, models, a network gateway or a scheduler.
Tracking verification history does not guarantee semantic truth. Separate calls
to the same model do not establish statistically independent judgments.

## Install and check

```sh
python -m pip install evidence-gap-router==0.2.4
egr --version
egr demo --json
```

These commands need no model or network after installation. The demo uses
artificial data. [Getting started](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/getting-started.md) creates actual UTF-8
CSV/JSON files, including quoted paths with spaces and Japanese characters,
then checks them with `egr check-data`.

## Connect a callback

This complete ordinary-wheel example parses the supplied content, selects a
check, records its actual result and shows the remaining blocking issues:

```python
from hashlib import sha256
from evidence_gap_router import (
    ActionCandidate,
    Budget,
    CallbackView,
    CheckerPermission,
    Evidence,
    HandlerRegistration,
    Obligation,
    Policy,
    Resources,
    State,
    plan,
    run,
)

content = "4"
evidence = Evidence(
    id="answer",
    obligation_id="sum",
    scope="example",
    digest=sha256(content.encode()).hexdigest(),
    content=content,
    producer="calculator",
    source="local-calculation",
    provenance_group="calculator",
)
state = State(
    obligations=(
        Obligation(
            id="sum",
            description="Check arithmetic",
            scope="example",
            acceptance="Parsed answer equals 2 + 2",
        ),
    ),
    evidence=(evidence,),
)
action = ActionCandidate(
    id="check-answer",
    obligation_id="sum",
    scope="example",
    kind="verify",
    handler_id="check",
    target_evidence_id="answer",
    target_digest=evidence.digest,
    checker_id="arithmetic-check",
    resources=Resources(actions=1, verifications=1),
)
policy = Policy(
    trusted_verifiers=("arithmetic-check",),
    handlers=(
        HandlerRegistration(
            handler_id="check",
            roles=("verify",),
            checkers=(CheckerPermission(checker_id="arithmetic-check"),),
        ),
    ),
)


def check(view: CallbackView):
    passed = int(view.inputs[0].content or "") == 2 + 2
    return view.result(
        actual_resources=Resources(actions=1, verifications=1),
        checks=(view.check(status="PASS" if passed else "FAIL", reason="Compared with 2 + 2"),),
    )


budget = Budget(limits=Resources(actions=1, verifications=1))
next_step = plan(state, (action,), budget, policy)
assert next_step.action is not None
print(next_step.action.id)  # check-answer

report = run(
    state,
    (action,),
    budget,
    policy,
    {"check": check},
    max_steps=8,
)
print(report.state.checks[-1].status)  # PASS
print(report.decision.stop_reason)  # satisfied
print([r.code for r in report.decision.residuals if r.blocking])  # []
```

The host registers checker permission; `view.check` binds the issued target,
contract and inputs. An ID supplied by an output grants no authority.
`step` invokes at most one callback; `run` has a finite step limit. Runner stops
and unresolved domain requirements are separate. Pending attempts and unknown
budgeted consumption block automatic continuation.

See [Concepts](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/design.md), [API](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/api.md) and
[snapshot/migration](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/migration.md) for acquisition, invalidation, rechecking,
selectors and retained costs. Limited callback views are application disclosures,
not a Python sandbox. The host owns input trust, effects, costs and single-writer use.

## Local Ollama experiment

The optional [Ollama guide](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/ollama-guide.md) uses source-level examples with
an ordinary installed SDK and explicit local inference. Ollama is not required
by core imports or the offline CLI. Model weights and user credentials are absent
from the package; normal tests and release CI do not run model inference.

A uses EGR ordering; B uses strong verify-first ordering with the same public
runner, pool, permissions, callbacks and budgets. C is a pooled-information
reference. The comparison concerns extra selection value within the shared
feasibility mechanism, not independent agent frameworks or a model ranking.

Current local tags `qwen3.6:35b-a3b` and `gemma4:e4b` completed 96 main trials
on one Windows CPU host. Each arm has 16 artificial parents: 12 answerable and
four insufficient. Verified completion requires independently supported evidence
and the current review/acceptance conditions.

| Model | Arm | Answerable verified /12 | All verified /16 | False acceptance /16 |
|---|---|---:|---:|---:|
| Qwen | A | 0 | 0 | 15 |
| Qwen | B | 8 | 10 | 4 |
| Qwen | C | 12 | 15 | 1 |
| Gemma | A | 3 | 4 | 2 |
| Gemma | B | 8 | 9 | 1 |
| Gemma | C | 10 | 14 | 2 |

A underperformed B in this frozen profile. All main trials have known usage;
there were zero unexecuted trials or transport/format faults. Small artificial
tasks share development families; these results do not establish general
performance. All 64 stop-sensitivity trials completed; recovery triggered zero
times, so its benefit remains unmeasured.
Initial invalid measurements and all expenses remain retained separately.
See the [technical report](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/ollama-experiment-v0.2.4.md),
[Japanese summary](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/ollama-experiment-v0.2.4.ja.md) and
[archived v0.2.3 report](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/ollama-experiment.md).

[Audit](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/audit-024.md) · [Validation](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/validation.md) ·
[Releasing](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/docs/releasing.md) · [Security](https://github.com/kadubon/evidence-gap-router/blob/v0.2.4/SECURITY.md)
