Commit Graph
323 Commits
Author SHA1 Message Date
Khawar Zamman Wani 259b5590ae Merge origin/main (655295b2a2) into PR #10897 branch
Keep the PSD memory admission work and upstream's scratch storage
together. Conflicts resolved:
- Cargo.lock: both sysinfo versions are required. 0.40.1 serves
  photocraft-io's adaptive import budget; 0.37.2 serves
  photocraft-raster's scratch volume and memory supervision. Cargo
  metadata resolved the lock with no other changes.
- crates/engine/src/lib.rs: Session keeps pending_preflights and
  next_pending_preflight beside scratch_runtime and scratch_epoch.
  Session derives Default, so neither set needs a manual initializer.

Upstream: 655295b2a2
2026-11-03 12:54:59 +05:30
Khawar Zamman Wani 5992650b36 fix: address PSD admission review and enable platform memory consent 2026-11-03 01:26:13 +05:30
dotCooCoo e7829eb449 Merge main into feat/pcraft-full-composite 2026-11-01 15:30:48 -08:00
RickiNanoandClaude Opus 5.5 122e55a4a0 Ask before re-importing a brush or gradient file over its group (#10640)
Importing an .abr or .grd whose name matched an existing group silently
deleted that group's user presets (edited or moved-in ones included); the
preset libraries are outside document history, so it could not be undone.

- brush.presets.importAbr / gradient.presets.importGrd: `replace` now
  defaults to false; a taken group name imports beside it as "Kit (2)",
  "Kit (3)"…, and the result's `group` names the one it landed in.
- UI: when the group already holds the user's presets, a prompt asks
  Import as New Group (default) / Replace (can't be undone) / Cancel.
  Agents drive it with ui.dialog.set {"choice":"replace"} / confirm / cancel.
- The status bar names the group the file landed in.

Fixes #10640

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:49:33 +01:00
David Mann e5b4ea6781 Merge main at e7b7cf11e into integration batch 10
i18n catalogs: main's new rows (#10328) appended after the batch's, as a union.
2026-10-31 02:05:31 +01:00
David MannandClaude Opus 5.5 28185d6dc3 Shift+right-click menu: Edit Brush… and every painting tool's own Mode list
#4985 added a canvas Shift+right-click popup that worked only for the
Brush and listed only its painting modes. In the reference application
Shift+right-click opens a menu for every painting tool: Edit Brush…
(the Brush Preset picker a plain right-click opens), a separator, then
the tool's own Mode list from its options bar:

- Brush, Pencil: the painting modes with Behind and Clear
- Clone Stamp, Pattern Stamp, History Brush: the blend modes
- Mixer Brush, Color Replacement, Background Eraser: Edit Brush… only
- Eraser: Brush / Pencil / Block (no Edit Brush…)
- Blur, Sharpen, Smudge: Edit Brush… (the reference lists modes too)
- Dodge, Burn: Shadows / Midtones / Highlights; Sponge: Desaturate /
  Saturate
- Healing Brush: its blend modes; Gradient: the blend modes; Paint
  Bucket: the blend modes with Clear (no Edit Brush…)
- Spot Healing, Magic Eraser and non-painting tools: no menu, the
  gesture keeps its old route

brush_mode_menu.rs is now a per-tool item list (Item enum + items(tool))
instead of a Brush-only list. Each row sets exactly what the tool's
options-bar control sets: a brush-based tool's mode through
tools.setBrush (Brush/Pencil also Behind and their own Clear flag), the
Eraser mode, tone range, sponge mode, gradient and bucket modes as tool
options. Blend modes are grouped with separators; the current choice is
checked; Behind and Clear are greyed on the Background layer. The menu
remembers the tool that opened it and closes on a tool change.

Only settings the options bar already has are offered. Not offered yet
(no setting here): Behind for the stamps, History Brush, Gradient and
Paint Bucket; the Blur/Sharpen/Smudge modes; the Spot Healing modes;
the Healing Brush's Sampled/Pattern source and Replace; the History
Brush source.

Control: ui.inspect's brushModeMenu reports tool, mode, choices (the
active tool's labels) and items (label/enabled/checked, separators);
ui.context.choose {id: <label>} picks a row, an unknown or greyed row
is an error that changes nothing.

Tests (kittest): each representative tool's rows in order, choosing a
row sets the options-bar state and journal, Edit Brush… opens the
picker at the click, Behind/Clear greyed on the Background, Magic
Eraser and Spot Healing open nothing; control graceful failure for bad
choices. "Edit Brush…" added to every catalog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 16:34:03 +01:00
dotCooCoo f121865ffa Docs: a .pcraft save can leave the full-size composite out
The doc.save row, docs/development.md, the MCP doc_save description, the
file.saveACopy params text, the --pcraft-full-composite help and the
option's doc comments said the option writes composite/full.png. A save
leaves it out when the canvas is past 2^26 pixels, when its pixels cannot
be allocated or encoded, or when a ZIP bundle would pass its limits. They
now say so and point to the manifest's full_composite member, which names
the entry when it was written.
2026-10-30 08:20:23 -07:00
dotCooCoo 49d12c57bf Merge main into feat/pcraft-full-composite
# Conflicts:
#	crates/ui-egui/src/i18n/cs.tsv
#	crates/ui-egui/src/i18n/de.tsv
#	crates/ui-egui/src/i18n/el.tsv
#	crates/ui-egui/src/i18n/es.tsv
#	crates/ui-egui/src/i18n/fr.tsv
#	crates/ui-egui/src/i18n/hu.tsv
#	crates/ui-egui/src/i18n/id.tsv
#	crates/ui-egui/src/i18n/it.tsv
#	crates/ui-egui/src/i18n/ja.tsv
#	crates/ui-egui/src/i18n/ko.tsv
#	crates/ui-egui/src/i18n/nl.tsv
#	crates/ui-egui/src/i18n/pl.tsv
#	crates/ui-egui/src/i18n/pt-br.tsv
#	crates/ui-egui/src/i18n/ru.tsv
#	crates/ui-egui/src/i18n/tr.tsv
#	crates/ui-egui/src/i18n/uk.tsv
#	crates/ui-egui/src/i18n/vi.tsv
#	crates/ui-egui/src/i18n/zh-hans.tsv
#	crates/ui-egui/src/i18n/zh-hant.tsv
2026-10-30 06:26:41 -07:00
David Mann f5ae6d5276 Merge main into pr-9274-fixup
# Conflicts:
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/dialogs/adjust_editors/curves.rs
#	docs/gaps.md
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-30 13:16:39 +01:00
FredApps 255ecc81d0 Remove 21 requested PR contributions from the 108-PR integration
Retain 87 PRs. Reconcile overlapping integration fixes and update testing scope.
Removed: #7153 #7742 #5493 #9282 #3455 #9172 #3139 #3967 #4783 #5453 #8347 #1991 #3345 #4042 #4305 #4883 #4890 #5090 #6621 #5870 #5939.

Combined CI pending for this source; historical portable artifact is not applicable.
2026-10-29 18:49:17 +01:00
FredApps c9430c92e3 Merge approved PhotoCraft PR #3748: control: suggest near matches for unknown command ids and methods (#3674)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Add bounded deterministic suggestions via current error/session/control modules while preserving authorization/modal checks. Register hints and all original tests; fix scrollbar choice import and updated PSD image fixture field found by 100-head check.
2026-10-29 06:14:31 +01:00
FredApps 97dfeda00c Merge approved PhotoCraft PR #3967: Add move and delete actions to Smart Filter rows
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Port guarded filter context actions and selection updates into current Layers/Smart UI modules. Register all new modules and regressions; preserve current filter blend button and drag-to-reorder routing, document/modal/job ownership.
2026-10-29 06:13:32 +01:00
FredApps 1953077164 Merge approved PhotoCraft PR #5270: Layer Style: Gradient Overlay takes any number of colour stops (#5177)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Port arbitrary-stop editor into current responsive dialog. Preserve source interpolation and exact model colors; unchanged dense imported snapshot lists roundtrip while edited lists retain 256-stop cap. Retain both validation guards and all original regression tests. Correct saved-path callers, floating-window and crop fixtures found by frozen 88-head all-target check.
2026-10-29 06:02:29 +01:00
FredApps 8323688e1f Merge approved PhotoCraft PR #5453: Shapes: independent fill and stroke paints (solid, gradient, pattern), part 1
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Integrated independent exact shape paints and atomic pattern clipboard snapshots into current modules, preserving current soft-mask coverage, shape cache keys and gradient stop caps. Shared bounded COW pattern sampling now retains minification filtering; shapes/clipboards resolve lazy catalog entries to full pixels. Preserved CPU/GPU/depth/model regression matrices; also corrected missing glow-test enum imports found by the 80-head check.
2026-10-29 05:53:29 +01:00
FredApps a72296ee57 Merge approved PhotoCraft PR #6139: Fix painting workflows, File Info and layer selection
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Ported Behind paint across engine/render and shared options-bar/canvas mode menus, preserving Clear and current popup ownership. Added localized responsive picker title/width and File Info multiline fields without dropping ordered fields, Browse or camera metadata; ported Pen anchor repositioning, copy cursor, grayscale-target sampling and authorized select-under-cursor dispatch into current modules with original regressions.
2026-10-29 05:39:00 +01:00
FredApps 2f6156bebe Merge approved PhotoCraft PR #5090: Actions: add editable PhotoCraft Essentials starter presets
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Register starter actions and bounded background-blur command in current modules; preserve persistent migration marker and portable JSON defaults compatibility.
2026-10-29 04:18:29 +01:00
FredApps ab9c044fba Merge approved PhotoCraft PR #3461: Replay recorded layer visibility on the intended named layer
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Resolve recorded visibility targets before both engine and shell authorization, preserving bounded playback, paused dialogs and existing journal coalescing; retain ActionState take generation.
2026-10-29 04:16:32 +01:00
FredApps 6e13443ca6 Merge approved PhotoCraft PR #3455: Undo and redo action definition edits from the Actions panel
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Keep action-definition undo separate from document history and preserve upstream panel routing and layout.
2026-10-29 04:12:47 +01:00
FredApps 663c0204dd Merge approved PhotoCraft PR #8896: Select and Mask: Photoshop's full-window workspace (#7069, #8148)
Resolve moved test modules and independent catalog/workflow additions without changing behavior.
2026-10-29 03:32:04 +01:00
FredApps 86fcbf26ee Merge approved PhotoCraft PR #7648: Pen: Path Operations menu, as in Photoshop (#1397) 2026-10-29 03:29:31 +01:00
FredApps c50539ea84 Merge approved PhotoCraft PR #6510: Automation: resolve configured root aliases for absolute paths (#6426) 2026-10-29 03:29:25 +01:00
FredApps 08e35bedc1 Merge approved PhotoCraft PR #4985: feat(ui): add Shift+right-click brush mode picker 2026-10-29 03:28:59 +01:00
Vlad Grankovsky 94c1ddcb2f Merge origin/main into codex/multi-channel-editing
Integrate main 69b8fd9c1, retaining multi-channel selection and editing through extracted channel-panel, Move-pointer and tone-editor helpers. Adapt explicit imports and preserve progress-document histories.
2026-10-29 00:37:26 +01:00
Ikki Nishihara 1dc98f80f6 docs(control): associate brush mode gesture with ui.pointer
Signed-off-by: Ikki Nishihara <223786623+haranishi@users.noreply.github.com>
2026-10-28 16:24:15 +09:00
Ikki Nishihara ca17e9b627 Merge current main and preserve brush mode picker behavior
Signed-off-by: Ikki Nishihara <223786623+haranishi@users.noreply.github.com>
2026-10-28 15:55:25 +09:00
Brennan StehlingandClaude Opus 5.5 ce8f3e719e Docs: perf.slowFrames, and the stroke trace reads the shared frame stages (#9328)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-27 23:08:06 -07:00
Khawar Zamman Wani 8b835a103c Merge origin/main into pen-path-operations 2026-10-28 09:22:55 +05:30
Khawar Zamman Wani 4e22d214dc Merge origin/main into select-mask-workspace 2026-10-28 09:22:54 +05:30
aiongg b4e69af424 Merge main into perf/9328-fallback-reason 2026-10-28 03:00:01 +00:00
dotCooCoo b527b5062a Save the flattened document at full size into .pcraft files as an option
A .pcraft bundle holds the flattened document only as thumb.png (at most
256 px) and composite/preview.png (at most 1024 px). A new option also
writes composite/full.png: the flattened document at its canvas size,
an 8-bit RGBA PNG made like the two previews, with the ICC profile of
its pixels embedded. The option is off by default, and a save without
it writes the same bytes as before.

- Preferences > File Handling > Save Full-Size Composite in .pcraft
  Files sets it for the app's Save, Save As and Save a Copy, in the
  desktop and web builds.
- The engine's file.saveACopy and its batch and export commands take
  "pcraftFullComposite" (unset, the preference), the automation
  doc.save and MCP doc_save take
  "pcraftFullComposite": true, and photocraft-cli convert, run and
  batch take --pcraft-full-composite.

The manifest names the image in a new optional member, full_composite;
the format version stays 1, and bundles without it open as before. A
canvas over 2^30 pixels, or one whose pixels cannot be allocated, is
saved without it, and so is a ZIP bundle that it would take past 4 GiB
or 65,535 entries.
2026-10-27 17:51:43 -07:00
David MannandClaude Opus 5.5 6fcbedd229 Merge origin/main into pr-4329-fixup
Main moved the engine commands into crates/engine/src/cmd/ and the
dialogs and panels into submodules. The PR's placement calls follow
them, and main's new insert sites (new_adjustment in adjust_params.rs,
Place in file_cmds/open.rs, shapes in vector_cmds/shape.rs) use
layer_place::insert_new like the PR's originals. The New Group dialog
moves to dialogs/new_group_ui.rs; the Layers panel flyout's New Group…
opens it.

Main's Session::precheck now also checks layer.new.group's and
layer.new.groupFromLayers' new params (name, color, mode, opacity,
position), so precheck_agrees_with_execute holds. Main had since added
"New Group…" to every catalog: the PR's duplicate rows are dropped.
Main's newer tests that made a layer with an open group active now
open the group last, as the PR did for the older ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 15:22:03 +01:00
Brennan StehlingandClaude Opus 5.5 b0688ee9a3 Render path: the status bar names a non-memory reason, and perf.gpuFallback follows the active document (#9328)
A reason other than the memory budget (a flipped view, Advanced Blending…)
now shows "CPU Rendering" even while the measured layer fit is over the
budget. perf.gpu_fallback is set in one place from the active document's
reason, also each frame after a switch of document, so a refresh of an
arranged cell or another window can't make it disagree with
perf.renderPath's current. The control protocol says a history entry's doc
is the changed document's id, or 0 for every document.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-27 02:07:25 -07:00
Brennan Stehling ae043f50a0 Render path: the adjustment preview's CPU-proxy reason has its own slot (#9328)
A clipped or Blend If adjustment preview runs on the CPU proxy. Its reason
lives in a slot of its own, separate from the canvas's per-document reasons
and the app-wide reason, so closing or retargeting the dialog ends only the
preview's entry and can never report the canvas back on the GPU.
2026-10-27 02:07:25 -07:00
Brennan StehlingandClaude Opus 5.5 63b718a0b3 Docs: perf.renderPath in the control protocol and the development guide (#9328)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-27 02:07:25 -07:00
PerchAnton 8bb0a5e674 Merge main and preserve automation root alias tests in extracted module 2026-10-27 10:27:26 +02:00
Vlad Grankovsky 7dfc1b8b75 Merge origin/main into codex/multi-channel-editing
Integrate main 59cb4c49b, including egui 0.37, the rebuilt Histogram
panel, live Mixer Brush and smart-filter mask painting. Preserve selected
native components and captured mask/dialog targets through the merge,
with preview, replay, undo and mode/depth regressions.
2026-10-26 18:15:19 +01:00
Khawar Zamman Wani 56008a682d Merge origin/main into select-mask-workspace 2026-10-26 10:20:37 +05:30
Khawar Zamman Wani 07549fd6a6 Merge origin/main into pen-path-operations 2026-10-26 10:20:27 +05:30
aiongg b078e0e8a6 Panels: review follow-ups to the shared docking and egui 0.37 merges (#9575) 2026-10-25 22:03:26 -04:00
aiongg da02d0ef2d Merge remote-tracking branch 'upstream/main' into docking-adopt
# Conflicts:
#	Cargo.toml
#	crates/ui-egui/Cargo.toml
2026-10-26 00:12:23 +00:00
David MannandClaude Opus 5.5 8812fe1e73 Merge main (egui 0.37, #9363)
Conflicts: the batch's wheel reads (#5547 Animated Zoom) keep their extra
argument with main's ids (`Id::unique`, `ui.scope_id()`); crop presets keep
#6620's `apply_choice` with main's accessible name; Bevel & Emboss keeps
#9370's per-mode id with main's name argument; the Stroke field keeps
#7203's gradients with main's name; tone.rs keeps #9139's move of the
Histogram panel to histogram_panel.rs (main only renamed ids there);
translation catalogs as unions.

Not flagged by git, the batch's new code follows egui 0.37 too: dropdowns
take an accessible name (Histogram Channel/Source #9139, tool Mode #5504,
Art History Style #1610, New Snapshot From #3567), MouseWheel events carry
`source`, `WidgetType` is `Role` (ColorButton is ColorWell, #7203),
`Id::new`/`Ui::id` are `Id::unique`/`Ui::scope_id`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 20:53:11 +01:00
5c9192bbe2 Migrate PhotoCraft to egui 0.37 (#9363)
* egui037: name each control for what it sets, and order the eager fonts for the UI

CodeRabbit review follow-ups on the migration: the Artboard X/Y fields, the CAF
dropdowns, the channel Solidity field, the GPU backend/adapter dropdowns, the
corner radius fields and the canvas extension colour all had an accessible name
that named another control (or was shared by four). The eager craft-fonts
registration now puts the UI Japanese face first, as the lazy loader does, so
Japanese UI is not drawn in the manifest's Mincho face and shared Han characters
do not take Japanese forms.

Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* egui037: rustfmt the eager craft-font order

---------

Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>
Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-25 15:04:35 -04:00
aiongg 292f869d8a Merge remote-tracking branch 'upstream/egui037' into docking-adopt
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	crates/ui-egui/src/gallery_ui.rs
#	crates/ui-egui/src/layer_props_ui.rs
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/panel_docking.rs
#	crates/ui-egui/src/panel_docking_tests.rs
#	crates/ui-egui/src/view_cmds.rs
#	crates/ui-egui/tests/it/batch_export_options.rs
2026-10-25 17:51:11 +00:00
Khawar Zamman Wani 18b32f1202 Merge origin/main into pen-path-operations 2026-10-25 21:25:26 +05:30
Vlad Grankovsky a37d21de7e Merge origin/main into codex/multi-channel-editing 2026-10-25 16:30:23 +01:00
David Mann ff479a2c01 Merge PR #9139: Rebuild the Histogram panel
# Conflicts:
#	crates/ui-egui/src/control.rs
#	docs/scorecard.md
#	docs/ui-parity.md
2026-10-25 16:11:31 +01:00
a87d9cb637 Integration: Histogram panel review fixes (#9139)
- Cache Levels 1 in Preferences turned off the 250 ms recount throttle,
  because "forced" was derived from max_level == 1: only an Uncached
  Refresh skips it now.
- The proxy factor became 2^(level-1) for every count, so the Levels,
  Curves and Threshold dialogs counted a 6000x3000 image on an 8x proxy
  instead of main's 7x (a 36 MP one 16x instead of 9x). Uncapped counts
  use main's factor again; only a Cache Levels cap halves by powers of two.
- The panel opens in Compact View, as in Photoshop, and Compact View
  counts the entire image whatever Source Expanded View was left at.
- The clipping corner marks are gone: Photoshop's Histogram panel has none.
- ui.inspect: "preview" counts only the active document's preview, and
  "current" compares the source and cache level too, not only the
  revision (a Source change left it true until the recount landed).
- ui-parity row lists two more differences (selection, Selected Layer
  with a dialog preview); cargo fmt.

Co-authored-by: mathildalabs <347373177+mathildalabs@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:08:36 +01:00
Khawar Zamman Wani e5d9727ba2 Merge main into select-mask-workspace 2026-10-25 20:37:21 +05:30
David Mann 7b79f70787 Merge PR #3297: Smart Filters: paint the filter mask directly, with undo (#3290)
Merged with our fix-up pr-3297-fixup (1de1e9eb58) on top of the author's head 053e1e0d03.
Conflicts resolved: channel_cmds.rs routed() keeps the PR's PAINT_IDS list plus the batch's
paint.artHistoryBrush; paint_cmds.rs Paint Bucket params keep the batch's "mode" and the PR's
"filterMask" target; docs/scorecard.md takes the batch's numbers with FILE-215-3 done.
2026-10-25 15:42:51 +01:00
1de1e9eb58 Integration: keep the filter mask target to commands that edit it (#3297)
Redone on the PR head 053e1e0d0 (the author's main merge); the earlier
fix-up f7af09d0f carried the first six points.

With a smart object's filter mask targeted, every routed command got
"target":"filterMask" and the filter-mask precondition instead of its own:

- Cmd+T and Edit > Transform > Flip/Rotate failed ("can't transform a
  filter mask on its own"); now the smart object transforms, as in
  Photoshop (lone_target -> Ok(None), and transforms get no target).
- Move (layer.translate) re-rendered the whole filter stack on every
  nudge, and failed for contents that can't render.
- Convert for Smart Filters became enabled and nested the smart object;
  Apply Image, Last Filter, Liquify, the lens filters, Vanishing Point,
  the render filters and Desaturate ignore the target.
  `follows_filter_mask` now leaves these out, in the shell, in
  inject_target, in the precondition and in the re-render hook; Paste
  keeps its own precondition.
- With the filter mask shown (Alt-click), clicking the layer, layer-mask
  or vector-mask thumbnail (or ui.set maskTarget/vectorMaskTarget/
  filterMaskTarget:false) left the view on (and ui.set maskTarget:false
  left the filter mask targeted), so strokes kept landing in
  the filter mask; those now end the view (CodeRabbit, panels.rs).
- ui.set filterMaskTarget:true on a layer without smart filters, or with
  a single channel targeted, cleared the mask target and answered ok; it
  is now refused before anything changes (CodeRabbit, control.rs).
- Curves on a targeted filter mask showed colour channels and the smart
  object's histogram; it is now a gray plane with the mask's histogram
  (GraySurface::FilterMask).

New on this head:

- Filters with a parameter schema (Gaussian Blur, High Pass, ...)
  refused "target":"filterMask" ("`target` must be pixels, mask,
  quickMask or {channel}"), so blurring the filter mask, the usual way to
  feather it, failed from the menu, the dialog and agents. The filter
  validation now accepts it (blurring_the_filter_mask_feathers_it).
- Delete with a selection and the filter mask targeted ran Edit > Clear
  on the smart object ("not a pixel layer"); it now fills the filter mask
  with the background colour there, as Photoshop does. With no selection
  Photoshop deletes the layer, which Delete already did
  (delete_with_the_filter_mask_targeted_edits_the_filter_mask).
- docs/control-protocol.md: the ui.set line lost its closing parenthesis
  in the main merge.

Co-authored-by: Valentin Klein <271991477+vangel76@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:21:05 +01:00