Replaces the flat additive batch-size correction with a per-user
multiplicative pace factor learned from each account's own logged
roasts (shared/learn.js, GET /api/machine-profile), plus a lot-scoped
"last refine" auto-suggestion. Also fixes the reference data being
framed as "your own roasts" on a now-multi-user product, and
reclassifies the drying/Maillard sanity checks as informational since
they're algebraically derived from the DTR check rather than
independent (yellow = 0.56 x first crack, not entered separately).
Bug fixes found by an adversarial Opus review of the first pass:
- Unicode minus sign (U+2212) broke duration parsing against the
app's own generated refine-suggestion text
- Printed sanity-checks table still showed a bare pass/fail glyph for
the now-informational drying/Maillard rows
- Printed time-ledger box didn't show the pace multiplication step,
so it stopped reconciling by hand once pace != 1
- Field 6.4 (manual batch correction) was double-counted: excluded
from the learned-pace fit but added back after the multiplication
- Learned pace had no outlier rejection or hard clamp
- computeLedger had no test coverage
- Batch-size help copy overstated what the pace factor models (it's
a single blanket ratio, not conditioned on batch weight)
A follow-up Opus pass also caught the per-user profile cache
surviving logout/account-switch in a shared browser; fixed by
sweeping it alongside the existing plan-draft cleanup.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
- shared/ ports the worksheet's ledger math, time parsing, and reference tables
(cultivars/processes/roast-levels/machine bands) as browser-safe ESM, imported
by both the server and the browser so the arithmetic can't drift between them.
- server/prefill.js runs a zero-tool Pi Coding Agent SDK turn to extract page facts
from a bean product URL, then derives worksheet field IDs deterministically from
reference-data.js — the model never invents a first-crack anchor or a modifier.
- server/alog.js ports the Python alog_parser.py's format handling, including the
tokenizer-based Python-dict-literal-to-JSON conversion the real files need.
- public/ is the worksheet reproduced as a live HTML form: worksheet.css is a
verbatim copy of the paper worksheet's print CSS, print.js bakes values into
the print layout so the same DOM renders both on screen and on paper.
- Ledger math verified against both of the paper worksheet's worked examples;
alog parser verified against all 14 real logs in ref/roasts/.
Co-Authored-By: Claude Sonnet 5 <[email protected]>