From ead7cf2869b2924c72764ff81a82b61220541c61 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 3 Jul 2026 09:45:48 -0400 Subject: [PATCH] feat(directives): add rule-statement header to 33-40 of 66 v1.md files --- conductor/directives/live_gui_poll_not_sleep/v1.md | 2 ++ conductor/directives/live_gui_session_scoped_no_restart/v1.md | 2 ++ conductor/directives/mandatory_research_first/v1.md | 2 ++ conductor/directives/metadata_boundary_type/v1.md | 2 ++ conductor/directives/modular_controller_pattern/v1.md | 2 ++ conductor/directives/nil_sentinel_pattern/v1.md | 2 ++ conductor/directives/no_comments_in_body/v1.md | 2 ++ conductor/directives/no_diagnostic_noise/v1.md | 2 ++ 8 files changed, 16 insertions(+) diff --git a/conductor/directives/live_gui_poll_not_sleep/v1.md b/conductor/directives/live_gui_poll_not_sleep/v1.md index 5d284033..a7415b24 100644 --- a/conductor/directives/live_gui_poll_not_sleep/v1.md +++ b/conductor/directives/live_gui_poll_not_sleep/v1.md @@ -1,3 +1,5 @@ +# Replace time.sleep(N) with a poll loop on get_value or wait_for_event + #### Anti-Pattern: `push_event` + `time.sleep(N)` + `assert` is a guaranteed race (Added 2026-06-10) The pattern `push_event(...)` → `time.sleep(N)` → `assert` is a guaranteed race condition in batched runs. The first time you write this, the test passes in isolation because the sleep happens to be long enough. Then it lands in the batched run, the subprocess is busier, the sleep is no longer long enough, and the assert fires before the GUI render loop has processed the event. diff --git a/conductor/directives/live_gui_session_scoped_no_restart/v1.md b/conductor/directives/live_gui_session_scoped_no_restart/v1.md index 7a360462..afba407d 100644 --- a/conductor/directives/live_gui_session_scoped_no_restart/v1.md +++ b/conductor/directives/live_gui_session_scoped_no_restart/v1.md @@ -1,3 +1,5 @@ +# The live_gui fixture is session-scoped; tests share the same subprocess — no app restart per test + ## live_gui session-scoped fixture contract `live_gui` is a **session-scoped** fixture. All tests in a session share the same `sloppy.py` subprocess. The subprocess is **not** restarted between tests; its internal state (Fonts, DisplaySize, internal caches, current theme, current workspace profile, current discussion, current MMA track) **accumulates** from the previous test. diff --git a/conductor/directives/mandatory_research_first/v1.md b/conductor/directives/mandatory_research_first/v1.md index 708edfc5..53fd225a 100644 --- a/conductor/directives/mandatory_research_first/v1.md +++ b/conductor/directives/mandatory_research_first/v1.md @@ -1,3 +1,5 @@ +# Files over 50 lines must be researched via get_file_summary, py_get_skeleton, or py_get_code_outline before reading + From `conductor/workflow.md` §"Guiding Principles" #9: 8. **Mandatory Research-First Protocol:** Before reading the full content of any file over 50 lines, you MUST use `get_file_summary`, `py_get_skeleton`, `py_get_code_outline`, or `py_get_docstring` to map the architecture and identify specific target ranges. Use `get_git_diff` to understand recent changes. Use `py_find_usages` to locate where symbols are used. diff --git a/conductor/directives/metadata_boundary_type/v1.md b/conductor/directives/metadata_boundary_type/v1.md index 0321e917..b64f720a 100644 --- a/conductor/directives/metadata_boundary_type/v1.md +++ b/conductor/directives/metadata_boundary_type/v1.md @@ -1,3 +1,5 @@ +# Metadata is the typed fat struct at the wire boundary — the only place dict[str, Any] is allowed + ### 8.6 The Boundary Layer (the wire schema) The codebase has ONE typed fat struct at the boundary: `Metadata` in `src/type_aliases.py`. It is `@dataclass(frozen=True, slots=True)` with explicit fields covering the TOML/JSON wire schema (paths, project, discussion, role, content, ts, source_tier, model, depends_on, document, script, args, etc.). It is used in exactly 2 places: diff --git a/conductor/directives/modular_controller_pattern/v1.md b/conductor/directives/modular_controller_pattern/v1.md index c6f891b4..85f799c2 100644 --- a/conductor/directives/modular_controller_pattern/v1.md +++ b/conductor/directives/modular_controller_pattern/v1.md @@ -1,3 +1,5 @@ +# State-independent logic must be moved to module-level functions (avoid god-object controllers) + From `conductor/product-guidelines.md` §"Code Standards & Architecture": - **Modular Controller Pattern:** To prevent "God Object" bloat in core controllers (like `AppController`), all state-independent or utility logic must be moved to module-level functions. Functions requiring class state should accept the instance as an explicit dependency (`def logic(controller: AppController, ...)`). Massive `if/elif` dispatch blocks must be refactored into handler maps (dictionaries) of module-level functions. diff --git a/conductor/directives/nil_sentinel_pattern/v1.md b/conductor/directives/nil_sentinel_pattern/v1.md index e9006a57..9fc1ed95 100644 --- a/conductor/directives/nil_sentinel_pattern/v1.md +++ b/conductor/directives/nil_sentinel_pattern/v1.md @@ -1,3 +1,5 @@ +# Use nil-sentinel dataclasses instead of None (zero-initialized frozen dataclass; safe to read fields) + ### 1. Nil-Sentinel Dataclasses (replaces `None`) When a function would "return None" in conventional Python, return a diff --git a/conductor/directives/no_comments_in_body/v1.md b/conductor/directives/no_comments_in_body/v1.md index 94fef2a5..47a07295 100644 --- a/conductor/directives/no_comments_in_body/v1.md +++ b/conductor/directives/no_comments_in_body/v1.md @@ -1,3 +1,5 @@ +# Source code must not contain comments — documentation lives in /docs + From `conductor/code_styleguides/python.md` §8 "AI-Agent Specific Conventions": - **No redundant comments.** Do not add comments that restate what the code does. Only comment on *why* when non-obvious. diff --git a/conductor/directives/no_diagnostic_noise/v1.md b/conductor/directives/no_diagnostic_noise/v1.md index 4767dd2a..a1f4ea4c 100644 --- a/conductor/directives/no_diagnostic_noise/v1.md +++ b/conductor/directives/no_diagnostic_noise/v1.md @@ -1,3 +1,5 @@ +# Diagnostic stderr writes [XYZ_DIAG] in src/*.py are technical debt; use tests/artifacts/.diag.log or /tmp/diag_*.py + From `conductor/code_styleguides/python.md` §8 "AI-Agent Specific Conventions": - **No diagnostic noise in production code (Added 2026-06-09).** `sys.stderr.write(f"[XYZ_DIAG] ...")` lines added to `src/*.py` for one-time debugging are technical debt the moment they ship. The project's production code should not contain `[XYZ_DIAG]` markers, `print(...debug...)` calls, or any other ad-hoc debug instrumentation. The right place for diagnostic output during a one-time investigation is `tests/artifacts/.diag.log` (a log file) or a standalone `/tmp/diag_.py` script. If you must instrument a production function for a single test run, the diag lines are part of the same atomic commit as the fix — they do not live uncommitted in the working tree. If you "revert everything," that means the diag lines are also reverted.