Source: Transferred from lifecycle ecosystem analysis (2026-03-02)
Context: Pre-refactoring analysis to preserve valuable insights during engine abstraction.
Trellis v0.7+ is not just a state machine engine — it's a complete platform with 5 architectural layers. Before extracting the abstract engine, preserve these 10 critical insights.
Insight: Markdown links become implicit transitions.
# Welcome
[Log In](./login.md) or [Register](./register.md)?Impact: Drastically lowers barrier to entry.
Scope: Generic — any DSL can use this pattern.
Insight: repo/about.md → /about node (Astro/Next.js style).
Impact: Trellis becomes a "Stateful Web Server" with HATEOAS.
Scope: Generic protocol adapter — reusable across DSLs.
Insight: LLMs orchestrate flows via Model Context Protocol.
Impact: AI agents can navigate/render/graph flows.
Scope: Generic adapter — life-dsl, scrape-dsl can reuse.
Insight: Zero-config reactive UI at /ui.
Impact: Instant visualization for any flow.
Scope: Partially generic (reactivity = yes, chat theme = flow-specific).
Insight: Execute .sh, .py, .js, .ps1 via Unix contract (ENV, STDIN, STDOUT).
Impact: Trellis as "Polyglot Orchestrator".
Scope: 100% generic — extract to trellis-tooling.
Insight: Durable execution via snapshotting (no Event Sourcing).
Impact: Long-running flows survive restarts.
Scope: Generic — extract to trellis-persistence.
Insight: Type-check variables before runtime.
Impact: Catch errors early.
Scope: Generic — part of abstract engine.
Insight: Fluent API avoids YAML verbosity.
Scope: Pattern reusable — each DSL implements its own builder.
Insight: SIGINT ≠ SIGTERM (User Interrupt vs System Termination).
Status: ✅ Already in lifecycle v1.5.
Action: Upgrade Trellis from lifecycle v0.1.1 → v1.7+.
Insight: Support multiple conventions.
Scope: DSL-specific (configurable, not hardcoded).
Goal: Organize Trellis into clear layers without extracting repos.
trellis/
├── pkg/
│ ├── engine/ ← Core execution (generic)
│ ├── flow/ ← Flow-DSL specifics
│ ├── protocols/ ← HTTP, MCP, SSE (generic)
│ ├── persistence/ ← State store, sessions (generic)
│ ├── tooling/ ← Tool registry (generic)
│ └── ui/ ← Patterns (generic) + themes (specific)
└── trellis.go ← Backward compat facade
Validation: All tests pass, Arbour continues working.
Goal: Implement life-dsl inside trellis repo to discover what's truly generic.
trellis/pkg/
├── engine/ ← Shared by flow + life
├── flow/ ← Flow-DSL specifics
└── life/ ← Life-DSL experiment
├── types.go (workers, habits)
├── compiler.go (life.yaml → engine)
└── executors.go (CLI, Browser, Notify)
Questions to Answer:
- Does life-dsl need HTTP server? → protocols/ is generic ✓
- Does life-dsl need sessions? → persistence/ is generic ✓
- Does life-dsl need tool registry? → tooling/ is generic ✓
- Different node types? → engine/ needs more abstraction
Goal: Extract only validated generic components.
Extract:
trellis-protocols(HTTP, MCP, SSE)trellis-persistence(StateStore, Session)trellis-tooling(Tool Registry, Process Adapter)
Keep Monolithic:
pkg/engine/(needs more iteration)pkg/ui/(themes are flow-specific)pkg/dsl/(each DSL has its own)
// Flexibility (functions) + Safety (interface) + DX (builder)
type Node struct {
id string
execute func(ctx context.Context) error
schedule Scheduler
onStart func(ctx context.Context) error
onFailure func(ctx context.Context, err error) error
}
type Executable interface {
ID() string
Execute(ctx context.Context) error
Scheduler() Scheduler
}
// Builder pattern for ergonomics
func NewNode(id string) *NodeBuilder {
return &NodeBuilder{node: &Node{id: id}}
}Why Hybrid?
- Functions = composable, testable
- Interface = engine contract guaranteed
- Builder = idiomatic Go, readable
- Extensible = add hooks without breaking
type Scheduler interface {
Next(ctx context.Context, current Node) (Node, error)
}
// Implementations:
// - CronScheduler (time-based for life-dsl)
// - StateMachineScheduler (transition-based for flow-dsl)
// - SelectorScheduler (DOM traversal for scrape-dsl)type StateStore interface {
Get(ctx context.Context, nodeID string) (*NodeState, error)
Set(ctx context.Context, nodeID string, state *NodeState) error
Checkpoint(ctx context.Context) error
Restore(ctx context.Context) error
}
// Implementations: MemoryStore, SQLiteStore, RedisStore, LoamStoreCurrent: Trellis uses lifecycle v0.1.1 (basic cancellation only).
Target: Deep integration with lifecycle v1.5+ (Control Plane).
type Engine struct {
router *lifecycle.Router // Event routing
supervisor *lifecycle.Supervisor // Worker orchestration
store StateStore // Persistence
}
func (e *Engine) Run(ctx context.Context, nodes []Executable) error {
ctx = lifecycle.Attach(ctx, e.router)
for _, node := range nodes {
worker := e.supervisor.Add(node.ID(), node.Execute)
worker.RestartPolicy = lifecycle.Always
}
return lifecycle.Run(ctx, e.supervisor)
}Benefits:
- Suspend/Resume flows
- Graceful shutdown with checkpointing
- Signal differentiation (SIGINT vs SIGTERM)
- Event-driven control (webhooks, file watches, health checks)
- Review this document and consolidate with PLANNING.md
- Create
trellis/docs/ECOSYSTEM_INTEGRATION.md(use lifecycle's as template) - Audit current architecture vs 5-layer stack
- Identify all coupling points (DSL ↔ Engine)
- Restructure
pkg/into engine/flow/protocols/persistence/tooling/ui - Maintain 100% backward compatibility
- Run full test suite after each move
- Update Arbour integration tests
- Implement life-dsl experiment in
pkg/life/ - Document friction points (what's hard to reuse?)
- Validate generic vs specific boundaries
- Create concrete extraction checklist
- Extract validated components to separate repos
- Update import paths with backward compat aliases
- Publish extraction ADR
- Update ecosystem documentation
- trellis/PLANNING.md — Project roadmap
- trellis/docs/ECOSYSTEM_INTEGRATION.md — Integration with lifecycle ecosystem
- lifecycle/docs/ecosystem/engine_abstraction.md — Full vision & design
Last Updated: 2026-03-02
Status: Ready for Phase 2a implementation
Next Step: Implement Execution Contract v0 and validate with Life-DSL/Scrape-DSL discovery spikes