code-context-control 2.82.0__tar.gz → 2.86.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.82.0/code_context_control.egg-info → code_context_control-2.86.0}/PKG-INFO +3 -2
- {code_context_control-2.82.0 → code_context_control-2.86.0}/README.md +2 -1
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/c3.py +33 -2
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/commands/parser.py +27 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_access_guard.py +25 -3
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_server.py +14 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/mcp_server.py +23 -4
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/server.py +14 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/ci.py +126 -3
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/shell.py +56 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/tasks.py +22 -1
- {code_context_control-2.82.0 → code_context_control-2.86.0/code_context_control.egg-info}/PKG-INFO +3 -2
- {code_context_control-2.82.0 → code_context_control-2.86.0}/code_context_control.egg-info/SOURCES.txt +7 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/mobile_api.py +14 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/pyproject.toml +1 -1
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/access_guard.py +27 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/ci_act.py +36 -0
- code_context_control-2.86.0/services/ci_cache.py +345 -0
- code_context_control-2.86.0/services/ci_github.py +161 -0
- code_context_control-2.86.0/services/ci_impact.py +269 -0
- code_context_control-2.86.0/services/ci_intel.py +188 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/ci_runner.py +138 -5
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/ci_workflow.py +1 -1
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/scanner.py +35 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/task_store.py +63 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_access_guard.py +72 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_c3_shell.py +101 -0
- code_context_control-2.86.0/tests/test_ci_cache.py +205 -0
- code_context_control-2.86.0/tests/test_ci_impact.py +274 -0
- code_context_control-2.86.0/tests/test_ci_intel.py +179 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hook_access_guard.py +30 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_init_scan.py +76 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_pm_api.py +25 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_task_store.py +45 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_task_tool.py +13 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/LICENSE +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/_hook_utils.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/commands/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/commands/common.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/docs.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/edits.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/access.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/credentials.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/index.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/masking.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/oracle.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/shared.css +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/tools.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/guide/workflow.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_artifact.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_c3read.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_filter.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_read.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/hub_ui.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/progress.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/_grants.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/agent.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/compress.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/credentials.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/delegate.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/edit.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/edits.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/federate.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/filter.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/impact.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/jira.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/locks.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/memory.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/override.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/project.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/read.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/search.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/session.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/status.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/tools/validate.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/api.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/app.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/access.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/icons.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/shared.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui/theme.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui_legacy.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/cli/ui_nano.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/core/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/core/config.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/core/ide.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/core/mcp_toml.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/core/web_security.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/config.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/oracle_server.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/local_session.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/activity.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/agents.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/app.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/busy.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/core.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/header.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/insights.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/projects.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/settings.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/access_telemetry.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/activity_log.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/agent_base.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/agent_locks.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/agents.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/artifact_defs.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/artifact_store.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/auto_memory.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/bench/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/bitbucket_client.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/ci_expr.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/ci_failures.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/circuit_breaker.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/claude_md.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/compressor.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/context_snapshot.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/conversation_store.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/credential_store.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/doc_index.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/e2e_tasks.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/edit_ledger.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/embedding_index.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/enforcement_policy.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/error_reporting.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/file_memory.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/git_context.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/hub_service.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/indexer.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/jira_client.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/jira_cloud.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/jira_credentials.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/jira_data_center.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/jira_links.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/mask_activation.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/mask_mirror.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/mask_presets.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/memory.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/memory_consolidator.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/memory_distiller.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/memory_graph.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/memory_grounder.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/memory_queue.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/memory_scorer.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/metrics.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/notifications.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/ollama_bridge.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/ollama_client.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/ollama_credentials.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/output_filter.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/override_grants.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/override_policy.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/override_requests.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/override_wake.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/parser.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/project_manager.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/project_runtime.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/protocol.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/proxy_state.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/repo_map.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/retention.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/retrieval_broker.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/router.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/runtime.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/session_benchmark.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/session_manager.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/session_preloader.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/subprojects.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/telemetry.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/text_index.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/time_tracker.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/tool_classifier.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/transcript_index.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/validation_cache.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/vector_store.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/watcher.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/services/win_subprocess.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/setup.cfg +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_ci_act.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_credential_store.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hook_state.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_jira_client.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_jira_links.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_memory_system.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_output_filter.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_override_grants.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_override_requests.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_override_wake.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_permissions.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_project_manager.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_project_tool.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_related_facts.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_repo_map.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_retention.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_review_digest.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_service_durability.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_session_budget.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_subprojects.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_validate.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_version_sync.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_web_security.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/backend.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/main.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/__init__.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/index_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/init_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/search_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/session_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/stats.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.82.0 → code_context_control-2.86.0}/tui/theme.tcss +0 -0
{code_context_control-2.82.0/code_context_control.egg-info → code_context_control-2.86.0}/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.86.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
|
|
@@ -178,7 +178,7 @@ Twelve tabs. The dashboard above shows token savings, indexed files, the live se
|
|
|
178
178
|
<img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/2026-07/ui_tasks.png" alt="C3 Tasks" width="900">
|
|
179
179
|
</p>
|
|
180
180
|
|
|
181
|
-
**Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board.
|
|
181
|
+
**Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board. Shipped milestones can be **completed** (v2.86.0) — they leave the board while their tasks keep the milestone link, unlike archiving, which detaches them.
|
|
182
182
|
|
|
183
183
|
**Instructions** keeps your agent-facing docs in sync. C3-generated content sits inside a `<!-- C3:BEGIN … -->` block; anything you write outside it is preserved. Since v2.60.0 generated docs point at `.c3/MAP.md` — a machine-owned, byte-stable repo map C3 refreshes automatically — instead of embedding a tree that goes stale. `AGENTS.md` serves both Codex and Antigravity; `GEMINI.md` is read if present but no longer generated (the Gemini CLI profile was removed in v2.52).
|
|
184
184
|
|
|
@@ -243,6 +243,7 @@ c3 access mask activate # purge pre-mask artifacts, buil
|
|
|
243
243
|
- **`deny` means deny-enumerate too** — denied paths never appear in search results, maps, or the vector index.
|
|
244
244
|
- **Masked means read-only, always.** Cropped rows have no inverse, so an edit in transformed coordinates would corrupt the one file you protected.
|
|
245
245
|
- **Four deterministic presets, no LLM in the read path:** `redact_secrets`, `redact_columns` (salted one-way pseudonyms — joins survive, no reverse dictionary), `sample_rows`, `signatures_only`.
|
|
246
|
+
- **Sensible defaults out of the box** (v2.86.0). A fresh install seeds `*.pem`, `id_rsa*`, and `*.key` as deny rules in global scope — visible in `c3 access list` and removable like any rule you wrote yourself. Delete one and it stays deleted.
|
|
246
247
|
- **Rule changes are human-only** (UI tab or CLI) and ledger-logged. Agents have no mutation surface.
|
|
247
248
|
- **Built-ins can be switched off when you need to** (v2.65.0). `**/.env*`, `**/.c3/**`, `**/.claude/settings*.json` and `**/.git/**` yield to `c3 access builtin disable <glob>`, which makes you retype the glob first. It takes **two keys** — a config entry *and* a keyring attestation — so an agent that manages to write `config.json` still cannot grant itself write access to your settings. The credential vault stays absolute.
|
|
248
249
|
- **Honest coverage.** This guards *cooperative* agents against mistakes and prompt injection. It is not a sandbox — a raw shell outside C3's tools still sees the real bytes.
|
|
@@ -115,7 +115,7 @@ Twelve tabs. The dashboard above shows token savings, indexed files, the live se
|
|
|
115
115
|
<img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/2026-07/ui_tasks.png" alt="C3 Tasks" width="900">
|
|
116
116
|
</p>
|
|
117
117
|
|
|
118
|
-
**Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board.
|
|
118
|
+
**Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board. Shipped milestones can be **completed** (v2.86.0) — they leave the board while their tasks keep the milestone link, unlike archiving, which detaches them.
|
|
119
119
|
|
|
120
120
|
**Instructions** keeps your agent-facing docs in sync. C3-generated content sits inside a `<!-- C3:BEGIN … -->` block; anything you write outside it is preserved. Since v2.60.0 generated docs point at `.c3/MAP.md` — a machine-owned, byte-stable repo map C3 refreshes automatically — instead of embedding a tree that goes stale. `AGENTS.md` serves both Codex and Antigravity; `GEMINI.md` is read if present but no longer generated (the Gemini CLI profile was removed in v2.52).
|
|
121
121
|
|
|
@@ -180,6 +180,7 @@ c3 access mask activate # purge pre-mask artifacts, buil
|
|
|
180
180
|
- **`deny` means deny-enumerate too** — denied paths never appear in search results, maps, or the vector index.
|
|
181
181
|
- **Masked means read-only, always.** Cropped rows have no inverse, so an edit in transformed coordinates would corrupt the one file you protected.
|
|
182
182
|
- **Four deterministic presets, no LLM in the read path:** `redact_secrets`, `redact_columns` (salted one-way pseudonyms — joins survive, no reverse dictionary), `sample_rows`, `signatures_only`.
|
|
183
|
+
- **Sensible defaults out of the box** (v2.86.0). A fresh install seeds `*.pem`, `id_rsa*`, and `*.key` as deny rules in global scope — visible in `c3 access list` and removable like any rule you wrote yourself. Delete one and it stays deleted.
|
|
183
184
|
- **Rule changes are human-only** (UI tab or CLI) and ledger-logged. Agents have no mutation surface.
|
|
184
185
|
- **Built-ins can be switched off when you need to** (v2.65.0). `**/.env*`, `**/.c3/**`, `**/.claude/settings*.json` and `**/.git/**` yield to `c3 access builtin disable <glob>`, which makes you retype the glob first. It takes **two keys** — a config entry *and* a keyring attestation — so an agent that manages to write `config.json` still cannot grant itself write access to your settings. The credential vault stays absolute.
|
|
185
186
|
- **Honest coverage.** This guards *cooperative* agents against mistakes and prompt injection. It is not a sandbox — a raw shell outside C3's tools still sees the real bytes.
|
|
@@ -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.86.0"
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -5535,6 +5535,14 @@ def cmd_install_mcp(args):
|
|
|
5535
5535
|
except Exception as e:
|
|
5536
5536
|
print(f"Warning: Could not update global CLAUDE.md: {e}")
|
|
5537
5537
|
|
|
5538
|
+
# ── Default Access Guard rules (first run only) ─────────────
|
|
5539
|
+
from services import access_guard
|
|
5540
|
+
seeded = access_guard.seed_default_global_rules()
|
|
5541
|
+
if seeded.get("seeded"):
|
|
5542
|
+
rules = ", ".join(seeded["rules"])
|
|
5543
|
+
print(f"Seeded default Access Guard deny rules into global scope: {rules}")
|
|
5544
|
+
print(" (remove with: c3 access remove <glob> --kind deny --global)")
|
|
5545
|
+
|
|
5538
5546
|
# ── Install /terse skill for supported IDEs ──────────────────
|
|
5539
5547
|
if profile.name in ("claude-code", "codex"):
|
|
5540
5548
|
try:
|
|
@@ -6055,6 +6063,15 @@ def _ci_main(args) -> int:
|
|
|
6055
6063
|
from cli.tools.ci import handle_ci
|
|
6056
6064
|
|
|
6057
6065
|
sub = getattr(args, "ci_cmd", None) or "inspect"
|
|
6066
|
+
if sub == "publish":
|
|
6067
|
+
if getattr(args, "dry_run", False):
|
|
6068
|
+
args.job = "dry-run"
|
|
6069
|
+
if getattr(args, "force", False):
|
|
6070
|
+
args.allow_side_effects = True
|
|
6071
|
+
if sub == "cache" and getattr(args, "clear", False):
|
|
6072
|
+
# `--clear` is a flag on the CLI; the shared handler takes it
|
|
6073
|
+
# positionally so both surfaces route through one code path.
|
|
6074
|
+
args.job = "clear"
|
|
6058
6075
|
project_path = getattr(args, "project_path", ".") or "."
|
|
6059
6076
|
as_json = bool(getattr(args, "json", False))
|
|
6060
6077
|
|
|
@@ -6106,7 +6123,11 @@ def _ci_main(args) -> int:
|
|
|
6106
6123
|
getattr(args, "event", "") or "",
|
|
6107
6124
|
getattr(args, "engine", "auto") or "auto",
|
|
6108
6125
|
bool(getattr(args, "allow_side_effects", False)),
|
|
6109
|
-
getattr(args, "network", "") or ""
|
|
6126
|
+
getattr(args, "network", "") or "",
|
|
6127
|
+
"required" if getattr(args, "required", False) else "full",
|
|
6128
|
+
getattr(args, "base", "") or "",
|
|
6129
|
+
bool(getattr(args, "allow_host_mutation", False)),
|
|
6130
|
+
bool(getattr(args, "no_cache", False)))
|
|
6110
6131
|
print(out)
|
|
6111
6132
|
# Exit code is the finding: a non-full verdict must not read as success to
|
|
6112
6133
|
# a shell script or a pre-push hook.
|
|
@@ -6590,6 +6611,16 @@ def _override_audit(grant: dict, project_path: str) -> None:
|
|
|
6590
6611
|
|
|
6591
6612
|
def cmd_access(args):
|
|
6592
6613
|
"""Access Guard rule management — human-only mutation surface (spec §1)."""
|
|
6614
|
+
from services import access_guard
|
|
6615
|
+
|
|
6616
|
+
# First `c3 access` touch seeds the removable defaults (spec §1). A
|
|
6617
|
+
# no-op forever after: any existing access section, even an emptied
|
|
6618
|
+
# one, means the user has taken over the scope.
|
|
6619
|
+
seeded = access_guard.seed_default_global_rules()
|
|
6620
|
+
if seeded.get("seeded"):
|
|
6621
|
+
print(f"[seeded] default global deny rules: {', '.join(seeded['rules'])}")
|
|
6622
|
+
print(" Remove any of them: c3 access remove <glob> --kind deny --global\n")
|
|
6623
|
+
|
|
6593
6624
|
sub = getattr(args, "access_cmd", None)
|
|
6594
6625
|
if not sub:
|
|
6595
6626
|
print("Usage: c3 access {list,add,remove,check,stats,mask,builtin} [args]")
|
|
@@ -507,6 +507,17 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
507
507
|
ci_run.add_argument("--allow-side-effects", action="store_true",
|
|
508
508
|
help="Let the act engine run jobs that look like they "
|
|
509
509
|
"publish or deploy. Refused by default.")
|
|
510
|
+
ci_run.add_argument("--required", action="store_true",
|
|
511
|
+
help="Run only the jobs a change could have broken "
|
|
512
|
+
"(conservative; see `c3 ci plan`)")
|
|
513
|
+
ci_run.add_argument("--base", default="",
|
|
514
|
+
help="Diff against this ref instead of the working tree")
|
|
515
|
+
ci_run.add_argument("--allow-host-mutation", action="store_true",
|
|
516
|
+
help="Permit native steps that reconfigure this machine "
|
|
517
|
+
"(pip/npm -g/apt install). Refused by default.")
|
|
518
|
+
ci_run.add_argument("--no-cache", action="store_true",
|
|
519
|
+
help="Ignore cached results and execute every "
|
|
520
|
+
"selected job")
|
|
510
521
|
ci_run.add_argument("--network", default="",
|
|
511
522
|
help="Container network for the act engine (e.g. `none` "
|
|
512
523
|
"to cut egress). Default: act's own.")
|
|
@@ -530,6 +541,22 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
530
541
|
ci_logs.add_argument("--tail", type=int, default=200)
|
|
531
542
|
|
|
532
543
|
_ci_common(ci_subs.add_parser("runs", help="Recent local CI runs"))
|
|
544
|
+
ci_plan = _ci_common(ci_subs.add_parser(
|
|
545
|
+
"plan", help="Show which jobs a change requires, and why"))
|
|
546
|
+
ci_plan.add_argument("--base", default="",
|
|
547
|
+
help="Diff against this ref instead of the working tree")
|
|
548
|
+
ci_pub = _ci_common(ci_subs.add_parser(
|
|
549
|
+
"publish", help="Post the last run as a GitHub commit status"))
|
|
550
|
+
ci_pub.add_argument("--run", dest="run_id", default="")
|
|
551
|
+
ci_pub.add_argument("--dry-run", action="store_true")
|
|
552
|
+
ci_pub.add_argument("--force", action="store_true",
|
|
553
|
+
help="Publish a PARTIAL result as `pending`")
|
|
554
|
+
_ci_common(ci_subs.add_parser(
|
|
555
|
+
"history", help="Per-job pass/fail history and flake detection"))
|
|
556
|
+
ci_cache_p = _ci_common(ci_subs.add_parser(
|
|
557
|
+
"cache", help="Cached-result store: size, or --clear it"))
|
|
558
|
+
ci_cache_p.add_argument("--clear", action="store_true",
|
|
559
|
+
help="Drop every cached result and dependency cache")
|
|
533
560
|
_ci_common(ci_subs.add_parser(
|
|
534
561
|
"doctor", help="Which execution engines are available on this machine"))
|
|
535
562
|
|
|
@@ -41,7 +41,24 @@ _MAX_TOKENS = 200
|
|
|
41
41
|
# "NTFS alternate data stream". The ADS check stays strict for real path
|
|
42
42
|
# arguments (_WRITE_TOOLS/_READ_TOOLS); here it only produced false denies on
|
|
43
43
|
# commit messages, curl, and gh (#50).
|
|
44
|
-
|
|
44
|
+
#
|
|
45
|
+
# UNANCHORED, and that is the fix rather than an oversight. `^…://` only ever
|
|
46
|
+
# recognised a token that BEGINS with a scheme, which is the same
|
|
47
|
+
# whitelist-a-shape mistake #50 made and this module's own header calls out —
|
|
48
|
+
# and the `_SYNTAX_CHARS` generalisation does not cover the gap, because a
|
|
49
|
+
# token can carry a URL and no syntax at all. Observed 2026-08-11: the single
|
|
50
|
+
# argument of
|
|
51
|
+
# printf '\n---\n\nhttps://claude.ai/code/session_01Hs28…\n' >> body.md
|
|
52
|
+
# strips to `\n---\n\nhttps://claude.ai/…`, which has a separator (`\` and
|
|
53
|
+
# `/`), no syntax characters, no `::`, and no leading scheme. It reached
|
|
54
|
+
# ag.check, canonicalised to a residual colon, and hard-denied a command whose
|
|
55
|
+
# only file argument was an ordinary markdown path. Third logged instance of
|
|
56
|
+
# this class in five days (two on 2026-08-07 were Windows paths inside Python
|
|
57
|
+
# string literals).
|
|
58
|
+
#
|
|
59
|
+
# A token containing `://` anywhere is a network literal, not an NTFS stream:
|
|
60
|
+
# a real stream is `file:name:$TYPE`, and no spelling of it contains `//`.
|
|
61
|
+
_SCHEME_RE = re.compile(r"[a-z][a-z0-9+.\-]*://", re.IGNORECASE)
|
|
45
62
|
# IPv6 literal or CIDR: >=2 colons, hex groups only, optional [] and /prefix.
|
|
46
63
|
# 'C:/x/f.txt:stream' has one colon and non-hex parts, so it never matches.
|
|
47
64
|
_IPV6_RE = re.compile(
|
|
@@ -104,8 +121,13 @@ _CD_RE = re.compile(
|
|
|
104
121
|
|
|
105
122
|
|
|
106
123
|
def _is_network_token(tok: str) -> bool:
|
|
107
|
-
"""True for URLs and IPv6 literals/CIDRs — never for an ADS spelling.
|
|
108
|
-
|
|
124
|
+
"""True for URLs and IPv6 literals/CIDRs — never for an ADS spelling.
|
|
125
|
+
|
|
126
|
+
``search`` for the scheme (a URL anywhere in the token disqualifies it as
|
|
127
|
+
a path), ``match`` for IPv6 — that pattern is a whole-token shape and
|
|
128
|
+
anchoring is what keeps `C:/x/f.txt:stream` from matching it.
|
|
129
|
+
"""
|
|
130
|
+
return bool(_SCHEME_RE.search(tok) or _IPV6_RE.match(tok))
|
|
109
131
|
|
|
110
132
|
|
|
111
133
|
def _is_scope_token(tok: str) -> bool:
|
|
@@ -2740,6 +2740,20 @@ def api_pm_milestone():
|
|
|
2740
2740
|
return jsonify({"error": "id is required"}), 400
|
|
2741
2741
|
|
|
2742
2742
|
if request.method == "PUT":
|
|
2743
|
+
# {complete: true} / {reopen: true} switch lifecycle; tasks keep
|
|
2744
|
+
# their milestone link (unlike DELETE = archive + detach).
|
|
2745
|
+
if data.get("complete"):
|
|
2746
|
+
res = store.complete_milestone(ms_id)
|
|
2747
|
+
if "error" in res:
|
|
2748
|
+
return jsonify(res), 400
|
|
2749
|
+
_pm_audit(resolved, "milestone", "complete", res["id"])
|
|
2750
|
+
return jsonify({"completed": True, "milestone": res})
|
|
2751
|
+
if data.get("reopen"):
|
|
2752
|
+
res = store.reopen_milestone(ms_id)
|
|
2753
|
+
if "error" in res:
|
|
2754
|
+
return jsonify(res), 400
|
|
2755
|
+
_pm_audit(resolved, "milestone", "reopen", res["id"])
|
|
2756
|
+
return jsonify({"reopened": True, "milestone": res})
|
|
2743
2757
|
res = store.update_milestone(ms_id, expected_rev=data.get("expected_rev"),
|
|
2744
2758
|
**(data.get("fields") or {}))
|
|
2745
2759
|
if "error" in res:
|
|
@@ -771,10 +771,25 @@ async def c3_ci(action: str = "inspect", job: str = "", run_id: str = "",
|
|
|
771
771
|
allow_foreign: bool = False, workflow: str = "",
|
|
772
772
|
tail: int = 200, timeout: int = 0, event: str = "",
|
|
773
773
|
engine: str = "auto", allow_side_effects: bool = False,
|
|
774
|
-
network: str = "",
|
|
774
|
+
network: str = "", mode: str = "full", base: str = "",
|
|
775
|
+
allow_host_mutation: bool = False,
|
|
776
|
+
no_cache: bool = False, ctx: Context = None) -> str:
|
|
775
777
|
"""RUN THIS REPO'S REAL CI LOCALLY — before pushing, not after.
|
|
776
778
|
Reads .github/workflows/*.yml as the source of truth (no second CI config).
|
|
777
|
-
actions: inspect | run | rerun | status | failures | logs | runs |
|
|
779
|
+
actions: inspect | plan | run | rerun | status | failures | logs | runs |
|
|
780
|
+
cache | history | publish | doctor. publish posts the last run as a
|
|
781
|
+
GitHub COMMIT STATUS via your gh auth; it refuses a dirty tree, an
|
|
782
|
+
unpushed commit, and (unless forced) a PARTIAL result. history reports per-job fail rates and
|
|
783
|
+
flags FLAKY jobs — ones that both passed and failed on identical
|
|
784
|
+
inputs, so the code cannot be the cause. A job whose inputs are unchanged since it last passed
|
|
785
|
+
is reused (status `cached`, nothing executed); no_cache forces it.
|
|
786
|
+
mode: full (default) | required. required runs only the jobs a change
|
|
787
|
+
could have broken; it is CONSERVATIVE — anything unmapped runs. Use
|
|
788
|
+
action='plan' to see the decision and reason for every job first.
|
|
789
|
+
allow_host_mutation: the NATIVE engine refuses steps that would
|
|
790
|
+
reconfigure this machine (pip/npm -g/apt/brew install...). It has no
|
|
791
|
+
isolation; running this repo's own CI natively once uninstalled C3.
|
|
792
|
+
Prefer engine='act'.
|
|
778
793
|
inspect: workflows, the job DAG, and which jobs are runnable on THIS host.
|
|
779
794
|
run: execute in dependency order; job='lint' or 'test (ubuntu-latest, 3.12)'
|
|
780
795
|
selects one (bare job name = all its matrix cells). A job whose dependency
|
|
@@ -798,7 +813,9 @@ async def c3_ci(action: str = "inspect", job: str = "", run_id: str = "",
|
|
|
798
813
|
return await asyncio.to_thread(handle_ci, action, job, run_id,
|
|
799
814
|
allow_foreign, workflow, tail, timeout,
|
|
800
815
|
svc, finalize, event, engine,
|
|
801
|
-
allow_side_effects, network
|
|
816
|
+
allow_side_effects, network,
|
|
817
|
+
mode, base, allow_host_mutation,
|
|
818
|
+
no_cache)
|
|
802
819
|
|
|
803
820
|
|
|
804
821
|
@mcp.tool()
|
|
@@ -1088,7 +1105,9 @@ async def c3_task(
|
|
|
1088
1105
|
Time: time_add (minutes 1-1440 [+note/due_date=date/task_id]), time_update / time_delete (ref=entry id),
|
|
1089
1106
|
time_list (manual entries + recent auto sessions), time_summary (today/7d/30d, auto vs manual).
|
|
1090
1107
|
Auto-tracking: server startup + tool calls ping .c3/time; idle gaps >15min close a session.
|
|
1091
|
-
Milestones: milestone_add (name [+target_date]), milestone_update, milestone_list (with progress %),
|
|
1108
|
+
Milestones: milestone_add (name [+target_date]), milestone_update, milestone_list (with progress %),
|
|
1109
|
+
milestone_complete (close a shipped milestone; refuses while open tasks remain; tasks KEEP their link),
|
|
1110
|
+
milestone_reopen (undo complete), milestone_archive (removal: detaches tasks).
|
|
1092
1111
|
Notes: note_add (note [+kind=decision] [+task_id]), note_list.
|
|
1093
1112
|
History: history ([+task_id] [+limit]) — append-only event log (who/what/when, before->after), newest first.
|
|
1094
1113
|
task_id accepts any unique id prefix (>=4 chars); milestone accepts id or unique name.
|
|
@@ -1295,6 +1295,20 @@ def api_pm_milestone():
|
|
|
1295
1295
|
if not ms_id:
|
|
1296
1296
|
return jsonify({"error": "id is required"}), 400
|
|
1297
1297
|
if request.method == "PUT":
|
|
1298
|
+
# {complete: true} / {reopen: true} switch lifecycle; tasks keep
|
|
1299
|
+
# their milestone link (unlike DELETE = archive + detach).
|
|
1300
|
+
if data.get("complete"):
|
|
1301
|
+
res = store.complete_milestone(ms_id)
|
|
1302
|
+
if "error" in res:
|
|
1303
|
+
return jsonify(res), 400
|
|
1304
|
+
_pm_audit("milestone", "complete", res["id"])
|
|
1305
|
+
return jsonify({"completed": True, "milestone": res})
|
|
1306
|
+
if data.get("reopen"):
|
|
1307
|
+
res = store.reopen_milestone(ms_id)
|
|
1308
|
+
if "error" in res:
|
|
1309
|
+
return jsonify(res), 400
|
|
1310
|
+
_pm_audit("milestone", "reopen", res["id"])
|
|
1311
|
+
return jsonify({"reopened": True, "milestone": res})
|
|
1298
1312
|
res = store.update_milestone(ms_id, expected_rev=data.get("expected_rev"),
|
|
1299
1313
|
**(data.get("fields") or {}))
|
|
1300
1314
|
if "error" in res:
|
|
@@ -12,13 +12,14 @@ That distinction is the product.
|
|
|
12
12
|
"""
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
+
from services import ci_impact
|
|
15
16
|
from services import ci_runner as cr
|
|
16
17
|
from services.ci_workflow import inspect_project
|
|
17
18
|
|
|
18
19
|
_MARK = {
|
|
19
20
|
cr.PASSED: "PASS", cr.FAILED: "FAIL", cr.SKIPPED: "SKIP",
|
|
20
21
|
cr.UNSUPPORTED: "UNSUP", cr.FOREIGN: "OTHER-OS", cr.TIMEOUT: "TIMEOUT",
|
|
21
|
-
cr.DESELECTED: "-",
|
|
22
|
+
cr.DESELECTED: "-", cr.CACHED: "CACHED",
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
# Verdicts an agent may treat as "safe to push". Deliberately one item long.
|
|
@@ -81,7 +82,10 @@ def _failure_rows(jobs: list, limit: int = 25) -> list:
|
|
|
81
82
|
def handle_ci(action: str, job: str, run_id: str, allow_foreign: bool,
|
|
82
83
|
workflow: str, tail: int, timeout: int, svc, finalize,
|
|
83
84
|
event: str = "", engine: str = "auto",
|
|
84
|
-
allow_side_effects: bool = False, network: str = ""
|
|
85
|
+
allow_side_effects: bool = False, network: str = "",
|
|
86
|
+
mode: str = "full", base: str = "",
|
|
87
|
+
allow_host_mutation: bool = False,
|
|
88
|
+
no_cache: bool = False) -> str:
|
|
85
89
|
"""Route c3_ci actions."""
|
|
86
90
|
project = str(svc.project_path)
|
|
87
91
|
action = (action or "inspect").strip().lower()
|
|
@@ -152,6 +156,43 @@ def handle_ci(action: str, job: str, run_id: str, allow_foreign: bool,
|
|
|
152
156
|
return finalize("c3_ci", args, "\n".join(lines),
|
|
153
157
|
f"{len(data['jobs'])} jobs, {len(data['runnable'])} runnable")
|
|
154
158
|
|
|
159
|
+
# ── plan (required mode, no execution) ───────────────────────────────
|
|
160
|
+
if action == "plan":
|
|
161
|
+
from services.ci_workflow import (
|
|
162
|
+
build_dag,
|
|
163
|
+
discover_workflows,
|
|
164
|
+
git_context,
|
|
165
|
+
parse_workflow,
|
|
166
|
+
)
|
|
167
|
+
wfs = [parse_workflow(p) for p in discover_workflows(project)]
|
|
168
|
+
dag = build_dag([w for w in wfs if not w.error],
|
|
169
|
+
event=event, git=git_context(project))
|
|
170
|
+
try:
|
|
171
|
+
ordered = dag.topo_order()
|
|
172
|
+
except Exception:
|
|
173
|
+
ordered = dag.instances
|
|
174
|
+
plan = ci_impact.plan_required(project, ordered, wfs, base=base,
|
|
175
|
+
event=event)
|
|
176
|
+
lines = [
|
|
177
|
+
f"Required-mode plan ({len(plan.selected)} run / "
|
|
178
|
+
f"{len(plan.skipped)} skip) vs {base or 'the working tree'}",
|
|
179
|
+
f"changed files: {len(plan.changed)}",
|
|
180
|
+
]
|
|
181
|
+
for path in plan.changed[:10]:
|
|
182
|
+
lines.append(f" {path}")
|
|
183
|
+
if len(plan.changed) > 10:
|
|
184
|
+
lines.append(f" ... and {len(plan.changed) - 10} more")
|
|
185
|
+
lines.append("")
|
|
186
|
+
for decision in plan.decisions:
|
|
187
|
+
mark = "RUN " if decision.decision == ci_impact.RUN else "skip"
|
|
188
|
+
lines.append(f" {mark} {decision.job}")
|
|
189
|
+
lines.append(f" {decision.reason}")
|
|
190
|
+
if plan.note:
|
|
191
|
+
lines.append(f"\n{plan.note}")
|
|
192
|
+
lines.append("\nRun it: c3_ci(action='run', mode='required')")
|
|
193
|
+
return finalize("c3_ci", args, "\n".join(lines),
|
|
194
|
+
f"{len(plan.selected)} required")
|
|
195
|
+
|
|
155
196
|
# ── run / rerun ──────────────────────────────────────────────────────
|
|
156
197
|
if action in ("run", "rerun"):
|
|
157
198
|
only = None
|
|
@@ -172,7 +213,9 @@ def handle_ci(action: str, job: str, run_id: str, allow_foreign: bool,
|
|
|
172
213
|
only=only, timeout=timeout or cr.DEFAULT_STEP_TIMEOUT,
|
|
173
214
|
workflow=workflow, event=event, engine=engine,
|
|
174
215
|
allow_side_effects=allow_side_effects,
|
|
175
|
-
network=network
|
|
216
|
+
network=network, mode=mode, base=base,
|
|
217
|
+
allow_host_mutation=allow_host_mutation,
|
|
218
|
+
no_cache=no_cache)
|
|
176
219
|
run = result.to_dict()
|
|
177
220
|
lines = [_verdict_line(run), f"run {run['run_id']} host={run['host_os']}"]
|
|
178
221
|
fp = run.get("fingerprint") or {}
|
|
@@ -245,6 +288,86 @@ def handle_ci(action: str, job: str, run_id: str, allow_foreign: bool,
|
|
|
245
288
|
f"{row.get('started_at', '')[:19]} {tally}")
|
|
246
289
|
return finalize("c3_ci", args, "\n".join(lines), f"{len(rows)} runs")
|
|
247
290
|
|
|
291
|
+
# ── history / intelligence ───────────────────────────────────────────
|
|
292
|
+
if action in ("history", "intel", "flaky"):
|
|
293
|
+
from services import ci_intel
|
|
294
|
+
data = ci_intel.analyse(project)
|
|
295
|
+
if not data["runs_analysed"]:
|
|
296
|
+
return finalize("c3_ci", args, data["note"], "no history")
|
|
297
|
+
lines = [data["note"], ""]
|
|
298
|
+
if data["flaky"]:
|
|
299
|
+
lines.append("FLAKY — passed AND failed on identical inputs:")
|
|
300
|
+
for job in data["flaky"]:
|
|
301
|
+
lines.append(f" {job['key']} {job['failed']}/{job['executed']} failed")
|
|
302
|
+
lines.append(" same fingerprint gave both answers, so the "
|
|
303
|
+
"code did not change between them")
|
|
304
|
+
lines.append("")
|
|
305
|
+
lines.append(f"{'job':<40}{'exec':>5}{'fail':>6}{'rate':>7}{'avg':>8}")
|
|
306
|
+
for job in data["jobs"][:15]:
|
|
307
|
+
rate = f"{job['fail_rate']:.0%}" if job["executed"] else "-"
|
|
308
|
+
avg = f"{job['avg_ms'] / 1000:.1f}s" if job["avg_ms"] else "-"
|
|
309
|
+
mark = "" if job["confident"] else " (low n)"
|
|
310
|
+
lines.append(f" {job['key']:<38}{job['executed']:>5}"
|
|
311
|
+
f"{job['failed']:>6}{rate:>7}{avg:>8}{mark}")
|
|
312
|
+
if data["slowest"]:
|
|
313
|
+
lines.append("\nSlowest: " + ", ".join(
|
|
314
|
+
f"{j['key']} {j['avg_ms'] / 1000:.1f}s" for j in data["slowest"][:3]))
|
|
315
|
+
return finalize("c3_ci", args, "\n".join(lines),
|
|
316
|
+
f"{len(data['flaky'])} flaky")
|
|
317
|
+
|
|
318
|
+
# ── publish (GitHub commit status) ───────────────────────────────────
|
|
319
|
+
if action == "publish":
|
|
320
|
+
from services import ci_github
|
|
321
|
+
run = cr.load_run(project, run_id)
|
|
322
|
+
if not run:
|
|
323
|
+
return finalize("c3_ci", args, "No run to publish.", "no runs")
|
|
324
|
+
res = ci_github.publish(project, run,
|
|
325
|
+
force=allow_side_effects,
|
|
326
|
+
dry_run=(job or "").lower() == "dry-run")
|
|
327
|
+
if res.get("dry_run"):
|
|
328
|
+
body = "\n".join([
|
|
329
|
+
f"Would POST {res['endpoint']}",
|
|
330
|
+
f" state={res['state']}",
|
|
331
|
+
f" {res['description']}",
|
|
332
|
+
])
|
|
333
|
+
return finalize("c3_ci", args, body, "dry run")
|
|
334
|
+
if not res.get("published"):
|
|
335
|
+
return finalize("c3_ci", args,
|
|
336
|
+
f"Not published: {res.get('reason')}", "refused")
|
|
337
|
+
body = (f"Published {res['state']} to {res['sha'][:8]} "
|
|
338
|
+
f"as {res['context']}.\n {res['description']}")
|
|
339
|
+
return finalize("c3_ci", args, body, res["state"])
|
|
340
|
+
|
|
341
|
+
# ── cache ────────────────────────────────────────────────────────────
|
|
342
|
+
if action == "cache":
|
|
343
|
+
from services import ci_cache
|
|
344
|
+
if (job or "").strip().lower() == "clear" or run_id == "clear":
|
|
345
|
+
freed = ci_cache.clear(project)
|
|
346
|
+
return finalize("c3_ci", args,
|
|
347
|
+
f"Cleared the CI cache ({freed / 1024:.0f} KB).",
|
|
348
|
+
"cache cleared")
|
|
349
|
+
info = ci_cache.stats(project)
|
|
350
|
+
rules = ci_impact.load_rules(project)
|
|
351
|
+
lines = [
|
|
352
|
+
f"Cached results: {info['results']}",
|
|
353
|
+
f"Dependency cache keys: {info['dependency_keys']}",
|
|
354
|
+
f"Location: {info['dir']}",
|
|
355
|
+
"",
|
|
356
|
+
"A job is reused when its definition, engine and inputs are all "
|
|
357
|
+
"unchanged since it last passed.",
|
|
358
|
+
]
|
|
359
|
+
if rules:
|
|
360
|
+
lines.append(
|
|
361
|
+
f"{len(rules)} job(s) declare inputs via ci.required_map, so "
|
|
362
|
+
"only those paths invalidate them.")
|
|
363
|
+
else:
|
|
364
|
+
lines.append(
|
|
365
|
+
"No ci.required_map: every job is fingerprinted over the whole "
|
|
366
|
+
"tree, so any edit invalidates every cached result. Declaring "
|
|
367
|
+
"inputs is what makes the cache bite.")
|
|
368
|
+
return finalize("c3_ci", args, "\n".join(lines),
|
|
369
|
+
f"{info['results']} cached")
|
|
370
|
+
|
|
248
371
|
# ── doctor ───────────────────────────────────────────────────────────
|
|
249
372
|
if action == "doctor":
|
|
250
373
|
from services import ci_act
|
|
@@ -69,6 +69,45 @@ _SOFT_WARN = re.compile(
|
|
|
69
69
|
|
|
70
70
|
_DEFAULT_TIMEOUT = 60
|
|
71
71
|
_MAX_TIMEOUT = 600
|
|
72
|
+
|
|
73
|
+
# The transport's own ceiling, and the reason _MAX_TIMEOUT alone is a lie.
|
|
74
|
+
#
|
|
75
|
+
# An MCP client kills a tool call at MCP_TOOL_TIMEOUT (Claude Code ships
|
|
76
|
+
# 120_000 ms and the value is set per-environment) — a limit this process does
|
|
77
|
+
# not choose and cannot raise. Until this existed, `c3_shell(timeout=600)` was
|
|
78
|
+
# accepted, clamped to 600, and then killed by the client at 120s with the
|
|
79
|
+
# subprocess still running: the caller saw the call "moved to background" and
|
|
80
|
+
# then fail, with no line anywhere naming the real limit or attributing the
|
|
81
|
+
# kill. The subprocess was NOT reaped by us, because our own deadline never
|
|
82
|
+
# arrived.
|
|
83
|
+
#
|
|
84
|
+
# The cost was not hypothetical. Two Higgsfield image generations (2-4 min
|
|
85
|
+
# each) were requested at timeout=420, killed at 120s, and the remote jobs
|
|
86
|
+
# completed and were BILLED while the local process died before downloading —
|
|
87
|
+
# one image landed, one was paid for and stranded.
|
|
88
|
+
#
|
|
89
|
+
# So: discover the client's ceiling, run just inside it, and SAY SO. Running
|
|
90
|
+
# inside it means OUR deadline fires first, which turns a phantom
|
|
91
|
+
# client-side kill into an ordinary `[c3_shell:TIMEOUT]` with stdout, a
|
|
92
|
+
# duration, and a process tree we actually killed.
|
|
93
|
+
_TRANSPORT_MARGIN_S = 5
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _transport_ceiling_s() -> int | None:
|
|
97
|
+
"""Seconds this call may run before the MCP client kills it, if knowable.
|
|
98
|
+
|
|
99
|
+
None when the variable is unset or unparseable — then nothing is capped
|
|
100
|
+
and behaviour is exactly what it was, because a guess here would cap
|
|
101
|
+
legitimate work on a client with no such limit.
|
|
102
|
+
"""
|
|
103
|
+
raw = (os.environ.get("MCP_TOOL_TIMEOUT") or "").strip()
|
|
104
|
+
if not raw:
|
|
105
|
+
return None
|
|
106
|
+
try:
|
|
107
|
+
ceiling = int(float(raw)) // 1000
|
|
108
|
+
except (TypeError, ValueError):
|
|
109
|
+
return None
|
|
110
|
+
return ceiling if ceiling > _TRANSPORT_MARGIN_S else None
|
|
72
111
|
_FILTER_THRESHOLD_LINES = 30
|
|
73
112
|
_JQ_INVOCATION = re.compile(r"(?:^|&&|\|\||[;|(])\s*jq(?:\s|$)", re.IGNORECASE)
|
|
74
113
|
|
|
@@ -468,6 +507,13 @@ async def handle_shell(cmd: str, cwd: str, timeout: int, filter_output: bool,
|
|
|
468
507
|
)
|
|
469
508
|
|
|
470
509
|
timeout = max(1, min(int(timeout or _DEFAULT_TIMEOUT), _MAX_TIMEOUT))
|
|
510
|
+
# Cap to what the transport will actually allow, and remember that we did
|
|
511
|
+
# so — the caller asked for a number, and a number quietly not honoured is
|
|
512
|
+
# the whole defect (see _transport_ceiling_s).
|
|
513
|
+
capped_from = 0
|
|
514
|
+
_ceiling = _transport_ceiling_s()
|
|
515
|
+
if _ceiling is not None and timeout > _ceiling - _TRANSPORT_MARGIN_S:
|
|
516
|
+
capped_from, timeout = timeout, _ceiling - _TRANSPORT_MARGIN_S
|
|
471
517
|
work_cwd = cwd or svc.project_path
|
|
472
518
|
work_cwd = str(Path(work_cwd).resolve())
|
|
473
519
|
|
|
@@ -601,6 +647,16 @@ async def handle_shell(cmd: str, cwd: str, timeout: int, filter_output: bool,
|
|
|
601
647
|
warn = ""
|
|
602
648
|
if _SOFT_WARN.search(cmd):
|
|
603
649
|
warn = "[c3_shell:warn] destructive pattern detected — verify before re-running\n"
|
|
650
|
+
if capped_from:
|
|
651
|
+
# Named at the moment of the mistake, not in documentation nobody
|
|
652
|
+
# reads at the moment they need it. The alternative IS the escape
|
|
653
|
+
# hatch, so the line says which one.
|
|
654
|
+
warn += (
|
|
655
|
+
f"[c3_shell:capped] timeout={capped_from}s was requested but this "
|
|
656
|
+
f"MCP client kills a tool call at {_ceiling}s; ran with {timeout}s. "
|
|
657
|
+
f"For longer work use the native Bash tool with "
|
|
658
|
+
f"run_in_background, which is not bound by this limit.\n"
|
|
659
|
+
)
|
|
604
660
|
|
|
605
661
|
if result["timed_out"]:
|
|
606
662
|
status = "TIMEOUT"
|
|
@@ -5,7 +5,8 @@ READ_ACTIONS = {"list", "get", "board", "history", "report",
|
|
|
5
5
|
|
|
6
6
|
_TASK_ACTIONS = ("add, update, done, list, get, board, history, report, archive, "
|
|
7
7
|
"block, unblock, link, unlink, "
|
|
8
|
-
"milestone_add, milestone_update, milestone_list,
|
|
8
|
+
"milestone_add, milestone_update, milestone_list, "
|
|
9
|
+
"milestone_complete, milestone_reopen, milestone_archive, "
|
|
9
10
|
"note_add, note_list, "
|
|
10
11
|
"time_add, time_update, time_delete, time_list, time_summary")
|
|
11
12
|
|
|
@@ -368,6 +369,26 @@ def handle_task(action, svc, finalize, *, title="", task_id="", status="",
|
|
|
368
369
|
return done_resp(f"[task:error] {res['error']}", "error")
|
|
369
370
|
return done_resp(f"[milestone:updated] {res['id'][:8]} \"{res['name']}\"", "updated")
|
|
370
371
|
|
|
372
|
+
if action == "milestone_complete":
|
|
373
|
+
if not milestone:
|
|
374
|
+
return done_resp("[task:error] milestone_complete requires milestone.", "error")
|
|
375
|
+
ms = store.resolve_milestone(milestone)
|
|
376
|
+
if ms is None:
|
|
377
|
+
return done_resp(f"[task:error] no milestone matches: {milestone}", "error")
|
|
378
|
+
res = store.complete_milestone(ms["id"])
|
|
379
|
+
if "error" in res:
|
|
380
|
+
return done_resp(f"[task:error] {res['error']}", "error")
|
|
381
|
+
return done_resp(f"[milestone:completed] \"{res['name']}\" "
|
|
382
|
+
f"(tasks keep their milestone link)", "completed")
|
|
383
|
+
|
|
384
|
+
if action == "milestone_reopen":
|
|
385
|
+
if not milestone:
|
|
386
|
+
return done_resp("[task:error] milestone_reopen requires milestone.", "error")
|
|
387
|
+
res = store.reopen_milestone(milestone)
|
|
388
|
+
if "error" in res:
|
|
389
|
+
return done_resp(f"[task:error] {res['error']}", "error")
|
|
390
|
+
return done_resp(f"[milestone:reopened] \"{res['name']}\"", "reopened")
|
|
391
|
+
|
|
371
392
|
if action == "milestone_archive":
|
|
372
393
|
if not milestone:
|
|
373
394
|
return done_resp("[task:error] milestone_archive requires milestone.", "error")
|
{code_context_control-2.82.0 → code_context_control-2.86.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.86.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
|
|
@@ -178,7 +178,7 @@ Twelve tabs. The dashboard above shows token savings, indexed files, the live se
|
|
|
178
178
|
<img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/2026-07/ui_tasks.png" alt="C3 Tasks" width="900">
|
|
179
179
|
</p>
|
|
180
180
|
|
|
181
|
-
**Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board.
|
|
181
|
+
**Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board. Shipped milestones can be **completed** (v2.86.0) — they leave the board while their tasks keep the milestone link, unlike archiving, which detaches them.
|
|
182
182
|
|
|
183
183
|
**Instructions** keeps your agent-facing docs in sync. C3-generated content sits inside a `<!-- C3:BEGIN … -->` block; anything you write outside it is preserved. Since v2.60.0 generated docs point at `.c3/MAP.md` — a machine-owned, byte-stable repo map C3 refreshes automatically — instead of embedding a tree that goes stale. `AGENTS.md` serves both Codex and Antigravity; `GEMINI.md` is read if present but no longer generated (the Gemini CLI profile was removed in v2.52).
|
|
184
184
|
|
|
@@ -243,6 +243,7 @@ c3 access mask activate # purge pre-mask artifacts, buil
|
|
|
243
243
|
- **`deny` means deny-enumerate too** — denied paths never appear in search results, maps, or the vector index.
|
|
244
244
|
- **Masked means read-only, always.** Cropped rows have no inverse, so an edit in transformed coordinates would corrupt the one file you protected.
|
|
245
245
|
- **Four deterministic presets, no LLM in the read path:** `redact_secrets`, `redact_columns` (salted one-way pseudonyms — joins survive, no reverse dictionary), `sample_rows`, `signatures_only`.
|
|
246
|
+
- **Sensible defaults out of the box** (v2.86.0). A fresh install seeds `*.pem`, `id_rsa*`, and `*.key` as deny rules in global scope — visible in `c3 access list` and removable like any rule you wrote yourself. Delete one and it stays deleted.
|
|
246
247
|
- **Rule changes are human-only** (UI tab or CLI) and ledger-logged. Agents have no mutation surface.
|
|
247
248
|
- **Built-ins can be switched off when you need to** (v2.65.0). `**/.env*`, `**/.c3/**`, `**/.claude/settings*.json` and `**/.git/**` yield to `c3 access builtin disable <glob>`, which makes you retype the glob first. It takes **two keys** — a config entry *and* a keyring attestation — so an agent that manages to write `config.json` still cannot grant itself write access to your settings. The credential vault stays absolute.
|
|
248
249
|
- **Honest coverage.** This guards *cooperative* agents against mistakes and prompt injection. It is not a sandbox — a raw shell outside C3's tools still sees the real bytes.
|
|
@@ -186,8 +186,12 @@ services/benchmark_dashboard.py
|
|
|
186
186
|
services/bitbucket_client.py
|
|
187
187
|
services/bitbucket_credentials.py
|
|
188
188
|
services/ci_act.py
|
|
189
|
+
services/ci_cache.py
|
|
189
190
|
services/ci_expr.py
|
|
190
191
|
services/ci_failures.py
|
|
192
|
+
services/ci_github.py
|
|
193
|
+
services/ci_impact.py
|
|
194
|
+
services/ci_intel.py
|
|
191
195
|
services/ci_runner.py
|
|
192
196
|
services/ci_workflow.py
|
|
193
197
|
services/circuit_breaker.py
|
|
@@ -283,7 +287,10 @@ tests/test_c3_bridge_project_artifacts.py
|
|
|
283
287
|
tests/test_c3_shell.py
|
|
284
288
|
tests/test_chat_poll.py
|
|
285
289
|
tests/test_ci_act.py
|
|
290
|
+
tests/test_ci_cache.py
|
|
286
291
|
tests/test_ci_expr.py
|
|
292
|
+
tests/test_ci_impact.py
|
|
293
|
+
tests/test_ci_intel.py
|
|
287
294
|
tests/test_ci_runner.py
|
|
288
295
|
tests/test_ci_workflow.py
|
|
289
296
|
tests/test_circuit_breaker.py
|