Projects

One idea runs through the recent verified-systems work: keep the consequential decision in deterministic code, and put an independent check on model output before it is trusted. The shorter studies under More work are learning and benchmarking projects and do not all follow it. Projects are ordered by what I would most want to discuss, not by date. Every case study states the engineering problem, the approach, and what was actually measured, including what is still unproven and one result that came back negative.

Current focus

The project I would most want to be asked about.

Grey-Resolve - Degraded-Media Entity Resolution, Evaluated Honestly

Oct 2026 Featured

An entity-resolution pipeline over degraded, uncurated media: detect a face, quality-gate it, embed it, retrieve near-duplicates, then try to break near-ties with lightweight context (time, coarse geo, source, text entities) - or honestly decline to resolve. The project is the evaluation: per-condition ROC/FMR/FNMR sweeps, a quality gate that measurably helps, and a central hypothesis (context resolves face near-ties) that was tested at scale and is not supported. Live Resolution Console on GitHub Pages; synthetic and public research data only, with candidate-ranking semantics throughout. Adapted from the vector-search coursework in Creating AI-Enabled Systems, a course in my JHU program.

Problem

Face matching looks solved on clean, well-lit images and quietly falls apart on the open-source media that real mission contexts supply: blurred, downsampled, off-angle, uncurated. A single accuracy percentage hides this, and a pipeline that always returns a top match will return a confident wrong one when several identities genuinely look alike. The harder question is whether contextual metadata can resolve those near-ties at all - and how you would know if it cannot.

Approach

Detect (SCRFD), quality-gate (FIQA-lite), embed (ArcFace, 512-d), and retrieve through a FAISS HNSW index with a SQLite metadata sidecar, then fuse context. Evaluation replaces accuracy percentages with EER, FMR and FNMR per degradation type (blur, downsampling, brightness, rotation), produced from one command, with detection failures counted per condition rather than hidden. The ambiguity regime is defined by measurement - the top-1/top-2 face-score gap - and four methods are compared on it: face-only, raw fusion, gap-gated selective fusion, and an evidence-only top-2 tiebreak, each swept across context-noise rates. Outputs are candidate rankings, never identifications, and the repo and UI carry no face imagery. Model weights are downloaded at runtime and never committed or baked into images; FastAPI and Docker Compose (API plus Qdrant) wrap the real pipeline.

Impact

The headline finding is structural: ranking quality is not operating-point calibration. EER stays near zero while FMR at FNMR=1% explodes to 0.873 under severe downsampling, so thresholds must be calibrated per condition. The quality gate lowers FNMR at a fixed threshold in nearly every condition (0.028 to 0.020 on clean probes) and rejects almost everything where quality is genuinely bad. The fusion claim did not hold: a small-run positive (n=4) did not replicate at scale (n=18) and reversed sign, with raw fusion cutting tight-gap hit@1 from 0.500 to 0.167. The mechanism was diagnosed (extreme-value noise from 59 competing context scores) and the guarded top-2 tiebreak was shown to be safe (overall exactly face-only, within +0.009/-0.019 across noise) but neutral. HNSW search p95 is at most 1.6 ms at 50k vectors against about 29 ms brute force on CPU. 241 deterministic tests, none needing model weights. Still unproven: results come from LFW-derived research data and synthetic scenarios, the FIQA gate is a heuristic rather than a measured assessor, runs use a single gallery draw, and nothing here transfers to real-world operational accuracy.

Live demo: pcschmidt.github.io/Grey-Resolve
FMR@FNMR=1% 0.873 at EER 0.046 (downsample x0.1)
Fusion claim tested at scale: not supported, reported as found

Selected work

The same discipline in many settings: computer vision safety monitoring, geospatial change detection, entity resolution, factuality checking, code linting, edge language models, multi-camera tracking, calibration, agent evaluation, a live intelligence product, and verifiable research agents.

SiteWatch AI - Computer Vision Safety Monitoring, Verified by an RLM Agent

Sep 2026 Featured

A two-plane safety monitor for warehouse and site video that keeps the safety decision deterministic and makes the AI prove its numbers. The fast plane (YOLO11s, ByteTrack, Kalman filtering, homography calibration to floor meters) applies versioned proximity, zone-dwell and speed rules on every frame at no AI cost. Only when a rule fires does a Prime Agent Recursive Language Model verify the event by running Python over the raw tracks, and a deterministic Band-3 gate recomputes its numbers before anything is stored. It grew out of the computer vision component of Creating AI-Enabled Systems, a course in my JHU program. Live demo on GitHub Pages replays the real pipeline output and recorded agent sessions.

Problem

Site-safety systems fail in one of two ways. Pure rules are fast and predictable but cannot tell a genuine near-miss from a tracking glitch, so operators drown in false alarms. Pure LLM pipelines can reason about context but are too slow and costly to run on every frame, and will state a distance that sounds confident and is simply wrong - unacceptable when the question is how close the forklift got.

Approach

Two planes and a referee neither can override. The fast plane detects and tracks people and vehicles, projects each to floor coordinates through one of three calibration methods, and fails safe: a camera whose calibration error exceeds 2.0 px keeps zone rules but switches off distance and speed rules. The only thing that crosses planes is a Pydantic-validated TriggerEvent plus the tracking window around it; the agent never sees video. Prime Agent runs headless over JSON-lines RPC, one fresh process per incident, and must answer from code it executes in its REPL rather than from prose. A feasibility spike showed its own turn limit did not stop a runaway task, so the real limit is an external 210 s timeout and kill in the adapter. The Band-3 gate recomputes distance, speed and zone dwell independently; any disagreement, timeout or malformed output becomes a needs_review incident with the evidence kept, never a dropped one. Redis Streams, Postgres, FastAPI with WebSocket push and a React dashboard carry the result; Terraform for AWS, GCP and Azure is validated in CI and deliberately never applied.

Impact

Against the real Prime Agent CLI, 26/30 hand-labeled incidents passed first time (86.7%); all four misses were the same timeout and completed correctly on retest, so the limit was raised on that evidence. Classification agreement with the labels was 82.1%, at about $0.002 and 43-56K tokens per incident. The gate earned its place on the live demo: the agent called a real aisle intrusion a false positive, and after a zone check was added to the gate the agent repeated the mistake and the gate caught it, sending the incident to review. The recorded transcript showed the agent had misread a rule id, fixed by putting rule definitions in the prompt. YOLO11s runs 35 FPS single-stream at 1080p; for three streams both the rested (30.2 FPS) and thermally throttled (9.5-13.2 FPS) numbers are published. 191 Python tests plus 6 dashboard tests, green in CI. Still unproven: inputs are looped stock clips, the demo calibrations are estimates rather than surveys, the gate cannot catch a plausible wrong judgment between allowed classes, and speed verdicts are not gated.

Live demo: pcschmidt.github.io/sitework-ai
Agent eval: 26/30 first pass; ~$0.002 per incident
Band-3 gate caught a real agent misclassification

Chokepoint - Provenance-Aware Transportation Intelligence

Sep 2026 - Present Featured

A verified analytical workflow over public transportation signals: deterministic metrics over normalized observations, reviewed geofences with a named human owner, and an agent that answers questions only from evaluator-approved evidence. Maritime core (three chokepoints) extended to air (ADS-B) and land (CBP border wait times) through the same admission-gate discipline. Live fixture-mode demo on GitHub Pages.

Problem

Raw movement data is not intelligence: positions are noisy, misclassified, and easy to over-read, and LLM agents over maps routinely invent intent, causes, and completeness that the data does not support. Missing data gets silently treated as zero, and "all vessels at the port" claims smuggle in scope the source never had.

Approach

Deterministic analytics before any AI: six versioned component metrics (vessel count, moving fraction, dwell estimates, entry/exit) computed over a canonical observation model that rejects invalid data instead of clamping it, inside nine reviewed geofences with per-vertex provenance and a named human review owner. The agent is evaluator-gated end to end: a typed-intent parser abstains rather than guessing scope, tools read only manager snapshots, a claim evaluator rejects causal/threat/predictive language, requires provenance on every claim, and verifies every number against the metrics — and the generator renders accepted claims only, structurally. Every live source went through a primary-source terms admission gate (AISStream risk-accepted with no ToS, adsb.lol under ODbL, CBP keyless; OpenSky rejected on its own written terms; rail deferred on evidence), and facility-level signals (border wait times) enter as a separate FacilityMetric model so entity data is never polluted.

Impact

341 offline deterministic tests, CI-green with zero credentials and zero network. Groundedness evaluation: 25/25 labeled scenarios (fabricated numbers rejected, causal/threat/predictive language rejected, scope overreach rejected, out-of-domain questions abstain). Detector evaluation: precision 1.0, recall 0.75, zero false positives with known failures documented. Replay performance profiled against documented budgets (render mean ~3ms, zero idle renders, 0% heap growth) — the profiler caught a real cursor bug synthetic tests had missed. Live at pcschmidt.github.io/chokepoint_app with a PWA offline shell, plus a Docker Compose observability stack (Prometheus + Grafana, bounded-label metrics, redacted JSON logs). The CBP live layer was verified against the real feed (85 crossings) and the demo honestly shows Suez as coverage-UNKNOWN rather than zero.

Live demo: pcschmidt.github.io/chokepoint_app
341 offline tests; groundedness eval 25/25
Evaluator rejects causal, threat, and fabricated claims

Meridian — Agent Harness for AI-Assisted Development

May 2026 – Present Featured

An agent harness that sits between an AI coding agent and the work, enforcing rules the model cannot hallucinate past. When a gate check fails, a shell hook exits with code 2 and the model’s next action is blocked. An independent evaluator subagent scores each gate’s work in a fresh context — eliminating the self-grading bias that lets agents mark unfinished work "done." Composable YAML gate DAG, schema-validated JSONL memory, and engineer-legible telemetry. Began as a fork of a fellow JHU student’s Syntaris framework.

Problem

AI coding agents fail predictably on multi-session projects: they declare features "done" before tests run, forget decisions across context resets, grade their own work generously, and drift from the original scope. None of these are prompt-quality problems — you cannot word-craft your way out of a structural failure.

Approach

Built infrastructure, not prompts. Gates are a project-defined YAML dependency graph enforced by shell hooks that exit 2 to block execution. A Gate Evaluator subagent runs in a fresh context, told "you did not produce this work," and blocks any gate scoring below 7.0. Three schema-validated JSONL memory types persist patterns, session events, and predicted-vs-actual calibration across resets. Every gate transition, block, and verdict is logged to queryable telemetry, and enforcement relocates to the git/CI boundary for non-Claude platforms.

Impact

Validated the core thesis by experiment: an agent scored its own work 5.5/10 while an independent evaluator scored the same work 2.5/10 — a 3.0-point gap the harness closes mechanically. 240 assertions across 18 suites, all three recipes verified end-to-end. Dogfooded on two production projects, where a gate caught stub citation code an agent had marked complete and forced it to be rebuilt as real infrastructure before it could ship as technical debt.

Self-grading gap closed: 5.5 → 2.5 (−3.0 pts)
240 assertions across 18 suites
Dogfooded on 2 production projects

Hard Power Intelligence — Markets Intelligence Engine

Jun 2026 – Present Featured

A recurring intelligence-production engine that turns scattered public data — SEC filings, federal contract awards, energy and regulatory releases, and news — into source-attributed, confidence-graded briefings across three converging sectors: AI infrastructure, defense, and energy. Live at hardpowerintel.com. Not a chatbot and not a stock-picker: every item shows its basis and confidence, and an entity-resolution graph links each event to the investable company behind it.

Problem

The data that moves the AI, defense, and energy build-outs — DoD awards, EDGAR filings, NRC licensing, hyperscaler capex, export-control actions — is public but fragmented, slow to read, and disconnected from its market meaning. Serious investors don’t lack data; they lack the time to aggregate it and the tooling to connect a raw event to the security it affects.

Approach

Built a full production stack: a Next.js reader on Vercel, a FastAPI intelligence engine, and Supabase (Postgres + pgvector). A per-source scheduler pulls four live adapters (USAspending, SEC EDGAR, arXiv, NRC) through a retry/backoff fetcher with DB-level dedup and a circuit breaker; records resolve into a bitemporal entity-resolution graph; change-detection plus graph-grounded RAG generate a cached BLUF brief per desk; an eval gate checks for fabrication and grades each item’s attribution before publish. A daily cron ingests once and publishes all three desks.

Impact

Live end-to-end and publishing daily from live data. The entity resolver holds precision 1.0 / recall 1.0 with zero false links on a golden set, rendering each item’s companies as clickable entity chips and flagging cross-desk convergence — a company appearing on two or more desks — as the core signal. An interactive Convergence Graph makes the entity network visible, with the cited stories behind each connection and a federal-funding overlay. Payments are built but not yet wired to a processor; turning on subscriptions is the next step to public launch.

Live: Next.js + FastAPI + Supabase
Entity resolver: 1.0 precision / 1.0 recall
3 desks, 4 live sources, daily cron

VERA - Literature Reviews and Review Papers You Can Check Sentence by Sentence, on Your Own Key

Sep – Oct 2026 Featured

VERA (Verifiable, Economical Research Agents) asks whether an AI research assistant can be cheap enough to use and checkable enough to trust. You give it a topic; it proposes one research question and waits for you to confirm it, searches several paper databases, reads the most relevant papers, writes a review in which every claim is tied to an exact quote from a source, and on request turns the review into a review paper with labelled interpretation sections. An audit then checks every sentence and says, in a colour and in words, what it could and could not confirm. Runs locally on your own model key with a hard spend cap. v1.0, closed after eleven gated increments; a read-only showcase of nine finished examples, six with the review paper made from them, is live on GitHub Pages.

Problem

Autonomous research agents now write papers that clear automated review bars, which leaves two gaps: almost nobody can afford to run them (the comparison system reports about $3,800 and 2 to 3 days per task), and nobody independent checks whether what they write is true. A fluent review with plausible citations is easy to produce and hard to trust.

Approach

Three layers: a cheap-by-default judge, an auditor, and a research agent that works under a hard budget. Each claim is one assertion with one quote; every other sentence is classed as synthesis (which must name the claims it follows from) or a transition (which must state no fact), and each is checked. A cheap judge answers first; a confident "no" on a claim or statement is put to a reference judge (Claude), an unsure reference makes the item "unsettled" rather than failed or passed, and a disagreement between judges is shown, not hidden. Every model call goes through a ledger and a budget that raises before a limit is crossed, the key is held in memory and written nowhere, and no component grades its own output. Test sets and code were frozen and hashed before the measurement they serve. Built with Claude Code under the Meridian harness: gated increments, human approvals, and an independent evaluator scoring every review.

Impact

A literature review costs $0.11 to $0.21 and a review paper $0.53 to $0.77 in model fees; the whole project spent $16.05. The audit caught 50 of 52 planted faults, and the sentence checks caught 15 of 21 real defects that earlier checks had missed (0 of 21), while flagging 14 of 69 sound items. No cheap judge met the 97% agreement bar against the reference (89% claims, 95% sentences, 89% statements), and the reference itself is unsure on about a fifth of verdicts. The headline negative: making the checks stricter made the light more honest but did not make the papers measurably better; independent readers still found claims that say a little more than their quotes. The six showcase papers are published as they are, three red and two amber, with their deficiencies listed. The research loop did not beat either parent baseline. Not shown: a new user completing a run, or labels from a person after Increment 6.

Live showcase: 9 examples and 6 review papers with evidence panel and PDF
Sentence checks: 15/21 real defects caught (0/21 before); judges below the 97% bar, reported as found
$0.11 to $0.21 per review, $0.53 to $0.77 per paper; 855 tests

geo-eval-gate - Satellite Change Detection Where an AI May Label a Change but Cannot Approve One

Oct 2026 Featured

A two-stage change detector for pairs of satellite images: a cheap deterministic screen (NDVI and structural-similarity change, cloud masking, morphology) proposes candidate boxes, and a vision-language model may only label a candidate, behind a gate that checks its reply against a strict schema, a confidence floor and an actionable-class list. Evaluated on real Sentinel-2 imagery with human labels (OSCD, 24 city pairs) under a protocol pushed before any result existed, with the test split run once. An extension tests whether a calibrated text-only judge (TypeSafe Jev) fixes the models' unusable self-reported confidence.

Problem

A raw difference between two satellite photos lights up everywhere: crops change colour with the season, clouds drift, sun angles differ. Sending every changed patch to a vision model is slow and costly, and a model that is allowed to approve changes will confidently approve the wrong ones. The open question is whether a vision model behind a deterministic screen actually helps, and whether the confidence it reports can be trusted at all.

Approach

The screen is fixed code and never sees a model. The gate is separate and deterministic: a reply that is not valid JSON, names a class outside the enum, or falls below the confidence floor is rejected, and a model can propose a label but never widen what is allowed through. The evaluation was written down first (PROTOCOL.md, with every deviation logged), tuned on a development split of 14 pairs and run once on 10 test pairs, with pair-level bootstrap intervals. Two local models (Gemma 4 12B and Qwen2.5-VL 7B) were compared against an RGB-difference baseline. The follow-up (PROTOCOL_JEV.md) was written before the first API call and is labelled as a second look at an already-seen test split.

Impact

The design screen (NDVI or SSIM) was not the best screen: development F1 0.227 against 0.297 for a plain RGB difference, and both screens find only about 39% of the 668 labelled change objects. Behind Gemma 4 12B the gate raised precision by +0.24 [+0.09, +0.33] for the design screen (0.42 to 0.67) while keeping about 70% of real candidates; Qwen2.5-VL 7B added nothing. An F1 gain and a win over a three-number regression are not established at 10 pairs. The models' verbalized confidence failed calibration. The calibrated judge matched Gemma's precision lift and recall, missed its own calibration-error target (0.166 and 0.124 against 0.10), did not beat a stacked logistic regression (AUROC 0.701 against 0.782), and cost about $0.06 in all: a calibration layer, not a better judge. 54 tests. Not shown: any effect with no labelled data, which is where the judge should help, and any result beyond one dataset of 24 pairs.

Gate precision +0.24 [0.09, 0.33] with Gemma 4 12B; Qwen2.5-VL 7B: no gain
Screens find only ~39% of labelled changes; design screen not the best
Calibrated judge missed its target and did not beat a regression, reported as found

entity-resolution-gate - Deduplicating Organisation Names with a Hard Registry-ID Rule

Oct 2026 Featured

An entity-resolution pipeline for messy organisation names: blocking, a hand-built similarity score, graph clustering, and a hard rule that two records with different registry IDs can never merge, whatever the similarity score says. Two real-data studies, each pre-registered with a held-out half scored once: a random sample of 3,000 Department of Defense contract recipients (name-only), and 60 slices of UK Companies House data where a registry ID is visible on half the records. A third, separate ablation tests what the graph-splitting step actually contributes.

Problem

Linking the same company across federal contracting, registry and filing data fails when it relies on fuzzy strings alone: similar names merge different companies, renamed companies split, and one oversized alias list can dominate a metric. A system that always takes the best-scoring merge has no way to promise that two companies with different official IDs stay apart.

Approach

Blocking and a composite name and address score propose pairs; a deterministic constraint vetoes any pair with contradicting IDs, same-ID records are treated as evidence, and community detection (Louvain) cuts clusters on the vetoed edges so the guarantee holds for whole clusters, not just pairs. B-cubed F1 is the primary metric because pairwise F1 was dominated by one 256-alias entity. The plans (PROTOCOL_SAMPLE, PROTOCOL_GATE, PROTOCOL_SPLIT) were pushed before the data were downloaded or run, and compared against a tuned plain fuzzy matcher and Splink. Several of my own mistakes were caught and are documented, including a first sample that was only the first 10,000 awards in name order.

Impact

On the random DoD sample, the name-only pipeline scored B-cubed F1 0.911 against 0.885 for tuned fuzzy matching (+0.026, 95% interval +0.019 to +0.034) and 0.893 for Splink; better blocking keys raised completeness but not F1, and my guess that token-sort scoring would help was wrong. On the UK data the full gate beat the same pipeline without IDs by +0.027 [0.025, 0.029], all 30 held-out slices improving, with zero rule-breaking clusters against 49 to 77 without the veto. Nearly all of the F1 gain came from the same-ID evidence, not the veto, and the graph-splitting step moved F1 by 0.0001 at a tuned threshold while making the guarantee true (6 rule-breaking clusters without it) and being worth +0.20 at an untuned one. 43 tests. Not shown: the registry ID is a company number, not a tax ID, and its visibility is simulated; 17% of true pairs are renames nobody recovers; the 100k-plus record benchmark is not done.

DoD sample: B-cubed F1 0.911 vs 0.885 tuned fuzzy (+0.026 [0.019, 0.034])
UK registry: 0 rule-breaking clusters vs 49 to 77 without the veto
Graph step +0.0001 F1 at a tuned threshold; +0.20 at an untuned one

rag-audit - A Claim-by-Claim Factuality Check for RAG Answers

Oct 2026 Featured

A Python library and command-line tool that checks whether each cited sentence in a generated answer is actually supported by the source it cites. It splits the answer into claims, finds each claim's cited passage, and asks a small local natural-language-inference model whether the passage entails the claim, flagging anything uncited, mis-cited or unsupported and writing a hashed audit record. Benchmarked on 1,800 FEVER items with thresholds frozen on a development split.

Problem

Generated briefings and RAG answers invent facts and mis-cite real ones. An LLM used as the judge is non-deterministic, costs money per claim and shares the generator's biases. What is needed is a cheap, repeatable check that fails toward flagging, plus a measured answer to how often it flags the wrong thing.

Approach

The checker is deterministic around one small model: sentence-level claim extraction, a footnote-to-passage mapping, an NLI model (DeBERTa-v3 small or base) scoring entailment, contradiction and neutral, and a fixed rule that anything not entailed is flagged. A 2x2 ablation crossed model size with whether passages carry their page title, because missing context was the suspected cause of false flags. Thresholds were fixed on development data per condition and each condition ran once on the same held-out items. A model trained on FEVER was skipped on purpose to avoid contaminating the benchmark, and an invalid first run is kept in the results with the reason.

Impact

Small model plus page titles reached F1 0.920 for flagging unsupported claims (precision 0.914, recall 0.927) while keeping 82.5% of supported claims, at 46 ms median; the base model with titles reached 0.933, a gap within noise. Missing context, not model size, caused most of the false flags: adding titles moved retention by 22 to 26 points, while moving from small to base without titles moved it by 8. The raw entailment probability is overconfident (calibration error 0.08 to 0.17) and should not be shown as a probability. 10 tests, no model download needed. Not shown: long documents, tables, non-English text or adversarial claims; support for a claim is not truth if the source is wrong; HaluEval, GPU timings and a PyPI release are not done.

FEVER F1 0.920 (small + titles), keeps 82.5% of supported claims
Page-title context moved retention 22 to 26 points; model size 8
Raw probability overconfident (ECE 0.08 to 0.17)

datapipeline-ast-guard - A Linter for AI-Written Data Pipelines, Measured on Real Code

Oct 2026 Featured

A command-line linter that parses Python data-pipeline code with the standard ast module, without running it, and flags three antipatterns that AI assistants tend to write: unbounded collect() and toPandas() calls, joins without equality keys, and hard-coded file paths. Output is JSON or SARIF with exact line numbers, and a GitHub Action can fail a pull request on a chosen severity. The project is mostly its evaluation: a pre-registered study on 300 real files from 83 public repositories, 200 model-written scripts and 133 challenge cases, then four rounds of fixes each re-measured on files nobody had read.

Problem

AI assistants write PySpark and Pandas that passes a toy test and misbehaves at scale: a whole table pulled to the driver, a join that explodes, a path that exists only on the author's laptop. A linter can catch these without executing anything, but only if its findings are worth a reviewer's time, and a rule that cries wolf gets switched off.

Approach

Three AST visitor rules, each deterministic and individually testable, with property-based tests and a strict type check. The evaluation separates three questions: is a finding faithful to the rule, is it actionable to a reviewer, and does the tool find defects planted in real code (mutation testing). Every version was frozen and tagged before the next sample was drawn, with the protocol pushed first (PROTOCOL through PROTOCOL_V4) and one rater, the author. A change that lowered the failure rate by changing a severity is recorded as that, not as an improvement.

Impact

On real code the rules were accurate and stable, but the one I had made critical was not useful: AG001 (unbounded collect) was faithful to its rule in 97% of findings and actionable in only 3 of 44 (about 1 in 15), so v2 demoted it to a warning, which cut the files failing the default gate from 21% to none with real findings without reducing the noise. AG002 (join without keys) has not found a true positive in real code; AG003 (hard-coded paths) went from 0.58 faithful to 0.94 on the first fix, then 0.83 on unseen files, and v4 reached 59 of 59 faithful on 300 fresh files with about 22% actionable and no new false-alarm kinds. Planted defects in their plain forms were found every time, which is a sanity check, not a recall estimate. 28 tests. Not shown: that it changes what engineers do, recall on forms I did not think of, or anything beyond one rater and a convenience sample of public repositories.

AG001 (once critical): 3 of 44 findings actionable, demoted to a warning
Default gate failures 21% to none with real findings; noise not reduced
AG003 59/59 faithful on 300 fresh files; 4 versions, each re-measured unseen

edge-slm-eval - Can a Small Local Model Make Safe Tool Calls Offline?

Oct 2026 Featured

A test harness for small quantized language models running entirely on one laptop with no network: it asks each model to write tool calls, forces valid JSON with grammar-constrained decoding, and passes every call through an AST gate that only lets four registered tools run. Four real GGUF models were measured on CPU (llama.cpp) and GPU (Ollama), constrained and unconstrained, 20 prompts each, including prompt-injection cases.

Problem

Tactical and offline deployments cannot use a cloud model, but small local models are unreliable at structured output, and an unchecked tool call is a way to run arbitrary code. Two questions need numbers: does constraining the output format actually help, and is a valid-looking call a correct, safe one?

Approach

A deterministic gate sits between the model and anything that executes: schema validation, then an AST check that the call is exactly one registered tool with the right argument form. The same weights run on both backends so CPU and GPU can be compared, and every result is scored three ways (schema valid, passes the gate, equals the expected call). A first pass that was invalid is kept with the reason. A post-hoc column shows what the strict keyword-argument rule costs, labelled as a diagnostic, not the headline.

Impact

Constrained decoding never lowered format adherence: Qwen2.5-Coder 7B went from 60 to 65% valid output to 100%, Llama 3B Q8 from 75% to 100%. A valid JSON wrapper was not a valid call: Llama 3B Q8 was 100% schema-valid but only 50 to 60% correct, because the grammar closed a string at an unescaped inner quote and truncated the call, which only the AST gate caught. One strict rule explains much of the Llama result (65% against 100% if keyword arguments are accepted). Across 320 first-pass outputs nothing outside the registered tools ran. GPU speeds (61 to 135 tokens per second) are throttled-laptop numbers, not hardware limits. 23 tests. Not shown: reasoning, long contexts or multi-turn tool use, other hardware, or any difference of one to three prompts out of 20 (about plus or minus 20 points).

4 real models x CPU/GPU x constrained/unconstrained (16 configurations)
Constrained decoding never hurt; Qwen 60 to 65% to 100% valid
Nothing outside the registered tools ever ran, including injection prompts

multicam-ground-fusion - Tracking People Across Cameras, and Finding Out the Detector Is the Problem

Oct 2026 Featured

A multi-camera tracker that projects each camera's detections onto one shared ground map with a homography, associates them with a Mahalanobis-gated Hungarian assignment, fuses them with a Kalman filter, and flags physically impossible speeds instead of smoothing them away. Validated first on a synthetic scene, then measured on two real datasets (Wildtrack and MMPTrack), with a pre-registered three-detector study asking how much of the remaining error is the detector.

Problem

One camera sees part of a site and loses people behind objects; several cameras can follow someone across views, but only if the system knows where each person is on the ground and whether two detections are the same person. A tracker that always attaches the nearest detection will teleport a track onto someone else, and a synthetic benchmark can make any such tracker look good.

Approach

Homography projection of box bottom-centres, chi-square gating that refuses surprising associations and counts them, a constant-velocity Kalman filter, and a speed-ceiling flag. Each real-data study was pre-registered: tuned on development frames, then run once on held-out sequences, with block-bootstrap intervals and ground-plane CLEAR-MOT and IDF1. The detector study compared a COCO Faster R-CNN, a COCO RetinaNet and a Faster R-CNN fine-tuned on earlier sessions of the same rooms, against the dataset's own boxes, with seven numeric hypotheses written first.

Impact

The synthetic score (MOTA 0.93 to 0.96) did not predict real footage: on Wildtrack the tracker scored 0.79 with perfect boxes and minus 0.17 with a COCO detector, mostly because that scene is crowded and sampled at 2 frames per second; on MMPTrack it scored 0.996 with clean boxes and 0.57 to 0.60 with a detector. In the detector study pooled MOTA was 0.524, 0.594 and 0.759 for the three detectors against 0.986 for clean boxes, so fine-tuning added +0.235 [0.164, 0.304] while a different COCO architecture added 0.07; five of seven hypotheses held. Two did not: with the best detector, fusion beat the best single camera in only one of three sequences, and camera consensus still helped (+0.021). 22 tests. Not shown: generalisation to a new site (the fine-tuned detector saw the same rooms), why about 8.8k false positives remain, YOLO with ByteTrack, an extended Kalman filter, or PETS 2009.

Synthetic MOTA 0.93 to 0.96 did not transfer: Wildtrack -0.17 with a COCO detector
Fine-tuned detector +0.235 MOTA [0.164, 0.304]; 5 of 7 hypotheses held
Fusion beat the best single camera in 1 of 3 sequences, reported as found

generative-modeling-study - Can You Trust a Generative Model’s "This Looks Unusual" Alarm?

Spring 2026 – Oct 2026 Featured

Two studies in one repository. The original is a from-scratch beta-VAE on MNIST with a beta sweep. The second is an uncertainty-calibration benchmark: split-conformal inference on the anomaly scores of a VAE, a diffusion model, an energy-based model and a Gaussian mixture, tested first on synthetic data with a known density and then, under a protocol pushed before any model was trained, on real tabular data (California Housing and Covertype). It asks whether the coverage guarantee holds, what happens under shift, and whether the same score actually detects novelty.

Problem

Generative models are often used to flag anomalies, but a score alone does not say how many alarms are false or how many real problems are missed. Conformal prediction promises a fixed alarm rate on normal data for any score, however poor, which is easy to state and easy to mistake for a promise that the detector works.

Approach

Plain split-conformal calibration (a deterministic, tested threshold) wrapped around small VAE, DDPM, energy-based and Gaussian-mixture models. The synthetic data are two half-moons with an exact density, so every score can be compared with the true likelihood. For the real tables, five hypotheses with numeric criteria, the grid of choices and the seeds were fixed in advance; choices were made on development seeds from a separate pool of rows and ten test seeds were run once, with paired comparisons.

Impact

Coverage held for every score on every dataset (0.895 to 0.902 synthetic, 0.897 to 0.907 on the real tables, nominal 0.90), as theory says it must, and said nothing about usefulness: novelty detection on Covertype was poor, with a best AUROC of 0.70 and 64 to 75% of novel rows still inside the 90% region. Under shift, the better a score noticed the shift, the faster its coverage fell. Two of five hypotheses were falsified: deep scores did beat a tuned mixture model by about 0.05 AUROC, and VAE reconstruction error was competitive rather than among the weakest. 43 tests. Not shown: other kinds of shift, adaptive conformal methods, larger models, image or text data, or a tight diffusion likelihood; the mixture baseline was capped at the edge of its grid, and UCI Sensorless Drive could not be downloaded.

Coverage held for every score (0.897 to 0.907 on real tables)
Covertype novelty detection poor: best AUROC 0.70
2 of 5 pre-registered hypotheses falsified, reported as found

More work

Studies and applications, kept brief on purpose. Each links to a repo with setup docs and evidence.

  • AI Diplomacy — Theory of Mind as Engineering

    Seven LLM powers negotiate, ally and betray each other in full-rules Diplomacy, each keeping an explicit trust model of the others that updates separately on what they promise and on what they then order.

  • Convex Optimization App — Live Optimization Workbench

    Three classic convex optimization problems solved by four first-order methods written from scratch in NumPy, benchmarked against SciPy ground truth, and served as a public web workbench with an LLM natural-language front door.

  • Advanced Stock Prediction App - The Model Maintenance Lifecycle

    A complete model-maintenance lifecycle on a financial forecasting problem: walk-forward evaluation, drift detection, retraining into versioned bundles, and validated rollback.

  • yt_rag - Real RAG over YouTube Transcripts

    A retrieval-augmented generation pipeline over YouTube transcripts done properly: chunk, embed, index with FAISS, retrieve top-4, and generate strictly from the retrieved chunks - with recorded evaluation numbers and a full bundle refresh/rollback loop..

  • Generative AI Journal Summarizer

    Multi-provider LLM gateway with RAG pipeline and ReAct agentic layer for journal entry analysis.

  • AeroIntel — Real-Time Aviation Intelligence Dashboard

    A real-time anomaly detection pipeline over live ADS-B telemetry with no labeled training data.

  • Production Inference Optimization Study

    Applied inference optimization techniques (ONNX export, INT8 quantization, adaptive batching) to SkillSwap's all-MiniLM-L6-v2 sentence transformer.

  • Parameter-Efficient Fine-Tuning Study (LoRA)

    Systematic LoRA rank ablation on GPT-2 (124M) for dialogue summarization.

  • RL Environment + Q-Learning Study

    Custom Windy Gridworld environment with tabular Q-learning and DQN agents, implemented from scratch using Gymnasium and PyTorch.

  • Optimizer Deep Dive: From Gradient Descent to Adam

    Pure NumPy implementations of BGD, SGD+Momentum, and Adam optimizers with a from-scratch neural network (backpropagation) trained on MNIST.

For perspectives on AI engineering, evaluation methodology, and where the field is heading:

Read My Thinking Posts →