@@ -292,6 +292,35 @@ impl LanceMembrane {
292292 self . version . load ( Ordering :: Acquire )
293293 }
294294
295+ /// Append an externally-built commit row — the **action-commit** sole-writer
296+ /// sibling of [`ExternalMembrane::project`].
297+ ///
298+ /// Where `project()` projects a cognitive cycle (`ShaderBus` + `MetaWord`),
299+ /// `commit_event` takes a caller-built [`CognitiveEventRow`] directly. It is
300+ /// the seam the Rubicon `CommitHook` lowers onto: on entering the `Committed`
301+ /// lifecycle state, the binding builds the row from the OGAR
302+ /// `ActionInvocation` and calls this. (See `ractor_actors::state_machine`
303+ /// `CommitHook::on_commit` + `CROSS_SESSION_COORDINATION.md` grill #10.)
304+ ///
305+ /// Unlike `project()`, the action commit is the authoritative **audit** event
306+ /// (the Rubicon crossing / rubberstamp), so it ALWAYS ticks the version and
307+ /// fans out — the server filter / gate throttle cognitive-cycle fan-out, not
308+ /// an explicit committed action.
309+ ///
310+ /// Returns the new monotonic Lance version (the same counter
311+ /// [`version`](Self::version) reports; Phase D wires it to the Lance dataset
312+ /// version). Kept on the concrete `LanceMembrane`, NOT on the zero-dep
313+ /// `ExternalMembrane` trait, so the contract crate stays zero-dep and the
314+ /// action-commit path never forces the cognitive-cycle `ShaderBus` shape.
315+ pub fn commit_event ( & self , row : CognitiveEventRow ) -> u64 {
316+ let version = self . version . fetch_add ( 1 , Ordering :: AcqRel ) + 1 ;
317+ #[ cfg( feature = "realtime" ) ]
318+ self . watcher . bump ( row) ;
319+ #[ cfg( not( feature = "realtime" ) ) ]
320+ let _ = row; // without realtime there are no subscribers to fan out to
321+ version
322+ }
323+
295324 /// Set the faculty context for the current cycle.
296325 ///
297326 /// Called by the orchestration layer (not by `ingest`) when
@@ -519,6 +548,21 @@ mod tests {
519548 ) ;
520549 }
521550
551+ #[ test]
552+ fn commit_event_ticks_version_and_returns_new ( ) {
553+ // The action-commit sole-writer sibling: each call ticks the monotonic
554+ // Lance version and returns the new value (the Rubicon crossing's audit
555+ // version). Mirrors the OGAR `CommitHook::on_commit` lowering.
556+ let m = LanceMembrane :: new ( ) ;
557+ assert_eq ! ( m. version( ) , 0 ) ;
558+ let v1 = m. commit_event ( crate :: external_intent:: CognitiveEventRow :: default ( ) ) ;
559+ assert_eq ! ( v1, 1 ) ;
560+ assert_eq ! ( m. version( ) , 1 ) ;
561+ let v2 = m. commit_event ( crate :: external_intent:: CognitiveEventRow :: default ( ) ) ;
562+ assert_eq ! ( v2, 2 ) ;
563+ assert_eq ! ( m. version( ) , 2 ) ;
564+ }
565+
522566 #[ test]
523567 fn project_emits_scalar_row ( ) {
524568 let m = LanceMembrane :: new ( ) ;
0 commit comments