marvisx-cli 0.1.0__tar.gz → 0.2.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.
- {marvisx_cli-0.1.0/marvisx_cli.egg-info → marvisx_cli-0.2.1}/PKG-INFO +4 -1
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/config.py +28 -2
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/db.py +71 -5
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/main.py +8 -2
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/rbac.py +8 -2
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/findings.py +6 -1
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/embedding_service.py +8 -2
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/insert_saga.py +53 -3
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/terminal_metrics_dump.py +30 -11
- marvisx_cli-0.2.1/core/api/tests/test_require_scope_empty_deny.py +65 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_safety_bridge.py +57 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/search.py +9 -14
- marvisx_cli-0.2.1/core/cli/marvis_account.py +132 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/marvis_init.py +41 -8
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/marvis_runtime.py +12 -3
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/safety_bridge.py +11 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/telemetry/client.py +1 -1
- marvisx_cli-0.2.1/core/telemetry/entitlements.py +26 -0
- marvisx_cli-0.2.1/core/telemetry/rollup.py +281 -0
- marvisx_cli-0.2.1/core/telemetry/sender.py +224 -0
- marvisx_cli-0.2.1/core/wizard/byok_vault.py +384 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1/marvisx_cli.egg-info}/PKG-INFO +4 -1
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/marvisx_cli.egg-info/SOURCES.txt +8 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/marvisx_cli.egg-info/requires.txt +4 -0
- marvisx_cli-0.2.1/migrations/144_notifications_pending_sync_index.sql +14 -0
- marvisx_cli-0.2.1/migrations/145_audit_log_immutable.sql +23 -0
- marvisx_cli-0.2.1/migrations/145_audit_log_immutable_down.sql +4 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/pyproject.toml +13 -1
- marvisx_cli-0.1.0/core/wizard/byok_vault.py +0 -147
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/LICENSE +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/MANIFEST.in +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/README.md +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/agents/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/agents/session_health.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/agents/session_manager.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/bin/marvisx-state-hook.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/dependencies/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/dependencies/tenant.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/_adapter.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/server.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/brain.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/graph.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/handoffs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/ingest.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/learnings.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/projects.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/pull_requests.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/safety.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/search.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/mcp/tools/tasks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/middleware/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/middleware/tool_call_audit.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/auth.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/brain.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/common.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/costs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/graph.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/graph_cosmo.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/graph_pr_impact.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/graph_ux.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/inbox.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/ingest_keys.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/kg.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/llm_config.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/monitoring.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/projects.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/search.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/sessions.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/tasks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/teams.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/models/users.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/observability/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/observability/tracing.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/paths.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/rate_limit.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/_adapter.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/admin_pr_impact.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/admin_settings.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/agent.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/agent_tokens.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/app_settings.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/audit.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/auth.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/bench.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/brain.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/brain_directions.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/ci_checks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/comments.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/costs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/docs_coverage.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/docs_governance.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/documents.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/files.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/finder.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/graph.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/handoffs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/inbox.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/ingest_api_keys.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/ingest_triage.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/judge.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/kg.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/learnings.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/llm_config.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/monitoring.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/notifications.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/pr_impact.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/projects.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/pull_requests.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/push.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/raci.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/search.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/sessions.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/settings.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/share_repo.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/status_updates.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/tags.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/tasks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/teams.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/terminal.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/users.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/routers/webhooks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/runtime_settings.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/security.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/audit.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/auto_approval.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/baseline.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/capabilities.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/cascade_rollup.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/compound_bridge.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/cycle.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/cycle_snapshot.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/digest_collector.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/direction.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/drift.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/drift_router.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/edge_metrics.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/events_reader.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/findings_reader.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/jobs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/journal.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/knowledge_forms.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/_runner.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/base.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/cache.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/constants.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/direction_alignment.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/factory.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/finding_reasoning.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/finding_summary.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/grounding.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/journal_polish.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/local_gateway.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/parsers.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/llm/router_glue.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/memory_ops.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/models.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/owner_hint.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/recap.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/_signals.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/dr1_activity_without_status.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/dr2_decision_without_adr.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/dr3_stale_open_loop.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/dr4_docs_governance_drift.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/dr5_playbook_changed.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/dr6_external_update_unpropagated.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/dr7_claimed_decision_gap.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/rules/dr8_direction_misalignment.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/runs_reader.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/scope.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/sources/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/sources/base.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/sources/git_kg.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/sources/handoffs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/sources/ingestor.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/sources/learnings.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/sources/pir_tasks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/watermarks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/brain/ws_emitter.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/cc_tasks_reader.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ci_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/claude_metrics.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/codex_metrics.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/conversation_reader.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/cost_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/crypto.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/docs_governance/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/docs_governance/confidence.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/docs_governance/config.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/docs_governance/enrichment.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/docs_governance/frontmatter_validator.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/docs_governance/hard_gates.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/docs_governance/triage_orchestrator.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/embedding_internal.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/event_dispatcher.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/events.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/git_ops.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/graph_cosmo_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/graph_ranker.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/graph_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_digest.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_digest_deep_research.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_digest_jobs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_gmail_sync.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_llm_classifier.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_source_identity.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_sources.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_taxonomy.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_tldr.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/inbox_triage.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/api_key_auth.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/auto_approve.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/classifier.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/confidence.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/dispatch.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/embedding_router.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/events.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/ignore_patterns.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/image_probe.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/ingress.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/anthropic_haiku.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/base.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/byok_provider.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/classification_context.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/config_store.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/factory.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/kg_enricher.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/local_gateway.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/local_vllm.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/llm/openai_nano.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/lock_advisory.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parser_router.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/docling_parser.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/docparse_gateway.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/docx_parser.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/folder_unpacker.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/gateway_aux.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/image_parser.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/internal_markdown.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/ocr_gateway.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/ocr_pdf_parser.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/pdf_types.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/transcript_parser.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/vision_gateway.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/xlsx_parser.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/parsers/zip_unpacker.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/preflight.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/retry_voyage.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/routing_policy.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/serializers/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/serializers/xlsx_to_markdown.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/skip_log.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/ingest/watcher.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg/audit.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg/hybrid_search.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg/lens.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg/pr_impact.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg/queries.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg/ranking.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg/rrf.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/kg_watcher_control.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/local_llm/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/local_llm/async_client.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/local_llm/client.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/local_llm/url_validator.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/metrics_collector.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/metrics_providers.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/model_registry.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/model_router.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/n8n_client.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/newsletter_llm_gateway.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/notification_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/openai_responses.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/opencode_metrics.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/opencode_sessions.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pii_redactor.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pr_impact_pipeline/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pr_impact_pipeline/differ.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pr_impact_pipeline/dispatcher.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pr_impact_pipeline/gc.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pr_impact_pipeline/languages.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pr_impact_pipeline/parser.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pr_impact_pipeline/writer.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/pr_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/project_paths.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/project_status_updates.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/providers.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/push_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/reminder_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/runas.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/salience_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/security_collector.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/session_catalog.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/session_metrics_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/session_ops.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/session_state.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/share_links.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/task_transitions.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/terminal_metrics.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/tmux.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/webhook_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/services/workspace_sync.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/templates/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/templates/markdown_share.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/terminal.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_agent_facing_auth_dependencies.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_audit_permissions.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_backfill_session_conversations.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_backfill_working_seconds_msg.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_claude_metrics.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_codex_metrics.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_finder_paths.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_git_ops_merge.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_learnings_check_search.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_metrics_providers.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_migration_087.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_migration_088.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_migration_089.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_openai_responses.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_opencode_metrics.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_opencode_sessions.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_pr_workflow_e2e.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_projects_handoffs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_providers.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_session_catalog.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_session_conversations.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_session_metrics_service.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_session_resume_paths.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_session_theme_mode_migration.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_sessions_rbac.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_share_edit.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_share_repo.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_terminal_session_manager.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_terminal_upload.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_tmux.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_workspace_sync.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/tests/test_ws_ticket_in_memory.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/_context.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/_errors.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/_roles.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/audit.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/brain.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/costs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/graph.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/handoffs.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/ingest_triage.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/learnings.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/projects.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/pull_requests.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/use_cases/tasks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/api/visibility.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/README.md +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/_index_source.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/_runtime_ctx.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/_transmute.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/marvis_doctor.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/marvis_feedback.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/marvis_governance.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/marvis_hooks.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/marvis_mcp.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/cli/marvis_telemetry.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/_drift_check.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/_frontmatter.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/_graph_writer.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/ast_parser.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/_config.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/block-dangerous-bash.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/block-db-direct-write.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/block-push-no-task.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/block-staging-to-prod.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/block-subtree-push.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/config.json +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/enforce-no-merge-main.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/enforce-worktree.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/quality-gate.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/safety_bridge.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/install_hooks/secret-scan.sh +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/migrate_spike_node_ids.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/populate_artifacts.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/populate_cross_project.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/populate_inbox_nodes.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/populate_pr_impact.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/populate_project_nodes.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/populate_touch_counter.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/scripts/reparse_failed.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/telemetry/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/telemetry/schema.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/wizard/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/wizard/defaults.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/wizard/state.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/wizard/steps.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/core/wizard/validation.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/marvisx_cli.egg-info/dependency_links.txt +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/marvisx_cli.egg-info/entry_points.txt +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/marvisx_cli.egg-info/top_level.txt +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/001_initial.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/002_tasks.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/003_session_management.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/004_projects_comments.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/005_session_intelligence.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/006_settings.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/007_task_scoring.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/008_cost_tracking.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/009_session_card_metrics.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/010_monitoring.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/012_agent_api.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/013_session_complete.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/015_pull_requests.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/015_pull_requests_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/016_users_raci.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/017_task_cost_entries.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/018_agents.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/018_agents_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/019_review_feedback.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/020_pr_commit_sha.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/021_webhook_events.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/022_devx_agent_managed.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/022_devx_agent_managed_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/023_devx_p1_gate.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/023_devx_p1_gate_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/024_chat_messages.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/024_pr_conversation_id.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/024_task_indexes.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/024_task_indexes_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/025_audit_log.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/026_agent_tokens.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/027_teams_auth_phase_b.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/028_learnings.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/029_team_roles.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/030_finder_pins.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/031_pr_deploy_status.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/032_task_reminders.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/033_events_retry_count.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/033_session_owner.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/034_notifications.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/035_shared_links.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/036_session_index_upgrade.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/037_pr_approval.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/038_pr_submitted_by.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/039_push_subscriptions.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/040_semantic_search.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/041_workspaces.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/042_oidc_providers.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/043_ci_checks.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/044_agent_metrics.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/045_documents_doc_type.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/046_salience.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/047_seed_missing_agents.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/048_fix_agent_paths_roles.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/049_agent_role_and_learnings_schema.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/050_session_provider.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/051_session_launch_profile.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/052_session_theme_mode.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/052_task_kind.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/053_inbox_items.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/054_inbox_triage_contract.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/055_inbox_topic_treatment.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/056_inbox_treatment_read_save.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/057_session_theme_mode_backfill.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/058_inbox_item_status_lifecycle.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/059_inbox_tldr_and_source_scores.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/060_newsletter.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/061_inbox_redesign.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/062_fix_inbox_sources_backfill.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/063_task_completion_mode.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/064_judge_mode_setting.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/065_knowledge_graph_spike.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/066_digest_ranking_inputs.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/066_kg_artifact_nodes.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/067_inbox_digest_selections.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/067_kg_temporal.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/068_inbox_digest_app_settings.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/068_kg_touch_counter.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/069_kg_doc_types.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/070_digest_ranking_inputs_recovery.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/071_inbox_digest_selections_recovery.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/072_inbox_digest_app_settings_recovery.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/073_kg_cross_project.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/073_kg_cross_project_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/074_kg_infra_types.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/074_kg_infra_types_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/075_kg_file_state_recovery.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/075_kg_file_state_recovery_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/076_kg_watcher_state.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/076_kg_watcher_state_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/077_kg_doc_types_extend.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/077_kg_doc_types_extend_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/078_kg_fts5.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/078_kg_fts5_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/079_kg_missing_indexes.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/079_kg_missing_indexes_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/080_kg_fts5_extended.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/080_kg_fts5_extended_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/081_kg_lens_indexes.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/081_kg_lens_indexes_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/082_kg_pins.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/082_kg_pins_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/083_kg_graph_nodes_degree.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/083_kg_graph_nodes_degree_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/084_drop_legacy_scheduler_tables.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/084_drop_legacy_scheduler_tables_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/085_kg_edge_resolves_to.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/085_kg_edge_resolves_to_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/086_project_status_updates_feed.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/086_project_status_updates_feed_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/087_session_metrics_dual.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/087_session_metrics_dual_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/088_rename_context_pct_legacy.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/088_rename_context_pct_legacy_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/089_session_metrics_equivalent_cost.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/089_session_metrics_equivalent_cost_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/090_kg_inbox_node_type.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/090_kg_inbox_node_type_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/091_kg_inbox_node_type_check.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/091_kg_inbox_node_type_check_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/092_sessions_activity_state_ts.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/092_sessions_activity_state_ts_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/093_sessions_activity_state_column.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/093_sessions_activity_state_column_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/094_ingest_pending.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/094_ingest_pending_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/095_kg_intent_first.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/095_kg_intent_first_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/096_kg_xlsx_artifact_prefix.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/096_kg_xlsx_artifact_prefix_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/097_ingest_change_history.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/097_ingest_change_history_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/098_kg_node_type_business.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/098_kg_node_type_business_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/099_kg_edges_restore_weight.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/099_kg_edges_restore_weight_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/100_kg_enriched_at.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/100_kg_enriched_at_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/101_local_llm_shadow_comparisons.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/101_local_llm_shadow_comparisons_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/102_promote_llm_costs.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/102_promote_llm_costs_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/103_ingest_skipped_log.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/103_ingest_skipped_log_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/120_docs_governance.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/120_docs_governance_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/121_notification_event_fk_cleanup.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/121_notification_event_fk_cleanup_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/122_docs_drift_history.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/122_docs_drift_history_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/123_ingest_parser_waiting_status.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/123_ingest_parser_waiting_status_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/124_heypocket_recordings.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/124_heypocket_recordings_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/125_kg_node_type_record.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/125_kg_node_type_record_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/126_ingest_terminal_upload_source_kind.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/126_ingest_terminal_upload_source_kind_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/127_brain_v1_substrate.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/127_brain_v1_substrate_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/128_brain_drift_signals.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/128_brain_drift_signals_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/129_brain_memory_operations.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/129_brain_memory_operations_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/130_brain_findings.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/130_brain_findings_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/132_kg_pr_modifies.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/132_kg_pr_modifies_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/133_brain_v1_2_direction_schema.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/133_brain_v1_2_direction_schema_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/134_brain_journal_narrative_polished.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/134_brain_journal_narrative_polished_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/135_kg_edges_provider.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/136_documents_fts.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/137_promote_llm_costs.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/137_promote_llm_costs_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/138_ingest_api_keys.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/138_ingest_api_keys_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/139_ingest_pending_ingress.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/139_ingest_pending_ingress_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/140_ingest_idempotency_quota.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/140_ingest_idempotency_quota_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/141_ingest_pending_metadata.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/141_ingest_pending_metadata_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/142_llm_function_config.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/142_llm_function_config_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/143_kg_code_embeddings.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/143_kg_code_embeddings_down.sql +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/migrations/__init__.py +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/projects/_template/project.yaml +0 -0
- {marvisx_cli-0.1.0 → marvisx_cli-0.2.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: marvisx-cli
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: MarvisX OSS — agent-native company-brain CLI runtime (init, status, brief, triage)
|
|
5
5
|
Author: MarvisX maintainers
|
|
6
6
|
License: BSL-1.1
|
|
@@ -68,9 +68,12 @@ Requires-Dist: tokenizers>=0.20
|
|
|
68
68
|
Requires-Dist: huggingface-hub>=0.24
|
|
69
69
|
Requires-Dist: numpy>=1.26
|
|
70
70
|
Requires-Dist: psutil>=5.9.0
|
|
71
|
+
Requires-Dist: sqlite-vec>=0.1.6
|
|
71
72
|
Provides-Extra: dev
|
|
72
73
|
Requires-Dist: pytest>=8; extra == "dev"
|
|
73
74
|
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
75
|
+
Provides-Extra: keyring
|
|
76
|
+
Requires-Dist: keyring>=24; extra == "keyring"
|
|
74
77
|
Dynamic: license-file
|
|
75
78
|
|
|
76
79
|
# marvis init
|
|
@@ -8,6 +8,29 @@ from typing import Literal
|
|
|
8
8
|
from pydantic import AliasChoices, Field, SecretStr
|
|
9
9
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
10
10
|
|
|
11
|
+
# Prod (Hetzner/Docker) ships the vec0 loadable at this path; it stays the
|
|
12
|
+
# final fallback so prod keeps working unchanged.
|
|
13
|
+
_VEC0_PATH_PROD_DEFAULT = "/data/pir/lib/vec0"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _default_vec0_path() -> str:
|
|
17
|
+
"""Resolve the vec0 loadable path for sqlite-vec.
|
|
18
|
+
|
|
19
|
+
Order:
|
|
20
|
+
1. ``$VEC0_PATH`` env — handled by pydantic-settings (overrides this
|
|
21
|
+
default_factory when set), so it is NOT re-read here.
|
|
22
|
+
2. The installed ``sqlite_vec`` package's bundled loadable
|
|
23
|
+
(``sqlite_vec.loadable_path()``) — the OSS clean-install path
|
|
24
|
+
(`pip install sqlite-vec`), platform-correct (.so / .dylib).
|
|
25
|
+
3. ``/data/pir/lib/vec0`` — prod fallback.
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
import sqlite_vec # type: ignore
|
|
29
|
+
|
|
30
|
+
return str(sqlite_vec.loadable_path())
|
|
31
|
+
except Exception: # noqa: BLE001 — missing/old package → prod fallback
|
|
32
|
+
return _VEC0_PATH_PROD_DEFAULT
|
|
33
|
+
|
|
11
34
|
|
|
12
35
|
class Settings(BaseSettings):
|
|
13
36
|
model_config = SettingsConfigDict(
|
|
@@ -381,8 +404,11 @@ class Settings(BaseSettings):
|
|
|
381
404
|
# Voyage AI embeddings
|
|
382
405
|
voyage_api_key: str = ""
|
|
383
406
|
|
|
384
|
-
# sqlite-vec
|
|
385
|
-
vec0_path: str =
|
|
407
|
+
# sqlite-vec: env VEC0_PATH → sqlite_vec.loadable_path() → prod fallback.
|
|
408
|
+
vec0_path: str = Field(
|
|
409
|
+
default_factory=_default_vec0_path,
|
|
410
|
+
validation_alias=AliasChoices("VEC0_PATH"),
|
|
411
|
+
)
|
|
386
412
|
|
|
387
413
|
# LifeOS
|
|
388
414
|
lifeos_data_dir: str = ""
|
|
@@ -101,6 +101,7 @@ _write_lock = asyncio.Lock()
|
|
|
101
101
|
|
|
102
102
|
WRITER_LOCK_EVENT_LIMIT = 500
|
|
103
103
|
WRITER_LOCK_SLOW_WAIT_MS = 50.0
|
|
104
|
+
WRITER_LOCK_SLOW_HOLD_MS = 1000.0 # Fase 0: log writer holds >1s to separate offenders from queued victims
|
|
104
105
|
_writer_metrics_lock = Lock()
|
|
105
106
|
_writer_wait_events: deque[dict[str, Any]] = deque(maxlen=WRITER_LOCK_EVENT_LIMIT)
|
|
106
107
|
_writer_hold_events: deque[dict[str, Any]] = deque(maxlen=WRITER_LOCK_EVENT_LIMIT)
|
|
@@ -291,7 +292,14 @@ def _start_writer_hold(
|
|
|
291
292
|
"blocked_by": blocked_by,
|
|
292
293
|
}
|
|
293
294
|
)
|
|
294
|
-
|
|
295
|
+
if wait_ms >= WRITER_LOCK_SLOW_WAIT_MS:
|
|
296
|
+
logger.warning(
|
|
297
|
+
"SQLite writer lock WAIT %.0fms for %s (blocked_by=%s)",
|
|
298
|
+
wait_ms,
|
|
299
|
+
label,
|
|
300
|
+
(blocked_by or {}).get("label"),
|
|
301
|
+
)
|
|
302
|
+
return holder
|
|
295
303
|
|
|
296
304
|
|
|
297
305
|
def _finish_writer_hold(holder: dict[str, Any]) -> None:
|
|
@@ -312,6 +320,13 @@ def _finish_writer_hold(holder: dict[str, Any]) -> None:
|
|
|
312
320
|
"blocked_by": holder.get("blocked_by"),
|
|
313
321
|
}
|
|
314
322
|
)
|
|
323
|
+
if hold_ms >= WRITER_LOCK_SLOW_HOLD_MS:
|
|
324
|
+
logger.warning(
|
|
325
|
+
"SQLite writer lock HELD %.0fms by %s (waited %.0fms) — offender, not victim",
|
|
326
|
+
hold_ms,
|
|
327
|
+
holder["label"],
|
|
328
|
+
holder.get("wait_ms", 0.0),
|
|
329
|
+
)
|
|
315
330
|
|
|
316
331
|
|
|
317
332
|
def get_writer_lock_snapshot(window_seconds: float = 60.0) -> dict[str, Any]:
|
|
@@ -494,18 +509,69 @@ async def wal_checkpoint() -> tuple[int, int, int]:
|
|
|
494
509
|
# sqlite-vec support
|
|
495
510
|
_vec_table_ready = False
|
|
496
511
|
|
|
512
|
+
# Platform-specific loadable-extension suffixes. The vec0 loadable is `.so` on
|
|
513
|
+
# Linux (prod), `.dylib` on macOS, `.dll` on Windows.
|
|
514
|
+
_VEC0_SUFFIXES = (".so", ".dylib", ".dll")
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def resolve_vec0_loadable() -> tuple[str | None, bool]:
|
|
518
|
+
"""Resolve the vec0 loadable path, cross-platform.
|
|
519
|
+
|
|
520
|
+
Returns ``(load_arg, found)`` where ``load_arg`` is the argument to pass to
|
|
521
|
+
``SELECT load_extension(?)`` and ``found`` is True when a real loadable file
|
|
522
|
+
exists on disk.
|
|
523
|
+
|
|
524
|
+
Resolution (prod-safe by construction):
|
|
525
|
+
1. ``settings.vec0_path`` when it resolves to a real file: if it already
|
|
526
|
+
carries a known suffix use it as-is, otherwise probe ``.so`` /
|
|
527
|
+
``.dylib`` / ``.dll``. Prod (Linux, ``/data/pir/lib/vec0`` →
|
|
528
|
+
``vec0.so``, set via ``VEC0_PATH``) resolves here and keeps using the
|
|
529
|
+
exact configured path.
|
|
530
|
+
2. Else the installed ``sqlite_vec`` package's own loadable
|
|
531
|
+
(``sqlite_vec.loadable_path()``) — the OSS clean-install path, where
|
|
532
|
+
``/data/pir/lib/vec0`` is absent and the bundled loadable is
|
|
533
|
+
platform-correct (.dylib on macOS, no longer rejected by a hardcoded
|
|
534
|
+
``.so`` check).
|
|
535
|
+
|
|
536
|
+
The suffix-less ``load_arg`` lets SQLite append the platform suffix itself.
|
|
537
|
+
"""
|
|
538
|
+
vec_path = Path(settings.vec0_path)
|
|
539
|
+
if vec_path.suffix:
|
|
540
|
+
if vec_path.exists():
|
|
541
|
+
return (str(vec_path), True)
|
|
542
|
+
else:
|
|
543
|
+
for suffix in _VEC0_SUFFIXES:
|
|
544
|
+
if vec_path.with_suffix(suffix).exists():
|
|
545
|
+
# Pass the suffix-less path; SQLite appends the platform suffix.
|
|
546
|
+
return (str(vec_path), True)
|
|
547
|
+
|
|
548
|
+
try:
|
|
549
|
+
import sqlite_vec # type: ignore
|
|
550
|
+
|
|
551
|
+
pkg_path = Path(str(sqlite_vec.loadable_path()))
|
|
552
|
+
if pkg_path.exists():
|
|
553
|
+
return (str(pkg_path), True)
|
|
554
|
+
# loadable_path() returns a suffix-less base on some builds; probe.
|
|
555
|
+
for suffix in _VEC0_SUFFIXES:
|
|
556
|
+
if pkg_path.with_suffix(suffix).exists():
|
|
557
|
+
return (str(pkg_path), True)
|
|
558
|
+
except Exception: # noqa: BLE001 — package missing/old → settings path is final
|
|
559
|
+
pass
|
|
560
|
+
|
|
561
|
+
# Nothing resolved; return the configured path so callers log a clear miss.
|
|
562
|
+
return (str(vec_path), False)
|
|
563
|
+
|
|
497
564
|
|
|
498
565
|
async def ensure_vec_documents(db: aiosqlite.Connection) -> bool:
|
|
499
566
|
"""Load sqlite-vec on an existing connection and ensure vec_documents exists."""
|
|
500
567
|
global _vec_table_ready
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
if not vec_so.exists():
|
|
568
|
+
load_arg, found = resolve_vec0_loadable()
|
|
569
|
+
if not found or load_arg is None:
|
|
504
570
|
return False
|
|
505
571
|
|
|
506
572
|
if not getattr(db, "_pir_vec_extension_loaded", False):
|
|
507
573
|
await db._execute(db._conn.enable_load_extension, True)
|
|
508
|
-
await db.execute("SELECT load_extension(?)", [
|
|
574
|
+
await db.execute("SELECT load_extension(?)", [load_arg])
|
|
509
575
|
setattr(db, "_pir_vec_extension_loaded", True)
|
|
510
576
|
if not _vec_table_ready:
|
|
511
577
|
await db.execute("""
|
|
@@ -870,11 +870,17 @@ async def _notifications_acted_at_sync_loop() -> None:
|
|
|
870
870
|
async with write_db() as db:
|
|
871
871
|
now = datetime.now(timezone.utc).isoformat()
|
|
872
872
|
await db.execute(
|
|
873
|
+
# Drive off the small still-pending set + idx_notifications_pending_sync
|
|
874
|
+
# (migration 144): NOT IN (pending) is sargable, the prior
|
|
875
|
+
# `!= 'pending'` forced a full scan -> ~15s writer-lock hold.
|
|
876
|
+
# A target_id pointing at a deleted task is now acted too (benign:
|
|
877
|
+
# the task is no longer pending). tasks.id is PK so no NULL in the
|
|
878
|
+
# subquery -> NOT IN is safe.
|
|
873
879
|
"""UPDATE notifications
|
|
874
880
|
SET acted_at = ?, read_at = COALESCE(read_at, ?)
|
|
875
881
|
WHERE acted_at IS NULL AND type = 'task_pending'
|
|
876
|
-
AND target_type = 'task' AND target_id IN (
|
|
877
|
-
SELECT id FROM tasks WHERE status
|
|
882
|
+
AND target_type = 'task' AND target_id NOT IN (
|
|
883
|
+
SELECT id FROM tasks WHERE status = 'pending'
|
|
878
884
|
)""",
|
|
879
885
|
(now, now),
|
|
880
886
|
)
|
|
@@ -80,9 +80,15 @@ def require_scope(*required_scopes: str) -> Callable[..., Awaitable[UserInfo]]:
|
|
|
80
80
|
if not user.username.startswith("agent:") and user.username not in agent_usernames:
|
|
81
81
|
return user
|
|
82
82
|
|
|
83
|
-
# Agent with no scopes
|
|
83
|
+
# Agent with no scopes (empty/null) = NO permission for scope-gated ops.
|
|
84
|
+
# Empty MUST deny, not allow-all: an unscoped agent token previously
|
|
85
|
+
# passed every scope check (authz bypass — empty list satisfied
|
|
86
|
+
# `not user.scopes`). Scope-gated endpoints require an explicit grant.
|
|
84
87
|
if not user.scopes:
|
|
85
|
-
|
|
88
|
+
raise HTTPException(
|
|
89
|
+
status_code=403,
|
|
90
|
+
detail=f"Token missing required scopes: {list(required_scopes)}",
|
|
91
|
+
)
|
|
86
92
|
|
|
87
93
|
# Check that all required scopes are present
|
|
88
94
|
missing = [s for s in required_scopes if s not in user.scopes]
|
|
@@ -1299,7 +1299,12 @@ async def emit_finding_dedup(
|
|
|
1299
1299
|
return (finding_id, False)
|
|
1300
1300
|
|
|
1301
1301
|
# INSERT path
|
|
1302
|
-
finding_id
|
|
1302
|
+
# Finding.finding_id requires exactly 32 chars (min_length=32,
|
|
1303
|
+
# max_length=32), matching the BLAKE2b-16 hex sibling ids
|
|
1304
|
+
# (signal_id/operation_id/event_id). Keep the "fnd_" prefix and pad to
|
|
1305
|
+
# 32 total chars (4 prefix + 28 hex) so every findings endpoint
|
|
1306
|
+
# validates instead of 500-ing.
|
|
1307
|
+
finding_id = f"fnd_{uuid.uuid4().hex[:28]}"
|
|
1303
1308
|
now_iso = _utc_iso(datetime.now(timezone.utc))
|
|
1304
1309
|
if expires_at is None:
|
|
1305
1310
|
expires_iso = _utc_iso(
|
|
@@ -482,9 +482,15 @@ async def embed_task_document(
|
|
|
482
482
|
|
|
483
483
|
|
|
484
484
|
async def _ensure_vec_documents(db: aiosqlite.Connection, vec0_path: str) -> None:
|
|
485
|
-
|
|
485
|
+
# Prefer the shared cross-platform resolver (sqlite_vec package loader /
|
|
486
|
+
# .so / .dylib probe) so macOS (.dylib) loads; fall back to the passed path.
|
|
487
|
+
from core.api.db import resolve_vec0_loadable
|
|
488
|
+
|
|
489
|
+
load_arg, found = resolve_vec0_loadable()
|
|
490
|
+
if not found or load_arg is None:
|
|
491
|
+
load_arg = str(Path(vec0_path))
|
|
486
492
|
await db._execute(db._conn.enable_load_extension, True)
|
|
487
|
-
await db.execute("SELECT load_extension(?)", [
|
|
493
|
+
await db.execute("SELECT load_extension(?)", [load_arg])
|
|
488
494
|
await db.execute("""
|
|
489
495
|
CREATE VIRTUAL TABLE IF NOT EXISTS vec_documents USING vec0(
|
|
490
496
|
doc_id INTEGER PRIMARY KEY,
|
|
@@ -20,8 +20,57 @@ from core.api.services.ingest.events import broadcast_ingest_changed
|
|
|
20
20
|
|
|
21
21
|
logger = logging.getLogger(__name__)
|
|
22
22
|
|
|
23
|
+
# Prod default (Docker): /data/projects exists, so the resolved value stays
|
|
24
|
+
# /data/projects there. Kept as a module-level attribute (not inlined) so it
|
|
25
|
+
# remains an explicit override point — tests monkeypatch it, and a future
|
|
26
|
+
# runtime hook could set it directly. _projects_root() treats any non-default
|
|
27
|
+
# value here as authoritative.
|
|
23
28
|
PROJECTS_ROOT = Path("/data/projects")
|
|
24
29
|
REPO_ROOT = repo_root(__file__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _projects_root() -> Path:
|
|
33
|
+
"""Resolve the projects root the same way the rest of the runtime does.
|
|
34
|
+
|
|
35
|
+
Order (prod-safe by construction):
|
|
36
|
+
1. The module-level ``PROJECTS_ROOT`` when it has been overridden from its
|
|
37
|
+
``/data/projects`` default (tests monkeypatch it; a runtime hook may
|
|
38
|
+
set it). An explicit override always wins.
|
|
39
|
+
2. ``$MARVIS_PROJECTS_ROOT`` (canonical override, see wizard/defaults.py).
|
|
40
|
+
Prod does NOT set it, so prod is unaffected.
|
|
41
|
+
3. The runtime-applied project dirs (``PROJECT_DIRS[0]``), which
|
|
42
|
+
``runtime_settings.apply_marvis_settings`` populates from
|
|
43
|
+
``~/.marvis/settings.yaml`` ``storage.projects_root`` — but ONLY when
|
|
44
|
+
``/data/projects`` does NOT exist, so prod (where it does) keeps using
|
|
45
|
+
``/data/projects`` rather than the DB-loaded ``~/workspace/projects``.
|
|
46
|
+
4. ``/data/projects`` default.
|
|
47
|
+
|
|
48
|
+
Resolved lazily per-call: the API process applies settings.yaml AFTER this
|
|
49
|
+
module imports, so reading at import time would lock in the bare default.
|
|
50
|
+
"""
|
|
51
|
+
default_root = Path("/data/projects")
|
|
52
|
+
|
|
53
|
+
# 1. Explicit module-level override (tests / runtime hook).
|
|
54
|
+
if PROJECTS_ROOT != default_root:
|
|
55
|
+
return Path(PROJECTS_ROOT).expanduser().resolve()
|
|
56
|
+
|
|
57
|
+
# 2. Canonical env override (OSS non-Docker).
|
|
58
|
+
env_root = os.environ.get("MARVIS_PROJECTS_ROOT")
|
|
59
|
+
if env_root:
|
|
60
|
+
return Path(env_root).expanduser().resolve()
|
|
61
|
+
|
|
62
|
+
# 3. Runtime settings (settings.yaml → PROJECT_DIRS) on non-Docker installs.
|
|
63
|
+
if not default_root.exists():
|
|
64
|
+
try:
|
|
65
|
+
from core.api.routers.projects import PROJECT_DIRS
|
|
66
|
+
|
|
67
|
+
if PROJECT_DIRS:
|
|
68
|
+
return Path(PROJECT_DIRS[0]).expanduser().resolve()
|
|
69
|
+
except Exception: # noqa: BLE001 — never let resolution crash the saga
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
# 4. Prod Docker default.
|
|
73
|
+
return default_root.resolve()
|
|
25
74
|
SUBPROCESS_TIMEOUT_SEC = 60
|
|
26
75
|
|
|
27
76
|
# Phase 1.5 E6: keep-ref so fire-and-forget background tasks don't get GC'd
|
|
@@ -53,7 +102,7 @@ ProjectType = Literal["work", "code", "system"]
|
|
|
53
102
|
|
|
54
103
|
|
|
55
104
|
def _project_root(slug: str) -> Path:
|
|
56
|
-
return (
|
|
105
|
+
return (_projects_root() / slug).resolve()
|
|
57
106
|
|
|
58
107
|
|
|
59
108
|
def _load_project_entry(slug: str) -> tuple[ProjectType, Path | None]:
|
|
@@ -418,12 +467,13 @@ async def _ensure_kg_edge(
|
|
|
418
467
|
},
|
|
419
468
|
ensure_ascii=False,
|
|
420
469
|
)
|
|
470
|
+
projects_root = _projects_root()
|
|
421
471
|
candidate_paths = [
|
|
422
472
|
str(target_path),
|
|
423
|
-
str(target_path.relative_to(
|
|
473
|
+
str(target_path.relative_to(projects_root)),
|
|
424
474
|
]
|
|
425
475
|
if project_slug == "marvisx":
|
|
426
|
-
candidate_paths.append(f"projects/{target_path.relative_to(
|
|
476
|
+
candidate_paths.append(f"projects/{target_path.relative_to(projects_root)}")
|
|
427
477
|
|
|
428
478
|
async with acquire_write_db() as db:
|
|
429
479
|
await db.execute(
|
|
@@ -32,6 +32,22 @@ INTERNET_PROBE_TARGETS = (
|
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
_PROBE_DISABLED_VALUES = {"0", "off", "false", "no"}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def network_probe_enabled() -> bool:
|
|
39
|
+
"""Whether the periodic internet probe (cloudflare.com/cdn-cgi/trace) runs.
|
|
40
|
+
|
|
41
|
+
Gated by ``$MARVIS_NETWORK_PROBE``: values in {0, off, false, no}
|
|
42
|
+
(case-insensitive) disable the probe — this is what makes an "offline mode"
|
|
43
|
+
honest. Default (env unset / any other value) = ON, so prod is unchanged.
|
|
44
|
+
"""
|
|
45
|
+
raw = os.environ.get("MARVIS_NETWORK_PROBE")
|
|
46
|
+
if raw is None:
|
|
47
|
+
return True
|
|
48
|
+
return raw.strip().lower() not in _PROBE_DISABLED_VALUES
|
|
49
|
+
|
|
50
|
+
|
|
35
51
|
def terminal_metrics_path(
|
|
36
52
|
*,
|
|
37
53
|
now: datetime | None = None,
|
|
@@ -175,17 +191,20 @@ async def terminal_metrics_background_loop(
|
|
|
175
191
|
collector.record_event_loop_lag(max(0.0, (now - expected_wake) * 1000))
|
|
176
192
|
|
|
177
193
|
if now >= next_probe_at:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
194
|
+
if network_probe_enabled():
|
|
195
|
+
try:
|
|
196
|
+
probe = await sample_internet_probe(collector)
|
|
197
|
+
await append_terminal_metrics_record(
|
|
198
|
+
{
|
|
199
|
+
"kind": "internet_probe",
|
|
200
|
+
"probe": probe,
|
|
201
|
+
},
|
|
202
|
+
output_dir=output_dir,
|
|
203
|
+
)
|
|
204
|
+
except Exception:
|
|
205
|
+
logger.warning(
|
|
206
|
+
"terminal metrics internet probe failed", exc_info=True
|
|
207
|
+
)
|
|
189
208
|
next_probe_at = now + network_interval_seconds
|
|
190
209
|
|
|
191
210
|
if now >= next_dump_at:
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Regression: require_scope must DENY agent tokens with empty/null scopes.
|
|
2
|
+
|
|
3
|
+
Audit S4: an agent token with scopes=[] previously satisfied `not user.scopes`
|
|
4
|
+
and was treated as unrestricted (authz bypass — a scope-gated PATCH succeeded
|
|
5
|
+
with an empty-scope token). Empty scopes must grant NO permission.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
from fastapi import HTTPException
|
|
11
|
+
|
|
12
|
+
from core.api.models.auth import UserInfo
|
|
13
|
+
from core.api.rbac import require_scope
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _agent(scopes: list[str]) -> UserInfo:
|
|
17
|
+
# "agent:" prefix forces the agent path (not the human cookie bypass).
|
|
18
|
+
return UserInfo(
|
|
19
|
+
username="agent:tester",
|
|
20
|
+
user_id="tok-1",
|
|
21
|
+
system_role="operator",
|
|
22
|
+
user_type="agent",
|
|
23
|
+
scopes=scopes,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _human(scopes: list[str]) -> UserInfo:
|
|
28
|
+
return UserInfo(
|
|
29
|
+
username="emilio",
|
|
30
|
+
user_id="user-1",
|
|
31
|
+
system_role="operator",
|
|
32
|
+
user_type="human",
|
|
33
|
+
scopes=scopes,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@pytest.mark.asyncio
|
|
38
|
+
async def test_empty_scopes_agent_denied():
|
|
39
|
+
check = require_scope("write")
|
|
40
|
+
with pytest.raises(HTTPException) as exc:
|
|
41
|
+
await check(user=_agent([]))
|
|
42
|
+
assert exc.value.status_code == 403
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.mark.asyncio
|
|
46
|
+
async def test_matching_scope_agent_allowed():
|
|
47
|
+
check = require_scope("write")
|
|
48
|
+
user = await check(user=_agent(["read", "write"]))
|
|
49
|
+
assert user.username == "agent:tester"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.mark.asyncio
|
|
53
|
+
async def test_missing_scope_agent_denied():
|
|
54
|
+
check = require_scope("write")
|
|
55
|
+
with pytest.raises(HTTPException) as exc:
|
|
56
|
+
await check(user=_agent(["read"]))
|
|
57
|
+
assert exc.value.status_code == 403
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@pytest.mark.asyncio
|
|
61
|
+
async def test_human_bypasses_scope_check_even_with_empty_scopes():
|
|
62
|
+
# Cookie/JWT humans are gated by role, not scopes — empty scopes is fine.
|
|
63
|
+
check = require_scope("write")
|
|
64
|
+
user = await check(user=_human([]))
|
|
65
|
+
assert user.username == "emilio"
|
|
@@ -345,3 +345,60 @@ def test_bash_action_returns_first_matching_rule(monkeypatch):
|
|
|
345
345
|
|
|
346
346
|
assert decision.allowed is False
|
|
347
347
|
assert decision.rule == "bash-merge"
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def test_secret_scan_runs_outside_git_repo(monkeypatch):
|
|
351
|
+
"""S5a: secret scan must NOT fail open when cwd is not a git repo.
|
|
352
|
+
|
|
353
|
+
Previously resolve_repo_root() returning None silently allowed, so a
|
|
354
|
+
`git commit` of an API_KEY=sk-live-... outside a repo slipped through.
|
|
355
|
+
"""
|
|
356
|
+
bridge = _load_bridge_module()
|
|
357
|
+
monkeypatch.setattr(
|
|
358
|
+
bridge, "resolve_repo_root", lambda file_path, cwd=None: None
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
decision = bridge.check_secret_scan(
|
|
362
|
+
"git commit -m 'add config' && export API_KEY=sk-live-abcd1234efgh5678ijkl",
|
|
363
|
+
"/tmp/not-a-repo",
|
|
364
|
+
_config(),
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
assert decision.allowed is False
|
|
368
|
+
assert decision.rule == "secret-scan"
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def test_secret_scan_outside_repo_allows_clean_command(monkeypatch):
|
|
372
|
+
"""Outside a git repo, a clean commit command (no secret) is still allowed."""
|
|
373
|
+
bridge = _load_bridge_module()
|
|
374
|
+
monkeypatch.setattr(
|
|
375
|
+
bridge, "resolve_repo_root", lambda file_path, cwd=None: None
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
decision = bridge.check_secret_scan(
|
|
379
|
+
"git commit -m 'docs: tidy readme'",
|
|
380
|
+
"/tmp/not-a-repo",
|
|
381
|
+
_config(),
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
assert decision.allowed is True
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def test_secret_scan_blocks_secret_in_staged_diff(monkeypatch):
|
|
388
|
+
"""In-repo path (unchanged behaviour): secret in staged diff is blocked."""
|
|
389
|
+
bridge = _load_bridge_module()
|
|
390
|
+
monkeypatch.setattr(
|
|
391
|
+
bridge, "resolve_repo_root", lambda file_path, cwd=None: "/repo"
|
|
392
|
+
)
|
|
393
|
+
monkeypatch.setattr(
|
|
394
|
+
bridge,
|
|
395
|
+
"_git_output",
|
|
396
|
+
lambda args, cwd: "+API_KEY=sk-live-abcd1234efgh5678ijkl",
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
decision = bridge.check_secret_scan(
|
|
400
|
+
"git commit -m 'add config'", "/repo", _config()
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
assert decision.allowed is False
|
|
404
|
+
assert decision.rule == "secret-scan"
|
|
@@ -225,20 +225,17 @@ async def trigger_reindex(
|
|
|
225
225
|
|
|
226
226
|
async def _reindex_type(doc_type: str, workspace_id: str) -> dict:
|
|
227
227
|
"""Reindex a single document type. Returns stats dict."""
|
|
228
|
-
from
|
|
229
|
-
|
|
230
|
-
from core.api.db import _configure_connection
|
|
228
|
+
from core.api.db import _configure_connection, resolve_vec0_loadable
|
|
231
229
|
|
|
232
230
|
db = await aiosqlite.connect(settings.db_path)
|
|
233
231
|
await _configure_connection(db)
|
|
234
232
|
db.row_factory = aiosqlite.Row
|
|
235
233
|
await db.execute("PRAGMA busy_timeout=60000")
|
|
236
234
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if vec_so.exists():
|
|
235
|
+
load_arg, vec_found = resolve_vec0_loadable()
|
|
236
|
+
if vec_found and load_arg is not None:
|
|
240
237
|
await db._execute(db._conn.enable_load_extension, True)
|
|
241
|
-
await db.execute("SELECT load_extension(?)", [
|
|
238
|
+
await db.execute("SELECT load_extension(?)", [load_arg])
|
|
242
239
|
await db.execute("""
|
|
243
240
|
CREATE VIRTUAL TABLE IF NOT EXISTS vec_documents USING vec0(
|
|
244
241
|
doc_id INTEGER PRIMARY KEY,
|
|
@@ -272,8 +269,7 @@ async def _reindex_all_bg(db_path: str) -> None:
|
|
|
272
269
|
Uses a SINGLE connection with vec extension loaded as both db and vec_db.
|
|
273
270
|
Two separate writers to the same DB cause 'database is locked' errors.
|
|
274
271
|
"""
|
|
275
|
-
from
|
|
276
|
-
from core.api.db import _configure_connection
|
|
272
|
+
from core.api.db import _configure_connection, resolve_vec0_loadable
|
|
277
273
|
|
|
278
274
|
logger.info("Reindex all: starting background job")
|
|
279
275
|
try:
|
|
@@ -282,12 +278,11 @@ async def _reindex_all_bg(db_path: str) -> None:
|
|
|
282
278
|
db.row_factory = aiosqlite.Row
|
|
283
279
|
# Higher busy_timeout for background reindex — avoids blocking regular requests
|
|
284
280
|
await db.execute("PRAGMA busy_timeout=60000")
|
|
285
|
-
# Load vec extension on the same connection
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
if vec_so.exists():
|
|
281
|
+
# Load vec extension on the same connection (cross-platform: .so/.dylib)
|
|
282
|
+
load_arg, vec_found = resolve_vec0_loadable()
|
|
283
|
+
if vec_found and load_arg is not None:
|
|
289
284
|
await db._execute(db._conn.enable_load_extension, True)
|
|
290
|
-
await db.execute("SELECT load_extension(?)", [
|
|
285
|
+
await db.execute("SELECT load_extension(?)", [load_arg])
|
|
291
286
|
await db.execute("""
|
|
292
287
|
CREATE VIRTUAL TABLE IF NOT EXISTS vec_documents USING vec0(
|
|
293
288
|
doc_id INTEGER PRIMARY KEY,
|