Harden song swarm rendering environment

This commit is contained in:
Meta Vens 2026-06-01 02:06:49 +01:00
commit 16995891fd
4 changed files with 52 additions and 10 deletions

View file

@ -42,15 +42,17 @@ voices with `gain=@/seq/kick`, `freq=@/seq/lead/freq`, or
Voice-like leads:
```aqua
source_port name=lead_src kind=syrinx pressure=.75 opening=.42
acoustic_network name=lead_body source=lead_src radiation=beak
acoustic_voice name=lead network=lead_body freq=@/seq/lead/freq gain=@/mix/lead/gain
voice name=vowel_lead wave=saw freq=@/seq/lead/freq gain=@/mix/lead/gain sustain=.18 decay=.22 fm=3 fmi=.25 lpf=.62
```
Use syrinx/acoustic ownership when the reference has singing, vocal chops,
creature calls, reed-like lead, or expressive vowel motion. Move pressure,
opening, filter/formant color, and pitch. A static syrinx badge is not a vocal
line.
creature calls, reed-like lead, or expressive vowel motion, but only if the
patch includes a complete, known-valid acoustic graph scaffold. A lone
`source_port` or `acoustic_network` line does not render. Start from
`patches/advanced/syrinx-voice.aqua` or `patches/advanced/bird-syrinx.aqua`
when using syrinx in the swarm; otherwise use a formant-filtered ordinary lead
for the attempt and write the missing syrinx scaffold as an Aqua gap. A static
syrinx badge is not a vocal line.
Subtractive drums:
@ -109,4 +111,3 @@ pressure.
- Hand-writing isolated frequencies when the reference suggests a tonal center
or progression.
- Treating a metric bump as a lesson without a reusable owner sentence.

View file

@ -193,7 +193,8 @@ public static class FaustCompiler
var dotnet = await RunAsync(
"dotnet",
["run", "--project", Path.Combine(tempDir, "Render.csproj"), "--", outputPath, options.SampleRate.ToString(CultureInfo.InvariantCulture), frames.ToString(CultureInfo.InvariantCulture)],
cancellationToken);
cancellationToken,
DotnetRenderEnvironment(tempDir));
if (dotnet.ExitCode != 0 || !File.Exists(outputPath))
{
return new FaustRender([], options.SampleRate, "dotnet", dotnet.Stdout, dotnet.Stderr);
@ -273,7 +274,8 @@ public static class FaustCompiler
private static async Task<(int ExitCode, string Stdout, string Stderr)> RunAsync(
string fileName,
IReadOnlyList<string> arguments,
CancellationToken cancellationToken)
CancellationToken cancellationToken,
IReadOnlyDictionary<string, string>? environment = null)
{
var start = new ProcessStartInfo(fileName)
{
@ -282,6 +284,13 @@ public static class FaustCompiler
UseShellExecute = false
};
foreach (var argument in arguments) start.ArgumentList.Add(argument);
if (environment is not null)
{
foreach (var (key, value) in environment)
{
start.Environment[key] = value;
}
}
using var process = Process.Start(start) ?? throw new InvalidOperationException($"failed to start `{fileName}`");
var stdout = process.StandardOutput.ReadToEndAsync();
@ -299,4 +308,27 @@ public static class FaustCompiler
return (process.ExitCode, await stdout, await stderr);
}
private static IReadOnlyDictionary<string, string> DotnetRenderEnvironment(string tempDir)
{
var home = Path.Combine(tempDir, "dotnet-home");
var appData = Path.Combine(tempDir, "dotnet-appdata");
var localAppData = Path.Combine(tempDir, "dotnet-localappdata");
var packages = Path.Combine(tempDir, "nuget-packages");
Directory.CreateDirectory(home);
Directory.CreateDirectory(appData);
Directory.CreateDirectory(localAppData);
Directory.CreateDirectory(packages);
return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["DOTNET_CLI_HOME"] = home,
["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "1",
["DOTNET_NOLOGO"] = "1",
["NUGET_PACKAGES"] = packages,
["APPDATA"] = appData,
["LOCALAPPDATA"] = localAppData,
["USERPROFILE"] = home,
["HOME"] = home
};
}
}

View file

@ -269,3 +269,4 @@
{"timestamp":"2026-06-01T00:31:00+01:00","topic":"cumulative-music-knowledge-and-external-signal-map","claim":"The song swarm now owns one cumulative loop-level music-production `.cc`: it seeds manuals once, indexes them before pass one, then appends pass-learned worker/curator evidence with `music-distill --learned-only true --include-manuals false`. Added a current music-intelligence source map: Every Noise is static genre-vocabulary context, Echo Nest is gone, Spotify audio features are restricted/deprecated and not a training substrate, AcousticBrainz is historical, and local Essentia-style extraction should own primary audio signal.","evidence":"tools/run-song-snippet-trial-swarm.ps1; tools/IpaTrialWorker/Program.cs; docs/music-production-knowledge/music-intelligence-source-map.md; artifacts/parity/song-snippet-swarms/20260531T232719334/music-production-knowledge-seed.md; artifacts/parity/manual-knowledge-smoke/20260601T002939/report.md"}
{"timestamp":"2026-06-01T01:05:00+01:00","topic":"per-target-local-music-intelligence","claim":"Each song challenge now emits a provider-labeled `intelligence.md` built from local audio analysis and source-path vocabulary, and musician prompts must read it alongside Qdrant music-production knowledge. The report translates tempo, register, brightness, noisiness, density, spectral motion, and cautious genre hints into AquaSynth production decisions. Keep prompt surfaces free of PowerShell markdown backtick escapes: escaped `r`/`t`/`n` tokens became hidden control characters in agent instructions, corrupting metric and file names.","evidence":"tools/IpaTrialWorker/Program.cs; tools/run-song-snippet-trial-swarm.ps1; artifacts/parity/song-snippet-swarms/20260531T234041397/pass-001/agent-01/target-01/intelligence.md; artifacts/parity/song-snippet-swarms/20260531T234041397/pass-001/agent-01/hypothesis-agent.prompt.md"}
{"timestamp":"2026-06-01T01:58:00+01:00","topic":"song-swarm-render-failure-visibility","claim":"Song-swarm render failure must be visible to agents and operators. `song-score` now writes `audio/render-failure.txt` and includes failure summaries in `evaluator-report.md`. The parser accepts documented `env=ad attack=... decay=...` syntax, because the manual taught that form and agents copied it. Codex musician jobs now set repo-local `DOTNET_CLI_HOME`/`NUGET_PACKAGES` with first-time-use disabled so internal renderer `dotnet run` calls do not write to denied sandbox home directories.","evidence":"src/AquaSynth.Core/PatchScript.cs; tests/AquaSynth.Dsl.Tests/PatchScriptTests.cs; tools/IpaTrialWorker/Program.cs; tools/run-song-snippet-trial-swarm.ps1; artifacts/parity/song-render-failure-smoke/20260601T0145-agent01-a01/smoke-agent01-target01-attempt01/song-candidates/agent_01__swarm__a01/audio/render-failure.txt; artifacts/parity/song-render-failure-smoke/20260601T0152-agent01-a01-after-ad/smoke-agent01-target01-attempt01/summary.csv"}
{"timestamp":"2026-06-01T02:08:00+01:00","topic":"song-swarm-render-environment-and-syrinx-scaffold","claim":"Renderer builds must not depend on user-profile NuGet or dotnet config. `FaustCompiler.RenderAsync` now runs its temporary C# render project with temp-local HOME, APPDATA, LOCALAPPDATA, DOTNET_CLI_HOME, and NUGET_PACKAGES. The music manual and swarm prompt now treat acoustic/syrinx as complete-graph syntax: agents should start from known-valid syrinx patches or log a gap, not submit isolated `source_port`/`acoustic_network` fragments that cannot render.","evidence":"src/AquaSynth.Faust/FaustCompiler.cs; docs/music-production-knowledge/aqua-dsp-usage-manual.md; tools/run-song-snippet-trial-swarm.ps1; artifacts/parity/song-snippet-swarms/20260601T005553312/pass-001/agent-01/iterations/attempt-01/target-01/agent-01-target-01-attempt-01/song-candidates/agent_01__swarm__scene_a/audio/render-failure.txt"}

View file

@ -91,9 +91,16 @@ function Start-CodexAgentJob {
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $JobLogPath) | Out-Null
$dotnetHome = Join-Path $JobRepoRoot ".dotnet_cli_home"
$nugetHome = Join-Path $JobRepoRoot ".nuget_packages"
New-Item -ItemType Directory -Force -Path $dotnetHome, $nugetHome | Out-Null
$appDataHome = Join-Path $JobRepoRoot ".dotnet_appdata"
$localAppDataHome = Join-Path $JobRepoRoot ".dotnet_localappdata"
$agentHome = Join-Path $JobRepoRoot ".dotnet_agent_home"
New-Item -ItemType Directory -Force -Path $dotnetHome, $nugetHome, $appDataHome, $localAppDataHome, $agentHome | Out-Null
$env:DOTNET_CLI_HOME = $dotnetHome
$env:NUGET_PACKAGES = $nugetHome
$env:APPDATA = $appDataHome
$env:LOCALAPPDATA = $localAppDataHome
$env:USERPROFILE = $agentHome
$env:HOME = $agentHome
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = "1"
$env:DOTNET_NOLOGO = "1"
Add-Content -LiteralPath $JobLogPath -Value "[$([DateTimeOffset]::UtcNow.ToString("O"))] $JobCodexCommand $($JobArgs -join ' ')"
@ -517,6 +524,7 @@ Noise and texture:
Instrument ownership:
- This harness is feeding the music-generator curriculum, so do not solve the target with three naked oscillators and a prayer. The scorer now records instrument-role metrics and chip-distress risk in CultCache.
- If the patch has a singing, creature, or alien lead role, use the syrinx/acoustic owner: source_port kind=syrinx, pressure/opening curves, acoustic_network, and acoustic_voice, then shape it with filters/modulation.
- Acoustic/syrinx graph syntax is complete-graph syntax. Do not write isolated source_port or acoustic_network fragments. If you use source_port, you must also define the referenced acoustic_path/path, terminals/connections/radiation_port, wave_clock when needed, acoustic_network, and acoustic_voice. If you cannot build that complete scaffold from a known-valid local patch such as patches/advanced/syrinx-voice.aqua, use a formant-filtered ordinary lead for this attempt and write the missing syrinx scaffold as an Aqua gap instead of submitting a non-rendering badge.
- If the patch has drums or rhythmic transients, use subtractive ownership: pitched sine/triangle body, filtered noise skin, short envelope, and pattern gate.
- If the patch has a pad, bed, drone, or harmonic wash, use additive/PAD ownership: `layer engine=add` or `engine=pad`, `harmonics`, `spectrum`, and slow modulation.
- Ordinary simple voices are still legal as helpers, but a candidate built mostly from square/sine/saw blips with no syrinx, subtractive drum, additive/PAD, or shaped texture role will be treated as chip-distress-risk evidence.