code-context-control 2.138.0__tar.gz → 2.140.0__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.138.0 → code_context_control-2.140.0}/PKG-INFO +1 -1
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/c3.py +22 -2
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/commands/parser.py +2 -1
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/tools.html +11 -2
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_access_guard.py +71 -3
- code_context_control-2.140.0/cli/hook_agent_model.py +68 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_dispatch.py +11 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_server.py +7 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/mcp_server.py +33 -4
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/delegate.py +286 -12
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/status.py +15 -2
- {code_context_control-2.138.0 → code_context_control-2.140.0}/code_context_control.egg-info/PKG-INFO +1 -1
- {code_context_control-2.138.0 → code_context_control-2.140.0}/code_context_control.egg-info/SOURCES.txt +8 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/config.py +13 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/pyproject.toml +3 -1
- code_context_control-2.140.0/services/agent_downshift.py +220 -0
- code_context_control-2.140.0/services/bench/delegate_write_eval.py +370 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/claude_md.py +1 -1
- code_context_control-2.140.0/services/delegate_hints.py +199 -0
- code_context_control-2.140.0/services/delegate_write.py +243 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/telemetry.py +5 -1
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_adoption_d4.py +9 -1
- code_context_control-2.140.0/tests/test_delegate_auto.py +362 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_telemetry_d0.py +18 -0
- code_context_control-2.140.0/tests/test_delegate_write.py +477 -0
- code_context_control-2.140.0/tests/test_delegate_write_eval.py +48 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/LICENSE +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/README.md +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/_hook_utils.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/_shell_writes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/commands/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/commands/common.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/docs.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/edits.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/access.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/credentials.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/index.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/masking.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/oracle.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/shared.css +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/guide/workflow.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_artifact.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_c3read.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_codex_lifecycle.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_filter.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_read.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_session_end.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_session_open.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/hub_access.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/hub_ui.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/progress.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/server.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/_grants.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/agent.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/ci.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/compress.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/credentials.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/edit.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/edits.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/federate.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/filter.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/impact.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/jira.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/locks.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/memory.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/override.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/project.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/read.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/search.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/session.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/shell.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/shell_job.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/shell_nudge.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/shell_parsers.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/shell_render.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/tasks.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/tools/validate.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/api.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/app.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/access.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/icons.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/shared.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui/theme.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui_legacy.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/cli/ui_nano.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/codex_patch.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/grok_payload.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/hook_command.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/host.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/ide.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/mcp_toml.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/core/web_security.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/config.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/listeners.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/oracle_server.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/client_tokens.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/local_session.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/mobile_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/activity.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/agents.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/app.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/busy.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/core.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/header.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/insights.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/projects.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/settings.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/access_guard.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/access_telemetry.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/activity_log.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/agent_base.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/agent_locks.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/agents.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/agents_workflow.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/artifact_defs.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/artifact_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/atomic_json.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/auto_memory.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/background_service.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bench/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bench/delegate_eval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bench/map_eval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bench/search_eval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bench/shell_eval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bitbucket_client.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_act.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_cache.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_expr.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_failures.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_github.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_impact.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_intel.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_runner.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ci_workflow.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/circuit_breaker.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/codex_integration.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/codex_transcript.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/compressor.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/context_snapshot.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/conversation_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/cred_audit.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/cred_telemetry.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/credential_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/delegate_agents.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/dir_map.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/doc_index.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/e2e_tasks.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/edit_ledger.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/embedding_index.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/enforcement_policy.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/error_reporting.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/file_map.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/file_memory.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/git_context.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/grok_integration.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/grok_transcript.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/host_sessions.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/hub_service.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/index_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/indexer.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/jira_client.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/jira_cloud.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/jira_credentials.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/jira_data_center.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/jira_links.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/lexical_index.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/mask_activation.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/mask_mirror.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/mask_presets.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/memory.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/memory_consolidator.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/memory_distiller.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/memory_graph.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/memory_grounder.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/memory_queue.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/memory_scorer.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/metrics.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/notifications.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ollama_bridge.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ollama_client.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/ollama_credentials.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/oracle_service.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/output_filter.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/override_costs.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/override_grants.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/override_policy.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/override_requests.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/override_wake.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/parser.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/project_manager.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/project_runtime.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/protocol.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/proxy_state.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/repo_map.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/repo_shape.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/reranker.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/retention.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/retrieval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/retrieval_broker.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/router.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/runtime.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/scanner.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/session_benchmark.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/session_live.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/session_manager.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/session_preloader.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/shell_jobs.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/shell_output.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/subprojects.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/task_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/text_index.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/time_tracker.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/tool_classifier.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/transcript_index.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/validation_cache.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/vector_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/watcher.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/services/win_subprocess.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/setup.cfg +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_access_guard.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_activity_log_find_last.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_atomic_json.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_background_service.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_builtin_modes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ci_act.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ci_dag_ownership.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_claude_md_updater.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_codex_mcp_transport.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_codex_native.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_confirm_guard.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_confirm_guard_wiring.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_cred_audit.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_credential_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_claude_d1.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_eval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_grok.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_host_d2.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_scout_d3.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_thinking_cap.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_tuning.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_dir_map_c3.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_env_parser.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_file_map_c1.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_grok_native.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_grok_compat.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_session_end.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_state.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_hook_migration.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_override_policy_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_override_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_index_cap_not_hardcoded.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_init_scan.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_jira_client.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_jira_links.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_large_files_c4.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_map_eval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_map_telemetry_c0.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_memory_system.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mobile_clients.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mobile_jobs_ci.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mobile_override_costs.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_notification_kinds.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_loopback.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_output_filter.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_override_costs.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_override_grants.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_override_requests.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_override_wake.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_permissions.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_pm_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_project_manager.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_project_tool.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_read_outside_root.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_related_facts.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_repo_map.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_retention.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_review_digest.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_search_eval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_search_p1.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_search_p2.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_search_p2b.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_search_p3.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_search_p4.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_search_p5.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_service_durability.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_session_budget.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_session_live.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_budget_s1.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_eval.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_jobs_s3.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_nudge_s4.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_output.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_parsers_s2.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_telemetry_s0.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_subproject_clear_scope.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_subproject_depth_consumers.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_subproject_linkage_api.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_subprojects.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_task_store.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_task_tool.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_token_tracking.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_ui_jsx_syntax.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_validate.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_version_sync.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_watcher_pruning.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_web_security.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/backend.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/main.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/__init__.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/index_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/init_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/search_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/session_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/stats.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.138.0 → code_context_control-2.140.0}/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.140.0
|
|
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
|
|
@@ -91,7 +91,10 @@ console = Console() if HAS_RICH else None
|
|
|
91
91
|
# Config
|
|
92
92
|
CONFIG_DIR = ".c3"
|
|
93
93
|
CONFIG_FILE = ".c3/config.json"
|
|
94
|
-
__version__ = "2.
|
|
94
|
+
__version__ = "2.140.0"
|
|
95
|
+
|
|
96
|
+
# The PreToolUse matcher for native subagent calls (installer and hub migration).
|
|
97
|
+
AGENT_MATCHER = "Agent|Task"
|
|
95
98
|
|
|
96
99
|
|
|
97
100
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -1583,6 +1586,19 @@ def cmd_delegate_eval(args):
|
|
|
1583
1586
|
|
|
1584
1587
|
targets = [t.strip() for t in (args.targets or "").split(",") if t.strip()]
|
|
1585
1588
|
case_ids = [c.strip() for c in (args.cases or "").split(",") if c.strip()]
|
|
1589
|
+
if args.suite == "write":
|
|
1590
|
+
# Write mode (docs/delegate-write.md): graded on the files left behind.
|
|
1591
|
+
from services.bench import delegate_write_eval as dwe
|
|
1592
|
+
if not targets:
|
|
1593
|
+
raise RuntimeError("--suite write needs --targets (e.g. claude:small,claude:medium, or gold)")
|
|
1594
|
+
try:
|
|
1595
|
+
overrides = json.loads(args.config) if getattr(args, "config", None) else None
|
|
1596
|
+
report = dwe.run_write_suite(targets, case_ids=case_ids or None, record=args.record,
|
|
1597
|
+
delegate_overrides=overrides)
|
|
1598
|
+
except ValueError as e:
|
|
1599
|
+
raise RuntimeError(str(e))
|
|
1600
|
+
print(json.dumps(report, indent=2) if args.json else dwe.render(report))
|
|
1601
|
+
return
|
|
1586
1602
|
overrides = json.loads(args.config) if getattr(args, "config", None) else None
|
|
1587
1603
|
if overrides is not None and not isinstance(overrides, dict):
|
|
1588
1604
|
raise RuntimeError("--config must be a JSON object")
|
|
@@ -5065,7 +5081,7 @@ back to native tools as the task progresses.
|
|
|
5065
5081
|
- **Filter**: `c3_filter(text=...)` — for terminal output >10 lines
|
|
5066
5082
|
- **Shell**: `c3_shell(cmd, timeout=60)` — structured shell exec (tests/git/build). Auto-filters output, logs git mutations to the ledger. Native Bash for interactive/TTY only
|
|
5067
5083
|
- **Memory**: `c3_memory(action='recall')` — full recall. `index` + `fetch` for token-efficient two-step retrieval
|
|
5068
|
-
- **Delegate**: `c3_delegate(task, task_type, context|file_path)` — your own provider one tier down (default `backend='host'`, `tier='small'`; Claude Code: Haiku) for bounded answers: summarize a diff/log, explain a function, triage a traceback. `scout=true` lets it look files up itself. Multi-step work: the `c3-scout` (haiku) / `c3-worker` (sonnet) subagents
|
|
5084
|
+
- **Delegate**: `c3_delegate(task, task_type, context|file_path)` — your own provider one tier down (default `backend='host'`, `tier='small'`; Claude Code: Haiku) for bounded answers: summarize a diff/log, explain a function, triage a traceback. `scout=true` lets it look files up itself; `write_paths='a.py,b.py'` has Sonnet make a change you specified in only those files and return the diff. Multi-step work: the `c3-scout` (haiku) / `c3-worker` (sonnet) subagents; an `Agent` call with no `model` runs one tier below you (pass `model=` to choose)
|
|
5069
5085
|
- **Local CI** (v2.79.0+): `c3_ci(action='inspect|run|rerun|failures')` — run THIS repo's real `.github/workflows` here instead of pushing for feedback. `run` executes in `needs` order; `failures` gives {file,line,message}; `rerun` retries only what failed. Only `FULL_CI_PASS` means safe to push — `PARTIAL_PASS` means something did not run (other OS, unsupported action, or your selection).
|
|
5070
5086
|
- **Bitbucket** (v2.30.0+, when `c3 bitbucket login` has run): `c3_bitbucket(action='list_prs|get_pr|merge_pr|...')` — self-hosted Bitbucket Data Center / Server. Token in OS keyring; mutating actions auto-log to the edit ledger.
|
|
5071
5087
|
- **Cross-project** (v2.31.0+): `c3_project(action='list|scan|search|read|edit|...', project='<name|path>')` — discover and operate on OTHER c3-installed projects. Reads run freely; writes (edit/shell/memory) need `allow_write=true`.
|
|
@@ -5684,6 +5700,10 @@ def cmd_install_mcp(args):
|
|
|
5684
5700
|
shell_matcher,
|
|
5685
5701
|
"run_shell_command",
|
|
5686
5702
|
]
|
|
5703
|
+
# Native subagents (v2.140.0): a blank `model` is filled one tier below
|
|
5704
|
+
# the parent by hook_agent_model — without this matcher PreToolUse
|
|
5705
|
+
# never fires for Agent calls.
|
|
5706
|
+
_pre_matcher_names.append(AGENT_MATCHER)
|
|
5687
5707
|
desired_pre_hooks = [
|
|
5688
5708
|
{"matcher": m, "hooks": [{"type": "command", "command": hook_pretool_cmd}]}
|
|
5689
5709
|
for m in _pre_matcher_names
|
|
@@ -92,7 +92,8 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
92
92
|
p_delegate_eval = subparsers.add_parser(
|
|
93
93
|
"delegate-eval", help="Grade c3_delegate answers per backend/tier (docs/delegate-eval.md)")
|
|
94
94
|
p_delegate_eval.add_argument("--suite", default="gold",
|
|
95
|
-
help="'gold' (bundled)
|
|
95
|
+
help="'gold' (bundled), 'write' (write mode, docs/delegate-write.md) "
|
|
96
|
+
"or a .jsonl path")
|
|
96
97
|
p_delegate_eval.add_argument("--targets", default="",
|
|
97
98
|
help="Comma-separated backend[:tier] list, e.g. 'claude:small,claude:medium'")
|
|
98
99
|
p_delegate_eval.add_argument("--cases", default="", help="Comma-separated case ids (default: all)")
|
|
@@ -954,6 +954,12 @@ c3_status(view=<span class="str">'sessions'</span>) <span class="com">#
|
|
|
954
954
|
<td class="param-default">false</td>
|
|
955
955
|
<td class="param-desc">Let the delegate Read/Grep/Glob the project itself, for lookups when you cannot name the files. Claude runs <code>--restricted</code> with Access Guard's read denies; Codex uses its read-only sandbox.</td>
|
|
956
956
|
</tr>
|
|
957
|
+
<tr>
|
|
958
|
+
<td class="param-name">write_paths</td>
|
|
959
|
+
<td class="param-type">string</td>
|
|
960
|
+
<td class="param-default">""</td>
|
|
961
|
+
<td class="param-desc">Write mode (Claude only, defaults to Sonnet). Comma-separated project-relative globs the delegate may edit or create. You decide the change; it makes it with Read/Grep/Glob/Edit/Write, no commands. You get back the diff, and each change is in the edit ledger. Access Guard applies; confirm-held, locked, <code>.git/</code> and <code>.c3/</code> paths are refused. Review the diff and run the tests yourself.</td>
|
|
962
|
+
</tr>
|
|
957
963
|
</tbody>
|
|
958
964
|
</table>
|
|
959
965
|
|
|
@@ -965,12 +971,15 @@ c3_delegate(task=<span class="str">'Summarize this diff for a changelog in three
|
|
|
965
971
|
c3_delegate(task=<span class="str">'What does resolve_host return inside a grok child?'</span>, file_path=<span class="str">'core/host.py'</span>, task_type=<span class="str">'explain'</span>, tier=<span class="str">'medium'</span>)
|
|
966
972
|
|
|
967
973
|
<span class="com"># A lookup the delegate does itself</span>
|
|
968
|
-
c3_delegate(task=<span class="str">'Which functions call charge_card, and where?'</span>, scout=<span class="kw">True</span>)
|
|
974
|
+
c3_delegate(task=<span class="str">'Which functions call charge_card, and where?'</span>, scout=<span class="kw">True</span>)
|
|
975
|
+
|
|
976
|
+
<span class="com"># A change you have decided, made by Sonnet inside a write set</span>
|
|
977
|
+
c3_delegate(task=<span class="str">'Rename calc_total to order_total in its definition and every use; no alias'</span>, write_paths=<span class="str">'inv/orders.py, inv/report.py, tests/test_orders.py'</span>)</code></pre>
|
|
969
978
|
|
|
970
979
|
<div class="callout callout-info">
|
|
971
980
|
<span class="callout-icon">ℹ️</span>
|
|
972
981
|
<div class="callout-body">
|
|
973
|
-
For multi-step work in Claude Code, <code>c3 install-mcp</code> also writes two subagents to <code>.claude/agents</code>: <code>c3-scout</code> (Haiku, read-only) and <code>c3-worker</code> (Sonnet). They run inside your session, so C3's hooks apply to them. Skip them with <code>--no-agents</code>. <code>c3 delegate-eval</code> measures pass rate and cost per backend and tier on your machine.
|
|
982
|
+
For multi-step work in Claude Code, <code>c3 install-mcp</code> also writes two subagents to <code>.claude/agents</code>: <code>c3-scout</code> (Haiku, read-only) and <code>c3-worker</code> (Sonnet). They run inside your session, so C3's hooks apply to them. Skip them with <code>--no-agents</code>. Any other <code>Agent</code> call that leaves <code>model</code> blank runs one tier below your session (Fable → Opus → Sonnet, never below Sonnet); set <code>delegate.agent_downshift</code> to <code>"off"</code> to keep the parent's model. When your own work looks delegable, a <code>[c3:delegate-hint]</code> line on the tool response names the call to make. <code>c3 delegate-eval</code> measures pass rate and cost per backend and tier on your machine.
|
|
974
983
|
</div>
|
|
975
984
|
</div>
|
|
976
985
|
</div>
|
|
@@ -503,14 +503,77 @@ def run(payload: dict, project_path: Path | None = None,
|
|
|
503
503
|
return None
|
|
504
504
|
|
|
505
505
|
|
|
506
|
+
def _worker_refusal(rel: str, why: str) -> dict:
|
|
507
|
+
return _deny(f"[c3-delegate:refused] {rel}: {why}. Do not write it another way; "
|
|
508
|
+
"leave it and say in your report what change it needed.")
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def worker_run(payload: dict, project_path: Path, state_dir: Path) -> dict | None:
|
|
512
|
+
"""PreToolUse for a ``c3_delegate`` write-mode worker (see services/delegate_write).
|
|
513
|
+
|
|
514
|
+
Reads go through ``run`` exactly as for a scout. A write must pass, in
|
|
515
|
+
order: canonicalization inside the project, never ``.git/`` or ``.c3/``,
|
|
516
|
+
never the credential vault, Access Guard with NO grants and NO filed
|
|
517
|
+
requests (a confirm hold is a refusal here — a headless worker cannot
|
|
518
|
+
wait for a human, and the caller can make that edit itself), the caller's
|
|
519
|
+
write set, and another agent's lock. Then the pre-image is saved before
|
|
520
|
+
the write is allowed. Raises on a broken spec; main() turns that into a
|
|
521
|
+
deny.
|
|
522
|
+
"""
|
|
523
|
+
from services import delegate_write as dw
|
|
524
|
+
|
|
525
|
+
tool = normalize_tool_name(payload.get("tool_name", ""))
|
|
526
|
+
if tool not in _WRITE_TOOLS:
|
|
527
|
+
return run(payload, project_path)
|
|
528
|
+
spec = dw.load_spec(state_dir)
|
|
529
|
+
fp = _target(payload.get("tool_input", {}) or {})
|
|
530
|
+
if not fp:
|
|
531
|
+
return _deny("[c3-delegate:refused] a write with no target path")
|
|
532
|
+
base = str(project_path)
|
|
533
|
+
canon, rel, denial = ag.canonicalize(fp, base)
|
|
534
|
+
if denial:
|
|
535
|
+
return _worker_refusal(fp, f"path refused ({denial.reason})")
|
|
536
|
+
if not rel:
|
|
537
|
+
return _worker_refusal(fp, "outside the project")
|
|
538
|
+
if dw.forbidden(rel):
|
|
539
|
+
return _worker_refusal(rel, "under .git/ or .c3/, never delegate-writable")
|
|
540
|
+
try:
|
|
541
|
+
from services import credential_store as _cs
|
|
542
|
+
vault = _cs.vault_guard_reason(fp)
|
|
543
|
+
except Exception as exc: # fail closed: an unloadable vault check refuses
|
|
544
|
+
vault = f"vault check unavailable ({type(exc).__name__})"
|
|
545
|
+
if vault:
|
|
546
|
+
return _worker_refusal(rel, "credential vault file")
|
|
547
|
+
op = "write" if os.path.exists(fp) else "create"
|
|
548
|
+
denial = ag.check(fp, op, base)
|
|
549
|
+
if denial:
|
|
550
|
+
_record(denial, tool, op, fp, base, str(payload.get("session_id") or ""))
|
|
551
|
+
return _worker_refusal(rel, f"Access Guard {denial.kind} rule '{denial.rule}' "
|
|
552
|
+
f"({denial.scope})")
|
|
553
|
+
if not dw.in_write_set(rel, spec["write_paths"]):
|
|
554
|
+
return _worker_refusal(rel, "outside the write set the caller gave ("
|
|
555
|
+
+ ", ".join(spec["write_paths"]) + ")")
|
|
556
|
+
try:
|
|
557
|
+
from services import agent_locks
|
|
558
|
+
holder = agent_locks.check(fp, base, str(spec.get("session_id") or ""))
|
|
559
|
+
except Exception:
|
|
560
|
+
holder = None
|
|
561
|
+
if holder:
|
|
562
|
+
return _worker_refusal(rel, f"locked by {holder.get('agent_id', 'another agent')}")
|
|
563
|
+
dw.snapshot(state_dir, fp, canon)
|
|
564
|
+
return None
|
|
565
|
+
|
|
566
|
+
|
|
506
567
|
def main() -> None:
|
|
507
|
-
"""Standalone PreToolUse entry for a ``c3_delegate`` scout run.
|
|
568
|
+
"""Standalone PreToolUse entry for a ``c3_delegate`` scout or worker run.
|
|
508
569
|
|
|
509
570
|
A scout is ``claude -p --restricted`` with Read/Grep/Glob and no C3 MCP
|
|
510
571
|
server, so the dispatcher's discipline hook (hook_pretool_enforce) would
|
|
511
572
|
refuse every native read. Only the access guard runs here. It prints a
|
|
512
573
|
deny and nothing else: grants and search footers are for an agent that
|
|
513
574
|
can act on them. Any failure denies (fail closed).
|
|
575
|
+
|
|
576
|
+
``--worker-state DIR``: a write-mode worker; see ``worker_run``.
|
|
514
577
|
"""
|
|
515
578
|
import argparse
|
|
516
579
|
import json
|
|
@@ -520,6 +583,7 @@ def main() -> None:
|
|
|
520
583
|
ensure_utf8_stdio()
|
|
521
584
|
parser = argparse.ArgumentParser()
|
|
522
585
|
parser.add_argument("--project", required=True)
|
|
586
|
+
parser.add_argument("--worker-state", default="")
|
|
523
587
|
args = parser.parse_args()
|
|
524
588
|
try:
|
|
525
589
|
raw = sys.stdin.read()
|
|
@@ -527,9 +591,13 @@ def main() -> None:
|
|
|
527
591
|
if not isinstance(payload, dict):
|
|
528
592
|
raise ValueError("hook payload must be a JSON object")
|
|
529
593
|
# access_guard canonicalizes the base itself (no direct resolve here).
|
|
530
|
-
|
|
594
|
+
if args.worker_state:
|
|
595
|
+
out = worker_run(payload, Path(args.project), Path(args.worker_state))
|
|
596
|
+
else:
|
|
597
|
+
out = run(payload, Path(args.project))
|
|
531
598
|
except Exception as exc:
|
|
532
|
-
|
|
599
|
+
who = "worker" if args.worker_state else "scout"
|
|
600
|
+
out = _deny(f"[c3-access:error] {who} guard failed ({type(exc).__name__}: {exc}); "
|
|
533
601
|
"refusing the call")
|
|
534
602
|
if isinstance(out, dict) and isinstance(out.get("hookSpecificOutput"), dict):
|
|
535
603
|
print(json.dumps({"hookSpecificOutput": out["hookSpecificOutput"]}))
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""PreToolUse sub-hook: a native subagent with no ``model`` gets one tier below its parent.
|
|
2
|
+
|
|
3
|
+
Routed by cli/hook_dispatch.py for ``Agent`` / ``Task`` on Claude Code only;
|
|
4
|
+
the policy lives in services/agent_downshift.py. Returns
|
|
5
|
+
``hookSpecificOutput.updatedInput`` (the whole tool_input with ``model`` set),
|
|
6
|
+
or None to leave the call as it is. Every decision on a blank call — applied
|
|
7
|
+
or not, and why — is one ``agent_downshift`` telemetry row, so coverage is
|
|
8
|
+
measurable (how many calls fell through as ``parent_unknown``).
|
|
9
|
+
|
|
10
|
+
Opt out per project with ``delegate.agent_downshift: "off"``, or for a shell
|
|
11
|
+
with ``C3_AGENT_DOWNSHIFT=0``. Never raises into the tool call.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
20
|
+
|
|
21
|
+
from cli._hook_utils import find_project, log_hook_error # noqa: E402
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def run(payload: dict, project_path: Path | None = None):
|
|
25
|
+
try:
|
|
26
|
+
return _run(payload, project_path)
|
|
27
|
+
except Exception as exc: # a model choice is never worth a failed tool call
|
|
28
|
+
log_hook_error("hook_agent_model", exc)
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _run(payload: dict, project_path):
|
|
33
|
+
from services import agent_downshift as ad
|
|
34
|
+
|
|
35
|
+
if str(payload.get("tool_name") or "") not in ad.SUBAGENT_TOOLS:
|
|
36
|
+
return None
|
|
37
|
+
tool_input = payload.get("tool_input")
|
|
38
|
+
if not isinstance(tool_input, dict):
|
|
39
|
+
return None
|
|
40
|
+
if str(tool_input.get("model") or "").strip():
|
|
41
|
+
return None # the caller chose
|
|
42
|
+
if os.environ.get("C3_AGENT_DOWNSHIFT", "").strip().lower() in ("0", "off", "false", "no"):
|
|
43
|
+
return None
|
|
44
|
+
project = find_project(payload, project_path)
|
|
45
|
+
if project is None:
|
|
46
|
+
return None
|
|
47
|
+
from core.config import load_delegate_config
|
|
48
|
+
|
|
49
|
+
cfg = load_delegate_config(str(project))
|
|
50
|
+
stype = str(tool_input.get("subagent_type") or "general-purpose")
|
|
51
|
+
if ":" in stype:
|
|
52
|
+
return None # plugin agent: its definition is not ours to second-guess
|
|
53
|
+
if ad.definition_sets_model(stype, project):
|
|
54
|
+
return None
|
|
55
|
+
parent, source = ad.parent_model(payload, project)
|
|
56
|
+
target, reason = ad.resolve(stype, parent, cfg)
|
|
57
|
+
try:
|
|
58
|
+
from services.telemetry import append_telemetry_record
|
|
59
|
+
append_telemetry_record(project, {"tool": "agent_downshift" if target else "agent_downshift_skip",
|
|
60
|
+
"detail": {
|
|
61
|
+
"subagent_type": stype, "parent_model": parent, "parent_source": source,
|
|
62
|
+
"model": target, "reason": reason, "applied": bool(target)}})
|
|
63
|
+
except Exception:
|
|
64
|
+
pass
|
|
65
|
+
if not target:
|
|
66
|
+
return None
|
|
67
|
+
return {"hookSpecificOutput": {"hookEventName": "PreToolUse",
|
|
68
|
+
"updatedInput": {**tool_input, "model": target}}}
|
|
@@ -136,6 +136,10 @@ def _routes(event: str, raw_tool: str, norm_tool: str, host: str = HOST_CLAUDE):
|
|
|
136
136
|
yield "hook_access_guard"
|
|
137
137
|
# hook_pretool_enforce self-filters via its _PREREQS table.
|
|
138
138
|
yield "hook_pretool_enforce"
|
|
139
|
+
# A native subagent with no model inherits the parent's; this fills
|
|
140
|
+
# one in (services/agent_downshift.py). Claude Code only.
|
|
141
|
+
if raw_tool in ("Agent", "Task") and host == HOST_CLAUDE:
|
|
142
|
+
yield "hook_agent_model"
|
|
139
143
|
elif event == "posttool":
|
|
140
144
|
# hook_filter is the ONE sub-hook that reads the whole tool payload:
|
|
141
145
|
# it tiktoken-encodes the entire Bash output to measure savings, a
|
|
@@ -402,6 +406,7 @@ def merge_outputs(outputs: list, warnings: list, is_gemini: bool = False,
|
|
|
402
406
|
host = HOST_GEMINI if is_gemini else HOST_CLAUDE
|
|
403
407
|
|
|
404
408
|
deny_hso = None
|
|
409
|
+
updated_input = None
|
|
405
410
|
contexts: list = []
|
|
406
411
|
texts: list = []
|
|
407
412
|
tool_result = None
|
|
@@ -413,6 +418,8 @@ def merge_outputs(outputs: list, warnings: list, is_gemini: bool = False,
|
|
|
413
418
|
if isinstance(hso, dict):
|
|
414
419
|
if deny_hso is None and hso.get("permissionDecision") == "deny":
|
|
415
420
|
deny_hso = hso
|
|
421
|
+
if updated_input is None and isinstance(hso.get("updatedInput"), dict):
|
|
422
|
+
updated_input = hso["updatedInput"]
|
|
416
423
|
nested_ctx = hso.get("additionalContext")
|
|
417
424
|
if nested_ctx and hso.get("permissionDecision") != "deny":
|
|
418
425
|
contexts.append(str(nested_ctx))
|
|
@@ -435,6 +442,10 @@ def merge_outputs(outputs: list, warnings: list, is_gemini: bool = False,
|
|
|
435
442
|
result: dict = {}
|
|
436
443
|
if deny_hso is not None:
|
|
437
444
|
result["hookSpecificOutput"] = deny_hso
|
|
445
|
+
elif updated_input is not None and host == HOST_CLAUDE and event == "pretool":
|
|
446
|
+
# A rewritten tool input (hook_agent_model) — never alongside a deny.
|
|
447
|
+
result["hookSpecificOutput"] = {"hookEventName": "PreToolUse",
|
|
448
|
+
"updatedInput": updated_input}
|
|
438
449
|
if tool_result is not None:
|
|
439
450
|
if is_gemini:
|
|
440
451
|
# Gemini has no tool_result replacement — degrade to context,
|
|
@@ -4516,9 +4516,16 @@ def c3_hook_migrations(cli_dir: Path | None = None) -> list:
|
|
|
4516
4516
|
"command": f"{dispatch} {arg}"}]},
|
|
4517
4517
|
}
|
|
4518
4518
|
|
|
4519
|
+
# v2.140.0: native subagent calls reach the pretool dispatcher, where
|
|
4520
|
+
# hook_agent_model fills a blank model. Same literal as cli.c3.AGENT_MATCHER.
|
|
4521
|
+
agent_entry = {"matcher": "Agent|Task",
|
|
4522
|
+
"hooks": [{"type": "command", "command": f"{dispatch} pretool"}]}
|
|
4523
|
+
|
|
4519
4524
|
return [
|
|
4520
4525
|
{"settings": ".claude/settings.local.json", "event": "PostToolUse",
|
|
4521
4526
|
"present": c3read_present, "entry": c3read_entry},
|
|
4527
|
+
{"settings": ".claude/settings.local.json", "event": "PreToolUse",
|
|
4528
|
+
"present": _has_matcher("Agent|Task"), "entry": agent_entry},
|
|
4522
4529
|
{"settings": ".gemini/settings.json", "event": "AfterTool",
|
|
4523
4530
|
"present": c3read_present, "entry": c3read_entry},
|
|
4524
4531
|
# Claude only — Gemini has no session-lifecycle event to hang these on.
|
|
@@ -25,6 +25,7 @@ from fastmcp import Context, FastMCP
|
|
|
25
25
|
|
|
26
26
|
from core.host import resolve_host
|
|
27
27
|
from core.ide import get_profile
|
|
28
|
+
from services import delegate_hints
|
|
28
29
|
from services.auto_memory import AutoMemory
|
|
29
30
|
from services.context_snapshot import ContextSnapshot
|
|
30
31
|
from services.runtime import C3Runtime, build_runtime, start_runtime, stop_runtime
|
|
@@ -515,6 +516,21 @@ _last_badge_count: int = 0 # delta-based: only show badge when count increases
|
|
|
515
516
|
_finalize_lock = threading.Lock()
|
|
516
517
|
|
|
517
518
|
|
|
519
|
+
def _with_hint(resp, make_hint) -> str:
|
|
520
|
+
"""``resp`` plus a delegation hint line (services/delegate_hints), when the
|
|
521
|
+
call succeeded and a hint is due. A hint is advice: it never fails a call."""
|
|
522
|
+
if not isinstance(resp, str):
|
|
523
|
+
return resp
|
|
524
|
+
try:
|
|
525
|
+
from cli._hook_utils import response_text_failed
|
|
526
|
+
if response_text_failed(resp):
|
|
527
|
+
return resp
|
|
528
|
+
hint = make_hint()
|
|
529
|
+
except Exception:
|
|
530
|
+
return resp
|
|
531
|
+
return f"{resp}\n{hint}" if hint else resp
|
|
532
|
+
|
|
533
|
+
|
|
518
534
|
def _finalize_response(ctx: Context, tool_name: str, args: dict,
|
|
519
535
|
response: str, summary: str = "",
|
|
520
536
|
response_tokens: int = 0) -> str:
|
|
@@ -668,10 +684,11 @@ async def c3_search(query: str, action: str = "code", top_k: int = 3,
|
|
|
668
684
|
def finalize(name, args, resp, summ, **kw):
|
|
669
685
|
return _finalize_response(ctx, name, args, resp, summ, **kw)
|
|
670
686
|
|
|
671
|
-
|
|
687
|
+
resp = await asyncio.to_thread(handle_search, query, action, top_k, max_tokens, svc,
|
|
672
688
|
finalize, maybe_related_facts, prefetch=prefetch,
|
|
673
689
|
scope=scope, ignore_case=ignore_case,
|
|
674
690
|
path=path, lang=lang, kind=kind)
|
|
691
|
+
return _with_hint(resp, lambda: delegate_hints.after_read(svc, ""))
|
|
675
692
|
|
|
676
693
|
|
|
677
694
|
@mcp.tool()
|
|
@@ -746,7 +763,10 @@ async def c3_read(file_path: str, symbols: Any = None, lines: Any = None,
|
|
|
746
763
|
def finalize(name, args, resp, summ, **kw):
|
|
747
764
|
return _finalize_response(ctx, name, args, resp, summ, **kw)
|
|
748
765
|
|
|
749
|
-
|
|
766
|
+
resp = await asyncio.to_thread(handle_read, file_path, symbols, lines, include_docstrings, svc, finalize)
|
|
767
|
+
if not (symbols or lines):
|
|
768
|
+
return resp # a map is the cheap way to look; it does not count toward the hint
|
|
769
|
+
return _with_hint(resp, lambda: delegate_hints.after_read(svc, file_path.split(",")[0].strip()))
|
|
750
770
|
|
|
751
771
|
|
|
752
772
|
# c3_compress left the MCP surface in 2.124.0: c3_read(file_path) serves the
|
|
@@ -806,11 +826,13 @@ async def c3_delegate(task: str, task_type: str = "ask", context: str = "",
|
|
|
806
826
|
file_path: str = "", backend: str = "host",
|
|
807
827
|
allow_write_delegation: bool = False,
|
|
808
828
|
tier: str = "", model: str = "", scout: bool = False,
|
|
829
|
+
write_paths: str = "",
|
|
809
830
|
ctx: Context = None) -> str:
|
|
810
831
|
"""OFFLOAD to another model — use when the subtask is local-model-sized or needs a different perspective.
|
|
811
832
|
backend: host (default: your own provider, one tier down — Claude Code->claude, Codex->codex, Grok->grok, Antigravity->gemini) | claude|codex|gemini|grok|ollama|auto. task_type: auto, summarize, explain, review, ask, test, diagnose, ping (live auth check), available, codex_check, gemini_check, grok_check, codex_resume.
|
|
812
833
|
tier: small (default; scout=true defaults to medium) | medium | large | default. claude: haiku/sonnet/opus; codex/grok: reasoning effort; gemini: flash-lite/flash/pro. model overrides the tier. Context + file_path are packed by C3 under Access Guard; a file over 8k tokens goes as its map, so for line-level questions on a big file paste the excerpt or use scout=true.
|
|
813
834
|
scout=true: the delegate may Read/Grep/Glob the project itself (claude: read-only, guard-denied paths refused; codex: its read-only sandbox) — for lookups when you cannot name the files.
|
|
835
|
+
write_paths: comma-separated project-relative globs the delegate may edit or create (write mode; claude only, tier defaults to medium). You decide the change: say what to change, where, and the intended behaviour. It cannot run commands. You get back the diff (each change is in the edit ledger): review it and run the tests yourself. Access Guard applies; confirm-held, locked, .git/ and .c3/ paths are refused.
|
|
814
836
|
grok runs read-only in a temp dir unless delegate.grok_allow_write=true (then --yolo in the project, loading its trusted .grok MCP servers and hooks).
|
|
815
837
|
allow_write_delegation: explicit user opt-in for write-capable backends (gemini/grok write mode/codex_resume) while Access Guard rules are active; codex is pinned read-only instead."""
|
|
816
838
|
svc = _svc(ctx)
|
|
@@ -825,10 +847,15 @@ async def c3_delegate(task: str, task_type: str = "ask", context: str = "",
|
|
|
825
847
|
task.add_done_callback(lambda done: done.exception() if not done.cancelled() else None)
|
|
826
848
|
loop.call_soon_threadsafe(schedule)
|
|
827
849
|
svc._agent_progress_cb = _progress_cb
|
|
850
|
+
try:
|
|
851
|
+
delegate_hints.after_delegate(svc, write=bool(str(write_paths or "").strip()), scout=bool(scout))
|
|
852
|
+
except Exception:
|
|
853
|
+
pass
|
|
828
854
|
try:
|
|
829
855
|
return await asyncio.to_thread(handle_delegate, task, task_type, context,
|
|
830
856
|
file_path, svc, finalize, backend,
|
|
831
|
-
allow_write_delegation, tier, model, scout
|
|
857
|
+
allow_write_delegation, tier, model, scout,
|
|
858
|
+
write_paths)
|
|
832
859
|
finally:
|
|
833
860
|
svc._agent_progress_cb = None
|
|
834
861
|
|
|
@@ -876,8 +903,10 @@ async def c3_edit(file_path: str, old_string: str = "", new_string: str = "",
|
|
|
876
903
|
def finalize(name, args, resp, summ, **kw):
|
|
877
904
|
return _finalize_response(ctx, name, args, resp, summ, **kw)
|
|
878
905
|
|
|
879
|
-
|
|
906
|
+
resp = await asyncio.to_thread(handle_edit, file_path, old_string, new_string,
|
|
880
907
|
summary, tags, replace_all, svc, finalize, edits)
|
|
908
|
+
return _with_hint(resp, lambda: delegate_hints.after_edit(
|
|
909
|
+
svc, file_path, delegate_hints.edit_chars(new_string, edits)))
|
|
881
910
|
|
|
882
911
|
|
|
883
912
|
@mcp.tool()
|