legionio 1.4.52 → 1.4.53

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08a5e7057699e03532d0815dc93823ed321ea0f5767915033b10ca5aa75afb40'
4
- data.tar.gz: bf1311709df94b55812ba9e53360b456b3b80cd1d1bed0450fe7a1b33d5e04c2
3
+ metadata.gz: 1c0d47e1dc027fcf06d57aad2e04cc5217189555f4c2801bad0339bd97b2cef4
4
+ data.tar.gz: 591da91efe655fe18c84fa248ef9446c0708d06d5a4ddab2fc7b785ef95aedfc
5
5
  SHA512:
6
- metadata.gz: c44772264edc55cf816923a596d5092f43394dcd292884eadbddc0b88d09e25cb17a75cab374ee3dfffe046e81edd142728bc4647f2ab2c6a3edcc67f1729bc6
7
- data.tar.gz: '096080ad2b1b2a9103d262ba2547c9442249a08505bf86b60a88927820a00528ba2cc6fed53e9ee9f330202631834b14dc017df394215abdddfaff38d4851887'
6
+ metadata.gz: 4736ccb5a8f385295543757bc8a8e7d26d4aa70fe7fce868cae656dc8217e5c409e82f429c813bb61e8d44c1144587fd6979b06827872df26f44fc959be1371c
7
+ data.tar.gz: 35888fd8a241fac71a4d5738b8322b33fdff3114ce2001ad4098d3fb0c84bafdd4c3d5d04febeb8f2a7ee90fd61f800135ec72c37011efe39071fc4097d60764
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Legion Changelog
2
2
 
3
+ ## [1.4.53] - 2026-03-17
4
+
5
+ ### Fixed
6
+ - Extension discovery now correctly parses multi-hyphenated gem names (e.g., `lex-cognitive-reappraisal`)
7
+ - `gem_names_for_discovery` returns structured data instead of ambiguous `name-version` strings
8
+ - Updated fallback path to use `Gem::Specification.latest_specs` instead of `all_names`
9
+
3
10
  ## [1.4.52] - 2026-03-17
4
11
 
5
12
  ### Added
data/CLAUDE.md CHANGED
@@ -9,7 +9,7 @@ The primary gem for the LegionIO framework. An extensible async job engine for s
9
9
 
10
10
  **GitHub**: https://github.com/LegionIO/LegionIO
11
11
  **Gem**: `legionio`
12
- **Version**: 1.4.36
12
+ **Version**: 1.4.52
13
13
  **License**: Apache-2.0
14
14
  **Docker**: `legionio/legion`
15
15
  **Ruby**: >= 3.4
@@ -107,23 +107,33 @@ Legion (lib/legion.rb)
107
107
  │ │ ├── Extensions # Nested: extensions/runners/functions + invoke
108
108
  │ │ ├── Nodes # List/show nodes (filterable by active/status)
109
109
  │ │ ├── Schedules # CRUD for lex-scheduler schedules + logs
110
- │ │ ├── Relationships # Stub (501) - no data model yet
110
+ │ │ ├── Relationships # CRUD (backed by legion-data migration 013)
111
111
  │ │ ├── Chains # Stub (501) - no data model yet
112
112
  │ │ ├── Settings # Read/write settings with redaction + readonly guards
113
113
  │ │ ├── Events # SSE stream (sinatra stream) + ring buffer polling fallback
114
114
  │ │ ├── Transport # Connection status, exchanges, queues, publish
115
115
  │ │ ├── Hooks # List + trigger registered extension hooks
116
116
  │ │ ├── Workers # Digital worker lifecycle (`/api/workers/*`) + team routes (`/api/teams/*`)
117
- │ │ └── Coldstart # `POST /api/coldstart/ingest` — trigger lex-coldstart ingest from API
117
+ │ │ ├── Coldstart # `POST /api/coldstart/ingest` — trigger lex-coldstart ingest from API
118
+ │ │ ├── Capacity # Aggregate, forecast, per-worker capacity endpoints
119
+ │ │ ├── Tenants # Tenant listing, provisioning, suspension, quota
120
+ │ │ ├── Audit # Audit log query: list, show, count, export
121
+ │ │ ├── Rbac # RBAC: role listing, permission grants, access checks
122
+ │ │ ├── Webhooks # Webhook subscription CRUD + delivery status
123
+ │ │ └── Validators # Request body schema validation helpers
118
124
  │ ├── Middleware/
119
- │ │ └── Auth # JWT Bearer auth middleware (real validation, skip paths for health/ready)
125
+ │ │ ├── Auth # JWT Bearer auth middleware (real validation, skip paths for health/ready)
126
+ │ │ ├── Tenant # Tenant extraction from JWT/header, sets TenantContext
127
+ │ │ ├── ApiVersion # `/api/v1/` rewrite, Deprecation/Sunset headers
128
+ │ │ ├── BodyLimit # Request body size limit (1MB max, returns 413)
129
+ │ │ └── RateLimit # Sliding-window rate limiting with per-IP/agent/tenant tiers
120
130
  │ └── hook_registry # Class-level registry: register_hook, find_hook, registered_hooks
121
131
  │ # Populated by extensions via Legion::API.register_hook(...)
122
132
 
123
133
  ├── MCP (mcp gem) # MCP server for AI agent integration
124
134
  │ ├── MCP.server # Singleton factory: Legion::MCP.server returns MCP::Server instance
125
135
  │ ├── Server # MCP::Server builder, tool/resource registration
126
- │ ├── Tools/ # 30 MCP::Tool subclasses (legion.* namespace)
136
+ │ ├── Tools/ # 35 MCP::Tool subclasses (legion.* namespace)
127
137
  │ │ ├── RunTask # Agentic: dot notation task execution
128
138
  │ │ ├── DescribeRunner # Agentic: runner/function discovery
129
139
  │ │ ├── List/Get/Delete Task + GetTaskLogs
@@ -132,7 +142,8 @@ Legion (lib/legion.rb)
132
142
  │ │ ├── List/Get/Enable/Disable Extension
133
143
  │ │ ├── List/Create/Update/Delete Schedule
134
144
  │ │ ├── GetStatus, GetConfig
135
- │ │ └── ListWorkers, ShowWorker, WorkerLifecycle, WorkerCosts, TeamSummary, RoutingStats
145
+ │ │ ├── ListWorkers, ShowWorker, WorkerLifecycle, WorkerCosts, TeamSummary, RoutingStats
146
+ │ │ └── RbacAssignments, RbacCheck, RbacGrants
136
147
  │ └── Resources/
137
148
  │ ├── RunnerCatalog # legion://runners - all ext.runner.func paths
138
149
  │ └── ExtensionInfo # legion://extensions/{name} - extension detail template
@@ -143,6 +154,14 @@ Legion (lib/legion.rb)
143
154
  │ ├── RiskTier # AIRB risk tier classification + governance constraints
144
155
  │ └── ValueMetrics # Token/cost/latency value tracking
145
156
 
157
+ ├── Graph # Task relationship visualization
158
+ │ ├── Builder # Builds adjacency graph from relationships table (chain/worker filtering)
159
+ │ └── Exporter # Renders to Mermaid and DOT (Graphviz) formats
160
+
161
+ ├── TraceSearch # Natural language trace search via LLM structured output
162
+ │ # Translates NL queries to safe JSON filter DSL (column allowlist)
163
+ │ # Uses Legion::LLM.structured for JSON extraction
164
+
146
165
  ├── Runner # Task execution engine
147
166
  │ ├── Log # Task logging
148
167
  │ └── Status # Task status tracking
@@ -194,6 +213,22 @@ Legion (lib/legion.rb)
194
213
  ├── Pr # `legion pr` - AI-generated PR title and description via LLM
195
214
  ├── Review # `legion review` - AI code review with severity levels
196
215
  ├── Gaia # `legion gaia` - Gaia status
216
+ ├── Graph # `legion graph show` - task relationship graph (mermaid/dot)
217
+ ├── Trace # `legion trace search` - NL trace search via LLM
218
+ ├── Dashboard # `legion dashboard` - TUI operational dashboard with auto-refresh
219
+ │ ├── DataFetcher # Polls REST API for workers, health, events
220
+ │ └── Renderer # Terminal-based dashboard rendering
221
+ ├── Cost # `legion cost` - cost summary, worker, team, top, budget, export
222
+ │ └── DataClient # API client for cost data aggregation
223
+ ├── Skill # `legion skill` - list, show, create, run skill files
224
+ ├── Audit # `legion audit` - query audit log (list, show, count, export)
225
+ ├── Rbac # `legion rbac` - role management, permission grants, access check
226
+ ├── Init # `legion init` - interactive project setup wizard
227
+ │ ├── ConfigGenerator # Generates starter config files from templates
228
+ │ └── EnvironmentDetector # Detects runtime environment (Docker, CI, services)
229
+ ├── Marketplace # `legion marketplace` - extension marketplace (search, install, publish)
230
+ ├── Notebook # `legion notebook` - interactive task notebook REPL
231
+ ├── Update # `legion update` - self-update via Homebrew or gem
197
232
  ├── Schedule # `legion schedule` - schedule list/show/add/remove/logs
198
233
  └── Completion # `legion completion` - bash/zsh tab completion scripts
199
234
  ```
@@ -361,6 +396,53 @@ legion
361
396
  stats [SESSION_ID] # aggregate or per-session telemetry stats
362
397
  ingest PATH # manually ingest a session log file
363
398
 
399
+ graph
400
+ show [--chain ID] [--worker ID] # display task relationship graph
401
+ [--format mermaid|dot] [--output FILE] [--limit N]
402
+
403
+ trace
404
+ search QUERY [--limit N] # natural language trace search via LLM
405
+
406
+ dashboard
407
+ start [--url URL] [--refresh N] # TUI operational dashboard with auto-refresh
408
+
409
+ cost
410
+ summary # overall cost summary (today/week/month)
411
+ worker <id> # per-worker cost breakdown
412
+ team <name> # per-team cost attribution
413
+ top [--limit 10] # top cost consumers
414
+ budget # budget status
415
+ export [--format csv|json] # export cost data
416
+
417
+ skill
418
+ list # list discovered skills
419
+ show <name> # display skill definition
420
+ create <name> # scaffold new skill file
421
+ run <name> [args] # run skill outside of chat
422
+
423
+ audit
424
+ list [--entity TYPE] [--action ACT] [--limit N]
425
+ show <id>
426
+ count [--entity TYPE] [--since TIME]
427
+ export [--format json|csv]
428
+
429
+ rbac
430
+ roles # list roles
431
+ grants <identity> # list grants for identity
432
+ check <identity> <resource> <action> # check access
433
+
434
+ init # interactive project setup wizard
435
+ [--dir PATH] [--template NAME]
436
+
437
+ marketplace
438
+ search QUERY # search extension marketplace
439
+ install NAME # install extension
440
+ publish # publish current extension
441
+
442
+ notebook # interactive task notebook REPL
443
+
444
+ update # self-update via Homebrew or gem
445
+
364
446
  auth
365
447
  teams [--tenant-id ID] [--client-id ID] # browser OAuth flow for Microsoft Teams
366
448
  ```
@@ -445,6 +527,17 @@ rack-test, rake, rspec, rubocop, rubocop-rspec, simplecov
445
527
  | `lib/legion/extensions/data/` | Extension-level migrator and model |
446
528
  | `lib/legion/extensions/hooks/base.rb` | Webhook hook base class |
447
529
  | `lib/legion/extensions/transport.rb` | Extension transport setup |
530
+ | `lib/legion/graph/builder.rb` | Graph builder: adjacency list from relationships table with chain/worker filtering |
531
+ | `lib/legion/graph/exporter.rb` | Graph exporter: renders to Mermaid (`graph TD`) and DOT (Graphviz `digraph`) formats |
532
+ | `lib/legion/trace_search.rb` | NL trace search: LLM structured output to JSON filter DSL with column allowlist |
533
+ | `lib/legion/guardrails.rb` | Input validation guardrails for runner payloads |
534
+ | `lib/legion/isolation.rb` | Process isolation for untrusted extension execution |
535
+ | `lib/legion/sandbox.rb` | Sandboxed execution environment for extensions |
536
+ | `lib/legion/context.rb` | Thread-local execution context (request tracing, tenant) |
537
+ | `lib/legion/catalog.rb` | Extension catalog: registry of available extensions with metadata |
538
+ | `lib/legion/registry.rb` | Extension registry with security scanning |
539
+ | `lib/legion/registry/security_scanner.rb` | Gem security scanner (CVE checks, signature verification) |
540
+ | `lib/legion/webhooks.rb` | Webhook delivery system: HTTP POST with retry, HMAC signing |
448
541
  | `lib/legion/runner.rb` | Task execution engine |
449
542
  | `lib/legion/runner/log.rb` | Task logging |
450
543
  | `lib/legion/runner/status.rb` | Task status tracking |
@@ -457,7 +550,7 @@ rack-test, rake, rspec, rubocop, rubocop-rspec, simplecov
457
550
  | `lib/legion/api/extensions.rb` | Extensions: nested REST (extensions/runners/functions + invoke) |
458
551
  | `lib/legion/api/nodes.rb` | Nodes: list (filterable), show |
459
552
  | `lib/legion/api/schedules.rb` | Schedules: CRUD + logs (requires lex-scheduler) |
460
- | `lib/legion/api/relationships.rb` | Relationships: stub (501, no data model yet) |
553
+ | `lib/legion/api/relationships.rb` | Relationships: CRUD (backed by legion-data migration 013) |
461
554
  | `lib/legion/api/chains.rb` | Chains: stub (501, no data model yet) |
462
555
  | `lib/legion/api/settings.rb` | Settings: read/write with redaction + readonly guards |
463
556
  | `lib/legion/api/events.rb` | Events: SSE stream + polling fallback (ring buffer) |
@@ -469,7 +562,17 @@ rack-test, rake, rspec, rubocop, rubocop-rspec, simplecov
469
562
  | `lib/legion/api/token.rb` | Token: JWT token issuance endpoint |
470
563
  | `lib/legion/api/openapi.rb` | OpenAPI: `Legion::API::OpenAPI.spec` / `.to_json`; also served at `GET /api/openapi.json` |
471
564
  | `lib/legion/api/oauth.rb` | OAuth: `GET /api/oauth/microsoft_teams/callback` — receives delegated OAuth redirect and stores tokens |
565
+ | `lib/legion/api/capacity.rb` | Capacity: aggregate, forecast, and per-worker capacity endpoints |
566
+ | `lib/legion/api/tenants.rb` | Tenants: listing, provisioning, suspension, quota check |
567
+ | `lib/legion/api/audit.rb` | Audit: list, show, count, export audit log entries |
568
+ | `lib/legion/api/auth_human.rb` | Auth: human user authentication endpoints |
569
+ | `lib/legion/api/auth_worker.rb` | Auth: digital worker authentication endpoints |
570
+ | `lib/legion/api/rbac.rb` | RBAC: role listing, permission grants, access checks |
571
+ | `lib/legion/api/validators.rb` | Request validators: schema validation helpers for API inputs |
572
+ | `lib/legion/api/webhooks.rb` | Webhooks: CRUD for webhook subscriptions + delivery status |
472
573
  | `lib/legion/audit.rb` | Audit logging: AMQP publish + query layer (recent_for, count_for, resources_for, recent) backed by AuditLog model |
574
+ | `lib/legion/audit/hash_chain.rb` | Tamper-evident hash chain for audit entries |
575
+ | `lib/legion/audit/siem_export.rb` | SIEM export: format audit entries for Splunk/ELK ingestion |
473
576
  | `lib/legion/alerts.rb` | Configurable alerting rules engine: pattern matching, count conditions, cooldown dedup |
474
577
  | `lib/legion/telemetry.rb` | Opt-in OpenTelemetry tracing: `with_span` wrapper, `sanitize_attributes`, `record_exception` |
475
578
  | `lib/legion/metrics.rb` | Opt-in Prometheus metrics: event-driven counters, pull-based gauges, `prometheus-client` guarded |
@@ -480,6 +583,10 @@ rack-test, rake, rspec, rubocop, rubocop-rspec, simplecov
480
583
  | `lib/legion/api/middleware/api_version.rb` | ApiVersion: rewrites `/api/v1/` to `/api/`, adds Deprecation/Sunset headers on unversioned paths |
481
584
  | `lib/legion/api/middleware/body_limit.rb` | BodyLimit: request body size limit (1MB max, returns 413) |
482
585
  | `lib/legion/api/middleware/rate_limit.rb` | RateLimit: sliding-window rate limiting with per-IP/agent/tenant tiers |
586
+ | `lib/legion/api/middleware/tenant.rb` | Tenant: extracts tenant_id from JWT/header, sets TenantContext per request |
587
+ | `lib/legion/tenant_context.rb` | Thread-local tenant context propagation (set, clear, with block) |
588
+ | `lib/legion/tenants.rb` | Tenant CRUD, suspension, quota enforcement |
589
+ | `lib/legion/capacity/model.rb` | Workforce capacity calculation (throughput, utilization, forecast, per-worker) |
483
590
  | **MCP** | |
484
591
  | `lib/legion/mcp.rb` | Entry point: `Legion::MCP.server` singleton factory, `server_for(token:)` |
485
592
  | `lib/legion/mcp/auth.rb` | MCP authentication: JWT + API key verification |
@@ -490,7 +597,7 @@ rack-test, rake, rspec, rubocop, rubocop-rspec, simplecov
490
597
  | `lib/legion/digital_worker/registry.rb` | In-process worker registry |
491
598
  | `lib/legion/digital_worker/risk_tier.rb` | AIRB risk tier + governance constraints |
492
599
  | `lib/legion/digital_worker/value_metrics.rb` | Token/cost/latency tracking |
493
- | `lib/legion/mcp/tools/` | 30 MCP::Tool subclasses |
600
+ | `lib/legion/mcp/tools/` | 35 MCP::Tool subclasses (incl. rbac_assignments, rbac_check, rbac_grants) |
494
601
  | `lib/legion/mcp/resources/runner_catalog.rb` | `legion://runners` resource |
495
602
  | `lib/legion/mcp/resources/extension_info.rb` | `legion://extensions/{name}` resource template |
496
603
  | **CLI v2** | |
@@ -527,7 +634,30 @@ rack-test, rake, rspec, rubocop, rubocop-rspec, simplecov
527
634
  | `lib/legion/cli/chat/agent_registry.rb` | Custom agent definitions from `.legion/agents/*.json` and `.yaml` |
528
635
  | `lib/legion/cli/chat/agent_delegator.rb` | `@name` at-mention parsing and dispatch via Subagent |
529
636
  | `lib/legion/cli/chat/chat_logger.rb` | Chat-specific logging |
637
+ | `lib/legion/cli/chat/progress_bar.rb` | Progress bar rendering for long operations |
638
+ | `lib/legion/cli/chat/status_indicator.rb` | Status indicator (spinner, checkmark, cross) |
639
+ | `lib/legion/cli/chat/team.rb` | Multi-user team support for chat sessions |
530
640
  | `lib/legion/cli/chat/tools/` | Built-in tools: read_file, write_file, edit_file (string + line-number mode), search_files, search_content, run_command, save_memory, search_memory, web_search, spawn_agent |
641
+ | `lib/legion/chat/skills.rb` | Skill discovery: parses `.legion/skills/` and `~/.legionio/skills/` YAML frontmatter files |
642
+ | `lib/legion/cli/graph_command.rb` | `legion graph` subcommands (show with --format mermaid\|dot, --chain, --output) |
643
+ | `lib/legion/cli/trace_command.rb` | `legion trace search` — NL trace search via LLM |
644
+ | `lib/legion/cli/dashboard_command.rb` | `legion dashboard` — TUI operational dashboard |
645
+ | `lib/legion/cli/dashboard/data_fetcher.rb` | Dashboard API poller: workers, health, events |
646
+ | `lib/legion/cli/dashboard/renderer.rb` | Dashboard terminal renderer with sections |
647
+ | `lib/legion/cli/cost_command.rb` | `legion cost` — cost summary, worker, team, top, budget, export |
648
+ | `lib/legion/cli/cost/data_client.rb` | Cost data aggregation API client |
649
+ | `lib/legion/cli/skill_command.rb` | `legion skill` — list, show, create, run skill files |
650
+ | `lib/legion/cli/audit_command.rb` | `legion audit` — query audit log (list, show, count, export) |
651
+ | `lib/legion/cli/rbac_command.rb` | `legion rbac` — role management, permission grants, access checks |
652
+ | `lib/legion/cli/init_command.rb` | `legion init` — interactive project setup wizard |
653
+ | `lib/legion/cli/init/config_generator.rb` | Config file generation from templates |
654
+ | `lib/legion/cli/init/environment_detector.rb` | Runtime environment detection (Docker, CI, services) |
655
+ | `lib/legion/cli/marketplace_command.rb` | `legion marketplace` — extension search, install, publish |
656
+ | `lib/legion/cli/notebook_command.rb` | `legion notebook` — interactive task notebook REPL |
657
+ | `lib/legion/cli/update_command.rb` | `legion update` — self-update via Homebrew or gem |
658
+ | `lib/legion/cli/lex_templates.rb` | LEX scaffold templates for generator |
659
+ | `lib/legion/cli/version.rb` | CLI version display helper |
660
+ | `lib/legion/docs/site_generator.rb` | Static documentation site generator |
531
661
  | `lib/legion/cli/memory_command.rb` | `legion memory` subcommands (list, add, forget, search, clear) |
532
662
  | `lib/legion/cli/plan_command.rb` | `legion plan` — read-only exploration mode with /save to docs/plans/ |
533
663
  | `lib/legion/cli/swarm_command.rb` | `legion swarm` — multi-agent workflow orchestration from `.legion/swarms/` |
@@ -581,8 +711,8 @@ rack-test, rake, rspec, rubocop, rubocop-rspec, simplecov
581
711
 
582
712
  ```bash
583
713
  bundle install
584
- bundle exec rspec # 1088 examples, 0 failures
585
- bundle exec rubocop # 0 offenses
714
+ bundle exec rspec # 1208 examples, 0 failures
715
+ bundle exec rubocop # 396 files, 0 offenses
586
716
  ```
587
717
 
588
718
  Specs use `rack-test` for API testing. `Legion::JSON.load` returns symbol keys — use `body[:data]` not `body['data']` in specs.
@@ -211,9 +211,9 @@ module Legion
211
211
 
212
212
  def gem_names_for_discovery
213
213
  if defined?(Bundler)
214
- Bundler.load.specs.map { |s| "#{s.name}-#{s.version}" }
214
+ Bundler.load.specs.map { |s| { name: s.name, version: s.version.to_s } }
215
215
  else
216
- Gem::Specification.all_names
216
+ Gem::Specification.latest_specs.map { |s| { name: s.name, version: s.version.to_s } }
217
217
  end
218
218
  end
219
219
 
@@ -266,15 +266,15 @@ module Legion
266
266
 
267
267
  def find_extensions
268
268
  @extensions ||= {}
269
- gem_names_for_discovery.each do |gem|
270
- next unless gem.start_with?('lex-')
271
-
272
- lex = gem.split('-')
273
- @extensions[lex[1]] = { full_gem_name: gem,
274
- gem_name: "lex-#{lex[1]}",
275
- extension_name: lex[1],
276
- version: lex[2],
277
- extension_class: "Legion::Extensions::#{lex[1].split('_').collect(&:capitalize).join}" }
269
+ gem_names_for_discovery.each do |spec|
270
+ next unless spec[:name].start_with?('lex-')
271
+
272
+ ext_name = spec[:name].delete_prefix('lex-').tr('-', '_')
273
+ @extensions[ext_name] = { full_gem_name: "#{spec[:name]}-#{spec[:version]}",
274
+ gem_name: spec[:name],
275
+ extension_name: ext_name,
276
+ version: spec[:version],
277
+ extension_class: "Legion::Extensions::#{ext_name.split('_').collect(&:capitalize).join}" }
278
278
  end
279
279
 
280
280
  apply_role_filter
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Legion
4
- VERSION = '1.4.52'
4
+ VERSION = '1.4.53'
5
5
  end
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.4.52
4
+ version: 1.4.53
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity