Vlad Bondarenko

Engineering

How I engineer

The decisions I made, the bugs I traced to their root cause, how I test, and how I keep AI coding agents honest. Every claim links to the code, so you can check it instead of taking my word for it.

Test strategy

I start from what would hurt if it broke, and put the cheapest reliable check in front of it. A rule that can be code is code; a judgment that needs a model gets an eval gate with an answer key. Tests run offline and do not depend on today's date, so a red build means a real problem.

ProjectTestsWhat they coverGate in CI
Market Terminal430+Unit, Flask route tests, an offline end-to-end run, replay from stored responses. Any network call in a test raises NetworkBlocked.The whole suite, then again with the clock 400 days ahead. A daily run catches dependency drift.
ReqTrace36Parsing, deterministic checks, the citation guardrail, and tests proving the gate fails on a missed defect and on a false positive.Eval gate: fails below 5 of 5 planted defects or above 0 false positives. Releases re-run it.
Take the Wheel16 (67 guard cases)The security guard, the Bedrock backend and telemetry. A live end-to-end run checks the guard against Haiku, Sonnet and Opus.Guard tests on Node 20, 22 and 24.
vlad.yt2613 Playwright tests on desktop and phone: no console errors, axe WCAG A/AA, a no-WebGL fallback, reduced motion, structured data.Deploys only if every test passes and the committed bundle equals a fresh build, then smoke-tests the live site.

Design decisions

Each one names what I rejected and why. ReqTrace keeps a full decision log.

Take the Wheel: a browser agent

ReqTrace: AI for regulated engineering

Market Terminal: a data pipeline

Bugs I root-caused

The fix is half the job. The other half is the test or guard that stops it from coming back.

SymptomRoot causeWhat stops it returning
An agent restricted to one CLI still ran pwdRead-only commands are auto-approved before the allowlist is checked, and the wildcard also admitted the user's GitHub login, file upload and blocked sitesA fail-closed hook with 67 test cases in CI, plus before-and-after recordings
The agent reported 25 of 25 done; 23 wereThe way it read the page let it lose track while scrollingA page digest and a chained check; it now verifies 25 of 25 in 4 turns instead of 29
A price premium chart ranged from −2% to +39%69 of 325 rows used a frozen futures priceEach price paired with the same run's benchmark, with dedicated tests
CI failed with no code changeA test depended on today's dateInjected clock, and CI re-runs every test 400 days ahead, which found three more
The test suite was calling live APIsA test replaced one fetcher but not anotherNetwork access in tests raises an error that wrappers cannot swallow
Every Yahoo symbol failed on the live serverA test run had cached an empty cookie in the shared cacheTests use their own cache
A prompt edit could replay a stale model answerThe fixture key hashed the input but not the promptThe key includes the prompt; mock mode fails on a stale fixture
Intermittent false positives in the evalThe reviewer was right: my synthetic spec had two real gapsFixed the input, left the answer key alone, and disclosed it; 5 of 5 with 0 false positives on every run since

Working with coding agents

I use Claude Code and other agents to build faster, and I treat their output the way I treat any system under test: it has to prove itself. The root causes above are what that looks like in practice.

Leading quality

Code from before AI tools

I was writing software long before coding assistants existed. These are early projects I built while teaching myself to program.

ProjectWhat it isWritten
search-engine-phpA complete search engine in PHP2013–2015
search-crawler-php-pythonIts crawler, which ran on a jailbroken iPod and indexed about 4,000 sites a night2013–2015
snapchat-client-phpA Snapchat web client built on the old private API2014–2015
pokes-social-network-phpA small social network2016
android-notesA Pastebin-style Android app in Kotlin2017

Check any of it

Pick any row on this page and I'll walk you through the code, the decision and what I'd do differently.

Get in touch GitHub LinkedIn