caishen

State Machine Code Generator (SMCG)

RISE Framework Specification

Spec ID: 62
Version: 1.1
Document ID: caishen-rise-smcg-v1.1
Last Updated: 2026-02-23
Source: Extracted from SCDE/SMCG/StateBuilderLib/ (StateBuilder.cs, CoderStateMachine.cs, CoderFeeder.cs, CoderContext.cs, CoderState.cs, CoderParallel.cs)
Implementation: smcraft — Python: smcraft/py/smcraft/codegen.py, cli.py | TypeScript: smcraft/ts/src/codegen.ts | MCP: smcraft/mcp/

Creative Intent

What SMCG Enables Users to Create:

Desired Outcomes:

  1. A single definition file produces a complete, compilable state machine implementation
  2. Generated code follows target language idioms and best practices
  3. Users extend generated behavior through partial classes/hooks without modifying generated files
  4. Code regeneration is safe — user customizations survive via extension points

Architecture Overview

┌─────────────────────────────────────────────────────────────────┐
│                    Code Generator Pipeline                       │
│                                                                  │
│  ┌──────────┐   ┌──────────────┐   ┌───────────────────────┐   │
│  │  Parser   │──▶│ Object Model │──▶│   Code Emitters       │   │
│  │ (XML/JSON)│   │ (validated)  │   │                       │   │
│  └──────────┘   └──────────────┘   │ ┌───────────────────┐ │   │
│                                     │ │  CoderFeeder      │ │   │
│                                     │ │  (event feeders)  │ │   │
│                                     │ ├───────────────────┤ │   │
│                                     │ │  CoderContext     │ │   │
│                                     │ │  (context class)  │ │   │
│                                     │ ├───────────────────┤ │   │
│                                     │ │  CoderState       │ │   │
│                                     │ │  (state classes)  │ │   │
│                                     │ ├───────────────────┤ │   │
│                                     │ │  CoderParallel    │ │   │
│                                     │ │  (parallel ctxs)  │ │   │
│                                     │ └───────────────────┘ │   │
│                                     └───────────────────────┘   │
│                                              │                   │
│                                     ┌────────▼────────┐         │
│                                     │  Output File(s) │         │
│                                     │  (.py / .ts /   │         │
│                                     │   .cs)          │         │
│                                     └─────────────────┘         │
└─────────────────────────────────────────────────────────────────┘

Core Components

StateBuilder (Orchestrator)

The main entry point that coordinates the entire code generation pipeline.

Behavior:

Class StateBuilder:

  Properties:
    - InputFile: string — path to .smdf.json or .smdf.xml definition
    - OutputDir: string — directory for generated output
    - OutputFile: string — generated filename (defaults to {name}_fsm.{ext})
    - TargetLanguage: LanguageTarget — Python, TypeScript, or CSharp
    - PrependFile: string (optional) — file content to prepend (headers, licenses)

  Methods:
    - Build() → BuildResult
        Behavior:
          1. Parse input file via StateMachineParser
          2. Validate the object model (Spec 60 validation rules V001-V014)
          3. Create code emitter for target language
          4. Invoke CoderStateMachine.Generate(model, emitter)
          5. Write output file(s)
          6. Return BuildResult with success/errors

    - BuildFromString(definition: string, format: "json"|"xml") → BuildResult
        Behavior: Same as Build() but parses from string instead of file

Enum LanguageTarget:
  - Python
  - TypeScript
  - CSharp

Class BuildResult:
  Properties:
    - Success: bool
    - OutputFiles: string[]
    - Errors: ValidationError[]
    - Warnings: string[]

StateMachineParser

Parses definition files into the in-memory object model.

Behavior:

Class StateMachineParser:

  Methods:
    - ParseFile(path: string) → StateMachineModel
        Behavior: Detects format from extension, parses, validates
    - ParseJson(content: string) → StateMachineModel
        Behavior: Deserializes JSON, enriches model
    - ParseXml(content: string) → StateMachineModel
        Behavior: Deserializes XML (StateMachineDotNet-v1), enriches model
    - Validate(model: StateMachineModel) → ValidationError[]
        Behavior: Applies rules V001-V014 from Spec 60

  Internal:
    - EnrichModel(model: StateMachineModel) → void
        Behavior:
          1. Build state map (name → StateNode)
          2. Set parent references for all states
          3. Classify state types (Leaf, Composite, Root, Final, etc.)
          4. Build event map (id → EventDef)
          5. Build timer map (name → TimerDef)
          6. Build feeder map (feeder name → EventDef[])
          7. Resolve transition targets

StateMachineModel (In-Memory Object Model)

The enriched, validated representation of a state machine definition.

Class StateMachineModel:

  Properties:
    - Settings: SettingsModel
    - RootState: StateNode
    - StateMap: Map<string, StateNode>
    - EventMap: Map<string, EventDef>
    - TimerMap: Map<string, TimerDef>
    - FeedersMap: Map<string, EventDef[]>
    - EventInterfaceMap: Map<string, string>

  Methods:
    - GetStateLeaf(state: StateNode) → StateNode
        Behavior: Recursively finds the initial leaf state
    - GetEventsForState(state: StateNode) → EventDef[]
        Behavior: Returns events that have transitions in this state
    - GetTransitionList(state: StateNode, eventId: string) → TransitionDef[]
        Behavior: Returns all transitions for a given event in a state
    - GetTransitionName(transition: TransitionDef) → string
        Behavior: Returns "eventId" or "eventId[condition]"
    - GetStateTop(state: StateNode) → StateNode
        Behavior: Walks up to find the topmost ancestor
    - ContextDepth(state: StateNode, nextState: StateNode) → int
        Behavior: Returns depth between states across parallel contexts

Class StateNode:
  Properties:
    - name: string
    - kind: StateKindType (final, history, or unset)
    - type: TypeFlags (ROOT | TOP | COMPOSITE | LEAF | FINAL | HISTORY | HAS_HISTORY | PARALLEL)
    - parent: StateNode
    - stateParallel: StateNode — enclosing parallel state
    - children: StateNode[]
    - parallelRegions: StateNode[] — for parallel states
    - onEntry: ActionDef[]
    - onExit: ActionDef[]
    - transitions: TransitionDef[]

  Flags TypeFlags:
    - ROOT = 1
    - TOP = 2
    - COMPOSITE = 4
    - LEAF = 8
    - FINAL = 16
    - ERROR = 32
    - HISTORY = 64
    - HAS_HISTORY = 128
    - PARALLEL = 256

CoderStateMachine (Coordinator)

Coordinates the specialized coders to produce complete output.

Behavior:

Class CoderStateMachine:

  Methods:
    - Generate(model: StateMachineModel, emitter: CodeEmitter) → void
        Behavior:
          1. Emit file header (imports, namespace open)
          2. CoderFeeder.Generate() — event feeder classes
          3. CoderContext.Generate() — main context class
          4. CoderParallel.Generate() — parallel region contexts (if any)
          5. CoderState.Generate() — state classes and enum
          6. Emit namespace close

CoderFeeder (Event Feeder Generator)

Generates feeder classes that provide clean event APIs.

Behavior:

CoderFeeder generates for each Feeder:

  Class {FeederName}:  (partial / extensible)
    Properties:
      - context: {ContextName} — reference to the state machine context

    Constructor:
      - Accepts context reference
      - Wires event delegates to context methods

    For each Event in the feeder:
      Method {EventId}(params...):
        Behavior:
          1. Call On{EventId}Pre(params) — extension hook (no-op by default)
          2. Feed event into context (sync: direct dispatch, async: ScheduleEvent)
          3. Call On{EventId}Post(params) — extension hook (no-op by default)

      Extension Methods (partial / overridable):
        - On{EventId}Pre(params) → void
        - On{EventId}Post(params) → void

CoderContext (Context Class Generator)

Generates the main context class that manages state machine execution.

Behavior:

CoderContext generates:

  Class {ContextName} extends Context<StateBase, ContextParent>:

    State Fields:
      - For each leaf state: static {StateName}: State{StateName}

    Timer Fields:
      - For each timer: _{timerName}: Timer

    Constructor:
      - Instantiates all state objects
      - Creates timer instances
      - Sets initial state reference

    Methods:
      - EnterInitialState() → void
          Behavior: Enters root → top → initial leaf state (OnEntry chain)

      - LeaveCurrentState() → void
          Behavior: Exits current state up to root (OnExit chain)

      - SetState(stateName: string) → void
          Behavior: Switch on stateName, set StateCurrent for deserialization

      For each Event:
      - On{EventId}(params...) → void
          Behavior: Delegates to StateCurrent.On{EventId}(context, params)

      For each Timer:
      - Start{TimerName}(duration: int) → void
          Behavior: Creates and starts timer, wires callback to On{TimerId}
      - Stop{TimerName}() → void
          Behavior: Stops and disposes timer

      - EnterHistoryState() → void  (if any state has history)
          Behavior: Restores StateHistory as StateCurrent

CoderState (State Class Generator)

Generates individual state classes and the state enumeration.

Behavior:

CoderState generates:

  Enum {MachineName}StateEnum:
    - For each state: {StateName} = {index}

  Abstract Class State{RootName}:
    Methods:
      - OnEntry(context) → void (virtual, empty default)
      - OnExit(context) → void (virtual, empty default)
      - For each Event: On{EventId}(context, params) → void (virtual, empty default)

  For each Leaf State:
  Class State{StateName} extends State{RootName}:

    Properties:
      - Name: "{StateName}"
      - Kind: StateKind.Leaf (or Final)
      - StateParent: reference to parent state instance

    OnEntry(context):
      Behavior: Executes onEntry actions from definition
               Observer.OnEntry(context.Name, this.Name)

    OnExit(context):
      Behavior: Executes onExit actions from definition
               Observer.OnExit(context.Name, this.Name)

    For each Event with transitions in this state:
    On{EventId}(context, params):
      Behavior:
        For each transition with this event:
          1. If transition has condition, evaluate guard
          2. If guard passes (or no guard):
             a. TransitionHelper.ProcessTransitionBegin(context, this, targetState, transitionName)
             b. Execute transition actions
             c. context.StateCurrent = targetState
             d. TransitionHelper.ProcessTransitionEnd(context, this, targetState)
          3. If internal transition (no nextState): execute actions only

CoderParallel (Parallel Region Generator)

Generates context classes for each parallel region.

Behavior:

CoderParallel generates for each Parallel State:

  Class {ParallelName}Context extends ContextParallel:

    Properties:
      - For each orthogonal region: {RegionName}Context: Context
      - ActiveState: int — starts at number of regions

    Constructor:
      - Creates sub-contexts for each region
      - Registers completion handlers
      - Sets ActiveState = region count

    TransitionToNextState():
      Behavior:
        1. Decrement ActiveState
        2. If ActiveState == 0:
           a. Transition parent context to parallel's nextState

Code Emitter Abstraction

Language-specific code emission is handled through a CodeEmitter abstraction:

Interface CodeEmitter:

  Methods:
    - EmitFileHeader(namespace: string, imports: string[]) → void
    - EmitFileFooter() → void
    - EmitClassOpen(name: string, extends: string, modifiers: string[]) → void
    - EmitClassClose() → void
    - EmitMethod(name: string, params: ParamDef[], returnType: string, body: string[]) → void
    - EmitProperty(name: string, type: string, visibility: string) → void
    - EmitEnum(name: string, values: EnumValue[]) → void
    - EmitConstructor(className: string, params: ParamDef[], body: string[]) → void
    - EmitComment(text: string) → void
    - GetOutput() → string

Implementations:
  - PythonEmitter: Generates Python 3.10+ with dataclasses, type hints, protocols
  - TypeScriptEmitter: Generates TypeScript with interfaces, classes, strict types
  - CSharpEmitter: Generates C# with CodeDom compatibility (legacy)

CLI Interface

Command: smcg

Usage: smcg <input-file> [options]

Options:
  --output, -o <dir>        Output directory (default: current directory)
  --language, -l <lang>     Target language: python|typescript|csharp (default: python)
  --name, -n <name>         Override state machine name
  --prepend <file>          File to prepend to output (license headers, etc.)
  --validate-only           Only validate, don't generate code
  --verbose, -v             Verbose output with generation details
  --watch, -w               Watch input file for changes, regenerate automatically

Examples:
  smcg strategy.smdf.json -l python -o ./generated/
  smcg strategy.smdf.xml -l typescript
  smcg strategy.smdf.json --validate-only

Creative Advancement Scenarios

Scenario: Python Strategy State Machine

Desired Outcome: Generate a complete Python state machine from a JSON definition
Current Reality: State machine logic is hand-written Python with manual state tracking
Natural Progression:

  1. User creates bdbo_strategy.smdf.json defining strategy lifecycle states
  2. Runs smcg bdbo_strategy.smdf.json -l python
  3. Parser validates the definition against Spec 60 rules
  4. CoderStateMachine coordinates generation:
    • CoderFeeder creates StrategyFeeder class with typed event methods
    • CoderContext creates BDBOStrategyContext with state management
    • CoderState creates individual state classes with transition logic
  5. Output: bdbo_strategy_fsm.py — a complete, runnable state machine
    Resolution: Production-ready Python state machine from a single declarative definition

Scenario: Safe Regeneration with User Extensions

Desired Outcome: User extends generated code without losing changes on regeneration
Current Reality: Generated code must be manually merged with custom logic
Natural Progression:

  1. SMCG generates strategy_fsm.py with base state machine code
  2. User creates strategy_extensions.py with custom entry/exit actions
  3. Feeder pre/post hooks allow behavior injection without modifying generated code
  4. User runs smcg again after definition changes
  5. strategy_fsm.py is regenerated; strategy_extensions.py is untouched
    Resolution: Clean separation between generated infrastructure and user business logic

Generated Output Examples

Python Output Structure

# bdbo_strategy_fsm.py — Generated by SMCG. Do not edit.
# Source: bdbo_strategy.smdf.json

from __future__ import annotations
from enum import IntEnum
from statemachine_runtime import (
    ContextBase, ContextAsync, State, StateKind,
    TransitionHelper, IObserver, ObserverNull, EventFactory
)

class BDBOStrategyStateEnum(IntEnum):
    Idle = 0
    Active_WaitingBreakout = 1
    Active_WaitingSignal = 2
    Active_WaitingEntry = 3
    Completed = 4
    Failed = 5

class StateBDBOStrategy:
    """Base state with virtual event handlers."""
    def on_entry(self, context): pass
    def on_exit(self, context): pass
    def on_strategy_created(self, context, strategy_id): pass
    def on_price_breakout(self, context, price, direction): pass
    def on_signal_found(self, context): pass
    # ...

class StateIdle(StateBDBOStrategy):
    name = "Idle"
    kind = StateKind.LEAF

    def on_strategy_created(self, context, strategy_id):
        TransitionHelper.process_transition_begin(context, self, context.state_active_waiting_breakout, "StrategyCreated")
        context.state_current = context.state_active_waiting_breakout
        TransitionHelper.process_transition_end(context, self, context.state_active_waiting_breakout)

# ... more state classes ...

class BDBOStrategyContext(ContextAsync):
    def __init__(self, strategy):
        super().__init__()
        self.strategy = strategy
        self.state_idle = StateIdle()
        self.state_active_waiting_breakout = StateActiveWaitingBreakout()
        # ... initialize all states ...

    def enter_initial_state(self):
        self.state_current = self.state_idle
        self.state_current.on_entry(self)

class StrategyFeeder:
    def __init__(self, context: BDBOStrategyContext):
        self.context = context

    def strategy_created(self, strategy_id: str):
        self.context.schedule_event(
            EventFactory.create("StrategyCreated", self.context.on_strategy_created, strategy_id)
        )

Dependencies


Implementation Notes

Extension Points Pattern

Generated code uses language-appropriate extension mechanisms:

Language Extension Mechanism
Python Inheritance + super() calls, mixin classes
TypeScript abstract + override, interface extension
C# partial classes, virtual methods

File Naming Convention

Language Output Filename
Python {name}_fsm.py
TypeScript {name}_fsm.ts
C# {name}_fsm.cs