Skip to content

feat(s133): embedding spaces, operator pinning and the static floor - #119

Open
HackTuah wants to merge 2 commits into
mainfrom
slice/133-embedder-ladder-static-floor
Open

HackTuah wants to merge 2 commits into
mainfrom
slice/133-embedder-ladder-static-floor

Conversation

@HackTuah

@HackTuah HackTuah commented Oct 8, 2026

Copy link
Copy Markdown
Member

Slice 133: embedding spaces, operator pinning and the static floor. The slice stays in_progress until the owner's two items are done: the legal review of the static weights (D7), and the 100-label audit before the eval's scored run.

What lands

  • Embedding spaces: a new memory_embeddings table keyed (memory_id, space_id), and embedding_spaces, which holds each space's 14-field manifest identified by SHA-256 over RFC 8785 JSON. On Postgres the column is an untyped vector with one partial HNSW index per space, so spaces of different widths coexist. Existing vectors migrate under a legacy space with their bytes unchanged.
  • Operator pinning: one active space per store.
    • mix trinity.space.retier builds the new space beside the old and moves the pointer in one transaction.
    • mix trinity.space.drop needs --confirm and refuses the active space.
    • A row that does not fit the active space makes the store refuse rather than rank.
  • Declared locality: in_process, within_boundary or external. Configuration faults refuse a :regulated boot. Runtime faults turn semantic memory off with a named reason while full-text search keeps answering.
  • The static embedder: pure-Elixir WordPiece plus mean pooling, with no NIF. Its weights are a derived artifact whose digest is pinned in code; the weights are not in the tree.
  • Scoring: an int8 scorer, plus a sign/Hamming prefilter measured but not yet wired in. At 10^4 x 256, prefilter p95 is 10.3 ms and exact p95 24.5 ms, under the 50 ms line, so no scoring NIF is needed.
  • TRINITY_WITHOUT_ML=1 builds without nx, bumblebee and exla, and that release boots, embeds and recalls.
  • The eval harness and corpus. The scored run refuses until the audit is done.

Criteria

  • Proven: AC1 to AC11 and AC16. AC1 and AC4 on SQLite and Postgres, AC2 on Postgres. AC8 on the author's machine, since the weights cannot go to CI before D7.
  • Measured: AC13.
  • Waiting on the owner:
    • AC12's second half (the Linux bundle reporting semantic memory ON) and AC15 (the Windows bundle): both need the weights bundled, which waits on D7.
    • AC14: the label audit.

Evidence

  • Author's gate: exit 0, 1017 passed (21 properties, 996 tests), 31 excluded, prod_check: PASS, coverage 80.49% against 80.31%.
  • Postgres full suite: 999 passed.
  • Reviewer re-run before commit:
    • the 25 changed and new test files: 92 passed, 14 excluded;
    • with the weights cache set, --only static_weights: 11 passed;
    • with the variable pointing at a missing directory: 8 failed, 3 invalid. That is the owner's rule: the tests fail, never skip;
    • mix format --check-formatted OK; mix credo --strict --all found no issues.

Slice 133, to G3 apart from what waits on the owner: the legal review of
the static weights (D7), and the label audit before the eval's scored run.

- Vectors move out of memories into memory_embeddings, keyed
  (memory_id, space_id). Each space is an embedding_spaces row holding its
  14-field manifest, identified by SHA-256 over RFC 8785 JSON. On Postgres
  the column is an untyped vector with one partial HNSW index per space.
  Existing vectors migrate under a legacy space with their bytes
  unchanged.
- One active space per store, moved only by the operator:
  trinity.space.retier builds the new space beside the old and moves the
  pointer in one transaction, and trinity.space.drop needs --confirm and
  refuses the active space. A row that does not fit the active space makes
  the store refuse rather than rank.
- Locality is declared: in_process, within_boundary or external. Under
  :regulated a fault in configuration refuses the boot; a runtime fault
  turns semantic memory off with its reason while full-text search keeps
  answering.
- Trinity.Memory.Embedders.Static is a pure-Elixir WordPiece tokenizer and
  EmbeddingBag mean pool, with no NIF. Its weights are a derived artifact
  whose digest is pinned in code. The weights are not in the tree.
- The int8 scorer, the sign and Hamming prefilter, and their measurement
  (docs/perf.md): prefilter p95 10.3 ms and exact p95 24.5 ms at 10^4 x 256,
  under the 50 ms line, so no scoring NIF.
- TRINITY_WITHOUT_ML=1 builds without nx, bumblebee and exla, and that
  release boots, embeds and recalls.
- The eval harness, corpus pipeline and label freezing. The scored run
  refuses until the owner's audit is done.

Weight-dependent tests are tagged static_weights, excluded when
TRINITY_STATIC_MODEL_DIR is unset and failing when it is set and the
weights are absent. Red evidence R1 to R9 is in the slice NOTES.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
Signed-off-by: Ayla Croft <aylacroft@proton.me>

# Conflicts:
#	CHANGELOG.md
#	config/config.exs
#	lib/trinity/smoke.ex
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant