Skip to main content

DiscourseState

Struct DiscourseState 

Source
pub struct DiscourseState { /* private fields */ }
Expand description

Tracks discourse state across multiple render calls for natural output.

This is the engine’s internal memory — it knows what entities were recently mentioned, what templates were recently used, what connectives were recently inserted, and what words appeared in recent output.

Implementations§

Source§

impl DiscourseState

Source

pub fn new() -> Self

Source

pub fn set_focus_plural(&mut self, plural: bool)

Mark the current focus as a compound/plural subject so the next pronoun reference uses “they” rather than “it”.

Source

pub fn focus_is_plural(&self) -> bool

Whether the current focus is a plural/compound subject.

Source

pub fn reset(&mut self)

Clear ALL discourse state, including the cross-paragraph list-style cycle counter. Use when starting a fully unrelated narrative — most callers want Self::reset_for_paragraph instead so consecutive paragraphs continue to rotate list-style phrasings.

Source

pub fn reset_for_paragraph(&mut self)

Clear discourse state at a paragraph boundary while preserving the narrative-level stylistic anti-repeat machinery. This is the reset used by [Session::reset_for_paragraph] so multi-paragraph narratives don’t restart variant cycles, list-style rotation, word-repetition penalties, or sentence-rhythm memory on every paragraph break.

Preserved (narrative-level): last_list_style and recent_list_styles (list-style cycle plus anti-repeat window), template_history (variant anti-repeat), connective_history (connective anti-repeat), word_history plus interner (repetition scoring), sentence_length_history (cadence/rhythm scoring), render_index (so word-history distances stay correct and has_prior_render keeps reporting earlier discourse exists).

Cleared (paragraph-local): the entity table, focus entity and its plurality, last_template_key/last_entity_name (so cross-paragraph relation/connective inference is suppressed), the Centering Theory Cb/Cf machinery (cb, previous_focus, current_cf, previous_cf, last_transition), and per-render diagnostic signals.

The clearance set is the load-bearing invariant: anaphora must not resolve to entities introduced in an earlier paragraph, and rhetorical connectives (“Furthermore,”, “However,”) must not jump paragraph boundaries.

Source

pub fn reset_list_cycle(&mut self)

Clear only the list-style cycle counter and its anti-repeat window. Mirrors [Session::reset_temporal] for callers that want to start a fresh list-style rotation without otherwise resetting discourse state.

Source

pub fn begin_render(&mut self)

Advance to the next render. Must be called at the start of each render.

Source

pub fn mention_entity(&mut self, name: &str, entity_type: &str)

Record that an entity was mentioned in the current render at rank 0 (Subject position). Delegates to Self::mention_entity_ranked.

Resets the focus-plural flag — compound subjects must mark themselves explicitly via Self::set_focus_plural.

Source

pub fn mention_entity_ranked(&mut self, name: &str, entity_type: &str, rank: u8)

Record that an entity was mentioned in the current render with an explicit grammatical-role rank. Lower rank = more prominent.

Rank convention:

  • 0: Subject (most prominent — the Cp candidate)
  • 1: Direct Object
  • 2: Indirect Object / Location
  • 3+: Oblique / other

The entity is inserted into current_cf in rank-ascending order. If the entity is already in the Cf list, the lower of the two ranks is kept (a subject mention always beats an object mention).

focus_entity is updated when rank == 0 or when no focus has been set yet for this render; this keeps the Cp semantics: the Subject is the preferred center.

Source

pub fn reference_form_with_density( &self, name: &str, density_low: bool, density_high: bool, ) -> ReferenceForm

Profile-aware variant of Self::reference_form.

PronounDensity::Default is identical to reference_form. Low demotes any computed Pronoun to ShortName, biasing toward formal register that keeps full names visible longer. High promotes a ShortName to Pronoun when the entity is recent enough (distance ≤ 2) and not in an ambiguity context — biasing toward conversational register.

Source

pub fn reference_form(&self, name: &str) -> ReferenceForm

Determine how to refer to an entity given discourse history.

Source

pub fn record_template_choice(&mut self, key: &str, variant_index: usize)

Record which template variant was selected for anti-repeat.

Source

pub fn last_template_variant(&self, key: &str) -> Option<usize>

Get the last variant index used for a key (to avoid repeating it).

Source

pub fn detect_relation( &self, current_key: &str, current_entity: Option<&str>, ) -> DiscourseRelation

Detect the relationship between the current render and the previous one.

Both entities must be present (and comparable) to assert a “same entity” or “different entity” relationship — otherwise the engine would incorrectly emit e.g. a Similarly, connective for a repeated entity-less template, where no entity comparison is actually meaningful.

Source

pub fn select_connective( &mut self, relation: &DiscourseRelation, ) -> Option<&'static str>

Select a discourse connective for the given relation, preferring candidates absent from recent history. Three deterministic guardrails layer on top of the LRU pick:

  1. Connector-family budget. Each pool maps to a lexical family (continuation, similarity, contrast). When the family already contributes pool.len() emissions inside the trailing FAMILY_WINDOW, return None so the next sentence renders plain. This is the lever that breaks the Similarly,/Likewise,/Similarly,/Likewise, pattern Matt flagged in service-shape prose: the two-element similarity pool is forced to alternate after two emissions, so the third call drops the connective entirely.
  2. Exact-connector cooldown. The immediately preceding connective is excluded from candidacy when the pool offers an alternative — preserves the existing back-to-back anti-repeat.
  3. A/B alternation penalty. Candidates equal to connective_history[len-2] take a score deduction so the LRU pick will not extend an A/B pattern into A/B/A when a fresh option exists. For three-element pools this preserves the A,B,C cycle; for two-element pools the family budget kicks in first and the penalty is moot.
Source

pub fn select_connective_filtered( &mut self, relation: &DiscourseRelation, allowed: Option<&[&str]>, preferred: Option<&[(&str, f32)]>, forbidden: Option<&[&str]>, ) -> Option<&'static str>

Profile-aware variant of Self::select_connective.

allowed (when Some) restricts the candidate pool to connectives also present in the slice. If the resulting pool is empty (every allowed entry was filtered by the existing anti-repeat or family budget logic, OR no allowed entries match the base pool at all), the engine falls back to the unfiltered base pool — profile preferences are biases, never hard constraints.

preferred (when Some) adds a per-connective tie-breaker bonus to the existing distance/alternation score. Weights are interpreted in 0.0..=1.0 and scaled by 10 to land in the same rough magnitude as the existing scoring terms.

forbidden (when Some) is a strict subtractive filter applied after the allowed/fallback computation — used by the retrospective refine pass for BlacklistConnective constraints. Unlike allowed, an empty post-forbidden pool emits None rather than falling back: that’s the whole point of a blacklist.

Source

pub fn record_output_words(&mut self, output: &str)

Record the words from a rendered output for repetition scoring.

Source

pub fn sentence_length_iter(&self) -> impl Iterator<Item = usize> + '_

Iterate over the recent sentence-length history (newest last). Each value is the word count of one emitted sentence inside the rhythm-tracking window. Exposed for profile-aware scorers that need to read the cadence buffer without snapshotting the whole session — the buffer is short and read-only from outside.

Source

pub fn record_sentence_rhythm(&mut self, output: &str)

Record word counts for the sentences emitted by the committed render.

Source

pub fn repetition_score(&self, candidate: &str) -> f64

Score a candidate output for repetition against recent history. Lower score = less repetition = better.

Source

pub fn sentence_rhythm_score(&self, candidate: &str) -> f64

Score a candidate output against recent sentence-length cadence. Lower is better: candidates with sentence lengths that were just emitted receive a penalty, while noticeably shorter or longer variants are preferred when repetition scores are otherwise close.

In addition to the per-sentence closeness/mean components, a bounded same-side penalty fires for each consecutive sentence pair (history → candidate, then candidate → candidate) that lands on the same side of the running mean. This nudges the selector toward burst-pivot cadence — alternating short/long around the mean — which is a hallmark of natural prose. The penalty is purely additive and capped per sentence so it cannot zero out repetition penalties or push the score negative.

Source

pub fn word_frequency(&self, word: &str) -> f64

Recency-weighted frequency of a specific word in recent output. Higher numbers mean the word has appeared recently and/or often. Used to pick the least-recently-used synonym from a registered group for elegant variation.

Source

pub fn next_list_style(&mut self) -> ListStyle

Select the next list style. Walks LIST_STYLES deterministically from last_list_style forward and returns the first style that is not in the recent-window (recent_list_styles). The walk advances past the chosen slot so subsequent calls progress through the palette rather than locking onto the first non-recent slot.

Anti-repeat is fully deterministic — no RNG dependency — and ensures that an explicit forced style (e.g. {|join:bracketed} recorded via Self::record_list_style_used) does not collide with the very next auto-cycle pick. Falls back to the modulo slot if every style somehow sits in the recent window (unreachable while LIST_STYLE_RECENT_WINDOW < LIST_STYLES.len(), but kept defensive).

Source

pub fn next_list_style_with_bias( &mut self, bias: Option<ListStyle>, ) -> ListStyle

Profile-aware variant of Self::next_list_style.

When bias is Some(target) and target is not currently inside the anti-repeat window, the cycle advances to the slot just past target and emits it. When bias is None (i.e., the profile’s ListStyleBias::Auto default), or when the bias target is in the recent window, the natural cycle picks as in next_list_style. The bias is a preference, not an override — anti-repeat always wins.

Source

pub fn record_list_style_used(&mut self, style: ListStyle)

Record an explicit list style (e.g. {|join:bracketed}) for diagnostics AND anti-repeat. Forced styles count toward the recent window so a subsequent auto-cycle pick won’t immediately repeat the forced phrasing.

Source

pub fn last_list_style_used(&self) -> Option<ListStyle>

List style applied by the most recent render’s |join pipe (if any).

Source

pub fn set_cleanup_stripped_tail(&mut self, stripped: bool)

Record whether Silent-mode cleanup stripped any trailing orphan words during the most recent render.

Source

pub fn last_cleanup_stripped_tail(&self) -> bool

Whether the most recent render’s cleanup pass removed trailing orphan words (Silent strictness only). false in other modes.

Source

pub fn is_first_render(&self) -> bool

Whether this is the first render (no prior discourse context).

Source

pub fn has_prior_render(&self) -> bool

Whether a prior render happened in this discourse scope, used by the {noun|demonstrative} pipe to decide between “this X” and “the X”. Cleared by reset().

Source

pub fn advance_cb(&mut self)

Advance Cb tracking for the next render. Call this after all mutations from the current render (mention_entity, record_output_words) have completed and the render has committed. On render failure the Session snapshot/restore path will roll back cb and previous_focus along with all other fields via Clone.

Called by Engine::render_tx at the end of each successful render.

Source

pub fn last_transition(&self) -> Transition

The Centering Theory transition class from the most recent advance_cb call. Returns Transition::NoCb before any render or after a reset.

Source

pub fn cb(&self) -> Option<&str>

The current backward-looking center, if any.

Source

pub fn cf(&self) -> &[Cf]

The forward-looking centers being built during the current render, ordered by rank ascending (Cp = first element).

Source

pub fn previous_cf(&self) -> &[Cf]

The forward-looking centers from the previous render.

Trait Implementations§

Source§

impl Clone for DiscourseState

Source§

fn clone(&self) -> DiscourseState

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DiscourseState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for DiscourseState

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.