code-context-control 2.113.0__tar.gz → 2.114.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.113.0 → code_context_control-2.114.0}/PKG-INFO +1 -1
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/c3.py +3 -2
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_dispatch.py +1 -1
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/mcp_server.py +40 -1
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/project.py +11 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/shell.py +3 -2
- code_context_control-2.114.0/cli/tools/shell_job.py +363 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/code_context_control.egg-info/PKG-INFO +1 -1
- {code_context_control-2.113.0 → code_context_control-2.114.0}/code_context_control.egg-info/SOURCES.txt +3 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/pyproject.toml +1 -1
- code_context_control-2.114.0/services/shell_jobs.py +1160 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/shell_output.py +11 -4
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_c3_shell.py +1 -1
- code_context_control-2.114.0/tests/test_shell_jobs_s3.py +488 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/LICENSE +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/README.md +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/_hook_utils.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/_shell_writes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/commands/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/commands/common.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/commands/parser.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/docs.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/edits.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/access.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/credentials.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/index.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/masking.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/oracle.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/shared.css +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/tools.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/guide/workflow.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_artifact.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_c3read.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_filter.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_read.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_server.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/hub_access.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/hub_ui.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/progress.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/server.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/_grants.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/agent.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/ci.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/compress.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/credentials.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/delegate.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/edit.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/edits.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/federate.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/filter.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/impact.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/jira.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/locks.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/memory.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/override.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/read.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/search.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/session.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/shell_parsers.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/shell_render.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/status.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/tasks.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/tools/validate.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/api.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/app.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/access.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/icons.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/shared.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui/theme.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui_legacy.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/cli/ui_nano.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/core/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/core/config.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/core/ide.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/core/mcp_toml.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/core/web_security.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/config.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/oracle_server.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/local_session.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/mobile_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/activity.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/agents.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/app.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/busy.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/core.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/header.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/insights.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/projects.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/settings.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/access_guard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/access_telemetry.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/activity_log.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/agent_base.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/agent_locks.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/agents.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/artifact_defs.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/artifact_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/auto_memory.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/background_service.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/bench/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/bench/search_eval.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/bench/shell_eval.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/bitbucket_client.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_act.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_cache.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_expr.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_failures.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_github.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_impact.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_intel.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_runner.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ci_workflow.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/circuit_breaker.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/claude_md.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/compressor.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/context_snapshot.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/conversation_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/cred_audit.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/cred_telemetry.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/credential_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/doc_index.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/e2e_tasks.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/edit_ledger.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/embedding_index.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/enforcement_policy.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/error_reporting.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/file_memory.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/git_context.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/hub_service.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/index_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/indexer.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/jira_client.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/jira_cloud.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/jira_credentials.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/jira_data_center.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/jira_links.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/lexical_index.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/mask_activation.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/mask_mirror.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/mask_presets.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/memory.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/memory_consolidator.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/memory_distiller.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/memory_graph.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/memory_grounder.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/memory_queue.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/memory_scorer.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/metrics.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/notifications.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ollama_bridge.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ollama_client.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/ollama_credentials.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/oracle_service.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/output_filter.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/override_grants.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/override_policy.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/override_requests.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/override_wake.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/parser.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/project_manager.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/project_runtime.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/protocol.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/proxy_state.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/repo_map.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/repo_shape.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/reranker.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/retention.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/retrieval.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/retrieval_broker.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/router.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/runtime.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/scanner.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/session_benchmark.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/session_manager.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/session_preloader.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/subprojects.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/task_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/telemetry.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/text_index.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/time_tracker.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/tool_classifier.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/transcript_index.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/validation_cache.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/vector_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/watcher.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/services/win_subprocess.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/setup.cfg +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_access_guard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_background_service.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_builtin_modes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ci_act.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_claude_md_updater.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_confirm_guard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_confirm_guard_wiring.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_cred_audit.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_credential_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_env_parser.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hook_state.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_override_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_index_cap_not_hardcoded.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_init_scan.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_jira_client.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_jira_links.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_memory_system.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_output_filter.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_override_grants.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_override_requests.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_override_wake.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_permissions.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_pm_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_project_manager.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_project_tool.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_related_facts.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_repo_map.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_retention.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_review_digest.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_search_eval.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_search_p1.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_search_p2.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_search_p2b.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_search_p3.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_search_p4.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_search_p5.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_service_durability.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_session_budget.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_budget_s1.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_eval.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_output.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_parsers_s2.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_telemetry_s0.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_subproject_clear_scope.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_subproject_depth_consumers.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_subproject_linkage_api.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_subprojects.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_task_store.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_task_tool.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_token_tracking.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_ui_jsx_syntax.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_validate.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_version_sync.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_web_security.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/backend.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/main.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/__init__.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/index_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/init_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/search_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/session_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/stats.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.0}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.113.0 → code_context_control-2.114.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.114.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
|
|
@@ -92,7 +92,7 @@ console = Console() if HAS_RICH else None
|
|
|
92
92
|
# Config
|
|
93
93
|
CONFIG_DIR = ".c3"
|
|
94
94
|
CONFIG_FILE = ".c3/config.json"
|
|
95
|
-
__version__ = "2.
|
|
95
|
+
__version__ = "2.114.0"
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -261,7 +261,7 @@ _C3_MCP_ALLOW = [
|
|
|
261
261
|
"mcp__c3__c3_bitbucket",
|
|
262
262
|
"mcp__c3__c3_jira", "mcp__c3__c3_credentials",
|
|
263
263
|
"mcp__c3__c3_project", "mcp__c3__c3_task", "mcp__c3__c3_artifacts",
|
|
264
|
-
"mcp__c3__c3_override", "mcp__c3__c3_ci",
|
|
264
|
+
"mcp__c3__c3_override", "mcp__c3__c3_ci", "mcp__c3__c3_shell_job",
|
|
265
265
|
]
|
|
266
266
|
|
|
267
267
|
# Obsolete MCP tool names from earlier C3 versions. `c3 permissions clean`
|
|
@@ -5639,6 +5639,7 @@ def cmd_install_mcp(args):
|
|
|
5639
5639
|
"mcp__c3__c3_delegate",
|
|
5640
5640
|
"mcp__c3__c3_session",
|
|
5641
5641
|
"mcp__c3__c3_agent",
|
|
5642
|
+
"mcp__c3__c3_shell_job",
|
|
5642
5643
|
edit_matcher,
|
|
5643
5644
|
write_matcher,
|
|
5644
5645
|
*extra_edit_matchers,
|
|
@@ -97,7 +97,7 @@ _SIGNAL_TOOLS = {
|
|
|
97
97
|
"mcp__c3__c3_compress", "mcp__c3__c3_filter", "mcp__c3__c3_memory",
|
|
98
98
|
"mcp__c3__c3_validate", "mcp__c3__c3_edit", "mcp__c3__c3_edits",
|
|
99
99
|
"mcp__c3__c3_impact", "mcp__c3__c3_status", "mcp__c3__c3_delegate",
|
|
100
|
-
"mcp__c3__c3_session", "mcp__c3__c3_agent",
|
|
100
|
+
"mcp__c3__c3_session", "mcp__c3__c3_agent", "mcp__c3__c3_shell_job",
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
# hook_edit_unlock was registered only for c3_compress and c3_agent
|
|
@@ -917,7 +917,10 @@ async def c3_shell(cmd: str = "", cwd: str = "", timeout: int = 60,
|
|
|
917
917
|
$HOME/~; fork bombs; whole-drive wipes) — a guard, NOT a sandbox. Soft-warns on
|
|
918
918
|
--force, --no-verify, reset --hard.
|
|
919
919
|
Git Bash may not include optional tools such as jq; use `python -m json.tool`
|
|
920
|
-
for portable JSON formatting. Native Bash remains the fallback for interactive/TTY commands.
|
|
920
|
+
for portable JSON formatting. Native Bash remains the fallback for interactive/TTY commands.
|
|
921
|
+
Work longer than this client's tool-call ceiling (full test suites, builds, device
|
|
922
|
+
commands) belongs in c3_shell_job, which runs it in a detached supervisor for up to 6 h
|
|
923
|
+
and keeps its output in the same store — a timeout here is never converted into a job."""
|
|
921
924
|
svc = _svc(ctx)
|
|
922
925
|
|
|
923
926
|
def finalize(name, args, resp, summ, **kw):
|
|
@@ -930,6 +933,42 @@ async def c3_shell(cmd: str = "", cwd: str = "", timeout: int = 60,
|
|
|
930
933
|
max_bytes=max_bytes or None)
|
|
931
934
|
|
|
932
935
|
|
|
936
|
+
@mcp.tool()
|
|
937
|
+
async def c3_shell_job(action: str, cmd: str = "", cwd: str = "", timeout: int = 1800,
|
|
938
|
+
env_creds: str = "", job_id: str = "", stream: str = "stdout",
|
|
939
|
+
lines: str = "", max_bytes: int = 0,
|
|
940
|
+
ctx: Context = None) -> str:
|
|
941
|
+
"""BACKGROUND shell job — start | status | tail | cancel | list. For work that outlives a
|
|
942
|
+
tool call: full test suites, long builds, device/emulator commands, anything over the
|
|
943
|
+
client's ~2 min ceiling on c3_shell. Prefer c3_ci for a repository's own workflows.
|
|
944
|
+
start: cmd (+cwd, env_creds, timeout in seconds — default 1800, ceiling 21600 = 6 h)
|
|
945
|
+
runs c3_shell's full pre-flight (blocklist, access-guard cwd deny, advisory read scan,
|
|
946
|
+
write scan with confirm holds, credential expansion) and then hands the command to a
|
|
947
|
+
DETACHED supervisor process that survives this server; replies with a job_id='j-…'
|
|
948
|
+
at once. Nothing here waits on the job, and a c3_shell timeout is never turned into one.
|
|
949
|
+
status: one line — queued|running|done|failed|timeout|cancelled|lost, exit code,
|
|
950
|
+
duration, and the output_id once finished. tail: the last `lines` (default 50) of
|
|
951
|
+
stream='stdout'|'stderr' — the GROWING output while running, the kept output after —
|
|
952
|
+
under the same byte budget as c3_shell (max_bytes may only lower it). cancel: kills the
|
|
953
|
+
child process tree ONLY if the recorded pid still has the creation time recorded at
|
|
954
|
+
spawn (a reused pid is never signalled) and records 'cancelled'. list: this project +
|
|
955
|
+
session's jobs.
|
|
956
|
+
Output lands in the same spill store as c3_shell, ALWAYS kept for 3 days: page it with
|
|
957
|
+
c3_shell(output_id='o-…', output_action='read'|'search'|'tail'). Jobs and their output
|
|
958
|
+
are per project AND per session, resolved under the current access rules; another
|
|
959
|
+
project or session sees 'not found'. Credentials are redacted in the kept output and
|
|
960
|
+
never touch the command line, the environment of the supervisor, or disk."""
|
|
961
|
+
svc = _svc(ctx)
|
|
962
|
+
|
|
963
|
+
def finalize(name, args, resp, summ, **kw):
|
|
964
|
+
return _finalize_response(ctx, name, args, resp, summ, **kw)
|
|
965
|
+
|
|
966
|
+
from cli.tools.shell_job import handle_shell_job
|
|
967
|
+
return await asyncio.to_thread(handle_shell_job, action, cmd, cwd, timeout, env_creds,
|
|
968
|
+
job_id, stream, lines or None, max_bytes or None,
|
|
969
|
+
svc, finalize)
|
|
970
|
+
|
|
971
|
+
|
|
933
972
|
@mcp.tool()
|
|
934
973
|
async def c3_bitbucket(
|
|
935
974
|
action: str,
|
|
@@ -467,6 +467,17 @@ def handle_project(action, svc, finalize, *, project="", query="", file_path="",
|
|
|
467
467
|
from_project=str(getattr(svc, "project_path", ""))),
|
|
468
468
|
action)
|
|
469
469
|
|
|
470
|
+
if action in ("shell_job", "job", "jobs"):
|
|
471
|
+
# S3: a background job is bound to the project AND session that
|
|
472
|
+
# started it (services/shell_jobs.py); proxying one would either run
|
|
473
|
+
# it under the caller's identity or hand another project's session a
|
|
474
|
+
# handle it must not have. Not offered cross-project.
|
|
475
|
+
return done(
|
|
476
|
+
"[c3_project:error] c3_shell_job is not proxied across projects — "
|
|
477
|
+
"start, poll and cancel background jobs from the target project's "
|
|
478
|
+
"own session.",
|
|
479
|
+
"error")
|
|
480
|
+
|
|
470
481
|
if action not in _READ_OPS and action not in _WRITE_OPS:
|
|
471
482
|
return done(
|
|
472
483
|
f"[c3_project:error] Unknown action '{action}'. "
|
|
@@ -1234,8 +1234,9 @@ async def handle_shell(cmd: str, cwd: str, timeout: int, filter_output: bool,
|
|
|
1234
1234
|
capped_note = (
|
|
1235
1235
|
f"[c3_shell:capped] timeout={capped_from}s was requested but this "
|
|
1236
1236
|
f"MCP client kills a tool call at {_ceiling}s; ran with {timeout}s. "
|
|
1237
|
-
f"For longer work use
|
|
1238
|
-
f"
|
|
1237
|
+
f"For longer work use c3_shell_job(action='start', cmd=..., timeout=...), "
|
|
1238
|
+
f"which runs detached (up to 6 h), keeps the ledger and telemetry, and "
|
|
1239
|
+
f"pages its output back by id.\n"
|
|
1239
1240
|
)
|
|
1240
1241
|
|
|
1241
1242
|
try:
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"""c3_shell_job — background shell jobs: start | status | tail | cancel | list (S3).
|
|
2
|
+
|
|
3
|
+
A job is a c3_shell command that outlives the MCP tool call: the run happens
|
|
4
|
+
in a detached supervisor (services/shell_jobs.py) and this handler only
|
|
5
|
+
starts, polls, tails and cancels it — nothing here ever waits on a job.
|
|
6
|
+
|
|
7
|
+
``start`` performs c3_shell's FULL pre-flight before anything is spawned:
|
|
8
|
+
the catastrophic-command blocklist, the Access Guard cwd deny, credential
|
|
9
|
+
expansion (``{{cred:NAME}}`` + ``env_creds``), the advisory read scan, and the
|
|
10
|
+
write scan with its confirm holds. Those pieces are imported from
|
|
11
|
+
cli.tools.shell so the two surfaces cannot drift; only the credential block
|
|
12
|
+
is repeated here, because it lives inline in handle_shell (S2 owns that file
|
|
13
|
+
during this phase — see the S3 brief).
|
|
14
|
+
|
|
15
|
+
A synchronous c3_shell timeout is never converted into a job: the caller
|
|
16
|
+
chooses this surface explicitly, and c3_shell's own `[c3_shell:capped]`
|
|
17
|
+
note names it as the escape hatch.
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
from cli.tools import _grants
|
|
25
|
+
from cli.tools._helpers import finalize_with_tokens
|
|
26
|
+
from cli.tools.shell import (
|
|
27
|
+
_BLOCKED,
|
|
28
|
+
_advisory_guard_scan,
|
|
29
|
+
_scan_candidates,
|
|
30
|
+
_write_scan,
|
|
31
|
+
)
|
|
32
|
+
from cli.tools.shell_render import effective_budget, human_bytes
|
|
33
|
+
from core import count_tokens
|
|
34
|
+
from services import access_guard
|
|
35
|
+
from services.shell_jobs import (
|
|
36
|
+
DEFAULT_TIMEOUT_S,
|
|
37
|
+
MAX_TIMEOUT_S,
|
|
38
|
+
JobAccessError,
|
|
39
|
+
JobState,
|
|
40
|
+
JobStore,
|
|
41
|
+
_log_tail,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
TOOL = "c3_shell_job"
|
|
45
|
+
_ACTIONS = ("start", "status", "tail", "cancel", "list")
|
|
46
|
+
_TAG = "[c3_shell_job"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _err(msg: str) -> str:
|
|
50
|
+
return f"{_TAG}:error] {msg}"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _guard_check(svc):
|
|
54
|
+
project_path = str(svc.project_path)
|
|
55
|
+
|
|
56
|
+
def check(path: str):
|
|
57
|
+
try:
|
|
58
|
+
return access_guard.check(path, "read", project_path)
|
|
59
|
+
except Exception as exc: # evaluator error fails closed
|
|
60
|
+
return access_guard.Denial("<evaluator-error>", "deny", "builtin",
|
|
61
|
+
f"evaluator error: {type(exc).__name__}")
|
|
62
|
+
return check
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _log_denied(svc, work_cwd: str, denial, surface: str) -> None:
|
|
66
|
+
if not getattr(svc, "activity_log", None):
|
|
67
|
+
return
|
|
68
|
+
try:
|
|
69
|
+
svc.activity_log.log("access_denied", {
|
|
70
|
+
"tool": TOOL, "surface": surface, "cwd": work_cwd,
|
|
71
|
+
"rule": denial.rule, "scope": denial.scope,
|
|
72
|
+
})
|
|
73
|
+
except Exception:
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _redact(text: str) -> str:
|
|
78
|
+
try:
|
|
79
|
+
from services import credential_store as _creds
|
|
80
|
+
return _creds.redact_text(text)
|
|
81
|
+
except Exception:
|
|
82
|
+
return text
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _fmt_s(seconds: float) -> str:
|
|
86
|
+
seconds = float(seconds or 0)
|
|
87
|
+
if seconds < 60:
|
|
88
|
+
return f"{seconds:.1f}s"
|
|
89
|
+
if seconds < 3600:
|
|
90
|
+
return f"{int(seconds // 60)}m{int(seconds % 60):02d}s"
|
|
91
|
+
return f"{int(seconds // 3600)}h{int((seconds % 3600) // 60):02d}m"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _stream_note(job: JobState, stream: str) -> str:
|
|
95
|
+
facts = getattr(job, stream) or {}
|
|
96
|
+
if facts:
|
|
97
|
+
return f"{stream} {human_bytes(int(facts.get('bytes', 0)))}/{int(facts.get('lines', 0))} lines"
|
|
98
|
+
path = (job.spool or {}).get(stream)
|
|
99
|
+
if path:
|
|
100
|
+
try:
|
|
101
|
+
return f"{stream} {human_bytes(Path(path).stat().st_size)} so far"
|
|
102
|
+
except OSError:
|
|
103
|
+
pass
|
|
104
|
+
return f"{stream} —"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _status_line(job: JobState) -> str:
|
|
108
|
+
"""One line the agent can act on: state, exit, duration, and where the output is."""
|
|
109
|
+
head = f"{_TAG}:status] {job.id} {job.status}"
|
|
110
|
+
if job.status == "running":
|
|
111
|
+
body = (f"{head} {_fmt_s(job.elapsed_s())} of {job.timeout_s}s · $ {job.cmd_display} · "
|
|
112
|
+
f"child pid {job.child_pid} · {_stream_note(job, 'stdout')}, {_stream_note(job, 'stderr')}\n"
|
|
113
|
+
f"poll with action='status', read with action='tail' (stream='stdout'|'stderr', lines='80'), "
|
|
114
|
+
f"stop with action='cancel'\n")
|
|
115
|
+
elif job.status == "queued":
|
|
116
|
+
body = f"{head} · $ {job.cmd_display} · supervisor pid {job.supervisor_pid} starting\n"
|
|
117
|
+
else:
|
|
118
|
+
exit_note = f"exit {job.exit_code}" if job.exit_code is not None else "no exit code"
|
|
119
|
+
if job.timed_out:
|
|
120
|
+
exit_note += f" (timed out at {job.timeout_s}s)"
|
|
121
|
+
body = f"{head} {exit_note} in {_fmt_s((job.duration_ms or 0) / 1000)} · $ {job.cmd_display}"
|
|
122
|
+
if job.output_id:
|
|
123
|
+
body += (f"\noutput_id={job.output_id} ({_stream_note(job, 'stdout')}, {_stream_note(job, 'stderr')}) — "
|
|
124
|
+
f"page with c3_shell(output_id='{job.output_id}', output_action='read'|'search'|'tail')")
|
|
125
|
+
if job.error:
|
|
126
|
+
body += f"\nnote: {job.error}"
|
|
127
|
+
body += "\n"
|
|
128
|
+
return body
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _list_line(job: JobState) -> str:
|
|
132
|
+
when = job.finished_at or job.started_at or job.created_at
|
|
133
|
+
extra = ""
|
|
134
|
+
if job.status == "running":
|
|
135
|
+
extra = f" {_fmt_s(job.elapsed_s())}/{job.timeout_s}s"
|
|
136
|
+
elif job.exit_code is not None:
|
|
137
|
+
extra = f" exit {job.exit_code}"
|
|
138
|
+
if job.output_id:
|
|
139
|
+
extra += f" output_id={job.output_id}"
|
|
140
|
+
return f"{job.id} {job.status}{extra} · {when[:19]} · $ {job.cmd_display}"
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _finalize(svc, finalize, action: str, args: dict, body: str, summary: str, job_id: str = "") -> str:
|
|
144
|
+
if not body.endswith("\n"):
|
|
145
|
+
body += "\n"
|
|
146
|
+
tokens = count_tokens(body)
|
|
147
|
+
return finalize_with_tokens(
|
|
148
|
+
finalize, svc, TOOL, {"action": action, **args}, body, summary,
|
|
149
|
+
detail={"cmd_class": "job", "action": action, "job_id": job_id,
|
|
150
|
+
"response_bytes": len(body.encode("utf-8", errors="replace")),
|
|
151
|
+
"response_tokens": tokens},
|
|
152
|
+
response_tokens=tokens,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# ── start ───────────────────────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
def _start(cmd: str, cwd: str, timeout, env_creds: str, svc, finalize) -> str:
|
|
159
|
+
if not cmd or not cmd.strip():
|
|
160
|
+
return _err("empty command")
|
|
161
|
+
# _BLOCKED never consults grants — no approval flow reaches the
|
|
162
|
+
# catastrophic tier, by spec (docs/confirm-guard.md §7).
|
|
163
|
+
if _BLOCKED.search(cmd):
|
|
164
|
+
return _err("blocked pattern — use native Bash with explicit approval if this is truly intended")
|
|
165
|
+
try:
|
|
166
|
+
timeout_s = int(timeout or DEFAULT_TIMEOUT_S)
|
|
167
|
+
except (TypeError, ValueError):
|
|
168
|
+
timeout_s = DEFAULT_TIMEOUT_S
|
|
169
|
+
capped_from = 0
|
|
170
|
+
if timeout_s > MAX_TIMEOUT_S:
|
|
171
|
+
capped_from, timeout_s = timeout_s, MAX_TIMEOUT_S
|
|
172
|
+
timeout_s = max(1, timeout_s)
|
|
173
|
+
work_cwd = str(Path(cwd or svc.project_path).resolve())
|
|
174
|
+
project_path = str(svc.project_path)
|
|
175
|
+
|
|
176
|
+
# ── Access Guard: HARD deny when the effective cwd is under a deny rule
|
|
177
|
+
# (same row as handle_shell; evaluator errors fail closed).
|
|
178
|
+
try:
|
|
179
|
+
cwd_denial = access_guard.check(work_cwd, "read", project_path)
|
|
180
|
+
except Exception as exc:
|
|
181
|
+
cwd_denial = access_guard.Denial("<evaluator-error>", "deny", "builtin",
|
|
182
|
+
f"evaluator error: {type(exc).__name__}")
|
|
183
|
+
if cwd_denial is not None and cwd_denial.kind == "deny":
|
|
184
|
+
_log_denied(svc, work_cwd, cwd_denial, "cwd")
|
|
185
|
+
return access_guard.refusal(cwd_denial, work_cwd, "read")
|
|
186
|
+
|
|
187
|
+
# ── credential expansion — `cmd` stays the RAW template form for every
|
|
188
|
+
# echo/log; `exec_cmd` and the decoded values travel to the supervisor on
|
|
189
|
+
# its stdin only (never argv, env or a file).
|
|
190
|
+
from services import credential_store as _creds
|
|
191
|
+
exec_cmd = cmd
|
|
192
|
+
extra_env: dict[str, str] = {}
|
|
193
|
+
secret_values: dict[str, str] = {}
|
|
194
|
+
cred_names: list[str] = []
|
|
195
|
+
tmpl_used: list[str] = []
|
|
196
|
+
try:
|
|
197
|
+
exec_cmd, tmpl_used, tmpl_missing = _creds.expand_templates(cmd, project_path)
|
|
198
|
+
requested = [n.strip() for n in (env_creds or "").split(",") if n.strip()]
|
|
199
|
+
auto = [n for n, e in _creds.list_entries(project_path).items()
|
|
200
|
+
if e.get("inject") and n not in requested
|
|
201
|
+
and e.get("type") not in _creds.STRUCTURED_TYPES]
|
|
202
|
+
values, missing = _creds.resolve(requested + auto, project_path)
|
|
203
|
+
hard_missing = sorted(set(tmpl_missing) | (set(missing) & set(requested)))
|
|
204
|
+
if hard_missing:
|
|
205
|
+
reasons = _creds.describe_missing(hard_missing, project_path)
|
|
206
|
+
detail = "\n".join(f" {r}: {reasons.get(r, 'unresolvable')}" for r in hard_missing)
|
|
207
|
+
return _err(f"unresolvable credential ref(s):\n{detail}\nsee c3_credentials(action='list')")
|
|
208
|
+
env_owner: dict[str, str] = {}
|
|
209
|
+
for ref, cval in values.items():
|
|
210
|
+
base_name, _, fld = ref.partition(".")
|
|
211
|
+
entry = _creds.get_entry(base_name, project_path=project_path) or {}
|
|
212
|
+
env_name = entry.get("env_var") or base_name
|
|
213
|
+
if fld:
|
|
214
|
+
env_name = f"{env_name}_{fld.upper()}"
|
|
215
|
+
if env_name in env_owner and env_owner[env_name] != ref:
|
|
216
|
+
return _err(f"env-var collision: {env_owner[env_name]} and {ref} both map to "
|
|
217
|
+
f"${env_name} — set a distinct env_var on one of the entries")
|
|
218
|
+
env_owner[env_name] = ref
|
|
219
|
+
extra_env[env_name] = cval
|
|
220
|
+
secret_values[ref] = cval
|
|
221
|
+
if tmpl_used:
|
|
222
|
+
tvals, _ = _creds.resolve(list(tmpl_used), project_path)
|
|
223
|
+
secret_values.update({k: v for k, v in tvals.items() if isinstance(v, str)})
|
|
224
|
+
cred_names = sorted(set(tmpl_used) | set(values))
|
|
225
|
+
except RuntimeError as exc: # keyring/crypto unavailable
|
|
226
|
+
return _err(f"credential store unavailable: {exc}")
|
|
227
|
+
if exec_cmd != cmd and _BLOCKED.search(exec_cmd):
|
|
228
|
+
return _err("blocked pattern after credential expansion")
|
|
229
|
+
|
|
230
|
+
# ── Access Guard ADVISORY token scan — best-effort, not enforcement;
|
|
231
|
+
# the raw and (when different) the expanded command are both scanned.
|
|
232
|
+
for scan_text in ([cmd] if exec_cmd == cmd else [cmd, exec_cmd]):
|
|
233
|
+
scan_denial, hit_tok = _advisory_guard_scan(scan_text, work_cwd, project_path)
|
|
234
|
+
if scan_denial is not None:
|
|
235
|
+
_log_denied(svc, work_cwd, scan_denial, "token_scan")
|
|
236
|
+
return _redact(access_guard.refusal(scan_denial, hit_tok, "read") + (
|
|
237
|
+
f"\n{_TAG}:note] shell path scanning is best-effort (advisory) — a denied hit "
|
|
238
|
+
"refuses the whole job, but a clean scan is not enforcement."))
|
|
239
|
+
|
|
240
|
+
# ── Access Guard WRITE-class scan with confirm holds (v2.102.0 semantics).
|
|
241
|
+
write_refusal, write_grants = _write_scan(cmd, exec_cmd, work_cwd, svc)
|
|
242
|
+
if write_refusal:
|
|
243
|
+
return _redact(write_refusal.replace("[c3_shell:note]", f"{_TAG}:note]"))
|
|
244
|
+
|
|
245
|
+
payload = {"cmd": cmd, "exec_cmd": exec_cmd, "env": extra_env, "secrets": secret_values,
|
|
246
|
+
"cred_names": cred_names, "tmpl_used": list(tmpl_used)}
|
|
247
|
+
session_id = _grants.session_id(svc)
|
|
248
|
+
store = JobStore()
|
|
249
|
+
try:
|
|
250
|
+
job = store.start(project_path=project_path, session_id=session_id, cmd=cmd, cwd=work_cwd,
|
|
251
|
+
timeout_s=timeout_s, payload=payload,
|
|
252
|
+
guard_paths=_scan_candidates(cmd, work_cwd), cred_names=cred_names)
|
|
253
|
+
except Exception as exc:
|
|
254
|
+
return _err(f"could not start the supervisor: {type(exc).__name__}: {exc}")
|
|
255
|
+
if cred_names:
|
|
256
|
+
try:
|
|
257
|
+
_creds.touch_last_used(sorted({r.partition(".")[0] for r in cred_names}), project_path)
|
|
258
|
+
except Exception:
|
|
259
|
+
pass
|
|
260
|
+
if getattr(svc, "activity_log", None):
|
|
261
|
+
try:
|
|
262
|
+
svc.activity_log.log("shell_job", {
|
|
263
|
+
"action": "start", "job_id": job.id, "cmd": cmd[:200], "cwd": work_cwd,
|
|
264
|
+
"timeout_s": timeout_s, "creds": cred_names, "status": job.status,
|
|
265
|
+
})
|
|
266
|
+
except Exception:
|
|
267
|
+
pass
|
|
268
|
+
|
|
269
|
+
if job.status in ("failed", "lost"):
|
|
270
|
+
log_tail = _log_tail(job.log_path)
|
|
271
|
+
body = (f"{_TAG}:error] {job.id} {job.status} before running: {job.error or 'no detail'}"
|
|
272
|
+
+ (f"\n--- supervisor log ---\n{log_tail}" if log_tail else "") + "\n")
|
|
273
|
+
return _finalize(svc, finalize, "start", {"cmd": cmd[:120], "cwd": work_cwd}, body,
|
|
274
|
+
f"shell job {job.id} {job.status}", job.id)
|
|
275
|
+
lines = [f"{_TAG}:started] {job.id} $ {job.cmd_display} (timeout {timeout_s}s) — "
|
|
276
|
+
f"poll with action='status', read with action='tail'"]
|
|
277
|
+
pids = f"supervisor pid {job.supervisor_pid}"
|
|
278
|
+
if job.child_pid:
|
|
279
|
+
pids += f", child pid {job.child_pid}"
|
|
280
|
+
lines.append(f"{job.status} · {pids} · cwd {work_cwd}" + (f" · creds {', '.join(cred_names)}" if cred_names else ""))
|
|
281
|
+
if capped_from:
|
|
282
|
+
lines.append(f"{_TAG}:capped] timeout={capped_from}s was requested; jobs run at most "
|
|
283
|
+
f"{MAX_TIMEOUT_S}s (6 h)")
|
|
284
|
+
lines.extend(write_grants)
|
|
285
|
+
body = "\n".join(lines) + "\n"
|
|
286
|
+
return _finalize(svc, finalize, "start", {"cmd": cmd[:120], "cwd": work_cwd}, body,
|
|
287
|
+
f"shell job started {job.id}", job.id)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# ── entry point ─────────────────────────────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
def handle_shell_job(action: str, cmd: str = "", cwd: str = "", timeout=DEFAULT_TIMEOUT_S,
|
|
293
|
+
env_creds: str = "", job_id: str = "", stream: str = "stdout",
|
|
294
|
+
lines=None, max_bytes=None, svc=None, finalize=None) -> str:
|
|
295
|
+
action = (action or "").strip().lower()
|
|
296
|
+
if action not in _ACTIONS:
|
|
297
|
+
return _err(f"action must be one of {', '.join(_ACTIONS)}; got {action!r}")
|
|
298
|
+
if finalize is None:
|
|
299
|
+
def finalize(name, args, resp, summ, **kw): # noqa: E306 — plain passthrough
|
|
300
|
+
return resp
|
|
301
|
+
if action == "start":
|
|
302
|
+
return _start(cmd, cwd, timeout, env_creds, svc, finalize)
|
|
303
|
+
|
|
304
|
+
project_path = str(svc.project_path)
|
|
305
|
+
session_id = _grants.session_id(svc)
|
|
306
|
+
store = JobStore()
|
|
307
|
+
if action == "list":
|
|
308
|
+
jobs = store.list(project_path=project_path, session_id=session_id)
|
|
309
|
+
if not jobs:
|
|
310
|
+
body = f"{_TAG}:list] no jobs for this project and session\n"
|
|
311
|
+
else:
|
|
312
|
+
body = f"{_TAG}:list] {len(jobs)} job(s) for this project and session\n" + "\n".join(
|
|
313
|
+
_list_line(j) for j in jobs) + "\n"
|
|
314
|
+
return _finalize(svc, finalize, "list", {}, body, f"shell jobs list ({len(jobs)})")
|
|
315
|
+
|
|
316
|
+
if not job_id:
|
|
317
|
+
return _err(f"action='{action}' needs job_id='j-…'")
|
|
318
|
+
guard_check = _guard_check(svc)
|
|
319
|
+
try:
|
|
320
|
+
job = store.resolve(job_id, project_path=project_path, session_id=session_id, guard_check=guard_check)
|
|
321
|
+
except JobAccessError as exc:
|
|
322
|
+
return _err(str(exc))
|
|
323
|
+
|
|
324
|
+
if action == "status":
|
|
325
|
+
return _finalize(svc, finalize, "status", {"job_id": job.id}, _status_line(job),
|
|
326
|
+
f"shell job {job.id} {job.status}", job.id)
|
|
327
|
+
|
|
328
|
+
if action == "cancel":
|
|
329
|
+
job, note = store.cancel(job)
|
|
330
|
+
body = f"{_TAG}:cancel] {job.id} {note}\n" + _status_line(job)
|
|
331
|
+
return _finalize(svc, finalize, "cancel", {"job_id": job.id}, body,
|
|
332
|
+
f"shell job {job.id} cancel → {job.status}", job.id)
|
|
333
|
+
|
|
334
|
+
# tail
|
|
335
|
+
stream = (stream or "stdout").strip().lower()
|
|
336
|
+
if stream not in ("stdout", "stderr"):
|
|
337
|
+
return _err("stream must be 'stdout' or 'stderr'")
|
|
338
|
+
n = 50
|
|
339
|
+
if isinstance(lines, int) and not isinstance(lines, bool) and lines > 0:
|
|
340
|
+
n = lines
|
|
341
|
+
elif isinstance(lines, str) and lines.strip():
|
|
342
|
+
digits = re.sub(r"[^0-9]", "", lines)
|
|
343
|
+
if digits:
|
|
344
|
+
n = max(int(digits), 1)
|
|
345
|
+
config_default = None
|
|
346
|
+
try:
|
|
347
|
+
config_default = (getattr(svc, "hybrid_config", None) or {}).get("shell_budget_bytes")
|
|
348
|
+
except Exception:
|
|
349
|
+
pass
|
|
350
|
+
budget = effective_budget(max_bytes, config_default=config_default) - 512
|
|
351
|
+
try:
|
|
352
|
+
text = store.tail(job, stream, lines=n, max_bytes=budget, guard_check=guard_check)
|
|
353
|
+
except Exception as exc:
|
|
354
|
+
return _err(f"{job.id}: {exc}")
|
|
355
|
+
header = f"{_TAG}:tail] {job.id} {job.status} · $ {job.cmd_display}"
|
|
356
|
+
if job.terminal and job.output_id:
|
|
357
|
+
header += f" · output_id={job.output_id}"
|
|
358
|
+
body = header + "\n" + text + "\n"
|
|
359
|
+
return _finalize(svc, finalize, "tail", {"job_id": job.id, "stream": stream, "lines": n}, body,
|
|
360
|
+
f"shell job {job.id} tail {stream}", job.id)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
__all__ = ["handle_shell_job", "TOOL"]
|
{code_context_control-2.113.0 → code_context_control-2.114.0}/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.114.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
|
|
@@ -98,6 +98,7 @@ cli/tools/read.py
|
|
|
98
98
|
cli/tools/search.py
|
|
99
99
|
cli/tools/session.py
|
|
100
100
|
cli/tools/shell.py
|
|
101
|
+
cli/tools/shell_job.py
|
|
101
102
|
cli/tools/shell_parsers.py
|
|
102
103
|
cli/tools/shell_render.py
|
|
103
104
|
cli/tools/status.py
|
|
@@ -266,6 +267,7 @@ services/scanner.py
|
|
|
266
267
|
services/session_benchmark.py
|
|
267
268
|
services/session_manager.py
|
|
268
269
|
services/session_preloader.py
|
|
270
|
+
services/shell_jobs.py
|
|
269
271
|
services/shell_output.py
|
|
270
272
|
services/subprojects.py
|
|
271
273
|
services/task_store.py
|
|
@@ -443,6 +445,7 @@ tests/test_session_budget.py
|
|
|
443
445
|
tests/test_shell_budget_s1.py
|
|
444
446
|
tests/test_shell_creds.py
|
|
445
447
|
tests/test_shell_eval.py
|
|
448
|
+
tests/test_shell_jobs_s3.py
|
|
446
449
|
tests/test_shell_output.py
|
|
447
450
|
tests/test_shell_parsers_s2.py
|
|
448
451
|
tests/test_shell_robustness.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.114.0"
|
|
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"
|