App._post_init now resolves src = paths.get_layouts_dir()/default.ini
and dst = Path.cwd()/manualslop_layout.ini, then calls the drain-plane
helper before the warmup-complete registration block. Errors drain to
self._startup_timeline_errors per the data-oriented convention, so a
missing bundled layout (e.g. partial wheel install) does not crash the
GUI: panels just stay invisible until the user drops a real INI in.
Test fix: test_default_layout_install._GUI_SCRIPT was a relative path,
but the subprocess Popen runs with cwd = temp_workspace where sloppy.py
does not exist. Switched to an absolute path via _PROJECT_ROOT, the
same pattern conftest.py:648 uses for the live_gui fixture.
3 tests in tests/test_default_layout_install.py per spec G6/G7 acceptance:
- test_default_layout_installed_when_ini_missing
- test_default_layout_installed_when_ini_empty
- test_default_layout_NOT_installed_when_layout_present
Currently fail as expected (no install helper exists yet). Test 3 passes as
a positive control (custom user INI is preserved when no install logic
runs).
Subprocess spawn pattern: each test creates its own tmp_path workspace,
spawns sloppy.py without --enable-test-hooks (avoids port-8999 conflict
with the live_gui session fixture's subprocess), waits 5s, terminates
via taskkill /F /T, asserts on the saved INI content.
state.toml: phase 1 marked completed; tasks t1_1-t1_10 recorded with
SHA 7577d7d. plan.md updated for Phase 1 task completion.