ENGINE INTEGRATION — NOT MAPSWIPE-SPECIFIC

Load. Infer.
Unload.

The geoai worker owns the QueueLLM Runtime lifecycle. No ambiguity about model state. No orphaned GPU memory. The worker subscribes to the aerollm-bus, collects telemetry events in real time, and finalizes a deterministic receipt at shutdown. This page is generic engine/control-plane plumbing — it applies the same way whether the resulting predictions go to MapSwipe, a private evaluation, or nowhere at all. For the MapSwipe-specific export and permission path, see MapSwipe Integration.

CONTROL PLANE — DDAC INTEGRATION

INFERENCE REQUEST FLOW

DDaC

Manifest declares model, imagery, spatial splits, run config

Queue

InferenceRun objects published to the queue

Worker

Fetches run, processes with QueueLLM, produces receipt

Receipt

Content-addressed, immutable record of what the machine did — signing is a roadmap step

DDaC

Receipt recorded in audit trail for provenance

PINNED DDAC CONTRACTS

dac.manifest/v2

Dataset declaration: imagery source, imagery license, spatial splits, model metadata, run parameters

dac.zero-claw-exec/v1

Immutable execution envelope: model digest, sandbox profile, provenance chain, receipt validator

dac.InferenceRun

Task declaration for a single model run: model_path, model_digest, prompt, max_tokens, temperature, sandbox_profile, run_id

GeoAI consumes these as pinned specs from qukaizen-dac; never forks them. See ADR-0001 for boundary discipline.

DATA FLOW — WORKER LIFECYCLE

1. FETCH INFERENCE RUN

Worker fetches next InferenceRun from dac control plane

InferenceRun carries: model_path, model_digest, prompt, max_tokens, temperature, sandbox_profile, run_id. Worker stores run_id for receipt key.

2. UNLOAD PREVIOUS

If a model is loaded, shut it down cleanly via LifecycleController

if let Some(runtime) = self.runtime.take() { drop(runtime); } Drop triggers the destructor, which calls LifecycleController::shutdown(). GPU memory freed. Worker logs ShutdownComplete event with peak_rss and timestamp.

3. LOAD MODEL

Initialize AeroRuntime for the new model

let runtime = AeroRuntime::new(&run.model_path, config).await?; MLX context initializes. Model weights are mmapped (not loaded into RAM yet). Worker observes LoadComplete event on the bus and records it.

4. SUBSCRIBE TO AEROLLM-BUS

Open a channel to the runtime's telemetry stream

let mut subscriber = self.bus_subscriber.subscribe(); Now the worker will receive Init, Loading, LoadComplete, TokenEmitted, PrefetchHit, LayerEvicted, LayerInstalled, ArenaReset events.

5. RUN INFERENCE

Stream tokens and drain telemetry events in the inner loop

let mut token_stream = runtime.generate_streaming(...).await?;Inner loop: grab next token_id, drain all pending bus events, log each (TokenEmitted → token_id + rss + timestamp; PrefetchHit → layer + timestamp; LayerEvicted → layer + timestamp). Continue until max_tokens or signal.

6. FINALIZE RECEIPT

Mint the geoai.receipt/v1alpha1 with all collected telemetry

Receipt fields: model_digest, prompt_tokens, sampled_tokens, peak_rss, start_time, end_time, telemetry_log (all events collected), status, egress_audit_result. Finalize the receipt (content-addressed; signing lands later as a roadmap step) and write it to durable storage (for audit trail).

7. LOOP

Go back to step 1 and fetch the next run

The worker runs indefinitely. Each iteration: clean unload → fresh load → isolated inference → sealed receipt. No state leaks between runs.

RECEIPT VERIFICATION: THE HASH CHAIN

CANONICALIZATION: M1 · SIGNING: M3 (ADR-0004, DRAFT)

A receipt is not a log line. It is a chain of hashes: every input, every code path, every policy, and every output gets fingerprinted, and the fingerprints are checked against each other before a result is ever trusted. This is what turns "prove it ran on the right data" into a command you can run, instead of a promise you take on faith.

THE THREE-WAY MATCH (WHAT PROVES "RIGHT DATASET")

DECLARED

dac InferenceRun

  • dataset.expectedDigest
  • task.expectedDigest
  • model.expectedDigest

MATERIALIZED

bundle manifest, on disk

  • per-file sha256 set
  • task/ digests
  • model.ref.json digest

EXECUTED

geoai.receipt/v1alpha1

  • bundle_digest
  • task_digest
  • model_digest

The worker checks manifest against disk before running (fail closed on any mismatch, symlink escape, or undeclared file). The control plane checks declared against executed after. All three digests must agree, or the run is rejected: using the wrong dataset is not a mistake caught later, it is a run that never gets accepted in the first place.

WHAT ONE SIGNATURE COVERS

The signature (M3) is computed over the whole chain at once, never over a single field alone:

signature = sign(
  bundle_digest ‖ model_digest ‖ task_digest
  ‖ engine.build ‖ sandbox.profile_digest
  ‖ output_digest
)

Change any link (swap a tile, nudge a prompt file, downgrade the sandbox) and either a digest stops matching or the signature stops verifying. There is no path to a quiet substitution.

WHAT A RECEIPT PROVES (AND DOES NOT)

Proves: this exact bundle, this exact model, this exact task ran under this exact sandbox at this enforcement level, egress tests passed, and produced exactly these bytes.

Does not prove: that the prediction is correct (review and evaluation own truth), that the model is unbiased, or that the imagery handed to the worker was itself the untampered original the tile provider published. That last gap is the open question below.

OPEN QUESTION: WHO SIGNS, AND WHAT ABOUT THE TILES?

Two different questions get asked as one, and they have two different owners.

EXECUTION INTEGRITY (WE CAN SIGN THIS ALONE)

"This machine ran this model on this bundle in this sandbox and produced these bytes." Every digest in that claim is generated on our own hardware, from our own build, inside our own sandbox. A project key (cosign/DSSE) signing the receipt on acceptance covers this completely; no outside party needs to be involved for this half to be trustworthy.

SOURCE PROVENANCE (WE CANNOT SIGN THIS ALONE)

"The tiles we processed are the same tiles the imagery provider actually published, untampered." Our receipt can only hash what arrived at our door. To prove that hash matches the provider's original, the provider (Maxar, Planet, OSM/HOT's own imagery catalog, etc.) has to publish its own checksum or manifest independently, so a third party can compare the two. That checksum has to come from them, not from us: a self-issued claim cannot verify itself.

The practical shape (matching the SLSA/in-toto pattern of separate source, build, and acceptance attestations, each signed by a different identity) is three links, not one:

  1. 1. Source attestation (their signature): the imagery/tile provider or HOT's data pipeline publishes a digest for the exact tile set handed off for a given task.
  2. 2. Execution attestation (our signature): the geoai receipt, proving the bundle we actually ran matches that same digest and ran under a verified zero-egress sandbox.
  3. 3. Acceptance attestation (control plane or HOT, on ingest): dac (or HOT) countersigns that both of the above were checked before results are trusted downstream.

So: we can, unilaterally, sign and prove everything that happens after the tiles reach our sandbox. We cannot, unilaterally, prove the tiles themselves were untampered before that point; that half needs the imagery source to publish its own digest so ours has something independent to match against. This is tracked as ADR-0004 open question 2, and is a conversation to have with HOT and the imagery-source maintainers (per the COMMUNITY.md outreach plan), not something we can close by ourselves.

CRITICAL PATTERNS

NO AMBIGUITY ON SHUTDOWN

LifecycleController::shutdown() fires on Drop

The runtime doesn't expose shutdown() as a callable method. Dropping the Runtime value triggers the destructor, which calls LifecycleController::shutdown(). No way to forget. No orphaned processes.

TELEMETRY DRAIN IN LOOP

Empty the bus channel every iteration

while let Ok(event) = subscriber.try_recv() { ... } Never block on the bus. Non-blocking recv keeps inference flowing. Events are timestamped at source (aerollm runtime) so clock skew is zero.

RSS MEASUREMENT IS RUNTIME-OBSERVABLE

Log peak memory in every telemetry event

Each event carries rss = get_current_rss_bytes(). Worker tracks peak across all events during inference. Receipt contains peak_rss so operators can audit hardware requirements and catch runaway memory.

RECEIPT IS THE SOURCE OF TRUTH

Every receipt is deterministic

Worker → Receipt → Durable storage (filesystem or DDAC). The receipt is immutable proof. No re-inference needed to audit. Receipts can be shared downstream for provenance verification before predictions are used anywhere.

SMALL MODELS = NO EVICTION

Layer prefetch still runs

If the model fits in VRAM, ring eviction doesn't trigger. LayerEvicted events never fire. Receipt shows this honestly — zero evictions. Prefetch latency is minimal. You're not paying overhead for something you don't need.

OPERATOR EXPERIENCE

Worker is fire-and-forget

Operator runs geoai worker --config=/path/to/config.yaml. Worker loops, fetches runs, manages models, produces receipts. Operator can walk away; everything stops cleanly on interrupt. Next run uses the same binary.

NEXT STEPS — M1

M1.1 — Implement worker loop

Build GeoAIWorker struct with fetch → unload → load → subscribe → infer → finalize cycle. Use aerollm_api crate (PyO3 wheel not needed yet; work in Rust).

M1.2 — Receipt schema + harness

Define geoai.receipt/v1alpha1 in schemas/. Build ReceiptBuilder with telemetry_log serialization. Write a receipt to disk and validate it round-trips.

M1.3 — Sandbox profile + egress audit

Integrate macOS sandbox profile (qukaizen-geoai has the profile YAML). Wire egress test suite results into the receipt.

M1.4 — End-to-end smoke test

Run a small model (Qwen2.5-0.5B) through the full cycle. Verify receipt is well-formed, all telemetry events are logged, shutdown is clean, and peak_rss is reasonable.

Dictionary →