code-context-control 2.95.0__tar.gz → 2.96.1__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.95.0/code_context_control.egg-info → code_context_control-2.96.1}/PKG-INFO +3 -3
- {code_context_control-2.95.0 → code_context_control-2.96.1}/README.md +2 -2
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/c3.py +117 -9
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/commands/parser.py +9 -2
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/tools.html +16 -1
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/workflow.html +40 -10
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_server.py +123 -3
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/drill_panel.js +4 -2
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/modals.js +309 -16
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/project_card.js +26 -24
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/project_tree.js +44 -40
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/state.js +46 -11
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/mcp_server.py +10 -2
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/federate.py +7 -3
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/project.py +77 -20
- {code_context_control-2.95.0 → code_context_control-2.96.1/code_context_control.egg-info}/PKG-INFO +3 -3
- {code_context_control-2.95.0 → code_context_control-2.96.1}/code_context_control.egg-info/SOURCES.txt +3 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/c3_bridge.py +31 -5
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/federated_graph.py +21 -2
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/project_scanner.py +19 -9
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/tool_registry.py +10 -5
- {code_context_control-2.95.0 → code_context_control-2.96.1}/pyproject.toml +1 -1
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/claude_md.py +1 -1
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/project_manager.py +30 -2
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/repo_map.py +6 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/subprojects.py +431 -57
- code_context_control-2.96.1/tests/test_subproject_clear_scope.py +118 -0
- code_context_control-2.96.1/tests/test_subproject_depth_consumers.py +205 -0
- code_context_control-2.96.1/tests/test_subproject_linkage_api.py +305 -0
- code_context_control-2.96.1/tests/test_subprojects.py +651 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ui_jsx_syntax.py +49 -3
- code_context_control-2.95.0/tests/test_subprojects.py +0 -294
- {code_context_control-2.95.0 → code_context_control-2.96.1}/LICENSE +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/_hook_utils.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/_shell_writes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/commands/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/commands/common.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/docs.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/edits.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/access.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/credentials.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/index.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/masking.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/oracle.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/guide/shared.css +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_artifact.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_c3read.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_filter.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_read.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/progress.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/server.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/_grants.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/agent.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/ci.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/compress.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/credentials.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/delegate.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/edit.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/edits.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/filter.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/impact.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/jira.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/locks.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/memory.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/override.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/read.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/search.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/session.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/shell.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/status.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/tasks.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/tools/validate.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/api.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/app.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/access.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/icons.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/shared.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui/theme.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui_legacy.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/cli/ui_nano.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/core/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/core/config.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/core/ide.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/core/mcp_toml.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/core/web_security.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/config.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/oracle_server.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/local_session.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/mobile_api.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/activity.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/agents.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/app.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/busy.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/core.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/header.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/insights.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/projects.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/settings.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/access_guard.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/access_telemetry.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/activity_log.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/agent_base.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/agent_locks.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/agents.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/artifact_defs.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/artifact_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/auto_memory.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/background_service.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/bench/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/bitbucket_client.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_act.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_cache.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_expr.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_failures.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_github.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_impact.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_intel.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_runner.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ci_workflow.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/circuit_breaker.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/compressor.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/context_snapshot.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/conversation_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/cred_audit.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/cred_telemetry.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/credential_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/doc_index.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/e2e_tasks.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/edit_ledger.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/embedding_index.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/enforcement_policy.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/error_reporting.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/file_memory.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/git_context.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/hub_service.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/indexer.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/jira_client.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/jira_cloud.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/jira_credentials.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/jira_data_center.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/jira_links.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/mask_activation.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/mask_mirror.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/mask_presets.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/memory.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/memory_consolidator.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/memory_distiller.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/memory_graph.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/memory_grounder.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/memory_queue.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/memory_scorer.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/metrics.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/notifications.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ollama_bridge.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ollama_client.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/ollama_credentials.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/oracle_service.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/output_filter.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/override_grants.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/override_policy.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/override_requests.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/override_wake.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/parser.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/project_runtime.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/protocol.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/proxy_state.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/repo_shape.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/retention.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/retrieval_broker.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/router.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/runtime.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/scanner.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/session_benchmark.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/session_manager.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/session_preloader.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/task_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/telemetry.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/text_index.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/time_tracker.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/tool_classifier.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/transcript_index.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/validation_cache.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/vector_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/watcher.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/services/win_subprocess.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/setup.cfg +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_access_guard.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_background_service.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ci_act.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_cred_audit.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_credential_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_env_parser.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hook_state.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_init_scan.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_jira_client.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_jira_links.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_memory_system.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_output_filter.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_override_grants.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_override_requests.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_override_wake.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_permissions.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_pm_api.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_project_manager.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_project_tool.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_related_facts.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_repo_map.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_retention.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_review_digest.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_service_durability.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_session_budget.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_task_store.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_task_tool.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_token_tracking.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_validate.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_version_sync.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_web_security.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/backend.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/main.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/__init__.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/index_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/init_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/search_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/session_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/stats.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.95.0 → code_context_control-2.96.1}/tui/theme.tcss +0 -0
{code_context_control-2.95.0/code_context_control.egg-info → code_context_control-2.96.1}/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.96.1
|
|
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
|
|
@@ -149,7 +149,7 @@ Every C3-initialized project registers itself here on `c3 init`. Filter by activ
|
|
|
149
149
|
|
|
150
150
|
Three top-level views — **Projects**, **Tasks** (a cross-project kanban), and **Credentials** — plus a drill-in panel per project covering Overview, Sub-projects, Tasks, Artifacts, Memory, Ledger, Sessions, Health, Budget, Credentials, Config, and MCP.
|
|
151
151
|
|
|
152
|
-
**Sub-projects** make
|
|
152
|
+
**Sub-projects** make one project a first-class child of another, with its own `.c3`. It can be a nested repo — the parent's index then excludes its subtree — or a project anywhere else on disk, linked by path. Hierarchies nest up to 8 levels, and `c3_search` / `c3_memory` fan out on demand (`scope='all'`, or one by name). → [Sub-projects guide](https://github.com/drknowhow/code-context-control/blob/main/docs/sub-projects.md)
|
|
153
153
|
|
|
154
154
|
### Per-project UI
|
|
155
155
|
|
|
@@ -211,7 +211,7 @@ C3 exposes **21 tools** as a native MCP server. Your IDE calls them directly:
|
|
|
211
211
|
| `c3_credentials` | Named-secret vault; values never enter model context (v2.58.0). `import_env` bulk-imports a `.env` the agent still cannot read (v2.93.0) |
|
|
212
212
|
| `c3_bitbucket` | Bitbucket Data Center — PRs, branches, builds, admin (v2.30.0) |
|
|
213
213
|
| `c3_jira` | Jira Cloud + Data Center — JQL, issues, transitions (v2.56.0) |
|
|
214
|
-
| `c3_project` | Cross-project discovery & operations; guarded writes (v2.31.0) |
|
|
214
|
+
| `c3_project` | Cross-project discovery & operations; sub-project hierarchy (link by path, inspect, multi-level tree); guarded writes (v2.31.0) |
|
|
215
215
|
|
|
216
216
|
Every tool is **read-only safe in plan mode** except `c3_edit`, `c3_shell`, `c3_ci(action='run'|'rerun')`, `c3_artifacts(action='restore')`, `c3_delegate` with write delegation enabled, and write actions on `c3_bitbucket` / `c3_jira` / `c3_credentials` / `c3_project` / `c3_task` / `c3_locks`.
|
|
217
217
|
|
|
@@ -86,7 +86,7 @@ Every C3-initialized project registers itself here on `c3 init`. Filter by activ
|
|
|
86
86
|
|
|
87
87
|
Three top-level views — **Projects**, **Tasks** (a cross-project kanban), and **Credentials** — plus a drill-in panel per project covering Overview, Sub-projects, Tasks, Artifacts, Memory, Ledger, Sessions, Health, Budget, Credentials, Config, and MCP.
|
|
88
88
|
|
|
89
|
-
**Sub-projects** make
|
|
89
|
+
**Sub-projects** make one project a first-class child of another, with its own `.c3`. It can be a nested repo — the parent's index then excludes its subtree — or a project anywhere else on disk, linked by path. Hierarchies nest up to 8 levels, and `c3_search` / `c3_memory` fan out on demand (`scope='all'`, or one by name). → [Sub-projects guide](https://github.com/drknowhow/code-context-control/blob/main/docs/sub-projects.md)
|
|
90
90
|
|
|
91
91
|
### Per-project UI
|
|
92
92
|
|
|
@@ -148,7 +148,7 @@ C3 exposes **21 tools** as a native MCP server. Your IDE calls them directly:
|
|
|
148
148
|
| `c3_credentials` | Named-secret vault; values never enter model context (v2.58.0). `import_env` bulk-imports a `.env` the agent still cannot read (v2.93.0) |
|
|
149
149
|
| `c3_bitbucket` | Bitbucket Data Center — PRs, branches, builds, admin (v2.30.0) |
|
|
150
150
|
| `c3_jira` | Jira Cloud + Data Center — JQL, issues, transitions (v2.56.0) |
|
|
151
|
-
| `c3_project` | Cross-project discovery & operations; guarded writes (v2.31.0) |
|
|
151
|
+
| `c3_project` | Cross-project discovery & operations; sub-project hierarchy (link by path, inspect, multi-level tree); guarded writes (v2.31.0) |
|
|
152
152
|
|
|
153
153
|
Every tool is **read-only safe in plan mode** except `c3_edit`, `c3_shell`, `c3_ci(action='run'|'rerun')`, `c3_artifacts(action='restore')`, `c3_delegate` with write delegation enabled, and write actions on `c3_bitbucket` / `c3_jira` / `c3_credentials` / `c3_project` / `c3_task` / `c3_locks`.
|
|
154
154
|
|
|
@@ -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.96.1"
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -7986,14 +7986,117 @@ def cmd_sub(args):
|
|
|
7986
7986
|
print(f"No .c3 found in {parent}. Run 'c3 init' there first.")
|
|
7987
7987
|
return
|
|
7988
7988
|
# Import after the cheap guard — the registry module needs a resolvable home.
|
|
7989
|
-
from services.subprojects import
|
|
7989
|
+
from services.subprojects import (
|
|
7990
|
+
MAX_DEPTH,
|
|
7991
|
+
VALID_CASCADE_OPS,
|
|
7992
|
+
SubprojectManager,
|
|
7993
|
+
inspect_path,
|
|
7994
|
+
)
|
|
7990
7995
|
|
|
7991
7996
|
sm = SubprojectManager(parent)
|
|
7992
7997
|
sub = getattr(args, "sub_cmd", "list") or "list"
|
|
7993
7998
|
target = getattr(args, "target", None)
|
|
7994
7999
|
as_json = getattr(args, "json", False)
|
|
8000
|
+
depth = getattr(args, "depth", None) or MAX_DEPTH
|
|
7995
8001
|
|
|
7996
|
-
if sub == "
|
|
8002
|
+
if sub == "inspect":
|
|
8003
|
+
if not target:
|
|
8004
|
+
print("Usage: c3 sub inspect <path> [--json]")
|
|
8005
|
+
return
|
|
8006
|
+
rep = inspect_path(target, detect=not getattr(args, "no_detect", False))
|
|
8007
|
+
if as_json:
|
|
8008
|
+
print(json.dumps(rep, indent=2))
|
|
8009
|
+
return
|
|
8010
|
+
print(f"\n{rep['path']}")
|
|
8011
|
+
if not rep["is_dir"]:
|
|
8012
|
+
print(" not a folder")
|
|
8013
|
+
return
|
|
8014
|
+
proj = rep.get("project")
|
|
8015
|
+
if proj:
|
|
8016
|
+
reg = "registered" if rep["registered"] else "NOT registered"
|
|
8017
|
+
print(f" C3 project: {proj['name']} (v{proj.get('c3_version') or '?'}, "
|
|
8018
|
+
f"ide={proj.get('ide') or '?'}, {reg})")
|
|
8019
|
+
print(f" {proj['facts_count']} facts, {proj['sessions']} sessions, "
|
|
8020
|
+
f"{proj['edit_ledger_entries']} ledger entries, "
|
|
8021
|
+
f"{proj['notification_count']} alerts")
|
|
8022
|
+
else:
|
|
8023
|
+
print(" no .c3 — not a C3 project yet")
|
|
8024
|
+
if rep["ancestors"]:
|
|
8025
|
+
chain = " < ".join(a["name"] for a in rep["ancestors"])
|
|
8026
|
+
print(f" parent chain (depth {rep['depth']}): {chain}")
|
|
8027
|
+
else:
|
|
8028
|
+
print(" top-level (no parent)")
|
|
8029
|
+
if rep["children"]:
|
|
8030
|
+
print(f" {len(rep['children'])} sub-project(s):")
|
|
8031
|
+
for c in rep["children"]:
|
|
8032
|
+
print(f" - {c['name']:<22} [{c['link_kind']}/{c['status']}] {c['path']}")
|
|
8033
|
+
if rep["detected"]:
|
|
8034
|
+
print(f" {len(rep['detected'])} unlinked project(s) detected inside:")
|
|
8035
|
+
for d in rep["detected"]:
|
|
8036
|
+
print(f" ? {d['name']:<22} {d['path']}")
|
|
8037
|
+
print(" (suggestions only — link with `c3 sub link <path>`)")
|
|
8038
|
+
for w in rep["warnings"]:
|
|
8039
|
+
print(f" warning: {w}")
|
|
8040
|
+
|
|
8041
|
+
elif sub == "tree":
|
|
8042
|
+
t = sm.tree(depth=depth)
|
|
8043
|
+
if as_json:
|
|
8044
|
+
print(json.dumps(t, indent=2))
|
|
8045
|
+
return
|
|
8046
|
+
r = t["rollup"]
|
|
8047
|
+
print(f"\n{t['parent']['name']} ({t['parent']['path']})")
|
|
8048
|
+
|
|
8049
|
+
def _render(rows, indent=" "):
|
|
8050
|
+
for row in rows:
|
|
8051
|
+
flag = "" if row["status"] == "ok" else f" [{row['status']}]"
|
|
8052
|
+
kind = "" if row["link_kind"] == "nested" else " (linked)"
|
|
8053
|
+
print(f"{indent}- {row['name']}{kind}{flag}")
|
|
8054
|
+
_render(row.get("children") or [], indent + " ")
|
|
8055
|
+
|
|
8056
|
+
_render(t["children"])
|
|
8057
|
+
if not t["children"]:
|
|
8058
|
+
print(" No sub-projects designated. Use `c3 sub link <path>`.")
|
|
8059
|
+
return
|
|
8060
|
+
line = f"\n{r['children']} descendant(s), {r['direct_children']} direct"
|
|
8061
|
+
if r["issues"]:
|
|
8062
|
+
line += f" -- {r['issues']} with issues (run `c3 sub check --fix`)"
|
|
8063
|
+
print(line)
|
|
8064
|
+
|
|
8065
|
+
elif sub == "link":
|
|
8066
|
+
if not target:
|
|
8067
|
+
print("Usage: c3 sub link <path> [--parent PATH] [--name NAME] [--init]")
|
|
8068
|
+
return
|
|
8069
|
+
# link is designation for a project that already exists anywhere on
|
|
8070
|
+
# disk; add is for a folder this parent should initialize.
|
|
8071
|
+
want_init = getattr(args, "init", False)
|
|
8072
|
+
candidate = target if Path(target).is_absolute() else str(Path(parent) / target)
|
|
8073
|
+
probe = inspect_path(candidate, detect=False)
|
|
8074
|
+
if probe["is_dir"] and not probe["has_c3"] and not want_init:
|
|
8075
|
+
err = (f"not a C3 project: {probe['path']} — "
|
|
8076
|
+
"pass --init to initialize it, or run `c3 init` there first")
|
|
8077
|
+
if as_json:
|
|
8078
|
+
print(json.dumps({"added": False, "error": err}, indent=2))
|
|
8079
|
+
else:
|
|
8080
|
+
print(f"Failed: {err}")
|
|
8081
|
+
return
|
|
8082
|
+
result = sm.add(
|
|
8083
|
+
target,
|
|
8084
|
+
name=getattr(args, "name", None),
|
|
8085
|
+
ide=getattr(args, "ide", None),
|
|
8086
|
+
run_init=want_init,
|
|
8087
|
+
reindex_parent=not getattr(args, "no_reindex_parent", False),
|
|
8088
|
+
)
|
|
8089
|
+
if as_json:
|
|
8090
|
+
print(json.dumps(result, indent=2))
|
|
8091
|
+
return
|
|
8092
|
+
if not result.get("added"):
|
|
8093
|
+
print(f"Failed: {result.get('error')}")
|
|
8094
|
+
return
|
|
8095
|
+
where = "by path" if result["link_kind"] == "external" else f"at {result['rel_path']}"
|
|
8096
|
+
print(f"\n[OK] Linked {result['name']} {where} (depth {result['depth']})")
|
|
8097
|
+
print(f" {result['path']}")
|
|
8098
|
+
|
|
8099
|
+
elif sub == "add":
|
|
7997
8100
|
if not target:
|
|
7998
8101
|
print("Usage: c3 sub add <folder> [--parent PATH] [--name NAME]")
|
|
7999
8102
|
return
|
|
@@ -8026,16 +8129,19 @@ def cmd_sub(args):
|
|
|
8026
8129
|
if not children:
|
|
8027
8130
|
print("No sub-projects designated. Use `c3 sub add <folder>`.")
|
|
8028
8131
|
return
|
|
8029
|
-
fmt = "{:<22} {:<16} {:>6} {:>7} {}"
|
|
8030
|
-
print(fmt.format("NAME", "STATUS", "FACTS", "ALERTS", "
|
|
8031
|
-
print("-" *
|
|
8132
|
+
fmt = "{:<22} {:<16} {:<9} {:>6} {:>7} {}"
|
|
8133
|
+
print(fmt.format("NAME", "STATUS", "LINK", "FACTS", "ALERTS", "LOCATION"))
|
|
8134
|
+
print("-" * 90)
|
|
8032
8135
|
for c in children:
|
|
8136
|
+
# An external child has no rel_path — show where it actually lives.
|
|
8137
|
+
location = c.get("rel_path") or c.get("path", "")
|
|
8033
8138
|
print(fmt.format(
|
|
8034
8139
|
(c.get("name") or "?")[:21],
|
|
8035
8140
|
c.get("status", "?"),
|
|
8141
|
+
c.get("link_kind", "nested"),
|
|
8036
8142
|
c.get("facts_count", 0),
|
|
8037
8143
|
c.get("notification_count", 0),
|
|
8038
|
-
|
|
8144
|
+
location,
|
|
8039
8145
|
))
|
|
8040
8146
|
issues = sum(1 for c in children if c["status"] != "ok")
|
|
8041
8147
|
line = f"\n{len(children)} sub-project(s)"
|
|
@@ -8075,7 +8181,8 @@ def cmd_sub(args):
|
|
|
8075
8181
|
return
|
|
8076
8182
|
result = sm.cascade(target,
|
|
8077
8183
|
include_parent=getattr(args, "include_parent", False),
|
|
8078
|
-
mcp=getattr(args, "mcp", False)
|
|
8184
|
+
mcp=getattr(args, "mcp", False),
|
|
8185
|
+
depth=depth)
|
|
8079
8186
|
if as_json:
|
|
8080
8187
|
print(json.dumps(result, indent=2))
|
|
8081
8188
|
return
|
|
@@ -8096,7 +8203,8 @@ def cmd_sub(args):
|
|
|
8096
8203
|
print("No sub-projects designated.")
|
|
8097
8204
|
return
|
|
8098
8205
|
for c in result["children"]:
|
|
8099
|
-
|
|
8206
|
+
location = c.get("rel_path") or c.get("path", "")
|
|
8207
|
+
print(f" [{c['status']:<16}] {c.get('name') or '?':<22} {location}")
|
|
8100
8208
|
for o in result["orphans"]:
|
|
8101
8209
|
print(f" [orphan_registry ] {o}")
|
|
8102
8210
|
for f in result.get("fixed", []):
|
|
@@ -152,7 +152,7 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
152
152
|
p_sub.add_argument(
|
|
153
153
|
"sub_cmd",
|
|
154
154
|
nargs="?",
|
|
155
|
-
choices=["add", "list", "remove", "run", "check"],
|
|
155
|
+
choices=["add", "link", "inspect", "list", "tree", "remove", "run", "check"],
|
|
156
156
|
default="list",
|
|
157
157
|
help="Sub-command (default: list)",
|
|
158
158
|
)
|
|
@@ -160,7 +160,8 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
160
160
|
"target",
|
|
161
161
|
nargs="?",
|
|
162
162
|
default=None,
|
|
163
|
-
help="Folder (add),
|
|
163
|
+
help="Folder (add), path to an existing project (link|inspect), "
|
|
164
|
+
"sub-project name/path (remove), or operation update|reindex|health (run)",
|
|
164
165
|
)
|
|
165
166
|
p_sub.add_argument("--parent", default=".", help="Parent project path (default: current directory)")
|
|
166
167
|
p_sub.add_argument("--name", default=None, help="Display name for the sub-project (add)")
|
|
@@ -173,6 +174,12 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
173
174
|
p_sub.add_argument("--mcp", action="store_true", help="Also reinstall MCP config on update (run update)")
|
|
174
175
|
p_sub.add_argument("--fix", action="store_true", help="Repair links from the parent config (check)")
|
|
175
176
|
p_sub.add_argument("--prune", action="store_true", help="With --fix: drop entries whose folder is gone (check)")
|
|
177
|
+
p_sub.add_argument("--depth", default=None, type=int,
|
|
178
|
+
help="Levels to descend (tree|run); default: the full hierarchy")
|
|
179
|
+
p_sub.add_argument("--init", action="store_true",
|
|
180
|
+
help="Initialize the folder if it is not a C3 project yet (link)")
|
|
181
|
+
p_sub.add_argument("--no-detect", action="store_true",
|
|
182
|
+
help="Skip the scan for unlinked nested projects (inspect)")
|
|
176
183
|
p_sub.add_argument("--json", action="store_true", help="Emit JSON output")
|
|
177
184
|
|
|
178
185
|
p_perms = subparsers.add_parser("permissions",
|
|
@@ -1394,10 +1394,14 @@ c3_jira(action=<span class="str">'comment'</span>, issue=<span class="str">'PROJ
|
|
|
1394
1394
|
<tr><td class="param-name">scan</td><td>Discover</td><td class="param-desc">Registry + bounded filesystem scan for unregistered <code>.c3</code> projects nearby</td></tr>
|
|
1395
1395
|
<tr><td class="param-name">info, register, unregister</td><td>Discover</td><td class="param-desc">Project details / add to / remove from the registry</td></tr>
|
|
1396
1396
|
<tr><td class="param-name">search, read, compress, status, memory, impact, edits, validate, filter</td><td>Read</td><td class="param-desc">Proxy the matching c3_* tool against the target project</td></tr>
|
|
1397
|
+
<tr><td class="param-name">subprojects, sub_tree, sub_inspect</td><td>Read</td><td class="param-desc">Direct children; the whole hierarchy; a read-only report on any path (what is there, who already claims it, what it claims, which nested projects under it are unlinked)</td></tr>
|
|
1398
|
+
<tr><td class="param-name">sub_add, sub_link, sub_remove, sub_cascade</td><td>Write</td><td class="param-desc">Designate / link by path / unlink / cascade across the subtree — require <code>allow_write=true</code> (<code>sub_cascade</code> with <code>mode='health'</code> is a read)</td></tr>
|
|
1397
1399
|
<tr><td class="param-name">edit, shell, memory(add/update/delete)</td><td>Write</td><td class="param-desc">Mutate the target project — require <code>allow_write=true</code></td></tr>
|
|
1398
1400
|
</tbody>
|
|
1399
1401
|
</table>
|
|
1400
1402
|
|
|
1403
|
+
<p class="tool-desc"><strong>Sub-project hierarchy:</strong> <code>project</code> is the PARENT. A child need not live inside it — <code>sub_link</code> takes an absolute path anywhere on disk, including another drive — and hierarchies nest up to 8 levels. Nested children are excluded from the parent's index; externally linked ones were never in it. Linking is refused if it would make a project its own ancestor.</p>
|
|
1404
|
+
|
|
1401
1405
|
<h4>Examples</h4>
|
|
1402
1406
|
<pre><code><span class="com"># Which projects have C3 installed?</span>
|
|
1403
1407
|
c3_project(action=<span class="str">'list'</span>)
|
|
@@ -1414,7 +1418,18 @@ c3_project(action=<span class="str">'memory'</span>, project=<span class="str">'
|
|
|
1414
1418
|
c3_project(action=<span class="str">'edit'</span>, project=<span class="str">'Sentinel'</span>,
|
|
1415
1419
|
file_path=<span class="str">'README.md'</span>,
|
|
1416
1420
|
old_string=<span class="str">'v1'</span>, new_string=<span class="str">'v2'</span>,
|
|
1417
|
-
allow_write=<span class="num">true</span>)
|
|
1421
|
+
allow_write=<span class="num">true</span>)
|
|
1422
|
+
|
|
1423
|
+
<span class="com"># What is at this path, and who already claims it? (read-only)</span>
|
|
1424
|
+
c3_project(action=<span class="str">'sub_inspect'</span>, project=<span class="str">'Code Context Control'</span>,
|
|
1425
|
+
target=<span class="str">r'U:\1. Projects\Claude Code Companion (C3)\c3-mobile'</span>)
|
|
1426
|
+
|
|
1427
|
+
<span class="com"># Link it — a sibling on disk, not nested, so containment cannot express it</span>
|
|
1428
|
+
c3_project(action=<span class="str">'sub_link'</span>, project=<span class="str">'Code Context Control'</span>,
|
|
1429
|
+
target=<span class="str">r'U:\1. Projects\Claude Code Companion (C3)\c3-mobile'</span>,
|
|
1430
|
+
allow_write=<span class="num">true</span>)
|
|
1431
|
+
|
|
1432
|
+
c3_project(action=<span class="str">'sub_tree'</span>, project=<span class="str">'Code Context Control'</span>) <span class="com"># every level</span></code></pre>
|
|
1418
1433
|
|
|
1419
1434
|
<p class="tool-desc"><strong>Sub-action params:</strong> <code>search_action</code> (code/files/semantic/…), <code>mem_action</code> (recall/index/fetch/add/…), and <code>edits_action</code> (history/versions/stats) pick the operation for those verbs; <code>scan_roots</code> (comma-separated) overrides where <code>scan</code> looks.</p>
|
|
1420
1435
|
</div>
|
|
@@ -912,12 +912,29 @@ c3_session(action=<span class="str">'restore'</span>)</code></pre>
|
|
|
912
912
|
<section class="section" id="subprojects">
|
|
913
913
|
<div class="section-title"><span class="icon">🌳</span> Sub-projects</div>
|
|
914
914
|
|
|
915
|
-
<p>
|
|
915
|
+
<p>A c3 project can claim another one as a <strong>sub-project</strong>. Each child keeps its own full <code>.c3</code> (index, memory, config), and the link is recorded in three places at once: the parent config's <code>subprojects[]</code> array, a back-link in the child's config, and the hub registry.</p>
|
|
916
|
+
|
|
917
|
+
<p>Since v2.96.0 the child does <strong>not</strong> have to live inside the parent's folder, and hierarchies nest to <strong>8 levels</strong> — a sub-project can have sub-projects of its own. There are two link kinds, and C3 picks from the path you give it:</p>
|
|
918
|
+
<table class="table">
|
|
919
|
+
<thead><tr><th>Kind</th><th>Where the child lives</th><th>Effect on the parent's index</th></tr></thead>
|
|
920
|
+
<tbody>
|
|
921
|
+
<tr><td><code>nested</code></td><td>Inside the parent's folder</td><td>The child's subtree is excluded, so nothing is indexed twice</td></tr>
|
|
922
|
+
<tr><td><code>external</code></td><td>Anywhere — a sibling folder, another drive</td><td>None: the child was never inside the tree the parent scans</td></tr>
|
|
923
|
+
</tbody>
|
|
924
|
+
</table>
|
|
916
925
|
|
|
917
926
|
<div class="callout callout-tip">
|
|
918
927
|
<span class="callout-icon">💡</span>
|
|
919
928
|
<div class="callout-body">
|
|
920
|
-
Use sub-projects for monorepos and nested apps:
|
|
929
|
+
Use sub-projects for monorepos and nested apps, and for the case that has no folder to nest: two checkouts of one product sitting side by side. Each child stays independently searchable with its own memory, while the parent can fan queries out across the whole family.
|
|
930
|
+
</div>
|
|
931
|
+
</div>
|
|
932
|
+
|
|
933
|
+
<div class="callout callout-warning">
|
|
934
|
+
<span class="callout-icon">⚠️</span>
|
|
935
|
+
<div class="callout-body">
|
|
936
|
+
<strong>No cycles</strong>
|
|
937
|
+
Hierarchy is a strict tree: one parent per project. While a child had to live inside its parent, a loop was impossible by construction; now that it can live anywhere, every link is checked against the ancestor chain and refused if it would make a project its own ancestor.
|
|
921
938
|
</div>
|
|
922
939
|
</div>
|
|
923
940
|
|
|
@@ -925,21 +942,33 @@ c3_session(action=<span class="str">'restore'</span>)</code></pre>
|
|
|
925
942
|
<table class="table">
|
|
926
943
|
<thead><tr><th>Command</th><th>Effect</th></tr></thead>
|
|
927
944
|
<tbody>
|
|
945
|
+
<tr>
|
|
946
|
+
<td><code>c3 sub link <path> [--name --init]</code></td>
|
|
947
|
+
<td>Link an existing C3 project as a child — anywhere on disk, including another drive. Refuses a folder that is not already a project unless you pass <code>--init</code>.</td>
|
|
948
|
+
</tr>
|
|
949
|
+
<tr>
|
|
950
|
+
<td><code>c3 sub inspect <path></code></td>
|
|
951
|
+
<td>Read-only report on any path: is there a project there, what is in it, who already claims it, what it claims, and which nested projects underneath are not linked yet. Mutates nothing.</td>
|
|
952
|
+
</tr>
|
|
928
953
|
<tr>
|
|
929
954
|
<td><code>c3 sub add <folder> [--name --ide]</code></td>
|
|
930
|
-
<td>
|
|
955
|
+
<td>Designate a folder as a child, initializing it. Adopts an existing <code>.c3</code>, otherwise runs a full init. <code>--no-init</code> links without initializing; <code>--parent <path></code> targets a different parent.</td>
|
|
931
956
|
</tr>
|
|
932
957
|
<tr>
|
|
933
958
|
<td><code>c3 sub list</code></td>
|
|
934
|
-
<td>
|
|
959
|
+
<td>Direct children with status and link kind (the default when no sub-command is given).</td>
|
|
960
|
+
</tr>
|
|
961
|
+
<tr>
|
|
962
|
+
<td><code>c3 sub tree [--depth N]</code></td>
|
|
963
|
+
<td>The whole hierarchy, indented, with a subtree rollup. <code>--depth</code> stops the walk early.</td>
|
|
935
964
|
</tr>
|
|
936
965
|
<tr>
|
|
937
966
|
<td><code>c3 sub remove <ref> [--clear]</code></td>
|
|
938
967
|
<td>Unlink a child and promote it to a standalone top-level project (its <code>.c3</code> is kept). <code>--clear</code> also wipes <code>.c3</code>, uninstalls the MCP config and instruction docs, and deregisters it.</td>
|
|
939
968
|
</tr>
|
|
940
969
|
<tr>
|
|
941
|
-
<td><code>c3 sub run <update|reindex|health> [--include-parent]</code></td>
|
|
942
|
-
<td>Cascade an operation across
|
|
970
|
+
<td><code>c3 sub run <update|reindex|health> [--include-parent --depth N]</code></td>
|
|
971
|
+
<td>Cascade an operation across the whole subtree. <code>--mcp</code> also reinstalls the MCP config during <code>update</code>.</td>
|
|
943
972
|
</tr>
|
|
944
973
|
<tr>
|
|
945
974
|
<td><code>c3 sub check [--fix --prune]</code></td>
|
|
@@ -954,8 +983,8 @@ c3_session(action=<span class="str">'restore'</span>)</code></pre>
|
|
|
954
983
|
<thead><tr><th>Value</th><th>Meaning</th></tr></thead>
|
|
955
984
|
<tbody>
|
|
956
985
|
<tr><td><code>''</code></td><td>Current project only (default)</td></tr>
|
|
957
|
-
<tr><td><code>'all'</code></td><td>Fan out across the parent and
|
|
958
|
-
<tr><td><code>'<child>'</code></td><td>One specific
|
|
986
|
+
<tr><td><code>'all'</code></td><td>Fan out across the parent and every descendant, at any depth</td></tr>
|
|
987
|
+
<tr><td><code>'<child>'</code></td><td>One specific descendant by name</td></tr>
|
|
959
988
|
</tbody>
|
|
960
989
|
</table>
|
|
961
990
|
|
|
@@ -967,11 +996,12 @@ c3_memory(action=<span class="str">'recall'</span>, query=<span class="str">'pay
|
|
|
967
996
|
<h4>Hub UI management (v2.57.0)</h4>
|
|
968
997
|
<p>Everything the CLI does — plus the operations that need multi-step safety — is available in the Hub:</p>
|
|
969
998
|
<ul>
|
|
999
|
+
<li><strong>"Link project by path…"</strong> (v2.96.0) — kebab menu on any card, at any depth. Browse anywhere or paste a path; C3 inspects it before anything happens and shows you what you are about to claim — the project's name and version, whether the hub already knows it, how much is in it, who already claims it, and what sub-projects it would bring with it. One confirm registers and links an unregistered project. Unlinked nested projects it finds are offered as suggestions, never applied.</li>
|
|
970
1000
|
<li><strong>Designate</strong> — kebab menu → "Designate sub-project…" on any project card, or from the drill-in <strong>Sub-projects</strong> tab. A folder picker fenced to the parent's subtree validates the choice, shows adopt-vs-initialize expectations up front, and offers an instruction-docs/IDE picker (<code>auto | claude | vscode | cursor | codex | antigravity</code>).</li>
|
|
971
|
-
<li><strong>"Make sub-project of…"</strong> — the reverse move:
|
|
1001
|
+
<li><strong>"Make sub-project of…"</strong> — the reverse move: pick any registered project to sit under. The only projects excluded are this one and its own descendants.</li>
|
|
972
1002
|
<li><strong>Sub-projects drill tab</strong> — per-child rows with inline <em>Validate</em> and <em>Promote</em>; inline <em>Reconcile</em> with per-issue detail and planned repair actions; a <em>Cascade</em> launcher with operation picker, include-parent toggle, affected-children preview, live progress, and Cancel.</li>
|
|
973
1003
|
<li><strong>Link health, passively</strong> — parents show a red "N link issues" badge and children a status badge (<code>ok · backlink_broken · unregistered · missing_folder · missing_c3 · orphan</code>), computed from config + filesystem on every listing — no manual reconcile needed to spot trouble.</li>
|
|
974
|
-
<li><strong>"Change parent…"</strong> —
|
|
1004
|
+
<li><strong>"Change parent…"</strong> — unlink → validate → relink, with a per-step checklist. Since a child can be addressed by absolute path, re-parenting is a configuration change and no files move.</li>
|
|
975
1005
|
<li><strong>"De-initialize…"</strong> — clear-mode removal behind a typed-name confirmation: deletes <code>.c3</code>, uninstalls the MCP config, removes instruction docs, deregisters. Your code is untouched.</li>
|
|
976
1006
|
<li><strong>Federation toggles</strong> — the config editor's Sub-projects section on parent projects: memory roll-up, search fan-out for <code>scope='all'</code>, and max children per query, persisted under <code>hybrid.subprojects</code>.</li>
|
|
977
1007
|
<li><strong>Ctrl-K scope chips</strong> — global search can target All, Top-level only, or one parent + its children; child results carry a "parent › child" breadcrumb.</li>
|
|
@@ -537,7 +537,7 @@ def _compute_subproject_links(projects):
|
|
|
537
537
|
config_paths = set()
|
|
538
538
|
for entry in entries:
|
|
539
539
|
try:
|
|
540
|
-
key = _norm_realpath(mgr._abs_child(entry
|
|
540
|
+
key = _norm_realpath(mgr._abs_child(entry))
|
|
541
541
|
status = mgr._entry_status(entry, registry)
|
|
542
542
|
except Exception:
|
|
543
543
|
continue
|
|
@@ -609,10 +609,26 @@ def api_projects_list():
|
|
|
609
609
|
from services.task_store import open_task_count
|
|
610
610
|
projects = _pm().list_projects()
|
|
611
611
|
parent_paths = {os.path.normcase(p["parent_path"]) for p in projects if p.get("parent_path")}
|
|
612
|
+
# Depth from the registry alone — no disk reads. Bounded by the number
|
|
613
|
+
# of projects and a visited-set, so a corrupt cycle cannot hang the poll.
|
|
614
|
+
by_path = {os.path.normcase(p.get("path", "")): p for p in projects}
|
|
615
|
+
|
|
616
|
+
def _depth(row):
|
|
617
|
+
n, seen, cursor = 0, set(), row
|
|
618
|
+
while cursor and cursor.get("parent_path"):
|
|
619
|
+
key = os.path.normcase(cursor["parent_path"])
|
|
620
|
+
if key in seen or key not in by_path:
|
|
621
|
+
break
|
|
622
|
+
seen.add(key)
|
|
623
|
+
cursor = by_path[key]
|
|
624
|
+
n += 1
|
|
625
|
+
return n
|
|
626
|
+
|
|
612
627
|
for p in projects:
|
|
613
628
|
p["notification_count"] = _notification_count(p.get("path", ""))
|
|
614
629
|
p["is_parent"] = os.path.normcase(p.get("path", "")) in parent_paths
|
|
615
630
|
p["open_task_count"] = open_task_count(p.get("path", ""))
|
|
631
|
+
p["depth"] = _depth(p)
|
|
616
632
|
_annotate_subproject_links(projects)
|
|
617
633
|
return jsonify(projects)
|
|
618
634
|
except Exception as e:
|
|
@@ -1438,18 +1454,87 @@ def _parse_json_tail(output: str):
|
|
|
1438
1454
|
|
|
1439
1455
|
@app.route("/api/projects/subprojects", methods=["GET"])
|
|
1440
1456
|
def api_subprojects_tree():
|
|
1441
|
-
"""Parent +
|
|
1457
|
+
"""Parent + descendants + rollup. Query: ?parent=<path>&depth=<n>
|
|
1458
|
+
|
|
1459
|
+
``depth`` defaults to the full hierarchy; pass 1 for the direct-children
|
|
1460
|
+
shape the drill-in panel used before 2.96.
|
|
1461
|
+
"""
|
|
1442
1462
|
parent = (request.args.get("parent") or "").strip()
|
|
1443
1463
|
if not parent:
|
|
1444
1464
|
return jsonify({"error": "parent is required"}), 400
|
|
1445
1465
|
try:
|
|
1446
|
-
|
|
1466
|
+
from services.subprojects import MAX_DEPTH
|
|
1467
|
+
depth = int(request.args.get("depth") or MAX_DEPTH)
|
|
1468
|
+
except (TypeError, ValueError):
|
|
1469
|
+
return jsonify({"error": "depth must be an integer"}), 400
|
|
1470
|
+
try:
|
|
1471
|
+
return jsonify(_sub_manager(parent).tree(depth=depth))
|
|
1447
1472
|
except ValueError as e:
|
|
1448
1473
|
return jsonify({"error": str(e)}), 404
|
|
1449
1474
|
except Exception as e:
|
|
1450
1475
|
return jsonify({"error": str(e)}), 500
|
|
1451
1476
|
|
|
1452
1477
|
|
|
1478
|
+
@app.route("/api/projects/subprojects/inspect", methods=["POST"])
|
|
1479
|
+
def api_subprojects_inspect():
|
|
1480
|
+
"""Read-only report on any path. Body: {path, detect?}
|
|
1481
|
+
|
|
1482
|
+
Answers "is there a C3 project here, what is in it, who already claims it,
|
|
1483
|
+
what does it claim, and what nested projects under it are unlinked?" —
|
|
1484
|
+
without registering, linking, or initializing anything. This is what the
|
|
1485
|
+
Hub calls before offering to link, so it must stay side-effect free.
|
|
1486
|
+
"""
|
|
1487
|
+
data = request.get_json(force=True) or {}
|
|
1488
|
+
path = (data.get("path") or "").strip()
|
|
1489
|
+
if not path:
|
|
1490
|
+
return jsonify({"error": "path is required"}), 400
|
|
1491
|
+
try:
|
|
1492
|
+
from services.subprojects import inspect_path
|
|
1493
|
+
return jsonify(inspect_path(path, detect=bool(data.get("detect", True))))
|
|
1494
|
+
except Exception as e:
|
|
1495
|
+
return jsonify({"error": str(e)}), 500
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
@app.route("/api/projects/hierarchy", methods=["GET"])
|
|
1499
|
+
def api_projects_hierarchy():
|
|
1500
|
+
"""The whole forest: every root project with its descendants. Query: ?depth=<n>
|
|
1501
|
+
|
|
1502
|
+
Roots are registered projects with no parent back-link. A project whose
|
|
1503
|
+
parent is not itself registered still surfaces as a root, so nothing can
|
|
1504
|
+
fall out of the listing because of a broken link.
|
|
1505
|
+
"""
|
|
1506
|
+
try:
|
|
1507
|
+
from services.subprojects import MAX_DEPTH, SubprojectManager, parent_link
|
|
1508
|
+
depth = int(request.args.get("depth") or MAX_DEPTH)
|
|
1509
|
+
except (TypeError, ValueError):
|
|
1510
|
+
return jsonify({"error": "depth must be an integer"}), 400
|
|
1511
|
+
try:
|
|
1512
|
+
projects = ProjectManager()._read_projects()
|
|
1513
|
+
known = {os.path.normcase(p.get("path", "")) for p in projects}
|
|
1514
|
+
roots, claimed = [], set()
|
|
1515
|
+
for p in projects:
|
|
1516
|
+
path = p.get("path", "")
|
|
1517
|
+
if not path:
|
|
1518
|
+
continue
|
|
1519
|
+
link = parent_link(path)
|
|
1520
|
+
parent = link.get("path") or p.get("parent_path")
|
|
1521
|
+
if parent and os.path.normcase(str(Path(parent).resolve())) in known:
|
|
1522
|
+
claimed.add(os.path.normcase(path))
|
|
1523
|
+
continue
|
|
1524
|
+
roots.append(p)
|
|
1525
|
+
out = []
|
|
1526
|
+
for p in roots:
|
|
1527
|
+
try:
|
|
1528
|
+
out.append(SubprojectManager(p["path"]).tree(depth=depth))
|
|
1529
|
+
except Exception as e: # one bad root must not blank the forest
|
|
1530
|
+
out.append({"parent": {"name": p.get("name"), "path": p["path"]},
|
|
1531
|
+
"children": [], "rollup": {}, "error": str(e)})
|
|
1532
|
+
return jsonify({"roots": out, "root_count": len(out),
|
|
1533
|
+
"linked_count": len(claimed), "depth": depth})
|
|
1534
|
+
except Exception as e:
|
|
1535
|
+
return jsonify({"error": str(e)}), 500
|
|
1536
|
+
|
|
1537
|
+
|
|
1453
1538
|
@app.route("/api/projects/subprojects/validate", methods=["POST"])
|
|
1454
1539
|
def api_subprojects_validate():
|
|
1455
1540
|
"""Pre-flight a designation. Body: {parent, folder}"""
|
|
@@ -1493,6 +1578,41 @@ def api_subprojects_add():
|
|
|
1493
1578
|
return jsonify(body), (201 if ok else 500)
|
|
1494
1579
|
|
|
1495
1580
|
|
|
1581
|
+
@app.route("/api/projects/subprojects/link", methods=["POST"])
|
|
1582
|
+
def api_subprojects_link():
|
|
1583
|
+
"""Link an existing project by path. Body: {parent, folder, name?, ide?, init?}
|
|
1584
|
+
|
|
1585
|
+
The register-and-link one-shot behind the Hub's "Register + link" button.
|
|
1586
|
+
``folder`` may be anywhere on disk — inside the parent, a sibling, another
|
|
1587
|
+
drive. Unlike ``/add`` this refuses a folder that is not already a C3
|
|
1588
|
+
project unless ``init`` is set, so "link" never silently creates one.
|
|
1589
|
+
|
|
1590
|
+
Shells out like /add and /remove, so errors land at result.error and the
|
|
1591
|
+
frontend's apiErr() keeps reading them.
|
|
1592
|
+
"""
|
|
1593
|
+
data = request.get_json(force=True) or {}
|
|
1594
|
+
parent = (data.get("parent") or "").strip()
|
|
1595
|
+
folder = (data.get("folder") or "").strip()
|
|
1596
|
+
if not parent or not folder:
|
|
1597
|
+
return jsonify({"error": "parent and folder are required"}), 400
|
|
1598
|
+
args = ["sub", "link", folder, "--parent", parent, "--json"]
|
|
1599
|
+
name = (data.get("name") or "").strip()
|
|
1600
|
+
if name:
|
|
1601
|
+
args += ["--name", name]
|
|
1602
|
+
ide = (data.get("ide") or "").strip()
|
|
1603
|
+
if ide and ide != "unknown":
|
|
1604
|
+
args += ["--ide", ide]
|
|
1605
|
+
if data.get("init"):
|
|
1606
|
+
args.append("--init")
|
|
1607
|
+
res = _run_c3(args, timeout=300)
|
|
1608
|
+
payload = _parse_json_tail(res.get("output", ""))
|
|
1609
|
+
ok = res.get("success") and bool((payload or {}).get("added"))
|
|
1610
|
+
if ok:
|
|
1611
|
+
_invalidate_subproject_links()
|
|
1612
|
+
body = {"success": ok, "result": payload, "output": res.get("output", "")}
|
|
1613
|
+
return jsonify(body), (201 if ok else 500)
|
|
1614
|
+
|
|
1615
|
+
|
|
1496
1616
|
@app.route("/api/projects/subprojects/remove", methods=["POST"])
|
|
1497
1617
|
def api_subprojects_remove():
|
|
1498
1618
|
"""Unlink (Promote) or clear a sub-project. Body: {parent, ref, mode: unlink|clear}"""
|
{code_context_control-2.95.0 → code_context_control-2.96.1}/cli/hub_ui/components/drill_panel.js
RENAMED
|
@@ -111,9 +111,11 @@ function DrillNeedsInit({ project, onReady }) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function DrillPanel({ project, tab, setTab, onClose, onChanged, onOpenModal, projects }) {
|
|
114
|
-
//
|
|
114
|
+
// A sub-project may have sub-projects of its own, so the Sub-projects tab
|
|
115
|
+
// stays available at every level. isChild now only drives the "under
|
|
116
|
+
// <parent>" chip below.
|
|
115
117
|
const isChild = !!project.parent_path;
|
|
116
|
-
const tabs = DRILL_PANEL_TABS
|
|
118
|
+
const tabs = DRILL_PANEL_TABS;
|
|
117
119
|
// "under <parent>" chip: friendly name from the loaded project list when
|
|
118
120
|
// available (optional prop), else the last path segment.
|
|
119
121
|
const parentName = (() => {
|