rubocop-legion 0.1.9 → 0.1.10

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: 88034e8168ad8e5634a580f3a07ca2f030bd46be31b6c9607dbc64a28935bcd0
4
- data.tar.gz: 353647b902a3271fe17809769674778b528eb3e97dda8704934addf80b69b397
3
+ metadata.gz: 4d9316d83d8676fe5adb80fd7500f3daece09203ece25f0ce0c81887d19982ca
4
+ data.tar.gz: 646cab78aebc73b233882dcfc594d6c0efbea0acb3e2881e02a1f888ec5513e4
5
5
  SHA512:
6
- metadata.gz: 0b7d05703e9bd6762628d25f082a738fba9972f66eda2b650ab5e3c0dace6b3569df16c754f935f8f62caf861eaf3984018c3a4f3f73de01cc0871fcf91cfebd
7
- data.tar.gz: d598e5090c4ba1242ec371fd2d3b935412f9fe8c4e24fe907a9e18bd6052999568bed0c252a983559e4b33e1c0502a724e02df5244db46b98c5cdad899f62e93
6
+ metadata.gz: 83f63897f48898014d992e98b11cdfd9f2b830e405b2fd49bff484acffdaaeafd853dea8016baaa280787302a0c15a701e2f1d0c71274d1bf0fa04761574e8bd
7
+ data.tar.gz: 69aa65b8634cef75041fe37a57b87ca54bdc911a59fc12710193a66550b71c01926831618ef9100b775c5fc498d0705d8eaab50af11c5c1446d36ab801be51ae
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.10] - 2026-07-31
4
+
5
+ ### Fixed
6
+ - `Legion/Llm/TaxonomyEnum` no longer over-matches: `:type` is only validated when it appears alongside `:tier` or `:circuit_state` in the same hash (taxonomy context). Previously any `{ type: :string }` or schema hash triggered a false positive.
7
+ - Added `Legion/Llm` department to `config/default.yml` — all four cops (`TaxonomyEnum`, `SettingsAccessPath`, `NoLoopDo`, `RescueLogLevel`) were loaded but never registered in the config, causing consumer repos to report "unrecognized cop" when referencing `Legion/Llm/TaxonomyEnum`.
8
+ - `TaxonomyEnum` is now Include-scoped to `lib/legion/llm/**/*.rb` and `lib/legion/extensions/llm/**/*.rb` so it only runs on LLM routing code.
9
+
3
10
  ## [0.1.8] - 2026-06-16
4
11
 
5
12
  ### Added
data/config/default.yml CHANGED
@@ -363,3 +363,38 @@ Legion/Framework/NoShapeDuckTyping:
363
363
  Severity: convention
364
364
  VersionAdded: '0.1.8'
365
365
  Safe: false
366
+
367
+ # Legion/Llm — cops specific to legion-llm and lex-llm-* provider pipelines
368
+
369
+ Legion/Llm:
370
+ Enabled: true
371
+ Include:
372
+ - 'lib/legion/llm/**/*.rb'
373
+ - 'lib/legion/extensions/llm/**/*.rb'
374
+
375
+ Legion/Llm/TaxonomyEnum:
376
+ Description: 'Validate :tier, :type, and :circuit_state literals against LegionIO taxonomy enums.'
377
+ Enabled: true
378
+ Severity: convention
379
+ VersionAdded: '0.1.9'
380
+ Include:
381
+ - 'lib/legion/llm/**/*.rb'
382
+ - 'lib/legion/extensions/llm/**/*.rb'
383
+
384
+ Legion/Llm/SettingsAccessPath:
385
+ Description: 'Use `Legion::Settings.dig(...)` instead of `Legion::Settings.loader.settings[...][...]`.'
386
+ Enabled: true
387
+ Severity: convention
388
+ VersionAdded: '0.1.9'
389
+
390
+ Legion/Llm/NoLoopDo:
391
+ Description: 'Ban `loop do` — use bounded iteration (`N.times`, `each`, or `while` with explicit bound).'
392
+ Enabled: true
393
+ Severity: warning
394
+ VersionAdded: '0.1.9'
395
+
396
+ Legion/Llm/RescueLogLevel:
397
+ Description: 'Minimum log level for `handle_exception` in rescue blocks is `:warn`.'
398
+ Enabled: true
399
+ Severity: warning
400
+ VersionAdded: '0.1.9'
@@ -8,6 +8,11 @@ module RuboCop
8
8
  # Flags `:tier`, `:type`, and `:circuit_state` literals that are not in
9
9
  # the known-valid sets, catching typos at lint time.
10
10
  #
11
+ # `:tier` and `:circuit_state` are domain-specific keys and are always
12
+ # validated. `:type` is only validated when it appears in a hash that
13
+ # also contains `:tier` or `:circuit_state`, since `:type` alone is too
14
+ # common in non-taxonomy contexts.
15
+ #
11
16
  # Valid values (from Inventory::DEFAULT_PROVIDER_TIERS and the SSOT design):
12
17
  # tier: :local, :fleet, :cloud, :frontier, :direct
13
18
  # type: :inference, :embedding, :moderation, :rerank, :image
@@ -17,15 +22,24 @@ module RuboCop
17
22
  # # bad (typo)
18
23
  # { tier: :fronteir }
19
24
  # health[:circuit_state] = :half_opened
25
+ # { tier: :cloud, type: :inferencing }
20
26
  #
21
27
  # # good
22
28
  # { tier: :frontier }
23
29
  # health[:circuit_state] = :half_open
30
+ # { tier: :cloud, type: :inference }
31
+ #
32
+ # # ignored (`:type` alone, no taxonomy context)
33
+ # { type: :string }
34
+ # { type: :integer }
24
35
  class TaxonomyEnum < Base
25
36
  VALID_TIERS = %i[local fleet cloud frontier direct].freeze
26
37
  VALID_TYPES = %i[inference embedding moderation rerank image].freeze
27
38
  VALID_CIRCUIT_STATES = %i[closed open half_open].freeze
28
39
 
40
+ TAXONOMY_KEYS = %i[tier type circuit_state].freeze
41
+ CONTEXT_KEYS = %i[tier circuit_state].freeze
42
+
29
43
  MSG_TIER = 'Unknown tier `%<val>s`. Valid: %<valid>s.'
30
44
  MSG_TYPE = 'Unknown type `%<val>s`. Valid: %<valid>s.'
31
45
  MSG_CIRCUIT = 'Unknown circuit_state `%<val>s`. Valid: %<valid>s.'
@@ -38,7 +52,6 @@ module RuboCop
38
52
  end
39
53
 
40
54
  def on_send(node)
41
- # health[:circuit_state] = :bad_value
42
55
  return unless node.method_name == :[]=
43
56
  return unless node.arguments.size == 2
44
57
 
@@ -54,22 +67,34 @@ module RuboCop
54
67
  val = val_node.value
55
68
  case key
56
69
  when :tier
57
- unless VALID_TIERS.include?(val)
58
- add_offense(parent_node,
59
- message: format(MSG_TIER, val: val, valid: VALID_TIERS.join(', ')))
60
- end
70
+ return if VALID_TIERS.include?(val)
71
+
72
+ add_offense(parent_node,
73
+ message: format(MSG_TIER, val: val, valid: VALID_TIERS.join(', ')))
61
74
  when :type
62
- unless VALID_TYPES.include?(val)
63
- add_offense(parent_node,
64
- message: format(MSG_TYPE, val: val, valid: VALID_TYPES.join(', ')))
65
- end
75
+ return if VALID_TYPES.include?(val)
76
+ return unless taxonomy_context?(parent_node)
77
+
78
+ add_offense(parent_node,
79
+ message: format(MSG_TYPE, val: val, valid: VALID_TYPES.join(', ')))
66
80
  when :circuit_state
67
- unless VALID_CIRCUIT_STATES.include?(val)
68
- msg = format(MSG_CIRCUIT, val: val, valid: VALID_CIRCUIT_STATES.join(', '))
69
- add_offense(parent_node, message: msg)
70
- end
81
+ return if VALID_CIRCUIT_STATES.include?(val)
82
+
83
+ add_offense(parent_node,
84
+ message: format(MSG_CIRCUIT, val: val, valid: VALID_CIRCUIT_STATES.join(', ')))
71
85
  end
72
86
  end
87
+
88
+ def taxonomy_context?(pair_node)
89
+ hash_node = pair_node.parent
90
+ return false unless hash_node&.hash_type?
91
+
92
+ sibling_keys = hash_node.pairs.filter_map do |pair|
93
+ pair.key.value if pair.key.sym_type?
94
+ end
95
+
96
+ sibling_keys.intersect?(CONTEXT_KEYS)
97
+ end
73
98
  end
74
99
  end
75
100
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Legion
5
- VERSION = '0.1.9'
5
+ VERSION = '0.1.10'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-legion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity