Commit Graph
42 Commits
Author SHA1 Message Date
mjohnson7cd dda1a155fd docs(readme): fetch the OCR models in Get started (refs storytold/artcraft#2104) (#1006) 2026-10-11 13:28:42 -04:00
RidwanandBrandon Thomas d9660d4e73 Docs: sync the progress docs with issues closed on 2026-10-10 (#1064)
The parity and roadmap docs were last refreshed before a batch of fixes
merged, so they still described closed issues as open problems.

- #774 (encrypted output rejected by Acrobat, fixed by #836): gap 1
  removed from gaps.md; its remaining interop-suite work moved to gap 12.
  Gap numbers are kept so existing "gap N" references stay valid.
- #756 (Windows printing, #847): Printers row, Print area and roadmap
  rank 1 now name web printing as the remaining gap.
- #740 column select (#765), #759 1:1 touchpad scrolling (#868),
  #810 Shift-Cmd-G (#835), #825 (#822).
- #844 multi-object move (#907): marked partial, same page only.
- #799, #800, #807, #809, #811, #815-#819, #821 (incl. the #816 panic):
  gap 6 and the area tables list them as fixed.

Scores, readiness percentages and the stage are not re-judged; only the
rank-0 estimate drops by gap 1's 8-15 h (40-70 -> 32-55).

Co-authored-by: Brandon Thomas <[email protected]>
2026-10-11 13:14:48 -04:00
skylar taylor-barrick ae4f5d44f3 Merge pull request #966 from skylartaylor/codex/ui-suite-integration-20261010
Adopt shared panel docking with document-aware visibility
2026-10-10 20:03:37 -06:00
skylar taylor-barrick ecd9d158ea UI: preserve shared document workspace on current main 2026-10-10 19:10:14 -06:00
Brandon ThomasandClaude Opus 5.5 53a5880386 Bump to 0.6.0; add a Linux riscv64 release build (#945)
- Cargo.toml: [workspace.package] and the internal path-dependency requirements move to 0.6.0
  (they pinned 0.5.0, which `cargo update -w` can't match); Cargo.lock refreshed.
- release.yml: new `linux-riscv64` job, ported from GridCraft. Cross-compiles on ubuntu-24.04
  against ports.ubuntu.com riscv64 libs (the linux job's -dev packages, :riscv64), builds the
  tar.gz and the CLI-only tar.gz, smoke-tests pdfcraft-cli under QEMU, and is in the draft
  release job's needs, so SHA256SUMS covers it.
- packaging/linux/package.sh: CROSS_ARCH / CROSS_TARGET / CROSS_COMPILE / EMULATOR support.
- README and docs/releasing.md list the riscv64 tarballs (glibc 2.39+).
- contributors.json refreshed.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-10 20:50:57 -04:00
skylar taylor-barrick 8ff27dc86e UI.9: preserve PDFCraft panels and document lifecycle 2026-10-10 15:46:23 -06:00
Brandon ThomasandClaude Opus 5.5 798650e8a0 Progress docs: target-app parity, gaps, alpha gate, readiness by audience (#873)
Progress docs per craftrules standards/progress-docs.md: target-app parity, gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, and feature, format, PDF-spec, hardware, UI and localization parity docs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 14:23:28 -04:00
74e30e5803 CLI: pdfcraft-cli ui refuses a control file another user could plant (#597)
* Security: pdfcraft-cli ui refuses a control file another user could plant

`pdfcraft-cli ui --control FILE` sent the token and every command, typed
text included, to whatever port FILE named, without checking who owned it.
The README suggested `/tmp/pc.json`; in a shared /tmp another local user
can create that file first, so the CLI talked to their listener.

The CLI now refuses a symbolic link and anything but a regular file, a file
over 64 KiB, and on Unix a file owned by another user or with any group or
other permission bits (the app writes 600). The owner and mode are read from
the opened file, and its device and inode must match the path's, so a swap
after the check is refused too. std has no geteuid and unsafe is forbidden,
so the effective uid is the owner of a file the CLI creates in the temp
folder and removes. The README now uses a per-user path.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Security: stop the app when --control can't be published

A control file that couldn't be written was only logged, and the app ran
on with a listener nobody could reach. The failure can mean another user
already created a file at a shared path to receive the commands, and a
script started with --control would otherwise drive nothing without being
told. The app now exits with the error, before any document opens, so no
work is lost. The README and the app's usage comment say so.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* CLI: pdfcraft-cli ui refuses a control-file port above 65535

`ui` truncated the control file's port with `as u16`, so 65536 + N reached
port N, and the token and command went to whatever listened there. A port
that doesn't fit is now refused, before connecting.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* CLI: learn the effective uid from rustix, not a temp-file probe

Review on #597: the probe made `pdfcraft-cli ui` depend on a writable temp
folder to judge a control file somewhere else, created and removed a file
on every call, and could leave one behind. rustix's `geteuid` is safe and
can't fail, and rustix is already in Cargo.lock; it is a Unix-only
dependency of the CLI, so Windows builds don't compile it.

A control file of your own now works with TMPDIR pointing at a folder that
doesn't exist; the probe refused it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-09 19:01:05 -04:00
Brandon ThomasandClaude Opus 5.5 d483d6d475 Fix #423: publish a standalone Linux CLI archive (#613)
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]>
2026-10-09 16:45:13 -04:00
midasdf 57c281ca0a M3: keep overflowed document tabs reachable (#416)
Refs #397. Scroll the tab strip, reveal the active tab and preserve the existing close-confirmation path.

Assisted-by: OpenAI GPT-6.1 (gpt-6.1-sol)
2026-10-09 09:15:24 -04:00
midasdf c8c7959c0f M4.6: search bookmark titles without changing the outline (#424)
Refs #257. Show matching entries and their ancestors, keep original edit paths and preserve per-document view state.

Assisted-by: OpenAI GPT-6.1 (gpt-6.1-sol)
2026-10-09 09:15:18 -04:00
MarekSpodBiedryandBrandon Thomas 2f42c743b9 Issue #157: the Windows portable zip keeps settings, logs and recovery beside pdfcraft.exe (#325)
* Issue #157: the Windows portable zip keeps settings, logs and recovery beside pdfcraft.exe

The portable zip had no portable.txt, and the app had no portable mode: it always wrote %APPDATA%\PdfCraft and %LOCALAPPDATA%\PdfCraft. Now portable.txt (or PdfCraft.portable) beside the executable puts the settings, log files, crash recovery and new digital IDs in PdfCraftData next to it, as PhotoCraft does, and the zip ships portable.txt. An unwritable PdfCraftData falls back to the per-user folders and says so.

* Issue #157: update ATTRIBUTION.toml SHA-256 for the translation catalogs this PR changes

---------

Co-authored-by: Brandon Thomas <[email protected]>
2026-10-08 17:29:59 -04:00
868bd727d1 M13: pdfcraft-cli mcp --compact lists 12 tools and finds the rest by search (#353)
`tools/list` returns all 132 tools (109,578 bytes, ~27k tokens), which an
agent pays on every session. With `--compact` (library:
`McpServer::with_compact(true)`) it returns the 10 core tools
(`mcp::COMPACT_CORE_TOOLS`) plus `tool_search` (query / category / name
with the full schema) and `tool_call` (runs any tool through the same
`Automation::call`): 12 tools, 7,697 bytes. `tools/call` by name keeps
working for every tool; without the flag nothing changes. Same shape as
`lightcraft-cli mcp --compact`; the meta tools are not called
`*_command` because "command" already means a registry command here.

Both meta tools reject unknown outer keys and report failures as
`isError` results; `tool_call` honours `--root` exactly like a direct
call. Tests: automation integration tests (compact list, discovery,
dispatch, errors, root confinement) and a CLI test that launches the
binary with and without `--compact`.

Co-authored-by: Oldrich333 <[email protected]>
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-08 16:55:25 -04:00
d801407a9f Windows MSI: reject per-user overrides and retain progress text (#305) (#310)
* #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]>
2026-10-08 13:40:30 -04:00
4dc79ccc41 README Downloads: where to get it first, then builds with Windows before macOS (#279)
Also drop "signed installers" from the thin-or-missing list: release installers are signed.

Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 09:58:57 -04:00
7f4677dc93 Release: Flatpak bundles, AppImage zsync updates, README Downloads (#275)
* 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]>
2026-10-08 09:58:13 -04:00
Gert Pellin - GPE 1d31c230c9 Desktop: write log records to standard error and a rotating log file (#239)
The desktop app installed no logger, so every log::warn!/log::error! in
the workspace was discarded: a failed autosave, a page that would not
render, a render worker that could not start. A launch from a desktop
menu has no terminal either, so there was nothing to attach to a bug
report.

apps/pdfcraft/src/logging.rs (no new dependency besides log):
- standard error plus <settings dir>/logs/pdfcraft.log, next to app.ron
  (Linux $XDG_DATA_HOME/pdfcraft); each launch rotates the previous log
  to pdfcraft.1.log and .2.log, so the log of a run that crashed
  survives the next start; the file is capped at 16 MiB
- records logged before the settings directory is known are buffered
  (bounded) and written once the file is attached
- default levels: info for pdfcraft*, warn for everything else;
  RUST_LOG replaces them with env_logger-style directives
- never panics: an unusable directory or a failed write leaves standard
  error as the only sink

The logger is installed first in main, so the panic hook's report is
recorded too; the start-up messages in main go through it. The file is
opened after argument parsing (--version leaves no file) and after the
PrintCraft folder migration, which a fresh settings folder would block.
Documented in docs/development.md (Logs, environment variables).
2026-10-08 05:48:52 -04:00
Gert Pellin - GPE eb46a993bf README: install on Gentoo from the ::snakebyte overlay (#237)
* README: install on Gentoo from the ::snakebyte overlay

* Contributors: credit switch87 as Gert Pellin
2026-10-08 05:30:34 -04:00
a4340d34c8 M14: complete Japanese dialogs, panels, shortcuts and diagnostics (#141)
* i18n: Czech interface language

Adds Czech (Čeština, code `cs`) next to English and Japanese:
Preferences ▸ Interface language, `ui.set language cs`, `ui.state`
and persisted preferences all accept it.

- i18n: `Language::Cs`; `tr()` picks the language's table with a match
  (English has none), panic-free. The CZECH table (83 entries) covers
  every label passed to `.tr("…")` (main menu, View zoom/theme/side-panel
  entries, Preferences dialog), every registered File/Edit/Pages/View/Help
  command shown by `registry_menu`, and every key of the Japanese table.
  Written clean-room from the English meaning, not from any Acrobat
  localisation.
- Tests: Czech covers every registered menu title and label, every
  `.tr("…")` literal found by scanning the crate's sources, and the
  Japanese keys; nothing is left identical except an explicit KEEP_AS_IS
  list ("OK"); ellipses match the source; keys are unique per language;
  `cs` round-trips through set_option, ui.set/ui.state and persistence.
- theme: the font setup is split into `font_definitions()`, and a test
  checks with skrifa (dev-dependency, already in the tree via egui) that
  Inter Regular/Medium/SemiBold and JetBrains Mono draw all Czech letters
  and every Czech translation, so nothing falls back to Shippori Mincho.
- The `language` error lists `cs`; docs/localization.md, the parity note
  for misc.prefs-language and the ROADMAP log mention Czech.

Co-Authored-By: Claude Opus 5.5 (1M context) <[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]>

* M14: complete Japanese dialogs, panels, shortcuts and diagnostics

Expand Japanese from 49 to 1830 interface entries, expose language preferences in the Edit menu, preserve opaque template and history values, and localize known application diagnostics only at the UI boundary. Add control, persistence, template and desktop/web glyph regressions.

Co-authored-by: Codex <[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]>

* M14: Czech as a TSV catalog

Move #68's Czech table into crates/ui-egui/src/i18n/cs.tsv (PrintCraft
labels renamed PdfCraft, plus Auto) and register it with PhotoCraft's
Czech plural rule (one / few / other). #68's tests become catalog
tests: Czech covers every registered menu title and menu command label,
keeps ellipses, uses no three-dot ellipsis or stray whitespace, and only
leaves "OK" untranslated; the code persists and `cz` is rejected. The
source-scanning `.tr("…")` test is dropped: strings now go through tl!
and the catalog tests check consistency.

The font-coverage test moves to tests/fonts.rs and covers both Latin
catalogs (cs, pt-br) against Inter and JetBrains Mono. It keeps skrifa
as a dev-dependency (the version pdfcraft-fonts already uses): egui's
has_glyphs can't answer it, since a family with only the primary face
also uses that face as its replacement face.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: route every UI string through the catalog; Japanese as ja.tsv

Port #141's wiring to the catalog API from land/106:
- `crate::i18n::tr(ui, s)` becomes `tl!(s)`, `tr_fmt`/`tr_template`
  become `i18n::fmt(tl!(..), ..)`, and `Language::get`/`store` (the
  egui temp-data copy of the language) are gone: the drawing language
  is the per-thread `i18n::current()`, set from the preference at the
  start of each frame. Worker threads (export, OCR, batch actions) take
  the UI's language with them for their summaries.
- ja.rs (1,830 pairs) becomes ja.tsv, merged with the existing entries
  and renamed PrintCraft -> PdfCraft. The 29 diagnostic templates of
  errors.rs are dropped.
- `Language::diagnostic` and errors.rs are dropped: matching engine and
  OS messages against English templates breaks silently whenever the
  wording changes. Error details are shown as they are, inside the
  translated frame ("{label} failed: {e}").
- History labels (`command_label`/`action_label`) move into i18n and keep
  captured file and field names; registry menus prefer `@id` entries.
- Preferences: Auto plus every registered language, relabelled at once.
- Tests: Japanese covers every command and All tools entry; Japanese
  labels have glyphs with the desktop faces and with the web subset
  (with craft-fonts); history labels; #141's control tests, with the
  error-detail expectation updated.

Co-Authored-By: shuiyue-cmyk <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Preferences in the Edit menu, Cmd/Ctrl-comma

Split out of #141: register app.preferences in the Edit menu with the
platform's usual shortcut (Command-comma on macOS, Ctrl-comma
elsewhere), so the interface language can be found and changed with no
document open. Shortcut keys may now be punctuation (egui's key name
","). #141's control test drives the menu item, the language selector
and the shortcut in Japanese and English.

Co-Authored-By: sakamoto824 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Petr Leo Compel <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: Codex <[email protected]>
Co-authored-by: RicSchonfelder <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
Co-authored-by: shuiyue-cmyk <[email protected]>
2026-10-07 22:16:07 -04:00
jcl-bitandClaude Opus 5.5 70da0179a6 Security: --root confinement leaks and escapes (#136, #137) (#164)
* Automation: --root refuses every outside path the same way (#136)

With a root set, `resolve` canonicalized a path before checking it against
the root, so an existing outside path got "is outside the allowed
directory" while a missing one got the OS error ("No such file or
directory", "Not a directory", "invalid path"): a confined MCP client or
script could probe which files and folders exist anywhere on the disk.

Containment is now decided before anything about an outside path is
reported:
- `..` is resolved by name first (as Windows does), so a path can't pass
  through an outside folder on its way back in;
- on Windows another network share or device namespace (`\\host\share`,
  `\\?\UNC\...`, `\\.\...`) is refused by name, without contacting it;
- the deepest existing ancestor, links followed, must be inside the root
  before anything is said about the rest;
- a broken link is refused the same way, so whether its target exists
  stays hidden too.

Every outside path now gets `<path> is outside the allowed directory
<root>`, existing or not, file or folder, read or write. Filesystem errors
such as "not found" are still reported for paths inside the root.

Behaviour change: on Unix, `..` now means the parent by name, as on
Windows (`link/../x` is `x` beside `link`), and a write such as
`new/../x.pdf` that stays in the root now succeeds instead of failing with
"'..' is not allowed here".

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* CLI: script images stay inside --root (#137)

`pdfcraft-cli run --script steps.json --root DIR` wrote each step's
`"out"` PNG with `std::fs::write`, never through the root check the tools
use: an absolute `"out"` created or replaced any file the process could
write, and a relative one landed in the working directory instead of the
root.

The image is now saved through the new `Automation::write_output`, which
uses the same resolver and atomic write as a tool's own output: outside
paths get the usual "is outside the allowed directory" refusal (the step
fails, nothing is written), relative paths resolve inside the root, and
without --root the path is written as given, in place as before (so
`/dev/stdout` still works). `run <tool> --out` goes the same way.

Found while testing this, the same "." problem in two tools:
- a write path naming a folder, such as "." (the root itself), staged its
  temporary file beside that folder, i.e. outside the root for ".",
  overwriting and then deleting any file there called
  `.root.pdfcraft-tmp`. `write_atomic` now refuses a folder before
  writing anything;
- `image_save` adds an extension to a path without one, so "." became
  `root.png` beside the root. It now refuses a folder first.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Automation: files named after a document stay in the output folder

Found while reviewing the --root fixes for #136 and #137. Folder outputs
name their files after the document and joined that name straight onto the
resolved folder, without checking the result against the root:

- `doc_export_images` and `doc_export_all_images` used the whole document
  name, so `doc_create` with `name: "../../escape"` followed by
  `doc_export_images` wrote `escape_page_1.png` outside the root (an
  absolute name went anywhere);
- `page_extract` (separate files), `doc_split`, `ocr_recognize_files` and
  `action_run` took the last component, but on Windows a name such as
  `x/C:evil.pdf` gives `C:evil`, and `folder.join("C:evil-page1.pdf")`
  replaces the folder with a path relative to the current directory on C:.

Every such name now goes through `child()`, which turns separators,
colons and control characters into `_` (and prefixes a name of only dots),
so the file is always a direct child of the folder. `with_root` also
refuses a root that is not a folder.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 21:12:32 -04:00
Brandon ThomasandClaude Opus 5.5 d3db99818f Rename PrintCraft to PdfCraft (#174)
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]>
2026-10-07 16:03:57 -04:00
Brandon ThomasandClaude Opus 5.5 1d67833599 Fonts: use craft-fonts as an optional build input; move the Japanese fonts out
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]>
2026-10-06 11:36:23 -04:00
Brandon ThomasandClaude Opus 5.5 07d7fbfa07 Windows on ARM64: release builds, and CI that installs and runs them on ARM64 (#61)
- 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]>
2026-10-06 07:41:47 -04:00
Brandon ThomasandClaude Opus 5.5 37748260ff FreeBSD: release tarball and platform docs
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]>
2026-10-05 10:57:30 -04:00
Brandon ThomasandClaude Opus 5.5 f97684f0d8 Docs: honest parity assessment, gap list and direction (ROADMAP, README, CLAUDE.md)
ROADMAP gains an honest assessment by dimension (features, effort,
foundations, robustness, fidelity, product readiness) and by area, what
'shipped' does and doesn't mean, and a ranked list of where we're lacking
and where we're going. Numbers refreshed (804 features, 49.5% shipped,
effort ≈ 30–35%). README's stale 'What's next' becomes an honest status
summary; CLAUDE.md points every agent session at both sections.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 06:19:06 -04:00
Brandon ThomasandClaude Opus 5.5 d20eef9d56 Licensing: standard LICENSE files, NOTICE, ArtCraft brand terms
Adopt the shared Crafting Apps licensing standard. LICENSE-MIT names "ArtCraft Team and the
PrintCraft contributors"; LICENSE-APACHE matches the standard byte for byte; NOTICE gets the
standard header and brand paragraph above the existing third-party list. docs/brand/LICENSE-brand.txt
now holds the ArtCraft Team brand terms: the marks may be used only unmodified within PrintCraft,
and forks and modified versions must remove them. The brand entries in ATTRIBUTION.toml, AGENTS.md
§1.2 and the README follow suit, and the README's Licence section becomes the standard
"License and credits" block. xtask inherits the workspace licence.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-04 10:07:05 -04:00
Brandon ThomasandClaude Opus 5.5 1dd9f27b36 README: tagline names the Adobe app it reimplements; standard Adobe trademark and non-affiliation notice
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 12:24:17 -04:00
Brandon ThomasandClaude Opus 5.5 ff0d0ac294 README: Crafting Apps table in five columns (icon, app, purpose, GitHub, Website)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 12:19:06 -04:00
Brandon ThomasandClaude Opus 5.5 099ea8c152 README: drop the old DrawCraft name; VectorCraft links to /apps/vectorcraft
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 12:18:18 -04:00
Brandon ThomasandClaude Opus 5.5 fa601c1641 README: app icons in the Crafting Apps table
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]>
2026-10-02 12:17:17 -04:00
Brandon ThomasandClaude Opus 4.8 4466fe8623 Signed release pipeline (macOS/Windows/Linux/Web); README community note
Ports photocraft's release workflow + packaging (signing, notarization,
MSI/DMG/deb/rpm/AppImage/web), adds `cargo xtask version`. File-type
associations omitted (route B); app keeps its own .desktop. Fresh WiX
UpgradeCode. README 'about' note updated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-10-02 12:06:19 -04:00
Brandon ThomasandClaude Opus 5.5 1f2e267f32 app icon: lion (owner's ArtCraft drawing), Dock/taskbar/launcher wiring, palette docs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 09:53:34 -04:00
Brandon ThomasandClaude Opus 5.5 67ff9303c8 M6.1/M6.2: form filling: new fonts (L2) and forms (L3) crates; field tree with inheritance, widgets, options; set_value with validation and regenerated appearances (auto-size, comb, multiline, password, quadding, /MK, combo, list selection), check/radio states (own AP when missing), reset to /DV; engine SetFieldValue/ResetForm with fill-forms permission; UI in-place editor (Enter/click-away commit, Escape, Tab with select-all), check/radio toggle, choice popup, Clear form; tools form_fields/form_fill/form_reset. Perf: named destinations indexed once (190 MB manual opens in 1.8 s instead of 172 s); comment and form edits refresh view data from the object graph instead of a full re-inspection (6x faster per edit on large files; equivalence-tested). annot uses the shared fonts helpers. Docs, parity, roadmap.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 22:37:35 -04:00
Brandon ThomasandClaude Opus 5.5 54e288c5fe M5.3/M5.4: commenting UI: quick-bar Comment/Highlight/Draw flyout groups with pin, colour and thickness; sticky note and text box composer; highlight/underline/strikethrough from text selection; freehand, line, arrow, rectangle and oval gestures with live previews; Select tool selects (per-line frames for markup), moves, resizes with 8 handles, edits and deletes comments; canvas context menu (edit, reply, set status, colour, delete); Comments panel rewrite (add-a-comment box, search, selectable cards with reply box, ... menu, inline edit, status badges); comment edits re-render only their page and keep stale rasters on screen; control channel ui.drag, secondary click, pages_on_screen and comment state; view options quick/author/comment; 7 Lucide icons; parity entries; README
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 21:38:07 -04:00
Brandon ThomasandClaude Opus 5.5 2fc7cb4e64 Community links: Discord button in the title bar, ArtCraft community card on Home, About dialog with ArtCraft mark/wordmark and links, Help menu commands (help.discord/app_page/github/website), CLI --version and MCP websiteUrl, README Community section; 4 Lucide icons (attributed); regenerated screenshots with honest brand attribution
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 14:15:05 -04:00
Brandon ThomasandClaude Opus 5.5 bb31b5a1b5 Brand assets: ArtCraft logos attributed as Storyteller-owned (not open source, LicenseRef-Storyteller-Trademark) with a narrow asset-gate exception for docs/brand logos; AGENTS.md §1.2
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 14:02:40 -04:00
Brandon ThomasandClaude Opus 5.5 93fa9b79a8 M3.9: UI control channel (opt-in --control; ui.state/inspect/click/type/key/command/set/open/screenshot over token-authenticated loopback JSON-RPC; printcraft-cli ui)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 08:20:59 -04:00
Brandon ThomasandClaude Opus 5.5 b8fed39be5 M13.1: docs for agent control (README, AGENTS §3, crate README, CLAUDE.md)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 23:33:21 -04:00
Brandon ThomasandClaude Opus 5.5 5f5f83cc0c Session 4: M1.6 encryption (crypt crate R2-R6), M4 command registry, combine/extract/split, autosave + crash recovery, asset policy + xtask assets, README screenshots
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 23:12:34 -04:00
Brandon Thomas 5f61bde5eb more work 2026-09-30 11:34:29 -04:00
Brandon Thomas 108fdc108c more progress, roadmap, wip 2026-09-30 11:00:02 -04:00
Brandon Thomas f0b5f8ff55 one-shot first ver 2026-09-30 05:17:08 -04:00