rigortype 0.4.5 → 0.4.6

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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/docs/handbook/11-sig-gen.md +11 -2
  4. data/docs/manual/02-cli-reference.md +46 -7
  5. data/docs/manual/03-configuration.md +2 -1
  6. data/docs/manual/04-diagnostics.md +1 -1
  7. data/docs/manual/10-mcp-server.md +9 -1
  8. data/docs/manual/12-caching.md +8 -1
  9. data/docs/manual/plugins/rigor-actionmailer.md +30 -0
  10. data/docs/manual/plugins/rigor-actionpack.md +30 -0
  11. data/docs/manual/plugins/rigor-devise.md +15 -0
  12. data/docs/manual/plugins/rigor-rspec.md +2 -1
  13. data/lib/rigor/analysis/buffer_binding.rb +14 -0
  14. data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +30 -9
  15. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +142 -15
  16. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +4 -0
  17. data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +66 -3
  18. data/lib/rigor/analysis/check_rules/rebinding_block_callees/dispatch.rb +112 -0
  19. data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +394 -0
  20. data/lib/rigor/analysis/check_rules/ruby_deprecations.rb +7 -0
  21. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +51 -0
  22. data/lib/rigor/analysis/check_rules.rb +93 -8
  23. data/lib/rigor/analysis/dependency_recorder.rb +11 -0
  24. data/lib/rigor/analysis/edit_replay.rb +67 -0
  25. data/lib/rigor/analysis/incremental.rb +37 -0
  26. data/lib/rigor/analysis/incremental_session.rb +175 -27
  27. data/lib/rigor/analysis/path_expansion.rb +41 -0
  28. data/lib/rigor/analysis/require_relative_closure.rb +100 -0
  29. data/lib/rigor/analysis/rule_catalog.rb +5 -1
  30. data/lib/rigor/analysis/run_disclosure_credit.rb +80 -0
  31. data/lib/rigor/analysis/run_disclosure_ledger.rb +155 -0
  32. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -2
  33. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +11 -3
  34. data/lib/rigor/analysis/runner/pool_coordinator.rb +17 -4
  35. data/lib/rigor/analysis/runner/project_pre_passes.rb +45 -3
  36. data/lib/rigor/analysis/runner/scan_environment.rb +51 -0
  37. data/lib/rigor/analysis/runner.rb +156 -49
  38. data/lib/rigor/analysis/worker_session.rb +14 -2
  39. data/lib/rigor/cache/incremental_snapshot.rb +30 -7
  40. data/lib/rigor/cli/check_command.rb +93 -4
  41. data/lib/rigor/cli/diff_command.rb +2 -1
  42. data/lib/rigor/cli/lens_command.rb +5 -5
  43. data/lib/rigor/cli/mcp_command.rb +2 -1
  44. data/lib/rigor/cli/options.rb +20 -3
  45. data/lib/rigor/cli/plugins_command.rb +5 -0
  46. data/lib/rigor/cli/plugins_renderer.rb +24 -2
  47. data/lib/rigor/cli/show_bleedingedge_command.rb +2 -1
  48. data/lib/rigor/cli/sig_gen_command.rb +46 -7
  49. data/lib/rigor/cli/type_of_command.rb +2 -1
  50. data/lib/rigor/cli/type_of_project_scope.rb +27 -0
  51. data/lib/rigor/config_audit.rb +16 -5
  52. data/lib/rigor/configuration.rb +14 -4
  53. data/lib/rigor/environment/rbs_loader.rb +115 -6
  54. data/lib/rigor/environment/required_features.rb +136 -29
  55. data/lib/rigor/environment/ruby_library_roots.rb +122 -0
  56. data/lib/rigor/environment.rb +4 -2
  57. data/lib/rigor/inference/callee_mutation_chain.rb +115 -0
  58. data/lib/rigor/inference/deep_erasure.rb +138 -0
  59. data/lib/rigor/inference/def_return_typer.rb +159 -9
  60. data/lib/rigor/inference/definer_resolution.rb +17 -3
  61. data/lib/rigor/inference/error_info.rb +17 -3
  62. data/lib/rigor/inference/expression_typer.rb +62 -13
  63. data/lib/rigor/inference/global_write_census.rb +36 -1
  64. data/lib/rigor/inference/ivar_writer_census.rb +195 -0
  65. data/lib/rigor/inference/loop_value_record.rb +53 -0
  66. data/lib/rigor/inference/match_rebinding/frame.rb +19 -0
  67. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +110 -9
  68. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +6 -2
  69. data/lib/rigor/inference/method_dispatcher/set_folding.rb +53 -20
  70. data/lib/rigor/inference/method_dispatcher.rb +46 -16
  71. data/lib/rigor/inference/module_function_state/spellings.rb +64 -0
  72. data/lib/rigor/inference/module_function_state.rb +12 -0
  73. data/lib/rigor/inference/mutation_widening.rb +5 -2
  74. data/lib/rigor/inference/narrowing.rb +66 -5
  75. data/lib/rigor/inference/object_mixins.rb +13 -1
  76. data/lib/rigor/inference/project_seed_tables.rb +2 -1
  77. data/lib/rigor/inference/project_yielder.rb +128 -0
  78. data/lib/rigor/inference/scope_indexer/certainty.rb +9 -0
  79. data/lib/rigor/inference/scope_indexer/declared_ivar_types.rb +64 -0
  80. data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +162 -0
  81. data/lib/rigor/inference/scope_indexer/unseen_ivar_writers.rb +133 -0
  82. data/lib/rigor/inference/scope_indexer.rb +480 -103
  83. data/lib/rigor/inference/self_call_ivar_writes.rb +18 -6
  84. data/lib/rigor/inference/statement_evaluator.rb +658 -90
  85. data/lib/rigor/inference/synthetic_method_index.rb +23 -0
  86. data/lib/rigor/inference/synthetic_method_scanner/project_members.rb +130 -0
  87. data/lib/rigor/inference/synthetic_method_scanner.rb +72 -12
  88. data/lib/rigor/language_server/buffer_table.rb +6 -0
  89. data/lib/rigor/language_server/diagnostic_publisher.rb +20 -6
  90. data/lib/rigor/language_server/project_context.rb +59 -3
  91. data/lib/rigor/language_server/server.rb +5 -3
  92. data/lib/rigor/mcp/server.rb +9 -1
  93. data/lib/rigor/plugin/base.rb +26 -11
  94. data/lib/rigor/plugin/manifest.rb +29 -3
  95. data/lib/rigor/plugin/registry.rb +38 -0
  96. data/lib/rigor/protection/discovery_seed.rb +57 -2
  97. data/lib/rigor/rooted_glob.rb +10 -1
  98. data/lib/rigor/scope.rb +14 -5
  99. data/lib/rigor/sig_gen/generator.rb +308 -37
  100. data/lib/rigor/sig_gen/observation_collector.rb +4 -1
  101. data/lib/rigor/sig_gen/rbs_validity.rb +1 -1
  102. data/lib/rigor/sig_gen/renderer.rb +6 -3
  103. data/lib/rigor/sig_gen/type_elaborator.rb +21 -5
  104. data/lib/rigor/type/combinator.rb +4 -3
  105. data/lib/rigor/type/constant.rb +45 -3
  106. data/lib/rigor/type/hash_shape.rb +14 -9
  107. data/lib/rigor/type/struct_instance.rb +3 -2
  108. data/lib/rigor/version.rb +1 -1
  109. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +60 -43
  110. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +20 -1
  111. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +13 -0
  112. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +4 -2
  113. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +5 -3
  114. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +6 -5
  115. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +102 -11
  116. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +4 -2
  117. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer.rb +1 -1
  118. data/sig/rigor/analysis/baseline.rbs +3 -2
  119. data/sig/rigor/effects/file_collection.rbs +5 -6
  120. data/sig/rigor/effects/registry.rbs +8 -6
  121. data/sig/rigor/effects/summary.rbs +6 -5
  122. data/sig/rigor/environment.rbs +5 -3
  123. data/sig/rigor/inference/optimistic_origin.rbs +11 -0
  124. data/sig/rigor/inference.rbs +6 -0
  125. data/sig/rigor/plugin/additional_initializer.rbs +5 -5
  126. data/sig/rigor/plugin/effect_ancestry.rbs +6 -4
  127. data/sig/rigor/plugin/effect_attribution.rbs +25 -10
  128. data/sig/rigor/plugin/effect_edge.rbs +12 -5
  129. data/sig/rigor/plugin/effect_entry_points.rbs +8 -3
  130. data/sig/rigor/plugin/io_boundary.rbs +4 -4
  131. data/sig/rigor/plugin/manifest.rbs +16 -18
  132. data/sig/rigor/plugin/protocol_contract.rbs +10 -9
  133. data/sig/rigor/plugin/registry.rbs +1 -1
  134. data/sig/rigor/scope.rbs +31 -50
  135. data/sig/rigor/type.rbs +0 -6
  136. metadata +20 -1
@@ -32,17 +32,19 @@ module Rigor
32
32
  # an empty vocabulary (fail-open).
33
33
  def self.load_file: (untyped path) -> Registry
34
34
 
35
- # sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from the
36
- # parameter of the same name; sig-gen proposes `untyped` for it.
37
35
  attr_reader vocabulary_version: Integer
38
- # sig-gen gap: #1154 — every declared label, sorted; implied ancestors are recognised by
39
- # {#known?} but not listed here.
36
+ # sig-gen gap: #2321 — `labels:` is declared `Array[untyped]` (input `untyped`, looks deliberate; a declared
37
+ # type is authoring intent tracked by #2325, and only then does this row generate; coercion-facing:
38
+ # `map(&:to_s)`); every declared label, sorted. Implied ancestors are recognised by {#known?} but not listed
39
+ # here.
40
40
  attr_reader labels: Array[String]
41
41
  # The roots of the vocabulary — the outermost segments {#with} treats as already owned.
42
42
  # Unmarked residue: `@roots` is computed from `@known` in `initialize`, not assigned from a
43
- # parameter, so #1154 does not cover it.
43
+ # parameter, so no parameter credit applies.
44
44
  attr_reader roots: Array[String]
45
- # sig-gen gap: #1154 — one line per root, from the data file's `descriptions:`.
45
+ # sig-gen gap: #2321 — `descriptions:` is declared `Hash[untyped, untyped]` (input `untyped`, looks deliberate;
46
+ # a declared type is authoring intent tracked by #2325, and only then does this row generate; coercion-facing:
47
+ # keys and texts `to_s`'d); one line per root, from the data file's `descriptions:`.
46
48
  attr_reader descriptions: Hash[String, String]
47
49
 
48
50
  def initialize: (vocabulary_version: Integer, labels: Array[untyped],
@@ -12,17 +12,18 @@ module Rigor
12
12
  # could not finish.
13
13
  def self.tainted: (String cause, ?String? detail) -> Summary
14
14
 
15
- # sig-gen gap: #1154 — `initialize` normalizes the `bundles:`/`declared_bundles:` kwargs through
16
- # `normalize_bundles` (join-merging per origin), so the readers do not trace to the parameters.
15
+ # sig-gen gap: #2312 — `initialize` normalizes the `bundles:`/`declared_bundles:` kwargs through
16
+ # `normalize_bundles` (join-merging per origin), a private helper whose parameters are undeclared.
17
17
  attr_reader bundles: Hash[Origin, LabelSet]
18
- # sig-gen gap: #1154 — as above.
18
+ # sig-gen gap: #2312 — as above.
19
19
  attr_reader declared_bundles: Hash[Origin, LabelSet]
20
20
  # Unmarked residue — `proven`/`declared` are flattened from the bundle tables by `initialize`,
21
- # not assigned from a parameter, so #1154 does not cover them (same shape as
21
+ # not assigned from a parameter at all, so no parameter credit applies (same shape as
22
22
  # `Registry#additional_initializers`).
23
23
  attr_reader declared: LabelSet
24
24
  attr_reader proven: LabelSet
25
- # sig-gen gap: #1154 — `causes` are `[cause, detail]` pairs normalized in `initialize`.
25
+ # sig-gen gap: #2312 — `causes` are `[cause, detail]` pairs normalized by the private `normalize_causes` helper,
26
+ # whose parameters are undeclared.
26
27
  attr_reader causes: Array[[String, String?]]
27
28
 
28
29
  def initialize: (?bundles: Hash[Origin, LabelSet], ?declared_bundles: Hash[Origin, LabelSet],
@@ -31,8 +31,6 @@ module Rigor
31
31
  def nominal_for_name: (String | Symbol name) -> Type::Nominal?
32
32
  def singleton_for_name: (String | Symbol name) -> Type::Singleton?
33
33
  def constant_for_name: (String | Symbol name) -> Type::t?
34
- # sig-gen gap: #1154 — the answer comes through `rbs_loader`, an `attr_reader` over an ivar assigned in
35
- # `initialize` from a parameter, which reaches `untyped`.
36
34
  def global_for_name: (String | Symbol name, ?builtin: bool) -> Type::t?
37
35
  def class_known?: (String | Symbol name) -> bool
38
36
  def rbs_module?: (String | Symbol name) -> bool
@@ -57,7 +55,8 @@ module Rigor
57
55
  attr_reader libraries: Array[String]
58
56
  attr_reader signature_paths: Array[String | _ToPath]
59
57
  attr_reader cache_store: untyped?
60
- # sig-gen gap: #160 — sig-gen emits no `attr_reader` for the loader's readers; typed as the initializer stores it.
58
+ # sig-gen gap: #160 — sig-gen emits no `attr_reader` for the loader's readers; typed as the initializer stores
59
+ # it.
61
60
  attr_reader deferred_signature_paths: Array[Pathname]
62
61
 
63
62
  def self.default: () -> RbsLoader
@@ -82,6 +81,9 @@ module Rigor
82
81
  def singleton_extended_module_names: (String | Symbol class_name) -> Array[String]
83
82
  def constant_type: (String name) -> Type::t?
84
83
  def constant_names: () -> Array[String]
84
+ # sig-gen gap: #2326 — the answer is `global_declarations[name.to_sym]&.first`, a lookup in the loader's memo
85
+ # hash `@state`, which sig-gen skips as untyped.
86
+ def global_type: (String | Symbol name) -> Type::t?
85
87
  def each_known_class_name: () { (String name) -> void } -> void
86
88
  | () -> ::Enumerator[String, void]
87
89
  end
@@ -5,6 +5,17 @@ module Rigor
5
5
  # (sig.skipped.untyped-return). The answer is the recorded `true` / `false` / `nil`, or the `UNKNOWN_MISS`
6
6
  # sentinel; declaring it is what lets sig-gen type `Scope#optimistic_local_miss` / `#optimistic_ivar_miss`.
7
7
  def self?.bound_miss: (untyped mark) -> Object?
8
+
9
+ class BoundMark < ::Data
10
+ # sig-gen gap: #1150 — a `Data.define` member; sig-gen proposes `untyped`. The cause a mark records.
11
+ def cause: () -> Symbol
12
+ # sig-gen gap: #1150 — a `Data.define` member; the recorded miss answer.
13
+ def miss: () -> bool?
14
+ # sig-gen gap: #1150 — the `Data.define` constructor; sig-gen types its members `untyped`.
15
+ def self.new: (cause: Symbol, miss: bool?) -> instance | (Symbol cause, bool? miss) -> instance
16
+ # sig-gen gap: #1150 — as above.
17
+ def self.[]: (cause: Symbol, miss: bool?) -> instance | (Symbol cause, bool? miss) -> instance
18
+ end
8
19
  end
9
20
  end
10
21
  end
@@ -174,6 +174,12 @@ module Rigor
174
174
  def self?.constant_literal_value: (untyped rvalue) -> Array[untyped]?
175
175
  def self?.finalize_constant_writes: (Hash[String, Hash[String, untyped]] writes) -> [Hash[String, Type::Constant], Hash[String, Set[String]]]
176
176
  def self?.propagate: (untyped node, Hash[untyped, Scope] table, Scope parent_scope) -> void
177
+
178
+ class LayeredDefNestings
179
+ def initialize: (Hash[untyped, Array[String]] file, Scope::DiscoveryIndex::def_nestings seed) -> void
180
+ def []: (untyped def_node) -> Array[String]?
181
+ def empty?: () -> bool
182
+ end
177
183
  end
178
184
 
179
185
  class CoverageScanner
@@ -4,15 +4,15 @@ module Rigor
4
4
  # the read-before-write nil soundness gate does not widen their ivars. See
5
5
  # lib/rigor/plugin/additional_initializer.rb for the full contract.
6
6
  class AdditionalInitializer
7
- # sig-gen gap: #1154 — `attr_reader` rows over ivars assigned from `initialize` parameters are
8
- # skipped (untyped return); the constructor validates `receiver_constraint` is a non-empty
9
- # String and normalizes both lists with `map(&:to_sym)`, so the stored types are hand-written.
7
+ # sig-gen gap: #2321 — `attr_reader` rows over ivars `initialize` assigns from expressions derived from its
8
+ # parameters are skipped (untyped return); the constructor validates `receiver_constraint` is a non-empty String
9
+ # and normalizes both lists with `map(&:to_sym)`, so the stored types are hand-written.
10
10
  attr_reader receiver_constraint: String
11
11
 
12
- # sig-gen gap: #1154 — as above.
12
+ # sig-gen gap: #2321 — as above.
13
13
  attr_reader methods: Array[Symbol]
14
14
 
15
- # sig-gen gap: #1154 — as above.
15
+ # sig-gen gap: #2321 — as above.
16
16
  attr_reader block_methods: Array[Symbol]
17
17
 
18
18
  # The validators accept Symbol or non-empty String elements; `initialize` normalizes to
@@ -5,12 +5,14 @@ module Rigor
5
5
  # immediate superclass. Bundled plugins only — `Effects::PluginFacts` enforces it. Frozen value
6
6
  # object.
7
7
  class EffectAncestry
8
- # sig-gen gap: #1154 — validated in `initialize` from the parameter of the same name
9
- # (`to_s`-normalized, frozen), so sig-gen proposes the raw parameter shape.
8
+ # sig-gen gap: #2312 — `child:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
9
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`, then a class-name
10
+ # check), and `initialize` stores the private `validate_class_name!` helper's result (#2312).
10
11
  attr_reader child: String
11
- # sig-gen gap: #1154 — same shape as `child`.
12
+ # sig-gen gap: #2312 — same shape as `child`.
12
13
  attr_reader parent: String
13
- # sig-gen gap: #1154 — same shape; `why:` is required and validated non-empty.
14
+ # sig-gen gap: #2312 — same shape; `why:` is `untyped` and the private `validate_why!` helper (#2312) requires
15
+ # it non-empty.
14
16
  attr_reader why: String
15
17
 
16
18
  def initialize: (child: untyped, parent: untyped, why: untyped) -> void
@@ -15,28 +15,43 @@ module Rigor
15
15
  # The taint causes a plugin row may name — a closed subset of `Effects::TaintCause::ALL`.
16
16
  TAINT_CAUSES: Array[String]
17
17
 
18
- # sig-gen gap: #1154 — normalized/validated in `initialize` from the parameter of the same
19
- # name (`to_s`-coerced, frozen), so sig-gen proposes the raw parameter shape.
18
+ # sig-gen gap: #2312 — `receiver:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
19
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`), and `initialize`
20
+ # stores the private `validate_receiver!` helper's result (#2312).
20
21
  attr_reader receiver: String
21
- # sig-gen gap: #1154 — `to_sym`-normalized from the `method:` parameter.
22
+ # sig-gen gap: #2321 — `method:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
23
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `String | Symbol`), stored as
24
+ # `method.to_sym`.
22
25
  attr_reader method: Symbol
23
26
  attr_reader singleton: bool
24
- # sig-gen gap: #1154 — `Array()`-normalized, deduplicated and frozen from `labels:`.
27
+ # sig-gen gap: #2312 — `labels:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
28
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `Array()` of anything
29
+ # answering `to_s`), stored from the private `normalize_labels` helper (#2312).
25
30
  attr_reader labels: Array[String]
26
- # sig-gen gap: #1154 — `to_s`-normalized from the `narrow:` parameter.
31
+ # sig-gen gap: #2321 — `narrow:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
32
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`, nil kept).
27
33
  attr_reader narrow: String?
28
34
  attr_reader discharge: bool
29
- # sig-gen gap: #1154 — `to_s`-normalized from the `within:` parameter.
35
+ # sig-gen gap: #2312 — `within:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
36
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`), stored from the
37
+ # private `validate_within!` helper (#2312).
30
38
  attr_reader within: String?
31
39
  attr_reader on_result: bool
32
- # sig-gen gap: #1154 — `to_s`-normalized from the `taint:` parameter.
40
+ # sig-gen gap: #2312 — `taint:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
41
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`), stored from the
42
+ # private `validate_taint!` helper (#2312).
33
43
  attr_reader taint: String?
34
- # sig-gen gap: #1154 — `to_s`-normalized from the `callee:` parameter.
44
+ # sig-gen gap: #2321 — `callee:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
45
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`, nil kept).
35
46
  attr_reader callee: String?
36
- # sig-gen gap: #1154 — normalized from the `callee_fallbacks:` parameter.
47
+ # sig-gen gap: #2312 — `callee_fallbacks:` is `untyped` (input `untyped`, looks deliberate; a declared type is
48
+ # authoring intent tracked by #2325, and only then does this row generate; coercion-facing: a Hash of coercible
49
+ # names), stored from the private `validate_callee_fallbacks!` helper (#2312).
37
50
  attr_reader callee_fallbacks: Hash[String, Array[String]]?
38
51
  attr_reader responds: bool
39
- # sig-gen gap: #1154 — `to_s`-normalized from the `why:` parameter.
52
+ # sig-gen gap: #2312 — `why:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
53
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`), stored from the
54
+ # private `validate_why!` helper (#2312).
40
55
  attr_reader why: String
41
56
 
42
57
  # The coercion-facing constructor: every parameter is `to_s`/`to_sym`/`Array()`-normalized,
@@ -7,15 +7,22 @@ module Rigor
7
7
  # The closed set of framework-edge strategies the engine implements.
8
8
  TARGETS: Array[Symbol]
9
9
 
10
- # sig-gen gap: #1154 — validated/normalized in `initialize` from the parameter of the same
11
- # name, so sig-gen proposes the raw parameter shape.
10
+ # sig-gen gap: #2312 — `receiver:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
11
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`), and `initialize`
12
+ # stores the result of the private `validate_receiver!` helper (#2312).
12
13
  attr_reader receiver: String
13
- # sig-gen gap: #1154 — `to_sym`-normalized from the `method:` parameter.
14
+ # sig-gen gap: #2321 — `method:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
15
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `String | Symbol | nil`),
16
+ # stored as `method&.to_sym`.
14
17
  attr_reader method: Symbol?
15
18
  attr_reader singleton: bool
16
- # sig-gen gap: #1154 — validated against `TARGETS` in `initialize`.
19
+ # sig-gen gap: #2312 — `target:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
20
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: a Symbol or String checked
21
+ # against `TARGETS`), stored from the private `validate_target!` helper (#2312).
17
22
  attr_reader target: (:activerecord_callbacks | :perform_now | :mailer_body)
18
- # sig-gen gap: #1154 — `to_s`-normalized from the `why:` parameter.
23
+ # sig-gen gap: #2312 — `why:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
24
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`), stored from the
25
+ # private `validate_why!` helper (#2312).
19
26
  attr_reader why: String
20
27
 
21
28
  def initialize: (receiver: untyped, target: untyped, why: untyped, ?method: untyped,
@@ -4,11 +4,16 @@ module Rigor
4
4
  # framework entry points (ADR-103 WD6). Frozen value object; {#globs} are deduplicated and
5
5
  # sorted in `initialize`.
6
6
  class EffectEntryPoints
7
- # sig-gen gap: #1154 — `to_s`-normalized in `initialize` from the `name:` parameter.
7
+ # sig-gen gap: #2321 — `initialize` declares `name:` `untyped` (input `untyped`, looks deliberate; a declared
8
+ # type is authoring intent tracked by #2325, and only then does this row generate; coercion-facing: it takes
9
+ # anything that answers `to_s`), so no input type reaches the reader.
8
10
  attr_reader name: String
9
- # sig-gen gap: #1154 — deduplicated/sorted/frozen in `initialize` from `globs:`.
11
+ # sig-gen gap: #2321 — `globs:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
12
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `Array(globs)`, each `to_s`),
13
+ # deduplicated and sorted in `initialize`.
10
14
  attr_reader globs: Array[String]
11
- # sig-gen gap: #1154 — `to_s`-normalized in `initialize` from `why:`.
15
+ # sig-gen gap: #2321 — `why:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
16
+ # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`).
12
17
  attr_reader why: String
13
18
 
14
19
  def initialize: (name: untyped, globs: untyped, ?why: untyped) -> void
@@ -8,10 +8,10 @@ class Rigor::Plugin::IoBoundary
8
8
  # Records a `:names` glob row (membership only); a caller needing a match's content `read_file`s it. A `..`
9
9
  # segment, a brace or a backslash in `pattern` raises `AccessDeniedError`.
10
10
  def glob: (untyped root, untyped pattern) -> Array[String]
11
- # sig-gen gap: #1154 — the proposal leaves both string fields untyped. `nearest_root` comes from `@policy`, an
12
- # ivar assigned from an `initialize` parameter (the #1154 shape); `first_path` comes from `@first_refused_path`,
13
- # written from `record_refusal(path)`'s parameter outside `initialize`, a case #1154 as titled does not yet cover.
14
- # The record's fields are the running count and the first refused path, nil when nothing was refused.
11
+ # sig-gen gap: #2312 — the proposal leaves both string fields untyped. `nearest_root` comes from `@policy`, a bare
12
+ # assignment of the `policy:` parameter, declared `untyped` above (a `TrustPolicy`; typing it is authoring work,
13
+ # tracked by #2325); `first_path` comes from `@first_refused_path`, written from the private `record_refusal(path)`,
14
+ # whose parameter is undeclared.
15
15
  def refusal_summary: () -> { count: Integer, first_path: String?, nearest_root: String? }?
16
16
  def open_url: (untyped url) -> String
17
17
  # Returns a frozen `Rigor::Cache::Descriptor` (no RBS yet -> untyped).
@@ -3,7 +3,7 @@ class Rigor::Plugin::Manifest::Consumption
3
3
  end
4
4
 
5
5
  class Rigor::Plugin::Manifest
6
- def initialize: (id: untyped, version: untyped, ?description: untyped, ?config_schema: untyped, ?target_gems: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?open_receivers: untyped, ?rbs_complete_ancestors: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?nested_class_templates: untyped, ?trait_registries: untyped, ?hkt_registrations: untyped, ?hkt_definitions: untyped, ?signature_paths: untyped, ?protocol_contracts: Array[Rigor::Plugin::ProtocolContract], ?source_rbs_synthesizer: untyped, ?additional_initializers: Array[Rigor::Plugin::AdditionalInitializer], ?effect_root: String?, ?effect_labels: Array[String], ?effect_attributions: Array[Rigor::Plugin::EffectAttribution], ?effect_edges: Array[Rigor::Plugin::EffectEdge], ?effect_entry_points: Array[Rigor::Plugin::EffectEntryPoints], ?effect_ancestry: Array[Rigor::Plugin::EffectAncestry], ?template_globs: untyped) -> void
6
+ def initialize: (id: untyped, version: untyped, ?description: untyped, ?config_schema: untyped, ?target_gems: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?open_receivers: untyped, ?rbs_complete_ancestors: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?nested_class_templates: untyped, ?trait_registries: untyped, ?hkt_registrations: untyped, ?hkt_definitions: untyped, ?signature_paths: untyped, ?protocol_contracts: Array[Rigor::Plugin::ProtocolContract], ?source_rbs_synthesizer: untyped, ?additional_initializers: Array[Rigor::Plugin::AdditionalInitializer], ?effect_root: String?, ?effect_labels: Array[String], ?effect_attributions: Array[Rigor::Plugin::EffectAttribution], ?effect_edges: Array[Rigor::Plugin::EffectEdge], ?effect_entry_points: Array[Rigor::Plugin::EffectEntryPoints], ?effect_ancestry: Array[Rigor::Plugin::EffectAncestry], ?template_globs: Array[String], ?per_invocation_classes: Array[String], ?per_invocation_non_action_macros: Array[Symbol | String]) -> void
7
7
 
8
8
  # Public attribute readers (the full `attr_reader` surface). Plugins
9
9
  # read `manifest.id` / `manifest.protocol_contracts` etc.; declaring
@@ -18,9 +18,9 @@ class Rigor::Plugin::Manifest
18
18
  def config_schema: () -> untyped
19
19
  def config_defaults: () -> Hash[String, untyped]
20
20
  def target_gems: () -> Array[String]
21
- # sig-gen gap: #1154 — an `attr_reader` over an ivar assigned in `initialize` from a parameter the
22
- # manifest validates but does not type, so inference reaches `untyped` where the contract is
23
- # `Array[String]` (the same gap every other reader in this block carries).
21
+ # sig-gen gap: #2321 — written by a private `assign_*` helper whose parameters are undeclared (`initialize` hands
22
+ # its fields to such helpers); each write is a derived expression (`dup.freeze`, `map`), so the helper's parameter
23
+ # types alone would not generate it.
24
24
  def template_globs: () -> Array[String]
25
25
  def produces: () -> Array[Symbol]
26
26
  def consumes: () -> Array[Rigor::Plugin::Manifest::Consumption]
@@ -35,33 +35,31 @@ class Rigor::Plugin::Manifest
35
35
  def hkt_registrations: () -> untyped
36
36
  def hkt_definitions: () -> untyped
37
37
  def signature_paths: () -> Array[String]
38
- # sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from a parameter;
39
- # `validate_protocol_contracts!` requires every element `is_a?(ProtocolContract)`.
38
+ # sig-gen gap: #2321 — same shape as `template_globs`: `validate_protocol_contracts!` requires every element
39
+ # `is_a?(ProtocolContract)`.
40
40
  def protocol_contracts: () -> Array[Rigor::Plugin::ProtocolContract]
41
41
  # ADR-32 WD6/WD12 — any object responding to `call`, and its result is a documented multi-shape
42
42
  # outcome (`String` / nil / `[:error, msg]` / `[:ok, src, msgs]`), not `String?` — `untyped` is the
43
43
  # honest claim until the outcome has a sig'd shape.
44
44
  def source_rbs_synthesizer: () -> untyped
45
- # sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from a parameter;
46
- # the validator (`validate_additional_initializers!`) requires every element
47
- # `is_a?(AdditionalInitializer)`, so the element type is hand-written.
45
+ # sig-gen gap: #2321 — same shape as `template_globs`: the validator (`validate_additional_initializers!`) requires
46
+ # every element `is_a?(AdditionalInitializer)`, so the element type is hand-written.
48
47
  def additional_initializers: () -> Array[Rigor::Plugin::AdditionalInitializer]
49
48
 
50
- # sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from a parameter
51
- # (`to_s`-normalized); `validate_effect_root!` bounds the spelling.
49
+ # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_root!` bounds the spelling.
52
50
  def effect_root: () -> String?
53
- # sig-gen gap: #1154 — `attr_reader` over an ivar normalized in `initialize` from a parameter;
54
- # `validate_effect_labels!` requires non-empty `String` elements.
51
+ # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_labels!` requires non-empty `String`
52
+ # elements.
55
53
  def effect_labels: () -> Array[String]
56
- # sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from a parameter;
57
- # `validate_effect_attributions!` requires every element `is_a?(EffectAttribution)`.
54
+ # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_attributions!` requires every element
55
+ # `is_a?(EffectAttribution)`.
58
56
  def effect_attributions: () -> Array[Rigor::Plugin::EffectAttribution]
59
- # sig-gen gap: #1154 — same shape; `validate_effect_edges!` requires `is_a?(EffectEdge)`.
57
+ # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_edges!` requires `is_a?(EffectEdge)`.
60
58
  def effect_edges: () -> Array[Rigor::Plugin::EffectEdge]
61
- # sig-gen gap: #1154 — same shape; `validate_effect_entry_points!` requires
59
+ # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_entry_points!` requires
62
60
  # `is_a?(EffectEntryPoints)`.
63
61
  def effect_entry_points: () -> Array[Rigor::Plugin::EffectEntryPoints]
64
- # sig-gen gap: #1154 — same shape; `validate_effect_ancestry!` requires `is_a?(EffectAncestry)`.
62
+ # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_ancestry!` requires `is_a?(EffectAncestry)`.
65
63
  def effect_ancestry: () -> Array[Rigor::Plugin::EffectAncestry]
66
64
 
67
65
  # The identity opening a root when this plugin's labels join the run's vocabulary: the
@@ -23,26 +23,27 @@ module Rigor
23
23
  def self.[]: (index: Integer, type_name: String) -> instance | (Integer index, String type_name) -> instance
24
24
  end
25
25
 
26
- # sig-gen gap: #1154 — `attr_reader` rows over ivars assigned in `initialize`; each is
27
- # validated/normalized first (`dup.freeze`/`to_sym`/truthiness collapse/coerce), so the
28
- # stored types are hand-written.
26
+ # sig-gen gap: #2321 — `attr_reader` rows over ivars `initialize` assigns from expressions derived
27
+ # from its parameters (`dup.freeze`/`to_sym`), so the stored types are hand-written.
29
28
  attr_reader path_glob: String
30
29
 
31
- # sig-gen gap: #1154 — as above (`to_sym` normalizes the accepted Symbol|String).
30
+ # sig-gen gap: #2321 — as above (`to_sym` normalizes the accepted Symbol|String).
32
31
  attr_reader method_name: Symbol
33
32
 
34
33
  # `singleton ? true : false` collapses any truthy input to bool — sig-gen already infers
35
- # `false | true`, so this row is generated-equivalent rather than a #1154 gap.
34
+ # `false | true`, so this row is generated-equivalent rather than a gap.
36
35
  attr_reader singleton: bool
37
36
 
38
- # sig-gen gap: #1154 — as above (`coerce_param_types` guarantees `Array[ParamType]`).
37
+ # sig-gen gap: #2312 — `initialize` stores what the private `coerce_param_types` helper returns, whose
38
+ # parameters are undeclared (it guarantees `Array[ParamType]`).
39
39
  attr_reader param_types: Array[ParamType]
40
40
 
41
- # sig-gen gap: #1154 — as above (nil or a non-empty `dup.freeze`d String).
41
+ # sig-gen gap: #2321 — as above (nil or a non-empty `dup.freeze`d String).
42
42
  attr_reader return_type_name: String?
43
43
 
44
- # sig-gen gap: #1154 — as above (`VALID_SEVERITIES.include?(to_sym)` bounds the stored value
45
- # to the three declared literals).
44
+ # sig-gen gap: #2321 — as above (`VALID_SEVERITIES.include?(to_sym)` bounds the stored value
45
+ # to the three declared literals; a derived-write credit would generate `Symbol`, not the literal union, so
46
+ # this row needs the declared literals kept as intent).
46
47
  attr_reader severity: :error | :warning | :info
47
48
 
48
49
  # `method_name`/`severity` accept String too (both are `to_sym`'d); `param_types` entries are
@@ -18,7 +18,7 @@ class Rigor::Plugin::Registry
18
18
 
19
19
  # Newly declared — the attr_reader was absent from the sig. `compile_aggregates` builds the ivar
20
20
  # with `flat_map` over the manifests (not from an `initialize` parameter, so this is unmarked
21
- # residue like the `rbs_complete_ancestors` sibling rather than a #1154 row); the element type is
21
+ # residue like the `rbs_complete_ancestors` sibling rather than a parameter-credit row); the element type is
22
22
  # `AdditionalInitializer`, enforced per manifest by `validate_additional_initializers!`.
23
23
  attr_reader additional_initializers: Array[Rigor::Plugin::AdditionalInitializer]
24
24