Skip to content
This repository was archived by the owner on Aug 7, 2026. It is now read-only.

RFL-171 Seam A: helm-event-substrate — Bedrock-owned event/lease contracts; crm-helm to apps/ - #15

Merged
kpernyer merged 12 commits into
mainfrom
e12/rfl-171-event-substrate
Jul 8, 2026
Merged

RFL-171 Seam A: helm-event-substrate — Bedrock-owned event/lease contracts; crm-helm to apps/#15
kpernyer merged 12 commits into
mainfrom
e12/rfl-171-event-substrate

Conversation

@kpernyer

@kpernyer kpernyer commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Linear: https://linear.app/reflective-labs/issue/RFL-171

  • NEW contracts/crates/helm-event-substrate 0.1.0: event/lease/error contracts, EventHub machinery, SSE (feature sse), in-memory implementors (feature memory) with CAS-parity property tests; 53 tests + soak (10k iters, 542ms, no gaps); rustdoc 0 warnings
  • crm-helm: showcase/ → apps/ (deployed variant); showcase/ deleted; headless variant repatriates to atelier
  • KB one-story + CHANGELOG; zero #[allow]; pre-existing fmt drift committed as hygiene at branch base
  • Landing order: this first, then runway rewire, then atelier scenario
  • Whole-branch review (3 repos): ready-to-merge; cleanups tracked (redb-oracle parity upgrade, registry entry)

🤖 Generated with Claude Code


Note

High Risk
This is a cross-repo seam extraction touching realtime event ordering, durable replay, leases, and SSE—behavior regressions would affect live streams and session ownership even though runway source rewires may land separately.

Overview
Introduces helm-event-substrate 0.1.0 under contracts/crates/ as the Bedrock-owned Seam A boundary: event ledger traits (EventLog, SyncableEventLog, StoredEvent, EventQuery), lease/session ownership (LeaseStore and related types), SubstrateError, in-process EventHub / EventHubHandle, and optional sse (default) and memory implementors (InMemoryEventLog, InMemoryLeaseStore). runway-app-host and runway-storage are wired to depend on the new crate in the lockfile; production backends are expected to keep re-exporting the moved types so old import paths still compile after the follow-on runway rewire.

The PR adds a large test and quality wave: hub replay/eviction and durable-log behavior, negative cases (malformed stored payloads, limit: 0, post-eviction cursors), lease proptest parity against an inline reference model, an optional soak test over InMemoryEventLog, a cargo check --no-default-features feature-gate test, rustdoc cleanup, and InMemoryEventLog.append dedup changed from O(N) to O(1) via seen_ids.

crm-helm moves from apps/showcase/ to apps/crm-helm/, joins the root workspace, and its Cargo.toml path-deps point at in-repo Helms crates plus sibling runtime-runway paths. Architecture docs (Module Map, Foundation Contracts) and CHANGELOG record ownership, implementors, and what stays in runway (e.g. SessionOwnershipLayer until RFL-178).

Reviewed by Cursor Bugbot for commit c9e410f. Bugbot is set up for automated code reviews on this repo. Configure here.

kpernyer and others added 12 commits July 8, 2026 12:43
Additive contract crate registered in contracts mini-workspace. Deps:
serde/chrono/uuid/thiserror/tokio(sync,time)/async-trait/serde_json.
Features: default=["sse"] (axum+tokio-stream+async-stream+futures
optional), memory=[] (placeholder for T3 in-memory impls). SubstrateError
(moved from runway_storage::traits::Error) and Result alias live in lib.rs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ubstrate (RFL-171 T1)

StoredEvent / EventQuery / EventLog / SyncableEventLog moved verbatim from
runway-storage/src/traits/event.rs; error type retargeted to
crate::SubstrateError. Pure stream types EventEnvelope / EventCursor /
EventSubscription moved verbatim from runway-app-host/src/realtime.rs:11-49
with three envelope serde tests (lines 51-116) carried. EventHub stays in
realtime.rs (T2 scope).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt-substrate (RFL-171 T1)

LeaseScope (+ key() / RP-NO-LEASE-WITHOUT-FENCING-V1 doc) / LeaseRecord /
AcquireOutcome / RenewOutcome / LeaseStore moved verbatim from
runway-storage/src/traits/lease.rs; error type retargeted to
crate::SubstrateError. Two carried tests: scope_key_is_pipe_delimited,
lease_record_serde_roundtrip. All 5 crate tests green; helm-module-contracts
(28+23+25+1 tests) untouched and green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…AM annotation found in working tree

Found uncommitted before Seam A work: rustfmt reflow in 4 contract files
(semantically neutral) and the approved-seam annotation on crm-helm's
runway deps. Committed as-found to keep the seam branch's own diffs clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…te (RFL-171 T2)

Verbatim port from runway-app-host/src/realtime.rs:119-651.
Imports retargeted: envelope/cursor/subscription/EventLog/StoredEvent come
from crate::event; replay_from_log returns crate::Result.

Durable-storage integration tests carried with an in-file TestEventLog stub
(Arc<Mutex<Vec>> — replaces runway_storage::StorageKit, no runway dep).

Hub tests: 10 in-memory + 4 durable = 14 tests; all green.
cargo tree -p helm-event-substrate --features sse | grep runway = 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…1 T2)

Verbatim port from runway-app-host/src/sse.rs:1-185.
Imports retargeted: crate::event for EventEnvelope/EventSubscription,
crate::hub for EventHubHandle. Gated via #[cfg(feature = "sse")] pub mod sse
in lib.rs (feature default = on).

tokio-stream gains the `sync` feature (required for BroadcastStream).

SSE tests: 3 (sse_endpoint_is_reachable, event_stream_replay_filters_and_terminates,
event_stream_live_dedups_by_sequence); all green.

Total helm-event-substrate: 21 tests; cargo tree runway dep count = 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…feature (RFL-171 T3)

- InMemoryEventLog: Arc<Mutex<EventLogInner>> (events Vec + synced HashSet).
  OR-IGNORE append, query with full filter semantics (org/app/type/since/limit,
  sort by occurred_at), SyncableEventLog via synced-id set + synced_at stamping.
- InMemoryLeaseStore: Arc<Mutex<HashMap<String,LeaseRecord>>> keyed by
  LeaseScope::key(). Internal _at methods inject chrono::DateTime<Utc> for
  deterministic testing. CAS semantics match redb arm-by-arm: idempotent
  re-acquire (refreshes TTL), steal-after-expiry, HeldByOther on live conflict,
  renew holder-match only (expired same-holder → Lost), non-holder release no-op.
- lib.rs: #[cfg(feature="memory")] pub mod memory + re-exports.
- Cargo.toml: add proptest dev-dep (needed for parity property tests in T3).
- Feature hygiene: cargo check -p helm-event-substrate (default=sse) does NOT
  compile memory.rs. No #[allow] attributes.
- Oracle: inline RefLeaseModel (not RedbLeaseStore -- too heavy as dev-dep;
  see module-level doc for rationale and T9 cross-crate follow-up).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…71 T3)

Unit tests (17): all LeaseStore semantic bullets covered — acquire-on-empty,
idempotent re-acquire, HeldByOther on live conflict, steal-after-expiry, renew
by holder while live, renew Lost for wrong holder, renew Lost when expired even
for same-holder (matches redb comment), renew Lost with None when no lease,
non-holder release no-op, current returns expired record (expiry-agnostic).
EventLog: append idempotence, all five filters, limit truncation, unsynced
query, mark_synced removes + sets synced_at + idempotent.

Parity property test (lease_store_parity_with_ref_model): proptest generates
op sequences (Acquire/Renew/Release over 3 holders × Long/Short TTL + TimeStep
advancing virtual clock past short-TTL). Both InMemoryLeaseStore._at and the
inline RefLeaseModel receive identical (scope, holder, ttl, now) — outcomes
must match discriminant + holder_id + expires_at.

EventLog property tests (4): limit ⊆ full (prefix property), since exclusive,
occurred_at order preserved, limit ≤ n. All tested against apply_query directly
(no async/runtime overhead in proptest cases).

Oracle: inline RefLeaseModel (not RedbLeaseStore; rationale in module doc).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
git mv showcase/crm-helm apps/crm-helm; showcase/ now empty and removed.
Fixed cross-repo path deps for new depth (../../crates/*, ../../../../runtime-runway/*).
Added apps/crm-helm to workspace members. async-trait stays pinned (not in
workspace.dependencies); tokio-stream/tracing-subscriber now use workspace refs.
cargo check -p example-crm-helm-showcase passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…c 0 warnings (RFL-171 T9)

- Soak test (#[ignore], SOAK_ITERS env, default 100_000): publish/subscribe
  through EventHub+InMemoryEventLog — proves monotone sequence, no gaps,
  bounded replay buffer (eviction), and fresh-hub durable replay equals
  in-order publication. Proven at SOAK_ITERS=10000 in 543ms (18k iter/s).
- Negative additions: malformed StoredEvent payload skipped-not-panicked in
  stored_to_envelope path; EventQuery limit=0 returns empty; subscribe-after-
  eviction cursor returns only buffer-resident events.
- Compile-fail guard: cargo check --no-default-features gate in
  tests/feature_gate.rs; trybuild excluded (cannot control features per-case
  when gate command adds --features memory,sse).
- Rustdoc: fix 2 broken intra-doc links (EventSubscription, subscribe);
  add missing docs to EventQuery, EventEnvelope, EventHub, EventHubHandle
  and all pub methods; crate-level doc extended with RFL-178 note
  (SessionOwnershipLayer stays app-side pending OrgIdentity neutralisation).
- Perf fix: InMemoryEventLog.append O(N)→O(1) dedup via seen_ids HashSet.

gate: cargo test -p helm-event-substrate --features memory,sse
  → 52 unit + 1 integration = 53 passed, 1 ignored; doc warnings = 0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…LOG (RFL-171 T9)

- kb/Architecture/Module Map.md: add helm-event-substrate under Seam Contracts
  with ownership, dropped edges, what stays in runway, RFL-178 note.
- kb/Architecture/Foundation Contracts.md: add Event Substrate Seam section
  with contract surface table and implementor map.
- CHANGELOG.md: T9 quality wave entry + T1-T7 Seam A extraction summary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…strate

# Conflicts:
#	apps/crm-helm/Cargo.toml
@kpernyer
kpernyer merged commit f36db0e into main Jul 8, 2026
1 of 2 checks passed
@kpernyer
kpernyer deleted the e12/rfl-171-event-substrate branch July 8, 2026 12:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant