WPI Computer Science, BS/MS ’29, 4.0 GPA

Merged upstream.

I build infrastructure for AI tooling, and fix the Linux and Python layers it runs on. My event store for MCP servers, mcp-persist, has 19,000+ downloads and runs in production inside mlrouter, the LLM gateway I'm shipping. My fixes are merged upstream in systemd, CPython and across the AI data stack.

Open to Summer 2027 Software Engineering internships

mcp-persist

Durable persistence for MCP servers · PyPI · v2.1.1 · MIT

The problem. The MCP Python SDK ships with an in-memory event store. It works until the first deploy. Restart the process and every client's Last-Event-ID points at history that no longer exists, so resumable SSE streams quietly stop being resumable. Add a second worker and it gets worse: each worker holds its own private history.

Interactive simulation of the SSE resume protocol. Kill the server with the in-memory store and events are lost; switch to mcp-persist and the missed events replay on reconnect.

The design. mcp-persist replaces that single point of loss with swappable, durable EventStore backends. Redis covers production fleets. SQLite covers single-node deployments. PostgreSQL slots into stacks that already run it. The Redis layout is built for replay. An INCR counter issues monotonic event IDs and the events themselves live in HASHes. A per-stream ZSET supports ranged reads so a reconnecting client can resume from any point. TTLs bound storage. A key_prefix namespace makes one Redis safe for many tenants.

Adoption. Shipped at v1.0.0 and versioned steadily forward through real usage: 19,000+ downloads on PyPI and confirmed production deployments. The test suite runs 300+ async tests against fakeredis and real backends, with CI across Python 3.10 through 3.13.

Positioning. mcp-persist plugs into the official SDK's EventStore interface, so it tracks upstream releases and existing servers adopt it unchanged. Where a server can't be modified at all, the PersistenceProxy adds durability from the outside.

from mcp_persist import with_persistence

mcp = FastMCP("my-server")
app = with_persistence(mcp, backend="redis", url="redis://localhost:6379")

Full adoption is two lines. For servers you can't modify, including servers that aren't written in Python, a standalone PersistenceProxy sits in front as an ASGI layer. It tracks the full SSE state machine and replays cold or hot history to any client that reconnects.

mcp-persist request and replay path An MCP client connects to a server or PersistenceProxy, which writes events to a durable EventStore backed by Redis, SQLite, or Postgres. On reconnect, the client sends Last-Event-ID and the store replays the missed events. MCP client SSE stream server / PersistenceProxy session manager EventStore Redis · SQLite Postgres Last-Event-ID replay

mlrouter

One OpenAI-compatible API across every model provider · mlrouter.com Live · entering production

mlrouter is a multi-model LLM gateway: a single OpenAI-compatible endpoint that routes requests across OpenAI, Anthropic, Google, Mistral, HuggingFace, XAI, OpenRouter, Deepseek, and many others. It picks a backend by cost or latency, scores each provider's health, and fails over through circuit breakers and fallback chains when one degrades. Virtual keys carry spend caps; every request is logged. It's live at mlrouter.com and going into production with its first customers. It's also the platform where my open-source packages run as first-class services.

Unified gateway
One /v1/chat/completions across every major provider. The model prefix selects the backend; auto routes on cost.
Cost & latency routing
Strategies score providers on price and p50/p95 latency, with automatic context-window escalation when a prompt outgrows a model.
Health & failover
Per-provider health scores, circuit breakers, and fallback chains keep the endpoint answering when an upstream goes bad.
Virtual keys
Hashed virtual keys resolve to real provider keys server-side, never exposed, with per-key spend caps enforced in Redis.
Durable sessions mcp-persist
Streaming sessions survive a restart and resume mid-stream, powered by my own mcp-persist.
Tokenizer safety TokenDrift
Token counts and migration-safety checks run before a model swap reaches production, powered by TokenDrift.

The parts and the whole. mlrouter ships my open source as production services: mcp-persist for durable sessions, TokenDrift for tokenizer safety, a prompt compressor, and a no-code MCP server builder. The packages are the parts; the platform is the whole.

Next.js 15 · Hono · FastAPI · Neon / Drizzle · Upstash Redis · Clerk · Stripe · BullMQ · Docker MCP runtime

Also shipped.

codebase-rag

v1.0.1

A symbol-aware, self-updating vector index and reference graph over a whole repo, served over MCP, so an agent answers "who calls this / what breaks if I change it" in one call instead of a pile of greps. Built on rag-timetravel; keeps itself fresh with a git pre-push hook.

rag-timetravel

v1.1.0

Time-travel debugger for RAG retrieval pipelines. Pin any past query to the exact index version it ran against, replay retrieval, and diff what changed. Now the indexing core that codebase-rag builds on.

TokenDrift

v1.0.0

Tokenizer diffing for LLM upgrades. Measures token count shifts, cost deltas, vocabulary changes, and remapped IDs before they hit production.

The ledger.

Every pull request I've had merged into projects other people depend on. States are checked against GitHub daily, and Debug replays what each fix changed.

40 merged across 8 repositories, in C, Rust, Zig and Python.

  1. util-linux/util-linux2026-09-29

    setpriv: match Landlock fs rights exactly

    setpriv accepted any prefix of a Landlock filesystem right, so a typo like fs:remove quietly gave a weaker sandbox than the one asked for. Now rejected.

  2. systemd/systemd2026-09-23

    siphash24: force inlining of the round

    Forced SipHash's round inline where gcc -O2 declined, making short-key hashing up to 6.6x faster across systemd's hashmaps.

  3. systemd/systemd2026-09-23

    journalctl: make the read path 1.7x to 2.5x faster

    Three fixes on journalctl's per-entry read path, including a UTF-8 decoder that ran twice per byte. Output is byte-for-byte identical, 1.7x to 2.5x faster.

  4. systemd/systemd2026-09-22

    utf8,format-table: make the console width helpers agree with the UTF-8 validators

    The console-width helper used the permissive UTF-8 decoder, so one invalid cell failed a whole table with a bogus out-of-memory error.

  5. util-linux/util-linux2026-09-21

    mbsalign: skip whole CSI sequences when counting cells

    column(1) mis-measured cells after any non-SGR escape sequence; the scan now stops at a real ECMA-48 CSI final byte.

  6. systemd/systemd2026-09-14

    parse-util: fix ineffective overflow guards in store_loadavg_fixed_point()

    Fixed both overflow guards in the load-average parser: one was inverted and one ran after the shift, so values from 2^53 up wrapped to 0.00 instead of being rejected.

  7. systemd/systemd2026-09-04

    resolved: don't disable the listening socket when a datagram is dropped

    One datagram with a bad checksum, sendable by anyone on the link, disabled resolved's mDNS, LLMNR or stub listener until restart.

  8. systemd/systemd2026-09-02

    resolve: fix use-after-free of the service browser in mDNS maintenance

    A leaked reference let resolved free an mDNS service browser while its maintenance timer still used it: a use-after-free, fixed in one line.

  9. systemd/systemd2026-09-02

    compress: fix unbounded buffer growth on truncated streams, and fuzz the decompressors

    Stopped unbounded buffer growth on truncated compressed streams, and added fuzzers that feed hostile input to every decompressor and to importd's qcow2 path.

  10. coreos/afterburn2026-08-28

    proxmoxve: Emit one nameserver= karg per address

    ProxmoxVE configs with more than one nameserver left DNS unset at boot; now emits one dracut nameserver= per address, IPv6 bracketed.

  11. coreos/afterburn2026-08-28

    providers: Don't panic truncating a multi-byte hostname

    Truncating a long multi-byte hostname split a UTF-8 character and panicked, failing afterburn-hostname.service at boot.

  12. BerriAI/litellm2026-08-14

    feat(proxy): serve Anthropic-native /v1/models for Claude Code gateway discovery

    Re-landed Anthropic-native /v1/models after a staging revert, so Claude Code's model picker populates through a litellm gateway.

  13. systemd/systemd2026-08-12

    strv: treat newlines as hard line breaks in strv_rebreak_lines()

    The line re-breaker dropped text before an embedded newline and returned entries spanning lines, which could emit uncommented lines in Varlink IDL output.

  14. systemd/systemd2026-08-12

    options: reject an empty long option name

    An empty long option (--=VALUE) prefix-matched every option, and with only one defined was silently accepted as it. Now rejected.

  15. lance-format/lance2026-08-04

    fix(ngram): recheck contains() with sub-trigram needle instead of dropping rows

    An NGRAM-indexed contains() with a needle under three characters returned zero rows; it now falls back to a full recheck.

  16. systemd/systemd2026-07-31

    string-util: don't miss ANSI sequence at the very end in previous_ansi_sequence()

    An off-by-one skipped the last offset a two-byte escape sequence can start at, so ellipsize() over-truncated strings containing ESC M.

  17. systemd/systemd2026-07-25

    ask-password: refuse agent requests with unsafe characters in prompt fields

    A newline in an ask-password prompt could inject a Socket= line and send the typed password to another path. Unsafe characters are now refused.

  18. systemd/systemd2026-07-23

    ask-password: reject oversized Plymouth prompts

    Prompts of 255+ bytes wrapped Plymouth's one-byte length field, so the rest of the prompt was parsed as protocol data. Now rejected with -EMSGSIZE.

  19. systemd/systemd2026-07-23

    strv: don't read past end of string on invalid UTF-8 in strv_rebreak_lines()

    A truncated multi-byte character at the end of a string made the line breaker step past the NUL terminator and read out of bounds.

  20. systemd/systemd2026-07-21

    escape: reject UTF-16 surrogates in \u escapes in cunescape_one()

    \u escapes accepted UTF-16 surrogates and produced invalid UTF-8 downstream; now rejected, matching the \U form.

  21. systemd/systemd2026-07-20

    hostname-util: strip all trailing separators in hostname_cleanup()

    hostname_cleanup() stripped only one trailing separator, so foobar-- came back as the invalid hostname foobar-.

  22. lancedb/lancedb2026-07-01

    fix(python): average MRR reciprocal ranks over all rankings

    MRR fusion averaged only over the rankings a document appeared in, letting a single-system hit outrank a consensus pick.

  23. systemd/systemd2026-06-19

    sysupdate: refuse reboot/pending logic when --component= is used

    Fixed incorrect reboot/pending logic in sysupdate when --component= is used. First PR merged into systemd.

  24. lightpanda-io/browser2026-06-19

    feat(cdp): implement Browser.setDownloadBehavior file downloads

    Implemented Browser.setDownloadBehavior for CDP-driven file download automation.

  25. lance-format/lance2026-06-19

    fix: evaluate all list-element docs in FTS prefilter walk-the-allowlist branch

    Fixed incorrect evaluation of list-element docs in the FTS prefilter walk-the-allowlist branch.

  26. lancedb/lancedb2026-06-17

    fix(rust): return typed errors instead of panicking in Bedrock embedding path

    Replaced panic paths in the Bedrock embedding provider with typed error returns across serialization, API, and runtime failure modes.

  27. lancedb/lancedb2026-06-17

    fix(python): raise clear TypeError for bare List/Tuple in pydantic schema conversion

    Fixed opaque AttributeError for bare List/Tuple generics in Pydantic schema conversion, raising a clear TypeError instead.

  28. BerriAI/litellm2026-06-17

    feat(proxy): serve Anthropic-native /v1/models for Claude Code gateway discovery

    Enabled Anthropic-native model discovery for Claude Code gateway deployments.

  29. BerriAI/litellm2026-06-17

    fix(openai): preserve cache_control for openai-compatible custom endpoints

    Preserved cache_control headers for OpenAI-compatible custom endpoints, fixing silent cache bypass.

  30. BerriAI/litellm2026-06-17

    feat(proxy): surface max_input_tokens/max_output_tokens on /v1/models

    Surfaced max_input_tokens and max_output_tokens on /v1/models for accurate client-side capacity planning.

  31. lance-format/lance2026-06-16

    fix: merge_insert silently drops matches when a leading payload column is all-null

    Critical fix: merge_insert silently dropped matched rows when the leading payload column was all-null.

  32. BerriAI/litellm2026-06-11

    fix(proxy): release max_parallel_requests slot when a stream is cancelled mid-flight

    Stopped a cancelled stream from stranding its max_parallel_requests slot, which had been pinning capped keys at their limit.

  33. BerriAI/litellm2026-06-08

    feat(proxy): add disable_budget_reservation general setting

    Added a proxy-wide setting to disable budget reservation.

  34. lancedb/lancedb2026-06-05

    fix(python): run AsyncTable.search embeddings on a dedicated executor

    Moved embedding search onto a dedicated executor to stop event-loop stalls.

  35. lightpanda-io/browser2026-06-05

    Implement input type=file support (FileList, input.files/value, DOM.setFileInputFiles)

    Completed file-input support, from FileList through DOM.setFileInputFiles.

  36. lancedb/lancedb2026-06-03

    feat(rust): support datafusion expressions for merge insert predicates

    The same DataFusion capability carried into LanceDB's Rust core.

  37. BerriAI/litellm2026-06-02

    fix(proxy): don't enforce budgets on model-discovery / info routes

    Stopped budget enforcement on model-discovery and info routes.

  38. python/cpython2026-05-28

    gh-150311: Fix minor issues in configure.ac for the CYGWIN port

    Build-system fix accepted into the reference Python implementation.

  39. lance-format/lance2026-05-28

    feat(rust): support datafusion expressions for merge insert predicates

    DataFusion expressions for merge-insert predicates in a production columnar format.

  40. lightpanda-io/browser2026-05-25

    feat(webapi): implement W3C File API

    W3C File API surface implemented in Zig for an AI-agent headless browser.

The same list on GitHub

RunixOS.

A capability-based microkernel. CS3013 Operating Systems independent study, advised by Prof. Craig Wills

RunixOS started as a from-scratch microkernel and is now my formal CS3013 Operating Systems independent study at WPI, advised by Prof. Craig Wills. It re-derives classic process, thread, and synchronization coursework on a kernel with no shared memory and no ambient authority, where every right is an explicit capability.

It's a capability-based, IPC-first microkernel written in Rust for x86_64, booting via UEFI on QEMU. The kernel implements capabilities with attenuation and revocation, a preemptible scheduler, synchronous and asynchronous IPC, and a capability-gated filesystem, all backing an interactive console with tracing and profiling tools. A companion research paper examines what preemption does to capability atomicity, tracing a real TOCTOU vulnerability from discovery through a working fix.

The groundwork before it

Binary exploitation

Completed the CS:APP attack and bomb labs end to end, including the hidden phase and a full ROP chain. Then went past the assignment and reverse engineered the lab harnesses themselves with objdump and GDB.

Memory systems

Wrote an N-way set-associative cache simulator in C with LRU eviction, then used it to drive a cache-conscious matrix transpose. Valgrind traces guided the access patterns.

Off the clock, sort of.

Back at WPI for the fall, teaching intro systems as a Peer Learning Assistant, serving as a Community Advisor in residence life, and building RunixOS as an independent study.

Upstream, most of my time now goes into systemd and the Linux userspace around it: a use-after-free in resolved's mDNS path, a password-redirect hole in ask-password, and a journalctl read path that runs 1.7x to 2.5x faster. Over the summer I led development of mlrouter, which runs mcp-persist in production.

The lab next to my desk is still a Fedora laptop running a 35B mixture-of-experts model through llama.cpp, wired to a filesystem MCP server, because the fastest way to find what breaks in MCP infrastructure is to live on it. Before any of this I spent a decade teaching Shotokan karate as a second-degree black belt, which is where I learned to explain hard things patiently. I'm open to Summer 2027 Software Engineering internships.

BS/MS Computer Science, WPI · 4.0 GPA · Worcester, MA · EST · asandhu@wpi.edu

The site, as a shell.

Everything on this page is a command away. Replay any fix from the ledger with debug, or start with help.

This terminal needs JavaScript. Everything it shows is also on the page above.
~ ❯

Get in touch.

Email is fastest. I read everything.

asandhu@wpi.edu

Colophon

Built by hand: HTML, CSS and zero-dependency JavaScript, with no framework and no build step. The backdrop is a 3D graph of merges drawn on a canvas: main runs into the screen, branches fork off and merge back, and scrolling flies you down it. The terminal reads every answer off this page, and PR states refresh daily through a GitHub Action that commits static JSON, so nothing here calls a third-party API while you read. Type is IBM Plex. Hosted on GitHub Pages. Source

Lighthouse: run it yourself