Tags: nyblnet/bento
Tags
Release 1.0.19 (#419) The release that makes slides usable on a phone, and gives code on a slide the morph treatment the rest of the deck already had. Checked the changelog against the COMMITS rather than against itself, which is the check that missed code morphing before v1.0.18 was cut. Two commits looked unaccounted for and both resolve: #292's formatting bar is inside the phone bundle rather than its own entry, and #351's pptx importer is kernel-only groundwork — nothing under slides/src/ imports it, and the shipped shell contains no trace of it (inflated the runtime and searched: zero markers). Notes read from --dry-run output rather than from the changelog, per the zone brief. Six lead-ins, all 1.0.19 features, none of them a fix introducing the release: Bento Slides works on a phone. Code on a slide — and it morphs. A deck can set its own morph tempo. Deck-wide brand colours. The web demo says where your deck went. Every deck you save is smaller. The date is 2026-09-04, the day of the cut. It was 2026-08-30 in the first push -- I took the date from surrounding context instead of reading the clock, which put the heading five days in the past and BEFORE eight of the commits it describes. Caught by integrator. A date is inside the signed envelope and the channel refuses to re-sign a version, so wrong at the cut is wrong permanently. Rebased onto f937419 so the base includes #417 and #418; [Unreleased] is empty and all 18 entries sit under the new heading. Claude-Session: https://claude.ai/code/session_01FqzzY5iHopxZNvScbuqk2v
Release 1.0.18 (#311) Security release. Offline mode did not block everything it promised, and one of the paths it leaked from is the update check itself — so the people most likely to want this fix are the ones who cannot reach it without doing the thing they turned the switch on to prevent. That is the argument for cutting now rather than batching. Also in: the Tray update flow finishing without a dialog, the Share popover no longer clipped inside the folded toolbar menu, and the update card losing an accent stripe that ignored the theme. Signed notes verified with --print-notes before tagging: the four 1.0.18 lead-ins lead, then two from 1.0.17 so anyone skipping a release still sees what they missed.
Prepare 1.0.17 (#289) slides/package.json 1.0.16 -> 1.0.17, and the CHANGELOG's [Unreleased] section becomes [1.0.17] - 2026-08-10. Also orders the release notes. The first six bold lead-ins become the notes inside the SIGNED manifest, and re-signing a version is refused, so the order is not revisable after the cut. They were in merge order, which put two minor fixes above the headline feature. Now: the security fix, the dark interface, hide a slide, the shared-deck warning, the live-session crash, the toolbar cut off the right edge. Verified a pure permutation - every non-blank line preserved exactly - and every entry checked against v1.0.16 to confirm it describes a bug that actually shipped.
Release 1.0.16 (#231) A single-fix release for a regression I shipped in 1.0.14: the pan room added to the canvas moved the slide within the scrollable area without moving the view with it, so a deck whose stage outgrows the canvas opened parked in the empty margin -- slide shoved to one side and clipped. Every 1600x900 deck on an ordinary laptop, with no zooming required to reach it. Held to one entry deliberately. The other commits since v1.0.15 are dash M0, decision records and publish tooling; none of them change the slides shell, and a release announcing a fix should say that and nothing else.
changelog: the collab property-removal crash (#219) (#221) It is the reason for the next release and had no entry, so release.mjs would have signed a manifest whose notes did not mention it. The notes ride in the signed envelope and are what people read in the About dialog while deciding whether to update -- for a fix to a crash they have been hitting, that is the one line that matters.
dash: formulas and charts (#235) The two things a first release cannot ship without. 43 KB shell. FORMULAS — one expression per COLUMN, which is the largest structural improvement over a spreadsheet available here. Excel stores a formula per CELL, so a 100k-row model with twelve computed columns has 1.2 MILLION graph nodes, each carrying its own copy of the same expression and its own ranges that shift when a row is inserted. Here it is twelve nodes and twelve stored strings, and inserting a row changes nothing at all: the #REF! class and the shifted-VLOOKUP class do not exist, because there is no range to shift. Evaluation is VECTORISED. Every node returns a scalar or a column of n values and the two combine by broadcasting, so `Value * Rate` is one pass over two arrays, and `Value / SUM(Value)` mixes a column with an aggregate without either side knowing about the other. ~50 functions including SUMIF/COUNTIF/ AVERAGEIF, which are high-frequency enough to be v1. Recalculation is Kahn over columns. Order is derived, not declared -- a column declared before the one it depends on still computes second -- and anything left when the queue drains reads #CYCLE! rather than a plausible number. TODAY() is FROZEN from the document rather than banned. Two of the three design proposals banned volatiles for determinism; that sends people to hard-coding a date, which is worse. The value is stamped in, so every reader of a saved file sees the same number. CHARTS — a tile NAMES a sheet and columns, and the series are derived at render and never stored. Slides learned this the expensive way with syncLinkedChart: a chart carrying its own copy of the numbers can disagree with the table beside it, go stale silently, and doubles the file. Promoted from a special case to the rule, and verified: the document contains no series array and no computed values, and editing a cell rescales the chart. TWO BUGS WORTH RECORDING. A self-reference was not a cycle. `a = a + 1` had its self-edge excluded from the dependency set, so indegree 0, so it drained from the queue and computed against its own stale values -- producing a number. Self-edges are now included and it reports #CYCLE!. The default chart put a PERCENT column on the same axis as money. 0-to-1 beside tens of thousands draws no visible bar, so the legend named a series the reader could not see -- which reads as missing data rather than as a wrong scale. Percent is now excluded unless it is all there is. AND A BAD MEASUREMENT, mine: I first "verified" the chart updates on edit by sorting bar y-positions and comparing the lowest three, which cannot distinguish a rescale from no change and reported a false negative. The axis labels going from 0-60,000 to 0-250,000 is the observation that actually shows it. 69 new checks across two rigs, each verified against reintroduced regressions: nulls-as-zeroes loses 2, alphabetical categories 1, percent-in-default 1, self-edges-excluded 1, errors-as-zero 5.
dash 0.1.0: version, changelog, and per-app release notes (#234) Two things, both needed before dash can be released at all. dash/package.json 0.0.1 -> 0.1.0. That version is APP_VERSION in the shell and the version in the signed manifest, and it is what a shipped file compares against to decide whether an update is for it. release.mjs reads a PER-APP CHANGELOG when one exists. The root CHANGELOG.md is slides' -- it says so in its own first line -- and its versions are 1.0.x, so a second app releasing 0.1.0 matched no section and would have shipped a manifest with no notes at all. Those notes are what a reader sees inline in the About dialog while deciding whether to take the update, so an empty set is not a cosmetic loss. Falls back to the root changelog, so slides and spaces are unaffected. dash/CHANGELOG.md is the first entry, written for that dialog: what the release IS rather than what was merged last, with lead-ins that carry information on their own because in the dialog the lead-in is all the reader gets.
Release 1.0.14 (#203) Version bump plus the CHANGELOG in RELEASE order rather than merge order: the first five bold lead-ins become the notes in the SIGNED manifest, and in the About dialog the lead-in is all a reader gets while deciding whether to update. Left alone, a gallery template font fix would have introduced the release. The two morph fixes are merged into one entry because they are one story -- entrances and count-ups were both skipped wholesale on morph arrivals, and both now run per element depending on whether it has a morph partner. Two entries would have spent two of the five slots saying the same thing twice.
Release 1.0.13 — transitions, clipboard fonts, spanning update notes (#… …186) Two contributed fixes and one of ours. Fade, slide and zoom had been instant cuts, not animations — Reveal's viewDistance was 1, so the slide being moved TO was never mounted and the CSS transition had nothing to animate into. Broken since c6ca5a4, long before 1.0.11. Found and fixed by James London. Copy-paste lost embedded typefaces: elements carried no fonts at all, slides carried every face in the source deck while omitting the bytes they pointed at. Fixed by Kushida, with a rig that reports 3/10 against the unfixed code. And update notes now span the versions a reader skipped, which this release needed immediately: 1.0.12 was a day old, so almost everyone updating to 1.0.13 would otherwise never have learned what it contained. Verified: the spanning notes string carries both fixes plus the three 1.0.12 headlines, each tagged with its version. tsc, language coverage, packed-table check and shell-gate all pass.
i18n: bring every catalog and pack to 100%, and gate it in CI (#182) Portuguese was missing three CORE strings — the Slideshow panel's Slide number, Progress bar and Corner arrows. Core catalogs are compiled into every saved file, so a hole there ships as English inside an otherwise translated interface, in every deck anyone saves, and cannot be corrected without cutting a release. All 8 core locales are now complete. All 22 packs were 16 strings behind: the slideshow toggles from 1.0.11, the laser pointer, and the file-identity and drop-to-open messages from 1.0.12. Every pack is now at 100%. Turkmen needed one extra. It was written against 'restore earlier versions from About - Version history', which #168 renamed to 'Save - Version history', so the pack carried a key the source no longer has. That is exactly the pack/shell key drift documented in RELEASING.md, showing up in the opposite direction: a pack written before a rename rather than after. New gate: scripts/test-i18n-coverage.mjs, wired into CI. Two rules, because the two kinds of catalog fail differently. CORE must be 100% or the build fails. PACKS get a floor (90%) plus a printed report: they are downloaded on demand and re-publishable without an app release, so a hard gate there would block every feature release that adds a string, while a collapse still gets caught. It reads the generated packed.ts for the key universe — the same source build-i18n.mjs uses, so the gate and the generator cannot disagree — and it evaluates pack modules rather than regexing them. Both of those are deliberate: build-i18n.mjs records that 'a regex over the source silently missed 54 of 650 entries', and a first attempt at this gate read each pack's exported label instead of its strings and counted the characters of a Korean word. Negative control: removing one core string makes it exit 1; restoring it exits 0. A gate nobody has watched fail is not a gate.
PreviousNext