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.
Files changed (546) hide show
  1. {conexus-4.2.0 → conexus-4.2.2}/.claude-plugin/marketplace.json +2 -2
  2. {conexus-4.2.0 → conexus-4.2.2}/CHANGELOG.md +22 -0
  3. {conexus-4.2.0 → conexus-4.2.2}/CLAUDE.md +22 -0
  4. {conexus-4.2.0 → conexus-4.2.2}/PKG-INFO +1 -1
  5. {conexus-4.2.0 → conexus-4.2.2}/nx/.claude-plugin/plugin.json +1 -1
  6. {conexus-4.2.0 → conexus-4.2.2}/nx/CHANGELOG.md +8 -0
  7. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/hooks.json +1 -1
  8. {conexus-4.2.0 → conexus-4.2.2}/pyproject.toml +1 -1
  9. {conexus-4.2.0 → conexus-4.2.2}/sn/.claude-plugin/plugin.json +1 -1
  10. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/taxonomy_cmd.py +52 -15
  11. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/upgrade.py +7 -6
  12. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/migrations.py +49 -10
  13. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/catalog_taxonomy.py +93 -16
  14. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/health.py +59 -0
  15. {conexus-4.2.0 → conexus-4.2.2}/tests/test_phase5_integration.py +3 -1
  16. {conexus-4.2.0 → conexus-4.2.2}/tests/test_taxonomy.py +20 -26
  17. {conexus-4.2.0 → conexus-4.2.2}/tests/test_upgrade_cmd.py +21 -5
  18. {conexus-4.2.0 → conexus-4.2.2}/tests/test_upgrade_e2e.py +9 -3
  19. {conexus-4.2.0 → conexus-4.2.2}/uv.lock +1 -1
  20. {conexus-4.2.0 → conexus-4.2.2}/.beads/.gitignore +0 -0
  21. {conexus-4.2.0 → conexus-4.2.2}/.beads/README.md +0 -0
  22. {conexus-4.2.0 → conexus-4.2.2}/.beads/config.yaml +0 -0
  23. {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/post-checkout +0 -0
  24. {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/post-merge +0 -0
  25. {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/pre-commit +0 -0
  26. {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/pre-push +0 -0
  27. {conexus-4.2.0 → conexus-4.2.2}/.beads/hooks/prepare-commit-msg +0 -0
  28. {conexus-4.2.0 → conexus-4.2.2}/.beads/interactions.jsonl +0 -0
  29. {conexus-4.2.0 → conexus-4.2.2}/.beads/issues.jsonl +0 -0
  30. {conexus-4.2.0 → conexus-4.2.2}/.beads/metadata.json +0 -0
  31. {conexus-4.2.0 → conexus-4.2.2}/.claude/skills/release.md +0 -0
  32. {conexus-4.2.0 → conexus-4.2.2}/.devcontainer/Dockerfile +0 -0
  33. {conexus-4.2.0 → conexus-4.2.2}/.devcontainer/devcontainer.json +0 -0
  34. {conexus-4.2.0 → conexus-4.2.2}/.dockerignore +0 -0
  35. {conexus-4.2.0 → conexus-4.2.2}/.env.example +0 -0
  36. {conexus-4.2.0 → conexus-4.2.2}/.gitattributes +0 -0
  37. {conexus-4.2.0 → conexus-4.2.2}/.github/workflows/ci.yml +0 -0
  38. {conexus-4.2.0 → conexus-4.2.2}/.github/workflows/release.yml +0 -0
  39. {conexus-4.2.0 → conexus-4.2.2}/.gitignore +0 -0
  40. {conexus-4.2.0 → conexus-4.2.2}/.markdownlint.json +0 -0
  41. {conexus-4.2.0 → conexus-4.2.2}/.plans/rdr-066-plan.md +0 -0
  42. {conexus-4.2.0 → conexus-4.2.2}/AGENTS.md +0 -0
  43. {conexus-4.2.0 → conexus-4.2.2}/Formula/nx.rb +0 -0
  44. {conexus-4.2.0 → conexus-4.2.2}/LICENSE +0 -0
  45. {conexus-4.2.0 → conexus-4.2.2}/README.md +0 -0
  46. {conexus-4.2.0 → conexus-4.2.2}/docs/README.md +0 -0
  47. {conexus-4.2.0 → conexus-4.2.2}/docs/architecture.md +0 -0
  48. {conexus-4.2.0 → conexus-4.2.2}/docs/catalog.md +0 -0
  49. {conexus-4.2.0 → conexus-4.2.2}/docs/cli-reference.md +0 -0
  50. {conexus-4.2.0 → conexus-4.2.2}/docs/configuration.md +0 -0
  51. {conexus-4.2.0 → conexus-4.2.2}/docs/contributing.md +0 -0
  52. {conexus-4.2.0 → conexus-4.2.2}/docs/getting-started.md +0 -0
  53. {conexus-4.2.0 → conexus-4.2.2}/docs/historical.md +0 -0
  54. {conexus-4.2.0 → conexus-4.2.2}/docs/logging.md +0 -0
  55. {conexus-4.2.0 → conexus-4.2.2}/docs/mcp-servers.md +0 -0
  56. {conexus-4.2.0 → conexus-4.2.2}/docs/memory-and-tasks.md +0 -0
  57. {conexus-4.2.0 → conexus-4.2.2}/docs/postmortem/2026-03-23-pdf-index-collection-mismatch.md +0 -0
  58. {conexus-4.2.0 → conexus-4.2.2}/docs/postmortem/2026-03-24-pdf-index-fix-not-applied.md +0 -0
  59. {conexus-4.2.0 → conexus-4.2.2}/docs/querying-guide.md +0 -0
  60. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/README.md +0 -0
  61. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/001-rdr-process-validation.md +0 -0
  62. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/002-t2-status-synchronization.md +0 -0
  63. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/010-t1-http-server.md +0 -0
  64. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/011-pdf-ingest-test-coverage.md +0 -0
  65. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/012-pdfplumber-extraction-tier.md +0 -0
  66. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/014-knowledge-base-retrieval-quality.md +0 -0
  67. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/015-indexing-pipeline-rethink.md +0 -0
  68. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/016-ast-chunk-line-range-bug.md +0 -0
  69. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/017-indexing-progress-reporting.md +0 -0
  70. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/018-replace-serve-with-git-hooks.md +0 -0
  71. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/023-agent-tool-permissions-audit.md +0 -0
  72. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/024-rdr-process-guardrails.md +0 -0
  73. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/028-language-registry-unification.md +0 -0
  74. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/029-pipeline-versioning.md +0 -0
  75. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/048-streaming-pdf-pipeline.md +0 -0
  76. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/049-git-backed-catalog.md +0 -0
  77. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/050-catalog-query-integration.md +0 -0
  78. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/051-link-lifecycle.md +0 -0
  79. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/052-catalog-first-query-routing.md +0 -0
  80. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/053-xanadu-fidelity.md +0 -0
  81. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/058-pipeline-orchestration-plan-reuse.md +0 -0
  82. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/060-catalog-path-rationalization-link-usability.md +0 -0
  83. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/063-t2-domain-split.md +0 -0
  84. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/065-close-time-funnel-hardening.md +0 -0
  85. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/067-cross-project-rdr-audit-loop.md +0 -0
  86. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/post-mortem/cce-query-model-mismatch.md +0 -0
  87. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-001-rdr-process-validation.md +0 -0
  88. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-002-t2-status-synchronization.md +0 -0
  89. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-004-four-store-architecture.md +0 -0
  90. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-005-chromadb-cloud-quota-enforcement.md +0 -0
  91. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-006-chunk-size-configuration.md +0 -0
  92. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-007-claude-adoption-session-context-and-search-guidance.md +0 -0
  93. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-008-nx-workflow-integration.md +0 -0
  94. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-009-remove-agentic-and-answer-flags.md +0 -0
  95. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-010-t1-scratch-persistent-bounded-store.md +0 -0
  96. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-011-pdf-ingest-test-coverage.md +0 -0
  97. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-012-pdfplumber-extraction-tier.md +0 -0
  98. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-013-remove-nx-pm-layer.md +0 -0
  99. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-014-knowledge-base-retrieval-quality.md +0 -0
  100. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-015-indexing-pipeline-rethink.md +0 -0
  101. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-016-ast-chunk-line-range-bug.md +0 -0
  102. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-017-indexing-progress-reporting.md +0 -0
  103. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-018-replace-serve-with-git-hooks.md +0 -0
  104. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-019-chromadb-transient-retry.md +0 -0
  105. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-020-voyage-chromadb-read-timeout.md +0 -0
  106. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-021-docling-pdf-extraction.md +0 -0
  107. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-022-memory-delete-command.md +0 -0
  108. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-023-agent-tool-permissions-audit.md +0 -0
  109. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-024-rdr-process-guardrails.md +0 -0
  110. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-025-language-agnostic-agents.md +0 -0
  111. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-026-hybrid-search-fusion.md +0 -0
  112. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-027-search-results-ux.md +0 -0
  113. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-028-code-search-recall.md +0 -0
  114. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-029-pipeline-versioning.md +0 -0
  115. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-030-reliability-hardening.md +0 -0
  116. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-031-collection-portability.md +0 -0
  117. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-032-indexer-decomposition.md +0 -0
  118. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-033-pdf-agent-nx-index-alignment.md +0 -0
  119. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-034-mcp-server-agent-storage.md +0 -0
  120. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-035-plugin-agent-mcp-tool-access.md +0 -0
  121. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-036-post-accept-planning-workflow.md +0 -0
  122. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-037-t3-database-consolidation.md +0 -0
  123. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-038-local-t3-backend.md +0 -0
  124. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-039-claude-code-framework-alignment.md +0 -0
  125. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-040-cce-postmortem-gaps-mcp-enhancement.md +0 -0
  126. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-040-developer-agent-circuit-breaker.md +0 -0
  127. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-041-t1-scratch-inter-agent-context.md +0 -0
  128. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-042-agenticscholar-enhancements.md +0 -0
  129. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-043-plan-enricher-scope.md +0 -0
  130. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-044-math-aware-pdf-extraction.md +0 -0
  131. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-045-post-implementation-verification.md +0 -0
  132. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-046-mineru-server-backed-extraction.md +0 -0
  133. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-047-large-pdf-extraction-resilience.md +0 -0
  134. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-048-streaming-pdf-pipeline.md +0 -0
  135. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-049-consolidation-plan.md +0 -0
  136. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-049-git-backed-catalog.md +0 -0
  137. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-050-knowledge-graph-query-planning.md +0 -0
  138. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-051-link-lifecycle.md +0 -0
  139. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-052-catalog-first-query-routing.md +0 -0
  140. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-053-xanadu-fidelity.md +0 -0
  141. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-054-chunk-boundary-equation-splitting.md +0 -0
  142. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-055-section-type-metadata-quality-scoring.md +0 -0
  143. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-056-search-robustness-result-clustering.md +0 -0
  144. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-057-progressive-formalization-memory-tiers.md +0 -0
  145. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-058-pipeline-orchestration-plan-reuse.md +0 -0
  146. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-059-code-search-embedding-mismatch.md +0 -0
  147. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-060-catalog-path-rationalization-link-usability.md +0 -0
  148. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-061-literature-grounded-search-knowledge-enhancement.md +0 -0
  149. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-062-mcp-interface-tiering.md +0 -0
  150. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-063-t2-domain-split.md +0 -0
  151. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-064-nx-console-embedded-web-ui.md +0 -0
  152. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-065-close-time-funnel-hardening.md +0 -0
  153. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-066-composition-smoke-probe-at-coordinator-beads.md +0 -0
  154. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-067-cross-project-rdr-audit-loop.md +0 -0
  155. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-068-dimensional-contracts-at-enrichment.md +0 -0
  156. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-069-automatic-substantive-critic-at-close.md +0 -0
  157. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-070-incremental-taxonomy-clustered-search.md +0 -0
  158. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-071-query-sanitizer-permanence-mode.md +0 -0
  159. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-072-progressive-context-loading.md +0 -0
  160. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-073-temporal-entity-knowledge-graph.md +0 -0
  161. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-074-permanence-mode.md +0 -0
  162. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-075-cross-collection-topic-projection.md +0 -0
  163. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr/rdr-076-idempotent-upgrade-mechanism.md +0 -0
  164. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr-nexus-integration.md +0 -0
  165. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr-overview.md +0 -0
  166. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr-templates.md +0 -0
  167. {conexus-4.2.0 → conexus-4.2.2}/docs/rdr-workflow.md +0 -0
  168. {conexus-4.2.0 → conexus-4.2.2}/docs/repo-indexing.md +0 -0
  169. {conexus-4.2.0 → conexus-4.2.2}/docs/storage-tiers.md +0 -0
  170. {conexus-4.2.0 → conexus-4.2.2}/docs/taxonomy.md +0 -0
  171. {conexus-4.2.0 → conexus-4.2.2}/docs/xanadu-in-nexus.md +0 -0
  172. {conexus-4.2.0 → conexus-4.2.2}/nx/.mcp.json +0 -0
  173. {conexus-4.2.0 → conexus-4.2.2}/nx/README.md +0 -0
  174. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/CONTEXT_PROTOCOL.md +0 -0
  175. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/ERROR_HANDLING.md +0 -0
  176. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/MAINTENANCE.md +0 -0
  177. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/README.md +0 -0
  178. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/_shared/RELAY_TEMPLATE.md +0 -0
  179. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/analytical-operator.md +0 -0
  180. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/architect-planner.md +0 -0
  181. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/code-review-expert.md +0 -0
  182. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/codebase-deep-analyzer.md +0 -0
  183. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/debugger.md +0 -0
  184. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/deep-analyst.md +0 -0
  185. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/deep-research-synthesizer.md +0 -0
  186. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/developer.md +0 -0
  187. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/knowledge-tidier.md +0 -0
  188. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/pdf-chromadb-processor.md +0 -0
  189. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/plan-auditor.md +0 -0
  190. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/plan-enricher.md +0 -0
  191. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/query-planner.md +0 -0
  192. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/strategic-planner.md +0 -0
  193. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/substantive-critic.md +0 -0
  194. {conexus-4.2.0 → conexus-4.2.2}/nx/agents/test-validator.md +0 -0
  195. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/analyze-code.md +0 -0
  196. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/architecture.md +0 -0
  197. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/create-plan.md +0 -0
  198. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/debug.md +0 -0
  199. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/deep-analysis.md +0 -0
  200. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/enrich-plan.md +0 -0
  201. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/implement.md +0 -0
  202. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/knowledge-tidy.md +0 -0
  203. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/nx-preflight.md +0 -0
  204. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/pdf-process.md +0 -0
  205. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/plan-audit.md +0 -0
  206. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-accept.md +0 -0
  207. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-audit.md +0 -0
  208. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-close.md +0 -0
  209. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-create.md +0 -0
  210. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-gate.md +0 -0
  211. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-list.md +0 -0
  212. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-research.md +0 -0
  213. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/rdr-show.md +0 -0
  214. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/research.md +0 -0
  215. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/review-code.md +0 -0
  216. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/substantive-critique.md +0 -0
  217. {conexus-4.2.0 → conexus-4.2.2}/nx/commands/test-validate.md +0 -0
  218. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/auto-approve-nx-mcp.sh +0 -0
  219. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/divergence-language-guard.sh +0 -0
  220. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/post_compact_hook.sh +0 -0
  221. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/pre_close_verification_hook.sh +0 -0
  222. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/rdr_hook.py +0 -0
  223. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/read_verification_config.py +0 -0
  224. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/session_start_hook.py +0 -0
  225. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/stop_failure_hook.py +0 -0
  226. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/stop_verification_hook.sh +0 -0
  227. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/subagent-start.sh +0 -0
  228. {conexus-4.2.0 → conexus-4.2.2}/nx/hooks/scripts/t2_prefix_scan.py +0 -0
  229. {conexus-4.2.0 → conexus-4.2.2}/nx/registry.yaml +0 -0
  230. {conexus-4.2.0 → conexus-4.2.2}/nx/resources/rdr/README-TEMPLATE.md +0 -0
  231. {conexus-4.2.0 → conexus-4.2.2}/nx/resources/rdr/TEMPLATE.md +0 -0
  232. {conexus-4.2.0 → conexus-4.2.2}/nx/resources/rdr/post-mortem/TEMPLATE.md +0 -0
  233. {conexus-4.2.0 → conexus-4.2.2}/nx/resources/rdr_process/INCIDENT-TEMPLATE.md +0 -0
  234. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/architecture/SKILL.md +0 -0
  235. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/brainstorming-gate/SKILL.md +0 -0
  236. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/catalog/SKILL.md +0 -0
  237. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/cli-controller/SKILL.md +0 -0
  238. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/code-review/SKILL.md +0 -0
  239. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/codebase-analysis/SKILL.md +0 -0
  240. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/composition-probe/SKILL.md +0 -0
  241. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/debugging/SKILL.md +0 -0
  242. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/deep-analysis/SKILL.md +0 -0
  243. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/development/SKILL.md +0 -0
  244. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/enrich-plan/SKILL.md +0 -0
  245. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/finishing-branch/SKILL.md +0 -0
  246. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/git-worktrees/SKILL.md +0 -0
  247. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/knowledge-tidying/SKILL.md +0 -0
  248. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/nexus/SKILL.md +0 -0
  249. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/nexus/reference.md +0 -0
  250. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/orchestration/SKILL.md +0 -0
  251. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/orchestration/reference.md +0 -0
  252. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/pdf-processing/SKILL.md +0 -0
  253. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/plan-validation/SKILL.md +0 -0
  254. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/query/SKILL.md +0 -0
  255. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-accept/SKILL.md +0 -0
  256. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-audit/SKILL.md +0 -0
  257. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-close/SKILL.md +0 -0
  258. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-create/SKILL.md +0 -0
  259. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-gate/SKILL.md +0 -0
  260. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-list/SKILL.md +0 -0
  261. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-research/SKILL.md +0 -0
  262. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/rdr-show/SKILL.md +0 -0
  263. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/receiving-review/SKILL.md +0 -0
  264. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/research-synthesis/SKILL.md +0 -0
  265. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/serena-code-nav/SKILL.md +0 -0
  266. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/strategic-planning/SKILL.md +0 -0
  267. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/substantive-critique/SKILL.md +0 -0
  268. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/test-validation/SKILL.md +0 -0
  269. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/using-nx-skills/SKILL.md +0 -0
  270. {conexus-4.2.0 → conexus-4.2.2}/nx/skills/writing-nx-skills/SKILL.md +0 -0
  271. {conexus-4.2.0 → conexus-4.2.2}/scripts/batch-label-taxonomy.py +0 -0
  272. {conexus-4.2.0 → conexus-4.2.2}/scripts/cron/README.md +0 -0
  273. {conexus-4.2.0 → conexus-4.2.2}/scripts/cron/rdr-audit.crontab +0 -0
  274. {conexus-4.2.0 → conexus-4.2.2}/scripts/cron-rdr-audit.sh +0 -0
  275. {conexus-4.2.0 → conexus-4.2.2}/scripts/launchd/README.md +0 -0
  276. {conexus-4.2.0 → conexus-4.2.2}/scripts/launchd/com.nexus.rdr-audit.PROJECT.plist +0 -0
  277. {conexus-4.2.0 → conexus-4.2.2}/scripts/reinstall-tool.sh +0 -0
  278. {conexus-4.2.0 → conexus-4.2.2}/scripts/smoke-test-taxonomy.py +0 -0
  279. {conexus-4.2.0 → conexus-4.2.2}/sn/.mcp.json +0 -0
  280. {conexus-4.2.0 → conexus-4.2.2}/sn/README.md +0 -0
  281. {conexus-4.2.0 → conexus-4.2.2}/sn/hooks/hooks.json +0 -0
  282. {conexus-4.2.0 → conexus-4.2.2}/sn/hooks/scripts/auto-approve-sn-mcp.sh +0 -0
  283. {conexus-4.2.0 → conexus-4.2.2}/sn/hooks/scripts/mcp-inject.sh +0 -0
  284. {conexus-4.2.0 → conexus-4.2.2}/sn/hooks/scripts/session-start.sh +0 -0
  285. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/__init__.py +0 -0
  286. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/bib_enricher.py +0 -0
  287. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/__init__.py +0 -0
  288. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/auto_linker.py +0 -0
  289. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/catalog.py +0 -0
  290. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/catalog_db.py +0 -0
  291. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/consolidation.py +0 -0
  292. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/link_generator.py +0 -0
  293. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/catalog/tumbler.py +0 -0
  294. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/checkpoint.py +0 -0
  295. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/chunker.py +0 -0
  296. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/classifier.py +0 -0
  297. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/cli.py +0 -0
  298. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/code_indexer.py +0 -0
  299. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/__init__.py +0 -0
  300. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/_helpers.py +0 -0
  301. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/_provision.py +0 -0
  302. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/catalog.py +0 -0
  303. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/collection.py +0 -0
  304. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/config_cmd.py +0 -0
  305. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/console.py +0 -0
  306. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/context_cmd.py +0 -0
  307. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/doctor.py +0 -0
  308. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/enrich.py +0 -0
  309. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/hook.py +0 -0
  310. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/hooks.py +0 -0
  311. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/index.py +0 -0
  312. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/memory.py +0 -0
  313. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/mineru.py +0 -0
  314. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/scratch.py +0 -0
  315. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/search_cmd.py +0 -0
  316. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/commands/store.py +0 -0
  317. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/config.py +0 -0
  318. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/__init__.py +0 -0
  319. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/app.py +0 -0
  320. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/config.py +0 -0
  321. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/__init__.py +0 -0
  322. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/activity.py +0 -0
  323. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/campaigns.py +0 -0
  324. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/health.py +0 -0
  325. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/routes/partials.py +0 -0
  326. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/static/alpine.min.js +0 -0
  327. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/static/console.css +0 -0
  328. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/static/htmx.min.js +0 -0
  329. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/static/pico.min.css +0 -0
  330. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/activity/_detail.html +0 -0
  331. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/activity/_stream.html +0 -0
  332. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/activity/index.html +0 -0
  333. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/base.html +0 -0
  334. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/campaigns/detail.html +0 -0
  335. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/campaigns/index.html +0 -0
  336. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/health/_cards.html +0 -0
  337. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/templates/health/index.html +0 -0
  338. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/console/watchers.py +0 -0
  339. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/context.py +0 -0
  340. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/corpus.py +0 -0
  341. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/__init__.py +0 -0
  342. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/chroma_quotas.py +0 -0
  343. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/local_ef.py +0 -0
  344. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t1.py +0 -0
  345. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/__init__.py +0 -0
  346. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/memory_store.py +0 -0
  347. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/plan_library.py +0 -0
  348. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t2/telemetry.py +0 -0
  349. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/db/t3.py +0 -0
  350. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/doc_indexer.py +0 -0
  351. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/errors.py +0 -0
  352. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/exporter.py +0 -0
  353. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/filters.py +0 -0
  354. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/formatters.py +0 -0
  355. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/frecency.py +0 -0
  356. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/hooks.py +0 -0
  357. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/index_context.py +0 -0
  358. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/indexer.py +0 -0
  359. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/indexer_utils.py +0 -0
  360. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/languages.py +0 -0
  361. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/logging_setup.py +0 -0
  362. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp/__init__.py +0 -0
  363. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp/catalog.py +0 -0
  364. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp/core.py +0 -0
  365. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp_infra.py +0 -0
  366. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/mcp_server.py +0 -0
  367. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/md_chunker.py +0 -0
  368. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/pdf_chunker.py +0 -0
  369. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/pdf_extractor.py +0 -0
  370. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/pipeline_buffer.py +0 -0
  371. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/pipeline_stages.py +0 -0
  372. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/prose_indexer.py +0 -0
  373. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/registry.py +0 -0
  374. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/retry.py +0 -0
  375. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/ripgrep_cache.py +0 -0
  376. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/scoring.py +0 -0
  377. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/search_clusterer.py +0 -0
  378. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/search_engine.py +0 -0
  379. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/session.py +0 -0
  380. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/taxonomy.py +0 -0
  381. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/ttl.py +0 -0
  382. {conexus-4.2.0 → conexus-4.2.2}/src/nexus/types.py +0 -0
  383. {conexus-4.2.0 → conexus-4.2.2}/tests/__init__.py +0 -0
  384. {conexus-4.2.0 → conexus-4.2.2}/tests/__snapshots__/test_search_cmd.ambr +0 -0
  385. {conexus-4.2.0 → conexus-4.2.2}/tests/benchmarks/__init__.py +0 -0
  386. {conexus-4.2.0 → conexus-4.2.2}/tests/benchmarks/corpus.json +0 -0
  387. {conexus-4.2.0 → conexus-4.2.2}/tests/benchmarks/queries.json +0 -0
  388. {conexus-4.2.0 → conexus-4.2.2}/tests/benchmarks/test_retrieval_ndcg.py +0 -0
  389. {conexus-4.2.0 → conexus-4.2.2}/tests/conftest.py +0 -0
  390. {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/auth-login.sh +0 -0
  391. {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/lib.sh +0 -0
  392. {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/run.sh +0 -0
  393. {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/sandbox.sh +0 -0
  394. {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/scenarios/00_debug_load.sh +0 -0
  395. {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/scenarios/01_smoke.sh +0 -0
  396. {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/scenarios/02_sequential_thinking.sh +0 -0
  397. {conexus-4.2.0 → conexus-4.2.2}/tests/e2e/scenarios/03_skills.sh +0 -0
  398. {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/__init__.py +0 -0
  399. {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_permission_request_hooks.py +0 -0
  400. {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_post_compact_hook.py +0 -0
  401. {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_pre_close_verification_hook.py +0 -0
  402. {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_read_verification_config.py +0 -0
  403. {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_stop_failure_hook.py +0 -0
  404. {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_stop_verification_hook.py +0 -0
  405. {conexus-4.2.0 → conexus-4.2.2}/tests/hooks/test_verification_integration.py +0 -0
  406. {conexus-4.2.0 → conexus-4.2.2}/tests/test_activity_stream.py +0 -0
  407. {conexus-4.2.0 → conexus-4.2.2}/tests/test_ast_languages.py +0 -0
  408. {conexus-4.2.0 → conexus-4.2.2}/tests/test_auto_linker.py +0 -0
  409. {conexus-4.2.0 → conexus-4.2.2}/tests/test_backfill_hash.py +0 -0
  410. {conexus-4.2.0 → conexus-4.2.2}/tests/test_bib_enricher.py +0 -0
  411. {conexus-4.2.0 → conexus-4.2.2}/tests/test_campaigns_panel.py +0 -0
  412. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog.py +0 -0
  413. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_backfill.py +0 -0
  414. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_cli.py +0 -0
  415. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_consolidation.py +0 -0
  416. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_db.py +0 -0
  417. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_e2e.py +0 -0
  418. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_git.py +0 -0
  419. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_indexer_hook.py +0 -0
  420. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_jsonl.py +0 -0
  421. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_knowledge_hook.py +0 -0
  422. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_link_generation.py +0 -0
  423. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_links.py +0 -0
  424. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_mcp.py +0 -0
  425. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_path.py +0 -0
  426. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_pdf_hook.py +0 -0
  427. {conexus-4.2.0 → conexus-4.2.2}/tests/test_catalog_prefilter.py +0 -0
  428. {conexus-4.2.0 → conexus-4.2.2}/tests/test_checkpoint.py +0 -0
  429. {conexus-4.2.0 → conexus-4.2.2}/tests/test_chroma_quotas.py +0 -0
  430. {conexus-4.2.0 → conexus-4.2.2}/tests/test_chroma_retry.py +0 -0
  431. {conexus-4.2.0 → conexus-4.2.2}/tests/test_chunker.py +0 -0
  432. {conexus-4.2.0 → conexus-4.2.2}/tests/test_chunker_ast_languages.py +0 -0
  433. {conexus-4.2.0 → conexus-4.2.2}/tests/test_classifier.py +0 -0
  434. {conexus-4.2.0 → conexus-4.2.2}/tests/test_cli_registration.py +0 -0
  435. {conexus-4.2.0 → conexus-4.2.2}/tests/test_collection_cmd.py +0 -0
  436. {conexus-4.2.0 → conexus-4.2.2}/tests/test_config.py +0 -0
  437. {conexus-4.2.0 → conexus-4.2.2}/tests/test_config_cmd.py +0 -0
  438. {conexus-4.2.0 → conexus-4.2.2}/tests/test_console_app.py +0 -0
  439. {conexus-4.2.0 → conexus-4.2.2}/tests/test_console_deps.py +0 -0
  440. {conexus-4.2.0 → conexus-4.2.2}/tests/test_context.py +0 -0
  441. {conexus-4.2.0 → conexus-4.2.2}/tests/test_contradiction_flag.py +0 -0
  442. {conexus-4.2.0 → conexus-4.2.2}/tests/test_corpus.py +0 -0
  443. {conexus-4.2.0 → conexus-4.2.2}/tests/test_distance_thresholds.py +0 -0
  444. {conexus-4.2.0 → conexus-4.2.2}/tests/test_doc_indexer.py +0 -0
  445. {conexus-4.2.0 → conexus-4.2.2}/tests/test_doc_indexer_hash_sync.py +0 -0
  446. {conexus-4.2.0 → conexus-4.2.2}/tests/test_doc_indexer_pagination.py +0 -0
  447. {conexus-4.2.0 → conexus-4.2.2}/tests/test_doctor_cmd.py +0 -0
  448. {conexus-4.2.0 → conexus-4.2.2}/tests/test_doctor_integrity.py +0 -0
  449. {conexus-4.2.0 → conexus-4.2.2}/tests/test_e2e.py +0 -0
  450. {conexus-4.2.0 → conexus-4.2.2}/tests/test_enrich_command.py +0 -0
  451. {conexus-4.2.0 → conexus-4.2.2}/tests/test_exporter.py +0 -0
  452. {conexus-4.2.0 → conexus-4.2.2}/tests/test_formatters.py +0 -0
  453. {conexus-4.2.0 → conexus-4.2.2}/tests/test_frecency.py +0 -0
  454. {conexus-4.2.0 → conexus-4.2.2}/tests/test_git_hooks.py +0 -0
  455. {conexus-4.2.0 → conexus-4.2.2}/tests/test_health.py +0 -0
  456. {conexus-4.2.0 → conexus-4.2.2}/tests/test_health_panel.py +0 -0
  457. {conexus-4.2.0 → conexus-4.2.2}/tests/test_hooks.py +0 -0
  458. {conexus-4.2.0 → conexus-4.2.2}/tests/test_hybrid_boost.py +0 -0
  459. {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_cmd.py +0 -0
  460. {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_lock.py +0 -0
  461. {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_pdf_batch.py +0 -0
  462. {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_rdr_cmd.py +0 -0
  463. {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_reminder.py +0 -0
  464. {conexus-4.2.0 → conexus-4.2.2}/tests/test_index_taxonomy.py +0 -0
  465. {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer.py +0 -0
  466. {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer_chunk_flow.py +0 -0
  467. {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer_e2e.py +0 -0
  468. {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer_modules.py +0 -0
  469. {conexus-4.2.0 → conexus-4.2.2}/tests/test_indexer_utils_repo.py +0 -0
  470. {conexus-4.2.0 → conexus-4.2.2}/tests/test_integration.py +0 -0
  471. {conexus-4.2.0 → conexus-4.2.2}/tests/test_jsonl.py +0 -0
  472. {conexus-4.2.0 → conexus-4.2.2}/tests/test_languages.py +0 -0
  473. {conexus-4.2.0 → conexus-4.2.2}/tests/test_link_generator.py +0 -0
  474. {conexus-4.2.0 → conexus-4.2.2}/tests/test_local_mode.py +0 -0
  475. {conexus-4.2.0 → conexus-4.2.2}/tests/test_logging_setup.py +0 -0
  476. {conexus-4.2.0 → conexus-4.2.2}/tests/test_mcp_concurrency.py +0 -0
  477. {conexus-4.2.0 → conexus-4.2.2}/tests/test_mcp_package.py +0 -0
  478. {conexus-4.2.0 → conexus-4.2.2}/tests/test_mcp_server.py +0 -0
  479. {conexus-4.2.0 → conexus-4.2.2}/tests/test_md_chunker.py +0 -0
  480. {conexus-4.2.0 → conexus-4.2.2}/tests/test_md_chunker_semantic_integrity.py +0 -0
  481. {conexus-4.2.0 → conexus-4.2.2}/tests/test_md_preservation.py +0 -0
  482. {conexus-4.2.0 → conexus-4.2.2}/tests/test_memory.py +0 -0
  483. {conexus-4.2.0 → conexus-4.2.2}/tests/test_memory_consolidation.py +0 -0
  484. {conexus-4.2.0 → conexus-4.2.2}/tests/test_migrations.py +0 -0
  485. {conexus-4.2.0 → conexus-4.2.2}/tests/test_mineru_cmd.py +0 -0
  486. {conexus-4.2.0 → conexus-4.2.2}/tests/test_mineru_extractor.py +0 -0
  487. {conexus-4.2.0 → conexus-4.2.2}/tests/test_minified_chunking.py +0 -0
  488. {conexus-4.2.0 → conexus-4.2.2}/tests/test_overfetch_pipeline.py +0 -0
  489. {conexus-4.2.0 → conexus-4.2.2}/tests/test_p0_regressions.py +0 -0
  490. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_chunker.py +0 -0
  491. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_chunker_integration.py +0 -0
  492. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_e2e.py +0 -0
  493. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_extractor.py +0 -0
  494. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_extractor_integration.py +0 -0
  495. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_extractor_normalization.py +0 -0
  496. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_extractor_server.py +0 -0
  497. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pdf_subsystem.py +0 -0
  498. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pipeline_buffer.py +0 -0
  499. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pipeline_stages.py +0 -0
  500. {conexus-4.2.0 → conexus-4.2.2}/tests/test_pipeline_version.py +0 -0
  501. {conexus-4.2.0 → conexus-4.2.2}/tests/test_plan_library.py +0 -0
  502. {conexus-4.2.0 → conexus-4.2.2}/tests/test_plugin.py +0 -0
  503. {conexus-4.2.0 → conexus-4.2.2}/tests/test_plugin_install.py +0 -0
  504. {conexus-4.2.0 → conexus-4.2.2}/tests/test_plugin_structure.py +0 -0
  505. {conexus-4.2.0 → conexus-4.2.2}/tests/test_post_store_hook.py +0 -0
  506. {conexus-4.2.0 → conexus-4.2.2}/tests/test_ppid_chain_hypothesis.py +0 -0
  507. {conexus-4.2.0 → conexus-4.2.2}/tests/test_provision.py +0 -0
  508. {conexus-4.2.0 → conexus-4.2.2}/tests/test_quality_score.py +0 -0
  509. {conexus-4.2.0 → conexus-4.2.2}/tests/test_query_sanitizer.py +0 -0
  510. {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr052_verification.py +0 -0
  511. {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr053_verification.py +0 -0
  512. {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr_audit_incident_template.py +0 -0
  513. {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr_audit_scheduling.py +0 -0
  514. {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr_audit_skill.py +0 -0
  515. {conexus-4.2.0 → conexus-4.2.2}/tests/test_rdr_close_gate.py +0 -0
  516. {conexus-4.2.0 → conexus-4.2.2}/tests/test_registry.py +0 -0
  517. {conexus-4.2.0 → conexus-4.2.2}/tests/test_relevance_log.py +0 -0
  518. {conexus-4.2.0 → conexus-4.2.2}/tests/test_ripgrep_cache.py +0 -0
  519. {conexus-4.2.0 → conexus-4.2.2}/tests/test_schema.py +0 -0
  520. {conexus-4.2.0 → conexus-4.2.2}/tests/test_scoring.py +0 -0
  521. {conexus-4.2.0 → conexus-4.2.2}/tests/test_scratch.py +0 -0
  522. {conexus-4.2.0 → conexus-4.2.2}/tests/test_scratch_cmd.py +0 -0
  523. {conexus-4.2.0 → conexus-4.2.2}/tests/test_search_clusterer.py +0 -0
  524. {conexus-4.2.0 → conexus-4.2.2}/tests/test_search_clustering_integration.py +0 -0
  525. {conexus-4.2.0 → conexus-4.2.2}/tests/test_search_cmd.py +0 -0
  526. {conexus-4.2.0 → conexus-4.2.2}/tests/test_search_engine.py +0 -0
  527. {conexus-4.2.0 → conexus-4.2.2}/tests/test_session.py +0 -0
  528. {conexus-4.2.0 → conexus-4.2.2}/tests/test_session_propagation_hypotheses.py +0 -0
  529. {conexus-4.2.0 → conexus-4.2.2}/tests/test_silent_error_logging.py +0 -0
  530. {conexus-4.2.0 → conexus-4.2.2}/tests/test_sn_plugin.py +0 -0
  531. {conexus-4.2.0 → conexus-4.2.2}/tests/test_store_cmd.py +0 -0
  532. {conexus-4.2.0 → conexus-4.2.2}/tests/test_structlog_events.py +0 -0
  533. {conexus-4.2.0 → conexus-4.2.2}/tests/test_t1.py +0 -0
  534. {conexus-4.2.0 → conexus-4.2.2}/tests/test_t2.py +0 -0
  535. {conexus-4.2.0 → conexus-4.2.2}/tests/test_t2_concurrency.py +0 -0
  536. {conexus-4.2.0 → conexus-4.2.2}/tests/test_t2_prefix_scan.py +0 -0
  537. {conexus-4.2.0 → conexus-4.2.2}/tests/test_t3.py +0 -0
  538. {conexus-4.2.0 → conexus-4.2.2}/tests/test_t3_hnsw_ef.py +0 -0
  539. {conexus-4.2.0 → conexus-4.2.2}/tests/test_t3_quota_enforcement.py +0 -0
  540. {conexus-4.2.0 → conexus-4.2.2}/tests/test_table_extraction.py +0 -0
  541. {conexus-4.2.0 → conexus-4.2.2}/tests/test_taxonomy_e2e.py +0 -0
  542. {conexus-4.2.0 → conexus-4.2.2}/tests/test_ttl.py +0 -0
  543. {conexus-4.2.0 → conexus-4.2.2}/tests/test_tumbler.py +0 -0
  544. {conexus-4.2.0 → conexus-4.2.2}/tests/test_tuning_config.py +0 -0
  545. {conexus-4.2.0 → conexus-4.2.2}/tests/test_verify_multiprobe.py +0 -0
  546. {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.0"
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.0"
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.0
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.0",
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
@@ -6,7 +6,7 @@
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
9
- "command": "nx upgrade --auto",
9
+ "command": "nx upgrade --auto 2>/dev/null || echo 'nx plugin requires conexus >= 4.2.0 — run: uv tool upgrade conexus' >&2",
10
10
  "timeout": 30
11
11
  },
12
12
  {
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "conexus"
7
- version = "4.2.0"
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"
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "sn",
3
- "version": "4.2.0",
3
+ "version": "4.2.2",
4
4
  "description": "Injects Serena and Context7 MCP tool usage guidance into subagents via SubagentStart hook."
5
5
  }
@@ -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
- def links_cmd(collection: str) -> None:
760
- """Show inter-topic relationships derived from catalog links."""
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
- catalog = _try_load_catalog()
763
- if catalog is None:
764
- click.echo("No catalog initialized. Run `nx catalog setup` first.")
765
- return
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
- result = compute_topic_links(
768
- db.taxonomy, catalog, collection=collection, persist=True,
769
- )
770
- if not result:
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(result)} pairs):\n")
775
- for pair in result:
776
- types_str = ", ".join(pair["link_types"])
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" {pair['from_topic']} <-> {pair['to_topic']}"
779
- f" ({pair['link_count']} links: {types_str})"
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
- def upgrade(dry_run: bool, force: bool, auto_mode: bool) -> None:
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
- log.info("backfill_projection_start", collections=len(collections))
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
- except Exception:
343
- log.debug("backfill_projection_collection_failed", collection=src, exc_info=True)
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.debug("backfill_cooccurrence_failed", exc_info=True)
350
-
351
- log.info("backfill_projection_complete", total_assigned=total_assigned)
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
- centroid_coll.upsert(ids=c_ids, embeddings=c_embs, metadatas=c_metas)
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
- centroid_coll.upsert(ids=c_ids_out, embeddings=c_embs, metadatas=c_metas)
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 = centroid_coll.get(
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 to avoid OOM on large collections
1331
- _PAGE = 2000
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 = centroid_coll.get(
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 = centroid_coll.get(
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
- old_centroid_ids = centroid_coll.get(
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
- if old_centroid_ids:
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
- centroid_coll.upsert(ids=c_ids, embeddings=c_embs, metadatas=c_metas)
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
- assert startup_hooks[0]["command"] == "nx upgrade --auto"
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