The spec was drafted while the working tree was on tier2/post_module_taxonomy_de_cruft_20260627, but the track targets master. 2 line numbers were from the cruft branch, not master: - src/commands.py reset_layout: spec said :342-378 + :371; master is :248-275 + :268 - src/command_palette.py: spec said 208 lines; master is 165 lines Also added a Branch State Warning section documenting: - main working tree is on tier2/post_module_taxonomy_de_cruft_20260627 (NOT master) - module_taxonomy_refactor_20260627 + post_module_taxonomy_de_cruft_20260627 are NOT merged to master - this track does NOT depend on those cruft tracks - master worktree at C:\projects\manual_slop_master is the editing surface All other line numbers (App._post_init:566, App.run:619, _run_immapp_result:691, _post_init_callback_result:1449, render_persona_editor_window:3433, orphan end_child:6990, paths.py themes:60/83/150/209-216/295) verified correct against master.
25 KiB
Track Specification: Default Layout Extract + Hard Visual Verification
Overview
Extract tier-2's GOOD work on the default layout setup (the layouts/ directory, the install-on-empty-INI helpers, the pre-run install timing fix, and the orphan-end-child cleanup) into master, and replace the previous tier-2 "fake" verification (INI content assertions only) with a HARD 4-layer visual verification protocol that catches the "panels don't render" regression every time it occurs.
Current State Audit (as of commit 466d2656 on master)
Branch State Warning
The main working tree at C:\projects\manual_slop is currently on branch tier2/post_module_taxonomy_de_cruft_20260627 (NOT master). This track targets master. All line numbers below are from master (verified via git show master:src/gui_2.py). The cruft-elimination tracks (module_taxonomy_refactor_20260627 + post_module_taxonomy_de_cruft_20260627) are NOT merged to master — they live on tier-2 branches only. This track does NOT depend on those cruft tracks; it depends only on cruft_elimination_20260627 (which IS merged to master) + the themes infrastructure in src/paths.py (which is on master). A separate master worktree exists at C:\projects\manual_slop_master for editing on the master branch without disturbing the cruft-branch working tree.
Already Implemented on Master
src/paths.py:60,83,150,209-216— themes infrastructure (the pattern to mirror for layouts):themes: Pathfield in_AppPaths, defaultroot_dir / "themes", env overrideSLOP_GLOBAL_THEMES, gettersget_global_themes_path()andget_project_themes_path(project_root), plus the path info dict entry at line 295.src/theme_2.py:340-346+src/theme_models.py:181-225— themes loader pair (the pattern to mirror for layouts):load_themes_from_disk()callsget_global_themes_path()thenload_themes_from_dir(path, scope); the latter iterates children, parses, builds typed@dataclass(frozen=True, slots=True)records, drains errors viaResult + ErrorInfo.src/gui_2.py:1776—from src.command_palette import render_palette_modal. MASTER WORKS:src/command_palette.pyEXISTS (165 lines, hasCommand,ScoredCommand,CommandRegistry,render_palette_modal). Tier-2 broke because they deletedsrc/command_palette.pyinmodule_taxonomy_refactor_20260627(commit3dd153f7, NOT merged to master).src/gui_2.py:580-611—_diag_layout_state(one-shot startup diagnostic that logsshow_windowscount + INI file size + stale window name warnings). Used as the install verification hook.src/gui_2.py:619-703—App.run. Calls_run_immapp_result(self)at line 691. HelloImGui readsrunner_params.ini_filename("manualslop_layout.ini") from cwd at load_user_pref time, BEFOREcallbacks.post_initfires.src/gui_2.py:566-578—App._post_init. Calls_post_init_callback_resultand_diag_layout_state. Fires AFTER HelloImGui has loaded the INI from disk.src/gui_2.py:1449-1470—_post_init_callback_result(drain-aware wrapper forApp._post_init). The pattern Tier-2's_install_default_layout_if_empty_resultand_install_default_layout_pre_run_resultfollow.src/gui_2.py:1658-1660— orphan-end-child bug was refactored OUT of_tier_stream_scroll_sync_result(the helper that was previously buggy). The orphan at line 6990 (inrender_tier_stream_panel's except block) STILL exists on master.src/gui_2.py:6981-6991—render_tier_stream_panelhas the latent orphan-end-child bug:try: ... imgui.end_child()at line 6988;except (TypeError, AttributeError): imgui.end_child()at line 6990. When the try block raises (e.g.len(None)), the secondend_child()fires with no matchingbegin_child()and ImGui emits "In window 'MainDockSpace': Missing End()". Currently latent becauselen(content)rarely raises.tests/conftest.py:700-712— pre-bakedtests/artifacts/manualslop_layout_default.inishipped to fresh test workspaces. Hardcoded path (cwd-relative test fixture) — violates "production code uses cwd-relative paths only" rule.src/commands.py:248-275—reset_layoutcommand with hardcodedtests/artifacts/live_gui_workspace/manualslop_layout.inipath at line 268 (dead code in production; references a test-fixture path that doesn't exist in production cwd).conductor/tracks/default_layout_install_20260629/— Tier-1 track scaffolding from this session. States the user's intent.conductor/tracks/default_layout_install_followup_20260629/— Tier-1 followup track that supersedes Tier-2's wrong-theorye9654518strip-docking fix.
Already Implemented on Tier-2 Branch (NOT on master)
layouts/default.ini(2971 bytes, 101 lines) — bundled INI with full[Docking][Data]hierarchy (DockSpace ID=0xAFC85805 + DockNode 0x00000001 + DockNode 0x00000002 + 8 per-windowDockId=...entries). Comments document the runtime-generated ID semantics.src/layouts.py(3178 bytes, 88 lines) —LayoutFiledataclass +load_layouts_from_file()+load_layouts_from_dir()+load_layouts_from_disk()(mirrorssrc/theme_models.py:181-225shape exactly).src/gui_2.py:1481-1540—_install_default_layout_if_empty+_install_default_layout_if_empty_result(drain-aware wrapper). The function: reads dst INI; if empty (<1000 bytes OR no[Window][), reads bundled src INI, writes to dst, callsimgui.load_ini_settings_from_memory(src_text)to apply to live session.src/gui_2.py:1543-1590—_install_default_layout_pre_run_result. Same logic but disk-only (noload_ini_settings_from_memory) because imgui is not yet initialized beforeimmapp.run(). This is the timing fix Tier-2 added after the post-init version was too late for the first session.src/gui_2.py:701-706—App.runwiring: calls_install_default_layout_pre_run_result(self)BEFORE_run_immapp_result(self). Drains errors to_startup_timeline_errors.src/gui_2.py:579-582—App._post_initwiring: calls_install_default_layout_if_empty_result(self, src_layout_path, dst_layout_path). Drains errors.tests/test_layout_reorganization.py(66 lines) — RED tests for the install-on-empty-INI behavior (per tier-2 claim "17/17 PASSED"; tests check INI content, not visible panels).
Gaps to Fill (This Track's Scope)
| Gap | Severity | Layer |
|---|---|---|
layouts/ directory + layouts/default.ini + src/layouts.py missing on master |
High | (the assets themselves) |
_install_default_layout_if_empty + _install_default_layout_pre_run_result helpers missing on master |
High | (the install behavior) |
App._post_init and App.run wiring missing on master |
High | (the install triggers) |
get_layouts_dir() in src/paths.py missing on master |
High | (the path resolver; mirrors themes) |
reset_layout command still references dead tests/artifacts/manualslop_layout_default.ini path |
Medium | cleanup |
Orphan imgui.end_child() at src/gui_2.py:6990 (latent; fires when tier-stream try-block raises) |
Medium | cleanup |
| No hard verification that panels actually render visually | Critical | verification infrastructure |
Tier-2's "Bullshit" We're NOT Extracting
| Commit | Why Skip |
|---|---|
e9654518 "strip stale dockspace IDs" |
Wrong theory (superseded by 2afb0126; that one we DO extract) |
13ad9d3e "idk" |
Meaningless commit message; bulk-edited manualslop_layout.ini |
28527851 "artifacts" |
Meaningless commit; bulk-edited artifacts |
9437af6c "archive 27 diagnostic scripts" |
27 throwaway scripts not needed in master |
4acf8b15, b80e5afb, c42a7599, cf5244b1, b1632f46, 06476c56, 519e1340, cf6a2e20, 4bf5ecd6, 5e53d477, d4116f19, 7d5a5492, 15cd1262, 23566da8 |
Tier-2 internal track-marking commits; we write our own |
71028dad "drop stale from src.command_palette import" |
Tier-2 specific: master has src/command_palette.py so the import WORKS on master. The stale import bug only exists on tier-2 because they deleted the module. We do not cherry-pick this. |
Why the User Wants This Track
The tier-2 track was marked "SHIPPED" based on:
- 17/17 install/layout tests PASS (which only check INI content, not visible panels)
- Manual launch produces a 3072-byte INI with correct structure (content check, not visible check)
- "the imgui core loader rejected the literal IDs from the bundled INI because the runtime IDs didn't match" — claim contradicted by post-fix INI matching runtime IDs
None of those commits empirically verified visible panels after install. The user wants this regression to never happen again. The previous tier-2 "fake" verification must be replaced by a HARD one.
Goals
G1. Master has layouts/default.ini + src/layouts.py + get_layouts_dir() so the app boots with a non-empty INI on first launch.
G2. Master has _install_default_layout_if_empty + _install_default_layout_pre_run_result wired into App._post_init + App.run so empty-INI detection + install-on-empty works at both phases (live session + first session).
G3. Master has reset_layout cleaned up to remove the dead test-fixture path (no more tests/artifacts/... in production code).
G4. Master has the orphan imgui.end_child() at src/gui_2.py:6990 removed.
G5. Master has a HARD 4-layer visual verification infrastructure:
- Layer 1 (Per-Panel Sentinel): a
tests/test_panels_visible_after_install.pytest that asserts everyshow_windows[k]==Truepanel has nonzero render size after first frame. - Layer 2 (Win32 PrintWindow Pixel Baseline): a
tests/test_visual_baseline_default.pytest that captures the running GUI window's pixels via Win32PrintWindowAPI and compares againsttests/artifacts/visual_baseline_default.pngwith <1% pixel-diff tolerance. Catches ALL visual regressions (empty workspace, wrong INI, missing panels, overlap, theme corruption). - Layer 3 (Forced Test Viewport + Theme):
MANUAL_SLOP_TEST_VIEWPORT=1680x1050+MANUAL_SLOP_TEST_THEME=darkenv vars honored at startup. Forces fixed viewport + known theme so the baseline PNG is deterministic. - Layer 4 (Cannot-Skip Gates):
scripts/check_visual_baseline.py(exits 1 if pixel diff > 1%); wire intoscripts/run_tests_batched.py; requiregit tag VERIFIED-<YYYYMMDD>on the merge commit;conductor/tracks.mdschema update so[x]-completion requires the tag.
G6. A regression test demonstrates that the verification infrastructure catches the original "panels don't render" bug (negative test: corrupt the installed INI, verify the sentinel + pixel baseline both fail).
Functional Requirements
FR1. Tier-2 Asset Extraction (Hybrid Approach C)
- F1.1. Port
layouts/default.inifresh from tier-2'sC:\projects\manual_slop_tier2\layouts\default.ini(2971 bytes, 101 lines) tolayouts/default.iniat master repo root. Rationale: clean history for new asset; user-facing content. - F1.2. Port
src/layouts.pyfresh from tier-2'sC:\projects\manual_slop_tier2\src\layouts.py(88 lines). Mirrorssrc/theme_models.py:181-225shape. Rationale: clean history for new module; matchessrc/theme_2.py+src/theme_models.pypair. - F1.3. Add
get_layouts_dir()tosrc/paths.pymirroringget_global_themes_path()at line 209. Addlayouts: Pathfield to_AppPaths(line 60), defaultroot_dir / "layouts"(line 83), env overrideSLOP_GLOBAL_LAYOUTS(line 150), path info dict entry (line 295). User explicitly authorized "make a layouts directory similar to the themes directory" in the prior session. - F1.4. Port
tests/test_layout_reorganization.pyfresh from tier-2 (66 lines). Rationale: tests for the install helpers.
FR2. Install Helpers + Wiring
- F2.1. Add
_install_default_layout_if_empty(src_ini: Path, dst_ini: Path) -> Result[bool]tosrc/gui_2.py(per tier-2 line 1481). Reads dst; if empty (<1000 bytes OR no[Window][), copies src→dst and callsimgui.load_ini_settings_from_memory(src_text)to apply to live session. - F2.2. Add
_install_default_layout_if_empty_result(app: "App", src: Path, dst: Path) -> Result[bool](per tier-2 line 1530). Drain-aware passthrough wrapper. - F2.3. Add
_install_default_layout_pre_run_result(app: "App") -> Result[bool](per tier-2 line 1543). Disk-only install (noload_ini_settings_from_memory); imgui isn't initialized yet. - F2.4. Wire
_install_default_layout_if_empty_resultintoApp._post_init(line 566-578). Source path:get_layouts_dir() / "default.ini". Dst path:Path.cwd() / "manualslop_layout.ini". Drain errors to_startup_timeline_errors. - F2.5. Wire
_install_default_layout_pre_run_resultintoApp.run(line 619-703, insert before line 691_run_immapp_result(self)). Drain errors to_startup_timeline_errors.
FR3. Surgical Cherry-Picks
- F3.1. Cherry-pick
c2155593 fix(gui): remove orphan imgui.end_child() in render_tier_stream_panel except handler. Apply the 1-line deletion tosrc/gui_2.py:6990. Tier-2 verified this fixes an imgui "Missing End()" error in MainDockSpace when the tier-stream try-block raises. Latent on master but real. - F3.2. Cherry-pick
3b966288 chore(commands): remove dead test-fixture path from reset_layout. Apply the deletion tosrc/commands.py:268(thetests/artifacts/live_gui_workspace/manualslop_layout.inihardcoded path in thelayout_pathslist).
FR4. Layer 1 — Per-Panel Render Sentinel
- F4.1. New test file
tests/test_panels_visible_after_install.py. Importslive_guifixture fromtests/conftest.py. - F4.2. RED: assert that for each
show_windows[k]==Trueentry, after first frame,imgui.find_window_viewport(k).size.x > 0 AND .size.y > 0. Test should fail on the current baseline (we don't have the install helpers yet) — confirms sentinel catches the regression. - F4.3. GREEN: with the install helpers in place (FR2), test passes.
- F4.4. Test must use poll-loop (not
time.sleep) perconductor/workflow.md"Async Setters Need Poll-For-State".
FR5. Layer 2 — Win32 PrintWindow Pixel Baseline
- F5.1. New test file
tests/test_visual_baseline_default.py. Importslive_guifixture. - F5.2. Capture: import
win32guifrompywin32; find imgui window HWND viawin32gui.FindWindow(None, "manual slop"); allocate DC + bitmap; callwin32gui.PrintWindow(hwnd, hdc, PW_RENDERFULLCONTENT); convert bitmap to PNG viaPillow(already a dep); save totests/artifacts/<test_session>_<date>.png. - F5.3. Baseline: commit
tests/artifacts/visual_baseline_default.png(the "known good" reference). Generated AFTER F5.1 + F5.2 are GREEN against the new install infrastructure. - F5.4. Compare: load baseline + current via
Pillow.Image.open(...); convert to RGB; compute pixel diff vianumpy.abs(np.array(a) - np.array(b)).mean() / 255.0. Threshold: 0.01 (1%). Fail if > 1%. - F5.5. RED: with the install infrastructure removed, the test must fail. Confirms the test catches the regression.
- F5.6. Test must poll for first frame + capture screenshot AT MOST ONCE (don't spam captures).
FR6. Layer 3 — Forced Test Viewport + Theme
- F6.1. Add
MANUAL_SLOP_TEST_VIEWPORT=1680x1050env var support toApp.run(line 619). If set, overrideself.runner_params.app_window_params.window_geometry.sizeto the env-var value (parsed asWxH). - F6.2. Add
MANUAL_SLOP_TEST_THEME=darkenv var support toApp.run(line 619). If set, forceself.runner_params.imgui_window_params.tweaked_theme = ImGuiTheme_.ImGuiColorsDark(the default dark theme). - F6.3. RED: write
tests/test_test_mode_env_vars.pythat asserts both env vars are honored when set (vialive_guifixture with env vars). - F6.4. GREEN: implement the env-var parsing in
App.run.
FR7. Layer 4 — Cannot-Skip Gates
- F7.1. New file
scripts/check_visual_baseline.py. Importslive_gui(no — too heavy for a CLI script). Instead, accepts--baseline <path>+--current <path>+--threshold <float>CLI args. UsesPillow.Image.open()+numpy.abs(...).mean()to compute diff. Exits 1 if diff > threshold. - F7.2. Add
scripts/check_visual_baseline.pytoscripts/run_tests_batched.pytier-2 test list (or a new tier dedicated to visual regression). - F7.3. Document the
VERIFIED-<YYYYMMDD>git-tag requirement inconductor/tracks.mdschema section. Tracks that touchsrc/gui_2.pyMUST carry the tag for[x]-completion. - F7.4. New doc
docs/guide_visual_verification.md(200-300 lines). Documents the 4 layers, how to add a new visual baseline, how to update an existing baseline, the env-var protocol, the tag protocol.
FR8. Negative Test (Regression Catch Demonstration)
- F8.1. New test file
tests/test_visual_baseline_catches_corrupt_ini.py. Useslive_guifixture; AFTER the install infrastructure has run, manually corrupt the installed INI (delete[Docking][Data]line). Re-launch + capture screenshot. Verify pixel diff > 5% (the corrupted INI shows empty workspace, baseline shows full panels). - F8.2. Negative test must run in a separate
pytestsession (not pollutelive_guistate).
Non-Functional Requirements
NFR1. Atomic Per-Task Commits
Every Phase task results in exactly ONE atomic commit. No batched commits. Per AGENTS.md "Critical Anti-Patterns" — "Do not batch commits - commit per-task for atomic rollback".
NFR2. TDD Red-First
Every implementation task has a preceding RED test task. Per conductor/workflow.md "Standard Task Workflow" §4.
NFR3. No Comments in Source Code
Per AGENTS.md "Critical Anti-Patterns" — "Do not add comments to source code; documentation lives in /docs".
NFR4. No Diagnostic Noise in Production
Per AGENTS.md "Critical Anti-Patterns" — diag stderr goes to tests/artifacts/*.diag.log or /tmp, NOT src/*.py.
NFR5. 1-Space Indentation
Per conductor/workflow.md "Code Style (MANDATORY - Python)" — exactly 1 space per level for ALL Python code.
NFR6. CRLF Line Endings on Windows
Per conductor/workflow.md "Code Style (MANDATORY - Python)" — preserve CRLF.
NFR7. Type Hints Required
Per conductor/product-guidelines.md "AI-Optimized Compact Style" — strict type hints on all parameters, return types, globals.
NFR8. No dict[str, Any] / Optional[T] in Non-Boundary Code
Per conductor/code_styleguides/data_oriented_design.md §8.5 + python.md §17. Typed @dataclass(frozen=True, slots=True) + Result[T] + NIL_T.
NFR9. ImGui Defer Patterns
Per conductor/code_styleguides/python.md — use imscope context managers over manual imgui.begin/end pairs (where applicable). Existing manual pairs in src/gui_2.py are unchanged.
NFR10. Manual Slop MCP Tools Only
Per the system prompt — use manual-slop_* MCP tools, NOT native read/edit/grep (where the MCP equivalents are available). When MCP tools aren't available (which is the case for this Tier-1 track creation), native read/edit/grep/write are the fallback.
Architecture Reference
docs/guide_gui_2.md§"App class lifecycle" + §"_post_init + App.run" — current rendering flow; where the install helpers slot in.docs/guide_architecture.md§"Thread domains, event system" — confirms main thread ownsApp.run; install helpers run on main thread (no thread-safety concerns).docs/guide_testing.md§"live_guifixture" + §"Puppeteer pattern" + §"Structural Testing Contract" — the live_gui fixture is the test harness for FR4-FR8.conductor/code_styleguides/data_oriented_design.md§8.5 — the Python Type Promotion Mandate. Bound by NFR8.conductor/code_styleguides/error_handling.md—Result[T]+ErrorInfo+ErrorKindusage. The install helpers returnResult[bool]per this styleguide.conductor/code_styleguides/type_aliases.md—Metadata = TrackMetadataetc. The newLayoutFiledataclass follows the typed-record pattern from this styleguide.conductor/code_styleguides/feature_flags.md— "delete to turn off" (file presence) for the bundled INI. Iflayouts/default.iniis deleted,_install_default_layout_if_emptyreturnsResult(data=False)(no install).docs/guide_visual_verification.md(NEW, FR7.4) — the documentation deliverable.
Out of Scope
- Fleury declarative view-constructs migration (
PANELS: tuple[PanelDef, ...]). Logged indefault_layout_install_20260629/metadata.jsondeferred_to_followup_tracks[0]. Requires its own track. - imgui_test_engine integration (
test_engine_integration_20260627). Provides pixel-level diff viactx.capture_screenshot_window(). Our Win32 PrintWindow approach is simpler + works without test engine. The two approaches are complementary; layering them is a future task. - Reverting tier-2's working tree state. User's responsibility per the Inherited-Cruft rule. Tier-2's
git statusshows uncommittedmanual_slop.toml+manual_slop_history.tomldeletions; user must explicitly handle those. - Cross-platform pixel diff (Linux/macOS). Win32 PrintWindow is Windows-only. The track ships Windows-only; CI on Linux/macOS would skip FR5 (marked
@pytest.mark.skipif(sys.platform != "win32")). - Pre-baked test INI shipped from
tests/conftest.py:700-712. Replaced by FR5.3 baseline PNG. render_persona_editor_windowbug atsrc/gui_2.py:3433+(opens + immediately closes the Persona Editor window when not embedded). Pre-existing; unrelated to panel visibility. Logged for followup.
Coordination with Pending Tracks
default_layout_install_20260629/— supersedes. Tier-1 scaffolding for this work. The plan.md tasks here replaceconductor/tracks/default_layout_install_20260629/plan.md.default_layout_install_followup_20260629/— supersedes. The followup plan assumed tier-2'se9654518INI strip was the right fix; this track's plan supersedes that with the hybrid extraction.test_engine_integration_20260627— independent. Not blocked by, does not block this track. May consume the env-var protocol (FR6.1 + F6.2) once integrated.panel_defs_fleury_migration_20260629(deferred) — future. Will consumeLayoutFile+get_layouts_dir()from this track.
Verification Criteria (Track Completion Gates)
- All Phase 1-9 tasks committed (atomic per-task)
tests/test_panels_visible_after_install.pypasses (Layer 1 sentinel)tests/test_visual_baseline_default.pypasses (Layer 2 pixel diff < 1%)tests/test_test_mode_env_vars.pypasses (Layer 3 env vars honored)tests/test_visual_baseline_catches_corrupt_ini.pypasses (FR8 negative test)scripts/check_visual_baseline.py --helpworks;--strictmode exits 1 on diff > 1%scripts/run_tests_batched.pyincludes the visual verification teststests/artifacts/visual_baseline_default.pngis committed to masterdocs/guide_visual_verification.mdis committed; cross-referenced fromdocs/Readme.mdconductor/tracks.mdschema updated to requireVERIFIED-<YYYYMMDD>tag for[x]-completion of tracks touchingsrc/gui_2.py- MANUAL GATE: user runs
uv run sloppy.pyfrom master, confirms panels render visibly. User commits theVERIFIED-<date>tag. docs/reports/TRACK_COMPLETION_default_layout_extract_20260629.mdcommitted- Tier-2 branch status: marked for archival (user's responsibility per AGENTS.md "Inherited-Cruft")
Scope Summary (per workflow.md "Tier 1 Track Initialization Rules")
- Scope: 9 phases, ~36 tasks
- Files touched: ~12 (3 new:
src/layouts.py,layouts/default.ini,tests/artifacts/visual_baseline_default.png,scripts/check_visual_baseline.py,docs/guide_visual_verification.md; 6 modified:src/gui_2.py,src/paths.py,src/commands.py,tests/test_layout_reorganization.py,tests/test_panels_visible_after_install.py(new),tests/test_visual_baseline_default.py(new),tests/test_test_mode_env_vars.py(new),tests/test_visual_baseline_catches_corrupt_ini.py(new),scripts/run_tests_batched.py,conductor/tracks.md,docs/Readme.md) - Sites modified: ~15 (in
_post_init,App.run,_install_default_layout_*,_diag_layout_state, etc.) - Tasks: ~36
Risk Register
- R1 — Win32 PrintWindow may fail for the imgui-bundle HelloImGui window (HWND lookup or print flags). Mitigation: pre-flight check
win32gui.IsWindow(hwnd)before capture; fall back toBitBltof the screen region. - R2 — Pixel baseline may be too sensitive (font hinting, GPU driver variations). Mitigation: tolerance is 1%; if false positives appear, raise to 2% and document.
- R3 — Forced viewport env var may not work on multi-monitor systems. Mitigation: scope the env var to test fixtures only (
tests/conftest.pysets it before spawning). - R4 — Tier-2 sandbox has uncommitted edits that may conflict when cherry-picking. Mitigation: cherry-pick to master directly (master is clean); tier-2 archival is user's responsibility.
- R5 — User-visible panel rendering depends on
_install_default_layout_pre_run_resultfiring BEFOREimmapp.run. If the user's cwd already has a validmanualslop_layout.ini, the install is skipped. The pixel baseline test must run with cwd-deletedmanualslop_layout.inito exercise the install path. Mitigation:live_guifixture already cleans cwd before spawning.