Public: anyone can read this; the crew can change it.

Migrated from github.com/Trevato/SO-ARM100

Cited sources in the care app: every target, reminder and stage links to a trusted reference (extension and peer-reviewed first); a Learn page per plant #627

Merged opened this in answer to

Check · Review · Land done · Live — Landed; nothing deploys from this branch, so this is the end of its path.

Merged

The care page now cites its sources, and there's a Learn page for spinach at `/care/learn`. The care tests pass (31, including a new one for the sourcing rules). `tsc` reports no errors in the care files, but it does report errors in other files (`hops.ts`, `stations.ts`, `ui/*.js`), which I didn't touch. I didn't run `bun scripts/design-lint.ts`: it doesn't exist at that path from the so101 direc…

shipped merged

opened this

The care page now cites its sources, and there's a Learn page for spinach at /care/learn. The care tests pass (31, including a new one for the sourcing rules). tsc reports no errors in the care files, but it does report errors in other files (hops.ts, stations.ts, ui/*.js), which I didn't touch. I didn't run bun scripts/design-lint.ts: it doesn't exist at that path from the so101 directory, and I didn't look for it elsewhere. I also didn't open the running page to look at it.

  • Data: spinach.json has a references table with the seven verified sources under your ids, each with its kind, an accessed date, topics and a one-line "covers". Sources are attached to light DLI and the long-day bolting warning, the timeline, the stage bands and the reminders.
  • Profile checks: parseProfile rejects a source id that doesn't resolve, a non-https URL or an unknown kind.
  • Care page: each target range, reminder and the light/timeline line carries a superscript. Tapping it opens a card with the title, publisher, kind, the exact claim and a "Read" link that opens in a new tab. A value with no source shows "grower consensus (unsourced)" instead. Reminders have a "why" line shown with their source, for example "Small reservoirs drift". There's a "Learn more" link at the bottom of the Metrics text.
  • Learn page: the sources are grouped by light, nutrients, climate, timeline and problems. Extension comes first, then peer-reviewed, grower and vendor.
  • Test: every source id resolves, every URL is https, the unsourced label renders, and each Learn section is ordered by trust.

Judgment calls:

  • Top-off and change cadence, EC, seedling pH and air temperature, humidity and the rest of the unsourced list are left unsourced rather than stretched to fit a source.
  • I gave Rise Gardens no claim, so it only appears on the Learn page.
  • Sensor prices and the heat-mat guidance aren't in the profile, so they're not labelled anywhere yet.
  • The 24-hour "Light ran" reminder cites Hydrobuilder's 10–14 h of light.
  • Other plant profiles still load. Any value they leave without sources shows as unsourced.

Closes #626

commented

The care page now cites its sources, and there's a Learn page for spinach at /care/learn. The care tests pass (31, including a new one for the sourcing rules). tsc reports no errors in the care files, but it does report errors in other files (hops.ts, stations.ts, ui/*.js), which I didn't touch. I didn't run bun scripts/design-lint.ts: it doesn't exist at that path from the so101 directory, and I didn't look for it elsewhere. I also didn't open the running page to look at it.

  • Data: spinach.json has a references table with the seven verified sources under your ids, each with its kind, an accessed date, topics and a one-line "covers". Sources are attached to light DLI and the long-day bolting warning, the timeline, the stage bands and the reminders.
  • Profile checks: parseProfile rejects a source id that doesn't resolve, a non-https URL or an unknown kind.
  • Care page: each target range, reminder and the light/timeline line carries a superscript. Tapping it opens a card with the title, publisher, kind, the exact claim and a "Read" link that opens in a new tab. A value with no source shows "grower consensus (unsourced)" instead. Reminders have a "why" line shown with their source, for example "Small reservoirs drift". There's a "Learn more" link at the bottom of the Metrics text.
  • Learn page: the sources are grouped by light, nutrients, climate, timeline and problems. Extension comes first, then peer-reviewed, grower and vendor.
  • Test: every source id resolves, every URL is https, the unsourced label renders, and each Learn section is ordered by trust.

Judgment calls:

  • Top-off and change cadence, EC, seedling pH and air temperature, humidity and the rest of the unsourced list are left unsourced rather than stretched to fit a source.
  • I gave Rise Gardens no claim, so it only appears on the Learn page.
  • Sensor prices and the heat-mat guidance aren't in the profile, so they're not labelled anywhere yet.
  • The 24-hour "Light ran" reminder cites Hydrobuilder's 10–14 h of light.
  • Other plant profiles still load. Any value they leave without sources shows as unsourced.
commented

I added the steward's six references to the spinach profile and corrected the advice they flagged. I ran only the care tests, which pass. I didn't run the tsc --noEmit type check cleanly: it printed errors in src/ui/zone-notes.js, src/ui/zone-notes.test.ts and src/visitor-counts.ts, files this change doesn't touch. I haven't looked at the care or Learn pages in a browser.

References. cornell-gpn-2016 was already in the profile. I reworded it to the Mattson paper and widened its topics. The five others are new: uky-hydro-lettuce, osu-root-zone, uga-c1304, kaska-2024 and vonrosen-2022. The von Rosen thesis is listed as peer-reviewed, because the reference kinds have no "thesis" value. The three spinach papers carry no "lettuce data" label.

Corrections.

  • Germination nutrients and light: The bottom-water reminder now says seedlings are fed from day 0 (100–150 ppm N, tagged lettuce data). The light reminder says sprouts need light right after sowing (at least 50 µmol/m²/s). The moisture reminder cites sub-irrigation of rockwool.
  • Heat mat: A new seedling reminder says to keep germinating cubes at room temperature with no heat mat. It cites the three spinach germination sources.
  • Pump: The pump reminders now read "running continuously" and cite the NFT flow figures from the Kentucky publication. They note that an on/off cycle is unsourced. I found no pump schedule or "15 on / 15 off" text in the repo, so there was nothing to change a default on.
  • Top-off and full-change: Both keep their cadence, and their reminder text says it is grower consensus, with Ohio State's "measure daily, discard when problems arise" beside it.
  • Other stated values now sourced: The profile now cites pH, EC and water temperature (Ohio State and Kentucky), air temperature (UGA and Cornell), transplant timing (UGA and Cornell) and the Pythium risk to baby-leaf spinach (Cornell).

Reminder cadences and tests. I changed these to match Ohio State, and I changed the tests that pinned the old cadences:

  • Measuring pH, EC and water temperature is now daily (24 h), and 12 h in a tower.
  • Probe calibration is weekly (168 h).
  • The transplant check says "3–4 true leaves".
  • I updated the expected values in care.test.ts to match, because the old ones encoded the unsourced figures.

I didn't read the three papers still marked "to read", so none of them is added.

🤖 Generated with Claude Code

commented

The Learn page now opens with a "Fundamentals: the biology from first principles" section, ahead of the per-topic reference lists. The care tests pass (31 of 31), and tsc shows no errors in the care files. I haven't looked at the page in a browser.

  • Week one: the seven steps run in the steward's order, headed "Week one (about 3.5 h)". Each step shows its kind and estimated minutes, with a link for each item.
  • Week two: the six readings follow the week-one steps, each linked.
  • Optional, not checked: the Michigan State DLI and VPD pages and the two books (Resh, Taiz & Zeiger) are listed by name only, with no links. I had no URLs for the Michigan State pages, so those two are names only.
  • Where it lives: the path is data in a new module, src/care-fundamentals.ts, rendered by renderLearn in src/care-sources.ts.
  • Test: care.test.ts now checks that "Week one" comes before "Week two" and that the unchecked block is present.

The fundamentals list does not draw on the profile's references, so none of these links appear as footnote cards on the care page.

🤖 Generated with Claude Code

commented

The preview's one failing test was a timeout, not a bug in the care changes. I raised the test's limit and pushed, but I haven't seen it pass under full-suite load.

The failing test was "on the fake bus there is one line per joint" in bench/limits-sweep.test.ts. It runs the arm sweep twice and had a 30 s limit. Run alone here, it passes but takes about 24 s. In the full 172-file suite it went over 30 s.

I changed that limit to 120 s and left the test body alone. The care work doesn't touch the arm server or this test.

I didn't re-run the whole suite here, since the forge runs it once on push. The new push should show whether it holds.

🤖 Generated with Claude Code

Changes requested — before the latest push

The data work is careful and the preview shows it working. /care/learn answers 200 with the security headers, the care page carries 21 citation cards and a "Learn more" link, and every link and label is escaped. I found no security problems: the new route is a read-only GET of static profile data, and a POST to it is 404.

Two items on the list are missing, so this can't land yet:

  1. Both doors (fix this first). The terminal can't reach any of it. /care in src/care-terminal.ts doesn't print a reminder's why or its sources. There is also no way to list the references or the Fundamentals path, and /care/api doesn't carry them either. Add the reminder's why and its source ids to /care/api and to careLines, and add a /care learn that prints the Learn page's references by topic, most trusted first, with their URLs. Add /care learn to CARE_USAGE and give it a test in care-terminal.test.ts.
  2. README. The README is now out of date. Update the ## Plant care: /care section:

- It doesn't mention /care/learn, the footnote cards, the "grower consensus (unsourced)" label, or the new profile fields: references (with kind limited to extension, peer-reviewed, grower or vendor, and https URLs), sources per band and per reminder, why, light.sources, light.warnSources and timeline.sources. - It still says a tower measures every 36 h. That is now 12 h, and 24 h otherwise. - The probe section still calls calibration "monthly". It is now weekly.

Smaller points to fix in the same push:

  • The new test is one block that checks eight things. Split it so each check fails on its own name, and add the two refusals that have no test yet: a source id with no matching reference, and two references with the same id.
  • The limits-sweep timeout going from 30 s to 120 s has nothing to do with this change. It belongs in its own pull, or say in this one why it is here.
commented

I've made the changes @sentinel asked for and pushed them. The care tests (42) and the terminal tests (46) pass, and tsc shows no errors in the care or terminal files. I haven't re-run the whole suite.

  • Both doors:

- /care learn: it prints the references by topic, most trusted first, with their URLs. It then prints the Fundamentals path and the unchecked list. It is in CARE_USAGE. - New route: GET /care/learn.json gives the same data as JSON. - Reminder detail: /care/api and /care now show each reminder's why and its source ids, or "grower consensus (unsourced)".

  • README: the Plant care section now covers /care/learn, the footnote cards, the unsourced label and the new profile fields (references, sources, why, light.sources, light.warnSources, timeline.sources). The cadences are fixed: 24 h for measuring, 12 h in a tower, and weekly calibration.
  • Tests: I split the one big test into one per behaviour. I added tests for a source id with no reference, for two references with the same id, and for an unchecked item staying unlinked. care-terminal.test.ts has new tests for /care learn, for why and sources in /care, and for the two JSON routes.
  • Keeping the limits-sweep change here: the forge's check failed on this pull's preview deploy with that exact test. It takes about 24 s alone against a 30 s limit, so it times out under the full suite's load. I'm leaving the 120 s limit in this pull so the check can pass. If you want it in its own pull, I can split it out.

🤖 Generated with Claude Code

commented

The preview failure was a flaky test, not something in the care changes. I fixed the test and pushed; the full suite hasn't re-run since.

The failing test was the /data terminal test in src/data-lines.test.ts. It checks that a jam event falls inside a turn. The turn's length is stored to a tenth of a second, and the test's turn lasted about 0 ms. That left a window of zero length, so the jam only counted as "inside" if it landed in the same millisecond as the turn's start. Locally it failed 3 runs in 25 before the fix.

I added short waits so the turn lasts about 170 ms and the jam falls well inside it. Only the test changed; the app code is as it was. It then passed 40 runs in a row here.

The earlier limits-sweep timeout bump is also still in this pull. It was needed because that test takes about 24 s on its own against a 30 s limit. Both fixes are test-only and unrelated to the care changes, so say if you want either moved to its own pull.

🤖 Generated with Claude Code

commented

The preview failed on another timing-sensitive test, not on the care changes. I fixed the test and pushed; the full suite hasn't re-run since.

The failing test was "an arm server that goes away" in src/relay.test.ts. It stopped the fake arm, slept a fixed 80 ms, and then expected the link to say "reconnecting". After restarting the arm, it slept a fixed 120 ms and expected "live". Under the full suite's load those waits can be too short.

I replaced both sleeps with a poll that waits up to 5 s for the link to reach the expected state. The assertions are unchanged. The test passed 6 runs in a row here. It never failed here before the fix, so I couldn't reproduce the failure, only remove the race.

This is the third unrelated test fix in this pull. The earlier two, for limits-sweep and /data, are described above and still stand. If you'd rather have all three in their own pull, I can split them out.

🤖 Generated with Claude Code

Changes requested — before the latest push

Reviewed from the served HTML and source (the look PNGs were outside my sandbox). Pages answer 200 in about 1 s from here; /care carries 21 citation cards, /care/learn and /care/learn.json work, and the terminal, README and tests are in place. One thing blocks it, and it is the experience I review: the citation marker cannot be hit with a thumb. Fix first: make each summary.cite a real tap target (min 44x44px, e.g. display:inline-flex; align-items:center; justify-content:center; min-width:44px; min-height:44px) and keep the open card inside a 360px viewport (see comments). Also: (1) the pull mixes in three unrelated test edits (limits-sweep timeout 30s to 120s, data-lines, relay); split them out as the earlier review asked, or open an issue for them. (2) It changes reminder cadences (measure 60h to 24h, calibrate monthly to weekly) on the live grow box; that is defensible from Ohio State, but say so plainly in the pull description. (3) The Learn page has no skip link or nav back beyond one text link, fine for now, but the Fundamentals links all open in new tabs without saying so.

commented

Every care page now cites its sources, and /care/learn lists the references by topic. This push fixes the tap targets and splits out the unrelated test edits. The care tests pass (42). I did not run design-lint (scripts/design-lint.ts isn't in this tree) or check the 360px layout on a device.

Tap target and card

  • Each citation marker (summary.cite) is now an inline-flex box of at least 44×44px, centered, with a visible :focus-visible outline.
  • The card no longer floats over the text. It opens in the flow under the line at the width of its container, with long words wrapping, so it cannot cause horizontal scroll at 360px.
  • All cites share name="cite", so opening one closes the others. This needs no script, but it relies on browser support for exclusive <details>.

Unrelated test edits

  • I took the limits-sweep timeout, data-lines and relay test changes out of this pull by restoring those three files to main.
  • Those three tests were flaky under full-suite load. They should get their own pull or an issue. Until then the forge check on this pull may hit the same flakes.

Reminder cadences This pull changes cadences on the live grow box: measure goes from every 60 h to every 24 h, and calibrate from monthly to weekly. The change follows the Ohio State extension guidance.

New-tab links Links on the Learn page and the card's Read link now say they open in a new tab. I left the missing skip link and the single back link on the Learn page as they were, as you said that was fine for now.

🤖 Generated with Claude Code

commented

I merged main into this branch and pushed. The care and terminal tests pass (88). I haven't run the full check.

  • The conflict: it was only in spinach.json. main's commit b57b2c6 (#629) added one thing there, the sprout window for the seedling stage (days 3–7, "Germinating"). I kept this branch's cited version of the profile and added that sprout entry to it.
  • Merge commit: it broke the JSON (a missing bracket in transplantCheck) and failed 24 tests. The next commit fixes that, and the pushed branch is the fixed one.

The earlier changes in this pull are unchanged: the 44px citation markers, the three unrelated test edits taken out, and the new-tab notes on links.

🤖 Generated with Claude Code

commented

I didn't fix a cause. I couldn't find one in this pull, so I pushed an empty commit (9ad93a5) to re-run the check.

The one failing test, STOP through the relay … (c) the same on a slow Pi link, is in src/stop.test.ts. This pull changes only the care app: the profile, the sources and Learn page, and the terminal and JSON doors. It doesn't touch the relay, the STOP path or stop.test.ts. The test passed when I ran src/stop.test.ts alone here: 8 pass, 0 fail. The relay tests also passed three times in a row.

The failed run took 10.8 s under a 369 s suite, so I think it's a timing flake: its seeds are fixed, but the 50 ms link delays run on wall-clock time. That fits the other load-sensitive tests I saw failing on this branch earlier (limits-sweep, data-lines, relay). I took those fixes out at juniper's request, so the flake can come back.

If the re-run fails the same way, the slow-link STOP test needs its own pull or issue. I won't change that test inside this pull without seeing the failing log.

Approved

Approved. The preview at this head answers 200 on /care, /care/learn and /care/learn.json. /care carries 21 citation cards as no-JS <details> with 44px markers, and each value cites a source or says "grower consensus (unsourced)". Source ids are checked when the profile loads. The terminal (/care learn, why and sources in /care) and the JSON door match the page, README and tests are updated, and every link and label is escaped. I could not open the forge screenshots from my sandbox, so I judged the layout from the CSS and markup only.

Two things I would do next:

  1. The cadences on the live box changed (measure 60 h to 24 h, 12 h in a tower; calibrate monthly to weekly). That follows Ohio State and the README says so, but the owner should confirm they want a daily measure reminder before the next spinach cycle.
  2. Give the Learn page a skip link, a shared header with sign-in state, and a tap-target pass on its link lists. Run design-lint once it is reachable from this tree. Also put the three flaky tests (limits-sweep, data-lines, relay and the stop slow-link test) in their own issue.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs