[webftr-js8-lab] command=selftest [webftr-js8-lab] root=/decoders/js8_decoder [webftr-js8-lab] log=/decoders/js8_decoder/logs/20260527T084305Z_selftest.log [webftr-js8-lab] manifest=/decoders/js8_decoder/logs/20260527T084305Z_selftest_manifest.json [webftr-js8-lab] utc=20260527T084305Z [webftr-js8-lab] rx-only guard: no TX / no PTT / no Tune / no Send [webftr-js8-lab] creating tone test WAV: /decoders/js8_decoder/runtime/selftest_1500hz.wav /decoders/js8_decoder/runtime/selftest_1500hz.wav [webftr-js8-lab] creating short synthetic JS8-like Costas probe WAV: /decoders/js8_decoder/runtime/selftest_js8_costas_probe.wav /decoders/js8_decoder/runtime/selftest_js8_costas_probe.wav [webftr-js8-lab] running WAV validator [webftr-js8-lab] JSON output: /decoders/js8_decoder/logs/20260527T084305Z_selftest_decode_output.json [webftr-js8-lab] JSON timeout guard: 180s { "ok": true, "mode": "JS8", "decoder": "webftr-js8-decoder-lab", "decoder_version": "step48-source-decoder-path-audit-2026-05-27", "timestamp_utc": "2026-05-27T08:43:08Z", "rx_only": true, "safety": { "tx": false, "ptt": false, "tune": false, "send": false, "rig_control": false, "js8call_api_control": false }, "capabilities": { "wav_validate": true, "audio_metrics": true, "spectrum_candidates": true, "sync_candidates": true, "soft_symbol_metrics": true, "fec_input_packager": true, "bit_pipeline_mapper": true, "ldpc_probe_harness": true, "message_parse": true, "real_js8_demod": false, "real_js8_fec_decode": false, "real_js8_unpack": false }, "warnings": [ "Step 48 adds an RX-only LDPC probe harness around the 174-bit candidates. It still does not perform final real JS8 LDPC/FEC or message unpack." ], "decodes": [], "input_wav": "/decoders/js8_decoder/runtime/selftest_1500hz.wav", "wav": { "path": "/decoders/js8_decoder/runtime/selftest_1500hz.wav", "channels": 1, "sample_rate": 12000, "sample_width_bytes": 2, "frames": 24000, "duration_seconds": 2.0, "rms_dbfs": -15.05, "peak_dbfs": -12.04, "clipped": false }, "spectrum_probe": { "ok": true, "method": "goertzel_300_3000hz_25hz_step", "note": "Audio plumbing probe only, not JS8 sync or demodulation.", "candidates": [ { "freq_hz": 1500.0, "relative_db": 0.0, "power": 374.91417208 }, { "freq_hz": 1475.0, "relative_db": -277.94, "power": 0.0 }, { "freq_hz": 1525.0, "relative_db": -283.93, "power": 0.0 }, { "freq_hz": 1400.0, "relative_db": -289.05, "power": 0.0 }, { "freq_hz": 1550.0, "relative_db": -293.96, "power": 0.0 }, { "freq_hz": 1650.0, "relative_db": -295.18, "power": 0.0 }, { "freq_hz": 1575.0, "relative_db": -296.53, "power": 0.0 }, { "freq_hz": 1175.0, "relative_db": -298.26, "power": 0.0 } ] }, "implementation_stage": "step48_message91_crc_distance_ranking_no_text_unpack", "next_steps": [ "audit JS8Call/JS8Call-Improved source to locate minimal RX decoder path", "run sync-probe, soft-symbols, bit-pipeline and ldpc-probe on real JS8 WAV captures", "extract/connect the real JS8 LDPC matrix/decoder using the Step9 174-bit soft candidates", "implement JS8 message unpack and map to stable decodes[] JSON" ] } [webftr-js8-lab] running JS8 text parser smoke test [webftr-js8-lab] JSON output: /decoders/js8_decoder/logs/20260527T084305Z_selftest_parse_output.json [webftr-js8-lab] JSON timeout guard: 180s { "ok": true, "mode": "JS8", "parser": "webftr-js8-message-parser", "count": 1, "messages": [ { "raw": "CQ DN9LO JO62", "normalized": "CQ DN9LO JO62", "message_type": "CQ", "directed_to": null, "callsigns": [ "DN9LO" ], "primary_callsign": "DN9LO", "locators": [ "JO62" ], "primary_locator": "JO62", "body": "CQ DN9LO JO62" } ] } [webftr-js8-lab] running input-check smoke test [webftr-js8-lab] JSON output: /decoders/js8_decoder/logs/20260527T084305Z_selftest_input_check_output.json [webftr-js8-lab] JSON timeout guard: 180s { "ok": true, "mode": "JS8", "tool": "webftr-js8-input-check", "tool_version": "step48-source-decoder-path-audit", "input_wav": "/decoders/js8_decoder/runtime/selftest_js8_costas_probe.wav", "rx_only": true, "safety": { "tx": false, "ptt": false, "tune": false, "send": false, "js8call_runtime_control": false }, "decodes": [], "warnings": [ "WAV is short. A longer JS8 capture improves profile and LDPC candidate checks." ], "wav": { "path": "/decoders/js8_decoder/runtime/selftest_js8_costas_probe.wav", "channels": 1, "sample_rate": 12000, "sample_width_bytes": 2, "frames": 148608, "duration_seconds": 12.384, "rms_dbfs": -15.61, "peak_dbfs": -12.25, "clipped": false }, "next_action": "Run profile-scan, then auto-ldpc-probe on this WAV." } [webftr-js8-lab] running short sync-probe smoke test [webftr-js8-lab] JSON output: /decoders/js8_decoder/logs/20260527T084305Z_selftest_sync_probe_output.json [webftr-js8-lab] JSON timeout guard: 180s { "ok": true, "mode": "JS8", "tool": "webftr-js8-sync-probe", "tool_version": "step48-source-decoder-path-audit", "input_wav": "/decoders/js8_decoder/runtime/selftest_js8_costas_probe.wav", "rx_only": true, "safety": { "tx": false, "ptt": false, "tune": false, "send": false, "js8call_runtime_control": false }, "implementation_stage": "step43_sync_candidates_with_ldpc_probe_followup_no_final_decode", "wav": { "path": "/decoders/js8_decoder/runtime/selftest_js8_costas_probe.wav", "channels": 1, "sample_rate": 12000, "sample_width_bytes": 2, "frames": 148608, "duration_seconds": 12.384, "rms_dbfs": -15.61, "peak_dbfs": -12.25, "clipped": false }, "js8_reference": { "source": "JS8Call-Improved source-map orientation plus FT8-like Costas7 hypothesis", "sample_rate_hz": 12000, "default_nsps": 6192, "default_symbol_duration_seconds": 0.516, "costas7_candidate": [ 3, 1, 4, 0, 6, 5, 2 ], "tone_count_candidate": 8, "note": "This is a sync/symbol candidate extractor only. It estimates frame/symbol candidates for lab work and does not perform LDPC/FEC decode or JS8 message unpacking." }, "scan": { "nsps": 6192, "tone_spacing_hz": 1.937984, "freq_min_hz": 300.0, "freq_max_hz": 3000.0, "max_seconds_analyzed": 4.0, "start_candidates_scanned": 1, "base_candidates_scanned": 1, "base_candidates_hz": [ 1000.0 ], "coarse_tone_candidates": [ { "freq_hz": 1000.0, "relative_db": 0.0, "power": 6.94910418 }, { "freq_hz": 1025.0, "relative_db": -27.24, "power": 0.0131166 }, { "freq_hz": 975.0, "relative_db": -27.53, "power": 0.01227993 }, { "freq_hz": 1050.0, "relative_db": -37.39, "power": 0.0012678 }, { "freq_hz": 1075.0, "relative_db": -41.43, "power": 0.00049951 }, { "freq_hz": 950.0, "relative_db": -43.35, "power": 0.00032115 }, { "freq_hz": 1100.0, "relative_db": -46.57, "power": 0.00015313 }, { "freq_hz": 1250.0, "relative_db": -47.96, "power": 0.00011108 }, { "freq_hz": 1125.0, "relative_db": -48.58, "power": 9.635e-05 }, { "freq_hz": 1200.0, "relative_db": -50.32, "power": 6.457e-05 }, { "freq_hz": 875.0, "relative_db": -50.9, "power": 5.646e-05 }, { "freq_hz": 1175.0, "relative_db": -51.46, "power": 4.965e-05 } ] }, "sync_candidates": [ { "ok": true, "start_sample": 0, "start_seconds": 0.0, "base_freq_hz": 1000.0, "tone_spacing_hz": 1.937984, "nsps": 6192, "costas_pattern": [ 3, 1, 4, 0, 6, 5, 2 ], "costas_hits": 7, "costas_symbols": 7, "avg_margin_db": 29.11, "energy_score_db": 29.11, "candidate_score": 128.22, "symbols": [ { "symbol": 0, "expected_tone": 3, "strongest_tone": 3, "expected_is_strongest": true, "expected_power": 83.0873099286, "median_other_power": 0.1042308968, "margin_db": 29.02, "tone_powers": [ 0.0981480318, 0.1051242996, 0.1064179268, 83.0873099286, 0.1057422016, 0.1042308968, 0.0993799575, 0.0932492823 ] }, { "symbol": 1, "expected_tone": 1, "strongest_tone": 1, "expected_is_strongest": true, "expected_power": 83.0774568889, "median_other_power": 0.1014706768, "margin_db": 29.13, "tone_powers": [ 0.1068702304, 83.0774568889, 0.1052822376, 0.105564598, 0.1014706768, 0.0956100015, 0.0879534486, 0.0800992227 ] }, { "symbol": 2, "expected_tone": 4, "strongest_tone": 4, "expected_is_strongest": true, "expected_power": 83.0917714671, "median_other_power": 0.1044873575, "margin_db": 29.0, "tone_powers": [ 0.0960127168, 0.0986802754, 0.1054058068, 0.1081981246, 83.0917714671, 0.1055965002, 0.1044873575, 0.0990928872 ] }, { "symbol": 3, "expected_tone": 0, "strongest_tone": 0, "expected_is_strongest": true, "expected_power": 83.0749822549, "median_other_power": 0.0948551103, "margin_db": 29.42, "tone_powers": [ 83.0749822549, 0.1081775542, 0.1032741915, 0.1002757935, 0.0948551103, 0.0864721839, 0.080493759, 0.0726495994 ] }, { "symbol": 4, "expected_tone": 6, "strongest_tone": 6, "expected_is_strongest": true, "expected_power": 83.0368796528, "median_other_power": 0.1013897721, "margin_db": 29.13, "tone_powers": [ 0.0811328494, 0.088780076, 0.0950670222, 0.1013897721, 0.1027811248, 0.1070386893, 83.0368796528, 0.1089829146 ] }, { "symbol": 5, "expected_tone": 5, "strongest_tone": 5, "expected_is_strongest": true, "expected_power": 83.0780861176, "median_other_power": 0.1045690469, "margin_db": 29.0, "tone_powers": [ 0.0865241623, 0.0949217802, 0.099666939, 0.1045690469, 0.1061057949, 83.0780861176, 0.1100149946, 0.1049352501 ] }, { "symbol": 6, "expected_tone": 2, "strongest_tone": 2, "expected_is_strongest": true, "expected_power": 83.0649691812, "median_other_power": 0.1027968836, "margin_db": 29.07, "tone_powers": [ 0.1060939743, 0.1064017103, 83.0649691812, 0.1058247328, 0.1027968836, 0.1002472492, 0.0945580448, 0.088818472 ] } ], "symbol_preview": [ { "symbol": 0, "tone_index": 3, "confidence_db": 28.93, "powers": [ 0.0981480318, 0.1051242996, 0.1064179268, 83.0873099286, 0.1057422016, 0.1042308968, 0.0993799575, 0.0932492823 ] }, { "symbol": 1, "tone_index": 1, "confidence_db": 28.91, "powers": [ 0.1068702304, 83.0774568889, 0.1052822376, 0.105564598, 0.1014706768, 0.0956100015, 0.0879534486, 0.0800992227 ] }, { "symbol": 2, "tone_index": 4, "confidence_db": 28.85, "powers": [ 0.0960127168, 0.0986802754, 0.1054058068, 0.1081981246, 83.0917714671, 0.1055965002, 0.1044873575, 0.0990928872 ] }, { "symbol": 3, "tone_index": 0, "confidence_db": 28.85, "powers": [ 83.0749822549, 0.1081775542, 0.1032741915, 0.1002757935, 0.0948551103, 0.0864721839, 0.080493759, 0.0726495994 ] }, { "symbol": 4, "tone_index": 6, "confidence_db": 28.82, "powers": [ 0.0811328494, 0.088780076, 0.0950670222, 0.1013897721, 0.1027811248, 0.1070386893, 83.0368796528, 0.1089829146 ] }, { "symbol": 5, "tone_index": 5, "confidence_db": 28.78, "powers": [ 0.0865241623, 0.0949217802, 0.099666939, 0.1045690469, 0.1061057949, 83.0780861176, 0.1100149946, 0.1049352501 ] }, { "symbol": 6, "tone_index": 2, "confidence_db": 28.92, "powers": [ 0.1060939743, 0.1064017103, 83.0649691812, 0.1058247328, 0.1027968836, 0.1002472492, 0.0945580448, 0.088818472 ] } ] } ], "decodes": [], "warnings": [ "No JS8 text decode is expected in Step 48. Final real LDPC/FEC and Varicode/message unpack are not implemented yet.", "Costas7 scoring is a lab candidate extractor; real decoder validation requires actual JS8 WAV samples." ], "next_action": "Run sync-probe on real JS8 WAV captures. If stable sync_candidates appear, Step 48 can continue soft-symbol metric extraction for the LDPC/FEC path." } [webftr-js8-lab] OK [webftr-js8-lab] log file: /decoders/js8_decoder/logs/20260527T084305Z_selftest.log [webftr-js8-lab] manifest: /decoders/js8_decoder/logs/20260527T084305Z_selftest_manifest.json