diff --git a/src/aggregate.py b/src/aggregate.py index 1c524a15..6754aee4 100644 --- a/src/aggregate.py +++ b/src/aggregate.py @@ -301,10 +301,7 @@ def build_file_items(base_dir: Path, files: list[str | Metadata]) -> list[Metada return items def _build_files_section_from_items(file_items: list[Metadata]) -> str: - """ - Build the files markdown section from pre-read file items (avoids double I/O). - [C: tests/test_aggregate_flags.py:test_auto_aggregate_skip, tests/test_context_composition_phase6.py:test_files_section_rendering, tests/test_tiered_context.py:test_build_files_section_with_dicts, tests/test_ui_summary_only_removal.py:test_aggregate_from_items_respects_auto_aggregate] - """ + """Build the files markdown section from pre-read file items (avoids double I/O).""" sections = [] file_items = file_items or [] for item in file_items: @@ -330,9 +327,6 @@ def _build_files_section_from_items(file_items: list[Metadata]) -> str: return "\n\n---\n\n".join(sections) def build_beads_section(base_dir: Path) -> str: - """ - [C: tests/test_aggregate_beads.py:test_build_beads_compaction] - """ client = beads_client.BeadsClient(base_dir) if not client.is_initialized(): return "" beads = client.list_beads() @@ -369,17 +363,11 @@ def build_markdown_from_items(file_items: list[Metadata], screenshot_base_dir: P return "\n\n---\n\n".join(parts) def build_markdown_no_history(file_items: list[Metadata], screenshot_base_dir: Path, screenshots: list[str], summary_only: bool = False, aggregation_strategy: str = "auto") -> str: - """ - Build markdown with only files + screenshots (no history). Used for stable caching. - [C: src/app_controller.py:AppController._do_generate, tests/test_history_management.py:test_aggregate_blacklist] - """ + """Build markdown with only files + screenshots (no history). Used for stable caching.""" return build_markdown_from_items(file_items, screenshot_base_dir, screenshots, history=[], summary_only=summary_only, aggregation_strategy=aggregation_strategy) def build_discussion_text(history: list[str]) -> str: - """ - Build just the discussion history section text. Returns empty string if no history. - [C: src/app_controller.py:AppController._do_generate, tests/test_history_management.py:test_aggregate_includes_segregated_history] - """ + """Build just the discussion history section text. Returns empty string if no history.""" if not history: return "" return "## Discussion History\n\n" + build_discussion_section(history) diff --git a/src/api_hook_client.py b/src/api_hook_client.py index 68417e73..e45c496f 100644 --- a/src/api_hook_client.py +++ b/src/api_hook_client.py @@ -56,17 +56,11 @@ from typing import Any class ApiHookClient: def __init__(self, base_url: str = "http://127.0.0.1:8999", api_key: str | None = None): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self.base_url = base_url.rstrip('/') self.api_key = api_key def _make_request(self, method: str, path: str, data: dict | None = None, timeout: float = 5.0) -> Metadata | None: - """ - Helper to make HTTP requests to the hook server. - [C: tests/test_api_hook_client.py:test_unsupported_method_error] - """ + """Helper to make HTTP requests to the hook server.""" url = f"{self.base_url}{path}" headers = {} if self.api_key: @@ -90,10 +84,7 @@ class ApiHookClient: return None def wait_for_server(self, timeout: int = 15) -> bool: - """ - Polls the health endpoint until the server responds or timeout occurs. - [C: simulation/live_walkthrough.py:main, simulation/ping_pong.py:main, simulation/sim_base.py:BaseSimulation.setup, tests/smoke_status_hook.py:test_status_hook, tests/test_ai_settings_layout.py:test_change_provider_via_hook, tests/test_ai_settings_layout.py:test_set_params_via_custom_callback, tests/test_auto_switch_sim.py:test_auto_switch_sim, tests/test_conductor_api_hook_integration.py:test_conductor_integrates_api_hook_client_for_verification, tests/test_deepseek_infra.py:test_gui_provider_list_via_hooks, tests/test_extended_sims.py:test_ai_settings_sim_live, tests/test_extended_sims.py:test_context_sim_live, tests/test_extended_sims.py:test_execution_sim_live, tests/test_extended_sims.py:test_tools_sim_live, tests/test_external_editor_gui.py:test_button_click_is_received, tests/test_external_editor_gui.py:test_patch_modal_shows_with_configured_editor, tests/test_external_editor_gui.py:test_vscode_launches_with_diff_view, tests/test_gui2_parity.py:test_gui2_click_hook_works, tests/test_gui2_parity.py:test_gui2_custom_callback_hook_works, tests/test_gui2_parity.py:test_gui2_set_value_hook_works, tests/test_gui_context_presets.py:test_gui_context_preset_save_load, tests/test_hooks.py:test_live_hook_server_responses, tests/test_live_workflow.py:test_full_live_workflow, tests/test_mma_concurrent_tracks_sim.py:test_mma_concurrent_tracks_execution, tests/test_mma_concurrent_tracks_stress_sim.py:test_mma_concurrent_tracks_stress, tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow, tests/test_patch_modal_gui.py:test_patch_apply_modal_workflow, tests/test_patch_modal_gui.py:test_patch_modal_appears_on_trigger, tests/test_phase6_simulation.py:test_ast_inspector_modal_opens, tests/test_phase6_simulation.py:test_batch_operations_shift_click, tests/test_phase6_simulation.py:test_slice_editor_add_remove, tests/test_preset_windows_layout.py:test_api_hook_under_load, tests/test_preset_windows_layout.py:test_preset_windows_opening, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_rag_visual_sim.py:test_rag_full_lifecycle_sim, tests/test_rag_visual_sim.py:test_rag_settings_persistence_sim, tests/test_selectable_ui.py:test_selectable_label_stability, tests/test_system_prompt_sim.py:test_system_prompt_sim, tests/test_tool_management_layout.py:test_tool_management_gettable_fields, tests/test_tool_management_layout.py:test_tool_management_state_updates, tests/test_ui_cache_controls_sim.py:test_ui_cache_controls, tests/test_undo_redo_sim.py:test_undo_redo_context_mutation, tests/test_undo_redo_sim.py:test_undo_redo_discussion_mutation, tests/test_undo_redo_sim.py:test_undo_redo_lifecycle, tests/test_visual_mma.py:test_visual_mma_components, tests/test_visual_orchestration.py:test_mma_epic_lifecycle, tests/test_visual_sim_gui_ux.py:test_gui_track_creation, tests/test_visual_sim_gui_ux.py:test_gui_ux_event_routing, tests/test_visual_sim_mma_v2.py:test_mma_complete_lifecycle, tests/test_workspace_profiles_sim.py:test_workspace_profiles_restoration, tests/test_z_negative_flows.py:test_mock_error_result, tests/test_z_negative_flows.py:test_mock_malformed_json, tests/test_z_negative_flows.py:test_mock_timeout] - """ + """Polls the health endpoint until the server responds or timeout occurs.""" start = time.time() while time.time() - start < timeout: status = self.get_status() @@ -103,10 +94,7 @@ class ApiHookClient: return False def get_status(self) -> Metadata: - """ - Checks the health of the hook server. - [C: tests/test_api_hook_client.py:test_get_status_success, tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation, tests/test_hooks.py:test_live_hook_server_responses, tests/test_mma_concurrent_tracks_stress_sim.py:test_mma_concurrent_tracks_stress, tests/test_phase6_simulation.py:test_ast_inspector_modal_opens, tests/test_phase6_simulation.py:test_batch_operations_shift_click, tests/test_phase6_simulation.py:test_slice_editor_add_remove, tests/test_preset_windows_layout.py:make_request, tests/test_preset_windows_layout.py:test_preset_windows_opening, tests/test_ui_cache_controls_sim.py:test_ui_cache_controls] - """ + """Checks the health of the hook server.""" res = self._make_request('GET', '/status') if res is None: # For backward compatibility with tests expecting ConnectionError @@ -115,10 +103,7 @@ class ApiHookClient: return res def post_session(self, session_entries: list[dict]) -> Metadata: - """ - Updates the session history. - [C: tests/test_gui_stress_performance.py:test_comms_volume_stress_performance, tests/test_live_workflow.py:test_full_live_workflow] - """ + """Updates the session history.""" return self._make_request('POST', '/api/session', data={"session": {"entries": session_entries}}) or {} def get_events(self) -> list[Metadata]: @@ -127,16 +112,10 @@ class ApiHookClient: return res.get("events", []) if res else [] def clear_events(self) -> list[Metadata]: - """ - Retrieves and clears the event queue. - [C: simulation/sim_base.py:BaseSimulation.setup] - """ + """Retrieves and clears the event queue.""" return self.get_events() def wait_for_event(self, event_type: str, timeout: int = 5) -> Metadata | None: - """ - [C: simulation/sim_base.py:BaseSimulation.wait_for_event, simulation/sim_execution.py:ExecutionSimulation.run, tests/test_z_negative_flows.py:test_mock_error_result, tests/test_z_negative_flows.py:test_mock_malformed_json, tests/test_z_negative_flows.py:test_mock_timeout] - """ start = time.time() while time.time() - start < timeout: events = self.get_events() @@ -147,33 +126,21 @@ class ApiHookClient: return None def post_gui(self, payload: dict) -> Metadata: - """ - Pushes an event to the GUI's AsyncEventQueue via the /api/gui endpoint. - [C: tests/test_ai_settings_layout.py:test_set_params_via_custom_callback, tests/test_api_hook_client.py:test_post_gui_success, tests/test_gui2_parity.py:test_gui2_custom_callback_hook_works, tests/test_gui2_parity.py:test_gui2_set_value_hook_works] - """ + """Pushes an event to the GUI's AsyncEventQueue via the /api/gui endpoint.""" return self._make_request('POST', '/api/gui', data=payload) or {} def push_event(self, action: str, payload: dict) -> Metadata: - """ - Convenience to push a GUI task. - [C: tests/test_auto_switch_sim.py:test_auto_switch_sim, tests/test_auto_switch_sim.py:trigger_tier, tests/test_external_editor_gui.py:test_button_click_is_received, tests/test_external_editor_gui.py:test_patch_modal_shows_with_configured_editor, tests/test_external_editor_gui.py:test_vscode_launches_with_diff_view, tests/test_gui_context_presets.py:test_gui_context_preset_save_load, tests/test_gui_text_viewer.py:test_text_viewer_state_update, tests/test_patch_modal_gui.py:test_patch_apply_modal_workflow, tests/test_patch_modal_gui.py:test_patch_modal_appears_on_trigger, tests/test_preset_windows_layout.py:test_preset_windows_opening, tests/test_saved_presets_sim.py:test_preset_manager_modal, tests/test_saved_presets_sim.py:test_preset_switching, tests/test_tool_management_layout.py:test_tool_management_state_updates, tests/test_tool_presets_sim.py:test_tool_preset_switching, tests/test_visual_mma.py:test_visual_mma_components, tests/test_visual_sim_gui_ux.py:test_gui_track_creation, tests/test_visual_sim_gui_ux.py:test_gui_ux_event_routing, tests/test_workspace_profiles_sim.py:test_workspace_profiles_restoration, tests/test_z_negative_flows.py:test_mock_error_result, tests/test_z_negative_flows.py:test_mock_malformed_json, tests/test_z_negative_flows.py:test_mock_timeout] - """ + """Convenience to push a GUI task.""" return self.post_gui({"action": action, **payload}) #region: Data def get_gui_state(self) -> Metadata: - """ - Returns the full GUI state available via the hook API. - [C: tests/test_ai_settings_layout.py:test_change_provider_via_hook, tests/test_ai_settings_layout.py:test_set_params_via_custom_callback, tests/test_conductor_api_hook_integration.py:simulate_conductor_phase_completion, tests/test_external_editor_gui.py:test_button_click_is_received, tests/test_external_editor_gui.py:test_patch_modal_shows_with_configured_editor, tests/test_external_editor_gui.py:test_vscode_launches_with_diff_view, tests/test_gui_text_viewer.py:test_text_viewer_state_update, tests/test_hooks.py:test_live_hook_server_responses, tests/test_live_gui_integration_v2.py:test_api_gui_state_live, tests/test_live_workflow.py:test_full_live_workflow, tests/test_live_workflow.py:wait_for_value, tests/test_patch_modal_gui.py:test_patch_apply_modal_workflow, tests/test_patch_modal_gui.py:test_patch_modal_appears_on_trigger, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_saved_presets_sim.py:test_preset_manager_modal, tests/test_saved_presets_sim.py:test_preset_switching, tests/test_task_dag_popout_sim.py:test_task_dag_popout, tests/test_tool_management_layout.py:test_tool_management_gettable_fields, tests/test_tool_management_layout.py:test_tool_management_state_updates, tests/test_tool_presets_sim.py:test_tool_preset_switching, tests/test_usage_analytics_popout_sim.py:test_usage_analytics_popout, tests/test_visual_mma.py:test_visual_mma_components] - """ + """Returns the full GUI state available via the hook API.""" return self._make_request('GET', '/api/gui/state') or {} def get_value(self, item: str) -> Any: - """ - Gets the value of a GUI item via its mapped field. - [C: simulation/sim_ai_settings.py:AISettingsSimulation.run, simulation/sim_base.py:BaseSimulation.get_value, simulation/sim_base.py:BaseSimulation.setup, simulation/sim_base.py:BaseSimulation.wait_for_element, simulation/sim_context.py:ContextSimulation.run, simulation/sim_execution.py:ExecutionSimulation.run, simulation/workflow_sim.py:WorkflowSimulator.run_discussion_turn_async, simulation/workflow_sim.py:WorkflowSimulator.wait_for_ai_response, tests/smoke_status_hook.py:test_status_hook, tests/smoke_status_hook.py:wait_for_value, tests/test_auto_switch_sim.py:test_auto_switch_sim, tests/test_deepseek_infra.py:test_gui_provider_list_via_hooks, tests/test_extended_sims.py:test_ai_settings_sim_live, tests/test_gui2_parity.py:test_gui2_click_hook_works, tests/test_gui2_parity.py:test_gui2_set_value_hook_works, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_rag_visual_sim.py:test_rag_full_lifecycle_sim, tests/test_rag_visual_sim.py:test_rag_settings_persistence_sim, tests/test_selectable_ui.py:test_selectable_label_stability, tests/test_system_prompt_sim.py:test_system_prompt_sim, tests/test_undo_redo_sim.py:test_undo_redo_context_mutation, tests/test_undo_redo_sim.py:test_undo_redo_discussion_mutation, tests/test_undo_redo_sim.py:test_undo_redo_lifecycle, tests/test_workspace_profiles_sim.py:test_workspace_profiles_restoration] - """ + """Gets the value of a GUI item via its mapped field.""" # Dict-key bracket notation: e.g. 'show_windows["Project Settings"]' if "[" in item and item.endswith("]"): dict_name, _, key_part = item.partition("[") @@ -202,18 +169,12 @@ class ApiHookClient: return None def get_text_value(self, item_tag: str) -> str | None: - """ - Wraps get_value and returns its string representation, or None. - [C: tests/test_api_hook_client.py:test_get_text_value] - """ + """Wraps get_value and returns its string representation, or None.""" val = self.get_value(item_tag) return str(val) if val is not None else None def set_value(self, item: str, value: Any) -> Metadata: - """ - Sets the value of a GUI widget. - [C: simulation/live_walkthrough.py:main, simulation/ping_pong.py:main, simulation/sim_ai_settings.py:AISettingsSimulation.run, simulation/sim_base.py:BaseSimulation.setup, simulation/workflow_sim.py:WorkflowSimulator.create_discussion, simulation/workflow_sim.py:WorkflowSimulator.run_discussion_turn_async, simulation/workflow_sim.py:WorkflowSimulator.setup_new_project, simulation/workflow_sim.py:WorkflowSimulator.truncate_history, tests/smoke_status_hook.py:test_status_hook, tests/test_ai_settings_layout.py:test_change_provider_via_hook, tests/test_auto_switch_sim.py:test_auto_switch_sim, tests/test_deepseek_infra.py:test_gui_provider_list_via_hooks, tests/test_extended_sims.py:test_ai_settings_sim_live, tests/test_extended_sims.py:test_context_sim_live, tests/test_extended_sims.py:test_execution_sim_live, tests/test_extended_sims.py:test_tools_sim_live, tests/test_gui2_parity.py:test_gui2_click_hook_works, tests/test_gui2_performance.py:test_performance_benchmarking, tests/test_live_gui_integration_v2.py:test_api_gui_state_live, tests/test_live_workflow.py:test_full_live_workflow, tests/test_mma_concurrent_tracks_sim.py:test_mma_concurrent_tracks_execution, tests/test_mma_concurrent_tracks_stress_sim.py:test_mma_concurrent_tracks_stress, tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_rag_visual_sim.py:test_rag_full_lifecycle_sim, tests/test_rag_visual_sim.py:test_rag_settings_persistence_sim, tests/test_saved_presets_sim.py:test_preset_manager_modal, tests/test_selectable_ui.py:test_selectable_label_stability, tests/test_system_prompt_sim.py:test_system_prompt_sim, tests/test_task_dag_popout_sim.py:test_task_dag_popout, tests/test_tool_presets_sim.py:test_tool_preset_switching, tests/test_undo_redo_sim.py:test_undo_redo_context_mutation, tests/test_undo_redo_sim.py:test_undo_redo_discussion_mutation, tests/test_undo_redo_sim.py:test_undo_redo_lifecycle, tests/test_usage_analytics_popout_sim.py:test_usage_analytics_popout, tests/test_visual_mma.py:test_visual_mma_components, tests/test_visual_orchestration.py:test_mma_epic_lifecycle, tests/test_visual_sim_mma_v2.py:test_mma_complete_lifecycle, tests/test_workspace_profiles_sim.py:test_workspace_profiles_restoration, tests/test_z_negative_flows.py:test_mock_error_result, tests/test_z_negative_flows.py:test_mock_malformed_json, tests/test_z_negative_flows.py:test_mock_timeout] - """ + """Sets the value of a GUI widget.""" return self.post_gui({"action": "set_value", "item": item, "value": value}) #endregion: Data @@ -221,31 +182,21 @@ class ApiHookClient: #region: Input def click(self, item: str, user_data: Any = None) -> Metadata: - """ - Simulates a button click. - [C: simulation/live_walkthrough.py:main, simulation/ping_pong.py:main, simulation/sim_base.py:BaseSimulation.setup, simulation/sim_context.py:ContextSimulation.run, simulation/sim_execution.py:ExecutionSimulation.run, simulation/workflow_sim.py:WorkflowSimulator.create_discussion, simulation/workflow_sim.py:WorkflowSimulator.load_prior_log, simulation/workflow_sim.py:WorkflowSimulator.run_discussion_turn_async, simulation/workflow_sim.py:WorkflowSimulator.setup_new_project, simulation/workflow_sim.py:WorkflowSimulator.truncate_history, simulation/workflow_sim.py:WorkflowSimulator.wait_for_ai_response, tests/test_external_editor_gui.py:test_button_click_is_received, tests/test_external_editor_gui.py:test_vscode_launches_with_diff_view, tests/test_gui2_parity.py:test_gui2_click_hook_works, tests/test_gui_text_viewer.py:test_text_viewer_state_update, tests/test_live_workflow.py:test_full_live_workflow, tests/test_mma_concurrent_tracks_sim.py:test_mma_concurrent_tracks_execution, tests/test_mma_concurrent_tracks_stress_sim.py:test_mma_concurrent_tracks_stress, tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_rag_visual_sim.py:test_rag_full_lifecycle_sim, tests/test_saved_presets_sim.py:test_preset_manager_modal, tests/test_saved_presets_sim.py:test_preset_switching, tests/test_system_prompt_sim.py:test_system_prompt_sim, tests/test_ui_cache_controls_sim.py:test_ui_cache_controls, tests/test_undo_redo_sim.py:test_undo_redo_context_mutation, tests/test_undo_redo_sim.py:test_undo_redo_discussion_mutation, tests/test_undo_redo_sim.py:test_undo_redo_lifecycle, tests/test_visual_mma.py:test_visual_mma_components, tests/test_visual_orchestration.py:test_mma_epic_lifecycle, tests/test_visual_sim_gui_ux.py:test_gui_track_creation, tests/test_visual_sim_gui_ux.py:test_gui_ux_event_routing, tests/test_visual_sim_mma_v2.py:_drain_approvals, tests/test_visual_sim_mma_v2.py:test_mma_complete_lifecycle, tests/test_z_negative_flows.py:test_mock_error_result, tests/test_z_negative_flows.py:test_mock_malformed_json, tests/test_z_negative_flows.py:test_mock_timeout] - """ + """Simulates a button click.""" return self.post_gui({"action": "click", "item": item, "user_data": user_data}) def drag(self, src_item: str, dst_item: str) -> Metadata: - """ - Simulates a drag and drop operation. - [C: tests/test_api_hook_client.py:test_drag_success] - """ + """Simulates a drag and drop operation.""" return self.push_event("drag", {"src_item": src_item, "dst_item": dst_item}) def right_click(self, item: str) -> Metadata: - """ - Simulates a right-click on an item. - [C: tests/test_api_hook_client.py:test_right_click_success] - """ + """Simulates a right-click on an item.""" return self.push_event("right_click", {"item": item}) def request_confirmation(self, tool_name: str, args: dict) -> bool | None: """ Pushes a manual confirmation request and waits for response. Blocks for up to 60 seconds. - [C: tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation, tests/test_sync_hooks.py:test_api_ask_client_error, tests/test_sync_hooks.py:test_api_ask_client_method, tests/test_sync_hooks.py:test_api_ask_client_rejection] """ # Long timeout as this waits for human input (60 seconds) res = self._make_request('POST', '/api/ask', @@ -254,17 +205,11 @@ class ApiHookClient: return res.get('response') if res else None def select_list_item(self, item: str, value: str) -> Metadata: - """ - Selects an item in a listbox or combo. - [C: simulation/workflow_sim.py:WorkflowSimulator.create_discussion, simulation/workflow_sim.py:WorkflowSimulator.switch_discussion, tests/test_api_hook_extensions.py:test_select_list_item_integration, tests/test_live_workflow.py:test_full_live_workflow] - """ + """Selects an item in a listbox or combo.""" return self.set_value(item, value) def select_tab(self, item: str, value: str) -> Metadata: - """ - Selects a specific tab in a tab bar. - [C: simulation/live_walkthrough.py:main, tests/test_api_hook_extensions.py:test_select_tab_integration] - """ + """Selects a specific tab in a tab bar.""" return self.set_value(item, value) #endregion: Input @@ -279,17 +224,11 @@ class ApiHookClient: }) or {} def apply_patch(self) -> Metadata: - """ - Applies the pending patch. - [C: tests/test_patch_modal.py:test_apply_callback] - """ + """Applies the pending patch.""" return self._make_request('POST', '/api/patch/apply') or {} def reject_patch(self) -> Metadata: - """ - Rejects the pending patch. - [C: tests/test_patch_modal.py:test_reject_callback, tests/test_patch_modal.py:test_reject_patch] - """ + """Rejects the pending patch.""" return self._make_request('POST', '/api/patch/reject') or {} def get_patch_status(self) -> Metadata: @@ -301,32 +240,20 @@ class ApiHookClient: #region: Diagnostics def get_indicator_state(self, item_tag: str) -> dict[str, bool]: - """ - Returns the visibility/active state of a status indicator. - [C: simulation/live_walkthrough.py:main, tests/test_api_hook_extensions.py:test_get_indicator_state_integration, tests/test_live_workflow.py:test_full_live_workflow] - """ + """Returns the visibility/active state of a status indicator.""" val = self.get_value(item_tag) return {"shown": bool(val)} def get_gui_diagnostics(self) -> Metadata: - """ - Retrieves performance and diagnostic metrics. - [C: tests/test_api_hook_client.py:test_get_performance_success, tests/test_hooks.py:test_live_hook_server_responses, tests/test_selectable_ui.py:test_selectable_label_stability, tests/test_visual_sim_gui_ux.py:test_gui_ux_event_routing] - """ + """Retrieves performance and diagnostic metrics.""" return self._make_request('GET', '/api/gui/diagnostics') or {} def get_performance(self) -> Metadata: - """ - Retrieves performance metrics from the dedicated endpoint. - [C: tests/test_gui2_performance.py:test_performance_benchmarking, tests/test_gui_performance_requirements.py:test_idle_performance_requirements, tests/test_gui_stress_performance.py:test_comms_volume_stress_performance, tests/test_selectable_ui.py:test_selectable_label_stability] - """ + """Retrieves performance metrics from the dedicated endpoint.""" return self._make_request('GET', '/api/performance') or {} def get_warmup_status(self) -> Metadata: - """ - Returns the current warmup status: {pending, completed, failed}. - [C: tests/test_api_hooks_warmup.py:test_get_warmup_status_calls_correct_endpoint, tests/test_api_hooks_warmup.py:test_get_warmup_status_handles_empty_response, tests/test_api_hooks_warmup.py:test_live_warmup_status_endpoint] - """ + """Returns the current warmup status: {pending, completed, failed}.""" return self._make_request('GET', '/api/warmup_status') or {} def get_warmup_wait(self, timeout: float = 30.0) -> Metadata: @@ -335,7 +262,6 @@ class ApiHookClient: complete, then returns the final status. Useful for external clients that need to wait until the system is fully ready before issuing AI requests. - [C: tests/test_api_hooks_warmup.py:test_get_warmup_wait_passes_timeout_as_query_string, tests/test_api_hooks_warmup.py:test_get_warmup_wait_uses_default_timeout_when_unspecified, tests/test_api_hooks_warmup.py:test_get_warmup_wait_handles_empty_response, tests/test_api_hooks_warmup.py:test_live_warmup_wait_endpoint_completes] """ return self._make_request('GET', f'/api/warmup_wait?timeout={timeout}') or {} @@ -345,7 +271,6 @@ class ApiHookClient: canary_id, module, thread_name, thread_id, submit_ts, start_ts, end_ts, elapsed_ms, status, error. Used for debugging which worker thread loaded which module and how long it took. - [C: tests/test_api_hooks_warmup.py:test_get_warmup_canaries_in_live_gui] """ result = self._make_request('GET', '/api/warmup_canaries') or {} return result.get("canaries", []) if isinstance(result, dict) else [] @@ -356,7 +281,6 @@ class ApiHookClient: first_frame_ts, warmup_ms, first_frame_after_init_ms, first_frame_after_warmup_ms. Lets external clients answer 'did the warmup block the first frame?'. - [C: tests/test_api_hooks_warmup.py:test_live_startup_timeline_endpoint] """ return self._make_request('GET', '/api/startup_timeline') or {} @@ -365,10 +289,7 @@ class ApiHookClient: #region: Project def get_project(self) -> Metadata: - """ - Retrieves the current project state. - [C: simulation/sim_context.py:ContextSimulation.run, tests/test_api_hook_client.py:test_get_project_success, tests/test_gui_context_presets.py:test_gui_context_preset_save_load, tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation, tests/test_hooks.py:test_live_hook_server_responses, tests/test_live_workflow.py:test_full_live_workflow] - """ + """Retrieves the current project state.""" return self._make_request('GET', '/api/project') or {} def get_project_switch_status(self) -> Metadata: @@ -379,7 +300,6 @@ class ApiHookClient: - error: string error message if the last switch failed; None on success Used by tests to wait deterministically for a project switch to complete instead of blind-polling the project state. - [C: tests/test_api_hooks_project_switch.py] """ result = self._make_request('GET', '/api/project_switch_status') if not result or not isinstance(result, dict): @@ -395,7 +315,6 @@ class ApiHookClient: - the controller reports an error during the switch - the path doesn't reach expected_path within the timeout - the controller is hung (in_progress stays True) - [C: tests/test_live_workflow.py:test_full_live_workflow] """ import os start = time.time() @@ -424,7 +343,6 @@ class ApiHookClient: - inflight: integer count of jobs submitted via submit_io Used by tests to wait for the pool to drain before submitting work when sharing a live_gui session with prior tests. - [C: tests/test_api_hook_client.py:test_get_io_pool_status_*] """ result = self._make_request('GET', '/api/io_pool_status') if not result or not isinstance(result, dict): @@ -440,7 +358,6 @@ class ApiHookClient: - degraded_reason: human-readable description of the failure (if any) - last_assert: full traceback of the last ImGui scope mismatch - io_pool_alive: True if submit_io is currently functional - [C: tests/test_api_hook_client_gui_health.py:test_get_gui_health_*] """ result = self._make_request('GET', '/api/gui_health') if not result or not isinstance(result, dict): @@ -457,7 +374,6 @@ class ApiHookClient: Blocks until the controller's io_pool reports idle=True or timeout. Returns True on idle, False on timeout. Use this to ensure prior tests' background work has completed before submitting new work. - [C: tests/test_live_workflow.py:test_full_live_workflow] """ start = time.time() while time.time() - start < timeout: @@ -471,10 +387,7 @@ class ApiHookClient: return last_status def post_project(self, project_data: dict) -> Metadata: - """ - Updates the current project configuration. - [C: simulation/sim_context.py:ContextSimulation.run] - """ + """Updates the current project configuration.""" return self._make_request('POST', '/api/project', data=project_data) or {} #endregion: Project @@ -482,17 +395,11 @@ class ApiHookClient: #region: Context def inject_context(self, data: dict) -> dict: - """ - Injects custom file context into the application. - [C: tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation] - """ + """Injects custom file context into the application.""" return self._make_request('POST', '/api/context/inject', data=data) or {} def get_context_state(self) -> Metadata: - """ - Retrieves the current file and screenshot context state. - [C: tests/test_gui_context_presets.py:test_gui_context_preset_save_load] - """ + """Retrieves the current file and screenshot context state.""" return self._make_request('GET', '/api/context/state') or {} #endregion: Context @@ -500,17 +407,11 @@ class ApiHookClient: #region: Discussion def get_session(self) -> Metadata: - """ - Retrieves the current discussion session history. - [C: simulation/ping_pong.py:main, simulation/sim_context.py:ContextSimulation.run, simulation/sim_execution.py:ExecutionSimulation.run, simulation/sim_tools.py:ToolsSimulation.run, simulation/workflow_sim.py:WorkflowSimulator.run_discussion_turn_async, simulation/workflow_sim.py:WorkflowSimulator.wait_for_ai_response, tests/test_api_hook_client.py:test_get_session_success, tests/test_gui_stress_performance.py:test_comms_volume_stress_performance, tests/test_live_workflow.py:test_full_live_workflow, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim] - """ + """Retrieves the current discussion session history.""" return self._make_request('GET', '/api/session') or {} def reset_session(self) -> None: - """ - Resets the current session via button click. - [C: src/app_controller.py:AppController._handle_reset_session, src/app_controller.py:AppController.current_model, src/app_controller.py:AppController.current_provider, src/app_controller.py:AppController.init_state, src/gui_2.py:App._render_provider_panel, src/gui_2.py:App._show_menus, src/multi_agent_conductor.py:run_worker_lifecycle, tests/conftest.py:live_gui, tests/conftest.py:reset_ai_client, tests/test_ai_cache_tracking.py:test_gemini_cache_tracking, tests/test_ai_client_cli.py:test_ai_client_send_gemini_cli, tests/test_api_events.py:test_send_emits_events_proper, tests/test_api_events.py:test_send_emits_tool_events, tests/test_deepseek_provider.py:test_deepseek_payload_verification, tests/test_deepseek_provider.py:test_deepseek_reasoner_payload_verification, tests/test_gemini_cli_integration.py:test_gemini_cli_full_integration, tests/test_gemini_cli_integration.py:test_gemini_cli_rejection_and_history, tests/test_gemini_metrics.py:test_get_gemini_cache_stats_with_mock_client, tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation, tests/test_mma_agent_focus_phase1.py:test_append_comms_has_source_tier_key, tests/test_mma_agent_focus_phase1.py:test_append_comms_source_tier_none_when_unset, tests/test_mma_agent_focus_phase1.py:test_append_comms_source_tier_set_when_current_tier_set, tests/test_mma_agent_focus_phase1.py:test_append_comms_source_tier_tier2, tests/test_session_logger_reset.py:test_reset_session, tests/test_token_usage.py:test_token_usage_tracking] - """ + """Resets the current session via button click.""" self.click("btn_reset") #endregion: Discussion @@ -530,32 +431,19 @@ class ApiHookClient: #region: MMA def get_node_status(self, node_id: str) -> Metadata: - """ - Retrieves status for a specific node in the MMA DAG. - [C: tests/test_api_hook_client.py:test_get_node_status] - """ + """Retrieves status for a specific node in the MMA DAG.""" return self._make_request('GET', f'/api/mma/node/{node_id}') or {} def get_mma_status(self) -> Metadata: - """ - Retrieves the dedicated MMA engine status. - [C: tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation, tests/test_live_workflow.py:test_full_live_workflow, tests/test_mma_concurrent_tracks_sim.py:_poll_mma_status, tests/test_mma_concurrent_tracks_sim.py:test_mma_concurrent_tracks_execution, tests/test_mma_concurrent_tracks_stress_sim.py:test_mma_concurrent_tracks_stress, tests/test_mma_step_mode_sim.py:_poll_mma_status, tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow, tests/test_visual_mma.py:test_visual_mma_components, tests/test_visual_orchestration.py:test_mma_epic_lifecycle, tests/test_visual_sim_gui_ux.py:test_gui_ux_event_routing, tests/test_visual_sim_mma_v2.py:_poll] - """ + """Retrieves the dedicated MMA engine status.""" return self._make_request('GET', '/api/gui/mma_status') or {} def get_mma_workers(self) -> Metadata: - """ - Retrieves status for all active MMA workers. - [C: tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation, tests/test_mma_concurrent_tracks_sim.py:test_mma_concurrent_tracks_execution, tests/test_mma_concurrent_tracks_stress_sim.py:_poll_mma_workers] - """ + """Retrieves status for all active MMA workers.""" return self._make_request('GET', '/api/mma/workers') or {} def spawn_mma_worker(self, data: dict) -> dict: - """ - - Spawns a new MMA worker with the provided configuration. - [C: tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation] - """ + """Spawns a new MMA worker with the provided configuration.""" return self._make_request('POST', '/api/mma/workers/spawn', data=data) or {} def kill_mma_worker(self, worker_id: str) -> dict: @@ -563,10 +451,7 @@ class ApiHookClient: return self._make_request('POST', '/api/mma/workers/kill', data={"worker_id": worker_id}) or {} def pause_mma_pipeline(self) -> dict: - """ - Pauses the MMA execution pipeline. - [C: tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow] - """ + """Pauses the MMA execution pipeline.""" return self._make_request('POST', '/api/mma/pipeline/pause') or {} def resume_mma_pipeline(self) -> dict: @@ -574,17 +459,11 @@ class ApiHookClient: return self._make_request('POST', '/api/mma/pipeline/resume') or {} def mutate_mma_dag(self, data: dict) -> dict: - """ - Mutates the MMA DAG (Directed Acyclic Graph) structure. - [C: tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation] - """ + """Mutates the MMA DAG (Directed Acyclic Graph) structure.""" return self._make_request('POST', '/api/mma/dag/mutate', data=data) or {} def approve_mma_ticket(self, ticket_id: str) -> dict: - """ - Manually approves a specific ticket for execution in Step Mode. - [C: tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow] - """ + """Manually approves a specific ticket for execution in Step Mode.""" return self._make_request('POST', '/api/mma/ticket/approve', data={"ticket_id": ticket_id}) or {} #endregion: MMA diff --git a/src/api_hooks.py b/src/api_hooks.py index b7f5b6dd..b59f6cec 100644 --- a/src/api_hooks.py +++ b/src/api_hooks.py @@ -33,7 +33,6 @@ def _create_generate_request() -> type: max_tokens=(int | None, None), ) - def _create_confirm_request() -> type: from src.module_loader import _require_warmed pydantic = _require_warmed("pydantic") @@ -49,7 +48,6 @@ _PYDANTIC_CLASS_FACTORIES: dict[str, callable] = { "ConfirmRequest": _create_confirm_request, } - def __getattr__(name: str) -> Any: if name in _PYDANTIC_CLASS_FACTORIES: cls = _PYDANTIC_CLASS_FACTORIES[name]() @@ -126,8 +124,6 @@ def _safe_controller_result(controller: Any, method_name: str, fallback: dict) - drain point. This helper internally does the try/except and returns Result[dict] (matching Heuristic A: Result-returning recovery = INTERNAL_COMPLIANT). The HTTP response (the drain point) terminates the propagation. - - [C: src/api_hooks.py:HookHandler.do_GET, src/api_hooks.py:HookHandler.do_POST] """ if controller is None or not hasattr(controller, method_name): return Result(data=fallback, errors=[ErrorInfo(kind=ErrorKind.NOT_READY, message=f"controller missing or has no {method_name}", source=f"api_hooks._safe_controller_result.{method_name}")]) @@ -143,8 +139,6 @@ def _parse_float_result(value: Any, default: float) -> Result[float]: Per error_handling.md: narrow-except fallback sites must propagate Result[T]. This helper does the parse + try/except + Result conversion internally (Heuristic A). - - [C: src/api_hooks.py:HookHandler.do_GET] """ try: return Result(data=float(value)) @@ -158,8 +152,6 @@ def _run_callback_result(callback) -> Result[bool]: Per error_handling.md: log/silent-fallback sites must propagate Result[T] to a true drain point. This helper internally does the try/except and returns Result[bool] (matching Heuristic A). The drain point is the HTTP response (self.send_response). - - [C: src/api_hooks.py:HookHandler.do_POST, src/api_hooks.py:HookHandler.do_GET] """ try: callback() @@ -171,12 +163,9 @@ def _run_callback_result(callback) -> Result[bool]: class HookServerInstance(ThreadingHTTPServer): allow_reuse_address = True """Custom HTTPServer that carries a reference to the main App instance.""" + def __init__(self, server_address: tuple[str, int], RequestHandlerClass: type, app: Any) -> None: - """ - - Initializes the server instance with an app reference. - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ + """Initializes the server instance with an app reference.""" super().__init__(server_address, RequestHandlerClass) self.app = app @@ -207,6 +196,7 @@ def _serialize_for_api(obj: Any) -> JsonValue: class HookHandler(BaseHTTPRequestHandler): """Handles incoming HTTP requests for the API hooks.""" + def do_GET(self) -> None: """Handles GET requests by routing to the appropriate state provider.""" try: @@ -934,15 +924,11 @@ class HookHandler(BaseHTTPRequestHandler): self.end_headers() self.wfile.write(json.dumps({"error": str(e)}).encode("utf-8")) - def log_message(self, format: str, *args: Any) -> None: logging.info("Hook API: " + format % args) class HookServer: def __init__(self, app: Any, port: int = 8999) -> None: - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self.app = app self.port = port self.server = None @@ -950,9 +936,6 @@ class HookServer: self.websocket_server: WebSocketServer | None = None def start(self) -> None: - """ - [C: src/app_controller.py:AppController._cb_accept_tracks, src/app_controller.py:AppController._cb_plan_epic, src/app_controller.py:AppController._cb_start_track, src/app_controller.py:AppController._fetch_models, src/app_controller.py:AppController._handle_approve_ask, src/app_controller.py:AppController._handle_generate_send, src/app_controller.py:AppController._handle_md_only, src/app_controller.py:AppController._handle_reject_ask, src/app_controller.py:AppController._init_ai_and_hooks, src/app_controller.py:AppController._process_event_queue, src/app_controller.py:AppController._prune_old_logs, src/app_controller.py:AppController._rebuild_rag_index, src/app_controller.py:AppController._run_event_loop, src/app_controller.py:AppController._start_track_logic, src/app_controller.py:AppController.cb_prune_logs, src/app_controller.py:AppController.init_state, src/app_controller.py:AppController.start_services, src/gui_2.py:App._render_discussion_entry_read_mode, src/gui_2.py:App._update_context_file_stats, src/mcp_client.py:ExternalMCPManager.add_server, src/multi_agent_conductor.py:WorkerPool.spawn, src/performance_monitor.py:PerformanceMonitor.__init__, tests/test_ai_client_concurrency.py:test_ai_client_tier_isolation, tests/test_conductor_engine_abort.py:test_kill_worker_sets_abort_and_joins_thread, tests/test_conductor_engine_v2.py:side_effect, tests/test_spawn_interception_v2.py:test_confirm_spawn_pushed_to_queue, tests/test_websocket_server.py:test_websocket_subscription_and_broadcast] - """ if self.thread and self.thread.is_alive(): return is_gemini_cli = _get_app_attr(self.app, 'current_provider', '') == 'gemini_cli' @@ -978,9 +961,6 @@ class HookServer: logging.info(f"Hook server started on port {self.port}") def stop(self) -> None: - """ - [C: src/app_controller.py:AppController.shutdown, src/mcp_client.py:ExternalMCPManager.stop_all, tests/test_performance_monitor.py:test_perf_monitor_basic_timing, tests/test_performance_monitor.py:test_perf_monitor_component_timing, tests/test_performance_monitor.py:test_perf_monitor_extended_metrics, tests/test_performance_monitor.py:test_perf_monitor_scope_context_manager, tests/test_websocket_server.py:test_websocket_subscription_and_broadcast] - """ if self.websocket_server: self.websocket_server.stop() if self.server: @@ -993,9 +973,6 @@ class HookServer: class WebSocketServer: """WebSocket gateway for real-time event streaming.""" def __init__(self, app: Any, port: int = 9000) -> None: - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self.app = app self.port = port self.clients: dict[str, set] = {"events": set(), "telemetry": set()} @@ -1048,27 +1025,18 @@ class WebSocketServer: self.loop.run_until_complete(main()) def start(self) -> None: - """ - [C: src/app_controller.py:AppController._cb_accept_tracks, src/app_controller.py:AppController._cb_plan_epic, src/app_controller.py:AppController._cb_start_track, src/app_controller.py:AppController._fetch_models, src/app_controller.py:AppController._handle_approve_ask, src/app_controller.py:AppController._handle_generate_send, src/app_controller.py:AppController._handle_md_only, src/app_controller.py:AppController._handle_reject_ask, src/app_controller.py:AppController._init_ai_and_hooks, src/app_controller.py:AppController._process_event_queue, src/app_controller.py:AppController._prune_old_logs, src/app_controller.py:AppController._rebuild_rag_index, src/app_controller.py:AppController._run_event_loop, src/app_controller.py:AppController._start_track_logic, src/app_controller.py:AppController.cb_prune_logs, src/app_controller.py:AppController.init_state, src/app_controller.py:AppController.start_services, src/gui_2.py:App._render_discussion_entry_read_mode, src/gui_2.py:App._update_context_file_stats, src/mcp_client.py:ExternalMCPManager.add_server, src/multi_agent_conductor.py:WorkerPool.spawn, src/performance_monitor.py:PerformanceMonitor.__init__, tests/test_ai_client_concurrency.py:test_ai_client_tier_isolation, tests/test_conductor_engine_abort.py:test_kill_worker_sets_abort_and_joins_thread, tests/test_conductor_engine_v2.py:side_effect, tests/test_spawn_interception_v2.py:test_confirm_spawn_pushed_to_queue, tests/test_websocket_server.py:test_websocket_subscription_and_broadcast] - """ if self.thread and self.thread.is_alive(): return self.thread = threading.Thread(target=self._run_loop, daemon=True) self.thread.start() def stop(self) -> None: - """ - [C: src/app_controller.py:AppController.shutdown, src/mcp_client.py:ExternalMCPManager.stop_all, tests/test_performance_monitor.py:test_perf_monitor_basic_timing, tests/test_performance_monitor.py:test_perf_monitor_component_timing, tests/test_performance_monitor.py:test_perf_monitor_extended_metrics, tests/test_performance_monitor.py:test_perf_monitor_scope_context_manager, tests/test_websocket_server.py:test_websocket_subscription_and_broadcast] - """ if self.loop and self._stop_event: self.loop.call_soon_threadsafe(self._stop_event.set) if self.thread: self.thread.join(timeout=2.0) def broadcast(self, message: WebSocketMessage) -> None: - """ - [C: src/app_controller.py:AppController._process_pending_gui_tasks, src/events.py:AsyncEventQueue.put, tests/test_websocket_server.py:test_websocket_subscription_and_broadcast] - """ if not self.loop or message.channel not in self.clients: return wire = json.dumps({"channel": message.channel, "payload": message.payload}) diff --git a/src/beads_client.py b/src/beads_client.py index 6a263468..42662536 100644 --- a/src/beads_client.py +++ b/src/beads_client.py @@ -22,29 +22,17 @@ class BeadsClient: self.beads_file = self.repo_dir / "beads.json" def init_repo(self) -> None: - """ - - Initialize the mock repository. - [C: tests/test_aggregate_beads.py:test_build_beads_compaction, tests/test_beads_client.py:test_beads_init_and_query, tests/test_gui_dag_beads.py:test_load_active_tickets_from_beads, tests/test_mcp_client_beads.py:test_bd_mcp_tools] - """ + """Initialize the mock repository.""" self.repo_dir.mkdir(parents=True, exist_ok=True) if not self.beads_file.exists(): self.beads_file.write_text("[]", encoding="utf-8") def is_initialized(self) -> bool: - """ - - Check if the repository is initialized. - [C: src/mcp_client.py:dispatch, tests/test_beads_client.py:test_beads_init_and_query] - """ + """Check if the repository is initialized.""" return self.beads_file.exists() def create_bead(self, title: str, description: str) -> str: - """ - - Create a new bead and return its ID. - [C: src/mcp_client.py:dispatch, tests/test_aggregate_beads.py:test_build_beads_compaction, tests/test_beads_client.py:test_beads_init_and_query, tests/test_gui_dag_beads.py:test_load_active_tickets_from_beads] - """ + """Create a new bead and return its ID.""" beads = self._read_beads() bead_id = f"bead-{len(beads) + 1}" bead = {"id": bead_id, "title": title, "description": description, "status": "active"} @@ -53,11 +41,7 @@ class BeadsClient: return bead_id def update_bead(self, bead_id: str, status: str) -> bool: - """ - - Update the status of an existing bead. - [C: src/mcp_client.py:dispatch, tests/test_aggregate_beads.py:test_build_beads_compaction, tests/test_beads_client.py:test_beads_init_and_query] - """ + """Update the status of an existing bead.""" beads = self._read_beads() for bead in beads: if bead["id"] == bead_id: @@ -67,11 +51,7 @@ class BeadsClient: return False def list_beads(self) -> List[Bead]: - """ - - List all beads. - [C: src/gui_2.py:App._render_beads_tab, src/mcp_client.py:dispatch, tests/test_beads_client.py:test_beads_init_and_query] - """ + """List all beads.""" return [Bead(**b) for b in self._read_beads()] def _read_beads(self) -> List[dict]: @@ -80,4 +60,4 @@ class BeadsClient: return json.loads(self.beads_file.read_text(encoding="utf-8")) def _write_beads(self, beads: List[dict]) -> None: - self.beads_file.write_text(json.dumps(beads, indent=1), encoding="utf-8") \ No newline at end of file + self.beads_file.write_text(json.dumps(beads, indent=1), encoding="utf-8") diff --git a/src/conductor_tech_lead.py b/src/conductor_tech_lead.py index 4bd65ae1..1e43a7eb 100644 --- a/src/conductor_tech_lead.py +++ b/src/conductor_tech_lead.py @@ -46,7 +46,6 @@ def generate_tickets(track_brief: str, module_skeletons: str) -> list[dict[str, """ Tier 2 (Tech Lead) call. Breaks down a Track Brief and module skeletons into discrete Tier 3 Tickets. - [C: tests/test_conductor_tech_lead.py:TestConductorTechLead.test_generate_tickets_retry_failure, tests/test_conductor_tech_lead.py:TestConductorTechLead.test_generate_tickets_retry_success, tests/test_conductor_tech_lead.py:TestConductorTechLead.test_generate_tickets_success, tests/test_orchestration_logic.py:test_generate_tickets] """ # 1. Set Tier 2 Model (Tech Lead - Flash) # 2. Construct Prompt @@ -108,7 +107,6 @@ def topological_sort(tickets: list[Ticket]) -> list[Ticket]: """ Sorts a list of Ticket objects based on their depends_on field. Raises ValueError if a circular dependency or missing internal dependency is detected. - [C: tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_complex, tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_cycle, tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_empty, tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_linear, tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_missing_dependency, tests/test_conductor_tech_lead.py:test_topological_sort_vlog, tests/test_dag_engine.py:test_topological_sort, tests/test_dag_engine.py:test_topological_sort_cycle, tests/test_orchestration_logic.py:test_topological_sort, tests/test_orchestration_logic.py:test_topological_sort_circular, tests/test_perf_dag.py:test_dag_edge_cases, tests/test_perf_dag.py:test_dag_performance] """ dag = TrackDAG(tickets) try: diff --git a/src/cost_tracker.py b/src/cost_tracker.py index 5016f7be..bbaba94a 100644 --- a/src/cost_tracker.py +++ b/src/cost_tracker.py @@ -67,8 +67,6 @@ def estimate_cost(model: str, input_tokens: int, output_tokens: int) -> float: """ Estimate the cost of a model call based on input and output tokens. Returns the total cost in USD. - - [C: src/gui_2.py:App._render_mma_track_summary, src/gui_2.py:App._render_mma_usage_section, src/gui_2.py:App._render_token_budget_panel, tests/test_cost_tracker.py:test_estimate_cost] """ if not model: return 0.0 diff --git a/src/dag_engine.py b/src/dag_engine.py index cffe0cbc..12e62f2a 100644 --- a/src/dag_engine.py +++ b/src/dag_engine.py @@ -43,7 +43,6 @@ class TrackDAG: Initializes the TrackDAG with a list of Ticket objects. Args: tickets: A list of Ticket instances defining the graph nodes and edges. - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] """ self.tickets = tickets self.ticket_map = {t.id: t for t in tickets} @@ -52,7 +51,6 @@ class TrackDAG: """ Transitively marks `todo` tickets as `blocked` if any dependency is `blocked`. Propagates 'blocked' status from initially blocked nodes to their dependents. - [C: tests/test_perf_dag.py:test_dag_performance] """ with get_monitor().scope("dag_cascade_blocks"): # Build adjacency list of dependents using object references to avoid lookups @@ -89,7 +87,6 @@ class TrackDAG: Returns a list of tickets that are in 'todo' status and whose dependencies are all 'completed'. Returns: A list of Ticket objects ready for execution. - [C: src/dag_engine.py:get_executable_tickets, tests/test_dag_engine.py:test_get_ready_tasks_branching, tests/test_dag_engine.py:test_get_ready_tasks_linear, tests/test_dag_engine.py:test_get_ready_tasks_multiple_deps, tests/test_orchestration_logic.py:test_track_executable_tickets] """ ready = [] for ticket in self.tickets: @@ -102,7 +99,6 @@ class TrackDAG: Performs an iterative Depth-First Search to detect cycles in the dependency graph. Returns: True if a cycle is detected, False otherwise. - [C: src/gui_2.py:App._render_task_dag_panel, tests/test_dag_engine.py:test_has_cycle_complex_no_cycle, tests/test_dag_engine.py:test_has_cycle_direct_cycle, tests/test_dag_engine.py:test_has_cycle_indirect_cycle, tests/test_dag_engine.py:test_has_cycle_no_cycle, tests/test_perf_dag.py:test_dag_edge_cases, tests/test_perf_dag.py:test_dag_performance] """ with get_monitor().scope("dag_has_cycle"): visited = set() @@ -135,7 +131,6 @@ class TrackDAG: A list of ticket ID strings. Raises: ValueError: If a dependency cycle is detected. - [C: tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_complex, tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_cycle, tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_empty, tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_linear, tests/test_conductor_tech_lead.py:TestTopologicalSort.test_topological_sort_missing_dependency, tests/test_conductor_tech_lead.py:test_topological_sort_vlog, tests/test_dag_engine.py:test_topological_sort, tests/test_dag_engine.py:test_topological_sort_cycle, tests/test_orchestration_logic.py:test_topological_sort, tests/test_orchestration_logic.py:test_topological_sort_circular, tests/test_perf_dag.py:test_dag_edge_cases, tests/test_perf_dag.py:test_dag_performance] """ with get_monitor().scope("dag_topological_sort"): in_degree = {t.id: len(t.depends_on) for t in self.tickets} @@ -168,7 +163,6 @@ def get_executable_tickets(track: "Track") -> List[Ticket]: Free function (instead of Track.get_executable_tickets) so that src/models.py does not need to import TrackDAG at module level, breaking the models<->dag_engine circular dependency. - [C: tests/test_mma_models.py:test_track_get_executable_tickets, tests/test_mma_models.py:test_track_get_executable_tickets_complex] """ return TrackDAG(track.tickets).get_ready_tasks() @@ -185,7 +179,6 @@ class ExecutionEngine: Args: dag: The TrackDAG instance to manage. auto_queue: If True, ready tasks will automatically move to 'in_progress'. - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] """ self.dag = dag self.auto_queue = auto_queue @@ -196,7 +189,6 @@ class ExecutionEngine: If auto_queue is enabled, tasks without 'step_mode' will be marked as 'in_progress'. Returns: A list of ready Ticket objects. - [C: src/multi_agent_conductor.py:ConductorEngine.run, tests/test_arch_boundary_phase3.py:TestArchBoundaryPhase3.test_cascade_blocks_multi_hop, tests/test_arch_boundary_phase3.py:TestArchBoundaryPhase3.test_cascade_blocks_simple, tests/test_arch_boundary_phase3.py:TestArchBoundaryPhase3.test_execution_engine_tick_cascades_blocks, tests/test_arch_boundary_phase3.py:TestArchBoundaryPhase3.test_in_progress_not_blocked, tests/test_arch_boundary_phase3.py:TestArchBoundaryPhase3.test_manual_unblock_restores_todo, tests/test_execution_engine.py:test_execution_engine_auto_queue, tests/test_execution_engine.py:test_execution_engine_basic_flow, tests/test_execution_engine.py:test_execution_engine_step_mode] """ with get_monitor().scope("dag_tick"): self.dag.cascade_blocks() @@ -208,7 +200,6 @@ class ExecutionEngine: Manually transitions a task from 'todo' to 'in_progress' if its dependencies are met. Args: task_id: The ID of the task to approve. - [C: src/multi_agent_conductor.py:ConductorEngine.approve_task, tests/test_execution_engine.py:test_execution_engine_approve_task, tests/test_execution_engine.py:test_execution_engine_step_mode] """ ticket = self.dag.ticket_map.get(task_id) if ticket and ticket.status == "todo" and self.dag.is_ticket_ready(ticket): @@ -220,7 +211,6 @@ class ExecutionEngine: Args: task_id: The ID of the task. status: The new status string (e.g., 'todo', 'in_progress', 'completed', 'blocked'). - [C: src/multi_agent_conductor.py:ConductorEngine.update_task_status, tests/test_arch_boundary_phase3.py:TestArchBoundaryPhase3.test_manual_unblock_restores_todo, tests/test_execution_engine.py:test_execution_engine_auto_queue, tests/test_execution_engine.py:test_execution_engine_basic_flow, tests/test_execution_engine.py:test_execution_engine_status_persistence, tests/test_execution_engine.py:test_execution_engine_update_nonexistent_task] """ ticket = self.dag.ticket_map.get(task_id) if ticket: diff --git a/src/events.py b/src/events.py index 2f990a0a..17e1fe81 100644 --- a/src/events.py +++ b/src/events.py @@ -41,10 +41,7 @@ class EventEmitter: """Simple event emitter for decoupled communication between modules.""" def __init__(self) -> None: - """ - Initializes the EventEmitter with an empty listener map. - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ + """Initializes the EventEmitter with an empty listener map.""" self._listeners: Dict[str, List[Callable[..., Any]]] = {} def on(self, event_name: str, callback: Callable[..., Any]) -> None: diff --git a/src/external_editor.py b/src/external_editor.py index 6e1a483c..a7a6e294 100644 --- a/src/external_editor.py +++ b/src/external_editor.py @@ -68,30 +68,18 @@ EMPTY_TEXT_EDITOR_CONFIG: TextEditorConfig = TextEditorConfig() class ExternalEditorLauncher: def __init__(self, config: ExternalEditorConfig): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self.config = config def get_editor(self, editor_name: Optional[str] = None) -> TextEditorConfig: - """ - [C: tests/test_external_editor.py:TestExternalEditorLauncher.test_get_editor_by_name, tests/test_external_editor.py:TestExternalEditorLauncher.test_get_editor_returns_default, tests/test_external_editor.py:TestExternalEditorLauncher.test_get_editor_unknown_name] - """ if editor_name: return self.config.editors.get(editor_name) or EMPTY_TEXT_EDITOR_CONFIG return self.config.get_default() def build_diff_command(self, editor: TextEditorConfig, original_path: str, modified_path: str) -> List[str]: - """ - [C: tests/test_external_editor.py:TestExternalEditorLauncher.test_build_diff_command, tests/test_external_editor_gui.py:test_verify_command_format, tests/test_external_editor_gui.py:test_verify_vscode_command_format] - """ cmd = [editor.path] + editor.diff_args + [original_path, modified_path] return cmd def launch_diff_result(self, editor_name: Optional[str], original_path: str, modified_path: str) -> Result[subprocess.Popen]: - """ - [C: src/gui_2.py:App._open_patch_in_external_editor, tests/test_external_editor.py:TestExternalEditorLauncher.test_launch_diff_file_not_found, tests/test_external_editor.py:TestExternalEditorLauncher.test_launch_diff_missing_editor, tests/test_external_editor.py:TestExternalEditorLauncher.test_launch_diff_success] - """ editor = self.get_editor(editor_name) if not editor.name or not editor.path: return Result(data=None, errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message=f"No editor configured: {editor_name}", source="external_editor.launch_diff_result")]) @@ -118,8 +106,8 @@ def _find_vscode_in_registry() -> Result[Optional[str]]: for key in reg_keys: try: result = subprocess.run( - ["powershell", "-Command", f"Get-ItemProperty -Path '{key}' -ErrorAction SilentlyContinue | Where-Object {{ $_.DisplayName -like '*Visual Studio Code*' }} | Select-Object -ExpandProperty InstallLocation"], - capture_output=True, text=True, timeout=5 + ["powershell", "-Command", f"Get-ItemProperty -Path '{key}' -ErrorAction SilentlyContinue | Where-Object {{ $_.DisplayName -like '*Visual Studio Code*' }} | Select-Object -ExpandProperty InstallLocation"], + capture_output=True, text=True, timeout=5 ) for line in result.stdout.strip().split('\n'): line = line.strip() @@ -171,7 +159,6 @@ def get_default_launcher(config: Optional[Dict[str, Any]] = None) -> ExternalEdi AppController). Direct file I/O (the legacy public functions on src.models) is an architectural smell (bypasses the controller state owner) and is forbidden by scripts/audit_no_models_config_io.py. - [C: src/gui_2.py:App._open_patch_in_external_editor, src/gui_2.py:App._render_external_editor_panel] """ editors_config = config.get("tools", {}).get("text_editors", {}) if config else {} default_editor = config.get("tools", {}).get("default_editor", {}).get("default_editor") if config else None @@ -193,9 +180,6 @@ def get_default_launcher(config: Optional[Dict[str, Any]] = None) -> ExternalEdi def create_temp_modified_file(content: str) -> str: - """ - [C: src/gui_2.py:App._open_patch_in_external_editor, tests/test_external_editor.py:TestHelperFunctions.test_create_temp_modified_file] - """ with tempfile.NamedTemporaryFile(mode="w", suffix="_modified", delete=False, encoding="utf-8") as f: f.write(content) return f.name diff --git a/src/file_cache.py b/src/file_cache.py index 8f9900c9..e3709584 100644 --- a/src/file_cache.py +++ b/src/file_cache.py @@ -76,9 +76,6 @@ class ASTParser: #region: Core Operations def __init__(self, language: str) -> None: - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ if language not in ("python", "cpp", "c"): raise ValueError(f"Language '{language}' not supported yet.") self.language_name = language @@ -91,10 +88,7 @@ class ASTParser: self.parser = ts.Parser(self.language) def parse(self, code: str) -> tree_sitter.Tree: - """ - Parse the given code and return the tree-sitter Tree. - [C: src/mcp_client.py:_search_file, src/mcp_client.py:derive_code_path, src/mcp_client.py:py_check_syntax, src/mcp_client.py:py_get_class_summary, src/mcp_client.py:py_get_definition, src/mcp_client.py:py_get_docstring, src/mcp_client.py:py_get_imports, src/mcp_client.py:py_get_signature, src/mcp_client.py:py_get_symbol_info, src/mcp_client.py:py_get_var_declaration, src/mcp_client.py:py_set_signature, src/mcp_client.py:py_set_var_declaration, src/mcp_client.py:py_update_definition, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/rag_engine.py:RAGEngine._chunk_code, src/summarize.py:_summarise_python, tests/test_ast_parser.py:test_ast_parser_parse, tests/test_tree_sitter_setup.py:test_tree_sitter_python_setup] - """ + """Parse the given code and return the tree-sitter Tree.""" return self.parser.parse(bytes(code, "utf8")) def get_cached_tree(self, path: Optional[str], code: str) -> tree_sitter.Tree: @@ -205,10 +199,7 @@ class ASTParser: #region: Skeleton & Curated Views def get_skeleton(self, code: str, path: Optional[str] = None) -> str: - """ - Returns a skeleton of a Python file (preserving docstrings, stripping function bodies). - [C: src/mcp_client.py:py_get_skeleton, src/mcp_client.py:ts_c_get_skeleton, src/mcp_client.py:ts_cpp_get_skeleton, src/multi_agent_conductor.py:run_worker_lifecycle, tests/test_ast_parser.py:test_ast_parser_get_skeleton_c, tests/test_ast_parser.py:test_ast_parser_get_skeleton_cpp, tests/test_ast_parser.py:test_ast_parser_get_skeleton_python, tests/test_context_pruner.py:test_ast_caching, tests/test_context_pruner.py:test_performance_large_file] - """ + """Returns a skeleton of a Python file (preserving docstrings, stripping function bodies).""" code_bytes = code.encode("utf8") tree = self.get_cached_tree(path, code) edits: List[Tuple[int, int, str]] = [] @@ -220,9 +211,6 @@ class ASTParser: return False def walk(node: tree_sitter.Node) -> None: - """ - [C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python] - """ if node.type in ("function_definition", "method_definition"): body = node.child_by_field_name("body") if not body: @@ -293,7 +281,6 @@ class ASTParser: Returns a curated skeleton of a Python file. Preserves function bodies if they have @core_logic decorator or # [HOT] comment. Otherwise strips bodies but preserves docstrings. - [C: src/multi_agent_conductor.py:run_worker_lifecycle, tests/test_ast_parser.py:test_ast_parser_get_curated_view] """ code_bytes = code.encode("utf8") tree = self.get_cached_tree(path, code) @@ -330,9 +317,6 @@ class ASTParser: return False def walk(node: tree_sitter.Node) -> None: - """ - [C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python] - """ if node.type == "function_definition": body = node.child_by_field_name("body") if body and body.type in ("block", "compound_statement"): @@ -369,11 +353,7 @@ class ASTParser: #region: Targeted Views def get_targeted_view(self, code: str, function_names: List[str], path: Optional[str] = None) -> str: - """ - Returns a targeted view of the code including only the specified functions - and their dependencies up to depth 2. - [C: src/multi_agent_conductor.py:run_worker_lifecycle, tests/test_ast_parser.py:test_ast_parser_get_targeted_view, tests/test_context_pruner.py:test_class_targeted_extraction, tests/test_context_pruner.py:test_targeted_extraction] - """ + """Returns a targeted view of the code including only the specified functions and their dependencies up to depth 2.""" code_bytes = code.encode("utf8") tree = self.get_cached_tree(path, code) all_functions = {} @@ -539,7 +519,6 @@ class ASTParser: """ Returns the full source code for a specific definition by name. Supports 'ClassName::method' or 'method' for C++. - [C: src/mcp_client.py:trace, src/mcp_client.py:ts_c_get_definition, src/mcp_client.py:ts_cpp_get_definition, tests/test_ast_parser.py:test_ast_parser_get_definition_c, tests/test_ast_parser.py:test_ast_parser_get_definition_cpp, tests/test_ast_parser.py:test_ast_parser_get_definition_cpp_template] """ code_bytes = code.encode("utf8") tree = self.get_cached_tree(path, code) @@ -547,9 +526,6 @@ class ASTParser: parts = re.split(r'::|\.', name) def walk(node: tree_sitter.Node, target_parts: List[str]) -> tree_sitter.Node: - """ - [C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python] - """ if not target_parts: return node target = target_parts[0] @@ -637,16 +613,12 @@ class ASTParser: """ Returns only the signature part of a function or method. For C/C++, this is the code from the start of the definition until the block start '{'. - [C: src/mcp_client.py:ts_c_get_signature, src/mcp_client.py:ts_cpp_get_signature, tests/test_ast_parser.py:test_ast_parser_get_signature_c, tests/test_ast_parser.py:test_ast_parser_get_signature_cpp] """ code_bytes = code.encode("utf8") tree = self.get_cached_tree(path, code) parts = re.split(r'::|\.', name) def walk(node: tree_sitter.Node, target_parts: List[str]) -> tree_sitter.Node: - """ - [C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python] - """ if not target_parts: return node target = target_parts[0] @@ -746,18 +718,12 @@ class ASTParser: #region: Analysis & Updates def get_code_outline(self, code: str, path: Optional[str] = None) -> str: - """ - Returns a hierarchical outline of the code (classes, structs, functions, methods). - [C: src/mcp_client.py:ts_c_get_code_outline, src/mcp_client.py:ts_cpp_get_code_outline, tests/test_ast_parser.py:test_ast_parser_get_code_outline_c, tests/test_ast_parser.py:test_ast_parser_get_code_outline_cpp] - """ + """Returns a hierarchical outline of the code (classes, structs, functions, methods).""" code_bytes = code.encode("utf8") tree = self.get_cached_tree(path, code) output = [] def walk(node: tree_sitter.Node, indent: int = 0) -> None: - """ - [C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python] - """ ntype = node.type label = "" if ntype in ("class_definition", "class_specifier"): @@ -788,18 +754,12 @@ class ASTParser: return "\n".join(output) def update_definition(self, code: str, name: str, new_content: str, path: Optional[str] = None) -> str: - """ - Surgically replace the definition of a class or function by name. - [C: src/mcp_client.py:ts_c_update_definition, src/mcp_client.py:ts_cpp_update_definition, tests/test_ast_parser.py:test_ast_parser_update_definition_cpp] - """ + """Surgically replace the definition of a class or function by name.""" code_bytes = code.encode("utf8") tree = self.get_cached_tree(path, code) parts = re.split(r'::|\.', name) def walk(node: tree_sitter.Node, target_parts: List[str]) -> tree_sitter.Node: - """ - [C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python] - """ if not target_parts: return node target = target_parts[0] diff --git a/src/fuzzy_anchor.py b/src/fuzzy_anchor.py index 219608fa..4bfc9df3 100644 --- a/src/fuzzy_anchor.py +++ b/src/fuzzy_anchor.py @@ -18,10 +18,7 @@ class FuzzyAnchor: @classmethod def create_slice(cls, text: str, start_line: int, end_line: int) -> dict: - """ - start_line and end_line are 1-based. - [C: src/gui_2.py:App._populate_auto_slices, src/gui_2.py:App._render_text_viewer_window, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_create_slice_basic, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_anchor_mismatch_returns_none, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_exact_match, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_line_deleted_before_returns_none, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_line_inserted_before, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_multiple_lines_changed, tests/test_slice_editor_behavior.py:test_add_slice_with_annotations] - """ + """start_line and end_line are 1-based.""" lines = text.splitlines() s_idx = max(0, start_line - 1) e_idx = min(len(lines), end_line) diff --git a/src/gemini_cli_adapter.py b/src/gemini_cli_adapter.py index ea7fcb56..95b7d870 100644 --- a/src/gemini_cli_adapter.py +++ b/src/gemini_cli_adapter.py @@ -49,10 +49,7 @@ class GeminiCliAdapter: Adapter for the Gemini CLI that parses streaming JSON output. """ def __init__(self, binary_path: str = "gemini"): - """ - Initializes the adapter with the path to the gemini CLI executable. - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ + """Initializes the adapter with the path to the gemini CLI executable.""" self.binary_path = binary_path self.session_id: Optional[str] = None self.last_usage: Optional[dict[str, Any]] = None @@ -62,7 +59,6 @@ class GeminiCliAdapter: """ Sends a message to the Gemini CLI and processes the streaming JSON output. Uses non-blocking line-by-line reading to allow stream_callback. - [C: simulation/user_agent.py:UserSimAgent.generate_response, src/multi_agent_conductor.py:run_worker_lifecycle, src/orchestrator_pm.py:generate_tracks, tests/test_ai_cache_tracking.py:test_gemini_cache_tracking, tests/test_ai_client_cli.py:test_ai_client_send_gemini_cli, tests/test_api_events.py:test_send_emits_events_proper, tests/test_api_events.py:test_send_emits_tool_events, tests/test_deepseek_provider.py:test_deepseek_completion_logic, tests/test_deepseek_provider.py:test_deepseek_payload_verification, tests/test_deepseek_provider.py:test_deepseek_reasoner_payload_verification, tests/test_deepseek_provider.py:test_deepseek_reasoning_logic, tests/test_deepseek_provider.py:test_deepseek_streaming, tests/test_deepseek_provider.py:test_deepseek_tool_calling, tests/test_gemini_cli_adapter.py:TestGeminiCliAdapter.test_full_flow_integration, tests/test_gemini_cli_adapter.py:TestGeminiCliAdapter.test_send_captures_usage_metadata, tests/test_gemini_cli_adapter.py:TestGeminiCliAdapter.test_send_handles_tool_use_events, tests/test_gemini_cli_adapter.py:TestGeminiCliAdapter.test_send_parses_jsonl_output, tests/test_gemini_cli_adapter.py:TestGeminiCliAdapter.test_send_starts_subprocess_with_correct_args, tests/test_gemini_cli_adapter_parity.py:TestGeminiCliAdapterParity.test_send_parses_tool_calls_from_streaming_json, tests/test_gemini_cli_adapter_parity.py:TestGeminiCliAdapterParity.test_send_starts_subprocess_with_model, tests/test_gemini_cli_edge_cases.py:test_gemini_cli_context_bleed_prevention, tests/test_gemini_cli_edge_cases.py:test_gemini_cli_loop_termination, tests/test_gemini_cli_integration.py:test_gemini_cli_full_integration, tests/test_gemini_cli_integration.py:test_gemini_cli_rejection_and_history, tests/test_gemini_cli_parity_regression.py:test_send_invokes_adapter_send, tests/test_gui2_mcp.py:test_mcp_tool_call_is_dispatched, tests/test_tier4_interceptor.py:test_ai_client_passes_qa_callback, tests/test_token_usage.py:test_token_usage_tracking, tests/test_websocket_server.py:test_websocket_subscription_and_broadcast] """ start_time = time.time() command_parts = [self.binary_path] @@ -192,7 +188,6 @@ class GeminiCliAdapter: """ Provides a character-based token estimation for the Gemini CLI. Uses 4 chars/token as a conservative average. - [C: tests/test_gemini_cli_adapter_parity.py:TestGeminiCliAdapterParity.test_count_tokens_fallback] """ total_chars = len("\n".join(contents)) return total_chars // 4 \ No newline at end of file diff --git a/src/history.py b/src/history.py index ab78dce7..c98ed51d 100644 --- a/src/history.py +++ b/src/history.py @@ -3,7 +3,6 @@ import typing from dataclasses import dataclass, field - @dataclass class UISnapshot: """Capture of restorable UI state.""" @@ -22,9 +21,6 @@ class UISnapshot: screenshots: list[str] def to_dict(self) -> dict: - """ - [C: src/models.py:ContextPreset.to_dict, src/models.py:ExternalEditorConfig.to_dict, src/models.py:MCPConfiguration.to_dict, src/models.py:RAGConfig.to_dict, src/models.py:ToolPreset.to_dict, src/models.py:Track.to_dict, src/models.py:TrackState.to_dict, src/personas.py:PersonaManager.save_persona, src/presets.py:PresetManager.save_preset, src/project_manager.py:save_project, src/project_manager.py:save_track_state, src/tool_presets.py:ToolPresetManager.save_bias_profile, src/tool_presets.py:ToolPresetManager.save_preset, src/workspace_manager.py:WorkspaceManager.save_profile, tests/test_bias_models.py:test_bias_profile_model, tests/test_bias_models.py:test_tool_model, tests/test_bias_models.py:test_tool_preset_extension, tests/test_context_presets_models.py:test_context_preset_serialization, tests/test_context_presets_models.py:test_file_view_preset_serialization, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_round_trip_annotations, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_serialization_with_annotations, tests/test_event_serialization.py:test_user_request_event_serialization, tests/test_external_editor.py:TestExternalEditorConfig.test_to_dict, tests/test_external_editor.py:TestTextEditorConfig.test_to_dict, tests/test_file_item_model.py:test_file_item_to_dict, tests/test_gui_events_v2.py:test_user_request_event_payload, tests/test_history_manager.py:TestHistoryManager.test_snapshot_roundtrip, tests/test_mcp_config.py:test_mcp_configuration_to_from_dict, tests/test_mcp_config.py:test_mcp_server_config_to_from_dict, tests/test_per_ticket_model.py:test_model_override_serialization, tests/test_persona_id.py:test_ticket_persona_id_serialization, tests/test_persona_models.py:test_persona_defaults, tests/test_persona_models.py:test_persona_serialization, tests/test_slice_editor_behavior.py:test_add_slice_with_annotations, tests/test_thinking_gui.py:test_thinking_segment_model_compatibility, tests/test_ticket_queue.py:test_ticket_to_dict_priority, tests/test_tiered_aggregation.py:test_persona_aggregation_strategy, tests/test_track_state_schema.py:test_track_state_to_dict, tests/test_track_state_schema.py:test_track_state_to_dict_with_none, tests/test_ui_summary_only_removal.py:test_file_item_serialization_with_flags] - """ return { "ai_input": self.ai_input, "project_system_prompt": self.project_system_prompt, @@ -43,9 +39,6 @@ class UISnapshot: @classmethod def from_dict(cls, data: dict) -> "UISnapshot": - """ - [C: src/models.py:ContextPreset.from_dict, src/models.py:ExternalEditorConfig.from_dict, src/models.py:MCPConfiguration.from_dict, src/models.py:RAGConfig.from_dict, src/models.py:ToolPreset.from_dict, src/models.py:Track.from_dict, src/models.py:TrackState.from_dict, src/models.py:load_mcp_config, src/personas.py:PersonaManager.load_all, src/presets.py:PresetManager.load_all, src/project_manager.py:load_project, src/project_manager.py:load_track_state, src/tool_presets.py:ToolPresetManager.load_all_bias_profiles, src/tool_presets.py:ToolPresetManager.load_all_presets, src/workspace_manager.py:WorkspaceManager.load_all_profiles, tests/test_bias_models.py:test_bias_profile_model, tests/test_bias_models.py:test_tool_model, tests/test_bias_models.py:test_tool_preset_extension, tests/test_context_presets_models.py:test_context_preset_from_dict_legacy, tests/test_context_presets_models.py:test_context_preset_serialization, tests/test_context_presets_models.py:test_file_view_preset_serialization, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_deserialization_with_annotations, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_round_trip_annotations, tests/test_external_editor.py:TestExternalEditorConfig.test_from_dict_with_dict_editors, tests/test_external_editor.py:TestExternalEditorConfig.test_from_dict_with_string_editors, tests/test_external_editor.py:TestTextEditorConfig.test_from_dict_with_diff_args, tests/test_external_editor.py:TestTextEditorConfig.test_from_dict_without_diff_args, tests/test_file_item_model.py:test_file_item_from_dict, tests/test_file_item_model.py:test_file_item_from_dict_defaults, tests/test_history_manager.py:TestHistoryManager.test_snapshot_roundtrip, tests/test_mcp_config.py:test_mcp_configuration_to_from_dict, tests/test_mcp_config.py:test_mcp_server_config_to_from_dict, tests/test_per_ticket_model.py:test_model_override_default_on_deserialize, tests/test_per_ticket_model.py:test_model_override_deserialization, tests/test_persona_id.py:test_ticket_persona_id_deserialization, tests/test_persona_models.py:test_persona_defaults, tests/test_persona_models.py:test_persona_deserialization, tests/test_project_serialization.py:TestProjectSerialization.test_backward_compatibility_strings, tests/test_slice_editor_behavior.py:test_add_slice_with_annotations, tests/test_ticket_queue.py:test_ticket_from_dict_default_priority, tests/test_ticket_queue.py:test_ticket_from_dict_priority, tests/test_tiered_aggregation.py:test_persona_aggregation_strategy, tests/test_track_state_schema.py:test_track_state_from_dict, tests/test_track_state_schema.py:test_track_state_from_dict_empty_and_missing, tests/test_ui_summary_only_removal.py:test_file_item_serialization_with_flags] - """ return cls( ai_input = data.get("ai_input", ""), project_system_prompt = data.get("project_system_prompt", ""), @@ -70,9 +63,6 @@ class HistoryEntry: class HistoryManager: def __init__(self, max_capacity: int = 100): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self.max_capacity = max_capacity self._undo_stack: typing.List[HistoryEntry] = [] self._redo_stack: typing.List[HistoryEntry] = [] @@ -81,7 +71,6 @@ class HistoryManager: """ Pushes a new state to the undo stack and clears the redo stack. If the undo stack exceeds max_capacity, the oldest state is removed. - [C: tests/test_history.py:test_jump_to_undo, tests/test_history.py:test_max_capacity, tests/test_history.py:test_push_state, tests/test_history.py:test_redo_cleared_on_push, tests/test_history.py:test_undo_redo, tests/test_history_manager.py:TestHistoryManager.test_get_history_returns_descriptions, tests/test_history_manager.py:TestHistoryManager.test_jump_to_undo, tests/test_history_manager.py:TestHistoryManager.test_push_and_undo, tests/test_history_manager.py:TestHistoryManager.test_push_clears_redo_stack, tests/test_history_manager.py:TestHistoryManager.test_undo_and_redo] """ entry = HistoryEntry(state=state, description=description) self._undo_stack.append(entry) @@ -93,7 +82,6 @@ class HistoryManager: """ Undoes the last action by moving the current_state to the redo stack and returning the top of the undo stack. - [C: tests/test_history.py:test_redo_cleared_on_push, tests/test_history.py:test_undo_redo, tests/test_history_manager.py:TestHistoryManager.test_push_and_undo, tests/test_history_manager.py:TestHistoryManager.test_push_clears_redo_stack, tests/test_history_manager.py:TestHistoryManager.test_undo_and_redo, tests/test_history_manager.py:TestHistoryManager.test_undo_no_history_returns_none] """ if not self._undo_stack: return None redo_entry = HistoryEntry(state=current_state, description=current_description) @@ -104,7 +92,6 @@ class HistoryManager: """ Redoes the last undone action by moving the current_state to the undo stack and returning the top of the redo stack. - [C: tests/test_history.py:test_undo_redo, tests/test_history_manager.py:TestHistoryManager.test_redo_no_history_returns_none, tests/test_history_manager.py:TestHistoryManager.test_undo_and_redo] """ if not self._redo_stack: return None undo_entry = HistoryEntry(state=current_state, description=current_description) @@ -117,21 +104,14 @@ class HistoryManager: def can_redo(self) -> bool: return len(self._redo_stack) > 0 def get_history(self) -> typing.List[typing.Dict[str, typing.Any]]: - """ - Returns a list of descriptions and timestamps for the undo stack. - [C: tests/test_history.py:test_initial_state, tests/test_history.py:test_push_state, tests/test_history_manager.py:TestHistoryManager.test_get_history_returns_descriptions] - """ + """Returns a list of descriptions and timestamps for the undo stack.""" return [ {"description": e.description, "timestamp": e.timestamp} for e in self._undo_stack ] def jump_to_undo(self, index: int, current_state: typing.Any, current_description: str = "Before Jump") -> typing.Optional[HistoryEntry]: - """ - Jumps to a specific state in the undo stack by moving subsequent states - and the current_state to the redo stack. - [C: tests/test_history.py:test_jump_to_undo, tests/test_history_manager.py:TestHistoryManager.test_jump_to_undo] - """ + """Jumps to a specific state in the undo stack by moving subsequent states and the current_state to the redo stack.""" if index < 0 or index >= len(self._undo_stack): return None # Move current state to redo self._redo_stack.append(HistoryEntry(state=current_state, description=current_description)) diff --git a/src/imgui_scopes.py b/src/imgui_scopes.py index 771fa9d1..884bf14d 100644 --- a/src/imgui_scopes.py +++ b/src/imgui_scopes.py @@ -9,9 +9,6 @@ from imgui_bundle import imgui_node_editor def child(id_str: str, size_x: float = 0, size_y: float = 0, flags: int = 0): return _ScopeChild(id_str, size_x, size_y, flags) class _ScopeChild: def __init__(self, id_str: str, size_x: float | imgui.ImVec2, size_y: float, flags: int): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._id = id_str # Check if size_x is likely an ImVec2 without using isinstance (which breaks with mocks) if hasattr(size_x, 'x') and hasattr(size_x, 'y'): @@ -37,9 +34,6 @@ class _ScopeGroup: def id(str_id: str): return _ScopeId(str_id) class _ScopeId: def __init__(self, str_id: str): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._id = str_id def __enter__(self): # Use explicit conversion to avoid any possible nanobind ambiguity @@ -62,9 +56,6 @@ class _ScopeIndent: def menu(label: str): return _ScopeMenu(label) class _ScopeMenu: def __init__(self, label: str): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._label = label self._active = False def __enter__(self): @@ -78,9 +69,6 @@ class _ScopeMenu: def menu_bar(): return _ScopeMenuBar() class _ScopeMenuBar: def __init__(self): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._active = False def __enter__(self): self._active = imgui.begin_menu_bar() @@ -93,9 +81,6 @@ class _ScopeMenuBar: def node(name: str): return _ScopeNode(name) class _ScopeNode: def __init__(self, name: str): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._name = name def __enter__(self): return imgui_node_editor.begin(self._name) @@ -106,9 +91,6 @@ class _ScopeNode: def popup(id_str: str): return _ScopePopup(id_str) class _ScopePopup: def __init__(self, id_str: str): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._id = id_str self._active = False def __enter__(self): @@ -122,9 +104,6 @@ class _ScopePopup: def popup_modal(name: str, visible: bool = True, flags: int = 0): return _ScopePopupModal(name, visible, flags) class _ScopePopupModal: def __init__(self, name: str, visible: bool, flags: int): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._name = name self._visible = visible self._flags = flags @@ -141,9 +120,6 @@ class _ScopePopupModal: def style_color(col: int, val: Any): return _ScopeStyleColor(col, val) class _ScopeStyleColor: def __init__(self, col: int, val: Any): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._col = col self._val = val def __enter__(self): @@ -155,9 +131,6 @@ class _ScopeStyleColor: def style_var(var: int, val: Any): return _ScopeStyleVar(var, val) class _ScopeStyleVar: def __init__(self, var: int, val: Any): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._var = var self._val = val def __enter__(self): @@ -169,9 +142,6 @@ class _ScopeStyleVar: def table(name: str, columns: int, flags: int = 0): return _ScopeTable(name, columns, flags) class _ScopeTable: def __init__(self, name: str, columns: int, flags: int): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._name = name self._columns = columns self._flags = flags @@ -187,9 +157,6 @@ class _ScopeTable: def tab_bar(id_str: str, flags: int = 0): return _ScopeTabBar(id_str, flags) class _ScopeTabBar: def __init__(self, id_str: str, flags: int): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._id = id_str self._flags = flags self._active = False @@ -204,9 +171,6 @@ class _ScopeTabBar: def tab_item(label: str, flags: int = 0): return _ScopeTabItem(label, flags) class _ScopeTabItem: def __init__(self, label: str, flags: int): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._label = label self._flags = flags self._expanded = False @@ -222,9 +186,6 @@ class _ScopeTabItem: def text_wrap(wrap_pos: float = 0.0): return _ScopeTextWrap(wrap_pos) class _ScopeTextWrap: def __init__(self, wrap_pos: float): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._wrap_pos = wrap_pos def __enter__(self): imgui.push_text_wrap_pos(self._wrap_pos) @@ -243,9 +204,6 @@ class _ScopeTooltip: def tree_node_ex(label: str, flags: int = 0): return _ScopeTreeNodeEx(label, flags) class _ScopeTreeNodeEx: def __init__(self, label: str, flags: int): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._label = label self._flags = flags self._opened = False @@ -260,9 +218,6 @@ class _ScopeTreeNodeEx: def window(name: str, visible: bool = True, flags: int = 0): return _ScopeWindow(name, visible, flags) class _ScopeWindow: def __init__(self, name: str, visible: bool, flags: int): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self._name = name self._visible = visible self._flags = flags diff --git a/src/layouts.py b/src/layouts.py index c13de356..0904a001 100644 --- a/src/layouts.py +++ b/src/layouts.py @@ -15,8 +15,7 @@ class LayoutFile: intended to be installed to cwd/manualslop_layout.ini by App._post_init when the user's INI is empty or missing. The raw text is opaque to this module; structure parsing (ImGui sections, [Window] entries) - is the consumer's responsibility. - [C: src/layouts.py:load_layouts_from_dir, src/gui_2.py:_install_default_layout_if_empty]""" + is the consumer's responsibility.""" name: str raw_text: str source_path: Path @@ -25,8 +24,7 @@ class LayoutFile: def load_layouts_from_file(path: Path, scope: str) -> dict[str, LayoutFile]: """Load ONE layout file and return a 1-entry dict. Public API matches - themes' load_themes_from_toml shape (dict out). - [C: src/layouts.py:load_layouts_from_dir]""" + themes' load_themes_from_toml shape (dict out).""" out: dict[str, LayoutFile] = {} if not path.exists() or not path.is_file(): return out @@ -45,8 +43,7 @@ def load_layouts_from_dir(path: Path, scope: str) -> dict[str, LayoutFile]: or all-skip (per the 'delete to turn off' pattern in conductor/code_styleguides/feature_flags.md). Per-file errors are drained via Result + stderr warn, mirroring - src/theme_models.py:load_themes_from_dir. - [C: src/layouts.py:load_layouts_from_disk]""" + src/theme_models.py:load_themes_from_dir.""" out: dict[str, LayoutFile] = {} if not path.exists() or not path.is_dir(): return out @@ -73,8 +70,7 @@ def load_layouts_from_disk() -> dict[str, LayoutFile]: """Load all bundled layouts from the global layouts dir (resolved via src/paths.py:get_layouts_dir()). Cached at the module level; callers iterate the returned dict. The 'delete to - turn off' guarantee: a missing or empty layouts/ dir returns {}. - [C: src/gui_2.py:_install_default_layout_if_empty]""" + turn off' guarantee: a missing or empty layouts/ dir returns {}.""" global _LAYOUTS_CACHE layouts_dir = get_layouts_dir() _LAYOUTS_CACHE = load_layouts_from_dir(layouts_dir, scope="global") diff --git a/src/log_pruner.py b/src/log_pruner.py index 7a94da09..d5c27b34 100644 --- a/src/log_pruner.py +++ b/src/log_pruner.py @@ -22,7 +22,6 @@ class LogPruner: Args: log_registry: An instance of LogRegistry to check session data. logs_dir: The path to the directory containing session sub-directories. - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] """ self.log_registry = log_registry self.logs_dir = logs_dir @@ -35,7 +34,6 @@ class LogPruner: 1. The session start time is older than max_age_days. 2. The session name is NOT in the whitelist provided by the LogRegistry. 3. The total size of all files within the session directory is less than min_size_kb. - [C: tests/test_log_pruner.py:test_prune_old_insignificant_logs, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_handles_relative_paths_starting_with_logs, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_empty_sessions_regardless_of_age, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_sessions_without_metadata_regardless_of_age, tests/test_logging_e2e.py:test_logging_e2e] """ now = datetime.now() cutoff_time = now - timedelta(days=max_age_days) diff --git a/src/log_registry.py b/src/log_registry.py index aa074160..46f5d426 100644 --- a/src/log_registry.py +++ b/src/log_registry.py @@ -145,7 +145,6 @@ class LogRegistry: Args: registry_path (str): The file path to the TOML registry. - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] """ self.registry_path = registry_path self.data: dict[str, Session] = {} @@ -188,7 +187,6 @@ class LogRegistry: """ Serializes and saves the current registry data to the TOML file. Converts internal datetime objects to ISO format strings for compatibility. - [C: tests/test_logging_e2e.py:test_logging_e2e] """ try: # Convert datetime objects to ISO format strings for TOML serialization @@ -228,7 +226,6 @@ class LogRegistry: session_id (str): Unique identifier for the session. path (str): File path to the session's log directory. start_time (datetime|str): The timestamp when the session started. - [C: src/session_logger.py:open_session, tests/test_auto_whitelist.py:test_auto_whitelist_keywords, tests/test_auto_whitelist.py:test_auto_whitelist_large_size, tests/test_auto_whitelist.py:test_auto_whitelist_message_count, tests/test_auto_whitelist.py:test_no_auto_whitelist_insignificant, tests/test_log_pruner.py:test_prune_old_insignificant_logs, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_get_old_non_whitelisted_sessions_includes_empty_sessions, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_get_old_non_whitelisted_sessions_includes_sessions_without_metadata, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_handles_relative_paths_starting_with_logs, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_empty_sessions_regardless_of_age, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_sessions_without_metadata_regardless_of_age, tests/test_log_registry.py:TestLogRegistry.test_get_old_non_whitelisted_sessions, tests/test_log_registry.py:TestLogRegistry.test_is_session_whitelisted, tests/test_log_registry.py:TestLogRegistry.test_register_session, tests/test_log_registry.py:TestLogRegistry.test_update_session_metadata, tests/test_logging_e2e.py:test_logging_e2e] """ if session_id in self.data: print(f"Warning: Session ID '{session_id}' already exists. Overwriting.") @@ -257,7 +254,6 @@ class LogRegistry: size_kb (int): Total size of the session logs in kilobytes. whitelisted (bool): Whether the session should be protected from pruning. reason (str): Explanation for the current whitelisting status. - [C: tests/test_auto_whitelist.py:test_auto_whitelist_large_size, tests/test_auto_whitelist.py:test_auto_whitelist_message_count, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_get_old_non_whitelisted_sessions_includes_empty_sessions, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_empty_sessions_regardless_of_age, tests/test_log_registry.py:TestLogRegistry.test_get_old_non_whitelisted_sessions, tests/test_log_registry.py:TestLogRegistry.test_is_session_whitelisted, tests/test_log_registry.py:TestLogRegistry.test_update_session_metadata] """ if session_id not in self.data: print(f"Error: Session ID '{session_id}' not found for metadata update.") @@ -291,7 +287,6 @@ class LogRegistry: Args: session_id (str): Unique identifier for the session. start_time (datetime|str): The new start timestamp. - [C: tests/test_logging_e2e.py:test_logging_e2e] """ if session_id not in self.data: print(f"Error: Session ID '{session_id}' not found for start_time update.") @@ -319,7 +314,6 @@ class LogRegistry: Returns: bool: True if whitelisted, False otherwise. - [C: tests/test_auto_whitelist.py:test_auto_whitelist_keywords, tests/test_auto_whitelist.py:test_auto_whitelist_large_size, tests/test_auto_whitelist.py:test_auto_whitelist_message_count, tests/test_no_auto_whitelist_insignificant, tests/test_log_registry.py:TestLogRegistry.test_is_session_whitelisted, tests/test_logging_e2e.py:test_logging_e2e] """ session = self.data.get(session_id) if session is None: @@ -334,7 +328,6 @@ class LogRegistry: Args: session_id (str): Unique identifier for the session to analyze. - [C: src/session_logger.py:close_session] """ if session_id not in self.data: return @@ -398,7 +391,6 @@ class LogRegistry: Returns: list: A list of dictionaries containing session details (id, path, start_time). - [C: tests/test_log_pruner.py:test_prune_old_insignificant_logs, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_get_old_non_whitelisted_sessions_includes_empty_sessions, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_get_old_non_whitelisted_sessions_includes_sessions_without_metadata, tests/test_log_registry.py:TestLogRegistry.test_get_old_non_whitelisted_sessions] """ old_sessions = [] for session_id, session in self.data.items(): diff --git a/src/markdown_helper.py b/src/markdown_helper.py index 0eb866d7..b09774d4 100644 --- a/src/markdown_helper.py +++ b/src/markdown_helper.py @@ -64,9 +64,6 @@ class MarkdownRenderer: and ImGuiColorTextEdit for syntax-highlighted code blocks. """ def __init__(self): - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self.options = imgui_md.MarkdownOptions() # Base path for fonts (Inter family) self.options.font_options.font_base_path = "fonts/Inter" @@ -126,10 +123,7 @@ class MarkdownRenderer: print(f"Error opening link {url}: {e}") def render(self, text: str, context_id: str = "default") -> None: - """ - Render Markdown text with code block interception and GFM table substitution. - [C: src/theme_2.py:render_post_fx, tests/test_theme_nerv_alert.py:test_alert_pulsing_render_active, tests/test_theme_nerv_alert.py:test_alert_pulsing_render_inactive, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_alert_pulsing_render, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_crt_filter_disabled, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_crt_filter_render] - """ + """Render Markdown text with code block interception and GFM table substitution.""" # Lazy lookup of src.markdown_table (Phase 5C). Warmup has already loaded # it on AppController's _io_pool, so this is an O(1) sys.modules get. markdown_table = _require_warmed("src.markdown_table") @@ -221,7 +215,6 @@ class MarkdownRenderer: next Y. The '-' delimiter uses Text+SameLine which works correctly. Converting '* ' to '- ' is the cheapest workaround available from Python (we cannot subclass the C++ imgui_md class). - [C: src/markdown_helper.py:MarkdownRenderer.render] """ return re.sub(r"(?m)^([ \t]*)\*[ \t]+", r"\1- ", text) @@ -233,7 +226,6 @@ class MarkdownRenderer: endings, no NewLine is emitted, so the next text starts at the same Y as the last list item (overlap). Inserting a blank line forces a paragraph break. Cannot fix the upstream C++ from Python. - [C: src/markdown_helper.py:MarkdownRenderer.render] """ lines = text.split("\n") out: list[str] = [] @@ -267,7 +259,6 @@ class MarkdownRenderer: continuation of the first paragraph (single BLOCK_P, proper line wrap, no overlap). Trade-off: the user cannot have separate paragraphs within a single list item. Acceptable for our use case. - [C: src.markdown_helper:MarkdownRenderer.render] """ lines = text.split("\n") out: list[str] = [] @@ -396,9 +387,6 @@ def get_renderer() -> MarkdownRenderer: return _renderer def render(text: str, context_id: str = "default") -> None: - """ - [C: src/theme_2.py:render_post_fx, tests/test_theme_nerv_alert.py:test_alert_pulsing_render_active, tests/test_theme_nerv_alert.py:test_alert_pulsing_render_inactive, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_alert_pulsing_render, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_crt_filter_disabled, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_crt_filter_render] - """ get_renderer().render(text, context_id) def render_unindented(text: str) -> None: diff --git a/src/markdown_table.py b/src/markdown_table.py index 9dfad20d..d3d8b4a7 100644 --- a/src/markdown_table.py +++ b/src/markdown_table.py @@ -7,9 +7,7 @@ from imgui_bundle import imgui, imgui_md _TABLE_SEPARATOR = re.compile(r"^\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?\s*$") def render_table(block: "TableBlock") -> None: - """Render a GFM table block via imgui.begin_table. - [C: src/markdown_helper.py:MarkdownRenderer.render] - """ + """Render a GFM table block via imgui.begin_table.""" n_cols = len(block.headers) if n_cols == 0: return flags = imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable @@ -26,9 +24,7 @@ def render_table(block: "TableBlock") -> None: @dataclass(frozen=True) class TableBlock: - """Frozen GFM table block. - [C: src/markdown_helper.py:MarkdownRenderer.render] - """ + """Frozen GFM table block.s""" headers: list[str] rows: list[list[str]] span: tuple[int, int] diff --git a/src/mcp_client.py b/src/mcp_client.py index 0c770f31..5493af76 100644 --- a/src/mcp_client.py +++ b/src/mcp_client.py @@ -228,7 +228,6 @@ def configure(file_items: list[dict[str, Any]], extra_base_dirs: list[str] | Non file_items : list of dicts from aggregate.build_file_items() extra_base_dirs : additional directory roots to allow traversal of - [C: tests/conftest.py:reset_ai_client, tests/test_arch_boundary_phase1.py:TestArchBoundaryPhase1.test_mcp_client_whitelist_enforcement, tests/test_mcp_client_beads.py:test_bd_mcp_tools, tests/test_py_struct_tools.py:test_mcp_dispatch_errors, tests/test_py_struct_tools.py:test_mcp_dispatch_integration] """ global _allowed_paths, _base_dirs, _primary_base_dir _allowed_paths = set() @@ -259,7 +258,6 @@ def _is_allowed(path: Path) -> bool: symlink-based path traversal. CRITICAL: Blacklisted files (history) are NEVER allowed. - [C: tests/test_arch_boundary_phase1.py:TestArchBoundaryPhase1.test_mcp_client_whitelist_enforcement, tests/test_history_management.py:test_mcp_blacklist] """ from src.paths import get_config_path, get_credentials_path @@ -1338,8 +1336,7 @@ def ts_c_update_definition(path: str, name: str, new_content: str) -> str: def ts_cpp_get_skeleton(path: str) -> str: """ - Returns a skeleton of a C++ file. - [C: tests/test_gencpp_full_suite.py:test_gencpp_full_suite, tests/test_ts_cpp_tools.py:test_exhaustive_cpp_samples, tests/test_ts_cpp_tools.py:test_exhaustive_gencpp_samples, tests/test_ts_cpp_tools.py:test_ts_cpp_get_skeleton] + Returns a skeleton of a C++ file. Thin wrapper over ts_cpp_get_skeleton_result; the legacy str shape is preserved for backward compatibility, but the try/except Exception @@ -1352,8 +1349,7 @@ def ts_cpp_get_skeleton(path: str) -> str: def ts_cpp_get_code_outline(path: str) -> str: """ - Returns a hierarchical outline of a C++ file. - [C: tests/test_gencpp_full_suite.py:test_gencpp_full_suite, tests/test_ts_cpp_tools.py:test_exhaustive_cpp_samples, tests/test_ts_cpp_tools.py:test_exhaustive_gencpp_samples, tests/test_ts_cpp_tools.py:test_ts_cpp_get_code_outline] + Returns a hierarchical outline of a C++ file. Thin wrapper over ts_cpp_get_code_outline_result; the legacy str shape is preserved for backward compatibility, but the try/except Exception @@ -1723,7 +1719,6 @@ def fetch_url(url: str) -> str: def get_ui_performance() -> str: """ Returns current UI performance metrics (FPS, Frame Time, CPU, Input Lag). - [C: tests/test_mcp_perf_tool.py:test_mcp_perf_tool_retrieval] Thin wrapper over get_ui_performance_result; the legacy str shape is preserved for backward compatibility, but the try/except Exception @@ -1750,9 +1745,6 @@ class StdioMCPServer: return self._id_counter async def start(self): - """ - [C: src/multi_agent_conductor.py:WorkerPool.spawn, src/performance_monitor.py:PerformanceMonitor.__init__, tests/test_ai_client_concurrency.py:test_ai_client_tier_isolation, tests/test_conductor_engine_abort.py:test_kill_worker_sets_abort_and_joins_thread, tests/test_conductor_engine_v2.py:side_effect, tests/test_spawn_interception_v2.py:test_confirm_spawn_pushed_to_queue, tests/test_websocket_server.py:test_websocket_subscription_and_broadcast] - """ self.status = 'starting' self.proc = await asyncio.create_subprocess_exec( self.config.command, @@ -1767,8 +1759,6 @@ class StdioMCPServer: async def stop(self): """ - [C: tests/test_performance_monitor.py:test_perf_monitor_basic_timing, tests/test_performance_monitor.py:test_perf_monitor_component_timing, tests/test_performance_monitor.py:test_perf_monitor_extended_metrics, tests/test_performance_monitor.py:test_perf_monitor_scope_context_manager, tests/test_websocket_server.py:test_websocket_subscription_and_broadcast] - Best-effort cleanup. Errors during cleanup are accumulated as ErrorInfo and surfaced via the [MCP::stop-warning] drain (consistent with _read_stderr which also uses print() as a stderr/stdout drain for visibility). @@ -1836,10 +1826,7 @@ class ExternalMCPManager: self.servers = {} async def add_server(self, config: MCPServerConfig): - """ - Add and start a new MCP server from a configuration object. - [C: tests/test_external_mcp.py:test_external_mcp_real_process, tests/test_external_mcp.py:test_get_tool_schemas_includes_external] - """ + """Add and start a new MCP server from a configuration object.""" if config.url: # RemoteMCPServer placeholder return @@ -1848,19 +1835,13 @@ class ExternalMCPManager: self.servers[config.name] = server async def stop_all(self): - """ - Stop all managed MCP servers and clear the registry. - [C: tests/test_external_mcp.py:test_external_mcp_real_process, tests/test_external_mcp.py:test_get_tool_schemas_includes_external, tests/test_external_mcp_e2e.py:test_external_mcp_e2e_refresh_and_call] - """ + """Stop all managed MCP servers and clear the registry.""" for server in self.servers.values(): await server.stop() self.servers = {} def get_all_tools(self) -> dict: - """ - Retrieve a dictionary of all tools available across all managed servers. - [C: tests/test_external_mcp.py:test_external_mcp_real_process, tests/test_external_mcp_e2e.py:test_external_mcp_e2e_refresh_and_call] - """ + """Retrieve a dictionary of all tools available across all managed servers.""" all_tools = {} for sname, server in self.servers.items(): for tname, tool in server.tools.items(): @@ -1872,10 +1853,7 @@ class ExternalMCPManager: return {name: server.status for name, server in self.servers.items()} async def async_dispatch(self, tool_name: str, tool_input: dict) -> str: - """ - Dispatch a tool call to the appropriate external MCP server asynchronously. - [C: src/rag_engine.py:RAGEngine._async_search_mcp, tests/test_external_mcp.py:test_external_mcp_real_process] - """ + """Dispatch a tool call to the appropriate external MCP server asynchronously.""" for server in self.servers.values(): if tool_name in server.tools: return await server.call_tool(tool_name, tool_input) @@ -1884,18 +1862,12 @@ class ExternalMCPManager: _external_mcp_manager = ExternalMCPManager() def get_external_mcp_manager() -> ExternalMCPManager: - """ - Retrieve the global ExternalMCPManager instance. - [C: tests/test_external_mcp.py:test_get_tool_schemas_includes_external, tests/test_external_mcp_e2e.py:test_external_mcp_e2e_refresh_and_call] - """ + """Retrieve the global ExternalMCPManager instance.""" global _external_mcp_manager return _external_mcp_manager def dispatch(tool_name: str, tool_input: dict[str, Any]) -> str: - """ - Dispatch an MCP tool call by name. Returns the result as a string. - [C: tests/test_gemini_cli_edge_cases.py:test_gemini_cli_parameter_resilience, tests/test_mcp_client_beads.py:test_bd_mcp_tools, tests/test_mcp_ts_integration.py:test_ts_c_get_code_outline_dispatch, tests/test_mcp_ts_integration.py:test_ts_c_get_definition_dispatch, tests/test_mcp_ts_integration.py:test_ts_c_get_signature_dispatch, tests/test_mcp_ts_integration.py:test_ts_c_get_skeleton_dispatch, tests/test_mcp_ts_integration.py:test_ts_c_update_definition_dispatch, tests/test_mcp_ts_integration.py:test_ts_cpp_get_code_outline_dispatch, tests/test_mcp_ts_integration.py:test_ts_cpp_get_definition_dispatch, tests/test_mcp_ts_integration.py:test_ts_cpp_get_signature_dispatch, tests/test_mcp_ts_integration.py:test_ts_cpp_get_skeleton_dispatch, tests/test_mcp_ts_integration.py:test_ts_cpp_update_definition_dispatch, tests/test_py_struct_tools.py:test_mcp_dispatch_errors, tests/test_py_struct_tools.py:test_mcp_dispatch_integration] - """ + """Dispatch an MCP tool call by name. Returns the result as a string.""" # py_struct_tools is loaded on-demand to keep the main-thread import graph lean. from scripts import py_struct_tools # Handle aliases @@ -2062,9 +2034,6 @@ def dispatch(tool_name: str, tool_input: dict[str, Any]) -> str: async def async_dispatch(tool_name: str, tool_input: dict[str, Any]) -> str: # Check native tools - """ - [C: src/rag_engine.py:RAGEngine._async_search_mcp, tests/test_external_mcp.py:test_external_mcp_real_process] - """ native_names = mcp_tool_specs.tool_names() if tool_name in native_names: return await asyncio.to_thread(dispatch, tool_name, tool_input) @@ -2076,9 +2045,6 @@ async def async_dispatch(tool_name: str, tool_input: dict[str, Any]) -> str: return f'ERROR: unknown MCP tool {tool_name}' def get_tool_schemas() -> list[dict[str, Any]]: - """ - [C: tests/test_arch_boundary_phase2.py:TestArchBoundaryPhase2.test_mcp_client_dispatch_completeness, tests/test_external_mcp.py:test_get_tool_schemas_includes_external, tests/test_mcp_client_beads.py:test_bd_mcp_tools] - """ res = [t.to_dict() for t in mcp_tool_specs.get_tool_schemas()] manager = get_external_mcp_manager() for tname, tinfo in manager.get_all_tools().items():