318 lines
8.8 KiB
Markdown
318 lines
8.8 KiB
Markdown
# SPRINT v0.1.34 - NEXT FOR OPENCODE
|
|
## Stop Mixing Sessions, Stop Validating Running Jobs, Recover Runtime Truth Before Musical Iteration
|
|
|
|
**Owner:** OpenCode
|
|
**Reviewer:** Codex
|
|
**Fecha:** 2026-04-03
|
|
**Report reviewed:** `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\docs\SPRINT_v0.1.33_VALIDATION_REPORT.md`
|
|
|
|
---
|
|
|
|
## 1. Executive Review
|
|
|
|
The main problem was not only that the set looked bad.
|
|
|
|
The main problem was that OpenCode validated and reported **mixed runtime truths**:
|
|
|
|
- one job was still running
|
|
- the manifest came from an older completed run
|
|
- the older completed run had actually ended with an internal error
|
|
|
|
That means the report was not a reliable description of one single generation.
|
|
|
|
This sprint is about restoring truth discipline before more musical iteration.
|
|
|
|
---
|
|
|
|
## 2. Runtime Truth Verified By Codex
|
|
|
|
Codex verified these facts from disk:
|
|
|
|
- `generation_manifests.json` latest persisted session is:
|
|
- `689f4f6b2361`
|
|
- `generation_jobs.json` shows:
|
|
- report job `f7bd2d0a95e8` was still `running`
|
|
- stage was only `generating_config`
|
|
- it had not completed when OpenCode validated
|
|
|
|
Codex also verified this:
|
|
|
|
- `ba1111cd6a59` stored `session_id = 689f4f6b2361`
|
|
- that job was marked `completed`
|
|
- but its `result_text` contains a real traceback:
|
|
- `KeyError: 'C:\\ProgramData\\Ableton\\Live 12 Suite\\Resources\\MIDI Remote Scripts\\libreria\\reggaeton\\kick\\kick nes 2.wav'`
|
|
- so that completed state was false-positive job bookkeeping
|
|
|
|
Therefore the v0.1.33 report mixed at least two incompatible truths:
|
|
|
|
1. live/validation state from the still-running async job `f7bd2d0a95e8`
|
|
2. manifest state from previous stored session `689f4f6b2361`
|
|
|
|
That invalidates the report as senior evidence.
|
|
|
|
---
|
|
|
|
## 3. Code Review Findings
|
|
|
|
### P0. Async jobs could be marked completed even when generation returned an error string
|
|
|
|
In:
|
|
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\AbletonMCP_AI\AbletonMCP_AI\MCP_Server\server.py`
|
|
|
|
`_run_generation_job(...)` treated any returned text from `generate_track(...)` or `generate_song(...)` as success.
|
|
|
|
That allowed this broken state:
|
|
|
|
- job status = `completed`
|
|
- result text = `Error generando track: ...`
|
|
|
|
This was a real reporting bug, not user confusion.
|
|
|
|
### P0. `get_generation_manifest()` returned stale latest manifest while a newer async job was still running
|
|
|
|
In:
|
|
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\AbletonMCP_AI\AbletonMCP_AI\MCP_Server\server.py`
|
|
|
|
OpenCode called `get_generation_manifest()` without explicit `session_id`.
|
|
|
|
While a newer job was still running, that returned the previous stored manifest instead of the current job truth.
|
|
|
|
This is exactly how the report ended up mixing:
|
|
|
|
- `job_id = f7bd2d0a95e8`
|
|
- `session_id = 689f4f6b2361`
|
|
|
|
### P0. Cross-generation memory could crash at generation end
|
|
|
|
In:
|
|
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\AbletonMCP_AI\AbletonMCP_AI\MCP_Server\sample_selector.py`
|
|
|
|
`_update_cross_generation_memory(...)` compacted `defaultdict` state into plain dicts, then later did `+=` on unseen keys.
|
|
|
|
That is the real cause of the stored traceback in the completed job.
|
|
|
|
### P1. QA bus counting depended on `list_buses`, but the active runtime does not expose that command
|
|
|
|
In:
|
|
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\AbletonMCP_AI\AbletonMCP_AI\MCP_Server\server.py`
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\abletonmcp_init.py`
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\AbletonMCP_AI\abletonmcp_runtime.py`
|
|
|
|
The runtime path used by validation did not implement `list_buses`.
|
|
|
|
So `diagnose_generated_set()` and parts of `validate_set()` could claim:
|
|
|
|
- `bus_count = 0`
|
|
|
|
even when the generation manifest had real buses.
|
|
|
|
### P1. QA over-penalized source MIDI tracks that were already replaced by audio
|
|
|
|
In:
|
|
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\AbletonMCP_AI\AbletonMCP_AI\MCP_Server\server.py`
|
|
|
|
`_validate_empty_clips(...)` treated empty source tracks as failures even when matching `AUDIO ...` replacement tracks existed.
|
|
|
|
That was inflating false negatives in audio-first or recovery-fallback runs.
|
|
|
|
---
|
|
|
|
## 4. Fixes Already Applied By Codex
|
|
|
|
These fixes are already on disk. Do not revert them.
|
|
|
|
### 4.1 Async job error detection
|
|
|
|
Codex added result-text failure detection in:
|
|
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\AbletonMCP_AI\AbletonMCP_AI\MCP_Server\server.py`
|
|
|
|
Now a job that returns:
|
|
|
|
- `Error generando track: ...`
|
|
|
|
is marked `failed`, not `completed`.
|
|
|
|
### 4.2 Stale manifest guard
|
|
|
|
Codex hardened:
|
|
|
|
- `get_generation_manifest(...)`
|
|
|
|
Now if there is an active `queued` or `running` generation and no explicit `session_id` was given, the tool returns an error instead of silently handing back a stale old manifest.
|
|
|
|
### 4.3 Cross-generation memory fix
|
|
|
|
Codex fixed:
|
|
|
|
- `C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\AbletonMCP_AI\AbletonMCP_AI\MCP_Server\sample_selector.py`
|
|
|
|
So cross-generation memory stays safe when new sample families or new paths appear after compaction.
|
|
|
|
### 4.4 Bus fallback for QA
|
|
|
|
Codex added server-side fallback bus inference from live track names.
|
|
|
|
This means validation/diagnosis no longer depends entirely on `list_buses`.
|
|
|
|
### 4.5 Audio replacement awareness in empty-clip QA
|
|
|
|
Codex changed QA so empty source MIDI tracks are not treated as hard failures when matching audio replacement tracks are already present.
|
|
|
|
---
|
|
|
|
## 5. Validation Performed By Codex
|
|
|
|
Codex verified:
|
|
|
|
- `python -m py_compile` passed for:
|
|
- `server.py`
|
|
- `sample_selector.py`
|
|
- `tests\test_sample_selector.py`
|
|
- `tests\test_piano_forward.py`
|
|
- tests passed:
|
|
- `tests\test_sample_selector.py`
|
|
- `tests\test_piano_forward.py`
|
|
|
|
Codex also added regression coverage for:
|
|
|
|
- cross-generation memory after compaction
|
|
- bus inference fallback when runtime has no `list_buses`
|
|
- async manifest guard while a job is still running
|
|
- result-text error detection for generation jobs
|
|
|
|
No new song was generated in this review turn.
|
|
|
|
---
|
|
|
|
## 6. What OpenCode Must Do Next
|
|
|
|
### P0. Never validate a running async job
|
|
|
|
If `get_generation_job_status(...)` returns:
|
|
|
|
- `queued`
|
|
- `running`
|
|
|
|
then:
|
|
|
|
- do not call `validate_set`
|
|
- do not call `diagnose_generated_set`
|
|
- do not call `get_generation_manifest("")`
|
|
- do not write a validation report yet
|
|
|
|
Wait until the job is:
|
|
|
|
- `completed`
|
|
- or `failed`
|
|
|
|
### P0. A report must describe one single run, not mixed state
|
|
|
|
The next report is invalid unless all of these match:
|
|
|
|
- `job_id`
|
|
- `session_id`
|
|
- validation target
|
|
- manifest target
|
|
|
|
If OpenCode uses:
|
|
|
|
- `job_id = X`
|
|
|
|
then the report must validate the completed session that belongs to `X`.
|
|
|
|
No mixing:
|
|
|
|
- running live state from one job
|
|
- manifest from another older job
|
|
|
|
### P0. If async generation fails, report failure honestly
|
|
|
|
If job status is `failed`, OpenCode must:
|
|
|
|
- stop claiming generation success
|
|
- include the actual `error`
|
|
- include `result_text`
|
|
- include `session_id` only if one was partially stored
|
|
- explain whether the set in Live is partial, stale, or broken
|
|
|
|
### P0. Use explicit `session_id` for manifest retrieval after async work
|
|
|
|
After a job completes:
|
|
|
|
1. call `get_generation_job_status(job_id)`
|
|
2. extract its final `session_id`
|
|
3. call `get_generation_manifest(session_id)`
|
|
|
|
Do not call:
|
|
|
|
- `get_generation_manifest("")`
|
|
|
|
after async generation unless there are no active jobs and you intentionally want the latest stored manifest.
|
|
|
|
### P1. Keep no-piano policy active
|
|
|
|
Still required:
|
|
|
|
- no piano audio loops
|
|
- no `HARMONY_PIANO_MIDI`
|
|
- no piano timbre as harmonic spine
|
|
|
|
Harmonic support must use non-piano families.
|
|
|
|
### P1. Only iterate musically after truth is clean
|
|
|
|
The user complaint about “porqueria” is valid.
|
|
|
|
But OpenCode must not jump back into musical tweaking until the next report proves:
|
|
|
|
- one job
|
|
- one session
|
|
- one manifest
|
|
- one validation target
|
|
|
|
Otherwise musical conclusions are unreliable.
|
|
|
|
---
|
|
|
|
## 7. Required Evidence For The Next Report
|
|
|
|
The next report is invalid unless it includes:
|
|
|
|
1. exact `job_id`
|
|
2. exact final job `status`
|
|
3. exact final `session_id`
|
|
4. explicit proof that validation ran after completion
|
|
5. manifest fetched with explicit `session_id`
|
|
6. clear statement whether the run is:
|
|
- usable
|
|
- partial
|
|
- failed
|
|
7. if failed, the real error text
|
|
|
|
If the job is still running, the correct report is not a validation report.
|
|
|
|
It is only a progress note.
|
|
|
|
---
|
|
|
|
## 8. Immediate Product Direction After Truth Recovery
|
|
|
|
Once the job/session/report mismatch is closed, the next real musical targets remain:
|
|
|
|
- stop 4-second loop feeling
|
|
- stop empty holes after one good block
|
|
- improve continuity in Arrangement
|
|
- improve real section-to-section development
|
|
- keep user library central
|
|
- keep vocals manual-only
|
|
|
|
But do not tackle those while the reporting layer is still lying.
|
|
|
|
Runtime truth first.
|