A new Recipes page at /recipes lets a cook paste a recipe, enter the… #7

Merged
cmoriarty merged 3 commits from osf/71-172-comparison-arm-parallel-scale into compare/parallel 2026-10-17 08:45:40 -04:00
Owner

What was done

  • A new Recipes page at /recipes lets a cook paste a recipe, enter the servings and choose Metric or US, and see it back scaled and converted, with each line that did not read shown beside its line number.
  • A recipe is read from plain text — a first line Serves N and then one ingredient a line, each a quantity (a whole number, a decimal, a fraction or a mixed number), an optional unit and a name — with a line that does not read reported by its line number while the ones that do are still read.
  • Scaling multiplies every quantity by the requested servings over the recipe's own, unrounded, and shows spoons, cups and unit-less counts in quarters and thirds and weights and other volumes as whole numbers from 10 up and one decimal below.
  • Converting turns amounts between Metric and US into the unit of their kind that keeps the number between 1/4 and 1000 (1,500 g shows as 1.5 kg), leaving an ingredient with no unit as it is.
  • Adding a recipe to the list gathers up to five; the same ingredient in the same unit is added up ignoring case and a plural s, the same ingredient in different units is listed once per unit, and the list is sorted by name.
  • The form keeps what the cook entered across requests, and every line and the list is HTML-escaped, including inside the hidden fields that carry the list.
  • The change is fully tested — unit tests for each part, page and route tests, and a browser test — and the project's CI passes; a judge opened the served page across all four states and passed it, after a single added CSS rule fixed the one layout defect (an oversized Servings field) found on the first pass.
  • Not done: the shopping list is carried only in the page's hidden form fields, not the database, so a full reload of /recipes empties it.

How to review

  1. Run the unit and route tests with npm test; if DATABASE_URL is unset the repository starts its own embedded Postgres, and every suite should pass.
  2. Install the browser once with npx playwright install chromium, then run the browser tests with npm run test:e2e; the three /recipes scenarios — opening the page, a doubled US recipe with one unread line, and a two-recipe list — should pass.
  3. Start the server with npm start and open http://localhost:3000/recipes; you should see one form with Metric chosen and "The shopping list is empty."
  4. Paste Serves 2, 200 g flour, a pinch of salt, 2 eggs, set Servings to 4, choose US and press Show recipe; expect 14 oz flour and 4 eggs with a red Line 3: a pinch of salt (no quantity), and the form keeping what you entered.
  5. Press Add to list, then add a second recipe (Serves 1, 2 eggs, Servings 1); the shopping list should then read 6 eggs and 14 oz flour.
  6. Read the code, starting with src/server.ts (the /recipes routes) and src/pages.ts (the page and its styles).

Code review

Reviewed scale-recipes-and-shopping-list against its proposal, specs, design and tasks: the four modules (src/recipe.ts, scale.ts, convert.ts, shopping.ts), the /recipes page and routes, the seven new test files, and the README/CHANGELOG entries. I hand-traced the quantity forms, the quarter/third and weight display rules including the pinned boundaries, the conversion ladder with the spec's exact factors, the list's name normalisation and unit ordering, the hidden-field round trip, and the escape handling; everything matches the specs, the commit carries no generated, cached or scratch files, and no code change was needed. All checks pass: tsc clean, 78 unit tests (including the pre-existing server tests) green, openspec --strict valid, Playwright lists the three new browser tests, and the release-notes CI script exits 0.

It found nothing to fix.

Tests

All 47 scenarios of scale-recipes-and-shopping-list have a tagged test.

The test lint found, in the run's tests on the last check:

Recorded, not decided

  • e2e/recipes.spec.ts:1 B7: no relative import: this file asserts on things it constructed itself, which is the measured 'asserted on my own mock' failure
  • test/recipes-page.test.ts:1 B7: nothing imported here looks like the module under test ('recipes-page')
  • test/recipes-server.test.ts:1 B7: nothing imported here looks like the module under test ('recipes-server')

Braid run

  • Workflow: Braid's OpenSpec flow, change scale-recipes-and-shopping-list (26 steps)
  • Issue: cmoriarty/braid-combined-test#4
  • Model: vLLM · qwen3.8-27b
  • Time: 1 h 17 m from start to this pull request, 1 h 22 m of it in the model
  • Tokens: 9.3M input, 60k output, 150k reasoning, over 235 model calls
  • Pre-flight estimate: fits, p50 197k / p80 286k tokens against a 394k-token step allowance
  • CI: passed its 6 jobs on ea3ec53184
  • Run: run_01M54SWRMP1TF0WA5K23BAWE0G

Opened by Braid.

## What was done - A new Recipes page at `/recipes` lets a cook paste a recipe, enter the servings and choose Metric or US, and see it back scaled and converted, with each line that did not read shown beside its line number. - A recipe is read from plain text — a first line `Serves N` and then one ingredient a line, each a quantity (a whole number, a decimal, a fraction or a mixed number), an optional unit and a name — with a line that does not read reported by its line number while the ones that do are still read. - Scaling multiplies every quantity by the requested servings over the recipe's own, unrounded, and shows spoons, cups and unit-less counts in quarters and thirds and weights and other volumes as whole numbers from 10 up and one decimal below. - Converting turns amounts between Metric and US into the unit of their kind that keeps the number between 1/4 and 1000 (1,500 g shows as 1.5 kg), leaving an ingredient with no unit as it is. - Adding a recipe to the list gathers up to five; the same ingredient in the same unit is added up ignoring case and a plural s, the same ingredient in different units is listed once per unit, and the list is sorted by name. - The form keeps what the cook entered across requests, and every line and the list is HTML-escaped, including inside the hidden fields that carry the list. - The change is fully tested — unit tests for each part, page and route tests, and a browser test — and the project's CI passes; a judge opened the served page across all four states and passed it, after a single added CSS rule fixed the one layout defect (an oversized Servings field) found on the first pass. - **Not done:** the shopping list is carried only in the page's hidden form fields, not the database, so a full reload of `/recipes` empties it. ## How to review 1. Run the unit and route tests with `npm test`; if `DATABASE_URL` is unset the repository starts its own embedded Postgres, and every suite should pass. 2. Install the browser once with `npx playwright install chromium`, then run the browser tests with `npm run test:e2e`; the three `/recipes` scenarios — opening the page, a doubled US recipe with one unread line, and a two-recipe list — should pass. 3. Start the server with `npm start` and open http://localhost:3000/recipes; you should see one form with Metric chosen and "The shopping list is empty." 4. Paste `Serves 2`, `200 g flour`, `a pinch of salt`, `2 eggs`, set Servings to 4, choose US and press Show recipe; expect `14 oz flour` and `4 eggs` with a red `Line 3: a pinch of salt (no quantity)`, and the form keeping what you entered. 5. Press Add to list, then add a second recipe (`Serves 1`, `2 eggs`, Servings 1); the shopping list should then read `6 eggs` and `14 oz flour`. 6. Read the code, starting with `src/server.ts` (the `/recipes` routes) and `src/pages.ts` (the page and its styles). ## Code review Reviewed scale-recipes-and-shopping-list against its proposal, specs, design and tasks: the four modules (src/recipe.ts, scale.ts, convert.ts, shopping.ts), the /recipes page and routes, the seven new test files, and the README/CHANGELOG entries. I hand-traced the quantity forms, the quarter/third and weight display rules including the pinned boundaries, the conversion ladder with the spec's exact factors, the list's name normalisation and unit ordering, the hidden-field round trip, and the escape handling; everything matches the specs, the commit carries no generated, cached or scratch files, and no code change was needed. All checks pass: tsc clean, 78 unit tests (including the pre-existing server tests) green, openspec --strict valid, Playwright lists the three new browser tests, and the release-notes CI script exits 0. It found nothing to fix. ## Tests All 47 scenarios of `scale-recipes-and-shopping-list` have a tagged test. The test lint found, in the run's tests on the last check: **Recorded, not decided** - `e2e/recipes.spec.ts:1` B7: no relative import: this file asserts on things it constructed itself, which is the measured 'asserted on my own mock' failure - `test/recipes-page.test.ts:1` B7: nothing imported here looks like the module under test ('recipes-page') - `test/recipes-server.test.ts:1` B7: nothing imported here looks like the module under test ('recipes-server') ## Braid run - **Workflow:** Braid's OpenSpec flow, change `scale-recipes-and-shopping-list` (26 steps) - **Issue:** cmoriarty/braid-combined-test#4 - **Model:** vLLM · qwen3.8-27b - **Time:** 1 h 17 m from start to this pull request, 1 h 22 m of it in the model - **Tokens:** 9.3M input, 60k output, 150k reasoning, over 235 model calls - **Pre-flight estimate:** fits, p50 197k / p80 286k tokens against a 394k-token step allowance - **CI:** passed its 6 jobs on `ea3ec53184` - **Run:** [run_01M54SWRMP1TF0WA5K23BAWE0G](http://openspecflow.internal.underthere.xyz/run/run_01M54SWRMP1TF0WA5K23BAWE0G) _Opened by Braid._
check: the code of fix-loop round 1, for the project's CI
All checks were successful
CI / Unit tests (pull_request) Successful in 1m2s
CI / Unit tests (push) Successful in 56s
CI / Release notes (pull_request) Successful in 10s
CI / Browser tests (pull_request) Successful in 1m1s
CI / Release notes (push) Successful in 13s
CI / Browser tests (push) Successful in 1m26s
ce08d5043c
cmoriarty force-pushed osf/71-172-comparison-arm-parallel-scale from ce08d5043c
All checks were successful
CI / Unit tests (pull_request) Successful in 1m2s
CI / Unit tests (push) Successful in 56s
CI / Release notes (pull_request) Successful in 10s
CI / Browser tests (pull_request) Successful in 1m1s
CI / Release notes (push) Successful in 13s
CI / Browser tests (push) Successful in 1m26s
to ea3ec53184
All checks were successful
CI / Release notes (pull_request) Successful in 13s
CI / Release notes (push) Successful in 10s
CI / Unit tests (push) Successful in 50s
CI / Browser tests (push) Successful in 1m0s
CI / Unit tests (pull_request) Successful in 1m8s
CI / Browser tests (pull_request) Successful in 1m3s
2026-10-17 08:28:24 -04:00
Compare
cmoriarty changed title from Scale a recipe, convert its units, and build a shopping list to A new Recipes page at /recipes lets a cook paste a recipe, enter the… 2026-10-17 08:45:20 -04:00
cmoriarty force-pushed osf/71-172-comparison-arm-parallel-scale from ea3ec53184
All checks were successful
CI / Release notes (pull_request) Successful in 13s
CI / Release notes (push) Successful in 10s
CI / Unit tests (push) Successful in 50s
CI / Browser tests (push) Successful in 1m0s
CI / Unit tests (pull_request) Successful in 1m8s
CI / Browser tests (pull_request) Successful in 1m3s
to ccfc5b7a93
All checks were successful
CI / Release notes (push) Successful in 10s
CI / Unit tests (push) Successful in 49s
CI / Browser tests (push) Successful in 1m1s
CI / Unit tests (pull_request) Successful in 1m11s
CI / Browser tests (pull_request) Successful in 1m4s
CI / Release notes (pull_request) Successful in 11s
2026-10-17 08:45:20 -04:00
Compare
cmoriarty merged commit ae7efd4758 into compare/parallel 2026-10-17 08:45:40 -04:00
cmoriarty deleted branch osf/71-172-comparison-arm-parallel-scale 2026-10-17 08:45:40 -04:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cmoriarty/braid-combined-test!7
No description provided.