code-context-control 2.126.1__tar.gz → 2.128.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {code_context_control-2.126.1 → code_context_control-2.128.1}/PKG-INFO +3 -1
- {code_context_control-2.126.1 → code_context_control-2.128.1}/README.md +2 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/_hook_utils.py +22 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/c3.py +41 -7
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/commands/parser.py +12 -0
- code_context_control-2.128.1/cli/hook_session_open.py +199 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_server.py +232 -49
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/hub_access.js +111 -11
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/project_card.js +6 -1
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/mcp_server.py +36 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/server.py +7 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/code_context_control.egg-info/PKG-INFO +3 -1
- {code_context_control-2.126.1 → code_context_control-2.128.1}/code_context_control.egg-info/SOURCES.txt +7 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/mobile_api.py +72 -1
- {code_context_control-2.126.1 → code_context_control-2.128.1}/pyproject.toml +1 -1
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/activity_log.py +48 -0
- code_context_control-2.128.1/services/override_costs.py +183 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/project_manager.py +263 -25
- code_context_control-2.128.1/services/session_live.py +139 -0
- code_context_control-2.128.1/tests/test_activity_log_find_last.py +96 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_session_end.py +125 -0
- code_context_control-2.128.1/tests/test_hub_hook_migration.py +230 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_override_routes.py +73 -0
- code_context_control-2.128.1/tests/test_mobile_override_costs.py +252 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mobile_override_routes.py +49 -0
- code_context_control-2.128.1/tests/test_override_costs.py +320 -0
- code_context_control-2.128.1/tests/test_project_manager.py +374 -0
- code_context_control-2.128.1/tests/test_session_live.py +142 -0
- code_context_control-2.126.1/cli/hook_session_open.py +0 -97
- code_context_control-2.126.1/tests/test_project_manager.py +0 -134
- {code_context_control-2.126.1 → code_context_control-2.128.1}/LICENSE +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/_shell_writes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/commands/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/commands/common.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/docs.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/edits.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/access.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/credentials.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/index.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/masking.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/oracle.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/shared.css +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/tools.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/guide/workflow.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_artifact.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_c3read.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_codex_lifecycle.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_filter.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_read.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_session_end.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/hub_ui.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/progress.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/_grants.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/agent.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/ci.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/compress.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/credentials.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/delegate.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/edit.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/edits.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/federate.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/filter.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/impact.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/jira.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/locks.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/memory.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/override.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/project.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/read.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/search.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/session.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/shell.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/shell_job.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/shell_nudge.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/shell_parsers.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/shell_render.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/status.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/tasks.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/tools/validate.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/api.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/app.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/access.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/icons.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/shared.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui/theme.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui_legacy.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/cli/ui_nano.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/core/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/core/codex_patch.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/core/config.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/core/host.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/core/ide.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/core/mcp_toml.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/core/web_security.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/config.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/listeners.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/oracle_server.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/client_tokens.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/local_session.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/activity.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/agents.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/app.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/busy.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/core.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/header.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/insights.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/projects.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/settings.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/access_guard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/access_telemetry.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/agent_base.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/agent_locks.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/agents.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/artifact_defs.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/artifact_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/atomic_json.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/auto_memory.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/background_service.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bench/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bench/map_eval.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bench/search_eval.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bench/shell_eval.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bitbucket_client.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_act.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_cache.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_expr.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_failures.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_github.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_impact.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_intel.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_runner.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ci_workflow.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/circuit_breaker.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/claude_md.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/codex_integration.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/codex_transcript.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/compressor.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/context_snapshot.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/conversation_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/cred_audit.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/cred_telemetry.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/credential_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/dir_map.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/doc_index.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/e2e_tasks.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/edit_ledger.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/embedding_index.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/enforcement_policy.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/error_reporting.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/file_map.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/file_memory.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/git_context.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/host_sessions.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/hub_service.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/index_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/indexer.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/jira_client.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/jira_cloud.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/jira_credentials.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/jira_data_center.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/jira_links.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/lexical_index.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/mask_activation.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/mask_mirror.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/mask_presets.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/memory.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/memory_consolidator.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/memory_distiller.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/memory_graph.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/memory_grounder.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/memory_queue.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/memory_scorer.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/metrics.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/notifications.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ollama_bridge.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ollama_client.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/ollama_credentials.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/oracle_service.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/output_filter.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/override_grants.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/override_policy.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/override_requests.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/override_wake.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/parser.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/project_runtime.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/protocol.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/proxy_state.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/repo_map.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/repo_shape.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/reranker.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/retention.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/retrieval.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/retrieval_broker.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/router.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/runtime.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/scanner.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/session_benchmark.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/session_manager.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/session_preloader.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/shell_jobs.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/shell_output.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/subprojects.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/task_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/telemetry.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/text_index.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/time_tracker.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/tool_classifier.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/transcript_index.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/validation_cache.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/vector_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/watcher.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/services/win_subprocess.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/setup.cfg +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_access_guard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_atomic_json.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_background_service.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_builtin_modes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ci_act.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_claude_md_updater.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_codex_mcp_transport.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_codex_native.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_confirm_guard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_confirm_guard_wiring.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_cred_audit.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_credential_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_dir_map_c3.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_env_parser.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_file_map_c1.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_state.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_index_cap_not_hardcoded.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_init_scan.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_jira_client.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_jira_links.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_large_files_c4.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_map_eval.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_map_telemetry_c0.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_memory_system.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mobile_clients.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mobile_jobs_ci.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_notification_kinds.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_loopback.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_output_filter.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_override_grants.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_override_requests.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_override_wake.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_permissions.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_pm_api.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_project_tool.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_related_facts.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_repo_map.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_retention.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_review_digest.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_search_eval.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_search_p1.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_search_p2.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_search_p2b.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_search_p3.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_search_p4.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_search_p5.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_service_durability.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_session_budget.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_budget_s1.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_eval.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_jobs_s3.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_nudge_s4.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_output.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_parsers_s2.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_telemetry_s0.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_subproject_clear_scope.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_subproject_depth_consumers.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_subproject_linkage_api.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_subprojects.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_task_store.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_task_tool.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_token_tracking.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_ui_jsx_syntax.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_validate.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_version_sync.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_web_security.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/backend.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/main.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/__init__.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/index_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/init_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/search_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/session_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/stats.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.126.1 → code_context_control-2.128.1}/tui/theme.tcss +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.128.1
|
|
4
4
|
Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -168,6 +168,8 @@ c3 ui # binds the first free port from 3333
|
|
|
168
168
|
|
|
169
169
|
Twelve tabs. The dashboard above shows token savings, indexed files, the live session, and a stream of recent tool calls and file changes.
|
|
170
170
|
|
|
171
|
+
Since v2.128.0 you rarely start it by hand: opening an IDE session in a registered project brings its UI up, and a session proves it is alive with a heartbeat rather than with tool-call traffic — so a quiet session stays live and a closed one disappears at once. Servers a session started are reaped once the session is gone; the ones you started are not. → [Session liveness](https://github.com/drknowhow/code-context-control/blob/main/docs/session-liveness.md)
|
|
172
|
+
|
|
171
173
|
| Tab | What it's for |
|
|
172
174
|
|---|---|
|
|
173
175
|
| **Dashboard** | Token savings, codebase breakdown, live session counters, recent activity |
|
|
@@ -102,6 +102,8 @@ c3 ui # binds the first free port from 3333
|
|
|
102
102
|
|
|
103
103
|
Twelve tabs. The dashboard above shows token savings, indexed files, the live session, and a stream of recent tool calls and file changes.
|
|
104
104
|
|
|
105
|
+
Since v2.128.0 you rarely start it by hand: opening an IDE session in a registered project brings its UI up, and a session proves it is alive with a heartbeat rather than with tool-call traffic — so a quiet session stays live and a closed one disappears at once. Servers a session started are reaped once the session is gone; the ones you started are not. → [Session liveness](https://github.com/drknowhow/code-context-control/blob/main/docs/session-liveness.md)
|
|
106
|
+
|
|
105
107
|
| Tab | What it's for |
|
|
106
108
|
|---|---|
|
|
107
109
|
| **Dashboard** | Token savings, codebase breakdown, live session counters, recent activity |
|
|
@@ -8,6 +8,7 @@ All hook reads/writes of enforcement state MUST go through this module.
|
|
|
8
8
|
import json
|
|
9
9
|
import os
|
|
10
10
|
import re
|
|
11
|
+
import shlex
|
|
11
12
|
import sys
|
|
12
13
|
import traceback
|
|
13
14
|
from datetime import datetime, timezone
|
|
@@ -34,6 +35,27 @@ LEGACY_UNLOCK_FILE = ".c3/unlocked_files.json"
|
|
|
34
35
|
STATE_WARNINGS: list = []
|
|
35
36
|
|
|
36
37
|
|
|
38
|
+
def hook_command_arg(raw) -> str:
|
|
39
|
+
"""Quote one argv element for a hook ``command`` string in settings.
|
|
40
|
+
|
|
41
|
+
Windows: a DOUBLE-quoted forward-slash path. Claude Code runs hooks through
|
|
42
|
+
Git Bash, where ``shlex.quote`` produces SINGLE quotes around a backslash
|
|
43
|
+
path — cmd.exe does not treat single quotes as quoting, so any path with a
|
|
44
|
+
space or parentheses (``Claude Code Companion (C3)``) breaks. A
|
|
45
|
+
double-quoted forward-slash path is parsed correctly by bash AND cmd.
|
|
46
|
+
Verified 2026-07-26 under Git Bash on Windows 11; the installer in
|
|
47
|
+
cli/c3.py carries the full investigation, including why no ``cmd.exe /c``
|
|
48
|
+
wrapper belongs here.
|
|
49
|
+
|
|
50
|
+
Anything that writes a hook command — the installer and the hub's
|
|
51
|
+
migration — must go through this, or the entry it writes is dead on
|
|
52
|
+
Windows.
|
|
53
|
+
"""
|
|
54
|
+
if sys.platform == "win32":
|
|
55
|
+
return '"' + str(raw).replace("\\", "/") + '"'
|
|
56
|
+
return shlex.quote(str(raw))
|
|
57
|
+
|
|
58
|
+
|
|
37
59
|
def ensure_utf8_stdio() -> None:
|
|
38
60
|
"""Force UTF-8 on the hook process's stdio pipes.
|
|
39
61
|
|
|
@@ -33,7 +33,6 @@ import json
|
|
|
33
33
|
import logging
|
|
34
34
|
import os
|
|
35
35
|
import re
|
|
36
|
-
import shlex
|
|
37
36
|
import subprocess
|
|
38
37
|
import sys
|
|
39
38
|
import tempfile
|
|
@@ -92,7 +91,7 @@ console = Console() if HAS_RICH else None
|
|
|
92
91
|
# Config
|
|
93
92
|
CONFIG_DIR = ".c3"
|
|
94
93
|
CONFIG_FILE = ".c3/config.json"
|
|
95
|
-
__version__ = "2.
|
|
94
|
+
__version__ = "2.128.1"
|
|
96
95
|
|
|
97
96
|
|
|
98
97
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -5542,10 +5541,10 @@ def cmd_install_mcp(args):
|
|
|
5542
5541
|
# the wrapper was never needed. A double-quoted forward-slash path is parsed
|
|
5543
5542
|
# correctly by bash AND cmd, including paths containing spaces or parentheses
|
|
5544
5543
|
# (e.g. "Claude Code Companion (C3)"), which is why the wrapper was added.
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5544
|
+
# Lives in cli/_hook_utils so the hub's hook migration quotes commands
|
|
5545
|
+
# the same way — it used shlex.quote and wrote entries that Windows
|
|
5546
|
+
# could not run.
|
|
5547
|
+
from cli._hook_utils import hook_command_arg as _hook_arg
|
|
5549
5548
|
|
|
5550
5549
|
# v2.42: single dispatcher script per hook event instead of N separate
|
|
5551
5550
|
# per-hook commands. One interpreter spawn per event; the dispatcher
|
|
@@ -6968,8 +6967,10 @@ def cmd_override(args):
|
|
|
6968
6967
|
"""
|
|
6969
6968
|
sub = getattr(args, "override_cmd", None)
|
|
6970
6969
|
if not sub:
|
|
6971
|
-
print("Usage: c3 override <policy|grant|list|revoke|check|sweep
|
|
6970
|
+
print("Usage: c3 override <policy|grant|list|revoke|check|sweep|"
|
|
6971
|
+
"requests|approve|deny|costs> ...")
|
|
6972
6972
|
print(" c3 override policy # what is escalatable right now")
|
|
6973
|
+
print(" c3 override costs # which rules keep holding the agent")
|
|
6973
6974
|
return
|
|
6974
6975
|
|
|
6975
6976
|
from services import override_grants as og
|
|
@@ -6998,6 +6999,39 @@ def cmd_override(args):
|
|
|
6998
6999
|
_override_requests(args, project_path)
|
|
6999
7000
|
elif sub in ("approve", "deny"):
|
|
7000
7001
|
_override_decide(args, sub, project_path)
|
|
7002
|
+
elif sub == "costs":
|
|
7003
|
+
_override_costs(args, project_path)
|
|
7004
|
+
|
|
7005
|
+
|
|
7006
|
+
def _override_costs(args, project_path: str) -> None:
|
|
7007
|
+
"""`c3 override costs` — which rules keep holding the agent (§11 T5)."""
|
|
7008
|
+
from services import override_costs as ocost
|
|
7009
|
+
|
|
7010
|
+
days = max(1, int(getattr(args, "days", None) or ocost.DEFAULT_DAYS))
|
|
7011
|
+
everywhere = bool(getattr(args, "all_projects", False))
|
|
7012
|
+
rows = ocost.rule_costs(project_path=None if everywhere else project_path,
|
|
7013
|
+
days=days)
|
|
7014
|
+
print_header(f"Override costs — last {days} day(s)"
|
|
7015
|
+
+ ("" if everywhere else f" · {Path(project_path).name}"))
|
|
7016
|
+
if not rows:
|
|
7017
|
+
print(" (no requests in the window)")
|
|
7018
|
+
return
|
|
7019
|
+
width = max(len(r["rule"]) for r in rows)
|
|
7020
|
+
print(f" {'held':>4} {'ok':>3} {'no':>3} {'exp':>3} {'wait':>4} "
|
|
7021
|
+
f"{'rule':<{width}} suggestion")
|
|
7022
|
+
for r in rows:
|
|
7023
|
+
line = (f" {r['count']:>4} {r['approved']:>3} {r['denied']:>3} "
|
|
7024
|
+
f"{r['expired']:>3} {r['pending']:>4} {r['rule']:<{width}} "
|
|
7025
|
+
f"{r['suggestion']}")
|
|
7026
|
+
if r["count"] >= ocost.NUDGE_THRESHOLD:
|
|
7027
|
+
line += " <- costing you"
|
|
7028
|
+
print(line)
|
|
7029
|
+
if everywhere:
|
|
7030
|
+
print(f" {'':22s} {r['project_path']}")
|
|
7031
|
+
print("\n held = requests filed; ok/no/exp/wait = approved/denied/"
|
|
7032
|
+
"expired/still pending (withdrawn counts in held only).")
|
|
7033
|
+
print(" A rule you keep approving is friction: edit it with `c3 access`. "
|
|
7034
|
+
"A rule you keep denying is working — mute the session instead.")
|
|
7001
7035
|
|
|
7002
7036
|
|
|
7003
7037
|
def _override_requests(args, project_path: str) -> None:
|
|
@@ -779,6 +779,18 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
779
779
|
ov_deny.add_argument("--path", dest="project_path", default=".",
|
|
780
780
|
help="Project directory (default: current)")
|
|
781
781
|
|
|
782
|
+
# Costs: which rules keep asking (spec §11 Threat 5, v2.127.0). A read
|
|
783
|
+
# over the request store — it decides nothing and edits no rule.
|
|
784
|
+
ov_costs = override_subs.add_parser(
|
|
785
|
+
"costs", help="Which rules held the agent most, and how you answered"
|
|
786
|
+
)
|
|
787
|
+
ov_costs.add_argument("--days", type=int, default=7,
|
|
788
|
+
help="Trailing window in days (default 7)")
|
|
789
|
+
ov_costs.add_argument("--all", dest="all_projects", action="store_true",
|
|
790
|
+
help="Every project, not just this one")
|
|
791
|
+
ov_costs.add_argument("--path", dest="project_path", default=".",
|
|
792
|
+
help="Project directory (default: current)")
|
|
793
|
+
|
|
782
794
|
# ── Tool discipline / enforcement mode (v2.66.0) ────────────────────
|
|
783
795
|
# LAYER C: how hard C3 pushes the agent toward c3_* tools. Distinct from
|
|
784
796
|
# `c3 access` (path policy — a security boundary) and from
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"""SessionStart hook: record that a host session opened (D0b, v2.126.0).
|
|
2
|
+
|
|
3
|
+
Claude Code's ``SessionStart`` event delivers on stdin::
|
|
4
|
+
|
|
5
|
+
{
|
|
6
|
+
"session_id": "<Claude Code UUID>",
|
|
7
|
+
"transcript_path": "...",
|
|
8
|
+
"cwd": "...",
|
|
9
|
+
"hook_event_name": "SessionStart",
|
|
10
|
+
"source": "startup" | "resume" | "clear" | "compact"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
Codex's ``SessionStart`` carries its thread id in the same ``session_id``
|
|
14
|
+
field and no ``source``; the dispatcher routes both here (event ``start``).
|
|
15
|
+
|
|
16
|
+
Records:
|
|
17
|
+
|
|
18
|
+
- ``{type: "session_open", host_session_id, source: <host>, start_source}``
|
|
19
|
+
in ``.c3/activity_log.jsonl``. ``source`` is the HOST (``claude`` /
|
|
20
|
+
``codex`` / ``gemini``), matching ``session_end``; the payload's own
|
|
21
|
+
``source`` (startup / resume / clear) is kept as ``start_source``.
|
|
22
|
+
- a ``session`` notification (``kind="session"``, ``ref_id=host id``,
|
|
23
|
+
``info``, title ``Session started <short id>``).
|
|
24
|
+
|
|
25
|
+
It also brings up the project's UI server when one is not already running
|
|
26
|
+
(``ensure_ui`` below, v2.128.0) — the only place in C3 where "a session
|
|
27
|
+
started" causes "the UI is up". It needs the project to be registered with
|
|
28
|
+
the hub, and it skips a project that already has a live UI port, so a
|
|
29
|
+
``resume`` or ``clear`` never stacks a second server. Opt out with
|
|
30
|
+
``C3_NO_UI_AUTOSTART=1`` or
|
|
31
|
+
``.c3/config.json → {"ui": {"autostart_on_session": false}}``.
|
|
32
|
+
|
|
33
|
+
``source: "compact"`` writes NOTHING: a compaction is the same session and
|
|
34
|
+
the same MCP process, and a "Session started" toast on every compaction
|
|
35
|
+
would teach the user to ignore the real ones.
|
|
36
|
+
|
|
37
|
+
The MCP server's own ``session_start`` row is untouched — it carries the C3
|
|
38
|
+
id and, when the host put its id in the environment, ``host_session_id``
|
|
39
|
+
too. This hook is what lets a client see the session before the runtime has
|
|
40
|
+
finished starting (~seconds), and it is the row the desktop's "MCP failed to
|
|
41
|
+
connect" sentinel starts its 30 s clock from.
|
|
42
|
+
|
|
43
|
+
Returns None always: SessionStart hook stdout becomes model context, and
|
|
44
|
+
this hook has nothing to tell the model.
|
|
45
|
+
"""
|
|
46
|
+
from __future__ import annotations
|
|
47
|
+
|
|
48
|
+
import json
|
|
49
|
+
import os
|
|
50
|
+
import sys
|
|
51
|
+
from pathlib import Path
|
|
52
|
+
|
|
53
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
54
|
+
|
|
55
|
+
from cli._hook_utils import detect_host, find_project, log_hook_error # noqa: E402
|
|
56
|
+
from cli.hook_session_end import short_id # noqa: E402
|
|
57
|
+
|
|
58
|
+
_SILENT_SOURCES = {"compact"}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _ui_autostart_enabled(project: Path) -> bool:
|
|
62
|
+
"""Opt-outs, in the order a user reaches for them."""
|
|
63
|
+
if os.environ.get("C3_NO_UI_AUTOSTART") or os.environ.get("C3_BENCHMARK_MODE"):
|
|
64
|
+
return False
|
|
65
|
+
try:
|
|
66
|
+
cfg = json.loads((project / ".c3" / "config.json").read_text(encoding="utf-8"))
|
|
67
|
+
except Exception:
|
|
68
|
+
return True # no readable config is not a reason to withhold the UI
|
|
69
|
+
ui = cfg.get("ui")
|
|
70
|
+
if isinstance(ui, dict) and "autostart_on_session" in ui:
|
|
71
|
+
return bool(ui.get("autostart_on_session"))
|
|
72
|
+
return True
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _is_registered(pm, project: Path) -> bool:
|
|
76
|
+
"""True when the hub knows this project.
|
|
77
|
+
|
|
78
|
+
The UI server is a hub-level surface: a directory the user never
|
|
79
|
+
registered gets nothing automatic (``c3 ui`` still works). This is also
|
|
80
|
+
what keeps a test fixture or a scratch clone from growing a web server.
|
|
81
|
+
"""
|
|
82
|
+
target = os.path.normcase(str(project))
|
|
83
|
+
for entry in pm._read_projects():
|
|
84
|
+
raw = str(entry.get("path") or "")
|
|
85
|
+
if raw and os.path.normcase(raw) == target:
|
|
86
|
+
return True
|
|
87
|
+
try:
|
|
88
|
+
if raw and os.path.normcase(str(Path(raw).resolve())) == target:
|
|
89
|
+
return True
|
|
90
|
+
except Exception:
|
|
91
|
+
continue
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _ui_running(pm, project: Path) -> bool:
|
|
96
|
+
"""True when a live UI server is already registered for this project.
|
|
97
|
+
|
|
98
|
+
This is what keeps `resume` / `clear` — both real SessionStart events —
|
|
99
|
+
from stacking a second server on every reconnect.
|
|
100
|
+
"""
|
|
101
|
+
target = os.path.normcase(str(project))
|
|
102
|
+
for entry in pm._read_registry():
|
|
103
|
+
raw = str(entry.get("project_path") or "")
|
|
104
|
+
if not raw:
|
|
105
|
+
continue
|
|
106
|
+
try:
|
|
107
|
+
same = os.path.normcase(str(Path(raw).resolve())) == target
|
|
108
|
+
except Exception:
|
|
109
|
+
same = os.path.normcase(raw) == target
|
|
110
|
+
if same and entry.get("port") and pm._port_alive(entry["port"]):
|
|
111
|
+
return True
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def ensure_ui(project: Path, host_session_id: str = "") -> str:
|
|
116
|
+
"""Bring up this project's UI server for the session that just opened.
|
|
117
|
+
|
|
118
|
+
Nothing else in C3 connected "a session started" to "the UI is running":
|
|
119
|
+
the hub's sweep only chases projects flagged `autostart_ui`, and before
|
|
120
|
+
2.128.0 it ran once at hub startup — so a UI was only ever there because
|
|
121
|
+
an earlier session had left one behind.
|
|
122
|
+
|
|
123
|
+
Returns a short reason string (tests and diagnostics read it). Never
|
|
124
|
+
raises and never prints — SessionStart stdout becomes model context.
|
|
125
|
+
"""
|
|
126
|
+
try:
|
|
127
|
+
project = Path(project).resolve()
|
|
128
|
+
except Exception:
|
|
129
|
+
project = Path(project)
|
|
130
|
+
if not _ui_autostart_enabled(project):
|
|
131
|
+
return "disabled"
|
|
132
|
+
try:
|
|
133
|
+
from services.project_manager import ProjectManager
|
|
134
|
+
pm = ProjectManager()
|
|
135
|
+
if not _is_registered(pm, project):
|
|
136
|
+
return "unregistered"
|
|
137
|
+
if _ui_running(pm, project):
|
|
138
|
+
return "already-running"
|
|
139
|
+
# launch_session copies os.environ into the detached child, which is
|
|
140
|
+
# where cli/server._register_session reads the ownership from.
|
|
141
|
+
os.environ["C3_UI_OWNER"] = "session"
|
|
142
|
+
if host_session_id:
|
|
143
|
+
os.environ["C3_UI_OWNER_SESSION"] = host_session_id
|
|
144
|
+
result = pm.launch_session(str(project))
|
|
145
|
+
if result.get("launched"):
|
|
146
|
+
return "launched"
|
|
147
|
+
return f"failed: {result.get('error', '')}".strip()
|
|
148
|
+
except Exception as exc:
|
|
149
|
+
log_hook_error("hook_session_open", exc)
|
|
150
|
+
return "error"
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def run(payload: dict, project_path: Path | None = None):
|
|
154
|
+
"""Core logic — importable by the dispatcher and tests. Returns None."""
|
|
155
|
+
start_source = str(payload.get("source") or "").strip().lower()
|
|
156
|
+
if start_source in _SILENT_SOURCES:
|
|
157
|
+
return None
|
|
158
|
+
project = find_project(payload, project_path)
|
|
159
|
+
if project is None:
|
|
160
|
+
return None
|
|
161
|
+
host = detect_host(payload)
|
|
162
|
+
host_sid = str(payload.get("session_id") or "").strip()
|
|
163
|
+
try:
|
|
164
|
+
from services.activity_log import ActivityLog
|
|
165
|
+
ActivityLog(str(project)).log("session_open", {
|
|
166
|
+
"host_session_id": host_sid,
|
|
167
|
+
"source": host,
|
|
168
|
+
"start_source": start_source,
|
|
169
|
+
})
|
|
170
|
+
except Exception as exc:
|
|
171
|
+
log_hook_error("hook_session_open", exc)
|
|
172
|
+
try:
|
|
173
|
+
from services.notifications import notify
|
|
174
|
+
notify(project, agent="session", severity="info",
|
|
175
|
+
title=f"Session started {short_id(host_sid)}",
|
|
176
|
+
message=(f"{host} session {host_sid or '?'} started"
|
|
177
|
+
+ (f" ({start_source})" if start_source else "")),
|
|
178
|
+
kind="session", ref_id=host_sid)
|
|
179
|
+
except Exception:
|
|
180
|
+
pass
|
|
181
|
+
ensure_ui(project, host_sid)
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def main() -> None:
|
|
186
|
+
try:
|
|
187
|
+
data = json.load(sys.stdin)
|
|
188
|
+
except Exception as exc:
|
|
189
|
+
log_hook_error("hook_session_open", exc)
|
|
190
|
+
sys.exit(0)
|
|
191
|
+
try:
|
|
192
|
+
run(data)
|
|
193
|
+
except Exception as exc:
|
|
194
|
+
log_hook_error("hook_session_open", exc)
|
|
195
|
+
sys.exit(0)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
if __name__ == "__main__":
|
|
199
|
+
main()
|