lex-detect 0.1.2 → 0.1.3
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/CHANGELOG.md +8 -0
- data/CLAUDE.md +10 -7
- data/lib/legion/extensions/detect/runners/task_observer.rb +88 -0
- data/lib/legion/extensions/detect/version.rb +1 -1
- data/lib/legion/extensions/detect.rb +1 -0
- 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: 119e238ddb0711af3bb4d23c5c65bb85c910420aa4ce79c1fe28c81950a38d0c
|
|
4
|
+
data.tar.gz: da4f50f6e3b1653c18d70617ab81630f3f9db6aa01cf6271205882f34df312f6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1f38552069181a4198433a821b64744f6bdf4cd42be0285c22eccfb4ef219f09f5d5d8a5825ac53c95ded7adb45278d5ca9ef20018c96f2dcac1ad61389da296
|
|
7
|
+
data.tar.gz: ecb32f15376b6079a1810c161a726f447e1aa6b07a3a187d894fe6393b31d608cc4c0a09227d52aefe88110e6f51ff3f3d9ba1e9e61772463587557600142896
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.3] - 2026-03-20
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `Runners::TaskObserver` for monitoring task failure patterns
|
|
7
|
+
- `check_and_publish_failure_patterns` publishes failure pattern events to AMQP for self-healing pipeline integration
|
|
8
|
+
- `extract_gem_name` helper derives gem name from runner class string
|
|
9
|
+
- `build_failure_pattern` creates structured failure pattern hash
|
|
10
|
+
|
|
3
11
|
## [0.1.2] - 2026-03-19
|
|
4
12
|
|
|
5
13
|
### Added
|
data/CLAUDE.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# lex-detect: Environment-Aware Extension Discovery
|
|
2
2
|
|
|
3
3
|
**Repository Level 3 Documentation**
|
|
4
|
-
- **Parent
|
|
5
|
-
- **
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-core/CLAUDE.md`
|
|
5
|
+
- **Grandparent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
|
|
6
6
|
|
|
7
7
|
## Purpose
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ Legion Extension that scans the local environment and recommends which `lex-*` e
|
|
|
10
10
|
|
|
11
11
|
**GitHub**: https://github.com/LegionIO/lex-detect
|
|
12
12
|
**License**: MIT
|
|
13
|
-
**Version**: 0.1.
|
|
13
|
+
**Version**: 0.1.2
|
|
14
14
|
|
|
15
15
|
## Architecture
|
|
16
16
|
|
|
@@ -19,10 +19,13 @@ Legion::Extensions::Detect
|
|
|
19
19
|
├── CATALOG (constant) # Frozen array of 20 detection rules
|
|
20
20
|
├── Scanner # Probes environment, matches against catalog
|
|
21
21
|
├── Installer # Gem.install wrapper with dry_run support
|
|
22
|
+
├── Actors/
|
|
23
|
+
│ ├── FullScan (Once) # Full environment scan at startup
|
|
24
|
+
│ └── DeltaScan (Every) # Periodic delta scan every 6 hours
|
|
22
25
|
└── Entry Point # Public API: scan, missing, install_missing!, catalog
|
|
23
26
|
```
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
Local-only utility gem. Actors run scans but do not create AMQP queues.
|
|
26
29
|
|
|
27
30
|
- `data_required? false` — no database needed
|
|
28
31
|
- `remote_invocable? false` — no AMQP queue creation
|
|
@@ -49,12 +52,12 @@ Legion::Extensions::Detect.catalog # raw CATALOG constant
|
|
|
49
52
|
|
|
50
53
|
## Design Docs
|
|
51
54
|
|
|
52
|
-
- Design: `docs/
|
|
53
|
-
- Implementation: `docs/
|
|
55
|
+
- Design: `docs/work/completed/2026-03-18-lex-detect-design.md`
|
|
56
|
+
- Implementation: `docs/work/completed/2026-03-18-lex-detect-implementation.md`
|
|
54
57
|
|
|
55
58
|
## Testing
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
40 specs across 6 spec files.
|
|
58
61
|
|
|
59
62
|
```bash
|
|
60
63
|
bundle install
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Detect
|
|
6
|
+
module Runners
|
|
7
|
+
module TaskObserver
|
|
8
|
+
extend self
|
|
9
|
+
|
|
10
|
+
def observe(tasks:, **)
|
|
11
|
+
return { success: true, alerts: [] } unless tasks.is_a?(Array)
|
|
12
|
+
|
|
13
|
+
alerts = generate_alerts(tasks)
|
|
14
|
+
check_and_publish_failure_patterns(tasks)
|
|
15
|
+
{ success: true, alerts: alerts, task_count: tasks.size }
|
|
16
|
+
rescue StandardError => e
|
|
17
|
+
{ success: false, reason: :error, message: e.message }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def generate_alerts(tasks)
|
|
23
|
+
failed = tasks.select { |t| t[:status] == 'failed' }
|
|
24
|
+
return [] if failed.empty?
|
|
25
|
+
|
|
26
|
+
failed.group_by { |t| t[:runner_class] }.filter_map do |runner_class, failures|
|
|
27
|
+
next unless failures.size >= 3
|
|
28
|
+
|
|
29
|
+
{ runner_class: runner_class, failure_count: failures.size, level: :warning }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def check_and_publish_failure_patterns(tasks)
|
|
34
|
+
return unless defined?(Legion::Data) && defined?(Legion::Transport)
|
|
35
|
+
|
|
36
|
+
runner_failures = tasks.select { |t| t[:status] == 'failed' }
|
|
37
|
+
.group_by { |t| t[:runner_class] }
|
|
38
|
+
|
|
39
|
+
runner_failures.each do |runner_class, failures|
|
|
40
|
+
next unless failures.size >= 3
|
|
41
|
+
|
|
42
|
+
gem_name = extract_gem_name(runner_class)
|
|
43
|
+
backtraces = failures.filter_map { |f| f[:error_backtrace] }.first(5)
|
|
44
|
+
error_class = failures.first[:error_class] || 'StandardError'
|
|
45
|
+
|
|
46
|
+
pattern = build_failure_pattern(gem_name, runner_class, error_class, backtraces, failures.size)
|
|
47
|
+
publish_failure_pattern(pattern)
|
|
48
|
+
end
|
|
49
|
+
rescue StandardError
|
|
50
|
+
nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def build_failure_pattern(gem_name, runner_class, error_class, backtraces, count)
|
|
54
|
+
{
|
|
55
|
+
gem_name: gem_name,
|
|
56
|
+
runner_class: runner_class,
|
|
57
|
+
error_class: error_class,
|
|
58
|
+
backtraces: backtraces,
|
|
59
|
+
failure_count: count,
|
|
60
|
+
window_minutes: 60
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def publish_failure_pattern(pattern)
|
|
65
|
+
return unless defined?(Legion::Transport::Messages::Dynamic)
|
|
66
|
+
|
|
67
|
+
Legion::Transport::Messages::Dynamic.new(
|
|
68
|
+
function: 'auto_fix',
|
|
69
|
+
payload: pattern
|
|
70
|
+
).publish
|
|
71
|
+
rescue StandardError
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def extract_gem_name(runner_class)
|
|
76
|
+
return nil unless runner_class
|
|
77
|
+
|
|
78
|
+
parts = runner_class.to_s.split('::')
|
|
79
|
+
ext_idx = parts.index('Extensions')
|
|
80
|
+
return nil unless ext_idx && parts[ext_idx + 1]
|
|
81
|
+
|
|
82
|
+
"lex-#{parts[ext_idx + 1].gsub(/([a-z])([A-Z])/, '\1_\2').downcase}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-detect
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -32,6 +32,7 @@ files:
|
|
|
32
32
|
- lib/legion/extensions/detect/catalog.rb
|
|
33
33
|
- lib/legion/extensions/detect/installer.rb
|
|
34
34
|
- lib/legion/extensions/detect/local_migrations/20260319000001_create_detect_results.rb
|
|
35
|
+
- lib/legion/extensions/detect/runners/task_observer.rb
|
|
35
36
|
- lib/legion/extensions/detect/scanner.rb
|
|
36
37
|
- lib/legion/extensions/detect/version.rb
|
|
37
38
|
homepage: https://github.com/LegionIO/lex-detect
|