Skip to main content
Glama
J-X0

Kingfisher Streaming Inference

by J-X0
README.md
# Kingfisher Streaming Inference

Incremental model scoring over an append-only event log, with a hash-chained
audit trail so every decision can be reviewed and independently re-verified.
Built for Quarryman Labs (Project Kingfisher).

## Why it is shaped this way

The governing constraint is that **every decision must carry a reviewable audit
trail**. That drives the architecture:

- Events land in an **append-only log** (`kingfisherstreaming/log.py`). There is
  no update or delete path; duplicate ids are rejected.
- Each event is scored **incrementally** (`kingfisherstreaming/scoring.py`)
  using Welford's online mean/variance. Scoring one event is O(1) and never
  rescans the log, which is what makes the stream tractable over time.
- Every decision is written to a **hash-chained audit log**
  (`kingfisherstreaming/audit.py`). Each record's SHA-256 covers its contents
  and the previous record's hash, so any later edit, reorder, or deletion is
  detectable with `verify()`.

Model behaviour sits behind a provider interface
(`kingfisherstreaming/providers/base.py`) with a deterministic, offline stub
(`stub.py`) used by the tests and an HTTP-backed implementation (`real.py`).
The full test suite runs offline with no API key.

## Layout

```
kingfisherstreaming/
  types.py          domain types (Event, Score, Decision, ...)
  log.py            append-only event log (in-memory + optional JSONL)
  scoring.py        Welford running stats + incremental scorer (core algorithm)
  audit.py          hash-chained, tamper-evident audit log
  engine.py         wires log + scorer + audit into one ingest path
  providers/
    base.py         ScoringProvider interface
    stub.py         deterministic offline provider
    real.py         HTTP-backed provider (optional 'real' extra)
tests/
```

## Install and test

```
make install      # creates .venv and installs with the dev extra
make test         # runs pytest
```

Override the interpreter if you manage your own venv:

```
make test PY=python
```

## Usage

```python
from kingfisherstreaming import StreamingInferenceEngine, Event
from kingfisherstreaming.providers.stub import StubProvider

engine = StreamingInferenceEngine(StubProvider(), threshold=3.0, min_samples=30)

score, record = engine.ingest(
    Event(event_id="lease-001", stream="office-cbd", timestamp=0.0, value=100.0)
)
print(score.decision, score.normalized_score)
assert engine.verify_audit()   # re-checks the entire chain
```

During cold start (fewer than `min_samples` observations on a stream) the
decision is `REVIEW`, not a guessed pass/flag: with too little history a z-score
is not trustworthy, and saying so is part of the audit trail.

To score against a real endpoint:

```
pip install '.[real]'
export KINGFISHER_SCORING_ENDPOINT=https://scoring.internal/score
export KINGFISHER_API_KEY=...
```

## Running the MCP server

The server speaks JSON-RPC 2.0 over stdio (one JSON object per line),
implemented with the standard library only. Logs are JSON on stderr; stdout
carries only protocol frames.

```
python -m kingfisherstreaming serve
```

Tools exposed: `ingest_event`, `verify_audit`, `stream_stats`, `export_audit`.
`verify_audit` and `export_audit` exist so a reviewer can pull and re-check the
hash chain through the same interface that produced the decisions.

Example exchange (request on stdin, response on stdout):

```
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"ingest_event","arguments":{"event_id":"lease-001","stream":"office-cbd","timestamp":0.0,"value":100.0}}}
```

## Batch scoring a file

```
python -m kingfisherstreaming score events.jsonl
```

One event object per line. Malformed lines are logged and skipped, not fatal;
the exit code is non-zero only if the resulting audit chain fails verification.

## Configuration

All configuration is read from the environment and validated at startup:

| Variable | Default | Meaning |
|---|---|---|
| `KINGFISHER_PROVIDER` | `stub` | `stub` (offline) or `real` (HTTP) |
| `KINGFISHER_THRESHOLD` | `3.0` | z-score magnitude that flags an event |
| `KINGFISHER_MIN_SAMPLES` | `30` | per-stream samples before scoring leaves REVIEW |
| `KINGFISHER_LOG_PATH` | unset | JSONL path to persist events |
| `KINGFISHER_AUDIT_PATH` | unset | JSONL path to persist the audit chain |
| `KINGFISHER_MAX_EVENT_BYTES` | `65536` | reject events larger than this |
| `KINGFISHER_MAX_FEATURES` | `256` | reject events with more features than this |
| `KINGFISHER_LOG_LEVEL` | `INFO` | logging level |

Invalid configuration exits non-zero with a message on stderr rather than a
traceback.

TDQS

A3.5/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a clear, distinct role: ingest_event adds data, verify_audit validates the chain, stream_stats provides metrics, and export_audit retrieves records. There is no functional overlap between any of the four tools.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (ingest_event, verify_audit, stream_stats, export_audit). The naming is predictable and immediately communicates each tool's action and target.

Tool Count5/5

With 4 tools, the set is tightly scoped to the server's apparent purpose of event ingestion and audit verification. Each tool earns its place, and the number is well within the typical range for a focused toolkit.

Completeness4/5

The set covers the core lifecycle of an audit chain: ingest, verify, export, and stream-level statistics. Minor gaps exist, such as no per-record retrieval or stream configuration, but the essential workflows are complete.

Maintenance

ActivityInactive
ResponsivenessNo issues