mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-25 11:54:39 +01:00
* 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>
232 lines
10 KiB
TOML
232 lines
10 KiB
TOML
# Scorecard checklist: open bugs (#203–#208).
|
||
# Each item: id, short target, status (done | partial | missing), issue, note (evidence).
|
||
# Statuses must be true on main. BUG-203 verified against 47f9306 on 2026-10-07; the rest
|
||
# against 4b53f62 on 2026-10-05, except BUG-204 against ec350d6 on 2026-10-09.
|
||
area = "bugs"
|
||
title = "Open bugs"
|
||
order = 9
|
||
|
||
[[item]]
|
||
id = "BUG-203-1"
|
||
target = "Every document write goes through one atomic_write (temp, fsync, rename)"
|
||
status = "done"
|
||
issue = 203
|
||
note = "photocraft_format::atomic_write (format/src/atomic.rs, #230/8227071); every write site routes through it: engine file_cmds.rs write_file and preset_store.rs, automation files.rs/headless.rs/workspace.rs, app services.rs write_atomic, format store.rs and autosave.rs"
|
||
|
||
[[item]]
|
||
id = "BUG-203-2"
|
||
target = "Temp file in the same dir, sync_all, rename over target, fsync dir on Unix"
|
||
status = "done"
|
||
issue = 203
|
||
note = "atomic.rs: temp_name in the same dir, create_new + write_all + sync_all, Unix directory fsync after the rename"
|
||
|
||
[[item]]
|
||
id = "BUG-203-3"
|
||
target = "Windows: retry the rename with backoff on PermissionDenied"
|
||
status = "done"
|
||
issue = 203
|
||
note = "atomic.rs RenameRetry::platform(): seven retries from 10 ms on Windows; retry_rename is shared with automation's cap-std workspace write"
|
||
|
||
[[item]]
|
||
id = "BUG-203-4"
|
||
target = "Unwritable directory errors clearly, never falls back to writing in place"
|
||
status = "done"
|
||
issue = 203
|
||
note = "atomic.rs maps read-only dir, disk-full and cross-device rename errors to messages that say the original was not changed; there is no in-place fallback path"
|
||
|
||
[[item]]
|
||
id = "BUG-203-5"
|
||
target = "On any failure the original file is untouched and the temp file removed"
|
||
status = "done"
|
||
issue = 203
|
||
note = "atomic.rs removes the temp file on every failure; tests assert the original bytes survive write and rename failures"
|
||
|
||
[[item]]
|
||
id = "BUG-203-6"
|
||
target = "Failure-injection tests: mid-write, rename and read-only dir errors keep original bytes"
|
||
status = "done"
|
||
issue = 203
|
||
note = "format/src/atomic/tests.rs: Faulty AtomicFs injects mid-write StorageFull, rename failure and a read-only dir; locked-target retries, symlink and file-mode preservation covered too"
|
||
|
||
[[item]]
|
||
id = "BUG-204-1"
|
||
target = "Interface prefs (UI scale, font size, channels in colour, sliders, tooltips) wired or hidden"
|
||
status = "done"
|
||
issue = 204
|
||
note = "prefs_ui.rs tick reads ui_scale (sync_display_scale), ui_font_size (theme::set_ui_font_size) and show_tooltips (sync_tooltips); show_channels_in_color is wired in channel_thumbs and the canvas channel view (#2385); dynamic_color_sliders is in prefs::HIDDEN_UNTIL_IMPLEMENTED"
|
||
|
||
[[item]]
|
||
id = "BUG-204-2"
|
||
target = "workspace.large_tabs, animated_zoom, auto_show_home_screen wired or hidden"
|
||
status = "done"
|
||
issue = 204
|
||
note = "workspace.large_tabs controls document tab height in canvas.rs; auto_show_home_screen drives the Home screen; animated_zoom is in prefs::HIDDEN_UNTIL_IMPLEMENTED"
|
||
|
||
[[item]]
|
||
id = "BUG-204-3"
|
||
target = "RAW prefs and ask_before_saving_layered_tiff read, or hidden"
|
||
status = "done"
|
||
issue = 204
|
||
note = "ask_before_saving_layered_tiff drives the TIFF Options prompt (ui-egui tiff_options_ui.rs); raw_defaults.open_in_camera_raw drives the Camera Raw dialog (camera_raw_ui.rs); the other raw_defaults fields are in prefs::HIDDEN_UNTIL_IMPLEMENTED"
|
||
|
||
[[item]]
|
||
id = "BUG-204-4"
|
||
target = "Recent files persisted through prefs across restarts"
|
||
status = "done"
|
||
issue = 204
|
||
note = "crates/ui-egui/src/lib.rs::push_recent stores the list in preferences; prefs_ui::load restores it and recent_files_survive_a_restart_and_honour_the_count verifies reload"
|
||
|
||
[[item]]
|
||
id = "BUG-204-5"
|
||
target = "Recent-files list honours recent_file_count (default 20)"
|
||
status = "done"
|
||
issue = 204
|
||
note = "lib.rs push_recent caps the list with recent_cap (recent_file_count); menus.rs covers default and custom limits"
|
||
|
||
[[item]]
|
||
id = "BUG-204-6"
|
||
target = "Test: every Prefs field is read somewhere or on a hidden allowlist"
|
||
status = "done"
|
||
issue = 204
|
||
note = "crates/engine/tests/prefs_usage.rs every_preference_is_read_or_hidden: each field is read outside prefs.rs or listed in prefs::HIDDEN_UNTIL_IMPLEMENTED, never both"
|
||
|
||
[[item]]
|
||
id = "BUG-205-1"
|
||
target = "Free Transform with a selection moves only the selected part of a linked mask"
|
||
status = "done"
|
||
issue = 205
|
||
note = "linked_mask_with_a_selection_moves_only_the_selected_region (transform_cmds.rs; 5a5facc, #242)"
|
||
|
||
[[item]]
|
||
id = "BUG-205-2"
|
||
target = "Live transform preview draws the layer with its mask applied"
|
||
status = "done"
|
||
issue = 205
|
||
note = "transform_tool.rs preview_mask + preview_applies_the_linked_mask (5a5facc, #242)"
|
||
|
||
[[item]]
|
||
id = "BUG-205-3"
|
||
target = "edit.transform honours target mask: transforms only a targeted, unlinked mask"
|
||
status = "done"
|
||
issue = 205
|
||
note = "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)"
|
||
|
||
[[item]]
|
||
id = "BUG-205-4"
|
||
target = "Test: a linked raster mask with no selection moves with the pixels"
|
||
status = "done"
|
||
issue = 205
|
||
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 = "done"
|
||
issue = 205
|
||
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 = "done"
|
||
issue = 206
|
||
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 = "done"
|
||
issue = 206
|
||
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 = "done"
|
||
issue = 206
|
||
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 = "done"
|
||
issue = 206
|
||
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 = "partial"
|
||
issue = 206
|
||
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"
|
||
target = "Retouch tools respect the paint target (mask, alpha channel, Quick Mask)"
|
||
status = "done"
|
||
issue = 207
|
||
note = "run_stroke paints channel_cmds::target_surface; retouch_strokes_paint_the_targeted_mask (retouch_ui.rs) and engine retouch_cmds/tests.rs (e2444ce, #234)"
|
||
|
||
[[item]]
|
||
id = "BUG-207-2"
|
||
target = "Sample All Layers applies to Blur, Sharpen and Smudge"
|
||
status = "done"
|
||
issue = 207
|
||
note = "retouch_ui.rs passes sampleAllLayers to paint.blur/sharpen/smudge; sample_all_layers_reaches_the_command (e2444ce, #234)"
|
||
|
||
[[item]]
|
||
id = "BUG-207-3"
|
||
target = "Smudge mixes premultiplied RGBA (no dark fringe at transparent edges)"
|
||
status = "done"
|
||
issue = 207
|
||
note = "paint/src/retouch.rs premultiplies; smudge_into_transparency_leaves_no_dark_fringe (e2444ce, #234)"
|
||
|
||
[[item]]
|
||
id = "BUG-207-4"
|
||
target = "edit.transform transforms a targeted alpha channel"
|
||
status = "done"
|
||
issue = 207
|
||
note = "edit.transform follows a targeted alpha channel or Quick Mask (explicit target since #242, Channels panel target with no target/layer param since #2835); Edit > Transform > Rotate/Flip are routed to the target too; transforms_follow_the_targeted_alpha_channel"
|
||
|
||
[[item]]
|
||
id = "BUG-207-5"
|
||
target = "Tests: per-tool mask/channel targeting, Sample All Layers, no smudge fringe"
|
||
status = "missing"
|
||
issue = 207
|
||
note = "Only smudge_drags_colour_along_the_stroke (retouch.rs:407)"
|
||
|
||
[[item]]
|
||
id = "BUG-208-1"
|
||
target = "Shift while dragging a Rect/Elliptical Marquee constrains to a square/circle"
|
||
status = "done"
|
||
issue = 208
|
||
note = "canvas.rs marquee_corners applies Shift via Drag::marquee_mods; marquee_tests.rs::shift_during_the_drag_draws_a_square_and_the_readout_follows covers the drag"
|
||
|
||
[[item]]
|
||
id = "BUG-208-2"
|
||
target = "Alt while dragging a marquee draws from the centre"
|
||
status = "done"
|
||
issue = 208
|
||
note = "canvas.rs marquee_corners centres Alt drags; marquee_tests.rs::alt_draws_from_the_centre_and_shift_alt_a_centred_circle verifies rectangles and ellipses"
|
||
|
||
[[item]]
|
||
id = "BUG-208-3"
|
||
target = "W x H px readout beside the cursor while dragging a marquee"
|
||
status = "done"
|
||
issue = 208
|
||
note = "canvas.rs marquee_readout draws the readout; marquee_tests.rs asserts dimensions while dragging and its removal after release"
|
||
|
||
[[item]]
|
||
id = "BUG-208-4"
|
||
target = "Add/subtract/intersect from modifiers pressed before the drag, kept by a test"
|
||
status = "partial"
|
||
issue = 208
|
||
note = "Mods captured at press (canvas.rs:1679, used :1779); only a badge test (tool_feedback.rs:195)"
|
||
|
||
[[item]]
|
||
id = "BUG-208-5"
|
||
target = "Kittest: Shift drag gives a square, Alt drag is centred, readout matches the size"
|
||
status = "done"
|
||
issue = 208
|
||
note = "crates/ui-egui/src/marquee_tests.rs covers Shift, Alt, selection bounds, W/H readout and drag completion"
|