Added a /recipes page where a cook pastes a plain-text recipe, asks… #8

Merged
cmoriarty merged 3 commits from osf/72-172-comparison-arm-parallel-2-scale into compare/parallel-2 2026-10-17 09:52:56 -04:00
Owner

What was done

  • Added a /recipes page where a cook pastes a plain-text recipe, asks for a number of servings and Metric or US units, then either sees it scaled and converted or adds it to a shopping list of up to five recipes.
  • A pasted recipe reads as a Serves N first line, then one ingredient per line (a quantity, an optional unit and a name), and a line that does not read is reported with its number and reason while the other lines are still shown.
  • The recipe is scaled to the servings asked for — leaving the field empty keeps the recipe's own — with spoons and cups shown as the nearest quarter or third and weights and volumes as a whole number or one decimal.
  • Units are converted between Metric and US so the number stays easy to measure (1500 g shows as 1.5 kg), and an ingredient without a unit is left exactly as it is.
  • The shopping list adds up the same ingredient in the same unit, keeps the same ingredient in different units on separate lines, and sorts its lines by name.
  • The new logic and the page each have unit tests and the page has a browser test, the page is documented in the README with a release-notes entry added, and the unit tests and the project's CI were run and passed with a judge opening the page as a person would to confirm it works.
  • Not done: the Servings input renders as a tall, empty-looking box because of the shared input styling in the form — it is still labelled and its value is readable, but it takes up a large block of the page.
  • Not done: the app ships no favicon, so the browser logs one 404 for it when the page first loads — nothing is shown to a person and it has no effect.

How to review

  1. Run npx vitest run — it starts the bundled Postgres if DATABASE_URL is not set, and the new tests for reading, scaling, converting, the shopping list, the page, and the routes should all pass.
  2. Point DATABASE_URL at a reachable Postgres (as in the README), start it with npm start, and open /recipes — paste Serves 2, 200 g flour, 2 eggs, enter 4, choose US, and Show recipe should read 14 oz flour and 4 eggs while Add to list adds the same lines under the shopping list.
  3. Install the browser once with npx playwright install chromium, then run npm run test:e2e (with the same reachable Postgres) — the two recipes-page scenarios should pass among the rest, the first on the doubled US output with its reported bad line and the second on the list summing to 6 eggs and 14 oz flour.
  4. Read src/pages.ts and src/server.ts first for the form and its routes, then src/scale.ts and src/convert.ts for the two transforms the page is built on.

Code review

Reviewed the scale-recipes-and-shopping-list change (src/recipe.ts, src/scale.ts, src/convert.ts, src/shopping.ts, the /recipes page and routes, and its seven test files) against the proposal, delta specs, design and tasks. The implementation matches every spec scenario I traced by hand: the reader (mixed numbers, zero and zero-denominator quantities, one plural s on units, line numbering over blank lines), the twelfths rounding with ties to the smaller, the unit ladders (kg/l/lb from 1, tbsp from 1, cup from 1/4), the name-keyed shopping list with its unit ordering, and the page (routes placed before the / branch, form values kept, hidden list fields with six-decimal quantities, every user-controlled value escaped including attribute values). All spec scenarios are covered by tagged tests; tsc --noEmit, openspec validate --strict, the release-notes check, and playwright --list all pass; no generated, cached or secret files are in the commit. No fixes were needed.

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 (23 steps)
  • Issue: cmoriarty/braid-combined-test#4
  • Model: vLLM · qwen3.8-27b
  • Time: 1 h 5 m from start to this pull request, 1 h 21 m of it in the model
  • Tokens: 7.4M input, 47k output, 168k reasoning, over 183 model calls
  • Pre-flight estimate: fits, p50 196k / p80 286k tokens against a 394k-token step allowance
  • CI: passed its 6 jobs on 366f4cf03f
  • Run: run_01M54YCZZG0NMX5C9HPNRMZ5YD

Opened by Braid.

## What was done - Added a /recipes page where a cook pastes a plain-text recipe, asks for a number of servings and Metric or US units, then either sees it scaled and converted or adds it to a shopping list of up to five recipes. - A pasted recipe reads as a Serves N first line, then one ingredient per line (a quantity, an optional unit and a name), and a line that does not read is reported with its number and reason while the other lines are still shown. - The recipe is scaled to the servings asked for — leaving the field empty keeps the recipe's own — with spoons and cups shown as the nearest quarter or third and weights and volumes as a whole number or one decimal. - Units are converted between Metric and US so the number stays easy to measure (1500 g shows as 1.5 kg), and an ingredient without a unit is left exactly as it is. - The shopping list adds up the same ingredient in the same unit, keeps the same ingredient in different units on separate lines, and sorts its lines by name. - The new logic and the page each have unit tests and the page has a browser test, the page is documented in the README with a release-notes entry added, and the unit tests and the project's CI were run and passed with a judge opening the page as a person would to confirm it works. - **Not done:** the Servings input renders as a tall, empty-looking box because of the shared input styling in the form — it is still labelled and its value is readable, but it takes up a large block of the page. - **Not done:** the app ships no favicon, so the browser logs one 404 for it when the page first loads — nothing is shown to a person and it has no effect. ## How to review 1. Run `npx vitest run` — it starts the bundled Postgres if `DATABASE_URL` is not set, and the new tests for reading, scaling, converting, the shopping list, the page, and the routes should all pass. 2. Point `DATABASE_URL` at a reachable Postgres (as in the README), start it with `npm start`, and open `/recipes` — paste `Serves 2`, `200 g flour`, `2 eggs`, enter `4`, choose US, and `Show recipe` should read `14 oz flour` and `4 eggs` while `Add to list` adds the same lines under the shopping list. 3. Install the browser once with `npx playwright install chromium`, then run `npm run test:e2e` (with the same reachable Postgres) — the two recipes-page scenarios should pass among the rest, the first on the doubled US output with its reported bad line and the second on the list summing to `6 eggs` and `14 oz flour`. 4. Read `src/pages.ts` and `src/server.ts` first for the form and its routes, then `src/scale.ts` and `src/convert.ts` for the two transforms the page is built on. ## Code review Reviewed the scale-recipes-and-shopping-list change (src/recipe.ts, src/scale.ts, src/convert.ts, src/shopping.ts, the /recipes page and routes, and its seven test files) against the proposal, delta specs, design and tasks. The implementation matches every spec scenario I traced by hand: the reader (mixed numbers, zero and zero-denominator quantities, one plural s on units, line numbering over blank lines), the twelfths rounding with ties to the smaller, the unit ladders (kg/l/lb from 1, tbsp from 1, cup from 1/4), the name-keyed shopping list with its unit ordering, and the page (routes placed before the /<code> branch, form values kept, hidden list fields with six-decimal quantities, every user-controlled value escaped including attribute values). All spec scenarios are covered by tagged tests; tsc --noEmit, openspec validate --strict, the release-notes check, and playwright --list all pass; no generated, cached or secret files are in the commit. No fixes were needed. 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` (23 steps) - **Issue:** cmoriarty/braid-combined-test#4 - **Model:** vLLM · qwen3.8-27b - **Time:** 1 h 5 m from start to this pull request, 1 h 21 m of it in the model - **Tokens:** 7.4M input, 47k output, 168k reasoning, over 183 model calls - **Pre-flight estimate:** fits, p50 196k / p80 286k tokens against a 394k-token step allowance - **CI:** passed its 6 jobs on `366f4cf03f` - **Run:** [run_01M54YCZZG0NMX5C9HPNRMZ5YD](http://openspecflow.internal.underthere.xyz/run/run_01M54YCZZG0NMX5C9HPNRMZ5YD) _Opened by Braid._
check: the code of fix-loop round 1, for the project's CI
All checks were successful
CI / Unit tests (push) Successful in 1m9s
CI / Release notes (pull_request) Successful in 10s
CI / Unit tests (pull_request) Successful in 49s
CI / Browser tests (pull_request) Successful in 1m2s
CI / Browser tests (push) Successful in 1m1s
CI / Release notes (push) Successful in 10s
366f4cf03f
cmoriarty changed title from Scale a recipe, convert its units, and build a shopping list to Added a /recipes page where a cook pastes a plain-text recipe, asks… 2026-10-17 09:52:32 -04:00
cmoriarty force-pushed osf/72-172-comparison-arm-parallel-2-scale from 366f4cf03f
All checks were successful
CI / Unit tests (push) Successful in 1m9s
CI / Release notes (pull_request) Successful in 10s
CI / Unit tests (pull_request) Successful in 49s
CI / Browser tests (pull_request) Successful in 1m2s
CI / Browser tests (push) Successful in 1m1s
CI / Release notes (push) Successful in 10s
to 8ecc2a30c1
All checks were successful
CI / Browser tests (push) Successful in 1m0s
CI / Unit tests (pull_request) Successful in 1m10s
CI / Release notes (pull_request) Successful in 9s
CI / Browser tests (pull_request) Successful in 1m7s
CI / Release notes (push) Successful in 9s
CI / Unit tests (push) Successful in 48s
2026-10-17 09:52:34 -04:00
Compare
cmoriarty merged commit 7c20bafb2c into compare/parallel-2 2026-10-17 09:52:56 -04:00
cmoriarty deleted branch osf/72-172-comparison-arm-parallel-2-scale 2026-10-17 09:52:56 -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!8
No description provided.