Repository navigation
Add a headless app gallery that pictures each panel - #117
Conversation
Six pictures of the application as it draws today, staged and taken by the test suite through ImGuiAppHarness and the configuration Program starts: the whole shell side by side, the storage comparison for the ISS a day out and a Molniya orbit a week out, the element inspector, a conjunction screen over constructed objects, and one approach measured in every storage type. A WriteTheIndex test writes the captions to docs/gallery/README.md. The pictures are byte-identical run to run. Nothing reaches the network or the wall clock: the storage comparison and inspector draw the element sets compiled into the application, and the screen runs over objects fitted at a fixed instant. The stopwatch columns read "hidden" while the gallery runs, through a new MeasuredDurations switch that is off in the application. The panels are placed as floating windows rather than docked. ImGuiApp's full-viewport ##mainWindow sits above the dockspace, so a docked panel is painted over by its almost opaque background and shows through dim. To reach the storage comparison from a test, its latest measurement became a read-only property, and it gained Select, IsMeasuring and ResetState. app-gallery.yml regenerates the pictures after the build job passes on main and commits them back as LFS objects. No pictures are committed here; the first run on main writes them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWRBkw7bXdWGzuLpqnCvrB
Path.Join does not discard the directory if a later segment happens to be rooted, and the storage comparison wait now compares minutes with a tolerance rather than exact equality. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWRBkw7bXdWGzuLpqnCvrB
|
"Build and test" is red, but the failure is not caused by this PR. The failing test is Cause. #108 changed
The ISS history is OMM, so the field-by-field term now uses OMM's finer eccentricity and B* steps. The Monte Carlo in No fix exists yet. The proposed patch is to make both sides use the same steps and drop the duplicate epoch term. Two ways to do that:
The second option also corrects the CLAUDE.md note that the Monte Carlo figure is an upper bound for OMM sets. I've left this out of the gallery PR so it doesn't widen. Generated by Claude Code |
The overview now stacks the storage comparison above a screened conjunction panel, with the element inspector down the right, so no panel is empty and no column is half blank. The storage comparison pictures are as tall as what they draw, and the Molniya caption says the resolution table is fixed at a 7,000 km radius. In the app, the approaches table now shows whole rows and leaves room for the storage-type comparison under it instead of capping itself at half the panel, so the last row is never cut and the table no longer resizes when an approach is selected. The element inspector's label column is wide enough for its "Identity" section caption. The README previews the gallery with the close-approach picture. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWRBkw7bXdWGzuLpqnCvrB
#112 made DataTerm format-aware and gave it the epoch, while #108's Monte Carlo still drew every field from the two-line text's steps and its test added the epoch to DataTerm a second time. The committed ISS snapshots are OMM, so the two measured different bands and TheMonteCarloAgreesWithTheFieldByFieldTerm failed on main (9.866e-3 against 9.459e-3). Perturb now takes ElementFieldQuantization.For(e), and the test compares against DataTerm alone: 9.274e-3 against 9.264e-3, 0.1% apart. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jxv8yPrvvmTax9Bhh9phBA
Requested by Matt · project thread
Before: there were no pictures of what Osculator's panels look like. The only way to see them was to build and run the app.
After:
Osculator.Tests/Gallery/stages the real application headlessly and photographs it.docs/gallery/README.mdwill caption six pictures:How: this follows the pattern ImageGui uses.
Programstarts,AppShell.BuildConfig(), throughImGuiAppHarnesson the CPU rasterizer, and loads ImGuiApp's font.WriteTheIndextest writes the captions.OSCULATOR_GALLERY_OUTnames one. Because the pictures are tests, every PR proves each one can still be staged.Determinism: the pictures are byte-identical from run to run.
MeasuredDurations.Hidden, which stays false in the application.Refactors to reach the app from a test, with no change in runtime behaviour:
MeasuredDurationsis a new class inOsculator.App/Shell/.StorageComparisonPanel's last result is now a read-onlyLatestproperty.StorageComparisonPanelgainedSelect(objectName, minutes),IsMeasuringandResetState().AllowUnsafeBlocks, because the font loader calls ImGui through pointers.Workflow:
.github/workflows/app-gallery.ymlfollows ImGuiApp's widget-gallery workflow. It regeneratesdocs/galleryand commits the PNGs back as LFS objects with[bot][skip ci] Regenerate the app gallery.dotnet.ymlcalls it as a job withneeds: buildon pushes to main. That is a different hook from the reference repos, which have it wait on a sharedcijob. Osculator has its owndotnet.ymland no release job, so it waits onbuild, and the workflow header says so.No PNGs are committed here. They, and
docs/gallery/README.md, arrive with the first run on main after merge, or sooner by dispatching the App Gallery workflow. The README now has a Gallery section previewinga-close-approach-in-every-storage-type.png, linked todocs/gallery/README.md. The image renders once the gallery job has run on main.A finding worth a look: the panels are placed as floating windows, not docked. ImGuiApp's full-viewport
##mainWindow(WindowBg alpha 0.94) is drawn above the dockspace host. The dockspace host is pushed to the back byNoBringToFrontOnFocus, so anything docked shows through dim. This is likely the same in the real application. Panels docked as tabs of one node also churn between frames, because Hexa closes on aBeginthat returned false and the panel guard then re-shows it.Second round of fixes, after a review of the rendered pictures:
Feature correctness: I checked each picture against the measured figures in CLAUDE.md and the tests.
Verified locally:
DecompositionTests.TheMonteCarloAgreesWithTheFieldByFieldTerm(0.009866 against an expected 0.009459), fails the same way on current main.🤖 Generated with Claude Code
https://claude.ai/code/session_01WWRBkw7bXdWGzuLpqnCvrB
Generated by Claude Code
Generated by Claude Code