marvisx-cli 0.3.7b3__tar.gz → 0.3.8b1__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.7b3 → marvisx_cli-0.3.8b1}/PKG-INFO +1 -1
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/config.py +49 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/learnings.py +45 -2
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/search.py +9 -1
- marvisx_cli-0.3.8b1/core/api/services/chunking.py +277 -0
- marvisx_cli-0.3.8b1/core/api/services/dream_cycle.py +213 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/embedding_internal.py +13 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/embedding_service.py +152 -0
- marvisx_cli-0.3.8b1/core/api/services/grounding/__init__.py +65 -0
- marvisx_cli-0.3.8b1/core/api/services/grounding/citations.py +348 -0
- marvisx_cli-0.3.8b1/core/api/services/grounding/verifier.py +118 -0
- marvisx_cli-0.3.8b1/core/api/services/kg/communities.py +227 -0
- marvisx_cli-0.3.8b1/core/api/services/kg/community_summary.py +105 -0
- marvisx_cli-0.3.8b1/core/api/services/kg/graph_lane.py +235 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg/hybrid_search.py +171 -7
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg/rrf.py +40 -0
- marvisx_cli-0.3.8b1/core/api/services/temporal_tiebreak.py +200 -0
- marvisx_cli-0.3.8b1/core/api/services/temporal_write.py +431 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/learnings.py +298 -7
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/projects.py +14 -2
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/search.py +12 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/marvisx_cli.egg-info/PKG-INFO +1 -1
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/marvisx_cli.egg-info/SOURCES.txt +14 -0
- marvisx_cli-0.3.8b1/migrations/147_chunks.sql +32 -0
- marvisx_cli-0.3.8b1/migrations/147_chunks_down.sql +5 -0
- marvisx_cli-0.3.8b1/migrations/148_bitemporal_learnings.sql +47 -0
- marvisx_cli-0.3.8b1/migrations/148_bitemporal_learnings_down.sql +17 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/pyproject.toml +1 -1
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/LICENSE +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/MANIFEST.in +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/README.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/agents/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/agents/session_health.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/agents/session_manager.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/bin/marvisx-state-hook.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/db.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/dependencies/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/dependencies/tenant.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/main.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/_adapter.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/server.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/brain.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/graph.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/handoffs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/ingest.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/learnings.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/projects.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/pull_requests.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/safety.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/search.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/tasks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/workflow_playbooks/brainstorm.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/workflow_playbooks/compound.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/workflow_playbooks/plan.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/mcp/tools/workflows.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/middleware/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/middleware/tool_call_audit.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/auth.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/brain.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/common.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/costs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/graph.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/graph_cosmo.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/graph_pr_impact.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/graph_ux.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/inbox.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/ingest_keys.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/kg.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/llm_config.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/monitoring.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/projects.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/search.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/sessions.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/tasks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/teams.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/models/users.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/observability/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/observability/tracing.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/paths.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/rate_limit.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/rbac.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/_adapter.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/admin_pr_impact.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/admin_settings.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/agent.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/agent_tokens.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/app_settings.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/audit.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/auth.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/bench.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/brain.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/brain_directions.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/ci_checks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/comments.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/costs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/docs_coverage.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/docs_governance.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/documents.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/files.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/finder.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/graph.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/handoffs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/inbox.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/ingest_api_keys.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/ingest_triage.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/judge.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/kg.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/llm_config.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/monitoring.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/notifications.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/pr_impact.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/projects.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/pull_requests.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/push.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/raci.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/sessions.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/settings.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/share_repo.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/status_updates.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/tags.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/tasks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/teams.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/terminal.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/users.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/routers/webhooks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/runtime_settings.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/security.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/_fts.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/audit.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/auto_approval.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/baseline.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/capabilities.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/cascade_rollup.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/compound_bridge.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/cycle.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/cycle_snapshot.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/digest_collector.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/direction.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/drift.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/drift_router.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/edge_metrics.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/events_reader.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/findings.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/findings_reader.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/jobs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/journal.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/knowledge_forms.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/_runner.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/base.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/cache.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/constants.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/direction_alignment.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/factory.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/finding_reasoning.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/finding_summary.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/grounding.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/journal_polish.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/local_gateway.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/parsers.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/llm/router_glue.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/memory_ops.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/models.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/owner_hint.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/recap.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/_signals.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/dr1_activity_without_status.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/dr2_decision_without_adr.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/dr3_stale_open_loop.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/dr4_docs_governance_drift.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/dr5_playbook_changed.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/dr6_external_update_unpropagated.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/dr7_claimed_decision_gap.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/rules/dr8_direction_misalignment.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/runs_reader.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/scope.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/sources/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/sources/base.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/sources/git_kg.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/sources/handoffs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/sources/ingestor.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/sources/learnings.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/sources/pir_tasks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/warehouse_consolidate.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/watermarks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/brain/ws_emitter.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/cc_tasks_reader.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ci_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/claude_metrics.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/codex_metrics.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/conversation_reader.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/cost_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/crypto.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/docs_governance/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/docs_governance/confidence.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/docs_governance/config.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/docs_governance/enrichment.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/docs_governance/frontmatter_validator.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/docs_governance/hard_gates.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/docs_governance/triage_orchestrator.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/embedding_backends/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/event_dispatcher.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/events.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/git_ops.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/graph_cosmo_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/graph_ranker.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/graph_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_digest.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_digest_deep_research.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_digest_jobs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_gmail_sync.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_llm_classifier.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_source_identity.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_sources.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_taxonomy.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_tldr.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/inbox_triage.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/api_key_auth.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/auto_approve.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/classifier.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/confidence.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/dispatch.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/embedding_router.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/events.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/ignore_patterns.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/image_probe.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/ingress.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/insert_saga.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/anthropic_haiku.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/base.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/byok_provider.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/classification_context.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/config_store.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/factory.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/kg_enricher.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/local_gateway.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/local_vllm.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/llm/openai_nano.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/lock_advisory.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parser_router.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/docling_parser.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/docparse_gateway.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/docx_parser.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/folder_unpacker.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/gateway_aux.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/image_parser.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/internal_markdown.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/ocr_gateway.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/ocr_pdf_parser.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/pdf_types.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/transcript_parser.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/vision_gateway.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/xlsx_parser.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/parsers/zip_unpacker.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/preflight.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/routing_policy.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/serializers/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/serializers/xlsx_to_markdown.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/skip_log.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/ingest/watcher.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg/audit.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg/lens.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg/pr_impact.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg/queries.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg/ranking.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/kg_watcher_control.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/local_llm/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/local_llm/async_client.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/local_llm/client.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/local_llm/url_validator.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/metrics_collector.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/metrics_providers.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/model_registry.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/model_router.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/n8n_client.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/newsletter_llm_gateway.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/notification_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/openai_responses.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/opencode_metrics.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/opencode_sessions.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pii_redactor.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pr_impact_pipeline/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pr_impact_pipeline/differ.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pr_impact_pipeline/dispatcher.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pr_impact_pipeline/gc.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pr_impact_pipeline/languages.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pr_impact_pipeline/parser.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pr_impact_pipeline/writer.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/pr_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/project_paths.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/project_status_updates.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/providers.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/push_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/reminder_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/runas.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/salience_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/security_collector.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/session_catalog.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/session_metrics_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/session_ops.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/session_state.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/share_links.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/task_transitions.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/terminal_metrics.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/terminal_metrics_dump.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/tmux.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/webhook_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/services/workspace_sync.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/templates/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/templates/markdown_share.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/terminal.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_agent_facing_auth_dependencies.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_audit_permissions.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_backfill_session_conversations.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_backfill_working_seconds_msg.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_claude_metrics.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_codex_metrics.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_config_env_aliases.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_finder_paths.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_git_ops_merge.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_learnings_check_search.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_metrics_providers.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_migration_087.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_migration_088.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_migration_089.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_openai_responses.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_opencode_metrics.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_opencode_sessions.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_pr_workflow_e2e.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_projects_handoffs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_providers.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_require_scope_empty_deny.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_safety_bridge.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_session_catalog.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_session_conversations.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_session_metrics_service.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_session_resume_paths.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_session_theme_mode_migration.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_sessions_rbac.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_share_edit.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_share_repo.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_terminal_session_manager.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_terminal_upload.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_tmux.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_workspace_sync.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/tests/test_ws_ticket_in_memory.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/_context.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/_errors.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/_roles.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/audit.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/brain.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/costs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/graph.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/handoffs.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/ingest_triage.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/pull_requests.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/use_cases/tasks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/api/visibility.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/README.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/_brain_opportunistic.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/_brain_schedule.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/_index_source.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/_runtime_ctx.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/_transmute.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/_update_check.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/guides/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/guides/marvis-way.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_account.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_brain.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_doctor.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_feedback.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_governance.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_guide.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_hooks.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_init.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_mcp.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_runtime.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/cli/marvis_telemetry.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/platform/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/_drift_check.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/_frontmatter.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/_graph_writer.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/ast_parser.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/_config.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/block-dangerous-bash.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/block-db-direct-write.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/block-push-no-task.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/block-staging-to-prod.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/block-subtree-push.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/config.json +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/enforce-no-merge-main.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/enforce-worktree.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/quality-gate.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/safety_bridge.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/install_hooks/secret-scan.sh +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/migrate_spike_node_ids.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/populate_artifacts.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/populate_cross_project.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/populate_inbox_nodes.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/populate_pr_impact.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/populate_project_nodes.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/populate_touch_counter.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/reparse_failed.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/scripts/safety_bridge.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/telemetry/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/telemetry/client.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/telemetry/entitlements.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/telemetry/rollup.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/telemetry/schema.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/telemetry/sender.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/wizard/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/wizard/byok_vault.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/wizard/defaults.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/wizard/state.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/wizard/steps.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/core/wizard/validation.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/marvisx_cli.egg-info/dependency_links.txt +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/marvisx_cli.egg-info/entry_points.txt +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/marvisx_cli.egg-info/requires.txt +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/marvisx_cli.egg-info/top_level.txt +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/001_initial.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/002_tasks.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/003_session_management.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/004_projects_comments.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/005_session_intelligence.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/006_settings.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/007_task_scoring.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/008_cost_tracking.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/009_session_card_metrics.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/010_monitoring.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/012_agent_api.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/013_session_complete.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/015_pull_requests.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/015_pull_requests_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/016_users_raci.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/017_task_cost_entries.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/018_agents.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/018_agents_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/019_review_feedback.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/020_pr_commit_sha.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/021_webhook_events.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/022_devx_agent_managed.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/022_devx_agent_managed_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/023_devx_p1_gate.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/023_devx_p1_gate_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/024_chat_messages.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/024_pr_conversation_id.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/024_task_indexes.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/024_task_indexes_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/025_audit_log.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/026_agent_tokens.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/027_teams_auth_phase_b.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/028_learnings.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/029_team_roles.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/030_finder_pins.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/031_pr_deploy_status.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/032_task_reminders.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/033_events_retry_count.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/033_session_owner.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/034_notifications.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/035_shared_links.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/036_session_index_upgrade.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/037_pr_approval.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/038_pr_submitted_by.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/039_push_subscriptions.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/040_semantic_search.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/041_workspaces.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/042_oidc_providers.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/043_ci_checks.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/044_agent_metrics.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/045_documents_doc_type.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/046_salience.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/047_seed_missing_agents.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/048_fix_agent_paths_roles.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/049_agent_role_and_learnings_schema.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/050_session_provider.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/051_session_launch_profile.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/052_session_theme_mode.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/052_task_kind.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/053_inbox_items.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/054_inbox_triage_contract.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/055_inbox_topic_treatment.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/056_inbox_treatment_read_save.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/057_session_theme_mode_backfill.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/058_inbox_item_status_lifecycle.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/059_inbox_tldr_and_source_scores.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/060_newsletter.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/061_inbox_redesign.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/062_fix_inbox_sources_backfill.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/063_task_completion_mode.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/064_judge_mode_setting.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/065_knowledge_graph_spike.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/066_digest_ranking_inputs.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/066_kg_artifact_nodes.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/067_inbox_digest_selections.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/067_kg_temporal.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/068_inbox_digest_app_settings.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/068_kg_touch_counter.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/069_kg_doc_types.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/070_digest_ranking_inputs_recovery.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/071_inbox_digest_selections_recovery.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/072_inbox_digest_app_settings_recovery.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/073_kg_cross_project.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/073_kg_cross_project_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/074_kg_infra_types.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/074_kg_infra_types_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/075_kg_file_state_recovery.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/075_kg_file_state_recovery_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/076_kg_watcher_state.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/076_kg_watcher_state_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/077_kg_doc_types_extend.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/077_kg_doc_types_extend_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/078_kg_fts5.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/078_kg_fts5_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/079_kg_missing_indexes.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/079_kg_missing_indexes_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/080_kg_fts5_extended.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/080_kg_fts5_extended_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/081_kg_lens_indexes.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/081_kg_lens_indexes_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/082_kg_pins.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/082_kg_pins_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/083_kg_graph_nodes_degree.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/083_kg_graph_nodes_degree_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/084_drop_legacy_scheduler_tables.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/084_drop_legacy_scheduler_tables_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/085_kg_edge_resolves_to.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/085_kg_edge_resolves_to_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/086_project_status_updates_feed.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/086_project_status_updates_feed_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/087_session_metrics_dual.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/087_session_metrics_dual_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/088_rename_context_pct_legacy.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/088_rename_context_pct_legacy_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/089_session_metrics_equivalent_cost.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/089_session_metrics_equivalent_cost_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/090_kg_inbox_node_type.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/090_kg_inbox_node_type_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/091_kg_inbox_node_type_check.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/091_kg_inbox_node_type_check_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/092_sessions_activity_state_ts.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/092_sessions_activity_state_ts_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/093_sessions_activity_state_column.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/093_sessions_activity_state_column_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/094_ingest_pending.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/094_ingest_pending_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/095_kg_intent_first.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/095_kg_intent_first_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/096_kg_xlsx_artifact_prefix.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/096_kg_xlsx_artifact_prefix_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/097_ingest_change_history.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/097_ingest_change_history_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/098_kg_node_type_business.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/098_kg_node_type_business_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/099_kg_edges_restore_weight.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/099_kg_edges_restore_weight_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/100_kg_enriched_at.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/100_kg_enriched_at_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/101_local_llm_shadow_comparisons.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/101_local_llm_shadow_comparisons_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/102_promote_llm_costs.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/102_promote_llm_costs_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/103_ingest_skipped_log.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/103_ingest_skipped_log_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/120_docs_governance.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/120_docs_governance_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/121_notification_event_fk_cleanup.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/121_notification_event_fk_cleanup_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/122_docs_drift_history.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/122_docs_drift_history_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/123_ingest_parser_waiting_status.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/123_ingest_parser_waiting_status_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/124_heypocket_recordings.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/124_heypocket_recordings_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/125_kg_node_type_record.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/125_kg_node_type_record_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/126_ingest_terminal_upload_source_kind.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/126_ingest_terminal_upload_source_kind_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/127_brain_v1_substrate.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/127_brain_v1_substrate_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/128_brain_drift_signals.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/128_brain_drift_signals_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/129_brain_memory_operations.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/129_brain_memory_operations_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/130_brain_findings.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/130_brain_findings_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/132_kg_pr_modifies.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/132_kg_pr_modifies_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/133_brain_v1_2_direction_schema.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/133_brain_v1_2_direction_schema_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/134_brain_journal_narrative_polished.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/134_brain_journal_narrative_polished_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/135_kg_edges_provider.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/136_documents_fts.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/137_promote_llm_costs.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/137_promote_llm_costs_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/138_ingest_api_keys.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/138_ingest_api_keys_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/139_ingest_pending_ingress.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/139_ingest_pending_ingress_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/140_ingest_idempotency_quota.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/140_ingest_idempotency_quota_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/141_ingest_pending_metadata.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/141_ingest_pending_metadata_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/142_llm_function_config.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/142_llm_function_config_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/143_kg_code_embeddings.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/143_kg_code_embeddings_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/144_notifications_pending_sync_index.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/145_audit_log_immutable.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/145_audit_log_immutable_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/146_drop_kg_backup_tables.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/146_drop_kg_backup_tables_down.sql +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/migrations/__init__.py +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/projects/_template/context.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/projects/_template/docs/brainstorms/YYYY-MM-DD-example-brainstorm.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/projects/_template/docs/plans/YYYY-MM-DD-example-plan.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/projects/_template/docs/solutions/YYYY-MM-DD-example-solution.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/projects/_template/input/README.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/projects/_template/memory/handoff.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/projects/_template/output/README.md +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/projects/_template/project.yaml +0 -0
- {marvisx_cli-0.3.7b3 → marvisx_cli-0.3.8b1}/setup.cfg +0 -0
|
@@ -439,6 +439,55 @@ class Settings(BaseSettings):
|
|
|
439
439
|
False # pydantic-settings maps KG_HTTP_DEEP_DEFAULT env var
|
|
440
440
|
)
|
|
441
441
|
|
|
442
|
+
# Track 2 #3a — STRUCTURAL graph-lane in the RRF fusion (DEFAULT OFF).
|
|
443
|
+
# When False the fused ranking is byte-identical to today (5 lanes). When
|
|
444
|
+
# True a 6th lane (seeded 1-hop edge-weighted KG expansion) joins the blend.
|
|
445
|
+
# graph_lane_hops / graph_lane_fanout / graph_lane_weight / graph_lane_seeds
|
|
446
|
+
# tune the lane without code changes. Edge-type subset = all 15 by default.
|
|
447
|
+
graph_lane_enabled: bool = Field(
|
|
448
|
+
default=False, alias="MARVIS_GRAPH_LANE"
|
|
449
|
+
)
|
|
450
|
+
graph_lane_hops: int = Field(default=1, alias="MARVIS_GRAPH_LANE_HOPS")
|
|
451
|
+
graph_lane_fanout: int = Field(default=25, alias="MARVIS_GRAPH_LANE_FANOUT")
|
|
452
|
+
graph_lane_seeds: int = Field(default=10, alias="MARVIS_GRAPH_LANE_SEEDS")
|
|
453
|
+
graph_lane_weight: float = Field(
|
|
454
|
+
default=0.12, alias="MARVIS_GRAPH_LANE_WEIGHT"
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
# Track 2 #1 — bi-temporal memory READ path (DEFAULT OFF). When False every
|
|
458
|
+
# learnings read is byte-identical to today (no invalid_at filter, no as_of):
|
|
459
|
+
# the temporal helper emits NO extra SQL. When True the default learnings
|
|
460
|
+
# reads (check/list/get + the learnings retrieval lane in search) add
|
|
461
|
+
# ``AND invalid_at IS NULL`` — a MECHANICAL, BINARY exclusion (superseded rows
|
|
462
|
+
# never reach the LLM; never a down-weight, which would still let the model
|
|
463
|
+
# cite the stale value). An explicit ``as_of=<ISO>`` relaxes the filter to the
|
|
464
|
+
# point-in-time window ``valid_from <= as_of AND (invalid_at IS NULL OR
|
|
465
|
+
# invalid_at > as_of)`` for audit. S3/S4/S5 (write path / LLM tiebreak / dream
|
|
466
|
+
# cycle) reuse this SAME flag. Requires migration 148 columns when enabled.
|
|
467
|
+
temporal_memory_enabled: bool = Field(
|
|
468
|
+
default=False, alias="MARVIS_TEMPORAL_MEMORY"
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
# Track 2 #3c — community summaries in the brief (GraphRAG global-search,
|
|
472
|
+
# DEFAULT OFF). When False the brief is byte-identical to today: the
|
|
473
|
+
# communities/community_summary modules are a flag-gated library + seam,
|
|
474
|
+
# never imported into session_brief. When True (off-host wiring), the KG is
|
|
475
|
+
# partitioned (deterministic label propagation, NO LLM) and per-community
|
|
476
|
+
# summaries enter the brief AFTER #2 so they inherit span-citation + NLI
|
|
477
|
+
# verification (a summary is itself a claim to ground, not free text).
|
|
478
|
+
community_summaries_enabled: bool = Field(
|
|
479
|
+
default=False, alias="MARVIS_COMMUNITY_SUMMARIES"
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
# Track 2 #2: span-citation + grounding-verification layer for the brief.
|
|
483
|
+
# DEFAULT OFF — the layer exists as a flag-gated library; when off the
|
|
484
|
+
# session_brief output is byte-for-byte unchanged (the seam is never entered).
|
|
485
|
+
# See core/api/services/grounding/. Wiring the NLI head (MiniCheck) is a
|
|
486
|
+
# separate, deliberate, off-host step (NoopVerifier is the default).
|
|
487
|
+
brief_citations_enabled: bool = Field(
|
|
488
|
+
default=False, alias="MARVIS_BRIEF_CITATIONS"
|
|
489
|
+
)
|
|
490
|
+
|
|
442
491
|
# WIP limit: max tasks in_progress per project (doc/none tasks count as 0.5)
|
|
443
492
|
wip_max_in_progress: int = 3
|
|
444
493
|
|
|
@@ -46,6 +46,8 @@ from core.api.use_cases.learnings import ( # noqa: F401 (re-export surface)
|
|
|
46
46
|
VALID_CATEGORIES,
|
|
47
47
|
VALID_SEVERITIES,
|
|
48
48
|
LearningCheckResponse,
|
|
49
|
+
LearningHistoryLink,
|
|
50
|
+
LearningHistoryResponse,
|
|
49
51
|
LearningResponse,
|
|
50
52
|
_extract_check_terms,
|
|
51
53
|
_learning_match_score,
|
|
@@ -158,13 +160,20 @@ async def check_learnings(
|
|
|
158
160
|
None, description="Filter by module (exact or LIKE match)"
|
|
159
161
|
),
|
|
160
162
|
deep: bool = Query(False, description="Attach KG context to each result (Phase 7.0)"),
|
|
163
|
+
as_of: str | None = Query(
|
|
164
|
+
None,
|
|
165
|
+
description=(
|
|
166
|
+
"Point-in-time audit (Track 2 #1). ISO timestamp; returns learnings live "
|
|
167
|
+
"at that instant. Only effective when MARVIS_TEMPORAL_MEMORY is enabled."
|
|
168
|
+
),
|
|
169
|
+
),
|
|
161
170
|
user: UserInfo = Depends(get_current_user_or_agent),
|
|
162
171
|
db: aiosqlite.Connection = Depends(get_db),
|
|
163
172
|
) -> LearningCheckResponse:
|
|
164
173
|
"""Search learnings relevant to a keyword/module. Used by MCP before risky actions."""
|
|
165
174
|
ctx = CallerContext.from_user_info(user, is_human_session=False)
|
|
166
175
|
try:
|
|
167
|
-
result = await uc.check_learnings(ctx, db, query=q, module=module)
|
|
176
|
+
result = await uc.check_learnings(ctx, db, query=q, module=module, as_of=as_of)
|
|
168
177
|
except ServiceError as e:
|
|
169
178
|
raise to_http(e)
|
|
170
179
|
|
|
@@ -194,6 +203,13 @@ async def list_learnings(
|
|
|
194
203
|
limit: int = Query(50, ge=1, le=200),
|
|
195
204
|
offset: int = Query(0, ge=0),
|
|
196
205
|
deep: bool = Query(False, description="Attach KG context (aggregate deferred to Phase 7.1)"),
|
|
206
|
+
as_of: str | None = Query(
|
|
207
|
+
None,
|
|
208
|
+
description=(
|
|
209
|
+
"Point-in-time audit (Track 2 #1). ISO timestamp; lists learnings live "
|
|
210
|
+
"at that instant. Only effective when MARVIS_TEMPORAL_MEMORY is enabled."
|
|
211
|
+
),
|
|
212
|
+
),
|
|
197
213
|
user: UserInfo = Depends(get_current_user_or_agent),
|
|
198
214
|
db: aiosqlite.Connection = Depends(get_db),
|
|
199
215
|
) -> list[LearningResponse]:
|
|
@@ -225,22 +241,49 @@ async def list_learnings(
|
|
|
225
241
|
limit=limit,
|
|
226
242
|
offset=offset,
|
|
227
243
|
visible_projects=visible_projects,
|
|
244
|
+
as_of=as_of,
|
|
228
245
|
)
|
|
229
246
|
except ServiceError as e:
|
|
230
247
|
raise to_http(e)
|
|
231
248
|
|
|
232
249
|
|
|
250
|
+
@router.get("/{learning_id}/history", response_model=LearningHistoryResponse)
|
|
251
|
+
async def get_learning_history(
|
|
252
|
+
learning_id: str,
|
|
253
|
+
user: UserInfo = Depends(get_current_user_or_agent),
|
|
254
|
+
db: aiosqlite.Connection = Depends(get_db),
|
|
255
|
+
) -> LearningHistoryResponse:
|
|
256
|
+
"""Walk a learning's supersede chain (Track 2 #1 audit trail, READ-ONLY).
|
|
257
|
+
|
|
258
|
+
Returns every link (the row + each ``superseded_by`` hop) with valid_from /
|
|
259
|
+
invalid_at / supersede_reason. Always walks the full chain regardless of the
|
|
260
|
+
``MARVIS_TEMPORAL_MEMORY`` flag — this is the deliberate audit surface.
|
|
261
|
+
"""
|
|
262
|
+
ctx = CallerContext.from_user_info(user, is_human_session=False)
|
|
263
|
+
try:
|
|
264
|
+
return await uc.get_learning_history(ctx, db, learning_id=learning_id)
|
|
265
|
+
except ServiceError as e:
|
|
266
|
+
raise to_http(e)
|
|
267
|
+
|
|
268
|
+
|
|
233
269
|
@router.get("/{learning_id}", response_model=LearningResponse)
|
|
234
270
|
async def get_learning(
|
|
235
271
|
learning_id: str,
|
|
236
272
|
deep: bool = Query(False, description="Attach KG context (Phase 7.0)"),
|
|
273
|
+
as_of: str | None = Query(
|
|
274
|
+
None,
|
|
275
|
+
description=(
|
|
276
|
+
"Point-in-time audit (Track 2 #1). ISO timestamp; returns the row iff it "
|
|
277
|
+
"was live at that instant. Only effective when MARVIS_TEMPORAL_MEMORY is enabled."
|
|
278
|
+
),
|
|
279
|
+
),
|
|
237
280
|
user: UserInfo = Depends(get_current_user_or_agent),
|
|
238
281
|
db: aiosqlite.Connection = Depends(get_db),
|
|
239
282
|
) -> LearningResponse:
|
|
240
283
|
"""Get a single learning by ID."""
|
|
241
284
|
ctx = CallerContext.from_user_info(user, is_human_session=False)
|
|
242
285
|
try:
|
|
243
|
-
result = await uc.get_learning(ctx, db, learning_id=learning_id)
|
|
286
|
+
result = await uc.get_learning(ctx, db, learning_id=learning_id, as_of=as_of)
|
|
244
287
|
except ServiceError as e:
|
|
245
288
|
raise to_http(e)
|
|
246
289
|
|
|
@@ -96,6 +96,14 @@ async def search(
|
|
|
96
96
|
description="True (default): RRF fusion semantic + KG FTS5. False: semantic-only (legacy v1.5 behavior).",
|
|
97
97
|
),
|
|
98
98
|
limit: int = Query(20, ge=1, le=50),
|
|
99
|
+
as_of: str | None = Query(
|
|
100
|
+
None,
|
|
101
|
+
description=(
|
|
102
|
+
"Point-in-time audit (Track 2 #1). ISO timestamp; reconstructs the "
|
|
103
|
+
"learnings live at that instant. Only effective when "
|
|
104
|
+
"MARVIS_TEMPORAL_MEMORY is enabled; ignored otherwise."
|
|
105
|
+
),
|
|
106
|
+
),
|
|
99
107
|
user: UserInfo = Depends(get_current_user_or_agent),
|
|
100
108
|
) -> SearchResponse:
|
|
101
109
|
"""Hybrid (default) or semantic search across the KG and embedding index."""
|
|
@@ -104,7 +112,7 @@ async def search(
|
|
|
104
112
|
|
|
105
113
|
ctx = CallerContext.from_user_info(user, is_human_session=False)
|
|
106
114
|
try:
|
|
107
|
-
return await uc.search(ctx, q=q, hybrid=hybrid, limit=limit)
|
|
115
|
+
return await uc.search(ctx, q=q, hybrid=hybrid, limit=limit, as_of=as_of)
|
|
108
116
|
except ServiceError as e:
|
|
109
117
|
raise to_http(e)
|
|
110
118
|
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# v1.0.0 - 2026-06-04 - Track 2 #4: fixed-size prose chunker (flag MARVIS_CHUNKING)
|
|
2
|
+
"""Pure, model-free fixed-size prose chunker (Track 2 #4).
|
|
3
|
+
|
|
4
|
+
Splits a prose document into fixed-size, overlapping, sentence-aware windows
|
|
5
|
+
BEFORE it is embedded, so a long handoff/plan no longer collapses to a single
|
|
6
|
+
over-compressed CLS vector (the embedder is a 32k-context ModernBert with CLS
|
|
7
|
+
pooling — there is no truncation pressure, the motivation is over-compression,
|
|
8
|
+
not truncation; see the roadmap "Research Insights — #4").
|
|
9
|
+
|
|
10
|
+
Design constraints (all load-bearing):
|
|
11
|
+
|
|
12
|
+
* **Model-free + pure.** No ONNX session, no model load, no I/O. The only
|
|
13
|
+
dependency is a *tokenizer* injected by the caller (``tokenizer`` param), so
|
|
14
|
+
this is unit-testable with a FAKE tokenizer and the real path reuses Granite's
|
|
15
|
+
already-loaded Rust ``tokenizers.Tokenizer`` (no second tokenizer, no second
|
|
16
|
+
model). The tokenizer is only asked for ``encode(text)`` exposing ``.ids`` and
|
|
17
|
+
``.offsets`` (per-token ``(char_start, char_end)`` into the ORIGINAL string —
|
|
18
|
+
exactly what the Rust ``tokenizers`` package returns).
|
|
19
|
+
* **UTF-8 BYTE offsets.** ``span_start`` / ``span_end`` are byte offsets into the
|
|
20
|
+
original text encoded as UTF-8, NOT character indices. Byte offsets round-trip
|
|
21
|
+
losslessly through multibyte Italian accents (à/è/ù) for the #2 span-citation
|
|
22
|
+
layer: ``text.encode("utf-8")[span_start:span_end].decode("utf-8")`` reproduces
|
|
23
|
+
the chunk content exactly.
|
|
24
|
+
* **Sentence-aware.** Window edges snap to the nearest sentence boundary within a
|
|
25
|
+
``±boundary_slack_tokens`` slack, so a chunk rarely cuts mid-sentence. The
|
|
26
|
+
splitter is a punkt-lite regex (no spaCy / nltk — those are host-pressure wheel
|
|
27
|
+
bloat; at ~15% overlap an imperfect boundary heals across the overlap).
|
|
28
|
+
* **Per-chunk content hash.** ``content_hash`` = sha256 of the chunk's byte span,
|
|
29
|
+
so a re-index re-embeds only the chunks that actually changed (editing one
|
|
30
|
+
paragraph churns ~1-2 chunks, not the whole doc).
|
|
31
|
+
|
|
32
|
+
Scope: PROSE ONLY. Code is already chunked per-symbol in
|
|
33
|
+
``core/cli/_index_source.py`` (``_embed_symbols``); a token windower over code
|
|
34
|
+
would split mid-symbol and break the KG anchors. This module is never invoked on
|
|
35
|
+
code.
|
|
36
|
+
"""
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
import hashlib
|
|
40
|
+
import re
|
|
41
|
+
from dataclasses import dataclass
|
|
42
|
+
from typing import Protocol, Sequence, runtime_checkable
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
"Chunk",
|
|
46
|
+
"TokenizerLike",
|
|
47
|
+
"chunk_prose",
|
|
48
|
+
"DEFAULT_TARGET_TOKENS",
|
|
49
|
+
"DEFAULT_OVERLAP_TOKENS",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
# Mirror of the F2 EMBEDDING_* knobs: defaults chosen for retrieval precision
|
|
53
|
+
# (recall peaks ~400 tokens per the Chroma/firecrawl ablation), ~15% overlap.
|
|
54
|
+
DEFAULT_TARGET_TOKENS = 400
|
|
55
|
+
DEFAULT_OVERLAP_TOKENS = 64
|
|
56
|
+
DEFAULT_BOUNDARY_SLACK_TOKENS = 32
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True, slots=True)
|
|
60
|
+
class Chunk:
|
|
61
|
+
"""One prose chunk.
|
|
62
|
+
|
|
63
|
+
``span_start`` / ``span_end`` are UTF-8 BYTE offsets into the ORIGINAL text
|
|
64
|
+
(half-open ``[start, end)``). ``content_hash`` is the sha256 hex of the chunk
|
|
65
|
+
byte span — the idempotency key (re-embed only changed chunks).
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
chunk_idx: int
|
|
69
|
+
span_start: int
|
|
70
|
+
span_end: int
|
|
71
|
+
content_hash: str
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@runtime_checkable
|
|
75
|
+
class TokenizerLike(Protocol):
|
|
76
|
+
"""Minimal surface of the Rust ``tokenizers.Tokenizer`` this chunker needs.
|
|
77
|
+
|
|
78
|
+
The real Granite tokenizer (``tokenizers.Tokenizer.from_file(...)``) satisfies
|
|
79
|
+
this: ``encode(text)`` returns an ``Encoding`` whose ``.offsets`` is a list of
|
|
80
|
+
``(char_start, char_end)`` tuples — one per token — into the ORIGINAL string.
|
|
81
|
+
A FAKE tokenizer in tests implements the same two attributes, so the chunker
|
|
82
|
+
is exercised with zero model load.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
def encode(self, text: str) -> "EncodingLike": ...
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@runtime_checkable
|
|
89
|
+
class EncodingLike(Protocol):
|
|
90
|
+
ids: Sequence[int]
|
|
91
|
+
# (char_start, char_end) per token, into the ORIGINAL (unencoded) string.
|
|
92
|
+
offsets: Sequence[tuple[int, int]]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# Punkt-lite sentence splitter: a boundary is sentence-final punctuation
|
|
96
|
+
# (. ! ? plus their typographic variants … ; and the IT/EN newline) followed by
|
|
97
|
+
# whitespace. Intentionally simple — overlap heals the misses (an abbreviation
|
|
98
|
+
# like "es." that splits early is recovered in the next window's prefix).
|
|
99
|
+
_SENTENCE_END = re.compile(r"[.!?…;\n]+[\s\"')\]]*")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _utf8_byte_offsets(text: str) -> list[int]:
|
|
103
|
+
"""Map char index -> UTF-8 byte offset (length == len(text) + 1).
|
|
104
|
+
|
|
105
|
+
``out[i]`` = byte offset where character ``i`` starts; ``out[len(text)]`` =
|
|
106
|
+
total byte length. Computed once per doc so char→byte conversion of every
|
|
107
|
+
token offset is O(1). Multibyte-safe: an accented char advances the byte
|
|
108
|
+
cursor by its UTF-8 width (2 for à/è/ù), so byte spans round-trip losslessly.
|
|
109
|
+
"""
|
|
110
|
+
out = [0] * (len(text) + 1)
|
|
111
|
+
byte = 0
|
|
112
|
+
for i, ch in enumerate(text):
|
|
113
|
+
out[i] = byte
|
|
114
|
+
byte += len(ch.encode("utf-8"))
|
|
115
|
+
out[len(text)] = byte
|
|
116
|
+
return out
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _sentence_boundary_chars(text: str) -> list[int]:
|
|
120
|
+
"""Character indices that are sentence boundaries (end of a sentence).
|
|
121
|
+
|
|
122
|
+
Returns the char index just AFTER each sentence-final punctuation run (i.e. a
|
|
123
|
+
valid place to start the next chunk). Always includes 0 and len(text) so the
|
|
124
|
+
snap logic has terminal anchors.
|
|
125
|
+
"""
|
|
126
|
+
bounds = {0, len(text)}
|
|
127
|
+
for m in _SENTENCE_END.finditer(text):
|
|
128
|
+
bounds.add(m.end())
|
|
129
|
+
return sorted(bounds)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _snap_to_boundary(
|
|
133
|
+
token_char_pos: int,
|
|
134
|
+
boundaries: Sequence[int],
|
|
135
|
+
*,
|
|
136
|
+
text_char_pos_window: tuple[int, int],
|
|
137
|
+
slack_chars: int,
|
|
138
|
+
) -> int:
|
|
139
|
+
"""Snap a proposed cut (char index) to the nearest sentence boundary in slack.
|
|
140
|
+
|
|
141
|
+
``token_char_pos`` is the char index the token-window would cut at. If a
|
|
142
|
+
sentence boundary lies within ``±slack_chars`` AND inside the allowed window
|
|
143
|
+
``text_char_pos_window`` (so we never snap past the doc edge or before the
|
|
144
|
+
chunk start), use the closest one; otherwise keep the token cut (hard split).
|
|
145
|
+
"""
|
|
146
|
+
lo, hi = text_char_pos_window
|
|
147
|
+
best = token_char_pos
|
|
148
|
+
best_dist = slack_chars + 1
|
|
149
|
+
for b in boundaries:
|
|
150
|
+
if b < lo or b > hi:
|
|
151
|
+
continue
|
|
152
|
+
dist = abs(b - token_char_pos)
|
|
153
|
+
if dist <= slack_chars and dist < best_dist:
|
|
154
|
+
best = b
|
|
155
|
+
best_dist = dist
|
|
156
|
+
return best
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def chunk_prose(
|
|
160
|
+
text: str,
|
|
161
|
+
tokenizer: TokenizerLike,
|
|
162
|
+
*,
|
|
163
|
+
target_tokens: int = DEFAULT_TARGET_TOKENS,
|
|
164
|
+
overlap_tokens: int = DEFAULT_OVERLAP_TOKENS,
|
|
165
|
+
boundary_slack_tokens: int = DEFAULT_BOUNDARY_SLACK_TOKENS,
|
|
166
|
+
) -> list[Chunk]:
|
|
167
|
+
"""Split ``text`` into fixed-size, overlapping, sentence-aware prose chunks.
|
|
168
|
+
|
|
169
|
+
Windowing is in TOKEN space (reusing the injected tokenizer's per-token char
|
|
170
|
+
offsets), so the window size is stable across mixed IT/EN text where char
|
|
171
|
+
windows over/under-fill. Each window edge is snapped to the nearest sentence
|
|
172
|
+
boundary within ``±boundary_slack_tokens`` (converted to a char slack via the
|
|
173
|
+
local token density). Span offsets are emitted as UTF-8 BYTE offsets.
|
|
174
|
+
|
|
175
|
+
Returns ``[]`` for empty/whitespace-only input. A short doc (<= target_tokens)
|
|
176
|
+
yields a single chunk covering the whole byte range.
|
|
177
|
+
"""
|
|
178
|
+
if not text or not text.strip():
|
|
179
|
+
return []
|
|
180
|
+
if target_tokens <= 0:
|
|
181
|
+
raise ValueError("target_tokens must be > 0")
|
|
182
|
+
if overlap_tokens < 0 or overlap_tokens >= target_tokens:
|
|
183
|
+
# overlap must leave forward progress; clamp defensively rather than loop.
|
|
184
|
+
overlap_tokens = max(0, min(overlap_tokens, target_tokens - 1))
|
|
185
|
+
|
|
186
|
+
enc = tokenizer.encode(text)
|
|
187
|
+
offsets = list(enc.offsets)
|
|
188
|
+
n_tokens = len(offsets)
|
|
189
|
+
byte_at = _utf8_byte_offsets(text)
|
|
190
|
+
total_bytes = byte_at[len(text)]
|
|
191
|
+
|
|
192
|
+
# Degenerate: tokenizer produced no usable offsets → one chunk, whole doc.
|
|
193
|
+
if n_tokens == 0:
|
|
194
|
+
return [
|
|
195
|
+
Chunk(
|
|
196
|
+
chunk_idx=0,
|
|
197
|
+
span_start=0,
|
|
198
|
+
span_end=total_bytes,
|
|
199
|
+
content_hash=_hash_byte_span(text, 0, total_bytes),
|
|
200
|
+
)
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
boundaries = _sentence_boundary_chars(text)
|
|
204
|
+
stride = target_tokens - overlap_tokens # > 0 (overlap clamped above)
|
|
205
|
+
|
|
206
|
+
# Mean chars/token for this doc → convert the token-space slack to char slack
|
|
207
|
+
# for the boundary snap (the boundary list is in char space).
|
|
208
|
+
mean_chars_per_token = max(1.0, len(text) / n_tokens)
|
|
209
|
+
slack_chars = int(round(boundary_slack_tokens * mean_chars_per_token))
|
|
210
|
+
|
|
211
|
+
chunks: list[Chunk] = []
|
|
212
|
+
chunk_idx = 0
|
|
213
|
+
tok_start = 0
|
|
214
|
+
while tok_start < n_tokens:
|
|
215
|
+
tok_end = min(tok_start + target_tokens, n_tokens)
|
|
216
|
+
|
|
217
|
+
# Char window for THIS chunk: start at the first token's char-start, end
|
|
218
|
+
# at the last covered token's char-end.
|
|
219
|
+
char_start = offsets[tok_start][0]
|
|
220
|
+
char_end = offsets[tok_end - 1][1]
|
|
221
|
+
|
|
222
|
+
is_last = tok_end >= n_tokens
|
|
223
|
+
|
|
224
|
+
# Snap the chunk START to a sentence boundary at/just-before it (only when
|
|
225
|
+
# this is NOT the first chunk — chunk 0 must begin at 0 to cover the head).
|
|
226
|
+
if chunk_idx > 0:
|
|
227
|
+
char_start = _snap_to_boundary(
|
|
228
|
+
char_start,
|
|
229
|
+
boundaries,
|
|
230
|
+
text_char_pos_window=(0, char_end),
|
|
231
|
+
slack_chars=slack_chars,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Snap the chunk END to a sentence boundary near it (never on the last
|
|
235
|
+
# chunk — the tail must reach len(text) so no bytes are dropped).
|
|
236
|
+
if not is_last:
|
|
237
|
+
char_end = _snap_to_boundary(
|
|
238
|
+
char_end,
|
|
239
|
+
boundaries,
|
|
240
|
+
text_char_pos_window=(char_start + 1, len(text)),
|
|
241
|
+
slack_chars=slack_chars,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
span_start = byte_at[char_start]
|
|
245
|
+
span_end = byte_at[char_end] if not is_last else total_bytes
|
|
246
|
+
|
|
247
|
+
if span_end > span_start:
|
|
248
|
+
chunks.append(
|
|
249
|
+
Chunk(
|
|
250
|
+
chunk_idx=chunk_idx,
|
|
251
|
+
span_start=span_start,
|
|
252
|
+
span_end=span_end,
|
|
253
|
+
content_hash=_hash_byte_span(text, span_start, span_end),
|
|
254
|
+
)
|
|
255
|
+
)
|
|
256
|
+
chunk_idx += 1
|
|
257
|
+
|
|
258
|
+
if is_last:
|
|
259
|
+
break
|
|
260
|
+
tok_start += stride
|
|
261
|
+
|
|
262
|
+
return chunks
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _hash_byte_span(text: str, span_start: int, span_end: int) -> str:
|
|
266
|
+
"""sha256 of the chunk's UTF-8 byte span (the per-chunk idempotency key)."""
|
|
267
|
+
raw = text.encode("utf-8")[span_start:span_end]
|
|
268
|
+
return hashlib.sha256(raw).hexdigest()
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def chunk_text_bytes(text: str, span_start: int, span_end: int) -> bytes:
|
|
272
|
+
"""Round-trip helper: the exact bytes a chunk's byte span refers to.
|
|
273
|
+
|
|
274
|
+
``chunk_text_bytes(text, c.span_start, c.span_end).decode("utf-8")`` is the
|
|
275
|
+
chunk content (used by the #2 citation resolver and by the round-trip test).
|
|
276
|
+
"""
|
|
277
|
+
return text.encode("utf-8")[span_start:span_end]
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# v1.0.0 - 2026-06-05 - Track 2 #1-S5: nightly dream-cycle consolidation (SHADOW/dry-run)
|
|
2
|
+
"""Nightly dream-cycle consolidation — SHADOW / dry-run only (Track 2 #1-S5).
|
|
3
|
+
|
|
4
|
+
Plan ``docs/plans/2026-06-04-track2-engine-moat-roadmap-plan.md`` (#1, sub-increment
|
|
5
|
+
S5, lines 343/350). This is the *batch* analogue of the S3 write-time gate. Where S3
|
|
6
|
+
decides ADD / NOOP / SUPERSEDE_CANDIDATE for ONE just-inserted learning, the dream
|
|
7
|
+
cycle scans the WHOLE live learnings store and, for each near-match pair in the
|
|
8
|
+
supersede band, writes a pending SUPERSEDE_CANDIDATE proposal into the SAME approval
|
|
9
|
+
gate the brain cycle drains (``brain_memory_operations``, mig 129).
|
|
10
|
+
|
|
11
|
+
DRY-RUN, NON-NEGOTIABLE. This module is SHADOW only — it ``propose``s, it NEVER
|
|
12
|
+
``apply``s:
|
|
13
|
+
* it NEVER calls :func:`temporal_write.apply_supersede`;
|
|
14
|
+
* it NEVER sets ``invalid_at`` / ``superseded_by`` on any row;
|
|
15
|
+
* it NEVER deletes a learning (no NOOP-style hard-remove like the write path does).
|
|
16
|
+
The verdict surfaces ONLY as a pending proposal for the human/Triage gate. Diffing
|
|
17
|
+
those proposals against the gold set (and only then enabling an auto-apply
|
|
18
|
+
high-confidence tier) is a deliberate, eval-gated, OFF-host follow-up — see plan
|
|
19
|
+
lines 341/343.
|
|
20
|
+
|
|
21
|
+
Reuses S3 verbatim (does NOT modify ``temporal_write`` / ``learnings``):
|
|
22
|
+
* :func:`temporal_write.decide_write_action` + the pinned 0.80 / 0.97 bands;
|
|
23
|
+
* :func:`temporal_write.propose_supersede_candidate` (the ``INSERT OR IGNORE`` on a
|
|
24
|
+
stable BLAKE2b ``operation_id`` is what makes a re-run idempotent — no duplicate
|
|
25
|
+
proposals);
|
|
26
|
+
* default vector source = :func:`temporal_write.fetch_learning_vector` +
|
|
27
|
+
:func:`temporal_write.fetch_live_neighbor_vectors`, which read PRE-COMPUTED
|
|
28
|
+
vectors back from the search-index mirror. **NO embedding model is EVER run.**
|
|
29
|
+
|
|
30
|
+
Flag gate: the SAME ``settings.temporal_memory_enabled`` (alias
|
|
31
|
+
``MARVIS_TEMPORAL_MEMORY``, default False). When OFF, :func:`run_dream_cycle_shadow`
|
|
32
|
+
is a no-op that returns an empty report and scans nothing.
|
|
33
|
+
|
|
34
|
+
Host-safety + testability: the neighbour/vector source is INJECTABLE via the
|
|
35
|
+
``neighbor_provider`` callable. Tests pass FAKE vectors of known cosine through it,
|
|
36
|
+
so the unit suite needs neither sqlite-vec nor a model. The default provider only
|
|
37
|
+
reads mirrored bytes — still model-free.
|
|
38
|
+
|
|
39
|
+
What this module deliberately does NOT do: it does NOT build or run a real nightly
|
|
40
|
+
scheduler (cron/launchd), and it does NOT run a real cycle over the prod store.
|
|
41
|
+
Wiring this STEP to the nightly schedule and flipping the (default-off)
|
|
42
|
+
warehouse-consolidation pass on are separate, eval-gated, off-host steps. This is the
|
|
43
|
+
pure batch step + its dry-run guarantee, unit-testable in isolation.
|
|
44
|
+
"""
|
|
45
|
+
from __future__ import annotations
|
|
46
|
+
|
|
47
|
+
from collections.abc import Awaitable, Callable
|
|
48
|
+
from dataclasses import dataclass
|
|
49
|
+
|
|
50
|
+
import aiosqlite
|
|
51
|
+
|
|
52
|
+
from core.api.config import settings
|
|
53
|
+
from core.api.services import temporal_write as tw
|
|
54
|
+
|
|
55
|
+
# A neighbour provider resolves, for a given live learning id, the pair
|
|
56
|
+
# ``(its_vector, [(neighbor_id, neighbor_vector), ...])`` that the PURE band decision
|
|
57
|
+
# consumes. ``None`` for the vector means "no mirrored embedding yet" → skip that row
|
|
58
|
+
# (mirrors the S3 write-path fallback: stay ADD, catch it on a later run). Injectable
|
|
59
|
+
# so tests feed FAKE vectors and the default reads mirrored bytes — neither runs a model.
|
|
60
|
+
NeighborProvider = Callable[
|
|
61
|
+
[aiosqlite.Connection, str, str],
|
|
62
|
+
Awaitable[tuple[list[float] | None, list[tuple[str, list[float]]]]],
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass(frozen=True)
|
|
67
|
+
class DreamCycleReport:
|
|
68
|
+
"""Outcome of one SHADOW dream-cycle pass.
|
|
69
|
+
|
|
70
|
+
``scanned`` — live learnings examined (``invalid_at IS NULL``).
|
|
71
|
+
``proposed`` — DISTINCT supersede-candidate pairs proposed this pass (the pair is
|
|
72
|
+
canonicalised by id, so the reverse-direction scan of the same pair
|
|
73
|
+
does NOT double-count). On a fresh store this equals the rows added
|
|
74
|
+
to the gate; on a re-run the gate's ``INSERT OR IGNORE`` on a stable
|
|
75
|
+
``operation_id`` keeps it duplicate-free, so re-running adds zero
|
|
76
|
+
gate rows even though it re-proposes (``proposed`` may be > 0 again).
|
|
77
|
+
``skipped`` — scanned learnings that produced NO new proposal: no mirrored vector
|
|
78
|
+
yet, no neighbours, a non-band verdict (ADD / NOOP), or the closest
|
|
79
|
+
neighbour forms a pair already proposed earlier in THIS pass.
|
|
80
|
+
|
|
81
|
+
Invariant: ``scanned == proposed + skipped``.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
scanned: int
|
|
85
|
+
proposed: int
|
|
86
|
+
skipped: int
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
async def _default_neighbor_provider(
|
|
90
|
+
db: aiosqlite.Connection,
|
|
91
|
+
workspace_id: str,
|
|
92
|
+
learning_id: str,
|
|
93
|
+
) -> tuple[list[float] | None, list[tuple[str, list[float]]]]:
|
|
94
|
+
"""Default vector source — reads PRE-COMPUTED vectors back. NEVER runs a model.
|
|
95
|
+
|
|
96
|
+
Mirrors the S3 write path exactly: pull the learning's own mirrored vector, then
|
|
97
|
+
its top-k LIVE (``invalid_at IS NULL``) neighbours via sqlite-vec kNN. Returns
|
|
98
|
+
``(None, [])`` when the mirror isn't present yet so the caller skips the row.
|
|
99
|
+
"""
|
|
100
|
+
new_vec = await tw.fetch_learning_vector(db, learning_id)
|
|
101
|
+
if new_vec is None:
|
|
102
|
+
return None, []
|
|
103
|
+
neighbors = await tw.fetch_live_neighbor_vectors(
|
|
104
|
+
db, workspace_id, new_vec, exclude_learning_id=learning_id
|
|
105
|
+
)
|
|
106
|
+
return new_vec, neighbors
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
async def _live_learning_ids(
|
|
110
|
+
db: aiosqlite.Connection, workspace_id: str
|
|
111
|
+
) -> list[tuple[str, str | None]]:
|
|
112
|
+
"""All LIVE learnings (``invalid_at IS NULL``) for the workspace: (id, project).
|
|
113
|
+
|
|
114
|
+
Workspace-scoped with the same ``COALESCE(workspace_id, 'ws_default')`` default as
|
|
115
|
+
the S3 neighbour fetch, so a row and its neighbours live in one scope. Stable order
|
|
116
|
+
so a re-run walks the store identically.
|
|
117
|
+
"""
|
|
118
|
+
cur = await db.execute(
|
|
119
|
+
"""
|
|
120
|
+
SELECT id, project
|
|
121
|
+
FROM learnings
|
|
122
|
+
WHERE invalid_at IS NULL
|
|
123
|
+
AND COALESCE(workspace_id, 'ws_default') = ?
|
|
124
|
+
ORDER BY id
|
|
125
|
+
""",
|
|
126
|
+
[workspace_id],
|
|
127
|
+
)
|
|
128
|
+
rows = await cur.fetchall()
|
|
129
|
+
return [(row["id"], row["project"]) for row in rows]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
async def run_dream_cycle_shadow(
|
|
133
|
+
db: aiosqlite.Connection,
|
|
134
|
+
workspace_id: str,
|
|
135
|
+
*,
|
|
136
|
+
neighbor_provider: NeighborProvider | None = None,
|
|
137
|
+
) -> DreamCycleReport:
|
|
138
|
+
"""Scan the full LIVE learnings store and PROPOSE supersede candidates. DRY-RUN.
|
|
139
|
+
|
|
140
|
+
For each live learning, resolve ``(its_vector, live_neighbours)`` via the injected
|
|
141
|
+
``neighbor_provider`` (default = mirrored-vector reader, no model), run the PURE
|
|
142
|
+
two-band cosine :func:`temporal_write.decide_write_action`, and on a
|
|
143
|
+
``SUPERSEDE_CANDIDATE`` verdict write ONE pending proposal into the existing
|
|
144
|
+
approval gate via :func:`temporal_write.propose_supersede_candidate`.
|
|
145
|
+
|
|
146
|
+
SHADOW guarantee: this only ever PROPOSES. It NEVER calls ``apply_supersede``,
|
|
147
|
+
NEVER stamps ``invalid_at`` / ``superseded_by``, NEVER deletes a row — not even on
|
|
148
|
+
a NOOP verdict (the write path retires a brand-new duplicate; a batch pass over the
|
|
149
|
+
persisted store must not, so NOOP here is a skip).
|
|
150
|
+
|
|
151
|
+
Idempotency: the (old, new) pair is canonicalised by sorted id BEFORE proposing, so
|
|
152
|
+
scanning A→B and later B→A target the SAME proposal. Combined with
|
|
153
|
+
``propose_supersede_candidate``'s stable ``operation_id`` + ``INSERT OR IGNORE``, a
|
|
154
|
+
re-run adds zero duplicate rows to the gate.
|
|
155
|
+
|
|
156
|
+
Flag OFF (``settings.temporal_memory_enabled`` False): no-op — returns an empty
|
|
157
|
+
report and scans nothing.
|
|
158
|
+
"""
|
|
159
|
+
if not settings.temporal_memory_enabled:
|
|
160
|
+
return DreamCycleReport(scanned=0, proposed=0, skipped=0)
|
|
161
|
+
|
|
162
|
+
provider = neighbor_provider or _default_neighbor_provider
|
|
163
|
+
|
|
164
|
+
scanned = 0
|
|
165
|
+
proposed = 0
|
|
166
|
+
skipped = 0
|
|
167
|
+
seen_pairs: set[tuple[str, str]] = set()
|
|
168
|
+
|
|
169
|
+
for learning_id, project in await _live_learning_ids(db, workspace_id):
|
|
170
|
+
scanned += 1
|
|
171
|
+
|
|
172
|
+
new_vec, neighbors = await provider(db, workspace_id, learning_id)
|
|
173
|
+
if new_vec is None or not neighbors:
|
|
174
|
+
skipped += 1
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
decision = tw.decide_write_action(new_vec, neighbors)
|
|
178
|
+
if (
|
|
179
|
+
decision.action is not tw.WriteAction.SUPERSEDE_CANDIDATE
|
|
180
|
+
or decision.neighbor_id is None
|
|
181
|
+
):
|
|
182
|
+
# ADD (distinct) / NOOP (near-dup) verdicts produce no proposal in shadow.
|
|
183
|
+
skipped += 1
|
|
184
|
+
continue
|
|
185
|
+
|
|
186
|
+
# Canonicalise the pair by id so A→B and B→A collapse to ONE proposal. The
|
|
187
|
+
# in-run ``seen_pairs`` guard makes ``proposed`` count DISTINCT pairs this pass
|
|
188
|
+
# (the reverse-direction scan is a skip, not a second proposal); the persisted
|
|
189
|
+
# gate is *also* dedup'd by propose_supersede_candidate's stable operation_id +
|
|
190
|
+
# INSERT OR IGNORE, so a re-run across passes adds nothing either.
|
|
191
|
+
pair = tuple(sorted((learning_id, decision.neighbor_id)))
|
|
192
|
+
if pair in seen_pairs:
|
|
193
|
+
skipped += 1
|
|
194
|
+
continue
|
|
195
|
+
seen_pairs.add(pair)
|
|
196
|
+
|
|
197
|
+
a, b = pair
|
|
198
|
+
score = decision.score if decision.score is not None else 0.0
|
|
199
|
+
await tw.propose_supersede_candidate(
|
|
200
|
+
db,
|
|
201
|
+
old_id=a,
|
|
202
|
+
new_id=b,
|
|
203
|
+
score=score,
|
|
204
|
+
summary=(
|
|
205
|
+
f"Dream-cycle near-match between learnings '{a}' and '{b}' "
|
|
206
|
+
f"(cosine={score:.4f}) — confirm supersede or keep both."
|
|
207
|
+
),
|
|
208
|
+
project=project,
|
|
209
|
+
)
|
|
210
|
+
proposed += 1
|
|
211
|
+
|
|
212
|
+
await db.commit()
|
|
213
|
+
return DreamCycleReport(scanned=scanned, proposed=proposed, skipped=skipped)
|