Skip to content

Commit 14984a8

Browse files
authored
Merge pull request #1413 from Hellblazer/release/v6.14.0
release: conexus 6.14.0
2 parents dc7420f + 8129ddb commit 14984a8

200 files changed

Lines changed: 15168 additions & 2687 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.beads/interactions.jsonl

Lines changed: 31 additions & 0 deletions
Large diffs are not rendered by default.

.claude-plugin/marketplace.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@
1111
"source": "git-subdir",
1212
"url": "https://github.com/Hellblazer/nexus.git",
1313
"path": "conexus",
14-
"ref": "v6.13.1"
14+
"ref": "v6.14.0"
1515
},
1616
"description": "Self-hosted three-tier knowledge management with 13 specialized agents, plan-centric retrieval via nx_answer, semantic search, and RDR decision tracking for Claude Code.",
17-
"version": "6.13.1"
17+
"version": "6.14.0"
1818
},
1919
{
2020
"name": "sn",
2121
"source": {
2222
"source": "git-subdir",
2323
"url": "https://github.com/Hellblazer/nexus.git",
2424
"path": "sn",
25-
"ref": "v6.13.1"
25+
"ref": "v6.14.0"
2626
},
2727
"description": "Injects Serena and Context7 MCP tool usage guidance into subagents via SubagentStart hook.",
28-
"version": "6.13.1"
28+
"version": "6.14.0"
2929
}
3030
]
3131
}

.claude/skills/engine-release/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ The Java CI (`service-ci.yml`) is **advisory** — it does not block auto-merge
5151
tests/e2e/migration-rehearsal/run.sh --guided # local -Ob native build → nx guided-upgrade MVV
5252
```
5353

54-
Must end `GUIDED-UPGRADE MVV PASSED`.
54+
Must end `GUIDED LAND-THEN-TRANSFORM GATE PASSED` (marker renamed at the RDR-180 gate rewrite, nexus-jxizy.10.10).
5555

5656
**Optional but recommended when the cut carries CLI-visible or concurrency-relevant service changes**: also run the candidate shakeout — the full CLI-verb matrix + incremental-index + concurrent-load journey against the SAME locally-built candidate (nexus-h8rf6; born from the 2026-07-03 post-release shakeout, whose findings were all locally discoverable):
5757

.github/workflows/guided-upgrade-mvv.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,11 @@ jobs:
9191
set -euo pipefail
9292
tests/e2e/migration-rehearsal/run.sh --guided 2>&1 | tee guided-mvv.log
9393
# Belt on the harness's own exit code: the success marker must be
94-
# present (a truncated/killed run must not read as green).
95-
grep -q "GUIDED-UPGRADE MVV PASSED" guided-mvv.log
94+
# present (a truncated/killed run must not read as green). Marker
95+
# renamed with the RDR-180 land-then-transform gate rewrite
96+
# (nexus-jxizy.10.10) — the in-container run PASSED on 296cf85e
97+
# while this grep still expected the old string.
98+
grep -q "GUIDED LAND-THEN-TRANSFORM GATE PASSED" guided-mvv.log
9699
97100
- name: Upload run log
98101
if: always()

AGENTS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ Collection prefixes coexist in one T3 database. Always `__` (double underscore)
3939

4040
| Prefix | Embedder | Document identity (catalog) | Chunk natural ID (T3) |
4141
|---|---|---|---|
42-
| `code__*` | `voyage-code-3` | `source_uri` (file path) | `chunk_text_hash[:32]` |
43-
| `docs__*`, `rdr__*` | `voyage-context-3` (CCE) | `source_uri` (file path) | `chunk_text_hash[:32]` |
44-
| `knowledge__*` | `voyage-context-3` | `source_uri` then `title` (fallback for MCP-stored notes) | `chunk_text_hash[:32]` |
42+
| `code__*` | `voyage-code-3` | `source_uri` (file path) | `chunk_text_hash` (full 64-hex; 32 bytes stored — RDR-180) |
43+
| `docs__*`, `rdr__*` | `voyage-context-3` (CCE) | `source_uri` (file path) | `chunk_text_hash` (full 64-hex) |
44+
| `knowledge__*` | `voyage-context-3` | `source_uri` then `title` (fallback for MCP-stored notes) | `chunk_text_hash` (full 64-hex) |
4545

46-
**Catalog/T3 split (RDR-108)**: Catalog Documents are graph nodes addressed by tumblers (`Document.tumbler`); T3 chunks are content-addressed blobs whose Chroma natural ID is `sha256(chunk_text)[:32]`. Document structure (which chashes compose a doc, in what order) lives in the catalog `document_chunks` manifest, not in chunk metadata. The doc-to-chunks join is `documents.tumbler -> document_chunks.doc_id -> document_chunks.chash`; `chash[:32]` is the Chroma natural ID directly, no further lookup. Identical chunk text in the same collection collapses to one T3 row by design; the manifest preserves position via `(doc_id, position)` rows pointing at the shared chash.
46+
**Catalog/T3 split (RDR-108, widths per RDR-180)**: Catalog Documents are graph nodes addressed by tumblers (`Document.tumbler`); T3 chunks are content-addressed blobs whose natural ID is the FULL `sha256(chunk_text)` — 64 lowercase hex on the wire, 32 raw bytes in storage (`bytea`, `octet_length=32`); hex only at boundaries (see `docs/architecture.md` § Chunk identity). Document structure (which chashes compose a doc, in what order) lives in the catalog `document_chunks` manifest, not in chunk metadata. The doc-to-chunks join is `documents.tumbler -> document_chunks.doc_id -> document_chunks.chash`; the chash is the chunk id directly, no further lookup. Identical chunk text in the same collection collapses to one T3 row by design; the manifest preserves position via `(doc_id, position)` rows pointing at the shared chash.
4747

4848
For the full module map, post-store hook contracts, T2 schema, and design heritage see [`docs/architecture.md`](docs/architecture.md). For module-local guidance see the `AGENTS.md` files inside `src/nexus/catalog/`, `src/nexus/db/`, and `src/nexus/mcp/`.
4949

CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,48 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
88

9+
## [6.14.0] - 2026-07-19
10+
11+
Ships with (and requires) engine-service-v0.1.49.
12+
13+
### Changed
14+
15+
- **chash is now the full 32-byte SHA-256, stored as raw bytes** (RDR-180,
16+
epic nexus-jxizy): the chunk content address was historically
17+
`sha256(text)[:32]` — half the digest as hex text — while the citation
18+
grammar advertised the full 64-hex. The producer now emits the full
19+
digest, the engine stores `bytea` with `CHECK (octet_length(chash)=32)`,
20+
and hex (64 lowercase chars) is strictly the interchange form. Requires
21+
the paired RDR-180 engine generation; `nx upgrade`'s new `chash-rekey`
22+
ladder rung performs the freeze-gated per-store cutover (rehash from
23+
stored text, no re-embed) and records every legacy id in the permanent
24+
`chash_alias` map so old 32-hex references stay resolvable forever.
25+
The 32-vs-64 width bug class is structurally eliminated; content
26+
citations (`chash:<64hex>`) now resolve at the full 256 bits they
27+
always claimed.
28+
- **Guided migration is LAND-THEN-TRANSFORM** (RDR-180, nexus-jxizy.10):
29+
the guided upgrade bulk-loads the legacy source into a PG staging schema,
30+
then performs ONE transactional in-DB re-identification + promote —
31+
retiring the per-leg in-flight rewrite class. The pregate width block is
32+
gone: 16-char (GH #1408) and 32-hex legacy stores migrate; a disk
33+
preflight and exact landing manifest run up front; promoted and rekeyed
34+
rows carry `chunk_text_hash` metadata parity at every touch site, so
35+
migrated chunks are immediately citable.
36+
37+
### Fixed
38+
39+
- **A table-rewriting migration now ANALYZEs what it rewrote, in the same
40+
changelog pass** (engine-service-v0.1.49, BUG-0148/conexus-xpg7): the
41+
RDR-180 `ALTER TYPE` boot conversion silently reset planner statistics —
42+
and a rewritten table looks fresh to autovacuum, so autoanalyze may never
43+
re-trigger — degrading sparse-text-gate hybrid queries to ZERO rows while
44+
every health probe stayed green (observed live in the managed cloud,
45+
2026-07-19). The engine floor bump is the delivery vehicle: this is why
46+
6.14.0 requires v0.1.49. Related, benign: any table rewrite rebuilds the
47+
HNSW indexes (graph construction is insertion-order dependent), so
48+
borderline approximate-rank orderings can shift permanently after the
49+
migration — re-baseline external oracles against post-migration serving.
50+
951
## [6.13.1] - 2026-07-18
1052

1153
Ships with (and requires) engine-service-v0.1.47 (unchanged from 6.13.0).

conexus/.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "conexus",
3-
"version": "6.13.1",
3+
"version": "6.14.0",
44
"description": "Self-hosted three-tier knowledge management with plan-centric retrieval (nx_answer), specialized agents, semantic search, and RDR decision tracking for Claude Code.",
55
"author": {
66
"name": "Hal Hildebrand",

conexus/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to the conexus plugin are documented here.
44
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
55
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [6.14.0] - 2026-07-19
8+
9+
- Plugin version aligned with conexus 6.14.0. No plugin-side changes. Root
10+
CHANGELOG: chash is the full 32-byte SHA-256 (RDR-180); guided migration
11+
is land-then-transform; engine pair v0.1.49 ANALYZEs rewritten tables in
12+
the migration pass (BUG-0148).
13+
714
## [6.13.1] - 2026-07-18
815

916
- Plugin version aligned with conexus 6.13.1. No plugin-side changes. Root

docs/architecture.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,48 @@ addressing, the `document_chunks` manifest schema, span formats (`chash:<hex>`
190190
content-addressed spans vs. positional line/char spans), link types, the
191191
migration runbook, and admin/maintenance CLI surface.
192192

193+
### Chunk identity: the canonical chash ([RDR-180](rdr/rdr-180-content-address-chash-binary-32byte.md))
194+
195+
A **chash IS the 32-byte SHA-256 digest of the chunk text** — the full digest,
196+
never truncated. It has exactly two representations, with a hard rule about
197+
which appears where:
198+
199+
- **Storage form: 32 raw bytes.** Postgres `BYTEA` with
200+
`CHECK (octet_length(chash) = 32)`. Content-addressable storage keys on the
201+
*value*, not its rendering; binary makes the width unambiguous (bytes are not
202+
characters) and halves the key width vs hex text.
203+
- **Interchange form: 64 lowercase hex chars.** JSON wire values, the
204+
`chash:[0-9a-f]{64}` citation grammar, CLI display, log lines. Hex belongs on
205+
the wire, never in the key column.
206+
207+
**One encode/decode seam, everywhere.** All conversions between the two forms
208+
go through a single boundary pair per side — nothing else encodes or decodes:
209+
210+
| Side | Storage → interchange | Interchange → storage |
211+
|---|---|---|
212+
| Python client (`chunk_identity.py`) | `to_citation_hex()` | `to_storage_bytes()` |
213+
| Java engine (`db/Chash.java`) | `Chash.toHex()` | `Chash.fromHex()` / `Chash.fromSha256Bytes()` |
214+
215+
Width validation lives inside that seam (the type constructor / the helper),
216+
so a wrong-width value fails loudly at the boundary with the offending length —
217+
never deep inside a transaction.
218+
219+
**Why this is written down** (the bug class this eliminates): historically the
220+
stored chunk id was `sha256(chunk_text).hexdigest()[:32]` — 32 *hex chars* =
221+
128 bits = **half** the digest — while the citation grammar advertised the full
222+
64-hex digest, bridged by silent truncation. "32" meant hex-chars in one place
223+
and bytes in another. The canonical definition above makes the two subsystems
224+
agree at the full 256 bits, by construction.
225+
226+
**Migration status:** the flip is IN this tree (epic `nexus-jxizy`): the
227+
producer emits the full digest, the engine stores bytea, and the
228+
`chash-rekey` ladder rung rekeys existing stores inside the freeze window. For every rehashable
229+
row the legacy 32-hex is the strict prefix of the new 64-hex (same text, same
230+
digest); the persisted `chash_alias` table is the collision-free resolver for
231+
legacy references thereafter (prefix matching only *builds* the map, it is not
232+
the resolver). The table below describes **current** (pre-flip) producer
233+
behavior.
234+
193235
### Metadata field semantics (chunk vs document level)
194236

195237
Two hash fields look similar but mean very different things. Confusing them produces false-positive panic findings (e.g. "94% redundancy across the corpus" turns out to be 94% of chunks share a doc-level hash, which is correct: every chunk of one paper has the same `content_hash`). The table below locks the contract; consult before drawing conclusions from a metadata distribution.
@@ -198,7 +240,7 @@ Two hash fields look similar but mean very different things. Confusing them prod
198240
|---|---|---|---|---|
199241
| `content_hash` | document | `sha256(file_bytes)` | every indexer at register time (`indexer.py:1198`) | document-level dedup; staleness comparison; backup-snapshot identity |
200242
| `chunk_text_hash` | chunk | `sha256(chunk_text)` (full 64 chars) | every indexer per chunk; healed on an upgraded store by the ladder (`nx upgrade`) | content-addressed link spans (`chash:<hex>`); `nx t3 reidentify` natural-ID source (first 32 chars); cross-collection chunk dedup |
201-
| `chunk_text_hash[:32]` | chunk | first 32 chars of the SHA | `nx t3 reidentify` upsert ([RDR-108](rdr/rdr-108-graph-identity-normalization.md) Phase 2) | Chroma natural ID for the chunk; the join key from `document_chunks.chash` |
243+
| `chunk_text_hash` (as chunk id) | chunk | the full SHA (RDR-180) | every indexer via `chunk_identity.chunk_id` | the chunk natural ID and the `document_chunks.chash` join key; the pre-RDR-180 `[:32]` truncation is retired (legacy 32-hex references resolve via `chash_alias`) |
202244
| `source_uri` | document | `file://...` or `x-devonthink-item://<uuid>` etc. | indexer / MCP write paths | persistent URI identity; aspect-extraction routing; audit-membership home detection |
203245
| `source_path` | document | absolute or repo-relative file path | indexer | display + grep targets; legacy path predating `source_uri` |
204246
| `chunk_start_char` / `chunk_end_char` | chunk | char offsets in the source file | indexer per chunk | `chunk:char` span resolution; UI highlight |

docs/cli-reference.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,7 @@ echo "# Cache Strategy" | nx store put - --collection knowledge --title "decisio
10281028
| Subcommand | Description |
10291029
|------------|-------------|
10301030
| `put FILE_OR_DASH` | Store document (use `-` for stdin) |
1031-
| `get DOC_ID` | Retrieve entry by 32-char hex ID (from `nx store list`) |
1031+
| `get DOC_ID` | Retrieve entry by 64-char hex ID (from `nx store list`) |
10321032
| `list` | List stored entries |
10331033
| `delete` | Delete a single entry by ID or title |
10341034
| `export [COLLECTION]` | Export a collection to portable `.nxexp` backup |
@@ -1059,11 +1059,11 @@ echo "# Cache Strategy" | nx store put - --collection knowledge --title "decisio
10591059
| Flag | Description |
10601060
|------|-------------|
10611061
| `-c` / `--collection NAME` | Collection name (required) |
1062-
| `--id ID` | Exact 32-char document ID from `nx store list` |
1062+
| `--id ID` | Exact 64-char document ID from `nx store list` |
10631063
| `--title TITLE` | Exact title metadata match (deletes all matching chunks) |
10641064
| `-y` / `--yes` | Skip confirmation prompt |
10651065
1066-
Note: IDs shown by `nx store list` are 32 hex chars (`sha256(text)[:32]`). `--title` delete is paginated and safe for multi-chunk documents. To delete an entire collection use `nx collection delete`.
1066+
Note: IDs shown by `nx store list` are 64 hex chars (the full `sha256(text)` digest — RDR-180; pre-cohort 32-hex IDs resolve via the permanent `chash_alias` route). `--title` delete is paginated and safe for multi-chunk documents. To delete an entire collection use `nx collection delete`.
10671067
10681068
**`get` flags:**
10691069
@@ -1090,9 +1090,10 @@ Note: IDs shown by `nx store list` are 32 hex chars (`sha256(text)[:32]`). `--ti
10901090
| `--assume-model MODEL` | Override the export header's declared embedding model. Pre-migration `.nxexp` files can carry a wrong label (GH #1370); use this to supply the true model instead of trusting the header |
10911091
| `--skip-existing` | Skip records whose id already exists in the target collection, instead of overwriting. Useful for resuming a partial import |
10921092
1093-
Non-conformant legacy chunk ids (16-char pre-migration ids that fail the
1094-
service backend's `chash` length constraint) are re-hashed to 32-char
1095-
content-derived ids automatically; the CLI reports how many were re-hashed.
1093+
Non-conformant legacy chunk ids (16- or 32-char pre-migration ids that fail
1094+
the service backend's `chash` length constraint) are re-hashed to full 64-char
1095+
content-derived ids automatically (RDR-180); the CLI reports how many were
1096+
re-hashed.
10961097
10971098
**Restoring a pre-migration (Chroma-era) backup:**
10981099

0 commit comments

Comments
 (0)