Commit Graph
144 Commits
Author SHA1 Message Date
Martin BallandClaude Opus 5.5 c36ea1bf64 i18n: review fixes (offered locales, locale-first fallback, pt plurals, scripts)
Skylar's review of 886a0b3:
1. tc/tid go locale by locale: in each locale the context or @id row,
   then the plain row, so pt-br's plain row beats pt's context row.
2. pt (and pt-* other than pt-br) uses pt-PT plural rules: 0 is plural.
3. A script subtag (sr-Latn-RS, sr_RS@latin, be_BY@latin) never picks a
   code of another script; sr-Cyrl-RS still picks sr.
4. A row defined twice is reported and the first kept, as in the checker.
5. The pseudo locale is debug-only via from_code, get marks too, and
   looked_up() lists what was looked up for an app's audit.
6. intl_pluralrules pinned to =7.0.2; plural_form_counts copied from the
   checker, plus pt.
7. I18n::new takes the app's offered codes: languages(), from_code,
   match_tag and system_lang only return those; others stay fallbacks.

Smaller: en/pseudo/repeated codes are skipped and reported,
system_lang is cached, zh-hant-hk falls back to zh-hant, rtl adds ckb,
dv, ps, sd, ug and yi.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 19:12:01 +01:00
Martin BallandClaude Opus 5.5 886a0b367f i18n: sr_RS@latin picks sr-latn; README macro and get wording
Review fixes (CodeRabbit): a glibc @latin/@cyrillic modifier becomes the
script subtag and only codes with that script are tried. sys-locale
drops the modifier, so on desktop Unix system_lang reads LANGUAGE,
LC_ALL, LC_MESSAGES and LANG raw, in its order. README: tl! qualifies
CURRENT with $crate; get follows the locale chain but never the plain
row or English.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 10:38:04 +01:00
Martin BallandClaude Opus 5.5 10592ba4fd ci(i18n): run clippy and tests for craft-i18n on all three platforms
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 10:07:11 +01:00
Martin BallandClaude Opus 5.5 841ebed58c i18n: prefer pt over pt-br, no fallback across scripts, lookup without fallback
Final review fixes: a European Portuguese locale wins over pt-br when both
are embedded; sr-latn no longer falls back to Cyrillic sr; get() looks up
one context with no plain or English fallback (key-cap names).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9fM3mv1PUyKpk5rdwUQrW
2026-10-18 09:33:21 +01:00
Martin BallandClaude Opus 5.5 c9bcc60832 i18n: README and library listing
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9fM3mv1PUyKpk5rdwUQrW
2026-10-18 09:33:21 +01:00
Martin BallandClaude Opus 5.5 6346621e91 i18n: pseudo locale
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9fM3mv1PUyKpk5rdwUQrW
2026-10-18 09:33:14 +01:00
Martin BallandClaude Opus 5.5 cfbc6a1adf i18n: languages, names and system locale matching
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9fM3mv1PUyKpk5rdwUQrW
2026-10-18 09:33:14 +01:00
Martin BallandClaude Opus 5.5 c84b14d6c2 i18n: plurals and placeholder filling
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9fM3mv1PUyKpk5rdwUQrW
2026-10-18 09:33:14 +01:00
Martin BallandClaude Opus 5.5 7b797335cb i18n: catalog parsing and lookup with fallback
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9fM3mv1PUyKpk5rdwUQrW
2026-10-18 09:33:14 +01:00
skylar taylor-barrick 82a24b006e Merge pull request #169 from skylartaylor/docpath-crate
Add craft-docpath
2026-10-17 12:00:19 -06:00
skylar taylor-barrick a92010200c test(docpath): assert Unix-shaped results only on Unix
resolve_absolute_refuses_results_that_are_not_absolute resolved links against a
document at /home/u/docs/a.doc outside its cfg!(windows) branch. On Windows that
path is rooted but has no drive, so it is not absolute, resolve_absolute refuses
the result as documented, and the unwrap panicked. The Windows arm already covers
the same three cases with a drive. Found by the new docpath CI job on its first run.
2026-10-17 11:10:18 -06:00
skylar taylor-barrick 5542a9466d ci(docpath): run clippy and tests for craft-docpath on all three platforms
The per-crate workflows name their crates with -p, so the new crate had no job
and its tests, including the Windows-only colon and stream assertions, never ran
in CI.
2026-10-17 10:20:41 -06:00
skylar taylor-barrick 04e83f095a Merge pull request #166 from storytold/fix/models-provenance-for-a-running-test
craft-ai-core: record which address a test's models came from
2026-10-17 08:50:21 -06:00
skylar taylor-barrick 559992953f craft-ai-core: record which address a test's models came from
A test is not instant and the address field stays editable while it runs,
so its answer can arrive after the address has changed. `set_models` then
recorded the models against whatever the field held by the time it
returned, filing one endpoint's models under another — the mislabelling
`models_fit` exists to prevent, reached the asynchronous way rather than
the synchronous ones already closed.

`set_models` now takes the address the test was started against and
returns whether the models were taken, so an answer that outlived its
address is dropped and the caller can say the result is out of date. The
parameter replaces the old signature rather than joining it: there was no
second legitimate caller, and leaving an address-free version beside it
would have left the racy call the shorter, easier one to reach — against
this module's rule that the rules live once so two screens cannot
disagree.

Also fixes a pre-existing mismatch found while testing this:
`from_connection` recorded the loaded address untrimmed while `prepare`
compares it trimmed, so a stored endpoint with stray whitespace dropped
its models on the first save.
2026-10-16 23:07:53 -06:00
aiongg c04cc16109 fix(docpath): colons in names are refused only on Windows 2026-10-17 04:14:51 +00:00
skylar taylor-barrick 15ed713b8f Merge pull request #69 from Jeremy8776/feat/ai-model
Model provenance across loaded and preset endpoints and repeated endpoint edits, so models from one endpoint are not relabelled as another's, and eligibility resolved in both directions: a model must accept every input the tool sends, and the tool must supply every input the model requires (new ResolveError::InputRequired).

All 18 checks pass on a40245bd, including craft-ai-core fmt, clippy -D warnings, tests and the wasm32 check on Ubuntu, Windows and macOS.

Note for callers: after a tracked endpoint change, use set_models for newly discovered models; direct assignment on fresh custom drafts and unchanged saved endpoints still works. The asynchronous in-flight probe race is separate and not addressed here.
2026-10-16 21:56:16 -06:00
aiongg 0d0e5efaac feat(docpath): add resolve_absolute
resolve_absolute refuses a result that is not absolute on the running
platform, such as a relative link in a document that has no path yet.
It is the function to call before opening a file.
2026-10-17 03:36:22 +00:00
aiongg d7772fbb39 fix(docpath): refuse colons inside path components
A stored path that starts with a URL scheme and a colon is a URL; a
colon in any other name is invalid. Only a leading drive letter keeps
its colon.
2026-10-17 03:35:36 +00:00
skylar taylor-barrick a40245bd36 craft-ai-core: track model provenance by address; require the inputs a model needs 2026-10-16 20:26:06 -06:00
skylar taylor-barrick 83bf4cb25c Merge pull request #148 from midasmatterhorn/fix/r4-cms-icc-checked
cms: bound the ICC curve count before it is multiplied, and read mluc record offsets checked
2026-10-16 10:58:04 -06:00
aiongg 12281d07fe fix(docpath): accept drive hosts, legacy escapes and colon names; refuse lookalike separators 2026-10-16 16:14:16 +00:00
aiongg ddc5012437 feat(docpath): add craft-docpath for checking paths stored in documents 2026-10-16 16:01:59 +00:00
midasmatterhorn 8b71728482 cms: the mluc record is read as one checked 12-byte slice
The eager tuple computed o + 8 even when the first read had failed,
overflowing a 32-bit usize at offsets near u32::MAX (n = 2 with
size = u32::MAX - 20 reaches it: o fits, o + 8 does not). The record is
now bounds-checked in one slice and the fields read inside it, the same
complete-record pattern the profile reader uses elsewhere.
2026-10-16 14:46:23 +03:00
Jeremy 90792958fb Merge remote-tracking branch 'upstream/main' into feat/ai-model
# Conflicts:
#	Cargo.toml
#	README.md
2026-10-15 20:07:18 +01:00
Jeremy bd175be54f craft-ai-core: rename from craft-ai-model; lapse each kind of consent on its own; keep models found at a new address
Consent expiry is now per kind of data: renewing text no longer renews an expired image permission. A connection edit keeps models found by a test at the new address, and drops only the ones saved for the old one.
2026-10-15 20:06:57 +01:00
midasmatterhorn 1db56c92d2 cms: bound the ICC curve count before it is multiplied, and read mluc record offsets checked
parse_curve computed 12 + n * 2 with n straight from the file and only
checked the 1 << 20 bound afterwards, inside the table arm — on a 32-bit
(wasm32) target, which craft-cms ships branches for, a trC curve count of
0xFFFFFFFF overflows with overflow checks on and panics before the guard
could reject it. The mluc reader computed 16 + k * size unchecked, where
wrapping reads another record's bytes as the language, length and offset
(wrong text, no error) instead of stopping.

Hoist the curve-count guard above the arithmetic and compute the record
offset with checked_mul/checked_add, breaking out when it does not fit.
This ports the app-side fix accepted as PhotoCraft #4976 / PR #5227,
which was never carried into craft-cms. On a 64-bit host both sites are
benign (the arithmetic fits), so the two new tests pass before and after
there; they bite on a 32-bit/overflow-check build, which deserves a
wasm32 CI job — craft-cms has none yet.
2026-10-15 17:58:13 +03:00
skylar taylor-barrickandskylartaylor 8f5a283161 ci: add comfortable runtime limits to unbounded jobs (#136)
Co-authored-by: skylartaylor <26588250+skylartaylor@users.noreply.github.com>
2026-10-15 05:15:52 +02:00
skylar taylor-barrick 2c67684303 feat(pdf): share patched PDF reading and rasterization (#106)
PDFR / #106: share the patched PDF reader, interpreter and raster boundary
with explicit input and decode limits, diagnostics and portable contracts.

Preserve the original reader/writer commits and immutable consumer pins.
Fresh current-main workspace gates and all 15 hosted jobs passed on the
exact integration tree. Applications retain their own import/export policy.
2026-10-14 20:01:00 -06:00
skylar taylor-barrick 7cd7fbbbe3 fix(pdf): integrate shared reader with main
PDFR: retain the reviewed reader and writer pins while incorporating current
printing changes and the CMS test lint correction.
2026-10-14 19:45:28 -06:00
skylar taylor-barrick 6cddad4079 feat(pdf): add guarded shared PDF writing (#105)
Add opt-in shared PDF authoring with bounded font preparation, caller-owned metadata and settings, guarded serialization, and a backend that rejects poisoned drawing state.

Preserve the existing writer commits so immutable dependency pins remain reachable from main. Reader and application migrations remain separate.

PR #105.
2026-10-14 19:19:41 -06:00
Jeremy cb7f55bae4 craft-ai-model: scope consent to a capability and let it lapse
A configured connection does not authorise an app by itself. An agreement now
covers one app, connection, destination and capability, for the kinds of data
it named, and may carry an expiry (unix seconds).

- Disclosure carries the capability; ConsentRecord gains optional capability
  and expires_at.
- ConsentLedger::needs_consent takes the time (the crate has no clock);
  grant_until sets an expiry, grant stays open-ended. The latest grant sets
  the expiry for that capability only.
- Records saved before this have no capability and cover nothing, so the
  person is asked once more.

Nine new tests; six deliberate bugs (expiry ignored, off by one, capability
ignored, legacy record covers everything, expiry not updated, timed grant made
permanent) were each caught.
2026-10-14 14:21:44 +01:00
skylar taylor-barrick ca50d63b77 fix(pdf): preserve upstream reader behavior during migration 2026-10-14 02:26:18 -06:00
skylar taylor-barrick b4712ff5e5 fix(pdf): preserve optional shaping in the reader stack 2026-10-14 00:11:03 -06:00
skylar taylor-barrick f39922b214 fix(pdf): make backend text shaping opt-in 2026-10-14 00:01:36 -06:00
skylar taylor-barrick 457a078809 Merge pull request #42: qualify native Windows printing
Validate native Windows submission and share RGB printing
2026-10-13 22:38:03 -06:00
skylartaylor 8b8576f0b0 Use fixed-size chunks in the CMS total-ink regression 2026-10-14 06:27:12 +02:00
skylartaylor 21e297f440 Merge commit '3d37da389a3618ab9b76109da11416e9ca4ea719' into codex/final-merge-native-libs-20261014-root 2026-10-14 06:16:39 +02:00
Jeremy ba6ff9187c Add craft-ai-model: the data model and contract for AI in the Craft Apps 2026-10-13 21:53:38 +01:00
skylar taylor-barrick 89dcbb3060 test(pdf): pin extraction policy and retry fixtures (PDFR) 2026-10-13 13:24:54 -06:00
skylar taylor-barrick c07b3fada6 feat(pdf): share patched reading and rasterization 2026-10-13 12:52:32 -06:00
skylar taylor-barrick c3487320b2 feat(pdf): add shared guarded writer foundation 2026-10-13 12:29:12 -06:00
skylar taylor-barrick e9546e191d Merge pull request #43 from storytold/codex/atomic-normal-permissions-20261013
craft-atomic: default to normal file permissions with explicit private writes
2026-10-12 23:38:37 -06:00
skylar taylor-barrick 278d276ae9 Merge pull request #39 from aiongg/craft-cms
Add craft-cms: ICC colour management from PhotoCraft, with a FOGRA39-fitted CMYK profile
2026-10-12 23:04:29 -06:00
aiongg 9e2b2b03d8 craft-cms: separate exact profile-name matches from stand-ins
Builtin::from_profile_name matches only a built-in's own description.
Builtin::stand_in_for adds the FOGRA39 approximations (Coated FOGRA39, ISO
Coated v2) for documents that name a profile without carrying its bytes.
ISO Coated v2 300% (ECI) has no stand-in: the built-in separates to up to
330 % total ink. The README example parses the document's ICC bytes first
and handles a missing stand-in explicitly.
2026-10-13 03:22:39 +00:00
aiongg d282bd06c6 craft-cms: reference-value regression cases, including the reported DesignCraft orange
The reference value for CMYK 0/41/90/4 in Coated FOGRA39 is 239,161,35.
The fitted profile gives 239,161,33 (ΔE00 0.16); the uncalibrated formula
DesignCraft used gives 245,144,25 (ΔE00 6.36). Six more reference values
(K50 grey, rich black, light tint, skin tone, C+Y green, near-neutral)
are within 0.7 ΔE00.
2026-10-13 03:17:20 +00:00
skylar taylor-barrick 3d37da389a Merge current core print progress while retaining submission guards 2026-10-13 05:03:53 +02:00
skylar taylor-barrick d873514e8a Document driver option refusal and equivalent grayscale capability 2026-10-13 04:50:19 +02:00
skylar taylor-barrick 3929c3d14c Refuse explicit print options dropped by Windows drivers 2026-10-13 04:48:42 +02:00
skylartaylor b55b21cdeb Apply permission policy review before first release 2026-10-13 04:33:01 +02:00
aiongg 7f05840bc0 craft-cms: portable moxcms CMYK oracle with the built-in Coated FOGRA39
The Generic CMYK oracle only runs where macOS ships that profile. The
same comparison (CMYK -> sRGB, 8-bit, relative colorimetric without
BPC, same bytes for both engines) with the built-in Coated FOGRA39
runs everywhere. Measured: max 10, p99 5, mean 0.89 codes; the worst
pixel matches an independent float computation, not moxcms.
2026-10-13 01:50:14 +00:00