code-context-control 2.125.0__tar.gz → 2.126.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.125.0/code_context_control.egg-info → code_context_control-2.126.1}/PKG-INFO +1 -1
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/_hook_utils.py +34 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/c3.py +23 -1
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_dispatch.py +12 -3
- code_context_control-2.126.1/cli/hook_session_end.py +103 -0
- code_context_control-2.126.1/cli/hook_session_open.py +97 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/mcp_server.py +114 -1
- {code_context_control-2.125.0 → code_context_control-2.126.1/code_context_control.egg-info}/PKG-INFO +1 -1
- {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/SOURCES.txt +6 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/mobile_api.py +159 -3
- {code_context_control-2.125.0 → code_context_control-2.126.1}/pyproject.toml +1 -1
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_runner.py +32 -0
- code_context_control-2.126.1/services/host_sessions.py +95 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/notifications.py +31 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/shell_jobs.py +93 -1
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_codex_compat.py +11 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_dispatch.py +9 -0
- code_context_control-2.126.1/tests/test_hook_session_end.py +291 -0
- code_context_control-2.126.1/tests/test_mobile_jobs_ci.py +327 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_override_routes.py +35 -0
- code_context_control-2.126.1/tests/test_notification_kinds.py +294 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_jobs_s3.py +4 -1
- {code_context_control-2.125.0 → code_context_control-2.126.1}/LICENSE +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/README.md +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/_shell_writes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/commands/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/commands/common.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/commands/parser.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/docs.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/edits.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/access.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/credentials.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/index.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/masking.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/oracle.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/shared.css +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/tools.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/workflow.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_artifact.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_c3read.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_codex_lifecycle.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_filter.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_read.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_server.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_access.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/progress.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/server.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/_grants.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/agent.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/ci.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/compress.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/credentials.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/delegate.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/edit.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/edits.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/federate.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/filter.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/impact.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/jira.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/locks.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/memory.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/override.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/project.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/read.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/search.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/session.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell_job.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell_nudge.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell_parsers.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell_render.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/status.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/tasks.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/validate.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/api.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/app.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/access.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/icons.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/shared.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/theme.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui_legacy.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui_nano.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/core/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/core/codex_patch.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/core/config.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/core/host.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/core/ide.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/core/mcp_toml.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/core/web_security.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/config.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/listeners.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/oracle_server.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/client_tokens.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/local_session.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/activity.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/agents.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/app.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/busy.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/core.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/header.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/insights.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/projects.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/settings.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/access_guard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/access_telemetry.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/activity_log.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/agent_base.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/agent_locks.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/agents.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/artifact_defs.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/artifact_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/atomic_json.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/auto_memory.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/background_service.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/map_eval.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/search_eval.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/shell_eval.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bitbucket_client.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_act.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_cache.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_expr.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_failures.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_github.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_impact.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_intel.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_workflow.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/circuit_breaker.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/claude_md.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/codex_integration.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/codex_transcript.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/compressor.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/context_snapshot.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/conversation_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/cred_audit.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/cred_telemetry.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/credential_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/dir_map.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/doc_index.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/e2e_tasks.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/edit_ledger.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/embedding_index.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/enforcement_policy.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/error_reporting.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/file_map.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/file_memory.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/git_context.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/hub_service.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/index_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/indexer.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_client.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_cloud.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_credentials.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_data_center.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_links.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/lexical_index.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/mask_activation.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/mask_mirror.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/mask_presets.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_consolidator.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_distiller.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_graph.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_grounder.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_queue.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_scorer.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/metrics.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ollama_bridge.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ollama_client.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ollama_credentials.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/oracle_service.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/output_filter.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/override_grants.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/override_policy.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/override_requests.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/override_wake.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/parser.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/project_manager.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/project_runtime.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/protocol.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/proxy_state.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/repo_map.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/repo_shape.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/reranker.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/retention.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/retrieval.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/retrieval_broker.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/router.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/runtime.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/scanner.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/session_benchmark.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/session_manager.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/session_preloader.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/shell_output.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/subprojects.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/task_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/telemetry.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/text_index.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/time_tracker.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/tool_classifier.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/transcript_index.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/validation_cache.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/vector_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/watcher.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/services/win_subprocess.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/setup.cfg +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_atomic_json.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_background_service.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_builtin_modes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_act.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_claude_md_updater.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_codex_mcp_transport.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_codex_native.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_confirm_guard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_confirm_guard_wiring.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_cred_audit.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credential_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_dir_map_c3.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_env_parser.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_file_map_c1.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_state.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_override_routes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_index_cap_not_hardcoded.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_init_scan.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_client.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_links.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_large_files_c4.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_map_eval.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_map_telemetry_c0.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_memory_system.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_clients.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_loopback.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_output_filter.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_override_grants.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_override_requests.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_override_wake.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_permissions.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_pm_api.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_project_manager.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_project_tool.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_related_facts.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_repo_map.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_retention.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_review_digest.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_eval.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p1.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p2.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p2b.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p3.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p4.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p5.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_service_durability.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_session_budget.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_budget_s1.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_eval.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_nudge_s4.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_output.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_parsers_s2.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_telemetry_s0.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_clear_scope.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_depth_consumers.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_linkage_api.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subprojects.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_task_store.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_task_tool.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_token_tracking.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ui_jsx_syntax.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_validate.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_version_sync.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_web_security.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/backend.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/main.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/__init__.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/index_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/init_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/search_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/session_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/stats.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/theme.tcss +0 -0
{code_context_control-2.125.0/code_context_control.egg-info → code_context_control-2.126.1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.126.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
|
|
@@ -500,6 +500,40 @@ def record_json_unlocks(
|
|
|
500
500
|
pass
|
|
501
501
|
|
|
502
502
|
|
|
503
|
+
_PROJECT_WALK_UP_LEVELS = 4
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def find_project(payload: dict, project_path=None) -> Path | None:
|
|
507
|
+
"""The nearest ancestor (≤ 4 levels) of ``project_path`` / ``payload.cwd``
|
|
508
|
+
that owns a ``.c3`` directory, or None.
|
|
509
|
+
|
|
510
|
+
Claude Code runs hooks from the project root, Codex passes ``--project``;
|
|
511
|
+
either way the payload's ``cwd`` may be a subdirectory (a session opened
|
|
512
|
+
in ``src/``). The walk is lexical on purpose — no path canonicalisation
|
|
513
|
+
happens here (see tests/test_access_guard_meta.py).
|
|
514
|
+
"""
|
|
515
|
+
candidates = []
|
|
516
|
+
if project_path:
|
|
517
|
+
candidates.append(Path(str(project_path)))
|
|
518
|
+
cwd = payload.get("cwd") if isinstance(payload, dict) else None
|
|
519
|
+
if cwd:
|
|
520
|
+
candidates.append(Path(str(cwd)))
|
|
521
|
+
if not candidates:
|
|
522
|
+
candidates.append(Path.cwd())
|
|
523
|
+
for base in candidates:
|
|
524
|
+
node = base
|
|
525
|
+
for _ in range(_PROJECT_WALK_UP_LEVELS):
|
|
526
|
+
try:
|
|
527
|
+
if (node / ".c3").is_dir():
|
|
528
|
+
return node
|
|
529
|
+
except OSError:
|
|
530
|
+
break
|
|
531
|
+
if node.parent == node:
|
|
532
|
+
break
|
|
533
|
+
node = node.parent
|
|
534
|
+
return None
|
|
535
|
+
|
|
536
|
+
|
|
503
537
|
def emit_additional_context(text: str, is_gemini: bool) -> None:
|
|
504
538
|
"""Write additionalContext JSON to stdout in the correct format for the IDE."""
|
|
505
539
|
if is_gemini:
|
|
@@ -92,7 +92,7 @@ console = Console() if HAS_RICH else None
|
|
|
92
92
|
# Config
|
|
93
93
|
CONFIG_DIR = ".c3"
|
|
94
94
|
CONFIG_FILE = ".c3/config.json"
|
|
95
|
-
__version__ = "2.
|
|
95
|
+
__version__ = "2.126.1"
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -5558,6 +5558,8 @@ def cmd_install_mcp(args):
|
|
|
5558
5558
|
hook_posttool_cmd = f"{_dispatch_base} posttool"
|
|
5559
5559
|
hook_stop_cmd = f"{_dispatch_base} stop"
|
|
5560
5560
|
hook_prompt_cmd = f"{_dispatch_base} prompt"
|
|
5561
|
+
hook_start_cmd = f"{_dispatch_base} start"
|
|
5562
|
+
hook_end_cmd = f"{_dispatch_base} end"
|
|
5561
5563
|
|
|
5562
5564
|
shell_matcher = "Bash"
|
|
5563
5565
|
read_matcher = "Read"
|
|
@@ -5696,6 +5698,25 @@ def cmd_install_mcp(args):
|
|
|
5696
5698
|
)
|
|
5697
5699
|
settings.setdefault("hooks", {})[prompt_event] = existing_prompt
|
|
5698
5700
|
|
|
5701
|
+
# ── SessionStart / SessionEnd hooks (v2.126.0: session_open /
|
|
5702
|
+
# session_end activity rows + `session` notifications, the join key
|
|
5703
|
+
# a desktop client needs). Same merge discipline: replace only C3's
|
|
5704
|
+
# own dispatcher entries, keep user-added ones. SessionStart's
|
|
5705
|
+
# matcher is the payload `source` (startup|resume|clear|compact);
|
|
5706
|
+
# empty matches all — the hook itself ignores `compact`.
|
|
5707
|
+
for _lifecycle_event, _lifecycle_cmd in (
|
|
5708
|
+
("SessionStart", hook_start_cmd),
|
|
5709
|
+
("SessionEnd", hook_end_cmd),
|
|
5710
|
+
):
|
|
5711
|
+
_kept = [
|
|
5712
|
+
h for h in settings.get("hooks", {}).get(_lifecycle_event, [])
|
|
5713
|
+
if not _is_c3_prompt_hook(h)
|
|
5714
|
+
]
|
|
5715
|
+
_kept.append(
|
|
5716
|
+
{"matcher": "", "hooks": [{"type": "command", "command": _lifecycle_cmd}]}
|
|
5717
|
+
)
|
|
5718
|
+
settings.setdefault("hooks", {})[_lifecycle_event] = _kept
|
|
5719
|
+
|
|
5699
5720
|
# Claude Code only: enable MCP server prompt settings
|
|
5700
5721
|
if profile.name == "claude-code":
|
|
5701
5722
|
settings["enableAllProjectMcpServers"] = True
|
|
@@ -5742,6 +5763,7 @@ def cmd_install_mcp(args):
|
|
|
5742
5763
|
print(f" Hooks ({hook_event}): dispatcher (1 spawn/event) — filter/ghost/read-guard/ledger/unlock/signal via cli/hook_dispatch.py posttool")
|
|
5743
5764
|
print(f" Hooks ({pre_event}): dispatcher — {read_matcher}/{grep_matcher}/{glob_matcher}/{edit_matcher}/{write_matcher} (c3 enforcement)")
|
|
5744
5765
|
print(" Hooks (Stop): dispatcher — session_stats + auto_snapshot + terse_advisor")
|
|
5766
|
+
print(" Hooks (SessionStart/SessionEnd): dispatcher — session_open / session_end rows + session notifications")
|
|
5745
5767
|
if profile.name == "claude-code":
|
|
5746
5768
|
print(" Claude MCP prompt settings enabled for this project")
|
|
5747
5769
|
if perm_tier and profile.name == "claude-code":
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Per-event hook dispatcher: ONE process per Claude Code / Gemini hook event.
|
|
3
3
|
|
|
4
|
-
Usage: python hook_dispatch.py <pretool|posttool|stop|prompt>
|
|
4
|
+
Usage: python hook_dispatch.py <pretool|posttool|stop|prompt|start|compact|end>
|
|
5
5
|
|
|
6
6
|
Before v2.42 every hook was registered as its own "cmd /c python <hook>.py"
|
|
7
7
|
subprocess, so a single native Read fired up to three interpreter spawns
|
|
@@ -167,8 +167,17 @@ def _routes(event: str, raw_tool: str, norm_tool: str, host: str = HOST_CLAUDE):
|
|
|
167
167
|
yield "hook_terse_advisor"
|
|
168
168
|
elif event == "prompt":
|
|
169
169
|
yield "hook_prompt_recall"
|
|
170
|
-
elif event in ("start", "compact", "end")
|
|
171
|
-
|
|
170
|
+
elif event in ("start", "compact", "end"):
|
|
171
|
+
# Codex's thread-bound handoff runs first (it may return context on
|
|
172
|
+
# SessionStart); the session bookkeeping below is host-agnostic and
|
|
173
|
+
# returns nothing (v2.126.0: session_open / session_end rows + the
|
|
174
|
+
# `session` notifications a desktop client wakes on).
|
|
175
|
+
if host == HOST_CODEX:
|
|
176
|
+
yield "hook_codex_lifecycle"
|
|
177
|
+
if event == "start":
|
|
178
|
+
yield "hook_session_open"
|
|
179
|
+
elif event == "end":
|
|
180
|
+
yield "hook_session_end"
|
|
172
181
|
|
|
173
182
|
|
|
174
183
|
_RUN_CACHE: dict = {}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""SessionEnd hook: record that a host session ended (D0b, v2.126.0).
|
|
2
|
+
|
|
3
|
+
Claude Code's ``SessionEnd`` event delivers on stdin::
|
|
4
|
+
|
|
5
|
+
{
|
|
6
|
+
"session_id": "<Claude Code UUID>",
|
|
7
|
+
"transcript_path": "...",
|
|
8
|
+
"cwd": "...",
|
|
9
|
+
"hook_event_name": "SessionEnd",
|
|
10
|
+
"reason": "clear" | "logout" | "prompt_input_exit" | "other"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
Codex's ``SessionEnd`` carries its thread id in the same ``session_id``
|
|
14
|
+
field; the dispatcher routes both here (``hook_dispatch._routes``, event
|
|
15
|
+
``end``).
|
|
16
|
+
|
|
17
|
+
Why this exists: this repo's activity log held 525 ``session_start`` rows
|
|
18
|
+
and 14 ``session_save`` rows — ``session_save`` is only written when a human
|
|
19
|
+
ends a session from the hub, so for a client the end of a conversation was
|
|
20
|
+
invisible. Two records fix that:
|
|
21
|
+
|
|
22
|
+
- ``{type: "session_end", session_id: <C3 id if known>, host_session_id,
|
|
23
|
+
reason, source}`` appended to ``.c3/activity_log.jsonl``. The C3 id comes
|
|
24
|
+
from the link file the MCP server wrote at session start
|
|
25
|
+
(``services.host_sessions``); it is ``""`` when the server never learned
|
|
26
|
+
the host id.
|
|
27
|
+
- a ``session`` notification (``kind="session"``, ``ref_id=host id``,
|
|
28
|
+
severity ``info``, title ``Session ended <short id>``) in
|
|
29
|
+
``.c3/notifications.jsonl`` — the write that wakes a ``/feed?wait=``
|
|
30
|
+
client.
|
|
31
|
+
|
|
32
|
+
Runs in a short-lived subprocess with a few seconds of budget; every step is
|
|
33
|
+
best-effort and nothing here can fail the session that is already ending.
|
|
34
|
+
"""
|
|
35
|
+
from __future__ import annotations
|
|
36
|
+
|
|
37
|
+
import sys
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
|
|
40
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
41
|
+
|
|
42
|
+
from cli._hook_utils import detect_host, find_project, log_hook_error # noqa: E402
|
|
43
|
+
|
|
44
|
+
SHORT_ID_CHARS = 8
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def short_id(session_id: str) -> str:
|
|
48
|
+
return str(session_id or "")[:SHORT_ID_CHARS] or "?"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def run(payload: dict, project_path: Path | None = None):
|
|
52
|
+
"""Core logic — importable by the dispatcher and tests. Returns None."""
|
|
53
|
+
project = find_project(payload, project_path)
|
|
54
|
+
if project is None:
|
|
55
|
+
return None
|
|
56
|
+
host = detect_host(payload)
|
|
57
|
+
host_sid = str(payload.get("session_id") or "").strip()
|
|
58
|
+
reason = str(payload.get("reason") or "").strip()
|
|
59
|
+
c3_sid = ""
|
|
60
|
+
try:
|
|
61
|
+
from services.host_sessions import linked_c3_session_id
|
|
62
|
+
c3_sid = linked_c3_session_id(project, host, host_sid)
|
|
63
|
+
except Exception:
|
|
64
|
+
c3_sid = ""
|
|
65
|
+
try:
|
|
66
|
+
from services.activity_log import ActivityLog
|
|
67
|
+
ActivityLog(str(project)).log("session_end", {
|
|
68
|
+
"session_id": c3_sid,
|
|
69
|
+
"host_session_id": host_sid,
|
|
70
|
+
"reason": reason,
|
|
71
|
+
"source": host,
|
|
72
|
+
})
|
|
73
|
+
except Exception as exc:
|
|
74
|
+
log_hook_error("hook_session_end", exc)
|
|
75
|
+
try:
|
|
76
|
+
from services.notifications import notify
|
|
77
|
+
notify(project, agent="session", severity="info",
|
|
78
|
+
title=f"Session ended {short_id(host_sid)}",
|
|
79
|
+
message=(f"{host} session {host_sid or '?'} ended"
|
|
80
|
+
+ (f" ({reason})" if reason else "")
|
|
81
|
+
+ (f"; C3 session {c3_sid}" if c3_sid else "")),
|
|
82
|
+
kind="session", ref_id=host_sid)
|
|
83
|
+
except Exception:
|
|
84
|
+
pass
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def main() -> None:
|
|
89
|
+
import json
|
|
90
|
+
try:
|
|
91
|
+
data = json.load(sys.stdin)
|
|
92
|
+
except Exception as exc:
|
|
93
|
+
log_hook_error("hook_session_end", exc)
|
|
94
|
+
sys.exit(0)
|
|
95
|
+
try:
|
|
96
|
+
run(data)
|
|
97
|
+
except Exception as exc:
|
|
98
|
+
log_hook_error("hook_session_end", exc)
|
|
99
|
+
sys.exit(0)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if __name__ == "__main__":
|
|
103
|
+
main()
|
|
@@ -0,0 +1,97 @@
|
|
|
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
|
+
``source: "compact"`` writes NOTHING: a compaction is the same session and
|
|
26
|
+
the same MCP process, and a "Session started" toast on every compaction
|
|
27
|
+
would teach the user to ignore the real ones.
|
|
28
|
+
|
|
29
|
+
The MCP server's own ``session_start`` row is untouched — it carries the C3
|
|
30
|
+
id and, when the host put its id in the environment, ``host_session_id``
|
|
31
|
+
too. This hook is what lets a client see the session before the runtime has
|
|
32
|
+
finished starting (~seconds), and it is the row the desktop's "MCP failed to
|
|
33
|
+
connect" sentinel starts its 30 s clock from.
|
|
34
|
+
|
|
35
|
+
Returns None always: SessionStart hook stdout becomes model context, and
|
|
36
|
+
this hook has nothing to tell the model.
|
|
37
|
+
"""
|
|
38
|
+
from __future__ import annotations
|
|
39
|
+
|
|
40
|
+
import sys
|
|
41
|
+
from pathlib import Path
|
|
42
|
+
|
|
43
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
44
|
+
|
|
45
|
+
from cli._hook_utils import detect_host, find_project, log_hook_error # noqa: E402
|
|
46
|
+
from cli.hook_session_end import short_id # noqa: E402
|
|
47
|
+
|
|
48
|
+
_SILENT_SOURCES = {"compact"}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def run(payload: dict, project_path: Path | None = None):
|
|
52
|
+
"""Core logic — importable by the dispatcher and tests. Returns None."""
|
|
53
|
+
start_source = str(payload.get("source") or "").strip().lower()
|
|
54
|
+
if start_source in _SILENT_SOURCES:
|
|
55
|
+
return None
|
|
56
|
+
project = find_project(payload, project_path)
|
|
57
|
+
if project is None:
|
|
58
|
+
return None
|
|
59
|
+
host = detect_host(payload)
|
|
60
|
+
host_sid = str(payload.get("session_id") or "").strip()
|
|
61
|
+
try:
|
|
62
|
+
from services.activity_log import ActivityLog
|
|
63
|
+
ActivityLog(str(project)).log("session_open", {
|
|
64
|
+
"host_session_id": host_sid,
|
|
65
|
+
"source": host,
|
|
66
|
+
"start_source": start_source,
|
|
67
|
+
})
|
|
68
|
+
except Exception as exc:
|
|
69
|
+
log_hook_error("hook_session_open", exc)
|
|
70
|
+
try:
|
|
71
|
+
from services.notifications import notify
|
|
72
|
+
notify(project, agent="session", severity="info",
|
|
73
|
+
title=f"Session started {short_id(host_sid)}",
|
|
74
|
+
message=(f"{host} session {host_sid or '?'} started"
|
|
75
|
+
+ (f" ({start_source})" if start_source else "")),
|
|
76
|
+
kind="session", ref_id=host_sid)
|
|
77
|
+
except Exception:
|
|
78
|
+
pass
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def main() -> None:
|
|
83
|
+
import json
|
|
84
|
+
try:
|
|
85
|
+
data = json.load(sys.stdin)
|
|
86
|
+
except Exception as exc:
|
|
87
|
+
log_hook_error("hook_session_open", exc)
|
|
88
|
+
sys.exit(0)
|
|
89
|
+
try:
|
|
90
|
+
run(data)
|
|
91
|
+
except Exception as exc:
|
|
92
|
+
log_hook_error("hook_session_open", exc)
|
|
93
|
+
sys.exit(0)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if __name__ == "__main__":
|
|
97
|
+
main()
|
|
@@ -100,6 +100,92 @@ def _build_instructions(ide_name: str) -> str:
|
|
|
100
100
|
)
|
|
101
101
|
|
|
102
102
|
|
|
103
|
+
# ── Host session id (the join key between hook rows and MCP rows) ──────────
|
|
104
|
+
# The PreToolUse hooks write .c3/enforcement_state.json with `session_id` =
|
|
105
|
+
# the host's id for the session that just called. When the host also put its
|
|
106
|
+
# id in this process's environment (CLAUDE_CODE_SESSION_ID / CODEX_THREAD_ID)
|
|
107
|
+
# the SessionManager already carries it and no file is read. Otherwise the
|
|
108
|
+
# state file is consulted at most once per _HOST_SID_TTL_S — a tool call is
|
|
109
|
+
# far hotter than that, and a per-call read would be a stat+parse on every
|
|
110
|
+
# c3_* invocation for a value that changes once per session.
|
|
111
|
+
_HOST_SID_TTL_S = 5.0
|
|
112
|
+
_host_sid_cache = {"value": "", "read_at": 0.0, "linked": ""}
|
|
113
|
+
_host_sid_lock = threading.Lock()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _host_session_id(svc) -> str:
|
|
117
|
+
"""The host session id for this process, or ``""`` when nobody knows it."""
|
|
118
|
+
try:
|
|
119
|
+
session = getattr(getattr(svc, "session_mgr", None), "current_session", None) or {}
|
|
120
|
+
env_sid = str(session.get("host_session_id") or "").strip()
|
|
121
|
+
except Exception:
|
|
122
|
+
env_sid = ""
|
|
123
|
+
if env_sid:
|
|
124
|
+
_link_host_session(svc, env_sid)
|
|
125
|
+
return env_sid
|
|
126
|
+
now = time.monotonic()
|
|
127
|
+
with _host_sid_lock:
|
|
128
|
+
if now - _host_sid_cache["read_at"] < _HOST_SID_TTL_S:
|
|
129
|
+
return _host_sid_cache["value"]
|
|
130
|
+
_host_sid_cache["read_at"] = now
|
|
131
|
+
value = ""
|
|
132
|
+
try:
|
|
133
|
+
import json as _json
|
|
134
|
+
|
|
135
|
+
from cli._hook_utils import ENFORCEMENT_STATE_FILE
|
|
136
|
+
state_path = Path(svc.project_path) / ENFORCEMENT_STATE_FILE
|
|
137
|
+
if state_path.is_file():
|
|
138
|
+
data = _json.loads(state_path.read_text(encoding="utf-8"))
|
|
139
|
+
if isinstance(data, dict):
|
|
140
|
+
value = str(data.get("session_id") or "").strip()
|
|
141
|
+
except Exception:
|
|
142
|
+
value = ""
|
|
143
|
+
with _host_sid_lock:
|
|
144
|
+
_host_sid_cache["value"] = value
|
|
145
|
+
if value:
|
|
146
|
+
_link_host_session(svc, value)
|
|
147
|
+
return value
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _link_host_session(svc, host_sid: str) -> None:
|
|
151
|
+
"""Write the host→C3 link file once per distinct host id (services.host_sessions)."""
|
|
152
|
+
with _host_sid_lock:
|
|
153
|
+
if _host_sid_cache["linked"] == host_sid:
|
|
154
|
+
return
|
|
155
|
+
_host_sid_cache["linked"] = host_sid
|
|
156
|
+
try:
|
|
157
|
+
session = getattr(getattr(svc, "session_mgr", None), "current_session", None) or {}
|
|
158
|
+
c3_id = str(session.get("id") or "")
|
|
159
|
+
if c3_id:
|
|
160
|
+
from services.host_sessions import write_link
|
|
161
|
+
write_link(svc.project_path, getattr(svc, "ide_name", "") or _IDE_NAME, host_sid, c3_id)
|
|
162
|
+
except Exception:
|
|
163
|
+
pass
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _notify_mcp_ready(svc) -> None:
|
|
167
|
+
"""``kind="mcp"`` / ``C3 connected`` — the runtime is ready to serve (D0b).
|
|
168
|
+
|
|
169
|
+
ref_id is the C3 session id, the same value ``session_start`` carries;
|
|
170
|
+
the host id rides in the message when known. Best-effort: a notification
|
|
171
|
+
failure must never keep the server from serving.
|
|
172
|
+
"""
|
|
173
|
+
try:
|
|
174
|
+
session = getattr(getattr(svc, "session_mgr", None), "current_session", None) or {}
|
|
175
|
+
c3_id = str(session.get("id") or "")
|
|
176
|
+
host_sid = _host_session_id(svc)
|
|
177
|
+
short = (host_sid or c3_id)[:8] or "?"
|
|
178
|
+
from services.notifications import notify
|
|
179
|
+
notify(svc.project_path, agent="c3", severity="info",
|
|
180
|
+
title=f"C3 connected {short}",
|
|
181
|
+
message=(f"C3 {C3_VERSION} MCP runtime ready for {_IDE_NAME}"
|
|
182
|
+
f" (session {c3_id}"
|
|
183
|
+
+ (f", host {host_sid}" if host_sid else "") + ")"),
|
|
184
|
+
kind="mcp", ref_id=c3_id)
|
|
185
|
+
except Exception:
|
|
186
|
+
pass
|
|
187
|
+
|
|
188
|
+
|
|
103
189
|
@asynccontextmanager
|
|
104
190
|
async def lifespan(server):
|
|
105
191
|
"""Initialize all services, auto-start session, start file watcher."""
|
|
@@ -223,9 +309,16 @@ async def lifespan(server):
|
|
|
223
309
|
services.auto_memory = AutoMemory(services.memory, services.session_mgr, auto_mem_cfg)
|
|
224
310
|
|
|
225
311
|
if services.session_mgr.current_session:
|
|
312
|
+
# host_session_id (the Claude Code UUID / Codex thread id) joins this
|
|
313
|
+
# row to the hooks' session_open / session_end rows, which only know
|
|
314
|
+
# the host id. Absent when the host did not put its id in the
|
|
315
|
+
# environment; the link file below is written lazily in that case
|
|
316
|
+
# the first time a hook reveals it (see _host_session_id).
|
|
317
|
+
_host_sid = _host_session_id(services)
|
|
226
318
|
services.activity_log.log("session_start", {
|
|
227
319
|
"session_id": services.session_mgr.current_session["id"],
|
|
228
320
|
"source_system": started_session.get("source_system", ""),
|
|
321
|
+
**({"host_session_id": _host_sid} if _host_sid else {}),
|
|
229
322
|
})
|
|
230
323
|
|
|
231
324
|
# Auto-restore latest snapshot if recent (< 30 min).
|
|
@@ -288,6 +381,12 @@ async def lifespan(server):
|
|
|
288
381
|
)
|
|
289
382
|
_t.Thread(target=_bg_validation_sweep, daemon=True, name="c3-validate-sweep").start()
|
|
290
383
|
|
|
384
|
+
# Runtime is ready to serve: say so where a client can hear it. A desktop
|
|
385
|
+
# "MCP failed to connect" sentinel keys on a session_open with no `mcp`
|
|
386
|
+
# notification within 30 s, so this must be the LAST thing before the
|
|
387
|
+
# handshake proceeds and must never be skipped on a partial init.
|
|
388
|
+
_notify_mcp_ready(services)
|
|
389
|
+
|
|
291
390
|
try:
|
|
292
391
|
yield services
|
|
293
392
|
finally:
|
|
@@ -430,8 +529,22 @@ def _finalize_response(ctx: Context, tool_name: str, args: dict,
|
|
|
430
529
|
call_ok = not _failed(response)
|
|
431
530
|
except Exception:
|
|
432
531
|
call_ok = True
|
|
532
|
+
# Both session ids on every tool_call row (D0b): C3's own id joins the
|
|
533
|
+
# row to session_start / the saved session file, the host id joins it to
|
|
534
|
+
# the hooks' session_open / session_end rows. Either may be absent.
|
|
535
|
+
_ids: dict = {}
|
|
536
|
+
try:
|
|
537
|
+
_c3_sid = str((svc.session_mgr.current_session or {}).get("id") or "")
|
|
538
|
+
if _c3_sid:
|
|
539
|
+
_ids["session_id"] = _c3_sid
|
|
540
|
+
_host_sid = _host_session_id(svc)
|
|
541
|
+
if _host_sid:
|
|
542
|
+
_ids["host_session_id"] = _host_sid
|
|
543
|
+
except Exception:
|
|
544
|
+
pass
|
|
433
545
|
svc.activity_log.log("tool_call", {"tool": tool_name, "args": args,
|
|
434
|
-
"result_summary": summary, "ok": call_ok
|
|
546
|
+
"result_summary": summary, "ok": call_ok,
|
|
547
|
+
**_ids})
|
|
435
548
|
tracker = getattr(svc, "time_tracker", None)
|
|
436
549
|
if tracker is not None:
|
|
437
550
|
try:
|
{code_context_control-2.125.0 → code_context_control-2.126.1/code_context_control.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.126.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
|
|
@@ -21,6 +21,8 @@ cli/hook_ghost_files.py
|
|
|
21
21
|
cli/hook_pretool_enforce.py
|
|
22
22
|
cli/hook_prompt_recall.py
|
|
23
23
|
cli/hook_read.py
|
|
24
|
+
cli/hook_session_end.py
|
|
25
|
+
cli/hook_session_open.py
|
|
24
26
|
cli/hook_session_stats.py
|
|
25
27
|
cli/hook_terse_advisor.py
|
|
26
28
|
cli/hub_server.py
|
|
@@ -231,6 +233,7 @@ services/error_reporting.py
|
|
|
231
233
|
services/file_map.py
|
|
232
234
|
services/file_memory.py
|
|
233
235
|
services/git_context.py
|
|
236
|
+
services/host_sessions.py
|
|
234
237
|
services/hub_service.py
|
|
235
238
|
services/index_store.py
|
|
236
239
|
services/indexer.py
|
|
@@ -372,6 +375,7 @@ tests/test_hook_codex_compat.py
|
|
|
372
375
|
tests/test_hook_dispatch.py
|
|
373
376
|
tests/test_hook_pretool_enforce.py
|
|
374
377
|
tests/test_hook_prompt_recall.py
|
|
378
|
+
tests/test_hook_session_end.py
|
|
375
379
|
tests/test_hook_smoke.py
|
|
376
380
|
tests/test_hook_state.py
|
|
377
381
|
tests/test_hook_utf8_stdio.py
|
|
@@ -414,11 +418,13 @@ tests/test_memory_system.py
|
|
|
414
418
|
tests/test_mobile_api.py
|
|
415
419
|
tests/test_mobile_clients.py
|
|
416
420
|
tests/test_mobile_extras.py
|
|
421
|
+
tests/test_mobile_jobs_ci.py
|
|
417
422
|
tests/test_mobile_override_routes.py
|
|
418
423
|
tests/test_mobile_security_api.py
|
|
419
424
|
tests/test_no_stale_model_pins.py
|
|
420
425
|
tests/test_notification_dedup.py
|
|
421
426
|
tests/test_notification_discipline.py
|
|
427
|
+
tests/test_notification_kinds.py
|
|
422
428
|
tests/test_ollama_credentials.py
|
|
423
429
|
tests/test_oracle_api_auth.py
|
|
424
430
|
tests/test_oracle_apikey_api.py
|