@riddledc/riddle-proof-packs 0.3.0 → 0.4.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.
package/dist/index.cjs CHANGED
@@ -1626,6 +1626,145 @@ 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: "run-ratchet-loop-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
+ minImprovement: 0.1
1684
+ }
1685
+ ],
1686
+ store_return_to: "__neonMixProof.ratchetLoop",
1687
+ capture_return: true,
1688
+ timeout_ms: 24e4,
1689
+ return_summary_fields: [
1690
+ {
1691
+ path: "ok"
1692
+ },
1693
+ {
1694
+ path: "status"
1695
+ },
1696
+ {
1697
+ path: "strategy"
1698
+ },
1699
+ {
1700
+ path: "improvement"
1701
+ },
1702
+ {
1703
+ path: "best.candidate.track"
1704
+ }
1705
+ ]
1706
+ },
1707
+ {
1708
+ type: "assert_window_value",
1709
+ path: "__neonMixProof.ratchetLoop.ok",
1710
+ expected_value: true,
1711
+ timeout_ms: 1e4
1712
+ },
1713
+ {
1714
+ type: "screenshot",
1715
+ label: "neon-ratchet-loop-mix-level-search",
1716
+ mode: "viewport"
1717
+ }
1718
+ ]
1719
+ },
1720
+ checks: [
1721
+ {
1722
+ type: "route_loaded",
1723
+ expected_path: "/games/drum-sequencer"
1724
+ },
1725
+ {
1726
+ type: "selector_visible",
1727
+ selector: ".drum-sequencer h1"
1728
+ },
1729
+ {
1730
+ type: "no_horizontal_overflow"
1731
+ },
1732
+ {
1733
+ type: "no_fatal_console_errors"
1734
+ }
1735
+ ],
1736
+ artifacts: [
1737
+ "screenshot",
1738
+ "console",
1739
+ "dom_summary",
1740
+ "proof_json"
1741
+ ],
1742
+ baseline_policy: "invariant_only",
1743
+ failure_policy: {
1744
+ environment_blocked: "neutral",
1745
+ proof_insufficient: "review",
1746
+ needs_human_review: "review",
1747
+ product_regression: "fail"
1748
+ },
1749
+ metadata: {
1750
+ pack_id: "neon_step_sequencer",
1751
+ pack_public_name: "Neon Step Sequencer Pack",
1752
+ evidence_role_pattern: "interaction_snapshots",
1753
+ purpose: "Run a bounded automated ratchet loop using the Neon mix-level-search strategy.",
1754
+ required_receipts: [
1755
+ "ratchet loop returns ok",
1756
+ "baseline proof-window summary is captured",
1757
+ "candidate attempts are captured",
1758
+ "best candidate or human-review status is captured"
1759
+ ],
1760
+ does_not_prove: [
1761
+ "subjective mix quality",
1762
+ "that the best objective candidate should be kept",
1763
+ "all possible mix edits"
1764
+ ]
1765
+ }
1766
+ };
1767
+
1629
1768
  // packs/neon-step-sequencer/profiles/source-readiness.json
1630
1769
  var source_readiness_default = {
1631
1770
  version: "riddle-proof.profile.v1",
@@ -2055,7 +2194,8 @@ var rawProfiles = {
2055
2194
  "neon-step-sequencer-mix-change-before-after": mix_change_before_after_default,
2056
2195
  "neon-step-sequencer-mobile-trainer-layout": mobile_trainer_layout_default,
2057
2196
  "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
2197
+ "neon-step-sequencer-explore-songs-and-mixes": explore_songs_and_mixes_default,
2198
+ "neon-step-sequencer-ratchet-loop-mix-level-search": ratchet_loop_mix_level_search_default
2059
2199
  };
2060
2200
  var sourcePathOverrides = Object.freeze({
2061
2201
  "neon-step-sequencer-fast-mix-health": "packs/neon-step-sequencer/profiles/fast-mix-health.json",
@@ -2064,7 +2204,8 @@ var sourcePathOverrides = Object.freeze({
2064
2204
  "neon-step-sequencer-mix-change-before-after": "packs/neon-step-sequencer/profiles/mix-change-before-after.json",
2065
2205
  "neon-step-sequencer-mobile-trainer-layout": "packs/neon-step-sequencer/profiles/mobile-trainer-layout.json",
2066
2206
  "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"
2207
+ "neon-step-sequencer-explore-songs-and-mixes": "packs/neon-step-sequencer/profiles/explore-songs-and-mixes.json",
2208
+ "neon-step-sequencer-ratchet-loop-mix-level-search": "packs/neon-step-sequencer/profiles/ratchet-loop-mix-level-search.json"
2068
2209
  });
2069
2210
  var RIDDLE_PROOF_PACK_PROFILES = Object.freeze(
2070
2211
  Object.fromEntries(
package/dist/index.js CHANGED
@@ -1591,6 +1591,145 @@ 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: "run-ratchet-loop-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
+ minImprovement: 0.1
1649
+ }
1650
+ ],
1651
+ store_return_to: "__neonMixProof.ratchetLoop",
1652
+ capture_return: true,
1653
+ timeout_ms: 24e4,
1654
+ return_summary_fields: [
1655
+ {
1656
+ path: "ok"
1657
+ },
1658
+ {
1659
+ path: "status"
1660
+ },
1661
+ {
1662
+ path: "strategy"
1663
+ },
1664
+ {
1665
+ path: "improvement"
1666
+ },
1667
+ {
1668
+ path: "best.candidate.track"
1669
+ }
1670
+ ]
1671
+ },
1672
+ {
1673
+ type: "assert_window_value",
1674
+ path: "__neonMixProof.ratchetLoop.ok",
1675
+ expected_value: true,
1676
+ timeout_ms: 1e4
1677
+ },
1678
+ {
1679
+ type: "screenshot",
1680
+ label: "neon-ratchet-loop-mix-level-search",
1681
+ mode: "viewport"
1682
+ }
1683
+ ]
1684
+ },
1685
+ checks: [
1686
+ {
1687
+ type: "route_loaded",
1688
+ expected_path: "/games/drum-sequencer"
1689
+ },
1690
+ {
1691
+ type: "selector_visible",
1692
+ selector: ".drum-sequencer h1"
1693
+ },
1694
+ {
1695
+ type: "no_horizontal_overflow"
1696
+ },
1697
+ {
1698
+ type: "no_fatal_console_errors"
1699
+ }
1700
+ ],
1701
+ artifacts: [
1702
+ "screenshot",
1703
+ "console",
1704
+ "dom_summary",
1705
+ "proof_json"
1706
+ ],
1707
+ baseline_policy: "invariant_only",
1708
+ failure_policy: {
1709
+ environment_blocked: "neutral",
1710
+ proof_insufficient: "review",
1711
+ needs_human_review: "review",
1712
+ product_regression: "fail"
1713
+ },
1714
+ metadata: {
1715
+ pack_id: "neon_step_sequencer",
1716
+ pack_public_name: "Neon Step Sequencer Pack",
1717
+ evidence_role_pattern: "interaction_snapshots",
1718
+ purpose: "Run a bounded automated ratchet loop using the Neon mix-level-search strategy.",
1719
+ required_receipts: [
1720
+ "ratchet loop returns ok",
1721
+ "baseline proof-window summary is captured",
1722
+ "candidate attempts are captured",
1723
+ "best candidate or human-review status is captured"
1724
+ ],
1725
+ does_not_prove: [
1726
+ "subjective mix quality",
1727
+ "that the best objective candidate should be kept",
1728
+ "all possible mix edits"
1729
+ ]
1730
+ }
1731
+ };
1732
+
1594
1733
  // packs/neon-step-sequencer/profiles/source-readiness.json
1595
1734
  var source_readiness_default = {
1596
1735
  version: "riddle-proof.profile.v1",
@@ -2020,7 +2159,8 @@ var rawProfiles = {
2020
2159
  "neon-step-sequencer-mix-change-before-after": mix_change_before_after_default,
2021
2160
  "neon-step-sequencer-mobile-trainer-layout": mobile_trainer_layout_default,
2022
2161
  "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
2162
+ "neon-step-sequencer-explore-songs-and-mixes": explore_songs_and_mixes_default,
2163
+ "neon-step-sequencer-ratchet-loop-mix-level-search": ratchet_loop_mix_level_search_default
2024
2164
  };
2025
2165
  var sourcePathOverrides = Object.freeze({
2026
2166
  "neon-step-sequencer-fast-mix-health": "packs/neon-step-sequencer/profiles/fast-mix-health.json",
@@ -2029,7 +2169,8 @@ var sourcePathOverrides = Object.freeze({
2029
2169
  "neon-step-sequencer-mix-change-before-after": "packs/neon-step-sequencer/profiles/mix-change-before-after.json",
2030
2170
  "neon-step-sequencer-mobile-trainer-layout": "packs/neon-step-sequencer/profiles/mobile-trainer-layout.json",
2031
2171
  "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"
2172
+ "neon-step-sequencer-explore-songs-and-mixes": "packs/neon-step-sequencer/profiles/explore-songs-and-mixes.json",
2173
+ "neon-step-sequencer-ratchet-loop-mix-level-search": "packs/neon-step-sequencer/profiles/ratchet-loop-mix-level-search.json"
2033
2174
  });
2034
2175
  var RIDDLE_PROOF_PACK_PROFILES = Object.freeze(
2035
2176
  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.0",
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 tries small level edits against Neon proof windows and returns objective evidence for the best candidate. 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 candidates and returned `chord -0.10` as the best objective candidate without keeping the edit.
38
46
 
39
47
  ## Naming note
40
48
 
@@ -90,9 +90,20 @@ 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 candidate edits, collect proof-window evidence, rank candidates, and restore state.
97
+ - observed evidence: `mix-level-search` tested `6` candidates; baseline score was `28.83345`; best score was `27.0708`; best candidate was `chord -0.10` to level `0.28`; loop status was `candidate_found`; console fatal count was `0`.
98
+ - classification: none; passing `interaction_snapshots` proof with subjective listening caveat.
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.
@@ -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` candidates, returned `chord -0.10` as the best objective candidate, 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,58 @@ 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 candidates, applies each candidate, captures proof-window evidence, ranks candidates by objective metrics, 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 proof-window score
189
+ - per-candidate proof-window score
190
+ - best candidate and objective improvement
191
+ - state restoration receipt
192
+ - compact caveats for human handoff
192
193
 
193
- Expected outcome:
194
+ Possible outcomes:
195
+
196
+ - `candidate_found`: at least one candidate improves objective metrics.
197
+ - `needs_human_review`: evidence is valid but no objective candidate clears the threshold.
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 score `28.83345`
210
+ - best score `27.0708`
211
+ - objective improvement `1.7627`
212
+ - best candidate `chord -0.10` to level `0.28`
213
+ - loop status `candidate_found`
214
+ - app state restored after the run
215
+ - console fatal count `0`
194
216
 
195
- Either a clean confidence map or a prioritized finding list.
217
+ Failure classification:
218
+
219
+ None. This was a passing `interaction_snapshots` loop proof, with an explicit listening-review caveat.
220
+
221
+ Smallest layer changed:
222
+
223
+ The app proof contract gained a generic `runRatchetLoop` method. The Neon-specific part is the `mix-level-search` strategy.
224
+
225
+ Next sharper question:
226
+
227
+ Can the pack explore song/mix combinations and produce a prioritized confidence map?
196
228
 
197
229
  ## Project note
198
230
 
@@ -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 candidate, apply it, collect evidence, classify the result, 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 candidates, returns the best objective candidate, and restores app state. |
14
15
 
15
16
  ## What these examples do not prove
16
17
 
@@ -18,3 +19,4 @@ 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.