One system: post-roast observations (weights, colour, DTR, cup notes,
'one change next batch', disproof) now live on the uploaded roast
(actual_roasts.after, migration 011), edited on the roast detail view
with weights/DTR prefilled from the .alog itself. The planner's screen
section is removed (the print worksheet keeps its hand-fill copy), and
the lot 'last refine' suggestion reads the note from both the new home
and legacy plans, newest wins.
Every roast now downloads two ways: the untouched original .alog, and
an updated supplemental copy with the app's data written back as valid
Artisan fields (weight, beans, roastingnotes incl. the LLM review,
cuppingnotes incl. linked cupping score/flavors) — serialized as a
Python literal so Artisan's ast.literal_eval re-imports it.
Co-Authored-By: Claude Fable 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]>