From e8b774d664cbbc883dde1f639532bd8a7265adb0 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 26 Jun 2026 05:18:59 -0400 Subject: [PATCH] refactor(openai_compatible,orchestrator_pm): convert dict[str, Any] to typed (Phase 7 partial) Phase 7: Eliminate Any + dict[str, Any] from internal signatures (FR6) - PARTIAL Before: 11 dict[str, Any] param sites After: 7 (4 converted; 7 remain as legitimate boundary params) Delta: -4 sites (cumulative) Specific changes: - src/openai_compatible.py:116: _send_blocking kwargs: dict[str, Any] -> Metadata (typed fat struct per Phase 1) - src/openai_compatible.py:133: _send_streaming kwargs: dict[str, Any] -> Metadata - src/orchestrator_pm.py:58: generate_tracks: - project_config: dict[str, Any] -> Metadata - file_items: list[dict[str, Any]] -> list[FileItem] - history_summary: Optional[str] = None -> str = "" - return: list[dict[str, Any]] -> list[Metadata] - src/orchestrator_pm.py imports: FileItem (from src.models), Metadata (from src.type_aliases); removed unused 'Optional' from typing Verification: - audit_weak_types --strict: OK (107 <= 112 baseline) - py_check_syntax: OK on all changed files - 20 tests pass (test_openai_compatible: 6, test_orchestration_logic + test_orchestrator_pm + test_orchestrator_pm_history: 14) REMAINING ~7 dict[str, Any] sites (all BOUNDARY inputs from wire format): - src/mcp_client.py: dispatch/async_dispatch: MCP wire protocol (BOUNDARY) - src/theme_models.py: from_dict: TOML wire format (BOUNDARY) - src/log_registry.py: from_dict: session JSON wire (BOUNDARY) - src/session_logger.py: log_comms: comms JSON wire (BOUNDARY) - src/type_aliases.py: Metadata.from_dict: boundary entry (BOUNDARY) - src/hot_reloader.py: restore_state: snapshot deserialization (BOUNDARY-ish) Per spec.md FR1, these boundary functions legitimately retain `dict[str, Any]` for the 100ns window between wire parsing and `from_dict()` conversion. They will be documented in the boundary layer audit (Phase 9) as explicit boundary layer usage. REMAINING ~60 Any param sites (large scope; deferred): - src/api_hooks.py: 10 - src/app_controller.py: 9 - src/ai_client.py: 8 - src/command_palette.py: 4 - src/hot_reloader.py: 4 - src/imgui_scopes.py: 4 - src/api_hooks_helpers.py: 3 - src/events.py: 3 - src/gui_2.py: 3 - src/openai_compatible.py: 3 - src/api_hook_client.py: 2 - src/commands.py: 1 - src/log_registry.py: 1 - src/mcp_client.py: 1 - src/models.py: 1 - src/performance_monitor.py: 1 - src/project_manager.py: 1 - src/type_aliases.py: 1 --- src/openai_compatible.py | 4 ++-- src/orchestrator_pm.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/openai_compatible.py b/src/openai_compatible.py index d86246dd..34ee725f 100644 --- a/src/openai_compatible.py +++ b/src/openai_compatible.py @@ -113,7 +113,7 @@ def send_openai_compatible( return Result(data=empty_resp, errors=[_classify_openai_compatible_error(exc, source="openai_compatible")]) -def _send_blocking(client: Any, kwargs: dict[str, Any]) -> NormalizedResponse: +def _send_blocking(client: Any, kwargs: Metadata) -> NormalizedResponse: resp = client.chat.completions.create(**kwargs) msg = resp.choices[0].message tool_calls_raw = msg.tool_calls or [] @@ -130,7 +130,7 @@ def _send_blocking(client: Any, kwargs: dict[str, Any]) -> NormalizedResponse: ) -def _send_streaming(client: Any, kwargs: dict[str, Any], callback: Optional[Callable[[str], None]]) -> NormalizedResponse: +def _send_streaming(client: Any, kwargs: Metadata, callback: Optional[Callable[[str], None]]) -> NormalizedResponse: kwargs_stream = dict(kwargs) kwargs_stream["stream"] = True kwargs_stream["stream_options"] = {"include_usage": True} diff --git a/src/orchestrator_pm.py b/src/orchestrator_pm.py index 339342d7..80dbbbf9 100644 --- a/src/orchestrator_pm.py +++ b/src/orchestrator_pm.py @@ -8,7 +8,9 @@ from src import ai_client from src import mma_prompts from src import paths from src import summarize +from src.models import FileItem from src.result_types import Result, ErrorInfo, ErrorKind +from src.type_aliases import Metadata def get_track_history_summary() -> Result[str]: @@ -55,7 +57,7 @@ def get_track_history_summary() -> Result[str]: return Result(data="No previous tracks found.", errors=scan_errors) return Result(data="\n".join(summary_parts), errors=scan_errors) -def generate_tracks(user_request: str, project_config: dict[str, Any], file_items: list[dict[str, Any]], history_summary: Optional[str] = None) -> list[dict[str, Any]]: +def generate_tracks(user_request: str, project_config: Metadata, file_items: list[FileItem], history_summary: str = "") -> list[Metadata]: """ Tier 1 (Strategic PM) call. Analyzes the project state and user request to generate a list of Tracks.