U of I × MindRouter App Gallery

Recall

Education Built with Pi v0.84.4 Critic status: shipped

Recall

Spaced-repetition flashcards for any course

Import a CSV or paste notes, study with a proven spaced-repetition schedule, and see exactly what you know — all stored privately in your own browser.

Recall running on a desktop screen, spaced-repetition flashcards for any course Desktop · click to enlarge
Recall running on a phone, spaced-repetition flashcards for any course
Phone · click to enlarge

What it is ✎ blurb written by the AI critic

Recall is a flashcard app that schedules your reviews with the SM-2 spaced-repetition method and keeps all decks and progress in your own browser. Start with two starter decks (Idaho state symbols and elevations checked against the Idaho Code and USGS, and statistics terms from the NIST/SEMATECH e-Handbook) or make your own by importing a CSV file or pasting 'term — definition' notes. A progress dashboard shows the review forecast for the next 16 weeks, an estimated retention curve, your streak and your hardest cards.

Try this

  1. Open the Idaho geography deck, press Space to flip each card and grade it with keys 1-4, then open the Progress tab
  2. Click 'Paste notes' and paste a few 'term — definition' lines from one of your own classes to build a deck in seconds
  3. Start a 'Test me' quiz on Common statistics terms and type an answer in your own words instead of picking an option

Highlights ✎ written by the AI critic

  • 3D flip cards graded Again / Hard / Good / Easy with keyboard shortcuts; each button shows the card's real next SM-2 interval
  • Import CSV/TSV or paste notes, export any deck back to CSV, and back up or restore everything as a JSON file
  • Card editor with Markdown and simple math ($x^2$, fractions, square roots, Greek letters), tag filters, search and bulk tag / move / delete
  • Progress dashboard: 16-week forecast heatmap with a next-7-days list, retention curve, day streak and hardest cards
  • Cram mode and a 'Test me' quiz (pick one of four answers or type your own) that leave your schedule untouched

Who it's for

Students in memorization-heavy courses (anatomy, languages, law, pharmacology), instructors sharing decks

Features

  • Deck library with import from CSV/TSV (front, back, tags) and paste-to-cards (one 'term — definition' per line)
  • Study session with 3D flip animation, keyboard shortcuts, Again/Hard/Good/Easy grading and SM-2 scheduling
  • Card editor with Markdown and math (simple inline formatting), tags, search and bulk edit
  • Progress dashboard: retention curve, review forecast calendar heatmap, streaks, hardest cards
  • Cram and 'test me' modes, and export back to CSV
  • Everything persisted to localStorage with backup/restore JSON

Data & sources

  • legislature.idaho.gov — Idaho Code Title 67, Chapter 45 'State Symbols' — Idaho State Legislature —
  • pubs.usgs.gov — Elevations and Distances in the United States (rev. 2001) — U.S. Geological Survey —
  • www.itl.nist.gov — NIST/SEMATECH e-Handbook of Statistical Methods §1.3.5.1 Measures of Location —
  • www.itl.nist.gov — NIST/SEMATECH e-Handbook of Statistical Methods §1.3.5.6 Measures of Scale —
  • www.itl.nist.gov — NIST/SEMATECH e-Handbook of Statistical Methods §7.1.3 What are statistical tests? —
  • www.itl.nist.gov — NIST/SEMATECH e-Handbook of Statistical Methods §7.1.3.1 Critical values and p values —
Full data provenance ✎ written by the AI reviewer

Raw reference sources — Recall (spaced-repetition flashcards)

Retrieval date for every file: 2026-09-13 (HTTP GET with curl, User-Agent UIdaho-gallery-data-prep/1.0). All files are byte-for-byte server responses; nothing was edited, filtered or reformatted.

  • Re-fetch note (verifier, 2026-09-13): every URL was fetched again and compared with the saved copy. The statute PDF is byte-identical.

  • The five HTML pages are the same size and differ only inside Cloudflare-injected, per-request tokens:

    • the window.__CF$cv$params={r:'…',t:'…'} script just before </body>;

    • on the USGS page, the hash in the /cdn-cgi/l/email-protection#… contact link.

      So a SHA-256 of a fresh download will not match the table below, but the content is the same.

SPEC.md says the app needs no external data. These six small files are reference pages only. They let the starter decks ("Idaho geography & natural history basics" and "Common statistics terms") be checked against authoritative wording. They are not datasets to chart. The cards themselves are authored content: the app should credit these pages as the sources the cards were checked against.

FileBytesSHA-256 (first 16 hex)Publisher
idaho_code_T67CH45_state_symbols.pdf38,873d93cf5502079d274Idaho State Legislature
usgs_elevations_distances_elvadist.html69,340917e503088d62655U.S. Geological Survey
nist_ehandbook_1.3.5.1_measures_of_location.htm16,6361627ccee87d5bf40NIST / SEMATECH
nist_ehandbook_1.3.5.6_measures_of_scale.htm17,3848bbc7b949cb6a27dNIST / SEMATECH
nist_ehandbook_7.1.3_statistical_tests.htm9,29747992c7ef3568047NIST / SEMATECH
nist_ehandbook_7.1.3.1_critical_values_p_values.htm6,9224f2b651cdd6668e1NIST / SEMATECH

Total ≈ 158 KB.


1. idaho_code_T67CH45_state_symbols.pdf

  • URL (GET): https://legislature.idaho.gov/wp-content/uploads/statutesrules/idstat/Title67/T67CH45.pdf (this is the "Download Entire Chapter (PDF)" link on the chapter page https://legislature.idaho.gov/statutesrules/idstat/Title67/T67CH45/)

  • Publisher: Idaho State Legislature (Legislative Services Office).

  • Retrieved: 2026-09-13. HTTP 200, application/pdf, Last-Modified: Wed, 01 Jul 2026 09:33:28 GMT.

  • Contents: the full text of Idaho Code Title 67 ("State Government and State Affairs"), Chapter 45 "State Symbols". Each section is followed by its legislative history in brackets.

  • Record count / date range: 17 sections, §§ 67-4501 through 67-4517. Enactment years run 1931–2026. PDF 1.4, 3 pages, not encrypted. The PDF CreationDate is 2026-07-01 (creator PTC Arbortext; producer PDFlib 9.0.3).

  • Parsing notes:

    • Text layer: the PDF has one, so pdftotext works with or without -layout.

    • Section headings: use ^\s*(67-45\d\d)\. ([A-Z ,]+)\. in multiline mode; the body text follows on the same line.

      • It matches all 17 headings in both output modes.

      • With -layout the headings are indented. Without it they start at column 0, so a ^\s+ pattern finds 0 headings.

    • History brackets: there are 17, one per section, and they come in two forms:

      • [(67-4501) 1931, ch. 64, sec. 1, p. 113; ...] for the first three sections (67-4501 to 67-4503);

      • [67-4504, added 1935, ch. 16, sec. 1, p. 35; ...] for 67-4504 through 67-4517.

    • Enactment year: take the first match of \b(?:19|20)\d\d\b inside the bracket.

      • Do not use a plain \d{4}: it matches the section number first (e.g. 4501).

      • Later amendment years appear as am. 2015 (67-4501, 67-4504) and am. 1955 (67-4503).

    • Hyphenation: words are hyphenated across line breaks (e.g. curru- / coides, desig- / nated).

    • Page breaks: each is a form feed (\f, 3 in total) followed on the same line by the page number ("2", "3").

    • 67-4503 (song): its body includes quoted, multi-line lyrics.

  • Facts this file supports (symbol — year added):

    • State bird: Mountain Bluebird (Sialia currucoides) — 1931 (§ 67-4501)

    • State flower: Syringa (Philadelphus lewisii) — 1931 (§ 67-4502)

    • State song: "Here We Have Idaho" (sometimes "Our Idaho"). Music by Sallie Hume Douglas, chorus words by McKinley Helm, verse words by Albert J. Tompkins — 1931, amended 1955 (§ 67-4503)

    • State tree: White Pine (Pinus monticola) — 1935 (§ 67-4504)

    • State gem (state stone): star garnet — 1967 (§ 67-4505)

    • State horse: Appaloosa — 1975 (§ 67-4506)

    • State fossil: Hagerman Horse Fossil (Equus simplicidens, originally described as Plesippus shoshonensis) — 1988 (§ 67-4507)

    • State fish: Cutthroat trout — 1990 (§ 67-4508)

    • State insect: monarch butterfly — 1992 (§ 67-4509)

    • State fruit: huckleberry — 2000 (§ 67-4510)

    • State vegetable: potato — 2002 (§ 67-4511)

    • State raptor: Peregrine Falcon — 2004 (§ 67-4512)

    • Idaho Noxious and Invasive Weed Awareness Week: the week before Memorial Day weekend, starting 2014 (§ 67-4513)

    • State amphibian: Idaho Giant Salamander — 2015 (§ 67-4514)

    • State cut for faceted gemstones: the Idaho cut — 2022 (§ 67-4515)

    • State dinosaur: Oryctodromeus — 2023 (§ 67-4516)

    • State sport: hunting — 2026, ch. 53 (§ 67-4517)

  • Not in this file (don't cite it for these): the nickname "Gem State", the motto, the capital, the statehood date, the state dance, the state seal or flag.

  • License / terms: statutory text is public law.

    • The Legislature's Site Disclaimer (https://legislature.idaho.gov/site-disclaimer/, quote re-checked 2026-09-13) says: "Neither the state of Idaho nor any agency, official or employee of the state can be liable for the results of any actions arising from use of this information. Official copies of the Idaho Code are published for the Idaho Code Commission by LEXIS Publishing."

    • So this web copy is informational, not the official printed code.

    • No copyright restriction is stated.

  • Suggested citation: Idaho Code Title 67, Chapter 45, "State Symbols" (§§ 67-4501–67-4517), Idaho State Legislature, https://legislature.idaho.gov/statutesrules/idstat/Title67/T67CH45/ (retrieved 2026-09-13).

2. usgs_elevations_distances_elvadist.html

  • URL (GET): https://pubs.usgs.gov/gip/Elevations-Distances/elvadist.html

  • Publisher: U.S. Geological Survey, General Interest Publication Elevations and Distances in the United States (Eastern Region Geography). The page says: "This booklet was originally published and printed in 1995 and revised and reprinted in 2001. The online edition contains the full text from the printed publication." Its <meta name="revised"> is 20050429.

  • Retrieved: 2026-09-13. HTTP 200, Content-Type: text/html; the header gives no charset and no Last-Modified. The body decodes cleanly as UTF-8 (e.g. "Pu'u Wēkiu").

  • Contents: one static page with 9 <table> elements (392 <tr>) under 8 <h2> table headings (a 9th <h2> is the introduction, "Elevations and Distances in the United States"), in page order. Table index = order of <table> in the file:

    • [0] Elevations of the 50 Largest Cities (by population, 1980 Census) — 50 data rows

    • [1] Highest and Lowest Elevations — 56 data rows

    • [2] Elevations of Named Summits Over 14,000 Feet Above Sea Level

    • [3] Elevations of Selected Summits East of the Rocky Mountains

    • [4] Geographic Centers, states — 51 data rows (50 states + District of Columbia): State | County | Locality

    • [5] Geographic Centers, national — 4 data rows (48 states, 49 states, 50 states, North American continent): Geographic Area | Locality | Latitude(N) | Longitude(W.)

    • [6] Distances From Extreme Points to Geographic Centers

    • [7] Extreme Distances (computed to mean sea level)

    • [8] Lengths of United States Boundaries

  • Record count / date range: the "Highest and Lowest Elevations" table (index 1) has one header row (<th> cells) and 56 data rows:

    • 50 states and the District of Columbia;

    • 4 territories: Guam, Puerto Rico, Samoa, Virgin Islands, listed alphabetically among the states;

    • a final "United States" row.

      Values are as of the printed 2001 revision; some names elsewhere in the table may have changed since (for example "Harney Peak", "Mount McKinley"). The Idaho entries are unaffected.

  • Parsing notes (use a real HTML parser, e.g. Python html.parser):

    • Table 1 columns: State or possession | Highest point | County or subdivision | Elevation feet | Lowest Point | County or subdivision | Elevation feet.

      • Header cells are <th> with <br> inside, so naive text joins give Elevationfeet.

      • Some place-name cells also contain <br> (e.g. Tenleytown at<br>Reno Reservoir).

    • Elevation values:

      • They are strings with thousands separators, in feet above sea level.

      • Negative values occur (-282 Death Valley, -8 New Orleans).

      • Sea level / Sea Level means 0.

    • County cells: a cell containing - - (space, hyphen, space, hyphen) means no county.

    • Footnote markers: these sit inside the elevation cells, as a <sup> before the number.

      • Examples: <td align="right"><sup>1</sup>14,494</td> (California high point), <sup>2</sup>279 (Illinois low point), <sup>3</sup>1,803 (New Jersey high point).

      • Kansas has an empty <sup></sup>4,039.

      • Drop the <sup> contents before reading the number; naive tag stripping turns 14,494 into 114,494.

      • The caption under the table reads: 1 = National Geodetic Survey, 2 = Corps of Engineers, 3 = State Surveys.

      • The 50-cities table uses the same markers.

      • The Idaho row has no footnote.

    • SSI error strings: the page shows two literal [an error occurred while processing this directive] strings near its end, one after the last table ("Lengths of United States Boundaries") and one after the closing review statement. They are server-side-include leftovers on the live page, not a failed download; all tables are complete.

    • Datum: no vertical datum is stated for the table.

  • Facts this file supports:

    • Idaho's highest point is Borah Peak, 12,662 ft, Custer County. Raw row: Idaho | Borah Peak | Custer | 12,662 | Snake River | Nez Perce | 710.

    • Idaho's lowest point is the Snake River, 710 ft, Nez Perce County. The page gives only the county, not the city (Lewiston).

    • The geographic center of Idaho is in Custer County, "At Custer, southwest of Challis." (table 4)

    • Derived (simple arithmetic, not stated on the page): Idaho's elevation range = 12,662 − 710 = 11,952 ft.

    • Cross-check, viewed but not saved: the U.S. Forest Service Salmon-Challis NF Borah Peak page (https://www.fs.usda.gov/r04/salmon-challis/recreation/epic-adventures/borah-peak), re-checked 2026-09-13, gives "Elevation of Summit: 12,662 feet" (jumpoff point 7,400 ft; total gain 5,262 ft; 3.5 miles one way).

  • Not in this file: state area, mean elevation, rivers other than the lowest-point entry, lakes, canyons, parks.

  • License / terms: "USGS-authored or produced data and information are considered to be in the U.S. Public Domain" (USGS Copyrights and Credits, https://www.usgs.gov/information-policies-and-instructions/copyrights-and-credits, quote re-checked 2026-09-13). Credit is requested.

  • Suggested citation: U.S. Geological Survey, Elevations and Distances in the United States (rev. 2001), https://pubs.usgs.gov/gip/Elevations-Distances/elvadist.html (retrieved 2026-09-13).

3–6. NIST/SEMATECH e-Handbook of Statistical Methods — four section pages

  • Common to all four: Publisher: National Institute of Standards and Technology (NIST), Statistical Engineering Division, with SEMATECH. The DOI https://doi.org/10.18434/M32189 redirects (HTTP 302) to https://www.itl.nist.gov/div898/handbook/ (checked 2026-09-13).

  • Format: static HTML, Content-Type: text/html; charset=utf-8, with an uppercase <TITLE> and handbook navigation links at the top.

    • Layout: old-style <TABLE> markup. Only the two 1.3.5.x pages mark paragraphs with <!-- begin paragraph --> comments (11 in 1.3.5.1, 8 in 1.3.5.6); the two 7.1.3.x pages have none. Walk the table cells instead of relying on those comments.

    • Formulas: TeX, rendered by MathJax 3, which is loaded from https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js.

      • 1.3.5.1 uses only display math \[ ... \] (3 formulas).

      • 1.3.5.6, 7.1.3 and 7.1.3.1 use only inline math \( ... \).

      • Symbols such as α and p are TeX too: 7.1.3.1 renders its heading as Critical values and \(p\) values, and \(\alpha\) = 0.05 is split across lines. Stripping tags therefore leaves raw TeX.

    • HTML comments: use a real HTML parser (e.g. Python html.parser), which skips comments.

      • Naive regex stripping leaves stray --> pieces.

      • It also leaves the old image-equation markup inside comments: eqns/mean.gif, eqns/variance.gif, gifs/alpha.gif, etc.

    • Other scripts: a digitalgov analytics script, relative ../../nist-header-footer/js/*.js, and the Cloudflare token script noted at the top.

    • Images: the live <img> tags are the two navigation bars (../../gifs/nvgtbr.gif, ../../gifs/nvgbrbtm.gif), plus one histogram figure each on 1.3.5.1 (gif/location.gif) and 1.3.5.6 (gif/scale.gif). None were downloaded.

  • Record count: each file is one handbook section; there are no dated records.

  • License / terms: NIST "Use of NIST information" (https://www.nist.gov/copyrights-disclaimers, quote re-checked 2026-09-13) says: "With the exception of material marked as copyrighted, information presented on NIST sites are considered public information and may be distributed or copied. Use of appropriate byline/photo/image credits is requested."

  • Suggested citation (for the whole group): NIST/SEMATECH e-Handbook of Statistical Methods, §§ 1.3.5.1, 1.3.5.6, 7.1.3, 7.1.3.1, https://doi.org/10.18434/M32189 (retrieved 2026-09-13).

3. nist_ehandbook_1.3.5.1_measures_of_location.htm
  • URL (GET): https://www.itl.nist.gov/div898/handbook/eda/section3/eda351.htm

  • Last-Modified header: Wed, 22 Apr 2026 02:03:02 GMT. Title "1.3.5.1. Measures of Location".

  • Terms supported:

    • mean: "the sum of the data points divided by the number of data points". The page says: "We will use the term average as a synonym for the mean".

    • median: "the value of the point which has half the data smaller than that point and half the data larger than that point", with the odd-N and even-N formulas.

    • mode: "the value of the random sample that occurs with the greatest frequency. It is not necessarily unique".

    • Why the measures differ: normal, exponential, Cauchy and lognormal examples. For skewed distributions "the mean will be pulled in the direction of the skewness", and the median is robust to extreme values.

    • symmetric distribution: "can be folded about an axis so that the 2 sides coincide".

4. nist_ehandbook_1.3.5.6_measures_of_scale.htm
  • URL (GET): https://www.itl.nist.gov/div898/handbook/eda/section3/eda356.htm

  • Last-Modified header: Wed, 22 Apr 2026 02:03:06 GMT. Title "1.3.5.6. Measures of Scale".

  • Terms supported:

    • variance: s² = Σ(Yᵢ − Ȳ)²/(N − 1), "roughly the arithmetic average of the squared distance from the mean".

    • standard deviation: "the square root of the variance"; it "restores the units of the spread to the original data units".

    • range: "the largest value minus the smallest value in a data set".

    • average absolute deviation (AAD): Σ|Yᵢ − Ȳ|/N.

    • median absolute deviation (MAD): median(|Yᵢ − Ỹ|).

    • interquartile range: "the value of the 75th percentile minus the value of the 25th percentile".

5. nist_ehandbook_7.1.3_statistical_tests.htm
  • URL (GET): https://www.itl.nist.gov/div898/handbook/prc/section1/prc13.htm

  • Last-Modified header: Fri, 12 Sep 2025 02:13:46 GMT. Title "7.1.3. What are statistical tests?".

  • Terms supported:

    • statistical test: "provides a mechanism for making quantitative decisions about a process or processes".

    • null hypothesis: "the conjecture is called the null hypothesis". The alternative hypothesis is its complement.

    • two-sided vs one-sided tests (linewidth and light-bulb examples).

    • test statistic compared against critical values.

    • significance level α: the test is constructed so that "the risk of rejecting the null hypothesis, when it is in fact true, is small. This risk, α, is often referred to as the significance level of the test." This is the Type I error rate, although the page does not use that name.

    • error of the second kind, β: "The risk of failing to reject the null hypothesis when it is in fact false"; "the risk β increases as the risk α decreases". This is the Type II error, again not named that way.

  • The page does not use the phrases "Type I error" or "Type II error"; it says "error of the second kind".

6. nist_ehandbook_7.1.3.1_critical_values_p_values.htm
  • URL (GET): https://www.itl.nist.gov/div898/handbook/prc/section1/prc131.htm

  • Last-Modified header: Fri, 12 Sep 2025 02:13:47 GMT. Title "7.1.3.1. Critical values and p values".

  • Terms supported:

    • significance level α: "A value of α = 0.05 implies that the null hypothesis is rejected 5 % of the time when it is in fact true". The page adds that "in practice values of 0.1, 0.05, and 0.01 are common".

    • critical values: "cut-off values that define regions where the test statistic is unlikely to lie". That region is the rejection region.

    • p-value: "the probability of the test statistic being at least as extreme as the one observed given that the null hypothesis is true". A small p-value "is an indication that the null hypothesis is false".


Considered but not saved (notes for the deck author)

  • Idaho Secretary of State, "Idaho State Symbols" — https://sos.idaho.gov/state-symbols/ (viewed 2026-09-13; re-checked by verifier).

    • Not saved, because the statute above is the primary source.

    • It lists a State Dance: Square Dance ("The 1989 legislature designated the Square Dance as the American Folk Dance of Idaho"). This is not in Idaho Code ch. 45.

    • It gives the Mountain Bluebird's scientific name as "Sialia arctcia", a misspelling. Use the statute's Sialia currucoides.

    • It calls the state tree "Western White Pine".

  • Idaho Blue Book 2025–2026 — https://archive.sos.idaho.gov/blue_book/blue_book_2025-2026.pdf. A HEAD request gives Content-Length 246,166,665 bytes (re-checked 2026-09-13), far over the ~20 MB budget, so it was not downloaded.

  • NIST e-Handbook glossary — https://www.itl.nist.gov/div898/handbook/glossary.htm. It is an engineering-statistics glossary adapted from an AMD donation and has no entries for p-value, null hypothesis or Type I error, so the section pages above were used instead.

  • USFS Borah Peak page — used only as the cross-check noted in §2.

Facts NOT backed by any saved file

The saved files do not cover these Idaho facts: capital (Boise), statehood date, "Gem State", motto, number of counties, state area, Hells Canyon, Craters of the Moon, Shoshone Falls, Lake Pend Oreille.

For statistics, they do not cover correlation, regression, normal distribution (beyond its use as an example), sample vs. population, or confidence interval. Type I/II error are not named, but the concepts are defined in § 7.1.3: α is the risk of rejecting a true null hypothesis, and β, the "error of the second kind", is the risk of failing to reject a false one.

If starter cards use any of these, the author must check them separately and should not attribute them to these files.

How it was built

Written by Pi 0.84.4 (pi.dev) on qwen/qwen3.8-27b, served by MindRouter, the University of Idaho's on-premises AI platform.

12harness rounds
181.9minutes of harness work (3.0 h)
2,740lines of code
171KB, single-file app

Rounds by kind

build1
continue4
feedback4
critic3

Lines of code per file

body html254
app css485
app js1,691
scripts310

Critic scores ✎ scored by the independent AI critic, 1–10

visual 8 out of 10
usefulness 8 out of 10
correctness 8 out of 10
interactivity 8 out of 10

Independent audits ✎ by the AI critic

Data honesty: checked against raw data Authorship audit: every app-code commit is a harness round

Automated checks

Console no console errors No network 0 external requests Phone layout 0 px overflow Canvases no empty canvases Brand header header present No key leak no key in source

Checked by critic-verify.

Data spot checks ✎ written by the AI critic

  • State gem card: app shows 'The star garnet, designated in 1967 (§ 67-4505)'; Idaho Code T67CH45 PDF reads '67-4505. STATE GEM DESIGNATED. The star garnet ... [67-4505, added 1967, ch. 33, sec. 1, p. 56.]' - match
  • Highest/lowest point cards: app shows 'Borah Peak, 12,662 ft, in Custer County' and 'The Snake River, 710 ft, in Nez Perce County'; USGS elvadist table row = Idaho | Borah Peak | Custer | 12,662 | Snake River | Nez Perce | 710 - match
  • Elevation range card (derived, and labelled as a subtraction on the Data tab): app 11,952 ft; independent 12,662 - 710 = 11,952 - match
  • State sport card: app 'Hunting, designated in 2026, ch. 53 (§ 67-4517)'; PDF '[67-4517, added 2026, ch. 53, sec. 2, p. 243.]' - match
  • Geographic center card: app 'In Custer County, at Custer, southwest of Challis'; USGS geographic-centers table row = Idaho | Custer | At Custer, southwest of Challis - match
Show all 11 spot checks
  • p-value card: app text equals NIST e-Handbook §7.1.3.1 wording 'the probability of the test statistic being at least as extreme as the one observed given that the null hypothesis is true'; mode, IQR, variance and beta-risk cards also checked against §1.3.5.1, §1.3.5.6, §7.1.3 - match
  • Data & sources tab counts 17 / 4 / 19 cards vs data/embed/starter_decks.json: 17 statute cards, 4 USGS cards, 19 NIST cards - match
  • Computed SM-2: after grading all 21 Idaho cards with Again/Hard/Good/Easy, localStorage holds ef 2.5/2.36/2.5/2.6, interval 1 day, due next day; an independent Python SM-2 gives identical values for all 21 cards
  • Computed forecast: after 139 simulated reviews (Sep 1-18, fake clock, today = Sep 22) the app's 'Next 7 days' list is 2, 12, 17, 4, 2, 2, 0 and the KPI says 2 due today; an independent count from the stored due dates gives 2, 12, 17, 4, 2, 2, 0 and 2 - match
  • Computed streak and heatmap dates with a fake clock: studying on Wed 16 and Thu 17 Sep gives an app streak of 2 (independent: 2); the 40 new cards due on Wed 16 Sep sit on the 'Wed, Sep 16' heatmap cell - match
  • Retention summary: app '86% of reviews graded Good or Easy (139 reviews)'; independent all-time share = 86% of 139 - match, but the label says 'Last 14 days' while only 14 of those reviews fall in the last 14 days (listed as a remaining issue)
Build notes ✎ written by the AI reviewer

Status is needs-work. Pi built a usable app: every required feature works, and there are no console or page errors and no external requests. But known defects remain: a dead 'Study all due' button, a 79 px phone overflow on the library page, overlapping heatmap legend labels and grey summary bars. Pi produced no code change in its last four attempts. All app code (src/, scripts/, data/embed/) was written by Pi, and the authorship guard never fired. The driver wrote only the prompts, FEEDBACK.md (removed in commit 5e8ced7), and its own test scripts and screenshots in the runs directory.

Data: dataprep_ready.sh returned 'READY ready-after-repair'. The six raw reference files, already committed as 'data: raw downloads' and 'data: verifier fixes', were checked and are valid (the PDF has 17 sections; the USGS table has Idaho's row; the four NIST pages have correct titles), so no new downloads were needed. The spec asks for no external data; the harness made compact starter-deck JSON from facts backed by those files.

Pi behaviour. In -p mode Pi prints nothing until it exits, so file changes were the only progress signal. Rounds 1, 2, 3, 5 and 9 stopped changing files and were killed under the stuck-round rule (exit 143). Round 1 had written the whole app before it went idle. Round 2 made small edits, then stalled with an open connection. Round 3 wrote nothing. Round 5 applied most fixes, then hung. Round 9 wrote nothing in 18 minutes. Round 4, a re-run of round 3's 13-item feedback, finished cleanly (exit 0) and fixed all 13 items. Rounds 6, 7 and 8 exited 0 within 4.5-8 minutes with empty output and no app changes, even after the feedback was cut to 5 targeted items that named functions and CSS rules. MindRouter returned 401 (reachable) at every check, and network_error_lines was 0 in every round, so this was not an outage. Other Pi apps in the gallery showed the same stall/kill pattern at the same time. My guess is that the model is struggling with the now-large app.js (67 KB), but I could not confirm this because Pi keeps no session logs.

Round accounting: 9 rounds in total. 1 build; 4 feedback (3, 5, 6, 8); 4 continue re-runs of stalled or empty rounds (2, 4, 7, 9). Total harness time 10,574 s.

In buildlog.json, feedback_items for a continue round repeats the item count of the FEEDBACK.md it re-ran.

Verification: verify_app.py ran after rounds 1, 4 and 5 and on the final build. The driver's own Playwright tests (featuretest.py, featuretest2.py, probe/diag scripts) exercised import, paste, study keys, cram, test me, editor math, bulk actions, export, backup/restore, progress charts and tooltips, and phone layouts. Some of the driver's test sections threw exceptions because of bugs in the test scripts themselves (a double dialog accept, a stale locator); those were re-checked with separate probes and are not counted as app bugs.

Round-by-round timeline

Every harness round, in order. The prompts and FEEDBACK.md were written by the AI reviewer; the app code was written by the harness. Expand a round to see the exact prompt and the FEEDBACK.md the harness received.

    1 build 27.9 min · 6 files changed, 3172 insertions(+), 3 deletions(-) Show prompt

    Prompt given to the harness:

    Read AGENTS.md, SPEC.md and BRAND.md in this directory. Then build the complete app they describe, step by step. First write a script in scripts/ (Python 3 standard library only) that produces compact JSON in data/embed/ with the two starter decks ('Idaho geography & natural history basics' and 'Common statistics terms', about 20-30 cards each, with tags and a per-card source). The facts on those cards must come from the reference files in data/raw/ — read data/raw/SOURCES.md, which lists exactly which facts each file supports and how to parse it; parse the files where practical, and do not put facts on a card that those files do not back up. Run the script. Then write src/body.html, src/app.css and src/app.js; run python3 build.py --check and fix any error it reports. Implement every required feature in SPEC.md with a polished, modern, responsive University of Idaho design, including a visible "Data & sources" section that credits and links the reference sources in data/raw/SOURCES.md. Do not stop until python3 build.py --check succeeds and every feature is implemented.
    

    No feedback file was sent in this round.

    2 continue 29.4 min · 3 files changed, 34 insertions(+), 28 deletions(-) Show prompt

    Prompt given to the harness:

    Read AGENTS.md, SPEC.md and BRAND.md in this directory. Then build the complete app they describe, step by step. First write a script in scripts/ (Python 3 standard library only) that produces compact JSON in data/embed/ with the two starter decks ('Idaho geography & natural history basics' and 'Common statistics terms', about 20-30 cards each, with tags and a per-card source). The facts on those cards must come from the reference files in data/raw/ — read data/raw/SOURCES.md, which lists exactly which facts each file supports and how to parse it; parse the files where practical, and do not put facts on a card that those files do not back up. Run the script. Then write src/body.html, src/app.css and src/app.js; run python3 build.py --check and fix any error it reports. Implement every required feature in SPEC.md with a polished, modern, responsive University of Idaho design, including a visible "Data & sources" section that credits and links the reference sources in data/raw/SOURCES.md. Do not stop until python3 build.py --check succeeds and every feature is implemented.
    

    No feedback file was sent in this round.

    4 continue 22.7 min · 4 files changed, 1667 insertions(+), 313 deletions(-) Show prompt

    Prompt given to the harness:

    Read FEEDBACK.md in this directory — it lists problems a reviewer found when testing index.html in a real browser. Fix every item, keeping everything that already works, then run python3 build.py --check.
    

    FEEDBACK.md the harness received ✎ written by the AI reviewer:

    Reviewer findings — round 2 build, tested in Chromium at 1366×900 and 390×844

    Most important first. Keep everything that already works: 3D flip, Space/1–4 keys, SM-2 fields in localStorage, paste-to-cards, editor search, bulk tag, Export CSV, Backup/Restore, reload persistence, no external requests, no horizontal overflow at 390 px.

    1. "Import CSV / TSV" button does nothing — the import dialog never opens (page error). Clicked "Import CSV / TSV" in the Deck library. Expected the import modal to open. Nothing appears, and the page throws, every click: TypeError: Cannot set properties of null (setting 'textContent') at HTMLButtonElement.importCsvModal importCsvModal() writes to an element #csv-error that does not exist in the markup, so it stops before the modal opens. CSV/TSV import (a required feature) is unreachable for users. When the file input is set directly, parsing works (4 cards, quoted commas OK), so fix the dialog and give it a visible error/success message area. Also show a preview of the parsed rows (the first few front/back/tags) with a "Import N cards" confirm button, rather than importing the moment a file is chosen.

    2. "Test me" mode is identical to Study mode. Chose Study → "Test me" → Start session. Expected a real test: type your answer (or pick from multiple choice), have it checked, then see a score at the end. It shows the same flip card with Again/Hard/Good/Easy buttons. Make "Test me" a quiz: show the front, give a text box (Enter submits) or 4 multiple-choice options drawn from other cards' backs. Mark the answer correct or incorrect with a clear green/red state and reveal the right answer. End with a score summary (e.g. 14/20 = 70%) and a "retry missed cards" button. Test answers should not change the SM-2 schedule (or say clearly if they do). Cram mode should say in the UI that it doesn't affect scheduling.

    3. No math rendering in the card editor or on cards. Typed x^2, H_2O and $\sqrt{x}$ into Back. The preview shows the raw text. SPEC asks for "Markdown and math (simple inline formatting)". Support at least: x^2 / x^{10} → superscript, H_2O / a_{ij} → subscript, \sqrt{x} → √x, \frac{a}{b} → a stacked or slashed fraction, and Greek/operators such as \alpha \beta \sigma \mu \Sigma \pm \le \ge \ne \approx \times, inside $...$. Also support - bullet lists and line breaks. Render the same way on the study card, the editor preview and the Test-me feedback. Put a short formatting cheat-sheet near the editor ("bold, italic, code, $x^2$, $H_2O$, $\sqrt{x}$").

    4. The review-forecast heatmap is unreadably tiny. Progress tab: the heatmap SVG has viewBox 1458×141 but is drawn 560 px wide and 54 px tall, so the cells are about 4 px and the day/week labels are illegible (see the "Review forecast" card; it's worse on a phone). Make it a real calendar heatmap: week columns × weekday rows with cells at least 12–14 px, readable month and weekday labels, and a colour legend (0 → max) using the warm sequential scale from BRAND.md. Show a tooltip on hover/tap with the date and number of cards due. Let it span the full width of the dashboard (its own row), and scroll horizontally inside its own container on phones.

    5. Retention curve and Hardest cards stay empty after studying. Graded about 8 cards (a mix of Again, Hard, Good and Easy), then opened Progress for that deck. "Retention curve" says "Review a few cards to see the curve", and "Hardest cards" says "No learned cards yet", even though the KPIs show 4 learned and 60% retention. Expected: (a) The retention curve should render with today's data alone. Draw a proper SVG line/area chart with axes, gridlines, % tick labels and point tooltips. A good option is estimated recall probability vs. days since review (a forgetting curve based on each card's interval/ease), with today's actual Good+Easy share as a point. (b) Hardest cards should include any card graded Again or Hard, ranked by lapses / low ease / % Again. Show the front text, the number of lapses and ease, and a button to study just those cards.

    6. Tabs are clipped on a phone. At 390 px the tab bar shows "Decks Study Progress Data & sourc", with the last tab cut off at the right edge and no visible way to reach it. All four tabs should be fully visible (e.g. shorter labels or icons+labels, a 2×2 grid, or a bottom tab bar), and tapping each should work.

    7. Welcome hint shows on every tab, above the study card. The yellow "Welcome to Recall…" box sits above the study session and the progress dashboard, pushing the flashcard down (on a phone the card starts around 430 px down). Show the hint only on the Deck library until it is dismissed. During a study session, keep the card, progress bar and grade buttons visible without scrolling on a 390×844 phone.

    8. The back of the card hides the question. After flipping, only the answer is shown, so the user cannot compare it with the prompt. Show the front text small and muted at the top of the back face. Also show the keyboard shortcut legend (Space flip · 1 Again · 2 Hard · 3 Good · 4 Easy · Esc quit) under the grade buttons on desktop.

    9. Study view has no deck chooser once a session ends, and there's no session summary chart. Add a short summary after a session: counts per grade shown as a small bar, time spent, and next due date. Keep the existing "Study again / View progress / Deck library" buttons.

    10. Empty deck is misleading. Created "Empty deck" via + New deck and closed the editor. The deck card says "All caught up ✓" and has an enabled Study button. Expected: a helpful empty state on the card ("No cards yet — add cards, paste notes or import a CSV") with an Add cards button, and Study disabled. Pressing Study on a deck with nothing due should offer "Cram all cards" instead of an empty session.

    11. Bulk edit is only "Tag selected" via a browser prompt() plus delete. Replace the native prompt with an inline bulk bar that appears when cards are checked: add tag, remove tag, move to another deck, reset scheduling, delete. Show "N selected", with Select all / Select none. Show each card's tags as chips in the list, and let a tag chip click filter the list.

    12. Duplicate deck names on import. Importing sample.csv and then sample.tsv creates two decks both named "sample". Pre-fill the name field from the file name and make it editable in the import preview; if the name already exists, append " (2)".

    13. Polish / "feel alive". The library cards and dashboard are clean but static. Add subtle transitions: hover lift on deck cards, modal fade/scale-in, count-up on KPI numbers, grade-button press feedback, and a brief confetti or checkmark animation when a session is finished. Give each deck card a mini "due in the next 7 days" sparkline or ring showing % learned. Respect prefers-reduced-motion.

    7 continue 4.6 min · — Show prompt

    Prompt given to the harness:

    Read FEEDBACK.md in this directory — it lists problems a reviewer found when testing index.html in a real browser. Fix every item, keeping everything that already works, then run python3 build.py --check.
    

    No feedback file was sent in this round.

    9 continue 18.9 min · — Show prompt

    Prompt given to the harness:

    Read FEEDBACK.md in this directory — it lists problems a reviewer found when testing index.html in a real browser. Fix every item, keeping everything that already works, then run python3 build.py --check.
    

    No feedback file was sent in this round.

    10 critic 3.2 min · 4 files changed, 256 insertions(+), 70 deletions(-) Show prompt

    Prompt given to the harness:

    Read FEEDBACK.md in this directory. It lists 12 problems a reviewer found when testing index.html in a real browser. Fix them in order, starting with item 1. For each item: read only the function or CSS rule it names (use grep/read with line ranges, the files are large), then change it with small targeted edits. Never rewrite src/app.js, src/app.css or src/body.html as a whole, and keep everything that already works. Run python3 build.py --check after every two or three items and fix any error it reports. Keep going until all 12 items are fixed, then run python3 build.py --check a final time.
    

    FEEDBACK.md the harness received ✎ written by the AI reviewer:

    Reviewer findings — critic pass (Chromium 1440×900 and 390×844 phone)

    Everything not listed here works: SM-2 values are correct, CSV/TSV import, export, backup/restore, editor search/tags/markdown/math, bulk edit, cram, progress KPIs, sources tab. Do not rewrite or restructure any file. Make small targeted edits (edit tool, not full-file rewrites) in the functions named below, in this order, and run python3 build.py --check after every two or three items.

    1. Deck-card "Due next 7 days" chart overflows its card (desktop and phone). dueBarsSVG() in src/app.js draws a 132-unit viewBox, but .rc-duebars in src/app.css has flex: none and no width, so it renders about 268 px wide and starts 130 px into the card. On desktop the bars cross into the neighbouring deck card and the last card's bars run past the page edge. On a 390 px phone they stick out 79 px, which makes the whole page scroll sideways (a real phone then zooms the entire app out to 469 px). Also only the first day letter is drawn: dayNames is a single string for today, so dayNames[i] is empty for i > 0. Expected: put the label above the chart, give the SVG width: 100%; max-width: 100%; height: auto, and draw one weekday letter under each of the 7 bars (compute the letter for addDays(new Date(), i)).

    2. Library strip always says "0 due today" and "Study all due" is disabled. In libraryStats() a card with sm === null (never studied) is not counted as due, but dueCards() counts it. Fresh load: the deck cards say 21 and 19 due, the strip says 0. Expected: count due cards exactly like dueCards() (40 on a fresh load), so the button reads "Study all due (40)" and starts a session.

    3. Card editor is unusable on a phone. At 390 px the editor's side column and form are 507 px wide inside a 437 px modal panel; card titles, the text boxes and the "Save card" button are cut off at the right edge. .rc-editor becomes grid-template-columns: 1fr at ≤720 px, but the grid items keep their min-content width. Expected: at phone width every editor element fits inside the panel (use minmax(0, 1fr) and min-width: 0 on .rc-editor__side / .rc-editor__main, let the footer buttons wrap), with no sideways scrolling.

    4. Test me accepts a single word as a correct typed answer. answerMatches() returns true when every typed word appears in the answer. For "Symmetric distribution" typing just coincide is marked "✓ Correct!"; for the state bird, typing 1931 or designated would be too. Expected: a typed answer is correct only when it covers most of the answer's key words (for example at least 60% of the non-filler words, or an exact/near match of the main term before the first comma/parenthesis). Picking the right option stays correct.

    5. Test me keyboard and feedback. The answer box is auto-focused, so pressing 1–4 types digits into it instead of choosing an option, although the hint says "1–4 pick an option". After picking a wrong option the result does not show which option you picked ("Your answer" only appears for typed answers). Expected: do not auto-focus the input (or let 1–4 pick an option while the input is empty), and after any answer show "Your answer" with the option text you picked.

    6. Grade button hints do not match the scheduler. The buttons say Again "< 1 min", Hard "~ 1 day", Good "~ 3 days", Easy "~ 7 days", but sm2() schedules every new card 1 day out whatever the grade (verified in localStorage), and an Again card is not shown again in the session. Expected: each button shows the real next interval for the current card, computed from a copy of its sm with the same SM-2 rule (e.g. "1d", "6d", "15d"), and the hint for Again says "1d" (or re-queue Again cards at the end of the session).

    7. Forecast heatmap puts counts on the wrong dates. In svgHeatmap() the grid starts on the Sunday of the current week, but counts[d] is indexed from today. With the clock set to Wednesday 16 Sep, the 40 cards due today are drawn on the cell labelled "Sun, Sep 13". Expected: cell d shows the count for addDays(start, d) (use counts[d - todayOffset], where todayOffset is today's weekday), past days in the first column show 0, and the tooltip date matches the count.

    8. Heatmap legend labels overlap. "fewer" and "more (21 cards)" are drawn on top of each other ("mfeweer(21 cards)") because the "more" text is right-aligned at the end of the swatches. Expected: "fewer" left of the 4 swatches and "more (N cards)" right of them on one line, inside the SVG. On desktop the heatmap sits in the left third of a full-width card; make the cells larger (or add an "Upcoming 7 days" list beside it) so the card is not mostly empty.

    9. Day streak ignores earlier days. computeStreak() and libraryStats() only use each card's sm.lastReviewed, so re-reviewing the same cards on a second day erases the first day. Test: study 21 cards on Wed, the same 21 on Thu → streak shows 1 (expected 2). Expected: build the set of study days from every sm.history[].d entry.

    10. Session summary bars are all grey. After a Study session the Again/Hard/Good/Easy bars all compute to rgb(128,128,128): the .rc-done__bar i rule overrides .rc-done__bar--again/--hard/--good/--easy. Expected: raspberry / leather / gold / clearwater bars (e.g. .rc-done__bar i.rc-done__bar--again).

    11. Paste notes rejects separators its hint promises, and "+ New card" leaves blank cards.

      • Paste hint: "an em dash, --, : or = also works". Of these 6 lines only the first 3 became cards: Mitochondrion — powerhouse of the cell, ATP -- adenosine triphosphate, Osmosis : diffusion of water, Ribosome: makes proteins, pH = negative log of H+ concentration, Neuron—nerve cell. Expected: all 6 (colon with or without a space before it, =, and an em dash without spaces).

      • Editor: clicking "+ New card" then "Close card" saves an empty card (blank front and back) into the deck, and it then appears in Study. Expected: an unsaved new card with an empty front is discarded on close.

    12. Small layout leftovers.

      • Study tab → Start a session: <select id="study-deck"> renders 21 px tall with a thin dark border (the .rc-study__deckpick select rule is not applied). Expected: 44 px, rounded, like the Progress deck dropdown.

      • Phone Progress tab: retention-chart axis text renders about 7 px (SVG is scaled down); hardest-card questions shrink to 13–20 px wide ("W.."). Expected: axis labels ≥ 11 px on a phone, and each hardest card shows its question on its own line (stack the deck chip and stats below it at ≤ 720 px).

    11 critic 1.3 min · 4 files changed, 162 insertions(+), 132 deletions(-) Show prompt

    Prompt given to the harness:

    Read FEEDBACK.md in this directory. It lists 6 problems a reviewer still found when testing index.html in a real browser after your last round. Fix them in order, starting with item 1. For each item: read only the function or CSS rule it names (use grep/read with line ranges, the files are large), then change it with small targeted edits. Never rewrite src/app.js, src/app.css or src/body.html as a whole, and keep everything that already works. Run python3 build.py --check after every two items and fix any error it reports. Keep going until all 6 items are fixed, then run python3 build.py --check a final time.
    

    FEEDBACK.md the harness received ✎ written by the AI reviewer:

    Reviewer findings — critic re-check after round 10 (Chromium 1440×900 and 390×844 phone)

    Round 10 fixed most items (deck due-bars, "Study all due", phone editor, grade hints, heatmap dates, streak, summary colours, paste separators, test-me keys). Six problems remain. Do not rewrite or restructure any file: make small targeted edits in the places named, in this order, and run python3 build.py --check after every two items.

    1. Test me still accepts one word (or part of a word) as a correct typed answer. In answerMatches() the new "main term" check uses mainTerm.includes(tStr). When the answer has no comma or parenthesis, the main term is the whole sentence, and includes also matches partial words. Measured with answerMatches(typed, answer) in the page:

      • coincide and folded → true for "A distribution that can be folded about an axis so that the two sides coincide." (should be false)

      • data → true for "The sum of the data points divided by the number of data points: …" (should be false)

      • blue → true for "The Mountain Bluebird (Sialia currucoides), designated in 1931 …" (should be false)

      • These must stay true: mountain bluebird, Borah Peak (answer "Borah Peak, 12,662 ft, in Custer County."), square root of the variance, folded about an axis so the two sides coincide. Expected: compare whole words, not substrings; accept the main-term route only when the typed words equal the main term's key words (ignoring "the/a/an") and the main term is short (at most 4 key words); otherwise require the 60% key-word coverage rule.

    2. A blank card is still saved when the editor is closed without "Close card". "+ New card" then pressing Esc (or the ✕ button, or clicking the backdrop) leaves the empty card in the deck; the next action that calls saveState() stores it (seen in localStorage: 1 card with an empty front). Expected: whenever the editor modal closes (Esc, ✕, backdrop, "← Decks"), discard an _unsaved card whose front is empty — put the discard logic in one helper and call it from all of those paths.

    3. Study tab deck dropdown is still 21 px tall. #study-deck gets the 44 px rule from .rc-study__deckpick select, but the older rule .rc-study__deckrow select { flex: 1; min-width: 200px; } (around line 96 of src/app.css) also applies, and .rc-study__deckpick is a column flexbox, so flex: 1 (flex-basis 0) shrinks the height to 21 px. Expected: 44 px tall on desktop and phone (e.g. give .rc-study__deckpick select flex: none, or remove flex: 1 from the old rule).

    4. Phone Progress page now scrolls sideways by 122 px (regression from round 10). The new .rc-retention { min-width: 340px; } inside @media (max-width: 720px) makes the one-column progress grid 458 px wide on a 390 px screen, so the KPI panel, heatmap card and hardest-cards list all run past the right edge (a phone then zooms the page out to 512 px). Expected: no horizontal page scroll at 390 px. Remove that min-width; use grid-template-columns: minmax(0, 1fr) for .rc-progress at ≤ 900 px; keep the heatmap scrolling inside its own .rc-heatwrap; and for readable axis labels on a phone draw the retention chart with a narrower viewBox (for example W = 340 when window.innerWidth < 720) instead of a min-width.

    5. Heatmap legend "fewer" is clipped, and the desktop forecast card is two-thirds empty. In svgHeatmap() "fewer" is drawn right-aligned at x = left - 10, so it starts left of the SVG and shows as "ewer". Expected: legend row = "fewer", then the 4 swatches, then "more (N cards)", all starting at x = left and fully inside the SVG. On desktop the 16-week grid fills only the left ~40% of the full-width card: add an "Upcoming" list to the right of the heatmap (flex row that stacks below it at ≤ 720 px) showing the next 7 days, e.g. "Today — 19 cards", "Mon 14 Sep — 21 cards", using the same counts as the heatmap.

    6. Unlabelled percentage in Hardest cards. Each row ends with a gold "0%" that has no label or tooltip (it is the share of Good/Easy grades). Expected: show it as "0% good" (or add a column header / title) so a visitor can tell what it means.

    12 critic 1.1 min · 4 files changed, 122 insertions(+), 137 deletions(-) Show prompt

    Prompt given to the harness:

    Read FEEDBACK.md in this directory. It lists 4 polish problems a reviewer still found on the Progress tab when testing index.html in a real browser after your last round. Fix them in order, starting with item 1. For each item: read only the function or CSS rule it names (use grep/read with line ranges, the files are large), then change it with small targeted edits. Never rewrite src/app.js, src/app.css or src/body.html as a whole, and keep everything that already works. Run python3 build.py --check after every two items and fix any error it reports. Keep going until all 4 items are fixed, then run python3 build.py --check a final time.
    

    FEEDBACK.md the harness received ✎ written by the AI reviewer:

    Reviewer findings — critic re-check after round 11 (Chromium 1440×900 and 390×844 phone)

    Round 11 fixed all six items (typed-answer matching, blank cards, study dropdown, phone Progress overflow, "% good" label). Four polish problems remain, all on the Progress tab. Do not rewrite or restructure any file: make small targeted edits in the places named, in this order, and run python3 build.py --check after every two items.

    1. Heatmap legend: "fewer" is hidden behind the colour swatches. In svgHeatmap() the "fewer" <text> is now at x = left and the 4 swatch <rect>s also start at x = left + k * (swatch + 4), so the swatches cover the word (only a sliver shows, desktop and phone). Expected, on one line and fully inside the SVG: "fewer" at x = left, then the swatches starting about 36 px to the right of it (x = left + 36 + k * (swatch + 4)), then "more (N cards)" 8 px after the last swatch.

    2. The "Upcoming" list sits under the heatmap and uses gold text on white. svgHeatmap() returns the <ul class="rc-upcoming"> right after the </svg>, so it ends up inside .rc-heatwrap (the scrolling box) below the grid, and the right half of the full-width forecast card stays empty on desktop. Also .rc-upcoming b { color: var(--ui-pride-gold) } puts Pride Gold text on a white card, which BRAND.md forbids (and it fails contrast). Expected: svgHeatmap() returns only the SVG; build the Upcoming list in a small helper and place it in renderProgress() as the second child of .rc-heatrow, so on desktop it is a column to the right of the heatmap (give it a heading "Next 7 days" and flex: 1; max-width: 320px) and at ≤ 720 px it stacks below. Colour the counts var(--ui-gold-ink) (or var(--text)), and show days with 0 cards in var(--muted).

    3. Retention chart draws a misleading "actual" line. In svgRetentionChart() the x-axis is "days since review" (0d–30d), but the red "actual" series places each calendar day at x(span - …). After studying on two consecutive days (all Again on day 1, all Good on day 2) it draws a near-vertical red line from 0% at "0d" to 100% at "1d", which reads as nonsense. The legend ("estimated", "actual") is also drawn on top of the "90% target" label. Expected: remove the red actual-retention series and its legend from this chart (keep the estimated curve, the 90% target line and the gold "today" dot), and instead add a short line under the chart, e.g. "Last 14 days: 62% of reviews graded Good or Easy (84 reviews)", computed from retentionSeries().

    4. Retention chart labels are small on a phone. When W = 340 the SVG is drawn about 320 px wide, so the 10-unit axis and target labels render at about 9 px. Expected: when W = 340, use font-size 12 for the tick labels, the "estimated recall" label and "90% target" (≈ 11 px on screen).

What the agent was asked

The full specification the harness received, rendered from the original Markdown.

Read the specification

Recall — Spaced-repetition flashcards for any course

Category: Education Who it is for: Students in memorization-heavy courses (anatomy, languages, law, pharmacology), instructors sharing decks

What it should do

Import a CSV or paste notes, study with a proven spaced-repetition schedule, and see exactly what you know — all stored privately in your own browser.

Data

No external data. Ship two small starter decks with factual, verifiable content (e.g. 'Idaho geography & natural history basics' and 'Common statistics terms'), each card checked for accuracy.

Raw downloads (if any) are in data/raw/ with data/raw/SOURCES.md describing where each file came from. Transform what the app needs into compact JSON in data/embed/ (write a small script in scripts/ to do it, so the transformation is reproducible). Every dataset the app shows must be credited in a visible "Data & sources" section of the app, with links. If a dataset is illustrative/synthetic, label it clearly as such in the UI — never present made-up numbers as real University of Idaho figures.

Required features

  • Deck library with import from CSV/TSV (front, back, tags) and paste-to-cards (one 'term — definition' per line)

  • Study session with 3D flip animation, keyboard shortcuts, Again/Hard/Good/Easy grading and SM-2 scheduling

  • Card editor with Markdown and math (simple inline formatting), tags, search and bulk edit

  • Progress dashboard: retention curve, review forecast calendar heatmap, streaks, hardest cards

  • Cram and 'test me' modes, and export back to CSV

  • Everything persisted to localStorage with backup/restore JSON

Quality bar

This app is going into a University of Idaho gallery that shows faculty, staff and students what they can build with AI coding agents. It must look polished and modern (think a well-designed data product, not a homework demo), feel alive (smooth transitions, responsive hover/selection states, animated where it helps understanding), and do real, useful work — every control should change something meaningful. It must work well on a laptop and on a phone. Include a short "How to use" hint for first-time visitors and a helpful empty state wherever the user must supply data.

Known limitations

Reported by the independent critic. ✎ written by the AI critic

  • The retention summary is labelled 'Last 14 days' but counts every review ever made (139 reviews in testing, when the last 14 days held 14).
  • A card graded Again is not shown again later in the same session; it simply comes back the next day.
  • The grade buttons are visible before the card is flipped, and pressing 1-4 on the front grades the card without showing the answer.
  • The paste-notes splitter now splits on every colon, so a line such as 'Meeting: 10:30' gets the back '10 — 30'.
  • The retention chart picks its phone or desktop size when the Progress tab renders; resizing the browser window does not re-layout it until the tab is re-opened.
  • The 'recent retention' KPI uses the last day that had any reviews, which can be a single review several days ago.
  • Harness note: Pi rounds 6-9 produced no app changes (empty exits or stalls). The three critic rounds (193 s, 78 s, 69 s) each applied every listed fix with small targeted edits.