From eced17263c2fd440a83790395e97f773d30960e9 Mon Sep 17 00:00:00 2001 From: Michael Fornaro <20387402+xUnholy@users.noreply.github.com> Date: Wed, 24 Jun 2026 19:12:10 +1000 Subject: [PATCH] feat(toolsearch): make the cellular identifier triad discoverable by "sim" / "cellular" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cellular identifier triad — iccid_decode (SIM serial), imsi_decode (subscriber), imei_decode (device) — is framed in its own docs as the identity set a SIM-swap / forensic-seizure / IMSI-catcher engagement enumerates, but the family terms an operator actually types didn't reach it. A probe against the live tool_search handler showed "decode this sim", "cellular identifiers", and "sim swap forensics" surfaced NONE of the triad: the leg names only matched by acronym ("imei", "imsi") while "sim" and "cellular" matched nothing. Same family-discoverability gap the v0.729 automotive and v0.738 financial synonym clusters fixed. Adds a cellular synonym cluster to internal/toolsearch: - "sim" -> iccid, imsi - "cellular" -> imei, imsi, iccid, gsmtap - "imsi" -> imsi, iccid Both new query tokens are telecom-specific (low collision); a probe confirmed "simulate a button press" and "similar tools" surface no cellular decoder. Known limitation (documented in the test): "sim card number" stays dominated by the broad "card" cluster (nfc/mifare/emv) — a legitimate card interpretation — so the triad ranks just out of its top results there. The family is reachable via "decode this sim" / "cellular identifiers" / "sim swap", which is the win this locks in. Verification: a new regression test (TestToolSearch_CellularOblique Discoverability) pins the three recovered queries; existing discoverability tests still pass. task test (full short suite) 398 ok / 0 fail; task eval 12/12; golangci-lint 0 issues; go vet clean; go build ./... clean. Wired: internal/toolsearch/search.go, internal/tools/tool_search_test.go. --- internal/tools/tool_search_test.go | 23 ++++++++++++++++ internal/toolsearch/search.go | 43 ++++++++++++++++++------------ 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/internal/tools/tool_search_test.go b/internal/tools/tool_search_test.go index dba8b625..2cc9b5b5 100644 --- a/internal/tools/tool_search_test.go +++ b/internal/tools/tool_search_test.go @@ -185,3 +185,26 @@ func TestToolSearch_FinancialObliqueDiscoverability(t *testing.T) { } } } + +// TestToolSearch_CellularObliqueDiscoverability locks in that the cellular +// identifier triad (iccid/imsi/imei) is reachable by the family terms "sim" +// and "cellular" — both returned nothing before the cellular synonym cluster +// was added. (The "card"-heavy phrasing "sim card number" is deliberately +// not pinned: it is dominated by the card-decoder cluster, a legitimate +// interpretation.) +func TestToolSearch_CellularObliqueDiscoverability(t *testing.T) { + cases := map[string]string{ + "decode this sim": "iccid_decode", + "cellular identifiers": "imei_decode", + "sim swap forensics": "iccid_decode", + } + for q, want := range cases { + out, err := toolSearchHandler(context.Background(), nil, map[string]any{"query": q, "limit": 8}) + if err != nil { + t.Fatalf("%q: handler: %v", q, err) + } + if !strings.Contains(out, `"name": "`+want+`"`) { + t.Errorf("query %q did not surface %s in the top results:\n%s", q, want, out) + } + } +} diff --git a/internal/toolsearch/search.go b/internal/toolsearch/search.go index f81a7842..3f237cad 100644 --- a/internal/toolsearch/search.go +++ b/internal/toolsearch/search.go @@ -110,23 +110,32 @@ var synonyms = map[string][]string{ //nolint:gochecknoglobals "securities": {"isin", "securities"}, "brokerage": {"isin", "securities"}, "financial": {"iban", "lei", "isin", "aba"}, - "bluetooth": {"ble", "bluetooth", "bt", "gatt"}, - "ble": {"ble", "bluetooth", "gatt"}, - "ir": {"ir", "infrared", "pronto"}, - "infrared": {"ir", "infrared", "pronto"}, - "jam": {"jammer", "jam"}, - "jammer": {"jammer", "jam"}, - "replay": {"replay", "bruteforce", "tx"}, - "brute": {"bruteforce", "brute", "crack"}, - "crack": {"crack", "hash", "bruteforce", "key"}, - "decode": {"decode", "decrypt", "parse"}, - "decrypt": {"decrypt", "decode"}, - "sniff": {"sniff", "capture", "monitor"}, - "capture": {"capture", "sniff", "monitor"}, - "weather": {"weather", "tpms", "lacrosse", "acurite"}, - "pager": {"pocsag", "pager"}, - "badusb": {"badusb", "ducky", "hid", "keystroke"}, - "keystroke": {"badusb", "hid", "usb"}, + // Cellular identifier triad: iccid_decode (SIM serial), imsi_decode + // (subscriber) and imei_decode (device) are the identities a SIM-swap / + // forensic-seizure / IMSI-catcher engagement enumerates. "phone imei" / + // "subscriber identity" already match by name/description, but the + // natural family terms "sim" and "cellular" ranked the SIM/subscriber + // legs out of the top results. Both are telecom-specific (low collision). + "sim": {"iccid", "imsi"}, + "cellular": {"imei", "imsi", "iccid", "gsmtap"}, + "imsi": {"imsi", "iccid"}, + "bluetooth": {"ble", "bluetooth", "bt", "gatt"}, + "ble": {"ble", "bluetooth", "gatt"}, + "ir": {"ir", "infrared", "pronto"}, + "infrared": {"ir", "infrared", "pronto"}, + "jam": {"jammer", "jam"}, + "jammer": {"jammer", "jam"}, + "replay": {"replay", "bruteforce", "tx"}, + "brute": {"bruteforce", "brute", "crack"}, + "crack": {"crack", "hash", "bruteforce", "key"}, + "decode": {"decode", "decrypt", "parse"}, + "decrypt": {"decrypt", "decode"}, + "sniff": {"sniff", "capture", "monitor"}, + "capture": {"capture", "sniff", "monitor"}, + "weather": {"weather", "tpms", "lacrosse", "acurite"}, + "pager": {"pocsag", "pager"}, + "badusb": {"badusb", "ducky", "hid", "keystroke"}, + "keystroke": {"badusb", "hid", "usb"}, } // Search returns the tools whose fields best match query, highest score first,