code-context-control 2.109.0__tar.gz → 2.110.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.109.0 → code_context_control-2.110.1}/PKG-INFO +1 -1
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/c3.py +1 -1
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/mcp_server.py +6 -3
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/search.py +120 -21
- {code_context_control-2.109.0 → code_context_control-2.110.1}/code_context_control.egg-info/PKG-INFO +1 -1
- {code_context_control-2.109.0 → code_context_control-2.110.1}/code_context_control.egg-info/SOURCES.txt +2 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/pyproject.toml +1 -1
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/agents.py +49 -5
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/bench/search_eval.py +6 -2
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/claude_md.py +18 -14
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/indexer.py +34 -4
- code_context_control-2.110.1/tests/test_claude_md_updater.py +163 -0
- code_context_control-2.110.1/tests/test_search_p5.py +280 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/LICENSE +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/README.md +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/_hook_utils.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/_shell_writes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/commands/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/commands/common.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/commands/parser.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/docs.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/edits.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/access.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/credentials.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/index.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/masking.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/oracle.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/shared.css +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/tools.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/guide/workflow.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_artifact.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_c3read.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_filter.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_read.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_server.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/hub_access.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/hub_ui.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/progress.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/server.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/_grants.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/agent.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/ci.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/compress.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/credentials.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/delegate.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/edit.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/edits.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/federate.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/filter.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/impact.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/jira.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/locks.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/memory.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/override.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/project.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/read.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/session.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/shell.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/status.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/tasks.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/tools/validate.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/api.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/app.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/access.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/icons.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/shared.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui/theme.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui_legacy.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/cli/ui_nano.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/core/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/core/config.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/core/ide.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/core/mcp_toml.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/core/web_security.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/config.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/oracle_server.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/local_session.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/mobile_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/activity.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/agents.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/app.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/busy.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/core.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/header.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/insights.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/projects.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/settings.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/access_guard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/access_telemetry.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/activity_log.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/agent_base.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/agent_locks.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/artifact_defs.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/artifact_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/auto_memory.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/background_service.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/bench/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/bitbucket_client.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_act.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_cache.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_expr.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_failures.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_github.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_impact.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_intel.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_runner.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ci_workflow.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/circuit_breaker.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/compressor.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/context_snapshot.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/conversation_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/cred_audit.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/cred_telemetry.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/credential_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/doc_index.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/e2e_tasks.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/edit_ledger.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/embedding_index.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/enforcement_policy.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/error_reporting.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/file_memory.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/git_context.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/hub_service.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/index_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/jira_client.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/jira_cloud.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/jira_credentials.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/jira_data_center.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/jira_links.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/lexical_index.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/mask_activation.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/mask_mirror.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/mask_presets.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/memory.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/memory_consolidator.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/memory_distiller.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/memory_graph.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/memory_grounder.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/memory_queue.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/memory_scorer.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/metrics.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/notifications.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ollama_bridge.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ollama_client.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/ollama_credentials.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/oracle_service.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/output_filter.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/override_grants.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/override_policy.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/override_requests.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/override_wake.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/parser.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/project_manager.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/project_runtime.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/protocol.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/proxy_state.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/repo_map.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/repo_shape.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/reranker.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/retention.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/retrieval.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/retrieval_broker.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/router.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/runtime.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/scanner.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/session_benchmark.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/session_manager.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/session_preloader.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/subprojects.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/task_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/telemetry.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/text_index.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/time_tracker.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/tool_classifier.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/transcript_index.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/validation_cache.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/vector_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/watcher.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/services/win_subprocess.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/setup.cfg +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_access_guard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_background_service.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_builtin_modes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ci_act.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_confirm_guard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_confirm_guard_wiring.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_cred_audit.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_credential_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_env_parser.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hook_state.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_override_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_index_cap_not_hardcoded.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_init_scan.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_jira_client.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_jira_links.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_memory_system.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_output_filter.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_override_grants.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_override_requests.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_override_wake.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_permissions.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_pm_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_project_manager.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_project_tool.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_related_facts.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_repo_map.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_retention.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_review_digest.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_search_eval.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_search_p1.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_search_p2.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_search_p2b.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_search_p3.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_search_p4.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_service_durability.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_session_budget.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_subproject_clear_scope.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_subproject_depth_consumers.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_subproject_linkage_api.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_subprojects.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_task_store.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_task_tool.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_token_tracking.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_ui_jsx_syntax.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_validate.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_version_sync.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_web_security.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/backend.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/main.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/__init__.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/index_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/init_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/search_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/session_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/stats.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.1}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.109.0 → code_context_control-2.110.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.110.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
|
|
@@ -489,13 +489,16 @@ async def c3_search(query: str, action: str = "code", top_k: int = 3,
|
|
|
489
489
|
action: 'code' (default: BM25 over identifiers and their parts, digits kept, fused with the embedding
|
|
490
490
|
index by reciprocal rank when one is ready; a query that IS a symbol name puts its definition first;
|
|
491
491
|
an oversized chunk comes back as a window), 'lexical' (the BM25 ranking alone), 'exact' (regex over
|
|
492
|
-
every indexed file; ignore_case=True for case-insensitive), 'files' (by
|
|
493
|
-
like 'configs/*.yml', or substring), 'semantic' (embeddings alone; falls
|
|
494
|
-
empty), 'transcript'.
|
|
492
|
+
every indexed file, definitions printed first; ignore_case=True for case-insensitive), 'files' (by
|
|
493
|
+
filename: exact name, glob like 'configs/*.yml', or substring), 'semantic' (embeddings alone; falls
|
|
494
|
+
back to code search when empty), 'transcript'.
|
|
495
495
|
Filters (all actions but transcript, comma-separated): path='src/**,*.go' (globs or substrings),
|
|
496
496
|
lang='python,go' (names or extensions), kind='test,doc,config,source' and/or chunk types
|
|
497
497
|
'function,class,method,heading'. A query that names tests or asks a how-to question already
|
|
498
498
|
leans that way; filters make it exact.
|
|
499
|
+
top_k: up to 50 for 'files' and 'exact', 10 otherwise. Each hit header ends in the backend that
|
|
500
|
+
produced it ([lexical], [dense], [lexical+dense], symbol+, reranked); a zero result says which
|
|
501
|
+
action to try next.
|
|
499
502
|
scope: '' current project | 'all' also searches linked sub-projects | '<name>' one sub-project.
|
|
500
503
|
prefetch: auto-compress top results. Next step: c3_compress/c3_read on hits."""
|
|
501
504
|
svc = _svc(ctx)
|
|
@@ -14,7 +14,7 @@ from cli.tools._helpers import finalize_with_tokens, show_token_ratios
|
|
|
14
14
|
from core import count_tokens
|
|
15
15
|
from services import access_guard
|
|
16
16
|
from services.indexer import DEFAULT_CODE_EXTS
|
|
17
|
-
from services.lexical_index import Filters
|
|
17
|
+
from services.lexical_index import Filters, doc_kind
|
|
18
18
|
from services.scanner import SKIP_DIRS, iter_files
|
|
19
19
|
|
|
20
20
|
# Hard cap: responses above this are truncated to avoid filling context.
|
|
@@ -24,6 +24,32 @@ _RESPONSE_TOKEN_CAP = 2400
|
|
|
24
24
|
# token budget and hide every other file.
|
|
25
25
|
_EXACT_MAX_MATCHES_PER_FILE = 20
|
|
26
26
|
_RG_TIMEOUT_SECONDS = 60
|
|
27
|
+
# top_k caps per action (2.110.0). A code hit spends a chunk of the token
|
|
28
|
+
# budget; a files row or an exact per-file block spends a line or two, so
|
|
29
|
+
# those actions may list many more before the response cap bites.
|
|
30
|
+
_TOP_K_CAP_DEFAULT = 10
|
|
31
|
+
_TOP_K_CAPS = {"files": 50, "exact": 50}
|
|
32
|
+
|
|
33
|
+
# `exact` orders files definitions-first (2.110.0): a hit on a line that
|
|
34
|
+
# declares something outranks a hit that merely mentions it, then source
|
|
35
|
+
# before config, docs and tests, then path order. The index's symbol table
|
|
36
|
+
# is consulted first when the query names one identifier; this regex is the
|
|
37
|
+
# language-agnostic fallback for keyword-declared definitions (def/class/
|
|
38
|
+
# fn/func/type/const/...) and top-level assignments. C-family functions
|
|
39
|
+
# without a keyword rely on the symbol table.
|
|
40
|
+
_DEF_LINE_RE = re.compile(
|
|
41
|
+
r"^\s*(?:(?:export|default|pub(?:\([^)]*\))?|public|private|protected|internal|static|"
|
|
42
|
+
r"abstract|final|async|unsafe|extern|declare|override|virtual|inline|constexpr)\s+)*"
|
|
43
|
+
r"(?:def|class|function|fn|func|type|struct|interface|enum|trait|impl|module|record|"
|
|
44
|
+
r"protocol|extension|object|namespace|const|let|var|val|#define)"
|
|
45
|
+
r"(?=\s+[A-Za-z_(*&\[]|\s*[<(])"
|
|
46
|
+
r"|^[A-Za-z_][\w.]*\s*(?::[^=]*)?=(?!=)")
|
|
47
|
+
_KIND_RANK = {"source": 0, "config": 1, "doc": 2, "test": 3}
|
|
48
|
+
# A forward slash or a dotted filename reads as a path; a backslash does not,
|
|
49
|
+
# because `\d` / `\s` in a regex are far more common in queries than Windows
|
|
50
|
+
# separators.
|
|
51
|
+
_PATHLIKE_RE = re.compile(r"/|^[\w.\-]+\.[A-Za-z0-9]{1,6}$")
|
|
52
|
+
_REGEX_META = set("\\^$.|?*+()[]{}")
|
|
27
53
|
|
|
28
54
|
|
|
29
55
|
def _read_denied(path, svc) -> bool:
|
|
@@ -77,11 +103,66 @@ def _cap_response(resp: str) -> str:
|
|
|
77
103
|
return "\n".join(lines[:20]) + "\n[truncated]"
|
|
78
104
|
|
|
79
105
|
|
|
106
|
+
def _via_tag(r: dict) -> str:
|
|
107
|
+
"""`` [lexical+dense, reranked]`` — which backend(s) produced the hit."""
|
|
108
|
+
via = r.get("via")
|
|
109
|
+
if not via:
|
|
110
|
+
return ""
|
|
111
|
+
return f" [{via}, reranked]" if r.get("reranked") else f" [{via}]"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _zero_hint(action: str, query: str, *, filters: Filters | None = None,
|
|
115
|
+
ignore_case: bool = False) -> str:
|
|
116
|
+
"""One clause naming what to try next when an action finds nothing.
|
|
117
|
+
|
|
118
|
+
Never echoes the query: the eval harness strips it before checking for
|
|
119
|
+
forbidden text, and a masked canary must not be printed twice.
|
|
120
|
+
"""
|
|
121
|
+
tips = []
|
|
122
|
+
if action == "exact":
|
|
123
|
+
if not ignore_case and re.search(r"[A-Za-z]", query):
|
|
124
|
+
tips.append("ignore_case=True")
|
|
125
|
+
tips.append("action='code', which matches identifiers by their parts")
|
|
126
|
+
elif action == "files":
|
|
127
|
+
if not any(ch in query for ch in "*?["):
|
|
128
|
+
tips.append("a glob like '**/*.yml'")
|
|
129
|
+
tips.append("action='exact' to search file contents")
|
|
130
|
+
else:
|
|
131
|
+
if _PATHLIKE_RE.search(query):
|
|
132
|
+
tips.append("action='files', which matches filenames")
|
|
133
|
+
elif any(ch in query for ch in _REGEX_META):
|
|
134
|
+
tips.append("action='exact', which takes a regex")
|
|
135
|
+
else:
|
|
136
|
+
tips.append("action='exact' for a literal or regex")
|
|
137
|
+
tips.append("action='files' for a filename")
|
|
138
|
+
if filters:
|
|
139
|
+
tips.append("dropping the path/lang/kind filter")
|
|
140
|
+
if not tips:
|
|
141
|
+
return ""
|
|
142
|
+
if len(tips) == 1:
|
|
143
|
+
return f"; try {tips[0]}"
|
|
144
|
+
return "; try " + ", ".join(tips[:-1]) + f", or {tips[-1]}"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _symbol_definition_files(query: str, svc) -> set:
|
|
148
|
+
"""Files whose indexed symbol table defines the identifier ``query`` names."""
|
|
149
|
+
idx = getattr(svc, "indexer", None)
|
|
150
|
+
fn = getattr(idx, "_exact_symbol_ids", None)
|
|
151
|
+
if not callable(fn):
|
|
152
|
+
return set()
|
|
153
|
+
try:
|
|
154
|
+
chunks = getattr(idx, "chunks", None) or {}
|
|
155
|
+
# doc ids carry the OS separator; the manifest is POSIX.
|
|
156
|
+
return {chunks[cid]["doc_id"].replace("\\", "/") for cid in fn(query) if cid in chunks}
|
|
157
|
+
except Exception:
|
|
158
|
+
return set()
|
|
159
|
+
|
|
160
|
+
|
|
80
161
|
def handle_search(query: str, action: str, top_k: int, max_tokens: int,
|
|
81
162
|
svc, finalize, maybe_facts, prefetch: bool = False,
|
|
82
163
|
scope: str = "", ignore_case: bool = False,
|
|
83
164
|
path: str = "", lang: str = "", kind: str = "") -> str:
|
|
84
|
-
top_k = max(1, min(int(top_k),
|
|
165
|
+
top_k = max(1, min(int(top_k), _TOP_K_CAPS.get(action, _TOP_K_CAP_DEFAULT)))
|
|
85
166
|
max_tokens = min(max(200, int(max_tokens)), _RESPONSE_TOKEN_CAP)
|
|
86
167
|
filters = Filters(path=path, lang=lang, kind=kind)
|
|
87
168
|
|
|
@@ -262,10 +343,13 @@ def _exact_search(query, top_k, max_tokens, svc, finalize, ignore_case: bool = F
|
|
|
262
343
|
return None
|
|
263
344
|
file_matches = []
|
|
264
345
|
n_matches = 0
|
|
346
|
+
def_line = False
|
|
265
347
|
for i, line in enumerate(lines):
|
|
266
348
|
if not pat.search(line):
|
|
267
349
|
continue
|
|
268
350
|
n_matches += 1
|
|
351
|
+
if not def_line and _DEF_LINE_RE.match(line):
|
|
352
|
+
def_line = True
|
|
269
353
|
if n_matches > _EXACT_MAX_MATCHES_PER_FILE:
|
|
270
354
|
continue # keep counting, stop printing
|
|
271
355
|
start = max(0, i - 1)
|
|
@@ -281,32 +365,45 @@ def _exact_search(query, top_k, max_tokens, svc, finalize, ignore_case: bool = F
|
|
|
281
365
|
file_matches.append(
|
|
282
366
|
f"[+{n_matches - _EXACT_MAX_MATCHES_PER_FILE} more matching lines in this file; "
|
|
283
367
|
"narrow the pattern]")
|
|
284
|
-
return (rel, file_matches) if file_matches else None
|
|
368
|
+
return (rel, file_matches, def_line) if file_matches else None
|
|
285
369
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
370
|
+
# Every matching file is collected, then ordered definitions-first: the
|
|
371
|
+
# manifest walk used to decide the order, so the definition of a symbol
|
|
372
|
+
# could print behind a test and a doc that merely mention it.
|
|
373
|
+
symbol_files = _symbol_definition_files(query, svc)
|
|
374
|
+
hits = []
|
|
289
375
|
if targets:
|
|
290
376
|
with ThreadPoolExecutor(max_workers=min(len(targets), 8)) as pool:
|
|
291
377
|
for result in pool.map(_scan_file, targets):
|
|
292
378
|
if result is None:
|
|
293
379
|
continue
|
|
294
|
-
rel, file_matches = result
|
|
380
|
+
rel, file_matches, def_line = result
|
|
295
381
|
if _read_denied(rel, svc):
|
|
296
382
|
continue # R2: denied paths never appear in results
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
383
|
+
def_rank = 0 if rel in symbol_files else (1 if def_line else 2)
|
|
384
|
+
hits.append(((def_rank, _KIND_RANK.get(doc_kind(rel), 9), rel),
|
|
385
|
+
rel, file_matches, def_rank < 2))
|
|
386
|
+
hits.sort(key=lambda h: h[0])
|
|
387
|
+
|
|
388
|
+
matched_parts = []
|
|
389
|
+
file_count = 0
|
|
390
|
+
total_tokens = 0
|
|
391
|
+
for _key, rel, file_matches, is_def in hits:
|
|
392
|
+
header = f"--- {rel} ---" + (" [definition]" if is_def else "")
|
|
393
|
+
chunk = header + "\n" + "\n".join(file_matches)
|
|
394
|
+
chunk_tokens = count_tokens(chunk)
|
|
395
|
+
if total_tokens + chunk_tokens > max_tokens and matched_parts:
|
|
396
|
+
break
|
|
397
|
+
file_count += 1
|
|
398
|
+
total_tokens += chunk_tokens
|
|
399
|
+
matched_parts.append(chunk)
|
|
400
|
+
if file_count >= top_k:
|
|
401
|
+
break
|
|
306
402
|
|
|
307
403
|
if not matched_parts:
|
|
404
|
+
hint = _zero_hint("exact", query, filters=filters, ignore_case=ignore_case)
|
|
308
405
|
return finalize("c3_search", {"action": "exact"},
|
|
309
|
-
f"[search:exact:{query}] 0 results in {len(manifest)} files", "0")
|
|
406
|
+
f"[search:exact:{query}] 0 results in {len(manifest)} files{hint}", "0")
|
|
310
407
|
|
|
311
408
|
resp = "\n".join(matched_parts)
|
|
312
409
|
return finalize("c3_search", {"action": "exact"}, resp, f"{file_count}f",
|
|
@@ -418,8 +515,9 @@ def _files_search(query, top_k, svc, finalize, filters: Filters | None = None):
|
|
|
418
515
|
**_filter_kwargs(filters))
|
|
419
516
|
res = [r for r in res if not _read_denied(r.get("file", ""), svc)]
|
|
420
517
|
if not res:
|
|
518
|
+
hint = _zero_hint("files", query, filters=filters)
|
|
421
519
|
return finalize("c3_search", {"action": "files"},
|
|
422
|
-
f"[search:files:{query}] 0 results", "0")
|
|
520
|
+
f"[search:files:{query}] 0 results{hint}", "0")
|
|
423
521
|
parts = []
|
|
424
522
|
for r in res:
|
|
425
523
|
meta = f"- {r['file']} (L{r['lines']})"
|
|
@@ -519,7 +617,7 @@ def _semantic_search(query, top_k, max_tokens, svc, finalize, maybe_facts,
|
|
|
519
617
|
total_tokens = 0
|
|
520
618
|
for r in results:
|
|
521
619
|
name = f" {r['name']}" if r.get('name') else ""
|
|
522
|
-
ref = f"--- {r['file']}:L{r['lines']}{name} ({r['type']})"
|
|
620
|
+
ref = f"--- {r['file']}:L{r['lines']}{name} ({r['type']}) [dense]"
|
|
523
621
|
lines.extend([ref, r['content']] if r.get('content') else [ref])
|
|
524
622
|
total_tokens += r['tokens']
|
|
525
623
|
|
|
@@ -539,7 +637,8 @@ def _code_search(query, top_k, max_tokens, svc, finalize, maybe_facts,
|
|
|
539
637
|
# Access Guard pre-filter BEFORE dedup/top_k (R2 deny-ENUMERATE).
|
|
540
638
|
results = [r for r in results if not _read_denied(r.get("file", ""), svc)]
|
|
541
639
|
if not results:
|
|
542
|
-
|
|
640
|
+
hint = _zero_hint("code", query, filters=filters)
|
|
641
|
+
return finalize("c3_search", {"query": query}, f"[search:{query}] 0 results{hint}", "0")
|
|
543
642
|
|
|
544
643
|
best_score = max((r.get("score", 0.0) for r in results), default=0.0)
|
|
545
644
|
if best_score > 0:
|
|
@@ -564,7 +663,7 @@ def _code_search(query, top_k, max_tokens, svc, finalize, maybe_facts,
|
|
|
564
663
|
total_tokens = 0
|
|
565
664
|
for r in deduped:
|
|
566
665
|
name = f" {r['name']}" if r['name'] else ""
|
|
567
|
-
ref = f"--- {r['file']}:L{r['lines']}{name} ({r['type']})"
|
|
666
|
+
ref = f"--- {r['file']}:L{r['lines']}{name} ({r['type']}){_via_tag(r)}"
|
|
568
667
|
lines.extend([ref, r['content']] if r.get('content') else [ref])
|
|
569
668
|
total_tokens += r['tokens']
|
|
570
669
|
|
{code_context_control-2.109.0 → code_context_control-2.110.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.110.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
|
|
@@ -311,6 +311,7 @@ tests/test_ci_runner.py
|
|
|
311
311
|
tests/test_ci_workflow.py
|
|
312
312
|
tests/test_circuit_breaker.py
|
|
313
313
|
tests/test_claude_md_merge.py
|
|
314
|
+
tests/test_claude_md_updater.py
|
|
314
315
|
tests/test_cli_smoke.py
|
|
315
316
|
tests/test_compressor_large_file.py
|
|
316
317
|
tests/test_confirm_guard.py
|
|
@@ -431,6 +432,7 @@ tests/test_search_p2.py
|
|
|
431
432
|
tests/test_search_p2b.py
|
|
432
433
|
tests/test_search_p3.py
|
|
433
434
|
tests/test_search_p4.py
|
|
435
|
+
tests/test_search_p5.py
|
|
434
436
|
tests/test_service_durability.py
|
|
435
437
|
tests/test_session_benchmark.py
|
|
436
438
|
tests/test_session_budget.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code-context-control"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.110.1"
|
|
8
8
|
description = "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."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -650,11 +650,12 @@ class ClaudeMdUpdaterAgent(BackgroundAgent):
|
|
|
650
650
|
|
|
651
651
|
for action_type, data in actions:
|
|
652
652
|
if action_type == "staleness":
|
|
653
|
-
# Regenerate the auto-generated sections
|
|
653
|
+
# Regenerate the auto-generated sections — inside the managed
|
|
654
|
+
# block, so user content around it survives.
|
|
654
655
|
try:
|
|
655
656
|
result = self.claude_md.generate(include_sessions=True)
|
|
656
657
|
if result.get("content") and self.auto_apply:
|
|
657
|
-
self.
|
|
658
|
+
self._write_managed_body(result["content"])
|
|
658
659
|
applied.append("Regenerated CLAUDE.md (stale)")
|
|
659
660
|
elif result.get("content"):
|
|
660
661
|
applied.append(f"CLAUDE.md is stale ({len(data.get('issues', []))} issues) — regeneration available")
|
|
@@ -810,16 +811,59 @@ class ClaudeMdUpdaterAgent(BackgroundAgent):
|
|
|
810
811
|
self._write_claude_md("\n".join(lines))
|
|
811
812
|
return additions
|
|
812
813
|
|
|
813
|
-
def
|
|
814
|
-
|
|
814
|
+
def _md_path(self):
|
|
815
|
+
return self.claude_md.project_path / self.claude_md.instructions_file
|
|
816
|
+
|
|
817
|
+
def _write_managed_body(self, body: str) -> bool:
|
|
818
|
+
"""Write regenerated C3 content INTO the managed block.
|
|
819
|
+
|
|
820
|
+
``generate()`` returns the block body, not a whole file. Writing it
|
|
821
|
+
raw (2.110.0 and earlier) dropped the ``C3:BEGIN``/``C3:END`` markers
|
|
822
|
+
and everything the user kept outside them; the next ``c3 install-mcp``
|
|
823
|
+
then re-wrapped the template as a legacy doc, so a committed
|
|
824
|
+
CLAUDE.md went dirty on every session start. The merge in
|
|
825
|
+
``write_c3_instruction_doc`` is the same one the installer uses.
|
|
826
|
+
"""
|
|
827
|
+
from services.claude_md import write_c3_instruction_doc
|
|
828
|
+
|
|
815
829
|
try:
|
|
816
|
-
|
|
830
|
+
final = write_c3_instruction_doc(self._md_path(), body,
|
|
831
|
+
project_path=self.claude_md.project_path,
|
|
832
|
+
source="claude_md_updater")
|
|
833
|
+
self._last_content_hash = hashlib.md5(final.encode()).hexdigest()
|
|
834
|
+
self._last_update_time = time.time()
|
|
835
|
+
return True
|
|
836
|
+
except Exception:
|
|
837
|
+
return False
|
|
838
|
+
|
|
839
|
+
def _write_claude_md(self, content: str) -> bool:
|
|
840
|
+
"""Write a WHOLE instructions file (compaction, promotions) and update hash.
|
|
841
|
+
|
|
842
|
+
Refuses when the file on disk carries the managed-block markers and
|
|
843
|
+
``content`` does not: that is a block body, and writing it here would
|
|
844
|
+
strip the markers — route it through ``_write_managed_body``.
|
|
845
|
+
"""
|
|
846
|
+
from services.claude_md import C3_BLOCK_BEGIN
|
|
847
|
+
|
|
848
|
+
try:
|
|
849
|
+
md_path = self._md_path()
|
|
817
850
|
md_path.parent.mkdir(parents=True, exist_ok=True)
|
|
851
|
+
if md_path.exists() and C3_BLOCK_BEGIN not in content:
|
|
852
|
+
existing = md_path.read_text(encoding="utf-8", errors="replace")
|
|
853
|
+
if C3_BLOCK_BEGIN in existing:
|
|
854
|
+
return False
|
|
818
855
|
md_path.write_text(content, encoding="utf-8")
|
|
819
856
|
self._last_content_hash = hashlib.md5(content.encode()).hexdigest()
|
|
820
857
|
self._last_update_time = time.time()
|
|
858
|
+
except Exception:
|
|
859
|
+
return False
|
|
860
|
+
try:
|
|
861
|
+
from services.artifact_defs import note_pending_write
|
|
862
|
+
note_pending_write(self.claude_md.project_path, self.claude_md.instructions_file,
|
|
863
|
+
"claude_md_updater")
|
|
821
864
|
except Exception:
|
|
822
865
|
pass
|
|
866
|
+
return True
|
|
823
867
|
|
|
824
868
|
def get_status(self) -> dict:
|
|
825
869
|
"""Extended status including updater-specific metrics."""
|
|
@@ -330,11 +330,15 @@ def _embedding_index(project: str, indexer, *, build: bool):
|
|
|
330
330
|
|
|
331
331
|
# ── Response parsing ────────────────────────────────────────────────────────
|
|
332
332
|
|
|
333
|
+
# Headers may carry a trailing ``[tag]`` (2.110.0): ``[lexical+dense]`` /
|
|
334
|
+
# ``[dense]`` / ``[symbol+lexical, reranked]`` on chunk hits, ``[definition]``
|
|
335
|
+
# on exact hits. The tag is provenance, not identity, so it is optional here.
|
|
333
336
|
_RE_CHUNK = re.compile(
|
|
334
|
-
r"^--- (?P<file>.+?):L(?P<lines>[^ ]+)(?: (?P<name>.+?))? \((?P<type>[^()]+)\)
|
|
337
|
+
r"^--- (?P<file>.+?):L(?P<lines>[^ ]+)(?: (?P<name>.+?))? \((?P<type>[^()]+)\)"
|
|
338
|
+
r"(?: \[(?P<via>[^\]]*)\])?\s*$")
|
|
335
339
|
_RE_FILE_ROW = re.compile(
|
|
336
340
|
r"^- (?P<file>.+?) \(L(?P<lines>[^)]+)\)(?:.*?contains (?P<type>\S+) '(?P<name>[^']*)')?")
|
|
337
|
-
_RE_EXACT = re.compile(r"^--- (?P<file>.+?)
|
|
341
|
+
_RE_EXACT = re.compile(r"^--- (?P<file>.+?) ---(?: \[(?P<via>[^\]]*)\])?\s*$")
|
|
338
342
|
|
|
339
343
|
|
|
340
344
|
def parse_hits(action: str, response: str) -> list[Hit]:
|
|
@@ -300,17 +300,19 @@ def strip_c3_block(existing: str) -> Optional[str]:
|
|
|
300
300
|
return None
|
|
301
301
|
|
|
302
302
|
|
|
303
|
-
def write_c3_instruction_doc(path, content: str, project_path=None
|
|
303
|
+
def write_c3_instruction_doc(path, content: str, project_path=None,
|
|
304
|
+
source: str = "install_mcp") -> str:
|
|
304
305
|
"""Write a C3-generated instruction doc without clobbering user content.
|
|
305
306
|
|
|
306
307
|
Wraps ``content`` in the C3 managed block and merges it into any existing
|
|
307
308
|
file via :func:`merge_c3_block`. Returns the exact text written to disk.
|
|
308
309
|
|
|
309
|
-
Self-reports the write to the agent-artifact tracker
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
310
|
+
Self-reports the write to the agent-artifact tracker under ``source``
|
|
311
|
+
(``install_mcp`` for the installer and CLI, ``claude_md_updater`` for the
|
|
312
|
+
background agent) so regeneration is attributed to C3 instead of
|
|
313
|
+
surfacing as anonymous out-of-band drift. ``project_path`` pins the
|
|
314
|
+
project root; when omitted it is inferred from the doc's location (root
|
|
315
|
+
or one level down, e.g. .github/copilot-instructions.md).
|
|
314
316
|
"""
|
|
315
317
|
p = Path(path)
|
|
316
318
|
p.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -329,7 +331,7 @@ def write_c3_instruction_doc(path, content: str, project_path=None) -> str:
|
|
|
329
331
|
if (c / ".c3").is_dir()), None)
|
|
330
332
|
if root is not None and (root / ".c3").is_dir():
|
|
331
333
|
note_pending_write(root, str(p.resolve().relative_to(root.resolve())),
|
|
332
|
-
"install_mcp")
|
|
334
|
+
source or "install_mcp")
|
|
333
335
|
except Exception:
|
|
334
336
|
pass
|
|
335
337
|
return final
|
|
@@ -533,13 +535,15 @@ class ClaudeMdManager:
|
|
|
533
535
|
),
|
|
534
536
|
})
|
|
535
537
|
|
|
536
|
-
# Structure drift
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
#
|
|
541
|
-
|
|
542
|
-
|
|
538
|
+
# Structure and tech-stack drift apply only to the legacy embedded
|
|
539
|
+
# tree. With the live repo map (default since 2.60.0) the doc carries
|
|
540
|
+
# neither — the map does — so there is nothing embedded to drift.
|
|
541
|
+
# Diffing anyway reported every detected technology as "not listed"
|
|
542
|
+
# on every check, and an auto-applying updater rewrote the file each
|
|
543
|
+
# time (2.110.1).
|
|
544
|
+
if not self._repo_map_enabled():
|
|
545
|
+
issues.extend(self._diff_structure(current))
|
|
546
|
+
issues.extend(self._diff_tech_stack(current))
|
|
543
547
|
|
|
544
548
|
# Session staleness
|
|
545
549
|
session_files = sorted(
|
|
@@ -230,13 +230,16 @@ class CodeIndex:
|
|
|
230
230
|
return "off"
|
|
231
231
|
return str(getattr(self.reranker, "name", None) or "on")
|
|
232
232
|
|
|
233
|
-
def _apply_rerank(self, query: str, base_tokens: list, ranked: list, exact_ids: set
|
|
233
|
+
def _apply_rerank(self, query: str, base_tokens: list, ranked: list, exact_ids: set,
|
|
234
|
+
reranked: set | None = None) -> list:
|
|
234
235
|
"""Cross-encoder pass over the top ``search_rerank_top_n`` candidates.
|
|
235
236
|
|
|
236
237
|
Identifier-shaped queries are left alone (services/reranker
|
|
237
238
|
.is_natural_language). Exact-symbol matches keep their place ahead of
|
|
238
239
|
the reranked block; candidates beyond the block keep their order.
|
|
239
240
|
Any reranker failure or empty answer leaves ``ranked`` unchanged.
|
|
241
|
+
``reranked``, when given, receives the ids the model actually
|
|
242
|
+
reordered so the caller can label them.
|
|
240
243
|
"""
|
|
241
244
|
from services.reranker import is_natural_language, passage_text
|
|
242
245
|
|
|
@@ -258,10 +261,12 @@ class CodeIndex:
|
|
|
258
261
|
return ranked
|
|
259
262
|
order = {cid: i for i, (cid, _) in enumerate(scored)}
|
|
260
263
|
block.sort(key=lambda cs: (order.get(cs[0], len(order)), -cs[1], cs[0]))
|
|
264
|
+
if reranked is not None:
|
|
265
|
+
reranked.update(cid for cid, _ in block)
|
|
261
266
|
return exact_head + block + ranked[n:]
|
|
262
267
|
|
|
263
268
|
def _fuse_dense(self, query: str, lexical_ranked: list, filters: Filters,
|
|
264
|
-
exact_ids: set, want: int) -> list:
|
|
269
|
+
exact_ids: set, want: int, provenance: dict | None = None) -> list:
|
|
265
270
|
"""RRF of the lexical ranking with the dense backend's candidates.
|
|
266
271
|
|
|
267
272
|
Each list contributes its top ``n`` (20..50, from ``want``); dense ids
|
|
@@ -270,6 +275,9 @@ class CodeIndex:
|
|
|
270
275
|
their override through the rank key. Lexical candidates beyond ``n``
|
|
271
276
|
trail the fused block so budget filling can continue past it. Any
|
|
272
277
|
backend failure returns the lexical ranking unchanged.
|
|
278
|
+
``provenance``, when given, is filled with ``chunk_id -> {"lexical",
|
|
279
|
+
"dense"}`` naming the list(s) each fused id came from; it stays empty
|
|
280
|
+
when fusion did not happen, which the caller reads as lexical-only.
|
|
273
281
|
"""
|
|
274
282
|
from services.retrieval import rrf
|
|
275
283
|
|
|
@@ -297,6 +305,15 @@ class CodeIndex:
|
|
|
297
305
|
fused.setdefault(cid, 0.0)
|
|
298
306
|
ranked = sorted(fused.items(), key=self._rank_key(exact_ids), reverse=True)
|
|
299
307
|
tail = [(cid, score) for cid, score in lexical_ranked[n:] if cid not in fused]
|
|
308
|
+
if provenance is not None:
|
|
309
|
+
for cid in fused:
|
|
310
|
+
provenance[cid] = set()
|
|
311
|
+
for cid in lexical:
|
|
312
|
+
provenance[cid].add("lexical")
|
|
313
|
+
for cid in dense:
|
|
314
|
+
provenance[cid].add("dense")
|
|
315
|
+
for cid, _ in tail:
|
|
316
|
+
provenance[cid] = {"lexical"}
|
|
300
317
|
return ranked + tail
|
|
301
318
|
|
|
302
319
|
def _lexical_wanted(self) -> bool:
|
|
@@ -1254,10 +1271,17 @@ class CodeIndex:
|
|
|
1254
1271
|
if ranked is None:
|
|
1255
1272
|
ranked = self._rank_tfidf(query, query_tokens, query_bigrams, filters,
|
|
1256
1273
|
exact_ids, max_mtime)
|
|
1274
|
+
# Provenance (2.110.0): which list(s) produced each id, so the tool
|
|
1275
|
+
# can label a hit ``[lexical+dense]`` instead of leaving the agent to
|
|
1276
|
+
# guess why an unrelated-looking chunk ranked. Empty = lexical only.
|
|
1277
|
+
provenance: dict = {}
|
|
1278
|
+
reranked_ids: set = set()
|
|
1257
1279
|
if fuse:
|
|
1258
|
-
ranked = self._fuse_dense(query, ranked, filters, exact_ids, want=top_k
|
|
1280
|
+
ranked = self._fuse_dense(query, ranked, filters, exact_ids, want=top_k,
|
|
1281
|
+
provenance=provenance)
|
|
1259
1282
|
if rerank_now:
|
|
1260
|
-
ranked = self._apply_rerank(query, base_tokens, ranked, exact_ids
|
|
1283
|
+
ranked = self._apply_rerank(query, base_tokens, ranked, exact_ids,
|
|
1284
|
+
reranked=reranked_ids)
|
|
1261
1285
|
|
|
1262
1286
|
# Collect results up to token budget
|
|
1263
1287
|
results = []
|
|
@@ -1298,6 +1322,12 @@ class CodeIndex:
|
|
|
1298
1322
|
# a windowed class scores low on TF-IDF and is still the
|
|
1299
1323
|
# definition the query named.
|
|
1300
1324
|
result["exact_symbol"] = True
|
|
1325
|
+
sources = ["symbol"] if chunk_id in exact_ids else []
|
|
1326
|
+
lists = provenance[chunk_id] if chunk_id in provenance else {"lexical"}
|
|
1327
|
+
sources.extend(s for s in ("lexical", "dense") if s in lists)
|
|
1328
|
+
result["via"] = "+".join(sources)
|
|
1329
|
+
if chunk_id in reranked_ids:
|
|
1330
|
+
result["reranked"] = True
|
|
1301
1331
|
if include_content:
|
|
1302
1332
|
result["content"] = window["content"] if window else chunk["content"]
|
|
1303
1333
|
|