Files
roast_command_center/README.md
T
snowspeederandClaude Sonnet 5 fedaf29847 Initial roast planner webapp: fillable worksheet, live ledger, curve, URL prefill, .alog reference curve
- 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]>
2026-07-29 15:41:35 -04:00

3.1 KiB

Roast Planner Webapp

A fillable, live-computing web version of the manual coffee roast plan worksheet (hope_roaster/roast-planner/manual-roast-planner.html), plus:

  • Prefill from a bean URL — paste a roaster's product page URL; the server fetches it and uses the Pi Coding Agent SDK (zero-tool, one-turn extraction) to pull out whatever it can find (cultivar, origin, processing, roast level), then deterministically maps that to worksheet field IDs using the same reference tables as the paper worksheet. It never invents a first-crack anchor or a modifier — those only ever come from the reference tables, keyed off what the page actually states.
  • Reference curve from an Artisan .alog — upload a real roast log (or browse a local library directory) to overlay its actual milestones/curve on the same SVG grid as your plan, dashed and in a different color.
  • Live ledger — the worksheet's time-ledger math (first crack, yellow, Maillard, development, drop, and the four sanity-check ratios) recomputes as you type, using the exact same arithmetic as the paper worksheet (verified against both its worked examples).
  • Print — bakes typed values into the print layout and reuses the paper worksheet's print CSS, so File > Print produces the same 2-page front/back sheet.

Run it

npm install
npm start        # http://localhost:8090 (set PORT to override)

Prefill requires a model configured via the pi CLI (~/.pi/agent/{models,auth}.json) — without one, /api/prefill returns 503 no_model rather than crashing. Everything else (the form, ledger, curve, .alog upload) works with no model configured.

Layout

  • shared/ — browser-safe ESM modules imported by both the Node server and the browser (served statically at /shared/). This is the single source of truth for the ledger math, time parsing, and reference data tables — never duplicate this logic in server/ or public/js/.
  • server/ — Express routes: /api/prefill, /api/alog, /api/alog/library[/:filename].
  • public/ — the static frontend: index.html (the worksheet as a form), worksheet.css (a verbatim copy of the paper worksheet's print CSS — port changes from there, don't hand-edit divergently), app.css (screen-only chrome + form-control styling), js/.

Where the reference numbers come from

shared/reference-data.js is ported from /Users/shane/dev/hope_roaster/roast-planner/manual-roast-planner.html's Step 1 (cultivars), Step 3 (processing), Step 4 (roast levels), Step 8 (machine bands), and Step 7 (sanity bands). If those tables change in the paper worksheet, port the change here too.

Known gaps (v1)

  • No automated test suite yet (the ledger math and .alog parser were verified manually against the worksheet's worked examples and all 14 logs in ref/roasts/, respectively).
  • Roastetta (roastetta.com) integration is intentionally out of scope — it needs a headed, Cloudflare-clearing browser and the operator's own credentials. Use the .alog file picker, or point ALOG_DIR at wherever the roastetta skill already downloaded files.