446 Commits
Author SHA1 Message Date
FredApps 885a6ddf27 Merge pull request #9864 from Higgs32584/fix/8806-rasterize-click-replay
fix(ui-egui): the rasterize prompt no longer replays the click that opened it (#8806)
2026-11-09 11:55:33 +01:00
David MannandClaude Opus 5.5 7c0cc59ca3 Merge main into feat/auto-219-8-panel-command-check
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 19:13:19 +01:00
David Mann 017c4aab9e Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	docs/scorecard.md
2026-11-06 22:57:46 +01:00
Saloouu 3ed01375e5 Merge main 2026-11-06 18:13:34 +01:00
Saloouu 633201a72b Merge main 2026-11-06 04:45:27 +01:00
David Mann 66c328dc2b Merge commit '9bef3b2dc8b84c1b6cefc8ce0dc2b01d089cd9e8' into HEAD
# Conflicts:
#	docs/scorecard.md
2026-11-06 02:29:28 +01:00
David Mann dabf3bab97 Merge commit '9bef3b2dc8b84c1b6cefc8ce0dc2b01d089cd9e8' into HEAD
# Conflicts:
#	docs/scorecard.md
2026-11-06 01:54:36 +01:00
e4e2607c85 Preview spot inks over the RGB/CMYK composite as an overprint (#10276)
* PSD: a flat file's named extra channels are not its transparency

A PSD without layer records had its first extra channel read as the merged
transparency, so the first spot or alpha channel of a flattened document
vanished and its ink punched a transparent hole in the image (psd-tools
cmyk-alpha-spot.psd, cmyk-spot.psd). When the alpha channel names (1045, or
1006 when 1045 is missing) name every extra channel and the first is not
"Transparency", there is none. The import also reads channel names from
1006 when 1045 is missing, and a spot whose DisplayInfo colour space is
unknown takes its ink from the Alternate Spot Colors (1067).

* channel_map: read 1067 records with as_chunks

* Preview spot inks over the RGB/CMYK composite as an overprint

Visible spot channels of RGB and CMYK documents print over the canvas
composite with the Multichannel ink formula, in Channels panel order,
instead of a tint; alpha channels and Quick Mask still tint over them.
Spot channels open visible, and the PSD thumbnail (1036) prints them.
flatten, export and the merged image stay free of spot inks. Ink
colours go through the document's CMYK profile, and into an RGB
document's own profile.

Refs #10249

* channel_view: test solidity over a gray picture

* Thumbnail: matte only inked pixels; test the merged planes directly

Review feedback on #10276: pixels without spot ink keep their
transparency in the thumbnail buffer, and the thumbnail test checks the
saved merged process planes instead of a re-imported flatten.

* Thumbnail spot inks: sample big boxes on a 4x4 grid

Review feedback on #10276: reducing each spot channel no longer scans the
whole document; a thumbnail pixel averages at most 4x4 samples, so a huge
document costs about h x 4 row reads per spot.

* Spot overlay: composite a proxy for the first draw of big documents

The overprint needs the composite under the inks. Rendering the full-resolution
composite to sample every factor-th pixel cost ~1 s for a 24 MP CMYK document.
A proxy document picks the same pixels (nearest-neighbour downsample) for about
1/factor² of the work. Documents with layer effects, vector masks or feathered
masks keep the full-resolution path.

* Proxy: downsample rows in parallel; the overlay proxy leaves out unused channels

The spot overlay's proxy shrank the spot channels, selection and Quick Mask that an
RGB or CMYK composite never reads: about two thirds of its cost. downsample now
reads its rows in parallel, 64 at a time.

* Spot overlay proxy: keep the full-resolution composite under uncached pattern fills

A pattern fill renders its tiles at their own size on a proxy, so the proxy would
sample other pattern pixels. Unless the fill's matching cache is shrunk with the
proxy, use the full-resolution composite.

* Spot overlay proxy: hidden layers don't decide the composite path

Hidden layers and the contents of hidden groups are not composited, so a hidden
feathered mask or pattern fill no longer forces the full-resolution composite
(the same rule as proxy_faithful).

* Update crates/compose/src/multichannel.rs

Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>

* Spot overlay: only inked pixels replace the canvas; inks through the display transform

Where every visible spot is 0 the overlay stays transparent, so the normal
canvas (display LUT, proofing, 32-bit preview, full resolution) shows; an
empty spot renders no composite. Printed pixels go through the canvas
display transform (sRGB encoding of linear composites, monitor profile,
Proof Colors), keyed into the texture. Ink colours come from one InkSpace
per render: the document's profiles are parsed once, not per spot per
damage rect.

* test(compose): cover hidden spot preview and document approximation

* fix(ui-egui): preserve solo spot channel display when process colours are hidden

Clicking a spot channel row in the Channels panel targets the channel alone
and hides all process colour channels (`vis == 0`). Overprint inks were
previously extracted from `overlays` before checking `vis == 0`, leaving
`overlays` empty and causing the solo channel view to fall back to an active
layer mask (or return `None` if the layer had no mask).

Keep the spot channel in `overlays` so `vis == 0` can select it as the solo
grayscale picture, separating overprint inks only when process colours are
visible (`vis > 0`).

Adds a regression test targeting an existing spot channel in RGB and CMYK on
an unmasked layer and editing it.

* channel_view: document the spot overprint preview as an approximation

* test(ui-egui): solo spot channel wins over an unrelated layer mask

* channel_view: sRGB spot inks, lazy display transform, inked-area composite

Review fixes for the spot overprint preview:

- RGB spot colours are sRGB, like the CMYK, Lab and gray ones: InkSpace now
  converts them into an RGB document's own profile too. In a linear (EXR/HDR),
  Adobe RGB or ProPhoto document an RGB ink showed the wrong colour (brightened
  in a linear one once the canvas sRGB-encoded it).
- The display transform is looked up only when the view is redrawn and inks
  are shown, not every frame before the cache check; display_transform_for
  borrows the proof state (proof_ref) instead of cloning a default CMYK profile.
- Visible spot channels without ink, with nothing else shown, draw no texture:
  render returns None and ensure remembers it, instead of uploading an
  all-transparent document-sized texture. A damage re-render that finds nothing
  clears its rect, so erased ink never lingers.
- Printing a few inked pixels composites only their bounding box when that is
  cheaper than the whole (proxy) composite, and a cached composite is borrowed
  instead of copied.

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

---------

Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 23:34:12 +01:00
Saloouu 75df80fe33 Merge main and regenerate the scorecard 2026-11-05 19:18:47 +01:00
d7d138b1e5 Art History Brush: Opacity on the options bar (#10263) (#10278)
* Art History Brush: Opacity on the options bar (#10263)

The Art History Brush's own brush opacity is shown in its options bar
(0-100%) and sent to paint.artHistoryBrush. It is kept per tool, saved
across launches, set by the 1-0 keys and restored to 100% by Reset Tool,
as the Clone Stamp's is. Tests cover the UI wiring, per-tool persistence,
Reset Tool and stroke output at 8/16/32-bit.

* Update crates/ui-egui/src/panels/options_bar.rs

Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>

* Art History Brush starts at 100% opacity on first use

A tool picked for the first time takes the outgoing brush; the Art
History Brush now takes it at full opacity, as the issue's default asks,
so a 30% Brush no longer makes the first Art History stroke 30%. Other
tools keep inheriting opacity.

* Art History Brush: document Opacity in the command contract and carry it in tool presets

---------

Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-05 07:15:57 +01:00
Khawar Zamman WaniandFredApps ad59d9962c Type: add OpenType Stylistic Sets submenu (Set 1–20) (#10304)
* Type: add OpenType Stylistic Sets submenu (Set 1–20)

Type > OpenType > Stylistic Sets toggles ss01–ss20 through new
type.openType.stylisticSets.setN commands on the usual formatting scope
(selected characters while editing, else the selected type layers).
The toggle direction and the menu checkmark follow the style at the
selection start. Updates TYPE-218-5 and G8.

Closes #10285

* Stylistic Sets: round-trip test through a full PSD; scorecard parity count

* Stylistic Sets: test PSD round trip on an opened file; record the new-document PSD gap

Documents made in PhotoCraft get no Txt2 block on PSD save, and the set
mask lives only there, so their sets are not saved to PSD yet. The engine
test keeps the .pcraft round trip, an io test covers the PSD round trip
of a file with type objects, and TYPE-218-5 and G8 record the gap.

* Stylistic Sets: share one tag table between the engine and the menu

The engine exports STYLISTIC_SET_TAGS; the Set 1–20 commands index it and
the menu checkmarks read it, so the 20 tags are listed once.

* Stylistic Sets: check malformed menu ids through the resolver, not the menu list

* Scorecard: TYPE-218-5 notes PSD save of stylistic sets in documents made here (#10308)

---------

Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-05 06:16:54 +01:00
Saloouu c426d4fbe5 Toolbar slots and tool keys keep their last tool across launches (#3569) 2026-11-04 19:58:46 +01:00
Michael Higgins 2b99fa9a5b Merge branch 'storytold:main' into fix/8806-rasterize-click-replay 2026-11-03 16:15:52 -05:00
David Mann 4bbe9c78de Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	docs/scorecard.md
2026-11-03 20:32:22 +01:00
David Mann 93384bf46e Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/ui-egui/src/canvas/wheel_nav.rs
#	docs/scorecard.md
2026-11-03 20:23:24 +01:00
David Mann 3d36330d94 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	docs/scorecard.md
2026-11-03 18:08:29 +01:00
d21c403e5f Type: add OpenType Numerals submenu (figure styles) (#11051)
* Type: add OpenType Numerals submenu (figure styles)

Type › OpenType › Numerals sets lnum/onum/pnum/tnum as a radio style
(Default through Tabular Oldstyle). Checkmarks follow the selection
start; TYPE-218-5 scorecard/gaps updated; parity floor 640.

* refactor(engine): one style-at-character lookup for the OpenType menus

feature_on_at and numerals_style_at each walked the runs the same way;
they now share style_at. NumeralsStyle::from_id and numerals_style_of
read the existing tables instead of repeating them.

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

* fix(text): persist OpenType numeral tags through PSD EngineData

Map lnum/pnum/tnum as EngineData bools and the width×height combos as
FigureStyle (Krita/Illustrator), so Numerals choices survive PSD round-trip.

* docs(gaps): note Numerals PSD figure-tag round-trip

* revert(text): keep PSD EngineData to the keys Photoshop writes

Backs out the PSD half of 18610324 and its gaps note (58813de3); the
engine reformat in that commit stays.

- `LiningFigures`, `ProportionalFigures` and `TabularFigures` are not
  Photoshop EngineData keys (the commit says Photoshop only has
  `OldStyle`), so writing them puts keys of our own into users' PSDs.
- The `/FigureStyle` code table (1-4) has no oracle: no Photoshop-authored
  file in photocraft-corpus, and neither ag-psd nor psd-tools reads it.

AGENTS.md rule 3 asks for public specs or observation. PSD persistence
of the numeral styles can come back with a Photoshop-authored oracle.
The Numerals menu still round-trips through .pcraft.

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

* test(text): lock PSD EngineData to Photoshop OldStyle for numerals

Document AGENTS.md clean-room: only onum survives TySh round-trip; lnum/pnum/tnum stay .pcraft-only until a Photoshop-authored corpus oracle.

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:55:35 +01:00
David Mann 559d3fe0f4 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/engine/src/cmd/file_cmds.rs
#	crates/ui-egui/src/app/files.rs
#	crates/ui-egui/src/dialogs/tiff_options_ui.rs
#	docs/file-format-parity.md
#	docs/gaps.md
#	docs/ui-parity.md
2026-11-03 17:11:53 +01:00
Yuki-init e3a84b628d TIFF Options: compression, image pyramid and Save Transparency (#8827) (#10932)
Offer TIFF compression, image pyramid and transparency options on Save As and Save a Copy, with matching CLI and automation parameters.

Follow-up: preserve the unsaved state when a copy discards layers over the document's own file, and check the other export formats for the same issue.

Closes #8827.
2026-11-03 15:39:15 +01:00
David Mann 7329c700bb Merge remote-tracking branch 'origin/main' into integration-batch-13
# Conflicts:
#	apps/photocraft-cli/src/args.rs
#	crates/engine/src/jobs.rs
#	crates/engine/src/jobs/tests.rs
2026-11-03 13:52:30 +01:00
FredApps 7e29a9999c Wire EXR band streaming into main's path open
- import_file_for_open_with decodes single-part flat scanline EXR block by block into
  tiles; headers the band decoder refuses fall back to the whole-file decoder, so files
  main opened still open. Band-time failures and cancellation publish no document.
- The RAM tile budget and scratch-disk checks live in exr_native (the PSD stream module
  they came from is dropped); over-budget opens fail with IoError::OutOfMemory.
- The band decoder picks colour channels with exr_color_channels, like the byte decoder.
- Tests move into the per-crate it binaries and use import_file; an engine open-job test
  covers the OpenSource::Path route. The ui-egui sync open test is dropped: main's
  synchronous open reads bytes, and the io test covers the oversized header.
- docs/streaming-io.md, roadmap, scratch-disks and REL-212-1 describe EXR only.
2026-11-03 09:23:15 +01:00
FredApps fdab6c0a33 Merge remote-tracking branch 'upstream/main' into pr-5331 2026-11-03 09:06:31 +01:00
David Mann 4f6a2c50f0 Merge #4579: the author's latest commits
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
2026-11-03 01:05:27 +01:00
Fabio Lissi a2c4ac0b0c Match Batch Esc flow and show read-only input preview 2026-11-02 17:36:55 -06:00
David Mann 2915849b07 Merge #4514: Record actions in a document-independent form (#219) [depends on #4496]
# Conflicts:
#	crates/engine/src/cmd/type_spell_cmds.rs
#	crates/engine/src/jobs.rs
#	docs/gaps.md
#	docs/target-app-parity.md
2026-11-03 00:36:40 +01:00
FredApps b0f3c7516b Merge current main into codex/scratch-storage
Resolve conflicts with main's prefs UI split, session/execute.rs move, GPU memory
budget (gpuMemoryMb, 0 = auto, kept from main) and effective_memory_usage_mb history
budget. Port the Memory Usage % and Scratch Disks preferences into prefs_ui, the edit
integrity guard into session/execute.rs, and adapt main's new pixel readers to the
guarded TileBytes API. Cargo.lock regenerated; scorecard regenerated.
2026-11-02 22:16:22 +01:00
Fabio Lissi 00f75988b9 Match measured Photoshop Batch naming and error logs 2026-11-02 11:30:58 -06:00
Fabio Lissi 50360ac4ef Record portable nudges, document switches, and type positions 2026-11-02 11:30:37 -06:00
David MannandClaude Opus 5.5 89b4ca021b Merge main into fix/remove-enable-animations
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 16:42:54 +01:00
Fabio Lissi 03799b62bc Keep recorded layer targets portable across documents 2026-11-01 23:54:42 -06:00
Fabio Lissi 4eba6bd2e9 Merge current main and complete Batch automation options 2026-11-01 23:04:19 -06:00
Fabio Lissi 21c0444559 Merge current main and preserve portable action recording 2026-11-01 23:01:23 -06:00
Khawar Zamman Wani a24e155a6f Merge upstream main into large TIFF fix 2026-10-29 22:39:27 +05:30
David Mann b60b6471d4 Merge remote-tracking branch 'origin/main' into HEAD 2026-10-29 18:08:49 +01:00
aiongg c645d5fcc9 Merge pull request #8896 from wanikhawar/select-mask-workspace
Select and Mask: Photoshop's full-window workspace (#7069, #8148)
2026-10-29 12:15:14 -04:00
David Mann d1af5a2867 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/ui-egui/src/canvas.rs
2026-10-29 16:50:35 +01:00
David MannandClaude Opus 5.5 77339962cc xtask: panel-commands allowlist follows main's panels/ split; lexer helpers keep clippy's complexity limit
Main moved crates/ui-egui/src/panels.rs into panels/*.rs, so the color_field entry now names
panels/color.rs (scorecard note too), and main's cognitive_complexity deny split lex()'s block
comment and string skipping into helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 16:49:12 +01:00
David Mann 5dd023f949 Merge remote-tracking branch 'origin/main' into HEAD 2026-10-29 16:45:03 +01:00
bd9590d060 Arabic interface language, combined from the community catalogs
Adds Arabic (ar, العربية) as an interface language. The catalog combines
the open Arabic catalogs of #2505, #4520, #4569, #5593, #5915, #6092 and
#6287: each row takes the best of their translations, with one Arabic
term per concept across the UI, and the strings added since are filled
in. Modern Standard Arabic, Western digits, the six CLDR plural forms
(zero|one|two|few|many|other).

The two tests that used ar-SA as an unsupported locale now use sw-KE, and
the direction test expects Arabic to be the one right-to-left catalog.

Co-authored-by: azizr12 <163084230+azizr12@users.noreply.github.com>
Co-authored-by: hicbest <213873494+hicbest@users.noreply.github.com>
Co-authored-by: hasan-sdaif <306196098+hasan-sdaif@users.noreply.github.com>
Co-authored-by: NibrasAz7 <34162952+NibrasAz7@users.noreply.github.com>
Co-authored-by: vfggf95565 <74471233+vfggf95565@users.noreply.github.com>
Co-authored-by: syrrevshin4202-prog <243624842+syrrevshin4202-prog@users.noreply.github.com>
Co-authored-by: test-bit-sys <336050374+test-bit-sys@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:22:26 +01:00
Higgs32584andClaude Opus 5.5 54515f94b3 fix(ui-egui): the rasterize prompt no longer replays the click that opened it (#8806)
Pressing a pixel tool on a type, shape, Smart Object or fill layer opens the
"Rasterize?" prompt. On OK, confirm() ran layer.rasterize.* and then replayed
the stored press as ToolEvent::Down/Up, so the brush, eraser or bucket acted
on a click the user had made only to get past the dialog. Photoshop 2026
converts the layer and does nothing else; the next click paints.

confirm() now only rasterizes and returns {"rasterized"}. The prompt still
records the tool and point in its fields. The control-protocol doc and the
TOOL-213-5 scorecard row describe the new behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 11:50:31 -04:00
David MannandClaude Opus 5.5 523c2cc8d3 Merge main into feat/auto-219-8-panel-command-check
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 03:08:53 +01:00
David Mann 7451739eef Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/wheel_nav.rs
#	docs/scorecard.md
2026-10-26 14:10:11 +01:00
Khawar Zamman Wani 56008a682d Merge origin/main into select-mask-workspace 2026-10-26 10:20:37 +05:30
Khawar Zamman Wani cdc3bdbd2f Merge origin/main into fix/8169-huge-tiff-open 2026-10-26 10:20:12 +05:30
David MannandClaude Opus 5.5 9142a1036c Interface: remove the Enable animations preference (#9479)
Photoshop has no general animation setting (its only motion settings are
Animated Zoom, Flick Panning and Overscroll in Preferences > Tools), so
Preferences > Interface > Enable animations goes:

- interface.enableAnimations leaves the prefs model. Saved files that
  still have it load whole (unknown keys are ignored, nothing is reported
  as invalid); prefs.set/prefs.get on it are "unknown preference" errors.
- sync_animations is gone: egui's fades and scroll-area glides keep
  egui's defaults everywhere.
- The canvas wheel pans without egui's glide, as Photoshop does
  (measured: one notch moves the view in a single frame, nothing after).
  The unsmoothed pan now folds Shift and Cmd/Ctrl sideways the way egui
  does, so Ctrl+wheel still scrolls sideways (the old Enable animations
  off path dropped it). Liquify and Camera Raw previews keep read()'s
  smoothed pan, so read_with keeps its smooth parameter.
- The label leaves the 20 i18n catalogs; scorecard UI-217-10 no longer
  lists an animation toggle; docs/scorecard.md regenerated.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 17:34:31 +01:00
David Mann c01dc04b5f Revert "Merge PR #4573: Interface: Animation Effects follows the system setting, or is on or off"
This reverts commit acd7e07252, reversing
changes made to bc0354db5d.
2026-10-25 16:36:09 +01:00
David MannandClaude Opus 5.5 38609e5615 Merge PR #8885: PSD: spot channels in Photoshop's polarity; PSDs from earlier PhotoCraft versions keep their ink
Merged with our fix-up branch pr-8885-fixup (8f6863f53) on the author's head 996b55eb4.

Conflicts resolved:
- crates/io/src/tiff_layers.rs: #9148's tiff_source (an empty LMsk gets Photoshop's 14 bytes)
  gives way to #8885's tiff_image_source, which writes the same bytes for an empty or short
  LMsk; #9148's test stays.
- crates/io/src/flat.rs: #8776's DDS alpha step and #8885's TIFF channel stamp both run.
- crates/io/Cargo.toml, Cargo.lock: #8402's zune dev-deps and #8885's tiff dev-dep.
- crates/io/tests/it/tiff_layers.rs, docs: unions; docs/scorecard.md kept as is, regenerated at
  the batch gate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:28:00 +01:00
8f6863f536 Integration: a kept 1053 doesn't hide an earlier PhotoCraft's spot ink (#8885)
Earlier PhotoCraft versions kept the 1053 of a Photoshop file they opened
and wrote it back unchanged, while storing spot channels added there
straight. A transparent Photoshop document carries 1053 = [0], so a white
plate added to it in 0.16.0 or earlier sat behind a 1053, and the rule
read that file in Photoshop's polarity: the added spot opened inverted.

A 1053 that lists fewer channels (non-zero ids; 0 is the transparency's)
than the file has after its transparency now counts as kept, with the
PhotoCraft 1057 and DisplayInfo spot conditions unchanged. Planes the
kept 1053 lists stay in Photoshop's polarity (they are the Photoshop
file's own); the ones after them are read straight. Photoshop and this
version write one id per extra channel, so their files are unaffected.
Known limit, as before: channels reordered there, or as many deleted as
added, can't be told apart from the Photoshop file's own.

The earlier versions are 0.1.0 to 0.16.0, not 0.11.1: every release
since writes the same 1057 and straight spot planes without a 1053.

Co-authored-by: jasallen <615848+jasallen@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:22:13 +01:00
David MannandClaude Opus 5.5 4365c0537d Integration: merge main, resolve conflicts (#8885)
psd_import.rs keeps main's warning for an incomplete merged extra channel
next to the PR's Photoshop spot polarity. people.toml takes main's entries
plus jasallen's own. Docs take both sides' status lines and revision rows;
docs/scorecard.md is regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:07:44 +01:00
David Mann ef98aa507a Merge PR #3281: Vanishing Point: tear off planes and clone in perspective (#3280) 2026-10-25 15:57:43 +01:00