{
  "ok": true,
  "tool": "webftr-js8-source-confirmed-control-frame-rx-release",
  "tool_version": "step67-source-confirmed-control-frame-rx-release",
  "rx_only_guard": {
    "tx": false,
    "ptt": false,
    "tune": false,
    "send": false,
    "js8call_runtime_control": false
  },
  "no_gui_runtime_started": true,
  "root": "/decoders/js8_decoder",
  "log_dir": "/decoders/js8_decoder/logs",
  "input_reports": [
    {
      "path": "/decoders/js8_decoder/logs/20260527T174048Z_source_varicode_frame_unpack_probe_output.json",
      "exists": true,
      "selected_input": true,
      "input_kind": "step66_source_varicode_frame_unpack_probe"
    }
  ],
  "source_step66_version": "step66-source-varicode-frame-unpack-probe",
  "source_frame_probe_count": 2,
  "source_webftr_display_count_before_release": 0,
  "frame_type_counts": {
    "FrameHeartbeat": 1,
    "FrameDirected": 1
  },
  "release_contract": {
    "allowed_to_display": [
      "FrameCompound",
      "FrameCompoundDirected",
      "FrameDirected",
      "FrameHeartbeat"
    ],
    "blocked_until_future_steps": [
      "FrameData",
      "FrameDataCompressed"
    ],
    "minimum_conditions": [
      "valid_message174_crc12 == true",
      "crc12_distance == 0",
      "source Varicode frame unpack produced a supported fixed control frame",
      "frame_display_candidate == true"
    ],
    "data_text_rule": "FrameData and FrameDataCompressed stay hidden until JSC::decompress/multi-frame assembly is ported and tested."
  },
  "input_candidate_count": 2,
  "webftr_display_count": 2,
  "hidden_candidate_count": 0,
  "webftr_rx_rows": [
    {
      "id": "js8-rx67-de15d3110b0d",
      "source_candidate_id": "js8-frame66-bf1ce62fdb4a",
      "source_decode_id": "js8-msg174-2b7db8e6",
      "mode": "JS8",
      "raw_message174": "001XqOA2iDZ0",
      "valid_message174_crc12": true,
      "crc12_distance": 0,
      "received_crc12": 2920,
      "computed_crc12": 2920,
      "frame_type": "FrameHeartbeat",
      "confidence": "high",
      "confidence_score": 6,
      "confidence_reasons": [
        "valid_heartbeat_callsign",
        "valid_heartbeat_grid"
      ],
      "show_in_rx_list": true,
      "candidate_class": "webftr_control_frame_display_ready",
      "release_guard": "step67_source_confirmed_fixed_control_frame_only",
      "sort_index": 0,
      "source": {
        "source_file": "/decoders/js8_decoder/logs/20260527T150600Z_source_exact_map_probe_output.json",
        "json_path": "$.best_candidate.candidate_bits",
        "source_kind": "generic_bit_list",
        "row_index": 237,
        "map_name": "raw",
        "map_source": null
      },
      "status": "HB",
      "from": "004REY/0V4",
      "to": "@HB",
      "grid": "OJ16",
      "message": "HB 004REY/0V4 OJ16",
      "text": "HB 004REY/0V4 OJ16",
      "display_text": "HB 004REY/0V4 OJ16",
      "is_control_frame": true
    },
    {
      "id": "js8-rx67-bd37f68199eb",
      "source_candidate_id": "js8-frame66-66ab29ded46c",
      "source_decode_id": "js8-msg174-369b0507",
      "mode": "JS8",
      "raw_message174": "Q0VsKWqfJ96x",
      "valid_message174_crc12": true,
      "crc12_distance": 0,
      "received_crc12": 980,
      "computed_crc12": 980,
      "frame_type": "FrameDirected",
      "confidence": "high",
      "confidence_score": 10,
      "confidence_reasons": [
        "valid_directed_from",
        "valid_directed_to",
        "directed_command"
      ],
      "show_in_rx_list": true,
      "candidate_class": "webftr_control_frame_display_ready",
      "release_guard": "step67_source_confirmed_fixed_control_frame_only",
      "sort_index": 1,
      "source": {
        "source_file": "/decoders/js8_decoder/logs/20260527T150600Z_source_exact_map_probe_output.json",
        "json_path": "$.top_llr_row_exports[6].hard_bits",
        "source_kind": "generic_bit_list",
        "row_index": 82,
        "map_name": "raw",
        "map_source": null
      },
      "status": "INFO",
      "from": "9I2TZR/P",
      "to": "0Z0PMP",
      "command": "INFO",
      "extra": 59,
      "extra_value": {
        "kind": "number",
        "value": 28
      },
      "message": "INFO 28",
      "text": "9I2TZR/P 0Z0PMP INFO 28",
      "display_text": "9I2TZR/P 0Z0PMP INFO 28",
      "is_control_frame": true
    }
  ],
  "candidate_rows": [
    {
      "id": "js8-frame66-bf1ce62fdb4a",
      "source_decode_id": "js8-msg174-2b7db8e6",
      "mode": "JS8",
      "text": "001XqOA2iDZ0",
      "valid_message174_crc12": true,
      "crc12_distance": 0,
      "received_crc12": 2920,
      "computed_crc12": 2920,
      "source": {
        "source_file": "/decoders/js8_decoder/logs/20260527T150600Z_source_exact_map_probe_output.json",
        "json_path": "$.best_candidate.candidate_bits",
        "source_kind": "generic_bit_list",
        "row_index": 237,
        "map_name": "raw",
        "map_source": null
      },
      "frame_probe": {
        "message_text_12chars": "001XqOA2iDZ0",
        "length": 12,
        "source_alphabet72_compatible": true,
        "ok": true,
        "unpack72": {
          "value": 107552465662168,
          "value_hex": "0x000061d18282b0d8",
          "rem": 192,
          "top3": 0,
          "top2": 0,
          "first_16_bits": "0000000000000000"
        },
        "frame_type": "FrameHeartbeat",
        "frame_type_bits": 0,
        "displayable_after_frame_unpack": false,
        "frame_fields": {
          "packed_type": 0,
          "callsign": "004REY/0V4",
          "packed_callsign": 52515852374,
          "packed_num": 6936,
          "bits3": 0,
          "valid_callsign_hint": true,
          "kind": "heartbeat_or_cq",
          "is_cq_alt": false,
          "grid": "OJ16",
          "message_token": "HB",
          "valid_grid_hint": true
        },
        "plausibility": {
          "score": 6,
          "reasons": [
            "valid_heartbeat_callsign",
            "valid_heartbeat_grid"
          ]
        },
        "frame_display_candidate": true,
        "display_guard_reason": "step66_annotation_only_pending_jsc_or_multiframe_text_confirmation",
        "candidate_class": "source_varicode_frame_candidate_guarded",
        "display_text_hint": "HB 004REY/0V4 OJ16"
      },
      "show_in_rx_list": false,
      "display_text": "HB 004REY/0V4 OJ16",
      "candidate_class": "source_varicode_frame_candidate_guarded",
      "sort_index": 0
    },
    {
      "id": "js8-frame66-66ab29ded46c",
      "source_decode_id": "js8-msg174-369b0507",
      "mode": "JS8",
      "text": "Q0VsKWqfJ96x",
      "valid_message174_crc12": true,
      "crc12_distance": 0,
      "received_crc12": 980,
      "computed_crc12": 980,
      "source": {
        "source_file": "/decoders/js8_decoder/logs/20260527T150600Z_source_exact_map_probe_output.json",
        "json_path": "$.top_llr_row_exports[6].hard_bits",
        "source_kind": "generic_bit_list",
        "row_index": 82,
        "map_name": "raw",
        "map_source": null
      },
      "frame_probe": {
        "message_text_12chars": "Q0VsKWqfJ96x",
        "length": 12,
        "source_alphabet72_compatible": true,
        "ok": true,
        "unpack72": {
          "value": 7496230937050041489,
          "value_hex": "0x6807f6520d294c91",
          "rem": 187,
          "top3": 3,
          "top2": 1,
          "first_16_bits": "0110100000000111"
        },
        "frame_type": "FrameDirected",
        "frame_type_bits": 3,
        "displayable_after_frame_unpack": false,
        "frame_fields": {
          "from": "9I2TZR/P",
          "to": "0Z0PMP",
          "cmd_id": 17,
          "cmd": " INFO",
          "extra": 59,
          "extra_value": {
            "kind": "number",
            "value": 28
          },
          "portable_from": true,
          "portable_to": false,
          "valid_from_hint": true,
          "valid_to_hint": true
        },
        "plausibility": {
          "score": 10,
          "reasons": [
            "valid_directed_from",
            "valid_directed_to",
            "directed_command"
          ]
        },
        "frame_display_candidate": true,
        "display_guard_reason": "step66_annotation_only_pending_jsc_or_multiframe_text_confirmation",
        "candidate_class": "source_varicode_frame_candidate_guarded",
        "display_text_hint": "9I2TZR/P 0Z0PMP INFO 28"
      },
      "show_in_rx_list": false,
      "display_text": "9I2TZR/P 0Z0PMP INFO 28",
      "candidate_class": "source_varicode_frame_candidate_guarded",
      "sort_index": 1
    }
  ],
  "suppressed_candidates": [],
  "release_decisions": [
    {
      "source_candidate_id": "js8-frame66-bf1ce62fdb4a",
      "raw_message174": "001XqOA2iDZ0",
      "frame_type": "FrameHeartbeat",
      "decision": "released_source_confirmed_control_frame",
      "sort_index": 0,
      "released_row_id": "js8-rx67-de15d3110b0d"
    },
    {
      "source_candidate_id": "js8-frame66-66ab29ded46c",
      "raw_message174": "Q0VsKWqfJ96x",
      "frame_type": "FrameDirected",
      "decision": "released_source_confirmed_control_frame",
      "sort_index": 1,
      "released_row_id": "js8-rx67-bd37f68199eb"
    }
  ],
  "verdict": "source_confirmed_control_frames_ready_for_webftr_rx_rows",
  "warnings": [
    "Step67 is still RX-only and does not start JS8Call GUI/Qt.",
    "Only source-confirmed fixed control frames such as Heartbeat/Directed/Compound are released to webftr_rx_rows.",
    "Free-text Data/Compressed frames remain blocked until JSC::decompress and multi-frame assembly are source-ported and tested."
  ],
  "next_action": "Wire these guarded webftr_rx_rows into the JS8 RX display contract, then continue with JSC::decompress/multi-frame assembly for real JS8 chat text."
}
