rail_verdict 1.0.0

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 (110) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/NOTICE +14 -0
  4. data/README.md +192 -0
  5. data/exe/railverdict +6 -0
  6. data/exe/railverdict-minitest-reporter.rb +90 -0
  7. data/lib/rail_verdict/analyzers/_shared.rb +54 -0
  8. data/lib/rail_verdict/analyzers/bundler_audit.rb +186 -0
  9. data/lib/rail_verdict/analyzers/minitest.rb +312 -0
  10. data/lib/rail_verdict/analyzers/rspec.rb +274 -0
  11. data/lib/rail_verdict/analyzers/rubocop.rb +289 -0
  12. data/lib/rail_verdict/analyzers/simplecov.rb +178 -0
  13. data/lib/rail_verdict/baseline.rb +151 -0
  14. data/lib/rail_verdict/check.rb +415 -0
  15. data/lib/rail_verdict/cli.rb +471 -0
  16. data/lib/rail_verdict/comparison.rb +216 -0
  17. data/lib/rail_verdict/configuration.rb +165 -0
  18. data/lib/rail_verdict/contracts/analyzer_result.rb +138 -0
  19. data/lib/rail_verdict/contracts/finding.rb +154 -0
  20. data/lib/rail_verdict/contracts/gate_result.rb +171 -0
  21. data/lib/rail_verdict/coverage/changed_line_evaluator.rb +70 -0
  22. data/lib/rail_verdict/doctor.rb +132 -0
  23. data/lib/rail_verdict/errors.rb +17 -0
  24. data/lib/rail_verdict/findings_command.rb +24 -0
  25. data/lib/rail_verdict/fingerprint.rb +72 -0
  26. data/lib/rail_verdict/git/command.rb +48 -0
  27. data/lib/rail_verdict/git/context.rb +361 -0
  28. data/lib/rail_verdict/git/diff_parser.rb +200 -0
  29. data/lib/rail_verdict/git/errors.rb +16 -0
  30. data/lib/rail_verdict/init.rb +38 -0
  31. data/lib/rail_verdict/intelligence/ai_analysis.rb +82 -0
  32. data/lib/rail_verdict/intelligence/ai_failure.rb +44 -0
  33. data/lib/rail_verdict/intelligence/budget.rb +36 -0
  34. data/lib/rail_verdict/intelligence/cache.rb +74 -0
  35. data/lib/rail_verdict/intelligence/context_builder.rb +92 -0
  36. data/lib/rail_verdict/intelligence/manifest.rb +70 -0
  37. data/lib/rail_verdict/intelligence/orchestrator.rb +77 -0
  38. data/lib/rail_verdict/intelligence/prompt.rb +28 -0
  39. data/lib/rail_verdict/intelligence/provider.rb +14 -0
  40. data/lib/rail_verdict/intelligence/providers/fake_provider.rb +31 -0
  41. data/lib/rail_verdict/intelligence/providers/openai_compat.rb +119 -0
  42. data/lib/rail_verdict/intelligence/redactor.rb +51 -0
  43. data/lib/rail_verdict/intelligence/secret_detector.rb +45 -0
  44. data/lib/rail_verdict/intelligence/source_reader.rb +49 -0
  45. data/lib/rail_verdict/intelligence.rb +11 -0
  46. data/lib/rail_verdict/mcp/cache.rb +233 -0
  47. data/lib/rail_verdict/mcp/repository_root.rb +31 -0
  48. data/lib/rail_verdict/mcp/serializers.rb +98 -0
  49. data/lib/rail_verdict/mcp/server.rb +110 -0
  50. data/lib/rail_verdict/mcp/tools/build_repair_packet.rb +85 -0
  51. data/lib/rail_verdict/mcp/tools/explain.rb +100 -0
  52. data/lib/rail_verdict/mcp/tools/get_finding.rb +139 -0
  53. data/lib/rail_verdict/mcp/tools/investigate.rb +107 -0
  54. data/lib/rail_verdict/mcp/tools/list_findings.rb +119 -0
  55. data/lib/rail_verdict/mcp/tools/verify.rb +137 -0
  56. data/lib/rail_verdict/mcp/tools/verify_repair.rb +105 -0
  57. data/lib/rail_verdict/mcp/validators.rb +81 -0
  58. data/lib/rail_verdict/mcp.rb +7 -0
  59. data/lib/rail_verdict/process_runner.rb +292 -0
  60. data/lib/rail_verdict/rails_context/classifier.rb +57 -0
  61. data/lib/rail_verdict/rails_context/confidence.rb +13 -0
  62. data/lib/rail_verdict/rails_context/constant_inferencer.rb +56 -0
  63. data/lib/rail_verdict/rails_context/context.rb +115 -0
  64. data/lib/rail_verdict/rails_context/detector.rb +141 -0
  65. data/lib/rail_verdict/rails_context/limits.rb +17 -0
  66. data/lib/rail_verdict/rails_context/resolvers/association_extractor.rb +48 -0
  67. data/lib/rail_verdict/rails_context/resolvers/policy_resolver.rb +45 -0
  68. data/lib/rail_verdict/rails_context/resolvers/route_resolver.rb +40 -0
  69. data/lib/rail_verdict/rails_context/resolvers/route_scanner.rb +55 -0
  70. data/lib/rail_verdict/rails_context/resolvers/schema_resolver.rb +90 -0
  71. data/lib/rail_verdict/rails_context/resolvers/test_candidates.rb +75 -0
  72. data/lib/rail_verdict/rails_context/resolvers/view_resolver.rb +45 -0
  73. data/lib/rail_verdict/rails_context/schema_parser.rb +50 -0
  74. data/lib/rail_verdict/rails_context.rb +21 -0
  75. data/lib/rail_verdict/repair/boundary.rb +36 -0
  76. data/lib/rail_verdict/repair/command.rb +89 -0
  77. data/lib/rail_verdict/repair/constraints.rb +31 -0
  78. data/lib/rail_verdict/repair/context_assembler.rb +301 -0
  79. data/lib/rail_verdict/repair/diff_context.rb +51 -0
  80. data/lib/rail_verdict/repair/packet.rb +158 -0
  81. data/lib/rail_verdict/repair/prompt_renderer.rb +27 -0
  82. data/lib/rail_verdict/repair/verification_plan.rb +45 -0
  83. data/lib/rail_verdict/repair/verifier.rb +84 -0
  84. data/lib/rail_verdict/reporters/console.rb +107 -0
  85. data/lib/rail_verdict/reporters/github_annotations.rb +104 -0
  86. data/lib/rail_verdict/reporters/json_reporter.rb +19 -0
  87. data/lib/rail_verdict/reporters/sarif.rb +138 -0
  88. data/lib/rail_verdict/run_context.rb +99 -0
  89. data/lib/rail_verdict/schema_validator.rb +85 -0
  90. data/lib/rail_verdict/strict_yaml.rb +134 -0
  91. data/lib/rail_verdict/verification/policy.rb +359 -0
  92. data/lib/rail_verdict/version.rb +5 -0
  93. data/lib/rail_verdict/waiver.rb +67 -0
  94. data/lib/rail_verdict/waiver_store.rb +59 -0
  95. data/lib/rail_verdict.rb +64 -0
  96. data/schemas/ai-analysis-v1.schema.json +54 -0
  97. data/schemas/baseline-v1.schema.json +108 -0
  98. data/schemas/configuration-v1.1.schema.json +150 -0
  99. data/schemas/configuration-v1.2.schema.json +182 -0
  100. data/schemas/configuration-v1.3.schema.json +198 -0
  101. data/schemas/configuration-v1.4.schema.json +146 -0
  102. data/schemas/configuration-v1.schema.json +72 -0
  103. data/schemas/coverage-v1.schema.json +51 -0
  104. data/schemas/finding-v1.schema.json +131 -0
  105. data/schemas/minitest-reporter-v1.schema.json +113 -0
  106. data/schemas/repair-packet-v1.schema.json +364 -0
  107. data/schemas/result-v1.schema.json +378 -0
  108. data/schemas/waiver-v1.schema.json +45 -0
  109. data/schemas/waivers-v1.schema.json +67 -0
  110. metadata +192 -0
@@ -0,0 +1,364 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://railverdict.dev/schemas/repair-packet/v1.schema.json",
4
+ "title": "RailVerdict RepairPacket v1",
5
+ "description": "Deterministic, bounded, machine-readable repair assignment. Deterministic evidence first; optional AI advisory separate. Never auto-edits source.",
6
+ "type": "object",
7
+ "required": [
8
+ "schema_version",
9
+ "packet_id",
10
+ "created_at",
11
+ "railverdict_version",
12
+ "source_revision",
13
+ "target",
14
+ "verification",
15
+ "evidence",
16
+ "git_context",
17
+ "rails_context",
18
+ "source_context",
19
+ "policy",
20
+ "baseline_state",
21
+ "waivers_state",
22
+ "verification_plan",
23
+ "constraints",
24
+ "completeness",
25
+ "success_criteria"
26
+ ],
27
+ "properties": {
28
+ "schema_version": { "const": "1.0" },
29
+ "packet_id": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
30
+ "created_at": { "type": "string", "format": "date-time" },
31
+ "railverdict_version": { "type": "string", "minLength": 1, "maxLength": 64 },
32
+ "source_revision": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
33
+ "base_revision": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
34
+ "merge_base": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
35
+ "target": { "$ref": "#/$defs/target" },
36
+ "verification": { "$ref": "#/$defs/verification" },
37
+ "evidence": { "$ref": "#/$defs/evidence" },
38
+ "git_context": { "$ref": "#/$defs/git_context" },
39
+ "diff_context": { "$ref": "#/$defs/diff_context" },
40
+ "rails_context": { "$ref": "#/$defs/rails_context" },
41
+ "source_context": { "$ref": "#/$defs/source_context" },
42
+ "policy": { "$ref": "#/$defs/policy" },
43
+ "baseline_state": { "$ref": "#/$defs/baseline_state" },
44
+ "waivers_state": { "$ref": "#/$defs/waivers_state" },
45
+ "ai_analysis": {
46
+ "anyOf": [
47
+ { "type": "null" },
48
+ { "type": "object" }
49
+ ]
50
+ },
51
+ "verification_plan": { "$ref": "#/$defs/verification_plan" },
52
+ "constraints": { "$ref": "#/$defs/constraints" },
53
+ "instructions": {
54
+ "type": "array",
55
+ "maxItems": 20,
56
+ "items": { "type": "string", "minLength": 1, "maxLength": 1024 }
57
+ },
58
+ "completeness": { "$ref": "#/$defs/completeness" },
59
+ "success_criteria": { "$ref": "#/$defs/success_criteria" },
60
+ "boundary": { "$ref": "#/$defs/boundary" }
61
+ },
62
+ "additionalProperties": false,
63
+ "unevaluatedProperties": false,
64
+ "$defs": {
65
+ "target": {
66
+ "type": "object",
67
+ "required": ["finding", "finding_state", "blocking", "severity"],
68
+ "properties": {
69
+ "finding": {
70
+ "type": "object",
71
+ "required": ["schema_version", "id", "fingerprint", "origin", "analyzer", "rule_id", "category", "severity", "confidence", "state", "evidence_ref", "location", "message"],
72
+ "properties": {
73
+ "schema_version": { "const": "1.0" },
74
+ "id": { "type": "string", "minLength": 1, "maxLength": 256 },
75
+ "fingerprint": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
76
+ "origin": { "enum": ["deterministic", "runtime", "ai", "custom"] },
77
+ "analyzer": { "type": "string", "minLength": 1, "maxLength": 256 },
78
+ "rule_id": { "type": "string", "minLength": 1, "maxLength": 256 },
79
+ "category": { "type": "string", "minLength": 1, "maxLength": 256 },
80
+ "severity": { "enum": ["info", "low", "medium", "high", "critical"] },
81
+ "confidence": { "enum": ["low", "medium", "high"] },
82
+ "state": { "enum": ["observed", "introduced", "existing", "resolved", "changed", "moved", "suppressed", "waived"] },
83
+ "evidence_ref": { "type": "string", "minLength": 1, "maxLength": 512 },
84
+ "location": {
85
+ "type": "object",
86
+ "required": ["path"],
87
+ "properties": {
88
+ "path": { "type": "string", "minLength": 1, "maxLength": 4096 },
89
+ "start_line": { "type": "integer", "minimum": 1 },
90
+ "end_line": { "type": "integer", "minimum": 1 }
91
+ },
92
+ "additionalProperties": false,
93
+ "unevaluatedProperties": false
94
+ },
95
+ "message": { "type": "string", "minLength": 1, "maxLength": 4096 }
96
+ },
97
+ "additionalProperties": false,
98
+ "unevaluatedProperties": false
99
+ },
100
+ "finding_state": { "enum": ["observed", "introduced", "existing", "changed", "moved", "waived"] },
101
+ "blocking": { "type": "boolean" },
102
+ "severity": { "enum": ["info", "low", "medium", "high", "critical"] }
103
+ },
104
+ "additionalProperties": false,
105
+ "unevaluatedProperties": false
106
+ },
107
+ "verification": {
108
+ "type": "object",
109
+ "required": ["gate", "policy_status", "mode", "decision_reasons", "comparison_counts"],
110
+ "properties": {
111
+ "gate": { "enum": ["PASS", "WARN", "FAIL", "INCOMPLETE"] },
112
+ "policy_status": { "enum": ["pass", "warn", "fail", "not_evaluated"] },
113
+ "mode": { "enum": ["advisory", "no_new_debt", "strict"] },
114
+ "decision_reasons": {
115
+ "type": "array",
116
+ "items": {
117
+ "type": "object",
118
+ "required": ["code", "message"],
119
+ "properties": {
120
+ "code": { "type": "string", "minLength": 1, "maxLength": 128 },
121
+ "message": { "type": "string", "minLength": 1, "maxLength": 4096 }
122
+ },
123
+ "additionalProperties": false,
124
+ "unevaluatedProperties": false
125
+ }
126
+ },
127
+ "comparison_counts": { "type": "object" }
128
+ },
129
+ "additionalProperties": false,
130
+ "unevaluatedProperties": false
131
+ },
132
+ "evidence": {
133
+ "type": "object",
134
+ "required": ["analyzer", "rule_id", "location", "message"],
135
+ "properties": {
136
+ "analyzer": { "type": "string", "minLength": 1, "maxLength": 256 },
137
+ "tool_version": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
138
+ "rule_id": { "type": "string", "minLength": 1, "maxLength": 256 },
139
+ "location": {
140
+ "type": "object",
141
+ "required": ["path"],
142
+ "properties": {
143
+ "path": { "type": "string", "minLength": 1, "maxLength": 4096 },
144
+ "start_line": { "type": "integer", "minimum": 1 },
145
+ "end_line": { "type": "integer", "minimum": 1 }
146
+ },
147
+ "additionalProperties": false,
148
+ "unevaluatedProperties": false
149
+ },
150
+ "message": { "type": "string", "minLength": 1, "maxLength": 4096 },
151
+ "evidence_summary": { "type": "object" }
152
+ },
153
+ "additionalProperties": false,
154
+ "unevaluatedProperties": false
155
+ },
156
+ "git_context": {
157
+ "type": "object",
158
+ "required": ["head", "base", "merge_base"],
159
+ "properties": {
160
+ "head": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
161
+ "base": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
162
+ "merge_base": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
163
+ "changed_file": {
164
+ "anyOf": [
165
+ { "type": "null" },
166
+ {
167
+ "type": "object",
168
+ "required": ["path", "status"],
169
+ "properties": {
170
+ "path": { "type": "string", "minLength": 1, "maxLength": 4096 },
171
+ "status": { "type": "string", "minLength": 1, "maxLength": 32 },
172
+ "score": { "type": ["integer", "null"] },
173
+ "old_path": { "type": ["string", "null"] },
174
+ "new_path": { "type": ["string", "null"] },
175
+ "binary": { "type": "boolean" }
176
+ },
177
+ "additionalProperties": false,
178
+ "unevaluatedProperties": false
179
+ }
180
+ ]
181
+ },
182
+ "changed_lines_for_target": {
183
+ "type": "array",
184
+ "items": { "type": "integer", "minimum": 1 }
185
+ },
186
+ "rename": {
187
+ "anyOf": [
188
+ { "type": "null" },
189
+ {
190
+ "type": "object",
191
+ "required": ["new_path", "old_path"],
192
+ "properties": {
193
+ "new_path": { "type": "string", "minLength": 1, "maxLength": 4096 },
194
+ "old_path": { "type": "string", "minLength": 1, "maxLength": 4096 }
195
+ },
196
+ "additionalProperties": false,
197
+ "unevaluatedProperties": false
198
+ }
199
+ ]
200
+ }
201
+ },
202
+ "additionalProperties": false,
203
+ "unevaluatedProperties": false
204
+ },
205
+ "diff_context": {
206
+ "type": "object",
207
+ "required": ["hunk", "truncated"],
208
+ "properties": {
209
+ "hunk": { "type": "string", "maxLength": 16384 },
210
+ "truncated": { "type": "boolean" }
211
+ },
212
+ "additionalProperties": false,
213
+ "unevaluatedProperties": false
214
+ },
215
+ "rails_context": {
216
+ "type": "object",
217
+ "required": ["detected", "entry", "related", "truncated"],
218
+ "properties": {
219
+ "detected": { "type": "object" },
220
+ "entry": { "anyOf": [{ "type": "null" }, { "type": "object" }] },
221
+ "related": {
222
+ "type": "array",
223
+ "maxItems": 20,
224
+ "items": { "type": "object" }
225
+ },
226
+ "truncated": { "type": "boolean" }
227
+ },
228
+ "additionalProperties": false,
229
+ "unevaluatedProperties": false
230
+ },
231
+ "source_context": {
232
+ "type": "object",
233
+ "required": ["snippets", "truncated"],
234
+ "properties": {
235
+ "snippets": {
236
+ "type": "array",
237
+ "maxItems": 3,
238
+ "items": {
239
+ "type": "object",
240
+ "required": ["path", "content", "truncated"],
241
+ "properties": {
242
+ "path": { "type": "string", "minLength": 1, "maxLength": 4096 },
243
+ "content": { "type": "string", "maxLength": 32768 },
244
+ "truncated": { "type": "boolean" }
245
+ },
246
+ "additionalProperties": false,
247
+ "unevaluatedProperties": false
248
+ }
249
+ },
250
+ "truncated": { "type": "boolean" }
251
+ },
252
+ "additionalProperties": false,
253
+ "unevaluatedProperties": false
254
+ },
255
+ "policy": {
256
+ "type": "object",
257
+ "required": ["mode", "configuration_digest"],
258
+ "properties": {
259
+ "mode": { "enum": ["advisory", "no_new_debt", "strict"] },
260
+ "configuration_digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
261
+ },
262
+ "additionalProperties": false,
263
+ "unevaluatedProperties": false
264
+ },
265
+ "baseline_state": {
266
+ "type": "object",
267
+ "required": ["loaded", "path", "digest"],
268
+ "properties": {
269
+ "loaded": { "type": "boolean" },
270
+ "path": { "type": ["string", "null"] },
271
+ "digest": { "type": ["string", "null"], "pattern": "^[0-9a-f]{64}$" }
272
+ },
273
+ "additionalProperties": false,
274
+ "unevaluatedProperties": false
275
+ },
276
+ "waivers_state": {
277
+ "type": "object",
278
+ "required": ["count", "path"],
279
+ "properties": {
280
+ "count": { "type": "integer", "minimum": 0 },
281
+ "path": { "type": ["string", "null"] },
282
+ "digest": { "type": ["string", "null"], "pattern": "^[0-9a-f]{64}$" }
283
+ },
284
+ "additionalProperties": false,
285
+ "unevaluatedProperties": false
286
+ },
287
+ "verification_plan": {
288
+ "type": "object",
289
+ "required": ["required", "suggested"],
290
+ "properties": {
291
+ "required": {
292
+ "type": "array",
293
+ "items": { "$ref": "#/$defs/command" }
294
+ },
295
+ "suggested": {
296
+ "type": "array",
297
+ "items": { "$ref": "#/$defs/command" }
298
+ }
299
+ },
300
+ "additionalProperties": false,
301
+ "unevaluatedProperties": false
302
+ },
303
+ "command": {
304
+ "type": "object",
305
+ "required": ["executable", "argv", "display"],
306
+ "properties": {
307
+ "executable": { "type": "string", "minLength": 1, "maxLength": 1024 },
308
+ "argv": { "type": "array", "items": { "type": "string", "maxLength": 4096 } },
309
+ "display": { "type": "string", "minLength": 1, "maxLength": 4096 }
310
+ },
311
+ "additionalProperties": false,
312
+ "unevaluatedProperties": false
313
+ },
314
+ "constraints": {
315
+ "type": "object",
316
+ "required": ["forbid_baseline_update", "forbid_waiver_creation", "forbid_policy_relaxation", "require_verification"],
317
+ "properties": {
318
+ "forbid_baseline_update": { "type": "boolean" },
319
+ "forbid_waiver_creation": { "type": "boolean" },
320
+ "forbid_policy_relaxation": { "type": "boolean" },
321
+ "require_verification": { "type": "boolean" }
322
+ },
323
+ "additionalProperties": false,
324
+ "unevaluatedProperties": false
325
+ },
326
+ "completeness": {
327
+ "type": "object",
328
+ "required": ["deterministic", "repair_context", "truncated"],
329
+ "properties": {
330
+ "deterministic": { "enum": ["complete"] },
331
+ "repair_context": { "enum": ["complete", "partial", "unavailable"] },
332
+ "truncated": { "type": "boolean" }
333
+ },
334
+ "additionalProperties": false,
335
+ "unevaluatedProperties": false
336
+ },
337
+ "success_criteria": {
338
+ "type": "object",
339
+ "required": ["description", "gate_must_be", "target_must_be_fixed", "completion_must_be", "boundary_must_be_unchanged"],
340
+ "properties": {
341
+ "description": { "type": "string", "minLength": 1, "maxLength": 4096 },
342
+ "gate_must_be": { "type": "array", "items": { "type": "string" } },
343
+ "target_must_be_fixed": { "type": "boolean" },
344
+ "completion_must_be": { "type": "string", "const": "complete" },
345
+ "boundary_must_be_unchanged": { "type": "boolean" }
346
+ },
347
+ "additionalProperties": false,
348
+ "unevaluatedProperties": false
349
+ },
350
+ "boundary": {
351
+ "type": "object",
352
+ "required": ["configuration_digest", "baseline_digest", "waivers_digest"],
353
+ "properties": {
354
+ "configuration_digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
355
+ "baseline_digest": { "type": ["string", "null"], "pattern": "^[0-9a-f]{64}$" },
356
+ "waivers_digest": { "type": ["string", "null"], "pattern": "^[0-9a-f]{64}$" },
357
+ "base_revision": { "type": ["string", "null"] },
358
+ "source_revision": { "type": ["string", "null"] }
359
+ },
360
+ "additionalProperties": false,
361
+ "unevaluatedProperties": false
362
+ }
363
+ }
364
+ }