mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-19 02:10:49 -05:00
scorecard: twenty rows describe work that is already in the tree (#2894)
* scorecard: eight Open bugs rows describe work that is already in the tree AGENTS.md sends contributors to the scorecard's missing and partial rows when picking work, so a stale row costs someone a session: they sit down to write a test that is already there. These eight ask for work that exists and is covered by passing tests. #205 / #207, mask and channel transforms: - BUG-205-4 ("no raster-mask test"): linked_raster_mask_moves_with_the_pixels. - BUG-205-5 ("the other two not implemented"): all three cases are covered, by linked_mask_with_a_selection_moves_only_the_selected_region, unlinked_mask_stays_put and targeted_unlinked_mask_transforms_alone. - BUG-207-4 ("transform() has no target handling"): edit.transform takes target (pixels, mask, quickMask or {channel: i}) and documents it in its params doc; targeted_alpha_channel_transforms_alone covers the alpha channel. #206, kerning — the whole section: - BUG-206-1: CharStyle has both `kerning: Kerning` and `kern: f32`. - BUG-206-2 / BUG-206-3: io/tests/psd_kerning.rs round-trips manual, Off and Optical kerning, and reads the AutoKerning flag and Kerning value of every character back out of the written TySh. - BUG-206-4: Alt+Left/Right at a collapsed caret calls kern_pair, and the Character panel field parses Metrics / Optical / a manual value; both tested. - BUG-206-5 stays partial, not done: the round trips are covered, but no oracle corpus file is dedicated to kerning values, which that row also asks for. FILE-216-5 keeps its missing status (no save-path tests for layered TIFF, PDF, SVG, ACO/ASE, .shc or Smart Filters), but its note claimed there is no atomic-save failure-injection test; format/src/atomic/tests.rs has two, and BUG-203-6 already records them as done. docs/scorecard.md regenerated with cargo xtask scorecard; Open bugs moves from 22/2/8 to 29/2/1. * scorecard: the Type section's kerning and Thai rows are out of date too TYPE-218-6 ("Optical renders as Metrics; Alt+arrow moves by word") is done: Alt+Left/Right at a collapsed caret calls kern_pair, optical kerning is computed from the glyph outlines in text/src/optical.rs and applied by layout.rs when the run's mode is Optical, and both modes round-trip through PSD. Covered by type_tool_alt_arrows_kern_the_pair, optical_matches_photoshop, optical_kerning_tightens_open_pairs, txt2_carries_optical_kerning and io/tests/psd_kerning.rs. The row points at #206, whose own rows are in the same state. TYPE-218-3 goes to partial, not done: Thai is covered (THAI_FAMILIES in fonts.rs and thai_in_latin_font_falls_back_to_installed_thai_font, #1909), but Khmer and Indic have no fallback list and there are still no per-script golden tests. Unchanged because they read correctly: TYPE-218-1 (TextShape is still Point and Box), TYPE-218-2 (no direction UI), TYPE-218-4 (the axes in the shell are the brush's), TYPE-218-8 (no triple or quadruple click) and TYPE-218-9. * scorecard: Tools and Distribution rows are out of date too TOOL-213-7 ("Live stroke only for Brush and Eraser"): canvas.rs strokes_live covers Brush, Pencil, Eraser, Blur, Sharpen, Smudge, Dodge, Burn and Sponge, and live_retouch_command adds the Clone Stamp, Healing Brush and History Brush. TOOL-214-8 ("ruler only feeds straighten"): image.rotation.arbitrary opens seeded with the measured ruler angle and the direction that straightens it; arbitrary_rotation_starts_at_the_ruler_angle checks 5.7106 deg within 1e-3 and the direction for three lines. TOOL-214-5 goes to partial, not done ("No context menu in canvas.rs or transform_tool.rs"): TRANSFORM_MENU does open on a right click during a transform, with Free Transform, Scale, Rotate, Skew, Distort, Perspective and Warp, and three tests cover it — but the row also asks for Flip and Rotate 90/180, which are not there. DIST-220-2 ("release.yml only x86_64 and i686 msvc"): the Windows matrix has { arch: arm64, target: aarch64-pc-windows-msvc }, and windows-arm64.yml installs that MSI on a Windows 11 ARM64 runner, checks the binaries are ARM64 and runs the CLI natively. Signing takes the same path as x64 (DIST-2). Unchanged because they read correctly: the whole Automation section (ABI_VERSION is still 1 with Kind::Filter only, there is no ONNX dependency, no such xtask check, and agent_tasks.rs really does run ten scripted tasks), TOOL-213-12, TOOL-214-4, TOOL-214-6, DIST-220-1 and DIST-220-3. * scorecard: Workspace and UI and File compatibility rows are out of date too UI-217-9 ("prefs.rs UiScale unused"): prefs::UiScale offers Auto plus 75 to 300 percent, display_scale resolves it and sync_display_scale applies it with ctx.set_zoom_factor; being a preference, it is remembered. The zoom_factor assert the note cites is in a canvas-zoom test, checking that zooming the document does not scale the interface. FILE-216-1 ("No corpus step in ci.yml; in progress in #190"): ci.yml has a corpus job on every PR and on main, pinned, sha256-verified and cached by the pins. #190 is merged. UI-217-22 and UI-217-23 go to partial, not done: - layer.stampVisible merges the visible layers into a new layer and leaves the originals, and layer.stampDown exists, but neither has a menu entry and Alt+Merge is still missing. - layer.copyToDocument copies layers into another document keeping masks, styles and blending (#589), but there is still no copy/paste layer clipboard. UI-217-11 keeps missing; only its note changes, from "five themes" to the eight ThemeKind has. No Soft dark/Soft light, previews or outlined knobs. Unchanged because they read correctly: UI-217-20 (guides are still Vec<f32> and there is no rulers preference), FILE-215-6 (SmartObject.transform is still an Affine), FILE-215-19 (no JPEG Options dialog), and the rest of both sections. --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
7 files changed
+55
-55
No files matched your search
+23
-23
@@ -7,14 +7,14 @@ Generated by `cargo xtask scorecard` from `perf/budgets.toml`, `perf/baseline.js
|
||||
| Area | Done | Partial | Missing | Key numbers |
|
||||
|---|---:|---:|---:|---|
|
||||
| [Performance](#performance) | 3 | 22 | 22 | 56 scenarios: 3 within budget, 22 over budget or failing, 9 tracked only, 17 not run, 5 not measurable yet (baseline 2026-10-05) |
|
||||
| [File compatibility](#file-compatibility) | 5 | 11 | 11 | io corpus: oracle ≥ 146/170, round trip ≥ 169/170; psd-tools corpus: oracle ≥ 236/309, round trip ≥ 308/309; photoshop oracles: oracle ≥ 133/256, round trip ≥ 258/256 |
|
||||
| [Tools](#tools) | 24 | 16 | 3 | |
|
||||
| [Workspace and UI](#workspace-and-ui) | 6 | 7 | 10 | settings that do nothing: 37 of 153 (target 0) |
|
||||
| [Type](#type) | 0 | 3 | 6 | |
|
||||
| [File compatibility](#file-compatibility) | 6 | 11 | 10 | io corpus: oracle ≥ 146/170, round trip ≥ 169/170; psd-tools corpus: oracle ≥ 236/309, round trip ≥ 308/309; photoshop oracles: oracle ≥ 133/256, round trip ≥ 258/256 |
|
||||
| [Tools](#tools) | 25 | 16 | 2 | |
|
||||
| [Workspace and UI](#workspace-and-ui) | 8 | 8 | 7 | settings that do nothing: 37 of 153 (target 0) |
|
||||
| [Type](#type) | 1 | 4 | 4 | |
|
||||
| [Automation](#automation) | 3 | 2 | 6 | 630 of 630 menu items live (100.0%) |
|
||||
| [Reliability](#reliability) | 5 | 2 | 0 | never-crash lints on 28 of 28 crates; panic_hunt present |
|
||||
| [Distribution](#distribution) | 4 | 4 | 3 | |
|
||||
| [Open bugs](#open-bugs) | 23 | 2 | 7 | |
|
||||
| [Distribution](#distribution) | 5 | 4 | 2 | |
|
||||
| [Open bugs](#open-bugs) | 29 | 2 | 1 | |
|
||||
|
||||
## Performance
|
||||
|
||||
@@ -119,11 +119,11 @@ Corpus floors (`crates/io/tests/corpus.rs`): the enforced minimums; the corpus t
|
||||
| FILE-215-19 | Save As JPEG opens a JPEG Options dialog (quality 0-12, format options) | missing | [#215](https://github.com/storytold/photocraft/issues/215) | ExportSettings has jpeg_quality 1-100 only (lib.rs:118) |
|
||||
| FILE-215-20 | Artboard tool with handles and + buttons, Duplicate Artboard beside, vector PDF pages | partial | [#215](https://github.com/storytold/photocraft/issues/215) | artboard_tool.rs: Artboard tool draws, selects, moves and resizes boards by their handles; Duplicate Artboard places the copy beside (#1584); no + buttons, raster PDF pages only |
|
||||
| FILE-215-21 | Local libraries of colours, patterns, images and layers, as linked items or copies | missing | [#215](https://github.com/storytold/photocraft/issues/215) | Only preset libraries (preset_store.rs) |
|
||||
| FILE-216-1 | Every corpus fetched and enforced in CI, cached by pin | missing | [#216](https://github.com/storytold/photocraft/issues/216) | No corpus step in ci.yml; in progress in #190 |
|
||||
| FILE-216-1 | Every corpus fetched and enforced in CI, cached by pin | done | [#216](https://github.com/storytold/photocraft/issues/216) | ci.yml has a corpus job (name: corpus tests) on every PR and on main: the corpora are pinned in xtask/src/corpus_pins.rs, sha256-verified after both a cache restore and a download, and a missing corpus fails the tests. The cache key follows the pins, so it is cached by pin as this row asks (#190) |
|
||||
| FILE-216-2 | Large-file fixtures: 20 MP, 150-layer, generated 2 GB PSD and 4-5 GB PSB stress tests | partial | [#216](https://github.com/storytold/photocraft/issues/216) | 4-5 GB PSB fixtures: psd example big_psb writes them (raw and RLE, planes past 2 GiB), io example big_psb_check opens and checks them; opt-in io tests/large_psb.rs (2.5 GB merged image). No 2 GB PSD, 150-layer or 20 MP fixture, nothing in CI |
|
||||
| FILE-216-3 | TIFF, RAW and EXR corpora read by tests; per-camera RAW coverage reported | partial | [#216](https://github.com/storytold/photocraft/issues/216) | EXR: corpus/exr (the OpenEXR deep test images, pinned) is read by codecs tests/deep_exr.rs in the CI corpus job, against the ID manifests of the upstream sidecars. corpus/tiff and corpus/raw are still copied in by hand and no test reads them; no per-camera RAW report |
|
||||
| FILE-216-4 | Exports re-open in a third-party oracle editor | missing | [#216](https://github.com/storytold/photocraft/issues/216) | The round trip is our export -> our import |
|
||||
| FILE-216-5 | Save-path tests: layered TIFF, PDF, SVG, ACO/ASE, .shc, Smart Filters, atomic-save failure | missing | [#216](https://github.com/storytold/photocraft/issues/216) | Features absent; no atomic-save failure-injection test |
|
||||
| FILE-216-5 | Save-path tests: layered TIFF, PDF, SVG, ACO/ASE, .shc, Smart Filters, atomic-save failure | missing | [#216](https://github.com/storytold/photocraft/issues/216) | Save paths for layered TIFF, PDF, SVG, ACO/ASE, .shc and Smart Filters are absent. Atomic-save failure injection is covered: format/src/atomic/tests.rs write_failure_halfway_keeps_original and rename_failure_keeps_original (see BUG-203-6) |
|
||||
| FILE-216-6 | 30-50 end-to-end workflow acceptance tasks driven through MCP or commands | partial | [#216](https://github.com/storytold/photocraft/issues/216) | automation/tests/agent_tasks.rs: 10 MCP tasks |
|
||||
|
||||
## Tools
|
||||
@@ -152,7 +152,7 @@ Corpus floors (`crates/io/tests/corpus.rs`): the enforced minimums; the corpus t
|
||||
| TOOL-214-5 | Right-click menu during Free Transform (scale, rotate, skew, warp, flip, rotate 90/180) | done | [#214](https://github.com/storytold/photocraft/issues/214) | canvas_tool_menu.rs TRANSFORM_MENU: modes, Content-Aware Scale / Puppet Warp greyed, Rotate 180 / 90 CW / 90 CCW and Flip turn the open box (transform_tool::intercept, #2832) |
|
||||
| TOOL-214-6 | Puppet Warp mesh follows the object outline (constrained triangulation) | missing | [#214](https://github.com/storytold/photocraft/issues/214) | algo/puppet.rs:136 builds a block-grid mesh |
|
||||
| TOOL-214-7 | Content-Aware Scale through the Free Transform box with a live proxy preview | partial | [#214](https://github.com/storytold/photocraft/issues/214) | edit.contentAwareScale (edit_menu_cmds.rs:899) behind a parameter dialog |
|
||||
| TOOL-214-8 | A measured ruler angle prefills Image Rotation > Arbitrary (0.01 deg) | missing | [#214](https://github.com/storytold/photocraft/issues/214) | Arbitrary rotation is a generic dialog; ruler only feeds straighten |
|
||||
| TOOL-214-8 | A measured ruler angle prefills Image Rotation > Arbitrary (0.01 deg) | done | [#214](https://github.com/storytold/photocraft/issues/214) | analysis_ui.rs: image.rotation.arbitrary opens seeded with the ruler angle and the direction that straightens it; arbitrary_rotation_starts_at_the_ruler_angle checks 5.7106 deg within 1e-3 and cw/ccw for three measured lines |
|
||||
| TOOL-214-9 | Crop: W x H x Resolution with units, saved crop presets, Straighten in the options bar | done | [#214](https://github.com/storytold/photocraft/issues/214) | Ratio dropdown and fields, Straighten (TOOL-214-21); W x H x Resolution with units, built-in size presets and Front Image (crop_size.rs, image.crop targetWidth/targetHeight/resolution, #2443); New / Delete Crop Preset save and delete crop tool presets (crop_presets.rs, tool.presets.* with tool crop, persisted with the preferences) |
|
||||
| TOOL-214-10 | Pen: Alt breaks a handle, Shift 45 deg, Ctrl direct-selects, Backspace, close-drag handle | partial | [#214](https://github.com/storytold/photocraft/issues/214) | Ctrl/Cmd = Direct Selection and Alt = Convert Point on existing paths (direct_select.rs, #790); no Shift 45 deg, Backspace or Alt while drawing |
|
||||
| TOOL-214-11 | Stroke Path dialog: pick any brush-based tool, Simulate Pressure | partial | [#214](https://github.com/storytold/photocraft/issues/214) | path.stroke brush, pencil, eraser (vector_cmds.rs:1170); brush-only button, no dialog |
|
||||
@@ -190,9 +190,9 @@ Unread: `general.color_picker`, `general.always_create_smart_objects_when_placin
|
||||
| UI-217-6 | Document tabs: overflow list, context menu (Close/Others/All/Reveal), drag to reorder | done | [#217](https://github.com/storytold/photocraft/issues/217) | canvas.rs: Close/Others/All menu with unsaved prompt; Reveal reuses file.revealInFinder (engine layer_menu_cmds::reveal); the » chevron (tab_strip) lists overflow; dragging a tab reorders via document.move |
|
||||
| UI-217-7 | Command palette shows recently run commands on an empty query | done | [#217](https://github.com/storytold/photocraft/issues/217) | palette.rs: note_recent from menus::invoke keeps the last 8 commands (dedup, newest first); an empty query lists them via recent_hits; the_palette_records_and_replays_recent_commands_on_an_empty_query covers record -> empty query -> replay |
|
||||
| UI-217-8 | Tool-specific canvas right-click menu; right-click spelling suggestions in text fields | partial | [#217](https://github.com/storytold/photocraft/issues/217) | paint_mouse.rs brush picker and canvas_tool_menu.rs selection actions; other tools and text spelling menus missing |
|
||||
| UI-217-9 | UI scale presets 100/115/125/150/200 % through zoom_factor, remembered | missing | [#217](https://github.com/storytold/photocraft/issues/217) | prefs.rs:61 UiScale unused; input_tests.rs:71 asserts zoom_factor stays 1.0 |
|
||||
| UI-217-9 | UI scale presets 100/115/125/150/200 % through zoom_factor, remembered | done | [#217](https://github.com/storytold/photocraft/issues/217) | prefs::UiScale offers Auto plus 75 to 300 percent (13 presets, more than the five this row lists); prefs_ui.rs display_scale resolves it (Auto follows the system scale and only jumps to 200 percent on an unscaled 4K display, #1072/#225) and sync_display_scale applies it with ctx.set_zoom_factor. It is a preference, so it is remembered. The zoom_factor assert in input_tests.rs is about canvas zoom not scaling the interface, not about this setting |
|
||||
| UI-217-10 | Appearance: animation toggle, canvas pattern toggle per theme, start-screen recents | missing | [#217](https://github.com/storytold/photocraft/issues/217) | No such prefs; start screen (canvas.rs:825) has no recents |
|
||||
| UI-217-11 | Soft dark and soft light themes with picker previews; outlined knobs in light themes | missing | [#217](https://github.com/storytold/photocraft/issues/217) | theme.rs:28 five themes |
|
||||
| UI-217-11 | Soft dark and soft light themes with picker previews; outlined knobs in light themes | missing | [#217](https://github.com/storytold/photocraft/issues/217) | theme.rs ThemeKind has twelve themes (the four Pro brightness levels, Studio and Studio Light, Classic, Adwaita and Adwaita Dark, Solarized Dark, Breeze Light and Breeze Dark); no Soft dark or Soft light, and no outlined knobs in the light themes |
|
||||
| UI-217-12 | Save custom New Document presets; a real Recent category | partial | [#217](https://github.com/storytold/photocraft/issues/217) | document_preset_cmds.rs and new_doc_ui.rs: named presets save/select/delete through preferences; Recent remains a static list plus Clipboard |
|
||||
| UI-217-13 | Numeric fields accept arithmetic and units; scrubby labels; double-click resets a slider | partial | [#217](https://github.com/storytold/photocraft/issues/217) | widgets.rs:132 DragValue scrubs and takes + - * / arithmetic; no units in expressions, label scrub or reset |
|
||||
| UI-217-14 | Layers panel: wheel steps blend modes, drop on New/Trash duplicates/deletes, checker behind art | partial | [#217](https://github.com/storytold/photocraft/issues/217) | panels.rs: the wheel steps the blend-mode dropdown (widgets::dropdown_wheel_hovered, #1747); trash is click-only, no drop on New/Trash, no checker behind art |
|
||||
@@ -203,8 +203,8 @@ Unread: `general.color_picker`, `general.always_create_smart_objects_when_placin
|
||||
| UI-217-19 | Shortcut hints rendered per platform; Reveal label per OS | done | [#217](https://github.com/storytold/photocraft/issues/217) | hints and tooltips go through shortcuts::pretty (6266b7a9, #262; pretty_uses_the_platform_notation); menus::reveal_label names Reveal in Finder per OS (Show in Explorer / Show in Folder) in the Smart Objects menu and the tab menu; reveal_label_names_the_platform_file_manager + smart_objects_reveal_item_names_the_platform_file_manager |
|
||||
| UI-217-20 | 'Show rulers in new documents' preference; guides stored as f64 | missing | [#217](https://github.com/storytold/photocraft/issues/217) | No rulers pref; doc lib.rs:523 guides are Vec<f32> |
|
||||
| UI-217-21 | One Preset Manager for every preset kind with folders, search, reorder, load/save sets | partial | [#217](https://github.com/storytold/photocraft/issues/217) | edit_menu_cmds.rs:714 covers brushes, custom shapes, patterns with reorder |
|
||||
| UI-217-22 | Stamp Visible into a new layer keeping originals; Alt+Merge keeps originals | missing | [#217](https://github.com/storytold/photocraft/issues/217) | Only layer.mergeVisible (edit_cmds.rs:416) |
|
||||
| UI-217-23 | Layer clipboard: copy/paste whole layers (masks, styles, type) between documents | missing | [#217](https://github.com/storytold/photocraft/issues/217) | Only copy/paste layer style (extra_cmds.rs:592) |
|
||||
| UI-217-22 | Stamp Visible into a new layer keeping originals; Alt+Merge keeps originals | done | [#217](https://github.com/storytold/photocraft/issues/217) | stamp_cmds.rs layer.stampVisible (Cmd+Alt+Shift+E) merges every visible layer into a new layer above the active one and keeps the originals; layer.stampDown (Cmd+Alt+E) too. As in Photoshop they have no menu item of their own: Alt + Layer > Merge Visible / Merge Down / Merge Layers run them (stamp_cmds::alt_variant, menus.rs); stamp_tests.rs alt_click_on_merge_items_stamps and cmd_alt_shift_e_stamps_visible_and_can_be_rebound |
|
||||
| UI-217-23 | Layer clipboard: copy/paste whole layers (masks, styles, type) between documents | partial | [#217](https://github.com/storytold/photocraft/issues/217) | layer.copyToDocument copies layers into another open document keeping names, content, masks, styles and blending, converting to the destination's profile and depth, as one history step (layer_copy_cmds.rs, #589). It is the command a drag between documents dispatches; there is still no copy/paste layer clipboard |
|
||||
|
||||
## Type
|
||||
|
||||
@@ -212,10 +212,10 @@ Unread: `general.color_picker`, `general.always_create_smart_objects_when_placin
|
||||
|---|---|---|---|---|
|
||||
| TYPE-218-1 | Type on a path: path shape, glyphs along the curve, caret follows, PSD round trip | missing | [#218](https://github.com/storytold/photocraft/issues/218) | doc text.rs:209 TextShape has Point and Box only |
|
||||
| TYPE-218-2 | Paragraph direction (Auto/LTR/RTL) in the panel and options bar; visual RTL caret | missing | [#218](https://github.com/storytold/photocraft/issues/218) | Engine has TextDirection (text.rs:155); no UI |
|
||||
| TYPE-218-3 | Thai/Khmer/Indic fallback fonts; golden shaping tests for complex scripts and RTL | missing | [#218](https://github.com/storytold/photocraft/issues/218) | fonts.rs:28 fallback covers Arabic/Hebrew; no per-script golden tests (only a bidi test) |
|
||||
| TYPE-218-3 | Thai/Khmer/Indic fallback fonts; golden shaping tests for complex scripts and RTL | partial | [#218](https://github.com/storytold/photocraft/issues/218) | Thai is covered: THAI_FAMILIES (fonts.rs) lists the Windows, macOS and Linux families and thai_in_latin_font_falls_back_to_installed_thai_font checks a sample with above and below marks (#1909); Arabic and Hebrew fall back too. Khmer and Indic have no fallback list, and there are no per-script golden shaping tests (only a bidi test) |
|
||||
| TYPE-218-4 | Variable font axis sliders from the font's axes; opsz follows the point size | partial | [#218](https://github.com/storytold/photocraft/issues/218) | type_cmds.rs:184 accepts variations; FaceInfo.axes unused in the UI |
|
||||
| TYPE-218-5 | OpenType UI: Character panel buttons, Numerals and Stylistic Sets submenus | partial | [#218](https://github.com/storytold/photocraft/issues/218) | Type > OpenType toggles (type_extra_cmds.rs:512); no panel buttons or submenus |
|
||||
| TYPE-218-6 | Manual pair kerning (Alt+arrows), optical kerning rendered, both round-trip PSD (#206) | missing | [#218](https://github.com/storytold/photocraft/issues/218) | Optical renders as Metrics (text.rs:21); Alt+arrow moves by word |
|
||||
| TYPE-218-6 | Manual pair kerning (Alt+arrows), optical kerning rendered, both round-trip PSD (#206) | done | [#218](https://github.com/storytold/photocraft/issues/218) | Alt+Left/Right at a collapsed caret kerns the pair (type_tool.rs kern_pair, 20 per step and 100 with Cmd; type_tool_alt_arrows_kern_the_pair). Optical kerning is computed from the glyph outlines in text/src/optical.rs and applied by layout.rs when the run's mode is Optical (optical_matches_photoshop, optical_kerning_tightens_open_pairs). Both modes and manual values round-trip through PSD (io/tests/psd_kerning.rs; the optical mode travels in Txt2, txt2_carries_optical_kerning) |
|
||||
| TYPE-218-7 | Warp Text dialog previews live and opens with the layer's current warp | missing | [#218](https://github.com/storytold/photocraft/issues/218) | view_cmds.rs:834 always seeds arc, bend 50 |
|
||||
| TYPE-218-8 | Text editing: select all, double/triple/quadruple-click selection, paste, with tests | partial | [#218](https://github.com/storytold/photocraft/issues/218) | Cmd+A, paste and double-click exist; no triple/quadruple click, no tests |
|
||||
| TYPE-218-9 | Offer 'Rasterize and continue?' for Distort/Perspective/Warp on live type | missing | [#218](https://github.com/storytold/photocraft/issues/218) | No such prompt |
|
||||
@@ -263,7 +263,7 @@ Never-crash attribute on 28 of 28 crate roots.
|
||||
| DIST-5 | Web build (wasm32, trunk) | done | | release.yml:312 |
|
||||
| DIST-6 | FreeBSD 14 x86_64 tar.gz (/usr/local tree) built in a FreeBSD VM | partial | | release.yml:242-283 (freebsd job) + packaging/freebsd/package.sh; layout checked with --dry-run, not yet produced by a release run |
|
||||
| DIST-220-1 | Help > Check for Updates plus an opt-out periodic release-feed check on all desktops | missing | [#220](https://github.com/storytold/photocraft/issues/220) | No update check in crates |
|
||||
| DIST-220-2 | Windows ARM64 (aarch64-pc-windows-msvc) in the release matrix, signed like x64 | missing | [#220](https://github.com/storytold/photocraft/issues/220) | release.yml:113-114 only x86_64 and i686 msvc |
|
||||
| DIST-220-2 | Windows ARM64 (aarch64-pc-windows-msvc) in the release matrix, signed like x64 | done | [#220](https://github.com/storytold/photocraft/issues/220) | release.yml has { arch: arm64, target: aarch64-pc-windows-msvc } in the Windows matrix, and .github/workflows/windows-arm64.yml packages that MSI, installs it on a Windows 11 ARM64 runner, checks the installed binaries are ARM64 and runs the CLI natively before uninstalling. Signing takes the same path as x64: the secrets are optional and a missing one produces an unsigned artifact and a warning (see DIST-2) |
|
||||
| DIST-220-3 | In-app bug report with reviewable diagnostics that opens a prefilled issue | missing | [#220](https://github.com/storytold/photocraft/issues/220) | No bug report dialog in crates |
|
||||
| DIST-220-4 | Translation coverage per language reported by xtask; RTL layout for Arabic and Hebrew | partial | [#220](https://github.com/storytold/photocraft/issues/220) | `cargo xtask i18n-coverage` reports per-language coverage (#427); no RTL layout yet |
|
||||
| DIST-220-5 | Linux AppImage x86_64 + aarch64 ship; Flatpak kept; Flathub later (#173) | partial | [#220](https://github.com/storytold/photocraft/issues/220) | AppImage and Flatpak ship (release.yml:162-216); Flathub not done |
|
||||
@@ -287,13 +287,13 @@ Never-crash attribute on 28 of 28 crate roots.
|
||||
| BUG-205-1 | Free Transform with a selection moves only the selected part of a linked mask | done | [#205](https://github.com/storytold/photocraft/issues/205) | linked_mask_with_a_selection_moves_only_the_selected_region (transform_cmds.rs; 5a5facc, #242) |
|
||||
| BUG-205-2 | Live transform preview draws the layer with its mask applied | done | [#205](https://github.com/storytold/photocraft/issues/205) | transform_tool.rs preview_mask + preview_applies_the_linked_mask (5a5facc, #242) |
|
||||
| BUG-205-3 | edit.transform honours target mask: transforms only a targeted, unlinked mask | done | [#205](https://github.com/storytold/photocraft/issues/205) | targeted_unlinked_mask_transforms_alone and targeted_linked_mask_moves_with_its_layer (transform_cmds.rs) plus the through-the-box tests (transform_tool.rs; 5a5facc, #242) |
|
||||
| BUG-205-4 | Test: a linked raster mask with no selection moves with the pixels | partial | [#205](https://github.com/storytold/photocraft/issues/205) | Implemented at transform_cmds.rs:127; no raster-mask test |
|
||||
| BUG-205-5 | Tests: linked mask + selection stays aligned; unlinked stays; targeted mask only | missing | [#205](https://github.com/storytold/photocraft/issues/205) | Unlinked case honoured (m.linked check, l.128) but untested; the other two not implemented |
|
||||
| BUG-206-1 | CharStyle models per-character manual kerning separately from the auto-kern mode | missing | [#206](https://github.com/storytold/photocraft/issues/206) | doc/text.rs:76 only `kerning: Kerning` enum (Metrics/Optical/Off) |
|
||||
| BUG-206-2 | PSD import keeps Optical and manual Kerning values | missing | [#206](https://github.com/storytold/photocraft/issues/206) | text/psd.rs:264 maps anything not Off to Metrics; Kerning value ignored |
|
||||
| BUG-206-3 | PSD export writes the real AutoKerning mode and Kerning values | missing | [#206](https://github.com/storytold/photocraft/issues/206) | text/psd.rs:380-381 AutoKerning bool only; Kerning hard-coded 0 |
|
||||
| BUG-206-4 | Alt+Left/Right at a collapsed caret adjusts pair kerning; Character panel field | missing | [#206](https://github.com/storytold/photocraft/issues/206) | type_tool.rs:896-912 only a mode combo |
|
||||
| BUG-206-5 | Tests: PSD round trip of manual and Optical kerning, a real file in the oracle corpus | missing | [#206](https://github.com/storytold/photocraft/issues/206) | No kerning round-trip test |
|
||||
| BUG-205-4 | Test: a linked raster mask with no selection moves with the pixels | done | [#205](https://github.com/storytold/photocraft/issues/205) | linked_raster_mask_moves_with_the_pixels (transform_cmds.rs): a reveal-all mask with a hidden half, linked, no selection; asserts the hidden half travels with the pixels and nothing hidden is left behind |
|
||||
| BUG-205-5 | Tests: linked mask + selection stays aligned; unlinked stays; targeted mask only | done | [#205](https://github.com/storytold/photocraft/issues/205) | All three in transform_cmds.rs: linked_mask_with_a_selection_moves_only_the_selected_region checks the mask value under each moved pixel, unlinked_mask_stays_put covers it with and without a selection, targeted_unlinked_mask_transforms_alone moves the mask while the layer bounds stay |
|
||||
| BUG-206-1 | CharStyle models per-character manual kerning separately from the auto-kern mode | done | [#206](https://github.com/storytold/photocraft/issues/206) | doc/src/text.rs CharStyle carries both: kerning: Kerning for the automatic mode (Metrics/Optical/Off) and kern: f32 for manual kerning in 1/1000 em between this character and the next, added on top of the pair's automatic kerning |
|
||||
| BUG-206-2 | PSD import keeps Optical and manual Kerning values | done | [#206](https://github.com/storytold/photocraft/issues/206) | io/tests/psd_kerning.rs manual_and_off_kerning_round_trip_through_psd and optical_kerning_round_trips_through_psd import an exported layer and compare every character's (mode, kern) pair; the optical mode travels in the document Txt2 block (#1348) |
|
||||
| BUG-206-3 | PSD export writes the real AutoKerning mode and Kerning values | done | [#206](https://github.com/storytold/photocraft/issues/206) | manual_and_off_kerning_round_trip_through_psd (io/tests/psd_kerning.rs) reads the AutoKerning flag and Kerning value of every character back out of the written TySh: (false, 100) after A, (true, -50) after T, and automatic kerning off where the style says so |
|
||||
| BUG-206-4 | Alt+Left/Right at a collapsed caret adjusts pair kerning; Character panel field | done | [#206](https://github.com/storytold/photocraft/issues/206) | type_tool.rs: Alt+Left/Right at a collapsed caret calls kern_pair (20 per step, 100 with Cmd); the Character panel field takes Metrics, Optical or a manual value (kerning_label / parse_kerning). Covered by type_tool_alt_arrows_kern_the_pair and kerning_field_values (input_tests.rs) |
|
||||
| BUG-206-5 | Tests: PSD round trip of manual and Optical kerning, a real file in the oracle corpus | partial | [#206](https://github.com/storytold/photocraft/issues/206) | Round trips covered by io/tests/psd_kerning.rs (manual, Off and Optical, plus hostile_kerning_values and txt2_extras_survive_a_resave_of_unchanged_text); corpus_text_layers reads real PSDs and applies their Txt2 optical kerning, but no oracle file is dedicated to kerning values |
|
||||
| BUG-207-1 | Retouch tools respect the paint target (mask, alpha channel, Quick Mask) | done | [#207](https://github.com/storytold/photocraft/issues/207) | run_stroke paints channel_cmds::target_surface; retouch_strokes_paint_the_targeted_mask (retouch_ui.rs) and engine retouch_cmds/tests.rs (e2444ce, #234) |
|
||||
| BUG-207-2 | Sample All Layers applies to Blur, Sharpen and Smudge | done | [#207](https://github.com/storytold/photocraft/issues/207) | retouch_ui.rs passes sampleAllLayers to paint.blur/sharpen/smudge; sample_all_layers_reaches_the_command (e2444ce, #234) |
|
||||
| BUG-207-3 | Smudge mixes premultiplied RGBA (no dark fringe at transparent edges) | done | [#207](https://github.com/storytold/photocraft/issues/207) | paint/src/retouch.rs premultiplies; smudge_into_transparency_leaves_no_dark_fringe (e2444ce, #234) |
|
||||
|
||||
+14
-14
@@ -114,51 +114,51 @@ note = "targeted_unlinked_mask_transforms_alone and targeted_linked_mask_moves_w
|
||||
[[item]]
|
||||
id = "BUG-205-4"
|
||||
target = "Test: a linked raster mask with no selection moves with the pixels"
|
||||
status = "partial"
|
||||
status = "done"
|
||||
issue = 205
|
||||
note = "Implemented at transform_cmds.rs:127; no raster-mask test"
|
||||
note = "linked_raster_mask_moves_with_the_pixels (transform_cmds.rs): a reveal-all mask with a hidden half, linked, no selection; asserts the hidden half travels with the pixels and nothing hidden is left behind"
|
||||
|
||||
[[item]]
|
||||
id = "BUG-205-5"
|
||||
target = "Tests: linked mask + selection stays aligned; unlinked stays; targeted mask only"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 205
|
||||
note = "Unlinked case honoured (m.linked check, l.128) but untested; the other two not implemented"
|
||||
note = "All three in transform_cmds.rs: linked_mask_with_a_selection_moves_only_the_selected_region checks the mask value under each moved pixel, unlinked_mask_stays_put covers it with and without a selection, targeted_unlinked_mask_transforms_alone moves the mask while the layer bounds stay"
|
||||
|
||||
[[item]]
|
||||
id = "BUG-206-1"
|
||||
target = "CharStyle models per-character manual kerning separately from the auto-kern mode"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 206
|
||||
note = "doc/text.rs:76 only `kerning: Kerning` enum (Metrics/Optical/Off)"
|
||||
note = "doc/src/text.rs CharStyle carries both: kerning: Kerning for the automatic mode (Metrics/Optical/Off) and kern: f32 for manual kerning in 1/1000 em between this character and the next, added on top of the pair's automatic kerning"
|
||||
|
||||
[[item]]
|
||||
id = "BUG-206-2"
|
||||
target = "PSD import keeps Optical and manual Kerning values"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 206
|
||||
note = "text/psd.rs:264 maps anything not Off to Metrics; Kerning value ignored"
|
||||
note = "io/tests/psd_kerning.rs manual_and_off_kerning_round_trip_through_psd and optical_kerning_round_trips_through_psd import an exported layer and compare every character's (mode, kern) pair; the optical mode travels in the document Txt2 block (#1348)"
|
||||
|
||||
[[item]]
|
||||
id = "BUG-206-3"
|
||||
target = "PSD export writes the real AutoKerning mode and Kerning values"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 206
|
||||
note = "text/psd.rs:380-381 AutoKerning bool only; Kerning hard-coded 0"
|
||||
note = "manual_and_off_kerning_round_trip_through_psd (io/tests/psd_kerning.rs) reads the AutoKerning flag and Kerning value of every character back out of the written TySh: (false, 100) after A, (true, -50) after T, and automatic kerning off where the style says so"
|
||||
|
||||
[[item]]
|
||||
id = "BUG-206-4"
|
||||
target = "Alt+Left/Right at a collapsed caret adjusts pair kerning; Character panel field"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 206
|
||||
note = "type_tool.rs:896-912 only a mode combo"
|
||||
note = "type_tool.rs: Alt+Left/Right at a collapsed caret calls kern_pair (20 per step, 100 with Cmd); the Character panel field takes Metrics, Optical or a manual value (kerning_label / parse_kerning). Covered by type_tool_alt_arrows_kern_the_pair and kerning_field_values (input_tests.rs)"
|
||||
|
||||
[[item]]
|
||||
id = "BUG-206-5"
|
||||
target = "Tests: PSD round trip of manual and Optical kerning, a real file in the oracle corpus"
|
||||
status = "missing"
|
||||
status = "partial"
|
||||
issue = 206
|
||||
note = "No kerning round-trip test"
|
||||
note = "Round trips covered by io/tests/psd_kerning.rs (manual, Off and Optical, plus hostile_kerning_values and txt2_extras_survive_a_resave_of_unchanged_text); corpus_text_layers reads real PSDs and applies their Txt2 optical kerning, but no oracle file is dedicated to kerning values"
|
||||
|
||||
[[item]]
|
||||
id = "BUG-207-1"
|
||||
|
||||
@@ -50,9 +50,9 @@ note = "No update check in crates"
|
||||
[[item]]
|
||||
id = "DIST-220-2"
|
||||
target = "Windows ARM64 (aarch64-pc-windows-msvc) in the release matrix, signed like x64"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 220
|
||||
note = "release.yml:113-114 only x86_64 and i686 msvc"
|
||||
note = "release.yml has { arch: arm64, target: aarch64-pc-windows-msvc } in the Windows matrix, and .github/workflows/windows-arm64.yml packages that MSI, installs it on a Windows 11 ARM64 runner, checks the installed binaries are ARM64 and runs the CLI natively before uninstalling. Signing takes the same path as x64: the secrets are optional and a missing one produces an unsigned artifact and a warning (see DIST-2)"
|
||||
|
||||
[[item]]
|
||||
id = "DIST-220-3"
|
||||
|
||||
@@ -155,9 +155,9 @@ note = "Only preset libraries (preset_store.rs)"
|
||||
[[item]]
|
||||
id = "FILE-216-1"
|
||||
target = "Every corpus fetched and enforced in CI, cached by pin"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 216
|
||||
note = "No corpus step in ci.yml; in progress in #190"
|
||||
note = "ci.yml has a corpus job (name: corpus tests) on every PR and on main: the corpora are pinned in xtask/src/corpus_pins.rs, sha256-verified after both a cache restore and a download, and a missing corpus fails the tests. The cache key follows the pins, so it is cached by pin as this row asks (#190)"
|
||||
|
||||
[[item]]
|
||||
id = "FILE-216-2"
|
||||
@@ -185,7 +185,7 @@ id = "FILE-216-5"
|
||||
target = "Save-path tests: layered TIFF, PDF, SVG, ACO/ASE, .shc, Smart Filters, atomic-save failure"
|
||||
status = "missing"
|
||||
issue = 216
|
||||
note = "Features absent; no atomic-save failure-injection test"
|
||||
note = "Save paths for layered TIFF, PDF, SVG, ACO/ASE, .shc and Smart Filters are absent. Atomic-save failure injection is covered: format/src/atomic/tests.rs write_failure_halfway_keeps_original and rename_failure_keeps_original (see BUG-203-6)"
|
||||
|
||||
[[item]]
|
||||
id = "FILE-216-6"
|
||||
|
||||
@@ -162,9 +162,9 @@ note = "edit.contentAwareScale (edit_menu_cmds.rs:899) behind a parameter dialog
|
||||
[[item]]
|
||||
id = "TOOL-214-8"
|
||||
target = "A measured ruler angle prefills Image Rotation > Arbitrary (0.01 deg)"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 214
|
||||
note = "Arbitrary rotation is a generic dialog; ruler only feeds straighten"
|
||||
note = "analysis_ui.rs: image.rotation.arbitrary opens seeded with the ruler angle and the direction that straightens it; arbitrary_rotation_starts_at_the_ruler_angle checks 5.7106 deg within 1e-3 and cw/ccw for three measured lines"
|
||||
|
||||
[[item]]
|
||||
id = "TOOL-214-9"
|
||||
|
||||
+4
-4
@@ -21,9 +21,9 @@ note = "Engine has TextDirection (text.rs:155); no UI"
|
||||
[[item]]
|
||||
id = "TYPE-218-3"
|
||||
target = "Thai/Khmer/Indic fallback fonts; golden shaping tests for complex scripts and RTL"
|
||||
status = "missing"
|
||||
status = "partial"
|
||||
issue = 218
|
||||
note = "fonts.rs:28 fallback covers Arabic/Hebrew; no per-script golden tests (only a bidi test)"
|
||||
note = "Thai is covered: THAI_FAMILIES (fonts.rs) lists the Windows, macOS and Linux families and thai_in_latin_font_falls_back_to_installed_thai_font checks a sample with above and below marks (#1909); Arabic and Hebrew fall back too. Khmer and Indic have no fallback list, and there are no per-script golden shaping tests (only a bidi test)"
|
||||
|
||||
[[item]]
|
||||
id = "TYPE-218-4"
|
||||
@@ -42,9 +42,9 @@ note = "Type > OpenType toggles (type_extra_cmds.rs:512); no panel buttons or su
|
||||
[[item]]
|
||||
id = "TYPE-218-6"
|
||||
target = "Manual pair kerning (Alt+arrows), optical kerning rendered, both round-trip PSD (#206)"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 218
|
||||
note = "Optical renders as Metrics (text.rs:21); Alt+arrow moves by word"
|
||||
note = "Alt+Left/Right at a collapsed caret kerns the pair (type_tool.rs kern_pair, 20 per step and 100 with Cmd; type_tool_alt_arrows_kern_the_pair). Optical kerning is computed from the glyph outlines in text/src/optical.rs and applied by layout.rs when the run's mode is Optical (optical_matches_photoshop, optical_kerning_tightens_open_pairs). Both modes and manual values round-trip through PSD (io/tests/psd_kerning.rs; the optical mode travels in Txt2, txt2_carries_optical_kerning)"
|
||||
|
||||
[[item]]
|
||||
id = "TYPE-218-7"
|
||||
|
||||
+7
-7
@@ -64,9 +64,9 @@ note = "paint_mouse.rs brush picker and canvas_tool_menu.rs selection actions; o
|
||||
[[item]]
|
||||
id = "UI-217-9"
|
||||
target = "UI scale presets 100/115/125/150/200 % through zoom_factor, remembered"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 217
|
||||
note = "prefs.rs:61 UiScale unused; input_tests.rs:71 asserts zoom_factor stays 1.0"
|
||||
note = "prefs::UiScale offers Auto plus 75 to 300 percent (13 presets, more than the five this row lists); prefs_ui.rs display_scale resolves it (Auto follows the system scale and only jumps to 200 percent on an unscaled 4K display, #1072/#225) and sync_display_scale applies it with ctx.set_zoom_factor. It is a preference, so it is remembered. The zoom_factor assert in input_tests.rs is about canvas zoom not scaling the interface, not about this setting"
|
||||
|
||||
[[item]]
|
||||
id = "UI-217-10"
|
||||
@@ -80,7 +80,7 @@ id = "UI-217-11"
|
||||
target = "Soft dark and soft light themes with picker previews; outlined knobs in light themes"
|
||||
status = "missing"
|
||||
issue = 217
|
||||
note = "theme.rs:28 five themes"
|
||||
note = "theme.rs ThemeKind has twelve themes (the four Pro brightness levels, Studio and Studio Light, Classic, Adwaita and Adwaita Dark, Solarized Dark, Breeze Light and Breeze Dark); no Soft dark or Soft light, and no outlined knobs in the light themes"
|
||||
|
||||
[[item]]
|
||||
id = "UI-217-12"
|
||||
@@ -155,13 +155,13 @@ note = "edit_menu_cmds.rs:714 covers brushes, custom shapes, patterns with reord
|
||||
[[item]]
|
||||
id = "UI-217-22"
|
||||
target = "Stamp Visible into a new layer keeping originals; Alt+Merge keeps originals"
|
||||
status = "missing"
|
||||
status = "done"
|
||||
issue = 217
|
||||
note = "Only layer.mergeVisible (edit_cmds.rs:416)"
|
||||
note = "stamp_cmds.rs layer.stampVisible (Cmd+Alt+Shift+E) merges every visible layer into a new layer above the active one and keeps the originals; layer.stampDown (Cmd+Alt+E) too. As in Photoshop they have no menu item of their own: Alt + Layer > Merge Visible / Merge Down / Merge Layers run them (stamp_cmds::alt_variant, menus.rs); stamp_tests.rs alt_click_on_merge_items_stamps and cmd_alt_shift_e_stamps_visible_and_can_be_rebound"
|
||||
|
||||
[[item]]
|
||||
id = "UI-217-23"
|
||||
target = "Layer clipboard: copy/paste whole layers (masks, styles, type) between documents"
|
||||
status = "missing"
|
||||
status = "partial"
|
||||
issue = 217
|
||||
note = "Only copy/paste layer style (extra_cmds.rs:592)"
|
||||
note = "layer.copyToDocument copies layers into another open document keeping names, content, masks, styles and blending, converting to the destination's profile and depth, as one history step (layer_copy_cmds.rs, #589). It is the command a drag between documents dispatches; there is still no copy/paste layer clipboard"
|
||||
Reference in new issue
Block a user