Repository navigation
Releases: sarang-cmd/bench
Release list
v1.2.8
1.2.8 - 2026-11-01
The site's page check has been red since 1.2.6, and the release went out anyway:
the add-in build, the core tests, the WebAssembly build and the toolchain job all
passed, so Bench-1.2.7.g3a and its zip are real - only "Site build and page
checks" failed, and it has been failing the same way since I added the starter
pack card to /downloads.
-
check-pages.mjschecked a file nothing had fetched. A fresh checkout has
nosite/public/Bench-*.g3aand nosite/public/Bench-starterpack-*.zip; both
are gitignored andfetch-addin.mjsputs them there duringnpm run build,
which runs after the page check. So the new "the zip the page offers is
really there, and hashes to what the page prints" check reported
"described but missing from public/" on every run. It now runs
fetch-addin.mjsitself before rendering, exactly as it already ran
fetch-spike.mjsfor the same reason; a failure there is reported, not fatal,
because the page still renders and the checks still say what is missing. -
The add-in gets the same check: the page prints a size and a SHA-256 for
the.g3a, and that file is now compared with them too, so a stale download in
public/cannot be served under a hash that belongs to a different build. -
Reproduced before fixing: a fresh
git clone --branch v1.2.7,npm ci,
node scripts/check-pages.mjsfails with exactly the CI message
(FAIL starter pack zip: Bench-starterpack-1.2.7.zip is described but missing from public/), and passes after the change. -
dist/keeps one starter pack zip:Bench-starterpack-1.2.8.zip(the ten
files, unchanged since 1.2.7), so the repository does not accumulate a copy per
release. The release job already deletes the old one before copying the new.
Nothing about the add-in changed: no C, no screen, no key. The tag exists so the
pipeline that builds a release is green end to end: the v1.2.7 tag points at a
commit from before this fix, so its own site job stays red for good.
v1.2.7
1.2.7 - 2026-11-01
Wording, not behaviour: the demo is the starter pack now. Everything the
add-in, the zip, the repository and the site call it uses one name, because
"demo" was doing three jobs at once - a demo of the software, throwaway sample
data, and the files a new install needs to have something to read.
- Every user-facing mention says starter pack: the README section, the
downloads page card,docs/TUTORIAL.md,docs/STATUS.md,dist/README.md,
the hardware checklist and the in-app comments. No screen inside the add-in
said "demo", so no tour script changed its content; step 99 is still the
first-run screenshot and the image is now99_starterpack_seeded.png. - The names on disk follow:
demo/isstarterpack/,
Bench-demo-<version>.zipisBench-starterpack-<version>.zip,
tools/gen_demo.pyistools/gen_starterpack.py,
tools/make_demo_zip.pyistools/make_starterpack_zip.py, and the make
targets arestarterpack-gen,starterpack-check,starterpack-zipand
starterpack-zip-check. So is the code:src/platform/starter.{h,c}
(starter_install()),src/apps/starter_data.{h,c}(starter_files[],
starter_file_count), andtests/test_starter_data.c,
tests/test_starter_files.c,tools/test_starterpack.py. - The wasm build follows too: the file the browser simulator seeds its
in-memory filesystem with isstarterpack.json, and the worker's message key
isstarterpack. - What did not change: the ten files, their text, the destination folders
(Bench/notes,Bench/cards,Bench/study,Bench/formulas), the rule that
only missing files are written, the ASCII-only check and the size budget. The
cards gained a few bytes because their own first line said "sample content for
the demo folder" and now says "starter pack folder" - 17 877 B becomes
17 901 B, and the zip 10 479 B becomes 10 495 B. Unverified on device. - 1.2.6 keeps its own names: that release carries
Bench-1.2.6.g3aand
Bench-demo-1.2.6.zip, and its entry below still says demo, because that is
what it shipped. From this version on, the file to download is
Bench-starterpack-1.2.7.zip. - two things the rename broke, both fixed here: the wasm build looked for a
directory calledstarter pack(a path hit by the rename), found none, and
wrote a zero-file seed - the browser simulator would have booted with an empty
card; it now fails the build rather than ship an empty seed. And
BENCH_NO_STARTERPACK=counted as "set", because the tour passes an empty
value when it wants the seed kept, so the first-run screenshot showed an empty
card. It reads the value now, and step 99 runs against a fresh filesystem.
v1.2.6
1.2.6 - 2026-11-01
Numbers here describe the source in main. The release carries
Bench-1.2.6.g3a built by CI from this commit, and nobody has had it on a
calculator yet.
- The demo travels inside the add-in now: a
.g3ais one file, so a folder
cannot come with it, and "copydemo/notesintoBench/notes" was three steps
on a PC before a new install had anything to look at. The ten demo files - the
three notes, the three decks, the study log and the three formula booklets -
are compiled into the add-in as C literals and written to the card on the first
run, so a fresh install opens Notes, Cards, Study log and Formula book and
finds something in every one. Rules: only files that are not there yet are
written, so nothing you wrote is ever overwritten, and at most twelve files are
written per run. The text is generated fromdemo/and
docs/samples/formulas/bytools/gen_demo.py;make demo-checkfails when
the generated table and the sources drift apart, andtests/test_demo_data.c
reads every entry back with the same checks (printable ASCII,lenequal to
the joined length, no duplicate, source file unchanged). One booklet is over
the 4095 bytes ISO C promises for a string literal, so each file is a list of
chunks the add-in joins before writing - the generator refuses anything over
6144 bytes, the sizestore_write()takes. Unverified on device. - The same demo is a separate download too:
Bench-demo-1.2.6.zipholds
Bench/notes,Bench/cards,Bench/studyandBench/formulas, so it
extracts ontoD:\in USB Flash mode and lands exactly where the add-in
writes. It is for a full card, a second card, or editing the notes on a PC
before they ever reach the calculator. Built bytools/make_demo_zip.py,
reproducible (sorted entries, fixed timestamps), checked in CI against the same
sources, attached to the release and kept indist/. store_exists(): the seeding needed a way to ask whether a file is there
without reading it, sosrc/platform/store.{h,c}gained one (aBFile_Open
in a world switch, closed immediately, no read).src/platform/demo.cis the
only caller and never touches anything else.- What this does not do: it does not touch a file that already exists, does
not run anywhere but start-up, and does not write anything outside
\fls0\Bench. A card that is full or write-protected still gets a working
add-in, just without the demo -demo_install()ignores the failure.
v1.2.3
1.2.3 - 2026-11-01
Numbers here describe the source in main, not a run on hardware: 1.2.3 is
built by CI from this commit, and nobody has had it on a calculator yet.
-
The calculator build has been failing since the Pi game landed:
app_pi.ccallsnt_appendwithout includingui/numtext.h. The host
preview took it as a warning and drew a perfect screenshot; the fxSDK build
runs-Werror=implicit-function-declarationand stopped, so there has been no
.g3asince 1.1.0 and the tagged release for 1.2.2 could not exist. The
include is one line; the reason it went unseen for four merges is that the two
builds disagreed about which warnings matter, so the preview now compiles with
the same-Werror=implicit-function-declarationas the calculator and the
candidate.g3acannot be the only thing that finds it. -
The committed WebAssembly build is rebuilt from these sources, so the
simulator on the site is the same code as the screenshots again. Its smoke
runs (down,exeand the worker path) pass. Unverified on device. -
The screen checker can see a label sitting on a border: it compared
rectangles, so two things that merely touched were "not overlapping" and
passed. The menu's first-run hint spent eleven merged pull requests with its
ascenders on the bottom tile border, and 97 green screenshots said nothing
about it.scr_frameis traced now -scr_fillrecords only panels of 8x4 or
more, and a two-pixel border is exactly the size that goes wrong - and a label
within two pixels of any frame, inside or out, fails the run. Checked against
the old layout: it reports the hint and nothing else, so the rule has teeth
without inventing work on the other 96 screens.docs/design.mdlists it.
Unverified on device. -
The softkey bar has room to breathe, and the first-run hint is no longer
jammed into the tiles: a 10-pixel label in a 16-pixel bar left three pixels
above and below, so the six labels read as text pressed into a slot rather
than six buttons. The bar is 20 pixels now, dividers stop short of its top and
bottom edges, a label keeps at least four pixels from the separator beside it
and is ellipsised rather than run into its neighbour, and the bar grows into
the content area on all thirteen screens at once because every screen places
its footer relative toTH_SOFT_H. The menu's first-run hint also had its
ascenders on the bottom tile border: it now has its own band, sized from the
text, and the grid stops clear of it, so there are eight pixels above the
words and five below. The line also lost the words "a tile" so it keeps a
margin at both ends instead of running edge to edge. Unverified on device. -
The site was not deploying at all:
node scripts/gen-tools.mjshas failed
on every push since the four V2 tools landed, because each says in its own
words what it does andsite/src/toolCopy.jsstill listed twenty-two of them.
The build reported "registry tool "factor" (Prime factors) has no copy" and
stopped, so the last successful deployment predates Prime factors, Percentages,
the Formula book and the Pi game. All four are intoolCopy.jsnow, with their
real screenshots, and are in the "own words" set that needs proofreading. -
The download picks the newest build by version, not by file date:
dist/
is a git checkout, so every.g3ain it is written at the same moment and the
order the filesystem hands back decided which one the page offered. It offered
1.0.0 while 1.1.0 sat beside it. The fallback compares the numbers in the file
name now, and a build's commit and date are dropped when the bytes came from a
different file than the oneBUILD.txtdescribes. -
CodeRabbit, configured in the repository instead of a dashboard:
.coderabbit.yamltells the reviewer what this project actually breaks on -
src/coremust not include gint or libm, a screen may only use the nine
palette colours with 2 px ink borders and a 3 px shadow under the selected
item, a new core function needs a test with a concrete vector, a regenerated
table is not a code change, and files are written to flash only at session
end. Generated files, images, binaries and the site lockfile are out of scope,
poems and UML diagrams are off, and automatic approvals are off because
merging here depends on whether anyone ran the build on a calculator.
tools/check_coderabbit.pyparses the YAML with its own small reader - no new
dependency - and rejects an unknown key, apath_instructionsglob that
matches no file (how a rule for a renamed directory stops applying), a tool
switched on with no config file or for a language the repository does not
contain, tabs and CRLF.make coderabbit-checkruns it and CI runs that.
Installing the GitHub App is the one step a commit cannot do;
docs/CODERABBIT.mdhas the four clicks. Unverified on device. -
A version number that moves with the work, and a check that it did: the
tree said 1.1.0 through fourteen merged pull requests, so the About screen, the
.g3aname and the website would have disagreed with the changelog the moment
anything shipped. The rule is now that every change bumps the version in the
same commit - patch for a fix or a doc, minor for a feature, major only for a
storage-layout change - and the version of record is 1.2.0.tools/ bump_version.pyrewritesversion.txt, thesrc/version.hfallback and the
example file name inCMakeLists.txtin one command (make bump-minor,
make bump-patch), and--checkcompares those against the changelog heading
and the README badge, naming each file that disagrees.make testruns it, and
so does CI, so a forgotten bump fails a build instead of shipping. 21 Python
tests cover the arithmetic and the rewriting, including that a bad version is
refused before any file is touched. The README's version badge now links to the
releases page rather than toreleases/tag/v<version>, because between a bump
and a release there is no such tag and a badge pointing at a 404 is a lie about
a page. Unverified on device. -
Percentages tool: the four questions a paper asks - percentage change,
add or take a percentage, reverse percentage, compound growth or depreciation -
on one Math screen, with the working written out under the answer. The point
of the reverse question is that it divides (34 / (1 - 15/100) = 40), which is
what people get wrong by adding 15% of 34 back on.src/core/percent.cwith 41
checks covers the vectors (500 at 4.5% for 7 years is 680.43; a car at 12% for
5 years keeps 52.8%), zero years, a negative rate, and the three questions with
no answer - a change from zero, a 100% discount, a period count outside 0..200- each of which is a sentence on screen rather than a 0 or an inf. One bug
caught by the tests before the screen existed: the fast exponentiation gave up
on an overflow by returning the principal, so a question with an unshowable
answer said "no growth". Unverified on device.
- each of which is a sentence on screen rather than a 0 or an inf. One bug
-
The formula book: the IB AA HL, Physics 2025 and Chemistry 2025 booklet
content, as a Study tile called Formula book. The booklets are plain text in
Bench/formulas/, one.txtper booklet, so a teacher (or you) can add one
without a rebuild - the list shows every file in the folder and its first#
line as the description. The viewer scrolls a line at a time and jumps a
topic at a time with LEFT/RIGHT, headings coloured red, blue and ink by
level. Newsrc/core/formula.cholds the line and heading arithmetic with 40
checks, including that a jump ignores###sub-headings - with those counted,
a booklet with a heading every few lines moved five lines a press, which is
not a section.
The content is a transcription nobody has proofread yet: the PDFs print
formulae as images, so the text was typed, and it is marked as unproofread in
three places - the first line of every booklet,docs/samples/formulas/ needs-human-proofreading/README.md, and the help page. Treat an unproofed
line as unchecked. -
The Pi game: a Study tile. The digits you have earned stay on screen,
grouped five to a line; type the next ones, EXE checks them, and the first
wrong digit costs a life. Three lives, F2 gives the next digit away and costs
one - a hint that is free is not part of a game - and the round ends with how
far you got and the best of the session. Nothing is written to the card, so
the best score lives and dies with the session, which is what the file-write
rule allows. The digits aresrc/core/pi.c: 200 of them, and
tests/test_pi.cchecks the table against a Rabinowitz-Wagon spigot computed
from the algorithm rather than copied - a typo in the table cannot hide by
being duplicated in the test (40 checks, first 100 digits plus the human
check that the 100th decimal is 9).pi_matchstops at the first wrong digit
so a guess that runs off the end cannot read past the table.
Unverified on device. -
Prime factors, on its own screen in Math: factorisation existed, three
levels down a list of nine Number theory functions, which is not where anyone
looks for it. The new screen takes a number up to 18 digits and shows the
factorisation written out -360 = 2^3 x 3^2 x 5- with the four numbers that
follow from it: divisor count, divisor sum, totient and square-free part, plus
how many distinct primes and whether the number is a perfect square. F2 halves
the number and factors again, which is the question that usually comes next.
New incore/numtheory.c, each with vectors checked by hand (1091 checks in
that suite):nt_factor_text(exact buffer arithmetic, so a text of exactly
the buffer's length is accepted and one byte less refused),
nt_divisor_count,nt_divisor_sum(the geometric series without a division,
wrapping ...
v1.1.0
1.1.0 - 2026-11-01
The two bugs from the first hardware session, the V2 tools, and the machinery
that stops the next one. Not run on a device yet: the 1.0.0 rows in
docs/HARDWARE.md are the only hardware results that exist.
-
A hardware report you can fill in on the calculator (V2, workstream J):
Settings gained F3, which opens a screen listing the eight assumptions
Bench makes about the CASIO filesystem, the font, ALPHA, the clock and the
frame time. Each row starts atnot tried; LEFT/RIGHT marks itworksor
failsafter the matching test indocs/HARDWARE.md. F2 writes
state/hwreport.txtin plain text, so the result comes off the calculator by
copy rather than by retyping, and nothing is written at any other moment.
The formatter issrc/core/hwreport.c(63 native checks, including a buffer
that is one byte too small), anddocs/HARDWARE.mdsays how the file slots
into the report. -
A shared number field and a history of answers (V2, workstream A5):
src/core/numedit.cis the one place that decides what a numeric field
accepts - digits, at most one dot, a lone zero replaced rather than stacked, a
leading dot turned into0.- withnumedit_valid()for "would numparse read
this?" (54 checks). The moles screen was carrying its own copy, which is how
1.2.3got in; it now uses the shared one.src/core/history.ckeeps the last
eight formatted results (33 checks) and the Root finder pushes every solve onto
it, with F4 to show the list - a panel, not a file, so nothing is written to
flash. -
WebAssembly build, and the loader that copes without it (V2, workstream
G):tools/sim/sim.cgains an__EMSCRIPTEN__path - keys from the page,
the framebuffer handed back as RGBA - andtools/wasm/build.shcompiles the
same sources the screenshots come from with emscripten and Asyncify. The
binary is a build artifact and is not in git: the site's/simulatorpage
loads it when this deployment has one and says so in one line when it does
not, and the gallery stays underneath either way. CI has an optional job for
it. Not built or run here: there is no emscripten in this environment, so
the C is unverified by compilation. -
Browser widths in CI (V2, workstream B):
site/scripts/check-widths.mjs
loads all eight routes at 320, 390, 768, 1024 and 1440 px and fails on a
horizontal scrollbar, an element that crosses the right edge or one wider than
the viewport. Chromium could not be downloaded here, so the sweep has only run
in CI; the result of that first run is in the pull request. -
Demo content (V2, workstream D):
demo/holds three notes, three decks
and a fortnight study log so a fresh install is not three empty screens. The
text is written from scratch, not copied from a booklet or a past paper, and
demo/README.mdsays in its first section that it needs human proofreading.
tests/test_demo_files.creads every demo file with the add-in's own parsers
(108 checks) and fails on a single skipped line, so the sample cannot rot into
something the calculator refuses to read. -
The site is eight pages, not one (V2):
/features,/simulator,
/tutorial,/install,/downloads,/changelogand/aboutjoin the
landing page, which keeps its layout.src/router.jsxis a 120-line path
switch with real<a href>s, so back, forward, middle-click and a shared link
all work;vercel.jsonrewrites every path toindex.html. Every route sets
its own title, description, canonical and Open Graph image.
scripts/gen-stats.mjsandscripts/gen-changelog.mjswrite the numbers and
the changelog fromCHANGELOG.md,docs/tools.jsonandsrc/, and
scripts/check-pages.mjsrenders all eight routes in Node and fails the build
if one throws. Eight 1200x630 Open Graph cards come from
tools/brand/make_brand.py. The canonical URL is now
bench-gdc.vercel.appeverywhere;sitemap.xmllists all eight
routes. -
The simulator page is honest about the simulator: the interactive
WebAssembly build (workstream G) is not done, and the page says so instead of
pretending. What it shows today is the real frame buffer: 75 captures made by
the add-in's own simulator. -
Settings, five rows (V2):
src/core/settings.cgains two keys,
angle_unit(0 degrees, 1 radians) andtour_done(0 or 1). The screen now
lists the unit the Triangle tool opens in and whether the first-run line on
the home screen has been read;app_triangle_init()takes its starting unit
from the setting, and F3/F4 still switch for that session only, without
writing the file. A settings file from 1.0.0 still loads: the new keys fall
back to their defaults. 687 native checks intests/test_settings.c.
Unverified on device. -
First-run hint (V2): with
tour_done 0the home screen prints one line
above the softkeys - "F1-F4 categories, F5 explains a tile, EXE opens it" -
and opening help with F5 setstour_doneand writes the file once. -
Complex numbers (F6):
src/core/cplx.cadds, subtracts, multiplies,
divides (division by zero is a NaN, not a wrong number), raises to an integer
power and reports the modulus, the argument (withbm_atan2, new in
src/core/mathfn.c) and the polar form.src/apps/app_cplx.cshows all three
at once, F2 cycles the operation, F3/F4 pick degrees or radians in the title
bar. 37 native checks. Unverified on device. -
The M1 spike has its own artifact. It used to ride inside
bench-g3a,
next to the add-in, so the thing you download to get Bench offered two
.g3afiles and one of them printed diagnostics.bench-g3anow holds
Bench-<version>.g3aand nothing else; the spike is inbench-spike. It was
never a release asset and still is not. -
Root finder (F4):
src/core/roots.cdoes bisection, Newton (numeric
derivative, step 1e-6) and the secant method, keeping every iterate so the
screen can show n, x, f(x) and the step size.src/apps/app_roots.csolves
from the shared expression engine, F2 cycles the method, F3 solves, and a
small plot marks each iterate on the curve. A bracket with no sign change, a
zero slope and a parse error each get their own sentence and column. 40
native checks. Unverified on device. -
Statistics with working (F7):
src/core/stats.cgives n, sum, mean,
median, mode, range, both quartile methods, the outlier fences and the
population and sample standard deviations (53 native checks). Paired data
gets the least squares line, r and r squared.src/apps/app_stats.cadds
values as you type them, shows the summary and a box plot, has a screen for
the working and a screen for the regression. Unverified on device. -
SUVAT and projectiles (F10):
src/core/suvat.csolves any three of s, u,
v, a and t, one table entry per triple, and reports the equation each answer
came from; when a quadratic gives two sensible times it keeps the first and
names the second (73 native checks).src/apps/app_suvat.cfills the grid as
you type, marks worked-out values with a dot, and draws the flight path for a
launch speed, angle and height. Unverified on device. -
Moles and solutions (F11):
src/core/chem.ccovers n = m / Mr, c = n / V,
pV = nRT with R in kPa dm3, dilution and the two percentages, refusing a zero
where a formula divides (47 native checks).src/apps/app_moles.chas one
mode per family, opens each on a worked example, and writes the substitution
out under the answer. Unverified on device. -
Base and bits (F12):
src/core/base.cparses and prints any base from 2
to 36, writes two's complement at 8, 16 and 32 bits (hex padded to the width,
binary grouped in fours), and does AND, OR, XOR and logical shifts, refusing a
shift of 63 or more (78 native checks).src/apps/app_base.cshows one value
in five bases with all three widths, and a second tab for the operators; F2
opens the letter keyboard because the keypad has no A-F keys. Unverified on
device. -
Lab graph (F8):
src/core/graph.cfits a line to measured points and
quotes the standard error of the gradient and the intercept from the
residuals, plus a round axis range for the plot (42 native checks).
src/apps/app_graph.ctakes x, y and an error per point, lists them with the
fit, and draws the graph with a bar through each point and the line of best
fit. Unverified on device. -
Study log (F13), Notes v2 (F14) and Cards v2 (F15): a plain text
log of what you studied and for how long, with totals, days logged and the
longest streak (src/core/logbook.c, 56 native checks); the Notes footer now
counts words as well as lines (textsearch_words, 6 more checks); and a
Cards deck can be drilled in a mixed order inside each box
(leitner_shuffle, deterministic for a session, 8 more checks). Bench cannot
read the calendar - gint's date fields were never checked on the hardware - so
a log entry takes the day after the newest one and UP/DOWN moves it.
Unverified on device.
Fixed
- Home tiles: the icon vanished on the selected tile. The icon was painted
in the tool's accent colour on a tile filled with that same colour. Every
foreground is now chosen by measurement (col_better_on), the icon is drawn
with a 2 px outline, and a check samples the pixels afterwards. This is
unverified on device: nobody has looked at the new screen on a calculator yet. - Labels drawn in a colour too close to their background. Ink on red is
2.75:1, paper on teal 3.00:1, a red cursor on the yellow field 2.91:1. Text is
now ink or blue on paper, and a selected tile is ink with paper text instead
of a tinted tile with a paper plate under the label. - The keyboard covered half of the note behind it. The modal now clears the
content area first, and the space key is marked instead of being drawn as an
empty cell....
v1.0.0
1.0.0 - 2026-10-31
First release. One add-in, five tools, settings and an About screen.
Added
- Shell: home screen with six tiles in the Bauhaus palette, title bar,
softkey bar, lists, fields, modals, a progress bar and an on-screen keyboard.
src/platform/{screen,input,store,mem}are the only files that call gint;
src/apps/app_menu.croutes,src/main.cruns the loop. - Pacer (
src/apps/app_pacer.c): setup, plan with the checkpoint table,
run with clock, marks, target, gap line and next checkpoint, done screen with
the final gap. - Uncertainty (
src/apps/app_uncert.c): six operations, chain mode, value
and absolute and percentage uncertainty on the result screen. - Cards (
src/apps/app_cards.c): deck list, deck report with problem lines,
session with reveal, summary, box statistics; progress file written once at
the end of a session. - Notes (
src/apps/app_notes.c): file list, Markdown and plain text
rendering, scroll by line and page, search with wrap, heading list, per-line
span drawing with the Phase A style (colour and underline). - Number theory (
src/apps/app_numtheory.c): nine functions, forms,
results with steps for gcd and ext gcd, a progress bar for factorisation that
EXIT cancels. - Settings (
src/apps/app_settings.c,src/core/settings.c): uncertainty
figures, pacer checkpoint size, note width; the file is written only when a
value changes. - About (
src/apps/app_about.c): version, build date, target, framebuffer
and window sizes, largest free block, limits, and the Exam Mode note. - Brand:
assets-cg/icon-uns.pngandicon-sel.png(92x64, neobrutalist
B with a red square and three bars), a wordmark SVG and a 1200x630 card, all
drawn bytools/brand/make_brand.py. No bitmap fonts, no external assets. - Host preview:
tools/sim/(a gint stand-in, key scripts and a tour) and
make sim,make shots, which render every screen todocs/images. - CI:
.github/workflows/build.ymlruns the native tests, the Python
tests, the preview, and buildsBench-<version>.g3awith the real fxSDK,
attaching it to the release on av*tag. - Docs:
README.md,docs/STATUS.md,docs/toolchain.md,docs/spike.md,
site/(the landing page: React 18 + Vite + Tailwind, deployed on Vercel).
Storage layout (new)
Bench/notes/*.md|*.txt notes (Notes)
Bench/cards/*.txt decks, "question | answer" a line (Cards)
Bench/state/cards.sav "# Bench cards state v1", "session N", "<hash> <box>"
Bench/state/settings.cfg "key value" lines, written on change only
The folder tree is created on first run. Files are written once and renamed
into place; the calculator's filesystem needs even-sized writes, so an
odd-length text file is padded with a newline.
Notes
- Screen geometry: 396x224 framebuffer, the OS shows the middle 384x216, so
every drawing call goes throughsrc/platform/screen.cand itsSCR_X,
SCR_Yoffset. No app knows the offset exists. - Colours are raw RGB565 words rather than
C_RGB(): gint's macro shifts green
by six while its own constants put green at bits 5..10, so the macro would
move green one bit. The three palette colours are written out intheme.h
with the hex they came from. - Text entry never relies on ALPHA: the search field uses the on-screen
keyboard, so a wrong ALPHA mapping cannot break input.
Test log
make test NATIVE TESTS PASSED (11 test programs)
cards 95, leitner 126, md_layout 95, md_parse 203, numfmt 182,
numparse 62, numtheory 1027, pacer 114, settings 659,
textsearch 84, uncert 144 -> 2791 checks, 0 failed
make py-test 28 tests, OK
make sim ok
make shots 26 screens rendered
Calculator side: not run by the agent (no fxSDK and no hardware here, see
docs/STATUS.md), so this version is 1.0.0 of the code, not a hardware-tested
release.
Bench - automatic build from main
Automatic build
Bench 1.0.0, built from the tip of main on 2026-10-31 (commit ea94a10).
Replaces the previous automatic build. For the released version, use the
tagged release instead.
What is in it
- Merge pull request #14 from sarang-cmd/arena/300c6ae2-bench
- CI: run the automatic build once on push, to prove it end to end
- Merge pull request #13 from sarang-cmd/arena/300c6ae2-bench
- CI: a rolling automatic build every few days
- Merge pull request #12 from sarang-cmd/arena/ad6d6f87-bench
- Docs: the release exists, and here is where the file is
- Merge pull request #11 from sarang-cmd/arena/ad6d6f87-bench
- CI: give the release what it needs
- Merge pull request #8 from sarang-cmd/arena/c64871cf-bench
- Fix the .g3a copy that failed the link step; split the toolchain job