* CI: FreeBSD builds with two jobs
The nightly FreeBSD run has been killed for memory (exit 137) while
compiling the workspace's test targets, on both architectures, every
night since at least 9 November. Two rustc processes at a time fit in
the VM's 12 GB.
* CI: one FreeBSD build job at a time
With two jobs the engine and ui-egui test builds were still killed when
they compiled together.
affinity-corpus.yml ran a local job; it now calls craft-common-actions
gate.yml with the same toolchain (1.95), environment and commands, and a
cache of its own. release.yml's git-sources copy is removed: the shared
release.yml runs the same check before any build.
release.yml also runs nightly on main with craft-common-actions' dry-run: every release build
except macOS, with nothing signed, pushed or drafted. Breakage that only the release build hits
(riscv64, Flatpak, FreeBSD, packaging) then shows up the next morning instead of on release
day, as it did on 11 Nov 2026.
Hovering looks up the bounds of every selected object, and each lookup
went through the memo key check, which compares the whole selection. That
made a hover quadratic in the selection: 1.5 s at 50,000 selected paths.
The walk now checks the key once and shares it across its lookups.
Part of #1280.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
First slice of https://github.com/storytold/vectorcraft/pull/1281, split
as the review asked. `--deep` gains rows for hovering, a hit test that
misses, marquee, smart guide targets and shift-click on a large document,
so the later slices have a baseline.
PathData::bounds built a kurbo path on every call. It now measures the
segments in place, with the same guards, and a proptest compares the
result bit for bit with what the path gave.
Co-Authored-By: arhammusheer <arhammusheer@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comparing the fitted widths missed the case it was meant for. Name is the
only growing column, so a longer name takes its extra width from the
spare room and the fit comes out the same: a dragged Name width stayed,
clipping the longer name.
It could also drop dragged widths by accident. The fit comes from the
available width inside the scroll area, which scrolling can nudge, so
scrolling a widened table could reset it.
The table now compares the natural widths and the clip rect's width,
which scrolling does not move.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The last column was egui's remainder column, which has no drag handle, so
it could only be resized from the edge before it. It is now an ordinary
column with its own handle.
A table keeps its column widths, so switching to a longer name left the
Name column at its old width and clipped the text. The table now goes
back to the opening fit whenever that fit changes: a longer widest cell
or a resized window. Dragged widths are dropped at that point.
fit_widths could overflow the room when one column hit the minimum,
because the other columns did not take up its share. Columns now give
way in proportion to their width above the minimum.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Contributors table and the Models table were egui Grids inside a
two-way scroll area: they opened wider than the dialog, so they scrolled
sideways, and Company and Model sat almost touching. Both are now
egui_extras tables. Each column opens at the width of its header and widest
cell, the spare width goes to the text columns (Name; Company and Model),
and every column edge can be dragged. Widening a column grows the table
like a spreadsheet, and only then does it scroll sideways; the header stays
put while the rows scroll. Counts and dates are right-aligned and every
cell is vertically centred.
The sorted column stays highlighted and its direction shows on the
toolbar's sort-order button, so headers no longer reserve room for an
arrow. The opening widths come from fit_widths, a pure function with unit
tests that a fitted table fills its room exactly and that only the text
columns give way when room is short.
The About dialog opens 820 points wide, so every column fits at its natural width.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ci: run the desktop printing check through the shared gate
print.yml ran its own Windows job, which the CI workflow rules phase out, and each PR saved its
own ~1.3 GB cache. The same commands now run through craft-common-actions' gate.yml on
windows-2022, without craft-fonts, nextest or the wasm target as before. The gate never saves
from a pull request; a manual run on main seeds the cache. storytold/craft-common-actions#118.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ci: call the shared gate at main
storytold/craft-common-actions#119 is merged, so main's gate takes an empty packages list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* ci: i18n report without a rebuild; PR print runs stop saving caches
- xtask ci: the i18n report selects the whole workspace as the test stage did. With
`-p vectorcraft-ui-egui` alone cargo resolved features differently and recompiled for about
3.5 minutes. `cargo xtask i18n-report` on its own still builds only that crate.
- print.yml: only main saves the desktop-print cache. Each PR saved its own 1.3 GB cache that
only that PR can read (6.3 GB across five PRs), pushing the repository past its 10 GB limit
and evicting caches main's gate restores.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ci(xtask): i18n report selects the test run's targets too
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test run builds --lib --bins --tests; a binary target's dependencies (the desktop app's
eframe features) could still resolve differently under --lib alone. Match the selection
exactly, and drop --quiet so a rebuild would show in the log.
* ci: leave print.yml unchanged
print.yml still runs its own jobs, and CLAUDE.md (CI workflows) keeps additions out of such files.
The cache churn it causes goes to craft-common-actions instead. This PR is now the xtask change only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
print.yml still runs its own jobs, and CLAUDE.md (CI workflows) keeps additions out of such files.
The cache churn it causes goes to craft-common-actions instead. This PR is now the xtask change only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test run builds --lib --bins --tests; a binary target's dependencies (the desktop app's
eframe features) could still resolve differently under --lib alone. Match the selection
exactly, and drop --quiet so a rebuild would show in the log.
- xtask ci: the i18n report selects the whole workspace as the test stage did. With
`-p vectorcraft-ui-egui` alone cargo resolved features differently and recompiled for about
3.5 minutes. `cargo xtask i18n-report` on its own still builds only that crate.
- print.yml: only main saves the desktop-print cache. Each PR saved its own 1.3 GB cache that
only that PR can read (6.3 GB across five PRs), pushing the repository past its 10 GB limit
and evicting caches main's gate restores.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1320 (write) and #1318 (read) landed on main; this keeps only the missing
regression: explicitly closed control-point splines export with the closed
bit and re-import closed, while open paths (even with coincident endpoints)
stay open, across every SPLINE-capable DXF version.
A click with the Polar Grid tool opens the shared shape dialog (width, height, concentric and
radial dividers), as the Rectangular Grid tool does, and keeps the divider counts as the tool's
options.