conexus 4.2.0__tar.gz → 4.2.2__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.
- {conexus-4.2.0 → conexus-4.2.2}/.claude-plugin/marketplace.json +2 -2
- {conexus-4.2.0 → conexus-4.2.2}/CHANGELOG.md +22 -0
- {conexus-4.2.0 → conexus-4.2.2}/CLAUDE.md +22 -0
- {conexus-4.2.0 → conexus-4.2.2}/PKG-INFO +1 -1
- {conexus-4.2.0 → conexus-4.2.2}/nx/.claude-plugin/plugin.json +1 -1
- {conexus-4.2.0 → conexus-4.2.2}/nx/CHANGELOG.md +8 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/hooks.json +1 -1
- {conexus-4.2.0 → conexus-4.2.2}/pyproject.toml +1 -1
- {conexus-4.2.0 → conexus-4.2.2}/sn/.claude-plugin/plugin.json +1 -1
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/taxonomy_cmd.py +52 -15
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/upgrade.py +7 -6
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/migrations.py +49 -10
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/catalog_taxonomy.py +93 -16
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/health.py +59 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_phase5_integration.py +3 -1
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_taxonomy.py +20 -26
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_upgrade_cmd.py +21 -5
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_upgrade_e2e.py +9 -3
- {conexus-4.2.0 → conexus-4.2.2}/uv.lock +1 -1
- {conexus-4.2.0 → conexus-4.2.2}/.beads/.gitignore +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/config.yaml +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/post-checkout +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/post-merge +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/pre-commit +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/pre-push +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/prepare-commit-msg +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/interactions.jsonl +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/issues.jsonl +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.beads/metadata.json +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.claude/skills/release.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.devcontainer/Dockerfile +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.devcontainer/devcontainer.json +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.dockerignore +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.env.example +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.gitattributes +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.github/workflows/ci.yml +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.github/workflows/release.yml +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.gitignore +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.markdownlint.json +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/.plans/rdr-066-plan.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/AGENTS.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/Formula/nx.rb +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/LICENSE +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/architecture.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/catalog.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/cli-reference.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/configuration.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/contributing.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/getting-started.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/historical.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/logging.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/mcp-servers.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/memory-and-tasks.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/postmortem/2026-03-23-pdf-index-collection-mismatch.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/postmortem/2026-03-24-pdf-index-fix-not-applied.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/querying-guide.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/001-rdr-process-validation.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/002-t2-status-synchronization.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/010-t1-http-server.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/011-pdf-ingest-test-coverage.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/012-pdfplumber-extraction-tier.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/014-knowledge-base-retrieval-quality.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/015-indexing-pipeline-rethink.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/016-ast-chunk-line-range-bug.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/017-indexing-progress-reporting.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/018-replace-serve-with-git-hooks.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/023-agent-tool-permissions-audit.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/024-rdr-process-guardrails.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/028-language-registry-unification.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/029-pipeline-versioning.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/048-streaming-pdf-pipeline.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/049-git-backed-catalog.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/050-catalog-query-integration.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/051-link-lifecycle.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/052-catalog-first-query-routing.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/053-xanadu-fidelity.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/058-pipeline-orchestration-plan-reuse.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/060-catalog-path-rationalization-link-usability.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/063-t2-domain-split.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/065-close-time-funnel-hardening.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/067-cross-project-rdr-audit-loop.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/cce-query-model-mismatch.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-001-rdr-process-validation.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-002-t2-status-synchronization.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-004-four-store-architecture.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-005-chromadb-cloud-quota-enforcement.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-006-chunk-size-configuration.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-007-claude-adoption-session-context-and-search-guidance.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-008-nx-workflow-integration.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-009-remove-agentic-and-answer-flags.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-010-t1-scratch-persistent-bounded-store.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-011-pdf-ingest-test-coverage.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-012-pdfplumber-extraction-tier.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-013-remove-nx-pm-layer.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-014-knowledge-base-retrieval-quality.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-015-indexing-pipeline-rethink.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-016-ast-chunk-line-range-bug.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-017-indexing-progress-reporting.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-018-replace-serve-with-git-hooks.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-019-chromadb-transient-retry.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-020-voyage-chromadb-read-timeout.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-021-docling-pdf-extraction.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-022-memory-delete-command.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-023-agent-tool-permissions-audit.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-024-rdr-process-guardrails.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-025-language-agnostic-agents.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-026-hybrid-search-fusion.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-027-search-results-ux.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-028-code-search-recall.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-029-pipeline-versioning.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-030-reliability-hardening.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-031-collection-portability.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-032-indexer-decomposition.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-033-pdf-agent-nx-index-alignment.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-034-mcp-server-agent-storage.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-035-plugin-agent-mcp-tool-access.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-036-post-accept-planning-workflow.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-037-t3-database-consolidation.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-038-local-t3-backend.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-039-claude-code-framework-alignment.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-040-cce-postmortem-gaps-mcp-enhancement.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-040-developer-agent-circuit-breaker.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-041-t1-scratch-inter-agent-context.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-042-agenticscholar-enhancements.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-043-plan-enricher-scope.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-044-math-aware-pdf-extraction.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-045-post-implementation-verification.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-046-mineru-server-backed-extraction.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-047-large-pdf-extraction-resilience.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-048-streaming-pdf-pipeline.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-049-consolidation-plan.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-049-git-backed-catalog.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-050-knowledge-graph-query-planning.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-051-link-lifecycle.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-052-catalog-first-query-routing.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-053-xanadu-fidelity.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-054-chunk-boundary-equation-splitting.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-055-section-type-metadata-quality-scoring.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-056-search-robustness-result-clustering.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-057-progressive-formalization-memory-tiers.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-058-pipeline-orchestration-plan-reuse.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-059-code-search-embedding-mismatch.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-060-catalog-path-rationalization-link-usability.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-061-literature-grounded-search-knowledge-enhancement.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-062-mcp-interface-tiering.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-063-t2-domain-split.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-064-nx-console-embedded-web-ui.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-065-close-time-funnel-hardening.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-066-composition-smoke-probe-at-coordinator-beads.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-067-cross-project-rdr-audit-loop.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-068-dimensional-contracts-at-enrichment.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-069-automatic-substantive-critic-at-close.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-070-incremental-taxonomy-clustered-search.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-071-query-sanitizer-permanence-mode.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-072-progressive-context-loading.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-073-temporal-entity-knowledge-graph.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-074-permanence-mode.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-075-cross-collection-topic-projection.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-076-idempotent-upgrade-mechanism.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr-nexus-integration.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr-overview.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr-templates.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/rdr-workflow.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/repo-indexing.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/storage-tiers.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/taxonomy.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/docs/xanadu-in-nexus.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/.mcp.json +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/CONTEXT_PROTOCOL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/ERROR_HANDLING.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/MAINTENANCE.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/RELAY_TEMPLATE.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/analytical-operator.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/architect-planner.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/code-review-expert.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/codebase-deep-analyzer.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/debugger.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/deep-analyst.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/deep-research-synthesizer.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/developer.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/knowledge-tidier.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/pdf-chromadb-processor.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/plan-auditor.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/plan-enricher.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/query-planner.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/strategic-planner.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/substantive-critic.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/agents/test-validator.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/analyze-code.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/architecture.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/create-plan.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/debug.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/deep-analysis.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/enrich-plan.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/implement.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/knowledge-tidy.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/nx-preflight.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/pdf-process.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/plan-audit.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-accept.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-audit.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-close.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-create.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-gate.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-list.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-research.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-show.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/research.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/review-code.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/substantive-critique.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/commands/test-validate.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/auto-approve-nx-mcp.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/divergence-language-guard.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/post_compact_hook.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/pre_close_verification_hook.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/rdr_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/read_verification_config.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/session_start_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/stop_failure_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/stop_verification_hook.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/subagent-start.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/t2_prefix_scan.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/registry.yaml +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/resources/rdr/README-TEMPLATE.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/resources/rdr/TEMPLATE.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/resources/rdr/post-mortem/TEMPLATE.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/resources/rdr_process/INCIDENT-TEMPLATE.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/architecture/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/brainstorming-gate/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/catalog/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/cli-controller/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/code-review/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/codebase-analysis/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/composition-probe/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/debugging/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/deep-analysis/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/development/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/enrich-plan/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/finishing-branch/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/git-worktrees/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/knowledge-tidying/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/nexus/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/nexus/reference.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/orchestration/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/orchestration/reference.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/pdf-processing/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/plan-validation/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/query/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-accept/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-audit/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-close/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-create/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-gate/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-list/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-research/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-show/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/receiving-review/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/research-synthesis/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/serena-code-nav/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/strategic-planning/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/substantive-critique/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/test-validation/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/using-nx-skills/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/nx/skills/writing-nx-skills/SKILL.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/scripts/batch-label-taxonomy.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/scripts/cron/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/scripts/cron/rdr-audit.crontab +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/scripts/cron-rdr-audit.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/scripts/launchd/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/scripts/launchd/com.nexus.rdr-audit.PROJECT.plist +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/scripts/reinstall-tool.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/scripts/smoke-test-taxonomy.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/sn/.mcp.json +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/sn/README.md +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/sn/hooks/hooks.json +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/sn/hooks/scripts/auto-approve-sn-mcp.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/sn/hooks/scripts/mcp-inject.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/sn/hooks/scripts/session-start.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/bib_enricher.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/auto_linker.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/catalog.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/catalog_db.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/consolidation.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/link_generator.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/tumbler.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/checkpoint.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/chunker.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/classifier.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/cli.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/code_indexer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/_helpers.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/_provision.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/catalog.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/collection.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/config_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/console.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/context_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/doctor.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/enrich.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/hooks.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/index.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/memory.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/mineru.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/scratch.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/search_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/store.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/config.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/app.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/config.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/activity.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/campaigns.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/health.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/partials.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/static/alpine.min.js +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/static/console.css +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/static/htmx.min.js +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/static/pico.min.css +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/activity/_detail.html +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/activity/_stream.html +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/activity/index.html +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/base.html +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/campaigns/detail.html +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/campaigns/index.html +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/health/_cards.html +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/health/index.html +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/watchers.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/context.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/corpus.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/chroma_quotas.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/local_ef.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t1.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/memory_store.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/plan_library.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/telemetry.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t3.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/doc_indexer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/errors.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/exporter.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/filters.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/formatters.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/frecency.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/hooks.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/index_context.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/indexer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/indexer_utils.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/languages.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/logging_setup.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp/catalog.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp/core.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp_infra.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp_server.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/md_chunker.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/pdf_chunker.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/pdf_extractor.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/pipeline_buffer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/pipeline_stages.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/prose_indexer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/registry.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/retry.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/ripgrep_cache.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/scoring.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/search_clusterer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/search_engine.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/session.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/taxonomy.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/ttl.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/src/nexus/types.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/__snapshots__/test_search_cmd.ambr +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/benchmarks/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/benchmarks/corpus.json +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/benchmarks/queries.json +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/benchmarks/test_retrieval_ndcg.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/conftest.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/auth-login.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/lib.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/run.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/sandbox.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/scenarios/00_debug_load.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/scenarios/01_smoke.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/scenarios/02_sequential_thinking.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/scenarios/03_skills.sh +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/__init__.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_permission_request_hooks.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_post_compact_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_pre_close_verification_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_read_verification_config.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_stop_failure_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_stop_verification_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_verification_integration.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_activity_stream.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_ast_languages.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_auto_linker.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_backfill_hash.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_bib_enricher.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_campaigns_panel.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_backfill.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_cli.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_consolidation.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_db.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_e2e.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_git.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_indexer_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_jsonl.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_knowledge_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_link_generation.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_links.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_mcp.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_path.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_pdf_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_prefilter.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_checkpoint.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_chroma_quotas.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_chroma_retry.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_chunker.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_chunker_ast_languages.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_classifier.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_cli_registration.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_collection_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_config.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_config_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_console_app.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_console_deps.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_context.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_contradiction_flag.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_corpus.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_distance_thresholds.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_doc_indexer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_doc_indexer_hash_sync.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_doc_indexer_pagination.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_doctor_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_doctor_integrity.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_e2e.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_enrich_command.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_exporter.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_formatters.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_frecency.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_git_hooks.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_health.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_health_panel.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_hooks.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_hybrid_boost.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_lock.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_pdf_batch.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_rdr_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_reminder.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_taxonomy.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer_chunk_flow.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer_e2e.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer_modules.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer_utils_repo.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_integration.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_jsonl.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_languages.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_link_generator.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_local_mode.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_logging_setup.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_mcp_concurrency.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_mcp_package.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_mcp_server.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_md_chunker.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_md_chunker_semantic_integrity.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_md_preservation.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_memory.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_memory_consolidation.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_migrations.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_mineru_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_mineru_extractor.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_minified_chunking.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_overfetch_pipeline.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_p0_regressions.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_chunker.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_chunker_integration.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_e2e.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_extractor.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_extractor_integration.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_extractor_normalization.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_extractor_server.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_subsystem.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pipeline_buffer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pipeline_stages.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_pipeline_version.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_plan_library.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_plugin.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_plugin_install.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_plugin_structure.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_post_store_hook.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_ppid_chain_hypothesis.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_provision.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_quality_score.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_query_sanitizer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr052_verification.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr053_verification.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr_audit_incident_template.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr_audit_scheduling.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr_audit_skill.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr_close_gate.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_registry.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_relevance_log.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_ripgrep_cache.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_schema.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_scoring.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_scratch.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_scratch_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_search_clusterer.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_search_clustering_integration.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_search_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_search_engine.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_session.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_session_propagation_hypotheses.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_silent_error_logging.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_sn_plugin.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_store_cmd.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_structlog_events.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_t1.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_t2.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_t2_concurrency.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_t2_prefix_scan.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_t3.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_t3_hnsw_ef.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_t3_quota_enforcement.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_table_extraction.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_taxonomy_e2e.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_ttl.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_tumbler.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_tuning_config.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_verify_multiprobe.py +0 -0
- {conexus-4.2.0 → conexus-4.2.2}/tests/test_voyage_retry.py +0 -0
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"name": "nx",
|
|
10
10
|
"source": "./nx",
|
|
11
11
|
"description": "Self-hosted three-tier knowledge management with 16 specialized agents, analytical query pipelines, semantic search, and RDR decision tracking for Claude Code.",
|
|
12
|
-
"version": "4.2.
|
|
12
|
+
"version": "4.2.2"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"name": "sn",
|
|
16
16
|
"source": "./sn",
|
|
17
17
|
"description": "Injects Serena and Context7 MCP tool usage guidance into subagents via SubagentStart hook.",
|
|
18
|
-
"version": "4.2.
|
|
18
|
+
"version": "4.2.2"
|
|
19
19
|
}
|
|
20
20
|
]
|
|
21
21
|
}
|
|
@@ -6,6 +6,28 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [4.2.2] - 2026-04-14
|
|
10
|
+
|
|
11
|
+
(Note: v4.2.1 was tagged but never published due to a test failure. v4.2.2 supersedes it and includes all 4.2.1 changes plus the ChromaDB Cloud quota audit and observability improvements found during a live shakeout.)
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`nx doctor` PyPI version check**: `_check_cli_version` queries https://pypi.org/pypi/conexus/json (3-second timeout) and reports current vs latest. When behind, suggests `uv tool upgrade conexus`. Network failures are silent (offline-tolerant).
|
|
16
|
+
- **`nx upgrade --skip-t3` flag**: skip T3 upgrade steps (e.g., heavy cross-collection projection backfill) for fast T2-only migrations.
|
|
17
|
+
- **`backfill_projection` per-collection progress**: prints `[i/N] collection: chunks, matches, attempted (elapsed)` to stderr during the T3 backfill, plus a final summary with total time and actual rows stored. Previously the backfill was silent for many minutes on large repos.
|
|
18
|
+
- **`CatalogTaxonomy._paginated_get`** + **`_batched_upsert`** helpers: wrap ChromaDB calls with the 300-record per-call cap (`MAX_QUERY_RESULTS` / `MAX_RECORDS_PER_WRITE`).
|
|
19
|
+
- **CLAUDE.md "External Service Limits" section**: documents ChromaDB Cloud + Voyage AI quotas with a reference table. Mandatory consult before any new ChromaDB call.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **`project_against` paginated `coll.get()`**: `_PAGE = 2000` exceeded the ChromaDB Cloud Get quota of 300, causing `nx taxonomy project` to fail on real cloud collections. Now `_PAGE = 300` with paginated source-collection fetch via `_paginated_get`.
|
|
24
|
+
- **4 unbounded `coll.get()` calls** in `catalog_taxonomy.py` (`_discover_cross_links`, `project_against` centroid filter, `rebuild_taxonomy` rebuild + cleanup paths) wrapped in `_paginated_get` to avoid OOM and quota errors at scale.
|
|
25
|
+
- **3 `centroid_coll.upsert()` sites** wrapped in `_batched_upsert` (defensive against `MAX_RECORDS_PER_WRITE = 300`).
|
|
26
|
+
- **`rebuild_taxonomy` cleanup**: paginated GET + batched DELETE so collections with >300 centroids don't fail rebuild.
|
|
27
|
+
- **`nx taxonomy links` invisible cross-collection links**: command queried `compute_topic_links` (catalog-derived only) and ignored the `topic_links` table. Cross-collection projection links written by `_discover_cross_links` and `generate_cooccurrence_links` were invisible. Now displays all rows in `topic_links` with `[collection]` prefix on each topic. New `--refresh` flag re-runs catalog-derived computation explicitly.
|
|
28
|
+
- **`backfill_projection` misleading count**: reported "X assignments" using the per-call attempt count, but `INSERT OR IGNORE` deduplicates. Now reports "X stored (Y attempted)" using `COUNT(*) FROM topic_assignments WHERE assigned_by = 'projection'`.
|
|
29
|
+
- **Plugin/CLI version mismatch UX**: when the nx plugin is upgraded but the conexus CLI is not, the `nx upgrade --auto` SessionStart hook would print a cryptic Click error. Now prints a helpful message: `nx plugin requires conexus >= 4.2.0 — run: uv tool upgrade conexus`.
|
|
30
|
+
|
|
9
31
|
## [4.2.0] - 2026-04-14
|
|
10
32
|
|
|
11
33
|
### Added
|
|
@@ -179,6 +179,28 @@ tests/ # pytest suite (unit + integration + e2e/)
|
|
|
179
179
|
docs/ # Documentation (architecture.md is the module map)
|
|
180
180
|
```
|
|
181
181
|
|
|
182
|
+
## External Service Limits — CHECK BEFORE EVERY CALL
|
|
183
|
+
|
|
184
|
+
**ALWAYS** consult `src/nexus/db/chroma_quotas.py` (the `QUOTAS` dataclass and `QuotaValidator`) before writing any ChromaDB call. Violating these at runtime produces `ChromaError: Quota exceeded` — costly to debug, embarrassing in release.
|
|
185
|
+
|
|
186
|
+
**ChromaDB Cloud free-tier caps** (single source of truth: `chroma_quotas.py`):
|
|
187
|
+
|
|
188
|
+
| Operation | Limit | Notes |
|
|
189
|
+
|-----------|-------|-------|
|
|
190
|
+
| `coll.get(limit=N)` | N ≤ 300 | Same cap as queries. `_PAGE = 300` max for pagination |
|
|
191
|
+
| `coll.query(n_results=N)` | N ≤ 300 | `MAX_QUERY_RESULTS` |
|
|
192
|
+
| `coll.upsert/add(ids=[...])` | ≤ 300 records | `MAX_RECORDS_PER_WRITE` |
|
|
193
|
+
| Concurrent reads per coll | ≤ 10 | `MAX_CONCURRENT_READS` |
|
|
194
|
+
| Concurrent writes per coll | ≤ 10 | `MAX_CONCURRENT_WRITES` |
|
|
195
|
+
| Document size | ≤ 16384 bytes | `MAX_DOCUMENT_BYTES` (use `SAFE_CHUNK_BYTES = 12288`) |
|
|
196
|
+
| Query string | ≤ 256 chars | `MAX_QUERY_STRING_CHARS` |
|
|
197
|
+
| `where` predicates | ≤ 8 top-level | `MAX_WHERE_PREDICATES` |
|
|
198
|
+
| Embedding dims | ≤ 4096 | `MAX_EMBEDDING_DIMENSIONS` |
|
|
199
|
+
|
|
200
|
+
**Voyage AI**: `voyage-3` / `voyage-code-3` / `voyage-context-3` = 1024 dims, 32k tokens/request. Batch requests up to 128 inputs. Use `nexus.retry._voyage_with_retry` for transient failure handling.
|
|
201
|
+
|
|
202
|
+
**Rule of thumb**: paginating through a large ChromaDB collection requires `limit ≤ 300` per call. When fetching N documents, use `offset += 300` in a loop. `MAX_RECORDS_PER_WRITE = 300` means upsert batches must also be capped.
|
|
203
|
+
|
|
182
204
|
## Development Conventions
|
|
183
205
|
|
|
184
206
|
- **Python 3.12+**: use `match/case`, `tomllib`, `typing.Protocol`, walrus operator freely
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conexus
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.2
|
|
4
4
|
Summary: Self-hosted semantic search and knowledge management for LLM-driven development
|
|
5
5
|
Project-URL: Homepage, https://github.com/Hellblazer/nexus
|
|
6
6
|
Project-URL: Repository, https://github.com/Hellblazer/nexus
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nx",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.2",
|
|
4
4
|
"description": "Self-hosted three-tier knowledge management with specialized agents, analytical query pipelines, semantic search, and RDR decision tracking for Claude Code.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Hal Hildebrand",
|
|
@@ -6,6 +6,14 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [4.2.2] - 2026-04-14
|
|
10
|
+
|
|
11
|
+
(v4.2.1 was tagged but never published due to a CLI test failure. v4.2.2 supersedes it.)
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **SessionStart hook fallback for old CLI**: when `nx upgrade --auto` fails (CLI < 4.2.0 doesn't have the upgrade command), the hook now prints `nx plugin requires conexus >= 4.2.0 — run: uv tool upgrade conexus` to stderr instead of the raw Click error.
|
|
16
|
+
|
|
9
17
|
## [4.2.0] - 2026-04-14
|
|
10
18
|
|
|
11
19
|
### Added
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "conexus"
|
|
7
|
-
version = "4.2.
|
|
7
|
+
version = "4.2.2"
|
|
8
8
|
description = "Self-hosted semantic search and knowledge management for LLM-driven development"
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.12,<3.14"
|
|
@@ -756,27 +756,64 @@ def compute_topic_links(
|
|
|
756
756
|
|
|
757
757
|
@taxonomy.command("links")
|
|
758
758
|
@click.option("--collection", "-c", default="", help="Filter by collection")
|
|
759
|
-
|
|
760
|
-
""
|
|
759
|
+
@click.option(
|
|
760
|
+
"--refresh", is_flag=True,
|
|
761
|
+
help="Recompute catalog-derived links before displaying (requires catalog).",
|
|
762
|
+
)
|
|
763
|
+
def links_cmd(collection: str, refresh: bool) -> None:
|
|
764
|
+
"""Show all inter-topic relationships in topic_links.
|
|
765
|
+
|
|
766
|
+
Includes cross-collection projection links from RDR-075 (link_types
|
|
767
|
+
contains 'projection' or 'cooccurrence') AND catalog-derived links
|
|
768
|
+
from compute_topic_links (link_types contains 'cites', 'implements',
|
|
769
|
+
etc.). Use --refresh to recompute catalog-derived links first.
|
|
770
|
+
"""
|
|
761
771
|
with _T2Database(_default_db_path()) as db:
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
772
|
+
if refresh:
|
|
773
|
+
catalog = _try_load_catalog()
|
|
774
|
+
if catalog is None:
|
|
775
|
+
click.echo("No catalog initialized — skipping --refresh.")
|
|
776
|
+
else:
|
|
777
|
+
compute_topic_links(
|
|
778
|
+
db.taxonomy, catalog, collection=collection, persist=True,
|
|
779
|
+
)
|
|
766
780
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
781
|
+
# Display all rows in topic_links, joined with topic labels
|
|
782
|
+
if collection:
|
|
783
|
+
rows = db.taxonomy.conn.execute(
|
|
784
|
+
"SELECT t1.label, t1.collection, t2.label, t2.collection, "
|
|
785
|
+
" tl.link_count, tl.link_types "
|
|
786
|
+
"FROM topic_links tl "
|
|
787
|
+
"JOIN topics t1 ON tl.from_topic_id = t1.id "
|
|
788
|
+
"JOIN topics t2 ON tl.to_topic_id = t2.id "
|
|
789
|
+
"WHERE t1.collection = ? OR t2.collection = ? "
|
|
790
|
+
"ORDER BY tl.link_count DESC",
|
|
791
|
+
(collection, collection),
|
|
792
|
+
).fetchall()
|
|
793
|
+
else:
|
|
794
|
+
rows = db.taxonomy.conn.execute(
|
|
795
|
+
"SELECT t1.label, t1.collection, t2.label, t2.collection, "
|
|
796
|
+
" tl.link_count, tl.link_types "
|
|
797
|
+
"FROM topic_links tl "
|
|
798
|
+
"JOIN topics t1 ON tl.from_topic_id = t1.id "
|
|
799
|
+
"JOIN topics t2 ON tl.to_topic_id = t2.id "
|
|
800
|
+
"ORDER BY tl.link_count DESC"
|
|
801
|
+
).fetchall()
|
|
802
|
+
|
|
803
|
+
if not rows:
|
|
771
804
|
click.echo("No topic links found.")
|
|
772
805
|
return
|
|
773
806
|
|
|
774
|
-
click.echo(f"Topic relationships ({len(
|
|
775
|
-
for
|
|
776
|
-
|
|
807
|
+
click.echo(f"Topic relationships ({len(rows)} pairs):\n")
|
|
808
|
+
for from_label, from_coll, to_label, to_coll, count, types_json in rows:
|
|
809
|
+
try:
|
|
810
|
+
import json as _json
|
|
811
|
+
types_str = ", ".join(_json.loads(types_json))
|
|
812
|
+
except Exception:
|
|
813
|
+
types_str = types_json
|
|
777
814
|
click.echo(
|
|
778
|
-
f" {
|
|
779
|
-
f" ({
|
|
815
|
+
f" [{from_coll}] {from_label} <-> [{to_coll}] {to_label}"
|
|
816
|
+
f" ({count} links: {types_str})"
|
|
780
817
|
)
|
|
781
818
|
|
|
782
819
|
|
|
@@ -42,10 +42,11 @@ def _current_version() -> str:
|
|
|
42
42
|
@click.option("--dry-run", is_flag=True, help="List pending migrations without executing (creates base tables if absent).")
|
|
43
43
|
@click.option("--force", is_flag=True, help="Reset version gate and re-run all migrations.")
|
|
44
44
|
@click.option("--auto", "auto_mode", is_flag=True, help="Quiet mode for hook invocation (T2 only, exit 0 always).")
|
|
45
|
-
|
|
45
|
+
@click.option("--skip-t3", is_flag=True, help="Skip T3 upgrade steps (e.g., cross-collection projection backfill). Useful for fast T2-only migrations.")
|
|
46
|
+
def upgrade(dry_run: bool, force: bool, auto_mode: bool, skip_t3: bool) -> None:
|
|
46
47
|
"""Run pending database migrations and upgrade steps."""
|
|
47
48
|
try:
|
|
48
|
-
_run_upgrade(dry_run=dry_run, force=force, auto_mode=auto_mode)
|
|
49
|
+
_run_upgrade(dry_run=dry_run, force=force, auto_mode=auto_mode, skip_t3=skip_t3)
|
|
49
50
|
except Exception:
|
|
50
51
|
if auto_mode:
|
|
51
52
|
_log.warning("upgrade_auto_error", exc_info=True)
|
|
@@ -53,7 +54,7 @@ def upgrade(dry_run: bool, force: bool, auto_mode: bool) -> None:
|
|
|
53
54
|
raise
|
|
54
55
|
|
|
55
56
|
|
|
56
|
-
def _run_upgrade(*, dry_run: bool, force: bool, auto_mode: bool) -> None:
|
|
57
|
+
def _run_upgrade(*, dry_run: bool, force: bool, auto_mode: bool, skip_t3: bool = False) -> None:
|
|
57
58
|
from pathlib import Path
|
|
58
59
|
|
|
59
60
|
db_path = _db_path()
|
|
@@ -90,9 +91,9 @@ def _run_upgrade(*, dry_run: bool, force: bool, auto_mode: bool) -> None:
|
|
|
90
91
|
and _parse_version(m.introduced) <= current_t
|
|
91
92
|
]
|
|
92
93
|
|
|
93
|
-
# Compute pending T3 steps (skip in auto mode)
|
|
94
|
+
# Compute pending T3 steps (skip in auto mode or when --skip-t3)
|
|
94
95
|
pending_t3 = []
|
|
95
|
-
if not auto_mode:
|
|
96
|
+
if not auto_mode and not skip_t3:
|
|
96
97
|
pending_t3 = [
|
|
97
98
|
s
|
|
98
99
|
for s in T3_UPGRADES
|
|
@@ -109,7 +110,7 @@ def _run_upgrade(*, dry_run: bool, force: bool, auto_mode: bool) -> None:
|
|
|
109
110
|
for m in pending_t2:
|
|
110
111
|
click.echo(f" T2: [{m.introduced}] {m.name}")
|
|
111
112
|
for s in pending_t3:
|
|
112
|
-
click.echo(f" T3: [{s.introduced}] {s.name}")
|
|
113
|
+
click.echo(f" T3: [{s.introduced}] {s.name} (heavy — skip with --skip-t3)")
|
|
113
114
|
return
|
|
114
115
|
|
|
115
116
|
# Execute T2 migrations
|
|
@@ -311,26 +311,39 @@ def backfill_projection(t3_db: Any, taxonomy: Any) -> None:
|
|
|
311
311
|
collections' centroids and stores assignments with ``assigned_by='projection'``.
|
|
312
312
|
Then generates co-occurrence topic links.
|
|
313
313
|
|
|
314
|
+
**Heavy operation** — scales O(collections²) with each pair requiring
|
|
315
|
+
paginated ChromaDB fetches. For a repo with N collections, expect
|
|
316
|
+
N*(N-1) projection calls. Prints per-collection progress to stderr.
|
|
317
|
+
|
|
314
318
|
RDR-075 RF-11. Idempotent via ``INSERT OR IGNORE`` in ``assign_topic``.
|
|
315
319
|
"""
|
|
320
|
+
import sys
|
|
321
|
+
import time
|
|
322
|
+
|
|
316
323
|
import structlog
|
|
317
324
|
|
|
318
325
|
log = structlog.get_logger()
|
|
319
326
|
|
|
320
|
-
# Find all collections with existing topics
|
|
321
327
|
collections = taxonomy.get_distinct_collections()
|
|
322
|
-
|
|
323
328
|
if not collections:
|
|
324
329
|
log.info("backfill_projection_skip", reason="no topics discovered yet")
|
|
325
330
|
return
|
|
326
331
|
|
|
327
|
-
|
|
332
|
+
n = len(collections)
|
|
333
|
+
print(
|
|
334
|
+
f" Backfilling projection across {n} collections "
|
|
335
|
+
f"(~{n * (n - 1)} projection calls).",
|
|
336
|
+
file=sys.stderr,
|
|
337
|
+
)
|
|
338
|
+
log.info("backfill_projection_start", collections=n)
|
|
328
339
|
total_assigned = 0
|
|
340
|
+
total_start = time.monotonic()
|
|
329
341
|
|
|
330
|
-
for src in collections:
|
|
342
|
+
for i, src in enumerate(collections, 1):
|
|
331
343
|
targets = [c for c in collections if c != src]
|
|
332
344
|
if not targets:
|
|
333
345
|
continue
|
|
346
|
+
t0 = time.monotonic()
|
|
334
347
|
try:
|
|
335
348
|
result = taxonomy.project_against(
|
|
336
349
|
src, targets, t3_db._client, threshold=0.85,
|
|
@@ -339,16 +352,42 @@ def backfill_projection(t3_db: Any, taxonomy: Any) -> None:
|
|
|
339
352
|
for doc_id, topic_id in assignments:
|
|
340
353
|
taxonomy.assign_topic(doc_id, topic_id, assigned_by="projection")
|
|
341
354
|
total_assigned += len(assignments)
|
|
342
|
-
|
|
343
|
-
|
|
355
|
+
elapsed = time.monotonic() - t0
|
|
356
|
+
print(
|
|
357
|
+
f" [{i}/{n}] {src}: "
|
|
358
|
+
f"{result.get('total_chunks', 0)} chunks, "
|
|
359
|
+
f"{len(result.get('matched_topics', []))} matches, "
|
|
360
|
+
f"{len(assignments)} attempted ({elapsed:.1f}s)",
|
|
361
|
+
file=sys.stderr,
|
|
362
|
+
)
|
|
363
|
+
except Exception as e:
|
|
364
|
+
log.warning("backfill_projection_collection_failed",
|
|
365
|
+
collection=src, exc_info=True)
|
|
366
|
+
print(f" [{i}/{n}] {src}: SKIPPED ({type(e).__name__})",
|
|
367
|
+
file=sys.stderr)
|
|
344
368
|
|
|
345
369
|
# Generate co-occurrence links from the new projection assignments
|
|
370
|
+
print(" Generating co-occurrence topic links...", file=sys.stderr)
|
|
346
371
|
try:
|
|
347
|
-
taxonomy.generate_cooccurrence_links()
|
|
372
|
+
link_count = taxonomy.generate_cooccurrence_links()
|
|
373
|
+
print(f" Generated {link_count} co-occurrence links.", file=sys.stderr)
|
|
348
374
|
except Exception:
|
|
349
|
-
log.
|
|
350
|
-
|
|
351
|
-
|
|
375
|
+
log.warning("backfill_cooccurrence_failed", exc_info=True)
|
|
376
|
+
print(" Co-occurrence link generation: SKIPPED", file=sys.stderr)
|
|
377
|
+
|
|
378
|
+
total_elapsed = time.monotonic() - total_start
|
|
379
|
+
# Count actual rows written (INSERT OR IGNORE deduplicates; the per-call
|
|
380
|
+
# 'attempted' counts may exceed actual writes).
|
|
381
|
+
actual_written = taxonomy.conn.execute(
|
|
382
|
+
"SELECT COUNT(*) FROM topic_assignments WHERE assigned_by = 'projection'"
|
|
383
|
+
).fetchone()[0]
|
|
384
|
+
print(
|
|
385
|
+
f" Backfill complete: {actual_written} projection assignments stored "
|
|
386
|
+
f"({total_assigned} attempted) in {total_elapsed:.1f}s across {n} collections.",
|
|
387
|
+
file=sys.stderr,
|
|
388
|
+
)
|
|
389
|
+
log.info("backfill_projection_complete",
|
|
390
|
+
total_assigned=total_assigned, elapsed_s=round(total_elapsed, 1))
|
|
352
391
|
|
|
353
392
|
|
|
354
393
|
T3_UPGRADES: list[T3UpgradeStep] = [
|
|
@@ -773,7 +773,7 @@ class CatalogTaxonomy:
|
|
|
773
773
|
except Exception:
|
|
774
774
|
pass # Parent centroid may not exist
|
|
775
775
|
if c_ids:
|
|
776
|
-
|
|
776
|
+
self._batched_upsert(centroid_coll, c_ids, c_embs, c_metas)
|
|
777
777
|
|
|
778
778
|
return child_count
|
|
779
779
|
|
|
@@ -1040,9 +1040,9 @@ class CatalogTaxonomy:
|
|
|
1040
1040
|
|
|
1041
1041
|
self.conn.commit()
|
|
1042
1042
|
|
|
1043
|
-
# Upsert centroids outside the lock
|
|
1043
|
+
# Upsert centroids outside the lock (batched at 300 per write)
|
|
1044
1044
|
if c_ids_out:
|
|
1045
|
-
|
|
1045
|
+
self._batched_upsert(centroid_coll, c_ids_out, c_embs, c_metas)
|
|
1046
1046
|
|
|
1047
1047
|
# Cross-collection post-pass: find topic links to other collections'
|
|
1048
1048
|
# centroids (RDR-075 SC-6, Phase 3). Lightweight: only new centroids
|
|
@@ -1109,6 +1109,77 @@ class CatalogTaxonomy:
|
|
|
1109
1109
|
|
|
1110
1110
|
_PROJECTION_THRESHOLD = 0.85
|
|
1111
1111
|
|
|
1112
|
+
@staticmethod
|
|
1113
|
+
def _batched_upsert(
|
|
1114
|
+
coll: Any,
|
|
1115
|
+
ids: list[str],
|
|
1116
|
+
embeddings: list,
|
|
1117
|
+
metadatas: list[dict],
|
|
1118
|
+
*,
|
|
1119
|
+
batch_size: int = 300,
|
|
1120
|
+
) -> None:
|
|
1121
|
+
"""Batched wrapper for ``coll.upsert()`` — caps at ChromaDB Cloud's
|
|
1122
|
+
300-record per-write limit (MAX_RECORDS_PER_WRITE).
|
|
1123
|
+
"""
|
|
1124
|
+
for i in range(0, len(ids), batch_size):
|
|
1125
|
+
j = i + batch_size
|
|
1126
|
+
coll.upsert(
|
|
1127
|
+
ids=ids[i:j],
|
|
1128
|
+
embeddings=embeddings[i:j],
|
|
1129
|
+
metadatas=metadatas[i:j],
|
|
1130
|
+
)
|
|
1131
|
+
|
|
1132
|
+
@staticmethod
|
|
1133
|
+
def _paginated_get(
|
|
1134
|
+
coll: Any,
|
|
1135
|
+
*,
|
|
1136
|
+
where: dict | None = None,
|
|
1137
|
+
include: list[str] | None = None,
|
|
1138
|
+
page_size: int = 300,
|
|
1139
|
+
) -> dict[str, list]:
|
|
1140
|
+
"""Paginated wrapper for ``coll.get()`` — caps at ChromaDB Cloud's
|
|
1141
|
+
300-record limit per call (MAX_QUERY_RESULTS).
|
|
1142
|
+
|
|
1143
|
+
Returns a dict with the same shape as ``coll.get()`` (keys: ids,
|
|
1144
|
+
embeddings, metadatas, documents) but with ALL pages concatenated.
|
|
1145
|
+
"""
|
|
1146
|
+
ids: list[str] = []
|
|
1147
|
+
embeddings: list[Any] = []
|
|
1148
|
+
metadatas: list[Any] = []
|
|
1149
|
+
documents: list[Any] = []
|
|
1150
|
+
offset = 0
|
|
1151
|
+
while True:
|
|
1152
|
+
kwargs: dict[str, Any] = {"limit": page_size, "offset": offset}
|
|
1153
|
+
if where is not None:
|
|
1154
|
+
kwargs["where"] = where
|
|
1155
|
+
if include is not None:
|
|
1156
|
+
kwargs["include"] = include
|
|
1157
|
+
page = coll.get(**kwargs)
|
|
1158
|
+
page_ids = page.get("ids") or []
|
|
1159
|
+
if not page_ids:
|
|
1160
|
+
break
|
|
1161
|
+
ids.extend(page_ids)
|
|
1162
|
+
if "embeddings" in (include or []):
|
|
1163
|
+
page_embs = page.get("embeddings")
|
|
1164
|
+
if page_embs is not None:
|
|
1165
|
+
embeddings.extend(page_embs)
|
|
1166
|
+
if "metadatas" in (include or []):
|
|
1167
|
+
metadatas.extend(page.get("metadatas") or [])
|
|
1168
|
+
if "documents" in (include or []):
|
|
1169
|
+
documents.extend(page.get("documents") or [])
|
|
1170
|
+
if len(page_ids) < page_size:
|
|
1171
|
+
break
|
|
1172
|
+
offset += page_size
|
|
1173
|
+
|
|
1174
|
+
result: dict[str, list] = {"ids": ids}
|
|
1175
|
+
if "embeddings" in (include or []):
|
|
1176
|
+
result["embeddings"] = embeddings
|
|
1177
|
+
if "metadatas" in (include or []):
|
|
1178
|
+
result["metadatas"] = metadatas
|
|
1179
|
+
if "documents" in (include or []):
|
|
1180
|
+
result["documents"] = documents
|
|
1181
|
+
return result
|
|
1182
|
+
|
|
1112
1183
|
def _discover_cross_links(
|
|
1113
1184
|
self,
|
|
1114
1185
|
collection_name: str,
|
|
@@ -1122,9 +1193,10 @@ class CatalogTaxonomy:
|
|
|
1122
1193
|
existing centroids from all OTHER collections. Store matches
|
|
1123
1194
|
above ``_PROJECTION_THRESHOLD`` as ``topic_links`` entries.
|
|
1124
1195
|
"""
|
|
1125
|
-
# Fetch all centroids NOT in this collection
|
|
1196
|
+
# Fetch all centroids NOT in this collection (paginated, ChromaDB cap = 300)
|
|
1126
1197
|
try:
|
|
1127
|
-
other =
|
|
1198
|
+
other = self._paginated_get(
|
|
1199
|
+
centroid_coll,
|
|
1128
1200
|
where={"collection": {"$ne": collection_name}},
|
|
1129
1201
|
include=["embeddings", "metadatas"],
|
|
1130
1202
|
)
|
|
@@ -1327,8 +1399,8 @@ class CatalogTaxonomy:
|
|
|
1327
1399
|
"total_centroids": 0,
|
|
1328
1400
|
}
|
|
1329
1401
|
|
|
1330
|
-
# Paginated fetch
|
|
1331
|
-
_PAGE =
|
|
1402
|
+
# Paginated fetch — ChromaDB Cloud caps Get at 300 (MAX_QUERY_RESULTS)
|
|
1403
|
+
_PAGE = 300
|
|
1332
1404
|
src_ids: list[str] = []
|
|
1333
1405
|
src_emb_pages: list[np.ndarray] = []
|
|
1334
1406
|
offset = 0
|
|
@@ -1372,8 +1444,9 @@ class CatalogTaxonomy:
|
|
|
1372
1444
|
"total_centroids": 0,
|
|
1373
1445
|
}
|
|
1374
1446
|
|
|
1375
|
-
# Filter centroids to target collections
|
|
1376
|
-
ctr_data =
|
|
1447
|
+
# Filter centroids to target collections (paginated, ChromaDB cap = 300)
|
|
1448
|
+
ctr_data = self._paginated_get(
|
|
1449
|
+
centroid_coll,
|
|
1377
1450
|
where={"collection": {"$in": target_collections}},
|
|
1378
1451
|
include=["embeddings", "metadatas"],
|
|
1379
1452
|
)
|
|
@@ -1569,9 +1642,11 @@ class CatalogTaxonomy:
|
|
|
1569
1642
|
}
|
|
1570
1643
|
|
|
1571
1644
|
# Read old centroids from ChromaDB, resolve labels from T2
|
|
1645
|
+
# (paginated, ChromaDB cap = 300)
|
|
1572
1646
|
old_centroid_topic_ids: list[int] = [] # old topic_id per centroid index
|
|
1573
1647
|
try:
|
|
1574
|
-
old_data =
|
|
1648
|
+
old_data = self._paginated_get(
|
|
1649
|
+
centroid_coll,
|
|
1575
1650
|
where={"collection": collection_name},
|
|
1576
1651
|
include=["embeddings", "metadatas"],
|
|
1577
1652
|
)
|
|
@@ -1611,12 +1686,14 @@ class CatalogTaxonomy:
|
|
|
1611
1686
|
)
|
|
1612
1687
|
self.conn.commit()
|
|
1613
1688
|
|
|
1614
|
-
# Clear old centroids from ChromaDB
|
|
1615
|
-
|
|
1689
|
+
# Clear old centroids from ChromaDB. Paginated GET (cap 300) +
|
|
1690
|
+
# batched DELETE (MAX_RECORDS_PER_WRITE = 300).
|
|
1691
|
+
old_centroid_ids = self._paginated_get(
|
|
1692
|
+
centroid_coll,
|
|
1616
1693
|
where={"collection": collection_name},
|
|
1617
1694
|
).get("ids", [])
|
|
1618
|
-
|
|
1619
|
-
centroid_coll.delete(ids=old_centroid_ids)
|
|
1695
|
+
for i in range(0, len(old_centroid_ids), 300):
|
|
1696
|
+
centroid_coll.delete(ids=old_centroid_ids[i:i + 300])
|
|
1620
1697
|
|
|
1621
1698
|
# ── Step 3: HDBSCAN ──────────────────────────────────────────
|
|
1622
1699
|
n = len(doc_ids)
|
|
@@ -1757,9 +1834,9 @@ class CatalogTaxonomy:
|
|
|
1757
1834
|
|
|
1758
1835
|
self.conn.commit()
|
|
1759
1836
|
|
|
1760
|
-
# Upsert new centroids
|
|
1837
|
+
# Upsert new centroids (batched at 300 per write)
|
|
1761
1838
|
if c_ids:
|
|
1762
|
-
|
|
1839
|
+
self._batched_upsert(centroid_coll, c_ids, c_embs, c_metas)
|
|
1763
1840
|
|
|
1764
1841
|
# Record doc count for rebalance tracking
|
|
1765
1842
|
self.record_discover_count(collection_name, n)
|
|
@@ -104,6 +104,64 @@ def _check_python() -> list[HealthResult]:
|
|
|
104
104
|
return [r]
|
|
105
105
|
|
|
106
106
|
|
|
107
|
+
def _check_cli_version() -> list[HealthResult]:
|
|
108
|
+
"""Check whether a newer conexus version is available on PyPI."""
|
|
109
|
+
try:
|
|
110
|
+
from importlib.metadata import version as _pkg_version
|
|
111
|
+
|
|
112
|
+
current = _pkg_version("conexus")
|
|
113
|
+
except Exception:
|
|
114
|
+
return [] # silent — installed version unknown
|
|
115
|
+
|
|
116
|
+
# Check PyPI for latest (3-second timeout, network-tolerant)
|
|
117
|
+
import json
|
|
118
|
+
import urllib.error
|
|
119
|
+
import urllib.request
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
req = urllib.request.Request(
|
|
123
|
+
"https://pypi.org/pypi/conexus/json",
|
|
124
|
+
headers={"User-Agent": f"nx-doctor/{current}"},
|
|
125
|
+
)
|
|
126
|
+
with urllib.request.urlopen(req, timeout=3) as resp:
|
|
127
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
128
|
+
latest = data["info"]["version"]
|
|
129
|
+
except (urllib.error.URLError, OSError, json.JSONDecodeError, KeyError, TimeoutError):
|
|
130
|
+
return [HealthResult(
|
|
131
|
+
label="conexus version",
|
|
132
|
+
ok=True,
|
|
133
|
+
detail=f"{current} (PyPI check skipped — offline?)",
|
|
134
|
+
)]
|
|
135
|
+
|
|
136
|
+
# Compare via tuple parsing
|
|
137
|
+
def _parse(v: str) -> tuple[int, ...]:
|
|
138
|
+
try:
|
|
139
|
+
parts = tuple(int(x) for x in v.split(".")[:3])
|
|
140
|
+
return parts + (0,) * (3 - len(parts))
|
|
141
|
+
except ValueError:
|
|
142
|
+
return (0, 0, 0)
|
|
143
|
+
|
|
144
|
+
cur_t = _parse(current)
|
|
145
|
+
latest_t = _parse(latest)
|
|
146
|
+
|
|
147
|
+
if cur_t >= latest_t:
|
|
148
|
+
return [HealthResult(
|
|
149
|
+
label="conexus version",
|
|
150
|
+
ok=True,
|
|
151
|
+
detail=f"{current} (latest)",
|
|
152
|
+
)]
|
|
153
|
+
|
|
154
|
+
r = HealthResult(
|
|
155
|
+
label="conexus version",
|
|
156
|
+
ok=True, # not fatal — just informational
|
|
157
|
+
detail=f"{current} → {latest} available",
|
|
158
|
+
)
|
|
159
|
+
r.fix_suggestions = [
|
|
160
|
+
f"uv tool upgrade conexus # → {latest}",
|
|
161
|
+
]
|
|
162
|
+
return [r]
|
|
163
|
+
|
|
164
|
+
|
|
107
165
|
def _check_t3_local() -> list[HealthResult]:
|
|
108
166
|
from nexus.config import _default_local_path
|
|
109
167
|
|
|
@@ -637,6 +695,7 @@ def run_health_checks() -> tuple[list[HealthResult], bool]:
|
|
|
637
695
|
results: list[HealthResult] = []
|
|
638
696
|
|
|
639
697
|
results.extend(_check_python())
|
|
698
|
+
results.extend(_check_cli_version())
|
|
640
699
|
|
|
641
700
|
_local = is_local_mode()
|
|
642
701
|
if _local:
|
|
@@ -45,7 +45,9 @@ class TestHooksJson:
|
|
|
45
45
|
for h in data["hooks"]["SessionStart"]
|
|
46
46
|
if "startup" in h["matcher"]
|
|
47
47
|
)
|
|
48
|
-
|
|
48
|
+
# The first hook must start with `nx upgrade --auto`. The 4.2.1
|
|
49
|
+
# fallback appends a helpful error message for older CLIs.
|
|
50
|
+
assert startup_hooks[0]["command"].startswith("nx upgrade --auto")
|
|
49
51
|
assert startup_hooks[0]["timeout"] == 30
|
|
50
52
|
|
|
51
53
|
|