SSPACEAGEDOCUMENTATION/
Release and Assurance

SpaceAge Project Trust Audit

Updated Aug 27, 2026   |   11.6 KB   |   docs/Project_Trust_Audit.md

SpaceAge Project Trust Audit

Updated: 2026-08-01

Purpose

This document tracks the code paths that can fail outside the immediate button click or audio callback: asynchronous dialogs, background MIDI workers, project persistence, recovery, and support evidence. It separates verified backend safety from human workflow proof.

Closed In This Pass

Asynchronous editor callbacks

  • File chooser callbacks for MIDI import, sample loading, Bonus One-Shots, bulk sample loading, loop import, layer replacement, Quasar loading, Pad Vault maintenance, pad-bank save/load, TempoCalc export, and Arrangement WAV render now resolve a juce::Component::SafePointer before touching editor state.
  • Six asynchronous popup-menu completions now carry the same lifetime guard before invoking MIDI tasks, quantize, Drum Composer copy, render/export, or Blank Project actions.
  • The configured Release test target compiles the full editor and TempoCalc implementation after these changes.

Processor teardown

  • External MIDI inventory refresh stops first.
  • Open external MIDI inputs are closed before owner-backed queues are joined.
  • MIDI control mapping, SysEx capture, SysEx restore response, expression recording, and note recording queues now expose deterministic shutdownAndWait() contracts.
  • Each queue signals exit, wakes its worker, and joins before processor member destruction can begin.
  • Queue destructors retain the same shutdown contract as a defensive fallback.

Verification

  • Configured Release SampleSquadAudioTest target: PASS.
  • MIDI_RECORD_TIMING: PASS, including four-measure capture, long-clip capture, first-measure capture, two-controller ownership, direct-device disconnect, and source-generation handoff.
  • MIDI_HEALTH: PASS.
  • MIDI_CLOSEOUT: PASS, including live Automation, Instrument Bay/lane workflows, Arrangement record targeting, and repeated processor lifetimes.
  • git diff --check: PASS; line-ending notices only.
  • No customer executable was produced.

Open Trust Work

Detached callout ownership - closed 2026-08-01

The Sequencer Settings CallOutBox is now parent-owned by the editor, so the root Settings surface cannot outlive the editor that supplies its controls. Its MIDI Input, Timing, Sync, and Output child callbacks resolve the Settings panel through Component::SafePointer; MIDI Setup Guide processor work resolves a JUCE weak reference and returns closed default receipts after teardown. Together with the individually guarded MIDI Health, MIDI Maps, SysEx Vault, Hardware Passport, MIDI Patch, Automation, and smaller creative callouts, this closes the automated detached-surface ownership audit.

Support-bundle privacy - closed 2026-08-01

The ZIP retains its exact three-file shape, but diagnostics.txt is now generated exclusively from a typed numeric/boolean snapshot. The Settings action can no longer pass whole reports, device identifiers, lane names, or Hardware Passport names into the writer. A focused regression enforces the complete key allowlist, three-entry archive contract, sentinel-name absence, and fallback path redaction.

Unclean-session evidence - closed 2026-08-01

The standalone now owns one random-token active marker for its lifetime and writes one atomic last-session.json record on clean shutdown. A later launch probes JUCE interprocess locks before treating a marker as stale, so another SpaceAge window that is still open is never misclassified. Stale evidence is reported only as unclean_or_interrupted, never as a confirmed crash.

The closed schema contains only schema_version, state, and a UTC millisecond timestamp. It has no fields for paths, filenames, projects, lanes, notes, presets, samples, MIDI payloads, device identity, exception text, or free-form prose. A focused regression proves clean, interrupted, and concurrent-instance behavior plus exact-schema privacy.

Human proof

Real dialog cancellation, editor closure while menus and callouts are open, forced standalone termination, recovery selection, and support-bundle inspection still require Windows human QA.

Next Order

  1. Run support-bundle creation/reveal and content inspection on a supported Windows machine.
  2. Force-close the standalone, relaunch it, and confirm the customer-facing recovery/support wording remains conservative.
  3. Run the human project-trust session in Human_Beta_QA_Matrix.md.

2026-08-01 - Detached Callout Ownership, Slice 1

  • The processor is now JUCE weak-referenceable and invalidates weak references at the start of its destructor, before external MIDI producers and owner-backed queues are stopped.
  • Flux Nodes and Loop Processor panels no longer retain an unguarded processor reference. Their callbacks resolve a weak reference at use time and become no-ops after processor teardown begins.
  • Chord Performance callbacks and the Piano Roll Grid Color palette now use Component::SafePointer before touching editor state.
  • The configured Release audio-test target compiles. MIDI_RECORD_TIMING, MIDI_HEALTH, and MIDI_CLOSEOUT pass after the ownership changes.
  • Remaining detached-panel work is concentrated in Sequencer Settings, MIDI Assignments, MIDI Hardware, SysEx Vault, MIDI Expression, and MIDI Patch. Timer-backed panels must stop polling and dismiss themselves when their guarded owner expires.

2026-08-01 - Detached MIDI Health Ownership Complete

  • MIDI Health no longer captures a raw processor address in its detached refresh, receipt, or save callbacks.
  • Its two-Hz timer stops and dismisses the callout as soon as either the processor or editor owner expires.
  • Repair and navigation actions require both the detached Settings surface and its editor to remain alive before they can act.
  • The internal Release audio-test target rebuilds and the focused MIDI_HEALTH gate passes after the conversion.
  • MIDI Maps and SysEx Vault remain the next timer-backed ownership slices.

2026-08-01 - Detached MIDI Maps Ownership Complete

  • MIDI Maps no longer retains its launching editor. The detached panel owns only a weak processor reference.
  • Learn, cancel, duplicate repair, pending-capture confirmation, mapping enable/invert/pickup/resolution/range/curve/delete actions, drawing reads, and live value refresh all resolve the processor immediately before use.
  • The eight-Hz refresh timer stops and dismisses the callout when processor teardown invalidates the weak reference.
  • The internal Release audio-test target rebuilds. MIDI_CONTROL_QUEUE and MIDI_CLOSEOUT pass after the conversion.
  • SysEx Vault is the next timer-backed detached surface.

2026-08-01 - SysEx Vault detached-window ownership

  • SysExVaultPanel now holds a JUCE weak reference to the audio processor instead of a raw processor reference.
  • Its polling timer stops and the detached CallOutBox dismisses itself if the processor lifetime ends.
  • Capture, cancellation, Vault metadata edits, Passport linking, restore receipts, removal confirmation, and all timer refreshes resolve a live owner immediately before use.
  • The delayed removal confirmation retains both component safety (SafePointer) and processor safety (WeakReference).
  • Verified by a release-target rebuild plus SYSEX_CAPTURE, SYSEX_RESTORE_RESPONSE, and MIDI_CLOSEOUT gates.

2026-08-01 - Hardware Passport detached-window ownership

  • MidiHardwarePanel now holds a JUCE weak reference to the processor instead of a raw reference.
  • Paint-time Passport summaries, sync-policy editing, recall plan copies, closeout reports, safe-common-MIDI previews, and parameter-table previews all resolve a live owner before reading project state.
  • Delayed sync-policy confirmations, hardware recall confirmations, and asynchronous parameter-table file selection check both the panel SafePointer and processor WeakReference before continuing.
  • The panel dismisses itself when the project audio engine no longer exists; Passport removal still uses the existing editor SafePointer callback.
  • Verified by a release-target rebuild plus MIDI_SYNC_POLICY, MIDI_SETUP_QUEUE, and MIDI_CLOSEOUT gates.

2026-08-01 - MIDI Patch detached-window ownership

  • MidiPatchPanel now holds a Component::SafePointer to its launching editor instead of a raw editor reference.
  • Selection, report, Hardware Passport creation/attachment, NRPN definition, setup-card queue, pitch-bend test/verification, SoundFont mapping, drawing, and button-state paths refuse work after editor detachment.
  • Delayed confirmation callbacks validate both the panel and editor immediately before project mutation or hardware queueing.
  • The bridge back to MIDI OUT now captures a safe Settings-panel pointer, so dismissing Settings also makes that bridge a no-op.
  • Verified by a Release rebuild plus MIDI_SETUP_QUEUE, MIDI_SYNC_POLICY, and MIDI_CLOSEOUT gates.

2026-08-01 - Automation detached-window ownership

  • MidiExpressionPanel now owns its editor through Component::SafePointer and checks that owner before every interactive or mutating entry.
  • A four-Hz lifetime monitor stops and dismisses the detached CallOutBox when its editor disappears; paint, keyboard, mouse, ownership, curve, copy/paste, clear, delete, draw, transform, Variant, and MIDI Patch transition paths refuse detached work.
  • The conversion preserves shared-pattern acknowledgement, clip/lane-local ownership, live controller refresh, undo checkpoints, and Variant behavior.
  • Verified by a Release rebuild plus AUTOMATION_RESTORE, AUTOMATION_OWNERSHIP, and MIDI_CLOSEOUT gates.

2026-08-04 - Typed support-bundle privacy and lifecycle stages closed

  • BundleContext no longer accepts free-form diagnostics, caller-supplied product names, private roots, or report prose.
  • The archive writer serializes a closed spaceage-support-v5 schema containing only runtime mode, sample rate, block size, prior-session lifecycle state and last completed lifecycle stage, audio timing, host-sync state, MIDI device counts, queue timing/counters, and boolean input/output readiness evidence.
  • Runtime mode is only standalone, hosted, or unknown; no host name is recorded. Audio format evidence is numeric and carries no device identity.
  • The lifecycle stage vocabulary is fixed to process_started, audio_prepared, editor_ready, steady_state, shutdown_started, and clean_shutdown; no exception text or stack data is collected.
  • Device identifiers, device names, lane names, Hardware Passport names, project text, musical data, asset names, and arbitrary warnings have no field through which to enter diagnostics.txt.
  • The exact three-file ZIP contract remains intact; fixed system metadata keeps path redaction as a second line of defence.
  • Focused session and archive tests enforce every allowed key, lifecycle-stage round trips, concurrent marker updates, and sentinel absence. Human forced-interruption and report-readability QA remain required.

2026-08-01 - Sequencer Settings Ownership Root Closed

  • The root Sequencer Settings callout is now a child of the editor rather than an independent desktop surface with an unbounded editor reference.
  • MIDI Input, MIDI Timing, MIDI Sync, and MIDI Output callbacks resolve the Settings panel through Component::SafePointer and fail closed after dismissal.
  • MIDI Setup Guide processor callbacks resolve a WeakReference and return empty/default plans or receipts after processor teardown.
  • Existing root-panel controls remain valid because JUCE parent ownership now guarantees that the Settings panel cannot outlive the editor.
  • The full editor compiles. MIDI_CLOSEOUT, MIDI_HEALTH, MIDI_SYNC_POLICY, and MIDI_SETUP_QUEUE pass.
  • Human Windows cancellation, nested-confirmation closure, editor shutdown, and forced-standalone interruption remain required; this section does not mark R04 complete.