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]>
Machines:
- roasters table + actual_roasts.roaster_id (migrations 009): per-user
machines with a default; uploads attach to the default roaster and are
reassignable from the roast detail view
- Learning is now per machine: /api/roaster-profile scopes to a roaster
(default when unspecified) and applies the user's override tweaks
(milestone temps, TP time, pace factor) on top of learned medians
- /roasters page: machine list + analysis report showing learned vs
applied values with editable tweaks, typical RoR, and a plain-language
list of the adjustments applied to plans; planner honors a manual pace
override; evaluations use the roast's own machine profile
Mobile header redesign:
- The planner's header tools collapse behind a single 'Tools ▾'
disclosure (dropdown card) at ≤720px, keeping the fixed three-row
mobile header with no wrapped or scrolling button rows; desktop
renders inline via display:contents (same DOM, same handlers)
Profile pictures:
- users.avatar (migration 010) + PUT/GET/DELETE /api/account/avatar;
client-side centre-crop resize to 128px JPEG; avatar shows in the nav
chip on every page; included in full backups
Co-Authored-By: Claude Fable 5 <[email protected]>
- user_gear table (migration 008) + GET/PUT /api/gear (brewer keys
validated against the taxonomy, grinders deduped/trimmed)
- /gear page: silhouette multi-select for owned brewers (autosaves) and
a grinder list; nav gains Brewing → Equipment
- Brews page: with gear configured, the picker shows only owned brewers
(plus the edited brew's method) with a show-all toggle; grinder field
suggests your grinders; empty-gear state links to /gear
- Included in full backups, per-user export, and the OpenAPI spec
Co-Authored-By: Claude Fable 5 <[email protected]>
Free-text recipe (bloom, pours, timings) distinct from tasting notes and
next-time notes: new brews.recipe column (migration 007), form textarea,
shown under the recipe summary in brew history, carried by Brew again,
included in backups and the OpenAPI spec.
Co-Authored-By: Claude Fable 5 <[email protected]>
Brewing:
- roasted_beans + brews tables; /beans (bean management with LLM URL
prefill) and /brews (silhouette brewer picker across immersion/
percolation/espresso, recipe fields, auto ratio, 0-10 rating, tasting
notes); bean remaining weight derived from logged brew doses
- Green inventory lot form also prefills from a product URL
Navigation/UX:
- Side nav is now generated from one definition in nav.js, grouped
Roasting / Brewing / account, consistent on every page
LLM:
- 'Ask the LLM' chat drawer on the planner (stateless /api/plan-chat)
grounded in the plan, computed ledger, learned pace, and a new
roaster-behavior profile aggregated from uploaded .alogs
(/api/roaster-profile: TP lag, phase RoR, median milestone temps)
- The profile also feeds roast reviews and the planner curve's fallback
milestone temps
API platform:
- User-generated bearer tokens (rpt_…) with account-page management;
token requests skip CSRF; hand-authored OpenAPI 3 spec at
/api/openapi.json rendered by self-hosted Swagger UI at /api-docs
- Full-database backup export/import (admin) + per-user data export
Co-Authored-By: Claude Fable 5 <[email protected]>
- New server/llm.js consolidates ModelRuntime + model selection: admin
setting (app_settings.llm_model) > LLM_MODEL/PREFILL_MODEL env > first
available; used by both prefill and roast evaluation
- GET/PUT /api/admin/llm lists configured models and stores the choice
(validated against the list; empty = auto; audited); admin page gains
an LLM section with a model picker
- All user-facing 'Pi agent' wording is now 'LLM'; no_model error message
no longer references the pi CLI
- /roasts table: Review column removed (review lives in the detail view)
Co-Authored-By: Claude Fable 5 <[email protected]>
- POST /api/roasts stores the original .alog verbatim (multiple per plan),
parses it server-side, and kicks off an async zero-tool Pi agent review
(grade, highlights, concerns, next-batch suggestions, plan-vs-actual)
- /roasts page: table of historical actual roasts with review summaries;
row detail renders the BT curve as SVG with the plan curve overlaid,
shows the full review, and offers original-.alog backup download,
re-evaluate, and delete
- Planner's Reference curve drawer gains a multi-file finished-roast
uploader that attaches to the open (synced) plan
- Failed reviews record the error on the row and are retryable via
POST /api/roasts/:id/evaluate (e.g. once a model is configured)
Co-Authored-By: Claude Fable 5 <[email protected]>
Ports inventory management and SCA-style cupping scoring from
hope_roaster: lot tracking with audit-logged consumption, cupping
sessions with server-authoritative scoring and a live radar chart,
and links from the planner (draw-from-lot, open-cupping-session).
Also fixes the Blend/Single-origin toggle layout, replaces tooltips
with an in-context "why" teaching layer, and stages the planner UI
into pre-roast vs. post-roast phases.