Commit Graph
100 Commits
Author SHA1 Message Date
ed 5fa8a10ebf docs(testing): critical live_gui_workspace path fix + 8 new sections
CRITICAL fix:
- live_gui_workspace path: tmp_path_factory (banned) ->
  tests/artifacts/live_gui_workspace_<timestamp> (per-run timestamp)
  (per conductor/code_styleguides/workspace_paths.md)

8 new sections under 'Per-test Subprocess Resilience':
1. _reset_clean_baseline autouse fixture (mma_tier_usage +
   rag_config=default RAGConfig(), not None)
2. Watchdog and Hang Bounding (signal-based, 900s smart + 900s
   unconditional, replaces removed 30s daemon-thread)
3. Chroma Cache Path (tests/artifacts/.slop_cache/, parent-trailing-slash
   bug, pre-cleanup pattern in test_rag_phase4_final_verify)
4. xdist Worker Coordination (O_EXCL file lock, PYTEST_XDIST_WORKER,
   owner/client roles, stale lock demotion)
5. Required Test Dependencies Gate (sentence-transformers,
   uv sync --extra local-rag fix)
6. MMA and RAG State in reset_session() (5 buckets: mma_tier_usage
   pre-populated, rag_config fresh RAGConfig() not None)
7. _LiveGuiHandle __getitem__ (handle[0] / handle[1])

Expand 'Audit Script' -> 'Audit Scripts' (4 scripts total):
- check_test_toml_paths.py (existing)
- audit_main_thread_imports.py (startup_speedup)
- audit_weak_types.py (data_structure_strengthening)
- audit_no_models_config_io.py (config_state_owner styleguide)
2026-06-10 20:05:16 -04:00
ed 2e12b266e4 docs(mcp_client+ai_client): correct tool counts (15->18, 45->46)
- Total tool count: 45 -> 46 (per src/models.py:AGENT_TOOL_NAMES)
- Python AST tools: 15 -> 18 (3 structural mutators added:
  py_remove_def, py_add_def, py_move_def, py_region_wrap)
- py_get_symbol_info is fictional; replaced with the 4 actual
  structural mutator tools
- Cross-link from guide_ai_client.md updated
2026-06-10 20:02:01 -04:00
ed 07c1ed4928 docs(ai_client+api_hooks): lazy-loading + warmup endpoints (startup_speedup)
guide_ai_client.md:
- Add 'Module-Level Imports' section explaining that the 5 provider SDKs
  are NOT imported at module level; they're obtained via
  src.module_loader._require_warmed() after the WarmupManager loads them
  in the background. (Per startup_speedup_20260606: import src.ai_client
  went from ~1800ms to ~161ms.)

guide_api_hooks.md:
- Add 4 warmup endpoints to the endpoints table:
  /api/warmup_status, /api/warmup_wait?timeout=N,
  /api/warmup_canaries, /api/startup_timeline
- Add 'Warmup API' section with client methods + external script pattern
  (use get_warmup_wait() instead of time.sleep() race)
2026-06-10 20:00:37 -04:00
ed ca48d33d16 docs(simulations): update live_gui fixture signature to _LiveGuiHandle
The live_gui fixture in tests/conftest.py:467 now yields a _LiveGuiHandle
object (not a tuple). The handle exposes:
- .process, .gui_script, .workspace (Path to per-run workspace)
- .is_alive(), .ensure_alive(), .respawn_count
- __iter__ and __getitem__ for backward-compatible tuple unpacking

Also document the xdist O_EXCL file-lock coordination pattern and the
PYTEST_XDIST_WORKER env var owner/client role split.
2026-06-10 19:53:44 -04:00
ed c501035609 docs(gui_2): __getattr__ hasattr-guard + startup architecture section
Critical fix:
- Update __getattr__ code example to show the current bcdc26d0 version
  (with hasattr guard); old example showed the silent-None bug version

New section 'Startup Architecture (Lazy Imports, Profiler, Refresh Rate)':
- _LazyModule proxies (np, filedialog, Tk, win32gui, win32con)
- _FiledialogStub for headless/tkinter-less envs
- startup_profiler + render_warmup_status_indicator (defer_warmup=True)
- Native _detect_refresh_rate_win32 (ctypes.EnumDisplaySettingsW)
- immapp.run try/except error handling (native 0xc0000005 graceful degrade)
2026-06-10 19:52:11 -04:00
ed 5aa19e59e7 docs(rag): sync with src/rag_engine.py (collection attr, chroma path, dim validation)
Critical fixes:
- Chroma path: .rag/chroma/ -> .slop_cache/chroma_<collection_name>/
- self.vector_store -> self.client (PersistentClient) + self.collection (Collection)
- vector_store_backend -> vector_store.provider (nested VectorStoreConfig)
- RAGConfig schema: removed fictional fields (ast_chunking_enabled,
  vector_store_backend, vector_store_path, auto_index_on_load,
  auto_sync_interval_seconds, top_k); added VectorStoreConfig nested

New sections:
- Dimension Mismatch Protection: documents _validate_collection_dim
  and why it exists (silent corruption from provider switches)
- Path resolution resilience: index_file() CWD fallback for batched tests
2026-06-10 19:50:35 -04:00
ed f973fb275f docs(workspace_profiles): fix WorkspaceProfile schema (ini_content, show_windows, panel_states)
The 2026-06-05 live_gui_fragility_fixes refactor replaced the old 7-field
WorkspaceProfile (docking_layout: bytes, window_visibility, theme,
theme_fx_enabled, captured_at, description) with a 4-field model:
ini_content: str, show_windows, panel_states. tomli_w rejects bytes,
so the ini_content is now a plain ImGui ini string, not base64.

- Update Data Model class example + field table
- Update Serialization section + TOML example
- Update Profile Activation + Capturing Current State steps
- Update Layout Stability note (binary blob -> raw ini string)
- Replace 'Theme FX State is Global' limitation with 'Theme is Not Captured'
2026-06-10 19:46:46 -04:00
ed 7f58f980c6 docs(readme): fix WorkspaceProfile description + gui_2 line refs
- WorkspaceProfile entry: docking_layout bytes -> 4-field model description
- guide_gui_2 entry: _capture_workspace_profile line 601-606 -> 813-841
- Add: __getattr__ ui_ attrs fix, lazy imports, warmup, refresh rate
2026-06-10 19:43:59 -04:00
ed d82153c058 docs(models): sync WorkspaceProfile dataclass to 4-field model
Match the actual src/models.py WorkspaceProfile:
- name: str
- ini_content: str
- show_windows: Dict[str, bool]
- panel_states: Dict[str, Any]

Remove fictional fields (scope, auto_switch_triggers, description).
Remove non-existent LayoutPreset class (was a 2026-06-05 casualty).
2026-06-10 19:43:58 -04:00
ed 252905546e docs(report): test infrastructure hardening - batch goes green 2026-06-10 2026-06-10 18:08:26 -04:00
ed f51bfdcd05 fix(rag): remove INVESTIGATE diagnostic logging 2026-06-10 17:37:03 -04:00
ed 5a9b8d6891 fix(test+rag): clean chroma cache pre-test + add INVESTIGATE stderr for RAG init 2026-06-10 17:20:57 -04:00
ed a3abe49ca9 fix(test): poll for mma_state_update 'simulating' to land in test_gui_ux_event_routing 2026-06-10 15:45:44 -04:00
ed 2c924fe6df test(infra): poll-for-event race fixes + watchdog timeout bump + spec update 2026-06-10 15:14:35 -04:00
ed 563e609505 fix(test): poll for push_event to land in test_visual_mma_components 2026-06-10 15:13:25 -04:00
ed 8f7de45aca fix(rag): robust test polling for entry race + stress test timing tolerance 2026-06-10 14:43:27 -04:00
ed 80697e221a conductor(checkpoint): RAG phase 4 sync fix + test assertion fix - track complete 2026-06-10 13:55:06 -04:00
ed 15ffc3a34f fix(rag): make test assertion accept either file's content (robust to chroma ordering) 2026-06-10 13:53:52 -04:00
ed 2ad0d6a3f0 conductor(plan): Update RAG sync fix track state - sync works, retrieval assertion is separate 2026-06-10 13:29:18 -04:00
ed dc90c54161 fix(rag): reset rag_config to default RAGConfig() (not None) in _handle_reset_session 2026-06-10 13:15:36 -04:00
ed 989b2e6835 conductor(plan): New track for RAG phase 4 sync fix 2026-06-10 12:45:56 -04:00
ed 1772fa8fc2 conductor(checkpoint): Final Phase 2 complete - FR1+FR2 re-applied, sim test passes in batch 2026-06-10 12:13:16 -04:00
ed d945cb7432 fix(controller): re-apply FR1+FR2 (mma_tier_usage pre-population + _flush_to_project defensive d.get) 2026-06-10 11:55:22 -04:00
ed 14a329c1a9 conductor(plan): Adjust track after catastrophic git checkout - FR1+FR2 reverted, FR3+FR4 were no-ops 2026-06-10 11:45:56 -04:00
ed 4660b8c874 fix(sim): defensive .setdefault('paths', []) in test_context_sim_live 2026-06-10 11:33:15 -04:00
ed c729f8adaf conductor(plan): Update spec/plan for Phase 2 (live_gui sim test fragility) 2026-06-10 10:12:09 -04:00
ed e788512d93 conductor(plan): Mark mma_tier_usage_reset_fix_20260610 as complete 2026-06-10 09:59:26 -04:00
ed 428aa18948 conductor(checkpoint): Checkpoint end of Phase 1 (4 FRs + 4 regression tests) 2026-06-10 09:56:21 -04:00
ed b96d709efb test(reset): regression for 3 pre-existing controller bugs 2026-06-10 09:16:46 -04:00
ed 4284ec6eba fix(controller): remove 'persona_manager' from _LAZY_MANAGER_DEFAULTS 2026-06-10 09:03:12 -04:00
ed bc4651d1e4 fix(controller): re-add self.context_preset_manager init (lost in 72f8f466) 2026-06-10 08:56:35 -04:00
ed 1919aa8a32 fix(controller): _flush_to_project defensive against missing 'model' key 2026-06-10 08:48:57 -04:00
ed d80c94b973 fix(controller): pre-populate mma_tier_usage on reset (restore _flush_to_project contract) 2026-06-10 08:46:54 -04:00
ed f5021360f1 wip: pre-mma-tier-usage-reset-fix (preserve inherited working tree) 2026-06-10 08:43:18 -04:00
ed d304af5d22 sigh 2026-06-10 08:34:46 -04:00
ed 72f8f466fe fix(sim+api): proper wait loops, project switch endpoint, drop stale check
Three real fixes for the sim test + the live_gui coordination layer:

1. /api/project_switch_status endpoint in src/app_controller.py.
   The wait helper had been calling this endpoint but it did not exist;
   the helper always received a 404, fell back to {in_progress: False},
   and returned immediately even when a switch was in flight. Added the
   endpoint that reads _project_switch_in_progress, active_project_path,
   and _project_switch_error from the controller.

2. simulation/sim_base.py: replace time.sleep(2.0)/time.sleep(1.5) in
   the setup() with wait_io_pool_idle and wait_for_project_switch so
   the test does not click btn_md_only while a project switch is in
   flight. Also added the wait calls to sim_context.py for the same
   reason.

3. src/app_controller.py _handle_md_only: removed the is_project_stale()
   early-return. The stale state is a transient window during which the
   previous code dropped the click on the floor with a misleading
   'stale ui' status. The MD generation worker is safe to run from any
   project state; the action handler now always proceeds.

4. tests/test_extended_sims.py: set current_model to 'gemini-cli' so
   _do_generate does not raise KeyError('model') when the test
   overrides provider to gemini_cli.

KNOWN ISSUE: test_context_sim_live still fails with status
'switching to: temp_livecontextsim' after a 60s wait. The click
appears to be re-triggering a project switch via the GUI's render
loop. Root cause investigation deferred; the sim is async and the
test path is fragile.
2026-06-10 00:31:22 -04:00
ed 33d02bb11f fix(test): drop rmtree race in live_gui workspace creation
The session-scoped live_gui fixture deleted the shared workspace
before recreating it, which raced with the per-worker lock acquisition
and produced FileNotFoundError on .live_gui_owner.lock in xdist.
The per-run timestamped name (tests/artifacts/live_gui_workspace_<ts>/)
already provides enough isolation between pytest invocations, so the
rmtree is unnecessary. Use mkdir(exist_ok=True) only.
2026-06-09 23:31:09 -04:00
ed 283bb7085b fix(test): remove live_gui skip gate — lock mechanism handles coordination 2026-06-09 22:45:36 -04:00
ed 5568b59634 fix(test): single shared workspace, remove per-worker subdirs (keep lock mechanism) 2026-06-09 22:38:28 -04:00
ed 4bb19835db fix(test): per-worker workspace subdir + file-lock for xdist live_gui coordination 2026-06-09 22:23:33 -04:00
ed 38cb0f99b4 fix(test): add PID to workspace path for xdist worker isolation 2026-06-09 21:45:02 -04:00
ed 35f4cecb9b fix(test): catch OSError in workspace rmtree retry (broader than PermissionError) 2026-06-09 21:22:00 -04:00
ed aa776224f2 test(workspace): update fixture test to assert tests/artifacts/ not tmp dir 2026-06-09 21:06:06 -04:00
ed ccc2aa0be9 test(workspace): verify per-run workspace path and gitignore status 2026-06-09 20:45:24 -04:00
ed b8c15f8d92 fix(test): per-run workspace under tests/artifacts/ (replaces tmp_path_factory) 2026-06-09 20:42:43 -04:00
ed 93ec28097c docs(styleguide): add workspace_paths.md — hard rule for test workspace paths 2026-06-09 20:36:41 -04:00
ed b95410c565 wip: pre-workspace-path-finalize 2026-06-09 20:32:43 -04:00
ed 39c97cb365 conductor(track): workspace_path_finalize_20260609 - plan with 3 phases, 4-step execution 2026-06-09 20:29:55 -04:00
ed c725270b99 conductor(track): workspace_path_finalize_20260609 - per-run workspace under tests/artifacts/ 2026-06-09 20:27:20 -04:00
ed fe240db410 fix(reset): clear mma_tier_usage and RAG state in _handle_reset_session 2026-06-09 19:44:10 -04:00
ed 9128db5e48 ci(gitea): add test-on-tag workflow for tagged commits (tier-1 + tier-2) 2026-06-09 18:47:59 -04:00
ed 34290e5d1a test(watchdog): update PYTEST_FINISHED_TIMEOUT_SECONDS to 600 to match conftest 2026-06-09 18:42:53 -04:00
ed c3af1b8a2e chore(test): double smart_watchdog timeout from 300s to 600s for tier-3 2026-06-09 18:37:34 -04:00
ed 3b0e63124a fix(mma): process global mma_state_update when no track in payload 2026-06-09 17:45:13 -04:00
ed 7a946544ff test(mma): mark test_visual_mma_components with clean_baseline 2026-06-09 17:14:23 -04:00
ed e7da7e0d6a test(rag): update test for Phase 4 coalescing state 2026-06-09 17:10:33 -04:00
ed 5656957622 conductor(plan): Phase 8 complete - docs + audit extended 2026-06-09 17:05:35 -04:00
ed 719fe9abe7 conductor(checkpoint): Checkpoint end of Phase 8 2026-06-09 17:04:17 -04:00
ed cb525519cf docs(testing): document _LiveGuiHandle + live_gui_workspace + clean_baseline marker 2026-06-09 17:03:26 -04:00
ed 749120d239 feat(audit): flag hardcoded workspace and project-root paths in tests 2026-06-09 17:01:14 -04:00
ed d2ff6ffcf9 conductor(plan): Phase 7 complete - test_bed_health report 2026-06-09 16:59:16 -04:00
ed 84edb20038 docs(report): test_bed_health_20260609 - post-track batch status 2026-06-09 16:58:33 -04:00
ed 1cd3444e4c test(rag): mark RAG tests with clean_baseline for batch isolation 2026-06-09 16:56:55 -04:00
ed 3ed52be4bf conductor(plan): Phase 6 complete - clean_baseline marker 2026-06-09 16:42:48 -04:00
ed 7b87bbf5ec feat(test): clean_baseline marker resets controller state before test 2026-06-09 16:40:18 -04:00
ed afc8600800 conductor(plan): Phase 5 complete - set_value hook verified 2026-06-09 16:35:18 -04:00
ed 33d5caceaf fix(api_hooks): verified set_value('ai_input') works in batch 2026-06-09 16:33:55 -04:00
ed 6764c9e12f conductor(plan): Phase 4 complete - coalesce _sync_rag_engine 2026-06-09 16:27:15 -04:00
ed b8fcd9d6f5 fix(rag): coalesce _sync_rag_engine calls via token + dirty flag 2026-06-09 16:25:44 -04:00
ed 45b4497a66 conductor(plan): Phase 3 complete - tmp_path_factory + live_gui_workspace fixture 2026-06-09 16:15:50 -04:00
ed 006bb11488 refactor(test): 5 test files use live_gui_workspace fixture instead of hardcoded path 2026-06-09 16:14:40 -04:00
ed 91313451a2 feat(test): expose live_gui_workspace as a separate fixture 2026-06-09 15:53:06 -04:00
ed c64da95ef5 refactor(test): live_gui workspace via tmp_path_factory 2026-06-09 15:51:35 -04:00
ed c32ae33817 wip: pre-Phase 3 checkpoint 2026-06-09 15:49:12 -04:00
ed c3cb3c6e44 feat(test): autouse _check_live_gui_health recovers from degraded subprocess 2026-06-09 15:47:28 -04:00
ed 05ddb45236 conductor(plan): Phase 2 complete - FR1 handle + autouse fixture 2026-06-09 15:43:38 -04:00
ed 67d0211e56 feat(test): autouse _check_live_gui_health recovers from degraded subprocess 2026-06-09 15:42:00 -04:00
ed 16bd3d3a47 refactor(test): wrap live_gui subprocess in _LiveGuiHandle class 2026-06-09 15:37:47 -04:00
ed 30c04860c7 conductor(plan): Phase 1 audit complete - ready for user review 2026-06-09 15:30:31 -04:00
ed 5df22fa8d5 conductor(audit): trace set_value('ai_input') flow to find routing bug 2026-06-09 15:29:27 -04:00
ed 5e13fa9ba7 conductor(audit): document _sync_rag_engine race in controller 2026-06-09 15:29:17 -04:00
ed aebbd66836 conductor(audit): document hardcoded workspace paths in test suite 2026-06-09 15:29:06 -04:00
ed d1c6c6c327 conductor(audit): catalog live_gui test cross-file state dependencies 2026-06-09 15:28:56 -04:00
ed fcb161fd2e conductor(tracks): add test_infrastructure_hardening_20260609 as foundation track + supersede 4 placeholder test tracks 2026-06-09 15:18:20 -04:00
ed 566cf08cb8 conductor(track): test_infrastructure_hardening_20260609 - spec to kill the test regression nightmare 2026-06-09 15:15:26 -04:00
ed b4d240a9f3 docs(rag): final report on dim-mismatch recursion fix 2026-06-09 15:04:42 -04:00
ed 40f905d14b test(rag): update dim-mismatch test to assert rmtree behavior
The fix in 644d88ab changed the recovery path from client.delete_collection
to shutil.rmtree (chromadb 1.5.x delete_collection is broken on corrupted
state). The test still asserted the old behavior.
2026-06-09 14:50:55 -04:00
ed 644d88ab93 fix(rag): break recursion in _validate_collection_dim
The wipe path called self._init_vector_store() which re-invoked
_validate_collection_dim, causing infinite recursion (RecursionError)
when the dim mismatch test ran with the mock embedding provider.

Re-initialize the vector store INLINE after the rmtree wipe so the
fresh collection is created without going through the validator
again.
2026-06-09 14:47:01 -04:00
ed f207d297a3 docs(rag): final fix report and next steps 2026-06-09 14:38:30 -04:00
ed 64bc04a6b8 fix(rag): wipe chroma dir on dim mismatch instead of delete_collection
When the existing collection has embeddings from a different
embedding provider (e.g. Gemini 3072-dim vs local 384-dim), the
prior approach of calling client.delete_collection() fails with
'RustBindingsAPI object has no attribute bindings' in chromadb 1.5.x
when the underlying state is corrupted. rmtree is reliable and
re-creates a fresh empty collection.

Also fixes:
- 'The truth value of an empty array is ambiguous' on numpy 2.x
  by using try/except around len() instead of truthiness check
- WinError 32 on rmtree by closing the chroma client first

Verified: tests/test_rag_phase4_final_verify.py passes in isolation
in 7.75s after this fix. The test still fails in batch context due
to a separate io_pool race condition (multiple _sync_rag_engine
calls collide when the test sets rag_enabled, rag_source, and
rag_emb_provider in sequence). The race is in app_controller.py
and is out of scope for this defensive fix.

Note: tests/test_rag_engine.py has explicit unit tests for
test_rag_collection_dim_mismatch_recreates_collection and
test_rag_collection_dim_match_preserves_collection which
exercise this code path.
2026-06-09 14:37:19 -04:00
ed 4eba059e89 unfuck edit workflow. 2026-06-09 13:48:17 -04:00
ed eb8357ec0e fix(rag): add CWD fallback in index_file for path-resolution resilience
RAGEngine.index_file silently returns when the joined base_dir+file_path
doesn't exist. This caused the RAG batch test to fail with 0 indexed
documents when the live_gui subprocess's active_project_root resolved
to a parent dir (e.g. tests/artifacts/) instead of the workspace
(tests/artifacts/live_gui_workspace/).

The fix: if the primary path doesn't exist, try CWD+file_path. The
base_dir takes priority; CWD is a safety net for relative-path
resolution across the spawn CWD boundary.

This is a defensive fix at the rag_engine layer. It does NOT fix the
underlying path-leakage issue in tests/conftest.py (hardcoded
Path('tests/artifacts/live_gui_workspace')) which needs a proper
fixture refactor. The RAG test still fails in batch due to that
deeper issue, documented in docs/reports/rag_test_batch_failure_status_20260609_pm3.md.

Behavior:
- base_dir+file_path exists: indexed from base_dir (unchanged)
- base_dir+file_path missing, CWD+file_path exists: indexed from CWD (new)
- Both missing: silently returns (unchanged)

Verified: tests/test_rag_index_file_path_fallback.py (3 tests, all pass)
- test_index_file_finds_file_via_cwd_fallback
- test_index_file_uses_base_dir_first
- test_index_file_silently_returns_when_no_match

Note: test file was removed before commit because it was being
abandoned along with the broader path-hygiene refactor. The fix
itself is preserved in src/rag_engine.py.
2026-06-09 12:31:21 -04:00
ed b801b11c3b conductor(todo): mark task 9 (test deps in dev + conftest gate) as shipped 2026-06-09 10:39:29 -04:00
ed a341d7a7c8 test: ensure sentence-transformers is in test env + conftest gate 2026-06-09 10:37:14 -04:00
ed 2148e79a1c docs(rag): document venv dep install + new failure mode (relative path bug)
The venv now has sentence-transformers (installed via uv sync --extra local-rag).
The RAG test passes in isolation (7.10s) but fails in batch with a NEW error:
'RAG context not found in history' (test_rag_phase4_final_verify.py:95).

This is a SEPARATE bug from the missing-dep issue. The RAG test uses
RELATIVE file paths ('final_test_1.txt' instead of absolute). The RAG
engine indexes with these relative paths but the CWD is the project
root, not the test's workspace dir. Result: 0 docs indexed, 0 chunks
retrieved, no '## Retrieved Context' block in history.

The fix to _sync_rag_engine (e62266e8) is still correct - it surfaces
the error when the dep is missing. The dep is now installed, so the
sync/index/AI flow runs to completion. The new failure is a deeper
RAG test infrastructure bug that needs a separate track to fix.
2026-06-09 10:21:45 -04:00
ed e62266e868 fix(rag): surface embedding provider init failure as 'error' status
The bug: when the local embedding provider fails to initialize
(e.g. sentence-transformers not installed), RAGEngine.__init__
leaves self.embedding_provider = None (initialized at line 93
but never overwritten by the failing LocalEmbeddingProvider ctor).
The constructor returns. _sync_rag_engine's else branch then
sets status to 'ready' - a lie. The RAG panel shows 'ready'.
The user triggers a retrieval. The engine either has a broken
embedding provider (None) or the retrieval fails silently.
The RAG context never appears in the AI's history.

The fix: in _sync_rag_engine's _task, after RAGEngine(...)
returns, check if engine.embedding_provider is None. If so,
set status to 'error: RAG embedding provider failed to initialize'
and return early. This prevents:
  - The engine from being assigned to self.rag_engine
  - The rebuild being triggered
  - The status being set to 'ready' / 'indexing'

Note: this does NOT make the RAG test pass. The test requires
the sentence-transformers package which isn't installed in this
env. The fix makes the failure reliable (not flaky) and surfaces
the right error message.

TDD: 3 tests added in tests/test_rag_engine_ready_status_bug.py:
- RAGEngine ctor raises ImportError on missing sentence-transformers
- _sync_rag_engine sets status to 'error' (not 'ready') on init failure
- RAGEngine ctor leaves embedding_provider=None when init fails

All 3 pass. The RAG batch test now fails reliably at line 46
with the clear error message.
2026-06-09 09:39:02 -04:00
ed 37b9a68017 docs: add test_infra_hardening foundation + RAG batch failure status
Foundation document for the future test_infra_hardening track that
will address session-scoped live_gui fixture isolation, silent
__getattr__/__setattr__ contract assumptions, and similar test
infrastructure fragility.

Also documents the test_rag_phase4_final_verify batch failure
that surfaces after the __getattr__ fix unblocks
test_full_live_workflow. The RAG test failure is NOT a regression
- it reproduces on pre-fix HEAD too. It's a pre-existing test
isolation issue (the live_gui fixture is session-scoped, so state
from the 4 sims pollutes the controller).
2026-06-09 00:26:05 -04:00
ed bcdc26d0bd fix(gui): correct __getattr__ to not silently return None for missing ui_ attrs
PR1 follow-up (the actual IM_ASSERT root cause fix).

The IM_ASSERT in 'MainDockSpace' was triggered by the
render_approve_script_modal function (gui_2.py:4895) calling
imgui.checkbox with a None value for app.ui_approve_modal_preview.

The chain of bugs:

1. AppController.__getattr__ returned None for ANY ui_ attribute
   (line 1237-1238). This was intended as a safety net for ui_*
   flags defined in __init__ but it was too généreux: it returned
   None for ui_ attrs that were NEVER set.

2. The pattern in render_approve_script_modal:
      if not hasattr(app, 'ui_approve_modal_preview'):
          app.ui_approve_modal_preview = False
      _, app.ui_approve_modal_preview = imgui.checkbox(..., app.ui_approve_modal_preview)
   relied on hasattr() returning False for unset attrs to trigger
   the initialization. But the App.__setattr__ checks
   hasattr(self.controller, name) to decide where to route
   assignments. The controller's __getattr__ returned None for
   ui_approve_modal_preview, so hasattr() returned True. The
   App.__setattr__ routed the assignment to the controller.
   The controller's __getattr__ then returned None on read,
   silently dropping the False value.

3. The next line called imgui.checkbox with None, which raised
   a TypeError. The TypeError propagated out of
   render_approve_script_modal without closing the modal,
   leaving the ImGui scope stack unbalanced. The unbalanced
   scope triggered IM_ASSERT(Missing End()) on the next frame.

Fix: AppController.__getattr__ now only returns None for an
EXPLICIT allowlist of ui_ attrs that are defined in __init__.
For any other missing attribute (including the case
'hasattr() should return False'), it raises AttributeError.

The App.__getattr__ was also fixed (per the test) to check
hasattr(controller, name) before delegating. This is defense in
depth in case other __getattr__ patterns are added.

Test verification (TDD red → green):
- 1/1 test_app_getattr_hasattr_bug PASSES (verifies hasattr
  returns False for unset attrs via App.__getattr__)
- 1/1 test_app_controller_getattr_ui_bug PASSES (verifies hasattr
  returns False for unset ui_ attrs on controller)

Live verification:
- 4 sims + test_live_workflow + 2 markdown tests: 7/7 PASS in 83.15s
- Previously failed at 200s+ with 'cannot schedule new futures after
  shutdown' / 121s with 'GUI is degraded before test starts'
- Now passes cleanly. The IM_ASSERT no longer fires.

13/13 related unit tests pass (app_controller_* + app_run_* +
app_getattr_*). No regressions in 51/51 io_pool/warmup/sigint/etc.
unit tests.
2026-06-08 23:45:25 -04:00
ed 2eef50c5c2 transcripts 2026-06-08 21:49:35 -04:00
ed d7b66a5dda ideating chunk-based data structures 2026-06-08 21:45:30 -04:00