Skip to content

feat(sync): author a repo's memories to a public stream when published (#1157) - #1158

Merged
skakri merged 1 commit into
mainfrom
feat/public-node
Aug 6, 2026
Merged

feat(sync): author a repo's memories to a public stream when published (#1157)#1158
skakri merged 1 commit into
mainfrom
feat/public-node

Conversation

@skakri

@skakri skakri commented Aug 6, 2026

Copy link
Copy Markdown
Member

Groundwork for a dedicated public knowledge-base node (#1157) — the owner writes, anyone reads anonymously. A repo can be marked public, after which its memories are authored to a public_read /2 owner stream so the account is servable to anonymous readers (the transport for that merged in #1150#1153). Until a repo is published, nothing changes.

What changed

  • rag-rat sync publish marks the active repo's account as a public knowledge base: persists a one-way memory_stream_access_mode intent and ensures the public_read /2 stream. It refuses — rather than strand the account — when the account already holds a private stream (publishing an existing private repo is not supported; start a fresh public index), when sealing is intended (a public reader cannot unwrap sealed content), or on a legacy/local-only repo id.
  • One mode-aware seam. Memory authoring resolves the owner stream's access mode through owner_stream_access_mode: the persisted intent, falling back to the op-log fact (an already-owned public stream) so the one-way ratchet survives loss of the intent row. Every /2 resolver — live-write, drain, reconcile, catch-up — threads that mode, so they all target the same stream id. The access mode folds into the stream identity, so a public and a private stream are distinct; a mode split would otherwise author a second StreamOwn and mix the account permanently (an append-only, unservable state).
  • Mutual exclusion. Publish and sealing are incompatible one-way intents, refused in both directions.
  • Consolidation carries a lone public intent onto its fresh target and refuses two disagreeing explicit modes (unlike the seal ratchet's one-way merge, access mode has no safe winner).

Mechanism only: owned_stream_v2_id_with_mode / established_owned_stream_v2_with_mode default to Private, so this is a no-op until sync publish sets the intent.

Tests

Publish is idempotent and makes the account fully public + authors public; a repo with prior private memories refuses publish; publish×seal are mutually exclusive both directions; the access-mode ratchet survives a deleted intent row (no second private StreamOwn); consolidation carries the public intent and rejects an unknown token.

Scope

Serving a published account under public-read admission (flip the serve policy), and seeding an existing index's memories onto a fresh public node, follow in later changes.

Verification

cargo +nightly fmt --check; clippy --workspace --all-targets under --no-default-features and --all-features, plus the --features eval gates — all -D warnings clean; cargo nextest run --workspace (5005) and cargo test -p rag-rat-core -p rag-rat-oplog (both CI runners).

#1157)

Groundwork for a dedicated public knowledge-base node (owner writes, anyone
reads anonymously). A repo can now be marked public, after which its memories are
authored to a public_read `/2` owner stream so the account is servable to
anonymous readers; until then nothing changes.

- `sync publish` marks the active repo's account as a public knowledge base:
  it persists a one-way `memory_stream_access_mode` intent and ensures the
  public_read `/2` stream. It refuses — rather than strand the account — when the
  account already holds a private stream (publishing an existing private repo is
  not supported; start a fresh public index), when sealing is intended (a public
  reader cannot unwrap sealed content), or on a legacy/local-only repo id.
- Memory authoring resolves the owner stream's access mode through one seam,
  `owner_stream_access_mode`: the persisted intent, falling back to the op-log
  fact (an already-owned public stream) so the one-way ratchet survives loss of
  the intent row. Every `/2` resolver — live-write, drain, reconcile, catch-up —
  threads that mode, so they all target the same stream id; the access mode folds
  into the stream identity, so a public and a private stream are distinct and a
  mode split would otherwise mix the account permanently.
- Publish and sealing are mutually exclusive in both directions.
- Consolidation carries a lone public intent onto its fresh target and refuses
  two disagreeing explicit modes.

Serving a published account under public-read admission, and seeding an existing
index's memories onto a fresh public node, follow in later changes.
@skakri
skakri merged commit 2277864 into main Aug 6, 2026
12 of 16 checks passed
@skakri
skakri deleted the feat/public-node branch August 6, 2026 18:25
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Projectrag-rat
Branchfeat/public-node
Testbedubuntu-latest

⚠️ WARNING: No Threshold found!

Without a Threshold, no Alerts will ever be generated.

Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the --ci-only-thresholds flag.

Click to view all benchmark results
BenchmarkEstimated Cyclescycles x 1e6Instructionsinstructions x 1e6L1 Hitshits x 1e6LL Hitshits x 1e6RAM Hitshits x 1e3Total read+writereads/writes x 1e6
rag_pipeline::pipeline::index cargo_resolver:resolver_config()📈 view plot
⚠️ NO THRESHOLD
3,883.00 x 1e6📈 view plot
⚠️ NO THRESHOLD
2,580.90 x 1e6📈 view plot
⚠️ NO THRESHOLD
3,552.18 x 1e6📈 view plot
⚠️ NO THRESHOLD
56.73 x 1e6📈 view plot
⚠️ NO THRESHOLD
1,346.97 x 1e3📈 view plot
⚠️ NO THRESHOLD
3,610.26 x 1e6
rag_pipeline::pipeline::query_cold cargo_resolver:resolver_built_config()📈 view plot
⚠️ NO THRESHOLD
340.40 x 1e6📈 view plot
⚠️ NO THRESHOLD
226.70 x 1e6📈 view plot
⚠️ NO THRESHOLD
323.59 x 1e6📈 view plot
⚠️ NO THRESHOLD
3.14 x 1e6📈 view plot
⚠️ NO THRESHOLD
31.27 x 1e3📈 view plot
⚠️ NO THRESHOLD
326.77 x 1e6
rag_pipeline::pipeline::query_warm cargo_resolver:resolver_index()📈 view plot
⚠️ NO THRESHOLD
313.64 x 1e6📈 view plot
⚠️ NO THRESHOLD
208.39 x 1e6📈 view plot
⚠️ NO THRESHOLD
297.88 x 1e6📈 view plot
⚠️ NO THRESHOLD
2.92 x 1e6📈 view plot
⚠️ NO THRESHOLD
32.51 x 1e3📈 view plot
⚠️ NO THRESHOLD
300.84 x 1e6
🐰 View full continuous benchmarking report in Bencher

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Projectrag-rat
Branchfeat/public-node
Testbedubuntu-latest
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
seconds (s)
(Result Δ%)
Upper Boundary
seconds (s)
(Limit %)
index_time/full_rebuild_cargo📈 view plot
🚷 view threshold
6.19 s
(+12.05%)Baseline: 5.53 s
6.25 s
(99.03%)
🐰 View full continuous benchmarking report in Bencher

@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.81481% with 22 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
crates/rag-rat-cli/src/commands/sync.rs 12.50% 7 Missing ⚠️
crates/rag-rat-core/src/index/query_api/memory.rs 0.00% 5 Missing ⚠️
crates/rag-rat-core/src/index/consolidate.rs 94.28% 4 Missing ⚠️
crates/rag-rat-core/src/memory_write/authoring.rs 97.29% 3 Missing ⚠️
crates/rag-rat-oplog/src/account/authoring.rs 85.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

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