code-context-control 2.141.0__tar.gz → 2.143.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.141.0 → code_context_control-2.143.0}/PKG-INFO +3 -1
- {code_context_control-2.141.0 → code_context_control-2.143.0}/README.md +2 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/c3.py +2 -1
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_server.py +349 -44
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/app.js +4 -2
- code_context_control-2.143.0/cli/hub_ui/components/hub_sessions.js +446 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/topbar.js +1 -1
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/mcp_server.py +11 -4
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/session.py +94 -1
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/tasks.py +7 -1
- {code_context_control-2.141.0 → code_context_control-2.143.0}/code_context_control.egg-info/PKG-INFO +3 -1
- {code_context_control-2.141.0 → code_context_control-2.143.0}/code_context_control.egg-info/SOURCES.txt +7 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/pyproject.toml +1 -1
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/access_guard.py +22 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/claude_md.py +1 -1
- code_context_control-2.143.0/services/session_catalog.py +1078 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/task_store.py +1 -1
- code_context_control-2.143.0/services/terminal_launch.py +73 -0
- code_context_control-2.143.0/tests/test_hub_access_routes.py +230 -0
- code_context_control-2.143.0/tests/test_hub_sessions_routes.py +180 -0
- code_context_control-2.143.0/tests/test_session_catalog.py +374 -0
- code_context_control-2.143.0/tests/test_session_tool.py +129 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/LICENSE +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/_hook_utils.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/_shell_writes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/commands/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/commands/common.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/commands/parser.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/docs.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/edits.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/access.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/credentials.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/index.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/masking.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/oracle.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/shared.css +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/tools.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/guide/workflow.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_agent_model.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_artifact.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_c3read.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_codex_lifecycle.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_filter.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_read.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_session_end.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_session_open.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/hub_access.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/hub_ui.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/progress.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/server.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/_grants.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/agent.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/ci.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/compress.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/credentials.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/delegate.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/edit.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/edits.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/federate.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/filter.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/impact.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/jira.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/locks.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/memory.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/override.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/project.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/read.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/search.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/shell.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/shell_job.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/shell_nudge.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/shell_parsers.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/shell_render.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/status.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/tools/validate.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/api.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/app.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/access.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/icons.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/shared.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui/theme.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui_legacy.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/cli/ui_nano.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/codex_patch.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/config.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/grok_payload.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/hook_command.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/host.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/ide.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/mcp_toml.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/core/web_security.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/config.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/listeners.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/oracle_server.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/client_tokens.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/local_session.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/mobile_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/activity.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/agents.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/app.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/busy.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/core.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/header.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/insights.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/projects.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/settings.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/access_telemetry.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/activity_log.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/agent_base.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/agent_downshift.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/agent_locks.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/agents.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/agents_workflow.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/artifact_defs.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/artifact_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/atomic_json.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/auto_memory.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/background_service.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/delegate_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/delegate_write_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/map_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/search_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bench/shell_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bitbucket_client.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_act.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_cache.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_expr.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_failures.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_github.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_impact.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_intel.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_runner.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ci_workflow.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/circuit_breaker.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/codex_integration.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/codex_transcript.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/compressor.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/context_snapshot.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/conversation_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/cred_audit.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/cred_telemetry.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/credential_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/delegate_agents.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/delegate_hints.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/delegate_write.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/dir_map.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/doc_index.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/e2e_tasks.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/edit_ledger.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/embedding_index.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/enforcement_policy.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/error_reporting.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/file_map.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/file_memory.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/git_context.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/grok_integration.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/grok_transcript.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/host_sessions.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/hub_service.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/index_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/indexer.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/jira_client.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/jira_cloud.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/jira_credentials.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/jira_data_center.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/jira_links.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/lexical_index.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/mask_activation.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/mask_mirror.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/mask_presets.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/memory.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/memory_consolidator.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/memory_distiller.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/memory_graph.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/memory_grounder.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/memory_queue.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/memory_scorer.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/metrics.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/notifications.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ollama_bridge.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ollama_client.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/ollama_credentials.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/oracle_service.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/output_filter.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/override_costs.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/override_grants.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/override_policy.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/override_requests.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/override_wake.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/parser.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/project_manager.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/project_runtime.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/protocol.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/proxy_state.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/repo_map.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/repo_shape.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/reranker.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/retention.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/retrieval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/retrieval_broker.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/router.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/runtime.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/scanner.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/session_benchmark.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/session_live.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/session_manager.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/session_preloader.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/shell_jobs.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/shell_output.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/subprojects.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/telemetry.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/text_index.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/time_tracker.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/tool_classifier.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/transcript_index.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/validation_cache.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/vector_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/watcher.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/services/win_subprocess.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/setup.cfg +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_access_guard.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_activity_log_find_last.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_atomic_json.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_background_service.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_builtin_modes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ci_act.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ci_dag_ownership.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_claude_md_updater.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_codex_mcp_transport.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_codex_native.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_confirm_guard.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_confirm_guard_wiring.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_cred_audit.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_credential_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_adoption_d4.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_auto.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_claude_d1.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_grok.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_host_d2.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_scout_d3.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_telemetry_d0.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_thinking_cap.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_tuning.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_write.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_delegate_write_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_dir_map_c3.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_env_parser.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_file_map_c1.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_grok_native.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_grok_compat.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_session_end.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_state.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_hook_migration.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_override_policy_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_override_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_rules_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_index_cap_not_hardcoded.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_init_scan.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_jira_client.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_jira_links.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_large_files_c4.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_map_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_map_telemetry_c0.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_memory_system.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mobile_clients.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mobile_jobs_ci.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mobile_override_costs.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_notification_kinds.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_loopback.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_output_filter.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_override_costs.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_override_grants.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_override_requests.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_override_wake.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_permissions.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_pm_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_project_manager.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_project_tool.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_read_outside_root.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_related_facts.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_repo_map.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_retention.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_review_digest.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_search_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_search_p1.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_search_p2.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_search_p2b.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_search_p3.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_search_p4.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_search_p5.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_service_durability.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_session_budget.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_session_live.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_budget_s1.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_eval.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_jobs_s3.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_nudge_s4.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_output.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_parsers_s2.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_telemetry_s0.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_subproject_clear_scope.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_subproject_depth_consumers.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_subproject_linkage_api.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_subprojects.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_task_store.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_task_tool.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_token_tracking.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_ui_jsx_syntax.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_validate.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_version_sync.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_watcher_pruning.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_web_security.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/backend.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/main.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/__init__.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/index_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/init_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/search_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/session_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/stats.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.141.0 → code_context_control-2.143.0}/tui/theme.tcss +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.143.0
|
|
4
4
|
Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -163,6 +163,8 @@ Every C3-initialized project registers itself here on `c3 init`. Filter by activ
|
|
|
163
163
|
|
|
164
164
|
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.
|
|
165
165
|
|
|
166
|
+
**Sessions** (v2.143.0) lists past Claude Code sessions across projects: the title, first and last prompt, the agent's note, and linked tasks and decisions. **Resume** opens a terminal running `claude --resume <id>`, or you can copy the command or open the claude.ai/code link. Agents mark dead ends stale with `c3_session(action='stale')`. → [Sessions](https://github.com/drknowhow/code-context-control/blob/main/docs/sessions.md)
|
|
167
|
+
|
|
166
168
|
**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)
|
|
167
169
|
|
|
168
170
|
### Per-project UI
|
|
@@ -97,6 +97,8 @@ Every C3-initialized project registers itself here on `c3 init`. Filter by activ
|
|
|
97
97
|
|
|
98
98
|
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.
|
|
99
99
|
|
|
100
|
+
**Sessions** (v2.143.0) lists past Claude Code sessions across projects: the title, first and last prompt, the agent's note, and linked tasks and decisions. **Resume** opens a terminal running `claude --resume <id>`, or you can copy the command or open the claude.ai/code link. Agents mark dead ends stale with `c3_session(action='stale')`. → [Sessions](https://github.com/drknowhow/code-context-control/blob/main/docs/sessions.md)
|
|
101
|
+
|
|
100
102
|
**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)
|
|
101
103
|
|
|
102
104
|
### Per-project UI
|
|
@@ -91,7 +91,7 @@ console = Console() if HAS_RICH else None
|
|
|
91
91
|
# Config
|
|
92
92
|
CONFIG_DIR = ".c3"
|
|
93
93
|
CONFIG_FILE = ".c3/config.json"
|
|
94
|
-
__version__ = "2.
|
|
94
|
+
__version__ = "2.143.0"
|
|
95
95
|
|
|
96
96
|
# The PreToolUse matcher for native subagent calls (installer and hub migration).
|
|
97
97
|
AGENT_MATCHER = "Agent|Task"
|
|
@@ -5081,6 +5081,7 @@ back to native tools as the task progresses.
|
|
|
5081
5081
|
- **Filter**: `c3_filter(text=...)` — for terminal output >10 lines
|
|
5082
5082
|
- **Shell**: `c3_shell(cmd, timeout=60)` — structured shell exec (tests/git/build). Auto-filters output, logs git mutations to the ledger. Native Bash for interactive/TTY only
|
|
5083
5083
|
- **Memory**: `c3_memory(action='recall')` — full recall. `index` + `fetch` for token-efficient two-step retrieval
|
|
5084
|
+
- **Sessions** (v2.143.0+): `c3_session(action='note', data=<done>, reasoning=<next steps>)` before you stop; `c3_session(action='stale', target=<id>, reasoning=<why>)` when your work supersedes, finishes or abandons an earlier session (`action='list'` shows them). The Hub/Desk Sessions view resumes the rest
|
|
5084
5085
|
- **Delegate**: `c3_delegate(task, task_type, context|file_path)` — your own provider one tier down (default `backend='host'`, `tier='small'`; Claude Code: Haiku) for bounded answers: summarize a diff/log, explain a function, triage a traceback. `scout=true` lets it look files up itself; `write_paths='a.py,b.py'` has Sonnet make a change you specified in only those files and return the diff. Multi-step work: the `c3-scout` (haiku) / `c3-worker` (sonnet) subagents; an `Agent` call with no `model` runs one tier below you (pass `model=` to choose)
|
|
5085
5086
|
- **Local CI** (v2.79.0+): `c3_ci(action='inspect|run|rerun|failures')` — run THIS repo's real `.github/workflows` here instead of pushing for feedback. `run` executes in `needs` order; `failures` gives {file,line,message}; `rerun` retries only what failed. Only `FULL_CI_PASS` means safe to push — `PARTIAL_PASS` means something did not run (other OS, unsupported action, or your selection).
|
|
5086
5087
|
- **Bitbucket** (v2.30.0+, when `c3 bitbucket login` has run): `c3_bitbucket(action='list_prs|get_pr|merge_pr|...')` — self-hosted Bitbucket Data Center / Server. Token in OS keyring; mutating actions auto-log to the edit ledger.
|
|
@@ -77,6 +77,10 @@ _HUB_CONFIG_DEFAULTS = {
|
|
|
77
77
|
"ui_reap_minutes": 30,
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
# Top-bar tabs a persisted ``main_view`` may name (cli/hub_ui/components/topbar.js).
|
|
81
|
+
_MAIN_VIEWS = {"projects", "board", "ci", "creds", "tokens", "locks", "access",
|
|
82
|
+
"enforce", "sessions"}
|
|
83
|
+
|
|
80
84
|
# How often the hub reaps orphaned UI servers and chases autostart projects.
|
|
81
85
|
_UI_SWEEP_INTERVAL_S = 60
|
|
82
86
|
|
|
@@ -348,6 +352,7 @@ _HUB_JS_FILES = [
|
|
|
348
352
|
"hub_ui/components/hub_locks.js",
|
|
349
353
|
"hub_ui/components/hub_access.js",
|
|
350
354
|
"hub_ui/components/hub_enforcement.js",
|
|
355
|
+
"hub_ui/components/hub_sessions.js",
|
|
351
356
|
"hub_ui/components/hub_ci.js",
|
|
352
357
|
"hub_ui/components/drill_subprojects.js",
|
|
353
358
|
"hub_ui/components/drill_health.js",
|
|
@@ -447,9 +452,11 @@ def api_hub_config_set():
|
|
|
447
452
|
cfg["projects_view"] = projects_view
|
|
448
453
|
if "main_view" in data:
|
|
449
454
|
main_view = str(data["main_view"]).strip().lower()
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
455
|
+
# Every tab the top bar offers. ci, tokens and access were missing, so
|
|
456
|
+
# choosing one of those tabs 400'd here and never survived a reload.
|
|
457
|
+
if main_view not in _MAIN_VIEWS:
|
|
458
|
+
return jsonify({"error": "main_view must be one of: "
|
|
459
|
+
+ ", ".join(sorted(_MAIN_VIEWS))}), 400
|
|
453
460
|
cfg["main_view"] = main_view
|
|
454
461
|
if "oracle_url" in data:
|
|
455
462
|
cfg["oracle_url"] = str(data["oracle_url"]).strip()
|
|
@@ -777,45 +784,9 @@ def api_launch_ide():
|
|
|
777
784
|
kwargs = {"start_new_session": True}
|
|
778
785
|
subprocess.Popen([cmd, str(path)], **kwargs)
|
|
779
786
|
else:
|
|
780
|
-
# Terminal CLIs: open a new terminal window running the command
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
win_cmd = cmd
|
|
784
|
-
|
|
785
|
-
# Try Windows Terminal first, fall back to cmd
|
|
786
|
-
try:
|
|
787
|
-
# Windows Terminal 'wt' needs a full command to run
|
|
788
|
-
# We wrap the command in 'cmd /k' so the terminal stays open
|
|
789
|
-
subprocess.Popen(
|
|
790
|
-
["wt", "-d", str(path), "cmd", "/k", win_cmd],
|
|
791
|
-
creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP,
|
|
792
|
-
)
|
|
793
|
-
except FileNotFoundError:
|
|
794
|
-
# Fallback to classic cmd.exe
|
|
795
|
-
subprocess.Popen(
|
|
796
|
-
["cmd", "/c", "start", "", "cmd", "/k", win_cmd],
|
|
797
|
-
cwd=str(path),
|
|
798
|
-
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
|
|
799
|
-
)
|
|
800
|
-
elif sys.platform == "darwin":
|
|
801
|
-
script = (
|
|
802
|
-
f'tell application "Terminal" to do script '
|
|
803
|
-
f'"cd {shlex.quote(str(path))} && {cmd}"'
|
|
804
|
-
)
|
|
805
|
-
subprocess.Popen(["osascript", "-e", script])
|
|
806
|
-
else:
|
|
807
|
-
q = shlex.quote(str(path))
|
|
808
|
-
for term_args in [
|
|
809
|
-
["gnome-terminal", "--", "bash", "-c", f"cd {q} && {cmd}; exec bash"],
|
|
810
|
-
["xterm", "-e", f"bash -c 'cd {q} && {cmd}; exec bash'"],
|
|
811
|
-
["konsole", "-e", "bash", "-c", f"cd {q} && {cmd}; exec bash"],
|
|
812
|
-
["xfce4-terminal", "--command", f"bash -c 'cd {q} && {cmd}; exec bash'"],
|
|
813
|
-
]:
|
|
814
|
-
try:
|
|
815
|
-
subprocess.Popen(term_args, start_new_session=True)
|
|
816
|
-
break
|
|
817
|
-
except FileNotFoundError:
|
|
818
|
-
continue
|
|
787
|
+
# Terminal CLIs: open a new terminal window running the command.
|
|
788
|
+
from services.terminal_launch import spawn_terminal
|
|
789
|
+
spawn_terminal(path, [cmd])
|
|
819
790
|
|
|
820
791
|
return jsonify({"launched": True})
|
|
821
792
|
except Exception as e:
|
|
@@ -3658,8 +3629,10 @@ def api_hub_access():
|
|
|
3658
3629
|
"""Effective Access Guard rules + override policy for one project.
|
|
3659
3630
|
|
|
3660
3631
|
Read-only companion to the approvals list: the per-project mode matrix
|
|
3661
|
-
the tab renders under the pending cards.
|
|
3662
|
-
|
|
3632
|
+
the tab renders under the pending cards. This route never writes; rule
|
|
3633
|
+
mutation from the Hub is ``/api/hub/access/rule`` (add) and
|
|
3634
|
+
``/api/hub/access/rule/remove`` (v2.142.0), besides the per-project
|
|
3635
|
+
server and the CLI.
|
|
3663
3636
|
"""
|
|
3664
3637
|
from services import access_guard
|
|
3665
3638
|
from services import override_policy as opol
|
|
@@ -3679,6 +3652,180 @@ def api_hub_access():
|
|
|
3679
3652
|
"policy": policy})
|
|
3680
3653
|
|
|
3681
3654
|
|
|
3655
|
+
# ── Access Guard by file type, across projects (v2.142.0) ─────────────────
|
|
3656
|
+
# The desktop surface for path rules. The phone's /api/mobile/access/rule
|
|
3657
|
+
# cannot carry a bulk edit — 12 security calls a minute and no global scope,
|
|
3658
|
+
# both on purpose for a device that leaves the building — and the per-project
|
|
3659
|
+
# server only runs while its project's UI is open. So the Hub, loopback and
|
|
3660
|
+
# human-only, gains the same two verbs with the same asymmetry: adding a rule
|
|
3661
|
+
# tightens and is one call; removing a deny rule, or ANY global-scope rule,
|
|
3662
|
+
# needs the glob retyped. Every write is audited on the target (a global
|
|
3663
|
+
# write in ~/.c3, since it has no single target project).
|
|
3664
|
+
|
|
3665
|
+
def _hub_access_audit(action: str, glob: str, kind: str, scope: str,
|
|
3666
|
+
project) -> None:
|
|
3667
|
+
"""Globs only — never file content. Failure-safe. Mirrors the phone's
|
|
3668
|
+
``_access_audit`` with ``via='hub'``."""
|
|
3669
|
+
detail = {"kind": "access", "action": action, "glob": glob,
|
|
3670
|
+
"rule_kind": kind, "scope": scope, "via": "hub"}
|
|
3671
|
+
if project is not None:
|
|
3672
|
+
try:
|
|
3673
|
+
from services.activity_log import ActivityLog as _AL
|
|
3674
|
+
_AL(str(project)).log("access_action", dict(detail))
|
|
3675
|
+
except Exception:
|
|
3676
|
+
pass
|
|
3677
|
+
try:
|
|
3678
|
+
from services.edit_ledger import EditLedger
|
|
3679
|
+
EditLedger(str(project)).log_edit(
|
|
3680
|
+
file=f"access://{glob}", change_type=f"access_{action}",
|
|
3681
|
+
summary=f"{action} {kind} rule {glob} ({scope}) via the Hub",
|
|
3682
|
+
tags=["access", action], detail=dict(detail))
|
|
3683
|
+
except Exception:
|
|
3684
|
+
pass
|
|
3685
|
+
if scope == "global":
|
|
3686
|
+
try:
|
|
3687
|
+
from services import credential_store as cred_store
|
|
3688
|
+
from services.activity_log import ActivityLog as _AL
|
|
3689
|
+
home = cred_store.global_base()
|
|
3690
|
+
if home is not None:
|
|
3691
|
+
_AL(str(home)).log("access_action", dict(detail))
|
|
3692
|
+
except Exception:
|
|
3693
|
+
pass
|
|
3694
|
+
|
|
3695
|
+
|
|
3696
|
+
def _hub_access_target(data: dict):
|
|
3697
|
+
"""``(scope, project_path_or_None, error_response_or_None)``."""
|
|
3698
|
+
scope = str(data.get("scope") or "project").strip().lower()
|
|
3699
|
+
if scope not in ("project", "global"):
|
|
3700
|
+
return scope, None, (jsonify(
|
|
3701
|
+
{"error": "scope must be 'project' or 'global'"}), 400)
|
|
3702
|
+
if scope == "global":
|
|
3703
|
+
return scope, None, None
|
|
3704
|
+
raw = str(data.get("path") or "").strip()
|
|
3705
|
+
if not raw:
|
|
3706
|
+
return scope, None, (jsonify(
|
|
3707
|
+
{"error": "path is required for project scope"}), 400)
|
|
3708
|
+
try:
|
|
3709
|
+
resolved = _resolve_project_path(raw)
|
|
3710
|
+
except ValueError as e:
|
|
3711
|
+
return scope, None, (jsonify({"error": str(e)}), 404)
|
|
3712
|
+
# set_rule would create .c3/config.json in any directory it is handed;
|
|
3713
|
+
# a rule in a folder C3 does not manage protects nothing and says it does.
|
|
3714
|
+
if not (Path(resolved) / ".c3").is_dir():
|
|
3715
|
+
return scope, None, (jsonify(
|
|
3716
|
+
{"error": "not initialized for C3", "needs_init": True}), 409)
|
|
3717
|
+
return scope, str(resolved), None
|
|
3718
|
+
|
|
3719
|
+
|
|
3720
|
+
@app.route("/api/hub/access/overview", methods=["GET"])
|
|
3721
|
+
def api_hub_access_overview():
|
|
3722
|
+
"""Every registered project's own path rules, plus global and builtin.
|
|
3723
|
+
|
|
3724
|
+
Per-row isolation like the enforcement and policy overviews: a project we
|
|
3725
|
+
could not read reports ``error`` rather than an empty rule list — "no
|
|
3726
|
+
rules" is a claim about a repo, and we would be making it blind. A corrupt
|
|
3727
|
+
scope is reported as corrupt: it evaluates deny-all until repaired by
|
|
3728
|
+
hand, which is the opposite of what an empty list would suggest.
|
|
3729
|
+
Builtin rules are read once, from the global realm; a project-scope
|
|
3730
|
+
builtin mode (set with the CLI) is not reflected per row.
|
|
3731
|
+
"""
|
|
3732
|
+
empty = {"deny": [], "read_only": [], "confirm": [], "mask": 0,
|
|
3733
|
+
"corrupt": False}
|
|
3734
|
+
rows = []
|
|
3735
|
+
for p in _pm().list_projects():
|
|
3736
|
+
ppath = str(p.get("path") or "")
|
|
3737
|
+
row = {"name": p.get("name") or Path(ppath).name, "path": ppath,
|
|
3738
|
+
"initialized": True, "error": None, "rules": dict(empty)}
|
|
3739
|
+
try:
|
|
3740
|
+
if not (Path(ppath) / ".c3").is_dir():
|
|
3741
|
+
row["initialized"] = False
|
|
3742
|
+
else:
|
|
3743
|
+
row["rules"] = access_guard.scope_rules("project", ppath)
|
|
3744
|
+
except Exception as e:
|
|
3745
|
+
row["error"] = str(e)
|
|
3746
|
+
rows.append(row)
|
|
3747
|
+
|
|
3748
|
+
try:
|
|
3749
|
+
global_rules = {**access_guard.scope_rules("global"), "error": None}
|
|
3750
|
+
except Exception as e:
|
|
3751
|
+
global_rules = {**empty, "error": str(e)}
|
|
3752
|
+
try:
|
|
3753
|
+
home = access_guard._global_base()
|
|
3754
|
+
b = access_guard.list_rules(str(home) if home else ".")["builtin"]
|
|
3755
|
+
builtin = {"deny": list(b.get("deny") or []),
|
|
3756
|
+
"read_only": list(b.get("read_only") or []),
|
|
3757
|
+
"confirm": list(b.get("confirm") or []), "error": None}
|
|
3758
|
+
except Exception as e:
|
|
3759
|
+
builtin = {"deny": [], "read_only": [], "confirm": [], "error": str(e)}
|
|
3760
|
+
|
|
3761
|
+
return jsonify({
|
|
3762
|
+
"projects": rows,
|
|
3763
|
+
"global": global_rules,
|
|
3764
|
+
"builtin": builtin,
|
|
3765
|
+
# Strictest last. "allow" is the absence of a rule, not a kind.
|
|
3766
|
+
"kinds": ["confirm", "read_only", "deny"],
|
|
3767
|
+
"coverage_note": access_guard.COVERAGE_MATRIX,
|
|
3768
|
+
})
|
|
3769
|
+
|
|
3770
|
+
|
|
3771
|
+
@app.route("/api/hub/access/rule", methods=["POST"])
|
|
3772
|
+
def api_hub_access_rule_add():
|
|
3773
|
+
"""Add one deny / read_only / confirm rule. Tightening — no confirmation.
|
|
3774
|
+
|
|
3775
|
+
Body: ``{path?, scope?, glob, kind}``. ``added: false`` when an equivalent
|
|
3776
|
+
glob is already there (a 200, not an error: the caller asked for the
|
|
3777
|
+
state it is in).
|
|
3778
|
+
"""
|
|
3779
|
+
data = request.get_json(silent=True) or {}
|
|
3780
|
+
scope, project, err = _hub_access_target(data)
|
|
3781
|
+
if err:
|
|
3782
|
+
return err
|
|
3783
|
+
glob = str(data.get("glob") or "")
|
|
3784
|
+
kind = str(data.get("kind") or "").strip()
|
|
3785
|
+
try:
|
|
3786
|
+
result = access_guard.set_rule(glob, kind, scope, project or ".")
|
|
3787
|
+
except ValueError as exc:
|
|
3788
|
+
return jsonify({"error": str(exc)}), 400
|
|
3789
|
+
if result["added"]:
|
|
3790
|
+
_hub_access_audit("add", result["glob"], kind, scope, project)
|
|
3791
|
+
return jsonify({"rule": result})
|
|
3792
|
+
|
|
3793
|
+
|
|
3794
|
+
@app.route("/api/hub/access/rule/remove", methods=["POST"])
|
|
3795
|
+
def api_hub_access_rule_remove():
|
|
3796
|
+
"""Remove one rule. Loosening.
|
|
3797
|
+
|
|
3798
|
+
Body: ``{path?, scope?, glob, kind, confirm?}``. A ``deny`` rule, and any
|
|
3799
|
+
rule in the GLOBAL scope (it governs every project on the machine), needs
|
|
3800
|
+
``confirm`` equal to the glob — the CLI's "type the glob again". A
|
|
3801
|
+
read_only or confirm rule in one project does not: it downgrades writes
|
|
3802
|
+
to writable-or-ask, not to fully visible. POST rather than DELETE so the
|
|
3803
|
+
body survives every client.
|
|
3804
|
+
"""
|
|
3805
|
+
data = request.get_json(silent=True) or {}
|
|
3806
|
+
scope, project, err = _hub_access_target(data)
|
|
3807
|
+
if err:
|
|
3808
|
+
return err
|
|
3809
|
+
glob = str(data.get("glob") or "")
|
|
3810
|
+
kind = str(data.get("kind") or "").strip()
|
|
3811
|
+
canon = access_guard._norm_glob(glob)
|
|
3812
|
+
if kind == "deny" or scope == "global":
|
|
3813
|
+
if access_guard._norm_glob(data.get("confirm")) != canon or not canon:
|
|
3814
|
+
return jsonify({
|
|
3815
|
+
"error": ("removing a deny rule weakens protection"
|
|
3816
|
+
if kind == "deny" else
|
|
3817
|
+
"removing a global rule weakens every project"),
|
|
3818
|
+
"needs_confirmation": True, "confirm_with": canon,
|
|
3819
|
+
}), 400
|
|
3820
|
+
try:
|
|
3821
|
+
result = access_guard.remove_rule(glob, kind, scope, project or ".")
|
|
3822
|
+
except ValueError as exc:
|
|
3823
|
+
return jsonify({"error": str(exc)}), 400
|
|
3824
|
+
if result["removed"]:
|
|
3825
|
+
_hub_access_audit("remove", result["glob"], kind, scope, project)
|
|
3826
|
+
return jsonify(result)
|
|
3827
|
+
|
|
3828
|
+
|
|
3682
3829
|
# ── Project management: tasks / milestones / notes (v2.45.0) ──────────────
|
|
3683
3830
|
# Direct TaskStore per request (reload-per-op store — no runtime build needed
|
|
3684
3831
|
# for mutations); every write audited to the target project's activity log.
|
|
@@ -4632,6 +4779,164 @@ def api_sessions():
|
|
|
4632
4779
|
return jsonify({"error": str(e)}), 500
|
|
4633
4780
|
|
|
4634
4781
|
|
|
4782
|
+
# ─── Routes: session history (2.143.0) ──────────────────────────────────────
|
|
4783
|
+
# PAST agent sessions: find one, see what it was, resume it, mark it stale.
|
|
4784
|
+
# Not to be confused with /api/sessions* above, which manage per-project UI
|
|
4785
|
+
# servers. Loopback + the CSRF guard like every Hub route; deliberately NOT
|
|
4786
|
+
# mirrored on the Oracle gateway, which can bind to the tailnet — transcript
|
|
4787
|
+
# previews stay on this machine. See docs/sessions.md.
|
|
4788
|
+
|
|
4789
|
+
_SESSIONS_FEATURES = ["list", "detail", "mark", "note", "resume", "remote"]
|
|
4790
|
+
_SESSIONS_STALE = {"hide", "only", "likely", "all"}
|
|
4791
|
+
|
|
4792
|
+
|
|
4793
|
+
def _session_project(raw: str):
|
|
4794
|
+
"""``{name, path}`` of the REGISTERED project ``raw`` names, or None.
|
|
4795
|
+
|
|
4796
|
+
Every session route resolves its project against the registry first, so a
|
|
4797
|
+
caller can never point the catalog (or a terminal) at an arbitrary folder.
|
|
4798
|
+
"""
|
|
4799
|
+
raw = str(raw or "").strip()
|
|
4800
|
+
if not raw:
|
|
4801
|
+
return None
|
|
4802
|
+
want = os.path.normcase(os.path.normpath(raw))
|
|
4803
|
+
for p in _pm().list_projects():
|
|
4804
|
+
path = str(p.get("path") or "")
|
|
4805
|
+
if path and os.path.normcase(os.path.normpath(path)) == want:
|
|
4806
|
+
return {"name": str(p.get("name") or Path(path).name), "path": path}
|
|
4807
|
+
return None
|
|
4808
|
+
|
|
4809
|
+
|
|
4810
|
+
def _session_project_or_error(raw: str):
|
|
4811
|
+
proj = _session_project(raw)
|
|
4812
|
+
if proj is None:
|
|
4813
|
+
return None, (jsonify({"error": "not a registered project"}), 404)
|
|
4814
|
+
if not (Path(proj["path"]) / ".c3").is_dir():
|
|
4815
|
+
return None, (jsonify({"error": "C3 is not initialized in this project"}), 409)
|
|
4816
|
+
return proj, None
|
|
4817
|
+
|
|
4818
|
+
|
|
4819
|
+
@app.route("/api/hub/sessions/overview", methods=["GET"])
|
|
4820
|
+
def api_hub_sessions_overview():
|
|
4821
|
+
"""Per-project session counts for the picker. Stats files only."""
|
|
4822
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
4823
|
+
|
|
4824
|
+
from services import session_catalog as sc
|
|
4825
|
+
|
|
4826
|
+
def one(p):
|
|
4827
|
+
ppath = str(p.get("path") or "")
|
|
4828
|
+
name = str(p.get("name") or Path(ppath).name)
|
|
4829
|
+
row = {"name": name, "path": ppath, "initialized": True, "error": None,
|
|
4830
|
+
"counts": {"total": 0, "live": 0, "stale": 0, "idle": 0},
|
|
4831
|
+
"last_active": "", "newest": None, "transcripts": False}
|
|
4832
|
+
try:
|
|
4833
|
+
if not (Path(ppath) / ".c3").is_dir():
|
|
4834
|
+
row["initialized"] = False
|
|
4835
|
+
else:
|
|
4836
|
+
row.update(sc.overview(ppath, name=name))
|
|
4837
|
+
except Exception as e:
|
|
4838
|
+
row["error"] = str(e)
|
|
4839
|
+
return row
|
|
4840
|
+
|
|
4841
|
+
with ThreadPoolExecutor(max_workers=8) as pool:
|
|
4842
|
+
rows = list(pool.map(one, _pm().list_projects()))
|
|
4843
|
+
rows.sort(key=lambda r: r.get("last_active") or "", reverse=True)
|
|
4844
|
+
return jsonify({"projects": rows, "features": _SESSIONS_FEATURES})
|
|
4845
|
+
|
|
4846
|
+
|
|
4847
|
+
@app.route("/api/hub/sessions", methods=["GET"])
|
|
4848
|
+
def api_hub_sessions_list():
|
|
4849
|
+
"""Rows for one project (``?path=``) or every project (no path)."""
|
|
4850
|
+
from services import session_catalog as sc
|
|
4851
|
+
stale = (request.args.get("stale") or "hide").strip().lower()
|
|
4852
|
+
if stale not in _SESSIONS_STALE:
|
|
4853
|
+
return jsonify({"error": f"stale must be one of {sorted(_SESSIONS_STALE)}"}), 400
|
|
4854
|
+
try:
|
|
4855
|
+
limit = int(request.args.get("limit") or 50)
|
|
4856
|
+
except ValueError:
|
|
4857
|
+
return jsonify({"error": "limit must be an integer"}), 400
|
|
4858
|
+
q = (request.args.get("q") or "").strip()
|
|
4859
|
+
before = (request.args.get("before") or "").strip()
|
|
4860
|
+
raw = (request.args.get("path") or "").strip()
|
|
4861
|
+
try:
|
|
4862
|
+
if raw:
|
|
4863
|
+
proj, err = _session_project_or_error(raw)
|
|
4864
|
+
if err:
|
|
4865
|
+
return err
|
|
4866
|
+
res = sc.list_sessions(proj["path"], name=proj["name"], stale=stale, q=q,
|
|
4867
|
+
limit=limit, before=before)
|
|
4868
|
+
res["errors"] = []
|
|
4869
|
+
else:
|
|
4870
|
+
projects = [{"name": str(p.get("name") or ""), "path": str(p.get("path") or "")}
|
|
4871
|
+
for p in _pm().list_projects()]
|
|
4872
|
+
res = sc.list_many(projects, stale=stale, q=q, limit=limit, before=before)
|
|
4873
|
+
return jsonify(res)
|
|
4874
|
+
except Exception as e:
|
|
4875
|
+
return jsonify({"error": str(e)}), 500
|
|
4876
|
+
|
|
4877
|
+
|
|
4878
|
+
@app.route("/api/hub/sessions/detail", methods=["GET"])
|
|
4879
|
+
def api_hub_sessions_detail():
|
|
4880
|
+
from services import session_catalog as sc
|
|
4881
|
+
proj, err = _session_project_or_error(request.args.get("path") or "")
|
|
4882
|
+
if err:
|
|
4883
|
+
return err
|
|
4884
|
+
res = sc.get_session(proj["path"], request.args.get("id") or "", name=proj["name"])
|
|
4885
|
+
if "error" in res:
|
|
4886
|
+
return jsonify(res), 404
|
|
4887
|
+
return jsonify(res)
|
|
4888
|
+
|
|
4889
|
+
|
|
4890
|
+
@app.route("/api/hub/sessions/mark", methods=["POST"])
|
|
4891
|
+
def api_hub_sessions_mark():
|
|
4892
|
+
"""Body: {path, id, op: stale|unstale|note, reason?, successor?,
|
|
4893
|
+
summary?, next_steps?}. Recorded as ``by: user``."""
|
|
4894
|
+
from services import session_catalog as sc
|
|
4895
|
+
data = request.get_json(force=True) or {}
|
|
4896
|
+
proj, err = _session_project_or_error(data.get("path") or "")
|
|
4897
|
+
if err:
|
|
4898
|
+
return err
|
|
4899
|
+
res = sc.mark(proj["path"], str(data.get("id") or ""), str(data.get("op") or ""),
|
|
4900
|
+
reason=str(data.get("reason") or ""),
|
|
4901
|
+
successor=str(data.get("successor") or ""),
|
|
4902
|
+
summary=str(data.get("summary") or ""),
|
|
4903
|
+
next_steps=str(data.get("next_steps") or ""), by="user")
|
|
4904
|
+
if "error" in res:
|
|
4905
|
+
return jsonify({"error": res["error"]}), int(res.get("status") or 400)
|
|
4906
|
+
return jsonify(res)
|
|
4907
|
+
|
|
4908
|
+
|
|
4909
|
+
@app.route("/api/hub/sessions/resume", methods=["POST"])
|
|
4910
|
+
def api_hub_sessions_resume():
|
|
4911
|
+
"""Body: {path, id}. Opens a terminal running ``claude --resume <id>``.
|
|
4912
|
+
|
|
4913
|
+
The command is built by the catalog from a validated id — nothing from the
|
|
4914
|
+
request reaches the command line. 409 while the session is open.
|
|
4915
|
+
"""
|
|
4916
|
+
from services import session_catalog as sc
|
|
4917
|
+
from services import terminal_launch
|
|
4918
|
+
data = request.get_json(force=True) or {}
|
|
4919
|
+
proj, err = _session_project_or_error(data.get("path") or "")
|
|
4920
|
+
if err:
|
|
4921
|
+
return err
|
|
4922
|
+
spec = sc.resume_spec(proj["path"], str(data.get("id") or ""))
|
|
4923
|
+
if "error" in spec:
|
|
4924
|
+
return jsonify({"error": spec["error"]}), int(spec.get("status") or 404)
|
|
4925
|
+
try:
|
|
4926
|
+
terminal_launch.spawn_terminal(spec["cwd"], spec["argv"])
|
|
4927
|
+
except Exception as e:
|
|
4928
|
+
return jsonify({"error": f"could not open a terminal: {e}",
|
|
4929
|
+
"command": spec["command"]}), 500
|
|
4930
|
+
try:
|
|
4931
|
+
from services.activity_log import ActivityLog
|
|
4932
|
+
ActivityLog(proj["path"]).log("session_resume", {
|
|
4933
|
+
"host_session_id": spec["id"], "by": "user", "cwd": spec["cwd"]})
|
|
4934
|
+
except Exception:
|
|
4935
|
+
pass
|
|
4936
|
+
return jsonify({"launched": True, "id": spec["id"], "command": spec["command"],
|
|
4937
|
+
"cwd": spec["cwd"]})
|
|
4938
|
+
|
|
4939
|
+
|
|
4635
4940
|
# ─── Error handlers ──────────────────────────────────────────────────────────
|
|
4636
4941
|
|
|
4637
4942
|
@app.errorhandler(404)
|
|
@@ -17,7 +17,7 @@ function App() {
|
|
|
17
17
|
const [version, setVersion] = useState('');
|
|
18
18
|
const [projects, setProjects] = useState([]);
|
|
19
19
|
const [loaded, setLoaded] = useState(false);
|
|
20
|
-
const [mainView, setMainView] = useState('projects'); // projects | board | ci | creds | locks | enforce
|
|
20
|
+
const [mainView, setMainView] = useState('projects'); // projects | board | ci | creds | tokens | locks | access | enforce | sessions
|
|
21
21
|
const [filter, setFilter] = useState('all'); // all | active | idle | tag:<x>
|
|
22
22
|
const [search, setSearch] = useState('');
|
|
23
23
|
const [view, setView] = useState('list'); // list | grid
|
|
@@ -44,7 +44,7 @@ function App() {
|
|
|
44
44
|
if (cfg.projects_view === 'grid') setView('grid');
|
|
45
45
|
if (cfg.sidebar_collapsed != null) setSidebarCollapsed(!!cfg.sidebar_collapsed);
|
|
46
46
|
if (cfg.sidebar_group) setFilter(cfg.sidebar_group);
|
|
47
|
-
if (['board', 'ci', 'creds', 'tokens', 'locks', 'access', 'enforce'].includes(cfg.main_view)) setMainView(cfg.main_view);
|
|
47
|
+
if (['board', 'ci', 'creds', 'tokens', 'locks', 'access', 'enforce', 'sessions'].includes(cfg.main_view)) setMainView(cfg.main_view);
|
|
48
48
|
} catch { }
|
|
49
49
|
try { const v = await api.get('/api/version'); setVersion(v.c3_version || ''); } catch { }
|
|
50
50
|
}, []);
|
|
@@ -124,6 +124,8 @@ function App() {
|
|
|
124
124
|
<HubAccess projects={projects} />
|
|
125
125
|
) : mainView === 'enforce' ? (
|
|
126
126
|
<HubEnforcement projects={projects} onOpenDrill={openDrill} />
|
|
127
|
+
) : mainView === 'sessions' ? (
|
|
128
|
+
<HubSessions projects={projects} />
|
|
127
129
|
) : (
|
|
128
130
|
<React.Fragment>
|
|
129
131
|
<SummaryBar projects={projects} search={search} setSearch={setSearch}
|