Phase 6C: add real-world MIDI playback corpus lane - #89
EmergentMonk wants to merge 52 commits into
Conversation
There was a problem hiding this comment.
Sorry @EmergentMonk, you've used your own review budget of 250,000 diff characters for the last 7 days.
You can request another review in 1 day and 23 hours by commenting @sourcery-ai review. Upgrade to get a review now.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex Please Review this exact SHA 88c105a against the existing contract. Report only actionable correctness defects, with a minimal reproduction, expected versus actual behavior, and affected lines. State whether each reproduction was executed or statically inferred. Don’t repeat fixed findings without a new failing case. Keep architectural suggestions separate and non-blocking. This PR implements the current MIDI real-world corpus roadmap item. Review especially: manifest-pinned private corpus identity, standard-library SMF analysis, cross-track polyphony/overlap accounting, the boundary between untouched native MidiLoader import and the deterministic Sampulse audibility projection, raw MIDI/ZIP privacy exclusion, frozen-candidate representative direct-load evidence, and self-contained public component summaries. Original Psycle remains explicitly unobserved/unclassified in this donor-first phase. |
Reviewer's GuideThis PR introduces a private, manifest-bound real-world MIDI corpus lane with standard-library source analysis, native C-Psycle import evidence, a clearly separated deterministic Sampulse execution projection, frozen candidate direct-load observations, privacy-safe artifacts, and a continuously exercised synthetic CI path; all results remain observational with parity_status UNKNOWN. Sequence diagram for MIDI corpus donor observation and playback projectionsequenceDiagram
participant Workflow as PrivateWorkflow
participant Analyzer as phase6c-midi-corpus.py
participant Probe as MidiCorpusProbe
participant Loader as SongReader_MidiLoader
participant Player as Player
participant FileOut as FileOutDriver
Workflow->>Analyzer: prepare-bundle
Analyzer->>Analyzer: parse_smf
Analyzer-->>Workflow: manifest-bound private stems
Workflow->>Probe: process stem
Probe->>Loader: load MThd SMF
Loader-->>Probe: untouched imported tracker graph
Probe->>Probe: digest imported events
Probe->>Probe: attach deterministic Sampulse substrate
Probe->>Player: render 16-beat projection
Player->>FileOut: write transient WAV
FileOut-->>Probe: non-silent render
Probe-->>Workflow: sanitized observation and hashes
Workflow->>Workflow: delete MIDI, ZIP, and WAV bytes
Flow diagram for the MIDI corpus stress progressionflowchart LR
A[FM Doom<br/>gentle baseline] --> B[Celestial Mechanics<br/>older export behavior]
B --> C[Deterministic Pattern<br/>controlled follow-tempo]
C --> D[Blue Glare<br/>dense tempo maps]
D --> E[Polyrhythmic Patterns<br/>overlap and polyphony]
E --> F[NGC3603 Quantum Demoscene<br/>16-channel routing stress]
Flow diagram for continuous synthetic MIDI CI validationflowchart LR
Fixture[Generate SMF1/480 fixture] --> Import[SongReader / MidiLoader]
Import --> Digest[Digest untouched event graph]
Digest --> Project[Project notes to deterministic Sampulse]
Project --> Render[Player -> FileOutDriver]
Render --> Validate[Validate non-silent WAV and contract fields]
Validate --> Delete[Delete transient MIDI and WAV]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 88c105ac4f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex Please Review this exact SHA a76d155 against the existing contract. Report only actionable correctness defects, with a minimal reproduction, expected versus actual behavior, and affected lines. State whether each reproduction was executed or statically inferred. Don’t repeat fixed findings without a new failing case. Keep architectural suggestions separate and non-blocking. This head addresses the four latest corpus findings: representative and donor stem bytes are re-bound by re-opening the manifest-pinned private archives; equal-tick MIDI metrics preserve same-track ordering while remaining cross-track-order independent; candidate observations require the canonical Phase 6B build-tree ELF and frozen baseline identity rather than arbitrary supplied executables; and donor public evidence retains/validates distinct per-stem source/event/render records. The always-on fixture-contract job is green on this SHA. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a76d1558cc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex Please Review this exact SHA 4dfadff against the existing contract. Report only actionable correctness defects, with a minimal reproduction, expected versus actual behavior, and affected lines. State whether each reproduction was executed or statically inferred. Don’t repeat fixed findings without a new failing case. Keep architectural suggestions separate and non-blocking. This head includes the four latest evidence fixes (archive-member rebinding, same-track/equal-tick ordering, canonical Phase 6B candidate-player provenance, distinct per-stem donor records) plus the native Sampulse crash fix exposed by the synthetic MIDI projection: xmsamplerchannel_setnote now recalculates period only for a still-playing foreground voice, avoiding dereference of an ended voice whose wave controller has no sample. Failure-only GDB diagnostics are also preserved as an artifact. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4dfadffdf7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex Please Review this exact SHA 460f04f against the existing contract. Report only actionable correctness defects, with a minimal reproduction, expected versus actual behavior, and affected lines. State whether each reproduction was executed or statically inferred. Don’t repeat fixed findings without a new failing case. Keep architectural suggestions separate and non-blocking. This head addresses the two latest P1 findings as well: candidate-player identity now includes an immediate clean-rebuild attestation (initial canonical build hash must equal the clean rebuild hash, and this attestation runs in ordinary CI); MidiLoader now flushes pending end-of-track note-offs, and the synthetic SMF runtime contract requires exactly two imported releases before the non-silent projection render. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 460f04f946
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex Please Review this exact SHA 5603de2 against the existing contract. Report only actionable correctness defects, with a minimal reproduction, expected versus actual behavior, and affected lines. State whether each reproduction was executed or statically inferred. Don’t repeat fixed findings without a new failing case. Keep architectural suggestions separate and non-blocking. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5603de2b31
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex Please Review this exact SHA 80ecfb6 against the existing contract. Report only actionable correctness defects, with a minimal reproduction, expected versus actual behavior, and affected lines. State whether each reproduction was executed or statically inferred. Don’t repeat fixed findings without a new failing case. Keep architectural suggestions separate and non-blocking. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 80ecfb6ef3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| #define PSYCLE_USE_PSY2 | ||
| #define PSYCLE_USE_XM | ||
| /* #define PSYCLE_USE_MIDI_FILE */ | ||
| #define PSYCLE_USE_MIDI_FILE |
There was a problem hiding this comment.
Flush equal-tick releases before reusing their voice
Statically inferred fresh case beyond the fixed end-of-track case: import Note On C4 at tick 0, Note Off C4 at tick 10, then Note On D4 at the same tick 10. In midiloader_writepatternevent() the pending release fails the strict time < position test at midiloader.c:957, but lines 966-967 still select that voice and clear noteoff; the D4 event then overwrites the voice, so the expected two releases become only D4's later release and C4 remains sustained. Enabling the loader here exposes this path; either emit equal-tick releases before voice reuse or retain the pending state, and add this boundary fixture.
AGENTS.md reference: AGENTS.md:L330-L330
Useful? React with 👍 / 👎.
| unexpected = [ | ||
| value for value in untracked_after.stdout.splitlines() | ||
| if value != allowed_plugin and not value.startswith(allowed_diversalis) | ||
| ] |
There was a problem hiding this comment.
Verify allowlisted candidate dependencies before rebuilding
Statically inferred fresh bypass beyond the fixed generated-Makefile case: after staging the candidate dependencies, modify any compiled file under psycle-cpp-r12005-sanitized/diversalis/ and invoke attest-candidate-player. The expected result is rejection because the build no longer uses the pinned r12005 dependency, but this prefix exemption removes every such file from unexpected; git diff also ignores the untracked tree, so qmake rebuilds it and the receipt still identifies the output as the frozen candidate. Validate the staged dependency against a frozen manifest or SVN identity before allowing it.
AGENTS.md reference: AGENTS.md:L303-L303
Useful? React with 👍 / 👎.
| midiloader_insertnoteoff( | ||
| self, voice, &self->currtrack.channels[voice]); |
There was a problem hiding this comment.
Reclaim every voice whose release was emitted
Statically inferred minimal reproduction: import 63 successive two-note chords, using channel 0/note N and channel 1/note N for each chord and releasing both before advancing to the next chord. The expected graph contains all 126 note-ons, but each first attack flushes every pending release while channelvoice retains only the last released voice; the other released voice keeps a non-empty tracknote, so the free-voice scan at lines 971-976 never reclaims it and the second note of chord 63 is dropped after all 63 usable tracker voices appear occupied. Clear every released voice's stored note (while separately retaining the one selected for immediate reuse), and regress repeated chords.
AGENTS.md reference: AGENTS.md:L330-L330
Useful? React with 👍 / 👎.
| for (slot = 0; slot < 16u; ++slot) { | ||
| if (psy_audio_machines_at(machines, slot)) | ||
| ++stats->machines_before_projection; |
There was a problem hiding this comment.
Inspect every machine slot before claiming an empty import
Statically inferred minimal reproduction: have the loader place a machine in slot 16 and run this probe. The expected result is rejection because the native-import contract requires zero sound-generating machines before projection, but this loop inspects only slots 0-15 even though C-Psycle exposes ordinary machine slots through 127; the actual result leaves machines_before_projection at zero and publishes the false empty-import observation. Iterate all non-Master machine slots rather than the MIDI channel range.
AGENTS.md reference: AGENTS.md:L325-L325
Useful? React with 👍 / 👎.
| if obs.get("non_silent_projection") is not True: | ||
| die(f"{stem_id}: execution projection is silent") | ||
| if obs.get("projection_kind") != "deterministic-sampler": | ||
| die(f"{stem_id}: execution projection kind changed") |
There was a problem hiding this comment.
Validate the imported tempo map before accepting a stem
Executed reproduction: I called validate_donor_execution_observation() with a source analysis reporting 539 tempo events and an otherwise valid donor observation reporting tempo_commands: 0; it returned successfully. The expected behavior is to reject an import that lost the corpus's repeated tempo map (accounting separately for any tick-zero event normalized into song BPM), but the actual validator skips directly from note/release coverage to audibility and the public stem record drops tempo_commands, so every tempo change can disappear while the set is still reported fully imported and non-silent.
AGENTS.md reference: AGENTS.md:L320-L320
Useful? React with 👍 / 👎.
Summary
Implements the next item in
phase6c/LEGACY_PLAYBACK_IMPORT.md: the contributor-supplied MIDI real-world playback corpus.This phase uses the six manifest-pinned SMF stem sets to move from a gentle real-world workload through dense tempo/polyphony/overlap stress and finally full 16-channel routing stress.
The corpus remains external/private. Raw MIDI and ZIP bytes are not committed and are not uploaded as evidence artifacts.
Stress progression
The observation order is frozen as:
Executable corpus contract
phase6c/reference-corpus/manifest.jsonis upgraded to schema v2 and freezes:The Python corpus analyser independently parses SMF1/480 input using only the standard library. It does not normalize the malformed key-signature metadata away.
Native C-Psycle import boundary
C-Psycle has a real
MThd/MidiLoaderSongReader path.For every real stem, the donor lane freezes the untouched imported tracker graph before adding any sound source:
This is native MIDI import evidence, not an extension-only check.
Deterministic execution projection
SMF import does not choose an instrument or instantiate a machine. Therefore successful import alone is not treated as audible playback.
After the untouched graph is digested, the probe attaches one project-owned deterministic classic Sampler substrate:
Player -> FileOutDriverrenders a transient WAV;The projection proves that the imported event graph can execute through the engine. It is explicitly not evidence of native MIDI instrument-selection semantics.
Frozen C++ candidate boundary
The sanitized C++ candidate has internal MIDI-event machinery but no retained SMF loader entry point (
MThd/MidiLoader).The private workflow runs one manifest-bound representative stem from each set against the frozen candidate player and records the scoped direct-load rejection. That boundary says nothing about the candidate's internal MIDI event or plugin support.
Original Psycle boundary
Pinned Psycle 1.12.0 x86 is not observed or classified in this phase.
This is donor-first real-world robustness evidence. Any later original-reference MIDI claim must be a separate version-pinned observation.
All corpus outputs retain
parity_status: UNKNOWN, and no compatibility-matrix row is added or promoted.Private real-corpus workflow
Adds:
.github/workflows/phase6c-midi-corpus-private.ymlManual trigger:
workflow_dispatchRequired masked repository secret:
PSYCLE_PHASE6C_MIDI_CORPUS_URLThe secret points to an outer transport ZIP containing the six exact archive files. The outer ZIP is not authoritative; each inner archive must match its frozen filename and SHA-256.
Each real stem is processed privately. Raw MIDI, ZIP and transient WAV bytes are deleted before artifact upload.
Uploaded artifacts contain only:
midiloader.c;Continuous CI
Ordinary PR CI requires no private corpus.
It creates a project-owned SMF1/480 fixture and runs the same C probe end-to-end through:
The Python contract tests also exercise:
Temporary roadmap
The MIDI phase remains observationally pending until the private workflow is dispatched with
PSYCLE_PHASE6C_MIDI_CORPUS_URL, but the implementation and continuously testable execution path are introduced by this PR.Summary by Sourcery
Introduce a private, identity-bound MIDI corpus lane that validates C-Psycle import robustness and deterministic engine execution without promoting compatibility parity.
New Features:
Bug Fixes:
Enhancements:
Build:
CI:
Documentation:
Tests: