lee ming liang home · about · use cases · portfolio

the evidence

Five claims, and where each one came from.

The homepage makes five claims about working with specs and AI on live, long-lived systems. The evidence comes from two of them: a compact e-commerce rebuild carrying 10 years of production data — the method's proving ground — and the 18,000-file school platform where it now runs, with its Laravel successor specified this way from day one. Each case is dated, sourced from session logs, and honest about its limits.

the job, drawn: undocumented intent in, specs out
id: cold-start · tokens

One architecture decision, a fifth of the context

The setting: a live system with 10 years of production data and traps that exist nowhere in the code — a database whose latin1 columns deliberately hold UTF-8 bytes, passwords still on MD5 because a legacy reader depends on them. Exactly the kind of system where a confident newcomer is dangerous.

An AI session cold-started with nothing but the spec folder. It read about ten spec files — roughly 15k tokens — and from that alone assessed a proposed chat feature, settled its architecture, and wrote two new specs plus a migration. It never opened a single source file.

The session's own estimate for reaching the same understanding from raw source: 50–100k+ tokens and several extra rounds of tool calls — and some questions it would have answered wrongly, with confidence, because the facts simply aren't in the code.

HONESTY BOX

Self-reported by the session, one data point, not a benchmark. The gap is the point, not the precision.

source: session log, 2026-08-11 · e-commerce rebuild · pays the homepage cards "minutes to working context" and "a fraction of the tokens"
id: portable

The most valuable warning contradicts best practice

An AI's failure mode on a legacy system isn't ignorance — it's confident generic best practice. A fresh session arrives already wanting to connect with utf8mb4, retire the MD5 column, add a unique index on email. Right in 95% of the world's projects. All three would corrupt or break this one.

So a warning earns its place in proportion to how correct the forbidden practice usually is. A DON'T about an obscure operation is nearly worthless — the model wasn't going to do it anyway. The DON'T against the textbook move is the one that matters, because that's the step a capable AI takes without hesitating.

Then the stranger finding. One day a session's utf8mb4 suggestion was caught mid-flight — a near-miss, logged. Days later, a similar session read the warnings first and the suggestion never formed at all. No near-miss, no event, nothing to record. The mechanism working perfectly leaves no trace — so the evidence log is a lower bound on the method's value, reported by the only party who can see it: the AI that got blocked.

HONESTY BOX

Plain text, no tool-specific format — the warnings counter any model's priors, and a human newcomer's too. If it only made sense to one tool, it never encoded the intent.

source: audit log, 2026-08-15; near-miss logged 2026-08-10 · e-commerce rebuild · pays the homepage card "any model, any vendor — or none"
id: scale

More files, not a harder start

18,000+ files. 150+ modules. One school depending on all of it, daily. No single document — and no single context window — can hold that, so a flat "instructions file" fails in one of two ways: it grows unreadable, or it goes quietly stale.

The approach: split documentation by what actually changes independently. Architecture in one place, the database in another, the login and security flow in a third, one file per module. A cold start — new engineer or fresh AI session — reads two or three targeted files, not a codebase.

The consequence is the claim: growth changes the number of files, not the difficulty of starting. The map scales because no single sheet has to carry the territory.

source: the school platform's running documentation — 18k files, organised this way since mid-2026 · pays the homepage card "scoped units, not one giant mental model"
id: security

The review a CI gate can't run

A session cold-started on the spec folder, then ran the security checklist against a registration flow. It located three real holes in minutes — not by reading the whole codebase, but because the danger zones and the security spec told it where to look and what this system considers a threat. The fixes shipped: rate limiting, a honeypot, a bot challenge, anti-enumeration, plus an audit-log module.

Why a CI gate can't do this: a push hook catches what's written — a leaked secret, a syntax error, an injection pattern. A checklist read against intent catches what's missing — the rate limit that isn't there, the branch nobody guarded.

HONESTY BOX

From the same session's log: for planning work, specs replaced nearly all the reading. For security review they replaced "where to start and why" — not the line-by-line verification, which still means opening files. A method whose limits you can't state is marketing, not engineering.

source: session log, 2026-08-11 · e-commerce rebuild · pays the homepage card "a review a CI gate can't run"
id: the-loop

The loop that keeps the map honest

The uncomfortable truth the whole system is built around: a stale spec makes an AI wrong in exactly the same confident tone as a correct one. From outside, right and wrong are indistinguishable — the model won't raise its hand to say it's out of date. So freshness can't be a habit. It has to be a check that can fail.

Every spec names the real files it derives from (source:) and the date it was last verified (checked:). An automated pass flags drift. The rule when it fires: the code is truth, the spec is a hint.

And once, the loop proved itself on itself: the drift-checker raised a false alarm on a source that wasn't a file — and investigating the false alarm found and fixed two bugs in the checking tools. Even the error detector gets error-detected. That's what an honest loop looks like.

source: session log, 2026-08-11 · e-commerce rebuild · pays the diagram's "derived from / checked against" loop on the homepage
id: the-constraint

The cost, stated plainly

For an existing system, these specs don't write themselves. Someone who understands the system — or is willing to excavate it — has to digest years of undocumented intent and write it down. That archaeology is real work, and it's the method's main price. And it never fully ends: every change must update its spec in the same sitting, or the loop quietly dies and the map becomes the territory's most convincing liar.

For a fresh system, the cost inverts. Specify as you build: each spec written the day its subject is born, the set staying proportional to what exists. No excavation, no backlog — just a habit that costs minutes per change. That's the cheap path to a system that can grow large and stay manageable, because the map grows with the territory instead of being reconstructed after it.

Both halves are running right now: the 18k-file legacy system paid for its history, one dig at a time — and its successor's spec set was created when the new system was one sample page, so it will never have an archaeology bill at all.

the old system pays for its past; the new one only pays as it grows

what this page doesn't show yet

The visual half of the system — the dashboard that renders these specs as a browsable graph — deserves a screenshot rather than a description, and will get one. And the products these methods helped ship (an AI oral-practice tool, a budget module, a live event queue) belong on the portfolio page.

← back to the claims