99c145df11c04f80820690fd67e9499f296b4d7d
braney
  Sat Aug 1 12:58:39 2026 -0700
harvesters: resolve #defines per file, not pooled refs #37923 refs #37925 refs #37838

The first nightly run reported a new URL parameter, hggw_term, that had been in
the tree since the hgGateway redesign.  It was not new; the harvester had been
answering the question differently in two checkouts of the same commit.

SEARCH_TERM is "hggw_term" in hgGateway and "hgcd_term" in hgChooseDb.  The
#define table was pooled across the whole tree with setdefault, so the winner
was whichever file the filesystem walk reached first, and hgGateway's reads came
out as hgcd_term in my working tree and hggw_term in a fresh clone.  For a
nightly cron that means mail whenever a directory listing changes order, which
is worse than no cron.

So a name a file defines itself now wins, and a name the tree defines
inconsistently resolves to {NAME} instead of to a guess.  This is the call
bdc473369e1 already made for char * constants, for the same reason and with the
same tradeoff written up in the CONST_RE comment: an honest {ident} beats a
confident wrong answer.  Verified by harvesting both trees and diffing.

Twelve names leave the URL baseline as a result, the gisaidTable and hgg_
prefix families, which were pooled values from sibling CGIs rather than reads
in the file they were attributed to.  Recovering those properly means following
the #include chain to the header that defines them, which is not done here.

The URL catalog carried hgt_tSearch twice, once correctly as the track search
variable and once as hgGateway's search term, which was this bug showing up in
the curated half.  --check did not catch the duplicate because it only looks
within a section.  hgGateway now has hggw_term and hgChooseDb hgcd_term, both
confirmed at their call sites and in their CGI's excludeVars.

diff --git src/hg/utils/urlCommandCatalog/urlCommandCatalog.py src/hg/utils/urlCommandCatalog/urlCommandCatalog.py
index 2cf4b8f915f..3c0118beb1c 100755
--- src/hg/utils/urlCommandCatalog/urlCommandCatalog.py
+++ src/hg/utils/urlCommandCatalog/urlCommandCatalog.py
@@ -862,33 +862,42 @@
               note="Re-render the results already in the cart, rather than "
                    "running a new search.  How the banner and the table's "
                    "'Old BLAT result page' link switch format without "
                    "resubmitting the query."),
             c("wp_f", "action", "hg/hgPcr/hgPcr.c:847", value="<primer>",
               public=True, verified=True, note="Forward primer."),
             c("wp_r", "action", "hg/hgPcr/hgPcr.c:847", value="<primer>",
               public=True, verified=True, note="Reverse primer."),
             c("wp_showPage", "action", "hg/hgPcr/hgPcr.c:847", verified=True),
         ],
     },
     "hgGateway / hgSearch / hgChooseDb": {
         "what": "The gateway and search pages, which share a cartJson command "
                 "channel.",
         "cmds": [
-            c("hgt_tSearch", "action", "hg/hgGateway/hgGateway.c:1250",
+            c("hggw_term", "action", "hg/hgGateway/hgGateway.c:1254",
               value="<term>", verified=True,
-              note="Search term. Same variable name the track search uses."),
+              note="Species or assembly search term for the gateway's "
+                   "autocomplete.  Read before the cart is loaded, to keep the "
+                   "lookup fast, and in hgGateway's excludeVars.  Spelled "
+                   "SEARCH_TERM in the source, which is why this row used to "
+                   "say hgt_tSearch: that name is the track search's, and a "
+                   "pooled #define table answered for both."),
+            c("hgcd_term", "action", "hg/hgChooseDb/hgChooseDb.c:224",
+              value="<term>", verified=True,
+              note="The same search term on hgChooseDb, which spells its own "
+                   "SEARCH_TERM differently.  In that CGI's excludeVars."),
             c("cjCmd", "action", "hg/inc/cartJson.h:11", value="<json>",
               verified=True,
               note="cartJson command channel, used by the page's own AJAX."),
             c("search", "action", "hg/hgSearch/hgSearch.c:563", value="<term>",
               public=True, verified=True, leaks=True,
               note="Search term for the search results page."),
         ],
     },
     "hgIntegrator / hgVai": {
         "what": "Data Integrator and Variant Annotation Integrator.",
         "cmds": [
             c("hgi_doQuery", "action", "hg/hgIntegrator/hgIntegrator.c:48",
               verified=True, note="Run the integrator query."),
             c("hgva_startQuery", "action", "hg/hgVai/hgVai.c:68",
               verified=True, note="Run the annotation query."),