A folder tree for a production AI app went around LinkedIn last week. Clean separation. Components, services, prompts, agents, security, evaluation, observability. Each concern in its own home. CLAUDE.md and AGENTS.md at the root. The structure reads like rigor.
I looked and saw half a harness.
Parts 1 and 2 argued the harness matters. This part names the half teams leave out.
Two halves
A harness has two halves. Most teams build one and ship.
The first half is specification. You tell the model what to build. Folder structure. Instruction files. Prompt templates. Coding rules. The folder tree on LinkedIn is all specification. Every file in the frame describes intent.
The second half is enforcement. You prove the system works. Smoke tests against live endpoints. CI gates blocking the merge. Row-count checks after migration. API contract documents. TLS chain verification. None of these describe intent. They catch the gap between what you specified and what shipped.
Specification photographs well. Enforcement does not. The screenshot felt complete. The system was unproven.
Why specification alone fails
A model fills every gap you leave with its own assumption. Leave a question in the spec and the model answers for you, silently, in code. Swap the model and the assumptions change. Your folder tree stays identical while the behavior underneath shifts.
This is the failure mode behind the phrase "vibe coding." The output looks right. The structure looks right. Nobody verified the system returns real data through DNS with a real token from outside.
The day a health check lied
GoviHub cost me 5 days.
A database migration ran. 10 tables failed to create. No error surfaced. The health check returned 200 because the app booted fine. The frontend fell back to mock data, so the screens filled with plausible numbers. Everything looked alive.
Three fix cycles patched the frontend. Each one treated a display symptom. The backend stayed broken the whole time.
A 5-minute curl with a real token would have caught the failure on day one. Hit the business endpoint. Read an empty array. Query the table. Find zero rows. Done.
The lesson became a rule. No silent mock fallbacks outside development. Verify row counts after every migration. A health check is not a smoke test.
The cert that passed and failed at once
Second failure. A TLS certificate served the leaf only, no chain.
The smoke test used curl with the -k flag. The flag skips verification, so the test passed. Real clients do not skip verification. Claude.ai and every browser refused the connection. Zero external traffic. No obvious error in the logs.
The fix took one line. Concatenate the leaf and the CA bundle into a full chain. The deeper fix was the rule. Never use -k in a smoke test. Verify the full chain the way a real client does.
openssl s_client -connect host:443 -servername host
A smoke test skipping what real clients enforce is theater.
What the strong half contains
The enforcement half is a short list. None of these show up in a folder tree.
-
A smoke test hitting every business endpoint with a real token, from outside, through DNS. Non-empty responses required. No
-k. No localhost shortcut. -
A CI gate running the smoke test and blocking the merge on failure. The gate runs independent of which model wrote the code.
-
A row-count check after every migration. Expected table count and expected rows, verified, before the deploy is called done.
-
An API contract document. Every URL the frontend calls, mapped to the backend endpoint, checked for agreement before deploy.
-
A TLS chain verification with openssl, not
curl -k.
The enforcement half holds when something breaks.
The strong half is the fast half
Teams skip enforcement to ship faster. The skip is the slow path. GoviHub traded a 5-minute check for a 5-day hunt. The enforcement half is not a tax on speed. The enforcement half is how you deploy without holding your breath. You ship faster because you trust the green light.
Read your own structure again
Look at any AI project structure with this lens. Find the healthcheck.py and ask what it proves. Find the tests and ask if any of them hit a live endpoint. Find the CI config. With no CI config, the AGENTS.md at the root is a suggestion, not a gate.
The folder tree is the easy part. You write it once and it photographs forever. The harness runs on every deploy and reports the truth when the screens lie.
Build the half nobody photographs.
