Skip to content
team banzai

tech demo · software · legacy

Rebuilding a software's documentation by reading its code, exam included

We gave a system the source code of DOOM, changed four numbers behind its back and asked it to document how it works. It caught all four: it reported the changed value, with the exact line as proof, while the documentation humans have written about DOOM for thirty years still says the old one.

And so you don't have to take our word for it, the game runs right here, in your browser, compiled from that same changed copy. You open a door and a stopwatch measures how long it waits before closing: 3 seconds, the ones the docs claimed, not the usual 4.3. The proof stops being read and starts running.

Pick a system your company depends on: the ERP installed in 1998, the program that runs payroll, the one that decides which orders go through. It works. But the person who wrote it left years ago, the manual in a drawer describes a version from three overhauls ago, and nobody dares touch it because nobody fully knows what it does inside. The knowledge isn't lost: it's written, line by line, in the code. Only nobody reads it.

The capability we test here is exactly that: rebuilding how a system works from the real code, not from its manuals, and proving it isn't making it up. We show it with DOOM because its code is public, under a free licence, and anyone can check what we claim. The case is DOOM; the pattern works for your ERP.

And since documenting isn't one single thing, we generate four documentations from the same reading of the code, each in the format a different team uses: the technical one for whoever will maintain it, the functional one for the business analyst, an agile backlog of user stories for a Scrum team, and the plain manual for whoever just uses it. All four are right below the game, and you can open and download them.

The same code, running: time the gotcha

We don't show the code on one side and the game on the other: the engine below is compiled from the code we documented. Start it, open a door with the spacebar and watch the stopwatch top right. It isn't painted: it measures the engine's own clock (35 steps per second) between the door finishing its opening and starting to close. Switch between the usual copy and ours with the button, and you'll see the count change.

GPL engine · webassembly

DOOM, from our copy

The engine runs in your browser, compiled from the code with the four changes. It only downloads when you hit start (about 30 MB); nothing heavy loads before that.

build monitor
150 tics = 4.29 s — what the Doom Wiki and id Software's public code say for a normal door's wait.
105 tics = 3.00 s — what our docs said after reading the changed code. With that build loaded, the clock measures exactly that.
id Software's DOOM engine (GPL-2.0), compiled to WebAssembly from our copy with the four mutations. Game assets: Freedoom Phase 1 (BSD licence). Lazy-loaded, only on start. On mobile you get touch controls; the keyboard goes to the canvas when you tap it.

The four documentations, one per team

This is what the system produced, and it is the point of the demo: the same reading of the code, told four ways, each in the format a different team already uses. The technical one for whoever maintains the code, the functional one for business and QA, the agile backlog for a Scrum team, and the manual for whoever just plays. That is the thesis: the same knowledge, in the format your team uses.

Every claim with a number carries its file and line: click any and you open id Software's public code at that exact line. You'll see the usual value (150, not 105), because GitHub has the public code and here we document our copy with the four numbers changed. That difference is exactly the experiment, and further down we tell you how we set it up.

The door cycle, generated by reading the code in front of it. Every number carries its line and its confidence grade; no value is claimed that isn't on a line that was read.

Time and speed constants

VDOORSPEED = FRACUNIT*3 p_spec.h:364. With FRACUNIT = 65536, that's 3 map units per tic for the normal door. · high confidence

VDOORWAIT = 105 tics p_spec.h:365. At 35 tics per second doomdef.h:122, that's 105/35 = 3.00 seconds of wait at the top. · high confidence

Method note: VDOORWAIT and VDOORSPEED aren't checked against the Doom Wiki (which may reflect another build); they're checked by reading p_spec.h in this tree and, if wanted, by timing the door in the binary compiled from this code. That's exactly what the stopwatch above does.

State structure: vldoor_t

Defined at p_spec.h:343-360. The direction field is 1 (rising), 0 (waiting at top) or -1 (lowering); on reaching the top, a normal door goes to direction = 0 and starts the counter topcountdown = topwait p_doors.c:182.

State machine: T_VerticalDoor

The "thinker" that runs once per tic p_doors.c:63 branches by direction: rising, it moves the plane toward the ceiling p_doors.c:168; waiting, it decrements the counter and, on reaching zero, orders the close and plays the close sound p_doors.c:81; lowering, if something crosses it, it reopens instead of crushing p_doors.c:151.

Constants outside the door (part of the exam)

Bullet damage: damage = 7*(P_Random()%3+1) p_pspr.c:633, i.e. 7, 14 or 21 per hit. Clip: clipammo[am_clip] = 15 p_inter.c:59, a clip gives 15 bullets (cap 200).

Safe change points

I want to change…I touch…Blast radius
Door wait at the topVDOORWAIT p_spec.h:365every door with topwait = VDOORWAIT
Door speedVDOORSPEED p_spec.h:364normal door; the fast ones use VDOORSPEED*4 and scale too
Bullet damagemultiplier at p_pspr.c:633pistol and chaingun, both via P_GunShot
Bullets per clipclipammo[0] p_inter.c:59clip pickups and starting ammo

Declared uncertainty

How far a door rises in absolute units depends on the level geometry, not on a constant: you can't claim a fixed height without a specific map. Only the wait at the top (VDOORWAIT) is a fixed, quotable time in seconds.

the four sets of documentation, as pdf · in the format your team already knows
Technical the arc42 template, the standard for software architecture documentation. For whoever maintains it. Download PDF · 256 KB
Functional a requirements spec to ISO/IEC/IEEE 29148 with acceptance criteria in Gherkin. For business and QA. Download PDF · 164 KB
Agile backlog user stories with Gherkin criteria and MoSCoW priority. CSV importable to Jira + PDF. For a Scrum team. Download CSV · Jira Download PDF · 170 KB
Manual Microsoft Manual of Style, the one behind user manuals. For whoever uses it. Download PDF · 104 KB

How we do it: we change the exam without telling it

There's a trap to deal with before we start, and we say it out loud: DOOM is probably the most dissected program in history. There are whole books about it, and any modern AI knows it by heart. So asking it to "document DOOM" proves nothing: it recites it back. The good question isn't whether it knows DOOM, it's whether it documents the code in front of it or recites what the Doom Wiki says.

To find out, we changed four numbers in the code behind its back: how long a door waits before closing, how fast it moves, how much damage a bullet does and how many bullets a clip holds. Four numbers, changed in place, without telling it. Then we asked it to document how all of that works.

It's the teacher's trick of changing a number in the question to see who read and who copied from the book. Say the new number, you read the code. Say the book's number, you copied. And the nice part is that it checks itself: every claim in the doc carries its file and line, and the marker goes to that line to see whether the number is really there.

The result, with the trick in plain sight: world, change, docs

Like a magician's audience that does see the trick: for each number, three columns. What the world says (the Doom Wiki and id Software's public code), what we changed in secret, and what the generated docs ended up saying. Your eye jumps on its own: the docs match what we changed, not what the world says.

Door wait at the top p_spec.h:365
world150 tics · 4.29 s
we changed105 tics · 3.00 s
the docs said105 tics · 3.00 s
true to the code
Door speed p_spec.h:364
worldFRACUNIT*2 · 2 u/tic
we changedFRACUNIT*3 · 3 u/tic
the docs saidFRACUNIT*3 · 3 u/tic
true to the code
Damage per bullet p_pspr.c:633
world5, 10 or 15
we changed7, 14 or 21
the docs said7, 14 or 21
true to the code
Bullets per clip p_inter.c:59
world10 bullets
we changed15 bullets
the docs said15 bullets
true to the code

The real code, with the line lit up

You don't need to know C. Click a claim and it jumps to id Software's real file with the line that proves it lit up in amber. It's the same public code the citations link to: you'll see the usual value there (150, not 105), because GitHub has the public copy and we documented our changed one. That difference is exactly the experiment.

linuxdoom-1.10 / p_spec.h p_spec.h:364-365 · ver en GitHub ↗
    int             topwait;
    // (keep in case a door going down is reset)
    // when it reaches 0, start going down
    int             topcountdown;
    
} vldoor_t;



#define VDOORSPEED		FRACUNIT*2
#define VDOORWAIT		150

void
EV_VerticalDoor
( line_t*	line,
  mobj_t*	thing );

Highlighted with Shiki at build time, over the real C file. The line numbering matches the GitHub link.

the marker's tally output: evaluacion/resultado.json

4/4

gotchas caught: it reported the changed value, not the usual one, in all four

87/87

traceable citations: all 87 file:line references across the three docs point to a real line

0/4

negative control: docs that recite the usual values score zero, the instrument knows how to fail them

2/3

docs with confidence grades and an uncertainty section (the user manual leaves it out on purpose)

The negative control is what separates a test from a trick: we fed the marker a set of docs that recite the usual values, and it failed them on all four. If the instrument couldn't give a zero, passing would mean nothing.

Take it: the method, not our word

What we've done here you can do yourself with any documentation written by an AI. We leave you the tools: the plain-language checklist, the marker we used to score, and the four sets of documentation already typeset, each in its field's standard format.

The checklist for auditing AI docs

Nine common-sense checks, in plain language, that turn "trust me" into "I'll look myself":

  1. Every claim cites its source (no citation, doesn't count).
  2. The source really says that (you go and check).
  3. A change made behind its back gets caught (the exam-question trick).
  4. The marker knows how to fail (if it always passes, it's worthless).
  5. Declares what it doesn't know · separates fixed from variable · separates fact from inference · speaks the reader's language · is reproducible.

The marker, open

The same corrige.py that produces this page's tally: it goes to each cited line, checks the number by hand and decides with no judgement of its own. We publish it with the mutations and the reproducible report, so you can run it. It's heuristic, not a semantic parser, and we say so: its two false negatives are in "the caveats".

The marker (public repo)

repo link as soon as it's published

The caveats

What this first version doesn't prove yet, said plainly.

The model knows DOOM and knew it was being examined. Whoever wrote the docs had the changed code in front of them and also knows DOOM. Reporting the new values proves it read the code (had it recited, it would have written 150), and the marker measures that objectively. But the stronger test is blind: give it only the code, without telling it what was changed. That's next.
It's a slice, not the whole engine. We tested one door and three constants, not all of DOOM. Enough to validate the method; not yet "document all of DOOM".
The stopwatch times the copy, it doesn't audit the model. The clock above proves the binary compiled from our copy behaves as the docs said (3 s, not 4.3). That's the dynamic check that was missing. What it doesn't do is prove the model didn't already know the answer: that's what the blind exam in the first caveat is for.
The marker is heuristic, not infallible. It works by keywords plus contrast context, and its first version had two false negatives: it counted as "recited the old value" a sentence that mentioned the old value to warn that it isn't that one ("should be ~3.0 s, not ~4.3 s"). It was fixed by detecting the negation and validated with the negative control, but a contrived text could in theory fool it. Said and done.

And in your company?

Swap DOOM for what actually keeps you up at night: the ERP nobody dares migrate, the payroll program only the person who left understood, the business rules buried in a procedure nobody has reread. The knowledge is still there, written in the code. This pulls it out, tells it for whoever maintains it, whoever decides and whoever uses it, and leaves the exact line as proof it wasn't made up.

If this sounds like a problem of yours, get in touch and we'll talk it over. No fuss: we'll tell you whether it can be done or not.

What it's built with, no inflation. The documentation was written by a language model reading the code: that's the part that drafts and connects. But what decides pass or fail isn't the model: it's a deterministic marker in Python that goes to each cited line and checks the number by hand, with no judgement of its own. The model proposes; the marker, which has no opinion, verifies. The four mutations are deterministic patches over the code, reproducible byte for byte, and the 87 citations resolve against the real file. The game is id Software's GPL engine compiled to WebAssembly with Emscripten; the stopwatch reads the engine's own clock (our patch, published with the fork), it doesn't simulate it.

Licences and attribution

This demo exists because id Software released the DOOM source. Thank you.

The DOOM engine is id Software's, released under the GPL-2.0 licence. The code we show and the code we compile to WebAssembly come from github.com/id-Software/DOOM, commit a77dfb9, tree linuxdoom-1.10, via the doomgeneric port. Our copy with the four mutations and the stopwatch patch is distributed under GPL-2.0 too, as that licence requires. The game assets are Freedoom Phase 1 (BSD licence). DOOM is a trademark of id Software; this is not endorsed by id Software or ZeniMax.

Can you use this? Our text and analysis on this page are published under a CC BY 4.0 licence: use them citing the source, Team Banzai (team-banzai.com). The DOOM code keeps its GPL-2.0 licence.

← All tech demos