feat(separation): materialize playable stem artifacts - #1159
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review Please review the exact current Draft head. Prioritize Python/Rust boundary safety, deterministic PCM16 WAV publication, path-free status projection, symlink/reparse and identity-collision handling, cache-hit behavior, cleanup on failure, docstring/typing, and whether the temporary source-repair workflow can remove itself only after complete verification. Draft means the source-to-player vertical is incomplete; substantive findings should still be reported. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Exact checked-out head =='
git rev-parse HEAD
git status --short
printf '%s\n' '== PR merge-base and changed files =='
base="$(git merge-base HEAD origin/develop 2>/dev/null || true)"
printf 'merge-base: %s\n' "$base"
git diff --name-status "${base}...HEAD"
printf '%s\n' '== Diff stat =='
git diff --stat "${base}...HEAD"
printf '%s\n' '== Candidate source and test files =='
fd -t f . | rg '(playback_artifacts|separation|status|playback|source-repair|repair|ADR-0001|playable-stem)'
printf '%s\n' '== Python module outlines =='
while IFS= read -r file; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --type function,class 2>/dev/null || true
done < <(fd -t f -e py . | rg '(playback_artifacts|separation|status|playback)')
printf '%s\n' '== Boundary and artifact call sites =='
rg -n -C 4 --glob '*.py' --glob '*.rs' \
'(materialize_playable_stem_artifact_set|PlayableStem|playable.stem|artifact_set|artifact.*manifest|stem.*manifest|stem.*path|native.*path|status.*projection|source.repair|source_repair|cache.hit|cache_hit)' .
printf '%s\n' '== Relevant changed diff =='
git diff --find-renames --find-copies --unified=80 "${base}...HEAD" -- \
':(glob)**/*playback_artifacts*.py' \
':(glob)**/*separation*.py' \
':(glob)**/*.rs' \
':(glob)**/*status*.py' \
':(glob)**/*repair*' \
':(glob)docs/adr/0001-playable-stem-delivery-and-audition.md' \
':(glob)docs/superpowers/plans/2026-09-04-playable-stem-audition.md'Length of output: 8763 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Exact checked-out head =='
git rev-parse HEAD
git status --short
printf '%s\n' '== PR merge-base and changed files =='
base="$(git merge-base HEAD origin/develop 2>/dev/null || true)"
printf 'merge-base: %s\n' "$base"
git diff --name-status "${base}...HEAD"
printf '%s\n' '== Diff stat =='
git diff --stat "${base}...HEAD"
printf '%s\n' '== Candidate source and test files =='
fd -t f . | rg '(playback_artifacts|separation|status|playback|source-repair|repair|ADR-0001|playable-stem)'
printf '%s\n' '== Python module outlines =='
while IFS= read -r file; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --type function,class 2>/dev/null || true
done < <(fd -t f -e py . | rg '(playback_artifacts|separation|status|playback)')
printf '%s\n' '== Boundary and artifact call sites =='
rg -n -C 4 --glob '*.py' --glob '*.rs' \
'(materialize_playable_stem_artifact_set|PlayableStem|playable.stem|artifact_set|artifact.*manifest|stem.*manifest|stem.*path|native.*path|status.*projection|source.repair|source_repair|cache.hit|cache_hit)' .
printf '%s\n' '== Relevant changed diff =='
git diff --find-renames --find-copies --unified=80 "${base}...HEAD" -- \
':(glob)**/*playback_artifacts*.py' \
':(glob)**/*separation*.py' \
':(glob)**/*.rs' \
':(glob)**/*status*.py' \
':(glob)**/*repair*' \
':(glob)docs/adr/0001-playable-stem-delivery-and-audition.md' \
':(glob)docs/superpowers/plans/2026-09-04-playable-stem-audition.md'Length of output: 8765 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Remote PR identity =='
gh pr view 1159 --repo ContextualWisdomLab/bandscope \
--json number,state,isDraft,headRefName,headRefOid,baseRefName,url
printf '%s\n' '== Playback artifact materializer =='
cat -n services/analysis-engine/src/bandscope_analysis/separation/playback_artifacts.py
printf '%s\n' '== Separation exports and integration references =='
cat -n services/analysis-engine/src/bandscope_analysis/separation/__init__.py
rg -n -C 8 --glob '*.py' \
'\bmaterialize_playable_stem_artifact_set\s*\(|\bPlayableStemArtifact|artifact_set_identity|playable_stem' \
services/analysis-engine
printf '%s\n' '== Rust playback protocol and registration =='
cat -n apps/desktop/src-tauri/src/playback_protocol.rs
printf '%s\n' '== main.rs relevant registration and status sections =='
rg -n -C 12 \
'(playback_protocol|analysis.*status|get_analysis_job_status|invoke_handler|register|stem|path)' \
apps/desktop/src-tauri/src/main.rs
printf '%s\n' '== Analysis renderer boundary =='
cat -n apps/desktop/src/lib/analysis.ts
rg -n -C 8 --glob '*.ts' --glob '*.tsx' \
'(getAnalysisJobStatus|analysis.*status|stem|artifact|path)' \
apps/desktop/src
printf '%s\n' '== Temporary repair automation =='
cat -n scripts/repairs/apply_playable_stem_status.py
cat -n .github/workflows/playable-stem-status-repair.yml
printf '%s\n' '== Focused artifact and status tests =='
cat -n services/analysis-engine/tests/test_playback_artifacts.py
cat -n services/analysis-engine/tests/test_playback_artifact_status.py
cat -n services/analysis-engine/tests/test_playback_artifact_reference.pyLength of output: 145921 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Remote PR head =='
gh pr view 1159 --repo ContextualWisdomLab/bandscope \
--json headRefOid,headRefName,isDraft,url
printf '%s\n' '== Playback artifact materializer, bounded sections =='
sed -n '1,240p' services/analysis-engine/src/bandscope_analysis/separation/playback_artifacts.py | cat -n
sed -n '241,520p' services/analysis-engine/src/bandscope_analysis/separation/playback_artifacts.py | cat -n
printf '%s\n' '== Native playback protocol, bounded sections =='
sed -n '1,260p' apps/desktop/src-tauri/src/playback_protocol.rs | cat -n
sed -n '261,700p' apps/desktop/src-tauri/src/playback_protocol.rs | cat -n
printf '%s\n' '== Current API and repair markers =='
rg -n -C 10 --glob 'api.py' \
'(AudioStemSeparator|AnalysisJobStatus|_build_job_status|_stem_work_arrays_path|_feature_cache_paths|run_analysis_job_updates|_load_cached_local_audio_features)' \
services/analysis-engine/src/bandscope_analysis
sed -n '1,320p' services/analysis-engine/src/bandscope_analysis/api.py | cat -n
printf '%s\n' '== Workflow definitions and required-check candidates =='
fd -t f -e yml -e yaml .github/workflows | sort
rg -n -C 5 --glob '*.yml' --glob '*.yaml' \
'(pull_request|push:|workflow_run|cargo|tauri|pnpm|npm|uv run|pytest|ruff|mypy|security|sbom|sast)' \
.github/workflows
printf '%s\n' '== Repair workflow line-numbered section =='
sed -n '36,90p' .github/workflows/playable-stem-status-repair.yml | cat -nLength of output: 101596 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Exact materializer lines =='
nl -ba services/analysis-engine/src/bandscope_analysis/separation/playback_artifacts.py \
| sed -n '219,285p;300,390p'
printf '%s\n' '== Exact repair workflow lines =='
nl -ba .github/workflows/playable-stem-status-repair.yml | sed -n '1,105p'
printf '%s\n' '== Workflow event triggers =='
for workflow in .github/workflows/*.{yml,yaml}; do
[ -f "$workflow" ] || continue
printf '\n-- %s --\n' "$workflow"
sed -n '1,45p' "$workflow"
done
printf '%s\n' '== Regression-test coverage for float-width overflow and repair final head =='
rg -n -C 4 --glob '*.py' \
'(float64|float32|1e[0-9]{2,}|maximum.*sample|applied_gain|playable-stem-status-repair|apply_playable_stem_status)' \
services/analysis-engine/tests scripts .github/workflowsLength of output: 1203
I found two substantive issues.
The materializer otherwise has useful protections for fixed artifact names, static symlinks, collision comparison, staging cleanup, and path-free projection. The source-to-player integration remains intentionally incomplete at this Draft head.
|
Preserve the playable-stem publication delta while adopting #971's current Tauri dependency tree and stale-lock cleanup. No force update or evidence transfer.
Product outcome
#1159 is the canonical Python publication parent for #961's source-to-audible stem vertical. It materializes one complete aligned
vocals | bass | drums | otherset as mono PCM16 WAVs under the request-owned app temp root, attaches only a path-free reference to terminal-success process status, and keeps native paths out of renderer/project payloads.This remains a Draft prerequisite, not an audible-stem claim. Native actual-file admission, playback binding and buyer-facing source UX remain #1160; durable state remains #970/#962.
Exact current stack
Protected product source revalidated:
develop@314ddeae7b775a4957594b599358c8255617eb2e.#1159 validates exact canonical source kinds, aligned finite one-dimensional arrays and bounded integer sample rate, snapshots samples, applies set-wide peak protection when needed, writes same-filesystem staged WAVs, synchronizes publication and reuses an artifact identity only when names/sizes/SHA-256 agree. Unexpected entries, non-regular files, symlinks, collisions, malformed arrays and encoder failures fail closed.
A path-free artifact-set reference is publication evidence, never playback authority. #1160 derives only canonical app-owned paths from the request-owned temp root, verifies actual WAV layout/containment/size/header/SHA-256/native identity and atomically registers the complete set into #971's existing
PlaybackAuthority.The current #1160 source/UI child distinguishes verified Full-mix-only availability from failed/malformed native discovery, provides EN/KO error/empty/retry states, and preserves Full mix while rediscovery occurs. No Python publication logic was added for this UI state.
Canonical Project Persistence is #970
04e813eb928ac057147d2a5438e3fd0f699a8b0c, open/Draft/mergeable andbehind_by=0against protecteddevelop. Its Draft/unreleased v3 document retains the stableselectedPlaybackSourcesemantic and optional path-free SHA-256-backedsourceReference.Canonical Resource Admission is #866
dedaab78f8837dc6c1f4074c7a792ae999f49550. Local-file intake already materializes the admitted full mix under the app-owned project root, so the older “external absolutesourcePathremains the source” description is obsolete. #866 now owns native staged byte-count/SHA-256 receipts plus an already-open publication verifier bounded to the expected admitted byte count and one growth probe. The remaining audible-reopen prerequisite is the native Tauri handoff: its current materialization caller still uses the compatibility byte-count adapter, so the verified receipt is not yet bound to a reopened published descriptor or handed to #970.#970/#962 therefore consume #866's publication-bound evidence rather than reimplement copy/hash logic. Restart must re-admit only the app-owned artifact under regular/no-link containment, byte/digest and decode checks before #1160 resolves stored source intent to fresh playback authority. That work is not #1159 publication responsibility.
Canonical baseline owner #1116 remains source head
a7fa2652922a32b3efb808f0c5304264019e5893; its source remains stale relative to current #970/#866 and is a source-level repair finding. Queue descendant #968 remains2ef28c95616894203403ab913662788430f3c0f9; no restack is needed for metadata-only updates.Verification / merge gate
All predecessor checks/reviews remain historical. #1159 and #1160 remain Draft; #970 and #866 also require their own exact-head evidence. Each owner needs terminal protected CI, security/SAST, dependency/SBOM, coverage, Windows/macOS build and qualifying independent last-push review evidence on its unchanged exact head. Absent, queued, skipped, cancelled, stale, predecessor, self or model-only evidence is non-passing.