code-context-control 2.89.1__tar.gz → 2.92.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.89.1/code_context_control.egg-info → code_context_control-2.92.0}/PKG-INFO +2 -2
- {code_context_control-2.89.1 → code_context_control-2.92.0}/README.md +1 -1
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/c3.py +286 -49
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/commands/parser.py +9 -2
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/credentials.html +22 -5
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/oracle.html +18 -3
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_pretool_enforce.py +148 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_server.py +100 -1
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/app.js +2 -1
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/hub_credentials.js +26 -3
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/settings_modal.js +148 -33
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/topbar.js +4 -1
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/mcp_server.py +9 -5
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/credentials.py +9 -1
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/credentials.js +26 -3
- {code_context_control-2.89.1 → code_context_control-2.92.0/code_context_control.egg-info}/PKG-INFO +2 -2
- {code_context_control-2.89.1 → code_context_control-2.92.0}/code_context_control.egg-info/SOURCES.txt +10 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/oracle_server.py +32 -11
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/oracle_ui.html +31 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/local_session.py +72 -8
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/chat/send.js +6 -1
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/core.js +39 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/header.js +13 -1
- {code_context_control-2.89.1 → code_context_control-2.92.0}/pyproject.toml +1 -1
- code_context_control-2.92.0/services/background_service.py +662 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/claude_md.py +39 -1
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/credential_store.py +83 -3
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/enforcement_policy.py +9 -3
- code_context_control-2.92.0/services/hub_service.py +78 -0
- code_context_control-2.92.0/services/oracle_service.py +141 -0
- code_context_control-2.92.0/services/repo_shape.py +129 -0
- code_context_control-2.92.0/tests/test_background_service.py +445 -0
- code_context_control-2.92.0/tests/test_credential_login_kind.py +191 -0
- code_context_control-2.92.0/tests/test_credential_ui_parity.py +146 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hook_pretool_enforce.py +123 -0
- code_context_control-2.92.0/tests/test_hub_oracle_service_routes.py +202 -0
- code_context_control-2.92.0/tests/test_init_clear_preserves_user_content.py +236 -0
- code_context_control-2.92.0/tests/test_oracle_health_probe.py +73 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_session_bootstrap.py +69 -0
- code_context_control-2.92.0/tests/test_repo_shape.py +204 -0
- code_context_control-2.89.1/services/hub_service.py +0 -585
- {code_context_control-2.89.1 → code_context_control-2.92.0}/LICENSE +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/_hook_utils.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/commands/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/commands/common.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/docs.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/edits.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/access.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/index.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/masking.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/shared.css +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/tools.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/guide/workflow.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_artifact.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_c3read.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_filter.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_read.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/hub_ui.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/progress.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/server.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/_grants.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/agent.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/ci.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/compress.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/delegate.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/edit.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/edits.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/federate.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/filter.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/impact.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/jira.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/locks.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/memory.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/override.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/project.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/read.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/search.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/session.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/shell.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/status.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/tasks.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/tools/validate.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/api.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/app.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/access.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/icons.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/shared.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui/theme.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui_legacy.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/cli/ui_nano.html +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/core/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/core/config.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/core/ide.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/core/mcp_toml.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/core/web_security.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/config.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/mobile_api.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/activity.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/agents.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/app.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/busy.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/insights.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/projects.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/settings.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/access_guard.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/access_telemetry.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/activity_log.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/agent_base.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/agent_locks.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/agents.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/artifact_defs.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/artifact_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/auto_memory.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/bench/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/bitbucket_client.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_act.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_cache.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_expr.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_failures.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_github.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_impact.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_intel.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_runner.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ci_workflow.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/circuit_breaker.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/compressor.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/context_snapshot.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/conversation_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/cred_telemetry.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/doc_index.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/e2e_tasks.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/edit_ledger.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/embedding_index.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/error_reporting.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/file_memory.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/git_context.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/indexer.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/jira_client.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/jira_cloud.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/jira_credentials.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/jira_data_center.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/jira_links.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/mask_activation.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/mask_mirror.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/mask_presets.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/memory.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/memory_consolidator.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/memory_distiller.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/memory_graph.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/memory_grounder.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/memory_queue.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/memory_scorer.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/metrics.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/notifications.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ollama_bridge.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ollama_client.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/ollama_credentials.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/output_filter.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/override_grants.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/override_policy.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/override_requests.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/override_wake.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/parser.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/project_manager.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/project_runtime.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/protocol.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/proxy_state.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/repo_map.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/retention.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/retrieval_broker.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/router.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/runtime.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/scanner.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/session_benchmark.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/session_manager.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/session_preloader.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/subprojects.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/task_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/telemetry.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/text_index.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/time_tracker.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/tool_classifier.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/transcript_index.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/validation_cache.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/vector_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/watcher.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/services/win_subprocess.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/setup.cfg +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_access_guard.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ci_act.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_credential_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hook_state.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_init_scan.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_jira_client.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_jira_links.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_memory_system.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_output_filter.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_override_grants.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_override_requests.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_override_wake.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_permissions.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_pm_api.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_project_manager.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_project_tool.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_related_facts.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_repo_map.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_retention.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_review_digest.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_service_durability.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_session_budget.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_subprojects.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_task_store.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_task_tool.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_validate.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_version_sync.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_web_security.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/backend.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/main.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/__init__.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/index_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/init_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/search_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/session_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/stats.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.89.1 → code_context_control-2.92.0}/tui/theme.tcss +0 -0
{code_context_control-2.89.1/code_context_control.egg-info → code_context_control-2.92.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.92.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
|
|
@@ -137,7 +137,7 @@ Full notes: [Upgrading](https://github.com/drknowhow/code-context-control/blob/m
|
|
|
137
137
|
|
|
138
138
|
## The UI
|
|
139
139
|
|
|
140
|
-
Three local web apps, no Electron — pure Flask + vanilla JS: the **Hub** (`c3 hub`, port 3330), the **per-project UI** (`c3 ui`), and the optional **Oracle** (`c3 oracle serve`).
|
|
140
|
+
Three local web apps, no Electron — pure Flask + vanilla JS: the **Hub** (`c3 hub`, port 3330), the **per-project UI** (`c3 ui`), and the optional **Oracle** (`c3 oracle serve`). Both servers can run as windowless login services — `c3 hub --install`, `c3 oracle serve --install`, or the buttons in Hub → Settings.
|
|
141
141
|
|
|
142
142
|
### Project Hub — multi-project mission control
|
|
143
143
|
|
|
@@ -74,7 +74,7 @@ Full notes: [Upgrading](https://github.com/drknowhow/code-context-control/blob/m
|
|
|
74
74
|
|
|
75
75
|
## The UI
|
|
76
76
|
|
|
77
|
-
Three local web apps, no Electron — pure Flask + vanilla JS: the **Hub** (`c3 hub`, port 3330), the **per-project UI** (`c3 ui`), and the optional **Oracle** (`c3 oracle serve`).
|
|
77
|
+
Three local web apps, no Electron — pure Flask + vanilla JS: the **Hub** (`c3 hub`, port 3330), the **per-project UI** (`c3 ui`), and the optional **Oracle** (`c3 oracle serve`). Both servers can run as windowless login services — `c3 hub --install`, `c3 oracle serve --install`, or the buttons in Hub → Settings.
|
|
78
78
|
|
|
79
79
|
### Project Hub — multi-project mission control
|
|
80
80
|
|
|
@@ -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.92.0"
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -845,7 +845,8 @@ def _prompt_memory_llm(project_path: str) -> None:
|
|
|
845
845
|
+ ("cloud + local fallback." if section["cloud_enabled"] else "local only (private)."))
|
|
846
846
|
|
|
847
847
|
|
|
848
|
-
def _prompt_init_steps(project_path: str, ide_name: str, default_mode: str = "direct"
|
|
848
|
+
def _prompt_init_steps(project_path: str, ide_name: str, default_mode: str = "direct",
|
|
849
|
+
shape=None) -> tuple[str, bool]:
|
|
849
850
|
"""Run guided post-init setup steps for Git and MCP."""
|
|
850
851
|
chosen_ide = _select_init_ide(ide_name or "auto")
|
|
851
852
|
save_config({"ide": chosen_ide}, project_path)
|
|
@@ -916,7 +917,7 @@ def _prompt_init_steps(project_path: str, ide_name: str, default_mode: str = "di
|
|
|
916
917
|
)
|
|
917
918
|
include_wildcard = bool(wildcard_choice and wildcard_choice.startswith("Yes"))
|
|
918
919
|
|
|
919
|
-
chosen_enforcement = _prompt_enforcement(chosen_tier)
|
|
920
|
+
chosen_enforcement = _prompt_enforcement(chosen_tier, shape=shape)
|
|
920
921
|
|
|
921
922
|
_run_install_mcp(project_path, chosen_ide, mcp_mode=mcp_mode,
|
|
922
923
|
permissions=chosen_tier, include_mcp_wildcard=include_wildcard,
|
|
@@ -924,9 +925,70 @@ def _prompt_init_steps(project_path: str, ide_name: str, default_mode: str = "di
|
|
|
924
925
|
return chosen_ide, True
|
|
925
926
|
|
|
926
927
|
|
|
927
|
-
def
|
|
928
|
+
def _assess_repo_shape(project_path: str):
|
|
929
|
+
"""Measure the project (services.repo_shape). None when it cannot be measured."""
|
|
930
|
+
try:
|
|
931
|
+
from services import repo_shape
|
|
932
|
+
return repo_shape.assess(project_path)
|
|
933
|
+
except Exception:
|
|
934
|
+
_log.debug("repo shape assessment failed", exc_info=True)
|
|
935
|
+
return None
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
def _apply_repo_shape_default(project_path: str, explicit_enforcement: str | None = None,
|
|
939
|
+
shape=None) -> None:
|
|
940
|
+
"""Say what kind of project this is, and default a prose one to ``advisory``.
|
|
941
|
+
|
|
942
|
+
Field report 2026-08-22: a 636-file project, ~95% Markdown and .docx,
|
|
943
|
+
where every symbol-aware C3 tool had nothing to act on and strict
|
|
944
|
+
discipline was paid on every turn until C3 was uninstalled. The shape
|
|
945
|
+
is printed for every project; the default is written only for the prose
|
|
946
|
+
kind, only over a tier-derived or unset mode (never over ``c3 enforce``
|
|
947
|
+
or ``--enforcement``), with provenance ``set_by: repo-shape`` so
|
|
948
|
+
``c3 enforce`` shows where it came from, and with the way back printed.
|
|
949
|
+
"""
|
|
950
|
+
try:
|
|
951
|
+
from services import enforcement_policy as ep
|
|
952
|
+
from services import repo_shape
|
|
953
|
+
except Exception:
|
|
954
|
+
return
|
|
955
|
+
if shape is None:
|
|
956
|
+
shape = _assess_repo_shape(project_path)
|
|
957
|
+
if shape is None or shape.kind == repo_shape.KIND_EMPTY:
|
|
958
|
+
return
|
|
959
|
+
print(f"\n Repo shape: {shape.describe()}")
|
|
960
|
+
mode = repo_shape.recommended_mode(shape)
|
|
961
|
+
if not mode:
|
|
962
|
+
return
|
|
963
|
+
if explicit_enforcement:
|
|
964
|
+
print(f" Prose-heavy, but --enforcement {explicit_enforcement} was given — leaving it as set.")
|
|
965
|
+
return
|
|
966
|
+
current = ep.resolve(project_path)
|
|
967
|
+
if current.set_by == ep.SET_BY_USER:
|
|
968
|
+
print(f" Prose-heavy; tool discipline stays '{current.mode}' (your choice).")
|
|
969
|
+
return
|
|
970
|
+
if current.mode == mode:
|
|
971
|
+
print(f" Prose-heavy; tool discipline is already '{mode}'.")
|
|
972
|
+
return
|
|
973
|
+
try:
|
|
974
|
+
result = ep.set_mode(mode, project_path, set_by=ep.SET_BY_SHAPE, scope="project")
|
|
975
|
+
except ValueError:
|
|
976
|
+
return
|
|
977
|
+
if result.get("deferred"):
|
|
978
|
+
return
|
|
979
|
+
print(" [!] This is a documentation project: C3's symbol-aware tools (compress/read/impact/")
|
|
980
|
+
print(f" validate/CI) have little to act on here, so tool discipline is set to '{mode}' —")
|
|
981
|
+
print(" native Edit/Write are allowed with a nudge and the edit ledger still records them.")
|
|
982
|
+
print(" `c3 enforce strict` restores the hard block; `c3 enforce` shows the setting.")
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
def _prompt_enforcement(chosen_tier: str | None, shape=None) -> str | None:
|
|
928
986
|
"""Step 5/5 — tool discipline. Returns an explicit mode, or None to derive.
|
|
929
987
|
|
|
988
|
+
``shape`` (services.repo_shape.RepoShape) moves the suggested default to
|
|
989
|
+
``advisory`` for a documentation project and says why, so the user is
|
|
990
|
+
not asked to guess what C3's symbol tools will do with 600 Markdown files.
|
|
991
|
+
|
|
930
992
|
Asked separately from the permission tier because it answers a genuinely
|
|
931
993
|
different question: the tier controls what the IDE will let the agent call,
|
|
932
994
|
this controls how hard C3's own hook pushes it toward c3_* tools. Users hit
|
|
@@ -938,8 +1000,18 @@ def _prompt_enforcement(chosen_tier: str | None) -> str | None:
|
|
|
938
1000
|
return None
|
|
939
1001
|
|
|
940
1002
|
default_mode = ep.derive_from_tier(chosen_tier) if chosen_tier else ep.MODE_ADVISORY
|
|
1003
|
+
suggested_by = "Your permission tier suggests"
|
|
1004
|
+
try:
|
|
1005
|
+
from services import repo_shape
|
|
1006
|
+
shape_mode = repo_shape.recommended_mode(shape) if shape is not None else None
|
|
1007
|
+
except Exception:
|
|
1008
|
+
shape_mode = None
|
|
1009
|
+
if shape_mode:
|
|
1010
|
+
default_mode = shape_mode
|
|
1011
|
+
suggested_by = ("This is a documentation project — C3's symbol tools have "
|
|
1012
|
+
"little to act on here. Suggested")
|
|
941
1013
|
print()
|
|
942
|
-
print(f" (
|
|
1014
|
+
print(f" ({suggested_by}: {default_mode})")
|
|
943
1015
|
choice = _prompt_choice(
|
|
944
1016
|
"Step 5/5 — Tool discipline: how hard should C3 push toward c3_* tools?",
|
|
945
1017
|
[
|
|
@@ -1085,6 +1157,7 @@ def cmd_init(args):
|
|
|
1085
1157
|
if not c3_dir.exists() or not (c3_dir / "config.json").exists():
|
|
1086
1158
|
print_header(f"Initializing C3 for: {project_path}")
|
|
1087
1159
|
_do_init(project_path, ide_name=requested_ide, no_embed=no_embed)
|
|
1160
|
+
shape = _assess_repo_shape(project_path)
|
|
1088
1161
|
try:
|
|
1089
1162
|
from services.project_manager import ProjectManager
|
|
1090
1163
|
ProjectManager().add_project(project_path)
|
|
@@ -1101,7 +1174,11 @@ def cmd_init(args):
|
|
|
1101
1174
|
enforcement=getattr(args, "enforcement", None),
|
|
1102
1175
|
)
|
|
1103
1176
|
else:
|
|
1104
|
-
_prompt_init_steps(project_path, requested_ide,
|
|
1177
|
+
_prompt_init_steps(project_path, requested_ide,
|
|
1178
|
+
default_mode=getattr(args, "mcp_mode", "direct"), shape=shape)
|
|
1179
|
+
_apply_repo_shape_default(project_path,
|
|
1180
|
+
explicit_enforcement=getattr(args, "enforcement", None),
|
|
1181
|
+
shape=shape)
|
|
1105
1182
|
# Detect Codex CLI availability
|
|
1106
1183
|
try:
|
|
1107
1184
|
from cli.tools.delegate import check_codex
|
|
@@ -1285,11 +1362,7 @@ def cmd_init(args):
|
|
|
1285
1362
|
if c3_dir.exists():
|
|
1286
1363
|
shutil.rmtree(c3_dir)
|
|
1287
1364
|
print(" Deleted .c3/")
|
|
1288
|
-
|
|
1289
|
-
p = Path(project_path) / filename
|
|
1290
|
-
if p.exists():
|
|
1291
|
-
p.unlink()
|
|
1292
|
-
print(f" Deleted {filename}")
|
|
1365
|
+
_remove_c3_instruction_docs(project_path)
|
|
1293
1366
|
print("\n[OK] C3 project files removed.")
|
|
1294
1367
|
return
|
|
1295
1368
|
|
|
@@ -1361,9 +1434,10 @@ def cmd_init(args):
|
|
|
1361
1434
|
|
|
1362
1435
|
elif selected.startswith("Wipe"):
|
|
1363
1436
|
confirm = input(
|
|
1364
|
-
"\n WARNING: This will permanently delete .c3
|
|
1365
|
-
"
|
|
1366
|
-
"
|
|
1437
|
+
"\n WARNING: This will permanently delete .c3/, remove C3's managed\n"
|
|
1438
|
+
" block from CLAUDE.md / AGENTS.md / GEMINI.md (a file is deleted only\n"
|
|
1439
|
+
" when nothing else is in it), and remove C3 MCP configurations from\n"
|
|
1440
|
+
" your IDE. Type 'yes' to confirm: "
|
|
1367
1441
|
).strip().lower()
|
|
1368
1442
|
if confirm != "yes":
|
|
1369
1443
|
print(" Wipe cancelled.")
|
|
@@ -1375,11 +1449,7 @@ def cmd_init(args):
|
|
|
1375
1449
|
shutil.rmtree(c3_dir)
|
|
1376
1450
|
print(" Deleted .c3/")
|
|
1377
1451
|
|
|
1378
|
-
|
|
1379
|
-
p = Path(project_path) / filename
|
|
1380
|
-
if p.exists():
|
|
1381
|
-
p.unlink()
|
|
1382
|
-
print(f" Deleted {filename}")
|
|
1452
|
+
_remove_c3_instruction_docs(project_path)
|
|
1383
1453
|
|
|
1384
1454
|
print("\n[OK] C3 project files removed.")
|
|
1385
1455
|
|
|
@@ -4555,6 +4625,115 @@ def _ensure_global_session_fallbacks(server_script: str, c3_mcp_exe: str | None
|
|
|
4555
4625
|
print(f"Warning: Could not update {antigravity_path} (global fallback skipped)")
|
|
4556
4626
|
|
|
4557
4627
|
|
|
4628
|
+
# Every hook script C3 has ever registered in a settings file — the v2.42+
|
|
4629
|
+
# dispatcher plus the pre-v2.42 per-hook scripts — so uninstall recognises an
|
|
4630
|
+
# entry written by any C3 version. A user hook is anything not naming one.
|
|
4631
|
+
_C3_HOOK_SCRIPTS = (
|
|
4632
|
+
"hook_dispatch.py",
|
|
4633
|
+
"hook_access_guard.py", "hook_artifact.py", "hook_auto_snapshot.py",
|
|
4634
|
+
"hook_c3_signal.py", "hook_c3read.py", "hook_edit_ledger.py",
|
|
4635
|
+
"hook_edit_unlock.py", "hook_filter.py", "hook_ghost_files.py",
|
|
4636
|
+
"hook_pretool_enforce.py", "hook_prompt_recall.py", "hook_read.py",
|
|
4637
|
+
"hook_session_stats.py", "hook_terse_advisor.py",
|
|
4638
|
+
)
|
|
4639
|
+
|
|
4640
|
+
|
|
4641
|
+
def _is_c3_hook_command(command) -> bool:
|
|
4642
|
+
return any(script in str(command or "") for script in _C3_HOOK_SCRIPTS)
|
|
4643
|
+
|
|
4644
|
+
|
|
4645
|
+
def _is_c3_permission(rule) -> bool:
|
|
4646
|
+
"""``mcp__c3__<tool>``, ``mcp__c3__*``, or the bare ``mcp__c3`` server grant."""
|
|
4647
|
+
r = str(rule or "").strip()
|
|
4648
|
+
return r == "mcp__c3" or r.startswith("mcp__c3__")
|
|
4649
|
+
|
|
4650
|
+
|
|
4651
|
+
def _c3_references_in_settings(settings: dict) -> list:
|
|
4652
|
+
"""Every C3-owned entry present in a settings dict: hook commands (named
|
|
4653
|
+
by event) and permission rules. Used to decide whether there is anything
|
|
4654
|
+
to remove and, after writing, to check that it was actually removed."""
|
|
4655
|
+
refs: list = []
|
|
4656
|
+
hooks = settings.get("hooks")
|
|
4657
|
+
if isinstance(hooks, dict):
|
|
4658
|
+
for event, groups in hooks.items():
|
|
4659
|
+
for group in groups or []:
|
|
4660
|
+
if not isinstance(group, dict):
|
|
4661
|
+
continue
|
|
4662
|
+
for hk in group.get("hooks") or []:
|
|
4663
|
+
if isinstance(hk, dict) and _is_c3_hook_command(hk.get("command")):
|
|
4664
|
+
refs.append(f"hooks.{event}")
|
|
4665
|
+
perms = settings.get("permissions")
|
|
4666
|
+
if isinstance(perms, dict):
|
|
4667
|
+
for key in ("allow", "deny", "ask"):
|
|
4668
|
+
for rule in perms.get(key) or []:
|
|
4669
|
+
if _is_c3_permission(rule):
|
|
4670
|
+
refs.append(f"permissions.{key}:{rule}")
|
|
4671
|
+
if "c3" in (settings.get("enabledMcpjsonServers") or []):
|
|
4672
|
+
refs.append("enabledMcpjsonServers:c3")
|
|
4673
|
+
return refs
|
|
4674
|
+
|
|
4675
|
+
|
|
4676
|
+
def _strip_c3_from_settings(settings: dict) -> dict:
|
|
4677
|
+
"""Remove every C3-owned entry from a Claude Code settings dict (in place,
|
|
4678
|
+
and returned). Touches ONLY what C3 wrote: hook entries whose command runs
|
|
4679
|
+
a C3 hook script — any event, any matcher; the previous cleanup looked at
|
|
4680
|
+
three PostToolUse matchers from the pre-v2.42 layout and nothing else, so
|
|
4681
|
+
PreToolUse/Stop/UserPromptSubmit and the whole ``permissions.allow`` list
|
|
4682
|
+
survived an "uninstall" — plus ``mcp__c3__*`` permission rules and the
|
|
4683
|
+
``c3`` MCP-server enablement. User hooks, user permission rules and every
|
|
4684
|
+
other key are left exactly as found; containers emptied by the removal
|
|
4685
|
+
are dropped so a file C3 created alone ends up empty (and the caller
|
|
4686
|
+
deletes it) rather than as ``{"hooks": {}}``.
|
|
4687
|
+
"""
|
|
4688
|
+
hooks = settings.get("hooks")
|
|
4689
|
+
if isinstance(hooks, dict):
|
|
4690
|
+
for event in list(hooks.keys()):
|
|
4691
|
+
kept_groups = []
|
|
4692
|
+
for group in hooks.get(event) or []:
|
|
4693
|
+
if not isinstance(group, dict):
|
|
4694
|
+
kept_groups.append(group)
|
|
4695
|
+
continue
|
|
4696
|
+
entries = group.get("hooks") or []
|
|
4697
|
+
if not any(isinstance(hk, dict) and _is_c3_hook_command(hk.get("command"))
|
|
4698
|
+
for hk in entries):
|
|
4699
|
+
kept_groups.append(group) # not ours — untouched
|
|
4700
|
+
continue
|
|
4701
|
+
kept = [hk for hk in entries
|
|
4702
|
+
if not (isinstance(hk, dict) and _is_c3_hook_command(hk.get("command")))]
|
|
4703
|
+
if kept:
|
|
4704
|
+
group = dict(group)
|
|
4705
|
+
group["hooks"] = kept
|
|
4706
|
+
kept_groups.append(group)
|
|
4707
|
+
if kept_groups:
|
|
4708
|
+
hooks[event] = kept_groups
|
|
4709
|
+
else:
|
|
4710
|
+
del hooks[event]
|
|
4711
|
+
if not hooks:
|
|
4712
|
+
del settings["hooks"]
|
|
4713
|
+
|
|
4714
|
+
perms = settings.get("permissions")
|
|
4715
|
+
if isinstance(perms, dict):
|
|
4716
|
+
for key in ("allow", "deny", "ask"):
|
|
4717
|
+
rules = perms.get(key)
|
|
4718
|
+
if isinstance(rules, list) and any(_is_c3_permission(r) for r in rules):
|
|
4719
|
+
kept_rules = [r for r in rules if not _is_c3_permission(r)]
|
|
4720
|
+
if kept_rules:
|
|
4721
|
+
perms[key] = kept_rules
|
|
4722
|
+
else:
|
|
4723
|
+
del perms[key]
|
|
4724
|
+
if not perms:
|
|
4725
|
+
del settings["permissions"]
|
|
4726
|
+
|
|
4727
|
+
enabled = settings.get("enabledMcpjsonServers")
|
|
4728
|
+
if isinstance(enabled, list) and "c3" in enabled:
|
|
4729
|
+
enabled = [s for s in enabled if s != "c3"]
|
|
4730
|
+
if enabled:
|
|
4731
|
+
settings["enabledMcpjsonServers"] = enabled
|
|
4732
|
+
else:
|
|
4733
|
+
del settings["enabledMcpjsonServers"]
|
|
4734
|
+
return settings
|
|
4735
|
+
|
|
4736
|
+
|
|
4558
4737
|
def _uninstall_mcp_all(project_path: str, include_global: bool = True):
|
|
4559
4738
|
"""Remove C3 MCP server configurations from all supported IDEs.
|
|
4560
4739
|
|
|
@@ -4658,37 +4837,28 @@ def _uninstall_mcp_all(project_path: str, include_global: bool = True):
|
|
|
4658
4837
|
with open(settings_path, 'r', encoding="utf-8") as f:
|
|
4659
4838
|
settings = json.load(f)
|
|
4660
4839
|
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
c3_hook_files = {"hook_filter.py", "hook_read.py", "hook_c3read.py", "hook_dispatch.py"}
|
|
4665
|
-
for h in hooks:
|
|
4666
|
-
if h.get("matcher") in ("Bash", "Read", "mcp__c3__c3_read"):
|
|
4667
|
-
h["hooks"] = [hook for hook in h.get("hooks", [])
|
|
4668
|
-
if not any(f in hook.get("command", "") for f in c3_hook_files)]
|
|
4669
|
-
if h["hooks"]:
|
|
4670
|
-
new_hooks.append(h)
|
|
4671
|
-
else:
|
|
4672
|
-
new_hooks.append(h)
|
|
4673
|
-
|
|
4674
|
-
if new_hooks:
|
|
4675
|
-
settings["hooks"]["PostToolUse"] = new_hooks
|
|
4676
|
-
elif "hooks" in settings and "PostToolUse" in settings["hooks"]:
|
|
4677
|
-
del settings["hooks"]["PostToolUse"]
|
|
4678
|
-
if not settings["hooks"]:
|
|
4679
|
-
del settings["hooks"]
|
|
4680
|
-
|
|
4681
|
-
# Remove enabled server
|
|
4682
|
-
if "enabledMcpjsonServers" in settings and "c3" in settings["enabledMcpjsonServers"]:
|
|
4683
|
-
settings["enabledMcpjsonServers"].remove("c3")
|
|
4684
|
-
|
|
4685
|
-
if not settings:
|
|
4686
|
-
settings_path.unlink()
|
|
4687
|
-
print(f" Deleted empty {settings_path}")
|
|
4840
|
+
before = _c3_references_in_settings(settings)
|
|
4841
|
+
if not before:
|
|
4842
|
+
print(f" No C3 entries in {settings_path}")
|
|
4688
4843
|
else:
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4844
|
+
settings = _strip_c3_from_settings(settings)
|
|
4845
|
+
if not settings:
|
|
4846
|
+
settings_path.unlink()
|
|
4847
|
+
print(f" Deleted empty {settings_path}")
|
|
4848
|
+
else:
|
|
4849
|
+
with open(settings_path, 'w', encoding="utf-8") as f:
|
|
4850
|
+
json.dump(settings, f, indent=2)
|
|
4851
|
+
# Postcondition: re-read what is on disk and report
|
|
4852
|
+
# what is true, not what was attempted.
|
|
4853
|
+
with open(settings_path, 'r', encoding="utf-8") as f:
|
|
4854
|
+
remaining = _c3_references_in_settings(json.load(f))
|
|
4855
|
+
if remaining:
|
|
4856
|
+
shown = ", ".join(remaining[:5]) + (" ..." if len(remaining) > 5 else "")
|
|
4857
|
+
print(f" [!] C3 entries remain in {settings_path} "
|
|
4858
|
+
f"({len(remaining)}): {shown}")
|
|
4859
|
+
else:
|
|
4860
|
+
print(f" Removed C3 hooks/settings from {settings_path} "
|
|
4861
|
+
f"({len(before)} entries)")
|
|
4692
4862
|
except Exception as e:
|
|
4693
4863
|
print(f" Warning: Could not update {settings_path}: {e}")
|
|
4694
4864
|
|
|
@@ -4872,6 +5042,44 @@ def _instruction_documents_for_project() -> list[tuple[str, str]]:
|
|
|
4872
5042
|
]
|
|
4873
5043
|
|
|
4874
5044
|
|
|
5045
|
+
def _remove_c3_instruction_docs(project_path: str) -> None:
|
|
5046
|
+
"""Take C3's managed block OUT of every instruction doc it ever wrote.
|
|
5047
|
+
|
|
5048
|
+
Uninstall counterpart of ``_sync_project_instruction_docs``. Before
|
|
5049
|
+
v2.92 this was a bare ``unlink()`` of CLAUDE.md / AGENTS.md / GEMINI.md —
|
|
5050
|
+
which, in a project whose CLAUDE.md also carried another tool's managed
|
|
5051
|
+
block (``<!-- YEP:BEGIN -->``) or the user's own notes, destroyed content
|
|
5052
|
+
C3 never owned, with no warning and no way back unless git had it.
|
|
5053
|
+
Same rule every regeneration path already follows: C3 owns its slice,
|
|
5054
|
+
everything outside the markers is preserved. A file is deleted only when
|
|
5055
|
+
the block was all there was.
|
|
5056
|
+
"""
|
|
5057
|
+
from services.claude_md import strip_c3_block
|
|
5058
|
+
|
|
5059
|
+
for filename, _ in _instruction_documents_for_project():
|
|
5060
|
+
p = Path(project_path) / filename
|
|
5061
|
+
if not p.exists():
|
|
5062
|
+
continue
|
|
5063
|
+
try:
|
|
5064
|
+
existing = p.read_text(encoding="utf-8", errors="replace")
|
|
5065
|
+
except OSError as exc:
|
|
5066
|
+
print(f" Warning: Could not read {filename}: {exc}")
|
|
5067
|
+
continue
|
|
5068
|
+
remainder = strip_c3_block(existing)
|
|
5069
|
+
if remainder is None:
|
|
5070
|
+
print(f" Kept {filename} (no C3 block in it — not ours to delete)")
|
|
5071
|
+
elif remainder.strip():
|
|
5072
|
+
try:
|
|
5073
|
+
p.write_text(remainder, encoding="utf-8")
|
|
5074
|
+
except OSError as exc:
|
|
5075
|
+
print(f" Warning: Could not update {filename}: {exc}")
|
|
5076
|
+
continue
|
|
5077
|
+
print(f" Removed C3 block from {filename} (kept the rest of the file)")
|
|
5078
|
+
else:
|
|
5079
|
+
p.unlink()
|
|
5080
|
+
print(f" Deleted {filename}")
|
|
5081
|
+
|
|
5082
|
+
|
|
4875
5083
|
_LEGACY_INSTRUCTION_DOCS = ("GEMINI.md",) # Gemini CLI profile removed in v2.52
|
|
4876
5084
|
|
|
4877
5085
|
|
|
@@ -7426,10 +7634,39 @@ def _oracle_open(args):
|
|
|
7426
7634
|
webbrowser.open(url)
|
|
7427
7635
|
|
|
7428
7636
|
|
|
7637
|
+
def _oracle_service_cmd(args):
|
|
7638
|
+
"""`c3 oracle serve --install | --uninstall | --status` — mirrors `c3 hub`."""
|
|
7639
|
+
from services.oracle_service import OracleService
|
|
7640
|
+
svc = OracleService()
|
|
7641
|
+
port = getattr(args, "port", None) or svc.default_port()
|
|
7642
|
+
|
|
7643
|
+
if getattr(args, "install", False):
|
|
7644
|
+
res = svc.install(port)
|
|
7645
|
+
print(res.get("output", "Service installed."))
|
|
7646
|
+
if res.get("success"):
|
|
7647
|
+
print(f"Oracle will start at login (no terminal window); log: {svc.LOG_FILE}")
|
|
7648
|
+
return
|
|
7649
|
+
if getattr(args, "uninstall", False):
|
|
7650
|
+
res = svc.uninstall()
|
|
7651
|
+
print(res.get("output", "Service uninstalled."))
|
|
7652
|
+
return
|
|
7653
|
+
res = svc.status()
|
|
7654
|
+
print(f"Oracle Service Status ({res.get('platform', 'unknown')}):")
|
|
7655
|
+
print(f" Installed: {res.get('installed')}")
|
|
7656
|
+
print(f" Running : {res.get('running')}")
|
|
7657
|
+
print(f" Port : {res.get('port')} (bind {res.get('bind_host')}, MCP {res.get('mcp_port')})")
|
|
7658
|
+
print(f" URL : {res.get('url')}")
|
|
7659
|
+
print(f" Method : {res.get('method')}")
|
|
7660
|
+
print(f" Log : {res.get('log_path')}")
|
|
7661
|
+
|
|
7662
|
+
|
|
7429
7663
|
def cmd_oracle(args):
|
|
7430
7664
|
"""Oracle dashboard server + Discovery API key management."""
|
|
7431
7665
|
sub = getattr(args, "oracle_cmd", None)
|
|
7432
7666
|
if sub in ("serve", "start"):
|
|
7667
|
+
if any(getattr(args, f, False) for f in ("install", "uninstall", "status")):
|
|
7668
|
+
_oracle_service_cmd(args)
|
|
7669
|
+
return
|
|
7433
7670
|
# Lazy import: run_oracle builds all Oracle services (matches
|
|
7434
7671
|
# cmd_hub's deferred-import style so bare `c3` stays fast).
|
|
7435
7672
|
from oracle.oracle_server import run_oracle
|
|
@@ -421,9 +421,9 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
421
421
|
cr_set.add_argument("--stdin", action="store_true", help="Read the value from stdin (piped/multiline values)")
|
|
422
422
|
cr_set.add_argument("--type", dest="ctype",
|
|
423
423
|
choices=["token", "env", "multiline",
|
|
424
|
-
"address", "identity", "card"],
|
|
424
|
+
"address", "identity", "card", "login"],
|
|
425
425
|
default="token",
|
|
426
|
-
help="Entry type; address/identity/card are structured "
|
|
426
|
+
help="Entry type; address/identity/card/login are structured "
|
|
427
427
|
"(field payload, inject-only, never revealable to the agent)")
|
|
428
428
|
cr_set.add_argument("--desc", default="", help="Human description shown in list/UI")
|
|
429
429
|
cr_set.add_argument("--env-var", default="", help="Env var name used at injection (default: entry name)")
|
|
@@ -824,6 +824,13 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
824
824
|
help="Server port (default: config 'port', 3331)")
|
|
825
825
|
or_serve.add_argument("--no-browser", action="store_true",
|
|
826
826
|
help="Don't open the browser")
|
|
827
|
+
or_serve.add_argument("--install", action="store_true",
|
|
828
|
+
help="Register the Oracle as a login/startup service "
|
|
829
|
+
"(no terminal window) and start it now")
|
|
830
|
+
or_serve.add_argument("--uninstall", action="store_true",
|
|
831
|
+
help="Remove the Oracle's startup service registration")
|
|
832
|
+
or_serve.add_argument("--status", action="store_true",
|
|
833
|
+
help="Show the Oracle's startup service status")
|
|
827
834
|
or_open = or_subs.add_parser(
|
|
828
835
|
"open",
|
|
829
836
|
help="Sign in to a running dashboard via a single-use URL",
|
|
@@ -297,12 +297,14 @@ c3_shell(cmd=<span class="str">'terraform apply'</span>, env_creds=<span class="
|
|
|
297
297
|
|
|
298
298
|
<!-- ═══════════════════════════════════ STRUCTURED ═══ -->
|
|
299
299
|
<section id="structured" class="tool-section">
|
|
300
|
-
<h2>Structured kinds — cards, addresses, identity (v2.87.0)</h2>
|
|
300
|
+
<h2>Structured kinds — cards, addresses, identity, logins (v2.87.0)</h2>
|
|
301
301
|
|
|
302
|
-
<p>
|
|
302
|
+
<p>Four entry types hold <strong>named fields</strong> instead of one opaque value:
|
|
303
303
|
<code>card</code> (cardholder, number, expiry, optional cvc/billing_zip — Luhn-checked),
|
|
304
|
-
<code>address</code> (street1, city, state, zip, optional recipient/street2/country/phone)
|
|
305
|
-
<code>identity</code> (full_name, optional dob/ssn/phone/email)
|
|
304
|
+
<code>address</code> (street1, city, state, zip, optional recipient/street2/country/phone),
|
|
305
|
+
<code>identity</code> (full_name, optional dob/ssn/phone/email) and
|
|
306
|
+
<code>login</code> (site_id, canonical_origin, username, password, optional totp_secret —
|
|
307
|
+
v2.90.0). The payload is stored as one
|
|
306
308
|
canonical JSON object through the same keyring / encrypted-sidecar path as any other value.</p>
|
|
307
309
|
|
|
308
310
|
<p>They are <strong>inject-only by construction</strong>, which is stricter than a normal secret:</p>
|
|
@@ -315,7 +317,10 @@ c3_shell(cmd=<span class="str">'terraform apply'</span>, env_creds=<span class="
|
|
|
315
317
|
the field list rather than expanding the whole payload.</li>
|
|
316
318
|
<li><strong>The registry shows a projection, not the data.</strong> Lists and the UI display
|
|
317
319
|
<code>visa ••••4242</code> for a card (brand + last4, deliberately <em>not</em> expiry),
|
|
318
|
-
city/state for an address, the name for an identity
|
|
320
|
+
city/state for an address, the name for an identity, and
|
|
321
|
+
<code>github · https://github.com · 2FA</code> for a login — site, origin and a 2FA
|
|
322
|
+
boolean, with the <em>username withheld on purpose</em>, because username + origin is
|
|
323
|
+
half the credential. Field <em>names</em> are public;
|
|
319
324
|
field <em>values</em> never transit any HTTP response — a sweep test enforces this.</li>
|
|
320
325
|
<li><strong>Echoes redact per field</strong> to <code>[cred:NAME.field]</code>. Caveat: the
|
|
321
326
|
redactor only tracks values of 4+ characters, so a 3-digit CVC or 2-letter state that a
|
|
@@ -333,6 +338,18 @@ c3_shell(cmd=<span class="str">'terraform apply'</span>, env_creds=<span class="
|
|
|
333
338
|
<code>c3 creds get NAME --show</code> (all fields) or <code>--show --field number</code> —
|
|
334
339
|
the browser and the mobile gateway never carry the values, and mobile cannot create
|
|
335
340
|
structured entries at all.</p>
|
|
341
|
+
|
|
342
|
+
<p><strong><code>login</code> is storage only, and that is a design constraint, not a
|
|
343
|
+
gap.</strong> C3 has no browser surface and must not grow one: a login runner in which the
|
|
344
|
+
<em>agent</em> picks the destination URL turns page-content prompt injection into credential
|
|
345
|
+
exfiltration, and a check written into a script that already holds the plaintext in its own
|
|
346
|
+
environment is not a boundary — the script can simply not call it. That is what
|
|
347
|
+
<code>canonical_origin</code> is for: https-only, stored normalized
|
|
348
|
+
(<code>scheme://host[:port]</code>, no path/query/fragment/userinfo, host lowercased), so a
|
|
349
|
+
separate <em>out-of-process</em> runner that the agent does not author can pin a credential to
|
|
350
|
+
exactly one origin and check the live top-level frame before typing. That runner is
|
|
351
|
+
deliberately not shipped in this package. <code>totp_secret</code> must be base32 — a
|
|
352
|
+
malformed seed produces wrong codes that look exactly like a wrong password.</p>
|
|
336
353
|
</section>
|
|
337
354
|
|
|
338
355
|
<hr class="divider">
|
|
@@ -168,9 +168,10 @@
|
|
|
168
168
|
<div class="step-grid">
|
|
169
169
|
<div class="step-card">
|
|
170
170
|
<span class="step-num">1</span><h4>Start the Oracle</h4>
|
|
171
|
-
<pre><code>
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
<pre><code>c3 oracle serve --no-browser
|
|
172
|
+
<span class="com"># or: run it at login, no terminal window</span>
|
|
173
|
+
c3 oracle serve --install</code></pre>
|
|
174
|
+
<p style="font-size: 12px; color: var(--text-dim); margin: 8px 0 0;">Prints the REST + MCP URLs and ensures an API key exists. The MCP server starts in a background thread. <code>--install</code> registers a windowless background service (Task Scheduler / launchd / systemd) and starts it now — the same buttons live in <strong>Hub → Settings → Oracle service</strong>.</p>
|
|
174
175
|
</div>
|
|
175
176
|
<div class="step-card">
|
|
176
177
|
<span class="step-num">2</span><h4>Get the token</h4>
|
|
@@ -325,8 +326,14 @@ curl -X POST \
|
|
|
325
326
|
<tr><td><code>c3 oracle api key</code></td> <td>Print just the token (generating one if needed)</td></tr>
|
|
326
327
|
<tr><td><code>c3 oracle api rotate</code></td> <td>Replace the token with a fresh one</td></tr>
|
|
327
328
|
<tr><td><code>c3 oracle api clear</code></td> <td>Delete the stored token from the keyring</td></tr>
|
|
329
|
+
<tr><td><code>c3 oracle serve</code></td> <td>Run the dashboard + discovery endpoints in this terminal (<code>--no-browser</code>, <code>--port</code>)</td></tr>
|
|
330
|
+
<tr><td><code>c3 oracle serve --install</code></td> <td>Register the Oracle as a login/startup service — no terminal window — and start it now. Windows: Task Scheduler (Run-key fallback); macOS: launchd; Linux: systemd user unit</td></tr>
|
|
331
|
+
<tr><td><code>c3 oracle serve --uninstall</code></td> <td>Remove the startup registration (a running Oracle keeps running)</td></tr>
|
|
332
|
+
<tr><td><code>c3 oracle serve --status</code></td> <td>Installed? Running? Port, bind host, URL, and the launcher log path</td></tr>
|
|
333
|
+
<tr><td><code>c3 oracle open</code></td> <td>Sign in to a running dashboard via a single-use URL (the hub's <strong>Open Oracle</strong> button does the same thing)</td></tr>
|
|
328
334
|
</tbody>
|
|
329
335
|
</table>
|
|
336
|
+
<p style="font-size: 12px; color: var(--text-dim); margin: 8px 0 0;">The Hub exposes the same controls under <strong>Settings → Oracle service</strong> (Install / Uninstall / Start / Stop / Open). Starting the Oracle from there also fills in the Hub's <em>Oracle URL</em> when it is empty, so the Open Oracle button appears in the top bar. That button opens a <strong>signed-in</strong> dashboard: it redeems the Oracle's owner-only bootstrap key for you. Reaching the dashboard by pasting its URL instead leaves it read-only — the page renders and the header looks healthy, but chat, Save and Test Ollama answer <code>401 unauthorized</code>.</p>
|
|
330
337
|
</section>
|
|
331
338
|
|
|
332
339
|
<hr class="divider">
|
|
@@ -373,6 +380,14 @@ curl -X POST \
|
|
|
373
380
|
<td><code>The 'keyring' package is required</code></td>
|
|
374
381
|
<td><code>pip install keyring</code> — a C3 dependency that may be missing if you upgraded without re-installing.</td>
|
|
375
382
|
</tr>
|
|
383
|
+
<tr>
|
|
384
|
+
<td>Oracle is down after a reboot</td>
|
|
385
|
+
<td>Nothing restarts a terminal-launched Oracle. Register it once with <code>c3 oracle serve --install</code> (or Hub → Settings → Oracle service → Install); it then starts at login with no window. Startup problems land in <code>~/.c3/oracle/service.log</code> (the launcher) and <code>~/.c3/oracle/oracle.log</code> (the server).</td>
|
|
386
|
+
</tr>
|
|
387
|
+
<tr>
|
|
388
|
+
<td>Installed, but "stopped" right after login</td>
|
|
389
|
+
<td>If <code>bind_host</code> is a LAN/VPN address, the launcher waits up to 120 s for that address to come up before binding, and Task Scheduler retries a failed start three times a minute apart. Check <code>service.log</code> for <em>waiting for bind host</em>; if the address never appears, the Oracle starts anyway and fails to bind — fix the interface or set <code>bind_host</code> to <code>0.0.0.0</code>.</td>
|
|
390
|
+
</tr>
|
|
376
391
|
</tbody>
|
|
377
392
|
</table>
|
|
378
393
|
</section>
|