Skip to main content

frame_conv/
lib.rs

1//! Conversation patterns over the liminal participant substrate —
2//! request-response and subscription (F-3a), pub/sub and the workflow
3//! facade (F-3b): the four patterns this crate maps onto conversations
4//! so components interact through conversations rather than direct
5//! function calls.
6//!
7//! # What is here
8//!
9//! - [`ConversationHandle`] — the transport-agnostic entry (design D4): no
10//!   signature names a transport, and the embedded transport arrives later
11//!   behind these same types.
12//! - **Request-response** (`frame:conv-request@v1`): typed request with a
13//!   caller-supplied deadline riding the push-side wall; closed outcome set
14//!   ([`RequestOutcome`]); late and duplicate replies have defined, observable
15//!   fates on the typed anomaly surface ([`Anomaly`]).
16//! - **Subscription** (`frame:conv-subscription@v1`): typed events in the
17//!   substrate's proven delivery order ([`SubscriptionItem`] documents the
18//!   strength: ordered, contiguous, sender-excluded, membership-forward).
19//! - The caller-owned resume boundary ([`ResumeStore`], [`JoinGrant`]):
20//!   restore-then-reattach resume replaying the unacked window from the
21//!   committed cursor (F-0c §R4, proven).
22//! - **Pub/sub** (`frame:conv-pubsub@v1`): caller-minted
23//!   [`PublicationId`], substrate-only fan-out, O(1) sequence dedup,
24//!   typed [`PublicationItem`] stream with membership news and the typed
25//!   gap contract (F-3b R1; the A4-superseded honest contract is in the
26//!   module docs).
27//! - **The workflow pattern** ([`workflow`]) — one durable conversation
28//!   as a typed facade over exactly one aion workflow/run lineage (F-3b
29//!   R2): explicit-key open with the honest weaker idempotency contract,
30//!   reconstruction from held identity, reopen of terminal reopenable
31//!   runs, typed contributions, and event-driven observation with the
32//!   exhaustive progress/terminal projection.
33//!
34//! # What is deliberately NOT here (seams named)
35//!
36//! - **The embedded transport** — a later optimization behind the SAME
37//!   handle types (design D4); its absence is stated, not implied away.
38//! - **A schema-as-data registry** — v1's schema IS the typed Rust message
39//!   and validation IS serde at both ends (F-3a R1's pinned ruling).
40//!
41//! # Honest gates carried from the substrate characterization
42//!
43//! Characterized at published liminal 0.3.0 (`docs/briefs/F-0c-FINDINGS.md`)
44//! and RE-CHARACTERIZED at published liminal 0.3.1 — the early-car
45//! republish, whose 0.3.0→0.3.1 delta is a haematite 0.6.1 repin plus a
46//! dropped always-None config field — by re-running this crate's entire
47//! battery, including every live-server suite, green against the =0.3.1
48//! pin (2026-07-21, chore/liminal-031-consume). Every gate below held
49//! unchanged at 0.3.1:
50//!
51//! - **Peer death surfaces typed, before the deadline (ASK-4 discharged at
52//!   liminal 0.3.2).** Responder death mid-request is delivered, not waited
53//!   out: the caller observes [`RequestOutcome::ResponderFailed`] ahead of
54//!   the deadline wall, and the subscription stream carries the death
55//!   exactly once as [`SubscriptionItem::PeerFailed`] — one death, one
56//!   delivery per surface (proven at the socket,
57//!   `tests/pattern_crash_resume.rs`). The 0.3.0/0.3.1 truth this bullet
58//!   originally recorded — silence, no live producer for the typed
59//!   mapping — was superseded when the upstream death-delivery unit landed;
60//!   the deadline remains the wall only when nothing is there to die.
61//! - **The receive quantum is hardcoded upstream (upstream ASK-2).** The
62//!   substrate's 5-second IO quantum is not caller-settable and an elapsed
63//!   quantum is distinguishable from a dead socket only by error text; this
64//!   crate isolates that seam in one place, treats elapse as a benign
65//!   re-arm, and every wait parameter it exposes is a pure wait quantum —
66//!   an elapsed wait returns `Ok(None)`-shaped quiet, never a protocol
67//!   outcome.
68//! - **No backpressure vocabulary exists on the participant surface.** A
69//!   slow consumer surfaces nothing to anyone (F-0c §R5); this crate adds
70//!   no parallel vocabulary and will inherit the substrate's typed
71//!   Accept/Defer/Reject home when the upstream wiring lands (F-3a R5).
72
73pub mod action_dispatch;
74pub mod anomaly;
75pub mod config;
76pub mod envelope;
77pub mod error;
78pub mod handle;
79pub mod id;
80pub mod outcome;
81pub mod store;
82pub mod workflow;
83
84pub(crate) mod finite;
85pub(crate) mod seam;
86pub(crate) mod track;
87
88pub use action_dispatch::{
89    ActionDispatchError, ActionDispatchOutcome, conversation_for_action, dispatch_action,
90};
91pub use anomaly::{Anomaly, AnomalyCounters};
92pub use config::BusAttachment;
93pub use envelope::Envelope;
94pub use error::{
95    AttachError, CallError, CursorCommit, EnvelopeError, LeaveError, PublishError, RefusalClass,
96    StoreError,
97};
98pub use handle::ConversationHandle;
99pub use id::{
100    ConversationId, ConversationSeq, CorrelationId, MessageKind, ParticipantRef, PatternId,
101    PublicationId,
102};
103pub use outcome::{
104    DepartReason, InboundRequest, IncomingRequest, JoinCredential, JoinGrant, LeaveOutcome,
105    PublicationItem, PublishReceipt, RequestOutcome, SubscriptionItem,
106};
107pub use store::ResumeStore;