code-context-control 2.145.2__tar.gz → 2.149.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.145.2 → code_context_control-2.149.1}/PKG-INFO +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/c3.py +3 -3
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_access_guard.py +1 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_server.py +259 -43
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/app.js +4 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_access.js +119 -2
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_credentials.js +21 -14
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/modals.js +34 -12
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/settings_modal.js +11 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/state.js +7 -3
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui.html +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/mcp_server.py +11 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/server.py +4 -4
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/credentials.py +1 -2
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui.html +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/PKG-INFO +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/SOURCES.txt +4 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/pyproject.toml +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/access_guard.py +60 -4
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/activity_log.py +43 -15
- code_context_control-2.149.1/services/builtin_leases.py +182 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_act.py +22 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_workflow.py +5 -2
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/credential_backup.py +9 -3
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/credential_store.py +72 -10
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/project_manager.py +19 -2
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_catalog.py +82 -34
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_activity_log_find_last.py +29 -1
- code_context_control-2.149.1/tests/test_builtin_leases.py +210 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_act.py +27 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_cred_audit.py +2 -2
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credential_store.py +50 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_access_routes.py +1 -1
- code_context_control-2.149.1/tests/test_hub_builtin_routes.py +163 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_credentials_routes_write.py +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_enforcement_routes.py +1 -1
- code_context_control-2.149.1/tests/test_hub_ide_cmd.py +125 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_locks_routes.py +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_rules_routes.py +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_sessions_routes.py +1 -1
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_catalog.py +30 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_token_tracking.py +2 -2
- {code_context_control-2.145.2 → code_context_control-2.149.1}/LICENSE +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/README.md +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/_hook_utils.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/_shell_writes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/commands/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/commands/common.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/commands/parser.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/docs.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/edits.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/access.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/ci.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/credentials.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/delegate.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/index.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/jira.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/masking.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/oracle.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/sessions.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/shared.css +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/tools.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/workflow.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_agent_model.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_artifact.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_c3read.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_codex_lifecycle.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_filter.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_read.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_session_end.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_session_open.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_sessions.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/progress.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/_grants.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/agent.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/ci.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/compress.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/delegate.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/edit.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/edits.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/federate.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/filter.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/impact.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/jira.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/locks.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/memory.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/override.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/project.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/read.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/search.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/session.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell_job.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell_nudge.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell_parsers.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell_render.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/status.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/tasks.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/validate.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/api.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/app.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/access.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/icons.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/shared.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/theme.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui_legacy.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui_nano.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/codex_patch.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/config.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/grok_payload.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/hook_command.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/host.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/ide.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/mcp_toml.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/core/web_security.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/config.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/listeners.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/oracle_server.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/client_tokens.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/local_session.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/mobile_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/activity.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/agents.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/app.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/busy.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/core.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/header.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/insights.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/projects.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/settings.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/access_telemetry.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agent_base.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agent_downshift.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agent_locks.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agents.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agents_workflow.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/artifact_defs.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/artifact_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/atomic_json.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/auto_memory.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/background_service.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/delegate_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/delegate_write_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/map_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/search_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/shell_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bitbucket_client.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_cache.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_expr.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_failures.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_github.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_impact.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_intel.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_runner.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/circuit_breaker.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/claude_md.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/codex_integration.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/codex_transcript.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/compressor.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/context_snapshot.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/conversation_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/cred_audit.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/cred_telemetry.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/delegate_agents.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/delegate_hints.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/delegate_write.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/dir_map.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/doc_index.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/e2e_tasks.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/edit_ledger.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/embedding_index.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/enforcement_policy.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/error_reporting.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/file_map.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/file_memory.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/git_context.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/grok_integration.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/grok_transcript.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/host_sessions.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/hub_service.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/index_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/indexer.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_client.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_cloud.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_credentials.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_data_center.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_links.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/lexical_index.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/mask_activation.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/mask_mirror.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/mask_presets.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_consolidator.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_distiller.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_graph.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_grounder.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_queue.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_scorer.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/metrics.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/notifications.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ollama_bridge.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ollama_client.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ollama_credentials.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/oracle_service.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/output_filter.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_costs.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_grants.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_policy.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_requests.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_wake.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/parser.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/project_runtime.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/protocol.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/proxy_state.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/repo_map.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/repo_shape.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/reranker.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/retention.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/retrieval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/retrieval_broker.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/router.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/runtime.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/scanner.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_benchmark.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_live.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_manager.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_preloader.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/shell_jobs.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/shell_output.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/subprojects.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/task_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/telemetry.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/terminal_launch.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/text_index.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/time_tracker.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/tool_classifier.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/transcript_index.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/validation_cache.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/vector_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/watcher.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/services/win_subprocess.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/setup.cfg +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_atomic_json.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_background_service.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_builtin_modes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_dag_ownership.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_claude_md_updater.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_codex_mcp_transport.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_codex_native.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_confirm_guard.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_confirm_guard_wiring.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credential_backup.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_adoption_d4.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_auto.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_claude_d1.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_grok.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_host_d2.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_scout_d3.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_telemetry_d0.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_thinking_cap.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_tuning.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_write.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_write_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_dir_map_c3.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_embedding_index_corrupt_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_env_parser.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_file_map_c1.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_grok_native.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_grok_compat.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_session_end.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_state.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_hook_migration.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_override_policy_routes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_override_routes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_index_cap_not_hardcoded.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_init_scan.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_client.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_links.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_large_files_c4.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_map_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_map_telemetry_c0.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_memory_system.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_clients.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_jobs_ci.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_override_costs.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_security_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_notification_kinds.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_loopback.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_output_filter.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_costs.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_grants.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_requests.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_wake.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_permissions.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_pm_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_project_manager.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_project_tool.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_read_outside_root.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_related_facts.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_repo_map.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_retention.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_review_digest.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p1.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p2.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p2b.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p3.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p4.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p5.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_service_durability.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_budget.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_live.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_tool.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_budget_s1.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_eval.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_jobs_s3.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_nudge_s4.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_output.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_parsers_s2.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_telemetry_s0.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_clear_scope.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_depth_consumers.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_linkage_api.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subprojects.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_task_store.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_task_tool.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ui_jsx_syntax.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_validate.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_version_sync.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_watcher_pruning.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_web_security.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/backend.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/main.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/__init__.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/index_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/init_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/search_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/session_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/stats.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.145.2 → code_context_control-2.149.1}/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.149.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
|
|
@@ -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.149.1"
|
|
95
95
|
|
|
96
96
|
# The PreToolUse matcher for native subagent calls (installer and hub migration).
|
|
97
97
|
AGENT_MATCHER = "Agent|Task"
|
|
@@ -6685,10 +6685,10 @@ def _creds_cmd_list(args, project_path: str) -> None:
|
|
|
6685
6685
|
"(add --global for all projects).")
|
|
6686
6686
|
return
|
|
6687
6687
|
print(f"{len(entries)} credential(s) — project scope shadows global:")
|
|
6688
|
+
present = cred_store.presence_for(entries, project_path)
|
|
6688
6689
|
missing = 0
|
|
6689
6690
|
for name, entry in entries.items():
|
|
6690
|
-
gone = not
|
|
6691
|
-
name, project_path=project_path, scope=entry["scope"])
|
|
6691
|
+
gone = not present[name]
|
|
6692
6692
|
missing += gone
|
|
6693
6693
|
print(" " + _creds_entry_line(name, entry, gone))
|
|
6694
6694
|
if missing:
|
|
@@ -447,6 +447,7 @@ def run(payload: dict, project_path: Path | None = None,
|
|
|
447
447
|
tool_input = payload.get("tool_input", {}) or {}
|
|
448
448
|
base = str(project_path if project_path is not None else Path.cwd())
|
|
449
449
|
session_id = str(payload.get("session_id") or "")
|
|
450
|
+
ag.bind_session(session_id)
|
|
450
451
|
|
|
451
452
|
if tool in _WRITE_TOOLS or tool in _READ_TOOLS:
|
|
452
453
|
fp = _target(tool_input)
|
|
@@ -72,6 +72,10 @@ _HUB_CONFIG_DEFAULTS = {
|
|
|
72
72
|
"projects_view": "list",
|
|
73
73
|
"main_view": "projects",
|
|
74
74
|
"oracle_url": "",
|
|
75
|
+
# Per-IDE launch command overrides, e.g. {"claude-code": "yep"} when the
|
|
76
|
+
# agent is started through a wrapper script instead of the stock binary.
|
|
77
|
+
# A project's own `ide_cmd` (projects.json) wins over this.
|
|
78
|
+
"ide_cmds": {},
|
|
75
79
|
# Minutes of project silence, with no session heartbeat left, before a UI
|
|
76
80
|
# server that an IDE session launched is stopped. 0 = never reap.
|
|
77
81
|
"ui_reap_minutes": 30,
|
|
@@ -81,6 +85,48 @@ _HUB_CONFIG_DEFAULTS = {
|
|
|
81
85
|
_MAIN_VIEWS = {"projects", "board", "ci", "creds", "tokens", "locks", "access",
|
|
82
86
|
"enforce", "sessions"}
|
|
83
87
|
|
|
88
|
+
# Stock command per IDE id, and whether it takes the project path as an
|
|
89
|
+
# argument (GUI) instead of being run inside a terminal at that path.
|
|
90
|
+
_IDE_DEFAULT_CMDS = {
|
|
91
|
+
"claude-code": ("claude", False),
|
|
92
|
+
"claude-app": ("claude-app", True),
|
|
93
|
+
"codex": ("codex", False),
|
|
94
|
+
"grok": ("grok", False),
|
|
95
|
+
"gemini": ("gemini", False),
|
|
96
|
+
"antigravity": ("antigravity", False),
|
|
97
|
+
"vscode": ("code", True),
|
|
98
|
+
"cursor": ("cursor", True),
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _resolve_ide_cmd(ide: str, path: str, custom_cmd: str = "") -> tuple:
|
|
103
|
+
"""Resolve the command to launch for `ide` in `path`.
|
|
104
|
+
|
|
105
|
+
Precedence: explicit custom_cmd (this launch) → the project's stored
|
|
106
|
+
`ide_cmd` → hub config `ide_cmds[ide]` → the stock command.
|
|
107
|
+
Returns (cmd, is_gui, error) — error is a message when nothing resolves.
|
|
108
|
+
"""
|
|
109
|
+
default_cmd, is_gui = _IDE_DEFAULT_CMDS.get(ide, ("", False))
|
|
110
|
+
if ide != "custom" and not default_cmd:
|
|
111
|
+
return "", False, f"Unknown IDE: {ide}"
|
|
112
|
+
cmd = (custom_cmd or "").strip()
|
|
113
|
+
if not cmd:
|
|
114
|
+
try:
|
|
115
|
+
cmd = _pm().get_ide_cmd(path)
|
|
116
|
+
except Exception:
|
|
117
|
+
cmd = ""
|
|
118
|
+
if not cmd:
|
|
119
|
+
overrides = _read_hub_config().get("ide_cmds") or {}
|
|
120
|
+
if isinstance(overrides, dict):
|
|
121
|
+
cmd = str(overrides.get(ide) or "").strip()
|
|
122
|
+
if not cmd:
|
|
123
|
+
cmd = default_cmd
|
|
124
|
+
if not cmd:
|
|
125
|
+
return "", False, "custom_cmd is required for custom IDE"
|
|
126
|
+
# An overridden command replaces the binary, not the launch style: a
|
|
127
|
+
# wrapper for a terminal CLI is still a terminal CLI.
|
|
128
|
+
return cmd, is_gui, ""
|
|
129
|
+
|
|
84
130
|
# How often the hub reaps orphaned UI servers and chases autostart projects.
|
|
85
131
|
_UI_SWEEP_INTERVAL_S = 60
|
|
86
132
|
|
|
@@ -460,6 +506,15 @@ def api_hub_config_set():
|
|
|
460
506
|
cfg["main_view"] = main_view
|
|
461
507
|
if "oracle_url" in data:
|
|
462
508
|
cfg["oracle_url"] = str(data["oracle_url"]).strip()
|
|
509
|
+
if "ide_cmds" in data:
|
|
510
|
+
raw = data["ide_cmds"]
|
|
511
|
+
if not isinstance(raw, dict):
|
|
512
|
+
return jsonify({"error": "ide_cmds must be an object"}), 400
|
|
513
|
+
# Empty string = "back to the stock command", so the key is dropped
|
|
514
|
+
# rather than stored blank.
|
|
515
|
+
cfg["ide_cmds"] = {
|
|
516
|
+
str(k): str(v).strip() for k, v in raw.items() if str(v or "").strip()
|
|
517
|
+
}
|
|
463
518
|
if "sidebar_group" in data:
|
|
464
519
|
cfg["sidebar_group"] = str(data["sidebar_group"]).strip()
|
|
465
520
|
if "sidebar_collapsed" in data:
|
|
@@ -718,17 +773,11 @@ def api_projects_open():
|
|
|
718
773
|
|
|
719
774
|
@app.route("/api/projects/launch-ide", methods=["POST"])
|
|
720
775
|
def api_launch_ide():
|
|
721
|
-
"""Launch an IDE or CLI tool in the project directory. Body: {path, ide, custom_cmd?}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
"grok": ("grok", False),
|
|
727
|
-
"gemini": ("gemini", False),
|
|
728
|
-
"antigravity": ("antigravity", False),
|
|
729
|
-
"vscode": ("code", True),
|
|
730
|
-
"cursor": ("cursor", True),
|
|
731
|
-
}
|
|
776
|
+
"""Launch an IDE or CLI tool in the project directory. Body: {path, ide, custom_cmd?}
|
|
777
|
+
|
|
778
|
+
The command itself is resolved by _resolve_ide_cmd, so a project or the
|
|
779
|
+
hub can point `claude-code` at a wrapper such as `yep`.
|
|
780
|
+
"""
|
|
732
781
|
try:
|
|
733
782
|
data = request.get_json(force=True) or {}
|
|
734
783
|
path_str = (data.get("path") or "").strip()
|
|
@@ -744,14 +793,9 @@ def api_launch_ide():
|
|
|
744
793
|
if not path.exists():
|
|
745
794
|
return jsonify({"error": f"Path does not exist: {path_str}"}), 404
|
|
746
795
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
cmd, is_gui = custom_cmd, False
|
|
751
|
-
elif ide in _IDE_CMDS:
|
|
752
|
-
cmd, is_gui = _IDE_CMDS[ide]
|
|
753
|
-
else:
|
|
754
|
-
return jsonify({"error": f"Unknown IDE: {ide}"}), 400
|
|
796
|
+
cmd, is_gui, err = _resolve_ide_cmd(ide, str(path), custom_cmd)
|
|
797
|
+
if err:
|
|
798
|
+
return jsonify({"error": err}), 400
|
|
755
799
|
|
|
756
800
|
if is_gui:
|
|
757
801
|
# GUI IDEs (VS Code, Cursor) accept a path argument directly
|
|
@@ -795,7 +839,7 @@ def api_launch_ide():
|
|
|
795
839
|
|
|
796
840
|
@app.route("/api/projects/update", methods=["POST"])
|
|
797
841
|
def api_projects_update():
|
|
798
|
-
"""Update editable project fields
|
|
842
|
+
"""Update editable project fields. Body: {path, name?, tags?, notes?, ide_cmd?}"""
|
|
799
843
|
data = request.get_json(force=True) or {}
|
|
800
844
|
path = (data.get("path") or "").strip()
|
|
801
845
|
if not path:
|
|
@@ -812,6 +856,9 @@ def api_projects_update():
|
|
|
812
856
|
fields["tags"] = [t.strip() for t in str(raw).split(",") if t.strip()]
|
|
813
857
|
if "notes" in data:
|
|
814
858
|
fields["notes"] = str(data["notes"])
|
|
859
|
+
if "ide_cmd" in data:
|
|
860
|
+
# Blank clears the override and falls back to the stock command.
|
|
861
|
+
fields["ide_cmd"] = str(data["ide_cmd"] or "").strip()
|
|
815
862
|
try:
|
|
816
863
|
ok = _pm().update_project(path, **fields)
|
|
817
864
|
return jsonify({"updated": ok})
|
|
@@ -1804,7 +1851,7 @@ def api_projects_browse():
|
|
|
1804
1851
|
return jsonify({"error": str(e)}), 400
|
|
1805
1852
|
if not resolved.is_dir():
|
|
1806
1853
|
return jsonify({"error": f"Not a directory: {resolved}"}), 404
|
|
1807
|
-
registered = {os.path.normcase(p.get("path", "")) for p in _pm().
|
|
1854
|
+
registered = {os.path.normcase(p.get("path", "")) for p in _pm().list_registered()}
|
|
1808
1855
|
dirs = []
|
|
1809
1856
|
try:
|
|
1810
1857
|
for child in sorted(resolved.iterdir(), key=lambda c: c.name.lower()):
|
|
@@ -1913,7 +1960,7 @@ def api_search_global():
|
|
|
1913
1960
|
if wanted else None)
|
|
1914
1961
|
|
|
1915
1962
|
candidates, skipped = [], []
|
|
1916
|
-
for p in _pm().
|
|
1963
|
+
for p in _pm().list_registered():
|
|
1917
1964
|
ppath = p.get("path") or ""
|
|
1918
1965
|
if wanted_norm is not None and os.path.normcase(ppath) not in wanted_norm:
|
|
1919
1966
|
continue
|
|
@@ -2138,14 +2185,15 @@ def api_projects_credentials():
|
|
|
2138
2185
|
usage = cred_store.read_usage_state(str(resolved))
|
|
2139
2186
|
home = cred_store.global_base()
|
|
2140
2187
|
global_names = set(cred_store.list_entries(str(home))) if home else set()
|
|
2188
|
+
listed = cred_store.list_entries(str(resolved))
|
|
2189
|
+
present = cred_store.presence_for(listed, str(resolved))
|
|
2141
2190
|
entries = []
|
|
2142
|
-
for name, entry in
|
|
2191
|
+
for name, entry in listed.items():
|
|
2143
2192
|
entries.append(_cred_entry_public(
|
|
2144
2193
|
name, entry, usage=usage,
|
|
2145
2194
|
shadows_global=(entry.get("scope") == "project"
|
|
2146
2195
|
and name in global_names),
|
|
2147
|
-
value_ok=
|
|
2148
|
-
name, project_path=str(resolved), scope=entry["scope"])))
|
|
2196
|
+
value_ok=present[name]))
|
|
2149
2197
|
return jsonify({"path": str(resolved), "entries": entries})
|
|
2150
2198
|
|
|
2151
2199
|
|
|
@@ -2360,7 +2408,7 @@ def api_hub_credentials_audit():
|
|
|
2360
2408
|
only_global = (request.args.get("scope") or "").strip().lower() == "global"
|
|
2361
2409
|
|
|
2362
2410
|
events, errors = [], []
|
|
2363
|
-
for p in ([] if only_global else _pm().
|
|
2411
|
+
for p in ([] if only_global else _pm().list_registered()):
|
|
2364
2412
|
ppath = str(p.get("path") or "")
|
|
2365
2413
|
if not (Path(ppath) / ".c3").is_dir():
|
|
2366
2414
|
continue
|
|
@@ -2417,9 +2465,12 @@ def api_hub_credentials_overview():
|
|
|
2417
2465
|
from services import credential_store as cred_store
|
|
2418
2466
|
home = cred_store.global_base()
|
|
2419
2467
|
global_entries = cred_store.list_entries(str(home)) if home else {}
|
|
2468
|
+
# realm -> {name: value decodes}, probed once per vault and shared with
|
|
2469
|
+
# the backup banner, which asks the same question of the same entries.
|
|
2470
|
+
present = {"global": cred_store.value_presence("global", str(home))} if home else {}
|
|
2420
2471
|
shadowed_in = {name: [] for name in global_entries}
|
|
2421
2472
|
projects_out = []
|
|
2422
|
-
for p in _pm().
|
|
2473
|
+
for p in _pm().list_registered():
|
|
2423
2474
|
ppath = str(p.get("path") or "")
|
|
2424
2475
|
row = {"name": p.get("name") or "", "path": ppath,
|
|
2425
2476
|
"initialized": True, "error": None, "entries": []}
|
|
@@ -2428,14 +2479,15 @@ def api_hub_credentials_overview():
|
|
|
2428
2479
|
row["initialized"] = False
|
|
2429
2480
|
else:
|
|
2430
2481
|
usage = cred_store.read_usage_state(ppath)
|
|
2482
|
+
ok = cred_store.value_presence("project", ppath)
|
|
2483
|
+
present[cred_store.realm("project", ppath)] = ok
|
|
2431
2484
|
for name, entry in cred_store.list_entries(ppath).items():
|
|
2432
2485
|
if entry.get("scope") != "project":
|
|
2433
2486
|
continue
|
|
2434
2487
|
row["entries"].append(_cred_entry_public(
|
|
2435
2488
|
name, entry, usage=usage,
|
|
2436
2489
|
shadows_global=name in global_entries,
|
|
2437
|
-
value_ok=
|
|
2438
|
-
name, project_path=ppath, scope="project")))
|
|
2490
|
+
value_ok=ok.get(name, False)))
|
|
2439
2491
|
if name in shadowed_in:
|
|
2440
2492
|
shadowed_in[name].append(
|
|
2441
2493
|
{"name": row["name"], "path": ppath})
|
|
@@ -2446,21 +2498,21 @@ def api_hub_credentials_overview():
|
|
|
2446
2498
|
global_out = [
|
|
2447
2499
|
{**_cred_entry_public(
|
|
2448
2500
|
name, entry, usage=global_usage,
|
|
2449
|
-
value_ok=
|
|
2450
|
-
name, project_path=str(home), scope="global")),
|
|
2501
|
+
value_ok=present.get("global", {}).get(name, False)),
|
|
2451
2502
|
"shadowed_in": shadowed_in.get(name, [])}
|
|
2452
2503
|
for name, entry in global_entries.items()
|
|
2453
2504
|
]
|
|
2454
2505
|
return jsonify({"global": {"entries": global_out}, "projects": projects_out,
|
|
2455
2506
|
"backup": _cred_backup_summary(
|
|
2456
|
-
[row["path"] for row in projects_out if row["initialized"]]
|
|
2507
|
+
[row["path"] for row in projects_out if row["initialized"]],
|
|
2508
|
+
present)})
|
|
2457
2509
|
|
|
2458
2510
|
|
|
2459
|
-
def _cred_backup_summary(project_paths) -> dict:
|
|
2511
|
+
def _cred_backup_summary(project_paths, present) -> dict:
|
|
2460
2512
|
"""Backup state as counts for the Hub banner; a broken file reports its error."""
|
|
2461
2513
|
from services import credential_backup
|
|
2462
2514
|
try:
|
|
2463
|
-
st = credential_backup.status(project_paths)
|
|
2515
|
+
st = credential_backup.status(project_paths, presence=present)
|
|
2464
2516
|
except credential_backup.BackupError as exc:
|
|
2465
2517
|
return {"enabled": True, "error": str(exc), "restorable": 0, "lost": 0}
|
|
2466
2518
|
return {"enabled": st["enabled"], "restorable": len(st["restorable"]),
|
|
@@ -2612,7 +2664,7 @@ def api_hub_tokens_overview():
|
|
|
2612
2664
|
days = _hub_tokens_days(request.args.get("days"))
|
|
2613
2665
|
rows, totals = [], {"tool_calls": 0, "tool_tokens": 0,
|
|
2614
2666
|
"session_tokens": 0, "saved": 0}
|
|
2615
|
-
for p in _pm().
|
|
2667
|
+
for p in _pm().list_registered():
|
|
2616
2668
|
ppath = str(p.get("path") or "")
|
|
2617
2669
|
row = {"name": p.get("name") or "", "path": ppath, "initialized": True,
|
|
2618
2670
|
"error": None, "tool_calls": 0, "tool_tokens": 0,
|
|
@@ -2662,7 +2714,7 @@ def api_hub_locks_overview():
|
|
|
2662
2714
|
from services import agent_locks as al
|
|
2663
2715
|
|
|
2664
2716
|
rows, total = [], 0
|
|
2665
|
-
for p in _pm().
|
|
2717
|
+
for p in _pm().list_registered():
|
|
2666
2718
|
ppath = str(p.get("path") or "")
|
|
2667
2719
|
row = {"name": p.get("name") or "", "path": ppath, "initialized": True,
|
|
2668
2720
|
"error": None, "enabled": True, "mode": "advisory",
|
|
@@ -2752,7 +2804,7 @@ def api_hub_enforcement_overview():
|
|
|
2752
2804
|
|
|
2753
2805
|
rows = []
|
|
2754
2806
|
totals = {"discipline": 0, "access": 0}
|
|
2755
|
-
for p in _pm().
|
|
2807
|
+
for p in _pm().list_registered():
|
|
2756
2808
|
ppath = str(p.get("path") or "")
|
|
2757
2809
|
row = {"name": p.get("name") or "", "path": ppath, "initialized": True,
|
|
2758
2810
|
"error": None, "mode": None, "scope": "", "set_by": "",
|
|
@@ -3428,7 +3480,7 @@ def api_hub_override_policy_overview():
|
|
|
3428
3480
|
from services import override_policy as opol
|
|
3429
3481
|
|
|
3430
3482
|
rows = []
|
|
3431
|
-
for p in _pm().
|
|
3483
|
+
for p in _pm().list_registered():
|
|
3432
3484
|
ppath = str(p.get("path") or "")
|
|
3433
3485
|
row = {"name": p.get("name") or Path(ppath).name, "path": ppath,
|
|
3434
3486
|
"initialized": True, "error": None, "policy": None,
|
|
@@ -3740,7 +3792,7 @@ def api_hub_access_overview():
|
|
|
3740
3792
|
empty = {"deny": [], "read_only": [], "confirm": [], "mask": 0,
|
|
3741
3793
|
"corrupt": False}
|
|
3742
3794
|
rows = []
|
|
3743
|
-
for p in _pm().
|
|
3795
|
+
for p in _pm().list_registered():
|
|
3744
3796
|
ppath = str(p.get("path") or "")
|
|
3745
3797
|
row = {"name": p.get("name") or Path(ppath).name, "path": ppath,
|
|
3746
3798
|
"initialized": True, "error": None, "rules": dict(empty)}
|
|
@@ -3834,6 +3886,170 @@ def api_hub_access_rule_remove():
|
|
|
3834
3886
|
return jsonify(result)
|
|
3835
3887
|
|
|
3836
3888
|
|
|
3889
|
+
# ── Builtin guard modes (v2.147.0) ─────────────────────────────────────────
|
|
3890
|
+
|
|
3891
|
+
def _hub_human():
|
|
3892
|
+
"""The Desk client behind ``Authorization: Bearer``, else ``None``.
|
|
3893
|
+
|
|
3894
|
+
Loopback and the CSRF guard stop a browser, not a process on this
|
|
3895
|
+
machine: an agent can POST here as easily as a person. A Desk client
|
|
3896
|
+
token is minted only with ``bootstrap.key``, which Access Guard denies
|
|
3897
|
+
to agents, and is stored as a hash, so presenting one is the proof a
|
|
3898
|
+
loosening builtin change needs. A phone token does not count: builtin
|
|
3899
|
+
guards are not loosened from a device that leaves the building.
|
|
3900
|
+
"""
|
|
3901
|
+
from oracle.services import client_tokens
|
|
3902
|
+
scheme, _, token = (request.headers.get("Authorization") or "").partition(" ")
|
|
3903
|
+
if scheme.lower() != "bearer" or not token.strip():
|
|
3904
|
+
return None
|
|
3905
|
+
who = client_tokens.principal_for(token.strip())
|
|
3906
|
+
return who if who and who.get("kind") == "desk" else None
|
|
3907
|
+
|
|
3908
|
+
|
|
3909
|
+
@app.route("/api/hub/access/builtin", methods=["GET"])
|
|
3910
|
+
def api_hub_access_builtin():
|
|
3911
|
+
"""Every Tier-1 builtin with its live global mode, and each project's own.
|
|
3912
|
+
|
|
3913
|
+
Modes are read through the keyring (config and attestation must agree),
|
|
3914
|
+
so a mode listed here is one evaluation honours. ``projects`` holds only
|
|
3915
|
+
projects that set a mode of their own, or could not be read.
|
|
3916
|
+
``strictness`` ranks each mode 0 (allow) to 3 (full deny), so a client
|
|
3917
|
+
can tell loosening from tightening without knowing the tiers.
|
|
3918
|
+
"""
|
|
3919
|
+
try:
|
|
3920
|
+
global_modes = access_guard._scope_modes("global")
|
|
3921
|
+
except Exception as e:
|
|
3922
|
+
return jsonify({"error": str(e)}), 500
|
|
3923
|
+
home = access_guard._global_base()
|
|
3924
|
+
guards = []
|
|
3925
|
+
for glob in access_guard.DISABLEABLE_BUILTINS:
|
|
3926
|
+
canon = access_guard._norm_builtin(glob)
|
|
3927
|
+
guards.append({
|
|
3928
|
+
"glob": canon,
|
|
3929
|
+
"global": global_modes.get(canon, "default"),
|
|
3930
|
+
"strictness": {m: access_guard.builtin_strictness(canon, m)
|
|
3931
|
+
for m in (*access_guard.BUILTIN_MODES, "default")},
|
|
3932
|
+
})
|
|
3933
|
+
projects = []
|
|
3934
|
+
for p in _pm().list_registered():
|
|
3935
|
+
ppath = str(p.get("path") or "")
|
|
3936
|
+
row = {"name": p.get("name") or Path(ppath).name, "path": ppath,
|
|
3937
|
+
"modes": {}, "error": None}
|
|
3938
|
+
try:
|
|
3939
|
+
base = Path(ppath).resolve()
|
|
3940
|
+
if (base / ".c3").is_dir() and base != home:
|
|
3941
|
+
row["modes"] = access_guard._scope_modes("project", ppath)
|
|
3942
|
+
except Exception as e:
|
|
3943
|
+
row["error"] = str(e)
|
|
3944
|
+
if row["modes"] or row["error"]:
|
|
3945
|
+
projects.append(row)
|
|
3946
|
+
from services import builtin_leases
|
|
3947
|
+
return jsonify({"guards": guards, "projects": projects,
|
|
3948
|
+
"leases": builtin_leases.active()})
|
|
3949
|
+
|
|
3950
|
+
|
|
3951
|
+
@app.route("/api/hub/access/builtin/mode", methods=["POST"])
|
|
3952
|
+
def api_hub_access_builtin_mode():
|
|
3953
|
+
"""Set a Tier-1 builtin's mode in the global realm or one project's.
|
|
3954
|
+
|
|
3955
|
+
Body: ``{scope, path?, glob, mode, confirm?}``. A mode at least as strict
|
|
3956
|
+
as the live one needs nothing more. A looser one needs a Desk client
|
|
3957
|
+
token (403 ``needs_human`` without it) and ``confirm`` equal to the glob
|
|
3958
|
+
(400 ``needs_confirmation``). A project is judged against what its
|
|
3959
|
+
agents see today, which is the global mode unless it set its own.
|
|
3960
|
+
"""
|
|
3961
|
+
data = request.get_json(silent=True) or {}
|
|
3962
|
+
scope, project, err = _hub_access_target(data)
|
|
3963
|
+
if err:
|
|
3964
|
+
return err
|
|
3965
|
+
glob = str(data.get("glob") or "")
|
|
3966
|
+
mode = str(data.get("mode") or "").strip()
|
|
3967
|
+
canon = access_guard._norm_builtin(glob)
|
|
3968
|
+
try:
|
|
3969
|
+
new = access_guard.builtin_strictness(canon, mode)
|
|
3970
|
+
live = (access_guard._scope_modes("global") if scope == "global"
|
|
3971
|
+
else access_guard.effective_builtin_modes(project))
|
|
3972
|
+
old = access_guard.builtin_strictness(canon, live.get(canon, "default"))
|
|
3973
|
+
except ValueError as exc:
|
|
3974
|
+
return jsonify({"error": str(exc)}), 400
|
|
3975
|
+
if new < old:
|
|
3976
|
+
if _hub_human() is None:
|
|
3977
|
+
return jsonify({
|
|
3978
|
+
"error": "loosening a built-in guard needs C3 Desk",
|
|
3979
|
+
"needs_human": True,
|
|
3980
|
+
"command": f'c3 access builtin mode "{canon}" {mode}'
|
|
3981
|
+
+ (f' --project --path "{project}"'
|
|
3982
|
+
if scope == "project" else ""),
|
|
3983
|
+
}), 403
|
|
3984
|
+
if access_guard._norm_builtin(data.get("confirm")) != canon:
|
|
3985
|
+
return jsonify({
|
|
3986
|
+
"error": "loosening a built-in guard weakens protection",
|
|
3987
|
+
"needs_confirmation": True, "confirm_with": canon,
|
|
3988
|
+
}), 400
|
|
3989
|
+
try:
|
|
3990
|
+
result = access_guard.set_builtin_mode(canon, mode, scope,
|
|
3991
|
+
project or ".")
|
|
3992
|
+
except ValueError as exc:
|
|
3993
|
+
return jsonify({"error": str(exc)}), 400
|
|
3994
|
+
if result["changed"]:
|
|
3995
|
+
_hub_access_audit(f"builtin_mode_{result['mode']}", result["glob"],
|
|
3996
|
+
"builtin", scope, project)
|
|
3997
|
+
return jsonify({**result, "loosened": new < old})
|
|
3998
|
+
|
|
3999
|
+
|
|
4000
|
+
@app.route("/api/hub/access/builtin/lease", methods=["POST"])
|
|
4001
|
+
def api_hub_access_builtin_lease():
|
|
4002
|
+
"""Loosen a builtin for a while: every session, or one.
|
|
4003
|
+
|
|
4004
|
+
Body: ``{scope, path?, glob, mode, ttl_s, session_id?, confirm}``. A
|
|
4005
|
+
lease only ever loosens, so it always needs a Desk client token and the
|
|
4006
|
+
glob typed back, and a lease no looser than the live mode is a 400
|
|
4007
|
+
rather than a row that would never apply. ``ttl_s`` is 60 s to 8 h.
|
|
4008
|
+
"""
|
|
4009
|
+
from services import builtin_leases
|
|
4010
|
+
data = request.get_json(silent=True) or {}
|
|
4011
|
+
scope, project, err = _hub_access_target(data)
|
|
4012
|
+
if err:
|
|
4013
|
+
return err
|
|
4014
|
+
who = _hub_human()
|
|
4015
|
+
if who is None:
|
|
4016
|
+
return jsonify({"error": "a temporary built-in change needs C3 Desk",
|
|
4017
|
+
"needs_human": True}), 403
|
|
4018
|
+
canon = access_guard._norm_builtin(data.get("glob"))
|
|
4019
|
+
mode = str(data.get("mode") or "").strip()
|
|
4020
|
+
if access_guard._norm_builtin(data.get("confirm")) != canon or not canon:
|
|
4021
|
+
return jsonify({"error": "a temporary change weakens protection",
|
|
4022
|
+
"needs_confirmation": True, "confirm_with": canon}), 400
|
|
4023
|
+
try:
|
|
4024
|
+
live = access_guard.effective_builtin_modes(project or ".") \
|
|
4025
|
+
if scope == "project" else access_guard._scope_modes("global")
|
|
4026
|
+
if access_guard.builtin_strictness(canon, mode) >= \
|
|
4027
|
+
access_guard.builtin_strictness(canon, live.get(canon, "default")):
|
|
4028
|
+
return jsonify({"error": f"{canon} is already {live.get(canon, 'default')}"
|
|
4029
|
+
f" — a {mode} lease would change nothing"}), 400
|
|
4030
|
+
row = builtin_leases.mint(
|
|
4031
|
+
canon, mode, scope=scope, project_path=project or ".",
|
|
4032
|
+
session_id=str(data.get("session_id") or ""),
|
|
4033
|
+
ttl_s=data.get("ttl_s"), created_by=who["client_id"])
|
|
4034
|
+
except ValueError as exc:
|
|
4035
|
+
return jsonify({"error": str(exc)}), 400
|
|
4036
|
+
_hub_access_audit(f"builtin_lease_{mode}", canon, "builtin", scope, project)
|
|
4037
|
+
return jsonify({"lease": row})
|
|
4038
|
+
|
|
4039
|
+
|
|
4040
|
+
@app.route("/api/hub/access/builtin/lease/revoke", methods=["POST"])
|
|
4041
|
+
def api_hub_access_builtin_lease_revoke():
|
|
4042
|
+
"""End a lease now. Tightening, so no token. Body: ``{id}``."""
|
|
4043
|
+
from services import builtin_leases
|
|
4044
|
+
lease_id = str((request.get_json(silent=True) or {}).get("id") or "")
|
|
4045
|
+
gone = builtin_leases.revoke(lease_id) if lease_id else None
|
|
4046
|
+
if gone is None:
|
|
4047
|
+
return jsonify({"error": "unknown or already-expired lease"}), 404
|
|
4048
|
+
_hub_access_audit("builtin_lease_revoke", gone["glob"], "builtin",
|
|
4049
|
+
gone["scope"], gone.get("project_path") or None)
|
|
4050
|
+
return jsonify({"revoked": lease_id})
|
|
4051
|
+
|
|
4052
|
+
|
|
3837
4053
|
# ── Project management: tasks / milestones / notes (v2.45.0) ──────────────
|
|
3838
4054
|
# Direct TaskStore per request (reload-per-op store — no runtime build needed
|
|
3839
4055
|
# for mutations); every write audited to the target project's activity log.
|
|
@@ -4268,7 +4484,7 @@ def api_pm_global():
|
|
|
4268
4484
|
from services.task_store import TaskStore
|
|
4269
4485
|
|
|
4270
4486
|
tasks, skipped, by_project = [], [], {}
|
|
4271
|
-
entries = _pm().
|
|
4487
|
+
entries = _pm().list_registered()
|
|
4272
4488
|
for p in entries:
|
|
4273
4489
|
ppath = p.get("path") or ""
|
|
4274
4490
|
if not Path(ppath).is_dir():
|
|
@@ -4808,7 +5024,7 @@ def _session_project(raw: str):
|
|
|
4808
5024
|
if not raw:
|
|
4809
5025
|
return None
|
|
4810
5026
|
want = os.path.normcase(os.path.normpath(raw))
|
|
4811
|
-
for p in _pm().
|
|
5027
|
+
for p in _pm().list_registered():
|
|
4812
5028
|
path = str(p.get("path") or "")
|
|
4813
5029
|
if path and os.path.normcase(os.path.normpath(path)) == want:
|
|
4814
5030
|
return {"name": str(p.get("name") or Path(path).name), "path": path}
|
|
@@ -4847,7 +5063,7 @@ def api_hub_sessions_overview():
|
|
|
4847
5063
|
return row
|
|
4848
5064
|
|
|
4849
5065
|
with ThreadPoolExecutor(max_workers=8) as pool:
|
|
4850
|
-
rows = list(pool.map(one, _pm().
|
|
5066
|
+
rows = list(pool.map(one, _pm().list_registered()))
|
|
4851
5067
|
rows.sort(key=lambda r: r.get("last_active") or "", reverse=True)
|
|
4852
5068
|
return jsonify({"projects": rows, "features": _SESSIONS_FEATURES})
|
|
4853
5069
|
|
|
@@ -4876,7 +5092,7 @@ def api_hub_sessions_list():
|
|
|
4876
5092
|
res["errors"] = []
|
|
4877
5093
|
else:
|
|
4878
5094
|
projects = [{"name": str(p.get("name") or ""), "path": str(p.get("path") or "")}
|
|
4879
|
-
for p in _pm().
|
|
5095
|
+
for p in _pm().list_registered()]
|
|
4880
5096
|
res = sc.list_many(projects, stale=stale, q=q, limit=limit, before=before)
|
|
4881
5097
|
return jsonify(res)
|
|
4882
5098
|
except Exception as e:
|
|
@@ -50,7 +50,10 @@ function App() {
|
|
|
50
50
|
}, []);
|
|
51
51
|
|
|
52
52
|
useEffect(() => { loadConfig(); loadProjects(); }, []);
|
|
53
|
-
|
|
53
|
+
// Live status matters on the project list and in a drill-in. Elsewhere it
|
|
54
|
+
// only refreshes the sidebar and top-bar counts, which may lag 30 s, and
|
|
55
|
+
// each poll reads every project's activity log.
|
|
56
|
+
usePoll(loadProjects, mainView === 'projects' || drill ? 5000 : 30000);
|
|
54
57
|
|
|
55
58
|
// Persisted preferences
|
|
56
59
|
const toggleTheme = () => {
|