Skip to content

feat(continuum-core/persona): L0-3a.2a — EngramGraph + EngramEdge + EdgeKind (algorithm 3 substrate)#1474

Merged
joelteply merged 1 commit into
canaryfrom
8459bfa6/feat-engram-types-and-storage
May 30, 2026
Merged

feat(continuum-core/persona): L0-3a.2a — EngramGraph + EngramEdge + EdgeKind (algorithm 3 substrate)#1474
joelteply merged 1 commit into
canaryfrom
8459bfa6/feat-engram-types-and-storage

Conversation

@joelteply
Copy link
Copy Markdown
Contributor

Card: 8459bfa6-b40c-4c22-8f25-0963a7987c17

Sidecar substrate for algorithm 3 (activation spreading, COGNITION-ALGORITHMS.md §3). Pure storage layer — traversal logic lands in L0-3a.5. Does NOT modify the existing persona::engram admission membrane.

What ships

File Change
persona/engram_graph.rs new, 376 lines
persona/mod.rs pub mod engram_graph;
shared/generated/persona/EdgeKind.ts ts-rs
shared/generated/persona/EngramEdge.ts ts-rs

Module surface

pub enum EdgeKind {
    SharedEntity,        // highest prior — entity co-mention rare + meaningful
    SharedTopic,         // embedding-cluster
    CitedIn,             // asymmetric A→B
    RecallCoOccurrence,  // self-reinforcing
    ConversationalReply, // chat thread structure
    TaskOutcome,         // start→complete, feeds algorithm 4 outcome-linked salience
}

pub struct EngramEdge { target: Uuid, kind: EdgeKind, weight: f32 }

pub struct EngramGraph {
    edges: DashMap<Uuid, Vec<EngramEdge>>,  // sharded for concurrent writes
}

Surface: new() / with_capacity / default() / add_edge / neighbors / in_degree / edge_count / evict_engram (idempotent, removes outbound + inbound) / is_empty.

Sidecar pattern

Intentionally separate from persona::engram (the admission membrane):

  • engram.rs ships provenance, trust, content refs — where engrams come from
  • engram_graph.rs ships connectivity — how engrams connect

Keeping them separate means admission consumers don't grow algorithm-3 dependencies, and algorithm-3 consumers don't grow admission dependencies.

Tests (16 pass, 0 fail)

  • 14 unit tests: empty/add/neighbors/order/weights/in-degree (incl. multi-source + repeated), evict outbound/inbound/idempotent, constructors, EdgeKind serde round-trip, concurrent add from 8 threads × 100 edges (in_degree=800)
  • 2 ts-rs auto-tests: export_bindings_edgekind, export_bindings_engramedge

What is NOT in this card

  • spread_activation function (L0-3a.5, algorithm 3 — reads this graph)
  • EdgeKind weights tuned by algorithm 7 (L0-4c)
  • RecallMetadata sidecar (L0-3a.2b — salience, last_touched, access_count, embedding refs)
  • EngramRef shape (L0-3a.2b)
  • No changes to admission membrane

Predecessors merged

Flywheel

Third PR through the auto-merger after peer's #1091/#1092/#1093 shipped. Local fmt was scoped to only my file (no widespread cargo fmt -p sweep), so no companion fmt-drift PR needed this time — cleaner dogfood.

🤖 Generated with Claude Code

…dgeKind (algorithm 3 substrate)

Card: 8459bfa6-b40c-4c22-8f25-0963a7987c17

Sidecar substrate for algorithm 3 (activation spreading, COGNITION-ALGORITHMS.md §3). Pure storage layer — traversal logic lands in L0-3a.5. Does NOT modify the existing persona::engram admission membrane.

## What ships

### persona/engram_graph.rs (new, 376 lines)

- EdgeKind enum — SharedEntity | SharedTopic | CitedIn | RecallCoOccurrence | ConversationalReply | TaskOutcome
- EngramEdge { target: Uuid, kind: EdgeKind, weight: f32 } — algorithm-3 traversal payload
- EngramGraph — DashMap<Uuid, Vec<EngramEdge>> sharded for concurrent writes
  - new() / with_capacity(n) / default()
  - add_edge(from, to, kind, weight)
  - neighbors(id) — outbound edges, O(1) amortized, insertion order preserved
  - in_degree(id) — inbound count, O(N) scan (cold path — algorithm 4 centrality)
  - edge_count() — telemetry
  - evict_engram(id) — removes outbound + inbound, idempotent
  - is_empty()

### ts-rs bindings

shared/generated/persona/EdgeKind.ts
shared/generated/persona/EngramEdge.ts

## Sidecar pattern

Intentionally separate from persona::engram (the admission membrane):
- engram.rs ships provenance, trust, content refs — WHERE engrams come from
- engram_graph.rs ships connectivity — HOW engrams connect

Keeping them separate means admission consumers don't grow algorithm-3 dependencies, and algorithm-3 consumers don't grow admission dependencies. Clean concern boundaries.

## Tests (16 pass, 0 fail)

- new_engram_graph_is_empty
- add_edge_increments_count
- neighbors_returns_added_edges_in_insertion_order
- neighbors_of_unknown_source_is_empty
- weights_preserved_through_neighbors
- in_degree_counts_inbound_edges_across_sources
- in_degree_counts_repeated_edges_from_same_source
- evict_engram_removes_outbound_edges
- evict_engram_removes_inbound_edges_from_other_engrams
- evict_engram_is_idempotent
- concurrent_add_edge_from_threads_is_safe (8 threads × 100 edges, all targeting same id, in_degree=800)
- default_constructor_matches_new
- with_capacity_constructor_works
- edge_kind_round_trips_through_serde
- export_bindings_edgekind (ts-rs auto)
- export_bindings_engramedge (ts-rs auto)

## What is NOT in this card

- spread_activation function (L0-3a.5, algorithm 3 — reads this graph)
- EdgeKind weights tuned by algorithm 7 (L0-4c yield-learning)
- RecallMetadata sidecar (L0-3a.2b — salience, last_touched, access_count, embedding)
- EngramRef shape (L0-3a.2b)
- Engram admission membrane modifications (no changes to persona::engram)

## Predecessors

- #1473 (L0-3a.1 HippocampusModule skeleton) — merged
- #1471 (L0-3a.0 trait machinery) — merged
- #1470 (cognition algorithms doc) — merged

## Flywheel test

Third PR (after #1471, #1473) through the auto-merger flywheel that peer's #1091/#1092/#1093 enabled. Local fmt was scoped to ONLY my file (no widespread cargo fmt -p sweep), so no companion fmt-drift PR needed this time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@joelteply joelteply merged commit bf23618 into canary May 30, 2026
4 checks passed
@joelteply joelteply deleted the 8459bfa6/feat-engram-types-and-storage branch May 30, 2026 05:29
joelteply added a commit that referenced this pull request May 30, 2026
The `avatars: ./src/models/avatars` additional_context was added in
9b1f6ca (April 2026) when the plan was to bake CC0 avatar VRMs
into the continuum-core image. That plan never landed end-to-end —
docker/continuum-core.Dockerfile lines 131-143 document the rollback:
src/models is gitignored, the dir doesn't exist in CI checkouts,
and the Dockerfile uses `RUN mkdir -p /app/avatars` as a placeholder
instead of COPYing from the avatars context.

The compose-side context declaration was left behind, dangling. No
Dockerfile uses `--from=avatars` (verified by grep), so the declaration
referenced nothing in build instructions. But docker compose validates
that ALL additional_contexts resolve at build time — a missing local
context dir fails the whole build with "stat /tmp/carl-smoke-NNNN/src/
models/avatars: no such file or directory".

That's the exact failure mode currently blocking carl-install-smoke
on PR #1475 (Mac Intel hardware tier) — any PR that touches install.sh
triggers carl-install-smoke, which has been silently broken by this
dangling context since the rollback. Other PRs (e.g. #1471, #1473,
#1474) didn't touch install.sh so the check never ran on them; the
break was invisible until now.

Removing the line restores the carl-install-smoke happy path while
keeping the Dockerfile's empty-dir placeholder intact. Restore the
build context when the avatar-provisioning story lands (LFS, model-init
download, or curl from a CC0 URL in CI before docker build) per the
gap noted in docs/infrastructure/PR891-E2E-VALIDATION.md.

Inline comment preserves the context-of-removal in the file so a
future contributor doesn't re-add the dangling line.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
joelteply added a commit that referenced this pull request May 30, 2026
…se (#1476)

The `avatars: ./src/models/avatars` additional_context was added in
9b1f6ca (April 2026) when the plan was to bake CC0 avatar VRMs
into the continuum-core image. That plan never landed end-to-end —
docker/continuum-core.Dockerfile lines 131-143 document the rollback:
src/models is gitignored, the dir doesn't exist in CI checkouts,
and the Dockerfile uses `RUN mkdir -p /app/avatars` as a placeholder
instead of COPYing from the avatars context.

The compose-side context declaration was left behind, dangling. No
Dockerfile uses `--from=avatars` (verified by grep), so the declaration
referenced nothing in build instructions. But docker compose validates
that ALL additional_contexts resolve at build time — a missing local
context dir fails the whole build with "stat /tmp/carl-smoke-NNNN/src/
models/avatars: no such file or directory".

That's the exact failure mode currently blocking carl-install-smoke
on PR #1475 (Mac Intel hardware tier) — any PR that touches install.sh
triggers carl-install-smoke, which has been silently broken by this
dangling context since the rollback. Other PRs (e.g. #1471, #1473,
#1474) didn't touch install.sh so the check never ran on them; the
break was invisible until now.

Removing the line restores the carl-install-smoke happy path while
keeping the Dockerfile's empty-dir placeholder intact. Restore the
build context when the avatar-provisioning story lands (LFS, model-init
download, or curl from a CC0 URL in CI before docker build) per the
gap noted in docs/infrastructure/PR891-E2E-VALIDATION.md.

Inline comment preserves the context-of-removal in the file so a
future contributor doesn't re-add the dangling line.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant