feat(opsl): vendor OPSL o1nk docs and add Swift<->OPSL parity check #2

Merged
peterswimm merged 1 commit from feat/opsl-parity into main 2026-10-04 21:41:28 +00:00
Owner

Scope

Phase 4b of the OPSL alignment: vendor the o1nk OPSL documents and add an automated parity check between O1NKParameters.swift (the AU parameter tree) and the OPSL device/layout schema, so the two stop drifting silently.

  • Vendored the four o1nk OPSL documents from opsl-public tag v0.3.0 (commit 730919c) under opsl/:
    • toilville-o1nk.sampler.device.json (role init — factory defaults + domains)
    • toilville-o1nk-punchy-drums.device.json (role patch)
    • toilville-o1nk-default.movemap.layout.json (controller layout)
    • toilville-o1nk-demo.movemap.bundle.json (demo bundle)
    • opsl/VERSION records the source tag/commit for future re-vendoring
  • Added scripts/opsl_parity.py, a standalone parity check (no test target exists in o1nk.xcodeproj — only the o1nk and o1nkAudioUnitExtension targets — so this runs outside Xcode rather than via pbxproj surgery to add one). It parses O1NKParameters.swift with regex (the file's case .x: return y switches are regular enough that this was cross-checked byte-for-byte against literally compiling the real enum with swiftc) and compares every O1NKParam case against the OPSL init device + layout for:
    • identifier membership, both directions
    • numeric range / step, or enum value count, vs the device param's domain
    • defaultValue vs the init device's state.param_values[identifier].value (mapping enum indices through domain.values where needed)
    • section grouping vs section_hint, cross-checked against the movemap layout's actual placement
  • Added scripts/opsl_parity_allowlist.json for mismatches that are real but not obviously a typo on either side — documented with notes rather than silently fixed.
  • README: how to run the check and how to re-vendor the OPSL docs later.

Testing

  • python3 scripts/opsl_parity.py — passes (exit 0). It finds 5 mismatches across 3 identifiers, all allowlisted as pending decisions (see below); no new, unallowlisted mismatch exists today.
  • Rehearsed the check against three injected-failure controls (a corrupted default value, a missing identifier, a moved section hint) to confirm it actually fails non-zero and reports the right category before trusting the green run on real data. All three failed as expected; reverted before committing.
  • xcodebuild -project o1nk.xcodeproj -scheme o1nk -destination 'platform=iOS Simulator,id=<iPad simulator>' -configuration Debug build — BUILD SUCCEEDED, including the o1nkAudioUnitExtension target (embedded as a PlugIn of the app). Simulator builds use ad hoc "Sign to Run Locally" signing, so no code-signing blocker was hit. Did not attempt a device/Release build (would need a provisioning profile).

Mismatches found — need Peter's call, nothing changed on either side

None of these looked like an obvious typo (e.g., a transposed digit or a copy-paste slip with identical surrounding context), so per instructions I left both sides alone and just documented them in scripts/opsl_parity_allowlist.json:

  1. sample.index — range: Swift O1NKParam.range is 0...127; OPSL domain is -1...127 (-1 = "no sample loaded"). Default: Swift defaultValue is 0; OPSL init state.param_values["sample.index"].value is -1. Open question: should the AU range/default be widened to include the -1 sentinel, or is 0 (first sample) intentionally the AU-side floor with -1 being host/state-only?
  2. modulation.table — same shape as above: Swift range 0...128 / default 0 vs OPSL domain -1...127 / init value -1 (-1 = "none"). Same open question about the sentinel.
  3. sample.interpolation — Swift valueStrings has 3 modes (Classic, Linear, OverSmp — each documented in-code with distinct hardware-fidelity behavior); the OPSL domain.values only lists 2 (linear, none). Looks like the OPSL doc may predate the 3-way interpolation mode, but that's a guess — needs a decision on whether to add a 3rd domain value (and pick a raw token for Classic/OverSmp) or whether the device schema intentionally restricts this to 2 values.

Impact Statement

  • Existing features: None changed. O1NKParameters.swift is untouched; this PR only adds vendored reference docs and a check script.
  • Public APIs / contracts: None changed. The AU parameter tree (identifiers, ranges, defaults) is exactly as it was before this PR.
  • Schemas: No schema changes. The vendored OPSL documents are a read-only snapshot of opsl-public v0.3.0; nothing in this repo defines or mutates the OPSL schema.
  • Data / artifacts: Adds opsl/*.json (vendored, not generated) and opsl/VERSION as new tracked files. No existing data files touched.
  • Integrations: None. The parity script runs standalone (python3 scripts/opsl_parity.py) and isn't wired into CI yet — Peter can decide separately whether/where to run it as a gate (e.g. the same python:3.12-slim-style container opsl-public's own validator uses).
  • Mappings: No mapping changes; this PR only checks the existing Swift-to-OPSL mapping, documenting where it disagrees rather than changing it.
  • Backward compatibility: Fully backward compatible — additive only (new opsl/ and scripts/ directories, README section). No existing file was modified except README.md.

Docs

  • README.md — new "OPSL parity" section: how to run scripts/opsl_parity.py, what it checks, how the allowlist works, and the step-by-step for re-vendoring opsl/*.json + opsl/VERSION from a future opsl-public tag.
## Scope Phase 4b of the OPSL alignment: vendor the o1nk OPSL documents and add an automated parity check between `O1NKParameters.swift` (the AU parameter tree) and the OPSL device/layout schema, so the two stop drifting silently. - Vendored the four o1nk OPSL documents from `opsl-public` tag `v0.3.0` (commit `730919c`) under `opsl/`: - `toilville-o1nk.sampler.device.json` (role `init` — factory defaults + domains) - `toilville-o1nk-punchy-drums.device.json` (role `patch`) - `toilville-o1nk-default.movemap.layout.json` (controller layout) - `toilville-o1nk-demo.movemap.bundle.json` (demo bundle) - `opsl/VERSION` records the source tag/commit for future re-vendoring - Added `scripts/opsl_parity.py`, a standalone parity check (no test target exists in `o1nk.xcodeproj` — only the `o1nk` and `o1nkAudioUnitExtension` targets — so this runs outside Xcode rather than via pbxproj surgery to add one). It parses `O1NKParameters.swift` with regex (the file's `case .x: return y` switches are regular enough that this was cross-checked byte-for-byte against literally compiling the real enum with `swiftc`) and compares every `O1NKParam` case against the OPSL init device + layout for: - identifier membership, both directions - numeric range / step, or enum value count, vs the device param's `domain` - `defaultValue` vs the init device's `state.param_values[identifier].value` (mapping enum indices through `domain.values` where needed) - section grouping vs `section_hint`, cross-checked against the movemap layout's actual placement - Added `scripts/opsl_parity_allowlist.json` for mismatches that are real but not obviously a typo on either side — documented with notes rather than silently fixed. - README: how to run the check and how to re-vendor the OPSL docs later. ## Testing - `python3 scripts/opsl_parity.py` — **passes** (exit 0). It finds 5 mismatches across 3 identifiers, all allowlisted as pending decisions (see below); no new, unallowlisted mismatch exists today. - Rehearsed the check against three injected-failure controls (a corrupted default value, a missing identifier, a moved section hint) to confirm it actually fails non-zero and reports the right category before trusting the green run on real data. All three failed as expected; reverted before committing. - `xcodebuild -project o1nk.xcodeproj -scheme o1nk -destination 'platform=iOS Simulator,id=<iPad simulator>' -configuration Debug build` — **BUILD SUCCEEDED**, including the `o1nkAudioUnitExtension` target (embedded as a PlugIn of the app). Simulator builds use ad hoc "Sign to Run Locally" signing, so no code-signing blocker was hit. Did not attempt a device/Release build (would need a provisioning profile). ### Mismatches found — need Peter's call, nothing changed on either side None of these looked like an obvious typo (e.g., a transposed digit or a copy-paste slip with identical surrounding context), so per instructions I left both sides alone and just documented them in `scripts/opsl_parity_allowlist.json`: 1. **`sample.index`** — range: Swift `O1NKParam.range` is `0...127`; OPSL `domain` is `-1...127` (`-1` = "no sample loaded"). Default: Swift `defaultValue` is `0`; OPSL init `state.param_values["sample.index"].value` is `-1`. Open question: should the AU range/default be widened to include the `-1` sentinel, or is `0` (first sample) intentionally the AU-side floor with `-1` being host/state-only? 2. **`modulation.table`** — same shape as above: Swift range `0...128` / default `0` vs OPSL domain `-1...127` / init value `-1` (`-1` = "none"). Same open question about the sentinel. 3. **`sample.interpolation`** — Swift `valueStrings` has 3 modes (`Classic`, `Linear`, `OverSmp` — each documented in-code with distinct hardware-fidelity behavior); the OPSL `domain.values` only lists 2 (`linear`, `none`). Looks like the OPSL doc may predate the 3-way interpolation mode, but that's a guess — needs a decision on whether to add a 3rd domain value (and pick a raw token for `Classic`/`OverSmp`) or whether the device schema intentionally restricts this to 2 values. ## Impact Statement - **Existing features:** None changed. `O1NKParameters.swift` is untouched; this PR only adds vendored reference docs and a check script. - **Public APIs / contracts:** None changed. The AU parameter tree (identifiers, ranges, defaults) is exactly as it was before this PR. - **Schemas:** No schema changes. The vendored OPSL documents are a read-only snapshot of `opsl-public` v0.3.0; nothing in this repo defines or mutates the OPSL schema. - **Data / artifacts:** Adds `opsl/*.json` (vendored, not generated) and `opsl/VERSION` as new tracked files. No existing data files touched. - **Integrations:** None. The parity script runs standalone (`python3 scripts/opsl_parity.py`) and isn't wired into CI yet — Peter can decide separately whether/where to run it as a gate (e.g. the same `python:3.12-slim`-style container `opsl-public`'s own validator uses). - **Mappings:** No mapping changes; this PR only *checks* the existing Swift-to-OPSL mapping, documenting where it disagrees rather than changing it. - **Backward compatibility:** Fully backward compatible — additive only (new `opsl/` and `scripts/` directories, README section). No existing file was modified except README.md. ## Docs - `README.md` — new "OPSL parity" section: how to run `scripts/opsl_parity.py`, what it checks, how the allowlist works, and the step-by-step for re-vendoring `opsl/*.json` + `opsl/VERSION` from a future `opsl-public` tag.
Vendors the four o1nk OPSL documents (init device, punchy-drums patch,
default movemap layout, demo bundle) from opsl-public v0.3.0 (730919c)
under opsl/, and adds scripts/opsl_parity.py to check O1NKParameters.swift
against them: identifier membership, range/enum count, defaultValue vs
the init device's state, and section grouping vs section_hint/layout.

The check passes today but documents 5 open mismatches (sample.index and
modulation.table range/default around the -1 "none" sentinel; the 2-value
vs 3-value sample.interpolation enum) in scripts/opsl_parity_allowlist.json
for Peter to decide -- none of them looked like an obvious typo, so neither
side was changed.

o1nk.xcodeproj has no test target, so this is a standalone script rather
than a Swift unit test; see the script's docstring for why Python (regex
over O1NKParameters.swift) was chosen over a Swift script.
peterswimm deleted branch feat/opsl-parity 2026-10-04 21:41:28 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
peterswimm/01nk!2
No description provided.