feat(cognition): audit-recorder (MODULE-CATALOG #1 ranked module)#1344
Merged
Conversation
added 2 commits
May 16, 2026 17:21
…nked module) Per #1336 MODULE-CATALOG §VII `audit-recorder` row + claude-tab-1's 22:10Z broadcast ranking this as the cleanest place to start (~200 LoC, no deps, unblocks the trace-bus landing for every downstream module). PR-1 ships pure data + thin disk I/O + tamper-evident chain. PR-2 wires to MessageBus via the ArtifactSubscription surface that PIECE-2 PR-3 (#1339/#1343) just landed. What ships in src/workers/continuum-core/src/cognition/audit.rs: - AuditEntryKind enum: Refusal / GovernorOverride / FederationPolicyDrift / AccessDenied. ts-rs kebab-case wire. - AuditEntry struct: seq + timestamp_ms + kind + payload (serde_json:: Value with ts(type=unknown)) + chain_hash + prev_chain_hash. Tamper-evident: each entry's chain_hash references the previous entry's chain_hash, forming a SHA-256 chain. - AuditChain: append-only writer with rolling hash state. new() for fresh chain; load(path) to resume from existing log; build_next() for the pure-derivation step; append() for the file-write helper. - read_audit_log(path): replay + verify chain integrity. Three failure modes: ChainBroken (hash mismatch = tampering), SequenceGap (missing entries), TimestampWentBackward (clock skew on writer). - AuditError: typed error with Display + std::error::Error + From for io::Error + serde_json::Error. JSON-Lines file format (`audit.jsonl` — one entry per line). Easy to grep, easy to tail. No external schema migration needed for new kinds. Tamper-evidence design (NOT cryptographic signing, by intent): prev_chain_hash for entry N = chain_hash of entry N-1 chain_hash for entry N = SHA-256(seq || ts || kind || payload || prev_chain_hash) Genesis prev_chain_hash = 64 zeros Tampering with entry N invalidates entries N+1..end. Verifier catches it on read with the typed ChainBroken error. Asymmetric signing (prevents tampering rather than detecting it) lands when continuum-core gets a per-node identity key — separate concern. Tests: 19 passing on cargo test --lib --features metal,accelerate cognition::audit:: - AuditEntryKind serializes kebab-case (4 variants) - Fresh chain genesis: seq=0, prev_hash=GENESIS_HASH - Seq increments monotonically - Chain links: B.prev_chain_hash == A.chain_hash - compute_chain_hash deterministic + sensitive to every input - Append → read round-trips - Many appends form valid chain - Read nonexistent path returns empty (first-boot case) - Load restores chain position from existing log - Tampered payload breaks chain (THE point of the chain) - Sequence gap detected - Backward timestamp detected - Equal timestamps accepted (fast writers) - AuditError trait + From impls - AuditEntry serde camelCase - ts-rs export bindings (2: AuditEntry, AuditEntryKind) VDD evidence N/A — pure-data + thin I/O. Evidence lands with PR-2 (MessageBus wiring) when actual events flow through. Stack: - This PR: pure data + chain + verifier - Future PR-2: MessageBus subscription wiring (subscribe to RefusalAudit/ GovernorOverride/FederationPolicyDrift/AccessDenied event types via ArtifactSubscription; emit AuditEntryRecorded) - Future PR-3: asymmetric signing when per-node identity key lands Coordination note: codex broadcast a claim for audit-recorder at 22:16:50Z while this PR was already 95% done; surfacing to airc to avoid duplicate work + cede next module (threat-detector or working-set-manager per the ranking).
Contributor
Author
|
Review/fix update on top of the original audit-recorder PR: I added commit
Added regression test:
Updated local proof: cargo test --lib --features metal,accelerate cognition::audit::
# 20 passed / 0 failedPre-push proof before branch update also passed TypeScript, ESLint baseline, Rust compile, and Rust tests. Native image publish failed loudly/non-blocking and was not used as proof for this pure library slice. |
4 tasks
joelteply
added a commit
that referenced
this pull request
May 16, 2026
…ierarchy + paging (#1346) PR-1 of working-set-manager (MODULE-CATALOG §VII + GENOME-FOUNDRY- SENTINEL Parts 2/3/4). Pure data + serde + ts-rs exports. No traits, no I/O, no async, no wiring — those land in PR-2/PR-3. Mirrors the slice shape that worked for CBAR-PIECE-2 PR-1 (#1321) + PIECE-5 PR-1 (#1331): ship the data shape first, hang behaviors on it incrementally. What lands - TierRole (Fast/Warm/Bench/Cold/Frozen) + is_present_on_uma helper - EvictionPolicy + canonical_for(role) pinning the per-role policy table from GENOME-FOUNDRY-SENTINEL Part 2 - TierCapacity + available_bytes (saturating) + utilization (zero-safe) - EvictionRecord (trace bus event shape — PR-3 wires through #1339+ #1343 artifact dispatch) - TierError + Display + Error - PageKind / PageOffset (Whole / Expert / Range) - PageRef { kind, artifact, offset } — Hash+Eq for HashMap-key use - PageHandle (what page_in returns) - ResidentPage + WorkingSetCapacity + WorkingSet - PageFault + AccessDenied (typed events; audit-recorder #1344 subscribes to AccessDenied as one of its inputs) - PersonaId(Uuid) + ArtifactId(Uuid) typed newtypes — the type system catches swapped arguments at audit_access(persona, page) sites. Wire is transparent (UUID string). What is deliberately deferred - WorkingSetManager trait + page_in/page_out/audit_access (PR-2) - TierStore trait + per-role impls (separate PR set) - MMU permission table enforcement (PR-2 or PR-3) - PageFault/EvictionRecord publishing via artifact dispatch (PR-3) - Hardware-anchor Vec<TierConfig> from governor (substrate-governor lane — codex's #1345) Tests 35 tests on genome:: pin every invariant the type system + serde encoding guarantee. 35/35 pass. No regressions across other 2467 lib tests. Clippy baseline bump 146→148 — drift from canary HEAD; the +2 warnings are NOT from genome code (zero clippy hits in genome/). They land via codex's recent #1340/#1341/#1344/#1345 merges that didn't bump the file. Bumping here so the ratchet stays meaningful for the NEXT PR to gate against. Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply
added a commit
that referenced
this pull request
May 16, 2026
Joel's directive: 'ask for proof of performance concerns and then design harnesses.' This is step two (step one: airc broadcast asking for evidence is in flight). The architecture docs name performance covenants throughout — RAG composition < 500ms, vector search < 50ms, voice response < 3s, persona tick < 1ms, recall hot-path < 5ms on Air, working-set page-in < 1ms, governor current_policy() < 50ns, and ~30 more per-Part budgets in GENOME-FOUNDRY-SENTINEL. This document specifies the harnesses that turn the claims into evidence. Three principles: 1. Harnesses produce VDD records, not prose reports. The substrate's Standard VDD Record format (CBAR-SUBSTRATE §'Standard VDD Record') is the output of every harness. Humans paste it into PR comments; machines consume the JSONL form for regression detection. 2. Per-anchor scoping. Every harness runs against Air (UMA-16) + 5090 (discrete-32+64) at minimum. Intermediate hardware classes interpolate; explicit entries added as evidence accumulates. 3. Baseline-relative, not absolute. Pass/fail is RELATIVE to a committed baseline, not to a hand-written budget. Budgets bound expectations; baselines are the regression line. Sections: - Harness Anatomy: four-part Rust template (setup / scenario / measure / compare) with vdd_scope! instrumentation. Each harness ≤ 200 lines + a baseline JSON per hardware anchor. - Per-Anchor Scoping: concrete file paths for baselines per anchor. Missing baselines produce [Skipped: NoAirBaseline] — never silent pass. - Harness Catalog: 11 harnesses designed against substrate covenants: cold-start, persona-tick (< 1ms tick claim), rag-composition (< 500ms claim), vector-search (< 50ms claim), voice-response (< 3s claim), consolidation-phase, multi-persona-contention (validates A1-A3 invariants under load + prefix-share KV win), federation-gossip, speculation-hit-rate (validates Part 9 oscillation-free behavior), reprojection-confidence (validates CBAR-SUBSTRATE reprojection toolkit), governor-cascade (validates Part 11 hysteresis + restore-speculation-last rule), audit-recorder-roundtrip (gates regression on the just-shipped #1344). Each harness entry has: scenario, key VDD fields, pass thresholds for Air + 5090, cadence, baseline location. - Schema Extensions: typed extension structs per harness category (TickMetrics, CompositionMetrics, RecallMetrics, etc.). Base VDD Record stays uniform; extensions land alongside the harness that needs them. - Regression Detection: two layers. Layer 1 hard ceilings (covenant violations fail PR regardless of baseline). Layer 2 baseline delta (≤5% pass, 5-10% warn, 10-25% review-flag, >25% fail, ≥5% faster auto-suggests baseline update). Baselines are committed JSON; updating is a separate reviewable action. - CI Integration: tagged per-pr / weekly / nightly / release. A cargo continuum-vdd <harness> invocation runs harnesses locally; CI uses the same binary. - Harness Output Bundle: VDD record JSONL + reproducibility manifest TOML + human-readable summary markdown. All three under ~/.continuum/vdd/<sha>/<harness>/. - Pending Evidence-Driven Additions: placeholder section that fills in as the room responds to the perf evidence request. Each concrete data point becomes either a new harness, a sharpened pass-threshold, or a new VDD schema field. - Acceptance Criteria For The Framework: six checkpoints including the framework's own performance budget (< 50ms harness overhead excluding scenario). - 6 Open Questions including: where harnesses live in workspace, hardware availability for CI, handling noisy harnesses (P50/P99/ P99.9), baseline update authority, cross-harness regression detection, per-persona-shape harnesses. The framework lands with the airc broadcast in flight; specific harnesses will sharpen as evidence comes back from claude-tab-1 / codex / vhsm-d1f4 / the room. Doc-only. No code. Implementation lands as ALPHA-GAP Lane C (VDD telemetry substrate) — this doc is the spec. Co-authored-by: Test <test@test.com>
5 tasks
joelteply
added a commit
that referenced
this pull request
May 16, 2026
…e traits (+sentinel cleanup) (#1353) * feat(genome): working-set-manager PR-2 — WorkingSetManager + TierStore traits PR-2 of working-set-manager (MODULE-CATALOG §VII + GENOME-FOUNDRY- SENTINEL Parts 2/3/4). Trait surface on top of PR-1's typed data layer (#1346). No implementations — those are PR-3 + the per-role TierStore PRs. Mirrors the slice shape: PR-1 = data, PR-2 = traits, PR-3 = impl + wiring. Same pattern as CBAR-PIECE-2 (data #1321 → traits #1323 → dispatch #1339+#1343) and PIECE-5 (data #1331 → loader #1333 → probe #1335 → enforcement #1338). What lands - `genome::store::TierStore` — the trait every per-role tier implementation satisfies. Five methods: role / read / write / evict / capacity / observe_access. `Send + Sync + async_trait` for tokio concurrency. Used by working-set-manager (PR-3) as `Box<dyn TierStore>` per configured role. - `genome::manager::WorkingSetManager` — the top-level paging interface. Four methods this PR: page_in / page_out / working_set / audit_access. The fifth method `check_permission(actor, region, op)` from GENOME-FOUNDRY-SENTINEL Part 4 lands in PR-3 alongside the GenomeRegion + Op type definitions. - `genome::blob::ArtifactBlob` — bytes-side type for `TierStore::write`. Content-addressed via ArtifactId. NOT ts-rs-exported — large blobs don't belong on the TS wire. - `genome::blob::Provenance` — PR-2 minimal stub (artifact_id + created_at_ms). Full GENOME-FOUNDRY-SENTINEL Part 1 shape grows this type later without breaking the trait surface. Design refinements vs the raw spec - `working_set` returns `Option<&WorkingSet>` instead of `&WorkingSet`. Unregistered persona → `None` instead of fabricating an empty struct that masks wrong-persona-id bugs. - `page_in` returns `Result<PageHandle, PageFault>` per spec. Documented that PageFault is a typed observability signal, not a failure error — caller treats it as success-with-trace-event. Tests 13 new tests on genome::manager + genome::store + genome::blob: trait object-safety, dispatch through Arc/Box, audit_access denial shape, ArtifactBlob size invariant, Provenance wire shape. 48 genome:: tests total (PR-1's 35 + PR-2's 13). No regressions across the other 2487 lib tests. Stack #1339 / #1343 — CBAR-PIECE-2 PR-3 artifact dispatch (mine) #1344 — audit-recorder (codex's, subscribes to AccessDenied) #1346 — working-set-manager PR-1: data types (mine) THIS PR — working-set-manager PR-2: traits (mine) NEXT — working-set-manager PR-3: per-persona impl + PageFault / EvictionRecord publishing via artifact dispatch path Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(sentinel): remove dead self_clone — was masking under -D warnings test build Drift from canary HEAD: src/workers/continuum-core/src/modules/sentinel/mod.rs:1039 defined `let self_clone = Arc::new(self.sentinels.clone());` and never referenced it. The actual clone used downstream is `let sentinels = Arc::clone(&self.sentinels);` at line 1066 (now 1065 after this fix). Why it bit me: the test build for genome PR-2 (#1346 stack) `cargo test --lib --features metal,accelerate` is the gate the prepush hook runs, and that build has -D warnings effectively-on for unused_variables — so the warning became "error: could not compile." This blocks every Rust-touching push until fixed. Per Joel's boy-scout-rule + "Bugs from new users / new machines / new OS are GIFTS — fix the source, never hack": dead-code fix in place, sweeping as I go. This is NOT genome-PR-2 scope but is REQUIRED for the precommit gate to let genome-PR-2 through. Bundling here keeps the gate working; splitting it into a separate PR would block PR-2's push behind a fix that has nothing to do with PR-2's logic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(genome): scope uuid::Uuid import to test module in blob.rs Earlier fix in this branch removed `use uuid::Uuid;` from file scope because clippy on `cargo check --lib` flagged it unused. But the TEST module uses `Uuid::nil()` — `cargo test --lib` failed with E0433 "use of undeclared type Uuid" once the test build saw the references. Fix: move the import inside `#[cfg(test)] mod tests` so it lives where it's used. Clippy on the non-test build sees no Uuid usage in production code (correct — Provenance::minimal doesn't need it), and the test build sees the import where the test fixtures need it. 48/48 genome:: tests pass after the fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
joelteply
added a commit
that referenced
this pull request
May 16, 2026
…rocess impl (#1355) PR-3 of working-set-manager. Hangs the per-persona behaviors on the PR-1 data layer (#1346) + PR-2 trait surface (#1353). Pure local implementation — no MessageBus integration baked in (the trait's `page_in` Result already carries `PageFault` as the typed observability signal; callers wire to the artifact dispatch path #1339+#1343 themselves). Mirrors the slice shape: PR-1 = data, PR-2 = traits, PR-3 = impl. Same pattern as CBAR-PIECE-2 (data #1321 → traits #1323 → dispatch #1339+#1343) and PIECE-5 (data #1331 → loader #1333 → probe #1335 → enforcement #1338). What lands - `LocalWorkingSetManager` struct holding: - `Vec<Arc<dyn TierStore>>` — tier chain, ordered Fast → Frozen - `RwLock<HashMap<PersonaId, WorkingSet>>` — per-persona state - `RwLock<HashMap<PageRef, PersonaId>>` — page-ownership map for the MMU-style `audit_access` enforcement - Four trait method impls: - `page_in` — fast-path resident hit, otherwise walks tier chain top-down, returns PageFault with typed from_role/to_role (None from_role = true cold miss; Some = tier promotion) - `page_out` — removes from working set, observes target tier, skips pinned pages silently, returns `TierError::RoleNotConfigured` if the target tier isn't in the configured Vec - `working_set` — returns None per refined contract (lock-guard escape impossible through the trait signature; tests use the `working_set_snapshot` helper instead) - `audit_access` — checks page_owners map; returns typed `AccessDenied` with full context (actor + owner + reason) on cross-persona read - Two convenience methods: - `register_persona(persona, capacity)` — must be called before any page_in for the persona - `register_page_owner(page, owner)` — populates the MMU table - Diagnostic helper: - `working_set_snapshot(persona)` — clones for telemetry + tests Deliberately deferred (PR-4 or later) - MessageBus integration for PageFault/EvictionRecord publishing. The trait's Result<PageHandle, PageFault> contract gives caller- side observability today; bus publishing can stay caller-side too (and the artifact dispatch I shipped in #1339+#1343 is the publishing path when callers wire it). - Eviction policy invocation when target tier is at limit. PR-3 returns NoEvictionCandidate; PR-4 wires the callback so the manager observes + re-publishes the EvictionRecord. - `check_permission(actor, region, op)` — needs GenomeRegion + Op type definitions; lands with PR-4. Refinements to the PR-2 trait contract - `working_set` returns `None` because borrowing through the RwLock would expose the lock guard type and break the trait signature. Documented in the impl + the trait docstring. Tests + telemetry use `working_set_snapshot` (clone, not on hot path). Tests 8 new tests on genome::local_manager: - page_in_resident_returns_cached_without_tier_walk — hot-path correctness (whole point of a working set) - page_in_walks_tier_chain_and_records_promotion — Fast → Bench → Cold walk order, PageFault.from_role + to_role correctness - page_in_true_cold_miss_has_none_from_role — typed signal sentinel uses to distinguish "page never existed" - audit_access_denies_cross_persona_read — typed AccessDenied with full context, same contract PR-2's trait test pins - page_out_observes_target_tier_and_handles_unconfigured — typed RoleNotConfigured for "this hardware doesn't have that role" - page_out_skips_pinned_pages_silently — composition pin contract - working_set_snapshot_reflects_page_in_state — diagnostic helper - tier_count_reflects_configured_tiers — O(1) governor diagnostic 56 genome:: tests total (PR-1's 35 + PR-2's 13 + PR-3's 8). No regressions across other 2566 lib tests. Stack #1339 / #1343 — CBAR-PIECE-2 PR-3 artifact dispatch (mine) #1344 — audit-recorder (codex's, subscribes to AccessDenied) #1346 — working-set-manager PR-1: data types (mine) #1353 — working-set-manager PR-2: traits (mine) THIS PR — working-set-manager PR-3: per-process impl (mine) NEXT — PR-4: bus integration + eviction-callback wiring + check_permission + GenomeRegion/Op types Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merged
5 tasks
joelteply
added a commit
that referenced
this pull request
May 17, 2026
… publishing helpers (#1358) PR-4 of working-set-manager. Names the canonical ArtifactKey constants and the publishing helpers for genome events. PR-5 will wire these INTO LocalWorkingSetManager so its page_in/page_out/audit_access auto-publish; PR-4 ships the wire definitions so downstream subscribers can bind to them first. Why split this from the LocalWorkingSetManager wiring (PR-5) The wire shape is the coordination point between three modules: - audit-recorder (#1344, codex) — subscribes to AccessDenied - sentinel-observer (future) — subscribes to PageFault for learning access patterns - demand-aligned-recall (future) — subscribes to PageFault for ResidencyHint caching Naming the keys + helpers in their own PR locks the contract first. Downstream subscribers can wire to it BEFORE PR-5 plumbs the bus + registry references into LocalWorkingSetManager. Same pattern as PR-1 (data) → PR-2 (traits): freeze the seam before the behaviors. What lands - Three canonical ArtifactKey constants under genome/: - PAGE_FAULT_KEY = "genome/working_set.page_fault" - EVICTION_RECORD_KEY = "genome/working_set.eviction" - ACCESS_DENIED_KEY = "genome/working_set.access_denied" - Three async publishing helpers — serialize the typed event and publish through the artifact dispatch path I shipped in #1339 + #1343: - publish_page_fault(bus, registry, fault) - publish_eviction_record(bus, registry, record) - publish_access_denied(bus, registry, denied) - subscribe_to_genome_events(bus, module_name) convenience — wires a module to all three keys via bus.subscribe_artifact (#1343 path). - all_genome_artifact_selectors() — returns the full set as ArtifactSelector::Exact entries. Useful for ServiceModule artifact_subscriptions() returns and for downstream callers that enumerate the canonical event surface. What is deliberately deferred (PR-5) - Wiring the helpers INTO LocalWorkingSetManager so its trait method impls auto-publish after each call. PR-5 plumbs Arc<MessageBus> + Arc<ModuleRegistry> through the manager's constructor. - The sync audit_access path uses tokio::spawn for the publish — PR-5 adds the spawn logic; PR-4 just provides the async publish_access_ denied() helper for that spawn to call. Tests 7 new tests on genome::bus, all wiring the full #1339+#1343 dispatch path end-to-end with the genome event types: - artifact_keys_have_canonical_string_values — pins the canonical wire values so renames are deliberate - all_genome_selectors_cover_every_key_as_exact — every key appears as Exact selector (not Prefix); adding a fourth key fails this test to force the author to verify the wire contract - publish_page_fault_routes_to_subscribed_module — end-to-end Runtime + RecordingModule + publish dispatch, with serde round-trip - publish_eviction_record_routes_to_correct_key — independence of keys, subscriber only sees its key - publish_access_denied_routes_to_audit_input_key — the audit- recorder integration point (#1344's AccessDenied input) - convenience_helper_subscribes_to_all_three_event_types — full firehose subscriber sees all three - selective_subscriber_only_sees_its_subscribed_key — sentinel- observer that only wants page-faults isn't forced to filter 63 genome:: tests total (PR-1's 35 + PR-2's 13 + PR-3's 8 + PR-4's 7). No regressions across other 2582 lib tests. Stack #1339 / #1343 — CBAR-PIECE-2 PR-3 artifact dispatch + Prefix follow-up (mine; the dispatch path PR-4 publishes through) #1344 — audit-recorder (codex's, subscribes to AccessDenied) #1346 — working-set-manager PR-1: data types #1353 — working-set-manager PR-2: traits #1355 — working-set-manager PR-3: LocalWorkingSetManager THIS PR — working-set-manager PR-4: bus wire + helpers NEXT — PR-5: LocalWorkingSetManager auto-publish via these helpers Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply
added a commit
that referenced
this pull request
May 17, 2026
…publishes via bus hook (#1362) Closes the genome stack end-to-end. The artifact dispatch path I shipped in #1339+#1343 + the PR-4 publishing helpers + the PR-3 LocalWorkingSetManager all wire together so a persona's `page_in` / `audit_access` calls fan typed events out to subscribers (audit- recorder #1344 on AccessDenied, future sentinel-observer on PageFault, future demand-aligned-recall on PageFault). What lands - `LocalWorkingSetManager::with_bus(tiers, bus, registry)` — optional bus hook stored as `Option<BusHook>` on the manager. Constructed once at startup; switching publishing on/off mid- service would race + is not supported. - Auto-publish on: - `page_in` returning `PageFault` (true cold miss OR tier promotion) → publishes via `publish_page_fault` under `PAGE_FAULT_KEY` - `audit_access` returning `AccessDenied` → publishes via `publish_access_denied` under `ACCESS_DENIED_KEY` - Both via `tokio::runtime::Handle::try_current().spawn(...)` — see "Why spawn instead of await" below. - `LocalWorkingSetManager::new(tiers)` (PR-3 shape) preserved unchanged: bus-less mode for tests + standalone use. - `Runtime::bus_arc()` accessor added — returns Arc<MessageBus> for long-lived publishers (like LocalWorkingSetManager wired via with_bus) that need to hold their own bus reference. Why spawn instead of await `bus.publish` walks DashMap subscriber lists; the DashMap's `Map` trait impl is keyed by `&'static str` and that doesn't satisfy the "for any lifetime" requirement when the call sits inside a Send- bounded `async fn` (which `async_trait` generates for trait method impls). Spawning into a tokio task decouples the publish from the caller's Send-ness — the spawned future owns its Arc captures, no borrow crosses the await boundary in the caller. Sub-fix in MessageBus::publish While debugging the lifetime issue, found that `MessageBus::publish` held the DashMap borrow across the `await module.handle_event(...)` call inside both its glob_matched + artifact_matched walks. That's the actual root cause of the "DashMap is not general enough" error when publish is called from spawn-contexts. Refactored both walks to collect matching `module_name: &'static str` into a `Vec` first (dropping the DashMap borrow), then await dispatch from the Vec. Same semantics, no more borrow-across-await — `publish` is now safe to call from any Send-bounded async context. Tests 6 new tests on genome::local_manager::pr5 sub-section: - page_in_true_cold_miss_with_bus_publishes_page_fault — end-to-end Runtime + RecorderModule + with_bus + page_in → spawn → publish → subscriber. Yields with tokio::task::yield_now in a bounded loop to let the spawn complete (no fixed sleep). - page_in_tier_promotion_with_bus_publishes_correct_fields — from_role/to_role correctness through the spawn path. - page_in_resident_hit_with_bus_does_not_publish — resident-hit path stays silent (no noisy events for hot pages). - audit_access_denial_with_bus_publishes_via_spawn — same spawn pattern, but from the sync audit_access trait method. - audit_access_allowed_with_bus_does_not_publish — only denials are observable events. - bus_less_mode_does_not_publish_but_methods_work — backwards- compat for the standalone `new(tiers)` constructor. 69 genome:: tests total (PR-1's 35 + PR-2's 13 + PR-3's 8 + PR-4's 7 + PR-5's 6). All pass, no regressions across other 2615 lib tests. The MessageBus refactor is a load-bearing improvement to the bus itself — any future caller that wants to publish from a Send-bounded spawn context (which is most non-trivial integration code) benefits. Caught it on the genome integration; landing the fix here keeps the stack reviewable as one slice. Stack #1339 / #1343 — CBAR-PIECE-2 PR-3 artifact dispatch + Prefix follow-up (mine; the dispatch path PR-5 publishes through) #1344 — audit-recorder (codex's, now wired-in via AccessDenied) #1346 — working-set-manager PR-1: data types #1353 — working-set-manager PR-2: traits #1355 — working-set-manager PR-3: LocalWorkingSetManager #1358 — working-set-manager PR-4: bus keys + publishing helpers THIS PR — working-set-manager PR-5: auto-publish wiring (this is the architectural payoff of the whole genome stack) Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply
added a commit
that referenced
this pull request
May 18, 2026
…mentation Sketch (#1384) The 'Next Modules To Build' section + the audit-recorder Implementation Sketch I added in two follow-up commits on the original MODULE-CATALOG branch never made it to canary — the squash-merge of #1336 only captured the first commit (the initial 31-module catalog). Confirmed by checking the merged tree: catalog has Sections I-X but no queue + no per-module Implementation Sketch. This PR: 1. RESTORES the Next-Modules queue (now with checkmarks reflecting what's shipped): - #1 audit-recorder MERGED via #1344 - #2 threat-detector unclaimed, ready (Implementation Sketch below) - #3 working-set-manager MERGED end-to-end via PR-2/3/4/5 - #4 demand-aligned-recall MERGED end-to-end via PR-1 through PR-3f - #5 substrate-governor MERGED end-to-end via PR-1 through PR-3d plus newly unblocked next-tier: inference-llm, composer, speculator, reprojection-service, Lane D persona runtime frame. 2. INCLUDES the audit-recorder Implementation Sketch for reference (it's what the implementer copied from to produce #1344, even though it wasn't on canary at the time — they got it from the broadcast). 3. ADDS the threat-detector Implementation Sketch — catalog #2, next-up. ~260 LoC total for PR-1: - ThreatDetector trait (async inspect → Option<ThreatEvidence>) - ThreatDetectorModule that wakes on every RuntimeFrame and runs each registered detector - PromptInjectionDetector as the first ships-with-PR-1 detector (role-override patterns + length-attack heuristic) - 4 tokio tests covering: empty-list base case, role-override fires correctly, benign chat doesn't fire, pluggable-addition test that enforces P4 (evolving threat coverage) structurally - Memory cells deferred to PR-2; PR-1 ships stateless detectors This pluggable shape is the architectural answer to invariant P4 from PERSONA-COGNITION-CONTRACT: new threat patterns land as follow-up PRs adding a single ~50 LoC detector implementation with no changes to the substrate module itself. 4. NAMES what threat-detector unblocks downstream: - P4 invariant test (currently has no producer) - The PersonaDecision::Decline { AdversarialPattern } cognition path - audit-recorder's ThreatDetected subscription (currently dead; no producer until threat-detector ships) Doc-only change. No code touched. The Implementation Sketch is copy-pastable as the starting point for the next implementer. Co-authored-by: Test <test@test.com>
joelteply
added a commit
that referenced
this pull request
May 18, 2026
) Joel 2026-05-18: 'We need 100% Rust cognition sooner rather than later and proof it works. Solid recording and replay of persona, FROM PROD, not just dummy proof of concepts these guys always rig up. They need to up their game.' The substrate has shipped end-to-end in Rust over the last 48 hours (governor + working-set + recall + audit-recorder + check_redundancy oxidation, ~25+ PRs). None of it has been validated against production traffic. TurnReplayRecord type exists; no production turn has been recorded. Chat-roundtrip-live-harness exists; it consumes RuntimeFrame::synthetic_chat('hello'). Tests pass; demos work; behavior under real load — unknown. That's the gap. This document specifies the structural answer: a production-recording to deterministic-replay to bit-equal-validation loop where every persona turn in production produces a signed TurnReplayRecord that can be replayed against current substrate with deterministic-identical output, or fails loud with a typed ReplayDivergence. ## Four Substrate-Enforced Properties Property 1 — Every turn produces a signed TurnReplayRecord. Substrate enforces by type; persona-cognition handle_frame returns ModuleResult::Ok only after the record is signed. Property 2 — Records persist to a tamper-evident archive. ~/.continuum/replay/<turn_date>/<turn_id>.jsonl with chain-hash linking. Same shape as audit-recorder (#1344). Persona-private by default; federation requires explicit consent. Property 3 — Deterministic replay against current substrate. 'cargo replay <turn_id>' reconstructs substrate state (policy_version, working-set tier sizes, persona IdentityStateSnapshot), re-runs persona-cognition, produces a new record, diffs structured fields bit-equal. Three named divergence severities: BoundedNonDeterminism (logged), DecisionBoundaryCrossed (FAILS the harness), SubstrateStateDrift (flagged + rerun). Property 4 — Sentinel + harnesses consume records FROM PROD, not synthetic. Sentinel-AI attribution loop reads from the replay archive only; if archive is empty, emits NoTracesYet (explicit, not silent). Validation harnesses get a Tier-1 entry prod-replay-harness that consumes captured records and asserts bit-equal reproduction. ## Capture Discipline (Substrate-Enforced) 1. No synthetic-fixture path produces TurnReplayRecord. Test scaffolds construct synthetic frames but persona-cognition writes records ONLY when invoked through the production module-loop. Synthetic runs do not write to the archive. Prevents 'replay-harness passes against fake data' failure mode. 2. Sampling configurable; defaults 100%. High-volume deployments sample via governor policy; sampling decisions are themselves recorded. Per-persona consent applies; opted-out persona's turns produce no records, replay-harness skips with NotCaptured marker. 3. Privacy isolation structural. Cross-persona read requires explicit consent (same shape as engram sharing). 4. Records content-addressable. turn_id = content hash of (persona, frame_id, signature). Federation collisions are deterministic; no duplicates, no silent overwrites. ## Replay Discipline 1. Substrate-state reconstruction is faithful or refused. ReplayError::PolicyVersionUnknown when local doesn't have the recorded policy version. Never silently substituted. 2. Recall index snapshotted, not regenerated. Replay loads exact artifacts by content hash; ArtifactRetired error if any were retired in the meantime. Catches 'replay passes only because substrate evolved away from original state.' 3. Determinism boundaries named. BoundedNonDeterminism allowed for documented sources (parallel embedding order, tie-breaking); anything outside the documented set is DecisionBoundaryCrossed. 4. Replay cost = capture cost inverted. Capture sub-ms; replay bounded by original inference cost. Harnesses bound by turn count or wall-clock budget, feasible per-PR. ## End-To-End ASCII Flow Four-stage diagram showing: production capture → archive → deterministic replay → sentinel attribution → validation harness. Every step typed, every transition observable, every divergence has a named severity. ## Acceptance Criteria Capture: persona-cognition produces signed records on production path only (regression test asserts synthetic path produces 0 records, production path produces N for N turns). Archive append-only with chain-hash. Cross-persona read denied. Replay: bit-equal reproduction in structured-fields domain. Tampered record fails verify. Retired-artifact records surface ArtifactRetired not silent substitution. End-to-end: prod-replay-harness as Tier 1 in PERFORMANCE-HARNESS-FRAMEWORK; DecisionBoundaryCrossed divergence fails PR. Sentinel: reads from replay archive (not synthetic); smoke test empties archive, observes NoTracesYet emission; populates archive, observes attribution within one consolidation cycle. ## Why This Earns Its Space A 25-PR substrate landing is impressive volume but it's substrate scaffolding. Without prod-replay, every claim about behavior is 'the tests say so.' With prod-replay: a persona that drifted in production is reproducible bit-for-bit; sentinel's claims are checkable against real turn-by-turn evidence; regressions trip the harness before they can poison main; the 'rigged demo' gap is closed by structural enforcement, not by adding QA process. This is 100% Rust cognition + proof it works as substrate property, not as audit findings. ## Open Questions (6) Sampling under high load. Replay archive size growth + cold archive. Cross-substrate-version replay. Capture during sentinel refinement. Federated replay-records. The 'always rig up' failure mode the substrate must structurally prevent (synthetic path producing 0 records is the test). Doc-only PR. Implementation lands per Lane D + the next-tier cognition modules. This document specifies the alpha-gate. Co-authored-by: Test <test@test.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Per #1336 MODULE-CATALOG §VII
audit-recorder+ claude-tab-1's 22:10Z ranking putting this as the cleanest place to start (~200 LoC, no deps, unblocks the trace-bus landing for every downstream module).PR-1 ships pure data + thin disk I/O + tamper-evident chain. PR-2 wires to MessageBus via the
ArtifactSubscriptionsurface that PIECE-2 PR-3 (#1339/#1343) just landed.Why this module exists
Joel's "no silent fallback" rule + #1341
no_cpu_fallback_contractratchet REFUSALS at type-checking time. audit-recorder closes the next gap: making each individual refusal event OBSERVABLE in a tamper-evident log. "Cuda check refused at boot" / "governor overrode persona's chat lease" / "MMU denied genome cell access" are decisions that happened but nobody can prove in retrospect — the system did the right thing, quietly. The substrate needs a paper trail.What ships
src/workers/continuum-core/src/cognition/audit.rs:AuditEntryKindenum:Refusal | GovernorOverride | FederationPolicyDrift | AccessDenied. ts-rs kebab-case wire.AuditEntrystruct:seq + timestamp_ms + kind + payload(serde_json::Value, ts-rsunknown)+ chain_hash + prev_chain_hash.AuditChain— append-only writer with rolling hash state.new()for fresh;load(path)to resume;build_next()for pure derivation;append()for file-write.read_audit_log(path)— replay + verify chain integrity. Three failure modes:ChainBroken(hash mismatch = tampering),SequenceGap(missing entries),TimestampWentBackward(clock skew).AuditError— typed error withDisplay + std::error::Error + From<io::Error> + From<serde_json::Error>.JSON-Lines format (
audit.jsonl— one entry per line). Easy to grep, easy to tail.Tamper-evidence design (NOT cryptographic signing, by intent)
Tampering with entry N invalidates entries N+1..end. Verifier catches it on read with the typed
ChainBrokenerror. Asymmetric signing (prevents tampering rather than detecting it) lands when continuum-core gets a per-node identity key — separate concern.Test plan
19 passing on
cargo test --lib --features metal,accelerate cognition::audit::AuditEntryKindkebab-case serialization (4 variants)compute_chain_hashdeterministic + sensitive to every inputappend→read_audit_loground-tripread_audit_logon nonexistent path returns empty (first-boot)load()restores chain position from existing log (process restart)AuditErrortrait +FromimplsAuditEntryserde camelCaseVDD evidence
N/A — pure-data + thin I/O. Evidence lands with PR-2 (MessageBus wiring) when actual events flow through.
Stack
RefusalAudit/GovernorOverride/FederationPolicyDrift/AccessDeniedevent types viaArtifactSubscription; emitAuditEntryRecorded)Coordination
Codex broadcast a claim for audit-recorder at 22:16:50Z while this PR was already 95% done in this branch. Surfacing here to avoid duplicate work — codex will pivot to threat-detector or working-set-manager (next ranked modules in claude-tab-1's #1336 broadcast).