moon-fsm

An auditable, type-safe workflow state machine library for MoonBit.

moon add Rz-coder8848/moon-fsm@0.3.0
Download zip
Version
0.3.0
License
Apache-2.0
Last updated
7 hours ago
Downloads
20
README

#MoonBit-FSM

moon-fsm is an auditable finite state machine component for MoonBit projects that need workflow-style state progression without adopting a full BPM runtime. The remediation release for OSC2026 focuses on reviewable engineering value: structured transition errors, context-updating actions, execution history, validator reports, workflow-oriented examples, and reproducible CI.

#Package Identity

#Why This Library

Typical uses for this package include:

  • approval and review workflows
  • device and UI state orchestration
  • agent or simulation state control
  • teaching and documenting transition-heavy business rules

The library keeps the public surface small while making the transition path auditable in code review and acceptance review.

#Re-Review Capabilities

  • Typed builder API with guarded transitions and transition actions.
  • Structured runtime errors via try_send(event) -> Result[Unit, TransitionError].
  • Compatibility layer via send(event) -> Result[Unit, String].
  • Transition history through history().
  • Checkpoint and rollback through checkpoint() and restore(snapshot).
  • Ordered best-effort event batches through try_send_all(events), with per-event outcomes and explicit compensation support.
  • Execution metrics and an audit log for accepted and rejected attempts.
  • Validator reports for unreachable states, dead ends, duplicate transitions, and states without outgoing edges.
  • Mermaid export with guard and action annotations.
  • Lifecycle hook coverage with explicit tests for on_enter / on_exit.
  • Four-domain, 44-case benchmark corpus covering approval, order, device, and support workflows with deterministic expected outcomes.
  • Bounded retry policies and rejection budgets for integrations that need explicit error-storm protection without hiding failures.
  • Graph analysis with cycle, branching, terminal-state, reachability, and deterministic workflow-risk reports.
  • Operational journal with severity levels, ticket queries, acknowledgements, audit-log ingestion, SLA evaluation, and closure-gate summaries.
  • Production incident-response and customer-support runbooks covering escalation, mitigation, customer waiting, rollback, handover, and closure.
  • 44 deterministic benchmark scenarios and 52 executable tests across the library, support-ticket, and incident-response domains.
  • Boundary regression tests for empty machines, dead ends, blocked guards, unknown events, duplicate definitions, history ordering, and empty exports.
  • Runnable workflow examples and acceptance-oriented CI.

#Install

moon add Rz-coder8848/moon-fsm

#Minimal Example

let builder : @fsm.Builder[String, String, Int] = @fsm.Builder::new()
.transition_do("Draft", "Submit", "Review", fn(_s, _e, ctx) { ctx + 1 })
.transition_if_do(
"Review",
"Approve",
"Approved",
fn(_s, _e, ctx) { ctx >= 2 },
fn(_s, _e, ctx) { ctx + 10 },
)

let engine = builder.build("Draft", 1)
ignore(engine.try_send("Submit"))

#Workflow Example

The remediation release adds a composite approval workflow example:

stateDiagram-v2 Draft --> Review.Pending : Submit [action] Review.Pending --> Review.Approved : Approve [guard] [action] Review.Pending --> Review.Rework : RequestChanges Review.Pending --> Cancelled : Cancel Review.Pending --> Review.Rejected : Reject Review.Rework --> Review.Pending : Resubmit [action] Review.Rework --> Cancelled : Cancel Review.Rejected --> Error.Validation : Escalate Review.Approved --> Closed : Archive

The expanded order workflow demonstrates context actions, a guarded shipment, terminal error handling, lifecycle hooks, batch outcomes, and compensation:

stateDiagram-v2 Created --> Paid : Pay [action] Paid --> Packed : Pack [action] Packed --> Shipped : Ship [guard] [action] Shipped --> Delivered : Deliver Paid --> Cancelled : Cancel Packed --> Cancelled : Cancel Shipped --> Returned : Return [action]

Run it locally with:

moon run examples/approval_workflow moon run examples/order_workflow

Run the reproducible workflow benchmark corpus:

moon run benchmarks

The benchmark is a scenario benchmark rather than a hardware-dependent throughput claim. Its input cases are checked in under benchmarks/data/workflow_cases.csv, and the runner verifies expected final states, successful transitions, rejected events, successful history lengths, and one audit entry for every event attempt.

The vending machine example was further revised after the formal acceptance feedback on July 17, 2026. It no longer relies on duplicate (state, event) definitions, and now demonstrates a blocked purchase attempt followed by a successful retry after more coins are inserted.

#Core API

  • Builder::new() creates a workflow definition.
  • transition() and transition_if() add plain and guarded transitions.
  • transition_do() and transition_if_do() attach context-updating actions.
  • build() materializes an Engine.
  • try_send() returns TransitionError values for structured handling.
  • history() returns successful transition records.
  • checkpoint() and restore() provide explicit state/context/history snapshots for compensating workflows.
  • try_send_all() returns ordered BatchReport outcomes without silently stopping at the first rejected event.
  • metrics() and audit_log() expose execution evidence; reset_metrics() clears counters and audit entries while retaining the current workflow state.
  • last_error() exposes the most recent runtime failure.
  • validate_report() summarizes reachability and duplicate-definition issues.
  • to_mermaid() exports reviewer-friendly diagrams.

API details live in docs/api_reference.md.

#Examples

  • moon run examples/traffic_light
  • moon run examples/vending_machine
  • moon run examples/game_npc
  • moon run examples/approval_workflow
  • moon run examples/order_workflow
  • moon run examples/support_workflow
  • moon run examples/incident_workflow
  • moon run cmd/fsm-cli

#Verification

The current MoonBit 0.10.3-compatible verification set is:

moon version --all moon fmt --check moon info moon check --deny-warn --target all moon test --deny-warn --target all powershell -ExecutionPolicy Bypass -File scripts/verify_acceptance.ps1 -SkipMooncakes moon run benchmarks moon publish --dry-run

moon fmt --deny-warn and moon info --deny-warn are not used because the current CLI does not expose those flags; the repository instead runs the equivalent supported checks above. On Windows machines without a system C compiler, local moon test --deny-warn --target all may stop at the native target; the CI workflow remains the source of truth for full multi-target coverage.

#Release Alignment

  • 0.1.0 was the initial Mooncakes publication.
  • 0.1.1 was the first OSC2026 re-review remediation release.
  • 0.2.0 is the workflow-runtime expansion release with snapshots, batch dispatch, metrics, audit records, a 32-case corpus, and a runnable order workflow.
  • 0.2.1 is the MoonBit 0.10.3 compatibility patch for executable package configuration.
  • 0.3.0 adds reusable retry, rejection-budget, graph-analysis, operational journal, SLA, support-ticket, incident-response, and runbook APIs.
  • Release alignment details live in docs/release-alignment.md.

#Documentation

#Notes For Reviewers

  • GitHub and GitLink are both public review surfaces for the same codebase.
  • Generated build output is intentionally excluded from version control.
  • The checked-in competition material is 申报书.md.

#Contributing

Small, reviewable changes are preferred. Before opening a PR, run the same verification commands listed above and keep examples executable.

#
Callback

type Callback[S, E, Ctx] = (S, E, Ctx) -> Unit

A callback function that executes during a state lifecycle hook.

#
Guard

type Guard[S, E, Ctx] = (S, E, Ctx) -> Bool

A guard function that determines if a transition is allowed.

#
TransitionAction

type TransitionAction[S, E, Ctx] = (S, E, Ctx) -> Ctx

A transition action that returns the next context value for a transition.

#
AuditRecord

pub(all) struct AuditRecord[S, E] {
from : S
to : S
event : E
success : Bool
error : TransitionError?
history_index : Int?
}

Complete audit entry for one event attempt.

#
BatchReport

pub(all) struct BatchReport[E] {
outcomes : Array[DispatchOutcome[E]]
successful : Int
rejected : Int
complete : Bool
}

Summary of an ordered, best-effort event batch.

#
BudgetReport

pub(all) struct BudgetReport[E] {
outcomes : Array[DispatchOutcome[E]]
successful : Int
rejected : Int
processed : Int
stopped : Bool
}

A budgeted event dispatch stops after too many rejected attempts.

#
Builder

pub(all) struct Builder[S, E, Ctx] {
config : EngineConfig[S, E, Ctx]
}

A Builder for constructing finite state machines declaratively.

#
Builder::build

fn[S : Hash + Eq, E : Hash + Eq, Ctx] Builder::build(self : Builder[S, E, Ctx], initial_state : S, initial_context : Ctx) -> Engine[S, E, Ctx]

Builds the FSM runtime engine starting at the given state.

#
Builder::new

fn[S : Hash + Eq, E, Ctx] Builder::new() -> Builder[S, E, Ctx]

Creates a new FSM Builder.

#
Builder::on_enter

fn[S : Hash + Eq, E, Ctx] Builder::on_enter(self : Builder[S, E, Ctx], state : S, callback : (S, E, Ctx) -> Unit) -> Builder[S, E, Ctx]

Registers a callback to be executed when entering a specific state.

#
Builder::on_exit

fn[S : Hash + Eq, E, Ctx] Builder::on_exit(self : Builder[S, E, Ctx], state : S, callback : (S, E, Ctx) -> Unit) -> Builder[S, E, Ctx]

Registers a callback to be executed when exiting a specific state.

#
Builder::transition

fn[S, E, Ctx] Builder::transition(self : Builder[S, E, Ctx], from : S, event : E, to : S) -> Builder[S, E, Ctx]

Adds a transition from one state to another triggered by an event.

#
Builder::transition_do

fn[S, E, Ctx] Builder::transition_do(self : Builder[S, E, Ctx], from : S, event : E, to : S, action : (S, E, Ctx) -> Ctx) -> Builder[S, E, Ctx]

Adds a transition with a context-updating action.

#
Builder::transition_if

fn[S, E, Ctx] Builder::transition_if(self : Builder[S, E, Ctx], from : S, event : E, to : S, guard_cond : (S, E, Ctx) -> Bool) -> Builder[S, E, Ctx]

Adds a transition with a guard condition.

#
Builder::transition_if_do

fn[S, E, Ctx] Builder::transition_if_do(self : Builder[S, E, Ctx], from : S, event : E, to : S, guard_cond : (S, E, Ctx) -> Bool, action : (S, E, Ctx) -> Ctx) -> Builder[S, E, Ctx]

Adds a guarded transition with a context-updating action.

#
ContextManager

pub(all) struct ContextManager[Ctx] {
inner : Ctx
}

Internal context manager structure. Abstracting this logic allows future expansion for nested context trees.

#
ContextManager::get

fn[Ctx] ContextManager::get(self : ContextManager[Ctx]) -> Ctx

Retrieves the current context value.

#
ContextManager::new

fn[Ctx] ContextManager::new(initial : Ctx) -> ContextManager[Ctx]

Creates a new ContextManager.

#
ContextManager::set

fn[Ctx] ContextManager::set(self : ContextManager[Ctx], val : Ctx) -> Unit

Sets a new context value.

#
DispatchOutcome

pub(all) struct DispatchOutcome[E] {
event : E
success : Bool
error : TransitionError?
}

The result of one event attempt in an ordered batch dispatch.

#
DuplicateTransition

pub(all) struct DuplicateTransition[S, E] {
from : S
event : E
} derive(Eq)

A duplicate transition entry discovered during validation.

#
Engine

pub(all) struct Engine[S, E, Ctx] {
transitions : Map[S, Map[E, S]]
guards : Map[S, Map[E, (S, E, Ctx) -> Bool]]
actions : Map[S, Map[E, (S, E, Ctx) -> Ctx]]
on_enter : Map[S, (S, E, Ctx) -> Unit]
on_exit : Map[S, (S, E, Ctx) -> Unit]
history_entries : Array[TransitionRecord[S, E]]
audit_entries : Array[AuditRecord[S, E]]
metrics_value : ExecutionMetrics
current_state : S
context : Ctx
last_error_value : TransitionError?
build_error : TransitionError?
}

The runtime instance of the state machine.

#
Engine::audit_log

fn[S, E, Ctx] Engine::audit_log(self : Engine[S, E, Ctx]) -> Array[AuditRecord[S, E]]

Returns the complete event-attempt audit log.

#
Engine::checkpoint

fn[S, E, Ctx] Engine::checkpoint(self : Engine[S, E, Ctx]) -> EngineSnapshot[S, E, Ctx]

Captures the observable runtime state of an engine.

#
Engine::context

fn[S, E, Ctx] Engine::context(self : Engine[S, E, Ctx]) -> Ctx

Retrieves the current context of the engine.

#
Engine::history

fn[S, E, Ctx] Engine::history(self : Engine[S, E, Ctx]) -> Array[TransitionRecord[S, E]]

Returns the successful transition history.

#
Engine::last_error

fn[S, E, Ctx] Engine::last_error(self : Engine[S, E, Ctx]) -> TransitionError?

Returns the most recent transition error, if any.

#
Engine::metrics

fn[S, E, Ctx] Engine::metrics(self : Engine[S, E, Ctx]) -> ExecutionMetrics

Returns a copy of the execution metrics.

#
Engine::reset_metrics

fn[S, E, Ctx] Engine::reset_metrics(self : Engine[S, E, Ctx]) -> Unit

Resets metrics and audit entries without changing workflow state.

#
Engine::restore

fn[S, E, Ctx] Engine::restore(self : Engine[S, E, Ctx], snapshot : EngineSnapshot[S, E, Ctx]) -> Unit

Restores state, history, audit records, metrics, and the last error.

#
Engine::send

fn[S : Hash + Eq, E : Hash + Eq, Ctx] Engine::send(self : Engine[S, E, Ctx], event : E) -> Result[Unit, String]

Sends an event to the state machine engine to trigger a transition.

#
Engine::state

fn[S, E, Ctx] Engine::state(self : Engine[S, E, Ctx]) -> S

Retrieves the current state of the engine.

#
Engine::try_send

fn[S : Hash + Eq, E : Hash + Eq, Ctx] Engine::try_send(self : Engine[S, E, Ctx], event : E) -> Result[Unit, TransitionError]

Attempts a transition and returns a structured transition error on failure.

#
Engine::try_send_all

fn[S : Hash + Eq, E : Hash + Eq, Ctx] Engine::try_send_all(self : Engine[S, E, Ctx], events : Array[E]) -> BatchReport[E]

Dispatches events in order and records every success or rejection.

#
Engine::try_send_with_budget

fn[S : Hash + Eq, E : Hash + Eq, Ctx] Engine::try_send_with_budget(self : Engine[S, E, Ctx], events : Array[E], rejection_budget : Int) -> BudgetReport[E]

Dispatches events in order while protecting a workflow from an error storm. A zero budget means that the first rejection stops the batch.

#
Engine::try_send_with_retry

fn[S : Hash + Eq, E : Hash + Eq, Ctx] Engine::try_send_with_retry(self : Engine[S, E, Ctx], event : E, policy : RetryPolicy) -> RetryReport[E]

Sends one event repeatedly until it succeeds or the policy is exhausted.

The engine never sleeps or hides failures: callers can update external context between calls, while the report remains deterministic and auditable.

#
EngineConfig

pub(all) struct EngineConfig[S, E, Ctx] {
transitions : Array[Transition[S, E, Ctx]]
on_enter : Map[S, (S, E, Ctx) -> Unit]
on_exit : Map[S, (S, E, Ctx) -> Unit]
}

Core configuration for a state machine builder.

#
EngineOptions

pub(all) struct EngineOptions {
strict_mode : Bool
max_history : Int
}

FSM engine configuration parameters.

#
EngineOptions::default

fn EngineOptions::default() -> EngineOptions

Provides default engine options.

#
EngineSnapshot

pub(all) struct EngineSnapshot[S, E, Ctx] {
state : S
context : Ctx
history_entries : Array[TransitionRecord[S, E]]
audit_entries : Array[AuditRecord[S, E]]
metrics : ExecutionMetrics
last_error : TransitionError?
}

A restorable boundary for an engine's observable runtime state.

#
ExecutionMetrics

pub(all) struct ExecutionMetrics {
attempted : Int
successful : Int
rejected : Int
guard_rejected : Int
unknown_event : Int
no_outgoing_state : Int
duplicate_configuration : Int
invalid_configuration : Int
lifecycle_hooks : Int
} derive(Eq)

Runtime counters for successful and rejected event attempts.

#
ExecutionMetrics::copy

Copies all counters so snapshots and public reads do not share mutable state.

#
ExecutionMetrics::zero

Creates an empty execution counter set.

#
GraphSummary

pub(all) struct GraphSummary[S] {
state_count : Int
transition_count : Int
terminal_states : Array[S]
branching_states : Array[S]
reachable_states : Array[S]
unreachable_states : Array[S]
has_cycle : Bool
maximum_exploration_depth : Int
} derive(Eq)

Structural facts used to review a workflow before it is deployed.

#
HistorySummary

pub(all) struct HistorySummary {
transitions : Int
guarded_transitions : Int
action_transitions : Int
distinct_states : Int
first_state : String?
last_state : String?
}

A compact operational summary suitable for dashboards and acceptance logs.

#
JournalAggregate

pub(all) struct JournalAggregate {
tickets : Int
entries : Int
informational : Int
warnings : Int
errors : Int
critical : Int
unacknowledged : Int
}

A small aggregate for operational reporting across many tickets.

#
JournalEntry

pub(all) struct JournalEntry {
sequence : Int
ticket_id : String
state : String
event : String
level : JournalLevel
message : String
acknowledged : Bool
}

One immutable-facing entry in an operational audit stream.

#
JournalFilter

pub(all) struct JournalFilter {
ticket_id : String?
minimum_level : JournalLevel?
include_acknowledged : Bool
event_prefix : String?
}

A composable filter for operational journal queries.

#
JournalFilter::open_incidents

fn JournalFilter::open_incidents() -> JournalFilter

Creates a filter that returns every unacknowledged incident.

#
JournalFilter::ticket_events

fn JournalFilter::ticket_events(ticket_id : String, event_prefix : String) -> JournalFilter

Creates a filter for one ticket and one event family.

#
JournalLevel

pub(all) enum JournalLevel {
Info
Warning
Error
Critical
} derive(Eq)

Severity used by an operational workflow journal.

#
RetryAttempt

pub(all) struct RetryAttempt[E] {
attempt : Int
event : E
accepted : Bool
error : TransitionError?
}

A single observable attempt made by a policy-driven dispatch.

#
RetryMode

pub(all) enum RetryMode {
Never
GuardOnly
UnknownEventOnly
Recoverable
} derive(Eq)

Describes which deterministic failures may be retried by a caller.

#
RetryPolicy

pub(all) struct RetryPolicy {
max_attempts : Int
mode : RetryMode
} derive(Eq)

A bounded retry policy for integrations that can change context between attempts.

#
RetryPolicy::new

fn RetryPolicy::new(max_attempts : Int, mode : RetryMode) -> RetryPolicy

Creates a retry policy. The initial attempt is always counted.

#
RetryReport

pub(all) struct RetryReport[E] {
attempts : Array[RetryAttempt[E]]
accepted : Bool
exhausted : Bool
final_error : TransitionError?
}

Result of a bounded retry operation, including every failed attempt.

#
SlaEvaluation

pub(all) struct SlaEvaluation {
within_steps : Bool
within_escalations : Bool
breached : Bool
remaining_steps : Int
remaining_escalations : Int
}

Evaluation of a ticket against its service-level target.

#
SlaTarget

pub(all) struct SlaTarget {
max_steps : Int
max_escalations : Int
} derive(Eq)

A service-level target expressed in deterministic workflow steps.

#
TicketJournalSummary

pub(all) struct TicketJournalSummary {
ticket_id : String
total_entries : Int
accepted_events : Int
warnings : Int
incidents : Int
critical : Int
unacknowledged : Int
last_state : String?
}

A ticket-level operational summary for dashboards.

#
Transition

pub(all) struct Transition[S, E, Ctx] {
from : S
to : S
event : E
guard_cond : (S, E, Ctx) -> Bool?
action : (S, E, Ctx) -> Ctx?
}

A transition definition specifying the source state, event, and target state.

#
TransitionError

pub(all) enum TransitionError {
NoTransitionsForCurrentState
EventNotHandledInCurrentState
GuardRejected
DuplicateTransitionDefinition
InvalidConfiguration
} derive(Eq)

Structured transition errors returned by the enhanced runtime API.

#
TransitionRecord

pub(all) struct TransitionRecord[S, E] {
from : S
event : E
to : S
used_guard : Bool
used_action : Bool
} derive(Eq)

A record of a successful transition execution.

#
ValidationReport

pub(all) struct ValidationReport[S, E] {
unreachable_states : Array[S]
dead_end_states : Array[S]
duplicate_transitions : Array[DuplicateTransition[S, E]]
states_without_outgoing_edges : Array[S]
} derive(Eq)

Structured validation output for repository acceptance and reviewer audits.

#
WorkflowJournal

pub(all) struct WorkflowJournal {
entries : Array[JournalEntry]
next_sequence : Int
}

An in-memory journal suitable for deterministic tests and adapters.

#
WorkflowJournal::acknowledge

fn WorkflowJournal::acknowledge(self : WorkflowJournal, sequence : Int) -> Bool

Acknowledges one entry and reports whether it existed.

#
WorkflowJournal::acknowledge_ticket

fn WorkflowJournal::acknowledge_ticket(self : WorkflowJournal, ticket_id : String) -> Int

Acknowledges every entry for a ticket, useful when an incident is closed.

#
WorkflowJournal::append_audit

fn WorkflowJournal::append_audit(self : WorkflowJournal, ticket_id : String, audit : Array[AuditRecord[String, String]]) -> Int

Adds all accepted and rejected events from a string-labelled FSM audit log.

#
WorkflowJournal::count_level

fn WorkflowJournal::count_level(self : WorkflowJournal, level : JournalLevel) -> Int

Counts entries at one severity.

#
WorkflowJournal::critical

fn WorkflowJournal::critical(self : WorkflowJournal, ticket_id : String, state : String, event : String, message : String) -> Int

Appends a critical incident requiring explicit acknowledgement.

#
WorkflowJournal::entries

Reads a defensive copy of the journal.

#
WorkflowJournal::error

fn WorkflowJournal::error(self : WorkflowJournal, ticket_id : String, state : String, event : String, message : String) -> Int

Appends a recoverable error.

#
WorkflowJournal::for_ticket

fn WorkflowJournal::for_ticket(self : WorkflowJournal, ticket_id : String) -> Array[JournalEntry]

Returns entries belonging to a ticket in original sequence order.

#
WorkflowJournal::has_critical

fn WorkflowJournal::has_critical(self : WorkflowJournal, ticket_id : String) -> Bool

Returns true when a ticket has a journal entry at a critical severity.

#
WorkflowJournal::info

fn WorkflowJournal::info(self : WorkflowJournal, ticket_id : String, state : String, event : String, message : String) -> Int

Appends an informational operational note.

#
WorkflowJournal::latest_for_ticket

fn WorkflowJournal::latest_for_ticket(self : WorkflowJournal, ticket_id : String) -> JournalEntry?

Finds the final journal entry belonging to a ticket.

#
WorkflowJournal::new

Creates an empty journal with sequence numbers starting at one.

#
WorkflowJournal::unacknowledged_incidents

fn WorkflowJournal::unacknowledged_incidents(self : WorkflowJournal) -> Int

Counts unacknowledged error and critical entries.

#
WorkflowJournal::warning

fn WorkflowJournal::warning(self : WorkflowJournal, ticket_id : String, state : String, event : String, message : String) -> Int

Appends a warning that may need operator follow-up.

#
aggregate_journals

fn aggregate_journals(journals : Array[WorkflowJournal]) -> JournalAggregate

Aggregates a collection of ticket journals into one report.

#
assert_invariant

fn assert_invariant(cond : Bool, _msg : String) -> Unit

Assert a condition, panics if false (useful for internal engine invariants).

#
branching_states

fn[S : Hash + Eq, E, Ctx] branching_states(builder : Builder[S, E, Ctx]) -> Array[S]

Returns states with more than one outgoing event, useful for manual review.

#
duplicate_transition_entries

fn[S : Eq, E : Eq, Ctx] duplicate_transition_entries(builder : Builder[S, E, Ctx]) -> Array[DuplicateTransition[S, E]]

Returns duplicate (state, event) definitions discovered in a builder.

#
evaluate_sla

fn evaluate_sla(target : SlaTarget, elapsed_steps : Int, escalations : Int) -> SlaEvaluation

Evaluates elapsed steps and escalation count without depending on a clock.

#
format_journal_level

fn format_journal_level(level : JournalLevel) -> String

#
format_transition_error

fn format_transition_error(err : TransitionError) -> String

Converts a structured transition error into a stable public string.

#
format_transition_log

fn[S : Show, E : Show] format_transition_log(from : S, event : E, to : S) -> String

Helper to format transition logs.

#
graph_summary

fn[S : Hash + Eq, E, Ctx] graph_summary(builder : Builder[S, E, Ctx], initial_state : S) -> GraphSummary[S]

Computes graph shape, reachability, branching, cycles, and terminal states.

#
has_open_at_least

fn has_open_at_least(journal : WorkflowJournal, minimum : JournalLevel) -> Bool

Returns whether a journal has any unacknowledged entry at or above a level.

#
history_summary

fn history_summary(history : Array[TransitionRecord[String, String]]) -> HistorySummary

Summarizes a string-labelled workflow history without storing extra runtime state.

#
journal_line

fn journal_line(entry : JournalEntry) -> String

Formats a compact line for console logs and line-oriented exporters.

#
latest_matching

fn latest_matching(journal : WorkflowJournal, filter : JournalFilter) -> JournalEntry?

Returns the latest matching entry, if one exists.

#
level_counts

fn level_counts(journal : WorkflowJournal) -> Array[Int]

Produces a count table in Info, Warning, Error, Critical order.

#
query_journal

fn query_journal(journal : WorkflowJournal, filter : JournalFilter) -> Array[JournalEntry]

Executes a filter against a journal without changing the journal.

#
sla_status

fn sla_status(evaluation : SlaEvaluation) -> String

Returns a readable SLA status for dashboards.

#
successful_transitions

fn[S, E] successful_transitions(history : Array[TransitionRecord[S, E]]) -> Int

Returns the number of successful transitions represented by a history.

#
summarize_ticket

fn summarize_ticket(journal : WorkflowJournal, ticket_id : String) -> TicketJournalSummary

Summarizes one ticket using the journal's stable sequence order.

#
to_mermaid

fn[S : Show, E : Show, Ctx] to_mermaid(builder : Builder[S, E, Ctx]) -> String

Exports the FSM configuration as a Mermaid stateDiagram string.

#
validate

fn[S : Hash + Eq, E : Eq, Ctx] validate(builder : Builder[S, E, Ctx], initial_state : S) -> Array[S]

Returns the list of unreachable states for backwards compatibility.

#
validate_report

fn[S : Hash + Eq, E : Eq, Ctx] validate_report(builder : Builder[S, E, Ctx], initial_state : S) -> ValidationReport[S, E]

Validates the FSM configuration for unreachable states, dead ends, and duplicates.

#
workflow_risk_score

fn[S : Hash + Eq, E : Eq, Ctx] workflow_risk_score(builder : Builder[S, E, Ctx], initial_state : S) -> Int

Produces a stable integer risk score for dashboards and review gates. The score rewards reachable structure and penalizes unreachable states, duplicate definitions, and terminal states that are not explicitly expected.