Preview review notes · 2 October 2026
TRIAL BALANCE sales page: what needs Tim before it goes public
An unattended session built this page. It's a noindexed preview on a
pages.dev address: no domain, no DNS, no production routes.
Every number on it was checked against the game's code or produced by a
script in pages/trial-balance/build/. Nobody has approved
it for publishing.
Blockers
-
GAME BUG
The guilty party is always the last option on the filing form.
partiesWithActivity()returns parties in creation order, andworld.jsadds the culprit last. I measured it on 100 months × 5 cases: 500 of 500. A player who notices can read the answer off the form. Fix in the game, for example by sorting the form's party list by name. The page doesn't mention it. - GAME BUG The free ledger gives away two of the four schemes. Invoice numbers in
world.jscome from fixed ranges: legit vendors #2100–2899, the ghost vendor #3300–3699, personal-expense fraud #4400–4699, the clean decoy #4700–4899. The ledger is free, so a player who notices can read the culprit off the memo column. The cycle-2 reviewer measured this on all 1,256 ghost-vendor and personal-expense cases in months 1–500: read the ledger, pull one 1h invoice, file, and it's 3★ at 3h every time, under the partner's line. That undercuts the page's central promise ("the paper costs hours"). Fix: draw every invoice number in a case from one shared range, then rerunnpm run simandnode build/ladder.mjs. Fix this before publishing. -
GAME DESIGN
Brute force works more often than it should. If you accuse each
party in turn, cite all of that party's entries and cycle through the
schemes, you solve 380 of 500 cases and earn 3★ on 115 of them, as
long as you start from the culprit's end of the list (
node build/brute.mjs rev). Two things make this possible: citing "all of this party's entries" is a free, complete citation whenever the culprit has only fraud entries, and the last filing is free. The page used to claim you can't guess your way through. That claim is gone. The page now says only that a wrong guess costs 5 hours. -
Arcade stage is
internal. Promoting it is your call. The page serves its own copy of the game at/play/, which will drift from the repo. To refresh it:cp -R ~/Programming/games/deduction/trial-balance/{index.html,styles.css,src} dist/play/, then redeploy. The hero demo imports/play/src/sim/*.js, so it refreshes too. Rerunnode build/check-page.mjsafterwards. - Nobody has played it. HANDOFF step 1 ("Tim plays the slice") is still open. The page claims no players, no timings and no feelings. It also speaks in your first person ("What I like…", "I ran them…", "I think that's a fair simplification…"), so read those lines and make sure you'd say them.
- MOEHR HOLDINGS LLC, your real company name, is case 5: "Voss's biggest client", and a fraud victim. It's in the game already, and the page prints it twice. Decide whether that's a wink you want on a public page.
- Accounting terminology. The casebook's SKIMMING ("taken out of the till before it was ever written down") is proven by the register tape, which did write it down. A CFE calls that cash larceny. The page says so openly in the accountants' section. Your options: keep that disclosure, or reword the in-game card and drop it.
Review items
- Case 5's brief says "a tighter retainer". It isn't one: 16h, the same as cases 1 and 4, with the most slack of any case. The page avoids the claim.
- On the default month (seed 7), case 5 draws round-trip, the same scheme as case 4. The "full casebook" finale repeats the previous case. The page lists this as a gripe. A one-line fix in the game is to exclude case 4's scheme from case 5's draw.
-
Visual bug: the "OUT OF BALANCE by $349.00" line on the
trial-balance card is clipped at the card's bottom edge at 1440×900.
See
build/shots-raw/desk-open.pngin the instance folder. -
The page writes the game's save. Solving case 1 in the hero
writes
trialbalance.v1(case 2 unlocked, case-1 stars), so/play/on the same origin opens on case 2. On the real arcade, which is a different origin, that save won't carry over. -
Clear-note bugs (from the red team):
- At Brightwater, which has no register tape, accusing THE REGISTER prints "the tape matches the books."
- A wrong-scheme filing can print "(SKIMMING is still on the table somewhere)", which names the answer.
-
window.__trialbalance.debugTruth()prints the answer in the console.
- Stale docs: the GDD and HANDOFF say case 1 is "off by $412.00". The amount is seeded. On seed 7 it's $349.00 (seeds 1–10 range from $313 to $598).
- THE BILL in case 3: par needs exactly the 3 bad invoices out of the merchant's 4. The only tell is the invoice-number range. The page says the partner's line "is computed with hindsight". Fix this together with the invoice leak: once the numbers stop leaking, nothing separates the decoy invoice, so a fair player only gets THE BILL in personal-expense cases on a 1-in-4 draw (case 3 every month, case 5 in 146 of 500 months).
- Phone: the full game has no responsive layout. The page demo works at 390px, and every CTA says "desktop or laptop".
How the page was checked
npm run sim: 726/726 (re-run 2026-10-02).-
build/ladder.mjs: the game's five bots over 100 months × 5 cases. -
build/brute.mjs [rev]: the brute-force probe in both orders. -
build/check-page.mjs: plays the hero with real clicks at 1366px and 390px, including a refusal, a wrong filing and a solve. It also confirms the save write and that/play/opens on case 2. No console errors, no horizontal overflow. -
Two test-reader cycles (10 personas, a red team and a skimmer audit).
Reports are in
08-test-readers/output/.