DirectiveCraft
DocDC-000-T
SheetFreqCraft QA SOP

How FreqCraft is tested.

Before FreqCraft ships, it has to earn it. This is the actual release procedure the app is held to, the one that answers a single question under pressure: is this build safe to release? Reproduced in full below, sanitized only of internal file paths. Nothing hidden, including what the tests caught.

The problem

“It works on my machine” is not a release decision. A shipping app needs a repeatable, defensible answer to whether it’s ready, one that survives a deadline, a tired developer, and a feature added last week.

Memory and good intentions don’t scale. The process has to be written down, ordered, and gated.

The approach

Two layers, narrowest net first: an automated adversarial test suite, then a physical-device pass that ends in a release gate. Every test has an explicit pass condition.

Known issues are triaged by severity and disclosed, not buried. The gate states, in writing, ship or don’t ship.

Automated tests211
Manual procedures22
Physical devices02
Known issuesSev
Gate decisionWritten

211 automated tests and 22 manual procedures, run on two physical handsets. Counts verified against the source before publishing. The automated suite has already earned its keep twice: it caught a readout-overflow defect, and later a teardown race that four rounds of code review missed. Both are documented below.

FreqCraft Mobile QA Test SOP
Version 1.3  ·  2026-07-05  ·  Directive Craft LLC
App: FreqCraft Android 1.1.2 (Flutter/Dart)  ·  Status: ACTIVE, release QA procedure

Purpose. Define and execute pre-launch QA across two layers: an automated adversarial suite, then hands-on device work, a manual pass on the primary handset (Phase A) and physical-device release qualification on both handsets (Phase B). Phase B is the release gate; the app bundle is not submitted to the store until every Phase B criterion is met.

Scope. FreqCraft 1.1.2, Android only, including multi-voice sessions, the live waveform visualizer and timed-session behavior. Out of scope: iOS, accessibility/TalkBack (deferred). Trigger: developer declares the build ready for QA, run the automated suite first, then Phase A, then Phase B.

Automated coverage: run first

The adversarial suite is the first gate. It runs the build through input it was never meant to receive, and must pass clean before a human tests anything. It needs no device and no tether, so it runs on every change rather than once per release.

Location: test/, 15 files, 211 widget and unit tests, pumped at 720x1604
Run: flutter analyze then flutter test
Gate: analyze clean AND 211/211 green before manual testing begins. Analyze gates the build, not the other way round: a missing import fails a Gradle build in 49 seconds that analyze catches in four.
SUITEAdversarial Integration Suite
Confirm the app survives malformed and absurd input, mode and state transitions, and edge cases, automatically and repeatably.
  • Malformed numeric input: multiple dots, minus signs, letters, whitespace, leading zeros.
  • Absurd-value handling: a 14-digit carrier must not overflow the readout. (This case caught a real defect before it reached a device.)
  • Advisory thresholds: carrier ≥ 1000, beat > 100, isochronic pulse > 100.
  • Mode toggling and waveform switching mid-session.
  • Isochronic playback path; the 0 Hz / 0 Hz silence case.
  • Live carrier change during an active session.
  • State leak across begin → end → begin cycles.
  • Timed-session REMAINING readout show / clear.
Implementation note no pumpAndSettle: the live waveform animates continuously, so it never returns and the suite would hang. Use pump(Duration) only.
Pass 211/211 green, about 16 seconds, no device. Any failure is fixed and the suite re-run before Phase A.
Phase A: manual test procedure

Environment: Moto G 2025, Android 16, flutter run from project root.
Result codes: PASS · FAIL · NOTE (device or OEM behaviour, log and continue).
Why there is no emulator layer. There used to be one. It was retired because the development machine could not run an Android emulator well enough to trust what it reported about audio, and a test environment you have to discount is worse than none. Every procedure below now runs on hardware from the start, which is also where the audio faults actually live.

A-1First Launch, Disclaimer Flow
Verify the disclaimer runs once on first launch and is not skippable.
  • Clear stored preferences (adb shell pm clear com.directivecraft.freqcraft or wipe device data).
  • Launch the app; verify the disclaimer screen appears.
  • Acknowledge; verify navigation to the main screen.
  • Cold-start the app again; verify the disclaimer is skipped and the main screen loads directly.
Pass disclaimer appears on first launch only, skipped on every subsequent launch.
A-2Main Screen, Static UI
Verify layout, labels, and static elements are correct.
  • Verify the app bar: title centered, bold, letter-spaced; info icon present.
  • Open the About dialog; verify header, feature list, desktop-suite section, source attribution, and a working close action.
  • Verify the subtitle block (“Precision Mobile Tool” / desktop-suite line).
  • Verify no legacy or placeholder text appears anywhere on screen.
Pass all static elements present and correct, no legacy text visible.
A-3Mode Selector
Verify the mode toggle controls downstream UI correctly in both directions.
  • Confirm Binaural is selected on launch; verify it shows Carrier, Beat, and Waveform controls plus the stereo-headphones advisory.
  • Switch to Isochronic; verify Carrier and Pulse Rate show, the waveform selector hides, and the no-headphones advisory appears.
  • Switch back to Binaural; verify the layout reverts correctly.
Pass mode switch controls UI elements and advisory text correctly both ways.
A-4Numeric Field Behavior
Verify input fields accept correct values, handle edge cases, and release focus cleanly.
  • Tap each numeric field (Carrier, Beat, Fade In/Out, Timer); verify all text is selected on tap.
  • Enter 120 then 999 in Fade In; verify the value displays in full (field accommodates 3 digits).
  • Enter 150 in Beat; verify the out-of-range advisory appears, then clears when the value returns to range.
  • Regression type a value, then collapse the numpad with the system back gesture (not Done). Verify no text stays highlighted with selection handles, and no selection persists into the session. Values still apply only on Done/Begin.
Pass fields select-on-tap, accept valid values, show/clear advisories at threshold, and clear focus cleanly however the numpad is dismissed.
A-5Fade Field Alignment
Verify visual alignment of the fade controls and stability under toggling.
  • Verify both fade input fields share the same right edge (label expanded, field pushed right).
  • Toggle Fade In off then on; verify the field disappears and reappears at the same position with no layout jump.
Pass fields right-aligned; toggling causes no layout shift.
A-6Audio Playback, Basic
Verify audio starts, produces output, and stops cleanly in both modes.
  • Load default parameters (200 Hz carrier, 10 Hz beat, Binaural). Start the session; verify the button changes state and audio is audible.
  • End the session; verify audio stops and the button reverts.
  • Repeat in Isochronic mode.
Pass audio starts and stops cleanly; button state follows session state.
A-7Fade In / Fade Out, Perceptual Curve
Verify the fade curve is perceptually gradual across the full duration. Validates the fix for a prior linear fade that sounded complete in roughly one-third of the intended time.
  • Set a 30-second fade in. Start the session and monitor: very low for the first ~10s, rising through the middle third, full only near the 30s mark, never “done” early.
  • Enable a 30-second fade out and end the session; verify it is perceptually gradual, not abrupt.
Pass fade feels linear to the human ear across the full duration. (A quadratic curve produces this perception; linear does not.)
A-8Race Condition Regression, Volume Spike
Verify the “alarm-clock” volume spike is gone. History: volume spiked in the final seconds before fade-out when a timer was used with fade enabled (overlapping fade coroutines).
  • Set Timer = 1 minute, Fade In = 5s, Fade Out = 5s, at a comfortable (non-max) volume.
  • Start the session and monitor the full 60 seconds, focusing on the last 10.
  • Verify no sudden volume increase before fade-out, smooth fade from ~55s, and a clean end at 60s with audio at zero.
Fail any sudden volume spike or “alarm clock” effect in the final 10 seconds is a regression. Do not ship.
A-9Session Timer
Verify timer countdown, auto-stop, and fade-out display behavior.
  • Set a 2-minute timer, Fade Out off. Start; verify the countdown begins, audio auto-stops at zero, and the button reverts.
  • Set a 1-minute timer with a 10-second fade out. Verify the fade begins at ~50s.
  • Timer / fade display verify the REMAINING countdown keeps ticking through the fade-out and reaches 0:00 exactly as the audio goes silent. It must not jump to 0:00 early while audio is still fading. (1-minute timer, 5s in / 5s out = 5s fade-in, 50s full, 5s fade-out, silent at 0:00.) Manual END hides REMAINING immediately; ELAPSED persists by design.
Pass counts down correctly, auto-stops at zero, fade triggers at the right offset, and the countdown reaches 0:00 in sync with audio silence, no early jump.
A-10Preset Persistence, Cold Start
Verify stored presets survive a full app restart. (Hot reload does not test persistence, cold start required.)
  • Save a user preset with custom parameters and a unique name.
  • Kill the app and cold-start it.
  • Open the Presets screen; verify the preset is present and loads with all parameters restored.
Pass all saved values survive a cold restart.
A-11Presets Screen
Verify factory and user preset display and behavior in the single-open accordion UI.
  • Verify all 7 factory presets are listed (Deep Sleep, Recovery, Deep Calm, Theta Schumann, Alpha Calm, Beta Focus, Gamma Clarity), each with badge, band/Hz chip, and explore line.
  • Expand a factory preset; verify the drawer shows parameters, attributed note, source, safety note, and Load, with no delete on factory presets.
  • Verify user presets offer quick-Load on the collapsed row and Delete only inside the expanded drawer (with a confirm dialog).
  • Load a factory preset; verify parameters reach the main screen and Gamma Clarity loads in Isochronic mode.
Pass all presets present, accordion behavior correct, factory vs. user controls correct, modes load correctly.
A-12Footer Disclaimer
Verify the sourcing disclaimer is present at the bottom of the Presets screen.
  • Scroll to the bottom of the Presets screen; verify the sourcing/exploration disclaimer text is present, small, gray, and centered.
Pass footer disclaimer present, correct text and styling.
A-13Live Waveform Visualizer
Verify the live waveform renders continuously, matches the selected type and mode, stays readable across the Hz range, idles correctly, and does not stutter during a session.
  • Continuous scroll watch ≥10s; verify smooth scrolling with no seam, snap-back, or repeating-interval jump. It must read as a continuous feed, not a loop.
  • Shape matches type in Binaural, cycle Sine / Square / Sawtooth / Triangle; verify the on-screen shape changes to match each and matches the engine.
  • Isochronic density vary carrier and pulse across low and high values; verify visual density tracks the values and stays readable at low Hz (no lonely hump with dead gaps).
  • Readout overflow enter an absurd 14-digit carrier; verify the readout shrinks to fit and shows the full number, no overflow, no error, no truncation box. Normal values render unchanged.
  • Idle behavior stop the session; verify the wave freezes to a clean static silhouette (no mid-wave smear) and re-animates smoothly on restart.
  • No stutter during a timed session, watch ≥10s; verify no per-second hitch as ELAPSED / REMAINING tick.
Pass continuous, type- and mode-accurate, readable at all Hz, readout never overflows, idles and re-animates cleanly, no per-second stutter.
Phase B: physical device release gate

Prerequisites: automated suite green; all Phase A items PASS or NOTE (no unresolved FAILs).
Devices: Moto G7 Power (Android 10, wired-audio reference, 3.5mm jack); Moto G 2025 (Android 16, current-API reference). Oldest supported and newest supported, so a release is exercised at both ends of the range it claims. The release-validation install sideloads the signed app bundle.

B-0Device Setup
Prepare the physical device for testing.
  • Enable Developer Options and USB Debugging.
  • Connect via USB and confirm adb devices recognizes the device.
  • Install the build (debug install, or signed bundle via bundletool for release validation).
B-1All Phase A Tests, Repeat on Device
Confirm every Phase A behaviour holds on the SECOND handset and on the signed bundle, not just on the one it was developed against.
  • Run A-1 through A-13 on the Moto G7 Power, from the sideloaded signed app bundle.
  • Treat differences between the two handsets as data, log them with the OS version, and fail only if audio is clearly wrong.
Pass all Phase A items pass on both handsets, or the difference is logged against a named device and OS version.
B-2Binaural Audio Quality
Verify binaural beat perception on stereo headphones, different frequencies per ear.
  • On headphones, load Theta Schumann (7.83 Hz beat, 136.1 Hz carrier); verify an audible beating sensation at ~7–8 Hz.
  • Step up through Alpha Calm (10 Hz) and Beta Focus (14 Hz); verify the perceived rate increases. Verify a high carrier stays centered, not pushed to one ear.
  • Remove one headphone; verify the beat perception diminishes, confirming binaural, not isochronic, processing.
Pass rhythmic pulsing at the correct rate, stereo-dependent, tone centered.
B-3Isochronic Audio Quality
Verify isochronic pulses are audible and clean on both speakers and headphones.
  • Load Gamma Clarity (40 Hz isochronic); verify rapid pulsing on speakers and the same pulsing (not a beat) on headphones.
  • Set pulse rate to 4 Hz; verify slow, distinct pulses with clean edges. Set to 40 Hz; verify rapid pulsing stays clean, no buzzing or overflow artifacts.
Pass pulses audible on speakers, clean edges, no artifacts at any rate.
B-4Background Audio Mixing
Verify the app runs alongside other audio rather than muting it, a key design differentiator (ducking, not interrupting).
  • Start playback in a music app, switch to the app, and start a session.
  • Verify both are audible simultaneously (slight ducking of the music is acceptable).
  • End the session; verify the music app is unaffected.
Fail if the app mutes or pauses the music app entirely. Do not ship.
B-5Screen Lock / Background Playback
Verify audio continues when the screen locks.
  • Start a session (no timer, no fade), lock the screen, and wait 30 seconds; verify audio is still audible.
  • Unlock; verify the session is still active. End the session; audio stops.
Note if audio stops after lock, investigate the foreground-service path and log it. This blocks launch only if audio stops within 5 minutes (see B-6).
B-6OEM Battery Management, Extended Run
Detect audio termination by Android battery optimization, the risk that only real OEM power management produces, and the most common cause of a session dying unattended.
  • Start a continuous session at comfortable volume, lock the screen, and set the phone down.
  • Monitor audio at 5, 10, 15, and 20 minutes; document whether and when audio stops.
Pass audio runs continuously for 20+ minutes screen-locked.
Blocker audio stops within 5 minutes; the core use case is non-functional. Resolve before submitting. (Stops after 5 minutes: log and triage by device.)
B-7Volume Control
Verify system volume buttons and the in-app slider both affect output.
  • During a session, verify system volume up/down affects output, and the in-app slider adjusts level independently.
Pass both system and in-app controls govern audio level.
B-8Cold Start After Device Reboot
Verify stored state persists across a full device reboot.
  • Save a user preset and fully reboot the device.
  • Open the app; verify the disclaimer does not reappear and the saved preset is present.
Pass all state persists through a full reboot.

Release Gate Checklist

Every item must be checked before the app bundle is submitted.

  • Automated suite: analyze clean and 211/211 green.
  • B-1: all Phase A tests pass on the physical device.
  • B-2 / B-3: binaural beat perception and isochronic pulses confirmed.
  • B-4: background mixing confirmed, does not mute other apps.
  • B-5 / B-6: screen-lock playback stable; minimum 10 minutes background (20 preferred; under 5 minutes = launch blocker).
  • B-7: volume controls functional. B-8: persistence confirmed through reboot.

GATE STATUS:   [ ] OPEN   [ ] PASSED   [ ] BLOCKED

Known gaps and open issues

Disclosed and triaged, not hidden.

IDSeverityDescriptionStatus / Plan
STOPLowTeardown race in the stop path, a reference used after an await without a mounted-check could log an error if the screen was dismissed mid-stop. Surfaced by the expanded test suite, not by four rounds of code review (including a maximum-effort audit).Fixed + verified
P4LowA dead validation method in the engine, never called; validation handled in the UI.Later release
ENGDeferredEngine hardening (deterministic stop poll, completer-based fade cancel, band-limited waveforms).Post-launch

Version log

Change control is part of the deliverable.

v1.0  2026-06-12, Initial release. Built from the QA SOP handoff.
v1.1  2026-06-14, Accordion preset UI, preset names, contact email; Phase A + Phase B.
v1.2  2026-06-22, Stamped to app 1.0.0. Added the automated adversarial suite (29 tests) as the first gate; added the Live Waveform Visualizer section (A-13); added the timer fade-out display spec (A-9) and the numpad-focus regression (A-4). Sanitized internal paths; defect forensics tracked separately in the bug log.
v1.3  2026-07-05, Adversarial suite expanded 29 → 44 on-device checks; added 12 unit tests (56 automated total). Physical testing run on two handsets (Moto G7 Power + Pixel 6 Pro). Logged the teardown-race defect (STOP) the suite caught after code review missed it, fixed and verified. Counts verified against source.
v1.4  2026-08-29, Stamped to app 1.1.0 (five-voice sessions). Automated coverage restated: 211 widget and unit tests replacing the 56, and the suite no longer needs a tethered device, so it runs on every change instead of once per release. Fleet updated, the Pixel 6 Pro is out; the Moto G 2025 (Android 16) is in, pairing oldest-supported with newest-supported. Counts verified against source: 15 files, 211 green, analyze clean.
    Also v1.4, the emulator layer is retired and the process is now two layers, not three. The development machine could not run an Android emulator well enough to trust its audio, so Phase A moved onto the primary handset and Phase B became the second-handset and signed-bundle gate. Known issue P5 (channel reversal at low beat frequency) is withdrawn with it: it was only ever observed in that emulator and never reproduced on hardware.

This is the app it ships.

FreqCraft is built and tested the way this page describes: precision audio, zero data collection, one-time purchase. See it for yourself.

See FreqCraft