From 11e515a295665ac97911265e5c9ad4b127270519 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sun, 30 Aug 2026 10:21:32 +0200 Subject: [PATCH] Say which state NFR-P11 forbids losing, since one kind is dropped on purpose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NFR-P11's criterion was "no dropped frames, no state loss" across a layout class transition. Read literally, the interface already fails it, and fails it by design: `apply_layout_class` clears the user's panel open/closed choices whenever the class changes, and `PanelChoices` documents why — a choice made in landscape answers a different question from the one portrait asks, and carrying it across leaves a 232 px sidebar on a screen with no room for it. A requirement that the code deliberately contradicts is worse than no requirement, because the next person to read it either "fixes" the behaviour or learns to discount the register. So the criterion now names what must survive — the open image and version, the selection, scroll position, the in-progress edit and its undo history, the current mode — and states the exemption with the reasoning attached. Panel disclosure is a default re-derived per class, not state; the user's disagreement with it is remembered within the class where it was expressed. The intent is unchanged: a resize must not cost the photographer anything they did. It is now possible to write a test for that. Co-Authored-By: Claude Opus 5 (1M context) --- docs/requirements.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/requirements.md b/docs/requirements.md index b8d9b59..f8e1bfd 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -1330,13 +1330,25 @@ These are targets to design against and measure, on the reference desktop | **NFR-P14** | Focus peaking overlay ready | < 100 ms after preview | < 150 ms | | **NFR-P15** | Drawn mask stroke → visible (ARCH §6.11) | < 16 ms, no cursor lag | < 16 ms | | **NFR-P10** | Touch gesture → visual response | < 16 ms | < 16 ms | -| **NFR-P11** | Layout class transition (window resize) | No dropped frames, no state loss | n/a | +| **NFR-P11** | Layout class transition (window resize) | No dropped frames. No loss of *photographic* state: the open image and version, the selection, scroll position, the in-progress edit and its undo history, and the current mode. Panel disclosure is explicitly exempt — see below | n/a | | **NFR-P12** | Warm-start shader pipeline setup (cached) | < 100 ms | < 100 ms | Every target above requires a stated measurement method, workload, and pass threshold before it is testable. NFR-P8 in particular must state whether it measures RSS inclusive or exclusive of GPU allocations, and whether it holds after SQLite's page cache warms on a 50k catalog. +**On what NFR-P11 means by state.** It said "no state loss", which the implementation contradicts on +purpose, so the requirement has been made specific rather than left to be read as forbidding +something it should not. `apply_layout_class` discards the user's panel open/closed choices when the +class changes, and the argument for that is sound: a choice made in landscape answers a different +question from the one portrait asks, and carrying it across is how a photographer ends up with a +232 px sidebar on a screen with no room for it and no memory of having asked for it. Panel +disclosure is a *default*, re-derived per class, with the user's disagreement remembered only within +the class where it was expressed. + +Everything the photographer produced or navigated to is a different matter, and none of it may be +touched by a resize. That is the list in the criterion, and it is the testable half. + **Performance regressions fail the build.** §9's benchmark suite runs per-commit; a regression beyond a stated tolerance is a build failure, not a notification. Performance work rots otherwise.