senku. ai-transition / audit specimen
Template + worked hypothetical

Can one spreadsheet handoff become a system the owner can measure?

A two-week audit specimen for an established company whose orders move from email to spreadsheet to fulfilment by copying, memory and follow-up.

Unaudited template

The audit design below is ready to use. The worked numbers are invented and labelled H1. No client has bought or run this audit. The code-legibility proof later on this page was run once on our own system.

DAYS 1โ€“3 freeze 20 orders observe each touch record exceptions DAYS 4โ€“8 structured intake rules + queue human exceptions DAYS 9โ€“10 replay same 20 force 4 failures owner decides the spreadsheet stays available throughout no cutover is required to learn whether the intervention works
The specimen is bounded by one handoff and one frozen case pack. A broader transformation is a later decision.

The owner commissions one answer

Decision: fund an incremental replacement, repair the current process first, or stop. The sponsor must be the owner, CEO or board-mandated managing director. The process owner supplies access and facts; they do not control the verdict.

Boundary: one order type from first complete email to a fulfilment-ready row. Payroll, customer messaging and the fulfilment system remain outside the audit.

Before: freeze the evidence

Select 20 consecutive recent orders before building anything: 12 routine, four incomplete, two duplicates and two later changed by the customer. Keep the source email, spreadsheet history and final accepted record for each case. Use timestamps, screen capture or system history as evidence.

MeasureStartStop / test
Elapsed timecomplete emailaccepted row
Human touch timetimer startsactive work ends
Reworkfirst entrylater corrections
Exceptionsall 20human decision needed
Traceabilitysample a fieldsource + actor found
Recoverydelete a copyrestore verified state

The intervention

Build a narrow shadow path: a structured intake record, deterministic validation for required fields and duplicates, a work queue, and an append-only event log. An AI may extract proposed fields from email, but a person accepts exceptions. Every accepted field retains its source, actor and time. The existing spreadsheet remains the recoverable system of record.

Replay the frozen 20 cases without changing their inputs. Then force four faults: missing customer ID, duplicate order, AI extraction unavailable, and queue worker stopped. Each must refuse, route to a named human, or recover without silently losing an order.

After: the same ruler

Use the same definitions and case pack. Publish every case, including regressions. Report medians plus the slowest case; a fast routine majority cannot hide a failed exception. The handoff includes the evidence pack, runnable fault checks, rollback steps, named daytime owner, 2 a.m. escalation path and a recommendation with a stop option.

Worked H1 exampleBeforeAfter
Median elapsed time47 min11 min
Median human touch12 min4 min
Orders corrected later5 / 202 / 20
Field source found9 / 2020 / 20
Forced faults contained1 / 44 / 4

H1 is hypothetical. These numbers demonstrate the completed report's shape. They are not a forecast, benchmark or client outcome.

When the audit fails

Five honest failure modes and the verdict they trigger
  • No stable boundary. Orders cannot be isolated from pricing or fulfilment. Stop and map the dependency before proposing a build.
  • No trustworthy baseline. Missing histories make before/after unknowable. Report observability as the first intervention.
  • Exceptions dominate. The shadow path increases handling or error. Keep the spreadsheet and publish the regression.
  • AI adds no value. Rules handle the work as well or better. Ship rules only; do not manufacture an AI claim.
  • Nobody owns 2 a.m. A fault has no named response and escalation path. Refuse production cutover.

The proof behind the method

The specimen above has not met a client yet. The following before-and-after did run on a system we own: one source file whose cross-file claims had become unreadable to a machine.

LINE ANCHOR CONTENT ANCHOR sync.js:384 @"function appendEntry(" line 384 holds } found, exactly once, wherever it now sits CANNOT BE CHECKED silently false the moment anything above it moves CHECKED EVERY RUN must occur exactly once absent or twice is a failure positions move. content does not.
Real citation, real file. Hours after this was measured, an edit in the other repo moved appendEntry from line 135 to 136. The anchor followed it.

Why the hand fix did not hold

The commit at 17:31 corrected nine of these by re-reading every cited line, which is as careful as a person gets. Read back the same evening, several were false again. Anything inserted above a cited line moves it, and the comment goes on looking right.

The costly one pointed the other way. A watchdog that wakes Oleg's phone keeps its own copy of this script's verdict words, documented as read verbatim off two named lines. Those lines now hold an unrelated remark about daemons. Anyone checking whether the copy was still correct landed nowhere.

What changed, in one table

Same instrument at both ends, run on the script and the two files that consume it.

MeasuredBeforeAfter
Claims about other files4647
Line numbers asserted650
Claims a machine can verify047
Stale pointers in consuming code3 of 40 of 4
Consumers named in the file03

The claim count rose by one. Two citations that asserted several positions at once became one anchor each, and two naming adjacent lines of one crash handler became a single anchor. Nothing was deleted to move a number.

What the checker has to reject

A guard is worth what it has been seen to refuse. Each of these is forced against a fixture through the shipped command, and the whole set runs in 17 named cases.

FIVE WAYS A CITATION IS REFUSED Anchor absent the thing cited is not there Anchor occurs twice it identifies nothing Still a line number no machine can verify it Cited file missing there is nothing to check Bare filename, several matches unfollowable, and looks precise EXACTLY ONE MATCH the only state that passes, re-verified on every run 17 CASES
Every row was forced red against a fixture before the checker was believed.
The instrument was the first thing found broken

The checker searched two directories, one of which contained the other, so every local file was found twice and condemned for matching two files that were the same file. It manufactured the fault it reports.

Repairing it moved the headline split from 10 and 27 to 19 and 18. The earlier pair is absent from the before column above, because it was never a measurement. A regression case now pins both directions: a name matching one file must resolve, and a name matching two genuinely different files must still be refused.

Then it fired for real, the same evening. Someone working in the other repo renamed an argument, so one anchor stopped matching. The check went red on the next run and named the exact text that had gone. Two anchors in files that also moved kept resolving, which is the whole difference: one pointer broke loudly and the rest tracked the change in silence. Under line numbers all three would have gone quietly false and the suite would have stayed green.

Who breaks if I change this

The second question an agent cannot answer by reading. This script exports seven symbols and nothing anywhere imports it, because loading it runs the whole audit. Its real interface is a command line and an exit code, held by one caller that pages a phone.

52 FILES NAME IT 3 CAN BREAK a watchdog spawns it a library copies a constant a checker reads it DECLARED, AND GATED 49 CANNOT prose, comments, a log 340 lines of them wrong costs nothing counted, never gated the file now names its three, and a check refuses when the lists differ
A first version called 16 files consumers by treating any quoted string as code. Sixteen is a blast radius nobody believes.

What this does not show

It is one measure of one file, on a codebase we wrote. It says nothing about what your system would score, because it has never been run on one.

Nothing here improves the program. No verdict, no probe and no behaviour changed. The file grew by 134 lines, nearly all of it comment, so the legibility was bought with characters. And nothing schedules these two checks: they fail inside a test suite that runs when a person runs it, which is the same footing as the 354 cases that were already there.

Copying it

The repository is private, so here is the whole method. It needs no library and took a few hundred lines.

The format, and what a checker must do with it
path/to/file.js @"const ENTRY_RE ="
  • Resolve the path. A bare filename that matches several files is refused, even when only one exists today. Guessing is what makes the next collision silent.
  • Count the anchor in that file. Exactly one occurrence passes. Zero is a false claim. Two or more identify nothing.
  • Refuse a surviving line number. Otherwise the old form quietly stays.
  • Fail loudly when a file cannot be read. A checker that skips what it could not open reports green for work it never did.
  • Force each refusal against a fixture before trusting the green run.

Choose anchors a rename would break honestly: a declaration, a signature, a distinctive string. Anchors sitting inside quoted code need characters your own quoting survives.

Corrections and questions go to oleg@mlkv.org. If something on this page is wrong, it gets fixed here with the mistake left visible.