Skip to main content

Framework Patterns

Framework Patterns

How to Use This Skill

  1. Review the patterns and examples below
  2. Apply the relevant patterns to your implementation
  3. Follow the best practices outlined in this skill

Expert skill for event-driven systems, FSMs, architecture modeling, and reactive patterns.

When to Use

Use this skill when:

  • Implementing event-driven architecture (decoupled systems)
  • Designing finite state machines (FSM) for workflows/processes
  • Creating C4 architecture diagrams (Context, Container, Component, Code)
  • Building reactive systems (event streams, observables)
  • Modeling complex workflows (multi-state processes)
  • Documenting system architecture (visual + code patterns)
  • Time savings: 60% faster architecture design (3h→1h)
  • Proven: Used for T2 session management FSM, auth event flows

Don't use this skill when:

  • Simple CRUD operations (no state machine needed)
  • Synchronous request/response only (no events)
  • Single-file scripts (architecture overhead not worth it)
  • Prototypes without architectural requirements

Event-Driven Architecture

Core Concepts

Event: Immutable fact that something happened

  • Examples: UserLoggedIn, SessionCreated, TokenExpired
  • Properties: event_id, timestamp, event_type, payload, metadata

Event Producer: Component that emits events

  • Examples: Auth handler, Session manager, Workflow engine

Event Consumer: Component that reacts to events

  • Examples: Audit logger, Notification service, Metrics collector

Event Bus: Central hub for event routing

  • Decouples producers from consumers
  • Enables async processing

Event Pattern Template

// Event definition
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Event {
pub event_id: Uuid,
pub timestamp: DateTime<Utc>,
pub event_type: EventType,
pub payload: serde_json::Value,
pub metadata: EventMetadata,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EventType {
UserLoggedIn,
UserLoggedOut,
SessionCreated,
SessionInvalidated,
TokenRefreshed,
WorkflowStateChanged,
}

// Event producer
pub trait EventProducer {
async fn emit(&self, event: Event) -> Result<(), EventError>;
}

// Event consumer
pub trait EventConsumer {
async fn handle(&self, event: Event) -> Result<(), EventError>;
fn event_types(&self) -> Vec<EventType>;
}

// Event bus
pub struct EventBus {
consumers: HashMap<EventType, Vec<Box<dyn EventConsumer>>>,
}

impl EventBus {
pub async fn publish(&self, event: Event) -> Result<(), EventError> {
if let Some(consumers) = self.consumers.get(&event.event_type) {
for consumer in consumers {
consumer.handle(event.clone()).await?;
}
}
Ok(())
}
}

Event-Driven Workflow Example

// Login event flow
async fn login_handler(
credentials: LoginRequest,
event_bus: Arc<EventBus>,
fdb: Arc<FDBService>,
) -> Result<HttpResponse, ApiError> {
// 1. Validate credentials
let user = fdb.users().verify_credentials(&credentials).await?;

// 2. Create session
let session = fdb.sessions().create(&user.user_id).await?;

// 3. Generate JWT
let token = generate_jwt(&session)?;

// 4. Emit event (async, non-blocking)
event_bus.publish(Event {
event_id: Uuid::new_v4(),
timestamp: Utc::now(),
event_type: EventType::UserLoggedIn,
payload: json!({
"user_id": user.user_id,
"session_id": session.session_id,
"ip_address": get_client_ip(),
}),
metadata: EventMetadata::default(),
}).await?;

// 5. Return response (don't wait for event processing)
Ok(HttpResponse::Ok().json(LoginResponse { token, session }))
}

// Event consumers (triggered by event)
struct AuditLogger;
impl EventConsumer for AuditLogger {
async fn handle(&self, event: Event) -> Result<(), EventError> {
// Log to FDB audit table
log_audit_event(event).await
}

fn event_types(&self) -> Vec<EventType> {
vec![EventType::UserLoggedIn, EventType::UserLoggedOut]
}
}

struct MetricsCollector;
impl EventConsumer for MetricsCollector {
async fn handle(&self, event: Event) -> Result<(), EventError> {
// Update login metrics
increment_counter("user_logins_total").await
}

fn event_types(&self) -> Vec<EventType> {
vec![EventType::UserLoggedIn]
}
}

Finite State Machines (FSM)

Core Concepts

State: Discrete condition of the system

  • Examples: IDLE, RUNNING, PAUSED, COMPLETED, FAILED

Transition: Movement from one state to another

  • Triggered by: Events, commands, conditions

Guard: Condition that must be true for transition

  • Examples: user.is_active, token_not_expired

Action: Side effect when entering/exiting state

  • Examples: Send notification, update database

FSM Pattern Template

// State enum
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum State {
Idle,
Running,
Paused,
Completed,
Failed,
}

// Event/trigger enum
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Trigger {
Start,
Pause,
Resume,
Complete,
Fail(String),
}

// State machine
pub struct StateMachine {
current_state: State,
transitions: HashMap<(State, Trigger), State>,
guards: HashMap<(State, Trigger), Box<dyn Fn() -> bool>>,
on_enter: HashMap<State, Box<dyn Fn()>>,
on_exit: HashMap<State, Box<dyn Fn()>>,
}

impl StateMachine {
pub fn new() -> Self {
let mut transitions = HashMap::new();

// Define valid transitions
transitions.insert((State::Idle, Trigger::Start), State::Running);
transitions.insert((State::Running, Trigger::Pause), State::Paused);
transitions.insert((State::Paused, Trigger::Resume), State::Running);
transitions.insert((State::Running, Trigger::Complete), State::Completed);
// ... more transitions

Self {
current_state: State::Idle,
transitions,
guards: HashMap::new(),
on_enter: HashMap::new(),
on_exit: HashMap::new(),
}
}

pub fn transition(&mut self, trigger: Trigger) -> Result<State, FSMError> {
let key = (self.current_state, trigger.clone());

// Check if transition is valid
let next_state = self.transitions.get(&key)
.ok_or(FSMError::InvalidTransition {
from: self.current_state,
trigger: trigger.clone(),
})?;

// Check guard condition
if let Some(guard) = self.guards.get(&key) {
if !guard() {
return Err(FSMError::GuardFailed);
}
}

// Execute exit action
if let Some(on_exit) = self.on_exit.get(&self.current_state) {
on_exit();
}

// Transition
let prev_state = self.current_state;
self.current_state = *next_state;

// Execute enter action
if let Some(on_enter) = self.on_enter.get(&self.current_state) {
on_enter();
}

Ok(self.current_state)
}
}

Recursive Workflow FSM (T2 Pattern)

// From recursive_workflow command and workflow_validator.py
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum FSMState {
INITIATE,
IDENTIFY,
DOCUMENT,
SOLVE,
CODE,
DEPLOY,
TEST,
VALIDATE,
COMPLETE,
CHECKPOINT,
SUSPENDED,
ESCALATED,
}

pub struct RecursiveWorkflowFSM {
state: FSMState,
iteration_count: u32,
max_iterations: u32,
}

impl RecursiveWorkflowFSM {
pub fn new() -> Self {
Self {
state: FSMState::INITIATE,
iteration_count: 0,
max_iterations: 10,
}
}

pub fn valid_transitions(&self) -> Vec<FSMState> {
match self.state {
FSMState::INITIATE => vec![FSMState::IDENTIFY, FSMState::CHECKPOINT],
FSMState::IDENTIFY => vec![FSMState::DOCUMENT, FSMState::CHECKPOINT, FSMState::ESCALATED],
FSMState::DOCUMENT => vec![FSMState::SOLVE, FSMState::CHECKPOINT],
FSMState::SOLVE => vec![FSMState::CODE, FSMState::IDENTIFY, FSMState::CHECKPOINT],
FSMState::CODE => vec![FSMState::DEPLOY, FSMState::SOLVE, FSMState::CHECKPOINT],
FSMState::DEPLOY => vec![FSMState::TEST, FSMState::CODE, FSMState::CHECKPOINT],
FSMState::TEST => vec![
FSMState::VALIDATE,
FSMState::IDENTIFY, // Traceback: misidentified issue
FSMState::SOLVE, // Traceback: wrong approach
FSMState::CODE, // Traceback: implementation error
FSMState::CHECKPOINT
],
FSMState::VALIDATE => vec![FSMState::COMPLETE, FSMState::IDENTIFY, FSMState::CHECKPOINT],
FSMState::COMPLETE => vec![], // Terminal state
FSMState::CHECKPOINT => vec![FSMState::SUSPENDED],
FSMState::SUSPENDED => vec![], // Can resume to any saved state
FSMState::ESCALATED => vec![], // Terminal state
}
}

pub fn traceback(&mut self, failure_type: &str) -> FSMState {
self.iteration_count += 1;

if self.iteration_count >= self.max_iterations {
return FSMState::ESCALATED;
}

match failure_type {
"implementation_error" => FSMState::CODE,
"wrong_approach" => FSMState::SOLVE,
"misidentified_issue" => FSMState::IDENTIFY,
"missing_context" => FSMState::DOCUMENT,
"deployment_failure" => FSMState::DEPLOY,
_ => FSMState::ESCALATED,
}
}
}

C4 Architecture Modeling

C4 Model Levels

Level 1: Context Diagram - System boundary and external actors

  • Shows: System, users, external systems
  • Abstraction: Highest (birds-eye view)

Level 2: Container Diagram - Major components and tech stack

  • Shows: Web app, backend API, database, message queue
  • Abstraction: High (deployment units)

Level 3: Component Diagram - Internal structure of containers

  • Shows: Controllers, services, repositories
  • Abstraction: Medium (code organization)

Level 4: Code Diagram - Class/function level details

  • Shows: Classes, methods, relationships
  • Abstraction: Lowest (implementation)

C4 Mermaid Templates

Level 1: Context Diagram

Level 2: Container Diagram

Level 3: Component Diagram

Generating C4 Diagrams from Code

See core/generate_c4_diagram.py for automated C4 diagram generation from codebase analysis.

Reactive Programming Patterns

Observer Pattern

// Subject (Observable)
pub trait Observable<T> {
fn subscribe(&mut self, observer: Box<dyn Observer<T>>);
fn notify(&self, value: T);
}

// Observer
pub trait Observer<T> {
fn update(&self, value: T);
}

// Example: Session expiry notifications
struct SessionExpiryNotifier {
observers: Vec<Box<dyn Observer<Session>>>,
}

impl Observable<Session> for SessionExpiryNotifier {
fn subscribe(&mut self, observer: Box<dyn Observer<Session>>) {
self.observers.push(observer);
}

fn notify(&self, session: Session) {
for observer in &self.observers {
observer.update(session.clone());
}
}
}

// Observers
struct LogObserver;
impl Observer<Session> for LogObserver {
fn update(&self, session: Session) {
println!("Session expired: {}", session.session_id);
}
}

struct MetricsObserver;
impl Observer<Session> for MetricsObserver {
fn update(&self, session: Session) {
increment_counter("sessions_expired_total");
}
}

Reactive Streams (Rust Tokio)

use tokio::sync::mpsc;
use tokio_stream::{wrappers::ReceiverStream, StreamExt};

// Create event stream
let (tx, rx) = mpsc::channel::<Event>(100);
let stream = ReceiverStream::new(rx);

// Transform stream
let processed = stream
.filter(|event| event.event_type == EventType::UserLoggedIn)
.map(|event| transform_event(event))
.buffer_unordered(10); // Process up to 10 concurrently

// Consume stream
tokio::spawn(async move {
tokio::pin!(processed);
while let Some(result) = processed.next().await {
handle_result(result).await;
}
});

// Emit events
tx.send(Event { /* ... */ }).await.unwrap();

Executable Scripts

See core/generate_c4_diagram.py for C4 diagram generation. See core/fsm_validator.py for FSM validation.

Best Practices

Event-Driven

Events are immutable - Never modify after creation ✅ Events are facts - "UserLoggedIn", not "LoginUser" ✅ Async processing - Don't block on event handling ✅ Idempotent consumers - Handle duplicate events gracefully

Don't use events for RPC - Events announce facts, don't command ❌ Don't block on event emission - Fire and forget ❌ Don't couple producers to consumers - Use event bus

FSM

Define all states explicitly - No implicit states ✅ Validate transitions - Reject invalid transitions ✅ Use guards - Prevent invalid state changes ✅ Handle terminal states - COMPLETE, FAILED, ESCALATED

Don't allow arbitrary transitions - Explicit transition table ❌ Don't ignore iteration limits - Prevent infinite loops ❌ Don't skip state validation - Always check current state

C4 Modeling

Start with context - Level 1 first, then drill down ✅ Consistent notation - Use standard C4 shapes ✅ Focus on relationships - How components communicate ✅ Use technology labels - "Rust + Actix", "React 18"

Don't mix abstraction levels - Keep levels separate ❌ Don't include implementation details in context - Save for Level 4 ❌ Don't create diagrams manually - Generate from code when possible

Reactive

Use backpressure - Prevent overwhelming consumers ✅ Handle errors gracefully - Don't crash on one bad event ✅ Compose streams - Chain transformations ✅ Cancel when done - Clean up stream subscriptions

Don't block streams - Use async operations ❌ Don't ignore backpressure - Respect consumer limits ❌ Don't leak subscriptions - Always unsubscribe

Integration with T2 Project

Event-Driven Usage

// T2 uses event-driven for:
// - Audit logging (all auth events)
// - Metrics collection (session stats)
// - Workflow state changes (recursive workflows)
// - Multi-agent coordination (orchestrator events)

FSM Usage

// T2 uses FSM for:
// - Recursive workflows (INITIATE → IDENTIFY → ... → COMPLETE)
// - Session lifecycle (ACTIVE → EXPIRED → INVALIDATED)
// - Agent coordination (IDLE → DELEGATED → EXECUTING → COMPLETED)

C4 Modeling Usage

// T2 uses C4 for:
// - System architecture documentation (Level 1-2)
// - Component design (Level 3)
// - ADR diagrams (all levels)

Reactive Usage

// T2 uses reactive for:
// - Real-time file system monitoring (file-monitor daemon)
// - WebSocket connections (Theia IDE)
// - Agent event streams (orchestrator coordination)

Templates

See templates/ directory for:

  • event_driven_template.md - Event-driven system template
  • state_machine_template.md - FSM implementation template
  • c4_diagrams.md - C4 diagram Mermaid examples
  • reactive_streams.md - Reactive programming patterns

Multi-Context Window Support

This skill supports long-running architecture design and implementation across multiple context windows using Claude 4.5's enhanced state management capabilities.

State Tracking

Architecture Implementation State (JSON):

{
"checkpoint_id": "ckpt_20251129_152000",
"patterns_implemented": [
{"type": "event_driven", "components": ["EventBus", "UserLoginEvent"], "status": "complete"},
{"type": "fsm", "states": ["INITIATE", "IDENTIFY", "SOLVE"], "status": "in_progress"},
{"type": "c4_diagrams", "levels": [1, 2], "status": "complete"}
],
"diagrams_created": [
{"name": "context-diagram.mmd", "level": 1, "validated": true},
{"name": "container-diagram.mmd", "level": 2, "validated": true}
],
"fsm_transitions": {
"defined": 15,
"implemented": 10,
"tested": 7
},
"token_usage": 16000,
"created_at": "2025-11-29T15:20:00Z"
}

Progress Notes (Markdown):

# Framework Patterns Progress - 2025-11-29

## Completed
- Event-driven architecture for auth flow
- C4 Level 1 & 2 diagrams generated
- FSM states defined for recursive workflow

## In Progress
- Implementing FSM transitions (10/15 complete)
- Testing state machine edge cases

## Next Actions
- Complete remaining FSM transitions
- Add guard conditions for critical transitions
- Create C4 Level 3 component diagram
- Validate FSM with integration tests

Session Recovery

When starting a fresh context window after architecture work:

  1. Load Checkpoint State: Read .coditect/checkpoints/framework-patterns-latest.json
  2. Review Progress Notes: Check framework-patterns-progress.md for context
  3. Verify Diagrams: Open Mermaid diagrams to confirm accuracy
  4. Check FSM Implementation: Review state machine code and transitions
  5. Resume Pattern Implementation: Continue from last incomplete pattern

Recovery Commands:

# 1. Check latest checkpoint
cat .coditect/checkpoints/framework-patterns-latest.json | jq '.patterns_implemented'

# 2. Review progress
tail -30 framework-patterns-progress.md

# 3. Verify diagrams
ls -la diagrams/*.mmd

# 4. Check FSM status
cat .coditect/checkpoints/framework-patterns-latest.json | jq '.fsm_transitions'

# 5. Resume from incomplete transitions
# Continue implementing FSM

State Management Best Practices

Checkpoint Files (JSON Schema):

  • Store in .coditect/checkpoints/framework-patterns-{timestamp}.json
  • Include diagram file paths and validation status
  • Track FSM transition table completeness
  • Record event handler implementations

Progress Tracking (Markdown Narrative):

  • Maintain framework-patterns-progress.md with pattern completion
  • Document architectural decisions and trade-offs
  • Note FSM transition edge cases discovered
  • List diagram updates needed

Git Integration:

  • Create checkpoint after each major pattern implementation
  • Commit diagrams with descriptive messages: docs(arch): Add C4 Level 2 container diagram
  • Tag architecture milestones: git tag arch-fsm-complete

Progress Checkpoints

Natural Breaking Points:

  1. After each C4 diagram level completed
  2. After FSM states and transitions defined
  3. After event-driven components implemented
  4. Before reactive stream integration
  5. After all patterns validated with examples

Checkpoint Creation Pattern:

// Automatic checkpoint at architecture milestones
if diagrams_created >= 2 || fsm_transitions_complete >= 10 {
create_checkpoint({
"patterns": implemented_patterns,
"diagrams": diagram_files,
"fsm": transition_status,
"tokens": current_tokens
});
}

Example: Multi-Context Architecture Design

Context Window 1: Event-Driven & C4 Diagrams

{
"checkpoint_id": "ckpt_arch_foundation",
"phase": "architecture_design_complete",
"patterns": ["event_driven", "c4_level1", "c4_level2"],
"diagrams": 2,
"next_action": "Implement FSM for workflow",
"token_usage": 13000
}

Context Window 2: FSM Implementation

# Load checkpoint
cat .coditect/checkpoints/ckpt_arch_foundation.json

# Continue with FSM implementation
# Token savings: ~9000 tokens (diagrams already created, no re-design)

Token Savings Analysis:

  • Without checkpoint: 22000 tokens (re-create diagrams + design FSM)
  • With checkpoint: 13000 tokens (resume from validated diagrams)
  • Savings: 41% reduction (22000 → 13000 tokens)

Success Output

When successful, this skill MUST output:

✅ SKILL COMPLETE: framework-patterns

Completed:
- [x] Event-driven architecture defined (event types, producers, consumers)
- [x] Finite state machine implemented (states, transitions, guards)
- [x] C4 diagrams generated (context, container, component levels)
- [x] Reactive patterns applied (observables, streams)
- [x] Integration examples provided

Outputs:
- diagrams/c4-context.mmd (Level 1: system boundary, external actors)
- diagrams/c4-container.mmd (Level 2: major components, tech stack)
- diagrams/c4-component.mmd (Level 3: internal structure)
- src/events/ (event definitions, bus, producers, consumers)
- src/fsm/ (state machine implementation with transition validation)
- docs/architecture-patterns.md (pattern documentation with examples)

Completion Checklist

Before marking this skill as complete, verify:

  • Event types defined with clear naming (UserLoggedIn, not LoginUser)
  • Event bus decouples producers from consumers
  • FSM states explicitly enumerated (no implicit states)
  • FSM transition table validated (all paths legal)
  • FSM guards prevent invalid state changes
  • C4 diagrams start at context level (Level 1 before drilling down)
  • C4 diagrams use consistent notation and technology labels
  • Reactive streams handle backpressure
  • Code examples compile and execute successfully
  • Pattern documentation includes when to use / when NOT to use

Failure Indicators

This skill has FAILED if:

  • ❌ Event producer directly calls consumer (tight coupling)
  • ❌ FSM allows arbitrary transitions (no validation)
  • ❌ C4 diagrams mix abstraction levels (implementation details in context diagram)
  • ❌ Reactive streams ignore backpressure (consumer overload)
  • ❌ State machine lacks terminal states (infinite loops possible)
  • ❌ Event naming uses imperative commands (should be past-tense facts)
  • ❌ Diagrams generated manually without code validation

When NOT to Use

Do NOT use this skill when:

  • Simple CRUD operations (no state machine needed, direct request/response sufficient)
  • Synchronous-only requirements (no events, no async processing)
  • Single-file scripts (architecture overhead not justified)
  • Prototypes without architectural requirements (premature optimization)
  • Tight deadlines (<1 day) for architecture work (skill requires thoughtful design)
  • Team unfamiliar with patterns (training overhead exceeds benefit)

Use alternative skills:

  • database-patterns - When data modeling is primary concern
  • api-design-patterns - When REST/GraphQL API structure is focus
  • microservices-patterns - When service decomposition is needed

Anti-Patterns (Avoid)

Anti-PatternProblemSolution
Using events for RPCCouples systems, defeats purposeEvents announce facts, don't command actions
Blocking on event emissionDefeats async benefitsFire-and-forget pattern for event bus
Arbitrary FSM transitionsInvalid states reachableExplicit transition table with validation
Ignoring iteration limitsInfinite FSM loopsMax iterations with ESCALATED terminal state
Manual diagram maintenanceDiagrams drift from codeGenerate C4 from code analysis where possible
Skipping guards on critical transitionsInvalid state changesGuards for authentication, authorization, business rules
Leaking stream subscriptionsMemory leaksAlways unsubscribe/cancel when done

Principles

This skill embodies:

  • #2 First Principles - Understand event-driven, FSM, reactive fundamentals before implementing
  • #3 Keep It Simple - Start with simplest pattern that solves the problem
  • #4 Separation of Concerns - Events decouple producers from consumers
  • #5 Eliminate Ambiguity - FSM makes state transitions explicit and validated
  • #6 Clear, Understandable, Explainable - C4 diagrams communicate architecture visually

Full Standard: CODITECT-STANDARD-AUTOMATION.md