Framework Patterns
Framework Patterns
How to Use This Skill
- Review the patterns and examples below
- Apply the relevant patterns to your implementation
- 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 templatestate_machine_template.md- FSM implementation templatec4_diagrams.md- C4 diagram Mermaid examplesreactive_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:
- Load Checkpoint State: Read
.coditect/checkpoints/framework-patterns-latest.json - Review Progress Notes: Check
framework-patterns-progress.mdfor context - Verify Diagrams: Open Mermaid diagrams to confirm accuracy
- Check FSM Implementation: Review state machine code and transitions
- 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.mdwith 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:
- After each C4 diagram level completed
- After FSM states and transitions defined
- After event-driven components implemented
- Before reactive stream integration
- 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-Pattern | Problem | Solution |
|---|---|---|
| Using events for RPC | Couples systems, defeats purpose | Events announce facts, don't command actions |
| Blocking on event emission | Defeats async benefits | Fire-and-forget pattern for event bus |
| Arbitrary FSM transitions | Invalid states reachable | Explicit transition table with validation |
| Ignoring iteration limits | Infinite FSM loops | Max iterations with ESCALATED terminal state |
| Manual diagram maintenance | Diagrams drift from code | Generate C4 from code analysis where possible |
| Skipping guards on critical transitions | Invalid state changes | Guards for authentication, authorization, business rules |
| Leaking stream subscriptions | Memory leaks | Always 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