marvisx-cli 0.3.8b2__tar.gz → 0.3.8b4__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.3.8b2 → marvisx_cli-0.3.8b4}/PKG-INFO +1 -1
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/config.py +17 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/db.py +50 -42
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/server.py +7 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/graph.py +5 -4
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/graph_ux.py +62 -1
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/graph.py +50 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/jobs.py +72 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/memory_ops.py +15 -4
- marvisx_cli-0.3.8b4/core/api/services/brain/temporal_recency.py +195 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/graph_service.py +123 -5
- marvisx_cli-0.3.8b4/core/api/tests/test_graph_freshness_flag.py +136 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_graph_neighbors_denoise.py +167 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_graph_summary.py +32 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_kg_claims_builder.py +171 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_kg_claims_wire.py +128 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_kg_trust_write_path.py +143 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_migration_149.py +121 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_populate_decay_flag.py +67 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_session_brief_temporal.py +82 -0
- marvisx_cli-0.3.8b4/core/api/tests/test_temporal_recency.py +148 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/graph.py +419 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/projects.py +42 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/populate_project_nodes.py +115 -6
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/marvisx_cli.egg-info/PKG-INFO +1 -1
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/marvisx_cli.egg-info/SOURCES.txt +13 -0
- marvisx_cli-0.3.8b4/migrations/149_kg_trust_columns.sql +43 -0
- marvisx_cli-0.3.8b4/migrations/149_kg_trust_columns_down.sql +17 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/pyproject.toml +1 -1
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/LICENSE +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/MANIFEST.in +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/README.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/agents/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/agents/session_health.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/agents/session_manager.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/bin/marvisx-state-hook.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/dependencies/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/dependencies/tenant.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/main.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/_adapter.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/brain.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/handoffs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/ingest.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/learnings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/projects.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/pull_requests.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/safety.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/search.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/tasks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/workflow_playbooks/brainstorm.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/workflow_playbooks/compound.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/workflow_playbooks/plan.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/mcp/tools/workflows.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/middleware/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/middleware/tool_call_audit.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/auth.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/brain.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/common.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/costs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/graph.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/graph_cosmo.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/graph_pr_impact.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/inbox.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/ingest_keys.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/kg.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/llm_config.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/monitoring.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/projects.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/search.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/sessions.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/tasks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/teams.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/models/users.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/observability/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/observability/tracing.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/paths.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/rate_limit.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/rbac.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/_adapter.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/admin_pr_impact.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/admin_settings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/agent.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/agent_tokens.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/app_settings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/audit.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/auth.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/bench.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/brain.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/brain_directions.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/ci_checks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/comments.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/costs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/docs_coverage.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/docs_governance.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/documents.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/files.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/finder.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/handoffs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/inbox.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/ingest_api_keys.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/ingest_triage.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/judge.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/kg.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/learnings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/llm_config.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/monitoring.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/notifications.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/pr_impact.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/projects.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/pull_requests.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/push.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/raci.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/search.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/sessions.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/settings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/share_repo.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/status_updates.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/tags.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/tasks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/teams.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/terminal.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/users.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/routers/webhooks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/runtime_settings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/security.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/_fts.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/audit.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/auto_approval.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/baseline.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/capabilities.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/cascade_rollup.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/compound_bridge.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/cycle.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/cycle_snapshot.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/digest_collector.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/direction.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/drift.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/drift_router.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/edge_metrics.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/events_reader.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/findings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/findings_reader.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/journal.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/knowledge_forms.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/_runner.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/base.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/cache.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/constants.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/direction_alignment.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/factory.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/finding_reasoning.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/finding_summary.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/grounding.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/journal_polish.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/local_gateway.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/parsers.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/llm/router_glue.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/models.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/owner_hint.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/recap.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/_signals.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/dr1_activity_without_status.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/dr2_decision_without_adr.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/dr3_stale_open_loop.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/dr4_docs_governance_drift.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/dr5_playbook_changed.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/dr6_external_update_unpropagated.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/dr7_claimed_decision_gap.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/rules/dr8_direction_misalignment.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/runs_reader.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/scope.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/sources/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/sources/base.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/sources/git_kg.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/sources/handoffs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/sources/ingestor.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/sources/learnings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/sources/pir_tasks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/warehouse_consolidate.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/watermarks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/brain/ws_emitter.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/cc_tasks_reader.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/chunking.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ci_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/claude_metrics.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/codex_metrics.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/conversation_reader.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/cost_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/crypto.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/docs_governance/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/docs_governance/confidence.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/docs_governance/config.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/docs_governance/enrichment.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/docs_governance/frontmatter_validator.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/docs_governance/hard_gates.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/docs_governance/triage_orchestrator.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/dream_cycle.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/embedding_backends/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/embedding_internal.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/embedding_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/event_dispatcher.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/events.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/git_ops.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/graph_cosmo_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/graph_ranker.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/grounding/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/grounding/citations.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/grounding/verifier.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_digest.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_digest_deep_research.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_digest_jobs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_gmail_sync.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_llm_classifier.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_source_identity.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_sources.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_taxonomy.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_tldr.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/inbox_triage.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/api_key_auth.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/auto_approve.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/classifier.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/confidence.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/dispatch.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/embedding_router.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/events.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/ignore_patterns.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/image_probe.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/ingress.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/insert_saga.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/anthropic_haiku.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/base.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/byok_provider.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/classification_context.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/config_store.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/factory.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/kg_enricher.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/local_gateway.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/local_vllm.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/llm/openai_nano.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/lock_advisory.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parser_router.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/docling_parser.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/docparse_gateway.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/docx_parser.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/folder_unpacker.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/gateway_aux.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/image_parser.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/internal_markdown.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/ocr_gateway.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/ocr_pdf_parser.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/pdf_types.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/transcript_parser.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/vision_gateway.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/xlsx_parser.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/parsers/zip_unpacker.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/preflight.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/routing_policy.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/serializers/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/serializers/xlsx_to_markdown.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/skip_log.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/ingest/watcher.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/audit.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/communities.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/community_summary.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/graph_lane.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/hybrid_search.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/lens.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/pr_impact.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/queries.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/ranking.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg/rrf.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/kg_watcher_control.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/local_llm/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/local_llm/async_client.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/local_llm/client.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/local_llm/url_validator.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/metrics_collector.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/metrics_providers.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/model_registry.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/model_router.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/n8n_client.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/newsletter_llm_gateway.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/notification_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/openai_responses.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/opencode_metrics.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/opencode_sessions.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pii_redactor.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pr_impact_pipeline/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pr_impact_pipeline/differ.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pr_impact_pipeline/dispatcher.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pr_impact_pipeline/gc.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pr_impact_pipeline/languages.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pr_impact_pipeline/parser.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pr_impact_pipeline/writer.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/pr_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/project_paths.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/project_status_updates.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/providers.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/push_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/reminder_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/runas.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/salience_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/security_collector.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/session_catalog.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/session_metrics_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/session_ops.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/session_state.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/share_links.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/task_transitions.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/temporal_tiebreak.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/temporal_write.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/terminal_metrics.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/terminal_metrics_dump.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/tmux.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/webhook_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/services/workspace_sync.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/templates/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/templates/markdown_share.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/terminal.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_agent_facing_auth_dependencies.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_audit_permissions.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_backfill_session_conversations.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_backfill_working_seconds_msg.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_claude_metrics.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_codex_metrics.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_config_env_aliases.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_finder_paths.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_git_ops_merge.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_graph_freshness.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_learnings_check_search.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_learnings_create_pre148.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_metrics_providers.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_migration_087.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_migration_088.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_migration_089.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_openai_responses.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_opencode_metrics.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_opencode_sessions.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_pr_workflow_e2e.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_projects_handoffs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_providers.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_require_scope_empty_deny.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_safety_bridge.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_session_catalog.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_session_conversations.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_session_metrics_service.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_session_resume_paths.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_session_theme_mode_migration.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_sessions_rbac.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_share_edit.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_share_repo.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_terminal_session_manager.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_terminal_upload.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_tmux.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_workspace_sync.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/tests/test_ws_ticket_in_memory.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/_context.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/_errors.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/_roles.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/audit.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/brain.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/costs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/handoffs.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/ingest_triage.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/learnings.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/pull_requests.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/search.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/use_cases/tasks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/api/visibility.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/README.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/_brain_opportunistic.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/_brain_schedule.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/_index_source.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/_runtime_ctx.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/_transmute.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/_update_check.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/guides/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/guides/marvis-way.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_account.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_brain.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_doctor.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_feedback.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_governance.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_guide.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_hooks.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_init.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_mcp.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_runtime.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/cli/marvis_telemetry.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/platform/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/_drift_check.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/_frontmatter.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/_graph_writer.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/ast_parser.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/_config.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/block-dangerous-bash.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/block-db-direct-write.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/block-push-no-task.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/block-staging-to-prod.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/block-subtree-push.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/config.json +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/enforce-no-merge-main.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/enforce-worktree.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/quality-gate.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/safety_bridge.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/install_hooks/secret-scan.sh +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/migrate_spike_node_ids.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/populate_artifacts.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/populate_cross_project.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/populate_inbox_nodes.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/populate_pr_impact.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/populate_touch_counter.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/reparse_failed.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/scripts/safety_bridge.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/telemetry/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/telemetry/client.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/telemetry/entitlements.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/telemetry/rollup.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/telemetry/schema.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/telemetry/sender.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/wizard/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/wizard/byok_vault.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/wizard/defaults.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/wizard/state.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/wizard/steps.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/core/wizard/validation.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/marvisx_cli.egg-info/dependency_links.txt +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/marvisx_cli.egg-info/entry_points.txt +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/marvisx_cli.egg-info/requires.txt +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/marvisx_cli.egg-info/top_level.txt +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/001_initial.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/002_tasks.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/003_session_management.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/004_projects_comments.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/005_session_intelligence.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/006_settings.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/007_task_scoring.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/008_cost_tracking.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/009_session_card_metrics.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/010_monitoring.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/012_agent_api.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/013_session_complete.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/015_pull_requests.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/015_pull_requests_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/016_users_raci.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/017_task_cost_entries.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/018_agents.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/018_agents_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/019_review_feedback.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/020_pr_commit_sha.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/021_webhook_events.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/022_devx_agent_managed.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/022_devx_agent_managed_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/023_devx_p1_gate.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/023_devx_p1_gate_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/024_chat_messages.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/024_pr_conversation_id.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/024_task_indexes.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/024_task_indexes_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/025_audit_log.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/026_agent_tokens.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/027_teams_auth_phase_b.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/028_learnings.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/029_team_roles.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/030_finder_pins.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/031_pr_deploy_status.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/032_task_reminders.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/033_events_retry_count.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/033_session_owner.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/034_notifications.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/035_shared_links.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/036_session_index_upgrade.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/037_pr_approval.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/038_pr_submitted_by.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/039_push_subscriptions.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/040_semantic_search.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/041_workspaces.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/042_oidc_providers.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/043_ci_checks.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/044_agent_metrics.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/045_documents_doc_type.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/046_salience.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/047_seed_missing_agents.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/048_fix_agent_paths_roles.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/049_agent_role_and_learnings_schema.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/050_session_provider.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/051_session_launch_profile.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/052_session_theme_mode.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/052_task_kind.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/053_inbox_items.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/054_inbox_triage_contract.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/055_inbox_topic_treatment.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/056_inbox_treatment_read_save.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/057_session_theme_mode_backfill.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/058_inbox_item_status_lifecycle.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/059_inbox_tldr_and_source_scores.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/060_newsletter.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/061_inbox_redesign.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/062_fix_inbox_sources_backfill.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/063_task_completion_mode.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/064_judge_mode_setting.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/065_knowledge_graph_spike.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/066_digest_ranking_inputs.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/066_kg_artifact_nodes.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/067_inbox_digest_selections.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/067_kg_temporal.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/068_inbox_digest_app_settings.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/068_kg_touch_counter.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/069_kg_doc_types.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/070_digest_ranking_inputs_recovery.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/071_inbox_digest_selections_recovery.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/072_inbox_digest_app_settings_recovery.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/073_kg_cross_project.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/073_kg_cross_project_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/074_kg_infra_types.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/074_kg_infra_types_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/075_kg_file_state_recovery.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/075_kg_file_state_recovery_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/076_kg_watcher_state.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/076_kg_watcher_state_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/077_kg_doc_types_extend.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/077_kg_doc_types_extend_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/078_kg_fts5.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/078_kg_fts5_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/079_kg_missing_indexes.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/079_kg_missing_indexes_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/080_kg_fts5_extended.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/080_kg_fts5_extended_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/081_kg_lens_indexes.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/081_kg_lens_indexes_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/082_kg_pins.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/082_kg_pins_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/083_kg_graph_nodes_degree.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/083_kg_graph_nodes_degree_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/084_drop_legacy_scheduler_tables.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/084_drop_legacy_scheduler_tables_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/085_kg_edge_resolves_to.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/085_kg_edge_resolves_to_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/086_project_status_updates_feed.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/086_project_status_updates_feed_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/087_session_metrics_dual.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/087_session_metrics_dual_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/088_rename_context_pct_legacy.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/088_rename_context_pct_legacy_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/089_session_metrics_equivalent_cost.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/089_session_metrics_equivalent_cost_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/090_kg_inbox_node_type.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/090_kg_inbox_node_type_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/091_kg_inbox_node_type_check.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/091_kg_inbox_node_type_check_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/092_sessions_activity_state_ts.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/092_sessions_activity_state_ts_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/093_sessions_activity_state_column.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/093_sessions_activity_state_column_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/094_ingest_pending.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/094_ingest_pending_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/095_kg_intent_first.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/095_kg_intent_first_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/096_kg_xlsx_artifact_prefix.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/096_kg_xlsx_artifact_prefix_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/097_ingest_change_history.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/097_ingest_change_history_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/098_kg_node_type_business.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/098_kg_node_type_business_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/099_kg_edges_restore_weight.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/099_kg_edges_restore_weight_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/100_kg_enriched_at.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/100_kg_enriched_at_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/101_local_llm_shadow_comparisons.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/101_local_llm_shadow_comparisons_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/102_promote_llm_costs.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/102_promote_llm_costs_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/103_ingest_skipped_log.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/103_ingest_skipped_log_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/120_docs_governance.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/120_docs_governance_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/121_notification_event_fk_cleanup.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/121_notification_event_fk_cleanup_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/122_docs_drift_history.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/122_docs_drift_history_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/123_ingest_parser_waiting_status.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/123_ingest_parser_waiting_status_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/124_heypocket_recordings.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/124_heypocket_recordings_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/125_kg_node_type_record.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/125_kg_node_type_record_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/126_ingest_terminal_upload_source_kind.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/126_ingest_terminal_upload_source_kind_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/127_brain_v1_substrate.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/127_brain_v1_substrate_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/128_brain_drift_signals.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/128_brain_drift_signals_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/129_brain_memory_operations.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/129_brain_memory_operations_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/130_brain_findings.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/130_brain_findings_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/132_kg_pr_modifies.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/132_kg_pr_modifies_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/133_brain_v1_2_direction_schema.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/133_brain_v1_2_direction_schema_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/134_brain_journal_narrative_polished.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/134_brain_journal_narrative_polished_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/135_kg_edges_provider.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/136_documents_fts.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/137_promote_llm_costs.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/137_promote_llm_costs_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/138_ingest_api_keys.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/138_ingest_api_keys_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/139_ingest_pending_ingress.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/139_ingest_pending_ingress_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/140_ingest_idempotency_quota.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/140_ingest_idempotency_quota_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/141_ingest_pending_metadata.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/141_ingest_pending_metadata_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/142_llm_function_config.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/142_llm_function_config_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/143_kg_code_embeddings.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/143_kg_code_embeddings_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/144_notifications_pending_sync_index.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/145_audit_log_immutable.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/145_audit_log_immutable_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/146_drop_kg_backup_tables.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/146_drop_kg_backup_tables_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/147_chunks.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/147_chunks_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/148_bitemporal_learnings.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/148_bitemporal_learnings_down.sql +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/migrations/__init__.py +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/projects/_template/context.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/projects/_template/docs/brainstorms/YYYY-MM-DD-example-brainstorm.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/projects/_template/docs/plans/YYYY-MM-DD-example-plan.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/projects/_template/docs/solutions/YYYY-MM-DD-example-solution.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/projects/_template/input/README.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/projects/_template/memory/handoff.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/projects/_template/output/README.md +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/projects/_template/project.yaml +0 -0
- {marvisx_cli-0.3.8b2 → marvisx_cli-0.3.8b4}/setup.cfg +0 -0
|
@@ -125,6 +125,13 @@ class Settings(BaseSettings):
|
|
|
125
125
|
default=86400, alias="BRAIN_WAREHOUSE_CONSOLIDATION_INTERVAL_SECONDS"
|
|
126
126
|
)
|
|
127
127
|
|
|
128
|
+
# KG temporal recency pass (Fase D producer): proposes re-verifying aging,
|
|
129
|
+
# never-verified live nodes. Gated by temporal_memory_enabled (no separate
|
|
130
|
+
# enable flag — the flag IS the gate). Daily cadence guard.
|
|
131
|
+
brain_temporal_recency_interval_seconds: int = Field(
|
|
132
|
+
default=86400, alias="BRAIN_TEMPORAL_RECENCY_INTERVAL_SECONDS"
|
|
133
|
+
)
|
|
134
|
+
|
|
128
135
|
# GitHub Webhook
|
|
129
136
|
github_webhook_secret: str = ""
|
|
130
137
|
|
|
@@ -475,6 +482,16 @@ class Settings(BaseSettings):
|
|
|
475
482
|
default=False, alias="MARVIS_TEMPORAL_MEMORY"
|
|
476
483
|
)
|
|
477
484
|
|
|
485
|
+
# answer-ready claims (DEFAULT OFF). When False every reasoning-tool read is
|
|
486
|
+
# byte-identical to today (no `claims` key). When True, project_impact/
|
|
487
|
+
# graph_impact append a `claims[]` block: server-computed, relation-typed
|
|
488
|
+
# counts with provenance — the agent reports the value instead of re-counting
|
|
489
|
+
# raw edges (faithfulness). Separate from temporal_memory so grounding can be
|
|
490
|
+
# enabled without the freshness surface. See plan 2026-06-08-feat-answer-ready-claims.
|
|
491
|
+
kg_claims_enabled: bool = Field(
|
|
492
|
+
default=False, alias="MARVIS_KG_CLAIMS"
|
|
493
|
+
)
|
|
494
|
+
|
|
478
495
|
# Track 2 #3c — community summaries in the brief (GraphRAG global-search,
|
|
479
496
|
# DEFAULT OFF). When False the brief is byte-identical to today: the
|
|
480
497
|
# communities/community_summary modules are a flag-gated library + seam,
|
|
@@ -739,54 +739,62 @@ def _backfill_session_uuids(conn: sqlite3.Connection) -> None:
|
|
|
739
739
|
|
|
740
740
|
|
|
741
741
|
def _seed_users_and_migrate_owner(conn: sqlite3.Connection) -> None:
|
|
742
|
-
"""Migration 016 post-hook: seed the admin user + data-migrate
|
|
742
|
+
"""Migration 016 post-hook: seed the admin user (when configured) + data-migrate
|
|
743
|
+
tasks.owner_id.
|
|
743
744
|
|
|
744
745
|
Runs synchronously inside run_migrations() — do NOT use await here.
|
|
745
|
-
Accepts either PIR_ADMIN_PASSWORD_HASH (pre-hashed, preferred in production)
|
|
746
|
-
or PIR_PASSWORD (plaintext, will be bcrypt-hashed here).
|
|
747
|
-
At least one must be set or the migration aborts.
|
|
748
|
-
|
|
749
|
-
The admin identity is config-driven via the same MARVIS_ADMIN_* vars used by
|
|
750
|
-
the deploy bootstrap (scripts/init.sh), with generic defaults, so a fresh
|
|
751
|
-
install seeds no hardcoded name. On an existing deployment this seed is
|
|
752
|
-
skipped (users already exist), so the defaults never affect a running install.
|
|
753
|
-
"""
|
|
754
|
-
# Prefer pre-hashed password. Canonical var is MARVIS_ADMIN_PASSWORD_HASH;
|
|
755
|
-
# PIR_ADMIN_PASSWORD_HASH stays accepted as a deprecated alias.
|
|
756
|
-
hashed = (
|
|
757
|
-
os.environ.get("MARVIS_ADMIN_PASSWORD_HASH")
|
|
758
|
-
or os.environ.get("PIR_ADMIN_PASSWORD_HASH", "")
|
|
759
|
-
).strip()
|
|
760
|
-
if not hashed:
|
|
761
|
-
import bcrypt
|
|
762
|
-
|
|
763
|
-
seed_password = (
|
|
764
|
-
os.environ.get("MARVIS_PASSWORD")
|
|
765
|
-
or os.environ.get("PIR_PASSWORD", "")
|
|
766
|
-
).strip()
|
|
767
|
-
if not seed_password:
|
|
768
|
-
raise RuntimeError(
|
|
769
|
-
"Migration 016 requires MARVIS_ADMIN_PASSWORD_HASH or MARVIS_PASSWORD "
|
|
770
|
-
"env var (PIR_* aliases still accepted) to seed the admin user. "
|
|
771
|
-
"Set at least one in .env."
|
|
772
|
-
)
|
|
773
|
-
hashed = bcrypt.hashpw(seed_password.encode("utf-8"), bcrypt.gensalt()).decode()
|
|
774
|
-
|
|
775
|
-
admin_id = os.environ.get("MARVIS_ADMIN_USER_ID", "").strip() or "usr_admin"
|
|
776
|
-
admin_slug = os.environ.get("MARVIS_ADMIN_SLUG", "").strip() or "admin"
|
|
777
|
-
admin_name = os.environ.get("MARVIS_ADMIN_DISPLAY_NAME", "").strip() or "Admin"
|
|
778
746
|
|
|
747
|
+
Admin seeding is OPTIONAL and config-driven: the admin user is created only when
|
|
748
|
+
a real credential is present (MARVIS_ADMIN_PASSWORD_HASH or MARVIS_PASSWORD; PIR_*
|
|
749
|
+
aliases accepted). With NO credential — the OSS single-user case, where the CLI
|
|
750
|
+
uses the local single-user context and never logs in with a password — the seed
|
|
751
|
+
is SKIPPED (not aborted), so a fresh-DB boot via init_pool (MCP server / brain,
|
|
752
|
+
which now run migrations) does not crash on a clean install. `marvis init` sets
|
|
753
|
+
MARVIS_PASSWORD before migrating, so it still seeds the admin. The owner_id
|
|
754
|
+
slug→id data migration always runs (idempotent), regardless of seeding.
|
|
755
|
+
|
|
756
|
+
b3 note: the real cleanup is to decouple admin seeding from run_migrations
|
|
757
|
+
entirely — it belongs in `marvis init` / `marvis account`, not in a schema hook.
|
|
758
|
+
"""
|
|
779
759
|
cursor = conn.execute("SELECT COUNT(*) FROM users")
|
|
780
760
|
user_count = cursor.fetchone()[0]
|
|
781
761
|
if user_count == 0:
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
"
|
|
786
|
-
(
|
|
787
|
-
)
|
|
788
|
-
|
|
789
|
-
|
|
762
|
+
# Prefer a pre-hashed password (canonical MARVIS_ADMIN_PASSWORD_HASH;
|
|
763
|
+
# PIR_ADMIN_PASSWORD_HASH stays a deprecated alias).
|
|
764
|
+
hashed = (
|
|
765
|
+
os.environ.get("MARVIS_ADMIN_PASSWORD_HASH")
|
|
766
|
+
or os.environ.get("PIR_ADMIN_PASSWORD_HASH", "")
|
|
767
|
+
).strip()
|
|
768
|
+
if not hashed:
|
|
769
|
+
seed_password = (
|
|
770
|
+
os.environ.get("MARVIS_PASSWORD")
|
|
771
|
+
or os.environ.get("PIR_PASSWORD", "")
|
|
772
|
+
).strip()
|
|
773
|
+
if seed_password:
|
|
774
|
+
import bcrypt
|
|
775
|
+
|
|
776
|
+
hashed = bcrypt.hashpw(
|
|
777
|
+
seed_password.encode("utf-8"), bcrypt.gensalt()
|
|
778
|
+
).decode()
|
|
779
|
+
else:
|
|
780
|
+
logger.warning(
|
|
781
|
+
"Migration 016: no MARVIS_ADMIN_PASSWORD_HASH / MARVIS_PASSWORD in "
|
|
782
|
+
"env — admin user NOT seeded (schema applied). Single-user CLI uses "
|
|
783
|
+
"the local context (no login); create an admin later with `marvis "
|
|
784
|
+
"init` if you want HTTP login."
|
|
785
|
+
)
|
|
786
|
+
if hashed: # seed ONLY when we actually have a credential
|
|
787
|
+
admin_id = os.environ.get("MARVIS_ADMIN_USER_ID", "").strip() or "usr_admin"
|
|
788
|
+
admin_slug = os.environ.get("MARVIS_ADMIN_SLUG", "").strip() or "admin"
|
|
789
|
+
admin_name = os.environ.get("MARVIS_ADMIN_DISPLAY_NAME", "").strip() or "Admin"
|
|
790
|
+
conn.execute(
|
|
791
|
+
"INSERT OR IGNORE INTO users "
|
|
792
|
+
"(id, slug, display_name, type, password_hash, system_role) "
|
|
793
|
+
"VALUES (?, ?, ?, ?, ?, ?)",
|
|
794
|
+
(admin_id, admin_slug, admin_name, "human", hashed, "super_admin"),
|
|
795
|
+
)
|
|
796
|
+
conn.commit()
|
|
797
|
+
logger.info("Migration 016: seeded admin user '%s' (super_admin)", admin_slug)
|
|
790
798
|
|
|
791
799
|
# Data migration: owner_id may contain slug strings (e.g. "emilio") from before
|
|
792
800
|
# the users table existed. Resolve each slug to the corresponding users.id.
|
|
@@ -43,6 +43,13 @@ _INSTRUCTIONS = (
|
|
|
43
43
|
"- 'What breaks if I change function X' (code level): graph_impact / graph_neighbors on a 'py:function:...' node.\n"
|
|
44
44
|
"- 'What do we already know / what bit us before' (decisions and risky actions): check_learnings(q).\n"
|
|
45
45
|
"- Cross-project discovery by meaning: search(q). Body of ONE known project: get_project(slug) — do not layer search on top of get_project.\n"
|
|
46
|
+
"Before answering an orchestration or planning task, confirm you actually called the relevant "
|
|
47
|
+
"tool (session_brief / project_impact / graph_impact) AND that your answer addresses the task "
|
|
48
|
+
"as asked — do not reply from raw files or pivot to an unrelated skill.\n"
|
|
49
|
+
"When you state a number from the knowledge graph (a count, in-degree, how many dependents), "
|
|
50
|
+
"quote it from the tool result's `summary` block and cite it inline — e.g. \"148 edges from 11 "
|
|
51
|
+
"sources [graph_neighbors summary]\". Do NOT re-count a returned list by hand, and do NOT state a "
|
|
52
|
+
"count that no tool result supports.\n"
|
|
46
53
|
)
|
|
47
54
|
|
|
48
55
|
mcp = FastMCP("marvis", instructions=_INSTRUCTIONS)
|
|
@@ -124,9 +124,10 @@ def register(mcp) -> None:
|
|
|
124
124
|
as_of: Annotated[str, Field(pattern=_AS_OF_PATTERN, max_length=32)] | None = None,
|
|
125
125
|
) -> dict[str, Any]:
|
|
126
126
|
"""1-hop: chi tocca / dipende direttamente da un nodo. Funziona su codice ('py:function:...') E su progetti ('project:artifact:<slug>').
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
CHI DIPENDE DA X (in UNA call): graph_neighbors(node_id, direction='incoming', rank='degree') → i dipendenti diretti ordinati per grado + un blocco `summary` GIA' aggregato. E' il tool ovvio per 'chi cita / dipende da X' — NON fare N micro-query (project_impact e' il primo passo, non N).
|
|
128
|
+
ORCHESTRAZIONE: per i vicini diretti di un PROGETTO passa node_id='project:artifact:<slug>' con edge_types=['depends_on']. Codice: caller/callee 1-hop di una function.
|
|
129
|
+
QUANDO USARLO: vicinato diretto; caller inattesi; time-travel as_of; rank=suspect_write per bug write-through-read. Per il blast radius transitivo usa graph_impact / project_impact.
|
|
130
|
+
RESTITUISCE: {neighbors:[{node_id, relation, direction, rank_score?}], summary:{total, distinct_nodes, by_relation, by_direction} (CITA questi numeri, non ricontare la lista), freshness} cap 200."""
|
|
130
131
|
try:
|
|
131
132
|
async with acquire_db() as db:
|
|
132
133
|
# Node proxy hardcodes limit=200 (the surface exposes no limit param).
|
|
@@ -205,7 +206,7 @@ def register(mcp) -> None:
|
|
|
205
206
|
"""Portfolio blast radius: 'se pauso / chiudo / de-prioritizzo questo PROGETTO, quali altri progetti si bloccano?'. Il tool di prima classe per l'orchestrazione cross-progetto — distinto dal grafo-codice.
|
|
206
207
|
Risolve 'project:artifact:<slug>' e fa l'impact BFS sui soli edge progetto->progetto (depends_on / mentions / refers_to). La response porta il segnale freshness (indexed_sha vs HEAD) per non fidarsi di un indice stantio.
|
|
207
208
|
QUANDO USARLO: prima di pausare/chiudere/de-prioritizzare un progetto; sequenziare un portafoglio (cosa sblocca cosa); capire le dipendenze cross-progetto di una decisione.
|
|
208
|
-
RESTITUISCE: {direct_dependents[], transitive_list[], rank_score, freshness}."""
|
|
209
|
+
RESTITUISCE: {direct_dependents[], transitive_list[], rank_score, freshness}. Col flag MARVIS_KG_CLAIMS anche claims[]: quanti progetti dipendono DAVVERO da questo (kind=dependents_depends_on) vs quanti lo nominano soltanto (kind=mentioned_by), gia' contati server-side con provenienza e freschezza — riporta quei numeri, non ri-contare le liste."""
|
|
209
210
|
try:
|
|
210
211
|
async with acquire_db() as db:
|
|
211
212
|
result = await graph_uc.graph_impact(
|
|
@@ -13,7 +13,38 @@ from __future__ import annotations
|
|
|
13
13
|
from datetime import datetime
|
|
14
14
|
from typing import Literal
|
|
15
15
|
|
|
16
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
16
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
17
|
+
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
# answer-ready claims (behind MARVIS_KG_CLAIMS) — server-computed, relation-typed
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
class KGClaim(BaseModel):
|
|
23
|
+
"""A server-computed claim about a KG node: the value is counted by the DB,
|
|
24
|
+
not by the agent. The agent reports it (and the relation) instead of
|
|
25
|
+
re-counting raw edges — this is the faithfulness fix.
|
|
26
|
+
|
|
27
|
+
`kind` names the relation explicitly (e.g. `dependents_depends_on` = real
|
|
28
|
+
dependency, `mentioned_by` = associative, NOT a dependency). `sources` is a
|
|
29
|
+
capped sample of the provenance; `sources_total` is the full count.
|
|
30
|
+
"""
|
|
31
|
+
model_config = ConfigDict(extra="forbid")
|
|
32
|
+
|
|
33
|
+
kind: str = Field(..., description="dependents_depends_on | dependents_imports | dependents_calls | mentioned_by")
|
|
34
|
+
subject: str = Field(..., description="node_id the claim is about")
|
|
35
|
+
value: int = Field(..., ge=0, description="server-computed count (the number to report)")
|
|
36
|
+
sources: list[str] = Field(default_factory=list, description="capped sample of source node ids (provenance)")
|
|
37
|
+
sources_total: int = Field(..., ge=0, description="full provenance count before capping")
|
|
38
|
+
as_of: str | None = Field(None, description="last observation (last_seen_at) of the subject")
|
|
39
|
+
verified: str | None = Field(None, description="last Brain re-confirmation (last_verified_at), or null")
|
|
40
|
+
needs_review: bool = Field(False, description="subject is stale per the read-time freshness budget")
|
|
41
|
+
|
|
42
|
+
@model_validator(mode="after")
|
|
43
|
+
def _sources_within_total(self) -> "KGClaim":
|
|
44
|
+
if self.sources_total < len(self.sources):
|
|
45
|
+
raise ValueError("sources_total must be >= len(sources)")
|
|
46
|
+
return self
|
|
47
|
+
|
|
17
48
|
|
|
18
49
|
# ---------------------------------------------------------------------------
|
|
19
50
|
# Shared type alias (validated at model-field level via annotation)
|
|
@@ -47,6 +78,36 @@ class PinOut(BaseModel):
|
|
|
47
78
|
is_stale: bool = False # True if node was soft-deleted after pinning (belt-and-braces)
|
|
48
79
|
|
|
49
80
|
|
|
81
|
+
# ---------------------------------------------------------------------------
|
|
82
|
+
# Fase D — KG trust write-path request bodies (behind MARVIS_TEMPORAL_MEMORY).
|
|
83
|
+
# The apply actions an agent performs after Triage approves a Brain proposal.
|
|
84
|
+
# ---------------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
class VerifyNodeIn(BaseModel):
|
|
87
|
+
"""Request body for POST /graph/nodes/verify — stamp last_verified_at = now."""
|
|
88
|
+
node_id: str = Field(
|
|
89
|
+
...,
|
|
90
|
+
min_length=6,
|
|
91
|
+
max_length=256,
|
|
92
|
+
pattern=r"^[a-z]+:[a-z]+:.+$",
|
|
93
|
+
description="Node ID to mark re-verified (REINFORCE apply)",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class SupersedeEdgeIn(BaseModel):
|
|
98
|
+
"""Request body for POST /graph/edges/supersede — soft-invalidate an edge."""
|
|
99
|
+
source_id: str = Field(..., min_length=6, max_length=256, pattern=r"^[a-z]+:[a-z]+:.+$")
|
|
100
|
+
target_id: str = Field(..., min_length=6, max_length=256, pattern=r"^[a-z]+:[a-z]+:.+$")
|
|
101
|
+
relation: str = Field(
|
|
102
|
+
..., min_length=2, max_length=32,
|
|
103
|
+
description="Edge relation of the triple to supersede (e.g. depends_on)",
|
|
104
|
+
)
|
|
105
|
+
superseded_by: str | None = Field(
|
|
106
|
+
None, max_length=256,
|
|
107
|
+
description="Optional audit pointer to the replacing edge",
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
50
111
|
# ---------------------------------------------------------------------------
|
|
51
112
|
# Landing bundle
|
|
52
113
|
# ---------------------------------------------------------------------------
|
|
@@ -79,6 +79,8 @@ from core.api.models.graph_ux import (
|
|
|
79
79
|
PinIn,
|
|
80
80
|
PinOut,
|
|
81
81
|
ResolveOut,
|
|
82
|
+
SupersedeEdgeIn,
|
|
83
|
+
VerifyNodeIn,
|
|
82
84
|
)
|
|
83
85
|
from core.api.models.graph_cosmo import GraphCosmoOut
|
|
84
86
|
from core.api.rate_limit import limiter
|
|
@@ -701,6 +703,54 @@ async def delete_graph_pin(
|
|
|
701
703
|
return result
|
|
702
704
|
|
|
703
705
|
|
|
706
|
+
# --- KG trust write-path (Fase D, behind MARVIS_TEMPORAL_MEMORY) ---
|
|
707
|
+
|
|
708
|
+
@router.post("/nodes/verify", response_model=dict, summary="Mark a KG node re-verified")
|
|
709
|
+
@limiter.limit("60/minute")
|
|
710
|
+
async def mark_node_verified(
|
|
711
|
+
body: VerifyNodeIn,
|
|
712
|
+
request: Request,
|
|
713
|
+
user: UserInfo = Depends(get_current_user_or_agent),
|
|
714
|
+
db: aiosqlite.Connection = Depends(get_write_db),
|
|
715
|
+
) -> dict:
|
|
716
|
+
"""Stamp graph_nodes.last_verified_at = now (REINFORCE apply).
|
|
717
|
+
|
|
718
|
+
The action an agent performs after Triage approves a Brain recency proposal.
|
|
719
|
+
Inert (422) when MARVIS_TEMPORAL_MEMORY is off. 404 if the node is missing.
|
|
720
|
+
"""
|
|
721
|
+
ctx = CallerContext.from_user_info(user, is_human_session=False)
|
|
722
|
+
try:
|
|
723
|
+
return await uc.mark_node_verified(ctx, db, node_id=body.node_id)
|
|
724
|
+
except ServiceError as e:
|
|
725
|
+
raise to_http_legacy(e)
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
@router.post("/edges/supersede", response_model=dict, summary="Soft-invalidate a KG edge")
|
|
729
|
+
@limiter.limit("60/minute")
|
|
730
|
+
async def mark_edge_superseded(
|
|
731
|
+
body: SupersedeEdgeIn,
|
|
732
|
+
request: Request,
|
|
733
|
+
user: UserInfo = Depends(get_current_user_or_agent),
|
|
734
|
+
db: aiosqlite.Connection = Depends(get_write_db),
|
|
735
|
+
) -> dict:
|
|
736
|
+
"""Set graph_edges.valid_until = now (+ optional superseded_by) on a triple.
|
|
737
|
+
|
|
738
|
+
SUPERSEDE / CONTRADICTION apply. Soft, never deletes. Inert (422) when the
|
|
739
|
+
flag is off. 404 if the triple is absent.
|
|
740
|
+
"""
|
|
741
|
+
ctx = CallerContext.from_user_info(user, is_human_session=False)
|
|
742
|
+
try:
|
|
743
|
+
return await uc.mark_edge_superseded(
|
|
744
|
+
ctx, db,
|
|
745
|
+
source_id=body.source_id,
|
|
746
|
+
target_id=body.target_id,
|
|
747
|
+
relation=body.relation,
|
|
748
|
+
superseded_by=body.superseded_by,
|
|
749
|
+
)
|
|
750
|
+
except ServiceError as e:
|
|
751
|
+
raise to_http_legacy(e)
|
|
752
|
+
|
|
753
|
+
|
|
704
754
|
# --- Resolve file path → node_id ---
|
|
705
755
|
|
|
706
756
|
@router.get("/resolve", response_model=ResolveOut, summary="Resolve file path to KG node")
|
|
@@ -237,6 +237,40 @@ async def _warehouse_consolidation_due(
|
|
|
237
237
|
return elapsed >= interval_seconds
|
|
238
238
|
|
|
239
239
|
|
|
240
|
+
async def _temporal_recency_due(
|
|
241
|
+
*, workspace_id: str, now: datetime, interval_seconds: int
|
|
242
|
+
) -> bool:
|
|
243
|
+
"""Daily cadence guard for the KG temporal recency pass (Fase D).
|
|
244
|
+
|
|
245
|
+
Derives "last run" from the newest persisted recency proposal — these are
|
|
246
|
+
`operation_type='reinforce'` ops whose proposed_write target_type is 'none'
|
|
247
|
+
(M1 reinforce uses 'kg_edge_metric', so this filter isolates the recency
|
|
248
|
+
pass). Idempotent regardless (operation_id collision dedups within a cycle),
|
|
249
|
+
so a missing/unparseable timestamp falls back to "due".
|
|
250
|
+
"""
|
|
251
|
+
if interval_seconds <= 0:
|
|
252
|
+
return True
|
|
253
|
+
async with acquire_db() as db:
|
|
254
|
+
row = await (
|
|
255
|
+
await db.execute(
|
|
256
|
+
"SELECT MAX(detected_at) FROM brain_memory_operations"
|
|
257
|
+
" WHERE operation_type = 'reinforce'"
|
|
258
|
+
" AND proposed_write_target_type = 'none'",
|
|
259
|
+
)
|
|
260
|
+
).fetchone()
|
|
261
|
+
last_raw = row[0] if row else None
|
|
262
|
+
if not last_raw:
|
|
263
|
+
return True
|
|
264
|
+
try:
|
|
265
|
+
last_dt = datetime.fromisoformat(str(last_raw).replace("Z", "+00:00"))
|
|
266
|
+
except ValueError:
|
|
267
|
+
return True
|
|
268
|
+
if last_dt.tzinfo is None:
|
|
269
|
+
last_dt = last_dt.replace(tzinfo=timezone.utc)
|
|
270
|
+
elapsed = (now.astimezone(timezone.utc) - last_dt.astimezone(timezone.utc)).total_seconds()
|
|
271
|
+
return elapsed >= interval_seconds
|
|
272
|
+
|
|
273
|
+
|
|
240
274
|
def _cycle_window_from_key(
|
|
241
275
|
cycle_key: str, *, cutoff_hour_utc: int
|
|
242
276
|
) -> tuple[datetime, datetime]:
|
|
@@ -563,6 +597,44 @@ async def _execute_cycle(
|
|
|
563
597
|
SourceFailure(source_system="warehouse_consolidation", error=str(exc))
|
|
564
598
|
)
|
|
565
599
|
|
|
600
|
+
# Phase 4c — KG temporal recency (Fase D producer). Ships DORMANT: gated
|
|
601
|
+
# on temporal_memory_enabled (the MARVIS_TEMPORAL_MEMORY flag IS the gate;
|
|
602
|
+
# default off → skipped). When on, a daily cadence guard bounds re-emission.
|
|
603
|
+
# PROPOSALS only — never auto-applied. Isolated try/except so it can NEVER
|
|
604
|
+
# crash the cycle.
|
|
605
|
+
if app_settings.temporal_memory_enabled:
|
|
606
|
+
try:
|
|
607
|
+
from core.api.services.brain.temporal_recency import (
|
|
608
|
+
run_temporal_recency,
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
if await _temporal_recency_due(
|
|
612
|
+
workspace_id=workspace_id,
|
|
613
|
+
now=now,
|
|
614
|
+
interval_seconds=app_settings.brain_temporal_recency_interval_seconds,
|
|
615
|
+
):
|
|
616
|
+
tr_summary = await run_temporal_recency(
|
|
617
|
+
run_id=run_id,
|
|
618
|
+
cycle_key=cycle_key,
|
|
619
|
+
workspace_id=workspace_id,
|
|
620
|
+
now=now,
|
|
621
|
+
)
|
|
622
|
+
logger.info(
|
|
623
|
+
"brain.jobs: temporal recency run_id=%s summary=%s",
|
|
624
|
+
run_id,
|
|
625
|
+
tr_summary,
|
|
626
|
+
)
|
|
627
|
+
else:
|
|
628
|
+
logger.info(
|
|
629
|
+
"brain.jobs: temporal recency skipped (cadence guard) run_id=%s",
|
|
630
|
+
run_id,
|
|
631
|
+
)
|
|
632
|
+
except Exception as exc: # noqa: BLE001 — phase-level isolation
|
|
633
|
+
logger.exception("brain.jobs: temporal recency failed")
|
|
634
|
+
failures.append(
|
|
635
|
+
SourceFailure(source_system="temporal_recency", error=str(exc))
|
|
636
|
+
)
|
|
637
|
+
|
|
566
638
|
# Phase 5 — Learn Findings (sub-04). Final L5 phase of the cycle.
|
|
567
639
|
# Consumes digest events + journal entries + drift signals + memory
|
|
568
640
|
# operations of the current run_id (NEVER re-reads substrate).
|
|
@@ -1519,10 +1519,21 @@ def _next_action_for(op: MemoryOperation) -> ApplyNextAction:
|
|
|
1519
1519
|
target_type = pw.target_type # type: ignore[union-attr]
|
|
1520
1520
|
|
|
1521
1521
|
if op.operation_type == "reinforce":
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1522
|
+
if target_type == "none":
|
|
1523
|
+
# Fase D temporal recency: bump the node's last_verified_at via the
|
|
1524
|
+
# write-path tool (proposed_write is `none`; the node id rides in
|
|
1525
|
+
# source_ref). Guidance-only: the operator/agent runs the tool.
|
|
1526
|
+
tool = "mcp__marvis__mark_kg_verified"
|
|
1527
|
+
args = {"node_id": op.source_ref}
|
|
1528
|
+
rationale = (
|
|
1529
|
+
"Temporal recency: this live node is aging and never verified. "
|
|
1530
|
+
"Approve → mark_kg_verified stamps last_verified_at so it reads fresh."
|
|
1531
|
+
)
|
|
1532
|
+
else:
|
|
1533
|
+
tool = None
|
|
1534
|
+
rationale = "reinforce produces edge metric evidence only; v2 may write to graph_edge_metrics."
|
|
1535
|
+
if hasattr(pw, "edge_id"):
|
|
1536
|
+
args = {"edge_id": pw.edge_id, "metric_kind": pw.metric_kind, "delta": pw.delta}
|
|
1526
1537
|
elif op.operation_type == "cascade_rollup":
|
|
1527
1538
|
tool = None
|
|
1528
1539
|
rationale = "Cascade rollup is apply-guidance-only. Operator appends body to parent context.md."
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Brain v1 — Temporal recency pass (Fase D producer, KG freshness/trust).
|
|
2
|
+
#
|
|
3
|
+
# WHY this exists:
|
|
4
|
+
# The graph now carries graph_nodes.last_verified_at (mig 149) and the
|
|
5
|
+
# read-time needs_review (Fase A + D read-wiring) treats a re-verified node as
|
|
6
|
+
# fresh. This pass is the "suggester": it scans the graph for live nodes that
|
|
7
|
+
# are AGING (last seen a while ago) and NEVER explicitly verified, and PROPOSES
|
|
8
|
+
# a `reinforce` (bump last_verified_at) in the Triage queue. Approving one then
|
|
9
|
+
# calls mark_kg_verified (D write-path) → the node reads as fresh again.
|
|
10
|
+
#
|
|
11
|
+
# Mechanical, NO LLM (recency is mechanical per the plan). The LLM judgment for
|
|
12
|
+
# supersede/contradiction on derived edges is deferred to a follow-up.
|
|
13
|
+
#
|
|
14
|
+
# Layering invariants (mirror warehouse_consolidate):
|
|
15
|
+
# * NO LLM imports. NO substrate mutation (read-only scan; proposals only).
|
|
16
|
+
# * READ pool (acquire_db) for the scan — never hold the writer across it.
|
|
17
|
+
# * Reuses the memory_ops persist path (finalize_operation + _persist_operations)
|
|
18
|
+
# → proposals land as approval_state='pending', NEVER auto-applied.
|
|
19
|
+
# * Gated by MARVIS_TEMPORAL_MEMORY in jobs.py → dormant when off.
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import logging
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
from datetime import datetime, timedelta, timezone
|
|
25
|
+
|
|
26
|
+
import aiosqlite
|
|
27
|
+
|
|
28
|
+
from core.api.db import acquire_db
|
|
29
|
+
from core.api.services.brain.compound_bridge import proposed_write_none
|
|
30
|
+
from core.api.services.brain.memory_ops import (
|
|
31
|
+
OperationDraft,
|
|
32
|
+
_persist_operations,
|
|
33
|
+
_project_scope,
|
|
34
|
+
finalize_operation,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
# Node kinds worth re-verifying (skip noisy/derived kinds like commit/inbox).
|
|
40
|
+
RECHECK_TYPES: tuple[str, ...] = (
|
|
41
|
+
"function", "file", "module", "task", "project", "handoff", "learning",
|
|
42
|
+
"doc", "pr", "plan", "solution",
|
|
43
|
+
)
|
|
44
|
+
# A node is a candidate once it has not been observed for at least this long
|
|
45
|
+
# (aging — at risk of false-positive staleness) yet is still live + unverified.
|
|
46
|
+
MIN_AGE_DAYS: int = 14
|
|
47
|
+
# Hard cap per cycle — proposals are a Triage signal, never a flood.
|
|
48
|
+
MAX_CANDIDATES: int = 25
|
|
49
|
+
# Re-nag suppression window: a node dismissed/rejected within this many days is
|
|
50
|
+
# not re-proposed (respects the operator's "no"). A still-pending proposal is
|
|
51
|
+
# always suppressed regardless of age (no duplicate while one is open).
|
|
52
|
+
SUPPRESS_DISMISSED_DAYS: int = 30
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(slots=True, frozen=True)
|
|
56
|
+
class _NodeRow:
|
|
57
|
+
node_id: str
|
|
58
|
+
node_type: str
|
|
59
|
+
project_id: str | None
|
|
60
|
+
last_seen_at: str | None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _parse_iso(value: str | None) -> datetime | None:
|
|
64
|
+
if value is None:
|
|
65
|
+
return None
|
|
66
|
+
try:
|
|
67
|
+
dt = datetime.fromisoformat(str(value).replace(" ", "T").replace("Z", "+00:00"))
|
|
68
|
+
except ValueError:
|
|
69
|
+
return None
|
|
70
|
+
if dt.tzinfo is None:
|
|
71
|
+
dt = dt.replace(tzinfo=timezone.utc)
|
|
72
|
+
return dt.astimezone(timezone.utc)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _scan_query(*, now: datetime) -> tuple[str, list]:
|
|
76
|
+
"""(sql, params) for the candidate scan — pure, so it's unit-testable.
|
|
77
|
+
|
|
78
|
+
Robust to mixed 'YYYY-MM-DD HH:MM:SS' / ISO-'T' last_seen_at (datetime() both
|
|
79
|
+
sides). The NOT EXISTS guard is the re-nag brake: skip a node that already
|
|
80
|
+
has a recency proposal (reinforce + target_type='none') still PENDING (no
|
|
81
|
+
duplicate while one is open), or DISMISSED/REJECTED within
|
|
82
|
+
SUPPRESS_DISMISSED_DAYS (respect the operator's "no"). Without it the
|
|
83
|
+
cycle-key-scoped operation_id would mint a fresh proposal every night.
|
|
84
|
+
"""
|
|
85
|
+
aging_cutoff = (now.astimezone(timezone.utc) - timedelta(days=MIN_AGE_DAYS)).strftime(
|
|
86
|
+
"%Y-%m-%d %H:%M:%S"
|
|
87
|
+
)
|
|
88
|
+
suppress_cutoff = (
|
|
89
|
+
now.astimezone(timezone.utc) - timedelta(days=SUPPRESS_DISMISSED_DAYS)
|
|
90
|
+
).strftime("%Y-%m-%d %H:%M:%S")
|
|
91
|
+
placeholders = ",".join("?" * len(RECHECK_TYPES))
|
|
92
|
+
sql = (
|
|
93
|
+
"SELECT n.id, n.type, n.project_id, n.last_seen_at FROM graph_nodes n "
|
|
94
|
+
"WHERE n.deprecated_at IS NULL AND n.last_verified_at IS NULL "
|
|
95
|
+
"AND n.last_seen_at IS NOT NULL "
|
|
96
|
+
f"AND n.type IN ({placeholders}) "
|
|
97
|
+
"AND datetime(n.last_seen_at) <= datetime(?) "
|
|
98
|
+
"AND NOT EXISTS ("
|
|
99
|
+
" SELECT 1 FROM brain_memory_operations o "
|
|
100
|
+
" WHERE o.source_ref = n.id "
|
|
101
|
+
" AND o.operation_type = 'reinforce' "
|
|
102
|
+
" AND o.proposed_write_target_type = 'none' "
|
|
103
|
+
" AND (o.approval_state = 'pending' "
|
|
104
|
+
" OR (o.approval_state IN ('dismissed','rejected') "
|
|
105
|
+
" AND datetime(o.detected_at) >= datetime(?)))"
|
|
106
|
+
") "
|
|
107
|
+
"ORDER BY datetime(n.last_seen_at) ASC LIMIT ?"
|
|
108
|
+
)
|
|
109
|
+
params = [*RECHECK_TYPES, aging_cutoff, suppress_cutoff, MAX_CANDIDATES]
|
|
110
|
+
return sql, params
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
async def _scan_aging_unverified_nodes(*, now: datetime) -> list[_NodeRow]:
|
|
114
|
+
"""Live, significant, never-verified, aging nodes — minus those already
|
|
115
|
+
proposed/recently-dismissed (see _scan_query). Read pool; capped, oldest-first.
|
|
116
|
+
"""
|
|
117
|
+
sql, params = _scan_query(now=now)
|
|
118
|
+
async with acquire_db() as db:
|
|
119
|
+
db.row_factory = aiosqlite.Row
|
|
120
|
+
rows = await (await db.execute(sql, params)).fetchall()
|
|
121
|
+
return [
|
|
122
|
+
_NodeRow(
|
|
123
|
+
node_id=str(r["id"]),
|
|
124
|
+
node_type=str(r["type"]),
|
|
125
|
+
project_id=r["project_id"],
|
|
126
|
+
last_seen_at=r["last_seen_at"],
|
|
127
|
+
)
|
|
128
|
+
for r in rows
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def build_recency_drafts(nodes: list[_NodeRow], *, now: datetime) -> list[OperationDraft]:
|
|
133
|
+
"""One `reinforce` proposal per aging-unverified node. Deterministic.
|
|
134
|
+
|
|
135
|
+
proposed_write = none (no CHECK-migration needed); the node id rides in
|
|
136
|
+
source_ref, which the apply-guidance hands to mark_kg_verified. Evidence is
|
|
137
|
+
a single stable ref (`kg_node:<id>`) → stable evidence_hash → idempotent:
|
|
138
|
+
re-detecting the same node bumps recurrence rather than duplicating.
|
|
139
|
+
"""
|
|
140
|
+
drafts: list[OperationDraft] = []
|
|
141
|
+
for n in sorted(nodes, key=lambda x: x.node_id):
|
|
142
|
+
scope_type, scope_key = _project_scope(n.project_id)
|
|
143
|
+
seen = _parse_iso(n.last_seen_at)
|
|
144
|
+
age_days = int((now - seen).total_seconds() // 86400) if seen else None
|
|
145
|
+
age_txt = f"{age_days}d ago" if age_days is not None else "long ago"
|
|
146
|
+
# Older → higher priority; clamped to [0, 1].
|
|
147
|
+
score = min(1.0, 0.4 + (age_days or 0) / 180.0)
|
|
148
|
+
drafts.append(
|
|
149
|
+
OperationDraft(
|
|
150
|
+
operation_type="reinforce",
|
|
151
|
+
scope_type=scope_type,
|
|
152
|
+
scope_key=scope_key,
|
|
153
|
+
program_key=None,
|
|
154
|
+
source_ref=n.node_id,
|
|
155
|
+
target_ref="",
|
|
156
|
+
evidence=[f"kg_node:{n.node_id}"],
|
|
157
|
+
summary=(
|
|
158
|
+
f"Re-verify {n.node_type} {n.node_id}: live but last seen "
|
|
159
|
+
f"{age_txt}, never verified. Approve → mark_kg_verified bumps "
|
|
160
|
+
"last_verified_at so it reads fresh again."
|
|
161
|
+
),
|
|
162
|
+
proposed_write=proposed_write_none(),
|
|
163
|
+
involved_projects=[n.project_id] if n.project_id else [],
|
|
164
|
+
score=score,
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
return drafts
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
async def run_temporal_recency(
|
|
171
|
+
*,
|
|
172
|
+
run_id: str,
|
|
173
|
+
cycle_key: str,
|
|
174
|
+
workspace_id: str = "ws_default",
|
|
175
|
+
now: datetime,
|
|
176
|
+
) -> dict[str, int]:
|
|
177
|
+
"""Aging-node re-verification pass. PROPOSALS ONLY (approval_state=pending).
|
|
178
|
+
|
|
179
|
+
Reuses the memory_ops persist path so re-runs are idempotent (stable
|
|
180
|
+
operation_id collides on the natural key). Returns a small summary dict.
|
|
181
|
+
"""
|
|
182
|
+
now = now.astimezone(timezone.utc)
|
|
183
|
+
nodes = await _scan_aging_unverified_nodes(now=now)
|
|
184
|
+
drafts = build_recency_drafts(nodes, now=now)
|
|
185
|
+
operations = [
|
|
186
|
+
finalize_operation(draft=d, run_id=run_id, cycle_key=cycle_key, now=now)
|
|
187
|
+
for d in drafts
|
|
188
|
+
]
|
|
189
|
+
persisted, _recurrence_keys = await _persist_operations(
|
|
190
|
+
run_id=run_id, operations=operations
|
|
191
|
+
)
|
|
192
|
+
return {"candidates": len(nodes), "operations_persisted": persisted}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
__all__ = ["build_recency_drafts", "run_temporal_recency"]
|