CIViC grades every evidence item with a direction. Supports means the study found the effect; Does Not Support means it looked and didn’t. Our connector dropped that field from the raw predicate, so the item that argues against “BRAF V600E predicts resistance to panitumumab” was stored, typed and bridged exactly like one that argues for it. That pair is on Maureen’s own driver, in her cancer, in the same drug class as her cetuximab. The fix was to name what CIViC already ships. The raw predicate now carries the evidence type, the significance and the direction, with Supports unmarked so that every approved bridge member still names exactly the rows Richard approved. No mapping is decided along the way. One case almost slipped through: a no-therapy Predictive item, given its significance, would have been spelled exactly like the variant → drug string the sensitivity bridge approves, and would have joined it silently. Those rows keep the bare name.
The stored rows were renamed in place, each from its own evidence. A re-ingest couldn’t do this job: a plain one moves endpoints (#708), and the pinned one inserts only missing keys, so it would have added the new names beside the old ones. The dry run over 7,520 rows planned 3,166 renames and found zero rows it could not explain. That zero also tested the code that reconstructs the old names, against every stored row. The rename script refuses any row that matches neither naming, so a wrong reconstruction would have shown up as problems. Then I asked Richard. He said yes to the rename and to restoring the evidence items the old key had dropped. He also said yes to keeping Does Not Support rows out of training exports, and later took that back, which was right. The model has to understand negative edges as well as positive ones; what it needs is proof that a negative edge reaches the model as negative. My case for excluding them was “any edge reads as proximity”, and that was too strong. NBFNet’s learned messages can be inhibitory. The real problem is narrower. Our ULTRA fork gives a relation no parameters of its own: it sees a relation only through which other relations share its entities, in a binary graph, and nothing in the objective says a Does Not Support edge makes its positive claim false. Whether it works is something to test, not to assume (#726).
I had told him the restore would add 616 rows. The real dry run said 660. My estimate planned against the store as it was before the rename and subtracted the keys the rename would create. That misses the keys the rename frees. For 44 pairs, the old key had kept the Does Not Support item under the plain name and dropped the Supports one. Renaming the first item opened the name for the second, so those 44 had been invisible to the estimate. One of them is BRAF V600E → panitumumab resistance, Supports, level B, colorectal. Without it, the rename alone would have taken her pair out of the resistance bridge altogether, though CIViC has supporting level-B evidence for it. The count didn’t match what Richard had approved, so I stopped and asked again with the 44 listed. He approved 660, and her pair now holds all four CIViC items, each named for what it says.
The 23-minute gap mattered too. A comment on the issue had counted 16 restored rows as additions to the 565, but the restore had run before the issue was measured, so they were already inside it. The verification query turned up one more thing, unrelated to direction: every CIViC variant entity is named with its gene twice (“BRAF BRAF V600E”), 832 of them on entities other sources share. That went to its own task.
Later I said, almost in passing, that what our model doesn’t sign is a relation’s meaning. Richard stopped on that: he had always assumed our messages were signed. Numerically, they are. A message is the neighbour’s state times a learned relation vector, and that vector can be negative, so an edge type can suppress what the scorer reads. What carries no sign is the meaning. ULTRA gives a relation no parameters of its own and builds its vector from which other relations share its entities. So opposites with similar neighbourhoods push the same way. Another session’s rough count found CIViC’s Supports and Does Not Support twins, and sensitivity and resistance, separated by about a dozen rare relations out of 124. Whether fixing that is a large upgrade is now a spike (#751), not a claim.
He took my recommended option in all five decisions I put to him today, and two of those recommendations were wrong. One was the “exclude” lean above. The other was to fold a known-negatives loss into Arm B. He agreed. But that morning, in another session, he had closed #611 with Arm B changing relation identity only, to keep the comparison clean. A note search found it before I recorded anything; put back to him, he kept Arm B as decided. The lesson I’m keeping: a recommendation from me is close to a decision, so I have to check its premise in our code, and against his standing calls, before I offer it.
Main moved under the PR while this went on. Another session’s #708 work added a naming-version label, which stops a connector from writing rows under names that differ from the stored ones. It had left CIViC undeclared, waiting for this change. The merge declares CIViC’s naming as “2” and keeps my check of the stored rows beside the label check. I also recorded the label on prod’s CIViC source, after re-checking all 8,180 evidence rows. That closed the window, open since the morning’s rename, in which main’s older connector could have written the old names beside the new ones.