rigortype 0.1.16 → 0.1.18

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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +18 -1
  4. data/lib/rigor/analysis/check_rules/rule_walk.rb +67 -0
  5. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +100 -0
  6. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +226 -0
  7. data/lib/rigor/analysis/check_rules.rb +180 -73
  8. data/lib/rigor/analysis/dependency_recorder.rb +122 -0
  9. data/lib/rigor/analysis/diagnostic.rb +18 -0
  10. data/lib/rigor/analysis/incremental.rb +162 -0
  11. data/lib/rigor/analysis/incremental_session.rb +337 -0
  12. data/lib/rigor/analysis/rule_catalog.rb +48 -0
  13. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +580 -0
  14. data/lib/rigor/analysis/runner/pool_coordinator.rb +569 -0
  15. data/lib/rigor/analysis/runner/project_pre_passes.rb +318 -0
  16. data/lib/rigor/analysis/runner/run_snapshots.rb +46 -0
  17. data/lib/rigor/analysis/runner.rb +477 -1110
  18. data/lib/rigor/analysis/self_call_resolution_recorder.rb +121 -0
  19. data/lib/rigor/analysis/worker_session.rb +47 -8
  20. data/lib/rigor/builtins/static_return_refinements.rb +7 -1
  21. data/lib/rigor/cache/descriptor.rb +50 -49
  22. data/lib/rigor/cache/incremental_snapshot.rb +153 -0
  23. data/lib/rigor/cache/rbs_cache_producer.rb +34 -0
  24. data/lib/rigor/cache/rbs_class_ancestor_table.rb +2 -8
  25. data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -8
  26. data/lib/rigor/cache/rbs_constant_table.rb +2 -8
  27. data/lib/rigor/cache/rbs_environment.rb +2 -8
  28. data/lib/rigor/cache/rbs_known_class_names.rb +2 -8
  29. data/lib/rigor/cache/store.rb +145 -14
  30. data/lib/rigor/cli/annotate_command.rb +2 -7
  31. data/lib/rigor/cli/baseline_command.rb +2 -7
  32. data/lib/rigor/cli/check_command.rb +705 -0
  33. data/lib/rigor/cli/ci_detector.rb +94 -0
  34. data/lib/rigor/cli/command.rb +47 -0
  35. data/lib/rigor/cli/coverage_command.rb +3 -23
  36. data/lib/rigor/cli/coverage_renderer.rb +3 -8
  37. data/lib/rigor/cli/diagnostic_formats.rb +345 -0
  38. data/lib/rigor/cli/diff_command.rb +3 -7
  39. data/lib/rigor/cli/explain_command.rb +2 -7
  40. data/lib/rigor/cli/lsp_command.rb +3 -7
  41. data/lib/rigor/cli/mcp_command.rb +3 -7
  42. data/lib/rigor/cli/options.rb +57 -0
  43. data/lib/rigor/cli/plugin_command.rb +3 -7
  44. data/lib/rigor/cli/plugins_command.rb +2 -7
  45. data/lib/rigor/cli/prism_colorizer.rb +10 -3
  46. data/lib/rigor/cli/renderable.rb +26 -0
  47. data/lib/rigor/cli/sig_gen_command.rb +2 -7
  48. data/lib/rigor/cli/skill_command.rb +3 -7
  49. data/lib/rigor/cli/trace_command.rb +143 -0
  50. data/lib/rigor/cli/trace_renderer.rb +310 -0
  51. data/lib/rigor/cli/triage_command.rb +2 -7
  52. data/lib/rigor/cli/type_of_command.rb +5 -38
  53. data/lib/rigor/cli/type_of_renderer.rb +4 -9
  54. data/lib/rigor/cli/type_scan_command.rb +3 -23
  55. data/lib/rigor/cli/type_scan_renderer.rb +4 -9
  56. data/lib/rigor/cli.rb +15 -532
  57. data/lib/rigor/configuration/dependencies.rb +18 -1
  58. data/lib/rigor/configuration/severity_profile.rb +22 -3
  59. data/lib/rigor/configuration.rb +16 -3
  60. data/lib/rigor/environment/rbs_loader.rb +129 -71
  61. data/lib/rigor/environment.rb +1 -1
  62. data/lib/rigor/inference/acceptance.rb +10 -0
  63. data/lib/rigor/inference/block_parameter_binder.rb +1 -2
  64. data/lib/rigor/inference/builtins/array_catalog.rb +2 -5
  65. data/lib/rigor/inference/builtins/comparable_catalog.rb +2 -5
  66. data/lib/rigor/inference/builtins/complex_catalog.rb +2 -5
  67. data/lib/rigor/inference/builtins/date_catalog.rb +2 -5
  68. data/lib/rigor/inference/builtins/encoding_catalog.rb +2 -5
  69. data/lib/rigor/inference/builtins/enumerable_catalog.rb +2 -5
  70. data/lib/rigor/inference/builtins/exception_catalog.rb +2 -5
  71. data/lib/rigor/inference/builtins/hash_catalog.rb +2 -5
  72. data/lib/rigor/inference/builtins/method_catalog.rb +15 -0
  73. data/lib/rigor/inference/builtins/numeric_catalog.rb +21 -93
  74. data/lib/rigor/inference/builtins/pathname_catalog.rb +2 -5
  75. data/lib/rigor/inference/builtins/proc_catalog.rb +2 -5
  76. data/lib/rigor/inference/builtins/random_catalog.rb +2 -5
  77. data/lib/rigor/inference/builtins/range_catalog.rb +2 -5
  78. data/lib/rigor/inference/builtins/rational_catalog.rb +2 -5
  79. data/lib/rigor/inference/builtins/re_catalog.rb +2 -5
  80. data/lib/rigor/inference/builtins/set_catalog.rb +2 -5
  81. data/lib/rigor/inference/builtins/string_catalog.rb +2 -5
  82. data/lib/rigor/inference/builtins/struct_catalog.rb +2 -5
  83. data/lib/rigor/inference/builtins/time_catalog.rb +2 -5
  84. data/lib/rigor/inference/expression_typer.rb +149 -63
  85. data/lib/rigor/inference/flow_tracer.rb +180 -0
  86. data/lib/rigor/inference/macro_block_self_type.rb +10 -11
  87. data/lib/rigor/inference/method_dispatcher/block_folding.rb +5 -1
  88. data/lib/rigor/inference/method_dispatcher/call_context.rb +65 -0
  89. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +11 -10
  90. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +12 -6
  91. data/lib/rigor/inference/method_dispatcher/data_folding.rb +246 -0
  92. data/lib/rigor/inference/method_dispatcher/file_folding.rb +6 -2
  93. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
  94. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +4 -1
  95. data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +4 -1
  96. data/lib/rigor/inference/method_dispatcher/math_folding.rb +6 -6
  97. data/lib/rigor/inference/method_dispatcher/method_folding.rb +12 -7
  98. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +33 -1
  99. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +23 -13
  100. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +9 -9
  101. data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -6
  102. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +120 -9
  103. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +12 -12
  104. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +49 -0
  105. data/lib/rigor/inference/method_dispatcher/time_folding.rb +6 -6
  106. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -9
  107. data/lib/rigor/inference/method_dispatcher.rb +185 -84
  108. data/lib/rigor/inference/narrowing.rb +262 -5
  109. data/lib/rigor/inference/scope_indexer.rb +208 -21
  110. data/lib/rigor/inference/statement_evaluator.rb +110 -48
  111. data/lib/rigor/language_server/buffer_resolution.rb +33 -0
  112. data/lib/rigor/language_server/completion_provider.rb +4 -4
  113. data/lib/rigor/language_server/document_symbol_provider.rb +4 -4
  114. data/lib/rigor/language_server/folding_range_provider.rb +4 -4
  115. data/lib/rigor/language_server/hover_provider.rb +4 -4
  116. data/lib/rigor/language_server/selection_range_provider.rb +4 -4
  117. data/lib/rigor/language_server/signature_help_provider.rb +4 -4
  118. data/lib/rigor/plugin/additional_initializer.rb +61 -38
  119. data/lib/rigor/plugin/base.rb +302 -45
  120. data/lib/rigor/plugin/node_rule_walk.rb +147 -0
  121. data/lib/rigor/plugin/registry.rb +281 -15
  122. data/lib/rigor/plugin.rb +1 -0
  123. data/lib/rigor/rbs_extended/conformance_checker.rb +293 -0
  124. data/lib/rigor/rbs_extended.rb +39 -0
  125. data/lib/rigor/scope/discovery_index.rb +58 -0
  126. data/lib/rigor/scope.rb +150 -167
  127. data/lib/rigor/sig_gen/observation_collector.rb +6 -6
  128. data/lib/rigor/source/literals.rb +14 -0
  129. data/lib/rigor/type/acceptance_router.rb +19 -0
  130. data/lib/rigor/type/accepts_result.rb +3 -10
  131. data/lib/rigor/type/app.rb +3 -7
  132. data/lib/rigor/type/bot.rb +2 -3
  133. data/lib/rigor/type/bound_method.rb +5 -12
  134. data/lib/rigor/type/combinator.rb +22 -0
  135. data/lib/rigor/type/constant.rb +2 -3
  136. data/lib/rigor/type/data_class.rb +80 -0
  137. data/lib/rigor/type/data_instance.rb +100 -0
  138. data/lib/rigor/type/difference.rb +5 -10
  139. data/lib/rigor/type/dynamic.rb +5 -10
  140. data/lib/rigor/type/hash_shape.rb +5 -15
  141. data/lib/rigor/type/integer_range.rb +5 -10
  142. data/lib/rigor/type/intersection.rb +5 -10
  143. data/lib/rigor/type/nominal.rb +5 -10
  144. data/lib/rigor/type/refined.rb +5 -10
  145. data/lib/rigor/type/singleton.rb +5 -10
  146. data/lib/rigor/type/top.rb +2 -3
  147. data/lib/rigor/type/tuple.rb +5 -10
  148. data/lib/rigor/type/union.rb +5 -10
  149. data/lib/rigor/type.rb +2 -0
  150. data/lib/rigor/value_semantics.rb +77 -0
  151. data/lib/rigor/version.rb +1 -1
  152. data/lib/rigor.rb +1 -1
  153. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -2
  154. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +2 -4
  155. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +70 -32
  156. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +3 -3
  157. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +15 -21
  158. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +1 -1
  159. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -2
  160. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +2 -2
  161. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +12 -2
  162. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +12 -2
  163. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +1 -1
  164. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +35 -18
  165. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +8 -29
  166. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +17 -1
  167. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +2 -2
  168. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +83 -36
  169. data/sig/rigor/cache.rbs +19 -0
  170. data/sig/rigor/environment.rbs +0 -2
  171. data/sig/rigor/inference.rbs +27 -0
  172. data/sig/rigor/plugin/base.rbs +1 -2
  173. data/sig/rigor/rbs_extended.rbs +2 -0
  174. data/sig/rigor/scope.rbs +42 -25
  175. data/sig/rigor/source.rbs +1 -0
  176. data/sig/rigor/type.rbs +58 -1
  177. data/sig/rigor.rbs +6 -1
  178. data/skills/rigor-ci-setup/SKILL.md +319 -0
  179. metadata +36 -2
  180. data/lib/rigor/cache/rbs_instance_definitions.rb +0 -79
@@ -0,0 +1,319 @@
1
+ ---
2
+ name: rigor-ci-setup
3
+ description: |
4
+ Wire Rigor type-checking into a project's CI pipeline: run it in its own isolated Ruby-4.0 job and surface diagnostics inline on the pull / merge request via a CI-native output format (SARIF, GitHub Actions annotations, GitLab Code Quality, Checkstyle, JUnit) or through reviewdog. Triggers: "add Rigor to CI", "run rigor in GitHub Actions / GitLab CI", "show Rigor errors on the PR", "set up reviewdog for rigor". NOT for first-time project configuration (use rigor-project-init to create `.rigor.yml` first) or reducing a baseline (use rigor-baseline-reduce).
5
+ license: MPL-2.0
6
+ metadata:
7
+ version: 0.1.0
8
+ homepage: https://github.com/rigortype/rigor
9
+ ---
10
+
11
+ # Rigor CI Setup
12
+
13
+ Wire Rigor into a project's CI so type diagnostics appear **inline on the
14
+ pull / merge request**, not just in the job log. This skill is for **users
15
+ running Rigor on their own project** with the published `rigor` executable —
16
+ Rigor is a tool, not a library, so it is **not** added to the project's
17
+ `Gemfile` (see [ADR-27](https://github.com/rigortype/rigor/blob/main/docs/adr/27-tool-distribution-model.md)).
18
+
19
+ If the project has no `.rigor.yml` yet, run the **rigor-project-init** skill
20
+ first — this skill assumes `rigor check` already runs locally.
21
+
22
+ ## The one hard rule: Rigor gets its own job
23
+
24
+ Rigor runs on **Ruby 4.0**. `ruby/setup-ruby` sets the *job's* active Ruby,
25
+ so a job that provisions the project's test Ruby (often 3.x, or a matrix)
26
+ **cannot** also provision Rigor's 4.0 — the second `setup-ruby` clobbers the
27
+ first. Always give Rigor a **separate job** (better: a separate workflow
28
+ file, for its own triggers, concurrency, and status badge). Every template
29
+ below does this.
30
+
31
+ ## Phase 0 — Detect the project's CI platform
32
+
33
+ **Inspect the repository first; do not ask what you can detect.** Look for
34
+ these markers from the project root and let them drive the platform choice:
35
+
36
+ | Marker (check existence) | Platform → template |
37
+ | --- | --- |
38
+ | `.github/workflows/` directory exists | **GitHub Actions** (Phase 2 GitHub templates) |
39
+ | `.gitlab-ci.yml` exists | **GitLab CI** (Phase 2 GitLab template) |
40
+ | `.circleci/config.yml` exists | **CircleCI** (generic recipe, `junit`) |
41
+ | `Jenkinsfile` exists | **Jenkins** (generic recipe, `junit` / `checkstyle`) |
42
+ | `bitbucket-pipelines.yml` / `azure-pipelines.yml` / `.drone.yml` | that platform (generic recipe) |
43
+ | none of the above | no CI yet — **ask** the user which platform they use |
44
+
45
+ Concretely (the agent has file tools — use them):
46
+
47
+ - List `.github/workflows/*.yml` and `.gitlab-ci.yml`. **If
48
+ `.github/workflows/rigor.yml` already exists, read it** — this is an
49
+ *update*, not a fresh add: preserve the user's triggers / pinning and only
50
+ change the format / steps that are wrong or missing. The same applies to
51
+ an existing `rigor` job inside `.gitlab-ci.yml`.
52
+ - Check for an existing pin: `.github/rigor/Gemfile` (+ lockfile) means the
53
+ project already pins Rigor — keep it (Phase 4).
54
+ - Check for `.rigor-baseline.yml` — if present, the project is in baseline
55
+ adoption mode, which changes the gate advice (Phase 5).
56
+ - Grep existing CI files for `reviewdog` — if already used, prefer the
57
+ reviewdog path (Phase 3) for consistency.
58
+
59
+ **Routing:** exactly one platform marker → use it, state what you found, and
60
+ proceed. Multiple (e.g. both `.github/workflows/` and `.gitlab-ci.yml`) →
61
+ tell the user both were found and ask which to wire (or do both). None → ask.
62
+
63
+ ## Phase 1 — Pick the surface (what the reviewer should see)
64
+
65
+ With the platform from Phase 0, pick the matching `--format` (confirm with
66
+ the user only when the platform offers more than one good surface). All
67
+ formats are pure renderings of the same diagnostics; the exit code is
68
+ unchanged (`0` clean, `1` on errors), so the job still gates.
69
+
70
+ | Platform / goal | `--format` | How it surfaces |
71
+ | --- | --- | --- |
72
+ | **GitHub — the default** | `github` | `::error file=…::` workflow commands → inline PR-diff annotations. No upload, no permissions, works on **every** repo. |
73
+ | GitHub — Security tab + persistent/deduped alerts | `sarif` | SARIF 2.1.0 via `upload-sarif`. **Requires code scanning** (see note) + `security-events: write`. |
74
+ | GitHub/GitLab/Gerrit/Bitbucket/Gitea — PR/MR **review comments** | `checkstyle` (or `sarif`) piped to **reviewdog** | reviewdog posts comments. See Phase 3. |
75
+ | GitLab — MR Code Quality widget | `gitlab` | Code Quality JSON published as a `codequality` report artifact. |
76
+ | Any test-report CI (CircleCI, Jenkins, …) | `junit` | JUnit XML; every diagnostic is a `testcase` failure. |
77
+
78
+ **The GitHub default is `github` (annotations).** It is the one path that
79
+ works on every repository with zero setup — no upload step, no extra
80
+ permissions, no paid features — so lead with it unless the user asks for
81
+ more. (It is also what PHPStan recommends for GitHub Actions.)
82
+
83
+ In fact, on GitHub Actions and TeamCity Rigor **auto-detects the CI and
84
+ emits the native annotations even without `--format`** (it augments the
85
+ default text output; ADR-51 WD7). So the simplest GitHub setup is the
86
+ minimal workflow — plain `rigor check`, no `--format` — and you still get
87
+ inline annotations. Pass `--format github` only when you want *just* the
88
+ annotation stream (e.g. piping elsewhere); use `--no-ci-detect` to turn the
89
+ augmentation off. Upgrade beyond annotations only when there is a concrete
90
+ reason:
91
+
92
+ - **`sarif`** *only when code scanning is available* — i.e. a **public**
93
+ repo (free) or a **private** repo with **GitHub Advanced Security /
94
+ Code Security** enabled. Without it, `upload-sarif` fails with
95
+ *"GitHub Advanced Security must be enabled for this repository"*. When
96
+ available it adds the Security tab, deduped + persistent alerts, and PR
97
+ alerts. If you cannot tell whether the repo is public or has GHAS, **do
98
+ not default to SARIF** — use `github`, and offer SARIF as an option to a
99
+ public-repo / GHAS user.
100
+ - **reviewdog** when the team wants threaded **review comments** filtered to
101
+ the changed lines (works on private repos; needs a token, Phase 3).
102
+
103
+ GitHub annotation caveat: the run UI shows only a limited number of
104
+ annotations per type, so on a first adoption of a large codebase prefer the
105
+ baseline gate (Phase 5) or SARIF/reviewdog, which page through everything.
106
+
107
+ Other platforms: **Code Quality** (`gitlab`) on GitLab; `junit` on the
108
+ test-report CIs.
109
+
110
+ ## Phase 2 — Drop in the workflow
111
+
112
+ Pick **one** template, copy it into the project, and adjust nothing but the
113
+ trigger if asked. Pin the version later (Phase 4).
114
+
115
+ ### GitHub — inline annotations (no setup) — the default
116
+
117
+ ```yaml
118
+ # .github/workflows/rigor.yml
119
+ name: rigor
120
+ on: [push, pull_request]
121
+ jobs:
122
+ rigor:
123
+ runs-on: ubuntu-latest
124
+ steps:
125
+ - uses: actions/checkout@v4
126
+ - uses: ruby/setup-ruby@v1
127
+ with:
128
+ ruby-version: "4.0"
129
+ - run: gem install rigortype
130
+ - run: rigor check --format github
131
+ ```
132
+
133
+ ### GitHub — SARIF → code scanning
134
+
135
+ Use this **only if code scanning is available** for the repo — a public repo
136
+ (free), or a private repo with GitHub Advanced Security / Code Security.
137
+ Otherwise `upload-sarif` fails; use the annotations template above.
138
+
139
+ ```yaml
140
+ # .github/workflows/rigor.yml
141
+ name: rigor
142
+ on: [push, pull_request]
143
+ permissions:
144
+ contents: read
145
+ security-events: write # required by upload-sarif
146
+ jobs:
147
+ rigor:
148
+ runs-on: ubuntu-latest
149
+ steps:
150
+ - uses: actions/checkout@v4
151
+ - uses: ruby/setup-ruby@v1
152
+ with:
153
+ ruby-version: "4.0"
154
+ - run: gem install rigortype
155
+ - run: rigor check --format sarif > rigor.sarif
156
+ continue-on-error: true # so a non-zero exit still uploads
157
+ - uses: github/codeql-action/upload-sarif@v3
158
+ if: always()
159
+ with:
160
+ sarif_file: rigor.sarif
161
+ ```
162
+
163
+ ### GitLab — Code Quality widget
164
+
165
+ ```yaml
166
+ # .gitlab-ci.yml
167
+ rigor:
168
+ image: ruby:4.0
169
+ script:
170
+ - gem install rigortype
171
+ - rigor check --format gitlab > gl-code-quality-report.json
172
+ artifacts:
173
+ reports:
174
+ codequality: gl-code-quality-report.json
175
+ when: always
176
+ ```
177
+
178
+ `--format gitlab` emits exactly the
179
+ [Code Quality report format](https://docs.gitlab.com/ci/testing/code_quality/)
180
+ GitLab requires: each finding carries `description`, `check_name`,
181
+ `fingerprint` (a stable SHA-256, so a finding keeps its identity across
182
+ runs), `severity` (`major`/`minor`/`info`), and `location.path` +
183
+ `location.lines.begin`. Paths are repo-relative with no `./` prefix and the
184
+ JSON has no BOM, both of which GitLab demands. For the MR widget to show a
185
+ *diff* of new vs resolved findings, the report must exist on **both** the
186
+ target (default) branch and the MR branch — the job above runs on each
187
+ pipeline, which satisfies that automatically once it has run once on the
188
+ default branch. (Note: a long-standing GitLab display bug can hide
189
+ `check_name`; Rigor already folds the rule id into `description` as
190
+ `… [rule]`, so the identifier shows regardless.)
191
+
192
+ ### Other runners (generic)
193
+
194
+ Provision Ruby 4.0, `gem install rigortype`, then
195
+ `rigor check --format junit > junit.xml` (or `checkstyle`, `json`) and
196
+ publish the file with whatever artifact mechanism the platform offers.
197
+
198
+ ## Phase 3 — reviewdog (inline review comments)
199
+
200
+ [reviewdog](https://github.com/reviewdog/reviewdog) turns Rigor's output
201
+ into PR/MR review comments. It reads Rigor's `checkstyle` (preferred — light,
202
+ no code scanning) or `sarif`, so the format is the same everywhere — **but
203
+ the `-reporter` is platform-specific, so it must match the platform you
204
+ detected in Phase 0.** Pick the reporter first, then the token/env it needs:
205
+
206
+ | Phase 0 platform | `-reporter` | Token / env | Other needs |
207
+ | --- | --- | --- | --- |
208
+ | GitHub | `github-pr-review` (threaded comments) · `github-pr-check` (Check run) · `github-pr-annotations` | `REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}` | `permissions: pull-requests: write` |
209
+ | GitLab | `gitlab-mr-discussion` (threaded) · `gitlab-mr-commit` | `REVIEWDOG_GITLAB_API_TOKEN` (a project/personal token) + `CI_API_V4_URL` | runs on MR pipelines |
210
+ | Gerrit / Bitbucket / Gitea | `gerrit-change-review` · `bitbucket-code-report` · `gitea-pr-review` | the platform's token var (see reviewdog README) | — |
211
+
212
+ There is **no cross-platform reviewdog reporter** — `github-*` posts only to
213
+ GitHub, `gitlab-*` only to GitLab. So a reviewdog setup is always tied to one
214
+ platform; if a project targets two (e.g. a GitHub mirror of a GitLab repo),
215
+ wire one reviewdog job per platform, or use the platform-native format
216
+ (`sarif` / `gitlab`) on each.
217
+
218
+ Install reviewdog with
219
+ [`reviewdog/action-setup`](https://github.com/reviewdog/action-setup) (GitHub)
220
+ or `go install` / the binary (GitLab and others).
221
+
222
+ **GitHub** (`.github/workflows/rigor.yml`):
223
+
224
+ ```yaml
225
+ name: rigor
226
+ on: [pull_request]
227
+ permissions:
228
+ contents: read
229
+ pull-requests: write # required for github-pr-review
230
+ jobs:
231
+ rigor:
232
+ runs-on: ubuntu-latest
233
+ steps:
234
+ - uses: actions/checkout@v4
235
+ - uses: ruby/setup-ruby@v1
236
+ with:
237
+ ruby-version: "4.0"
238
+ - run: gem install rigortype
239
+ - uses: reviewdog/action-setup@v1
240
+ with:
241
+ reviewdog_version: latest
242
+ - run: rigor check --format checkstyle | reviewdog -f=checkstyle -reporter=github-pr-review -fail-level=error
243
+ env:
244
+ REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
245
+ ```
246
+
247
+ **GitLab** (`.gitlab-ci.yml`) — install the reviewdog binary, then pipe:
248
+
249
+ ```yaml
250
+ rigor:
251
+ image: ruby:4.0
252
+ rules:
253
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
254
+ variables:
255
+ REVIEWDOG_GITLAB_API_TOKEN: $RIGOR_REVIEWDOG_TOKEN # a CI/CD variable you set
256
+ script:
257
+ - gem install rigortype
258
+ - wget -O - -q https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s -- -b /usr/local/bin
259
+ - rigor check --format checkstyle | reviewdog -f=checkstyle -reporter=gitlab-mr-discussion -fail-level=error
260
+ ```
261
+
262
+ Knobs (both platforms):
263
+
264
+ - **`-fail-level`** — `error` fails the step only on Rigor errors (matches
265
+ Rigor's exit code); `any` fails on warnings too; `none` is comment-only.
266
+ Default `error`.
267
+ - **`-filter-mode`** — reviewdog's default `added` comments only on lines
268
+ the PR/MR changed; `nofilter` comments on everything. Keep `added` to adopt
269
+ on an existing codebase (the reviewdog analogue of Rigor's baseline).
270
+ - **`checkstyle` vs `sarif`** — both work (`-f=checkstyle` / `-f=sarif`);
271
+ prefer `checkstyle` (lighter, no code scanning). Use `sarif` only if the
272
+ job *also* uploads to the GitHub Security tab and wants a single format.
273
+
274
+ ## Phase 4 — Pin Rigor's version (reproducible CI)
275
+
276
+ The templates install the latest `rigortype` at run time. To pin it:
277
+
278
+ - **CI-only `Gemfile` (recommended, Dependabot-updatable).** Commit
279
+ `.github/rigor/Gemfile` (`source "https://rubygems.org"` +
280
+ `gem "rigortype", "~> 0.1"`) and its lockfile, set
281
+ `env: BUNDLE_GEMFILE: .github/rigor/Gemfile` on the Rigor job, use
282
+ `ruby/setup-ruby` with `bundler-cache: true`, and run `bundle exec rigor
283
+ check …`. Add a Dependabot `bundler` entry scoped to `/.github/rigor`.
284
+ This file is read only by the Rigor job — it never enters the project's
285
+ resolution.
286
+ - **Pinned `gem install`.** `gem install rigortype -v "X.Y.Z"`. Simple, but
287
+ Dependabot can't see it (manual updates).
288
+
289
+ ## Phase 5 — Gate behaviour (optional, with the user)
290
+
291
+ - **Baseline adoption.** If the project uses `.rigor-baseline.yml`
292
+ (rigor-project-init / rigor-baseline-reduce), the same `rigor check`
293
+ honours it — CI fails only on *new* diagnostics. Add `--baseline-strict`
294
+ to also fail when the baseline has drifted loose (a CI gate that forces
295
+ regeneration). With reviewdog, `-filter-mode=added` plays the analogous
296
+ role for review comments.
297
+ - **Determinism.** Add `--no-cache` in CI if you want each run independent
298
+ of any persisted `.rigor/cache`.
299
+
300
+ ## Verify
301
+
302
+ 1. The Rigor job runs on `ruby-version: "4.0"` in its own job (not merged
303
+ into a test matrix job).
304
+ 2. On a PR that introduces a type error, the finding appears inline (an
305
+ annotation / review comment / widget entry, per the chosen surface) and
306
+ the job fails (exit 1).
307
+ 3. On a clean PR the job passes (exit 0).
308
+
309
+ ## References
310
+
311
+ - Manual: `rigor`'s CI chapter — `docs/manual/11-ci.md` in the repo, or
312
+ <https://github.com/rigortype/rigor/blob/main/docs/manual/11-ci.md>. The
313
+ copy-paste template files live at `docs/manual/ci-templates/`.
314
+ - [ADR-51](https://github.com/rigortype/rigor/blob/main/docs/adr/51-ci-diagnostic-output-formats.md)
315
+ — the output-format surface (the severity / identifier contract).
316
+ - [ADR-27](https://github.com/rigortype/rigor/blob/main/docs/adr/27-tool-distribution-model.md)
317
+ — why Rigor installs standalone and runs in its own job.
318
+ - [reviewdog](https://github.com/reviewdog/reviewdog) /
319
+ [action-setup](https://github.com/reviewdog/action-setup).
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rigortype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.16
4
+ version: 0.1.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rigor contributors
@@ -289,6 +289,10 @@ files:
289
289
  - lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb
290
290
  - lib/rigor/analysis/check_rules/dead_assignment_collector.rb
291
291
  - lib/rigor/analysis/check_rules/ivar_write_collector.rb
292
+ - lib/rigor/analysis/check_rules/rule_walk.rb
293
+ - lib/rigor/analysis/check_rules/self_closedness_scanner.rb
294
+ - lib/rigor/analysis/check_rules/unreachable_clause_collector.rb
295
+ - lib/rigor/analysis/dependency_recorder.rb
292
296
  - lib/rigor/analysis/dependency_source_inference.rb
293
297
  - lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb
294
298
  - lib/rigor/analysis/dependency_source_inference/builder.rb
@@ -299,11 +303,18 @@ files:
299
303
  - lib/rigor/analysis/diagnostic.rb
300
304
  - lib/rigor/analysis/erb_template_detector.rb
301
305
  - lib/rigor/analysis/fact_store.rb
306
+ - lib/rigor/analysis/incremental.rb
307
+ - lib/rigor/analysis/incremental_session.rb
302
308
  - lib/rigor/analysis/project_scan.rb
303
309
  - lib/rigor/analysis/result.rb
304
310
  - lib/rigor/analysis/rule_catalog.rb
305
311
  - lib/rigor/analysis/run_stats.rb
306
312
  - lib/rigor/analysis/runner.rb
313
+ - lib/rigor/analysis/runner/diagnostic_aggregator.rb
314
+ - lib/rigor/analysis/runner/pool_coordinator.rb
315
+ - lib/rigor/analysis/runner/project_pre_passes.rb
316
+ - lib/rigor/analysis/runner/run_snapshots.rb
317
+ - lib/rigor/analysis/self_call_resolution_recorder.rb
307
318
  - lib/rigor/analysis/worker_session.rb
308
319
  - lib/rigor/ast.rb
309
320
  - lib/rigor/ast/type_node.rb
@@ -312,31 +323,40 @@ files:
312
323
  - lib/rigor/builtins/regex_refinement.rb
313
324
  - lib/rigor/builtins/static_return_refinements.rb
314
325
  - lib/rigor/cache/descriptor.rb
326
+ - lib/rigor/cache/incremental_snapshot.rb
327
+ - lib/rigor/cache/rbs_cache_producer.rb
315
328
  - lib/rigor/cache/rbs_class_ancestor_table.rb
316
329
  - lib/rigor/cache/rbs_class_type_param_names.rb
317
330
  - lib/rigor/cache/rbs_constant_table.rb
318
331
  - lib/rigor/cache/rbs_descriptor.rb
319
332
  - lib/rigor/cache/rbs_environment.rb
320
333
  - lib/rigor/cache/rbs_environment_marshal_patch.rb
321
- - lib/rigor/cache/rbs_instance_definitions.rb
322
334
  - lib/rigor/cache/rbs_known_class_names.rb
323
335
  - lib/rigor/cache/store.rb
324
336
  - lib/rigor/cli.rb
325
337
  - lib/rigor/cli/annotate_command.rb
326
338
  - lib/rigor/cli/baseline_command.rb
339
+ - lib/rigor/cli/check_command.rb
340
+ - lib/rigor/cli/ci_detector.rb
341
+ - lib/rigor/cli/command.rb
327
342
  - lib/rigor/cli/coverage_command.rb
328
343
  - lib/rigor/cli/coverage_renderer.rb
329
344
  - lib/rigor/cli/coverage_report.rb
345
+ - lib/rigor/cli/diagnostic_formats.rb
330
346
  - lib/rigor/cli/diff_command.rb
331
347
  - lib/rigor/cli/explain_command.rb
332
348
  - lib/rigor/cli/lsp_command.rb
333
349
  - lib/rigor/cli/mcp_command.rb
350
+ - lib/rigor/cli/options.rb
334
351
  - lib/rigor/cli/plugin_command.rb
335
352
  - lib/rigor/cli/plugins_command.rb
336
353
  - lib/rigor/cli/plugins_renderer.rb
337
354
  - lib/rigor/cli/prism_colorizer.rb
355
+ - lib/rigor/cli/renderable.rb
338
356
  - lib/rigor/cli/sig_gen_command.rb
339
357
  - lib/rigor/cli/skill_command.rb
358
+ - lib/rigor/cli/trace_command.rb
359
+ - lib/rigor/cli/trace_renderer.rb
340
360
  - lib/rigor/cli/triage_command.rb
341
361
  - lib/rigor/cli/triage_renderer.rb
342
362
  - lib/rigor/cli/type_of_command.rb
@@ -393,6 +413,7 @@ files:
393
413
  - lib/rigor/inference/expression_typer.rb
394
414
  - lib/rigor/inference/fallback.rb
395
415
  - lib/rigor/inference/fallback_tracer.rb
416
+ - lib/rigor/inference/flow_tracer.rb
396
417
  - lib/rigor/inference/hkt_body.rb
397
418
  - lib/rigor/inference/hkt_body_parser.rb
398
419
  - lib/rigor/inference/hkt_reducer.rb
@@ -401,8 +422,10 @@ files:
401
422
  - lib/rigor/inference/macro_block_self_type.rb
402
423
  - lib/rigor/inference/method_dispatcher.rb
403
424
  - lib/rigor/inference/method_dispatcher/block_folding.rb
425
+ - lib/rigor/inference/method_dispatcher/call_context.rb
404
426
  - lib/rigor/inference/method_dispatcher/cgi_folding.rb
405
427
  - lib/rigor/inference/method_dispatcher/constant_folding.rb
428
+ - lib/rigor/inference/method_dispatcher/data_folding.rb
406
429
  - lib/rigor/inference/method_dispatcher/file_folding.rb
407
430
  - lib/rigor/inference/method_dispatcher/iterator_dispatch.rb
408
431
  - lib/rigor/inference/method_dispatcher/kernel_dispatch.rb
@@ -416,6 +439,7 @@ files:
416
439
  - lib/rigor/inference/method_dispatcher/set_folding.rb
417
440
  - lib/rigor/inference/method_dispatcher/shape_dispatch.rb
418
441
  - lib/rigor/inference/method_dispatcher/shellwords_folding.rb
442
+ - lib/rigor/inference/method_dispatcher/singleton_folding.rb
419
443
  - lib/rigor/inference/method_dispatcher/time_folding.rb
420
444
  - lib/rigor/inference/method_dispatcher/uri_folding.rb
421
445
  - lib/rigor/inference/method_parameter_binder.rb
@@ -432,6 +456,7 @@ files:
432
456
  - lib/rigor/inference/synthetic_method_index.rb
433
457
  - lib/rigor/inference/synthetic_method_scanner.rb
434
458
  - lib/rigor/language_server.rb
459
+ - lib/rigor/language_server/buffer_resolution.rb
435
460
  - lib/rigor/language_server/buffer_table.rb
436
461
  - lib/rigor/language_server/completion_provider.rb
437
462
  - lib/rigor/language_server/debouncer.rb
@@ -470,6 +495,7 @@ files:
470
495
  - lib/rigor/plugin/macro/trait_registry.rb
471
496
  - lib/rigor/plugin/manifest.rb
472
497
  - lib/rigor/plugin/node_context.rb
498
+ - lib/rigor/plugin/node_rule_walk.rb
473
499
  - lib/rigor/plugin/protocol_contract.rb
474
500
  - lib/rigor/plugin/registry.rb
475
501
  - lib/rigor/plugin/services.rb
@@ -477,10 +503,12 @@ files:
477
503
  - lib/rigor/plugin/trust_policy.rb
478
504
  - lib/rigor/plugin/type_node_resolver.rb
479
505
  - lib/rigor/rbs_extended.rb
506
+ - lib/rigor/rbs_extended/conformance_checker.rb
480
507
  - lib/rigor/rbs_extended/hkt_directives.rb
481
508
  - lib/rigor/rbs_extended/reporter.rb
482
509
  - lib/rigor/reflection.rb
483
510
  - lib/rigor/scope.rb
511
+ - lib/rigor/scope/discovery_index.rb
484
512
  - lib/rigor/sig_gen.rb
485
513
  - lib/rigor/sig_gen/classification.rb
486
514
  - lib/rigor/sig_gen/generator.rb
@@ -503,12 +531,15 @@ files:
503
531
  - lib/rigor/triage/hint.rb
504
532
  - lib/rigor/trinary.rb
505
533
  - lib/rigor/type.rb
534
+ - lib/rigor/type/acceptance_router.rb
506
535
  - lib/rigor/type/accepts_result.rb
507
536
  - lib/rigor/type/app.rb
508
537
  - lib/rigor/type/bot.rb
509
538
  - lib/rigor/type/bound_method.rb
510
539
  - lib/rigor/type/combinator.rb
511
540
  - lib/rigor/type/constant.rb
541
+ - lib/rigor/type/data_class.rb
542
+ - lib/rigor/type/data_instance.rb
512
543
  - lib/rigor/type/difference.rb
513
544
  - lib/rigor/type/dynamic.rb
514
545
  - lib/rigor/type/hash_shape.rb
@@ -530,6 +561,7 @@ files:
530
561
  - lib/rigor/type_node/string_literal.rb
531
562
  - lib/rigor/type_node/symbol_literal.rb
532
563
  - lib/rigor/type_node/union.rb
564
+ - lib/rigor/value_semantics.rb
533
565
  - lib/rigor/version.rb
534
566
  - plugins/rigor-actioncable/lib/rigor-actioncable.rb
535
567
  - plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb
@@ -662,6 +694,7 @@ files:
662
694
  - sig/rigor/analysis/dependency_source_inference/index.rbs
663
695
  - sig/rigor/analysis/fact_store.rbs
664
696
  - sig/rigor/ast.rbs
697
+ - sig/rigor/cache.rbs
665
698
  - sig/rigor/cli/diff_command.rbs
666
699
  - sig/rigor/cli/explain_command.rbs
667
700
  - sig/rigor/cli/sig_gen_command.rbs
@@ -694,6 +727,7 @@ files:
694
727
  - skills/rigor-baseline-reduce/SKILL.md
695
728
  - skills/rigor-baseline-reduce/references/01-classify.md
696
729
  - skills/rigor-baseline-reduce/references/02-fix-or-suppress.md
730
+ - skills/rigor-ci-setup/SKILL.md
697
731
  - skills/rigor-plugin-author/SKILL.md
698
732
  - skills/rigor-plugin-author/references/01-plan-and-scaffold.md
699
733
  - skills/rigor-plugin-author/references/02-walker-and-types.md
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "rbs_descriptor"
4
- require_relative "rbs_environment_marshal_patch"
5
-
6
- module Rigor
7
- module Cache
8
- # Cache producer that materialises the full
9
- # `Hash<String, RBS::Definition>` for instance-side class
10
- # definitions in the RBS environment, in a single cache
11
- # entry. Mirrors the {RbsConstantTable} layout.
12
- #
13
- # ADR-7 § "Slice 6-D" carry-over and dogfooding feedback:
14
- # the earlier per-class cache layout (one entry per class,
15
- # ~1300 files) made warm runs *slower* than `--no-cache`
16
- # because each `instance_definition` call paid disk-open +
17
- # `Marshal.load` overhead and the in-memory
18
- # `RBS::DefinitionBuilder.build_instance` was actually fast
19
- # given a cached `RBS::Environment`. The single-blob layout
20
- # collapses that to one `Marshal.load` per process; warm runs
21
- # now match `--no-cache` timing while preserving the
22
- # cross-process invalidation story.
23
- #
24
- # Marshal-cleanness of `RBS::Definition` is enabled by the
25
- # v0.0.9 C2 `RBS::Location` patch.
26
- class RbsInstanceDefinitions
27
- PRODUCER_ID = "rbs.instance_definitions"
28
-
29
- # @param loader [Rigor::Environment::RbsLoader]
30
- # @param store [Rigor::Cache::Store]
31
- # @return [Hash{String => RBS::Definition}]
32
- def self.fetch(loader:, store:)
33
- descriptor = RbsDescriptor.build(loader)
34
- store.fetch_or_compute(producer_id: PRODUCER_ID, params: {}, descriptor: descriptor) do
35
- compute(loader)
36
- end
37
- end
38
-
39
- def self.compute(loader)
40
- table = {}
41
- loader.each_known_class_name do |name|
42
- definition = loader.uncached_instance_definition(name)
43
- table[name] = definition if definition
44
- end
45
- table
46
- end
47
-
48
- private_class_method :compute
49
- end
50
-
51
- # Singleton-side equivalent of {RbsInstanceDefinitions}.
52
- # Caches the full `Hash<String, RBS::Definition>` for the
53
- # singleton class of every RBS-known class.
54
- class RbsSingletonDefinitions
55
- PRODUCER_ID = "rbs.singleton_definitions"
56
-
57
- # @param loader [Rigor::Environment::RbsLoader]
58
- # @param store [Rigor::Cache::Store]
59
- # @return [Hash{String => RBS::Definition}]
60
- def self.fetch(loader:, store:)
61
- descriptor = RbsDescriptor.build(loader)
62
- store.fetch_or_compute(producer_id: PRODUCER_ID, params: {}, descriptor: descriptor) do
63
- compute(loader)
64
- end
65
- end
66
-
67
- def self.compute(loader)
68
- table = {}
69
- loader.each_known_class_name do |name|
70
- definition = loader.uncached_singleton_definition(name)
71
- table[name] = definition if definition
72
- end
73
- table
74
- end
75
-
76
- private_class_method :compute
77
- end
78
- end
79
- end