Custom macOS larger runners in a runner group do not pick up jobs; the
built-in M2 Pro label does. Only release.yml uses it, and the
actions_macos_xl budget caps the monthly spend.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The standard macOS runners are shared with all CI and queue for an hour or
more. The macos-release runner (GitHub-hosted M2 Pro) is in a runner group
usable only by release.yml on the release branch, with a monthly spend cap
on the actions_macos_xl SKU.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* About: contributors compiled in from contributors.json (grab bag + table, sortable, name toggle)
Help > About VectorCraft gains Contributors and Models tabs next to the existing About
content, following the craftrules standard (standards/contributors.md):
contributors/contributors.json is generated by craftrules/scripts/contributors.py and baked
into the binary by crates/ui-egui/build.rs as static tables (credits.rs). Each contributor
line: @username, opt-in display/real name, PRs, commits, lines +/-/delta, binary assets +/-,
first/last commit. Sortable by every column; alphabetical ignores case and the leading @.
Labels are translated (ja, zh-hant, pt-br catalog rows).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Contributors docs: craftrules is two levels up (../../craftrules)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Contributors: self-submitted names in contributors/people.toml; AGENTS.md credit-yourself section
build.rs reads contributors/people.toml next to the generated contributors.json and shows a name only
for entries the generator verified as written by that person (craftrules standards/contributors.md).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Contributors: regenerate (verified people.toml entries)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* i18n: credits labels for catalogs added on main since this branch
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Contributors: regenerate after rebase onto main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Contributors: regenerate (verified people.toml entries)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Add Snapping to the Artboard Tool
Merged with the Artboard tool's Alt-drag duplicate (#348): a copy snaps too, and to the artboard
and art it leaves behind (a move skips them).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Text in fonts that aren't installed comes in as live type in the fallback font again, named as
before (Helvetica-Bold → Helvetica Bold), not outlines plus pink copies on a non-printing layer.
- The installed face that matches a PDF font is decided once per font from its first comparable
glyph, not per glyph (loading up to 64 faces each time, and switching style mid-line).
- Kangxi radicals are unified only for text from Adobe's CID tables, not ToUnicode maps.
- A line is laid out again only when tracking changed it.
- CidText::of is tested on data that isn't a CID-keyed CFF (embedded fonts are untrusted).
- NOTICE: Adobe CMap resources (BSD-3-Clause) bundled through hayro-cmap.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The log queue is process-wide. Any server draining it after a request, whether or not its client
called logging/setLevel, could take another session's records; under parallel tests that made
log_records_go_out_as_notifications_once_asked_for flaky.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Each sample can take ~370 KB of texture; 3000 of them could hold about a gigabyte.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit d2daeefb6ef442a472696e78498deeedc03ca823)
A file can hold any number of saved selections; the duplicate-name check and the name lookup were quadratic.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 9bcb695ad3904565ed84b7562aa99dd818604cec)
Conflicts with #214 (fonts by PostScript name): this branch's name index (FaceKeys,
aliases) stays, and #214's `by_postscript_name` (used by PDF import) reads a PostScript
map filled from it, keyed by the same normalized names.
Removed: scanning ~/Library/Application Support/Adobe (CoreSync/plugins/livetype and
Fonts), and the preference that switched it (Type › Include Fonts of Other Design Apps'
Folders). Fonts activated through another vendor's subscription are licensed for use
through that vendor's own sync; reading their files from VectorCraft would go around that
licence, and the project's clean-room rules keep VectorCraft out of other vendors' files.
Fonts the user has installed in the system or user font folders are still found by every
name, as before.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Since 546a65f every release job checks storytold/craft-fonts out at its pinned commit and
builds with CRAFT_FONTS_DIR and CRAFT_FONTS_REQUIRED=1. The FreeBSD jobs do the same inside
the VM, so FreeBSD packages carry the Japanese fonts and their OFL texts. The package check
now requires each expected file (the font licences included) instead of any one of them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Shippori Mincho (assets/fonts, from #145) moves to storytold/craft-fonts. crates/text/build.rs
embeds the fonts of a craft-fonts checkout when CRAFT_FONTS_DIR is set (web: BIZ UDPGothic
Regular only) as vectorcraft_text::CRAFT_FONTS; unset, it is empty and Japanese falls back to the
installed fonts. Document text gets the Japanese faces after the bundled fonts (Mincho first); the
UI adds them at the end of every egui family (BIZ UDPGothic first), before ui_fonts' system-font
discovery. Release and FreeBSD CI builds check craft-fonts out at a pinned commit; packages carry
the fonts' OFL texts.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Release builds add an arm64 MSI and portable zip, cross-compiled on the x64
runner (signing and WiX as for x64). package.ps1 checks each binary's PE
header before packaging: Machine must match -Arch, the app must be a GUI
program and the CLI a console program. It skips the CLI smoke run when an
ARM64 build can't run on the host. A new Windows ARM64 workflow packages the
ARM64 MSI, installs it on a Windows 11 ARM64 runner, checks both installed
exes are ARM64, runs the CLI, and uninstalls. Ported from printcraft#66.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Fixes the Windows installer: the Start Menu shortcut and Add/Remove Programs icon were blank. Release builds no longer open a console window behind the app.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The MSI Icon id had no .ico/.exe extension, which Windows Installer needs for
advertised shortcuts and ARPPRODUCTICON, so both showed a blank icon. Release
builds of the desktop app are now GUI-subsystem (no console window; the CLI stays
a console program), the shortcut/summary description names what VectorCraft does, and
packaging-lint rejects an Icon id without an extension. Found in printcraft#57.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The appended Interface localization section moves into the roadmap's structure: a
Shipped so far entry, the Type advanced row (45%, CJK composition left), the gap list,
the inventories (16 stubbed menu items; Touch Type the only missing tool) and totals
recomputed from the parity table (75.3%, 211–332 h to feature parity); README Status
follows.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
47 of the 83 entries were labels from other apps ("New blank PDF", "Comments panel",
"Read mode"…) that never appear here. A test now walks the menu tree and fails on any
entry that isn't one of VectorCraft's labels.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- packaging/freebsd/package.sh builds vectorcraft and vectorcraft-cli and writes
vectorcraft-<version>-freebsd-x86_64.tar.gz, a /usr/local-style tree (bin/, the
freedesktop desktop entry, MIME type and metainfo, hicolor icons, licences, NOTICE
and ASSETS.md). FreeBSD's install(1) has no -D and uname -m says amd64.
- release.yml: a FreeBSD x86_64 job in the same FreeBSD 14.3 VM; the version, date
and SHA reach the VM through `envs:`. The draft release waits for it.
- freebsd.yml: vmactions/freebsd-vm pinned by commit (v1.5.9), git safe.directory for
the copied checkout, CARGO_BUILD_JOBS=4, and a `package` job that runs the script on
PRs touching FreeBSD packaging and on demand.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Real-file test oracles live in storytold/photocraft-corpus, explained in
craftrules standards/test-corpora.md. Never commit large binary fixtures
here; fetch them pinned and sha256-verified.
Co-authored-by: Claude Opus 5.5 <[email protected]>
- ROADMAP: a new "Honest assessment (2026-10-05)" section with:
- scores by dimension (breadth, depth, large missing subsystems, interaction
fidelity, look and feel, file interop, bundled content, performance,
robustness, platforms, automation) and how far to trust the self-graded scores;
- the prioritized gap list with one-agent hour sizes;
- the direction (next, then, alongside, 1.0).
- ROADMAP: the parity rows for files, export, print, links and UI chrome are
re-derived after M4 (feature parity ~74% on the rubric, 68–74% honest range;
~230–350 h to feature parity, ~335–520 h to full parity, one agent), the M4 and
M11 milestone rows and the inventories are updated, and "Shipped so far" lists M4
and the robustness work.
- README Status: where we are, what's missing, where we're going.
- AGENTS.md / CLAUDE.md: sessions start from the gap list; landing a task updates
the assessment, the parity row and the README status in the same PR.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Shipped code no longer unwraps, expects or panics: every one of the 124
unwrap()/expect()/panic!/unreachable! sites outside tests now handles the
failure (Result/Option, ?, let-else, defaults) and reports errors to the user.
- Lints: workspace clippy denies unwrap_used, expect_used, panic, todo,
unimplemented and unreachable; clippy.toml allows them in tests, and
integration tests, examples and testkit opt out explicitly.
- Safety net (vectorcraft_engine::guard): a panic in a top-level command rolls
the document back and returns EngineError::Internal; a panicking tool is
reset; the MCP server answers with an internal error and keeps serving; the
UI frame and each control request are guarded.
- APIs that hid failures now return them: Rendered::to_png/to_jpeg/to_webp
return Result (JPEG/WebP errors used to write empty files),
FontDb::face returns Option, Region::top returns Option.
- Fuzzing: engine/tests/import_fuzz.rs feeds garbage, hostile and mutated SVG
and PDF through import → render → export (30k cases locally, no panics).
- Docs: AGENTS.md/CLAUDE.md rule, docs/development.md "Robustness" section,
README pointer and a PR template checklist.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Adds LICENSE-MIT, LICENSE-APACHE and docs/brand/LICENSE-brand.txt from the Crafting Apps
licensing standard. NOTICE follows the standard template (copyright, licence, brand carve-out)
and keeps the third-party list, now noting the Feather-derived Lucide icons (also MIT) and the
egui default fonts compiled into the app. ASSETS.md gives the docs/brand/ files their trademark
terms and marks the 21 Feather-derived Lucide icons. README uses the standard License and credits
section; AGENTS.md/CLAUDE.md point to the licence and brand files.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Drop the app icon from the top of the README, matching PhotoCraft, and
show each app's icon next to its name in the Crafting Apps table in place
of the coloured name badges. The table is now identical across all seven
apps apart from the "you are here" row.
Co-Authored-By: Claude Opus 5.5 <[email protected]>