| title | How saying no built the product |
|---|---|
| description | A trust-bounded controller utility, built by one person with multiple agent sessions |
| permalink | / |
By Humphrey, with implementation by Claude Code and Codex agents under operator direction. Draft prose by a Claude Code researcher session (Claude Opus 4.7, 1M context). Acknowledgments at the end name the specific agents and dialogues that shaped each surface.
Date: 2026-06-04.
I'd been wanting to learn about agentic coding, and I already used the vendor's PC app for the ZD Ultimate Legend controller regularly — but some of its features didn't work, and I felt like I could make a better version. Continuing to troubleshoot and update it as the vendor patched the controller seemed like the kind of thing I'd stay interested in for a while.
Peripheral apps tend to be poor — mice, keyboards, controllers, controllers maybe worst of all — so just building a clean app seemed like a useful place to start. The constraints I ended up with (no drivers, no virtual devices, no input injection, no background service, no automation of any kind) weren't a thesis. They were my default for how to build software like this. They started doing real work later, when refusing specific features — an RC filter, an auto-update path — turned out to be the right call for real reasons. What I ended up with is a configuration tool defined mostly by those refusals, plus a controller-health layer wrapped around it that treats the device as a maintainable object rather than disposable hardware.
The other half is the agentic workflow that built it. Once the plan got harder, that's when agentic coding got most interesting to me: pushing agents to think outside the box, knowing when to hand a stuck problem to a different agent or to deep research, even reaching out to a human controller-tools researcher when creativity ran low. Seeing it actually work was what kept me motivated.
I still use the controller and the wrapper every day. If something's off, I can usually tell.
I bought a ZD Ultimate Legend controller in late 2025. Strong hardware: Hall-effect sticks, configurable modules, USB and Bluetooth, two onboard config slots. The advertised polling rate was 4 kHz when I bought it; ZD raised it to 8 kHz later through a firmware update — which is genuinely impressive, because most companies ship an 8 kHz "upgrade" as a whole new physical controller you have to buy, not as new firmware for the one you own. For the first few months I didn't use a PC app at all: the official Windows configuration app either wasn't out yet or wasn't offered through the international site I'd ordered from (zd-gaming.com). When it did turn up it was a Chinese-only Flutter/Dart AOT binary, distributed through forum-thread links and disappearing file drops — I ran the UI through Gemini Nano Banana, Google's image-editing model, to translate the toggle labels into English well enough to use it. Back-paddle binding worked, but the steps to get a clean "default" bind were fiddly — by default binding I just mean mapping an existing face button onto a paddle (say, binding B to the M1 paddle, so pressing either one independently registers as B). The installer also hooks the controller's HID device with permissions that don't match what the app visibly does, and the Android version of the same app exposes settings the Windows app silently drops. (The Android app isn't broken; I just prefer to do controller settings from a PC.)
The category splits cleanly into two tiers, and neither one is what I wanted. On one side, polished mainstream: Xbox Accessories, DualSense's tray app, Steam Input — these work on first-party hardware. On the other side, the enthusiast tier: reWASD, DS4Windows, JoyToKey, AHK scripts, ViGEm-backed virtual-controller stacks, HidHide. Powerful and well-maintained, but all sitting somewhere on the spectrum from "runs while you play" to "installs kernel drivers" — exactly the contrast class anti-cheat systems treat with escalating suspicion. Between those two tiers is a category of OEM-shipped tools I don't trust enough to run casually on a gaming PC, and the ZD's vendor app is one of them.
What I wanted was something the category doesn't have: a configuration tool I would actually trust on a machine I also game on. Not an emulator, not a remapper, not an in-game overlay. Just a way to set the controller's onboard memory to what I want, close the app, and play.
That's the original goal. The rest of this article is what happened when I took it seriously.
The product doctrine is a set of constraints, not features. The constraints came first, and the features were always shaped around them. Each constraint actually matters — drop any one of them and the whole thing collapses into the category I was trying to escape.
The constraints didn't arrive as a thought-through doctrine. They were the downstream consequence of two instincts I came in with. The first was security-first: before "what should this do," I'd ask "what's the threat surface, and what doesn't need to be in the build for it to do its job?" The wrapper is software that talks to a controller; almost everything else is optional. Every feature had to argue its way into the project, not the other way around. The second was a working belief that the simplest way to do something in programming tends to be the best way — Python over C# or C++ for a Windows-desktop config tool, the simplest path through the design space whenever a feature came up, complexity required to argue for itself if it wanted in. The list below is what fell out of those two instincts. I didn't write it first and then build around it.
In rough order of how often they came up in design decisions:
- HID-only. All writes are standard USB HID reports to the controller's MI_02 interface. No vendor IOCTLs, no kernel transport, no custom driver. From the OS's point of view the wrapper is just another HID-aware userspace process.
- No drivers. No
.sysfiles. No installer that requires admin to drop a kernel component. The Inno Setup bundle around the PyInstaller EXE writes files into%LOCALAPPDATA%and that's it. - No virtual devices. No ViGEmBus, no virtual gamepad, no HID-hide layer. The controller presents to Windows as exactly what it is, and the wrapper does not impersonate, intercept, or replace it.
- No input injection. Zero calls to
SendInput,keybd_event,mouse_event, or anything that synthesizes input. The wrapper writes settings to the controller; it does not press buttons on the user's behalf. - No game-process hooking. No DLL injection, no API hooks, no memory inspection of any running game. The wrapper has no idea what game you're playing.
- No background service. Launch, configure, close. No tray agent, no autostart, no
svchostcompanion. The EXE exits and the wrapper has zero residency. - No automation. No macros, no turbo, no timed sequences, no rapid-fire, no scripting. The wrapper does not enable any firmware feature that performs automated actions.
- No network calls. No call home, no update check, no telemetry, no cloud profile sync. There is no embedded HTTP client in the production path. (A short-lived "Safe Import" branch existed for opt-in profile sharing; the import button is dev-gated and the cloud-sync framing was rejected before it shipped.)
- Verified writes. Every HID write is followed by a read-back diffed against the requested value. If the diff fails, the wrapper reports the failure rather than claiming success.
- Local-only data. Restore points, Health Reports, wear-ledger entries, module-passport fingerprints — all stored in
%APPDATA%\ZDUltimateLegend\in plain JSON/JSONL. Diagnostic-bundle exports are operator-triggered, path-sanitized (the user's home path is rewritten to a placeholder), and require a manual share step.
These ten constraints define the product. If you understand them, you understand the wrapper.
Each constraint serves three purposes at once.
Anti-cheat compatibility. Modern anti-cheat vendors — Riot Vanguard, Easy Anti-Cheat, BattlEye, FACEIT Anti-Cheat, Activision Ricochet, VAC — are not reacting to "controller tooling" as a category. They react to where the tooling sits in the runtime stack. A multi-vendor research pass I commissioned in May 2026 (see §6) found that friction in the public incident record concentrates in four buckets: user-mode runtime remappers, kernel virtual-controller stacks with device-hiding filters, hardware-level input manipulation (XIM/Cronus), and macro/turbo tooling. Onboard HID configuration written once and closed — the bucket the wrapper sits in — has no strong public incident trail across the six systems surveyed. Every refusal in §2.1 is a refusal to enter a friction-prone bucket.
Trust. I'm asking someone to run an unsigned PyInstaller EXE that opens HID handles to their controller. That is, on its face, the kind of software a thoughtful person should be cautious about. The constraints make that caution survivable. "No drivers" means the install footprint is bounded. "No network" means there's no intentional path for the wrapper to send data anywhere — though locally-installed software can always leak through files, logs, clipboard, or subprocesses, so the constraint reduces intentional exfiltration surface rather than eliminating all possible leakage. "No background service" means closing the app means it's gone. "Verified writes" means every change is auditable. The constraints are enforced where it counts: in tests that fail the build if any of them is weakened — though without a public CI dashboard or released source repo to point at, that claim is on the honor system at the time of writing.
Product identity. Once you accept the constraint set, the set of design choices gets a lot smaller. There is no "should we add macros?" debate — the answer is structural: no. The constraints do the design work, leaving only the questions that matter: what's the controller's configuration surface, how do users safely interact with it, and how is every change made auditable?
A doctrine that lives only in the developer's head erodes. So the constraints are enforced where it counts — in code, tests, and centralized strings.
Forbidden-phrase tests. The wrapper's user-facing copy refuses certain words. "Latency," "calibrated," "verified polling," "factory image," "firmware backup," "clone," "approved," "whitelisted," "guaranteed safe" — none can appear in any locale file or rendered string for any subsystem that touches measurement claims. Tests at tests/test_health_report_forbidden_phrases.py and tests/test_restore_point_forbidden_phrases.py scan and fail the build if any appear. Module Passport, Wear Ledger, and Readiness Check screens each have their own scoped forbidden-phrase scans. Every measurement-claim surface enforces its vocabulary locally.
Single source of truth for claim boundaries. The "this is what the report is, this is what it isn't" paragraphs are not duplicated across exporters and UI. They live once, in a boundary.py module per subsystem (health_report/, restore_points/, diagnostic_bundle/). The forbidden-phrase tests deliberately whitelist these paragraphs — the only place the never-words are allowed, because the only place they appear in denial. The Diagnostic Bundle paragraph is representative:
This Diagnostic Bundle aggregates records this Windows app produced during local use of the controller: stick-module characterization fingerprints, exported Health Reports, and a summary of the wrapper's wear-ledger lifecycle log. Each record reflects only what the app could observe through Windows HID input reports and the wrapper's own operations — operator-assigned module IDs, operator-written service notes, and event counts the wrapper itself emitted. The bundle cannot prove true USB bus polling rate, firmware correctness, manufacturing defects, anti-cheat or tournament approval, controller hardware lineage, or end-to-end input latency.
Verbatim from zd_app/services/diagnostic_bundle/boundary.py. Same paragraph everywhere the bundle renders. No "marketing" version omits the denials.
Verified-write pattern. Every HID write goes through the apply coordinator, then a read-back diff. If the diff fails, the wrapper reports the failure and offers retry or rollback. During the v2 work we discovered that the controller's firmware silently rejects about two-thirds of step_size writes inside multi-field bursts — WriteFile returns success but the device never commits. The read-back caught this; without it, we'd have shipped a working-looking-but-broken slider for months. Fix: defer step_size after the burst.
Forbidden-phrase tests, centralized boundary paragraphs, verified-write reads. The doctrine becomes harder for future-me to weaken accidentally.
Most of the code is in zd_app/, decomposing along the constraint lines: i18n/ (locale dictionaries, en + zh-CN parity), protocol/ (HID encoding), services/ (business logic, no UI dependencies — settings_service.py raw HID transport, settings_apply_coordinator.py write-then-verify pipeline, restore_point_service.py, plus subdirectories for health_report/, wear_ledger/, module_passport/, diagnostic_bundle/ and ~25 others), storage/ (JSON/JSONL persistence), and ui/ (DearPyGui screens — no service logic).
There are no UI imports inside services/. The constraint is enforced by directory structure and by the test suite: services are unit-tested without a DPG context; screens are tested with a patched DPG that records widget-creation calls. This separation made the chip-based agentic workflow (§4) much more tractable — a chip targeting a service rarely touches UI, and vice versa, so independent lanes can land on the same branch without trampling each other.
For most of the project's life, it really was a configuration tool. The pivot happened over about ten days in the second half of May 2026. I directed the agents to build what I now think of as the "lifecycle layer" — the part of the wrapper that treats the controller as a maintainable instrument rather than a stateless peripheral.
The pivot was not pre-planned. It came out of a multi-model brainstorm (§4) where every model I asked converged on the same observation: I had built the hard part of "a configuration tool you can trust," and the next-most-valuable thing was not more configuration features, but the lifecycle surrounding the controller — onboarding, daily readiness, longitudinal wear, evidence for the manufacturer when something goes wrong.
Five surfaces landed across roughly seventeen merged chips over forty-eight hours.
When the wrapper first reads the controller in a session, a floating card appears at the top of the main window for about eight seconds. It says six things, in order: "Controller verified," the connection mode (USB / Bluetooth / XInput), "Local only. No network calls," "HID config only. No drivers, no virtual devices, no background service," firmware revision and active onboard slot (if both are readable), and "Settings written are verified by read-back." Then it fades.
No anti-cheat language on the card itself — full disclosure lives in the trust statement reference doc. The card is a brief confirmation, not a wall of text. The widget is gated to fire once per controller per app session and defers cleanly when the DPG context isn't ready yet — a real bug shipped in the first chip version, caught on hardware smoke, fixed in a follow-up chip the same evening.
The full Controller Health Report is a ~5-minute guided workflow producing an exportable Markdown + JSON report. That's the wrong instrument for a player about to queue a ranked match. So the lifecycle layer added a Readiness Check — a 20-second pre-match ritual that reuses the same measurement primitives as the full report (so verdicts can't drift between the two), runs three phases (rest, range, trigger), and produces a single green/yellow/red verdict with at most five observation lines.
The verdict-reduction logic is conservative on purpose: any phase with insufficient samples short-circuits to RED rather than producing a falsely-clean GREEN, and the worst-of-left/right rule means a degraded right stick can't be masked by a clean left stick. The right framing is a pre-flight checklist: a short equipment check before you commit to a match.
The Wear Ledger is the longest-lived piece of state in the wrapper. It records every wrapper lifecycle event: session start/end, profile applies, restore-point captures and restores, slider writes (one debounced event per "drag session" per field), Health Report runs, Readiness Check runs, module assignments, module characterizations, module-notes edits, free-text service notes, and diagnostic-bundle generations. The screen has two filter dropdowns, an expand-row affordance, and a verdict-trend sparkline (rendered as colored glyphs rather than a DPG plot, to keep the screen footprint bounded).
The discipline that mattered most here was append-only. There is no event editing. There is no event deletion. A fat-fingered module ID gets corrected by a follow-up note, not by editing the original. Same posture as a paper service book in a car maintenance shop, and for the same reason: the value of the log comes from its immutability over time.
The ZD Ultimate Legend's stick modules are user-swappable (this is one of the controller's headline features). Different modules — stock K-Silver, ALPS, Hall-effect, TMR — have measurably different behavior, and they wear differently over time. On my controller right now, the baseline modules are ALPS sticks. The natural data shape is a per-side, per-module characterization history, and that's what the Module Passport is.
The methodological lineage matters here. Rigorous, repeatable measurement on consumer controllers is rare — most controller "reviews" are vibes-based. The exception that shaped how the Module Passport is framed is John Punch's work at Gamepadla. Specific metrics, documented methods, concrete numbers, no overclaim. Seeing that pass over a wide range of consumer controllers is what made me think the same posture could be applied to a single-controller-deep tool. The Module Passport and Health Report borrow that posture: measure something specific, document the method, publish the numbers, and don't overclaim what the measurement implies.
There are two passports active at any time — one per side. Each contains an operator-assigned module ID, an assigned-at timestamp, optional free-text notes, and an append-only list of "fingerprints." A fingerprint is the output of a 60-second characterization session and contains eight metrics covering noise, centering, range coverage, deadzone span, asymmetry, observed bitness, tremor, and linearity. Four reuse Health Report primitives (so verdicts can't drift between the two surfaces); four are new to the passport. Verdict reduction is conservative — sub-minimum sample counts short-circuit to wear_observed, on the read that a false re-run prompt is preferable to a falsely-clean fingerprint.
Reassigning a module on one side archives the previous passport and starts a fresh one. The history is module-scoped, not controller-scoped — which is what you want when the modules are swappable. The per-side design also fits the situation I'm now in: one controller, a stack of module packs that arrived from ZD as a gift, and a need to track each module's history independently as they rotate in and out.
The Module Passport landed across three chips: core service plus screen, an advanced views chip (filtering, archive browser, cross-side compare), and a trend-analysis chip that adds linear-regression-over-time on each metric with explicitly advisory framing ("the data suggests…", "may be approaching…") — never as a deterministic claim. The brainstorm had warned that interpretation quality was the harder problem now that the measurement layer was solid, and the trend chip's design reflected that warning.
The Diagnostic Bundle is the wrapper's way of sharing evidence when something goes wrong. If a stick goes bad and you want to file an RMA, the bundle gives a single shareable artifact — Markdown or ZIP (Markdown plus raw JSON of passports, recent Health Reports, wear-ledger summary).
Two things worth calling out. Path sanitization: every absolute path is rewritten to an <APP_DATA> placeholder before the file lands on disk, with a test asserting no leaked usernames even when a service note contains a verbatim path. What's deliberately not included: the raw wear-ledger JSONL is never in the bundle, only the summarized roll-up — no IPs, no mtimes, no process telemetry. Every rendered bundle ends with an explicit "What was NOT included" section.
Most controller utilities treat the controller as a stateless object: connect, configure, forget. Controllers are not stateless. They wear, drift, and benefit from periodic checks. They're more like a bicycle than a USB drive.
The five surfaces compose into a loop: trust ritual is the moment-of-connect "this is what I am." Readiness Check is the pre-session "is the equipment trustworthy today." Wear Ledger is the long memory. Module Passport is the per-component microscope. Diagnostic Bundle is what you reach for when you need to share evidence externally. None of that loop existed in early May. All of it exists now.
The wrapper was built by a single human (me, Humphrey) directing several agent sessions through a parallel chip-based workflow. The agents wrote nearly all of the code. I wrote the doctrine, the specs, the test prompts, the merge decisions, and — when the agents got it wrong — the hardware smoke that caught the error.
This is a co-authored product. I'm going to be honest about what each party contributed.
The workflow wasn't this articulated at the start. The first time I sat with Codex, I was effectively using it as autocomplete — typing "next turn" as the prompt over and over and letting it grind forward on whatever it thought was next. I tried the same with Claude Code, and Claude told me in roughly so many words that I probably shouldn't just be saying "next turn"; I had a lot more control over the environment and the workflow than I was exercising. That was the moment the project changed shape for me. The agents weren't asking for free rein. They were waiting for me to act like the operator — choose context, scope chips, set priorities, redirect when work drifted. From that point I invested in the workflow itself (chips, worktrees, bridge files, multi-model brainstorms, cross-project digests) much more than in any individual prompt. The chip-and-worktree pattern in §4.2 wasn't an idea I had on day one. It's what emerged once I started treating myself as orchestrator instead of caller.
Four roles, each a different shape:
- Researcher (Claude Code, sometimes Hermes). Designs specs from operator direction, smoke-tests landed code on real hardware via computer-use, writes verdicts and memory updates, and forwards work between programmer lanes. Doctrinal coherence lives in the researcher session; there's typically one at a time, persisting across days. The session writing this draft is a researcher session.
- Programmer (Claude Code, in worktrees). UI screens, diagnostics, cross-cutting refactors. Multiple sessions run in parallel without colliding.
- Programmer (Codex). Service-layer code, apply coordinator, backend/protocol work. The split between Codex and Claude Code is rough but real: Codex handles smaller tool/analyzer/test work well; Claude Code handles orchestration and UI better.
- Reviewer (Claude Code or Codex). Independent code-quality / product-UX audits. Output goes to me and the researcher; the researcher triages and specs follow-up chips.
The unit of work is the chip: a self-contained, spec'd lane that lands as a single merge commit on the trunk branch. Each chip starts with a researcher-written spec, gets a fresh worktree, runs to completion in isolation (with its own context window), and merges back through a Merge Lane <name>: <description> commit. The mechanic comes from Claude Code's mcp__ccd_session__spawn_task tool, which gives a parallel lane an independent worktree. Multiple chips run in parallel; they don't see each other's untracked files but share the trunk commit they branched from.
A representative slice of the lifecycle-layer merge log:
c326725 Merge Lane module-passport-trend-analysis: longitudinal regression + advisory framing
68a5c33 Merge Lane wear-ledger: chronological maintenance log + screen + service
efffc2c Merge Lane trust-ritual-at-connect: brief trust card on first_readable_connect
Ten lifecycle merges over four days, plus a 17-chip day across the whole project on May 26. That does not mean seventeen production-perfect features; it means seventeen isolated merges, many of them narrow. The chip workflow scales for a solo operator in a way no other workflow I've tried does.
Chips run in their own worktrees, so they can't see each other's in-flight state. Cross-agent coordination happens through bridge files in zd_research/: researcher → programmer messages, programmer → researcher reports, per-chip lane reports written at merge time, and multi-model brainstorm responses. There are forty-plus lane reports at the time of writing. They are the project's institutional memory. When I (or a future agent session) need to understand why a particular constraint exists, the lane report from the relevant chip is the authoritative source. The git log tells you what changed; the lane reports tell you why and what the agent considered and rejected.
Several times — most pivotally on May 26-27, 2026 — I commissioned a multi-model brainstorm before making a direction-setting decision. The pattern: write a prompt framing the project's current state and asking a structured set of questions ("honest read of where this is," "top 3 things to build next," "one contrarian suggestion," "blind spots," "what to NOT do," "self-assessment"). Then fan it out across several frontier models via OpenRouter (lineup in Appendix A) and read the responses side by side.
Convergence patterns:
- Strong convergence (all models). The project is no longer a "config tool" — it's a trust-first instrument / stewardship platform. Longitudinal analysis on Module Passport / Wear Ledger data is the natural next build. Some form of architecture write-up is high-leverage before more building. A controlled private beta is more appealing than blind public release.
- Interesting disagreement. Claude Opus 4.7 argued specifically for publishing methodology before the app. GPT-5.5 emphasized release-candidate hardening. Gemini uniquely pushed a "Match Day lockout mode" demoting the settings editor behind a technician panel. Grok suggested an opt-in vendor-upload channel for diagnostic bundles (rejected — conflicts with no-network). DeepSeek suggested cryptographically signed profile sharing (rejected — conflicts with local-only).
The rejection cases were useful because they exposed where a suggestion violated the constraint architecture. The valuable disagreements are the ones that respect the constraints and still find genuinely different next moves.
This article is the direct consequence: the methodology-paper recommendation held up across multiple framings, so I commissioned it.
I run three projects that share an operator and overlap in capture-discipline / multi-agent-pattern terrain: this wrapper, the Controller Latency Analyzer, and the Apex Performance Lab. A "digest" is a researcher session walking the source project's recent activity with the destination project's posture in mind and surfacing items worth lifting. Cost: roughly one researcher session every two weeks. Benefit: patterns refined in one project don't have to be rediscovered in the others.
What worked. Constraint-driven specs (chip prompts are short and precise because the doctrine prunes the space). Lane-report institutional memory (every merged chip leaves a report; future chips read it instead of re-asking). Parallel chips with worktree isolation (two or three lanes in flight at once with no collision was the productivity ceiling on the 17-chip day). And hardware-smoke discipline — every lifecycle chip ended with the researcher driving the wrapper on real hardware via computer-use. This caught bugs the test suite missed, most clearly the trust-ritual gate-poisoning bug.
One pattern is worth naming on its own. Claude Code is the stronger orchestration and UI tool, and most of the project's central thinking lives there. But Claude has a failure mode where it gets stuck — overthinking, narrating reasons it can't make a fix instead of attempting one. The move that consistently unstuck the lane was to hand the same task to Codex. Codex would attempt the fix poorly, often ignoring constraints Claude had been agonizing over, and the attempt would land as a diff on a branch. I'd bring that diff back to Claude, which now had a concrete artifact to react to and could repair it cleanly. Dylan Patel has told a similar story publicly about a high-level kernel developer at a White Hat security outfit using the same Claude → Codex → Claude rotation on hard kernel problems. The agents aren't interchangeable. Most of the value of running two of them isn't redundancy — it's complementary unsticking. Knowing which to deploy when is part of the orchestration discipline.
What didn't, at least at first. I tried a formal coordination protocol early on (a dispatch/ folder with inbox.md, outbox.md, turn-log.md); it produced correctly-formatted ceremony and very little coordination value. Turned it off, productivity went up. Chip-author stale base bit me a couple of times — chips branching from commits several lanes behind trunk made for messy merges; the fix was specifying the exact base commit in the prompt. Programmer-tradeoff bugs are the persistent failure mode: agents will make tradeoffs that look reasonable in isolation but break under integration. The trust-ritual chip is the cleanest example I have. The programmer noticed a potential retry-storm risk on the per-session render gate and made what looked like a defensive choice: mark the gate as fired even when the DPG context wasn't ready, so a re-entry wouldn't spam. Tests passed. On real cold-launches, the card silently never appeared, because first_readable_connect fires in app_shell.py:879 before _dpg_context_ready=True is set three lines later — the gate poisoned itself on every real boot. The hardware smoke caught it; a follow-up chip the same evening added a pending-state plus a drain helper called after DPG comes up.
With this harness, I could hold more complexity than I normally associate with solo work. The wrapper has 2185+ tests, two locales, twenty-plus services, a dozen-plus screens, an installer, a hardware-smoke harness, and a meaningful methodology layer in the lifecycle work. One person built it, with very real but very specific help.
What does not scale yet: synthesizing across many simultaneous concerns at once. The agents are excellent at executing a well-scoped chip. They are not yet excellent at holding the whole product in working memory the way I do. The bridge-file institutional memory papers over that gap — the agent doesn't have to remember; the file does.
The frame that's been most useful to me for this seam is Andrej Karpathy's distinction between verifiable and non-verifiable work. Verifiable work — does this refactor pass, does this feature land green, does the build install — is what the agents are excellent at. Non-verifiable work — is this aligned with the doctrine, is this the project I want, does this feel right — is what stays with me. §5's override below is a long example of non-verifiable work. The brainstorm-and-pick pattern in §4.4 is another. Picking what not to build is a third. As verifiable work compresses under faster, more capable agents, the proportion of my time in the non-verifiable seat keeps growing. That's also become part of how I now think about which projects to start — partly by what counts as verifiable today, and partly by whether I want to sit in the non-verifiable layer for the rest.
I came to recognize a specific moment in this work that other practitioners might recognize, and it's important enough to surface honestly.
When I asked Claude — and GPT, and Gemini, and Grok, and DeepSeek — early in the project whether building a standalone Windows app for a niche Chinese controller was a good idea, the answers were uniformly cautious. The strongest summaries were variants of: the risk-adjusted expected value is low; don't ship publicly; consider whether personal-utility alone justifies the maintenance burden. The cited reasons were correct: maintenance burden of public Windows software, the difficulty of forming an OEM relationship as a solo dev, brittleness of unsigned PyInstaller distributions, the unlikely-to-materialize nature of manufacturer dialogues.
I overrode all of that, and I think I was right to. The override didn't reject the agents' analysis — it accepted the risks and committed to a project shape that absorbed them. That shape only had time to form because I kept building past the point the population statistics said to stop. The doctrine became coherent, the lifecycle layer became thinkable, and the manufacturer dialogue happened. None of those outcomes were available to the project as the agents pictured it. The override created the room to make the project's shape different.
The easy framing — "agents are too cautious, just do what you want" — is dangerous and wrong. The agents weren't wrong. They were calibrated to a population of solo-dev-Windows-app-against-niche-hardware projects, and the population-level expected value of that project type really is low. The mode of the distribution is "abandoned three months in." This project worked for specific reasons: I owned the hardware, I had the time, I had a personal motivation that wasn't going to evaporate, I had a multi-agent workflow that scaled, and the constraint architecture was tight enough that the agents could be productive inside it.
Two things to call out about the override pattern. First: agents are calibrated to a population; the operator knows the specific situation. "This kind of project usually fails" is true; "my version will fail" is a different claim, and the agent has no access to the local context that makes the specific instance an outlier. Second: the override has to respect the agents' actual concerns. Where their caution was correct was on specific failure modes — distribution friction, antivirus false-positives, the maintenance-burden ceiling. The override wasn't "ignore all of this"; it was "accept these risks, they are bounded, and adapt the project shape to mitigate them." The personal-utility-first focus, the deferred public release, the lack of an auto-update channel, the manual install discipline — all direct consequences of agreeing with the agents' concerns and choosing a project shape that survives them.
The project exists. The dialogue with the manufacturer has actually happened — Discord exchange, a generous gift of new stick module packs in response, the brief routed to their dev team's programmer. The doctrine is coherent. The lifecycle layer is unusual in this category. Those are real outcomes, not predictions from the population.
The agent has population statistics; I have local context. The work happens at that seam. The agents make me much faster at executing a vision. They do not — and probably should not — make me faster at choosing one. "The agents said don't" is a signal worth weighing. It is not a verdict to defer to.
The anti-cheat surface is where the trust posture is most testable. Two caveats up front. First, anti-cheat vendors change their policies — anything here is current as of May 2026 and may not be current later; the wrapper has no telemetry channel to know when a line moves, and if it does, the compatibility story will need a corresponding update. Second, the source material is public reporting and a ChatGPT Deep Research pass commissioned in May 2026; the full report (zd_research/hermes_anti_cheat_compat_response_2026-05-26.md) and the cached evidence-aligned wording (docs/trust_statement_reference.md) are kept in the project's private working repository.
The research surveyed the six major Windows anti-cheat systems active for PC gaming (Riot Vanguard, Easy Anti-Cheat, BattlEye, FACEIT Anti-Cheat, Activision Ricochet, VAC/VACnet) and found that public enforcement clusters around four architectural buckets, in decreasing order of incident-history concentration:
- Hardware/input manipulation and automation. XIM/Cronus-style hardware, macro/turbo tooling, DMA cheats, triggerbots. Active enforcement target across Ricochet, EAC, Vanguard, FACEIT, and BattlEye.
- Kernel virtual-controller / device-hiding stacks. DS4Windows + ViGEmBus + HidHide/HidGuardian, Interception. FACEIT explicitly blocks Interception drivers. EA/Apex community guidance repeatedly points at DS4Windows/VirtualController-style stacks. Highest scrutiny short of outright cheats.
- User-mode runtime remappers and live input translators. reWASD, JoyToKey, AHK controller scripts. Frequently blocked, kicked, or unsupported; sometimes escalates to bans when used for unfair advantage.
- Onboard HID configuration only; app closed before play. The bucket the wrapper sits in. Vendor utilities used only to write controller memory. Usually ignored / irrelevant, unless the controller itself exposes prohibited runtime behavior (turbo, macros) or presents through a weird device path. The lowest-risk bucket in the surveyed material.
Of the specific vendor utilities surveyed, FlyDigi Space Station had meaningful public friction in 2024-2025; 8BitDo Ultimate Software V2 and GuliKit KK3 Max did not. That is sparse-evidence territory, not a formal whitelist — "no strong surfaced public incident trail," not "certified safe everywhere."
The wrapper is deliberately situated in bucket #4, and the §2 constraint list does the architectural work to keep it there. The wrapper doesn't claim to be safe for any particular game; it claims to architecturally avoid the categories anti-cheat systems publicly target. Those are different claims.
The refusals in this section came out of the two instincts in §2 — security-first thinking and a bias toward the simplest path. The wrapper doesn't consult a list of forbidden features; it has a habit of asking "does this need to be in the build?" and refusing the answer "well, it's what other apps in this category do." What that habit produced divides into three groups: refusals that protect anti-cheat compatibility, refusals that protect the trust surface, and refusals that protect product coherence. §2 has the ten constraints; this section names the work each category of refusal does and adds the few that don't fit cleanly into the ten-item list.
Anti-cheat refusals keep the wrapper in §6's lowest-risk bucket. No macros, no turbo, no timed sequences. No virtual controller (ViGEm-class). No input injection — the wrapper writes settings, it never presses buttons. No driver, no background service. No game-process inspection. And no evasion language in user-facing copy, because the posture is "architecturally outside the bucket anti-cheat targets," not "evades detection." The wrong word in a piece of copy can do as much damage as the wrong piece of code.
The clearest near-miss in this category is one I want to name on its own, because it's the place "no automation" turned from an abstract refusal into a specific decision. Early on I genuinely considered adding an RC filter — a low-pass smoothing filter on analog-stick output — to the wrapper. The reasoning at the time was reasonable: smoothing could help with hand tremor, and Apex Legends amplifies stick shakiness (Apex uses 0% deadzone with linear sensitivity, which makes every micro-input visible). I'd seen the filter demonstrated on a Void Firebird — a Japanese-made PS4 controller — and the smoothed output really did feel better. So I started thinking about how the simplest version of it would slot into the wrapper.
Then the scandal broke. Beyond the smoothing case, RC filters can be tuned to add jitter to recoil control — automating the micro-circle mouse motion some Apex players had been doing manually. That's a much sharper line. It's no longer smoothing; it's automated aim assistance. The filter got banned in ALGS. GameSir added it to the G7 Pro 8K and later removed it. ZD's Mullen, who I'd been talking with on Discord by that point, said explicitly that ZD would never put it into their software, and I agreed with the decision and the reasoning. The "no automation" line in §2.1 isn't an abstract refusal of a category. It's the place I stopped after seeing what the next step of "smoothing seems cool" actually looked like.
The other concrete event that shaped the wireless / network refusal happened around the same time. The ZD Ultimate Legend itself was banned from an ALGS LAN in Japan, roughly 12 hours before the event (the Year 5 Championship in Sapporo). The concern was the Bluetooth surface the controller uses to talk to ZD's mobile app: in principle, someone in the audience could install the mobile app, pair with a pro player's controller, and change settings mid-match. Imperial Hal posted publicly about the ban; he, Verhulst, and Phony were among the pros who'd been using the ZD Ultimate Legend going into the tournament. GameSir loaned Hal a GameSir G7 Pro for the next day (this was pre-8K release). ZD responded fast: they patched in a "tournament mode" that disables all wireless connectivity, forces PC-app-only configuration, and removes macros for good measure — which, separately, were already a category I'd decided not to add to the wrapper. The controller was unbanned after the patch. Hal posted confirmation when it returned to legality.
(The RC-filter ALGS ban and the ZD LAN ban above are sourced to contemporaneous reporting, linked inline. A few specifics are from my own memory of following the events at the time rather than a cited link: that Verhulst and Phony were also using the controller going in, the GameSir G7 Pro loaner, and ZD's subsequent tournament-mode patch and the controller's reinstatement.)
The story doesn't reflect badly on ZD; they moved quickly and competently when it mattered. The point worth pulling out is that the wrapper's no-network, no-wireless-control posture isn't ambient paranoia — it's a refusal aligned with what pro competitive Apex was already enforcing in practice on this same hardware. The industry made the case before I did.
Trust refusals keep the install footprint bounded and the local-only story honest. No telemetry. No auto-update; manual updates with published SHA-256 hashes are the correct posture at this size. No cloud profile sharing — every model I've brainstormed with has, at some point, suggested some version of this, and for this project the suggestion is wrong every time. It collapses the local-only story and opens a moderation/phishing surface I can't maintain solo. The Safe Import code exists but is dev-gated. And no firmware flashing — the wrapper writes settings (data); it doesn't modify firmware (code).
The honest reason for these trust refusals, beyond "no," is honesty about what I can't credibly verify on my own. I'm not a cybersecurity expert and I don't claim to be. There's no equivalent of a "cybersecurity certificate" for current agentic workflows, and the agents themselves don't carry that kind of assurance. Given the steady stream of scandals about everyday consumer apps getting hacked, adding cloud-anything or unsigned-content channels into a wrapper at this scale and review level would be irresponsible. Better to refuse the feature than to ship an unsafe version of it. The constraint sits exactly where my ability to vouch ends.
Coherence refusal. No multi-controller scope creep. This is a deep tool for one controller family. Adding others dilutes the depth and turns the project into a generic "controller config app" — a categorically worse product position.
Add any one of these back and something collapses: the trust posture, the anti-cheat compatibility argument, the doctrinal coherence, or the self-pruning shape of the design space. The refusals are the architecture.
This is not a "weakness" section. It is a "what I don't know yet" section, and it matters.
Calibration and longitudinal sample size. Every Module Passport threshold, every Health Report verdict band, every "wear_observed" gate has been calibrated against a single controller and a single pair of hands — mine. The wrapper has never been used by anyone but me. The conservative-bias reduction (sub-minimum samples → automatic re-run prompt rather than trust) helps with the false-positive case, but it does not solve the underlying calibration problem. The parked-private-beta lane is the planned response — several brainstorm respondents correctly pointed out that a 5-10 person private beta would teach me more in two weeks than another month of solo building, and that is on the roadmap. The longitudinal trend metrics that landed on May 26 compute well-understood math, but the signal-to-noise on real wear data over months is unknown; the metrics may turn out to be noise-dominated when applied to actual longitudinal data, in which case the trend layer will need to be either retuned or scoped back. The 8-metric verdict bands are derived from Health Report family thresholds and round numbers, not population data — additional units beyond mine (a second controller, or a deliberately-worn unit from ZD's QA pile) would start moving the metrics from personal observations toward population calibration. Until then, I can only say "these are the values on my unit," not "these are the values on any ZD Ultimate Legend."
Whether the trust posture survives feature drift over years. I'm one person. Future me might be tempted to add a tray agent for "convenience." Future me might be tempted to add cloud sync because someone asks nicely. The constraint architecture is enforced today by tests and by my discipline; both are mortal. The negative-capability discipline in §7 is partly an attempt to put a stake in the ground that future me will be reluctant to cross.
Whether the ZD relationship materializes into something durable. The manufacturer dialogue happened, but it's early: Discord exchange, a generous gift of stick module packs, brief routed to a programmer. It is also paused — Discord conversations like this often go cold, and that is a normal outcome. The project does not depend on the relationship; if ZD becomes a contractor or partner, that's upside, but the personal-utility core of the project stands on its own.
Whether anti-cheat policies hold over time. The compatibility posture summarized in §6 is current as of May 2026. Anti-cheat vendors change their policies. Vanguard or FACEIT could decide tomorrow that any third-party controller utility is suspect, regardless of architecture. There is no telemetry channel in the wrapper to know when that line moves, and if it moves, the wrapper's compatibility story will need a corresponding update. The trust statement reference doc carries an explicit caveat about this, and it is correct to do so.
A few honest notes after spending two months on this.
The continuity is what made this feel different from prior AI tooling. I'd used a lot of generative AI before this, but agentic workflows — Claude Code and Codex first, now Hermes too — were a real step up. The pattern that mattered most was the workspace one: agents save notes, records, and analysis as they go and reflect on that context as they continue, which keeps expanding what they can hold in working memory. The continuity plus the intelligence is the part that impressed me. Yes, sometimes the agents need scope from me. But just as often I can check out, work on another project, and trust them with "if there are more chips to spawn, spawn them; if not, let me know." Claude in particular is good at flagging when a decision actually needs me, so stepping away doesn't mean coming back to a stalled lane.
A controller app sounded like the easy version of agentic work. It wasn't, and that turned out to be the point. I'd been listening to a Dylan Patel-hosted podcast, Transistor Radio (formerly on the China Talk channel, with Asianometry as a regular), where the workflows are things like tracking every power plant coming online in the US, or whole semiconductor supply chains end to end. Workflows on that scale sounded impossible to me. So when I started on a Windows utility for one controller, I figured: "Oh, that'll be pretty easy by comparison." It wasn't. It was much harder than I expected. But it was also much more rewarding — the difficulty is what made the doctrine and the lifecycle layer actually have to mean something, instead of decoration on a quick project.
This made me more optimistic about solo work with AI. I understand now why some people are spending so much time inside these workflows. Right now, my usage and uptime on Claude Code in particular have been great — especially after Anthropic's deal with Elon brought Colossus 1 online — and I always have something productive to do. The future worries me a little: newer frontier models are coming — Anthropic has Mythos in limited access under Project Glasswing right now — plus the compute and token demand that Dylan Patel has been calling tokenomics. It could get complicated. But the core feeling is optimistic. I can keep working smarter — ask agents what I did wrong, what I could do better, fan out brainstorms even when I don't have a specific idea I'm pursuing. Seeing several pathways a project (or a new project) could take opens up my own thinking.
- Claude Code (Anthropic, Claude Opus 4.7, 1M context) — primary researcher, primary UI/screens programmer, primary draft author of this article. Most lifecycle-layer chips ran through Claude Code programmer sessions.
- Codex — backend and service-layer programmer for many chips, especially the apply coordinator, the protocol layer, and small tools / analyzers / tests. Different failure modes from Claude, complementary in the way §4.6 describes.
- GPT-5.4 via Hermes — original brainstorm partner for the trust-first / lifecycle pivot direction. The cross-model brainstorm respondents on May 27 (GPT-5.5, Gemini 2.5 Pro, Grok 4.20, DeepSeek V4 Pro via OpenRouter) collectively produced the "publish methodology before more building" recommendation this article responds to.
- ChatGPT Deep Research — multi-vendor anti-cheat compatibility research grounding the trust statement reference doc.
- ZD — the controller manufacturer. They responded to my initial Discord outreach, sent a generous gift of new stick module packs, and routed my brief to their dev team's programmer. The dialogue is paused as of late May 2026; whether it resumes is open, but the gesture mattered.
- Mullen at ZD — specific credit. The Discord exchange was the actual human dialogue with the manufacturer. Mullen relayed ZD's posture on RC filters and on the v1.18 firmware fix, and that exchange shaped my own decisions on the wrapper's automation refusals.
- John Punch / Gamepadla (gamepadla.com) — author of multiple controller-measurement tools and operator of Gamepadla. His work is the methodological reference for the Health Report and Module Passport — specific metrics, documented methods, concrete numbers, no overclaim. He also sent feedback over email that helped clarify direction on several design questions; out of etiquette I'm not quoting any of it, but the credit is real.
- Marius Heier (tools.mariusheier.com) — inventor of the Marius Board (a PS4 controller) and author of a stack of controller-related tools at his site. His existence as a solo dev producing useful, durable controller tooling was an early signal that this whole shape of work was possible.
- Dylan Patel — for the publicly-told story about a top-tier kernel developer at a White Hat security outfit using a Claude → Codex → Claude rotation on hard problems. That framing of complementary agent failure modes matches my own lived experience on this project (§4.6).
- The Apex Legends competitive community — indirectly. The Hal LAN-ban arc in §7 is what established that the wireless-surface concern wasn't theoretical — pro Apex tournaments enforced it on this same hardware before I made the corresponding refusal in the wrapper.
- Sister projects — the Controller Latency Analyzer and Apex Performance Lab projects share an operator with this one; cross-project digests brought patterns that landed in the wrapper's capture-smoke discipline and methodology framing.
These are pointers, not full content. They reference files kept in the project's private working repository, named here so the reader knows what primary material exists behind each claim. They are not public links.
The May 27, 2026 brainstorm fanned out across Claude Opus 4.7, GPT-5.5, Gemini 2.5 Pro, Grok 4.20, and DeepSeek V4 Pro via OpenRouter, plus GPT-5.4 via Hermes from the day before. Full responses live in the project's private working repository under zd_research/openrouter_brainstorm_runs_2026-05-27/, with a SUMMARY.md tracking the convergence and disagreement patterns, and GPT-5.4's earlier response (which originally proposed the methodology-paper recommendation) at zd_research/hermes_brainstorm_response_gpt54_2026-05-27.md.
The full deep-research pass (zd_research/hermes_anti_cheat_compat_response_2026-05-26.md), the cached evidence-aligned wording (docs/trust_statement_reference.md), and the research brief that produced the pass (zd_research/hermes_anti_cheat_compat_brief_2026-05-26.md) are kept in the project's private working repository.
Representative test file: tests/test_health_report_forbidden_phrases.py. The pattern: scan a scoped i18n key set for vocabulary that overclaims ("latency," "calibrated," "verified polling rate," "factory image," "guaranteed safe") and fail the build if any appears. The whitelist of allowed forbidden words is the claim-boundary paragraphs themselves, which use the never-words in denial (the verbatim source lives at zd_app/services/health_report/boundary.py).
The latency-analyzer digest (zd_research/cross_project_digest_from_latency_analyzer_2026-05-26.md) brought DDSketch quantile primitives, JSON-record-with-fingerprint patterns, anti-cheat README language, and a cross-tool HTML output convention. The Apex performance lab digest (zd_research/cross_project_digest_from_apex_perf_lab_2026-05-26.md) brought capture-stack hardening discipline and a RegisterHotKey-only labeling reference implementation.
Independent writeup. No sponsorship or affiliation. Product, company, and individual names are used descriptively, based on public information; the author built the described software as a personal project. The internal file paths referenced throughout point to the project's private working repository and are not public links.