lex-planner
Fleet pipeline planning stage for LegionIO. Receives assessed work items, gathers repository context, and decomposes work into structured implementation plans using LLM structured output.
Architecture
lex.assessor exchange
lex.assessor.runners.assessor.# ──> lex.planner.runners.planner queue
│
▼
[Planner Actor]
│
┌────────────┼────────────┐
▼ ▼ ▼
ContextGatherer LLM Plan PlanSchema
(file tree, generation validation
docs, cache) (Prompt.dispatch)
│
▼
fleet:context:<id> (Redis, 24h TTL)
│
▼
work_item.pipeline.stage = 'planned'
│
▼
lex.developer exchange
Work Item Flow
An assessed work item arrives on the lex.planner.runners.planner queue. The planner:
-
Gathers repo context — fetches the file tree, documentation files (
CLAUDE.md,README.md,AGENTS.md), and relevant source files matched by keyword. Context is serialized and stored in Redis underfleet:context:<work_item_id>with a 24-hour TTL. -
Generates a plan — calls
Legion::LLM::Prompt.dispatchwith the structuredPlanSchema, passingtools: []and anintentderived from the work item's estimated difficulty. Anti-bias model exclusion prevents repeated use of the same model across pipeline stages. -
Validates the plan — checks required fields (
approach,files_to_modify,test_strategy,estimated_changes). Retries up tomax_iterationson quality failures; bubbles infrastructure errors immediately. -
Advances the stage — sets
pipeline.stage = 'planned', appends a trace entry, and routes to the developer stage.
Runners
Runners::Planner
| Function | Description |
|---|---|
plan(work_item:, **) |
Full pipeline: gather context → generate plan → validate → return planned work item |
gather_context(work_item:, **) |
Fetch and cache repo context independently; returns context_ref
|
Both accept results:, work_item:, and args: for flexible invocation from the task pipeline.
Helpers
| Helper | Purpose |
|---|---|
Helpers::PlanSchema |
JSON schema for LLM structured output + validate_plan method |
Helpers::SpecParser |
Markdown spec/requirements parser — extracts title, sections, bullet requirements |
Helpers::ContextGatherer |
Fetch file tree, docs, relevant files; cache/load context via Legion::Cache
|
Plan Schema
Plans are validated against a structured schema before the work item advances:
| Field | Type | Description |
|---|---|---|
approach |
string | High-level implementation strategy |
files_to_modify |
array | Files to create, modify, or delete (each with path, action, reason) |
files_to_read |
array | Supporting files to read before implementing |
test_strategy |
string | How to test the implementation |
estimated_changes |
integer | Number of files expected to change |
Configuration
All settings are read from Legion::Settings.dig(:fleet, ...).
| Setting | Default | Description |
|---|---|---|
fleet.planning.max_iterations |
5 |
Max LLM retries per plan (overridden by work_item.config.planning.max_iterations) |
fleet.planning.solvers |
1 |
Number of parallel plan candidates (>1 enables Dr. Zero pattern) |
fleet.context.load_file_tree |
true |
Whether to fetch the repo file tree |
fleet.context.load_repo_docs |
true |
Whether to fetch documentation files |
fleet.context.max_context_files |
50 |
Cap on relevant source files included in context |
Transport
| Component | Name |
|---|---|
| Exchange |
lex.planner (topic, durable) |
| Queue |
lex.planner.runners.planner (durable) |
| Routing key | lex.planner.runners.planner.# |
Installation
Add to your Gemfile:
gem 'lex-planner'Development
bundle install
bundle exec rspec # 38 examples
bundle exec rubocop # 0 offenses expectedDependencies
-
legion-cache— context caching (Redis/Memory) -
legion-json— symbol-key JSON serialization -
legion-settings— readsfleet.*config -
legion-transport— RabbitMQ exchange/queue binding -
legion-llm—Prompt.dispatchfor structured LLM output
License
MIT