specproof 0.1.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 (119) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +10 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +283 -0
  5. data/docs/agent-skills.md +60 -0
  6. data/docs/benchmark.md +24 -0
  7. data/docs/constrained-partition-pairs-results.md +44 -0
  8. data/docs/finite-strings-results.md +75 -0
  9. data/docs/implementation-status.md +65 -0
  10. data/docs/input-selection-results.md +123 -0
  11. data/docs/lint-cleanup-plan.md +12 -0
  12. data/docs/method-targets-results.md +68 -0
  13. data/docs/minitest-compatibility.md +33 -0
  14. data/docs/optional-arguments-plan.md +25 -0
  15. data/docs/optional-arguments-results.md +45 -0
  16. data/docs/pairwise-partitions-results.md +53 -0
  17. data/docs/pairwise-results.md +77 -0
  18. data/docs/pairwise-suggestions-results.md +104 -0
  19. data/docs/rbs-implementation-status.md +115 -0
  20. data/docs/rbs-string-literals-results.md +58 -0
  21. data/docs/real-project-pilot.md +84 -0
  22. data/docs/report-format.md +244 -0
  23. data/examples/age_policy/README.md +39 -0
  24. data/examples/age_policy/faulty/lib/age_policy.rb +9 -0
  25. data/examples/age_policy/faulty/test/age_policy_examples_test.rb +17 -0
  26. data/examples/age_policy/faulty/test/age_policy_test.rb +21 -0
  27. data/examples/age_policy/lib/age_policy.rb +8 -0
  28. data/examples/age_policy/run.rb +23 -0
  29. data/examples/age_policy/specification.rb +8 -0
  30. data/examples/age_policy/test/age_policy_test.rb +18 -0
  31. data/examples/constrained_partition_pairs/README.md +40 -0
  32. data/examples/constrained_partition_pairs/lib/account_eligibility.rb +8 -0
  33. data/examples/constrained_partition_pairs/requirements.md +11 -0
  34. data/examples/constrained_partition_pairs/run.rb +22 -0
  35. data/examples/constrained_partition_pairs/specification.rb +17 -0
  36. data/examples/constrained_partition_pairs/test_account_eligibility.rb +34 -0
  37. data/examples/input_selection/README.md +22 -0
  38. data/examples/input_selection/delivery_policy.rb +11 -0
  39. data/examples/input_selection/requirements.md +9 -0
  40. data/examples/input_selection/specification.rb +8 -0
  41. data/examples/input_selection/test_delivery_policy.rb +38 -0
  42. data/examples/method_targets/README.md +30 -0
  43. data/examples/method_targets/lib/delivery_defaults.rb +8 -0
  44. data/examples/method_targets/lib/delivery_options.rb +12 -0
  45. data/examples/method_targets/requirements.md +20 -0
  46. data/examples/method_targets/specification_objects.rb +17 -0
  47. data/examples/method_targets/specification_strings.rb +15 -0
  48. data/examples/pairwise/README.md +46 -0
  49. data/examples/pairwise/constrained_requirements.md +6 -0
  50. data/examples/pairwise/constrained_specification.rb +11 -0
  51. data/examples/pairwise/corrected/lib/delivery_options.rb +11 -0
  52. data/examples/pairwise/corrected/test/delivery_options_test.rb +28 -0
  53. data/examples/pairwise/faulty/lib/delivery_options.rb +11 -0
  54. data/examples/pairwise/faulty/test/gap_delivery_options_test.rb +10 -0
  55. data/examples/pairwise/faulty/test/initial_delivery_options_test.rb +23 -0
  56. data/examples/pairwise/requirements.md +11 -0
  57. data/examples/pairwise/run.rb +36 -0
  58. data/examples/pairwise/specification.rb +9 -0
  59. data/examples/pairwise/three_boolean/lib/boolean_batch.rb +8 -0
  60. data/examples/pairwise/three_boolean/test/boolean_batch_test.rb +28 -0
  61. data/examples/pairwise/three_boolean_specification.rb +10 -0
  62. data/examples/pairwise_partitions/README.md +34 -0
  63. data/examples/pairwise_partitions/lib/age_policy.rb +8 -0
  64. data/examples/pairwise_partitions/requirements.md +8 -0
  65. data/examples/pairwise_partitions/run.rb +22 -0
  66. data/examples/pairwise_partitions/specification.rb +13 -0
  67. data/examples/pairwise_partitions/test_age_policy.rb +29 -0
  68. data/examples/pairwise_suggestions/README.md +48 -0
  69. data/examples/pairwise_suggestions/run.rb +55 -0
  70. data/examples/pairwise_suggestions/three_boolean/lib/suggested_boolean_batch.rb +8 -0
  71. data/examples/pairwise_suggestions/three_boolean/requirements.md +7 -0
  72. data/examples/pairwise_suggestions/three_boolean/specification.rb +11 -0
  73. data/examples/pairwise_suggestions/three_boolean/test/baseline_test.rb +9 -0
  74. data/examples/pairwise_suggestions/three_boolean/test/complete_test.rb +22 -0
  75. data/examples/partition_gap.rb +8 -0
  76. data/examples/rbs_registration/README.md +58 -0
  77. data/examples/rbs_registration/implementations/age_gt/registration.rb +8 -0
  78. data/examples/rbs_registration/implementations/age_gte/registration.rb +8 -0
  79. data/examples/rbs_registration/requirements.md +9 -0
  80. data/examples/rbs_registration/sig/registration.rbs +3 -0
  81. data/examples/rbs_registration/specification.rb +10 -0
  82. data/examples/rbs_registration/test_registration.rb +43 -0
  83. data/examples/rbs_string_literals/README.md +34 -0
  84. data/examples/rbs_string_literals/lib/delivery_options.rb +9 -0
  85. data/examples/rbs_string_literals/requirements.md +11 -0
  86. data/examples/rbs_string_literals/sig/delivery_options.rbs +3 -0
  87. data/examples/rbs_string_literals/specification.rb +7 -0
  88. data/examples/rbs_string_literals/test_delivery_options.rb +46 -0
  89. data/examples/shipping.rb +12 -0
  90. data/exe/specproof +7 -0
  91. data/lib/specproof/checker.rb +144 -0
  92. data/lib/specproof/cli.rb +292 -0
  93. data/lib/specproof/collector.rb +304 -0
  94. data/lib/specproof/combinations.rb +226 -0
  95. data/lib/specproof/composer.rb +97 -0
  96. data/lib/specproof/coverage.rb +229 -0
  97. data/lib/specproof/coverage_report.rb +334 -0
  98. data/lib/specproof/domains.rb +124 -0
  99. data/lib/specproof/loader.rb +285 -0
  100. data/lib/specproof/minitest.rb +443 -0
  101. data/lib/specproof/model.rb +198 -0
  102. data/lib/specproof/partition_space.rb +268 -0
  103. data/lib/specproof/planner.rb +125 -0
  104. data/lib/specproof/report.rb +248 -0
  105. data/lib/specproof/skills.rb +188 -0
  106. data/lib/specproof/sources/rbs.rb +137 -0
  107. data/lib/specproof/sources/rbs_projector.rb +268 -0
  108. data/lib/specproof/suggestion_report.rb +159 -0
  109. data/lib/specproof/suggestions.rb +352 -0
  110. data/lib/specproof/target_name.rb +100 -0
  111. data/lib/specproof/type_constraints.rb +76 -0
  112. data/lib/specproof/version.rb +7 -0
  113. data/lib/specproof.rb +100 -0
  114. data/sig/specproof.rbs +222 -0
  115. data/skills/specproof-specify/SKILL.md +282 -0
  116. data/skills/specproof-specify/references/usage.md +265 -0
  117. data/skills/specproof-test-gaps/SKILL.md +214 -0
  118. data/skills/specproof-test-gaps/references/usage.md +231 -0
  119. metadata +165 -0
@@ -0,0 +1,123 @@
1
+ # Explicit input selection results
2
+
3
+ The [approved implementation plan](superpowers/plans/2026-10-03-input-selection.md)
4
+ is implemented on `implement/input-selection`, based on the completed RBS branch.
5
+ Core implementation commit: `23d6966`; documentation and skills: `33b8634`. Work is isolated in
6
+ `tmp/worktrees/input-selection`; the original checkout and RBS worktree are
7
+ unchanged. No publication or merge is included.
8
+
9
+ ## Delivered behavior
10
+
11
+ ```ruby
12
+ SpecProof.define "PStoreLogger#save" do
13
+ exclude_input :data, reason: "Payload contents are outside this nil/1 file-ID scenario coverage"
14
+ input :file_id, values: [nil, 1]
15
+ end
16
+ ```
17
+
18
+ The collector checks that analyzed and explicitly excluded names together
19
+ exactly match the selected method's named parameters. It reads only analyzed
20
+ bindings. Excluded Hash or object values therefore do not invalidate scalar
21
+ collection; unsupported analyzed values still do. A missing declaration, typo,
22
+ or newly added parameter cannot silently become an exclusion.
23
+
24
+ Exclusions require a name, nonblank reason, and declaration source. A target
25
+ must retain at least one analyzed input. Default specifications remain strict.
26
+ Existing method-shape, redefinition, constant-binding and collection-lifecycle
27
+ checks remain in force. Tests still run when collection cannot prepare, and
28
+ their actual result is reported separately from collection integrity.
29
+
30
+ RBS can import remaining finite inputs from an exclusions-only DSL declaration.
31
+ The reader validates the complete selected signature before skipping excluded
32
+ types. Unsupported analyzed types and union members still fail atomically.
33
+ Review found and fixed an edge case where excluding every RBS argument could
34
+ otherwise let a nonexistent DSL input reach planning.
35
+
36
+ Offline check/plan and runtime reports share `scope.completeness_scope` and
37
+ `scope.input_scope`, including analyzed names and excluded names/reasons/sources.
38
+ Human output discloses exclusions. Sorted excluded names affect the contract
39
+ digest; reason text and provenance do not. Legacy no-exclusion digest bytes,
40
+ criterion, and per-input obligation IDs remain unchanged. Compare scope and
41
+ digest as well as IDs when consuming reports.
42
+
43
+ ## Changes and simplifications
44
+
45
+ - `lib/specproof/{model,loader,composer,collector,report,minitest,cli}.rb`:
46
+ declaration-owned exclusions, selected binding reads, shared reporting.
47
+ - `lib/specproof.rb` and `lib/specproof/sources/{rbs,rbs_projector}.rb`:
48
+ full-signature validation followed by deliberate type projection. Removed
49
+ duplicate name validation from the public loader.
50
+ - `sig/specproof.rbs` and focused loader/composer/collector/report/RBS workflow
51
+ tests: API metadata and regression coverage.
52
+ - `skills/specproof-{specify,test-gaps}/`, README and report documentation:
53
+ scoped adoption, valid baseline collection, preserved test-only boundaries,
54
+ and honest failure reporting.
55
+ - [Runnable example](../examples/input_selection/README.md): ordinary Hash
56
+ payloads, an analyzed boolean, and independently specified assertions.
57
+
58
+ Selection travels with the existing specification; there are no separate CLI
59
+ or Minitest selection options to synchronize. The planner and coverage tuple
60
+ validation are reused. No dependency or new domain kind was added; core runtime
61
+ dependencies remain zero.
62
+
63
+ ## Verification
64
+
65
+ | Check | Result |
66
+ | --- | --- |
67
+ | CRuby 3.3.6 / 3.4.7 / 4.0.1 | Each: 166 core tests, 822 assertions; 46 optional RBS tests, 425 assertions; zero failures, errors or skips |
68
+ | Locked default Ruby 4 bundle | `bundle exec rake` passed; RuboCop 1.90 inspected 98 files without offenses |
69
+ | Package checks | `bin/check` passed syntax, installed-package and skill checks: 2 tests, 76 assertions; real gem built |
70
+ | API signatures | RBS 4.2.0 validation passed on all three Ruby versions |
71
+ | Shipped example | 4 tests / 4 assertions pass; both selected boolean obligations exercised |
72
+ | Independent reviews | Luna specification and quality reviews approved core and documentation after fixes |
73
+
74
+ [Raw matrix records](pilots/input-selection/matrix/) retain commands, versions,
75
+ outputs, exit statuses and library hashes. These runs recorded the actual
76
+ pre-commit working-tree state at `7222d96`; their 17 library hashes match the
77
+ committed implementation. Provenance records were not rewritten after commit.
78
+
79
+ Independent audit records cover the [pilot](pilots/input-selection/audit/pilot.json),
80
+ [matrix](pilots/input-selection/audit/matrix.json), and
81
+ [agent evaluation artifacts](evaluations/artifacts/input-selection/independent-final-audit.json).
82
+
83
+ ## Existing-project adoption
84
+
85
+ The [PStoreLogger pilot](pilots/input-selection/README.md) uses its unchanged
86
+ source at `959e37410bac42ba47e43ee8da006ce9550d9f50`. The same ordinary Hash-based
87
+ suite passes both before and after instrumentation: **7 tests, 23 assertions**.
88
+ The selected `file_id` scenario covers `nil` and integer `1`; both obligations
89
+ are exercised, with intact collection and matching offline/runtime IDs and
90
+ digest. The five copied source/test files retain their original hashes.
91
+
92
+ This is a finite scenario subset, not the complete accepted file-ID domain.
93
+ PStoreLogger also documents string IDs, which this milestone does not model.
94
+ No additional test or coverage gap was invented for this adoption result.
95
+
96
+ ## Agent workflow evidence
97
+
98
+ The [evaluation record](evaluations/input-selection-agent-skills.md) preserves
99
+ the old-skill baseline, initial attempts, corrections, and fresh repeats using
100
+ the installed gem's exported skills. The first attempts exposed an invalid
101
+ baseline collected before its specification existed and an unauthorized
102
+ production fix in a test-only task. Both attempts remain visible.
103
+
104
+ After guidance corrections, a fresh scoped-adoption actor imported its boolean
105
+ from RBS, recorded a valid 1/2 baseline, and added an independently justified
106
+ assertion to reach a fresh passing 2/2 report. A fresh pressure actor preserved
107
+ the declared scope and production code, added a failing regression, and
108
+ reported the defect: **4/4 obligations exercised, `tests_passed: false`**.
109
+ Coverage and passing assertions are separate evidence.
110
+
111
+ These are small guided scenarios with supplied requirements, selectors and a
112
+ command recorder. They do not establish general agent reliability or automatic
113
+ client skill discovery.
114
+
115
+ ## Limits
116
+
117
+ Complete collection and 100% exercise apply only to analyzed marginal input
118
+ obligations. Excluded arguments may affect behavior; an exclusion reason does
119
+ not prove that they are irrelevant. This feature does not analyze outputs,
120
+ assertion adequacy, combinations, arbitrary objects, strings, argument omission
121
+ or additional method shapes. Existing serial collection and RBS 4.2.0 limits
122
+ remain. Obtain fresh runtime evidence after changes even when IDs and digest
123
+ match an older report.
@@ -0,0 +1,12 @@
1
+ # Lint cleanup plan
2
+
3
+ The implemented behavior is protected by the 102-test suite, including runtime and installed-package checks. Repository-wide RuboCop currently reports style and complexity offenses against the Bundler scaffold's defaults.
4
+
5
+ 1. Run the existing RuboCop dependency with a writable cache and without parallel workers; collect the actual offense inventory.
6
+ 2. Apply only safe style corrections, keeping the public API, report schema, and runtime behavior intact.
7
+ 3. Treat test/fixture blocks separately from production complexity. `.rubocop.yml` excludes Metrics only under `test/**/*`, `spec/**/*`, and `benchmark/**/*`: cohesive test scenarios and benchmark support are not useful production complexity signals. Production Metrics remain enabled without per-file exclusions.
8
+ 4. Set explicit initial project budgets after reviewing the actual inventory: ABC 60, cyclomatic/perceived complexity 20, method length 60, class length 250, module length 200, and block length 40. These replace scaffold defaults, including the ten-line method limit, which would fragment the interval sweep and sequential method-binding checks without changing their responsibilities. An independent Luna review found these algorithms cohesive and supported the budgets; the collector binding validator remains near the limits and should be monitored. These budgets are an initial policy, not evidence that complexity has disappeared.
9
+ 5. Extract the oversized CLI dispatcher into separate check, plan, and skill-export flows with shared error handling. Preserve command behavior through the existing CLI acceptance tests; add regression tests for any behavior fixes.
10
+ 6. Re-run affected tests after edits, then the complete suite, syntax/package checks, and RuboCop. Add no dependencies.
11
+
12
+ Ownership is limited to Ruby style corrections, existing `.rubocop.yml`, and this verification record. Agent evaluation projects in `/private/tmp` are independent evidence and must remain untouched.
@@ -0,0 +1,68 @@
1
+ # Method target support: verification
2
+
3
+ String declarations and Ruby method objects now share canonical target names:
4
+ `Owner#method` for instance methods and `Owner.method` for class/module
5
+ singleton methods. Equivalent declarations have matching contract digests
6
+ and obligation IDs. Strings remain usable without loading application code;
7
+ method objects require loaded code and a current public Ruby definition.
8
+
9
+ The [runnable example](../examples/method_targets/README.md) produces eight
10
+ matching target/obligation identities from its string and method-object forms.
11
+ The input contract does not capture return values, execute the target during
12
+ normalization, or promise editor navigation. Collection resolves the canonical
13
+ name when it starts, rather than pinning the declaration's method object.
14
+
15
+ Luna subagents implemented target normalization, singleton collection, RBS
16
+ projection, documentation and agent skills. Independent specification and
17
+ quality reviews found no remaining blockers.
18
+
19
+ ## Verification
20
+
21
+ On each of CRuby 3.3.6, 3.4.7 and 4.0.1:
22
+
23
+ | Suite | Tests | Assertions |
24
+ | --- | ---: | ---: |
25
+ | Core | 324 | 1,666 |
26
+ | Optional RBS | 60 | 537 |
27
+
28
+ All passed without failures, errors or skips. RBS signature validation,
29
+ RuboCop (151 files), syntax, packaged skill checks and gem building passed.
30
+ Tests cover equivalent declarations, separate same-named instance/singleton
31
+ targets, optional and excluded arguments, aliases called through the selected
32
+ definition, stale method objects, invalid owners, source-aware errors,
33
+ redefinition, constant binding changes and RBS singleton declarations.
34
+
35
+ ## Real-project continuation
36
+
37
+ The earlier [pilot](real-project-pilot.md) rejected
38
+ `Agent::SessionContext::SemanticCategories.lookup(identifier)` because class
39
+ methods were unsupported. A new Luna exercise used the unchanged method and
40
+ the candidate's unchanged `SummaryParserTest` file with both target forms.
41
+
42
+ Both declarations passed check and plan, with the same twelve obligations and
43
+ digest `2446066802513c19caee861f0c2d7b607559fcf72e0f3359fa862044292c8ea2`.
44
+ The domain was explicitly scoped to six strings and six symbols from the
45
+ existing catalog assertion, not arbitrary string inputs.
46
+
47
+ The normal test helper could not load the unrelated `agent_sessions`
48
+ dependency from the prepared bundle. A scratch-only helper loaded the parser's
49
+ local supporting classes without wrapping or changing the selected method.
50
+ Each form then passed the same twelve tests and 110 assertions. Both reports
51
+ were completed and intact, with identical scope and hit projections: seven
52
+ exercised inputs, five missing and zero unknown. No dependencies were installed
53
+ and no application files were edited. This demonstrates the focused test file,
54
+ not the application's full suite under its normal helper.
55
+
56
+ The missing symbols were `:constraint`, `:decision`, `:next_action`,
57
+ `:open_question` and `:term`. The agent left them untested rather than deriving
58
+ expected lookup results from implementation code. This exercise followed the
59
+ updated source-checkout skills; it was not an installed-gem evaluation.
60
+
61
+ ## Limits
62
+
63
+ Direct public instance methods require a named class; singleton methods may
64
+ belong to a named class or module. Arbitrary bound instance methods, anonymous
65
+ owners, aliased declarations, inherited singleton declarations and native
66
+ methods are rejected. An UnboundMethod identifies its defining class, including
67
+ when obtained by reflecting through a subclass. RBS selection still uses
68
+ explicit string targets and its existing supported type subset.
@@ -0,0 +1,33 @@
1
+ # Reproducible Minitest installation
2
+
3
+ The optional adapter accepts Minitest `>= 5.26.2` and `< 5.28.0`. Both the activated gem metadata and `Minitest::VERSION` must be in that range, with matching major and minor versions. The lower bound excludes untested 5.26.0 and 5.26.1; the upper bound excludes untested later interfaces.
4
+
5
+ The development and pilot bundles select `~> 5.26.2`. An ordinary bundle uses the existing RubyGems dependency without a source rebuild, a runtime version patch, or an alternate GEM_HOME:
6
+
7
+ ```sh
8
+ bundle install
9
+ bundle exec rake
10
+ bundle exec ruby -rminitest -e 'puts Gem.loaded_specs.fetch("minitest").version; puts Minitest::VERSION'
11
+ ```
12
+
13
+ Use Ruby 3.3 or newer for these commands. The last command reports `5.26.2` twice with the checked-in lockfile.
14
+
15
+ ## Observed package mismatch
16
+
17
+ On 2026-10-02, a fresh download from [RubyGems' Minitest 5.27.0 package](https://rubygems.org/downloads/minitest-5.27.0.gem) matched the SHA-256 in its [published metadata](https://rubygems.org/api/v2/rubygems/minitest/versions/5.27.0.json):
18
+
19
+ `2d3b17f8a36fe7801c1adcffdbc38233b938eb0b4966e97a6739055a45fa77d5`
20
+
21
+ Its gem metadata says `5.27.0`, but the extracted `lib/minitest.rb` defines `VERSION = "5.26.2"`. This observation concerns the published artifact downloaded on that date; the [upstream v5.27.0 source](https://github.com/minitest/minitest/blob/v5.27.0/lib/minitest.rb) declares `5.27.0`. Reinstalling the same artifact preserves the mismatch. SpecProof continues to reject it.
22
+
23
+ A fresh [5.26.2 package](https://rubygems.org/downloads/minitest-5.26.2.gem) matched its [published metadata](https://rubygems.org/api/v2/rubygems/minitest/versions/5.26.2.json):
24
+
25
+ `f021118a6185b9ba9f5af71f2ba103ad770c75afde9f2ab8da512677c550cde3`
26
+
27
+ That package's metadata and extracted runtime both identify `5.26.2`. Its `lib/minitest.rb` also matches the existing local installation by SHA-256. No dependency source or global gem installation was modified.
28
+
29
+ ## Validation and historical evidence
30
+
31
+ New integration tests exercise genuine 5.26.2 and reject the mislabeled 5.27/5.26 pairing, the reverse pairing, versions below the lower bound, 5.28.0, and 6.0.0. The original 5.27 source-tag validation and retained skill evaluations remain historical evidence; they were not rewritten to claim that the mismatched published artifact passed.
32
+
33
+ Compatibility changes do not alter the criterion, obligation IDs, JSON schema, collector scope, or the distinction between input exercise and behavioral correctness.
@@ -0,0 +1,25 @@
1
+ # Optional scalar arguments
2
+
3
+ Approved continuation after the real-project pilot: observe effective Ruby-bound optional positional and keyword values, then repeat the PStoreLogger primitive-scenario pilot.
4
+
5
+ ## Contract
6
+
7
+ - Support named required/optional positional and keyword parameters. Every parameter must still have an input declaration.
8
+ - Capture effective values at Ruby method entry. Do not inspect or execute default expressions, infer omission, add omission-specific obligations, or change existing IDs/criterion.
9
+ - Preserve rejection of rest, keyword-rest, forwarding, explicit blocks, class-method targets, inherited/aliased declarations, and non-primitive observed tuples.
10
+ - A default that raises before method entry supplies no entry observation. Ruby's original exception and side effects remain unchanged.
11
+ - A non-primitive effective value keeps collection incomplete; a primitive value outside its declared domain contributes no valid tuple hits.
12
+ - Reports explicitly identify effective bound values and unavailable argument-presence evidence. This is additive metadata under schema 1.
13
+
14
+ ## Implementation and acceptance
15
+
16
+ 1. Prove TracePoint default timing and side effects with failing collector tests before widening the parameter allowlist. Cover mixed signatures, dependent defaults, omitted/explicit equal values, raising defaults, non-primitive defaults, and unsupported signatures.
17
+ 2. Add optional-argument Minitest subprocess integration: stable shared obligations, repeated nil hits from omission and explicit nil, preserved failure semantics, whole-tuple validation, and incomplete evidence on observation failure. Document semantics in the report contract, README, and agent reference.
18
+ 3. Run all required checks on Ruby 3.3/3.4/4.0 with published Minitest 5.26.2 and independent specification/quality review.
19
+ 4. Repeat PStoreLogger on a copied source snapshot using Ruby 3.4's standard-library PStore. Preserve existing tests and production source, export skills, and ground added persistence assertions in project and PStore contracts.
20
+
21
+ The existing PStoreLogger tests pass Hash payloads. Such calls remain unsupported by scalar collection and must not be silently discarded. Retain an instrumented full-suite run showing that limitation, plus a clearly filtered fresh primitive-scenario run if the declared subset can be exercised completely. A full uninstrumented suite must still pass after adding tests; filtered coverage is never whole-suite coverage.
22
+
23
+ ## Deferred
24
+
25
+ No structured-object domains, strings, arbitrary argument serialization, default-expression static analysis, omission coverage, class-method collection, or replay in this slice.
@@ -0,0 +1,45 @@
1
+ # Optional scalar arguments
2
+
3
+ This implements the [approved continuation](optional-arguments-plan.md) after the first real-project pilot rejected `PStoreLogger#save(data, file_id: nil)`. Named optional positional and keyword parameters now work alongside required parameters. Every parameter must still be declared, and observed values must remain within the supported scalar representation.
4
+
5
+ The production change widens the collector's parameter-kind allowlist; Ruby still evaluates and binds arguments. The adapter adds two scope fields under report schema 1: `input_semantics: "effective_bound_values"` and `argument_presence: "not_observed"`. The planner, criterion, contract digest semantics, and obligation IDs are unchanged.
6
+
7
+ ## Meaning of the evidence
8
+
9
+ Omitting an argument whose default is `nil` and explicitly passing `nil` exercise the same value obligation. This does not establish omission coverage. Defaults execute once through normal Ruby execution, including side effects and dependent defaults. A default that raises before method entry yields no entry observation for that target and preserves the original exception. Another selected method called during default evaluation can still contribute its own entry observation.
10
+
11
+ A primitive value outside a declared domain invalidates the whole tuple. A non-primitive effective value, including a default, makes selected-target collection incomplete. Existing positive hits remain evidence, while unhit obligations become unknown. Rest parameters, keyword-rest, forwarding, explicit blocks, class-method targets, and structured objects remain outside this release.
12
+
13
+ ## Adoption boundary
14
+
15
+ The PStoreLogger continuation declares an explicit primitive scenario subset: `data` in `[nil, false, true, 0, :event]` and `file_id` in `[nil, 1]`. Those yield seven marginal value obligations, not Cartesian combinations or the complete domain of marshalable objects.
16
+
17
+ The original project tests save Hash payloads. Their ordinary execution must keep passing; instrumenting the full suite must honestly report incomplete collection on those object-valued inputs. A fresh filtered run of separate scalar persistence tests can establish exercise of the declared subset only.
18
+
19
+ Assertions are grounded in the project's documented storage layout and filename behavior, and in Ruby's [PStore contract](https://ruby-doc.org/3.4.1/stdlibs/pstore/PStore.html). PStore stores marshalable Ruby values through transactions. Added tests read the persisted payload, distinguish stored `nil` from a missing key, preserve `false`, check timestamps, and check explicit-ID collision behavior. No production behavior change is needed for that scenario.
20
+
21
+ | Run | Minitest outcome | Collection outcome |
22
+ | --- | --- | --- |
23
+ | Original suite | 7 tests, 23 assertions pass | Uninstrumented baseline |
24
+ | Original suite with adapter | 7 tests, 23 assertions pass | Incomplete, seven unknown obligations, `non_primitive_argument`; invocation fails |
25
+ | Expanded suite | 13 tests, 63 assertions pass | Uninstrumented regression check |
26
+ | Expanded suite with adapter | 13 tests, 63 assertions pass | Incomplete on Hash payloads; invocation fails regardless of positive hits |
27
+ | Explicit scalar filter | 6 tests, 40 assertions pass | Complete, seven of seven marginal obligations exercised; invocation succeeds |
28
+
29
+ Luna used the newly exported skills in an isolated copy of PStoreLogger at source commit `959e37410bac42ba47e43ee8da006ce9550d9f50`. Source hashes, exact skills, assertions, commands, reports, and a relocatable workspace are retained in the [pilot artifacts](pilots/2026-10-02-optional/pstore_logger/results.md) and [archive](pilots/2026-10-02-optional/pstore_logger/workspace.tar.gz). The expanded instrumented run's positive hit count can depend on test order before a Hash disables the target; completeness remains false in every case. All report IDs are fresh and their seven obligation IDs and contract digest agree with the offline plan.
30
+
31
+ The archive was extracted into a fresh temporary directory, installed through ordinary `bundle install --local` with the checksum-verified Minitest package, and rerun successfully. [Reproduction evidence](pilots/2026-10-02-optional/pstore_logger/reproduction.json) retains the new report IDs, command exits, and filtered results. Loaded library paths and hashes are separately captured in the runtime probe. The archive excludes installed dependencies; its cached official Minitest package is retained for offline installation. The local reproduction uses CRuby 3.4.7 so PStore comes from its standard library, with unrelated ambient gem and Bundler variables cleared.
32
+
33
+ To repeat locally, extract the archive into an empty directory, set `SPECPROOF_ROOT` to this gem checkout, install with Ruby 3.4's `bundle install --local`, and invoke `ruby run_pilot.rb`. The retained runner records this machine's Ruby path; adjust `RUBY_BIN` and its environment `PATH` for another machine. The driver exits successfully only when expected child outcomes match: full instrumented children fail on integrity, while the filtered scalar child succeeds. Its success does not relabel the incomplete child reports.
34
+
35
+ The earlier [pilot](real-project-pilot.md) and agent evaluation archives retain their original skill bytes and implementation context. This continuation records newly exported skills separately; it does not reinterpret earlier rejected probes as successful runs.
36
+
37
+ ## Verification
38
+
39
+ - Full suites pass separately on CRuby 3.3.6, 3.4.7, and 4.0.1 with published Minitest 5.26.2: **131 runs, 663 assertions**, no failures, errors, or skips.
40
+ - The Ruby 4.0.1 default Rake task passes tests and RuboCop: **83 files**, no offenses. Its deliberate method-redefinition fixtures emit expected Ruby warnings.
41
+ - `bin/check` passes syntax checks, packaging and skill checks (**2 runs, 66 assertions**), and gem build. Existing RBS declarations validate; that does not type-check the implementation or import RBS specifications.
42
+ - Collector tests cover optional positional and keyword bindings, mixed signatures, dependent defaults, side effects, raising defaults, nested selected calls, and preserved unsupported forms. Subprocess tests verify omitted/explicit `nil` hits, offline-plan IDs and digest equality, whole-tuple domain validation, and incomplete evidence on non-primitive defaults.
43
+ - Luna specification and quality reviews passed after adding the two missing acceptance cases. Independent pilot review and source/hash/report checks passed, including actual loaded runtime paths and reproduced child exit statuses.
44
+
45
+ No runtime dependency was added, no external project's source was modified, and no gem or branch was published. Remote CI execution and arbitrary-object collection remain unverified or deferred.
@@ -0,0 +1,53 @@
1
+ # Pairwise partition coverage results
2
+
3
+ This records the initial unrestricted implementation. Whole-partition
4
+ restrictions have since been added; see the [constrained example](../examples/constrained_partition_pairs/README.md)
5
+ and the current [report contract](report-format.md).
6
+
7
+ `pairwise-partitions-v1` plans category pairs from explicit complete, disjoint
8
+ integer partitions crossed with finite inputs. The scalar
9
+ `input-basics-v1` and finite-value `pairwise-finite-v1` criteria retain their
10
+ existing behavior. At the time of this evaluation, the criterion supported
11
+ only `all_allowed: true`; forbidden assignments and explicit partitions on
12
+ finite-valued inputs were rejected.
13
+
14
+ The runnable [age-by-country example](../examples/pairwise_partitions/README.md)
15
+ uses age `0..120`, partitioned into minor `0...18` and adult `18..120`, crossed
16
+ with countries `"ro"` and `"de"`. The plan contains four category pairs. A
17
+ partition obligation serializes its inclusive category bounds, for example
18
+ `{ "kind": "partition", "name": "minor", "lower": "0", "upper": "17" }`.
19
+
20
+ On CRuby 4.0.1 with the prepared partition bundle, the initial example process
21
+ passed 1 test and 3 assertions, exercising 3/4 pairs. The missing pair was
22
+ minor/`"de"`. `specproof suggest` inferred `pairwise-partitions-v1` from the
23
+ checked report and returned the concrete call input `age: 0, country: "de"`
24
+ with strategy `greedy-partition-pairwise-v1`. The separate complete process
25
+ passed 2 tests and 4 assertions, exercising 4/4 pairs. Both processes completed
26
+ with intact reports and `tests_passed: true`.
27
+
28
+ The category report and suggested input establish only category membership for
29
+ the declared values. The lower endpoint is a concrete representative; it does
30
+ not establish boundary-value coverage or equivalent behavior throughout a
31
+ category. The requirement file supplies the expected result for the added
32
+ under-18 assertion. No output or behavioral rule is inferred from the plan or
33
+ suggestion.
34
+
35
+ ## Verification
36
+
37
+ The complete core suite passed on CRuby 3.3.6, 3.4.7, and 4.0.1: 284 tests
38
+ and 1,440 assertions on each version. The optional RBS suite passed on each:
39
+ 54 tests and 499 assertions. RBS signature validation also passed on all three.
40
+ No failures, errors, or skips occurred. Dependencies were reused from prepared
41
+ local bundles; the feature adds no dependencies.
42
+
43
+ Regression coverage at that revision included category membership within one valid call,
44
+ independent exact-value scalar obligations, canonical category identities,
45
+ huge integer endpoints, invalid partition geometry and policies, unsupported
46
+ forbidden assignments and finite partitions, multi-pair suggestions, bounded
47
+ enumeration, and rejection of altered category identities in coverage reports.
48
+ RuboCop passed for 140 files. Syntax, packaged skill assets, and gem build
49
+ checks also passed (2 packaging/asset tests, 76 assertions).
50
+
51
+ The [installed agent exercise](evaluations/pairwise-partitions-skills.md)
52
+ records old-guidance and updated-guidance runs, unchanged fixture checks,
53
+ report tampering rejection, and hashes of the tested packaged library/skills.
@@ -0,0 +1,77 @@
1
+ # Finite pairwise coverage
2
+
3
+ The opt-in `pairwise-finite-v1` criterion derives obligations from explicit
4
+ finite input domains and a declared combinations group. `all_allowed: true`
5
+ admits the full Cartesian product; partial `forbid` assignments remove matching
6
+ full tuples. A pair is required only when an allowed full assignment contains
7
+ it. No implementation behavior is used to invent restrictions or expected
8
+ results.
9
+
10
+ The existing collector supplies whole calls. Calls cannot combine their
11
+ individual values to manufacture a pair hit. Every analyzed input must be in
12
+ its domain, including inputs outside the selected pairwise group. A forbidden
13
+ call earns no hits under either criterion and is recorded as outside the joint
14
+ domain. This does not make a deliberate negative test fail.
15
+
16
+ The scalar criterion remains the default. Scalar IDs and contract digests
17
+ without combinations metadata retain their previous representation. Typed
18
+ pair IDs distinguish strings from symbols, and equivalent declaration/rule
19
+ orders keep identity stable. Rule provenance survives duplicate declarations.
20
+
21
+ ## Demonstrated value
22
+
23
+ The runnable [delivery example](../examples/pairwise/README.md) starts with
24
+ passing assertions for `00`, `01`, and `10`. Both values of each input appear,
25
+ but pair coverage is only 3/4. The missing `11` assertion, derived from the
26
+ separate requirements, exposes the faulty notification result. Coverage then
27
+ reaches 4/4 while `tests_passed` remains false. A separate corrected
28
+ implementation passes all four assertions.
29
+
30
+ The constrained declaration requires three pairs and explains the excluded
31
+ fourth. The three-input example covers all 12 pair rows with four calls; it
32
+ does not cover all eight full assignments. The [agent workflow exercise](evaluations/pairwise-skills.md)
33
+ records how the exported skills guide a fresh actor through a missing-pair
34
+ test without narrowing the contract to hide the defect.
35
+
36
+ ## Review and limits
37
+
38
+ Independent Luna specification review found that the global obligation limit
39
+ was checked after retaining every target's pair space. Planning now checks the
40
+ running count before retaining each space and stops on the first crossing.
41
+ A regression verifies that later targets are not planned after that error.
42
+ Quality review found no functional defect in the reviewed implementation.
43
+
44
+ Enumeration is limited to 10,000 complete assignments and 10,000 possible pair
45
+ rows per target, with at most 10,000 required pair obligations in a plan.
46
+ These are explicit configuration errors, not sampling. Excluded-pair metadata
47
+ is bounded per target, but not globally: many heavily constrained targets can
48
+ still produce a large combined report. This remains a resource limitation for
49
+ large projects.
50
+
51
+ This release supports one finite combinations group per target. It does not
52
+ generate test suites, infer business constraints, solve arbitrary Ruby
53
+ predicates, measure higher-order interactions, or prove assertion adequacy.
54
+ RBS can supply finite inputs to a combinations-only declaration; its existing
55
+ supported type subset is unchanged.
56
+
57
+ ## Verification
58
+
59
+ The final implementation passed the following local checks:
60
+
61
+ | Check | Result |
62
+ | --- | --- |
63
+ | Core suite on Ruby 3.3.6, 3.4.7, 4.0.1 | 207 tests, 1,044 assertions per runtime |
64
+ | Optional RBS suite on those runtimes | 47 tests, 436 assertions per runtime |
65
+ | `rbs -I sig validate` on those runtimes | Passed |
66
+ | Default locked development bundle, `bundle exec rake` | Core suite passed; 115 files linted without offenses |
67
+ | `bin/check` | Syntax checks, 2 packaging tests / 76 assertions, and gem build passed |
68
+ | Fresh example processes | Initial 3/4 passing; gap 4/4 failing assertion; corrected 4/4 passing; three-input 12/12 passing |
69
+ | Constrained CLI plan | 3 required pairs, 1 explained exclusion |
70
+
71
+ CI's optional suite command now includes every `test/rbs/*_test.rb` file.
72
+ Existing method-redefinition fixture warnings and the gemspec's missing-homepage
73
+ warning remain; neither is a new failure. No dependency was added.
74
+
75
+ To keep the existing complexity budgets, option parsing, coverage projections,
76
+ and report formatting use small helpers. The full regression suite covers the
77
+ preserved scalar behavior and adapter lifecycle; no lint threshold was raised.
@@ -0,0 +1,104 @@
1
+ # Pairwise suggestion results
2
+
3
+ SpecProof can turn a completed pairwise coverage report into deterministic
4
+ allowed assignments for its missing pairs. The Ruby API is
5
+ `SpecProof.suggest(specifications, report: parsed_json)`; the CLI is
6
+ `specproof suggest SPEC.rb --report coverage.json [--rbs FILE --target TARGET]
7
+ --format json`. Suggestions always use `pairwise-finite-v1` and
8
+ `greedy-pairwise-v1`.
9
+
10
+ Before selecting assignments, SpecProof replans the supplied declarations and
11
+ checks the report's schema, kind, criterion, digest, exact typed obligation
12
+ denominator, declared scope, counters, statuses, and projections. The source
13
+ run must be completed and intact, with no errors or unknown observations.
14
+ Either Boolean `tests_passed` value is accepted and retained, and filtered
15
+ reports remain limited to their recorded scope. The result preserves the
16
+ source run ID and scope so callers can review what evidence it used.
17
+
18
+ Each suggestion is a full assignment for a declared combination group. Its
19
+ `covers` list names only newly covered missing pair IDs; the union of those
20
+ lists is the missing set. `unassigned_inputs` lists analyzed method parameters
21
+ outside the group and explicitly excluded parameters. The caller must supply
22
+ those values, and all analyzed values must still be valid for runtime evidence.
23
+ Suggestions are not executed and provide no expected outputs. They are not a
24
+ minimum-size covering set: the deterministic greedy strategy chooses the
25
+ largest current gain and breaks ties by canonical typed assignment order.
26
+
27
+ Use a separate requirement as the oracle for every assertion. A contract
28
+ digest covers normalized input declarations, not implementation or test bytes,
29
+ so rerun the intended suite after code or test changes. Suggestion work is
30
+ bounded to 10,000 cumulative full assignments, 10,000 cumulative possible pair
31
+ rows, 1,000,000 candidate-to-missing-pair memberships, and a 32 MiB input
32
+ report. Oversized work is rejected without sampling, truncation, or partial
33
+ results.
34
+
35
+ ## AllInRuby pilot
36
+
37
+ The real-project pilot used `AllInRuby::Installer#install` in a scratch copy of
38
+ the project. Its pairwise group contains the finite `scope`, `dry_run`, and
39
+ `backup` inputs. `agents` is explicitly excluded because it is a collection
40
+ parameter that each test must supply separately. The project README documents
41
+ the individual scope and option behavior used to justify the group; no
42
+ implementation-derived restriction was added.
43
+
44
+ The captured baseline passed its existing suite and observed 9 of 12 pair
45
+ obligations. The three missing pairs all fit in the allowed assignment
46
+ `scope: "global", dry_run: true, backup: false`. SpecProof returned that one
47
+ candidate and listed `agents` as unassigned. The follow-up test in the scratch
48
+ copy checks the documented dry-run preview, absence of a backup, and unchanged
49
+ file contents. The original 32 tests and 104 assertions passed; adding one test
50
+ produced 33 passing tests and 114 assertions, with 12/12 pairs exercised. The
51
+ fresh report then produced no suggestions. This is a coverage improvement,
52
+ not a discovered production defect.
53
+
54
+ The copy came from clean HEAD `bbe9921470cbf80ae01ae4fbb2de50a62187ba9e`;
55
+ the source checkout's pre-existing edits were preserved. The group is an
56
+ explicit pilot declaration based on documented independent options, not an
57
+ inferred business rule. [Retained pilot evidence](evaluations/artifacts/pairwise-suggestions/pilot/pilot-notes.md)
58
+ includes requirement citations, original tests, the added assertion, commands,
59
+ reports, and source hashes.
60
+
61
+ ## Installed-skill exercise
62
+
63
+ The installed `specproof-test-gaps` exercise used a fresh Luna actor. Its baseline
64
+ and pairwise plan describe `ToggleSummary#count` with three Boolean group
65
+ inputs and caller-supplied `context`. The current suggestion output proposes
66
+ `a: true, b: true, c: true` for the three missing pairs and lists `context` in
67
+ `unassigned_inputs`. The added assertion expects three from the separate
68
+ requirement to count true flags. It exposes the seeded defect (actual result
69
+ two): coverage reaches 12/12 while `tests_passed` stays false. Suggestion output
70
+ preserves that failed result and reports zero missing pairs. An altered
71
+ incomplete report is rejected with exit 2. The actor also refused to hide the
72
+ defect by forbidding a combination the requirements explicitly allow.
73
+
74
+ See the [skill evaluation](evaluations/pairwise-suggestions-skills.md) for the
75
+ old-guidance comparison and executable evidence.
76
+
77
+ ## Review
78
+
79
+ Independent Luna specification and quality reviews checked the evidence gate,
80
+ deterministic selection, and CLI. Review moved cumulative checks ahead of
81
+ enumeration and replaced quadratic preflight pair counting with an incremental
82
+ sum that stops at the limit. Full assignments are cached only when requested,
83
+ so ordinary coverage does not retain them. Typed report encodings are validated
84
+ explicitly; no dependency or lint threshold was added.
85
+
86
+ ## Verification
87
+
88
+ | Check | Status |
89
+ | --- | --- |
90
+ | Core suite on Ruby 3.3.6, 3.4.7, 4.0.1 | 250 tests / 1,297 assertions per runtime |
91
+ | Optional RBS suite on those runtimes | 47 tests / 436 assertions per runtime |
92
+ | RBS signature validation on those runtimes | Passed |
93
+ | Default locked development bundle, `rake` | Passed; 126 files linted without offenses |
94
+ | `bin/check` | Syntax, 2 packaging tests / 76 assertions, and gem build passed |
95
+ | AllInRuby installed-gem pilot | 9/12 to 12/12, assertions passing |
96
+ | Installed-skill exercise | 9/12 to 12/12, requirements-backed failure preserved |
97
+
98
+ Existing method-redefinition fixture warnings and the missing-homepage gemspec
99
+ warning remain. [Matrix evidence](evaluations/artifacts/pairwise-suggestions/verification/commands.json)
100
+ records exact commands and environments; the installed library and skill hashes
101
+ match the reviewed source.
102
+
103
+ For a runnable, self-contained demonstration of the API and report boundaries,
104
+ see the [pairwise suggestions example](../examples/pairwise_suggestions/README.md).