@riddledc/riddle-proof-packs 0.3.0 → 0.4.1

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.
package/dist/index.cjs CHANGED
@@ -1626,6 +1626,149 @@ var playback_sync_default = {
1626
1626
  }
1627
1627
  };
1628
1628
 
1629
+ // packs/neon-step-sequencer/profiles/ratchet-loop-mix-level-search.json
1630
+ var ratchet_loop_mix_level_search_default = {
1631
+ version: "riddle-proof.profile.v1",
1632
+ name: "neon-step-sequencer-ratchet-loop-mix-level-search",
1633
+ target: {
1634
+ route: "/games/drum-sequencer?song=monkberry-moon-delight-tab&mix=profile&view=trainer&instrument=bass",
1635
+ viewports: [
1636
+ {
1637
+ name: "desktop",
1638
+ width: 1440,
1639
+ height: 1e3
1640
+ }
1641
+ ],
1642
+ timeout_sec: 360,
1643
+ wait_for_selector: ".drum-sequencer h1",
1644
+ setup_actions: [
1645
+ {
1646
+ type: "window_eval",
1647
+ label: "capture-neon-contract",
1648
+ timeout_ms: 1e4,
1649
+ store_return_to: "__neonMixProof.contract",
1650
+ script: "const contract=window.__NEON_MIX_PROOF__; const diagnostic=contract?.captureDiagnostic?.(); window.__neonMixProof={...(window.__neonMixProof||{}),contract:{available:Boolean(contract),diagnostic}}; return window.__neonMixProof.contract;",
1651
+ return_summary_fields: [
1652
+ {
1653
+ path: "available"
1654
+ },
1655
+ {
1656
+ path: "diagnostic.selectedSong.selectedSong"
1657
+ }
1658
+ ]
1659
+ },
1660
+ {
1661
+ type: "assert_window_value",
1662
+ path: "__neonMixProof.contract.available",
1663
+ expected_value: true,
1664
+ timeout_ms: 1e4
1665
+ },
1666
+ {
1667
+ type: "window_call",
1668
+ label: "test-claim-candidates-mix-level-search",
1669
+ path: "__NEON_MIX_PROOF__.runRatchetLoop",
1670
+ args: [
1671
+ {
1672
+ strategy: "mix-level-search",
1673
+ focusTracks: [
1674
+ "bass",
1675
+ "chord",
1676
+ "guitar",
1677
+ "rhythmSynth"
1678
+ ],
1679
+ maxIterations: 6,
1680
+ monitorProfile: "smallSpeaker",
1681
+ restore: true,
1682
+ applyBest: false
1683
+ }
1684
+ ],
1685
+ store_return_to: "__neonMixProof.ratchetLoop",
1686
+ capture_return: true,
1687
+ timeout_ms: 24e4,
1688
+ return_summary_fields: [
1689
+ {
1690
+ path: "ok"
1691
+ },
1692
+ {
1693
+ path: "status"
1694
+ },
1695
+ {
1696
+ path: "strategy"
1697
+ },
1698
+ {
1699
+ path: "best.claimVerdict.status"
1700
+ },
1701
+ {
1702
+ path: "best.claimCandidate.action.track"
1703
+ },
1704
+ {
1705
+ path: "supportedClaimCandidateCount"
1706
+ }
1707
+ ]
1708
+ },
1709
+ {
1710
+ type: "assert_window_value",
1711
+ path: "__neonMixProof.ratchetLoop.ok",
1712
+ expected_value: true,
1713
+ timeout_ms: 1e4
1714
+ },
1715
+ {
1716
+ type: "screenshot",
1717
+ label: "neon-ratchet-loop-mix-level-search",
1718
+ mode: "viewport"
1719
+ }
1720
+ ]
1721
+ },
1722
+ checks: [
1723
+ {
1724
+ type: "route_loaded",
1725
+ expected_path: "/games/drum-sequencer"
1726
+ },
1727
+ {
1728
+ type: "selector_visible",
1729
+ selector: ".drum-sequencer h1"
1730
+ },
1731
+ {
1732
+ type: "no_horizontal_overflow"
1733
+ },
1734
+ {
1735
+ type: "no_fatal_console_errors"
1736
+ }
1737
+ ],
1738
+ artifacts: [
1739
+ "screenshot",
1740
+ "console",
1741
+ "dom_summary",
1742
+ "proof_json"
1743
+ ],
1744
+ baseline_policy: "invariant_only",
1745
+ failure_policy: {
1746
+ environment_blocked: "neutral",
1747
+ proof_insufficient: "review",
1748
+ needs_human_review: "review",
1749
+ product_regression: "fail"
1750
+ },
1751
+ metadata: {
1752
+ pack_id: "neon_step_sequencer",
1753
+ pack_public_name: "Neon Step Sequencer Pack",
1754
+ evidence_role_pattern: "interaction_snapshots",
1755
+ purpose: "Run a bounded loop that tests Neon mix-level change-claim candidates using the mix-level-search strategy.",
1756
+ required_receipts: [
1757
+ "ratchet loop returns ok",
1758
+ "baseline proof-window summary is captured",
1759
+ "claim candidates are captured",
1760
+ "each candidate records claim receipts",
1761
+ "best supported claim candidate or human-review status is captured",
1762
+ "state restoration receipt is captured"
1763
+ ],
1764
+ does_not_prove: [
1765
+ "subjective mix quality",
1766
+ "that a supported claim candidate should be kept",
1767
+ "all possible mix edits"
1768
+ ]
1769
+ }
1770
+ };
1771
+
1629
1772
  // packs/neon-step-sequencer/profiles/source-readiness.json
1630
1773
  var source_readiness_default = {
1631
1774
  version: "riddle-proof.profile.v1",
@@ -2055,7 +2198,8 @@ var rawProfiles = {
2055
2198
  "neon-step-sequencer-mix-change-before-after": mix_change_before_after_default,
2056
2199
  "neon-step-sequencer-mobile-trainer-layout": mobile_trainer_layout_default,
2057
2200
  "neon-step-sequencer-full-mix-health-matrix": full_mix_health_matrix_default,
2058
- "neon-step-sequencer-explore-songs-and-mixes": explore_songs_and_mixes_default
2201
+ "neon-step-sequencer-explore-songs-and-mixes": explore_songs_and_mixes_default,
2202
+ "neon-step-sequencer-ratchet-loop-mix-level-search": ratchet_loop_mix_level_search_default
2059
2203
  };
2060
2204
  var sourcePathOverrides = Object.freeze({
2061
2205
  "neon-step-sequencer-fast-mix-health": "packs/neon-step-sequencer/profiles/fast-mix-health.json",
@@ -2064,7 +2208,8 @@ var sourcePathOverrides = Object.freeze({
2064
2208
  "neon-step-sequencer-mix-change-before-after": "packs/neon-step-sequencer/profiles/mix-change-before-after.json",
2065
2209
  "neon-step-sequencer-mobile-trainer-layout": "packs/neon-step-sequencer/profiles/mobile-trainer-layout.json",
2066
2210
  "neon-step-sequencer-full-mix-health-matrix": "packs/neon-step-sequencer/profiles/full-mix-health-matrix.json",
2067
- "neon-step-sequencer-explore-songs-and-mixes": "packs/neon-step-sequencer/profiles/explore-songs-and-mixes.json"
2211
+ "neon-step-sequencer-explore-songs-and-mixes": "packs/neon-step-sequencer/profiles/explore-songs-and-mixes.json",
2212
+ "neon-step-sequencer-ratchet-loop-mix-level-search": "packs/neon-step-sequencer/profiles/ratchet-loop-mix-level-search.json"
2068
2213
  });
2069
2214
  var RIDDLE_PROOF_PACK_PROFILES = Object.freeze(
2070
2215
  Object.fromEntries(
package/dist/index.js CHANGED
@@ -1591,6 +1591,149 @@ var playback_sync_default = {
1591
1591
  }
1592
1592
  };
1593
1593
 
1594
+ // packs/neon-step-sequencer/profiles/ratchet-loop-mix-level-search.json
1595
+ var ratchet_loop_mix_level_search_default = {
1596
+ version: "riddle-proof.profile.v1",
1597
+ name: "neon-step-sequencer-ratchet-loop-mix-level-search",
1598
+ target: {
1599
+ route: "/games/drum-sequencer?song=monkberry-moon-delight-tab&mix=profile&view=trainer&instrument=bass",
1600
+ viewports: [
1601
+ {
1602
+ name: "desktop",
1603
+ width: 1440,
1604
+ height: 1e3
1605
+ }
1606
+ ],
1607
+ timeout_sec: 360,
1608
+ wait_for_selector: ".drum-sequencer h1",
1609
+ setup_actions: [
1610
+ {
1611
+ type: "window_eval",
1612
+ label: "capture-neon-contract",
1613
+ timeout_ms: 1e4,
1614
+ store_return_to: "__neonMixProof.contract",
1615
+ script: "const contract=window.__NEON_MIX_PROOF__; const diagnostic=contract?.captureDiagnostic?.(); window.__neonMixProof={...(window.__neonMixProof||{}),contract:{available:Boolean(contract),diagnostic}}; return window.__neonMixProof.contract;",
1616
+ return_summary_fields: [
1617
+ {
1618
+ path: "available"
1619
+ },
1620
+ {
1621
+ path: "diagnostic.selectedSong.selectedSong"
1622
+ }
1623
+ ]
1624
+ },
1625
+ {
1626
+ type: "assert_window_value",
1627
+ path: "__neonMixProof.contract.available",
1628
+ expected_value: true,
1629
+ timeout_ms: 1e4
1630
+ },
1631
+ {
1632
+ type: "window_call",
1633
+ label: "test-claim-candidates-mix-level-search",
1634
+ path: "__NEON_MIX_PROOF__.runRatchetLoop",
1635
+ args: [
1636
+ {
1637
+ strategy: "mix-level-search",
1638
+ focusTracks: [
1639
+ "bass",
1640
+ "chord",
1641
+ "guitar",
1642
+ "rhythmSynth"
1643
+ ],
1644
+ maxIterations: 6,
1645
+ monitorProfile: "smallSpeaker",
1646
+ restore: true,
1647
+ applyBest: false
1648
+ }
1649
+ ],
1650
+ store_return_to: "__neonMixProof.ratchetLoop",
1651
+ capture_return: true,
1652
+ timeout_ms: 24e4,
1653
+ return_summary_fields: [
1654
+ {
1655
+ path: "ok"
1656
+ },
1657
+ {
1658
+ path: "status"
1659
+ },
1660
+ {
1661
+ path: "strategy"
1662
+ },
1663
+ {
1664
+ path: "best.claimVerdict.status"
1665
+ },
1666
+ {
1667
+ path: "best.claimCandidate.action.track"
1668
+ },
1669
+ {
1670
+ path: "supportedClaimCandidateCount"
1671
+ }
1672
+ ]
1673
+ },
1674
+ {
1675
+ type: "assert_window_value",
1676
+ path: "__neonMixProof.ratchetLoop.ok",
1677
+ expected_value: true,
1678
+ timeout_ms: 1e4
1679
+ },
1680
+ {
1681
+ type: "screenshot",
1682
+ label: "neon-ratchet-loop-mix-level-search",
1683
+ mode: "viewport"
1684
+ }
1685
+ ]
1686
+ },
1687
+ checks: [
1688
+ {
1689
+ type: "route_loaded",
1690
+ expected_path: "/games/drum-sequencer"
1691
+ },
1692
+ {
1693
+ type: "selector_visible",
1694
+ selector: ".drum-sequencer h1"
1695
+ },
1696
+ {
1697
+ type: "no_horizontal_overflow"
1698
+ },
1699
+ {
1700
+ type: "no_fatal_console_errors"
1701
+ }
1702
+ ],
1703
+ artifacts: [
1704
+ "screenshot",
1705
+ "console",
1706
+ "dom_summary",
1707
+ "proof_json"
1708
+ ],
1709
+ baseline_policy: "invariant_only",
1710
+ failure_policy: {
1711
+ environment_blocked: "neutral",
1712
+ proof_insufficient: "review",
1713
+ needs_human_review: "review",
1714
+ product_regression: "fail"
1715
+ },
1716
+ metadata: {
1717
+ pack_id: "neon_step_sequencer",
1718
+ pack_public_name: "Neon Step Sequencer Pack",
1719
+ evidence_role_pattern: "interaction_snapshots",
1720
+ purpose: "Run a bounded loop that tests Neon mix-level change-claim candidates using the mix-level-search strategy.",
1721
+ required_receipts: [
1722
+ "ratchet loop returns ok",
1723
+ "baseline proof-window summary is captured",
1724
+ "claim candidates are captured",
1725
+ "each candidate records claim receipts",
1726
+ "best supported claim candidate or human-review status is captured",
1727
+ "state restoration receipt is captured"
1728
+ ],
1729
+ does_not_prove: [
1730
+ "subjective mix quality",
1731
+ "that a supported claim candidate should be kept",
1732
+ "all possible mix edits"
1733
+ ]
1734
+ }
1735
+ };
1736
+
1594
1737
  // packs/neon-step-sequencer/profiles/source-readiness.json
1595
1738
  var source_readiness_default = {
1596
1739
  version: "riddle-proof.profile.v1",
@@ -2020,7 +2163,8 @@ var rawProfiles = {
2020
2163
  "neon-step-sequencer-mix-change-before-after": mix_change_before_after_default,
2021
2164
  "neon-step-sequencer-mobile-trainer-layout": mobile_trainer_layout_default,
2022
2165
  "neon-step-sequencer-full-mix-health-matrix": full_mix_health_matrix_default,
2023
- "neon-step-sequencer-explore-songs-and-mixes": explore_songs_and_mixes_default
2166
+ "neon-step-sequencer-explore-songs-and-mixes": explore_songs_and_mixes_default,
2167
+ "neon-step-sequencer-ratchet-loop-mix-level-search": ratchet_loop_mix_level_search_default
2024
2168
  };
2025
2169
  var sourcePathOverrides = Object.freeze({
2026
2170
  "neon-step-sequencer-fast-mix-health": "packs/neon-step-sequencer/profiles/fast-mix-health.json",
@@ -2029,7 +2173,8 @@ var sourcePathOverrides = Object.freeze({
2029
2173
  "neon-step-sequencer-mix-change-before-after": "packs/neon-step-sequencer/profiles/mix-change-before-after.json",
2030
2174
  "neon-step-sequencer-mobile-trainer-layout": "packs/neon-step-sequencer/profiles/mobile-trainer-layout.json",
2031
2175
  "neon-step-sequencer-full-mix-health-matrix": "packs/neon-step-sequencer/profiles/full-mix-health-matrix.json",
2032
- "neon-step-sequencer-explore-songs-and-mixes": "packs/neon-step-sequencer/profiles/explore-songs-and-mixes.json"
2176
+ "neon-step-sequencer-explore-songs-and-mixes": "packs/neon-step-sequencer/profiles/explore-songs-and-mixes.json",
2177
+ "neon-step-sequencer-ratchet-loop-mix-level-search": "packs/neon-step-sequencer/profiles/ratchet-loop-mix-level-search.json"
2033
2178
  });
2034
2179
  var RIDDLE_PROOF_PACK_PROFILES = Object.freeze(
2035
2180
  Object.fromEntries(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof-packs",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Reusable proof pack profiles and metadata helpers for the Riddle proof framework.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",
@@ -27,14 +27,22 @@ This pack is the first app-specific lab for the open Riddle Proof architecture.
27
27
  - `profiles/mobile-trainer-layout.json`: current-target audit for phone/tablet trainer reachability.
28
28
  - `profiles/full-mix-health-matrix.json`: current-target matrix across desktop, phone, iPad Mini, and iPad.
29
29
  - `profiles/explore-songs-and-mixes.json`: exploration sweep for proof-window health.
30
+ - `profiles/ratchet-loop-mix-level-search.json`: bounded ratchet loop using the Neon `mix-level-search` strategy.
31
+
32
+ ## Ratchet loop strategy
33
+
34
+ The loop is not mix-specific as a proof concept. The proof concept is a bounded ratchet loop: propose a candidate, apply it, collect evidence, classify the result, restore or keep state, and repeat until the budget is exhausted.
35
+
36
+ This pack's first concrete strategy is `mix-level-search`, which turns small level edits into change-claim candidates. Each candidate says what action will be attempted, what receipts must support the claim, and what evidence should be reviewed afterward. The loop may include a ranking metric to order review, but the verdict comes from receipts and invariants, not from a universal mix-quality number. It still does not decide subjective mix taste; the output is a listening and review packet.
30
37
 
31
38
  ## Example evidence
32
39
 
33
- The `examples/` directory contains three local Playwright proof results captured against LilArcade Neon Step Sequencer on May 24, 2026:
40
+ The `examples/` directory contains four local Playwright proof results captured against LilArcade Neon Step Sequencer on May 24, 2026:
34
41
 
35
42
  - `run-001-fast-mix-health`: passing `current_target` audit with proof contract, source readiness, mix RMS `0.1234`, peak `0.8321`, and no clipping.
36
43
  - `run-002-mix-change`: passing `interaction_snapshots` proof where a bass-level edit moved bass RMS from `0.0507` to `0.1071` and mix RMS from `0.073` to `0.1264` without clipping.
37
44
  - `run-003-full-matrix`: passing `current_target` viewport matrix across desktop, phone, iPad Mini, and iPad with `0 px` horizontal overflow.
45
+ - `run-004-ratchet-loop-mix-level-search`: passing `interaction_snapshots` proof where a bounded loop tested six mix-level change-claim candidates, found a supported `chord -0.10` candidate, recorded receipt-level verdicts, and restored app state without keeping the edit.
38
46
 
39
47
  ## Naming note
40
48
 
@@ -41,7 +41,7 @@ Profile render window, song fixture, or authoring guide.
41
41
 
42
42
  ### Subjective boundary
43
43
 
44
- Metrics pass, but deciding whether the mix is better requires listening.
44
+ Receipts can support that a requested mix-level change happened and stayed inside guardrails, but deciding whether the mix is musically better requires listening.
45
45
 
46
46
  Likely change:
47
47
 
@@ -90,13 +90,24 @@ Pack summary guidance first; Riddle Proof core only if a general display primiti
90
90
  - rerun: passed on May 24, 2026.
91
91
  - next sharper question: can the exploration profile produce a prioritized song/mix confidence map?
92
92
 
93
+ ### Run 004 proved the bounded loop shape without making it mix-specific
94
+
95
+ - run: `run-004-ratchet-loop-mix-level-search`
96
+ - claim: a bounded ratchet loop can try change-claim candidates, collect proof-window evidence, record receipt verdicts, select a supported candidate for review, and restore state.
97
+ - observed evidence: `mix-level-search` tested `6` candidates; baseline candidate-ranking metric was `28.8336`; best candidate-ranking metric was `27.07095`; best supported claim candidate was `chord -0.10` to level `0.28`; loop status was `claim_candidate_supported`; receipt checks covered edit acceptance, contract level agreement, rendered target metric movement, required instrument activity, no clipping, and no low-level proof window; console fatal count was `0`.
98
+ - classification: none; passing `interaction_snapshots` proof with subjective listening caveat. The ranking metric is a review-order hint, not a proof verdict.
99
+ - smallest layer changed: generic app proof-contract loop plus one Neon strategy.
100
+ - change made: added `runRatchetLoop` with a `mix-level-search` strategy and a proof-pack profile that calls it.
101
+ - rerun: passed on May 24, 2026.
102
+ - next sharper question: can the loop run multiple strategy classes without changing the proof primitive?
103
+
93
104
  ### Local runner shutdown needs a small ergonomics follow-up
94
105
 
95
- - run: `run-002-mix-change`, `run-003-full-matrix`
106
+ - run: `run-002-mix-change`, `run-003-full-matrix`, `run-004-ratchet-loop-mix-level-search`
96
107
  - claim: proof artifacts should be written and the CLI process should exit cleanly.
97
108
  - observed evidence: complete passing artifacts were written, but the wrapper process lingered after artifact write and had to be stopped.
98
109
  - classification: `proof_insufficient` for operator ergonomics, not a Neon product regression.
99
110
  - smallest layer changed: none in this pack.
100
- - change made: documented the issue and used an outer timeout for the matrix run.
101
- - rerun: not yet rerun after a runner fix.
111
+ - change made: fixed the local Playwright runner timeout cleanup in `@riddledc/riddle-proof-runner-playwright`.
112
+ - rerun: later runner smoke tests and the published `0.4.3` package exited cleanly.
102
113
  - next sharper question: should the local runner force-close browser handles or expose a clearer artifact-written exit phase?
@@ -33,7 +33,8 @@ The project shows that a complex audio app can improve proof confidence mostly b
33
33
  - Run 001: a `current_target` audit connected the Neon route, proof contract, source readiness, and offline mix-health metrics.
34
34
  - Run 002: an `interaction_snapshots` proof showed a bass-level edit moving bass RMS from `0.0507` to `0.1071` and mix RMS from `0.073` to `0.1264` without clipping.
35
35
  - Run 003: a `current_target` matrix passed across desktop, phone, iPad Mini, and iPad with `0 px` horizontal overflow.
36
+ - Run 004: a bounded loop tested six `mix-level-search` change-claim candidates, returned `chord -0.10` as a supported review candidate with receipt-level evidence, and restored app state.
36
37
 
37
38
  ## Honest boundary
38
39
 
39
- These runs prove objective claims about a running app target. They do not prove that the mix is tasteful, that every song section is healthy, or that a release candidate is better than production. Those are separate proof claims with separate evidence roles.
40
+ These runs prove objective claims about a running app target. They do not prove that the mix is tasteful, that every song section is healthy, or that a release candidate is better than production. The ratchet loop is a generic proof-loop shape; `mix-level-search` is only the first Neon strategy plugged into it.
@@ -173,26 +173,59 @@ Next sharper question:
173
173
 
174
174
  Can the pack explore song/mix combinations and produce a prioritized confidence map?
175
175
 
176
- ## Run 004 - Exploration sweep
176
+ ## Run 004 - Bounded mix-level ratchet loop
177
177
 
178
178
  Claim:
179
179
 
180
- The pack can identify which proof windows or song/mix combinations need attention.
180
+ Neon can run a bounded ratchet loop that proposes mix-level change-claim candidates, applies each candidate action, captures proof-window evidence, records receipt-level verdicts, selects a supported candidate for review, and restores app state.
181
181
 
182
182
  Profile:
183
183
 
184
- `profiles/explore-songs-and-mixes.json`
184
+ `profiles/ratchet-loop-mix-level-search.json`
185
185
 
186
186
  Evidence to capture:
187
187
 
188
- - app-provided proof windows
189
- - window-level render verdicts
190
- - failing or review-needed windows
191
- - compact summary for human handoff
188
+ - baseline candidate-ranking metric
189
+ - per-candidate receipt verdicts
190
+ - supported claim candidate and ranking metric delta
191
+ - state restoration receipt
192
+ - compact caveats for human handoff
192
193
 
193
- Expected outcome:
194
+ Possible outcomes:
195
+
196
+ - `claim_candidate_supported`: at least one candidate has the receipts needed to support its change claim.
197
+ - `needs_human_review`: evidence is valid but no candidate has enough receipts to support the proposed claim automatically.
198
+ - `proof_insufficient`: the app contract or proof window does not provide enough evidence.
199
+ - `profile_calibration`: the chosen tracks, windows, or thresholds do not fit the target.
200
+
201
+ Observed status:
202
+
203
+ Passed on May 24, 2026 with `local-playwright`.
204
+
205
+ Observed evidence:
206
+
207
+ - strategy `mix-level-search`
208
+ - tested `6` candidates across `bass`, `chord`, `guitar`, and `rhythmSynth`
209
+ - baseline candidate-ranking metric `28.8336`
210
+ - best candidate-ranking metric `27.07095`
211
+ - ranking metric delta `1.7627`
212
+ - best supported claim candidate `chord -0.10` to level `0.28`
213
+ - claim receipts recorded for edit acceptance, contract level agreement, rendered target metric movement, required instrument activity, no clipping, and no low-level proof window
214
+ - loop status `claim_candidate_supported`
215
+ - app state restored after the run
216
+ - console fatal count `0`
194
217
 
195
- Either a clean confidence map or a prioritized finding list.
218
+ Failure classification:
219
+
220
+ None. This was a passing `interaction_snapshots` loop proof, with an explicit listening-review caveat and a ranking metric that is only a review-order hint.
221
+
222
+ Smallest layer changed:
223
+
224
+ The app proof contract gained a generic `runRatchetLoop` method. The Neon-specific part is the `mix-level-search` strategy.
225
+
226
+ Next sharper question:
227
+
228
+ Can the pack explore song/mix combinations and produce a prioritized confidence map?
196
229
 
197
230
  ## Project note
198
231
 
@@ -25,3 +25,7 @@ Large metrics belong in artifacts. The summary should answer:
25
25
  ## Core changes are last
26
26
 
27
27
  Most ratchet steps should change profile JSON, pack docs, app proof contracts, or app fixtures. Riddle Proof core changes are justified only when the missing primitive applies beyond Neon.
28
+
29
+ ## Loops are generic
30
+
31
+ A ratchet loop should be domain-neutral: propose a claim candidate, apply its action, collect evidence, classify receipt-level support, restore or keep state, and repeat within a budget. Neon `mix-level-search` is a strategy plugged into that loop, not the loop's identity.
@@ -11,6 +11,7 @@ The raw `profile-result.json` files are real runner outputs. They intentionally
11
11
  | `run-001-fast-mix-health` | `current_target` | passed | The current Neon target exposes a proof contract, source receipts, and a bounded offline mix-health render. |
12
12
  | `run-002-mix-change` | `interaction_snapshots` | passed | A bass-level edit changes rendered bass and mix metrics without clipping. |
13
13
  | `run-003-full-matrix` | `current_target` | passed | The mix-health proof holds across desktop, phone, iPad Mini, and iPad viewports. |
14
+ | `run-004-ratchet-loop-mix-level-search` | `interaction_snapshots` | passed | A bounded ratchet loop tests mix-level change-claim candidates, records receipt verdicts, chooses a supported candidate for review, and restores app state. |
14
15
 
15
16
  ## What these examples do not prove
16
17
 
@@ -18,3 +19,5 @@ The raw `profile-result.json` files are real runner outputs. They intentionally
18
19
  - They do not prove every song, section, or mix preset.
19
20
  - They do not prove production CDN asset availability; these were local dev-server runs.
20
21
  - They do not prove a reference/candidate release delta. The mix-change run uses pre-action/post-action snapshots inside one proof run, not a separate baseline deployment.
22
+ - The ratchet-loop run does not prove that the loop primitive is mix-specific; `mix-level-search` is only this pack's first concrete strategy.
23
+ - The ratchet-loop run does not prove that the supported candidate should be kept. Its ranking metric is a review-order hint, not a taste verdict.