SSPACEAGEDOCUMENTATION/
Music and Workflow

SpaceAge Build, Test, And Package Workflow

Updated Aug 29, 2026   |   10.4 KB   |   docs/Build_Test_Package_Workflow.md

SpaceAge Build, Test, And Package Workflow

This document records the short repo-local commands used to reduce approval churn during Codex work.

Performance Change Requirement

Performance is a correctness gate, not optional polish. Any feature with meaningful realtime, scaling, memory, disk, worker, or UI-refresh cost must include a prediction before implementation and measured evidence afterward. Run focused sound/behavior tests together with an appropriate Release performance workload, repeat noisy timing results, and record accepted or rejected impact in docs/Performance_Optimization_Rule_And_Impact_Report.md.

Do not accept an optimization merely because it removes source-level operations. Eager cache preparation, branches, host calls, memory traffic, and idle-state work can cost more than the calculation they replace.

Refactoring Requirement

Follow docs/Refactoring_Policy.md. Clean touched boundaries continuously, review affected subsystems after every 5-10 meaningful changes, and perform a deeper pass at subsystem milestones. Refactors must preserve focused behavioral evidence; DSP refactors require exact or explicitly tolerance-defined audio comparison. Avoid broad cleanup during urgent defect fixes and feature freezes.

Scripts

All scripts live in tools/.

  • tools/run_tests.ps1
    • Builds SampleSquadAudioTest
    • Runs the regression executable
  • tools/test-convolution.ps1
    • Builds the small ConvTest target independently of the plugin UI and asset suite
    • Verifies the neutral FIR/reset contract, procedural convolution-reverb output, and sample-aligned automation invariance across fixed and variable host blocks
    • See docs/Convolution_Architecture.md for design boundaries, synthesis reuse, tail contracts, licensing posture, and remaining listening decisions
  • tools/build_release.ps1
    • Builds the full Release configuration
    • Verifies the standalone .exe and .vst3 artifacts exist
    • Refreshes docs/reports/index.html after successful validation
  • tools/update-reports-index.ps1
    • Rebuilds the searchable webpage of live links to every repository Markdown file
    • Must be run before handing the user any requested development build produced outside build_release.ps1
  • tools/package_release.ps1
    • Always builds Release from the exact clean commit; there is no stale-binary bypass
    • Refuses public packaging until all 72 canonical release-readiness checks are complete; ordinary development builds remain available
    • Rejects a public-package build-directory override, verifies the upstream-proven JUCE source fingerprint, and records the CMake/generator/compiler/PowerShell/Windows toolchain
    • Stages the standalone .exe, .vst3, README, third-party ledger, and required license notices
    • Reopens the finished archive and verifies its manifest, artifact hashes, evidence hashes, source commit, and runtime-import inventory
    • Writes a clean timestamped zip, .sha256 sidecar, and hash-bound human attestation into the outputs folder without leaving loose binaries in the repo root
  • tools/test-release-hygiene.ps1
    • Verifies product identity, offline boundaries, legal-source files, and package notice coverage
    • Runs automatically as gate R02-A in release convergence
  • tools/test-release-archive-contract.ps1
    • Builds a synthetic package, verifies it, corrupts its executable, adds an unmanifested file, and proves both invalid archives are rejected
  • tools/test-release-juce-source.ps1
    • Recomputes the complete local JUCE tree fingerprint offline and requires the official 8.0.8 commit identity
  • tools/test-release-archive-attestation.ps1
    • Binds final human approval to one exact ZIP filename, SHA-256, and source commit

Typical Commands

Show one consolidated release-candidate status without building:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\get-release-candidate-status.ps1'

Run tests:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\run_tests.ps1'

Run the fast focused convolution test:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\test-convolution.ps1'

External PCM WAV references can be measured in place without importing them:

python tools/analyse_convolution_references.py --spaceage <reference.wav> [more.wav ...]

See docs/Convolution_Reference_Calibration.md for the release boundary and current procedural-room calibration.

Render nine deterministic 48 kHz/24-bit listening references from the same shipping DSP: five production-mix comparisons, a dry reference, and wet-only Compact/Medium/Deep files for inspecting the continuous Size morph in isolation:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\test-convolution.ps1' -NoBuild -RenderAuditionDirectory '.\outputs\convolution-audition'

Add -VerifyAuditionDeterminism to render all nine WAVs twice and require an identical sorted filename, byte-length, and SHA-256 manifest from both passes.

The audition mode is intentionally separate from the regression run. It writes synthetic first-party excitation plus the wet return, requires no DAW or external audio asset, and does not alter the release package.

After configuring with CMake's default BUILD_TESTING=ON, the same focused binary is also registered as SpaceAgeConvolutionFocused for standard CTest discovery. It carries the audio and convolution labels and a 180-second timeout. CTest runs it serially so parallel test workers do not invalidate its wall-clock real-time watchdog:

ctest --test-dir '<build-directory>' -C Release -R SpaceAgeConvolutionFocused --output-on-failure

Build Release:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\build_release.ps1'

Refresh the persistent reports webpage without building:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\update-reports-index.ps1'

Every user-requested build handoff must include a link to both the executable and docs/reports/index.html. Report links target the source Markdown files directly, so edits to an existing report are visible immediately; regenerating the index adds newly created reports and refreshes titles, timestamps, and sizes.

Package a test build:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\package_release.ps1' -Label 'SPACEAGE_SOME_FEATURE' -CleanCheckoutReceiptPath '.\test-reports\clean-checkout-convergence-<sha>-<time>.out'

The receipt must come from the exact commit being packaged and contain a completed PASS. Packaging copies it into the archive and binds its hash in the release manifest. Public packaging also requires Release_Readiness_Checklist.md to contain exactly the canonical 72 unique IDs with no remaining open check.

Compare two independently produced candidates from the same exact commit:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\compare-release-candidates.ps1' -ArchiveA '<first.zip>' -ArchiveB '<second.zip>' -ExpectedCommit '<40-character-sha>'

The comparison ignores archive timestamps and generatedUtc, but requires the same customer binaries, package files, evidence, runtime imports, and toolchain.

Environment Overrides

Development build and test scripts default to the current Windows setup and can use these overrides. Public packaging deliberately rejects SPACEAGE_BUILD_DIR so a stale or foreign cache cannot be substituted:

  • SPACEAGE_BUILD_DIR
  • SPACEAGE_VSDEVCMD
  • SPACEAGE_CMAKE_EXE

Why This Exists

The old workflow used long one-off PowerShell commands for build, test, copy, zip, and push operations. Those commands were harder for Codex sandbox approval to classify and harder for humans to review.

The new workflow keeps the risky details in versioned scripts and lets future sessions run short, repeatable commands.

Candidate Clean-Checkout Convergence

After all release-proof source, test, resource, and tool dependencies are committed, certify the exact candidate commit without using the current build tree:

powershell -NoProfile -ExecutionPolicy Bypass -File '.\tools\test-clean-checkout-convergence.ps1' -CandidateSha '<full-or-resolvable-SHA>'

Use -ValidateOnly for the inexpensive syntax/manifest/dependency-status check. Use -ReceiptPath '<path>' to choose the receipt destination; otherwise the script writes an exact-SHA receipt under test-reports/.

The full command refuses dirty or untracked required dependencies before doing expensive work. It creates a guarded detached worktree outside the repository, verifies CMake/package dependencies are tracked at the candidate, configures from scratch, builds only SampleSquadAudioTest, invokes tools/run-release-convergence.ps1 -SkipBuild, runs git diff --check, rejects candidate-worktree mutations, records the exact SHA, and cleans only its own temporary worktree. It does not stage, commit, package, build a customer executable, or remove artifacts from the current workspace.

VST3 wrapper preflight

The canonical release build now produces CinematicDrums_VST3 and SpaceAgeVst3HostSmokeTest alongside the standalone and self-test. tools/test-vst3-host-smoke.ps1 runs the plugin in an isolated process with a 120-second timeout. tools/package_release.ps1 repeats the proof against the exact copied staging bundle before archive creation. A PASS requires discovery, note-driven audio above a silence baseline at two sample rates, a real continuous-parameter mutation, byte and semantic state restoration, and two native-peer editor lifecycles with JUCE message dispatch between open and close.

Deterministic release archives

tools/release_archive_helpers.ps1 is the only supported public ZIP writer. It sorts every file path, includes hidden files, and fixes ZIP entry timestamps. ReleaseManifest.json binds generatedUtc to the source commit timestamp rather than the packaging clock. The archive contract builds the same fixture twice and requires identical ZIP hashes, then proves that generation-time and toolchain drift are both rejected.

Project CPU Gate Asset Handling (2026-08-29)

  • PROJECT_CPU and PROJECT_CPU_SWEEP use named-argument splatting when invoking their profiling scripts.
  • A silent isolated lane passes as unavailable only when its stored instrument source is confirmed missing. It is omitted from workload rankings but retained in raw output. Silent lanes without missing-asset evidence remain failures.