Skip to main content

pollard-jev

A Python companion to Pollard that turns timestamped observations and permitted choices into a governed decision, a bounded simulated action, and an outcome record. The first milestone runs entirely offline after installation. It needs no credentials, model weights, or GPU.

python -m pip install pollard-jev
pollard-jev demo --output artifacts

Published under the MIT license. The initial release is 0.1; minor increments are +0.01, major increments are +0.10, and releases at or above 1.0 require the owner's explicit approval. See the release policy.

Run on Windows PowerShell

Requires Python 3.11 or newer. Tested here on Python 3.12.2.

git clone https://github.com/jemsbhai/pollard-jev.git
Set-Location pollard-jev
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e ".[test]"
.\.venv\Scripts\python.exe -m pollard_jev demo --output artifacts
.\.venv\Scripts\python.exe -m pytest -q

Setup uses PyPI; the demo and tests make no network requests. The equivalent installed entry point is .\.venv\Scripts\pollard-jev.exe demo --output artifacts. Each demo writes uniquely named JSONL records and a Pollard SQLite ledger.

Scenario Synthetic proposal Final policy Simulated action
Fresh coherent observations continue accept move 20 cm
Conflicting observations inspect need evidence none
Missing evidence inspect need evidence none
Evidence expires during inference continue defer none
Request budget exhausted none defer none
Provider failure none defer none

The stale scenario advances a virtual clock during inference so it is reproducible. Separate tests exercise real waiting, timeout, and cancellation. The state-machine baseline reads the same request at the final evaluation time. It has no provider and therefore no provider failures or inference-request cost; the table is a behavior comparison, not a performance benchmark.

Typed inputs and outputs

from datetime import datetime, timedelta, timezone
from pollard_jev.contracts import Observation
from pollard_jev.demo import example_request
from pollard_jev.loop import DecisionLoop
from pollard_jev.providers.fixture import FixtureProvider

now = datetime.now(timezone.utc)
range_reading = Observation(
    observation_id="range-42", source="front-range-sensor",
    feature="front_range_m", value=1.5, unit="m",
    observed_at=now, valid_until=now + timedelta(seconds=5),
)
# The demo request supplies all four required sensor features and four choices.
request = example_request(now, request_id="robot-42")
request = request.model_copy(update={
    "observations": (range_reading, *request.observations[1:]),
})
with DecisionLoop(FixtureProvider(), max_requests=2,
                  records_path="artifacts/decisions.jsonl",
                  pollard_path="artifacts/decisions.db") as loop:
    record = loop.decide(request)
    print(record.model_dump_json(indent=2))

Run the complete example with .\.venv\Scripts\python.exe examples\offline_loop.py. Unknown readings use status="unknown", value=None; absence of a required feature is also explicit insufficient evidence. Datetimes must have timezones, validity windows must be positive, and numeric values must be finite.

A successful record contains fields like these (excerpt):

{
  "schema_version": "1",
  "provider_status": "ok",
  "provider_result": {
    "semantics": "synthetic_support",
    "scores": {"continue": 0.94, "inspect": 0.12, "recover": 0.12, "request_help": 0.12},
    "proposed_action": "continue",
    "parameters": {"distance_cm": 20},
    "evidence": "sufficient"
  },
  "policy": {"disposition": "accept", "reason": "supported_and_feasible"},
  "action": {"action": "continue", "status": "completed", "simulated": true},
  "budget_limit_requests": 2,
  "budget_spent_requests": 1
}

Full records include observation IDs, timestamps and units; the question and allowed choices; provider identity, version and settings; policy configuration and version; simulated skill version and observed state; timing and budget fields; and Pollard root/model/action node IDs. Records round-trip through validated Pydantic models. The JSONL is a convenient export; the same complete record is also stored as a Pollard note.

How the loop works

DecisionProvider.infer(tuple[DecisionRequest, ...]) returns typed results. The interface is general; this milestone's policy and skill set are specific to the robot demonstration. Providers return data and receive no dispatcher.

Pollard 1.6.0 supplies the real model-call ledger, custom request budget, registered action allowlist, integer argument bounds, refusal nodes, action records, SQLite persistence, and integrity verification. The companion supplies contracts, evidence/support policy, sensor validity checks, deadlines, cancellation, simulation, and linked decision records. The older sibling Pollard checkout was inspected but is not modified or used as a dependency. See the API inspection for exact versions and boundaries.

The policy checks four engineered sensor features: range and camera clearance in metres, battery percentage, and a stuck indicator of 0 or 1. Conflicting, missing, duplicate, invalid, expired, and future-dated readings block action. Support threshold 0.80, score margin 0.15, clearance 0.5 m, battery 10%, and range disagreement 0.4 m are demonstration settings, configurable through PolicyConfig. Required physical units cannot be relabeled to change their meaning. The policy also checks feasibility separately from evidence support. Task utility is represented by the caller's question and choice hypotheses; there is no trained utility or physical success predictor here.

The bounded simulated skills are:

Skill Permitted integer parameter Default
continue distance_cm: 1–50 20
inspect samples: 1–5 2
recover distance_cm: 1–20 10
request_help retries: 1 1

The request's selected parameter values must also match the provider proposal. Acceptance never expands the caller's available actions. The registered handler rechecks policy, freshness, cancellation, and the monotonic deadline immediately before dispatch. A second action in the same batch requires new observations, including when the first attempted action fails.

Inference runs in one daemon worker per loop. A timeout or cancellation discards that worker's reply. Until it finishes, later calls return busy; this prevents unbounded abandoned workers. Python cannot terminate arbitrary native model compute. A timeout bounds response/dispatch eligibility, not GPU execution or total process resource use. Cancellation does not undo an action already dispatched. Actual controllers, watchdogs, immediate stopping, and motion limits remain outside this supervisor.

The resource budget counts logical provider batch attempts: one infer(requests) invocation costs one regardless of question count. Success, malformed output, provider failure, timeout, and cancellation after admission each consume one. Pre-cancelled, busy, and budget-refused calls consume zero. Actions and audit notes consume zero model requests. This is not token, HTTP request, measured energy, or estimated-joule accounting. An adapter may perform multiple internal forward passes per logical batch. Budgets last for one loop instance/run; creating a new loop creates a new budget.

Independent support/entailment scores remain independent; they are never normalized into an action distribution. Categorical results are validated as such only when explicitly declared. Neither score type proves physical success. The fixture scores are synthetic and uncalibrated.

History, policy simulation, and live reevaluation

These are separate operations:

$recordFile = (Get-ChildItem artifacts\decisions-*.jsonl | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName
.\.venv\Scripts\python.exe -m pollard_jev history $recordFile
.\.venv\Scripts\python.exe -m pollard_jev simulate-policy $recordFile
$ledgerFile = (Get-ChildItem artifacts\pollard-*.db | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName
.\.venv\Scripts\pollard.exe verify $ledgerFile --json

inspect_history(path) only loads recorded events. simulate_policy(record, config, at=...) evaluates recorded observations and provider output with a specified policy/time. Neither has a dispatcher or a provider. Policy simulation does not replay the resource ledger, cancellation state, or a new physical trajectory. A changed action does not reveal what its consequences would have been.

live_reevaluate(record, loop) is an explicit new provider invocation. It consumes the loop's request budget, writes a new record linked to the original, preserves the original timestamps, and always disables dispatch. It uses whatever provider the caller explicitly put in that loop; with a fixture it remains synthetic. Old evidence normally defers at today's time. Historical records are never overwritten.

Credential fields, arbitrary malformed responses, and exception text are not persisted. Provider authentication must remain inside the caller-owned client. Do not put secrets in questions, observations, model identities, or settings: these are intentional audit content, not automatically scrubbed free text. The JSONL export and SQLite ledger are not a cross-file transaction. A crash may leave an intent or action without the final JSONL record; use the ledger for inspection. This is a single-process demonstrator, not crash recovery or exactly-once actuator infrastructure.

Optional real backend and next milestone

The implemented adapter targets the inspected AlexWortega/openjev qwen3.5-4b-nli-v2 helper at a pinned commit. Its NLI request/result mapping and local-cache loader are tested with doubles. No real model inference was run. The default cache contains no selected checkpoint, and the project environment has no heavy model dependencies. See OpenJev setup and evidence for the optional dependency/download commands, API, licenses, and limitations.

The next milestone is an explicit pinned real-model benchmark: validate the Windows/CUDA runtime, compare 0.8B and 4B candidates against the state machine on recorded/noisy scenarios, measure decision errors, abstention and end-to-end latency, and calibrate support thresholds on held-out data. Add process-level inference cancellation before device integration. Measure energy with an actual meter when available; keep TOML and other proxies separate from joules. Native sensor encoders, controller connections, and MCU deployment are later work.

See implementation status for verified behavior and remaining limitations.

Release files for pollard-jev 0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pollard-jev 0.1
File Size Uploaded
pollard_jev-0.1.tar.gz 46.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pollard-jev 0.1
File Interpreter ABI Platform
pollard_jev-0.1-py3-none-any.whl Python 3 none any Details

Total release size: 74.0 kB

Release files / pollard_jev-0.1.tar.gz

Download URL pollard_jev-0.1.tar.gz
Size 46.9 kB
Tags Source
SHA-256 checksum
How to use checksums
cd13179254fc3f29c4a1b5265b514ef989f87bd3d19432ebd4ddfa839ce3da66
BLAKE2b-256 checksum
How to use checksums
4352443607631f09275da5c8399e3e6fc54a491215e52d774b9c20b6b92d55b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.2

Release files / pollard_jev-0.1-py3-none-any.whl

Download URL pollard_jev-0.1-py3-none-any.whl
Size 27.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9b2879f369329d38b521b0b2f1a6d93661ae4926cfc8c240446a68f39cad2a3f
BLAKE2b-256 checksum
How to use checksums
94a8902b9eb2044b9d77d0e7a2130d0e843adea1fcc4847c563b699ee575b391
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.2

Release history Release notifications | RSS feed

This release

0.1 This release

2 release 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