Commit Graph
3466 Commits
Author SHA1 Message Date
David MannandClaude Opus 5.5 e1ce85a5df PSD: Hue/Saturation export writes each triplet in its own slot (#7065)
The hue2 block holds a colorize triplet at byte 4 and a master triplet at
byte 10. The writer copied the active triplet into both, so a Colorize hue of
200 also landed in the master slot (outside its -180..180 range) and toggling
Colorize in Photoshop showed the wrong values.

Write the active triplet at its own offset and Photoshop's defaults in the
other (colorize 30/25/0, master 0/0/0), with the colorize hue stored signed as
Photoshop does (200 -> -160). The reader maps a negative colorize hue back to
the model's 0..360.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:55:28 +02:00
dotCooCoo c2cf0e0610 Merge main into fix/mixer-brush-clean-and-load 2026-10-17 16:28:35 -07:00
skylar taylor-barrick ead6d2197f Package: report its paths with / on Windows too (#7184)
`file.package` absolutised the caller's `dir` and then built `folder`, `document`
and every `links` entry on it with `join`, which always writes `/`. On Windows
that left one string spelt both ways:
`C:\Users\...\pkg/Print Me/Links/art.png`. The control channel takes `/` and
rejects alternate separators, so a reported path could not be handed back to it.

Spell the absolutised directory with `/` as well, keeping a leading `\\`
(verbatim and UNC prefixes, where Win32 does not accept `/`) intact.
2026-10-17 19:20:33 -04:00
skylar taylor-barrick f8cd3e7982 chore: clear the rustc 1.96 clippy lint that fails CI
Unrelated to this branch's change; main already fails clippy --all-targets -- -D warnings
without it, which is what failed the Windows integration job here. One
clippy::nonminimal_bool site in canvas.rs, taking clippy's own rewrite: the
negation stays outside, so the is_finite guards and their NaN behaviour are
unchanged. A sweep of all 30 workspace members found no other site.
2026-10-17 17:08:37 -06:00
dotCooCoo 3c9c93ed8c GPU startup: Auto on Windows leaves Vulkan out when an Intel adapter is present (#4)
With the `auto` backend on Windows, eframe created its wgpu instance with
Vulkan, and creating it, listing its adapters and asking each adapter
about the window's surface loaded and ran the Intel Vulkan driver
(igvk64.dll) before the adapter selector could pick Intel's DX12
adapter. When the driver crashed there, the first launch died, and only
the next one moved to DX12 through the startup marker.

`configure` now lists the DX12 adapters first, with a DX12-only
instance, when the plan is `auto` on Windows without WGPU_BACKEND. If
one of them is an Intel adapter, the instance is created with DX12 and
GL only (GL stays the last resort), so no Vulkan driver is loaded. On a
system with an Intel and a discrete GPU, the discrete GPU then runs on
DX12 instead of Vulkan. WGPU_BACKEND, --safe-gpu, a chosen backend and
the crash fallback are unchanged, and System Info still shows the Intel
DirectX 12 note.

The decision is `windows_auto_backends`, tested with vendor lists.
2026-10-17 15:28:20 -07:00
Michael Higgins 2e3aa8ded2 Merge branch 'main' into fix/5884-delay-load-windows-data-pdf 2026-10-17 18:17:21 -04:00
Diego Chagas 235e7578f3 Print through CUPS over IPP and the print portal, so File › Print works in the Flatpak (#2728) (#3017)
Main prints through craft-print, which runs `lp`; a Flatpak has no `lp`,
so File › Print fails there. This keeps craft-print as the route wherever
`lp` is on the path (and on Windows) and adds two more behind it:

- `photocraft-ipp`, a pure-Rust IPP client (CUPS-Get-Printers/Classes/
  Default, Print-Job over HTTP/1.1) that talks to CUPS over its socket or
  TCP; the Flatpak manifests grant --socket=cups for it. A `printServer`
  named in the request always takes this route. `file.print.printers`
  lists the queues.
- The XDG Print portal as the app's spooler (`Session::print_spooler`),
  for a sandbox without the CUPS socket or a system without a printer:
  the system print dialog, seeded with copies, paper and orientation.
  PHOTOCRAFT_PRINT_PORTAL=1 prefers it, =0 removes it.

A route that exists but fails (unknown printer, refused job) is an error;
only a missing route moves on. Results gain `backend` (lp, windows, ipp,
portal). docs/printing.md describes the routes.
2026-10-17 15:55:54 -06:00
Higgs32584andClaude Opus 5.5 86f6199b01 Print: load Windows.Data.Pdf.dll before using it; fix the error hint (#5884)
Review follow-up on #6395:
- Check that the DLL actually loads (winsafe `LoadLibrary`, no unsafe) rather than that the
  file exists: a DLL that is present but cannot load still aborts at the delay-load stub.
- The hint no longer says to clear Print Settings; that doesn't take a page off the PDF path.
  It now points to Save as PDF, or printing an RGB image without page text or labels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:53:11 -04:00
Derek GliwaandClaude Opus 5.5 2cf274f991 Brushes: accept .abr files up to 1 GiB
Import Brushes refused .abr files over 512 MiB: the engine's preset file cap
and the .abr decoder's sample budget were both 512 MiB. Raise both to 1 GiB
for brush files only; gradient, swatch, action and image-tip imports keep the
512 MiB cap. A compile-time assert keeps the reader and decoder caps equal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:38:11 -05:00
Michael HigginsandClaude Opus 5.5 1d65bd605b Web: Place Embedded and canvas drops place images (#5749) (#5817)
* Web: Place Embedded and canvas drops place images (#5749)

File > Place Embedded was disabled in the browser (the engine command reads a
path), though the menu path reads the picked file's bytes. Files dropped on
the canvas were always opened as new documents. The web shell now tracks the
drag position, and drops on the canvas are placed from their bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Format (cargo fmt)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Narrow to the web canvas-drop half: Place Embedded enablement landed in #5585

Drop the picker test that covered the part #5585 now owns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:20:44 -07:00
skylar taylor-barrick 06ad0d5c95 Merge pull request #2863 from 1Git2Clone/ci-panic-hunt
CI: run panic_hunt in the Linux test job
2026-10-17 12:14:20 -06:00
skylar taylor-barrick 039b86f8f6 Merge pull request #7149 from skylartaylor/linked-path-checks
Follow linked paths only on this computer or the document's share
2026-10-17 12:13:47 -06:00
skylar taylor-barrick 482fd899cf Build: take craft-docpath from the merged craft-libs rev
craft-libs#169 is merged, so the fork pin is no longer needed. Pinned to
storytold/craft-libs 82a24b006eefa036b43c09a67fb9a3fbd17ffe63 (main after the merge) rather than the older 12281d07,
which predates resolve_absolute and the Windows colon refusal.
2026-10-17 12:02:56 -06:00
Gert Pellin - GPE ba40454b18 Logging: a second launch leaves the running instance's log alone (#6432) (#6478)
logging::rotate renamed photocraft.log up the chain on every start without
knowing whether another instance still wrote to it. The running instance
kept its handle, so after a second launch its live log was .1.log, after a
third .2.log, and a fourth launch deleted it.

The instance that writes photocraft.log now holds an exclusive lock on
photocraft.lock until it exits (a separate file, since Windows locks are
mandatory and would keep the log itself from being opened). A start that
finds that lock held leaves the chain alone and writes
photocraft-<pid>.log, marked by photocraft-<pid>.lock. Those side-by-side
logs are pruned to the newest KEEP once their instances have exited; a
held one is never touched. Rotation and pruning run under rotate.lock so
two starts at once can't interleave. On a file system without locks every
start rotates as before.
2026-10-17 11:57:39 -06:00
Khawar Zamman WaniandClaude Opus 5.5 378231214a Desktop app: photocraft --help prints usage; unknown options are usage errors (#6431) (#6435)
* fix(desktop): `photocraft --help` prints usage; unknown options are usage errors (#6431)

The desktop binary's argument loop took every argument it didn't know as
a file, so `photocraft --help`, `-h` or a typo such as `--safegpu`
opened the window and logged "Couldn't open --help".

- `--help` / `-h` print the usage (every option and environment
  variable) and exit 0.
- Any other argument starting with `-` (except macOS `-psn_`) is named
  on stderr and the launch exits 2 before the log file or window, along
  with any bad `--control` port (`control_args_exit_code` becomes
  `usage_exit_code`).
- `--` ends the options, so a file whose name starts with `-` opens.
- `--help` and `--version` write without `println!`, so a closed pipe
  (`photocraft --help | head -1`) can't panic.

Tests: apps/photocraft/tests/command_line_usage.rs runs the binary with
no display; 4 of its 6 tests fail on the old code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(desktop): usage tests exit before the window opens; fmt smart_filter_authorization

`arguments_after_double_dash_are_files` and `macos_process_serial_number_is_still_ignored`
passed only valid arguments, so the app went on to open its window. Removing DISPLAY makes
that fail fast on Linux, but Windows runners have a desktop and both tests hung until
nextest's 600 s timeout. They now add a bad `--control` value so the launch always fails
with the usage errors, and assert stderr names only that error (no "unknown option").

Also `cargo fmt` crates/automation/tests/smart_filter_authorization.rs, left unformatted
on main by #5684, which failed the Format step of every PR's ubuntu test job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:57:27 -06:00
ZuujisandClaude Opus 5.5 796ee3b103 Image Assets: two layers naming the same file no longer overwrite each other (#6614) (#6668)
* Image Assets: two layers naming the same file no longer overwrite each other (#6614) [WIP]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Image Assets: two layers naming the same file no longer overwrite each other (#6614)

generate_assets wrote every requested asset, so two layers (or two
default variants) naming one file silently replaced each other and the
result listed the file twice. Each file is now written once per run:
layers go top first, as the Layers panel lists them, the first writer
keeps the name, and later ones are reported in errors. Names are
compared ignoring case, since Logo.png and logo.png are one file on
Windows and macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:55:54 -06:00
David MannandClaude Opus 5.5 589941a536 Save: refuse to replace a read-only file (#6600) (#6643)
Saving writes a temporary file and renames it over the destination. A
rename only needs the folder to be writable, so on Linux and macOS a
read-only (chmod 444) file was silently replaced, while on Windows the
rename failed with a vague "locked or read-only" access error.

atomic_write now asks the AtomicFs whether the existing destination is
read-only (new `is_readonly`, false by default for other implementors)
and refuses before anything is written: "cannot save <file>: the file
is read-only; the original file was not changed". New files and
writable files save as before. Photoshop refuses the same way; the
user saves a copy with Save As.

Tests: a fake AtomicFs reporting read-only gets the error with nothing
written or renamed; a real file marked read-only keeps its bytes and
mode and gets the clear message on every platform.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 11:55:43 -06:00
David MannandClaude Opus 5.5 c9899e9c29 Duotone: ink curve points must be finite (#7049) (#7050)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:55:31 -06:00
Marco Arnulfo e196d8e47c Opening a file that is already open shows its tab instead of a second copy (fixes #6598) (#6630) 2026-10-17 11:53:21 -06:00
ZuujisandClaude Opus 5.5 1dcaa28b96 Quick Export: Same Folder asks before replacing the document's own file (#6599) (#6632)
With Export Preferences › Location = Same Folder, Quick Export wrote
<name>.<format> beside the document's file with no check, so a document
opened from photo.png was exported over photo.png itself. The app now
opens the save dialog for that case, and file.export.quickExport refuses
it without a `path`. Overwriting an earlier export beside a PSD is kept.

Adds file_cmds::same_file (text, dev+inode on Unix, case-insensitive
canonical path on Windows).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:53:10 -06:00
David MannandClaude Opus 5.5 193f495e5a Perspective Crop and Rotate Arbitrary keep the Background opaque (#7138)
Both filled the Background's uncovered area with the background colour
including its alpha (tools.setColors accepts one), leaving see-through
pixels on a Background. They now use alpha 1, as crop_doc does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:44:29 +02:00
David MannandClaude Opus 5.5 2f038c5eb2 Perspective Crop: W and H follow the Point/Pica Size preference (#7135)
size_params converted points at a hard-coded 72 per inch. It now uses
Preferences › Point/Pica Size, as the rulers, the type tools and the
Crop tool do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:37:40 +02:00
Michael Higgins 4146d61b78 Merge branch 'storytold:main' into fix/6884-pen-tool 2026-10-17 13:36:48 -04:00
David MannandClaude Opus 5.5 2a690f0f71 Crop: a refused crop keeps the frame for fixing (#7133)
commit_crop cleared the box Undo, took the frame, turned the view upright
and reset the angle before running image.crop, and restored nothing when
the engine refused it (e.g. a resolution past 10 000 ppi). It now keeps
the frame, its turn, its box Undo/Redo and the view and puts them back on
an error. Leaving the tool with a refused frame cancels it instead of
retrying every frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:30:02 +02:00
David MannandClaude Opus 5.5 22cacbf198 Perspective Crop: switching documents drops the pending box (#7130)
perspective_crop_ui::cancel_stale ran only on a pointer event or a
commit, so after a tab switch the other document's quad was drawn (and
reported) until the next press. sync_views now runs it next to the Crop
tool's cancel_stale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:21:38 +02:00
Nicolas FalesyandClaude Opus 5.5 4b660fcffa perf(camera-raw): Shadows/Highlights 1.5× faster, bit for bit the same
The fast local Laplacian filter upsampled every remapped level in full for
every reference (up to 96), but each pixel reads that level for at most two
references. `llf` now samples it only where the weight is nonzero, with
`up_at` (same terms, same order as `up`; row taps found once per row,
`mirror` only near the edges). `quantile` selects its element instead of
sorting the whole work copy (5 sorts per render, serial).

36 MP dialog, all cores: Shadows 252 -> 168 ms, Highlights 275 -> 184 ms,
all 14 sliders 627 -> 411 ms. Output hashes match main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FUAqfMqVHdoeDa2y68KQQw
2026-10-17 13:18:21 -04:00
David MannandClaude Opus 5.5 b052fd591e Crop: Straighten is one box Undo step (#7127)
The Straighten branch of crop_ui::pointer returned before the press step
was recorded and pushed, although it turns the frame and makes it
pending. With a crop pending, Undo then undid the document (or skipped a
box step). It now records the step like every other frame gesture,
through a shared push_press_step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:15:25 +02:00
David MannandClaude Opus 5.5 617b75597c Image Size: type keeps its pixel size when the resolution changes (#7124)
image.imageSize set the new resolution and then resampled, which scales
the type transform by the pixel factor and re-renders at the new ppi
(text px = pt x dpi / 72): doubling 72 -> 144 ppi made text 4x as tall.
With Resample off the pixels stayed but the next re-render doubled them.

canvas_geom::set_resolution now changes the resolution keeping type the
same size in pixels, as Photoshop does: text space grows by new / old, so
the box and path scale with it and the layer transform undoes that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:08:58 +02:00
David MannandClaude Opus 5.5 fd99c1f464 Perspective Crop: a drag without area leaves no crop box (#7061)
A straight drag (no width or no height) made a zero-area quad that could neither be committed nor replaced by a new drag, only cleared with Esc. Such a drag now leaves no box.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:45:34 +02:00
skylar taylor-barrick 8c12449819 Save: keep the replaced file's metadata (#6603, #7073, #7094, #7095, #7096)
Saving writes a temporary file and renames it over the target, so everything
attached to the old file went with the file that was unlinked. Several of those
are security decisions, so a save quietly undid them: a download lost its Mark
of the Web, an explicit ACL fell back to whatever the folder hands down.

New crates/format/src/atomic/meta.rs, reached from atomic_write through two
AtomicFs methods (copy_permissions became copy_metadata; replace_existing is new
and defaults to rename, so the failure-injecting test file systems are
unchanged):

- Extended attributes (#6603): flistxattr/fgetxattr/fsetxattr through safe
  rustix, per attribute, best effort. macOS Finder tags, com.apple.quarantine
  (the Mark of the Web's macOS counterpart) and Linux user.* all ride along.
  Attributes the system owns refuse to be written and are skipped;
  com.apple.decmpfs is skipped deliberately, since it describes storage the new
  bytes do not have.
- macOS ACL (#7073): a new macOS-only exacl dependency (MIT).
  fcopyfile(COPYFILE_ACL) is an unsafe fn and fclonefileat(CLONE_ACL) is
  APFS-only and would mean writing every save as clone-then-truncate; the
  reasoning is in docs/decisions.md. A file with no ACL is left alone.
- Windows (#7094, #7096): ReplaceFileW through winsafe's kernel feature (MIT,
  no dependencies, a safe wrapper; the workspace forbids writing the FFI call
  here). One call keeps the destination's DACL, its named streams including
  Zone.Identifier, and its creation time.
- Automation write path (#7095): AuthorizedWorkspace::write copies the replaced
  file's attributes through the two cap-std descriptors, never a path, so a
  request path still cannot escape the write root. Permissions there remain
  #4963; ReplaceFileW is path-based and so is not used on that path.

The order inside copy_metadata matters: attributes and ACL first, permission
bits last. Writing an attribute needs the destination open for writing, so
copying a 0444 mode onto the temporary file first locks you out of your own
temporary file. Covered by a regression test.

Atomicity is not weakened. The metadata step runs on the temporary file before
the swap, never touches bytes, and never fails a save. Windows is the one place
the swap itself changed, and a backup file name is passed because it is a
correctness requirement, not an option: ReplaceFileW without one documents
ERROR_UNABLE_TO_MOVE_REPLACEMENT as leaving the replaced file deleted and the
replacement under its temporary name, which is a failed save that loses the
user's document. With a backup name the same failure leaves both files alone.
ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, the one error that does move things, is
unwound by hand; every other error falls back to the plain rename, i.e. to the
previous behaviour.

THE WINDOWS PATHS ARE UNVERIFIED ON WINDOWS. They were written and reviewed on
a Mac. The #[cfg(windows)] tests -- Zone.Identifier, a second named stream,
icacls output, creation time -- have never executed. They do compile and pass
clippy -D warnings against x86_64-pc-windows-msvc, which is as far as a Mac
gets. CI's Windows job is the first real run, and #7094 in particular (Mark of
the Web surviving a replace) is the whole point of the change and is the part
no one has observed working.

Tested on macOS: a real chmod +a entry and a real Finder tag both survive a
save (checked with ls -le and xattr, and as unit tests), plus a 64 KiB
attribute value, a read-only file, the mode, and the automation path.

Still open: Linux POSIX ACLs are not carried over (system.posix_acl_access is
not reported by listxattr, so it needs its own step; not part of these issues),
and macOS creation time is still reset by a save (that half of #6603 needs
setattrlist, which has no safe wrapper here).
2026-10-17 10:43:09 -06:00
David MannandClaude Opus 5.5 638912f0a6 Merge main into fix/6575-psd-unknown-adjustment
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:36:20 +02:00
David MannandClaude Opus 5.5 4286ff86a9 Merge main into fix/6550-selected-path-outline
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:30:12 +02:00
David MannandClaude Opus 5.5 5d6e0331e3 Merge main into feat/tool-213-4-cam-preview-large
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:30:04 +02:00
David MannandClaude Opus 5.5 b6f18820c6 Merge main into fix/pcraft-load-nonfinite
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:26:31 +02:00
David MannandClaude Opus 5.5 e30cedbb2a Merge main into fix/transform-fill-cache
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:24:17 +02:00
David MannandClaude Opus 5.5 c5b1f7769a Merge main into fix/6539-lightness-track
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:21:07 +02:00
David MannandClaude Opus 5.5 a4190ad6a0 Merge main into fix/droplet-conditional-actions
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:20:49 +02:00
David MannandClaude Opus 5.5 0e98028f24 Merge main into fix/tiff-filter-effects-sections
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:18:51 +02:00
David MannandClaude Opus 5.5 cdf7f2c7fe Merge main into fix/gradient-offset-resize
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:13:04 +02:00
itsF4LCON 3bca0123b0 Type: the blink-phase test finds the caret by its strokes
arrow_keys_reset_caret_blink_phase (#5512) looked for a 1.5-wide line, the old caret. The caret is now CARET_STROKES (a 3 pt white halo and a 1 pt black line), so the test matches those.
2026-10-17 18:12:29 +02:00
David MannandClaude Opus 5.5 847dc9eb08 Merge main into fix/auto-align-mask
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:10:39 +02:00
David MannandClaude Opus 5.5 f0cd444a53 Merge main into fix/6535-clipped-adjust-damage
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:10:24 +02:00
David MannandClaude Opus 5.5 0aa456edc3 Merge main into fix/6267-psd-hue-sat-sf
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:06:09 +02:00
itsF4LCON 6d521c2d3e Merge remote-tracking branch 'upstream/main' into fix/6085-text-caret-contrast 2026-10-17 18:04:21 +02:00
David MannandClaude Opus 5.5 363462e8d2 Merge main into fix/6268-psd-perspective-warp-sf
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:03:47 +02:00
dotCooCoo 074d4b08b6 Stack Mode: Kurtosis and Skewness give the same bits on Windows and Linux
`stat` raised each deviation from the mean to a power with `f32::powi`,
with the exponent passed through the moment closure. On
x86_64-pc-windows-msvc that call goes to the C runtime's `powf`, whose
cubes and fourth powers can differ from repeated multiplication in the
last bit. On Linux the same call gives the bits of repeated squaring, as
compiler-builtins' `__powisf2` computes it. Kurtosis
came out one ULP higher on Windows in two values of the test fixture, and
`stack::tests::statistics_are_bit_identical_to_the_serial_implementation`
failed there.

The moments and Skewness's `sd³` now use `ipow`, which multiplies by
repeated squaring: `x·x²` for the cube and `x²·x²` for the fourth power.
Results on Linux do not change, and the recorded bits stay as they are.
2026-10-17 08:58:44 -07:00
IvanandClaude Opus 5.5 a4fe4ffbed Contributors: add 1Git2Clone
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:37:13 +03:00
IvanandClaude Opus 5.5 45afd2e9d7 CI: run panic_hunt in the Linux test job
The full-registry fuzz (AGENTS.md Rule 9) is #[ignore]d and no workflow ran it, so nothing
enforced "must stay green". The new step reruns the Test step's nextest selection with
--run-ignored only, filtered to the panic_hunt binary, so nothing rebuilds; the ci profile
terminates it if it hangs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:37:12 +03:00
David MannandClaude Opus 5.5 3096e456dd Merge main into fix/preset-group-rename-unique
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 17:24:08 +02:00
David MannandClaude Opus 5.5 340f282c8a Merge main into fix/extending-crop-keeps-hidden-background
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 17:22:59 +02:00