I Can't Code, So I Built a System That Stops an AI From Lying
Subtitle: One month, about $110, dimensions matched to 0.02 px, visual resemblance: none.
1. The claim first
I live in a village, I can't code, and I never learned. I came across DeepSeek
Flash Vision while watching a Blender video on YouTube, and decided to point it at 3D: a photo of a payphone goes in, a finished model comes out. I had watched what Claude does on the same kind of task and wanted to repeat the result, not the path.
A month later I have measured dimensions, a documented refusal on visual resemblance, and 165 tools, more than a hundred of which exist only to stop the system from lying.
Here is the finding this article is about. The goal did not fail because something was broken. By the end the machinery worked: gates, work orders, registries, camera calibration, contours. And it was on working machinery that the real wall appeared. One photo covers twenty pixel-level parameters and seventeen millimetre-level ones. Sixty-four parameters — material, finish, wear, load, fastening — are not measured by any tool in the park. And I had no metric for "looks alike" in any version of the work. So "if everything had worked" would have produced the same outcome, only faster and cheaper.
Terms I use: the agent is the AI that writes code and carries out tasks; a shift is one chat session with the agent, bounded by context; a gate is a check at the start of every step that answers "allowed" or "not allowed"; a work order is a task to fix a violation that cannot be closed by promising.
2. How I work: five rules
This is the part that transfers to other people, so I put it before the story.
- Name the acceptance criterion before the work. Not after. If the criterion is not a number, the work cannot be finished or refused — only continued.
- A number comes from a record. Whatever the model says is a claim. A number is a number only if there is a file and a line behind it.
- A violation closes with a check, not a promise. Every violation gets a work order with a check command and a deadline. If the check does not pass, the order stays open and the next step is blocked.
- A rule has to stand in the path, not in the text. Text rules are forgotten inside one conversation. Reading with a receipt, a question at the entrance, a refusal at the action, and a review by the logs — that is what actually works.
- A tool nobody uses does not exist. Building is easier than adopting; the adoption has to be designed, not hoped for.
3. The context ends: a document, rules, and memory
The first problem was not about 3D. The model's context is limited, and the summaries it wrote lost details. Running the project in one dialogue was impossible.
Together with the model I made a primitive local document it was supposed to read in every new dialogue. Those dialogues later became sessions, and then shifts. The first rule was a backup: never change a file without a copy, copy in a separate folder, time in the name. The second was a handover: what is done, what is open, what is forbidden, where the source lives. The third was a summary read before work.
The rules were forgotten anyway. What worked was four steps: reading with a receipt (the rule files must be read to the last line in the current version, or no pass is issued); the rule as a question (a quiz of 13 questions, and the answer has to quote the question's own line); the rule as a refusal at the moment of action (a gateway checks the token, the answer mode, open violations, price); and review by the logs (detectors raise violations, and a violation closes only with a check).
The memory you cannot fix. There is a recorded experiment here. The client's memory is trimmed by size, not by count. When there were a hundred entries, about 59 KB, the agent saw the last five and a line saying "89 older memories omitted". The policy that followed: five to eight compact entries, two or three KB, and everything durable goes to files. Today the prompt again says forty-eight entries are hidden.
And one more thing: the client's system prompt, where the agent gets its rules, is not a file on disk. A law you cannot read as a file, you cannot check either.
4. Numbers come from records
The model named coordinates confidently. Checking by measurement produced three cases: a handset reported as "125 px" against measured 90.8; a body reported as "240" against 237.8; a post described as "narrow" against 42.3 px. The first can be called rounding. The third cannot: it was not an error, it was the absence of a measurement.
The rule became: a number without a record is not a number. Then the machinery: a log of turns, a log of violations, a log of work orders, a log of reads. Today those logs hold 31,554 turn lines, 5,060 violations, 4,577 work orders, 3,319 read records.
Lying became visible. The price was speed.
5. How to look without eyes
When you ask the model to "look", it does not see. It receives text and names coordinates. Putting the image itself into the agent's context costs money and gives no number.
So I built channels, one step at a time, and each step hit the limit of the previous one. First a brightness threshold — on the lock it outlined the wrong thing. Then the material region grown by groups of similar pixels — more accurate, more expensive. Then contrast edges, because the colour mask was only a hint of the region. Then a contour of segments on an upscaled image: the working photo was 960 by 720, one pixel there weighs 2.4 millimetres, and you cannot measure on that. Last came the refusal of a bounding box: a contour is presented as measured segments plus a human label, and a box is not a contour.
Crops. You can only measure in the right window, and a separate guard refuses to measure an element whose box touches the crop border. There was a case where the back edge of a plate sat 37 pixels above the frame and got "measured" on the cut edge. A measurable grid, a box and axes go onto the reference, and only then does a pixel become a millimetre.
The vision bridge. The accurate channel runs through the PlusVibe portal: portal address, key in a separate file, an accurate vision model, 3.4 and 20.37 rubles per million tokens. The image does not enter my context: text comes back.
Reading the photograph. The shot was decomposed into numbers: the sun's elevation 61.0 degrees, azimuth 120.88, status "derived", confirmed by two channels — astronomy from the image and photometry from the frame, with sign control at sunrise and noon. The shadow gives a direction of 300.9 degrees, but on one channel only. Focal length 693.4 pixels, camera tilt 0.0 plus or minus 0.007 pixels per pixel over five verticals out of six, depth ratio 0.46 plus or minus 0.05. The right side of the body resolved into three distinct edges: panel 703.49, seam 706.44, shell 714.46.
Three rejected material signs. The edge gradient gave 43.8 against 17–31 at the base; channel ratios and the share of specular pixels gave the same ranking as saturation. Material does not come out of a photograph: across the whole manual there is exactly one mention of steel and one of stainless, and aluminium, cast iron, brass and zinc appear zero times.
6. What one frame gives, and what it does not
I asked directly: can the pipeline give exhaustive information for modelling. The answer came with numbers: 102 parameters in 10 classes, 20 measurable in pixels, 17 in millimetres, and the remaining 64 — material, finish, ageing, load, fastening, wear — not measured by any tool in the park.
My conclusion changed everything: one reference cannot reproduce an object with full fidelity, and it should not try. The result goes to manual correction anyway, and services promising 3D from a photo are lying.
The acceptance criterion changed with it: not "proven", but "within tolerance, good enough for hand correction". The pipeline's role changed too: it is not the collector of data, it is the judge of channels.
7. A work order, not a promise
A violation would be recorded, I would promise to fix it, and that was the end. Next shift it happened again.
First came detectors over the logs — 41 classes today. Then it turned out a detector without closure is useless: it only accumulates a list. So the work order appeared: a check command and a deadline, closure only after the check passes. A word does not close a violation.
There is also a guard that verifies every detector is actually called: otherwise it stays silent, and that is the worst kind of failure. The price is a queue: at one point 29 open violations, and the next step blocked until they were cleared.
8. Departments, pipelines, and the machine
Tools appeared as pain appeared, with no borders. The departments formed in waves: the tool catalogue and the first departmental figures, then the test bench, stages and the complex passport, then the model cabinet and the board, last the lessons department.
A pipeline is a route of stages with a check at each. The plan pipeline carries a point from entry to acceptance and does not accept a verdict without a number. The reference pipeline decides what is even possible: one view gives proportions only, two or more give a metric, and acceptance requires the render to agree with the reference body by body.
A hole in the machine. The Blender bridge exposes 146 tools. The registry describes 18 of them — twelve percent. The other 128 have no recorded danger and no gate, and among them are sculpting, rigging, mocap, simulation, cloud rendering, and generation that costs money. The rule "a dangerous operation needs a check" holds for eighteen tools and fails for one hundred and twenty-eight.
9. Trees that turned out to be lists
I kept asking: is this a tree or are the questions asked all at once, where is the tree, why is there no tree in the pipeline. The answer was a flat list of 188 rows.
The tree files were lists: tools 152 nodes and 152 roots, documents 31 and 31, laws 85 and 85, predicates 22 and 22. After the repair, laws had 104 nodes and 19 roots, documents 298 nodes and one root, invalid nodes zero.
My requirement — never ask a question that cannot be answered — became a check: a node must point to a tool that is able to return a failure.
10. Radii: what an honest refusal looks like
The fillet shape was never obtained. Three methods: an angle estimator with a self-test of ten checks; a full pixel channel where one corner produced a number and three refused; a global fit of a rounded rectangle that gave 12.5, 25.0, 6.25 and 34.25 against true 12, 25, 6 and 34 — the box came from the registry while the outline was seven to nine pixels wider.
Real residuals: 5 to 27 pixels against 0.6 on synthetic data. After two failures I wrote a six-line refusal protocol instead of substituting a number.
Locking. The turn token with a limited lifetime: expire it and the entrance closes, while the only command able to refresh it was the one that got locked. The "answer only" mode locked the next turn. An open violation locked the repair tools. Three classes, one cause: the check and the means of repair were the same door.
Unresolved. A 19.3 millimetre discrepancy in housing height: the document gives 568.72, the outline 549.4. Still open.
11. The mask of an inscription: six attempts
I needed to read and measure an inscription on the device. I cannot trace it accurately by hand — that was my task for the agent, and it shifted the whole approach: the zone boundaries and the material are known, so the shape has to come from how the paint was applied.
Five attempts failed honestly: colour threshold, local contrast, black-hat, a blue mask overshooting, and Sauvola across all zones with masks covering 45–90 percent of the area. The sixth attempt came from my own observation: the paint is surrounded by black. The rule changed from colour to "a closed dark contour". Result: four components, 30.06 percent of the area, box 588.3 / 358.6 / 626.9 / 365.5.
The standard showed up too: the task is called ink extraction, with Sauvola and Niblack, a local threshold designed for "ink on uneven background". Not a service — two algorithms from a library.
12. Built is not the same as used
The turn log holds 2,213 lines with a command. Of 165 modules, 62 were called and 103 never were. The proportions speak for themselves: work orders 475 calls, file I/O 173, the turn gate 149, reading 65, the police 53, the bell 41, sessions 39 — and measurement 12, the crop-edge refusal 5, while contours, the grid, the single-view metric and vanishing points were zero.
In the Blender bridge, 191 calls in total. Of those, 134 were arbitrary Python inside Blender — seventy percent. Object creation twice, object listing seven times, scene description twice, checkpoints eight times. And arbitrary Python is the one tool the registry marks as dangerous. The checks stood at the doors, and I went through the window.
In the bridge there are 58 tool files, all of them imported on 25 August; the only trace of our own edit is a copy of a snapshot file.
Recipes existed: files from mid-October, a pipeline meant to pull them, code that turns a passed experiment into a project recipe. The word "recipe" never appears in the turn log.
13. Why the same mistakes come back
- A structure with no hook to the step. The tool exists; nothing forces a call. 103 of 165 uncalled; 128 of 146 undescribed.
- The check judges form, not meaning. The lint counts symbols and blocks, the gate counts coverage and answers; neither asks whether the work addresses the goal.
- Repair is locked by its own lock. Token, mode, open violation.
- Self-checking without an external witness. A detector could stay silently uncalled until a guard appeared.
- A rule living in text, not in the path. In a file of advice it was forgotten; the four steps worked.
- Memory trimmed by size. A hundred entries became five visible.
Plus the general one: the system grows faster than it is absorbed. In a month, 165 tools, 62 used, 18 described.
14. What I would do differently
The order should be the reverse of what I did: name what "looks alike" is measured by, then set up checks, then write tools. I started with tools and rules and got a month of work on something that cannot be verified.
A minimum kit: a copy before every edit; one handover file per shift; numbers only with a source; one work order per violation with a check; one turn log; one vision channel with a mandatory check; and the rule "metric first, safety nets after".
What is still not fixed: forgetfulness got smaller but did not disappear. In the same shift the agent appointed the "first problem" on its own without asking me; answered "I don't know" to a question whose answer was sitting in the files; and broke my own recorded rule about how the form is built. The agent still drifts off course.
One month, about $110, entries taking up to 23 minutes, a queue of up to 29 open violations, and more than a hundred tools busy with control rather than form. The complex ate the work it was built for.
The condition under which an AI cannot lie is simple and unpleasant: every claim must have a file behind it, every violation must have a check, and the goal must be a number before anyone starts building. Without that, you do not get a model — you get a very convincing opinion.
About me. I don't write code. I run an AI agent that does, and I keep it honest with copies, journals and checks — because the model has no memory, no eyes and no sense of price. I'm halfway through a 3D course (Super Blender, VideoSmile), so my modelling skills are ordinary; what I actually built here is the control system around them. Everything above is one month of work, a laptop in a village, and about $110.



