legionio 1.9.23 → 1.9.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/CHANGELOG.md +27 -0
- data/CLAUDE.md +62 -769
- data/Gemfile +2 -0
- data/lib/legion/api/identity_audit.rb +4 -4
- data/lib/legion/api/llm.rb +7 -4
- data/lib/legion/extensions/catalog/available.rb +0 -7
- data/lib/legion/identity/broker.rb +1 -1
- data/lib/legion/identity/middleware.rb +28 -10
- data/lib/legion/identity/resolver.rb +59 -45
- data/lib/legion/task_outcome_observer.rb +16 -2
- data/lib/legion/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 166725a37cf7c1d479070df9c3a19a53ec6fa915e1fe29b9e881358136392dc5
|
|
4
|
+
data.tar.gz: '09fe43d7158d9fea1439f820c231efeb25a3a1766b3c988411504f28cdbabf1d'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 424b1f6992f9bce5ae26fa0f09c986ee9bf961a9beccf64d3498f3db651747bbcab3ef8bb6ee25f45cdfc6c1df9e0ddd031132a253b334edeba1a63b2a1532cd
|
|
7
|
+
data.tar.gz: 2462fd9c2277a81b381f4b91c3674930606e6c80460d708c36d252a7a2a7e1475f9b397daa3d55c2c8b17b1c33dbb50eb2ceec7acd0dd3abfe59376d4913ef0a
|
data/.rspec
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.9.28] - 2026-05-08
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Task outcome observation now ignores internal runner completions without task ids, preventing periodic mesh gossip ticks from feeding meta-learning and Apollo ingestion.
|
|
9
|
+
- Identity resolver database persistence now targets the current identity provider, principal, identity, and audit log schema.
|
|
10
|
+
|
|
11
|
+
## [1.9.27] - 2026-05-08
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- Preserve omitted `/api/llm/inference` client tool definitions as absent instead of `tools: []`, allowing legion-llm registry and trigger-based tool injection to run for normal API requests.
|
|
15
|
+
- Added an opt-in live daemon integration spec suite that uses explicit Faraday test dependencies and its own isolated RSpec helper.
|
|
16
|
+
|
|
17
|
+
## [1.9.26] - 2026-05-07
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Use the local `Legion::Identity::Process` identity for unauthenticated loopback API principals even when the process is only fallback-bound, avoiding generic `system:system` attribution in downstream LLM audit flows.
|
|
21
|
+
|
|
22
|
+
## [1.9.25] - 2026-05-07
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- Updated identity model references in `identity_audit.rb` and `identity/broker.rb` to use the portable namespace (`Identity::AuditLog`, `Identity::Principal`, `Identity::GroupMembership`) after legacy top-level identity models were removed from legion-data.
|
|
26
|
+
|
|
27
|
+
## [1.9.24] - 2026-05-07
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- Removed deprecated direct AI provider extensions (`lex-azure-ai`, `lex-bedrock`, `lex-claude`, `lex-foundry`, `lex-gemini`, `lex-ollama`, `lex-openai`) from the extension catalog; use their `lex-llm-*` counterparts instead.
|
|
31
|
+
|
|
5
32
|
## [1.9.23] - 2026-05-07
|
|
6
33
|
|
|
7
34
|
### Fixed
|
data/CLAUDE.md
CHANGED
|
@@ -1,805 +1,98 @@
|
|
|
1
|
-
# LegionIO
|
|
1
|
+
# LegionIO
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
- **Parent**: `../CLAUDE.md`
|
|
5
|
-
|
|
6
|
-
## Purpose
|
|
7
|
-
|
|
8
|
-
The primary gem for the LegionIO framework. An extensible async job engine for scheduling tasks, creating relationships between services, and running them concurrently via RabbitMQ. Orchestrates all `legion-*` gems and loads Legion Extensions (LEXs).
|
|
3
|
+
Primary gem. Orchestrates all `legion-*` gems and loads LEX extensions.
|
|
9
4
|
|
|
10
5
|
**GitHub**: https://github.com/LegionIO/LegionIO
|
|
11
|
-
**Gem**: `legionio`
|
|
12
|
-
**Version**: 1.8.12
|
|
13
|
-
**License**: Apache-2.0
|
|
14
|
-
**Docker**: `legionio/legion`
|
|
15
|
-
**Ruby**: >= 3.4
|
|
6
|
+
**Gem**: `legionio` | **Ruby**: >= 3.4
|
|
16
7
|
|
|
17
8
|
## Binary Split
|
|
18
9
|
|
|
19
10
|
| Binary | Purpose |
|
|
20
11
|
|--------|---------|
|
|
21
|
-
| `legion` | Interactive TTY shell + dev-workflow
|
|
22
|
-
| `legionio` | Daemon lifecycle +
|
|
23
|
-
|
|
24
|
-
`legion` with no args launches the TTY interactive shell. With args, it routes to dev-workflow subcommands.
|
|
25
|
-
`legionio` is the full operational CLI — all 40+ subcommands.
|
|
26
|
-
|
|
27
|
-
## Architecture
|
|
28
|
-
|
|
29
|
-
### Boot Sequence (exe/legion)
|
|
30
|
-
|
|
31
|
-
Before any Legion code loads, `exe/legion` applies three performance optimizations:
|
|
32
|
-
|
|
33
|
-
1. **YJIT** — `RubyVM::YJIT.enable` for 15-30% runtime throughput (guarded with `if defined?`)
|
|
34
|
-
2. **GC tuning** — pre-allocates 600k heap slots, raises malloc limits (all `||=` so ENV overrides are respected)
|
|
35
|
-
3. **bootsnap** — caches YARV bytecodes and `$LOAD_PATH` resolution at `~/.legionio/cache/bootsnap/`
|
|
36
|
-
|
|
37
|
-
### Startup Sequence
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
Legion.start
|
|
41
|
-
└── Legion::Service.new
|
|
42
|
-
├── 1. setup_logging (legion-logging)
|
|
43
|
-
├── 2. setup_settings (legion-settings, loads /etc/legionio, ~/legionio, ./settings)
|
|
44
|
-
├── 3. Legion::Crypt.start (legion-crypt, Vault connection)
|
|
45
|
-
├── 4. setup_transport (legion-transport, RabbitMQ connection)
|
|
46
|
-
├── 5. require legion-cache
|
|
47
|
-
├── 6. setup_data (legion-data, MySQL/SQLite + migrations, optional)
|
|
48
|
-
├── 7. setup_rbac (legion-rbac, optional)
|
|
49
|
-
├── 8. setup_llm (legion-llm, AI provider setup + routing, optional)
|
|
50
|
-
├── 9. setup_apollo (legion-apollo, shared + local knowledge store, optional)
|
|
51
|
-
├── 10. setup_gaia (legion-gaia, cognitive coordination layer, optional)
|
|
52
|
-
├── 11. setup_telemetry (OpenTelemetry, optional)
|
|
53
|
-
├── 12. setup_supervision (process supervision)
|
|
54
|
-
├── 13. load_extensions (multi-phase: phase 0 (identity providers) loads and hooks actors first, then phase 1 (everything else))
|
|
55
|
-
├── 14. Legion::Crypt.cs (distribute cluster secret)
|
|
56
|
-
└── 15. setup_api (start Sinatra/Puma on port 4567)
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Each phase calls `Legion::Readiness.mark_ready(:component)`. All phases are individually toggleable via `Service.new(transport: false, ...)`.
|
|
60
|
-
|
|
61
|
-
Extension loading is multi-phase and parallel: `hook_extensions` calls `group_by_phase` to partition discovered extensions by phase number (from the category registry), then iterates phases sequentially. Phase 0 contains identity providers (`lex-identity-*` gems, category `:identity`, tier 0); phase 1 contains all other extensions. Within each phase, extensions are `require`d and `autobuild` runs concurrently on a `Concurrent::FixedThreadPool(min(count, extensions.parallel_pool_size))`, collecting actors into a thread-safe `Concurrent::Array` of `@pending_actors`. Pool size defaults to 24, configurable via `Legion::Settings[:extensions][:parallel_pool_size]`. After each phase's extensions are loaded, `hook_phase_actors` starts AMQP subscriptions, timers, and other actor types for that phase sequentially — ensuring identity providers are fully running before any other extension boots. Catalog transitions (`transition(:running)` and `flush_persisted_transitions`) happen after all phases complete. Thread safety relies on ThreadLocal AMQP channels, per-extension Settings keys, and sequential post-processing of Catalog transitions and Registry writes.
|
|
62
|
-
|
|
63
|
-
### Reload Sequence
|
|
64
|
-
|
|
65
|
-
`Legion.reload` shuts down all subsystems in reverse order, waits for them to drain, then re-runs setup from settings onward. Extensions and API are re-loaded fresh.
|
|
66
|
-
|
|
67
|
-
### Module Structure
|
|
68
|
-
|
|
69
|
-
```
|
|
70
|
-
Legion (lib/legion.rb)
|
|
71
|
-
├── Service # Orchestrator: initializes all modules, manages lifecycle
|
|
72
|
-
│ # Entry points: Legion.start, .shutdown, .reload
|
|
73
|
-
├── Process # Daemonization: PID management, signal traps (SIGINT=quit), main loop
|
|
74
|
-
├── Readiness # Startup readiness tracking
|
|
75
|
-
│ # COMPONENTS: settings, crypt, transport, cache, data, gaia, extensions, api
|
|
76
|
-
│ # Readiness.ready? checks all; /api/ready returns JSON status
|
|
77
|
-
├── Events # In-process pub/sub event bus
|
|
78
|
-
│ # Events.on(name) / .emit(name, **payload) / .once / .off
|
|
79
|
-
│ # Wildcard '*' listener supported
|
|
80
|
-
│ # Lifecycle: service.ready, service.shutting_down, service.shutdown
|
|
81
|
-
│ # Extension: extension.loaded
|
|
82
|
-
│ # Runner: ingress.received
|
|
83
|
-
├── Ingress # Universal entry point for runner invocation
|
|
84
|
-
│ # Sources: amqp, http, cli, api — all normalize through here
|
|
85
|
-
│ # Ingress.run(payload:, runner_class:, function:, source:)
|
|
86
|
-
│ # Ingress.normalize returns message hash without executing
|
|
87
|
-
├── Extensions # LEX discovery, loading, and lifecycle management
|
|
88
|
-
│ ├── Core # Mixin: data_required?, cache_required?, crypt_required?, mcp_tools?, mcp_tools_deferred?, etc.
|
|
89
|
-
│ ├── Actors/ # Actor execution modes
|
|
90
|
-
│ │ ├── Base # Base actor class
|
|
91
|
-
│ │ ├── Every # Run at interval (timer)
|
|
92
|
-
│ │ ├── Loop # Continuous loop
|
|
93
|
-
│ │ ├── Once # Run once at startup
|
|
94
|
-
│ │ ├── Poll # Polling actor
|
|
95
|
-
│ │ ├── Subscription # AMQP subscription (FixedThreadPool per worker count)
|
|
96
|
-
│ │ └── Nothing # No-op actor
|
|
97
|
-
│ ├── Builders/ # Build actors and runners from LEX definitions
|
|
98
|
-
│ │ ├── Actors # Build actors from extension definitions
|
|
99
|
-
│ │ ├── Runners # Build runners from extension definitions; exposes `runner_modules` accessor for Discovery
|
|
100
|
-
│ │ ├── Helpers # Builder utilities
|
|
101
|
-
│ │ ├── Hooks # Webhook hook system builder
|
|
102
|
-
│ │ └── Routes # Auto-route builder: introspects runners, registers POST /api/extensions/* routes
|
|
103
|
-
│ ├── Helpers/ # Helper mixins for extensions
|
|
104
|
-
│ │ ├── Base # Base helper mixin
|
|
105
|
-
│ │ ├── Core # Core helper mixin
|
|
106
|
-
│ │ ├── Cache # Cache access helper
|
|
107
|
-
│ │ ├── Data # Database access helper
|
|
108
|
-
│ │ ├── Logger # Logging helper
|
|
109
|
-
│ │ ├── Transport # AMQP transport helper
|
|
110
|
-
│ │ ├── Task # Task management helper (generate_task_id)
|
|
111
|
-
│ │ └── Lex # LEX metadata helper
|
|
112
|
-
│ ├── Data/ # Extension data layer
|
|
113
|
-
│ │ ├── Migrator # Extension-specific migrations
|
|
114
|
-
│ │ └── Model # Extension-specific models
|
|
115
|
-
│ ├── Hooks/
|
|
116
|
-
│ │ └── Base # Webhook hook system base class
|
|
117
|
-
│ └── Transport # Extension transport setup
|
|
118
|
-
│
|
|
119
|
-
├── API (Sinatra) # Full REST API under /api/ prefix, served by Puma
|
|
120
|
-
│ ├── Helpers # json_response, json_collection, json_error, pagination, redact_hash
|
|
121
|
-
│ │ # parse_request_body, paginate dataset
|
|
122
|
-
│ ├── Routes/
|
|
123
|
-
│ │ ├── Tasks # CRUD + trigger via Ingress, task logs
|
|
124
|
-
│ │ ├── Extensions # Nested: extensions/runners/functions + invoke
|
|
125
|
-
│ │ ├── Nodes # List/show nodes (filterable by active/status)
|
|
126
|
-
│ │ ├── Schedules # CRUD for lex-scheduler schedules + logs
|
|
127
|
-
│ │ ├── Relationships # CRUD (backed by legion-data migration 013)
|
|
128
|
-
│ │ ├── Chains # Stub (501) - no data model yet
|
|
129
|
-
│ │ ├── Settings # Read/write settings with redaction + readonly guards
|
|
130
|
-
│ │ ├── Events # SSE stream (sinatra stream) + ring buffer polling fallback
|
|
131
|
-
│ │ ├── Transport # Connection status, exchanges, queues, publish
|
|
132
|
-
│ │ ├── Hooks # List + trigger registered extension hooks
|
|
133
|
-
│ │ ├── LexDispatch # Dispatch: `POST /api/extensions/:lex/:type/:component/:method` + discovery GET
|
|
134
|
-
│ │ ├── Workers # Digital worker lifecycle (`/api/workers/*`) + team routes (`/api/teams/*`)
|
|
135
|
-
│ │ ├── Coldstart # `POST /api/coldstart/ingest` — trigger lex-coldstart ingest from API
|
|
136
|
-
│ │ ├── Capacity # Aggregate, forecast, per-worker capacity endpoints
|
|
137
|
-
│ │ ├── Tenants # Tenant listing, provisioning, suspension, quota
|
|
138
|
-
│ │ ├── Audit # Audit log query: list, show, count, export
|
|
139
|
-
│ │ ├── Rbac # RBAC: role listing, permission grants, access checks
|
|
140
|
-
│ │ ├── Webhooks # Webhook subscription CRUD + delivery status
|
|
141
|
-
│ │ └── Validators # Request body schema validation helpers
|
|
142
|
-
│ ├── Middleware/
|
|
143
|
-
│ │ ├── Auth # JWT Bearer auth middleware (real validation, skip paths for health/ready)
|
|
144
|
-
│ │ ├── Tenant # Tenant extraction from JWT/header, sets TenantContext
|
|
145
|
-
│ │ ├── ApiVersion # `/api/v1/` rewrite, Deprecation/Sunset headers
|
|
146
|
-
│ │ ├── BodyLimit # Request body size limit (1MB max, returns 413)
|
|
147
|
-
│ │ └── RateLimit # Sliding-window rate limiting with per-IP/agent/tenant tiers
|
|
148
|
-
│ └── router # Class-level Router: extension_names, find_extension_route, registered_routes
|
|
149
|
-
│ # Populated by Builders::Routes during autobuild via LexDispatch
|
|
150
|
-
│
|
|
151
|
-
├── MCP (legion-mcp gem) # Extracted to standalone gem — see legion-mcp/CLAUDE.md
|
|
152
|
-
│ └── (tools, 2 resources, TierRouter, PatternStore, ContextGuard, Observer, EmbeddingIndex)
|
|
153
|
-
│
|
|
154
|
-
├── Tools # Canonical tool layer — replaces Extensions::Capability and Catalog::Registry
|
|
155
|
-
│ ├── Base # Base class for all framework tools (Do, Status, Config are built-in statics)
|
|
156
|
-
│ ├── Registry # always/deferred classification for all tools; replaces Catalog::Registry
|
|
157
|
-
│ │ # Extensions declare tools via `mcp_tools?` / `mcp_tools_deferred?` DSL on Core
|
|
158
|
-
│ ├── Discovery # Auto-discovers tools from extension runner modules at boot
|
|
159
|
-
│ │ # `runner_modules` accessor on Builders::Runners feeds Discovery
|
|
160
|
-
│ │ # `loaded_extension_modules` on Extensions exposes the full set
|
|
161
|
-
│ └── EmbeddingCache # 5-tier persistent embedding cache:
|
|
162
|
-
│ # L0 in-memory hash → L1 Cache::Local → L2 Cache → L3 Data::Local → L4 Data
|
|
163
|
-
│
|
|
164
|
-
├── DigitalWorker # Digital worker platform (AI-as-labor governance)
|
|
165
|
-
│ ├── Lifecycle # Worker state machine (active/paused/retired/terminated)
|
|
166
|
-
│ ├── Registry # In-process worker registry
|
|
167
|
-
│ ├── RiskTier # AIRB risk tier classification + governance constraints
|
|
168
|
-
│ └── ValueMetrics # Token/cost/latency value tracking
|
|
169
|
-
│
|
|
170
|
-
├── Graph # Task relationship visualization
|
|
171
|
-
│ ├── Builder # Builds adjacency graph from relationships table (chain/worker filtering)
|
|
172
|
-
│ └── Exporter # Renders to Mermaid and DOT (Graphviz) formats
|
|
173
|
-
│
|
|
174
|
-
├── TraceSearch # Natural language trace search via LLM structured output
|
|
175
|
-
│ # Translates NL queries to safe JSON filter DSL (column allowlist)
|
|
176
|
-
│ # Uses Legion::LLM.structured for JSON extraction
|
|
177
|
-
│
|
|
178
|
-
├── Runner # Task execution engine
|
|
179
|
-
│ ├── Log # Task logging
|
|
180
|
-
│ └── Status # Task status tracking
|
|
181
|
-
│
|
|
182
|
-
├── Supervision # Process supervision
|
|
183
|
-
├── Lex # Legacy LEX gem discovery (see Extensions for current code)
|
|
184
|
-
│
|
|
185
|
-
└── CLI (Thor) # Unified CLI: exe/legion -> Legion::CLI::Main
|
|
186
|
-
├── Output::Formatter # color tables, JSON mode, status indicators, ANSI stripping
|
|
187
|
-
├── Theme # Purple palette, orbital ASCII banner, branded CLI output
|
|
188
|
-
├── Connection # Lazy connection manager (ensure_settings, ensure_transport, etc.)
|
|
189
|
-
├── Error # CLI-specific error class
|
|
190
|
-
├── Start # `legion start` - daemon boot via Legion::Process
|
|
191
|
-
├── Status # `legion status` - probes API or shows static info
|
|
192
|
-
├── Check # `legion check` - smoke-test subsystems, 3 depth levels
|
|
193
|
-
├── Lex # `legion lex` - list, info, create, enable, disable, exec/invoke_ext + LexGenerator
|
|
194
|
-
├── Task # `legion task` - list, show, logs, trigger (mapped as run), purge
|
|
195
|
-
├── Chain # `legion chain` - list, create, delete
|
|
196
|
-
├── Config # `legion config` - show (redacted), path, validate, scaffold
|
|
197
|
-
├── ConfigScaffold # `legion config scaffold` - generates starter JSON config files
|
|
198
|
-
├── Generate # `legion generate` - runner, actor, exchange, queue, message
|
|
199
|
-
├── Mcp # `legion mcp` - stdio (default) or HTTP transport
|
|
200
|
-
├── Worker # `legion worker` - digital worker lifecycle management
|
|
201
|
-
├── Coldstart # `legion coldstart` - ingest CLAUDE.md/MEMORY.md into lex-memory
|
|
202
|
-
├── Chat # `legion chat` - interactive AI REPL + headless prompt mode
|
|
203
|
-
│ ├── Session # Multi-turn chat session with streaming
|
|
204
|
-
│ ├── SessionStore # Persistent session save/load/list/resume/fork
|
|
205
|
-
│ ├── Permissions # Tool permission model (interactive/auto_approve/read_only)
|
|
206
|
-
│ ├── ToolRegistry # Chat tool discovery and registration (40 built-in tools + extension tools)
|
|
207
|
-
│ ├── ExtensionTool # permission_tier DSL module for LEX chat tools (:read/:write/:shell)
|
|
208
|
-
│ ├── ExtensionToolLoader # Lazy discovery of tools/ directories from loaded extensions
|
|
209
|
-
│ ├── Context # Project awareness (git, language, instructions, extra dirs)
|
|
210
|
-
│ ├── MarkdownRenderer # Terminal markdown rendering with syntax highlighting
|
|
211
|
-
│ ├── WebFetch # /fetch slash command for web page context injection
|
|
212
|
-
│ ├── WebSearch # DuckDuckGo HTML scraping search engine
|
|
213
|
-
│ ├── Checkpoint # File edit checkpointing with /rewind undo
|
|
214
|
-
│ ├── MemoryStore # Persistent memory (project + global scopes, markdown files)
|
|
215
|
-
│ ├── Subagent # Background subagent spawning via headless subprocess
|
|
216
|
-
│ ├── AgentRegistry # Custom agent definitions from .legion/agents/ (JSON/YAML)
|
|
217
|
-
│ ├── AgentDelegator # @name at-mention parsing and agent dispatch
|
|
218
|
-
│ ├── ChatLogger # Chat-specific logging
|
|
219
|
-
│ └── Tools/ # Built-in tools: read_file, write_file, edit_file,
|
|
220
|
-
│ # search_files, search_content, run_command,
|
|
221
|
-
│ # save_memory, search_memory, web_search, spawn_agent,
|
|
222
|
-
│ # search_traces, query_knowledge, ingest_knowledge,
|
|
223
|
-
│ # consolidate_memory, relate_knowledge, knowledge_maintenance,
|
|
224
|
-
│ # knowledge_stats, summarize_traces, list_extensions,
|
|
225
|
-
│ # manage_tasks, system_status, view_events
|
|
226
|
-
├── Memory # `legion memory` - persistent memory CLI (list/add/forget/search)
|
|
227
|
-
├── Plan # `legion plan` - read-only exploration mode
|
|
228
|
-
├── Swarm # `legion swarm` - multi-agent workflow orchestration
|
|
229
|
-
├── Commit # `legion commit` - AI-generated commit messages via LLM
|
|
230
|
-
├── Pr # `legion pr` - AI-generated PR title and description via LLM
|
|
231
|
-
├── Review # `legion review` - AI code review with severity levels
|
|
232
|
-
├── Gaia # `legion gaia` - Gaia status
|
|
233
|
-
├── Llm # `legion llm` - LLM subsystem status and provider health
|
|
234
|
-
├── Detect # `legion detect scan` - scan environment and recommend extensions
|
|
235
|
-
├── Observe # `legion observe stats` - MCP tool usage statistics from Observer
|
|
236
|
-
├── Tty # `legion tty interactive` - launch rich terminal UI (legion-tty)
|
|
237
|
-
├── Graph # `legion graph show` - task relationship graph (mermaid/dot)
|
|
238
|
-
├── Trace # `legion trace search` - NL trace search via LLM
|
|
239
|
-
├── Dashboard # `legion dashboard` - TUI operational dashboard with auto-refresh
|
|
240
|
-
│ ├── DataFetcher # Polls REST API for workers, health, events
|
|
241
|
-
│ └── Renderer # Terminal-based dashboard rendering
|
|
242
|
-
├── Cost # `legion cost` - cost summary, worker, team, top, budget, export
|
|
243
|
-
│ └── DataClient # API client for cost data aggregation
|
|
244
|
-
├── Skill # `legion skill` - list, show, create, run skill files
|
|
245
|
-
├── Audit # `legion audit` - query audit log (list, show, count, export)
|
|
246
|
-
├── Rbac # `legion rbac` - role management, permission grants, access check
|
|
247
|
-
├── Init # `legion init` - interactive project setup wizard
|
|
248
|
-
│ ├── ConfigGenerator # Generates starter config files from templates
|
|
249
|
-
│ └── EnvironmentDetector # Detects runtime environment (Docker, CI, services)
|
|
250
|
-
├── Marketplace # `legion marketplace` - extension marketplace (search, install, publish)
|
|
251
|
-
├── Notebook # `legion notebook` - interactive task notebook REPL
|
|
252
|
-
├── Update # `legion update` - self-update via Homebrew or gem
|
|
253
|
-
├── Schedule # `legion schedule` - schedule list/show/add/remove/logs
|
|
254
|
-
└── Completion # `legion completion` - bash/zsh tab completion scripts
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### Extension Discovery
|
|
12
|
+
| `legion` | Interactive TTY shell + dev-workflow (chat, commit, review, plan, memory) |
|
|
13
|
+
| `legionio` | Daemon lifecycle + operational commands (start, stop, lex, task, config, mcp) |
|
|
258
14
|
|
|
259
|
-
|
|
15
|
+
## Boot Sequence
|
|
260
16
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
| Category | Type | Tier | Phase | Matches |
|
|
264
|
-
|----------|------|------|-------|---------|
|
|
265
|
-
| `identity` | prefix | 0 | 0 | `lex-identity-*` gems |
|
|
266
|
-
| `core` | list | 1 | 1 | explicitly listed core extensions |
|
|
267
|
-
| `ai` | list | 2 | 1 | explicitly listed AI provider extensions |
|
|
268
|
-
| `gaia` | list | 3 | 1 | explicitly listed GAIA extensions |
|
|
269
|
-
| `agentic` | prefix | 4 | 1 | `lex-agentic-*` gems |
|
|
270
|
-
|
|
271
|
-
**Role-based filtering**: After discovery, `apply_role_filter` prunes extensions based on `Legion::Settings[:role][:profile]`:
|
|
272
|
-
|
|
273
|
-
| Profile | What loads |
|
|
274
|
-
|---------|-----------|
|
|
275
|
-
| `nil` (default) | Everything — no filtering |
|
|
276
|
-
| `:core` | 14 core operational extensions only |
|
|
277
|
-
| `:cognitive` | core + all agentic extensions |
|
|
278
|
-
| `:service` | core + service + other integrations |
|
|
279
|
-
| `:dev` | core + AI + essential agentic (~20 extensions) |
|
|
280
|
-
| `:custom` | only what's listed in `role[:extensions]` |
|
|
281
|
-
|
|
282
|
-
Configure via settings JSON: `{"role": {"profile": "dev"}}`
|
|
283
|
-
|
|
284
|
-
Loader checks per extension:
|
|
285
|
-
- `data_required?` — skipped if legion-data not connected
|
|
286
|
-
- `cache_required?` — skipped if legion-cache not connected
|
|
287
|
-
- `crypt_required?` — skipped if cluster secret not available
|
|
288
|
-
- `vault_required?` — skipped if Vault not connected
|
|
289
|
-
- `llm_required?` — skipped if legion-llm not connected
|
|
290
|
-
|
|
291
|
-
After loading, each extension calls `autobuild` then publishes a `LexRegister` message to RabbitMQ to persist runners in the database.
|
|
292
|
-
|
|
293
|
-
### CLI Details
|
|
17
|
+
`exe/legion` applies: YJIT, GC tuning (600k heap slots), bootsnap cache.
|
|
294
18
|
|
|
295
19
|
```
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
show <id>
|
|
313
|
-
logs <id> [-n 50]
|
|
314
|
-
run <ext.runner.func> [key:val ...] # 'run' is mapped to trigger method
|
|
315
|
-
purge [--days 7] [-y]
|
|
316
|
-
|
|
317
|
-
chain
|
|
318
|
-
list [-n 20]
|
|
319
|
-
create <name>
|
|
320
|
-
delete <id> [-y]
|
|
321
|
-
|
|
322
|
-
config
|
|
323
|
-
show [-s section]
|
|
324
|
-
path
|
|
325
|
-
validate
|
|
326
|
-
scaffold [--dir ./settings] [--only transport,data,...] [--full] [--force]
|
|
327
|
-
|
|
328
|
-
generate (alias: g)
|
|
329
|
-
runner <name> [--functions x]
|
|
330
|
-
actor <name> [--type sub]
|
|
331
|
-
exchange <name>
|
|
332
|
-
queue <name>
|
|
333
|
-
message <name>
|
|
334
|
-
tool <name>
|
|
335
|
-
|
|
336
|
-
mcp
|
|
337
|
-
stdio # default
|
|
338
|
-
http [--port 9393] [--host localhost]
|
|
339
|
-
|
|
340
|
-
worker
|
|
341
|
-
list [-s status] [-t risk_tier]
|
|
342
|
-
show <id>
|
|
343
|
-
create <name> --entra_app_id ID --owner_msid EMAIL --extension NAME [--team T] [--client_secret S]
|
|
344
|
-
pause <id>
|
|
345
|
-
activate <id>
|
|
346
|
-
retire <id>
|
|
347
|
-
terminate <id>
|
|
348
|
-
costs [--days 30]
|
|
349
|
-
|
|
350
|
-
coldstart
|
|
351
|
-
ingest <path> # file or directory, parses CLAUDE.md / MEMORY.md
|
|
352
|
-
preview <path> # dry-run, shows traces without storing
|
|
353
|
-
status
|
|
354
|
-
|
|
355
|
-
chat # interactive AI REPL (requires legion-llm)
|
|
356
|
-
prompt <text> # headless single-prompt mode (also accepts stdin pipe)
|
|
357
|
-
[--model MODEL] [--provider PROVIDER]
|
|
358
|
-
[--no_markdown] [--incognito]
|
|
359
|
-
[--max_budget_usd N] [--auto_approve / -y]
|
|
360
|
-
[--add_dir DIR ...] [--personality STYLE]
|
|
361
|
-
[--continue / -c] [--resume NAME] [--fork NAME]
|
|
362
|
-
# Slash commands:
|
|
363
|
-
# /help, /quit, /cost, /status, /clear, /new
|
|
364
|
-
# /save NAME, /load NAME, /sessions, /compact
|
|
365
|
-
# /fetch URL, /search QUERY, /diff, /copy
|
|
366
|
-
# /rewind [N|FILE], /memory [add TEXT]
|
|
367
|
-
# /agent TASK, /agents, /plan, /swarm NAME
|
|
368
|
-
# /review [SCOPE], /permissions [MODE], /personality STYLE
|
|
369
|
-
# /model X, /edit (open $EDITOR)
|
|
370
|
-
# /commit, /workers, /dream
|
|
371
|
-
# Bang commands: !<shell command> (quick shell exec with context injection)
|
|
372
|
-
# At-mentions: @agent_name <task> (delegate to custom agent)
|
|
373
|
-
|
|
374
|
-
memory # persistent memory management
|
|
375
|
-
list [--global]
|
|
376
|
-
add TEXT [--global]
|
|
377
|
-
forget INDEX [--global]
|
|
378
|
-
search QUERY
|
|
379
|
-
clear [--global] [-y]
|
|
380
|
-
|
|
381
|
-
plan # read-only exploration mode (no writes/edits/shell)
|
|
382
|
-
[--model MODEL] [--provider PROVIDER]
|
|
383
|
-
# Slash commands: /save (writes plan to docs/work/planning/), /help, /quit
|
|
384
|
-
|
|
385
|
-
swarm # multi-agent workflow orchestration
|
|
386
|
-
start NAME # run a workflow from .legion/swarms/NAME.json
|
|
387
|
-
list # list available workflows
|
|
388
|
-
show NAME # show workflow details
|
|
389
|
-
[--model MODEL]
|
|
390
|
-
|
|
391
|
-
commit # AI-generated commit message via LLM
|
|
392
|
-
[--model MODEL] [--provider PROVIDER]
|
|
393
|
-
|
|
394
|
-
pr # AI-generated PR title + description via LLM
|
|
395
|
-
[--model MODEL] [--provider PROVIDER]
|
|
396
|
-
[--base BRANCH] [--draft]
|
|
397
|
-
|
|
398
|
-
review [FILES...] # AI code review with severity levels
|
|
399
|
-
[--model MODEL] [--provider PROVIDER]
|
|
400
|
-
[--diff] # review staged/unstaged diff instead of files
|
|
401
|
-
|
|
402
|
-
gaia
|
|
403
|
-
status # show Gaia system status
|
|
404
|
-
|
|
405
|
-
schedule
|
|
406
|
-
list
|
|
407
|
-
show <id>
|
|
408
|
-
add <name> <cron> <runner>
|
|
409
|
-
remove <id>
|
|
410
|
-
logs <id>
|
|
411
|
-
|
|
412
|
-
completion
|
|
413
|
-
bash # output bash completion script
|
|
414
|
-
zsh # output zsh completion script
|
|
415
|
-
install # print installation instructions
|
|
416
|
-
|
|
417
|
-
openapi
|
|
418
|
-
generate [-o FILE] # output OpenAPI 3.1.0 spec JSON
|
|
419
|
-
routes # list all API routes with HTTP method + summary
|
|
420
|
-
|
|
421
|
-
doctor [--fix] [--json] # diagnose environment, suggest/apply fixes
|
|
422
|
-
# checks: Ruby, bundle, config, RabbitMQ, DB, cache, Vault,
|
|
423
|
-
# extensions, PID files, permissions
|
|
424
|
-
# exit 0=all pass, 1=any fail
|
|
425
|
-
|
|
426
|
-
telemetry
|
|
427
|
-
stats [SESSION_ID] # aggregate or per-session telemetry stats
|
|
428
|
-
ingest PATH # manually ingest a session log file
|
|
429
|
-
|
|
430
|
-
graph
|
|
431
|
-
show [--chain ID] [--worker ID] # display task relationship graph
|
|
432
|
-
[--format mermaid|dot] [--output FILE] [--limit N]
|
|
433
|
-
|
|
434
|
-
trace
|
|
435
|
-
search QUERY [--limit N] # natural language trace search via LLM
|
|
436
|
-
|
|
437
|
-
dashboard
|
|
438
|
-
start [--url URL] [--refresh N] # TUI operational dashboard with auto-refresh
|
|
439
|
-
|
|
440
|
-
cost
|
|
441
|
-
summary # overall cost summary (today/week/month)
|
|
442
|
-
worker <id> # per-worker cost breakdown
|
|
443
|
-
team <name> # per-team cost attribution
|
|
444
|
-
top [--limit 10] # top cost consumers
|
|
445
|
-
budget # budget status
|
|
446
|
-
export [--format csv|json] # export cost data
|
|
447
|
-
|
|
448
|
-
skill
|
|
449
|
-
list # list discovered skills
|
|
450
|
-
show <name> # display skill definition
|
|
451
|
-
create <name> # scaffold new skill file
|
|
452
|
-
run <name> [args] # run skill outside of chat
|
|
453
|
-
|
|
454
|
-
audit
|
|
455
|
-
list [--entity TYPE] [--action ACT] [--limit N]
|
|
456
|
-
show <id>
|
|
457
|
-
count [--entity TYPE] [--since TIME]
|
|
458
|
-
export [--format json|csv]
|
|
459
|
-
|
|
460
|
-
rbac
|
|
461
|
-
roles # list roles
|
|
462
|
-
grants <identity> # list grants for identity
|
|
463
|
-
check <identity> <resource> <action> # check access
|
|
464
|
-
|
|
465
|
-
init # interactive project setup wizard
|
|
466
|
-
[--dir PATH] [--template NAME]
|
|
467
|
-
|
|
468
|
-
marketplace
|
|
469
|
-
search QUERY # search extension marketplace
|
|
470
|
-
install NAME # install extension
|
|
471
|
-
publish # publish current extension
|
|
472
|
-
|
|
473
|
-
notebook # interactive task notebook REPL
|
|
474
|
-
|
|
475
|
-
update # self-update via Homebrew or gem
|
|
476
|
-
|
|
477
|
-
auth
|
|
478
|
-
teams [--tenant-id ID] [--client-id ID] # browser OAuth flow for Microsoft Teams
|
|
20
|
+
Legion.start → Legion::Service.new
|
|
21
|
+
1. setup_logging
|
|
22
|
+
2. setup_settings
|
|
23
|
+
3. Legion::Crypt.start
|
|
24
|
+
4. setup_transport (RabbitMQ)
|
|
25
|
+
5. require legion-cache
|
|
26
|
+
6. setup_data (optional)
|
|
27
|
+
7. setup_rbac (optional)
|
|
28
|
+
8. setup_llm (optional)
|
|
29
|
+
9. setup_apollo (optional)
|
|
30
|
+
10. setup_gaia (optional)
|
|
31
|
+
11. setup_telemetry (optional)
|
|
32
|
+
12. setup_supervision
|
|
33
|
+
13. load_extensions (multi-phase: phase 0 identity, phase 1 everything else, parallel)
|
|
34
|
+
14. Legion::Crypt.cs (distribute cluster secret)
|
|
35
|
+
15. setup_api (Sinatra/Puma on port 4567)
|
|
479
36
|
```
|
|
480
37
|
|
|
481
|
-
|
|
482
|
-
- Thor 1.5+ reserves `run` as a method name - use `map 'run' => :trigger` in Task subcommand
|
|
483
|
-
- `::Process` must be explicit inside `Legion::` namespace (resolves to `Legion::Process` otherwise)
|
|
484
|
-
- `Connection` is a module with class-level `ensure_*` methods, not instance-based
|
|
485
|
-
- All commands support `--json` and `--no-color` at the class_option level
|
|
486
|
-
- `::JSON` must be explicit inside `Legion::` namespace (resolves to `Legion::JSON` otherwise) — affects `pretty_generate` in config scaffold
|
|
38
|
+
Extension loading: phase 0 = `lex-identity-*` (sequential), phase 1 = everything else on `Concurrent::FixedThreadPool(24)`. After all phases: catalog transitions + registry writes.
|
|
487
39
|
|
|
488
|
-
|
|
40
|
+
## Extension Discovery
|
|
489
41
|
|
|
490
|
-
|
|
491
|
-
- All routes registered via `register Routes::ModuleName`
|
|
492
|
-
- Requires `set :host_authorization, permitted: :any` (Sinatra 4.0+, else all requests get 403)
|
|
493
|
-
- Response format: `{ data: ..., meta: { timestamp:, node: } }`
|
|
494
|
-
- Error format: `{ error: { code:, message: }, meta: { timestamp:, node: } }`
|
|
495
|
-
- `Legion::JSON.dump` takes exactly 1 positional arg — wrap kwargs in explicit `{}`
|
|
496
|
-
- `Legion::JSON.load` returns symbol keys
|
|
497
|
-
- Settings write: `Legion::Settings.loader.settings[:key] = value`
|
|
498
|
-
- `Legion::Settings.loader.to_hash` for full settings hash
|
|
42
|
+
`find_extensions` discovers `lex-*` gems via Bundler or `Gem::Specification`. Category registry determines load phase and tier. Extensions declare requirements via `data_required?`, `cache_required?`, `crypt_required?`, `vault_required?`, `llm_required?` — skipped if dependency unavailable.
|
|
499
43
|
|
|
500
|
-
|
|
44
|
+
Role profiles filter extensions: `nil` (all), `:core` (14), `:cognitive` (core + agentic), `:service` (core + integrations), `:dev` (core + AI + essential agentic), `:custom` (explicit list).
|
|
501
45
|
|
|
502
|
-
|
|
46
|
+
## CLI Design Rules
|
|
503
47
|
|
|
504
|
-
-
|
|
505
|
-
-
|
|
506
|
-
-
|
|
48
|
+
- Thor 1.5+ reserves `run` — use `map 'run' => :trigger` in Task subcommand
|
|
49
|
+
- `::Process` must be explicit (resolves to `Legion::Process` otherwise)
|
|
50
|
+
- `::JSON` must be explicit (resolves to `Legion::JSON` otherwise)
|
|
51
|
+
- All commands support `--json` and `--no-color` at class_option level
|
|
52
|
+
- `Connection` module has class-level `ensure_*` methods, not instance-based
|
|
507
53
|
|
|
508
|
-
|
|
54
|
+
## API Design
|
|
509
55
|
|
|
510
|
-
`
|
|
56
|
+
- `Legion::API < Sinatra::Base` with `set :host_authorization, permitted: :any`
|
|
57
|
+
- Response: `{ data: ..., meta: { timestamp:, node: } }`
|
|
58
|
+
- Error: `{ error: { code:, message: }, meta: ... }`
|
|
59
|
+
- `Legion::JSON.dump` — 1 positional arg, wrap kwargs in `{}`
|
|
60
|
+
- `Legion::JSON.load` — returns symbol keys
|
|
511
61
|
|
|
512
|
-
|
|
513
|
-
- `legion-cache` activates the `Memory` adapter (pure in-memory cache with TTL expiry and Mutex synchronization)
|
|
514
|
-
- Useful for single-machine development, CI, and testing without infrastructure dependencies
|
|
515
|
-
- Detection: `Connection.lite_mode?` checks `TYPE == 'local'`; cache checks `LEGION_MODE=lite` env var
|
|
62
|
+
## Module Structure (Key Parts)
|
|
516
63
|
|
|
517
|
-
### `legion do`
|
|
518
|
-
|
|
519
|
-
Natural-language intent router at the CLI level:
|
|
520
|
-
|
|
521
|
-
```bash
|
|
522
|
-
legion do "list all running tasks"
|
|
523
|
-
legion do "start the email extension"
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
Resolves free-text intent to Capability Registry entries. If the daemon is running, delegates to the MCP `legion.do` tool (Tier 0 fast path). If no daemon, runs in-process. Returns the runner's response.
|
|
527
|
-
|
|
528
|
-
### `legion mind-growth`
|
|
529
|
-
|
|
530
|
-
CLI for the autonomous cognitive architecture expansion system (`lex-mind-growth`). 10 subcommands:
|
|
531
|
-
|
|
532
|
-
```bash
|
|
533
|
-
legion mind-growth status # current growth cycle state
|
|
534
|
-
legion mind-growth analyze # gap analysis against 5 reference models
|
|
535
|
-
legion mind-growth propose # propose a new concept
|
|
536
|
-
legion mind-growth evaluate <id> # evaluate a proposal
|
|
537
|
-
legion mind-growth build <id> # run staged build pipeline
|
|
538
|
-
legion mind-growth list # list proposals
|
|
539
|
-
legion mind-growth approve <id> # manually approve
|
|
540
|
-
legion mind-growth reject <id> # manually reject
|
|
541
|
-
legion mind-growth profile # cognitive profile across all models
|
|
542
|
-
legion mind-growth health # extension fitness validation
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
Requires `lex-mind-growth` to be loaded. Also exposes 6 MCP tools in the `legion.mind_growth_*` namespace via `legion-mcp`.
|
|
546
|
-
|
|
547
|
-
## Dependencies
|
|
548
|
-
|
|
549
|
-
### Runtime Gems
|
|
550
|
-
| Gem | Purpose |
|
|
551
|
-
|-----|---------|
|
|
552
|
-
| `legion-cache` (>= 0.3) | Caching (Redis/Memcached) |
|
|
553
|
-
| `legion-crypt` (>= 0.3) | Encryption, Vault, JWT |
|
|
554
|
-
| `legion-json` (>= 1.2) | JSON serialization (multi_json wrapper) |
|
|
555
|
-
| `legion-logging` (>= 0.3) | Logging |
|
|
556
|
-
| `legion-settings` (>= 0.3) | Configuration + schema validation |
|
|
557
|
-
| `legion-transport` (>= 1.2) | RabbitMQ AMQP messaging |
|
|
558
|
-
| `lex-node` | Node identity extension |
|
|
559
|
-
| `concurrent-ruby` + `ext` (>= 1.2) | Thread pool, concurrency primitives |
|
|
560
|
-
| `daemons` (>= 1.4) | Process daemonization |
|
|
561
|
-
| `bootsnap` (>= 1.18) | YARV bytecode + load-path caching |
|
|
562
|
-
| `oj` (>= 3.16) | Fast JSON (C extension) |
|
|
563
|
-
| `puma` (>= 6.0) | HTTP server for API |
|
|
564
|
-
| `rackup` (>= 2.0) | Rack server launcher for MCP HTTP transport |
|
|
565
|
-
| `legion-mcp` (>= 0.5) | MCP server + Tier 0 routing (extracted gem) |
|
|
566
|
-
| `reline` (>= 0.5) | Interactive line editing for chat REPL |
|
|
567
|
-
| `rouge` (>= 4.0) | Syntax highlighting for chat markdown rendering |
|
|
568
|
-
| `tty-spinner` (~> 0.9) | Spinner animation for CLI loading states |
|
|
569
|
-
| `sinatra` (>= 4.0) | HTTP API framework |
|
|
570
|
-
| `thor` (>= 1.3) | CLI framework |
|
|
571
|
-
|
|
572
|
-
### Optional at Runtime (loaded dynamically)
|
|
573
|
-
| Gem | Purpose |
|
|
574
|
-
|-----|---------|
|
|
575
|
-
| `legion-data` | MySQL/SQLite persistence (tasks, extensions, scheduling) |
|
|
576
|
-
| `legion-llm` | LLM integration (Bedrock, Anthropic, OpenAI, Gemini, Ollama) |
|
|
577
|
-
|
|
578
|
-
### Dev Dependencies
|
|
579
64
|
```
|
|
580
|
-
|
|
65
|
+
Legion
|
|
66
|
+
├── Service # Lifecycle orchestrator
|
|
67
|
+
├── Process # PID, signals, daemonization
|
|
68
|
+
├── Readiness # Component readiness tracking
|
|
69
|
+
├── Events # In-process pub/sub (on/emit/once/off, wildcard *)
|
|
70
|
+
├── Ingress # Universal runner entry point (normalize + run)
|
|
71
|
+
├── Extensions # Discovery, loading, actors, builders, helpers
|
|
72
|
+
│ ├── Core # Mixin: requirement flags, autobuild
|
|
73
|
+
│ ├── Actors/ # Every, Loop, Once, Poll, Subscription, Nothing
|
|
74
|
+
│ └── Builders/ # Actors, Runners, Helpers, Hooks, Routes
|
|
75
|
+
├── Tools # Registry (always/deferred), Discovery, EmbeddingCache
|
|
76
|
+
├── API # Sinatra routes, middleware (Auth, Tenant, RateLimit, BodyLimit)
|
|
77
|
+
├── DigitalWorker # AI-as-labor: Lifecycle, Registry, RiskTier, ValueMetrics
|
|
78
|
+
├── CLI # Thor commands (40+ subcommands)
|
|
79
|
+
│ └── Chat # Interactive AI REPL (sessions, tools, memory, agents, skills)
|
|
80
|
+
└── Graph # Task relationship visualization (Mermaid/DOT)
|
|
581
81
|
```
|
|
582
82
|
|
|
583
|
-
##
|
|
83
|
+
## Lite Mode
|
|
584
84
|
|
|
585
|
-
|
|
586
|
-
|------|---------|
|
|
587
|
-
| `lib/legion.rb` | Entry point: `Legion.start`, `.shutdown`, `.reload` |
|
|
588
|
-
| `lib/legion/version.rb` | `Legion::VERSION` constant |
|
|
589
|
-
| `lib/legion/service.rb` | Module orchestrator, startup + shutdown + reload sequences |
|
|
590
|
-
| `lib/legion/process.rb` | Daemon lifecycle: PID management, daemonize, signal traps, main loop |
|
|
591
|
-
| `lib/legion/readiness.rb` | Component readiness tracking (COMPONENTS constant, `ready?`, `to_h`) |
|
|
592
|
-
| `lib/legion/events.rb` | In-process pub/sub: `on`, `emit`, `once`, `off`, wildcard `*` |
|
|
593
|
-
| `lib/legion/ingress.rb` | Universal runner invocation: `normalize`, `run` |
|
|
594
|
-
| `lib/legion/extensions.rb` | LEX discovery, loading, actor hooking, shutdown; exposes `loaded_extension_modules` for Tools::Discovery |
|
|
595
|
-
| `lib/legion/extensions/core.rb` | Extension mixin (requirement flags, autobuild) |
|
|
596
|
-
| `lib/legion/extensions/actors/` | Actor types: base, every, loop, once, poll, subscription, nothing, defaults |
|
|
597
|
-
| `lib/legion/extensions/builders/` | Build actors, runners, helpers, hooks, routes from definitions |
|
|
598
|
-
| `lib/legion/extensions/helpers/` | Mixins: base, core, cache, data, logger, transport, task, lex |
|
|
599
|
-
| `lib/legion/extensions/data/` | Extension-level migrator and model |
|
|
600
|
-
| `lib/legion/extensions/hooks/base.rb` | Webhook hook base class |
|
|
601
|
-
| `lib/legion/extensions/transport.rb` | Extension transport setup |
|
|
602
|
-
| `lib/legion/graph/builder.rb` | Graph builder: adjacency list from relationships table with chain/worker filtering |
|
|
603
|
-
| `lib/legion/graph/exporter.rb` | Graph exporter: renders to Mermaid (`graph TD`) and DOT (Graphviz `digraph`) formats |
|
|
604
|
-
| `lib/legion/trace_search.rb` | NL trace search: LLM structured output to JSON filter DSL with column allowlist |
|
|
605
|
-
| `lib/legion/guardrails.rb` | Input validation guardrails for runner payloads |
|
|
606
|
-
| `lib/legion/isolation.rb` | Process isolation for untrusted extension execution |
|
|
607
|
-
| `lib/legion/sandbox.rb` | Sandboxed execution environment for extensions |
|
|
608
|
-
| `lib/legion/context.rb` | Thread-local execution context (request tracing, tenant) |
|
|
609
|
-
| `lib/legion/catalog.rb` | Extension catalog: registry of available extensions with metadata (Catalog::Registry removed — replaced by Tools::Registry) |
|
|
610
|
-
| `lib/legion/tools.rb` | Tools module entry point |
|
|
611
|
-
| `lib/legion/tools/base.rb` | Tools::Base — canonical base class for all tools |
|
|
612
|
-
| `lib/legion/tools/registry.rb` | Tools::Registry — always/deferred classification, replaces Catalog::Registry |
|
|
613
|
-
| `lib/legion/tools/discovery.rb` | Tools::Discovery — auto-discovers tools from extension runner_modules at boot |
|
|
614
|
-
| `lib/legion/tools/embedding_cache.rb` | Tools::EmbeddingCache — 5-tier persistent embedding cache (L0–L4) |
|
|
615
|
-
| `lib/legion/registry.rb` | Extension registry with security scanning |
|
|
616
|
-
| `lib/legion/registry/security_scanner.rb` | Gem security scanner (CVE checks, signature verification) |
|
|
617
|
-
| `lib/legion/webhooks.rb` | Webhook delivery system: HTTP POST with retry, HMAC signing |
|
|
618
|
-
| `lib/legion/runner.rb` | Task execution engine |
|
|
619
|
-
| `lib/legion/runner/log.rb` | Task logging |
|
|
620
|
-
| `lib/legion/runner/status.rb` | Task status tracking |
|
|
621
|
-
| `lib/legion/supervision.rb` | Process supervision |
|
|
622
|
-
| `lib/legion/lex.rb` | Legacy `Legion::Cli::LexBuilder` (preserved, not used by new CLI) |
|
|
623
|
-
| **API** | |
|
|
624
|
-
| `lib/legion/api.rb` | Sinatra base app, health/ready routes, error handlers, hook registry |
|
|
625
|
-
| `lib/legion/api/helpers.rb` | json_response, json_collection, json_error, pagination, redact_hash |
|
|
626
|
-
| `lib/legion/api/tasks.rb` | Tasks: list, create (via Ingress), show, delete, logs |
|
|
627
|
-
| `lib/legion/api/extensions.rb` | Extensions: nested REST (extensions/runners/functions + invoke) |
|
|
628
|
-
| `lib/legion/api/nodes.rb` | Nodes: list (filterable), show |
|
|
629
|
-
| `lib/legion/api/schedules.rb` | Schedules: CRUD + logs (requires lex-scheduler) |
|
|
630
|
-
| `lib/legion/api/relationships.rb` | Relationships: CRUD (backed by legion-data migration 013) |
|
|
631
|
-
| `lib/legion/api/chains.rb` | Chains: stub (501, no data model yet) |
|
|
632
|
-
| `lib/legion/api/settings.rb` | Settings: read/write with redaction + readonly guards |
|
|
633
|
-
| `lib/legion/api/events.rb` | Events: SSE stream + polling fallback (ring buffer) |
|
|
634
|
-
| `lib/legion/api/transport.rb` | Transport: status, exchanges, queues, publish |
|
|
635
|
-
| `lib/legion/api/lex_dispatch.rb` | LexDispatch: `POST /api/extensions/:lex/:type/:component/:method` dispatch + `GET` discovery; remote AMQP forwarding, hook-aware routing via `Routes::LexDispatch` |
|
|
636
|
-
| `lib/legion/api/workers.rb` | Workers + Teams: digital worker lifecycle REST endpoints (`/api/workers/*`) and team cost endpoints (`/api/teams/*`) |
|
|
637
|
-
| `lib/legion/api/coldstart.rb` | Coldstart: `POST /api/coldstart/ingest` — triggers lex-coldstart ingest runner (requires lex-coldstart + lex-memory) |
|
|
638
|
-
| `lib/legion/api/gaia.rb` | Gaia: system status endpoints |
|
|
639
|
-
| `lib/legion/api/token.rb` | Token: JWT token issuance endpoint |
|
|
640
|
-
| `lib/legion/api/openapi.rb` | OpenAPI: `Legion::API::OpenAPI.spec` / `.to_json`; also served at `GET /api/openapi.json` |
|
|
641
|
-
| `lib/legion/api/capacity.rb` | Capacity: aggregate, forecast, and per-worker capacity endpoints |
|
|
642
|
-
| `lib/legion/api/tenants.rb` | Tenants: listing, provisioning, suspension, quota check |
|
|
643
|
-
| `lib/legion/api/catalog.rb` | Catalog: extension catalog with metadata endpoints |
|
|
644
|
-
| `lib/legion/api/llm.rb` | LLM: provider status and routing configuration endpoints |
|
|
645
|
-
| `lib/legion/api/audit.rb` | Audit: list, show, count, export audit log entries |
|
|
646
|
-
| `lib/legion/api/auth.rb` | Auth: combined token exchange endpoint (`POST /api/auth/token` — JWKS verify + RBAC claims mapper) |
|
|
647
|
-
| `lib/legion/api/auth_human.rb` | Auth: human user authentication endpoints |
|
|
648
|
-
| `lib/legion/api/auth_worker.rb` | Auth: digital worker authentication endpoints |
|
|
649
|
-
| `lib/legion/api/rbac.rb` | RBAC: role listing, permission grants, access checks |
|
|
650
|
-
| `lib/legion/api/validators.rb` | Request validators: schema validation helpers for API inputs |
|
|
651
|
-
| `lib/legion/api/webhooks.rb` | Webhooks: CRUD for webhook subscriptions + delivery status |
|
|
652
|
-
| `lib/legion/audit.rb` | Audit logging: AMQP publish + query layer (recent_for, count_for, resources_for, recent) backed by AuditLog model |
|
|
653
|
-
| `lib/legion/audit/hash_chain.rb` | Tamper-evident hash chain for audit entries |
|
|
654
|
-
| `lib/legion/audit/siem_export.rb` | SIEM export: format audit entries for Splunk/ELK ingestion |
|
|
655
|
-
| `lib/legion/alerts.rb` | Configurable alerting rules engine: pattern matching, count conditions, cooldown dedup |
|
|
656
|
-
| `lib/legion/telemetry.rb` | Opt-in OpenTelemetry tracing: `with_span` wrapper, `sanitize_attributes`, `record_exception` |
|
|
657
|
-
| `lib/legion/metrics.rb` | Opt-in Prometheus metrics: event-driven counters, pull-based gauges, `prometheus-client` guarded |
|
|
658
|
-
| `lib/legion/api/metrics.rb` | `GET /metrics` Prometheus text-format endpoint with gauge refresh |
|
|
659
|
-
| `lib/legion/api/stats.rb` | `GET /api/stats` comprehensive daemon runtime stats (extensions, gaia, transport, cache, llm, data, api) |
|
|
660
|
-
| `lib/legion/chat/notification_queue.rb` | Thread-safe priority queue for background notifications (critical/info/debug) |
|
|
661
|
-
| `lib/legion/chat/notification_bridge.rb` | Event-driven bridge: matches Legion events to chat notifications via fnmatch patterns |
|
|
662
|
-
| `lib/legion/api/middleware/auth.rb` | Auth: JWT Bearer auth middleware (real token validation, skip paths for health/ready) |
|
|
663
|
-
| `lib/legion/api/middleware/api_version.rb` | ApiVersion: rewrites `/api/v1/` to `/api/`, adds Deprecation/Sunset headers on unversioned paths |
|
|
664
|
-
| `lib/legion/api/middleware/body_limit.rb` | BodyLimit: request body size limit (1MB max, returns 413) |
|
|
665
|
-
| `lib/legion/api/middleware/rate_limit.rb` | RateLimit: sliding-window rate limiting with per-IP/agent/tenant tiers |
|
|
666
|
-
| `lib/legion/api/middleware/tenant.rb` | Tenant: extracts tenant_id from JWT/header, sets TenantContext per request |
|
|
667
|
-
| `lib/legion/tenant_context.rb` | Thread-local tenant context propagation (set, clear, with block) |
|
|
668
|
-
| `lib/legion/tenants.rb` | Tenant CRUD, suspension, quota enforcement |
|
|
669
|
-
| `lib/legion/capacity/model.rb` | Workforce capacity calculation (throughput, utilization, forecast, per-worker) |
|
|
670
|
-
| **MCP** (extracted to `legion-mcp` gem) | |
|
|
671
|
-
| `lib/legion/digital_worker.rb` | DigitalWorker module entry point |
|
|
672
|
-
| `lib/legion/digital_worker/lifecycle.rb` | Worker state machine |
|
|
673
|
-
| `lib/legion/digital_worker/registry.rb` | In-process worker registry |
|
|
674
|
-
| `lib/legion/digital_worker/risk_tier.rb` | AIRB risk tier + governance constraints |
|
|
675
|
-
| `lib/legion/digital_worker/value_metrics.rb` | Token/cost/latency tracking |
|
|
676
|
-
| **CLI v2** | |
|
|
677
|
-
| `lib/legion/cli.rb` | `Legion::CLI::Main` Thor app, global flags, version, start/stop/status/check |
|
|
678
|
-
| `lib/legion/cli/output.rb` | `Output::Formatter`: color, tables, JSON mode, ANSI stripping |
|
|
679
|
-
| `lib/legion/cli/connection.rb` | Lazy connection manager (`ensure_settings`, `ensure_transport`, etc.) |
|
|
680
|
-
| `lib/legion/cli/error.rb` | `CLI::Error` exception class |
|
|
681
|
-
| `lib/legion/cli/start.rb` | `legion start` — boots Legion::Process |
|
|
682
|
-
| `lib/legion/cli/status.rb` | `legion status` — probes API or returns static info |
|
|
683
|
-
| `lib/legion/cli/check_command.rb` | `legion check` — 3-level smoke test, exit code 0/1 |
|
|
684
|
-
| `lib/legion/cli/lex_command.rb` | `legion lex` subcommands + LexGenerator scaffolding + `invoke_ext`/`exec` dispatch via LexCliManifest |
|
|
685
|
-
| `lib/legion/cli/lex_cli_manifest.rb` | JSON manifest cache for LEX CLI commands (alias resolution, staleness check) |
|
|
686
|
-
| `lib/legion/cli/task_command.rb` | `legion task` subcommands (list, show, logs, trigger/run, purge) |
|
|
687
|
-
| `lib/legion/cli/chain_command.rb` | `legion chain` subcommands (list, create, delete) |
|
|
688
|
-
| `lib/legion/cli/config_command.rb` | `legion config` subcommands (show, path, validate, scaffold) |
|
|
689
|
-
| `lib/legion/cli/config_scaffold.rb` | `legion config scaffold` — generates starter JSON config files per subsystem |
|
|
690
|
-
| `lib/legion/cli/generate_command.rb` | `legion generate` subcommands (runner, actor, exchange, queue, message) |
|
|
691
|
-
| `lib/legion/cli/mcp_command.rb` | `legion mcp` subcommand (stdio + HTTP transports) |
|
|
692
|
-
| `lib/legion/cli/worker_command.rb` | `legion worker` subcommands (list, show, create, pause, retire, terminate, activate, costs) |
|
|
693
|
-
| `lib/legion/cli/coldstart_command.rb` | `legion coldstart` subcommands (ingest, preview, status) |
|
|
694
|
-
| `lib/legion/cli/chat_command.rb` | `legion chat` — interactive AI REPL + headless prompt mode |
|
|
695
|
-
| `lib/legion/cli/chat/session.rb` | Chat session: multi-turn conversation, streaming, tool use |
|
|
696
|
-
| `lib/legion/cli/chat/session_store.rb` | Session persistence: save, load, list, resume, fork |
|
|
697
|
-
| `lib/legion/cli/chat/permissions.rb` | Tool permission model (interactive/auto_approve/read_only) |
|
|
698
|
-
| `lib/legion/cli/chat/tool_registry.rb` | Chat tool discovery and registration (40 tools) |
|
|
699
|
-
| `lib/legion/cli/chat/extension_tool.rb` | permission_tier DSL module for extension chat tools |
|
|
700
|
-
| `lib/legion/cli/chat/extension_tool_loader.rb` | Lazy discovery engine: scans loaded extensions for tools/ directories |
|
|
701
|
-
| `lib/legion/cli/chat/context.rb` | Project awareness: git info, language detection, instructions, extra dirs |
|
|
702
|
-
| `lib/legion/cli/chat/markdown_renderer.rb` | Terminal markdown rendering with Rouge syntax highlighting |
|
|
703
|
-
| `lib/legion/cli/chat/web_fetch.rb` | `/fetch` slash command: fetches web page, extracts text for context |
|
|
704
|
-
| `lib/legion/cli/chat/web_search.rb` | DuckDuckGo HTML scraping search (parse results, extract URLs, auto-fetch) |
|
|
705
|
-
| `lib/legion/cli/chat/checkpoint.rb` | File edit checkpointing: save prior state, rewind (N steps, per-file) |
|
|
706
|
-
| `lib/legion/cli/chat/memory_store.rb` | Persistent memory: project (`.legion/memory.md`) + global (`~/.legion/memory/`) |
|
|
707
|
-
| `lib/legion/cli/chat/subagent.rb` | Background subagent spawning via `Open3.capture3` to `legion chat prompt` |
|
|
708
|
-
| `lib/legion/cli/chat/agent_registry.rb` | Custom agent definitions from `.legion/agents/*.json` and `.yaml` |
|
|
709
|
-
| `lib/legion/cli/chat/agent_delegator.rb` | `@name` at-mention parsing and dispatch via Subagent |
|
|
710
|
-
| `lib/legion/cli/chat/chat_logger.rb` | Chat-specific logging |
|
|
711
|
-
| `lib/legion/cli/chat/context_manager.rb` | Context window management: dedup, compression, summarization strategies |
|
|
712
|
-
| `lib/legion/cli/chat/progress_bar.rb` | Progress bar rendering for long operations |
|
|
713
|
-
| `lib/legion/cli/chat/status_indicator.rb` | Status indicator (spinner, checkmark, cross) |
|
|
714
|
-
| `lib/legion/cli/chat/team.rb` | Multi-user team support for chat sessions |
|
|
715
|
-
| `lib/legion/cli/chat/tools/` | 40 built-in tools: read_file, write_file, edit_file, search_files, search_content, run_command, save_memory, search_memory, web_search, spawn_agent, search_traces, query_knowledge, ingest_knowledge, consolidate_memory, relate_knowledge, knowledge_maintenance, knowledge_stats, summarize_traces, list_extensions, manage_tasks, system_status, view_events, cost_summary, reflect, manage_schedules, worker_status, detect_anomalies, view_trends, trigger_dream, generate_insights, budget_status, provider_health, model_comparison, shadow_eval_status, entity_extract, arbitrage_status, escalation_status, graph_explore, scheduling_status, memory_status |
|
|
716
|
-
| `lib/legion/chat/skills.rb` | Skill discovery: parses `.legion/skills/` and `~/.legionio/skills/` YAML frontmatter files |
|
|
717
|
-
| `lib/legion/cli/graph_command.rb` | `legion graph` subcommands (show with --format mermaid\|dot, --chain, --output) |
|
|
718
|
-
| `lib/legion/cli/trace_command.rb` | `legion trace search` — NL trace search via LLM |
|
|
719
|
-
| `lib/legion/cli/dashboard_command.rb` | `legion dashboard` — TUI operational dashboard |
|
|
720
|
-
| `lib/legion/cli/dashboard/data_fetcher.rb` | Dashboard API poller: workers, health, events |
|
|
721
|
-
| `lib/legion/cli/dashboard/renderer.rb` | Dashboard terminal renderer with sections |
|
|
722
|
-
| `lib/legion/cli/cost_command.rb` | `legion cost` — cost summary, worker, team, top, budget, export |
|
|
723
|
-
| `lib/legion/cli/cost/data_client.rb` | Cost data aggregation API client |
|
|
724
|
-
| `lib/legion/cli/skill_command.rb` | `legion skill` — list, show, create, run skill files |
|
|
725
|
-
| `lib/legion/cli/audit_command.rb` | `legion audit` — query audit log (list, show, count, export) |
|
|
726
|
-
| `lib/legion/cli/rbac_command.rb` | `legion rbac` — role management, permission grants, access checks |
|
|
727
|
-
| `lib/legion/cli/init_command.rb` | `legion init` — interactive project setup wizard |
|
|
728
|
-
| `lib/legion/cli/init/config_generator.rb` | Config file generation from templates |
|
|
729
|
-
| `lib/legion/cli/init/environment_detector.rb` | Runtime environment detection (Docker, CI, services) |
|
|
730
|
-
| `lib/legion/cli/marketplace_command.rb` | `legion marketplace` — extension search, install, publish |
|
|
731
|
-
| `lib/legion/cli/notebook_command.rb` | `legion notebook` — interactive task notebook REPL |
|
|
732
|
-
| `lib/legion/cli/update_command.rb` | `legion update` — self-update via Homebrew or gem |
|
|
733
|
-
| `lib/legion/cli/lex_templates.rb` | LEX scaffold templates for generator |
|
|
734
|
-
| `lib/legion/cli/version.rb` | CLI version display helper |
|
|
735
|
-
| `lib/legion/docs/site_generator.rb` | Static documentation site generator |
|
|
736
|
-
| `lib/legion/cli/memory_command.rb` | `legion memory` subcommands (list, add, forget, search, clear) |
|
|
737
|
-
| `lib/legion/cli/plan_command.rb` | `legion plan` — read-only exploration mode with /save to docs/work/planning/ |
|
|
738
|
-
| `lib/legion/cli/swarm_command.rb` | `legion swarm` — multi-agent workflow orchestration from `.legion/swarms/` |
|
|
739
|
-
| `lib/legion/cli/commit_command.rb` | `legion commit` — AI-generated commit messages via LLM |
|
|
740
|
-
| `lib/legion/cli/pr_command.rb` | `legion pr` — AI-generated PR title + description via LLM |
|
|
741
|
-
| `lib/legion/cli/review_command.rb` | `legion review` — AI code review with severity levels (CRITICAL/WARNING/SUGGESTION/NOTE) |
|
|
742
|
-
| `lib/legion/cli/gaia_command.rb` | `legion gaia` subcommands (status) |
|
|
743
|
-
| `lib/legion/cli/llm_command.rb` | `legion llm` subcommands (status) — LLM subsystem status and provider health |
|
|
744
|
-
| `lib/legion/cli/detect_command.rb` | `legion detect scan` — scan environment and recommend extensions |
|
|
745
|
-
| `lib/legion/cli/observe_command.rb` | `legion observe stats` — MCP tool usage statistics from Observer |
|
|
746
|
-
| `lib/legion/cli/tty_command.rb` | `legion tty interactive` — launch rich terminal UI (legion-tty interactive shell) |
|
|
747
|
-
| `lib/legion/cli/interactive.rb` | `Interactive` Thor class — shared CLI module for `legion` binary entry point |
|
|
748
|
-
| `lib/legion/cli/config_import.rb` | `legion config import` — import config from external sources |
|
|
749
|
-
| `lib/legion/cli/schedule_command.rb` | `legion schedule` subcommands (list, show, add, remove, logs) |
|
|
750
|
-
| `lib/legion/cli/completion_command.rb` | `legion completion` subcommands (bash, zsh, install) |
|
|
751
|
-
| `lib/legion/cli/openapi_command.rb` | `legion openapi` subcommands (generate, routes); also `GET /api/openapi.json` endpoint |
|
|
752
|
-
| `lib/legion/cli/doctor_command.rb` | `legion doctor` — 11-check environment diagnosis; `Doctor::Result` value object with status/message/prescription/auto_fixable |
|
|
753
|
-
| `lib/legion/cli/doctor/` | Individual check modules: ruby_version, bundle, config, rabbitmq, database, cache, vault, extensions, pid, permissions, plus result.rb |
|
|
754
|
-
| `lib/legion/cli/telemetry_command.rb` | `legion telemetry` subcommands (stats, ingest) — session log analytics |
|
|
755
|
-
| `lib/legion/cli/auth_command.rb` | `legion auth` subcommands (teams) — delegated OAuth browser flow for external services |
|
|
756
|
-
| `lib/legion/cli/admin_command.rb` | `legion admin` subcommands (purge-topology) — ops tooling for v2.0 AMQP topology cleanup |
|
|
757
|
-
| `completions/legion.bash` | Bash tab completion script |
|
|
758
|
-
| `completions/_legion` | Zsh tab completion script |
|
|
759
|
-
| `lib/legion/cli/theme.rb` | Purple palette, orbital ASCII banner, branded CLI output |
|
|
760
|
-
| **Legacy CLI (preserved, not loaded by new CLI)** | |
|
|
761
|
-
| `lib/legion/cli/task.rb` | Old task commands |
|
|
762
|
-
| `lib/legion/cli/trigger.rb` | Old trigger command |
|
|
763
|
-
| `lib/legion/cli/chain.rb` | Old chain commands |
|
|
764
|
-
| `lib/legion/cli/cohort.rb` | Old cohort commands |
|
|
765
|
-
| `lib/legion/cli/function.rb` | Old function commands |
|
|
766
|
-
| `lib/legion/cli/relationship.rb` | Old relationship commands |
|
|
767
|
-
| `lib/legion/cli/lex/` | Old LEX sub-generators + ERB templates (still used by LexGenerator) |
|
|
768
|
-
| **Executables** | |
|
|
769
|
-
| `exe/legion` | Executable: YJIT, GC tuning, bootsnap, then `Legion::CLI::Main.start(ARGV)` |
|
|
770
|
-
| `Dockerfile` | Docker build |
|
|
771
|
-
| `docker_deploy.rb` | Build + push Docker image |
|
|
772
|
-
| **Specs** | |
|
|
773
|
-
| `spec/spec_helper.rb` | RSpec configuration |
|
|
774
|
-
|
|
775
|
-
## Known Stubs / TODO
|
|
776
|
-
|
|
777
|
-
| Area | Status |
|
|
778
|
-
|------|--------|
|
|
779
|
-
| `API::Routes::Relationships` | Fully implemented (backed by legion-data migration 013) |
|
|
780
|
-
| `API::Routes::Chains` | 501 stub - no data model |
|
|
781
|
-
| `API::Middleware::Auth` | JWT Bearer auth middleware — real token validation and API key (`X-API-Key` header) auth both implemented |
|
|
782
|
-
| `legion-data` chains/relationships models | Not yet implemented |
|
|
783
|
-
|
|
784
|
-
## Rubocop Notes
|
|
785
|
-
|
|
786
|
-
- `.rubocop.yml` excludes `spec/**/*`, `legionio.gemspec`, `chat_command.rb`, `plan_command.rb`, `swarm_command.rb`, and `schedule_command.rb` from `Metrics/BlockLength`
|
|
787
|
-
- `chat_command.rb` also excluded from `Metrics/AbcSize`, `Metrics/MethodLength`, and `Metrics/CyclomaticComplexity` (large REPL loop + slash command dispatch)
|
|
788
|
-
- Hash alignment: `table` style enforced for both rocket and colon
|
|
789
|
-
- `Naming/PredicateMethod` disabled
|
|
85
|
+
`LEGION_MODE=lite` — `InProcess` transport adapter + `Memory` cache adapter. No RabbitMQ/Redis needed.
|
|
790
86
|
|
|
791
87
|
## Development
|
|
792
88
|
|
|
793
89
|
```bash
|
|
794
|
-
bundle
|
|
795
|
-
bundle exec rspec # ~3500+ examples, 0 failures
|
|
90
|
+
bundle exec rspec # ~3500+ examples
|
|
796
91
|
bundle exec rubocop # 0 offenses
|
|
797
92
|
```
|
|
798
93
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
Specs use `rack-test` for API testing. `Legion::JSON.load` returns symbol keys — use `body[:data]` not `body['data']` in specs.
|
|
94
|
+
Always run both before committing. Specs use `rack-test`. `Legion::JSON.load` returns symbol keys.
|
|
802
95
|
|
|
803
|
-
|
|
96
|
+
## Rubocop
|
|
804
97
|
|
|
805
|
-
|
|
98
|
+
`.rubocop.yml` excludes `spec/**/*` from `Metrics/BlockLength`. `chat_command.rb` excluded from most Metrics cops. Hash alignment: `table` style.
|
data/Gemfile
CHANGED
|
@@ -9,13 +9,13 @@ module Legion
|
|
|
9
9
|
|
|
10
10
|
app.get '/api/identity/audit' do
|
|
11
11
|
require_data!
|
|
12
|
-
halt 503, json_error('unavailable', 'identity audit log not available') unless defined?(Legion::Data::Model::
|
|
12
|
+
halt 503, json_error('unavailable', 'identity audit log not available') unless defined?(Legion::Data::Model::Identity::AuditLog)
|
|
13
13
|
|
|
14
|
-
dataset = Legion::Data::Model::
|
|
14
|
+
dataset = Legion::Data::Model::Identity::AuditLog.dataset
|
|
15
15
|
|
|
16
16
|
principal = params[:principal]
|
|
17
|
-
if principal && defined?(Legion::Data::Model::Principal)
|
|
18
|
-
principal_record = Legion::Data::Model::Principal.where(canonical_name: principal).first
|
|
17
|
+
if principal && defined?(Legion::Data::Model::Identity::Principal)
|
|
18
|
+
principal_record = Legion::Data::Model::Identity::Principal.where(canonical_name: principal).first
|
|
19
19
|
halt 404, json_error('not_found', "principal '#{principal}' not found") unless principal_record
|
|
20
20
|
dataset = dataset.where(principal_id: principal_record.id)
|
|
21
21
|
end
|
data/lib/legion/api/llm.rb
CHANGED
|
@@ -213,7 +213,8 @@ module Legion
|
|
|
213
213
|
validate_required!(body, :messages)
|
|
214
214
|
|
|
215
215
|
messages = body[:messages]
|
|
216
|
-
|
|
216
|
+
tools_present = body.key?(:tools)
|
|
217
|
+
tools = tools_present ? Array(body[:tools]) : []
|
|
217
218
|
model = body[:model]
|
|
218
219
|
provider = body[:provider]
|
|
219
220
|
requested_tools = body[:requested_tools] || []
|
|
@@ -267,17 +268,19 @@ module Legion
|
|
|
267
268
|
end
|
|
268
269
|
|
|
269
270
|
caller_metadata = body[:metadata].is_a?(Hash) ? body[:metadata] : {}
|
|
270
|
-
|
|
271
|
+
request_args = {
|
|
271
272
|
messages: messages,
|
|
272
273
|
system: body[:system],
|
|
273
274
|
routing: { provider: provider, model: model },
|
|
274
|
-
tools: tool_classes,
|
|
275
275
|
caller: caller_ctx,
|
|
276
276
|
conversation_id: body[:conversation_id],
|
|
277
277
|
metadata: caller_metadata.merge(requested_tools: requested_tools),
|
|
278
278
|
stream: streaming,
|
|
279
279
|
cache: { strategy: :default, cacheable: true }
|
|
280
|
-
|
|
280
|
+
}
|
|
281
|
+
request_args[:tools] = tool_classes if tools_present
|
|
282
|
+
|
|
283
|
+
req = Legion::LLM::Inference::Request.build(**request_args)
|
|
281
284
|
executor = Legion::LLM::Inference::Executor.new(req)
|
|
282
285
|
|
|
283
286
|
if streaming
|
|
@@ -27,13 +27,6 @@ module Legion
|
|
|
27
27
|
{ name: 'lex-transformer', category: 'core', description: 'Task chain transformation' },
|
|
28
28
|
{ name: 'lex-webhook', category: 'core', description: 'Inbound webhook receiver' },
|
|
29
29
|
# ai
|
|
30
|
-
{ name: 'lex-azure-ai', category: 'ai', description: 'Azure OpenAI provider integration' },
|
|
31
|
-
{ name: 'lex-bedrock', category: 'ai', description: 'AWS Bedrock LLM provider integration' },
|
|
32
|
-
{ name: 'lex-claude', category: 'ai', description: 'Anthropic Claude provider integration' },
|
|
33
|
-
{ name: 'lex-foundry', category: 'ai', description: 'Azure AI Foundry provider integration' },
|
|
34
|
-
{ name: 'lex-gemini', category: 'ai', description: 'Google Gemini provider integration' },
|
|
35
|
-
{ name: 'lex-ollama', category: 'ai', description: 'Ollama local LLM provider integration' },
|
|
36
|
-
{ name: 'lex-openai', category: 'ai', description: 'OpenAI provider integration' },
|
|
37
30
|
{ name: 'lex-xai', category: 'ai', description: 'xAI Grok provider integration' },
|
|
38
31
|
{ name: 'lex-llm', category: 'ai', description: 'Common LLM provider base and routing metadata' },
|
|
39
32
|
{ name: 'lex-llm-anthropic', category: 'ai', description: 'Anthropic LLM provider integration' },
|
|
@@ -275,7 +275,7 @@ module Legion
|
|
|
275
275
|
return [] unless defined?(Legion::Data) && Legion::Data.respond_to?(:connected?) && Legion::Data.connected?
|
|
276
276
|
|
|
277
277
|
model = begin
|
|
278
|
-
Legion::Data::Model::
|
|
278
|
+
Legion::Data::Model::Identity::GroupMembership
|
|
279
279
|
rescue StandardError
|
|
280
280
|
nil
|
|
281
281
|
end
|
|
@@ -115,23 +115,41 @@ module Legion
|
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
def system_principal
|
|
118
|
-
|
|
119
|
-
Legion::Identity::Process.canonical_name
|
|
120
|
-
else
|
|
121
|
-
'system'
|
|
122
|
-
end
|
|
118
|
+
attrs = system_identity_attributes
|
|
123
119
|
|
|
124
|
-
if @system_principal&.canonical_name !=
|
|
120
|
+
if @system_principal&.canonical_name != attrs[:canonical_name] ||
|
|
121
|
+
@system_principal&.kind != attrs[:kind] ||
|
|
122
|
+
@system_principal&.source != Identity::Request::SOURCE_NORMALIZATION.fetch(attrs[:source], attrs[:source])
|
|
125
123
|
@system_principal = Identity::Request.new(
|
|
126
|
-
principal_id: "system:#{
|
|
127
|
-
canonical_name:
|
|
128
|
-
kind: :
|
|
124
|
+
principal_id: "system:#{attrs[:canonical_name]}",
|
|
125
|
+
canonical_name: attrs[:canonical_name],
|
|
126
|
+
kind: attrs[:kind],
|
|
129
127
|
groups: [],
|
|
130
|
-
source: :
|
|
128
|
+
source: attrs[:source]
|
|
131
129
|
)
|
|
132
130
|
end
|
|
133
131
|
@system_principal
|
|
134
132
|
end
|
|
133
|
+
|
|
134
|
+
def system_identity_attributes
|
|
135
|
+
process = defined?(Legion::Identity::Process) ? Legion::Identity::Process : nil
|
|
136
|
+
canonical = process_value(process, :canonical_name)
|
|
137
|
+
canonical = 'system' if canonical.nil? || canonical.to_s.empty?
|
|
138
|
+
|
|
139
|
+
{
|
|
140
|
+
canonical_name: canonical.to_s,
|
|
141
|
+
kind: process_value(process, :kind) || :service,
|
|
142
|
+
source: process_value(process, :source) || :local
|
|
143
|
+
}
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def process_value(process, method_name)
|
|
147
|
+
return nil unless process.respond_to?(method_name)
|
|
148
|
+
|
|
149
|
+
process.public_send(method_name)
|
|
150
|
+
rescue StandardError
|
|
151
|
+
nil
|
|
152
|
+
end
|
|
135
153
|
end
|
|
136
154
|
end
|
|
137
155
|
end
|
|
@@ -316,57 +316,74 @@ module Legion
|
|
|
316
316
|
@resolved.make_true
|
|
317
317
|
end
|
|
318
318
|
|
|
319
|
-
def persist_to_db(composite) # rubocop:disable Metrics/
|
|
319
|
+
def persist_to_db(composite) # rubocop:disable Metrics/MethodLength
|
|
320
320
|
return unless defined?(Legion::Data) && Legion::Data.respond_to?(:connected?) && Legion::Data.connected?
|
|
321
|
-
return unless defined?(Legion::Data::Connection) &&
|
|
322
|
-
Legion::Data::Connection.respond_to?(:adapter) &&
|
|
323
|
-
Legion::Data::Connection.adapter == :postgres
|
|
324
321
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
322
|
+
now = Time.now.utc
|
|
323
|
+
db = Legion::Data.db
|
|
324
|
+
|
|
325
|
+
composite[:providers]&.each_key do |name|
|
|
326
|
+
db[:identity_providers].insert_conflict(
|
|
328
327
|
target: :name,
|
|
329
|
-
update: {
|
|
330
|
-
).insert(
|
|
328
|
+
update: { updated_at: now }
|
|
329
|
+
).insert(
|
|
330
|
+
uuid: SecureRandom.uuid,
|
|
331
|
+
name: name.to_s,
|
|
332
|
+
provider_type: 'authenticate',
|
|
333
|
+
facing: 'both',
|
|
334
|
+
source: 'resolver',
|
|
335
|
+
enabled: true,
|
|
336
|
+
created_at: now,
|
|
337
|
+
updated_at: now
|
|
338
|
+
)
|
|
331
339
|
end
|
|
332
340
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
update: { kind: composite[:kind].to_s, updated_at: Time.now }
|
|
341
|
+
db[:identity_principals].insert_conflict(
|
|
342
|
+
target: %i[canonical_name kind],
|
|
343
|
+
update: { last_seen_at: now, updated_at: now }
|
|
337
344
|
).insert(
|
|
345
|
+
uuid: SecureRandom.uuid,
|
|
338
346
|
canonical_name: composite[:canonical_name],
|
|
339
347
|
kind: composite[:kind].to_s,
|
|
340
|
-
|
|
341
|
-
|
|
348
|
+
active: true,
|
|
349
|
+
last_seen_at: now,
|
|
350
|
+
created_at: now,
|
|
351
|
+
updated_at: now
|
|
342
352
|
)
|
|
343
353
|
|
|
344
|
-
principal_row =
|
|
354
|
+
principal_row = db[:identity_principals].where(
|
|
355
|
+
canonical_name: composite[:canonical_name], kind: composite[:kind].to_s
|
|
356
|
+
).first
|
|
345
357
|
principal_id = principal_row[:id] if principal_row
|
|
346
358
|
|
|
347
|
-
# upsert identities per provider alias
|
|
348
359
|
composite[:aliases]&.each do |provider_name, identities|
|
|
360
|
+
provider_row = db[:identity_providers].where(name: provider_name.to_s).first
|
|
361
|
+
next unless provider_row
|
|
362
|
+
|
|
349
363
|
Array(identities).each do |ident|
|
|
350
|
-
|
|
351
|
-
target: %i[principal_id
|
|
352
|
-
update: { updated_at:
|
|
364
|
+
db[:identities].insert_conflict(
|
|
365
|
+
target: %i[principal_id provider_id provider_identity_key],
|
|
366
|
+
update: { last_authenticated_at: now, updated_at: now }
|
|
353
367
|
).insert(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
368
|
+
uuid: SecureRandom.uuid,
|
|
369
|
+
principal_id: principal_id,
|
|
370
|
+
provider_id: provider_row[:id],
|
|
371
|
+
provider_identity_key: ident,
|
|
372
|
+
active: true,
|
|
373
|
+
last_authenticated_at: now,
|
|
374
|
+
created_at: now,
|
|
375
|
+
updated_at: now
|
|
359
376
|
)
|
|
360
377
|
end
|
|
361
378
|
end
|
|
362
379
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
principal_id:
|
|
366
|
-
event_type:
|
|
367
|
-
provider_name:
|
|
368
|
-
trust_level:
|
|
369
|
-
|
|
380
|
+
db[:identity_audit_log].insert(
|
|
381
|
+
uuid: SecureRandom.uuid,
|
|
382
|
+
principal_id: principal_id,
|
|
383
|
+
event_type: 'identity.resolved',
|
|
384
|
+
provider_name: composite[:source].to_s,
|
|
385
|
+
trust_level: composite[:trust]&.to_s,
|
|
386
|
+
detail_payload: Legion::JSON.dump(
|
|
370
387
|
{
|
|
371
388
|
source: composite[:source],
|
|
372
389
|
trust: composite[:trust],
|
|
@@ -374,9 +391,9 @@ module Legion
|
|
|
374
391
|
session_id: @session_id
|
|
375
392
|
}
|
|
376
393
|
),
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
created_at:
|
|
394
|
+
node_ref: composite[:node_id],
|
|
395
|
+
session_ref: @session_id,
|
|
396
|
+
created_at: now
|
|
380
397
|
)
|
|
381
398
|
rescue StandardError => e
|
|
382
399
|
log_warn("DB persistence failed: #{e.message}")
|
|
@@ -406,18 +423,15 @@ module Legion
|
|
|
406
423
|
end
|
|
407
424
|
|
|
408
425
|
return unless defined?(Legion::Data) && Legion::Data.respond_to?(:connected?) && Legion::Data.connected?
|
|
409
|
-
return unless defined?(Legion::Data::Connection) &&
|
|
410
|
-
Legion::Data::Connection.respond_to?(:adapter) &&
|
|
411
|
-
Legion::Data::Connection.adapter == :postgres
|
|
412
426
|
|
|
413
|
-
|
|
414
|
-
old_row = Legion::Data.db[:principals].where(canonical_name: old_canonical).first
|
|
427
|
+
old_row = Legion::Data.db[:identity_principals].where(canonical_name: old_canonical).first
|
|
415
428
|
Legion::Data.db[:identity_audit_log].insert(
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
429
|
+
uuid: SecureRandom.uuid,
|
|
430
|
+
principal_id: old_row&.dig(:id),
|
|
431
|
+
event_type: 'identity.canonical_changed',
|
|
432
|
+
provider_name: 'resolver',
|
|
433
|
+
detail_payload: Legion::JSON.dump({ old: old_canonical, new: new_canonical }),
|
|
434
|
+
created_at: Time.now
|
|
421
435
|
)
|
|
422
436
|
rescue StandardError => e
|
|
423
437
|
log_warn("canonical change handling failed: #{e.message}")
|
|
@@ -34,8 +34,10 @@ module Legion
|
|
|
34
34
|
private
|
|
35
35
|
|
|
36
36
|
def handle_outcome(payload, success:)
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
return unless observable_outcome?(payload)
|
|
38
|
+
|
|
39
|
+
runner_class = outcome_value(payload, :runner_class).to_s
|
|
40
|
+
function = outcome_value(payload, :function).to_s
|
|
39
41
|
domain = derive_domain(runner_class)
|
|
40
42
|
|
|
41
43
|
record_learning(domain: domain, success: success)
|
|
@@ -52,6 +54,18 @@ module Legion
|
|
|
52
54
|
last.gsub(/([A-Z])/, '_\1').delete_prefix('_').downcase
|
|
53
55
|
end
|
|
54
56
|
|
|
57
|
+
def observable_outcome?(payload)
|
|
58
|
+
!outcome_value(payload, :task_id).to_s.strip.empty? &&
|
|
59
|
+
!outcome_value(payload, :runner_class).to_s.strip.empty? &&
|
|
60
|
+
!outcome_value(payload, :function).to_s.strip.empty?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def outcome_value(payload, key)
|
|
64
|
+
return unless payload.respond_to?(:[])
|
|
65
|
+
|
|
66
|
+
payload[key] || payload[key.to_s]
|
|
67
|
+
end
|
|
68
|
+
|
|
55
69
|
def record_learning(domain:, success:)
|
|
56
70
|
client = meta_learning_client
|
|
57
71
|
return unless client
|
data/lib/legion/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: legionio
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.
|
|
4
|
+
version: 1.9.28
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -405,6 +405,7 @@ files:
|
|
|
405
405
|
- ".github/workflows/ci.yml"
|
|
406
406
|
- ".github/workflows/publish-homebrew.yml"
|
|
407
407
|
- ".gitignore"
|
|
408
|
+
- ".rspec"
|
|
408
409
|
- ".rubocop.yml"
|
|
409
410
|
- AGENTS.md
|
|
410
411
|
- CHANGELOG.md
|