{
  "ok": true,
  "tool": "webftr-js8-source-varicode-frame-unpack-probe",
  "tool_version": "step66-source-varicode-frame-unpack-probe",
  "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/20260527T173043Z_source_confirmed_message174_decode_output.json",
      "exists": true,
      "selected_input": true
    }
  ],
  "source_resolution": {
    "selected_source_dir": "/decoders/js8_decoder/runtime/src/JS8Call-improved",
    "checked": [
      {
        "path": "/decoders/js8_decoder/runtime/src/JS8Call-improved",
        "exists": true,
        "is_dir": true
      }
    ]
  },
  "source_snippets": {
    "source_available": true,
    "source_dir": "/decoders/js8_decoder/runtime/src/JS8Call-improved",
    "focused_files_present": [
      "JS8_Main/Varicode.cpp",
      "JS8_Main/Varicode.h",
      "JS8_JSC/JSC.cpp",
      "JS8_JSC/JSC.h",
      "JS8_JSC/JSC_map.cpp",
      "JS8_JSC/JSC_list.cpp",
      "JS8_Mode/JS8.cpp"
    ],
    "focused_files_missing": [],
    "snippets": [
      {
        "name": "unpack72bits",
        "path": "JS8_Main/Varicode.cpp",
        "line": 767,
        "context": {
          "start_line": 762,
          "end_line": 772,
          "lines": [
            {
              "line": 762,
              "text": "    quint32 b = packed & 0xFFFFFFFF;"
            },
            {
              "line": 763,
              "text": "    return pack32bits(a) + pack32bits(b);"
            },
            {
              "line": 764,
              "text": "}"
            },
            {
              "line": 765,
              "text": ""
            },
            {
              "line": 766,
              "text": "// returns the first 64 bits and sets the last 8 bits in pRem"
            },
            {
              "line": 767,
              "text": "quint64 Varicode::unpack72bits(QString const &text, quint8 *pRem) {"
            },
            {
              "line": 768,
              "text": "    quint64 value = 0;"
            },
            {
              "line": 769,
              "text": "    quint8 rem = 0;"
            },
            {
              "line": 770,
              "text": "    quint8 mask2 = ((1 << 2) - 1);"
            },
            {
              "line": 771,
              "text": ""
            },
            {
              "line": 772,
              "text": "    for (int i = 0; i < 10; i++) {"
            }
          ]
        }
      },
      {
        "name": "pack72bits",
        "path": "JS8_Main/Varicode.cpp",
        "line": 767,
        "context": {
          "start_line": 762,
          "end_line": 772,
          "lines": [
            {
              "line": 762,
              "text": "    quint32 b = packed & 0xFFFFFFFF;"
            },
            {
              "line": 763,
              "text": "    return pack32bits(a) + pack32bits(b);"
            },
            {
              "line": 764,
              "text": "}"
            },
            {
              "line": 765,
              "text": ""
            },
            {
              "line": 766,
              "text": "// returns the first 64 bits and sets the last 8 bits in pRem"
            },
            {
              "line": 767,
              "text": "quint64 Varicode::unpack72bits(QString const &text, quint8 *pRem) {"
            },
            {
              "line": 768,
              "text": "    quint64 value = 0;"
            },
            {
              "line": 769,
              "text": "    quint8 rem = 0;"
            },
            {
              "line": 770,
              "text": "    quint8 mask2 = ((1 << 2) - 1);"
            },
            {
              "line": 771,
              "text": ""
            },
            {
              "line": 772,
              "text": "    for (int i = 0; i < 10; i++) {"
            }
          ]
        }
      },
      {
        "name": "unpackDirectedMessage",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1716,
        "context": {
          "start_line": 1711,
          "end_line": 1721,
          "lines": [
            {
              "line": 1711,
              "text": "    if (n)"
            },
            {
              "line": 1712,
              "text": "        *n = match.captured(0).length();"
            },
            {
              "line": 1713,
              "text": "    return Varicode::pack72bits(Varicode::bitsToInt(bits), packed_extra);"
            },
            {
              "line": 1714,
              "text": "}"
            },
            {
              "line": 1715,
              "text": ""
            },
            {
              "line": 1716,
              "text": "QStringList Varicode::unpackDirectedMessage(const QString &text,"
            },
            {
              "line": 1717,
              "text": "                                            quint8 *pType) {"
            },
            {
              "line": 1718,
              "text": "    QStringList unpacked;"
            },
            {
              "line": 1719,
              "text": ""
            },
            {
              "line": 1720,
              "text": "    if (text.length() < 12 || text.contains(\" \")) {"
            },
            {
              "line": 1721,
              "text": "        return unpacked;"
            }
          ]
        }
      },
      {
        "name": "packDirectedMessage",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1605,
        "context": {
          "start_line": 1600,
          "end_line": 1610,
          "lines": [
            {
              "line": 1600,
              "text": ""
            },
            {
              "line": 1601,
              "text": "// J1Y ACK"
            },
            {
              "line": 1602,
              "text": "// J1Y?"
            },
            {
              "line": 1603,
              "text": "// KN4CRD: J1Y$"
            },
            {
              "line": 1604,
              "text": "// KN4CRD: J1Y! HELLO WORLD"
            },
            {
              "line": 1605,
              "text": "QString Varicode::packDirectedMessage(const QString &text,"
            },
            {
              "line": 1606,
              "text": "                                      const QString &mycall, QString *pTo,"
            },
            {
              "line": 1607,
              "text": "                                      bool *pToCompound, QString *pCmd,"
            },
            {
              "line": 1608,
              "text": "                                      QString *pNum, int *n) {"
            },
            {
              "line": 1609,
              "text": "    QString frame;"
            },
            {
              "line": 1610,
              "text": ""
            }
          ]
        }
      },
      {
        "name": "unpackCompoundFrame",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1420,
        "context": {
          "start_line": 1415,
          "end_line": 1425,
          "lines": [
            {
              "line": 1415,
              "text": "                                             bool *isAlt, quint8 *pBits3) {"
            },
            {
              "line": 1416,
              "text": "    quint8 type = Varicode::FrameHeartbeat;"
            },
            {
              "line": 1417,
              "text": "    quint16 num = nmaxgrid;"
            },
            {
              "line": 1418,
              "text": "    quint8 bits3 = 0;"
            },
            {
              "line": 1419,
              "text": ""
            },
            {
              "line": 1420,
              "text": "    QStringList unpacked = unpackCompoundFrame(text, &type, &num, &bits3);"
            },
            {
              "line": 1421,
              "text": "    if (unpacked.isEmpty() || type != Varicode::FrameHeartbeat) {"
            },
            {
              "line": 1422,
              "text": "        return QStringList{};"
            },
            {
              "line": 1423,
              "text": "    }"
            },
            {
              "line": 1424,
              "text": ""
            },
            {
              "line": 1425,
              "text": "    unpacked.append(Varicode::unpackGrid(num & ((1 << 15) - 1)));"
            }
          ]
        }
      },
      {
        "name": "packCompoundFrame",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1401,
        "context": {
          "start_line": 1396,
          "end_line": 1406,
          "lines": [
            {
              "line": 1396,
              "text": "    if (isAlt) {"
            },
            {
              "line": 1397,
              "text": "        packed_extra |= (1 << 15);"
            },
            {
              "line": 1398,
              "text": "        cqNumber = cqs.key(type, 0);"
            },
            {
              "line": 1399,
              "text": "    }"
            },
            {
              "line": 1400,
              "text": ""
            },
            {
              "line": 1401,
              "text": "    frame = packCompoundFrame(callsign, Varicode::FrameHeartbeat, packed_extra,"
            },
            {
              "line": 1402,
              "text": "                              cqNumber);"
            },
            {
              "line": 1403,
              "text": "    if (frame.isEmpty()) {"
            },
            {
              "line": 1404,
              "text": "        if (n)"
            },
            {
              "line": 1405,
              "text": "            *n = 0;"
            },
            {
              "line": 1406,
              "text": "        return frame;"
            }
          ]
        }
      },
      {
        "name": "unpackCompoundMessage",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1491,
        "context": {
          "start_line": 1486,
          "end_line": 1496,
          "lines": [
            {
              "line": 1486,
              "text": "    if (n)"
            },
            {
              "line": 1487,
              "text": "        *n = parsedText.captured(0).length();"
            },
            {
              "line": 1488,
              "text": "    return frame;"
            },
            {
              "line": 1489,
              "text": "}"
            },
            {
              "line": 1490,
              "text": ""
            },
            {
              "line": 1491,
              "text": "QStringList Varicode::unpackCompoundMessage(const QString &text, quint8 *pType,"
            },
            {
              "line": 1492,
              "text": "                                            quint8 *pBits3) {"
            },
            {
              "line": 1493,
              "text": "    quint8 type = Varicode::FrameCompound;"
            },
            {
              "line": 1494,
              "text": "    quint16 extra = nmaxgrid;"
            },
            {
              "line": 1495,
              "text": "    quint8 bits3 = 0;"
            },
            {
              "line": 1496,
              "text": ""
            }
          ]
        }
      },
      {
        "name": "unpackHeartbeatMessage",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1414,
        "context": {
          "start_line": 1409,
          "end_line": 1419,
          "lines": [
            {
              "line": 1409,
              "text": "    if (n)"
            },
            {
              "line": 1410,
              "text": "        *n = parsedText.captured(0).length();"
            },
            {
              "line": 1411,
              "text": "    return frame;"
            },
            {
              "line": 1412,
              "text": "}"
            },
            {
              "line": 1413,
              "text": ""
            },
            {
              "line": 1414,
              "text": "QStringList Varicode::unpackHeartbeatMessage(const QString &text, quint8 *pType,"
            },
            {
              "line": 1415,
              "text": "                                             bool *isAlt, quint8 *pBits3) {"
            },
            {
              "line": 1416,
              "text": "    quint8 type = Varicode::FrameHeartbeat;"
            },
            {
              "line": 1417,
              "text": "    quint16 num = nmaxgrid;"
            },
            {
              "line": 1418,
              "text": "    quint8 bits3 = 0;"
            },
            {
              "line": 1419,
              "text": ""
            }
          ]
        }
      },
      {
        "name": "unpackDataMessage",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1912,
        "context": {
          "start_line": 1907,
          "end_line": 1917,
          "lines": [
            {
              "line": 1907,
              "text": "}"
            },
            {
              "line": 1908,
              "text": ""
            },
            {
              "line": 1909,
              "text": "// TODO: DEPRECATED in 2.2 (still available for decoding legacy frames, but will"
            },
            {
              "line": 1910,
              "text": "// eventually no longer be decodable) unpack data message using 70 bits"
            },
            {
              "line": 1911,
              "text": "// available flagged as data by the first 2 bits"
            },
            {
              "line": 1912,
              "text": "QString Varicode::unpackDataMessage(const QString &text) {"
            },
            {
              "line": 1913,
              "text": "    QString unpacked;"
            },
            {
              "line": 1914,
              "text": ""
            },
            {
              "line": 1915,
              "text": "    if (text.length() < 12 || text.contains(\" \")) {"
            },
            {
              "line": 1916,
              "text": "        return unpacked;"
            },
            {
              "line": 1917,
              "text": "    }"
            }
          ]
        }
      },
      {
        "name": "unpackFastDataMessage",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1983,
        "context": {
          "start_line": 1978,
          "end_line": 1988,
          "lines": [
            {
              "line": 1978,
              "text": "#endif"
            },
            {
              "line": 1979,
              "text": "}"
            },
            {
              "line": 1980,
              "text": ""
            },
            {
              "line": 1981,
              "text": "// unpack data message using the full 72 bits available (with the data flag in"
            },
            {
              "line": 1982,
              "text": "// the i3bit header)"
            },
            {
              "line": 1983,
              "text": "QString Varicode::unpackFastDataMessage(const QString &text) {"
            },
            {
              "line": 1984,
              "text": "    QString unpacked;"
            },
            {
              "line": 1985,
              "text": ""
            },
            {
              "line": 1986,
              "text": "    if (text.length() < 12 || text.contains(\" \")) {"
            },
            {
              "line": 1987,
              "text": "        return unpacked;"
            },
            {
              "line": 1988,
              "text": "    }"
            }
          ]
        }
      },
      {
        "name": "unpackCallsign",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1037,
        "context": {
          "start_line": 1032,
          "end_line": 1042,
          "lines": [
            {
              "line": 1032,
              "text": "    packed = 27 * packed + alphanumeric.indexOf(matched.at(5)) - 10;"
            },
            {
              "line": 1033,
              "text": ""
            },
            {
              "line": 1034,
              "text": "    return packed;"
            },
            {
              "line": 1035,
              "text": "}"
            },
            {
              "line": 1036,
              "text": ""
            },
            {
              "line": 1037,
              "text": "QString Varicode::unpackCallsign(quint32 value, bool portable) {"
            },
            {
              "line": 1038,
              "text": "    foreach (auto key, basecalls.keys()) {"
            },
            {
              "line": 1039,
              "text": "        if (basecalls[key] == value) {"
            },
            {
              "line": 1040,
              "text": "            return key;"
            },
            {
              "line": 1041,
              "text": "        }"
            },
            {
              "line": 1042,
              "text": "    }"
            }
          ]
        }
      },
      {
        "name": "unpackAlphaNumeric50",
        "path": "JS8_Main/Varicode.cpp",
        "line": 905,
        "context": {
          "start_line": 900,
          "end_line": 910,
          "lines": [
            {
              "line": 900,
              "text": "    quint64 packed = a + b + c + d + e + f + g + h + i + j + k;"
            },
            {
              "line": 901,
              "text": ""
            },
            {
              "line": 902,
              "text": "    return packed;"
            },
            {
              "line": 903,
              "text": "}"
            },
            {
              "line": 904,
              "text": ""
            },
            {
              "line": 905,
              "text": "QString Varicode::unpackAlphaNumeric50(quint64 packed) {"
            },
            {
              "line": 906,
              "text": "    QChar word[11];"
            },
            {
              "line": 907,
              "text": ""
            },
            {
              "line": 908,
              "text": "    quint64 tmp = packed % 38;"
            },
            {
              "line": 909,
              "text": "    word[10] = alphanumeric.at(tmp);"
            },
            {
              "line": 910,
              "text": "    packed = packed / 38;"
            }
          ]
        }
      },
      {
        "name": "unpackGrid",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1157,
        "context": {
          "start_line": 1152,
          "end_line": 1162,
          "lines": [
            {
              "line": 1152,
              "text": "    int ilat = pair.second + 90;"
            },
            {
              "line": 1153,
              "text": ""
            },
            {
              "line": 1154,
              "text": "    return ((ilong + 180) / 2) * 180 + ilat;"
            },
            {
              "line": 1155,
              "text": "}"
            },
            {
              "line": 1156,
              "text": ""
            },
            {
              "line": 1157,
              "text": "QString Varicode::unpackGrid(quint16 value) {"
            },
            {
              "line": 1158,
              "text": "    if (value > nbasegrid) {"
            },
            {
              "line": 1159,
              "text": "        return \"\";"
            },
            {
              "line": 1160,
              "text": "    }"
            },
            {
              "line": 1161,
              "text": ""
            },
            {
              "line": 1162,
              "text": "    float dlat = value % 180 - 90;"
            }
          ]
        }
      },
      {
        "name": "unpackCmd",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1207,
        "context": {
          "start_line": 1202,
          "end_line": 1212,
          "lines": [
            {
              "line": 1202,
              "text": "    }"
            },
            {
              "line": 1203,
              "text": ""
            },
            {
              "line": 1204,
              "text": "    return value;"
            },
            {
              "line": 1205,
              "text": "}"
            },
            {
              "line": 1206,
              "text": ""
            },
            {
              "line": 1207,
              "text": "quint8 Varicode::unpackCmd(quint8 value, quint8 *pNum) {"
            },
            {
              "line": 1208,
              "text": "    // if the first bit is 1, this is an SNR with a number encoded in the lower"
            },
            {
              "line": 1209,
              "text": "    // 6 bits"
            },
            {
              "line": 1210,
              "text": "    if (value & (1 << 7)) {"
            },
            {
              "line": 1211,
              "text": "        if (pNum)"
            },
            {
              "line": 1212,
              "text": "            *pNum = value & ((1 << 6) - 1);"
            }
          ]
        }
      },
      {
        "name": "huffDecode",
        "path": "JS8_Main/Varicode.cpp",
        "line": 597,
        "context": {
          "start_line": 592,
          "end_line": 602,
          "lines": [
            {
              "line": 592,
              "text": "    }"
            },
            {
              "line": 593,
              "text": ""
            },
            {
              "line": 594,
              "text": "    return out;"
            },
            {
              "line": 595,
              "text": "}"
            },
            {
              "line": 596,
              "text": ""
            },
            {
              "line": 597,
              "text": "QString Varicode::huffDecode(QMap<QString, QString> const &huff,"
            },
            {
              "line": 598,
              "text": "                             QVector<bool> const &bitvec) {"
            },
            {
              "line": 599,
              "text": "    QString text;"
            },
            {
              "line": 600,
              "text": ""
            },
            {
              "line": 601,
              "text": "    QString bits = Varicode::bitsToStr(bitvec);"
            },
            {
              "line": 602,
              "text": ""
            }
          ]
        }
      },
      {
        "name": "JSC::decompress",
        "path": "JS8_Main/Varicode.cpp",
        "line": 1938,
        "context": {
          "start_line": 1933,
          "end_line": 1943,
          "lines": [
            {
              "line": 1933,
              "text": "    // trim off the pad bits"
            },
            {
              "line": 1934,
              "text": "    bits = bits.mid(1, n - 1);"
            },
            {
              "line": 1935,
              "text": ""
            },
            {
              "line": 1936,
              "text": "    if (compressed) {"
            },
            {
              "line": 1937,
              "text": "        // partial word (s,c)-dense coding with code tables"
            },
            {
              "line": 1938,
              "text": "        unpacked = JSC::decompress(bits);"
            },
            {
              "line": 1939,
              "text": "    } else {"
            },
            {
              "line": 1940,
              "text": "        // huff decode the bits (without escapes)"
            },
            {
              "line": 1941,
              "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
            },
            {
              "line": 1942,
              "text": "    }"
            },
            {
              "line": 1943,
              "text": ""
            }
          ]
        }
      },
      {
        "name": "unpack72bits",
        "path": "JS8_Main/Varicode.h",
        "line": 135,
        "context": {
          "start_line": 130,
          "end_line": 140,
          "lines": [
            {
              "line": 130,
              "text": "    static QString pack32bits(quint32 packed);"
            },
            {
              "line": 131,
              "text": ""
            },
            {
              "line": 132,
              "text": "    static quint64 unpack64bits(QString const &value);"
            },
            {
              "line": 133,
              "text": "    static QString pack64bits(quint64 packed);"
            },
            {
              "line": 134,
              "text": ""
            },
            {
              "line": 135,
              "text": "    static quint64 unpack72bits(QString const &value, quint8 *pRem);"
            },
            {
              "line": 136,
              "text": "    static QString pack72bits(quint64 value, quint8 rem);"
            },
            {
              "line": 137,
              "text": ""
            },
            {
              "line": 138,
              "text": "    static quint32 packAlphaNumeric22(QString const &value, bool isFlag);"
            },
            {
              "line": 139,
              "text": "    static QString unpackAlphaNumeric22(quint32 packed, bool *isFlag);"
            },
            {
              "line": 140,
              "text": ""
            }
          ]
        }
      },
      {
        "name": "pack72bits",
        "path": "JS8_Main/Varicode.h",
        "line": 135,
        "context": {
          "start_line": 130,
          "end_line": 140,
          "lines": [
            {
              "line": 130,
              "text": "    static QString pack32bits(quint32 packed);"
            },
            {
              "line": 131,
              "text": ""
            },
            {
              "line": 132,
              "text": "    static quint64 unpack64bits(QString const &value);"
            },
            {
              "line": 133,
              "text": "    static QString pack64bits(quint64 packed);"
            },
            {
              "line": 134,
              "text": ""
            },
            {
              "line": 135,
              "text": "    static quint64 unpack72bits(QString const &value, quint8 *pRem);"
            },
            {
              "line": 136,
              "text": "    static QString pack72bits(quint64 value, quint8 rem);"
            },
            {
              "line": 137,
              "text": ""
            },
            {
              "line": 138,
              "text": "    static quint32 packAlphaNumeric22(QString const &value, bool isFlag);"
            },
            {
              "line": 139,
              "text": "    static QString unpackAlphaNumeric22(quint32 packed, bool *isFlag);"
            },
            {
              "line": 140,
              "text": ""
            }
          ]
        }
      },
      {
        "name": "unpackDirectedMessage",
        "path": "JS8_Main/Varicode.h",
        "line": 185,
        "context": {
          "start_line": 180,
          "end_line": 190,
          "lines": [
            {
              "line": 180,
              "text": ""
            },
            {
              "line": 181,
              "text": "    static QString packDirectedMessage(QString const &text,"
            },
            {
              "line": 182,
              "text": "                                       QString const &mycall, QString *pTo,"
            },
            {
              "line": 183,
              "text": "                                       bool *pToCompound, QString *pCmd,"
            },
            {
              "line": 184,
              "text": "                                       QString *pNum, int *n);"
            },
            {
              "line": 185,
              "text": "    static QStringList unpackDirectedMessage(QString const &text,"
            },
            {
              "line": 186,
              "text": "                                             quint8 *pType);"
            },
            {
              "line": 187,
              "text": ""
            },
            {
              "line": 188,
              "text": "    static QString packDataMessage(QString const &text, int *n);"
            },
            {
              "line": 189,
              "text": "    static QString unpackDataMessage(QString const &text);"
            },
            {
              "line": 190,
              "text": ""
            }
          ]
        }
      },
      {
        "name": "packDirectedMessage",
        "path": "JS8_Main/Varicode.h",
        "line": 181,
        "context": {
          "start_line": 176,
          "end_line": 186,
          "lines": [
            {
              "line": 176,
              "text": "    static QString packCompoundFrame(const QString &callsign, quint8 type,"
            },
            {
              "line": 177,
              "text": "                                     quint16 num, quint8 bits3);"
            },
            {
              "line": 178,
              "text": "    static QStringList unpackCompoundFrame(const QString &text, quint8 *pType,"
            },
            {
              "line": 179,
              "text": "                                           quint16 *pNum, quint8 *pBits3);"
            },
            {
              "line": 180,
              "text": ""
            },
            {
              "line": 181,
              "text": "    static QString packDirectedMessage(QString const &text,"
            },
            {
              "line": 182,
              "text": "                                       QString const &mycall, QString *pTo,"
            },
            {
              "line": 183,
              "text": "                                       bool *pToCompound, QString *pCmd,"
            },
            {
              "line": 184,
              "text": "                                       QString *pNum, int *n);"
            },
            {
              "line": 185,
              "text": "    static QStringList unpackDirectedMessage(QString const &text,"
            },
            {
              "line": 186,
              "text": "                                             quint8 *pType);"
            }
          ]
        }
      },
      {
        "name": "unpackCompoundFrame",
        "path": "JS8_Main/Varicode.h",
        "line": 178,
        "context": {
          "start_line": 173,
          "end_line": 183,
          "lines": [
            {
              "line": 173,
              "text": "    static QStringList unpackCompoundMessage(const QString &text, quint8 *pType,"
            },
            {
              "line": 174,
              "text": "                                             quint8 *pBits3);"
            },
            {
              "line": 175,
              "text": ""
            },
            {
              "line": 176,
              "text": "    static QString packCompoundFrame(const QString &callsign, quint8 type,"
            },
            {
              "line": 177,
              "text": "                                     quint16 num, quint8 bits3);"
            },
            {
              "line": 178,
              "text": "    static QStringList unpackCompoundFrame(const QString &text, quint8 *pType,"
            },
            {
              "line": 179,
              "text": "                                           quint16 *pNum, quint8 *pBits3);"
            },
            {
              "line": 180,
              "text": ""
            },
            {
              "line": 181,
              "text": "    static QString packDirectedMessage(QString const &text,"
            },
            {
              "line": 182,
              "text": "                                       QString const &mycall, QString *pTo,"
            },
            {
              "line": 183,
              "text": "                                       bool *pToCompound, QString *pCmd,"
            }
          ]
        }
      },
      {
        "name": "packCompoundFrame",
        "path": "JS8_Main/Varicode.h",
        "line": 176,
        "context": {
          "start_line": 171,
          "end_line": 181,
          "lines": [
            {
              "line": 171,
              "text": ""
            },
            {
              "line": 172,
              "text": "    static QString packCompoundMessage(QString const &text, int *n);"
            },
            {
              "line": 173,
              "text": "    static QStringList unpackCompoundMessage(const QString &text, quint8 *pType,"
            },
            {
              "line": 174,
              "text": "                                             quint8 *pBits3);"
            },
            {
              "line": 175,
              "text": ""
            },
            {
              "line": 176,
              "text": "    static QString packCompoundFrame(const QString &callsign, quint8 type,"
            },
            {
              "line": 177,
              "text": "                                     quint16 num, quint8 bits3);"
            },
            {
              "line": 178,
              "text": "    static QStringList unpackCompoundFrame(const QString &text, quint8 *pType,"
            },
            {
              "line": 179,
              "text": "                                           quint16 *pNum, quint8 *pBits3);"
            },
            {
              "line": 180,
              "text": ""
            },
            {
              "line": 181,
              "text": "    static QString packDirectedMessage(QString const &text,"
            }
          ]
        }
      },
      {
        "name": "unpackCompoundMessage",
        "path": "JS8_Main/Varicode.h",
        "line": 173,
        "context": {
          "start_line": 168,
          "end_line": 178,
          "lines": [
            {
              "line": 168,
              "text": "    static QStringList unpackHeartbeatMessage(const QString &text,"
            },
            {
              "line": 169,
              "text": "                                              quint8 *pType, bool *isAlt,"
            },
            {
              "line": 170,
              "text": "                                              quint8 *pBits3);"
            },
            {
              "line": 171,
              "text": ""
            },
            {
              "line": 172,
              "text": "    static QString packCompoundMessage(QString const &text, int *n);"
            },
            {
              "line": 173,
              "text": "    static QStringList unpackCompoundMessage(const QString &text, quint8 *pType,"
            },
            {
              "line": 174,
              "text": "                                             quint8 *pBits3);"
            },
            {
              "line": 175,
              "text": ""
            },
            {
              "line": 176,
              "text": "    static QString packCompoundFrame(const QString &callsign, quint8 type,"
            },
            {
              "line": 177,
              "text": "                                     quint16 num, quint8 bits3);"
            },
            {
              "line": 178,
              "text": "    static QStringList unpackCompoundFrame(const QString &text, quint8 *pType,"
            }
          ]
        }
      },
      {
        "name": "unpackHeartbeatMessage",
        "path": "JS8_Main/Varicode.h",
        "line": 168,
        "context": {
          "start_line": 163,
          "end_line": 173,
          "lines": [
            {
              "line": 163,
              "text": "    static bool isCompoundCallsign(const QString &callsign);"
            },
            {
              "line": 164,
              "text": "    static bool isGroupAllowed(const QString &group);"
            },
            {
              "line": 165,
              "text": ""
            },
            {
              "line": 166,
              "text": "    static QString packHeartbeatMessage(QString const &text,"
            },
            {
              "line": 167,
              "text": "                                        QString const &callsign, int *n);"
            },
            {
              "line": 168,
              "text": "    static QStringList unpackHeartbeatMessage(const QString &text,"
            },
            {
              "line": 169,
              "text": "                                              quint8 *pType, bool *isAlt,"
            },
            {
              "line": 170,
              "text": "                                              quint8 *pBits3);"
            },
            {
              "line": 171,
              "text": ""
            },
            {
              "line": 172,
              "text": "    static QString packCompoundMessage(QString const &text, int *n);"
            },
            {
              "line": 173,
              "text": "    static QStringList unpackCompoundMessage(const QString &text, quint8 *pType,"
            }
          ]
        }
      },
      {
        "name": "unpackDataMessage",
        "path": "JS8_Main/Varicode.h",
        "line": 189,
        "context": {
          "start_line": 184,
          "end_line": 194,
          "lines": [
            {
              "line": 184,
              "text": "                                       QString *pNum, int *n);"
            },
            {
              "line": 185,
              "text": "    static QStringList unpackDirectedMessage(QString const &text,"
            },
            {
              "line": 186,
              "text": "                                             quint8 *pType);"
            },
            {
              "line": 187,
              "text": ""
            },
            {
              "line": 188,
              "text": "    static QString packDataMessage(QString const &text, int *n);"
            },
            {
              "line": 189,
              "text": "    static QString unpackDataMessage(QString const &text);"
            },
            {
              "line": 190,
              "text": ""
            },
            {
              "line": 191,
              "text": "    static QString packFastDataMessage(QString const &text, int *n);"
            },
            {
              "line": 192,
              "text": "    static QString unpackFastDataMessage(QString const &text);"
            },
            {
              "line": 193,
              "text": ""
            },
            {
              "line": 194,
              "text": "    static QList<QPair<QString, int>>"
            }
          ]
        }
      },
      {
        "name": "unpackFastDataMessage",
        "path": "JS8_Main/Varicode.h",
        "line": 192,
        "context": {
          "start_line": 187,
          "end_line": 197,
          "lines": [
            {
              "line": 187,
              "text": ""
            },
            {
              "line": 188,
              "text": "    static QString packDataMessage(QString const &text, int *n);"
            },
            {
              "line": 189,
              "text": "    static QString unpackDataMessage(QString const &text);"
            },
            {
              "line": 190,
              "text": ""
            },
            {
              "line": 191,
              "text": "    static QString packFastDataMessage(QString const &text, int *n);"
            },
            {
              "line": 192,
              "text": "    static QString unpackFastDataMessage(QString const &text);"
            },
            {
              "line": 193,
              "text": ""
            },
            {
              "line": 194,
              "text": "    static QList<QPair<QString, int>>"
            },
            {
              "line": 195,
              "text": "    buildMessageFrames(QString const &mycall, QString const &mygrid,"
            },
            {
              "line": 196,
              "text": "                       QString const &selectedCall, QString const &text,"
            },
            {
              "line": 197,
              "text": "                       bool forceIdentify, bool forceData, int submode,"
            }
          ]
        }
      },
      {
        "name": "unpackCallsign",
        "path": "JS8_Main/Varicode.h",
        "line": 145,
        "context": {
          "start_line": 140,
          "end_line": 150,
          "lines": [
            {
              "line": 140,
              "text": ""
            },
            {
              "line": 141,
              "text": "    static quint64 packAlphaNumeric50(QString const &value);"
            },
            {
              "line": 142,
              "text": "    static QString unpackAlphaNumeric50(quint64 packed);"
            },
            {
              "line": 143,
              "text": ""
            },
            {
              "line": 144,
              "text": "    static quint32 packCallsign(QString const &value, bool *pPortable);"
            },
            {
              "line": 145,
              "text": "    static QString unpackCallsign(quint32 value, bool portable);"
            },
            {
              "line": 146,
              "text": ""
            },
            {
              "line": 147,
              "text": "    static QString deg2grid(float dlong, float dlat);"
            },
            {
              "line": 148,
              "text": "    static QPair<float, float> grid2deg(QString const &grid);"
            },
            {
              "line": 149,
              "text": "    static quint16 packGrid(QString const &value);"
            },
            {
              "line": 150,
              "text": "    static QString unpackGrid(quint16 value);"
            }
          ]
        }
      },
      {
        "name": "unpackAlphaNumeric50",
        "path": "JS8_Main/Varicode.h",
        "line": 142,
        "context": {
          "start_line": 137,
          "end_line": 147,
          "lines": [
            {
              "line": 137,
              "text": ""
            },
            {
              "line": 138,
              "text": "    static quint32 packAlphaNumeric22(QString const &value, bool isFlag);"
            },
            {
              "line": 139,
              "text": "    static QString unpackAlphaNumeric22(quint32 packed, bool *isFlag);"
            },
            {
              "line": 140,
              "text": ""
            },
            {
              "line": 141,
              "text": "    static quint64 packAlphaNumeric50(QString const &value);"
            },
            {
              "line": 142,
              "text": "    static QString unpackAlphaNumeric50(quint64 packed);"
            },
            {
              "line": 143,
              "text": ""
            },
            {
              "line": 144,
              "text": "    static quint32 packCallsign(QString const &value, bool *pPortable);"
            },
            {
              "line": 145,
              "text": "    static QString unpackCallsign(quint32 value, bool portable);"
            },
            {
              "line": 146,
              "text": ""
            },
            {
              "line": 147,
              "text": "    static QString deg2grid(float dlong, float dlat);"
            }
          ]
        }
      },
      {
        "name": "unpackGrid",
        "path": "JS8_Main/Varicode.h",
        "line": 150,
        "context": {
          "start_line": 145,
          "end_line": 155,
          "lines": [
            {
              "line": 145,
              "text": "    static QString unpackCallsign(quint32 value, bool portable);"
            },
            {
              "line": 146,
              "text": ""
            },
            {
              "line": 147,
              "text": "    static QString deg2grid(float dlong, float dlat);"
            },
            {
              "line": 148,
              "text": "    static QPair<float, float> grid2deg(QString const &grid);"
            },
            {
              "line": 149,
              "text": "    static quint16 packGrid(QString const &value);"
            },
            {
              "line": 150,
              "text": "    static QString unpackGrid(quint16 value);"
            },
            {
              "line": 151,
              "text": ""
            },
            {
              "line": 152,
              "text": "    static quint8 packNum(QString const &num, bool *ok);"
            },
            {
              "line": 153,
              "text": "    static quint8 packPwr(QString const &pwr, bool *ok);"
            },
            {
              "line": 154,
              "text": "    static quint8 packCmd(quint8 cmd, quint8 num, bool *pPackedNum);"
            },
            {
              "line": 155,
              "text": "    static quint8 unpackCmd(quint8 value, quint8 *pNum);"
            }
          ]
        }
      },
      {
        "name": "unpackCmd",
        "path": "JS8_Main/Varicode.h",
        "line": 155,
        "context": {
          "start_line": 150,
          "end_line": 160,
          "lines": [
            {
              "line": 150,
              "text": "    static QString unpackGrid(quint16 value);"
            },
            {
              "line": 151,
              "text": ""
            },
            {
              "line": 152,
              "text": "    static quint8 packNum(QString const &num, bool *ok);"
            },
            {
              "line": 153,
              "text": "    static quint8 packPwr(QString const &pwr, bool *ok);"
            },
            {
              "line": 154,
              "text": "    static quint8 packCmd(quint8 cmd, quint8 num, bool *pPackedNum);"
            },
            {
              "line": 155,
              "text": "    static quint8 unpackCmd(quint8 value, quint8 *pNum);"
            },
            {
              "line": 156,
              "text": ""
            },
            {
              "line": 157,
              "text": "    static bool isSNRCommand(const QString &cmd);"
            },
            {
              "line": 158,
              "text": "    static bool isCommandAllowed(const QString &cmd);"
            },
            {
              "line": 159,
              "text": "    static bool isCommandBuffered(const QString &cmd);"
            },
            {
              "line": 160,
              "text": "    static int isCommandChecksumed(const QString &cmd);"
            }
          ]
        }
      },
      {
        "name": "huffDecode",
        "path": "JS8_Main/Varicode.h",
        "line": 107,
        "context": {
          "start_line": 102,
          "end_line": 112,
          "lines": [
            {
              "line": 102,
              "text": "    static QStringList parseCallsigns(QString const &input);"
            },
            {
              "line": 103,
              "text": "    static QStringList parseGrids(QString const &input);"
            },
            {
              "line": 104,
              "text": ""
            },
            {
              "line": 105,
              "text": "    static QList<QPair<int, QVector<bool>>>"
            },
            {
              "line": 106,
              "text": "    huffEncode(const QMap<QString, QString> &huff, QString const &text);"
            },
            {
              "line": 107,
              "text": "    static QString huffDecode(const QMap<QString, QString> &huff,"
            },
            {
              "line": 108,
              "text": "                              QVector<bool> const &bitvec);"
            },
            {
              "line": 109,
              "text": "    static QSet<QString> huffValidChars(const QMap<QString, QString> &huff);"
            },
            {
              "line": 110,
              "text": ""
            },
            {
              "line": 111,
              "text": "    static QVector<bool> bytesToBits(char *bitvec, int n);"
            },
            {
              "line": 112,
              "text": "    static QVector<bool> strToBits(QString const &bitvec);"
            }
          ]
        }
      },
      {
        "name": "JSC::decompress",
        "path": "JS8_JSC/JSC.cpp",
        "line": 127,
        "context": {
          "start_line": 122,
          "end_line": 132,
          "lines": [
            {
              "line": 122,
              "text": " * @brief Decompresses the given bit vector into a string."
            },
            {
              "line": 123,
              "text": " *"
            },
            {
              "line": 124,
              "text": " * @param bitvec"
            },
            {
              "line": 125,
              "text": " * @return QString"
            },
            {
              "line": 126,
              "text": " */"
            },
            {
              "line": 127,
              "text": "QString JSC::decompress(Codeword const &bitvec) {"
            },
            {
              "line": 128,
              "text": "    const quint32 b = 4;"
            },
            {
              "line": 129,
              "text": "    const quint32 s = 7;"
            },
            {
              "line": 130,
              "text": "    const quint32 c = pow(2, b) - s;"
            },
            {
              "line": 131,
              "text": ""
            },
            {
              "line": 132,
              "text": "    QStringList out;"
            }
          ]
        }
      }
    ]
  },
  "source_contract": {
    "message174_alphabet": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+",
    "alphabet72": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+/?.",
    "frame_types": {
      "0": "FrameHeartbeat",
      "1": "FrameCompound",
      "2": "FrameCompoundDirected",
      "3": "FrameDirected",
      "4": "FrameData",
      "5": "FrameData",
      "6": "FrameDataCompressed",
      "7": "FrameDataCompressed"
    },
    "implemented_rx_unpack": [
      "unpack72bits",
      "frame_type",
      "directed",
      "heartbeat",
      "compound",
      "callsign",
      "grid",
      "legacy_huff_data_probe"
    ],
    "not_yet_ported": [
      "JSC::decompress full compressed text",
      "multi-frame buffer assembly",
      "WebFTR live integration"
    ]
  },
  "input_decode_count": 2,
  "frame_probe_count": 2,
  "webftr_display_count": 0,
  "hidden_candidate_count": 2,
  "frame_type_counts": {
    "FrameHeartbeat": 1,
    "FrameDirected": 1
  },
  "webftr_rx_rows": [],
  "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": [
    {
      "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
    }
  ],
  "verdict": "source_varicode_frames_classified_but_not_displayable",
  "warnings": [
    "Step66 is still RX-only diagnostics. It classifies message174 text as JS8 Varicode frame families but does not start JS8Call GUI/Qt.",
    "Rows remain hidden unless callsign/grid/command/text plausibility survives source-style frame unpacking.",
    "Compressed Data frames still require a later JSC::decompress port before real JS8 chat text can be displayed."
  ],
  "next_action": "If frame types look plausible but hidden, port JSC::decompress and multi-frame assembly next; if a display row appears, wire webftr_rx_rows into the JS8 RX UI contract."
}
