master
Drew Owens Publish 0.60.0 6600ce8

three-musketeers build: adom-gantt 0.57.0 and 0.57.1, 2026-09-29

What was built

adom-gantt 0.57.1, in gantt.html (server.js is unchanged), plus the package's first browser test suite, test/ui_test.mjs.

  • Collapse all / Expand all. One button at the start of the legend row. It persists across a refresh and the Table lens agrees with the chart.
  • Text size survives a refresh. It did not, for two reasons: an exported snapshot discarded every saved preference, and in the live app a second open tab wrote its old size back over the new one. Both are fixed. Preferences are now written key by key, so no tab can overwrite what another tab changed.
  • Quieter header. The bold repeat of the title and the dimmed description are gone. The brand block shows appName, or the project title when there is none.
  • Exact start date at every cell size.
  • Project Duration and Time Remaining replace the axis cell count ("25 weeks"). On the reference launch plan, on 2026-09-29, they read 16w 4d and 15w 3d. They ignore the cell size, update on every kind of edit, and leave cancelled rows out.
  • The legend wraps, so all 20 sections are visible and clickable.
  • The header fits by measuring, not by pixel breakpoints, so the readouts are never clipped and no control runs off screen from 320 to 2000px.

Independently verified state: a verifier drove all six behaviours in real Chrome and passed them with no page errors. The orchestrator re-ran the suite outside the builder: see Convergence for the final counts.

Decisions for you

  1. Re-export the launch plan wiki snapshot. the launch plan page carries gantt/index.html, exported by 0.56.0. It keeps the text-size bug until it is exported again from 0.57.1. Recommendation: re-export and push. Cost of not doing it: anyone reading the plan on the wiki still loses their text size on refresh.
  2. Cancelled rows and the start date. Duration and Remaining leave cancelled rows out. The start button still counts them, because it shifts the whole plan. On a plan whose earliest row is cancelled the two dates differ; each tooltip says why. Recommendation: keep. The alternative is a start button that moves rows it does not show.
  3. Time Remaining before the plan starts counts from today to the plan's end, so it can exceed Duration, with a visible "not started" note. Recommendation: keep, since the request was for a figure that accounts for today's date.
  4. Phone width. At 393px the header takes four rows and the legend chips become colour dots. Everything is reachable, but it is not a designed phone layout. Recommendation: leave until someone actually uses the plan on a phone.
  5. The suite now takes 12 to 14 minutes. --only runs a subset. Recommendation: subset while working, full run before a publish.

Key decisions made during the build

  • Text size had two causes, not one. The plan suspected the snapshot. The builder reproduced a second cause in the live app (the stale tab) before changing any code.
  • Merge-on-write preferences. The first fix synced only the text size between tabs. The adversary showed the same overwrite still destroyed the collapse state, so the fix moved to the root: a save writes only the keys this tab changed.
  • A measured header fit. The first build used pixel breakpoints, and the adversary showed the readouts clipped or hidden at 1280, 1366 and 1680. Breakpoints go stale the moment someone adds a button, so the header now measures itself.
  • Collapse all lives in the legend, because the legend is the one row present in both the chart and the table.
  • Cancelled rows are out of the clock, matching auto-schedule, the critical path and the hours totals.
  • Print names the plan. Removing the title from the header left a printed chart anonymous, so a print-only title line carries it.
  • Beyond the brief: the start month picker no longer turns the 31st into 3 March; an empty plan no longer throws a page error; one Ctrl+Z after the full editor's Apply now restores the section as well, and one Ctrl+Z takes back a whole batch Apply or a multi-bar drag where it used to restore a single row (both inherited from 0.56.0, both caught by the hardened suite).

Process appendix

Task: six header and view changes plus a test suite. Stage: published. Rounds: 2. Models: Builder Opus, Adversary Opus, Verifier Sonnet. Round 2 used three narrow reviewers in parallel (two Opus, one Sonnet) and a separate test hardener.

Adversary findings resolved

Finding Location Severity Resolution
Readouts clipped or hidden at common widths gantt.html header CSS High Fixed: measured fit
Controls off screen above the wrap point gantt.html header CSS Med Fixed: measured fit
Stale tab overwrites every pref except text size savePrefs Med Fixed: merge-on-write
Printed chart does not name the plan header, print CSS Med Fixed: print-only title
Cancelled rows inflate the clock planSpan Med Fixed: left out
Remaining exceeds Duration before the start readout Low Kept, visible note added
Viewport matrix too sparse to catch the clipping ui_test.mjs Med Fixed: width sweep
Suite trusts whatever answers on its port ui_test.mjs Low Fixed: free-port probe
Stored array swallows the snapshot's write storedPrefs Low Fixed
Start button inexact for year-month data syncStartBtn Low Fixed
Logs would ship in the package .adomignore Low Fixed: excluded
Failed save marked as saved, never retried savePrefs Low-Med Fixed in 0.57.1
Invalid stored values linger startup Low Fixed in 0.57.1
Cleared store only partly restored savePrefs Low Fixed in 0.57.1
Label-width drag across startup lost label resize Low Fixed in 0.57.1
Wrapped header hides button words for nothing fitHeader Med Fixed in 0.57.1
Header changes state when web fonts arrive fitHeader Low-Med Accepted; settles in one step
Error gate ignored failed own-server requests ui_test.mjs Med Fixed in 0.57.1
Visibility checks passed invisible elements ui_test.mjs Med Fixed in 0.57.1
Manifest: fictional flows, broad selectors, unwalked editors ui_test.mjs Med Fixed in 0.57.1
Undo after full-editor Apply keeps the new section imApply Med Fixed in 0.57.1
Batch Apply and multi-bar drag push one undo entry per row snapshotMany Med Fixed in 0.57.1

Behavioral verification

Flow exercised What the verifier did Result Notes
Collapse all Clicked, mixed states, 10 and 11 rapid clicks, reload Pass
Text size Reload, two tabs, snapshot over http and file Pass
Header declutter Compared with 0.56.0 at every width Pass
Exact start date All five cell sizes Pass
Duration and Remaining Hand-computed, then edits and undo Pass 116 and 108 days
Legend 20 chips, click on and off, scroll Pass 3 rows at 1440
Widths 393 to 1920, text 85 to 150% Overflow and overlap checks Pass
Edge plans Future, ended, cancelled, empty, one phase Pass
Print, light theme, lenses Emulated print media Pass Real paper not tested

Convergence

Round Adversary findings Verifier Suite (orchestrator's own run)
1 11 (1 High, 5 Med, 5 Low) not yet run 201 passed, 0 failed
1 fixes Pass, all flows 222 passed, 0 failed (real plan); 205, 0 (synthetic)
2 2 app (header), 4 app (prefs), 11 suite 318 passed, 1 failed: the hardened suite caught the batch undo bug
2 fixes 320 passed, 0 failed (real plan); 298, 0 (synthetic); 7 controls declared untested