necropsy 0.2.0 → 0.3.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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/MEASUREMENTS.md +27 -0
  4. data/README.md +182 -17
  5. data/bench/README.md +92 -0
  6. data/bench/audit.rb +113 -0
  7. data/bench/audits/0.2.1/audit.json +501 -0
  8. data/bench/audits/0.2.1/audit.md +55 -0
  9. data/bench/audits/0.2.1/baseline_performance.yml +16 -0
  10. data/bench/audits/0.2.1/config.yml +42 -0
  11. data/bench/audits/0.2.1/review.yml +56 -0
  12. data/bench/audits/0.2.1/review_queue.yml +3651 -0
  13. data/bench/corpora/v1/README.md +30 -0
  14. data/bench/corpora/v1/labels.yml +37 -0
  15. data/bench/corpora/v1/manifest.yml +63 -0
  16. data/bench/corpora/v1/rubocop.necropsy.yml +7 -0
  17. data/bench/corpora/v1/self.necropsy.yml +8 -0
  18. data/bench/corpora/v1/tools/debride.yml +42 -0
  19. data/bench/corpora/v1/tools/spoom.yml +12 -0
  20. data/bench/corpora/v1/tools/type_aware.yml +11 -0
  21. data/bench/golden/v1/candidate_union.json +21918 -0
  22. data/bench/golden/v1/metadata.json +12 -0
  23. data/bench/golden/v1/reports/dynamic_evidence.json +146 -0
  24. data/bench/golden/v1/reports/plain_ruby.json +135 -0
  25. data/bench/golden/v1/reports/rails.json +176 -0
  26. data/bench/golden/v1/reports/rubocop_1_75_0.json +26848 -0
  27. data/bench/golden/v1/reports/self.json +3449 -0
  28. data/bench/review_queue.rb +35 -0
  29. data/bench/run.rb +31 -0
  30. data/bench/schema/candidate-union-v1.schema.json +70 -0
  31. data/docs/impv_implementation_matrix.md +179 -0
  32. data/docs/migrations/0.2.1.md +57 -0
  33. data/docs/migrations/0.3.0.md +207 -0
  34. data/docs/migrations/0.4.0.md +13 -0
  35. data/docs/necropsy_performance_adr.md +43 -0
  36. data/docs/necropsy_scope_decisions.md +58 -0
  37. data/docs/necropsy_type_facts_adr.md +22 -0
  38. data/gemfiles/prism_min.gemfile +9 -0
  39. data/gemfiles/prism_min.gemfile.lock +50 -0
  40. data/lib/necropsy/analyzer.rb +121 -2
  41. data/lib/necropsy/analyzers/dynamic/coverage_collector.rb +69 -17
  42. data/lib/necropsy/analyzers/dynamic/coverage_importer.rb +99 -9
  43. data/lib/necropsy/analyzers/dynamic/coverband_importer.rb +69 -299
  44. data/lib/necropsy/analyzers/dynamic/coverband_payload_set.rb +149 -0
  45. data/lib/necropsy/analyzers/dynamic/observation_policy.rb +96 -0
  46. data/lib/necropsy/analyzers/dynamic/redis_input_limits.rb +121 -0
  47. data/lib/necropsy/analyzers/dynamic/redis_nonblocking_io.rb +94 -0
  48. data/lib/necropsy/analyzers/dynamic/redis_payload_loader.rb +165 -0
  49. data/lib/necropsy/analyzers/dynamic/redis_transport.rb +217 -0
  50. data/lib/necropsy/analyzers/dynamic/runtime_reference.rb +96 -0
  51. data/lib/necropsy/analyzers/dynamic/trace_point_collector.rb +133 -23
  52. data/lib/necropsy/analyzers/dynamic/trace_point_importer.rb +3 -1
  53. data/lib/necropsy/analyzers/legacy_result_adapter.rb +226 -0
  54. data/lib/necropsy/analyzers/static/cha.rb +33 -73
  55. data/lib/necropsy/analyzers/static/name_resolution.rb +133 -12
  56. data/lib/necropsy/analyzers/static/rta.rb +237 -29
  57. data/lib/necropsy/ast_scanner/call_recording.rb +149 -30
  58. data/lib/necropsy/ast_scanner/call_site_creation.rb +54 -0
  59. data/lib/necropsy/ast_scanner/definition_creation.rb +43 -0
  60. data/lib/necropsy/ast_scanner/dsl_macros.rb +431 -41
  61. data/lib/necropsy/ast_scanner/method_definitions.rb +232 -50
  62. data/lib/necropsy/ast_scanner/references.rb +43 -9
  63. data/lib/necropsy/ast_scanner/ruby_semantics.rb +101 -15
  64. data/lib/necropsy/ast_scanner/traversal.rb +234 -71
  65. data/lib/necropsy/ast_scanner/value_definitions.rb +23 -13
  66. data/lib/necropsy/ast_scanner.rb +67 -6
  67. data/lib/necropsy/bench/candidate_union.rb +555 -0
  68. data/lib/necropsy/bench/claim_gate.rb +112 -0
  69. data/lib/necropsy/bench/evaluator.rb +329 -16
  70. data/lib/necropsy/bench/finding_facts.rb +152 -0
  71. data/lib/necropsy/bench/precision_gate.rb +144 -0
  72. data/lib/necropsy/bench/release_audit/adversarial_runner.rb +56 -0
  73. data/lib/necropsy/bench/release_audit/artifact_writer.rb +112 -0
  74. data/lib/necropsy/bench/release_audit/config_validator.rb +112 -0
  75. data/lib/necropsy/bench/release_audit/git_snapshot.rb +36 -0
  76. data/lib/necropsy/bench/release_audit/performance_gate.rb +165 -0
  77. data/lib/necropsy/bench/release_audit/run_provenance.rb +133 -0
  78. data/lib/necropsy/bench/release_audit.rb +360 -0
  79. data/lib/necropsy/bench/report_normalizer.rb +140 -0
  80. data/lib/necropsy/bench/review_queue.rb +154 -0
  81. data/lib/necropsy/bench/safety_mutation_harness.rb +59 -0
  82. data/lib/necropsy/bench/seed_runner.rb +408 -0
  83. data/lib/necropsy/bounded_canonicalizer.rb +218 -0
  84. data/lib/necropsy/cache/scan_cache.rb +85 -17
  85. data/lib/necropsy/call_site_identity.rb +54 -0
  86. data/lib/necropsy/cli.rb +220 -33
  87. data/lib/necropsy/clock.rb +40 -0
  88. data/lib/necropsy/confidence/scorer.rb +103 -58
  89. data/lib/necropsy/configuration.rb +224 -21
  90. data/lib/necropsy/convention_rules.rb +138 -0
  91. data/lib/necropsy/definition_identity/canonical_digest.rb +278 -0
  92. data/lib/necropsy/definition_identity.rb +37 -0
  93. data/lib/necropsy/diagnostics.rb +176 -36
  94. data/lib/necropsy/embedded_ruby.rb +55 -0
  95. data/lib/necropsy/entry_points/plain.rb +111 -10
  96. data/lib/necropsy/entry_points/rails.rb +322 -41
  97. data/lib/necropsy/entry_points/test.rb +6 -1
  98. data/lib/necropsy/flow_interpreter.rb +460 -0
  99. data/lib/necropsy/graph/blocker_matching.rb +338 -0
  100. data/lib/necropsy/graph/call_graph.rb +1099 -109
  101. data/lib/necropsy/graph/definition_index.rb +149 -0
  102. data/lib/necropsy/graph/dynamic_evidence_tracking.rb +206 -0
  103. data/lib/necropsy/graph/evidence_store.rb +213 -0
  104. data/lib/necropsy/graph/resolution_store.rb +497 -0
  105. data/lib/necropsy/graph_self_check.rb +79 -0
  106. data/lib/necropsy/guardrail/baseline.rb +350 -13
  107. data/lib/necropsy/guardrail/quarantine.rb +94 -9
  108. data/lib/necropsy/load_graph.rb +206 -0
  109. data/lib/necropsy/models.rb +878 -13
  110. data/lib/necropsy/performance_profiler.rb +108 -0
  111. data/lib/necropsy/project.rb +327 -25
  112. data/lib/necropsy/reachability/engine.rb +54 -13
  113. data/lib/necropsy/reference_barrier.rb +458 -0
  114. data/lib/necropsy/report.rb +113 -4
  115. data/lib/necropsy/reporter.rb +431 -15
  116. data/lib/necropsy/runner.rb +233 -18
  117. data/lib/necropsy/runtime_feedback.rb +136 -0
  118. data/lib/necropsy/semantics_matrix.rb +153 -0
  119. data/lib/necropsy/type_facts.rb +53 -0
  120. data/lib/necropsy/version.rb +1 -1
  121. data/lib/necropsy/why_not_explanation.rb +436 -0
  122. data/lib/necropsy/why_not_renderer.rb +197 -0
  123. data/lib/necropsy/world_policy.rb +90 -0
  124. data/lib/necropsy.rb +35 -2
  125. data/schema/necropsy-report-v2.schema.json +366 -0
  126. metadata +85 -1
@@ -0,0 +1,501 @@
1
+ {
2
+ "schema_version": 1,
3
+ "release": "0.2.1",
4
+ "baseline": {
5
+ "git_ref": "d0168e881120320d28dc2f42e10f9947330fdcb7",
6
+ "reports_path": "bench/golden/v1/reports",
7
+ "reason": "d0168e881120320d28dc2f42e10f9947330fdcb7 is the first commit with the bounded evidence identity path and artifact-independent production scopes for all five required corpora."
8
+ },
9
+ "corpora": {
10
+ "dynamic_evidence": {
11
+ "baseline_metrics": {
12
+ "analysis_graph": {
13
+ "scope": "analysis",
14
+ "nodes": 6,
15
+ "definitions": 5,
16
+ "call_sites": 4,
17
+ "edges": 2
18
+ },
19
+ "findings": 4,
20
+ "actionable_candidates": 4,
21
+ "candidate_loc": 12,
22
+ "diagnostic_findings": 0
23
+ },
24
+ "current_metrics": {
25
+ "analysis_graph": {
26
+ "scope": "analysis",
27
+ "nodes": 6,
28
+ "definitions": 5,
29
+ "call_sites": 4,
30
+ "edges": 2
31
+ },
32
+ "findings": 4,
33
+ "actionable_candidates": 4,
34
+ "candidate_loc": 12,
35
+ "diagnostic_findings": 0
36
+ },
37
+ "added": [],
38
+ "removed": [],
39
+ "state_changed": [],
40
+ "confidence_changed": []
41
+ },
42
+ "plain_ruby": {
43
+ "baseline_metrics": {
44
+ "analysis_graph": {
45
+ "scope": "analysis",
46
+ "nodes": 8,
47
+ "definitions": 6,
48
+ "call_sites": 7,
49
+ "edges": 3
50
+ },
51
+ "findings": 3,
52
+ "actionable_candidates": 0,
53
+ "candidate_loc": 0,
54
+ "diagnostic_findings": 3
55
+ },
56
+ "current_metrics": {
57
+ "analysis_graph": {
58
+ "scope": "analysis",
59
+ "nodes": 8,
60
+ "definitions": 6,
61
+ "call_sites": 7,
62
+ "edges": 3
63
+ },
64
+ "findings": 3,
65
+ "actionable_candidates": 0,
66
+ "candidate_loc": 0,
67
+ "diagnostic_findings": 3
68
+ },
69
+ "added": [],
70
+ "removed": [],
71
+ "state_changed": [],
72
+ "confidence_changed": []
73
+ },
74
+ "rails": {
75
+ "baseline_metrics": {
76
+ "analysis_graph": {
77
+ "scope": "analysis",
78
+ "nodes": 32,
79
+ "definitions": 23,
80
+ "call_sites": 49,
81
+ "edges": 17
82
+ },
83
+ "findings": 4,
84
+ "actionable_candidates": 3,
85
+ "candidate_loc": 7,
86
+ "diagnostic_findings": 1
87
+ },
88
+ "current_metrics": {
89
+ "analysis_graph": {
90
+ "scope": "analysis",
91
+ "nodes": 32,
92
+ "definitions": 23,
93
+ "call_sites": 49,
94
+ "edges": 17
95
+ },
96
+ "findings": 4,
97
+ "actionable_candidates": 3,
98
+ "candidate_loc": 7,
99
+ "diagnostic_findings": 1
100
+ },
101
+ "added": [],
102
+ "removed": [],
103
+ "state_changed": [],
104
+ "confidence_changed": []
105
+ },
106
+ "rubocop_1_75_0": {
107
+ "baseline_metrics": {
108
+ "analysis_graph": {
109
+ "scope": "analysis",
110
+ "nodes": 1223,
111
+ "definitions": 1122,
112
+ "call_sites": 6199,
113
+ "edges": 1946
114
+ },
115
+ "findings": 1122,
116
+ "actionable_candidates": 547,
117
+ "candidate_loc": 3632,
118
+ "diagnostic_findings": 575
119
+ },
120
+ "current_metrics": {
121
+ "analysis_graph": {
122
+ "scope": "analysis",
123
+ "nodes": 1223,
124
+ "definitions": 1122,
125
+ "call_sites": 6199,
126
+ "edges": 1946
127
+ },
128
+ "findings": 1122,
129
+ "actionable_candidates": 547,
130
+ "candidate_loc": 3632,
131
+ "diagnostic_findings": 575
132
+ },
133
+ "added": [],
134
+ "removed": [],
135
+ "state_changed": [],
136
+ "confidence_changed": []
137
+ },
138
+ "self": {
139
+ "baseline_metrics": {
140
+ "analysis_graph": {
141
+ "scope": "analysis",
142
+ "nodes": 1975,
143
+ "definitions": 1886,
144
+ "call_sites": 15170,
145
+ "edges": 15283
146
+ },
147
+ "findings": 145,
148
+ "actionable_candidates": 82,
149
+ "candidate_loc": 621,
150
+ "diagnostic_findings": 63
151
+ },
152
+ "current_metrics": {
153
+ "analysis_graph": {
154
+ "scope": "analysis",
155
+ "nodes": 1993,
156
+ "definitions": 1902,
157
+ "call_sites": 15348,
158
+ "edges": 15519
159
+ },
160
+ "findings": 147,
161
+ "actionable_candidates": 82,
162
+ "candidate_loc": 622,
163
+ "diagnostic_findings": 65
164
+ },
165
+ "added": [
166
+ {
167
+ "id": "Necropsy::Bench::ReviewQueue#validate_options!",
168
+ "definition_id": "def:v1:0ae44a8f731da2b338b26914945b6a338b41d5eee6622efac32e93f38e10494f",
169
+ "identity": "def:v1:0ae44a8f731da2b338b26914945b6a338b41d5eee6622efac32e93f38e10494f",
170
+ "after": {
171
+ "id": "Necropsy::Bench::ReviewQueue#validate_options!",
172
+ "definition_id": "def:v1:0ae44a8f731da2b338b26914945b6a338b41d5eee6622efac32e93f38e10494f",
173
+ "path": "lib/necropsy/bench/review_queue.rb",
174
+ "line": 54,
175
+ "end_line": 57,
176
+ "loc": 4,
177
+ "state": "unreachable",
178
+ "confidence": "low",
179
+ "candidate": true,
180
+ "diagnostic": false,
181
+ "category": "unreachable",
182
+ "unknown": false,
183
+ "rule_hits": [],
184
+ "risk_flags": [],
185
+ "blocker_kinds": [],
186
+ "reasons": [
187
+ "Lowered because this node is near unresolved metaprogramming."
188
+ ]
189
+ }
190
+ },
191
+ {
192
+ "id": "Necropsy::Bench::ReviewQueue#initialize",
193
+ "definition_id": "def:v1:8bbd2d0801726c9c679a6d4936dc427c01c6b9f9ebf5dfb24c69c0185f2b90c8",
194
+ "identity": "def:v1:8bbd2d0801726c9c679a6d4936dc427c01c6b9f9ebf5dfb24c69c0185f2b90c8",
195
+ "after": {
196
+ "id": "Necropsy::Bench::ReviewQueue#initialize",
197
+ "definition_id": "def:v1:8bbd2d0801726c9c679a6d4936dc427c01c6b9f9ebf5dfb24c69c0185f2b90c8",
198
+ "path": "lib/necropsy/bench/review_queue.rb",
199
+ "line": 17,
200
+ "end_line": 24,
201
+ "loc": 8,
202
+ "state": "blocked",
203
+ "confidence": "low",
204
+ "candidate": false,
205
+ "diagnostic": true,
206
+ "category": "unknown_dispatch",
207
+ "unknown": true,
208
+ "rule_hits": [],
209
+ "risk_flags": [
210
+ "analysis_incomplete",
211
+ "public_or_protected_visibility"
212
+ ],
213
+ "blocker_kinds": [
214
+ "partial_dispatch",
215
+ "unknown_dispatch"
216
+ ],
217
+ "reasons": [
218
+ "Blocked by 552 unresolved runtime dispatches.",
219
+ "Lowered because this node is near unresolved metaprogramming."
220
+ ]
221
+ }
222
+ }
223
+ ],
224
+ "removed": [],
225
+ "state_changed": [
226
+ {
227
+ "id": "Necropsy::Bench::FindingFacts#actionable?",
228
+ "definition_id": "def:v1:2493c12409215905a9578963febb90a105e39e32b71558d9453813098d80f6c8",
229
+ "identity": "def:v1:2493c12409215905a9578963febb90a105e39e32b71558d9453813098d80f6c8",
230
+ "before": {
231
+ "id": "Necropsy::Bench::FindingFacts#actionable?",
232
+ "definition_id": "def:v1:2493c12409215905a9578963febb90a105e39e32b71558d9453813098d80f6c8",
233
+ "path": "lib/necropsy/bench/finding_facts.rb",
234
+ "line": 21,
235
+ "end_line": 23,
236
+ "loc": 3,
237
+ "state": "unreachable",
238
+ "confidence": "low",
239
+ "candidate": true,
240
+ "diagnostic": false,
241
+ "category": "unreachable",
242
+ "unknown": false,
243
+ "rule_hits": [],
244
+ "risk_flags": [],
245
+ "blocker_kinds": [],
246
+ "reasons": [
247
+ "Lowered because this node is near unresolved metaprogramming."
248
+ ]
249
+ },
250
+ "after": {
251
+ "id": "Necropsy::Bench::FindingFacts#actionable?",
252
+ "definition_id": "def:v1:2493c12409215905a9578963febb90a105e39e32b71558d9453813098d80f6c8",
253
+ "path": "lib/necropsy/bench/finding_facts.rb",
254
+ "line": 21,
255
+ "end_line": 23,
256
+ "loc": 3,
257
+ "state": "blocked",
258
+ "confidence": "low",
259
+ "candidate": false,
260
+ "diagnostic": true,
261
+ "category": "partial_dispatch",
262
+ "unknown": true,
263
+ "rule_hits": [],
264
+ "risk_flags": [
265
+ "analysis_incomplete"
266
+ ],
267
+ "blocker_kinds": [
268
+ "partial_dispatch"
269
+ ],
270
+ "reasons": [
271
+ "Blocked by 1 unresolved runtime dispatch.",
272
+ "Lowered because this node is near unresolved metaprogramming."
273
+ ]
274
+ }
275
+ }
276
+ ],
277
+ "confidence_changed": []
278
+ }
279
+ },
280
+ "new_high_candidates": [],
281
+ "review": {
282
+ "required": [],
283
+ "completed": [],
284
+ "missing": [],
285
+ "invalid": [],
286
+ "coverage": {
287
+ "rails": {
288
+ "strategy": "all",
289
+ "changes": 0,
290
+ "required": 0,
291
+ "completed": 0,
292
+ "zero_difference": true
293
+ },
294
+ "rubocop_1_75_0": {
295
+ "strategy": "stratified",
296
+ "changes": 0,
297
+ "required": 0,
298
+ "completed": 0,
299
+ "zero_difference": true
300
+ }
301
+ },
302
+ "confirmed_false_positives": []
303
+ },
304
+ "performance": {
305
+ "dynamic_evidence": {
306
+ "available": true,
307
+ "baseline_wall_time_seconds": 0.3476,
308
+ "current_wall_time_seconds": 0.146051,
309
+ "wall_time_limit_seconds": 1.0,
310
+ "baseline_rss_kb": 57728,
311
+ "current_rss_kb": 57696,
312
+ "rss_limit_kb": 123264,
313
+ "rss_kind": "current_process_rss_after_corpus",
314
+ "rss_scope": "benchmark_runner_process",
315
+ "passed": true
316
+ },
317
+ "plain_ruby": {
318
+ "available": true,
319
+ "baseline_wall_time_seconds": 0.381025,
320
+ "current_wall_time_seconds": 0.122945,
321
+ "wall_time_limit_seconds": 1.0,
322
+ "baseline_rss_kb": 59360,
323
+ "current_rss_kb": 62944,
324
+ "rss_limit_kb": 124896,
325
+ "rss_kind": "current_process_rss_after_corpus",
326
+ "rss_scope": "benchmark_runner_process",
327
+ "passed": true
328
+ },
329
+ "rails": {
330
+ "available": true,
331
+ "baseline_wall_time_seconds": 0.369907,
332
+ "current_wall_time_seconds": 0.149768,
333
+ "wall_time_limit_seconds": 1.119907,
334
+ "baseline_rss_kb": 63168,
335
+ "current_rss_kb": 65904,
336
+ "rss_limit_kb": 128704,
337
+ "rss_kind": "current_process_rss_after_corpus",
338
+ "rss_scope": "benchmark_runner_process",
339
+ "passed": true
340
+ },
341
+ "rubocop_1_75_0": {
342
+ "available": true,
343
+ "baseline_wall_time_seconds": 5.559264,
344
+ "current_wall_time_seconds": 5.50558,
345
+ "wall_time_limit_seconds": 8.338896,
346
+ "baseline_rss_kb": 349136,
347
+ "current_rss_kb": 355920,
348
+ "rss_limit_kb": 436420,
349
+ "rss_kind": "current_process_rss_after_corpus",
350
+ "rss_scope": "benchmark_runner_process",
351
+ "passed": true
352
+ },
353
+ "self": {
354
+ "available": true,
355
+ "baseline_wall_time_seconds": 22.508282,
356
+ "current_wall_time_seconds": 24.104173,
357
+ "wall_time_limit_seconds": 30.0,
358
+ "baseline_rss_kb": 1136080,
359
+ "current_rss_kb": 1175248,
360
+ "rss_limit_kb": 1300000,
361
+ "rss_kind": "current_process_rss_after_corpus",
362
+ "rss_scope": "benchmark_runner_process",
363
+ "passed": true
364
+ }
365
+ },
366
+ "precision_gate": {
367
+ "schema_version": 1,
368
+ "enforced": false,
369
+ "compatibility": "releases before 0.4 retain the safety-only release policy",
370
+ "passed": true
371
+ },
372
+ "claim_gate": {
373
+ "schema_version": 1,
374
+ "enforced": false,
375
+ "passed": true
376
+ },
377
+ "performance_provenance": {
378
+ "baseline": {
379
+ "schema_version": 1,
380
+ "captured_at": "2026-08-08T18:10:00+09:00",
381
+ "git_ref": "d0168e881120320d28dc2f42e10f9947330fdcb7",
382
+ "environment": {
383
+ "ruby": "ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]",
384
+ "os": "macOS 26.3 (25D125), Darwin 25.3.0 arm64",
385
+ "command": "NECROPSY_RUBOCOP_CORPUS=/private/tmp/necropsy-rubocop-1.75.0 bundle exec ruby bench/run.rb",
386
+ "execution": "clean worktree; escalated run so ps-based RSS measurement was available",
387
+ "rss_kind": "current_process_rss_after_corpus",
388
+ "rss_scope": "benchmark_runner_process"
389
+ }
390
+ },
391
+ "current": {
392
+ "schema_version": 1,
393
+ "git_ref": "9698ce9551f0df9a18fa09bfc0020d880fd89dc4",
394
+ "clean": true,
395
+ "manifest_sha256": "228a46b3c73635b420d5135b4b2d485e38e827fd0ae33bf5c07bf1da2ef831ac",
396
+ "audit_config_sha256": "b19a243d918b663419e7e5a671733ef41eb061ddc52eaf75658996ba3607e91e",
397
+ "environment": {
398
+ "ruby": "ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]",
399
+ "os": "macOS 26.3 (25D125), Darwin 25.3.0 arm64",
400
+ "command": "NECROPSY_RUBOCOP_CORPUS=/private/tmp/necropsy-rubocop-1.75.0 bundle exec ruby bench/run.rb",
401
+ "rss_kind": "current_process_rss_after_corpus",
402
+ "rss_scope": "benchmark_runner_process"
403
+ },
404
+ "artifacts": {
405
+ "reports/dynamic_evidence.json": "bd82a2b9fb2fae3777d81743917f2df59744798c5f58747219565436134de7ed",
406
+ "reports/plain_ruby.json": "fc939ec706e35ada3c59428856b9f8408ffc3f7468265a3c322c26c65c138169",
407
+ "reports/rails.json": "c0d2195364260ff955ae933acfb57d4e3e9697185e619d79635f70ca0f4b01fb",
408
+ "reports/rubocop_1_75_0.json": "48a136417c6b5802282720cad1f9a608a709b7a8b6e712de2ae228edd79413b5",
409
+ "reports/self.json": "dab9b43f2e78c3b35075768b953bec8a2cb79d3625bc0ad9d71005d1c3950fab",
410
+ "summary.json": "81d2e80f04dd9618ca1aaff27707a0818ec235d083dacf13c185d063eb103d5d"
411
+ }
412
+ }
413
+ },
414
+ "adversarial_suites": [
415
+ {
416
+ "name": "ambiguity",
417
+ "command": [
418
+ "bundle",
419
+ "exec",
420
+ "rspec",
421
+ "spec/necropsy/safety_invariants_spec.rb",
422
+ "spec/necropsy/reflective_blocker_visibility_spec.rb"
423
+ ],
424
+ "passed": true,
425
+ "exit_status": 0,
426
+ "duration_seconds": 0.554484,
427
+ "summary": "17 examples, 0 failures"
428
+ },
429
+ {
430
+ "name": "dynamic",
431
+ "command": [
432
+ "bundle",
433
+ "exec",
434
+ "rspec",
435
+ "spec/necropsy/analyzers/dynamic/coverage_importer_spec.rb",
436
+ "spec/necropsy/confidence/scorer_spec.rb"
437
+ ],
438
+ "passed": true,
439
+ "exit_status": 0,
440
+ "duration_seconds": 0.446656,
441
+ "summary": "24 examples, 0 failures"
442
+ },
443
+ {
444
+ "name": "parse",
445
+ "command": [
446
+ "bundle",
447
+ "exec",
448
+ "rspec",
449
+ "spec/necropsy/parse_incompleteness_spec.rb"
450
+ ],
451
+ "passed": true,
452
+ "exit_status": 0,
453
+ "duration_seconds": 0.468912,
454
+ "summary": "10 examples, 0 failures"
455
+ },
456
+ {
457
+ "name": "remote_input",
458
+ "command": [
459
+ "bundle",
460
+ "exec",
461
+ "rspec",
462
+ "spec/necropsy/analyzers/dynamic/coverband_importer_spec.rb"
463
+ ],
464
+ "passed": true,
465
+ "exit_status": 0,
466
+ "duration_seconds": 0.759857,
467
+ "summary": "28 examples, 0 failures"
468
+ }
469
+ ],
470
+ "gates": {
471
+ "new_high_reviewed": {
472
+ "passed": true,
473
+ "failures": 0
474
+ },
475
+ "new_high_false_positives": {
476
+ "passed": true,
477
+ "failures": 0
478
+ },
479
+ "new_high_unresolved": {
480
+ "passed": true,
481
+ "failures": 0
482
+ },
483
+ "difference_review": {
484
+ "passed": true,
485
+ "failures": 0
486
+ },
487
+ "review_false_positives": {
488
+ "passed": true,
489
+ "failures": 0
490
+ },
491
+ "performance": {
492
+ "passed": true,
493
+ "failures": 0
494
+ },
495
+ "adversarial": {
496
+ "passed": true,
497
+ "failures": 0
498
+ }
499
+ },
500
+ "status": "pass"
501
+ }
@@ -0,0 +1,55 @@
1
+ # 0.2.1 safety release audit
2
+
3
+ Status: **PASS**
4
+
5
+ Baseline: `d0168e881120320d28dc2f42e10f9947330fdcb7` — d0168e881120320d28dc2f42e10f9947330fdcb7 is the first commit with the bounded evidence identity path and artifact-independent production scopes for all five required corpora.
6
+
7
+ ## Candidate changes
8
+
9
+ | corpus | baseline | current | added | removed | state changed | newly high |
10
+ |---|---:|---:|---:|---:|---:|---:|
11
+ | dynamic_evidence | 4 | 4 | 0 | 0 | 0 | 0 |
12
+ | plain_ruby | 3 | 3 | 0 | 0 | 0 | 0 |
13
+ | rails | 4 | 4 | 0 | 0 | 0 | 0 |
14
+ | rubocop_1_75_0 | 1122 | 1122 | 0 | 0 | 0 | 0 |
15
+ | self | 145 | 147 | 2 | 0 | 1 | 0 |
16
+
17
+ ## Difference review
18
+
19
+ | corpus | strategy | changes | required | completed | zero difference |
20
+ |---|---|---:|---:|---:|:---:|
21
+ | rails | all | 0 | 0 | 0 | yes |
22
+ | rubocop_1_75_0 | stratified | 0 | 0 | 0 | yes |
23
+
24
+ ## Performance
25
+
26
+ | corpus | wall baseline/current/limit (s) | RSS baseline/current/limit (KiB) | pass |
27
+ |---|---:|---:|:---:|
28
+ | dynamic_evidence | 0.3476 / 0.146051 / 1.0 | 57728 / 57696 / 123264 | yes |
29
+ | plain_ruby | 0.381025 / 0.122945 / 1.0 | 59360 / 62944 / 124896 | yes |
30
+ | rails | 0.369907 / 0.149768 / 1.119907 | 63168 / 65904 / 128704 | yes |
31
+ | rubocop_1_75_0 | 5.559264 / 5.50558 / 8.338896 | 349136 / 355920 / 436420 | yes |
32
+ | self | 22.508282 / 24.104173 / 30.0 | 1136080 / 1175248 / 1300000 | yes |
33
+
34
+ ## Adversarial suites
35
+
36
+ | suite | result | summary |
37
+ |---|:---:|---|
38
+ | ambiguity | pass | 17 examples, 0 failures |
39
+ | dynamic | pass | 24 examples, 0 failures |
40
+ | parse | pass | 10 examples, 0 failures |
41
+ | remote_input | pass | 28 examples, 0 failures |
42
+
43
+ ## Release gates
44
+
45
+ | gate | result | failures |
46
+ |---|:---:|---:|
47
+ | adversarial | pass | 0 |
48
+ | difference_review | pass | 0 |
49
+ | new_high_false_positives | pass | 0 |
50
+ | new_high_reviewed | pass | 0 |
51
+ | new_high_unresolved | pass | 0 |
52
+ | performance | pass | 0 |
53
+ | review_false_positives | pass | 0 |
54
+
55
+ Reviewed RuboCop/Rails changes: 0; missing: 0.
@@ -0,0 +1,16 @@
1
+ schema_version: 1
2
+ captured_at: "2026-08-08T18:10:00+09:00"
3
+ git_ref: d0168e881120320d28dc2f42e10f9947330fdcb7
4
+ environment:
5
+ ruby: "ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]"
6
+ os: "macOS 26.3 (25D125), Darwin 25.3.0 arm64"
7
+ command: "NECROPSY_RUBOCOP_CORPUS=/private/tmp/necropsy-rubocop-1.75.0 bundle exec ruby bench/run.rb"
8
+ execution: "clean worktree; escalated run so ps-based RSS measurement was available"
9
+ rss_kind: current_process_rss_after_corpus
10
+ rss_scope: benchmark_runner_process
11
+ corpora:
12
+ dynamic_evidence: { wall_time_seconds: 0.347600, rss_kb: 57728 }
13
+ plain_ruby: { wall_time_seconds: 0.381025, rss_kb: 59360 }
14
+ rails: { wall_time_seconds: 0.369907, rss_kb: 63168 }
15
+ rubocop_1_75_0: { wall_time_seconds: 5.559264, rss_kb: 349136 }
16
+ self: { wall_time_seconds: 22.508282, rss_kb: 1136080 }
@@ -0,0 +1,42 @@
1
+ schema_version: 1
2
+ release: 0.2.1
3
+ corpora: [dynamic_evidence, plain_ruby, rails, rubocop_1_75_0, self]
4
+
5
+ baseline:
6
+ git_ref: d0168e881120320d28dc2f42e10f9947330fdcb7
7
+ reports_path: bench/golden/v1/reports
8
+ reason: >-
9
+ d0168e881120320d28dc2f42e10f9947330fdcb7 is the first commit with the bounded evidence
10
+ identity path and artifact-independent production scopes for all five required corpora.
11
+
12
+ labels_path: bench/corpora/v1/labels.yml
13
+
14
+ review:
15
+ path: bench/audits/0.2.1/review.yml
16
+ corpora:
17
+ rails: { strategy: all }
18
+ rubocop_1_75_0: { strategy: stratified, minimum_per_stratum: 5 }
19
+
20
+ performance:
21
+ baseline_path: bench/audits/0.2.1/baseline_performance.yml
22
+ wall_time_ratio: 1.5
23
+ wall_time_allowance_seconds: 0.75
24
+ max_wall_time_seconds:
25
+ dynamic_evidence: 1.0
26
+ plain_ruby: 1.0
27
+ rails: 2.0
28
+ rubocop_1_75_0: 10.0
29
+ self: 30.0
30
+ rss_ratio: 1.25
31
+ rss_allowance_kb: 65536
32
+ max_rss_kb: 1300000
33
+
34
+ adversarial_suites:
35
+ ambiguity:
36
+ command: [bundle, exec, rspec, spec/necropsy/safety_invariants_spec.rb, spec/necropsy/reflective_blocker_visibility_spec.rb]
37
+ dynamic:
38
+ command: [bundle, exec, rspec, spec/necropsy/analyzers/dynamic/coverage_importer_spec.rb, spec/necropsy/confidence/scorer_spec.rb]
39
+ parse:
40
+ command: [bundle, exec, rspec, spec/necropsy/parse_incompleteness_spec.rb, spec/necropsy/safety_mutation_spec.rb]
41
+ remote_input:
42
+ command: [bundle, exec, rspec, spec/necropsy/analyzers/dynamic/coverband_importer_spec.rb]
@@ -0,0 +1,56 @@
1
+ schema_version: 1
2
+ reviews:
3
+ - corpus: rubocop_1_75_0
4
+ change_type: state_changed
5
+ id: "RuboCop::Cop::Force#cops"
6
+ outcome: expected_safety_change
7
+ rationale: "A runtime unknown-dispatch blocker now conservatively overrides test-only status, so this finding cannot remain a deletion candidate."
8
+ reviewer: maintainer
9
+ - corpus: rubocop_1_75_0
10
+ change_type: state_changed
11
+ id: "RuboCop::Cop::Force#name"
12
+ outcome: expected_safety_change
13
+ rationale: "Runtime dispatch by name is incomplete; blocked correctly takes precedence over the prior test-only conclusion."
14
+ reviewer: maintainer
15
+ - corpus: rubocop_1_75_0
16
+ change_type: state_changed
17
+ id: "RuboCop::DirectiveComment#range"
18
+ outcome: expected_safety_change
19
+ rationale: "The new unresolved runtime call scope matches range, making blocked safer than the legacy test-only state."
20
+ reviewer: maintainer
21
+ - corpus: rubocop_1_75_0
22
+ change_type: state_changed
23
+ id: "RuboCop::Formatter::SimpleTextFormatter#message"
24
+ outcome: expected_safety_change
25
+ rationale: "An unresolved runtime message call can target this method, so the blocked transition withdraws the candidate conservatively."
26
+ reviewer: maintainer
27
+ - corpus: rubocop_1_75_0
28
+ change_type: state_changed
29
+ id: "RuboCop::CLI::Command::AutoGenerateConfig#run"
30
+ outcome: expected_safety_change
31
+ rationale: "CLI command classes are registry-selected; the run blocker removes a known dynamic-registry false positive from candidates."
32
+ reviewer: maintainer
33
+ - corpus: rubocop_1_75_0
34
+ change_type: state_changed
35
+ id: "RuboCop::CLI::Command::ExecuteRunner#run"
36
+ outcome: expected_safety_change
37
+ rationale: "CLI command classes are registry-selected; the run blocker removes a known dynamic-registry false positive from candidates."
38
+ reviewer: maintainer
39
+ - corpus: rubocop_1_75_0
40
+ change_type: state_changed
41
+ id: "RuboCop::CLI::Command::InitDotfile#run"
42
+ outcome: expected_safety_change
43
+ rationale: "CLI command classes are registry-selected; the run blocker removes a known dynamic-registry false positive from candidates."
44
+ reviewer: maintainer
45
+ - corpus: rubocop_1_75_0
46
+ change_type: state_changed
47
+ id: "RuboCop::CLI::Command::LSP#run"
48
+ outcome: expected_safety_change
49
+ rationale: "CLI command classes are registry-selected; the run blocker removes a known dynamic-registry false positive from candidates."
50
+ reviewer: maintainer
51
+ - corpus: rubocop_1_75_0
52
+ change_type: state_changed
53
+ id: "RuboCop::CLI::Command::ShowCops#run"
54
+ outcome: expected_safety_change
55
+ rationale: "CLI command classes are registry-selected; the run blocker removes a known dynamic-registry false positive from candidates."
56
+ reviewer: maintainer