AU
auapps / work · workshop
Filed23:47
Two projects · systems Section B · Workshop

Workshop.

Two systems-design pieces that don't fit a flagship card. One ships; one is paused for honest reasons. Combined because the substance is in the shape of each system, not the polish.

00

What connects them

system shape · end-to-end

Both are exercises in system shape: pick a domain (traffic dynamics, lead outreach), then build the thing end-to-end so the actual constraints surface — not just the diagrammed ones. One is academic, one is commercial. Both forced choices that don't appear until you've shipped past the wireframe and into the messy part. The shape of those choices is what's worth showing.

01Sumo · traffic simulation · group g8 · jan 2025

Adaptive traffic light controller, 2D/3D hybrid.

Java 21 + JavaFX desktop app driving Eclipse SUMO through libtraci (Java bindings to the simulation kernel). Adds a layer the stock SUMO GUI doesn't ship: batch vehicle injection, an adaptive controller that retunes phase splits from live queue density, FXyz3D for elevated 3D rendering, CSV reporting per intersection.

Java 21 JavaFX libtraci FXyz3D Maven SUMO 1.18
01a

The adaptive controller

−22% wait · benchmark dataset

SUMO ships with fixed-cycle traffic light logic by default — every phase gets a predetermined slice of the cycle regardless of who's waiting. The adaptive controller tears that out and replaces it with a feedback loop: every tick, it reads the queue length per approach via libtraci, weights it against minimum-green and pedestrian-cycle constraints, and retunes the next phase split toward whichever direction has the most pent-up demand. Result: a 22% drop in average wait time on the synthetic 4-way intersection dataset (group benchmark), at the cost of slightly noisier phase transitions that the report had to address explicitly.

01b

What the 3D layer is for

scrutability · not graphics

FXyz3D renders the intersection as an extruded geometry — buildings, road grade, vehicles. Not for graphics; for scrutability. A 2D top-down simulation is great until you need to argue about lane-line geometry or sightlines, at which point a top-down arrow stops being enough. The 3D view became the explanation surface: when the group reviewed the controller's decisions, the 3D render let us point at exactly which sightline the adaptive logic was responding to.

Documented — Code Documentation, Enhancements & Design Decisions, and AI Declaration PDFs ship alongside the binary. Runs locally; not deployed (academic project). Four-person group; my responsibility was the controller layer + the 3D rendering integration.

02Lead Outreach · n8n + supabase + twilio + gmailpaused · day 8/14

Deterministic, audit-friendly outreach stack.

Sheets → Supabase upsert (idempotent, fingerprinted) → LLM-drafted message per lead → multi-channel send (Email · SMS · WhatsApp) → tracking → unsubscribe enforcement → send queue + archive. DB-trigger-driven state machine; n8n patches queue to state='sent' and the trigger handles archive + draft-status. provider_message_id dedupes inbound; before-send check against (lead_id, draft_id, provider) blocks resends.

n8n Cloud Supabase Twilio Gmail API LLM (classifier + composer) paused
02a

Why this architecture

audit-friendly · deterministic

Lead outreach is the kind of system where the cost of a bug is asymmetric — a double-send or a missed unsubscribe is not a refactor, it's a complaint. So the design philosophy was: every state change has a database fingerprint, every send is checked against an idempotency key, and every external action is queued through a trigger rather than fired in-flight. If the workflow dies mid-execution, picking it up again replays cleanly. If the audit comes, the path from lead to sent message is one SQL query away.

n8n was chosen for the visual workflow layer not because it's the fastest path, but because the audit trail it produces is human-readable. A reviewer (regulator, client, or future-me) can open the run history and see exactly which lead got which message at which timestamp via which channel — without parsing logs.

02b

"Paused, day 8 of 14" — what it means

half-built · honest pause

Days 0–8 shipped: env + auth setup, import (Sheets → Supabase with write-back), LLM compose, Gmail send, Twilio send (SMS + WhatsApp), tracking outcomes (not pre-marked sent), unsubscribe handling, reliability hardening (retries · rate limits · idempotency).

Days 9–14 pending: inbound classifier with ACT.YES / ACT.NO / POTENTIAL.* / HUMAN routing, scheduling/templates, analytics, Airtable parity, polish.

The pause is honest: the half that's built is the "send" half, and continuing without a real outreach list to run against would mean building the "classify replies" half on synthetic data — which never matches production. Audit kit prepared and the system resumes the moment there's a live campaign to run. The reason it's mentioned here at all is because shipping half of a serious thing taught more than shipping a small thing whole.

Code & docs available on request — repos private during the paused window.