Skip to content

Selected work.

01  Projects

/exp  Experience

Carnegie Mellon University

Research Assistant Mar 2026 — Present Pittsburgh, PA
  • Two projects under Michael Tarr and Deva Ramanan: verifying visual chain-of-thought in vision-language models, and investigating positional embeddings in vision transformers.
  • Verifying Visual Chain-of-Thought — curating a dataset and developing interpretability methods to verify whether a VLM's stated thoughts are visually grounded and contribute to its final answer.
  • Positional Embeddings in ViTs — built and validated a controlled study showing RoPE can remain classification-robust while collapsing on dense prediction at high resolution, then causally localized the failure to out-of-range long-range rotary phases.
  • Developed matched from-scratch ablations over positional channels, tokenization, and topology; identified a mechanism-clean hybrid that matches or beats APE on 3 of 4 dense tasks under a no-uniform-method-win framing.

ChargePoint

Software Engineer Intern — Hardware Test Automation Jul 2024 — Present Campbell, CA
  • Built the first automated Outgoing Quality Control (OQC) for ChargePoint's DC fast chargers, on the team's in-house test framework — hardware-in-the-loop over SSH, UART, and RS232.
  • Drives a programmable power supply, discovers the controller over IPv6, then orchestrates commissioning, firmware/image verification, 35+ on-device self-tests, and system service/fault gating.
  • Replaced a slow, manual gate — months of backlog with units uncleared — with a deterministic ~1-hour run (including charging) that clears 10–12 units/day, one unit at a time.
  • Config-driven and resilient — part-number-to-cable mapping, externalized limits, timeout/kill-switch polling, automatic system-reset recovery — and standardized across AC and DC fast-charger lines.
Read the case study →

/work  Projects

2023 — 2026

001

UniMeet

2026

Cross-college .edu social app — a native SwiftUI iOS client on TestFlight beside the Next.js web app, on one Supabase/Postgres backend (43 migrations) built deny-by-default: zero client table writes, every mutation behind a SECURITY DEFINER function, and the permission matrix asserted by a generated pgTAP test rather than documented. The concurrency cases live in PL/pgSQL — sender-scoped message idempotency with a unique-violation retry path, and invite redemption locked against double-attribution with SELECT … FOR UPDATE and a row-count guard — and pushes flow through a transactional pgmq outbox to a Deno edge function that mints ES256 APNs tokens.

SwiftUI · Next.js · Supabase · APNs
002

Dobbify

2026

Evolved from cashback into a fashion decision engine — a deterministic per-product “should I buy this?” verdict, a brand-intelligence layer, and a price-history layer fed by a daily cron behind a pluggable provider interface. A native SwiftUI companion app on TestFlight reads the same Supabase backend.

Next.js · React · Supabase · SwiftUI
003

Windbourne

2026

Config-driven computer-vision pipeline — formerly badminton-mocap — that turns badminton match video into player pose, footwork, and shuttle tracking: 11 swappable stages, 307 tests, a custom PyTorch CNN tracking the shuttlecock frame by frame, and recovered motion exported to BVH for standard 3D tools. Elite-level racket-head speeds (38–49 m/s) fall out of the joint kinematics, and players are re-identified across clips with a mean-centered ResNet embedding plus average-linkage clustering, stable on 839 of 840 frames. An experiment pass then measured the pipeline against itself over six broadcast clips: replacing the classical blob tracker with the CNN plus short-gap interpolation — no Kalman smoother, which over-gated the shuttle's reversals at racket contact — lifted confirmed coverage from 0.46 to 0.72 and cut the false-positive rate from 0.16 to 0.07, while temporal pose smoothing, tested the same way, was rejected: Savitzky-Golay inflated peak wrist speed by 24–40%, and One-Euro bought nothing.

Python · PyTorch · YOLO11 · MediaPipe · OpenCV
004

assay

2026

A linter for agent execution traces — nine mechanical rules that flag conclusions a run's own recorded numbers do not support: a verdict contradicting its control metrics, a success threshold that moved mid-run, a tool error swallowed before the conclusion that depends on it. No rule asks a language model whether a run looks sound, because a judge would reintroduce exactly the unreliability being detected. 100% precision and recall on every rule over 31 labelled fixtures whose negatives are deliberately hard, and across 380 published third-party runs (52,494 events) it returned 246 findings for 2 true positives — with four of the nine rules unable to fire at all, because the agents that most need self-consistency checking are the ones that never record the controls and thresholds it reads.

Python
005

crucible

2026

Does forcing an evaluator to commit its falsification criteria before it sees the result change what it accepts? Over 50 statistical tasks, with every criteria set hashed into an append-only chain — 100 entries, verified intact — before the claim was revealed, the pass rate barely moved: 86% against 82%, McNemar exact p = 0.79. The criteria did. Post-hoc reviewers set their minimum sample size at a median 0.975× the n they had already been shown, against 0.016× when they committed first (paired Wilcoxon p = 1.03 × 10⁻⁸) — a nominally stricter bar that cannot fail the claim it exists to judge, and one the headline pass rate cannot see.

Python · SciPy · pandas
006

readout

2026

A prospective test of whether Phase 2 trial design predicts failure of the Phase 3 that follows, over 94,216 ClinicalTrials.gov records — and the answer is no. All eight specifications are reported rather than the best: the design model's advantage over a sponsor-class, indication and enrollment baseline runs −0.020 to +0.054 AUC, and every interval includes zero, from paired bootstraps on the difference rather than two separately resampled intervals. Naive programme linkage produced 45,440 obviously wrong pairs, so standard-of-care backbones are capped out and the dropped names published rather than quietly applied — and the minimum detectable effect (≈0.061 AUC) is stated, so the null cannot be read as more than it is.

Python · scikit-learn · pandas · ClinicalTrials.gov API
007

pharmacope

2026

A calibration harness for ranking rare regulatory pharmacogenomic variants — deliberately everything except the scorer, so a plausible ranked list can be shown to be worthless. A negative control matched on allele frequency and distance to the transcription start site pulls the standardized mean difference from 1.163 to 0.001, and under it a proximity-only scorer's apparent 0.768 AUROC collapses to 0.501, indistinguishable from the permutation null. Positives that cannot find matched partners inside the caliper are dropped rather than padded and the cost is reported, and the production scorer's seat raises instead of returning a number, so no result can be attributed to a model that was not run.

Python · gnomAD · Ensembl · PharmGKB
008

Cache Simulator and Verification Harness

2026

A trace-driven, write-back/write-allocate CPU cache simulator in C for any capacity, block size, and associativity, with true LRU, FIFO, and seeded-random replacement — and a harness built to prove it right rather than to demo it. An independently written Python reference model and a seeded trace generator with locality knobs drive a differential test of 3,684 runs — three shipped traces and 200 random ones across a grid of cache geometries and all three policies — with 0 mismatches; behind it sit 13 hand-computed unit tests that assert which line was evicted, invariants checked on every access under AddressSanitizer and UBSan, and mutation checks that catch a one-line LRU inversion within the first few runs. A sweep of 131 configurations over a 100,457-access trace maps the hit-rate knee — 70% at 256 B to 93% at 4 KB, with the sixteen-fold jump to 64 KB worth 2.3 points more — and the 72 configurations where write-back moves fewer bytes than write-through.

C · Python · AddressSanitizer · UBSan
009

Yummerz

2026

Invite-gated iOS app for sharing meal photos with friends, built on an append-only data model — every edit appends a version, nothing is ever truly deleted — and the latest build adds rounds, so more food can join the same post. The camera-to-cloud pipeline normalizes orientation, resizes to 1600 px, and strips EXIF/GPS before upload, and a crash-safe offline outbox writes image bytes before the metadata pointer and removes them pointer-first, so a post composed with no network can never be orphaned or resurrected. Who can see a meal is decided by one Postgres function mirrored into both table RLS and Storage policies and pinned by a pgTAP truth table — 84 migrations, 11 Deno edge functions.

SwiftUI · Supabase · Sign in with Apple · WidgetKit
010

Doses

2026

Local-only iOS medication tracker — SwiftData on device, no accounts, no backend, no analytics. Adherence is scored honestly (capped per day so double-dosing can't mask a miss), and interactive widgets, a Live Activity countdown, notification actions, Siri, and an Apple Watch app log doses without opening the phone app — every surface funnels through one idempotent path keyed on medicine and slot, so a double-tap or an offline Watch replay can never double-log a dose.

SwiftUI · SwiftData · WidgetKit · App Intents
011

whichcard

2026

Offline-first purchase optimizer that answers one question in the checkout line: which card, credit, protection, or already-included benefit saves money here. A deterministic engine ranks against a 317-record catalog of earning rules, credits, protections and lounge access, every record sourced and dated — and that engine is reimplemented natively in Swift, held to the TypeScript one by a shared 288-case golden-vector suite generated from a single written contract. No accounts and no backend: IndexedDB on the web, SwiftData on device, and one backup format that crosses between them.

Next.js · TypeScript · SwiftUI · SwiftData
012

Shazam4Spotify

2026

iOS app that recognizes ambient music with ShazamKit and auto-adds the ISRC-matched track to Spotify. The OAuth client is the interesting part — PKCE with no client secret, an S256 challenge over a random verifier, single-flight token refresh so concurrent calls share one refresh task, and a method-aware retry policy: 401 refresh-and-retry, 429 Retry-After, 5xx on GET only.

Swift · ShazamKit · OAuth 2.0 (PKCE) · async/await
013

taste-radio

2026

Local-first music discovery that clusters a Spotify library into taste-modes with TF-IDF and HDBSCAN, then fuses Last.fm and ListenBrainz collaborative-filter signals through a consensus scorer weighting cross-source agreement, popularity, and recency decay. A thumbs-feedback loop trains a class-balanced logistic regression online, and its coefficients become a per-candidate score multiplier.

Python · scikit-learn · HDBSCAN · Flask
014

Quick Autofill

2026

Chrome extension that autofills job applications across Workday, Ashby, and react-select forms — defeating React's controlled-input tracking via the native value setter and frame-accurate input/change event sequences, with a shadow-DOM-piercing field scanner and an all-frames iframe pass (214 tests). A two-tier engine resolves common fields locally with zero network calls, backed by a per-domain cache that replays confirmed fills and invalidates on a profile-hash change.

JavaScript · Chrome MV3
015

Nudge

2026

Silent macOS menu-bar reminders — no sound, no haptic, no modal, just a banner at the interval you set. Notifications post through osascript with no sound argument rather than a notification framework, which is the whole trick: one small Swift binary, no dock icon, nothing that steals focus. State persists to JSON across reboots and quiet hours wrap midnight correctly, with a global pause and per-reminder snooze one click each.

Swift · macOS
016

Chicago Airbnb Segmentation

2026

Team statistics project: a multivariate clustering pipeline over 7,749 Chicago Airbnb listings — PCA, k-means, and full-covariance GMM recovering four latent operating types, with separation validated by a from-scratch MANOVA (Wilks' Λ = 0.024) cross-checked against statsmodels to within 1%. Validation is built from scratch too — Box's M, a 1,000-permutation MANOVA, bootstrap Jaccard stability of 0.93–0.98 — behind an 89-assertion reproducibility audit that fails the build if any cited statistic drifts.

Python · scikit-learn · statsmodels · SciPy
017

SharprAI

2023–24

Chrome extension that captures the active tab as video and streams chunks to the cloud for AI-enhanced playback while you're still recording — sharper, cleaner footage delivered as an HLS stream.

TypeScript · React · Chrome MV3 · AWS S3 · Flask · HLS
018

Ovarian Cancer Histopathology

2023

Fine-tuned EfficientNet-B5 for ovarian cancer subtype classification. Kaggle competition entry with a custom PyTorch DataLoader for slides up to 100,000 × 50,000 px.

PyTorch · EfficientNet