Release builds said "Text recognition isn't installed: its models are
missing" because no packaging script or release job fetched the OCR
models: only `cargo xtask models` does, into the source tree.
- packaging/env.sh gains stage_models DEST, which runs
`cargo xtask models DEST` (every ATTRIBUTION.toml kind = "model" file,
SHA-256 verified, with its licence text). No model file is named, so
the models PRs #433/#572 add ship without packaging changes.
- `cargo xtask models` also writes ATTRIBUTION.txt crediting each model
(CC-BY-SA-4.0 requires attribution when redistributed).
- macOS: PdfCraft.app/Contents/Resources/models, before signing.
- Windows: models\ beside pdfcraft.exe in the MSI (WiX v5 <Files>
harvest) and the portable zip; test-msi.ps1 checks the folder.
- Linux deb/rpm/tar.gz/AppImage, Flatpak bundle and FreeBSD tarball:
share/pdfcraft/models beside bin/. Models::search_dirs now also looks
in <exe dir>/../share/pdfcraft/models (Models::dirs_beside_exe); a
test builds every package layout on disk and finds the models in each.
release.yml and freebsd.yml check the packages contain them.
- The missing-models messages no longer tell end users to run cargo,
and the 11 catalogs that keyed an old PRINTCRAFT_MODELS wording (or
the previous one) now key the current English text; ATTRIBUTION
hashes updated. A test checks the translations match.
The web (wasm) build, which the issue reports, still has no models; this
is the desktop half only.
Co-authored-by: Claude Opus 5.5 <[email protected]>
On Linux, pdfcraft-cli shipped only inside the desktop packages (about
55 MB), while macOS already publishes pdfcraft-cli-<v>-macos-universal.zip.
Servers, CI and agent sandboxes only need the headless CLI.
packaging/linux/package.sh gains a `cli` format, on by default, that writes
pdfcraft-cli-<v>-linux-<arch>.tar.gz: the stripped pdfcraft-cli from the
shared staging tree plus the licences/README via copy_docs. copy_docs now
also copies NOTICE (every package benefits). The release job already
uploads and checksums every file in dist/release; its package check now
lists the archive and runs the extracted binary. README and
docs/releasing.md list the new artifact and state the glibc 2.35 baseline.
Co-authored-by: Claude Opus 5.5 <[email protected]>
The org has 5 macOS slots in total (GitHub Team), shared by every repo's CI and
release builds, and PR CI kept them full, so release builds queued behind it.
macOS now runs only in release.yml; a release that fails on macOS is fixed and
rebuilt.
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* #305: harden Windows MSI deployment and progress UI
Co-authored-by: Codex <[email protected]>
* Keep the MSI manufacturer as Learning Machines LLC
The company name matches the Linux packages; changing it is the owner's call.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* #305: keep compiled-MSI checks compatible with PowerShell COM
Validated the compiled x64 MSI and negative scope, publisher and progress mutations.
Co-authored-by: Codex <[email protected]>
* ROADMAP: the publisher name is unchanged
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Codex <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Release: Flatpak bundles (x86_64, aarch64), AppImage zsync updates, README Downloads
- AppImages embed gh-releases-zsync update information and ship a .zsync beside them;
the Linux job installs zsync and checks both.
- New flatpak job (x86_64 on ubuntu-24.04, aarch64 on ubuntu-24.04-arm) repackages the
Linux tarball with packaging/linux/flatpak-bundle.sh and the new bundle manifest, then
smoke-tests it in the sandbox. finish-args shared with the Flathub manifest (packaging-lint
checks they match): Wayland/X11, dri, CUPS for printing, Documents and Downloads.
- Only the signing jobs and the draft-release job keep `environment: release`, so a branch
dispatch is a dry run of everything else and can never draft a release.
- README: a Downloads section listing every build; docs/releasing.md updated.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Flatpak: no CUPS socket (the runtime has no lp); document printing as unavailable there
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Release CI: macOS job on macos-15-xlarge
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]>
(cherry picked from commit 90d60b0c98)
* CI: tell actionlint about the org's macos-release runner label (#202)
Co-authored-by: Claude Opus 5.5 <[email protected]>
(cherry picked from commit ddea3c72e0)
* About: contributor and model credits compiled in (grab bag + table, self-submitted names) (#196)
* About: contributors compiled in from contributors.json (grab bag + table, sortable, name toggle)
Adds About ▸ Contributors and About ▸ Models tabs per 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; nothing is read at run time. Each contributor line: @username, opt-in
display/real name, PRs, commits, lines +/−/Δ, binary assets +/−, first/last commit.
Sortable by every column; alphabetical ignores case and the leading @.
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]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 41e214c318)
* M13: exit cleanly when stdout pipe closes (#203)
Co-authored-by: Brandon Thomas <[email protected]>
(cherry picked from commit 1cf0d319e4)
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Ayan <[email protected]>
* M14: translation catalogs, same system as PhotoCraft
Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).
The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.
Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* i18n: add Brazilian Portuguese (pt-br) UI translation
Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.
* M14: strict catalog validation, one-pass fmt, translation assets
Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
placeholder, ellipsis and plural-form mismatches and duplicates. The
bundled catalogs must have no errors (tests); at run time a bad line is
still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
`translation` kind that may never come from Adobe; ja.tsv gets its
ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
dirty state and command ids.
Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.
Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Brazilian Portuguese as a TSV catalog
Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
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]>
Since #164, a script step's "out" resolves inside --root like every other path, so
"smoke/page.png" landed in smoke/smoke/. Name it relative to the root.
Co-authored-by: Claude Opus 5.5 <[email protected]>
* #143: Windows MSI desktop shortcut checkbox and install-complete dialog
Add native installer dialogs (installer-ui.wxs): a welcome screen with a
"Create a desktop shortcut" checkbox (ticked by default), repair/remove,
progress, and "Setup completed successfully" / failed / cancelled screens
with Finish. Unattended /qn and /qb installs never wait on a dialog and can
skip the desktop shortcut with INSTALLDESKTOPSHORTCUT=0.
Start Menu and desktop shortcuts are now plain links to pdfcraft.exe in
their own components (HKLM key paths, removed on uninstall) instead of
advertised MSI shortcuts.
test-msi.ps1 checks the compiled MSI's shortcut, checkbox and dialog tables
during packaging; the ARM64 install smoke test checks both shortcut
targets, their removal on uninstall, and the INSTALLDESKTOPSHORTCUT=0
opt-out.
Co-authored-by: ChatGPT <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JqiBTPWGWbhQDYNFcxFte6
* #143: run test-msi out of process before signing; add files-in-use dialog
test-msi.ps1 held the MSI open through a Windows Installer COM handle in
package.ps1's own process, so signtool could fail on signed release builds.
Run it in a child process and release the COM objects.
The hand-authored UI had no MsiRMFilesInUse dialog, so an upgrade or repair
while PdfCraft is running could not offer to close it. Add one (OK closes the
programs with MSIRMSHUTDOWN=2, Cancel stops setup) and check for it in
test-msi.ps1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JqiBTPWGWbhQDYNFcxFte6
---------
Co-authored-by: ChatGPT <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
The app, crates, binaries, bundle id, packaging, icons, screenshots and docs are now
PdfCraft / pdfcraft (repo storytold/pdfcraft). On first launch the desktop app moves the
PrintCraft settings and crash-recovery folders to the new name, and both apps read settings
saved under the old storage key, so upgrades keep recent files, preferences and unsaved work.
The signing test fixtures keep their PrintCraft subject names (they are binary).
Co-authored-by: Claude Opus 5.5 <[email protected]>
Shippori Mincho (and its OFL file) leaves assets/fonts/: the Japanese fonts now
live in storytold/craft-fonts. printcraft-fonts gets craft-fonts' build.rs recipe:
with CRAFT_FONTS_DIR=<checkout> it embeds the manifest's fonts as CRAFT_FONTS
(wasm32: only BIZ UDPGothic Regular); without it CRAFT_FONTS is empty and the
app builds, tests and runs as before, minus the Japanese face.
- SHIPPORI_MINCHO is now Option<&[u8]> from CRAFT_FONTS; japanese_glyph
(was shippori_glyph) uses document_japanese_font() (Shippori Mincho, then
BIZ UDMincho, then any Jpan face) and returns GlyphError::NoFont without one.
- Editing PDF text into Japanese without craft-fonts is a clear EditError that
leaves the page untouched.
- UI: every Jpan craft font (BIZ UDPGothic first) is the last fallback of
every egui family, sharing the same static bytes.
- Tests: Japanese glyph/edit tests skip without craft-fonts; new UI tests for
no-tofu Japanese with craft-fonts and working fonts without it.
- CI: the Linux test job checks out craft-fonts at a pinned SHA and runs the
tests with CRAFT_FONTS_DIR. Releases build every platform with it
(CRAFT_FONTS_REQUIRED=1) and ship each font's OFL as OFL-<family>.txt.
- ATTRIBUTION.toml gains [[build_input]] (checked by xtask assets); NOTICE,
AGENTS.md, CLAUDE.md, README and docs say fonts live in craft-fonts.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
It was only for finding the WARP crash (fixed in the previous commit) and
was merged with #66 by accident; it ran a 60-iteration crash-dump loop and
edited the runner's registry on every push.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- package.ps1 takes -Arch arm64 (aarch64-pc-windows-msvc, WiX -arch arm64)
and now checks each binary's PE Machine as well as its Subsystem, so an x64
build can never ship labelled arm64.
- release.yml builds, signs and packages a Windows ARM64 MSI and portable zip
next to x64 and x86, cross-compiled on the x64 runner so signing and WiX
run exactly as they do for x64.
- New windows-arm64.yml (PRs touching Cargo/packaging, main, weekly):
packages the ARM64 MSI the same way (unsigned), installs it on a Windows 11
ARM64 runner, checks both installed binaries are ARM64, opens/reads/edits/
renders/saves a PDF with the installed CLI, uninstalls; and runs the whole
test suite natively on ARM64. The MSI is kept as an artifact for 7 days.
- README: Windows builds for x64, x86 and ARM64.
Requested by @maxffarrell.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- printcraft.exe release builds use the GUI subsystem, so launching it no
longer opens a console window next to it (debug builds keep the console).
- The MSI's Icon id gains its .ico extension: Windows Installer requires it
for advertised shortcuts and ARPPRODUCTICON, so the Start Menu shortcut and
Add/Remove Programs showed a blank icon.
- Guards: package.ps1 checks the PE subsystem of both binaries (app = GUI,
CLI = console) before packaging; packaging-lint fails on an Icon id without
.ico/.exe.
- The shortcut's description said "image editor"; it's a PDF workbench.
Reported, with the exact fixes, by @MikailuReeves.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Builds on #45's FreeBSD workflow: it now also runs packaging/freebsd/package.sh
end to end (a quicker release profile) and triggers on packaging changes. The
release job uses the same packages, 4 vCPUs and safe.directory, and removes
target/ in the VM before copying dist/ back out.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The release workflow gains a FreeBSD x86_64 job: packaging/freebsd/package.sh
builds in the same pinned FreeBSD VM and writes a /usr/local-style tar.gz
(app, CLI, desktop entry, MIME type, AppStream metadata, icons, licences).
README and CLAUDE.md list FreeBSD now that its CI job builds PrintCraft and
passes all 688 tests on FreeBSD 14.3.
Co-Authored-By: Claude Opus 5.5 <[email protected]>