code-context-control 2.49.1__tar.gz → 2.50.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.49.1/code_context_control.egg-info → code_context_control-2.50.0}/PKG-INFO +10 -1
- {code_context_control-2.49.1 → code_context_control-2.50.0}/README.md +8 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/commands/parser.py +5 -1
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/guide/bitbucket.html +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/guide/getting-started.html +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/guide/index.html +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/guide/oracle.html +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/guide/tools.html +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/guide/workflow.html +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/topbar.js +3 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/edit.py +118 -6
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/read.py +22 -4
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/app.js +9 -1
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/icons.js +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0/code_context_control.egg-info}/PKG-INFO +10 -1
- {code_context_control-2.49.1 → code_context_control-2.50.0}/code_context_control.egg-info/SOURCES.txt +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/oracle_ui.html +1 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/pyproject.toml +2 -1
- code_context_control-2.50.0/tests/test_read_edit_parity.py +208 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/main.py +5 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/LICENSE +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/_hook_utils.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/c3.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/commands/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/commands/common.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/docs.html +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/edits.html +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/guide/shared.css +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_artifact.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_c3read.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_filter.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_read.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub.html +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_server.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/hub_ui.html +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/mcp_server.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/server.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/agent.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/compress.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/delegate.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/edits.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/federate.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/filter.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/impact.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/memory.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/project.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/search.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/session.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/shell.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/status.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/tasks.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/tools/validate.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/api.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/shared.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui/theme.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui.html +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui_legacy.html +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/cli/ui_nano.html +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/core/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/core/config.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/core/ide.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/core/mcp_toml.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/core/web_security.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/config.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/oracle_server.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/local_session.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/ollama_bridge.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/activity.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/agents.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/app.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/busy.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/core.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/header.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/insights.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/projects.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/settings.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/activity_log.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/agent_base.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/agents.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/artifact_defs.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/artifact_store.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/auto_memory.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/bench/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/bitbucket_client.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/circuit_breaker.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/claude_md.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/compressor.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/context_snapshot.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/conversation_store.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/doc_index.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/e2e_tasks.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/edit_ledger.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/embedding_index.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/error_reporting.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/file_memory.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/git_context.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/hub_service.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/indexer.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/memory.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/memory_consolidator.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/memory_graph.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/memory_grounder.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/memory_scorer.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/metrics.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/notifications.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/ollama_client.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/output_filter.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/parser.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/project_manager.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/project_runtime.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/protocol.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/proxy_state.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/retention.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/retrieval_broker.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/router.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/runtime.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/session_benchmark.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/session_manager.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/session_preloader.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/subprojects.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/task_store.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/telemetry.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/text_index.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/tool_classifier.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/transcript_index.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/validation_cache.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/vector_store.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/watcher.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/services/win_subprocess.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/setup.cfg +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_hook_state.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_memory_system.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_output_filter.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_permissions.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_pm_api.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_project_manager.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_project_tool.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_retention.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_review_digest.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_service_durability.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_session_budget.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_subprojects.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_task_store.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_task_tool.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_validate.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_web_security.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/backend.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/__init__.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/index_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/init_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/search_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/session_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/stats.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.49.1 → code_context_control-2.50.0}/tui/theme.tcss +0 -0
{code_context_control-2.49.1/code_context_control.egg-info → code_context_control-2.50.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.50.0
|
|
4
4
|
Summary: Local code-intelligence layer for AI coding tools (Claude Code, Codex, Gemini, Copilot). Retrieve less, read less, edit safer — and version the configs that shape your agent (CLAUDE.md, skills, hooks, MCP).
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -9,6 +9,7 @@ Project-URL: Documentation, https://github.com/drknowhow/code-context-control#re
|
|
|
9
9
|
Project-URL: Repository, https://github.com/drknowhow/code-context-control
|
|
10
10
|
Project-URL: Changelog, https://github.com/drknowhow/code-context-control/blob/main/CHANGELOG.md
|
|
11
11
|
Project-URL: Issues, https://github.com/drknowhow/code-context-control/issues
|
|
12
|
+
Project-URL: Funding, https://github.com/sponsors/drknowhow
|
|
12
13
|
Keywords: claude,claude-code,mcp,ai,code-intelligence,code-context,developer-tools,llm-tools
|
|
13
14
|
Classifier: Development Status :: 4 - Beta
|
|
14
15
|
Classifier: Intended Audience :: Developers
|
|
@@ -74,6 +75,7 @@ Dynamic: license-file
|
|
|
74
75
|
<img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10%2B-blue.svg">
|
|
75
76
|
<img alt="Platforms" src="https://img.shields.io/badge/platform-windows%20%7C%20macos%20%7C%20linux-lightgrey">
|
|
76
77
|
<img alt="Status: Beta" src="https://img.shields.io/badge/status-beta-yellow">
|
|
78
|
+
<a href="https://github.com/sponsors/drknowhow"><img alt="Sponsor" src="https://img.shields.io/badge/sponsor-%E2%9D%A4-EA4AAA?logo=githubsponsors&logoColor=white"></a>
|
|
77
79
|
</p>
|
|
78
80
|
|
|
79
81
|
<p align="center">
|
|
@@ -423,6 +425,12 @@ Reports include token deltas, cost deltas, win rates, tool-usage analysis, and p
|
|
|
423
425
|
|
|
424
426
|
---
|
|
425
427
|
|
|
428
|
+
## Support C3
|
|
429
|
+
|
|
430
|
+
C3 is free, open source, and built by one person. If it saves you tokens (it should — that's the whole point), consider [sponsoring on GitHub](https://github.com/sponsors/drknowhow). Sponsorship directly funds API costs for cross-model test runs and dedicated development time.
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
426
434
|
## License
|
|
427
435
|
|
|
428
436
|
- **Current OSS license** — Apache License 2.0 ([`LICENSE`](LICENSE)). Free for any use, including commercial. Modify, fork, redistribute — all permitted under Apache-2.0 terms.
|
|
@@ -440,3 +448,4 @@ The author may introduce a paid offering or relicense future major versions; no
|
|
|
440
448
|
- **Security policy:** [`SECURITY.md`](SECURITY.md)
|
|
441
449
|
- **Licensing FAQ:** [`LICENSING.md`](LICENSING.md)
|
|
442
450
|
- **Issues:** https://github.com/drknowhow/code-context-control/issues
|
|
451
|
+
- **Sponsor:** https://github.com/sponsors/drknowhow
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
<img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10%2B-blue.svg">
|
|
13
13
|
<img alt="Platforms" src="https://img.shields.io/badge/platform-windows%20%7C%20macos%20%7C%20linux-lightgrey">
|
|
14
14
|
<img alt="Status: Beta" src="https://img.shields.io/badge/status-beta-yellow">
|
|
15
|
+
<a href="https://github.com/sponsors/drknowhow"><img alt="Sponsor" src="https://img.shields.io/badge/sponsor-%E2%9D%A4-EA4AAA?logo=githubsponsors&logoColor=white"></a>
|
|
15
16
|
</p>
|
|
16
17
|
|
|
17
18
|
<p align="center">
|
|
@@ -361,6 +362,12 @@ Reports include token deltas, cost deltas, win rates, tool-usage analysis, and p
|
|
|
361
362
|
|
|
362
363
|
---
|
|
363
364
|
|
|
365
|
+
## Support C3
|
|
366
|
+
|
|
367
|
+
C3 is free, open source, and built by one person. If it saves you tokens (it should — that's the whole point), consider [sponsoring on GitHub](https://github.com/sponsors/drknowhow). Sponsorship directly funds API costs for cross-model test runs and dedicated development time.
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
364
371
|
## License
|
|
365
372
|
|
|
366
373
|
- **Current OSS license** — Apache License 2.0 ([`LICENSE`](LICENSE)). Free for any use, including commercial. Modify, fork, redistribute — all permitted under Apache-2.0 terms.
|
|
@@ -378,3 +385,4 @@ The author may introduce a paid offering or relicense future major versions; no
|
|
|
378
385
|
- **Security policy:** [`SECURITY.md`](SECURITY.md)
|
|
379
386
|
- **Licensing FAQ:** [`LICENSING.md`](LICENSING.md)
|
|
380
387
|
- **Issues:** https://github.com/drknowhow/code-context-control/issues
|
|
388
|
+
- **Sponsor:** https://github.com/sponsors/drknowhow
|
|
@@ -9,8 +9,12 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
9
9
|
parser = argparse.ArgumentParser(
|
|
10
10
|
prog="c3",
|
|
11
11
|
description="Claude Code Companion - Reduce token usage with local intelligence",
|
|
12
|
+
epilog="Support C3 development: https://github.com/sponsors/drknowhow",
|
|
13
|
+
)
|
|
14
|
+
parser.add_argument(
|
|
15
|
+
"--version", "-v", action="version",
|
|
16
|
+
version=f"c3 version {version} | support C3: https://github.com/sponsors/drknowhow",
|
|
12
17
|
)
|
|
13
|
-
parser.add_argument("--version", "-v", action="version", version=f"c3 version {version}")
|
|
14
18
|
subparsers = parser.add_subparsers(dest="command")
|
|
15
19
|
|
|
16
20
|
p_init = subparsers.add_parser("init", help="Initialize C3 for a project")
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
<a href="tools.html">Tools</a>
|
|
80
80
|
<a href="bitbucket.html" class="active">Bitbucket</a>
|
|
81
81
|
<a href="oracle.html">Oracle</a>
|
|
82
|
+
<a href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" style="color:#EA4AAA">♥ Sponsor</a>
|
|
82
83
|
</nav>
|
|
83
84
|
<span class="header-version">v2.30.0</span>
|
|
84
85
|
</header>
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<a href="tools.html">Tools</a>
|
|
23
23
|
<a href="bitbucket.html">Bitbucket</a>
|
|
24
24
|
<a href="oracle.html">Oracle</a>
|
|
25
|
+
<a href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" style="color:#EA4AAA">♥ Sponsor</a>
|
|
25
26
|
</nav>
|
|
26
27
|
<span class="header-version">v2.x</span>
|
|
27
28
|
</header>
|
|
@@ -224,6 +224,7 @@
|
|
|
224
224
|
<a href="tools.html">Tools</a>
|
|
225
225
|
<a href="bitbucket.html">Bitbucket</a>
|
|
226
226
|
<a href="oracle.html">Oracle</a>
|
|
227
|
+
<a href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" style="color:#EA4AAA">♥ Sponsor</a>
|
|
227
228
|
</nav>
|
|
228
229
|
<span class="header-version">v2.x</span>
|
|
229
230
|
</header>
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
<a href="tools.html">Tools</a>
|
|
78
78
|
<a href="bitbucket.html">Bitbucket</a>
|
|
79
79
|
<a href="oracle.html" class="active">Oracle</a>
|
|
80
|
+
<a href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" style="color:#EA4AAA">♥ Sponsor</a>
|
|
80
81
|
</nav>
|
|
81
82
|
<span class="header-version">v2.32.0</span>
|
|
82
83
|
</header>
|
|
@@ -81,6 +81,7 @@
|
|
|
81
81
|
<a href="tools.html" class="active">Tools</a>
|
|
82
82
|
<a href="bitbucket.html">Bitbucket</a>
|
|
83
83
|
<a href="oracle.html">Oracle</a>
|
|
84
|
+
<a href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" style="color:#EA4AAA">♥ Sponsor</a>
|
|
84
85
|
</nav>
|
|
85
86
|
<span class="header-version">v2.x</span>
|
|
86
87
|
</header>
|
|
@@ -224,6 +224,7 @@
|
|
|
224
224
|
<a href="tools.html">Tools</a>
|
|
225
225
|
<a href="bitbucket.html">Bitbucket</a>
|
|
226
226
|
<a href="oracle.html">Oracle</a>
|
|
227
|
+
<a href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" style="color:#EA4AAA">♥ Sponsor</a>
|
|
227
228
|
</nav>
|
|
228
229
|
<span class="header-version">v2.x</span>
|
|
229
230
|
</header>
|
|
@@ -64,6 +64,9 @@ function TopBar({ version, activeCount, darkMode, hubConfig, mainView, setMainVi
|
|
|
64
64
|
<a href="/guide/" target="_blank" rel="noopener" title="Open the C3 guide" style={ctrl}>
|
|
65
65
|
<I name="fileText" size={13} color={T.textMuted} />
|
|
66
66
|
</a>
|
|
67
|
+
<a href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" title="Sponsor C3 development" style={ctrl}>
|
|
68
|
+
<I name="heart" size={13} color="#EA4AAA" />
|
|
69
|
+
</a>
|
|
67
70
|
{hubConfig && hubConfig.oracle_url && (
|
|
68
71
|
<a href={hubConfig.oracle_url} target="_blank" rel="noopener" title="Open Oracle" style={ctrl}>
|
|
69
72
|
<I name="external" size={13} color={T.textMuted} />
|
|
@@ -8,6 +8,7 @@ Parallel safety:
|
|
|
8
8
|
- Same file: serialized via per-file threading.Lock (_file_locks).
|
|
9
9
|
- Same file, multiple hunks: use the `edits` batch parameter — one read/write cycle.
|
|
10
10
|
"""
|
|
11
|
+
import difflib
|
|
11
12
|
import json
|
|
12
13
|
import threading
|
|
13
14
|
from pathlib import Path
|
|
@@ -33,12 +34,16 @@ def _read_preserving_newlines(path: Path) -> tuple[str, str]:
|
|
|
33
34
|
`newline` is the EOL to write back: ``\r\n`` if CRLF dominates the
|
|
34
35
|
file, otherwise ``\n``. This avoids Python's text-mode write rewriting
|
|
35
36
|
every line to ``os.linesep`` on Windows.
|
|
37
|
+
|
|
38
|
+
Decodes with errors="surrogateescape" so files containing non-UTF-8
|
|
39
|
+
bytes are still editable: invalid bytes round-trip losslessly through
|
|
40
|
+
_write_preserving_newlines instead of raising UnicodeDecodeError.
|
|
36
41
|
"""
|
|
37
42
|
raw = path.read_bytes()
|
|
38
43
|
crlf = raw.count(b"\r\n")
|
|
39
44
|
lf_only = raw.count(b"\n") - crlf
|
|
40
45
|
newline = "\r\n" if crlf > lf_only else "\n"
|
|
41
|
-
content = raw.decode("utf-8")
|
|
46
|
+
content = raw.decode("utf-8", errors="surrogateescape")
|
|
42
47
|
# Normalize to \n internally so replacement matching is EOL-agnostic.
|
|
43
48
|
content = content.replace("\r\n", "\n").replace("\r", "\n")
|
|
44
49
|
return content, newline
|
|
@@ -52,7 +57,8 @@ def _write_preserving_newlines(path: Path, content: str, newline: str) -> None:
|
|
|
52
57
|
"""
|
|
53
58
|
if newline != "\n":
|
|
54
59
|
content = content.replace("\n", newline)
|
|
55
|
-
with open(path, "w", encoding="utf-8",
|
|
60
|
+
with open(path, "w", encoding="utf-8", errors="surrogateescape",
|
|
61
|
+
newline="") as fh:
|
|
56
62
|
fh.write(content)
|
|
57
63
|
|
|
58
64
|
|
|
@@ -66,9 +72,23 @@ _LOOKALIKE_TRANS = str.maketrans({
|
|
|
66
72
|
"′": "'", "″": '"', # prime / double prime
|
|
67
73
|
"‐": "-", "‑": "-", "‒": "-", "–": "-", # hyphen / dashes
|
|
68
74
|
"—": "-", "―": "-", "−": "-",
|
|
69
|
-
"
|
|
75
|
+
"\u00a0": " ", "\u2007": " ", "\u202f": " ", # non-breaking / figure / narrow-nbsp
|
|
70
76
|
})
|
|
71
77
|
|
|
78
|
+
# Bytes that aren't valid UTF-8 decode to lone surrogates U+DC80-U+DCFF under
|
|
79
|
+
# errors="surrogateescape" (how _read_preserving_newlines reads files), while
|
|
80
|
+
# c3_read renders those same bytes as U+FFFD (errors="replace"). Fold both to
|
|
81
|
+
# U+FFFD — 1:1 like the lookalikes — so an old_string copied from c3_read
|
|
82
|
+
# output still matches file content around undecodable bytes.
|
|
83
|
+
_SURROGATE_TRANS = {c: "\ufffd" for c in range(0xDC80, 0xDD00)}
|
|
84
|
+
_LOOKALIKE_TRANS.update(_SURROGATE_TRANS)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _display_safe(s: str) -> str:
|
|
88
|
+
"""Fold surrogateescape'd bytes to U+FFFD for error-message display —
|
|
89
|
+
lone surrogates cannot be encoded for MCP transport."""
|
|
90
|
+
return s.translate(_SURROGATE_TRANS) if s else s
|
|
91
|
+
|
|
72
92
|
|
|
73
93
|
def _norm(s: str) -> str:
|
|
74
94
|
return s.translate(_LOOKALIKE_TRANS) if s else s
|
|
@@ -125,6 +145,81 @@ def _apply_replacement(content: str, old: str, new: str, replace_all: bool):
|
|
|
125
145
|
return (_positional_replace(content, nc, no, new, replace_all), count, True)
|
|
126
146
|
|
|
127
147
|
|
|
148
|
+
def _closest_region(content: str, old: str,
|
|
149
|
+
max_scan_lines: int = 40000, context: int = 2):
|
|
150
|
+
"""Locate the file region most similar to a failed old_string.
|
|
151
|
+
|
|
152
|
+
Returns (start_line, end_line, region_text, ratio) — 1-based inclusive
|
|
153
|
+
line numbers, region padded with `context` lines each side — or None when
|
|
154
|
+
no region clears the similarity floor. Powers the 'closest match' payload
|
|
155
|
+
in not-found errors so a mismatched edit can be repaired without
|
|
156
|
+
re-reading the file (the moment agents historically drifted back to
|
|
157
|
+
native Read).
|
|
158
|
+
"""
|
|
159
|
+
file_lines = content.split("\n")
|
|
160
|
+
old_lines = old.split("\n")
|
|
161
|
+
n, total = len(old_lines), len(file_lines)
|
|
162
|
+
if not old.strip() or total > max_scan_lines:
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
# Anchor on old_string's most distinctive line, shortlist file lines that
|
|
166
|
+
# resemble it (cheap quick_ratio pass), then score full windows aligned
|
|
167
|
+
# to each shortlisted line (expensive ratio, capped at 8 candidates).
|
|
168
|
+
anchor_off, anchor_line = max(enumerate(old_lines),
|
|
169
|
+
key=lambda p: len(p[1].strip()))
|
|
170
|
+
anchor = anchor_line.strip()
|
|
171
|
+
sm = difflib.SequenceMatcher(autojunk=False)
|
|
172
|
+
sm.set_seq2(anchor)
|
|
173
|
+
scored = []
|
|
174
|
+
for i, line in enumerate(file_lines):
|
|
175
|
+
sm.set_seq1(line.strip())
|
|
176
|
+
if sm.real_quick_ratio() < 0.6:
|
|
177
|
+
continue
|
|
178
|
+
q = sm.quick_ratio()
|
|
179
|
+
if q >= 0.6:
|
|
180
|
+
scored.append((q, i))
|
|
181
|
+
if not scored:
|
|
182
|
+
return None
|
|
183
|
+
scored.sort(key=lambda t: -t[0])
|
|
184
|
+
|
|
185
|
+
win = difflib.SequenceMatcher(autojunk=False)
|
|
186
|
+
win.set_seq2(old)
|
|
187
|
+
best_ratio, best_start = 0.0, None
|
|
188
|
+
for _, i in scored[:8]:
|
|
189
|
+
start = max(0, min(i - anchor_off, total - n))
|
|
190
|
+
win.set_seq1("\n".join(file_lines[start:start + n]))
|
|
191
|
+
r = win.ratio()
|
|
192
|
+
if r > best_ratio:
|
|
193
|
+
best_ratio, best_start = r, start
|
|
194
|
+
if best_start is None or best_ratio < 0.5:
|
|
195
|
+
return None
|
|
196
|
+
lo = max(0, best_start - context)
|
|
197
|
+
hi = min(total, best_start + n + context)
|
|
198
|
+
return lo + 1, hi, "\n".join(file_lines[lo:hi]), best_ratio
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
_REGION_CAP = 4000
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _not_found_payload(near, file_label: str) -> str:
|
|
205
|
+
"""Render a _closest_region result as an error-message appendix. The
|
|
206
|
+
region text is emitted verbatim (no indentation) so it can be copied
|
|
207
|
+
straight into a retry old_string."""
|
|
208
|
+
if not near:
|
|
209
|
+
return ""
|
|
210
|
+
lo, hi, region, ratio = near
|
|
211
|
+
region = _display_safe(region)
|
|
212
|
+
if len(region) > _REGION_CAP:
|
|
213
|
+
region = (region[:_REGION_CAP]
|
|
214
|
+
+ f"\n⟦trimmed — run c3_read(file_path='{file_label}', "
|
|
215
|
+
f"lines=[{lo},{hi}]) for the rest⟧")
|
|
216
|
+
return (f"\n closest match: L{lo}-L{hi} ({ratio:.0%} similar). "
|
|
217
|
+
f"Actual file text between the markers:\n"
|
|
218
|
+
f"⟦L{lo}-L{hi}⟧\n{region}\n⟦end⟧\n"
|
|
219
|
+
f" Retry with old_string copied exactly from the text above "
|
|
220
|
+
f"(markers excluded) — no need to re-read the file.")
|
|
221
|
+
|
|
222
|
+
|
|
128
223
|
def handle_edit(file_path: str, old_string: str, new_string: str,
|
|
129
224
|
summary: str, tags: str, replace_all: bool,
|
|
130
225
|
svc, finalize, edits: str = "") -> str:
|
|
@@ -209,8 +304,10 @@ def handle_edit(file_path: str, old_string: str, new_string: str,
|
|
|
209
304
|
f"Read error: {e}", "read error")
|
|
210
305
|
|
|
211
306
|
results = []
|
|
307
|
+
statuses = [] # parallel to results: 'ok' | 'miss' | 'ambiguous' | 'skipped'
|
|
212
308
|
any_normalized = False
|
|
213
309
|
any_applied = False
|
|
310
|
+
first_miss = ""
|
|
214
311
|
for i, patch in enumerate(edit_list):
|
|
215
312
|
old = patch.get("old_string", "")
|
|
216
313
|
new = patch.get("new_string", "")
|
|
@@ -219,15 +316,23 @@ def handle_edit(file_path: str, old_string: str, new_string: str,
|
|
|
219
316
|
|
|
220
317
|
if not old:
|
|
221
318
|
results.append(f" patch[{i}]: skipped — empty old_string")
|
|
319
|
+
statuses.append("skipped")
|
|
222
320
|
continue
|
|
223
321
|
|
|
224
322
|
new_content, count, used_fallback = _apply_replacement(content, old, new, r_all)
|
|
225
323
|
if new_content is None and count == 0:
|
|
226
|
-
|
|
324
|
+
near = _closest_region(content, old)
|
|
325
|
+
loc = (f" (closest: L{near[0]}-L{near[1]}, {near[3]:.0%} similar)"
|
|
326
|
+
if near else "")
|
|
327
|
+
results.append(f" patch[{i}]: NOT FOUND — {old[:80]!r}{loc}")
|
|
328
|
+
statuses.append("miss")
|
|
329
|
+
if near and not first_miss:
|
|
330
|
+
first_miss = _not_found_payload(near, file_path)
|
|
227
331
|
continue
|
|
228
332
|
if new_content is None:
|
|
229
333
|
tag = " (unicode-normalized)" if used_fallback else ""
|
|
230
334
|
results.append(f" patch[{i}]: AMBIGUOUS ({count} matches){tag} — {old[:60]!r}")
|
|
335
|
+
statuses.append("ambiguous")
|
|
231
336
|
continue
|
|
232
337
|
|
|
233
338
|
content = new_content
|
|
@@ -243,6 +348,7 @@ def handle_edit(file_path: str, old_string: str, new_string: str,
|
|
|
243
348
|
+ (f" ({n}x)" if n > 1 else "")
|
|
244
349
|
+ (" [norm]" if used_fallback else "")
|
|
245
350
|
+ f" | {desc}")
|
|
351
|
+
statuses.append("ok")
|
|
246
352
|
|
|
247
353
|
# Only touch the file when at least one patch actually changed it —
|
|
248
354
|
# avoids rewriting (and re-EOL-normalizing) an unchanged file and
|
|
@@ -266,12 +372,17 @@ def handle_edit(file_path: str, old_string: str, new_string: str,
|
|
|
266
372
|
]}
|
|
267
373
|
_log_to_ledger(rel, summary or f"Batch edit: {len(edit_list)} patches", tag_list, svc, detail=batch_detail)
|
|
268
374
|
|
|
269
|
-
|
|
375
|
+
# Classify from the structured status list, not by substring-scanning
|
|
376
|
+
# the human-readable result lines — a patch *summary* containing words
|
|
377
|
+
# like 'NOT FOUND' used to be miscounted as a failure.
|
|
378
|
+
applied = statuses.count("ok")
|
|
270
379
|
norm_tag = " [unicode-normalized]" if any_normalized else ""
|
|
271
380
|
short = f"✓ {rel} — {applied}/{len(edit_list)} patches applied{norm_tag}"
|
|
272
381
|
if applied < len(edit_list):
|
|
273
|
-
failed = [r for r in results if
|
|
382
|
+
failed = [r for r, s in zip(results, statuses) if s != "ok"]
|
|
274
383
|
short += "\n" + "\n".join(failed)
|
|
384
|
+
if first_miss:
|
|
385
|
+
short += first_miss
|
|
275
386
|
return finalize("c3_edit", {"file": file_path}, short,
|
|
276
387
|
f"{rel} patched ({len(edit_list)} patches)")
|
|
277
388
|
|
|
@@ -293,6 +404,7 @@ def handle_edit(file_path: str, old_string: str, new_string: str,
|
|
|
293
404
|
hint = ""
|
|
294
405
|
if _norm(old_string) != old_string or _norm(content) != content:
|
|
295
406
|
hint = "\n hint: unicode-lookalike normalization also failed to match."
|
|
407
|
+
hint += _not_found_payload(_closest_region(content, old_string), file_path)
|
|
296
408
|
return finalize("c3_edit", {"file": file_path},
|
|
297
409
|
f"old_string not found in {file_path}\n"
|
|
298
410
|
f" searched for: {old_string[:120]!r}{hint}",
|
|
@@ -172,7 +172,14 @@ def handle_read(file_path: str, symbols: Any = None, lines: Any = None,
|
|
|
172
172
|
pass
|
|
173
173
|
|
|
174
174
|
raw_text = full.read_text(encoding="utf-8", errors="replace")
|
|
175
|
-
|
|
175
|
+
# EOL-normalize exactly the way c3_edit's matcher does (\r\n and \r → \n),
|
|
176
|
+
# then split on \n ONLY. splitlines() also breaks on \x0c/\u2028/\x85 etc.,
|
|
177
|
+
# which rendered those in-line chars as line breaks — an old_string copied
|
|
178
|
+
# from that output (with \n) could never match the actual file bytes.
|
|
179
|
+
raw_text = raw_text.replace("\r\n", "\n").replace("\r", "\n")
|
|
180
|
+
content_lines = raw_text.split("\n")
|
|
181
|
+
if content_lines and content_lines[-1] == "":
|
|
182
|
+
content_lines.pop() # trailing \n would otherwise add a phantom empty line
|
|
176
183
|
# Lazy: only count full file tokens when needed for the summary string
|
|
177
184
|
_full_tok_cache = [None]
|
|
178
185
|
|
|
@@ -254,8 +261,9 @@ def handle_read(file_path: str, symbols: Any = None, lines: Any = None,
|
|
|
254
261
|
|
|
255
262
|
if not ranges:
|
|
256
263
|
file_map = svc.file_memory.get_or_build_map(rel_path)
|
|
257
|
-
|
|
258
|
-
|
|
264
|
+
resp = (file_map
|
|
265
|
+
+ "\n[map only — pass lines=[start,end] or symbols=[...] for exact source]")
|
|
266
|
+
map_tok = count_tokens(resp)
|
|
259
267
|
return finalize_with_tokens(
|
|
260
268
|
finalize, svc, "c3_read", {"file": file_path},
|
|
261
269
|
resp, f"{full_file_tokens()}->{map_tok}tok",
|
|
@@ -278,13 +286,23 @@ def handle_read(file_path: str, symbols: Any = None, lines: Any = None,
|
|
|
278
286
|
header = f"[read:{file_path}]"
|
|
279
287
|
|
|
280
288
|
parts = []
|
|
289
|
+
prev_end = None
|
|
281
290
|
for start, end in ranges:
|
|
282
291
|
s_idx = max(0, start - 1)
|
|
283
292
|
e_idx = min(len(content_lines), end)
|
|
284
293
|
chunk = content_lines[s_idx:e_idx]
|
|
285
294
|
if len(ranges) > 1:
|
|
286
|
-
|
|
295
|
+
# ⟦…⟧ markers are tool chrome, not file content. The gap note makes
|
|
296
|
+
# the discontinuity explicit so a copied old_string never spans it.
|
|
297
|
+
if prev_end is None:
|
|
298
|
+
parts.append(f"⟦L{start}-L{end}⟧")
|
|
299
|
+
else:
|
|
300
|
+
parts.append(
|
|
301
|
+
f"⟦L{start}-L{end} — {start - prev_end - 1} lines "
|
|
302
|
+
f"(L{prev_end + 1}-L{start - 1}) omitted; blocks are NOT "
|
|
303
|
+
f"contiguous, never span this marker in a c3_edit old_string⟧")
|
|
287
304
|
parts.extend(chunk)
|
|
305
|
+
prev_end = end
|
|
288
306
|
|
|
289
307
|
final_content = "\n".join(parts)
|
|
290
308
|
tokens = count_tokens(final_content)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ─── Main App ─────────────────────────────
|
|
2
|
-
const BUILD_TIME = "2026-
|
|
2
|
+
const BUILD_TIME = "2026-07-02 UI-v2";
|
|
3
3
|
const { useState, useEffect, useCallback, useRef } = React;
|
|
4
4
|
|
|
5
5
|
const tabs = [
|
|
@@ -191,6 +191,14 @@ function App() {
|
|
|
191
191
|
}}>
|
|
192
192
|
Ledger
|
|
193
193
|
</a>
|
|
194
|
+
<a href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" title="Sponsor C3 development"
|
|
195
|
+
style={{
|
|
196
|
+
width: 28, height: 28, borderRadius: 6, border: "1px solid #EA4AAA40",
|
|
197
|
+
background: "#EA4AAA12", textDecoration: "none", display: "flex",
|
|
198
|
+
alignItems: "center", justifyContent: "center"
|
|
199
|
+
}}>
|
|
200
|
+
<I name="heart" size={13} color="#EA4AAA" />
|
|
201
|
+
</a>
|
|
194
202
|
<button onClick={() => setDarkMode(!darkMode)} title="Toggle theme"
|
|
195
203
|
style={{
|
|
196
204
|
width: 28, height: 28, borderRadius: 6, border: `1px solid ${T.border}`,
|
|
@@ -18,6 +18,7 @@ const icons = {
|
|
|
18
18
|
refresh: "M1 4v6h6M23 20v-6h-6M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15",
|
|
19
19
|
copy: "M20 9h-9a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2zM5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1",
|
|
20
20
|
check: "M20 6L9 17l-5-5",
|
|
21
|
+
heart: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z",
|
|
21
22
|
layers: "M12 2l10 6.5v7L12 22 2 15.5v-7zM12 22v-7M22 8.5l-10 7-10-7",
|
|
22
23
|
brain: "M12 2a7 7 0 0 0-7 7c0 3 2 5.5 5 7v4h4v-4c3-1.5 5-4 5-7a7 7 0 0 0-7-7z",
|
|
23
24
|
chevron: "M9 18l6-6-6-6",
|
{code_context_control-2.49.1 → code_context_control-2.50.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.50.0
|
|
4
4
|
Summary: Local code-intelligence layer for AI coding tools (Claude Code, Codex, Gemini, Copilot). Retrieve less, read less, edit safer — and version the configs that shape your agent (CLAUDE.md, skills, hooks, MCP).
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -9,6 +9,7 @@ Project-URL: Documentation, https://github.com/drknowhow/code-context-control#re
|
|
|
9
9
|
Project-URL: Repository, https://github.com/drknowhow/code-context-control
|
|
10
10
|
Project-URL: Changelog, https://github.com/drknowhow/code-context-control/blob/main/CHANGELOG.md
|
|
11
11
|
Project-URL: Issues, https://github.com/drknowhow/code-context-control/issues
|
|
12
|
+
Project-URL: Funding, https://github.com/sponsors/drknowhow
|
|
12
13
|
Keywords: claude,claude-code,mcp,ai,code-intelligence,code-context,developer-tools,llm-tools
|
|
13
14
|
Classifier: Development Status :: 4 - Beta
|
|
14
15
|
Classifier: Intended Audience :: Developers
|
|
@@ -74,6 +75,7 @@ Dynamic: license-file
|
|
|
74
75
|
<img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10%2B-blue.svg">
|
|
75
76
|
<img alt="Platforms" src="https://img.shields.io/badge/platform-windows%20%7C%20macos%20%7C%20linux-lightgrey">
|
|
76
77
|
<img alt="Status: Beta" src="https://img.shields.io/badge/status-beta-yellow">
|
|
78
|
+
<a href="https://github.com/sponsors/drknowhow"><img alt="Sponsor" src="https://img.shields.io/badge/sponsor-%E2%9D%A4-EA4AAA?logo=githubsponsors&logoColor=white"></a>
|
|
77
79
|
</p>
|
|
78
80
|
|
|
79
81
|
<p align="center">
|
|
@@ -423,6 +425,12 @@ Reports include token deltas, cost deltas, win rates, tool-usage analysis, and p
|
|
|
423
425
|
|
|
424
426
|
---
|
|
425
427
|
|
|
428
|
+
## Support C3
|
|
429
|
+
|
|
430
|
+
C3 is free, open source, and built by one person. If it saves you tokens (it should — that's the whole point), consider [sponsoring on GitHub](https://github.com/sponsors/drknowhow). Sponsorship directly funds API costs for cross-model test runs and dedicated development time.
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
426
434
|
## License
|
|
427
435
|
|
|
428
436
|
- **Current OSS license** — Apache License 2.0 ([`LICENSE`](LICENSE)). Free for any use, including commercial. Modify, fork, redistribute — all permitted under Apache-2.0 terms.
|
|
@@ -440,3 +448,4 @@ The author may introduce a paid offering or relicense future major versions; no
|
|
|
440
448
|
- **Security policy:** [`SECURITY.md`](SECURITY.md)
|
|
441
449
|
- **Licensing FAQ:** [`LICENSING.md`](LICENSING.md)
|
|
442
450
|
- **Issues:** https://github.com/drknowhow/code-context-control/issues
|
|
451
|
+
- **Sponsor:** https://github.com/sponsors/drknowhow
|
|
@@ -267,6 +267,7 @@ tests/test_project_manager.py
|
|
|
267
267
|
tests/test_project_manager_merge.py
|
|
268
268
|
tests/test_project_tool.py
|
|
269
269
|
tests/test_read_coercion.py
|
|
270
|
+
tests/test_read_edit_parity.py
|
|
270
271
|
tests/test_response_boilerplate.py
|
|
271
272
|
tests/test_retention.py
|
|
272
273
|
tests/test_review_digest.py
|
|
@@ -827,6 +827,7 @@
|
|
|
827
827
|
</div>
|
|
828
828
|
</div>
|
|
829
829
|
</div>
|
|
830
|
+
<a class="header-btn" href="https://github.com/sponsors/drknowhow" target="_blank" rel="noopener" title="Sponsor C3 development"><span style="color:#EA4AAA">♥</span> Sponsor</a>
|
|
830
831
|
<a class="header-btn" id="hubLink" href="#" target="_blank" style="display:none">Open Hub</a>
|
|
831
832
|
<button class="header-btn" id="themeToggle" onclick="toggleTheme()">Theme: Dark</button>
|
|
832
833
|
</div>
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code-context-control"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.50.0"
|
|
8
8
|
description = "Local code-intelligence layer for AI coding tools (Claude Code, Codex, Gemini, Copilot). Retrieve less, read less, edit safer — and version the configs that shape your agent (CLAUDE.md, skills, hooks, MCP)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -81,6 +81,7 @@ Documentation = "https://github.com/drknowhow/code-context-control#readme"
|
|
|
81
81
|
Repository = "https://github.com/drknowhow/code-context-control"
|
|
82
82
|
Changelog = "https://github.com/drknowhow/code-context-control/blob/main/CHANGELOG.md"
|
|
83
83
|
Issues = "https://github.com/drknowhow/code-context-control/issues"
|
|
84
|
+
Funding = "https://github.com/sponsors/drknowhow"
|
|
84
85
|
|
|
85
86
|
[project.scripts]
|
|
86
87
|
c3 = "cli.c3:main"
|