Richard sent an article on adding temporal reasoning to Graph-RAG and asked me to work its ideas into Phase 13, or at least exhaust them. Its mechanism is small. Facts become quadruples with a date. A recency weight 0.5^(age/half_life) ranks them. An as-of filter drops anything dated after the query, and the freshest candidate wins a conflict. The result went into temporal_patient_modeling_planning.md as §8.

The as-of filter is the idea worth the most, and not for retrieval:

  • Decision-time snapshots. It is how a recommendation can record exactly the inputs it saw, which is open question 9.
  • Pairing each draw with its own profile. Since 13.1 the profile always takes the latest value. So the February 2025 RGCC draw is scored against a tumor panel reported seven months later. With an as-of build, each draw meets the profile from its own date. Two such pairs give a within-patient test: does the change in ranking track the change in sensitivity?

Adding it meant naming something the article leaves out. A fact has a time it was true of her body and a time Maple could have known it, and the two uses need different ones.

The decay weight needed reshaping before it fit her record:

  • Germline facts never go stale.
  • Medications have intervals, which answer “current?” exactly.
  • Tumor facts go stale through events. Twelve RGCC drugs moved as two coherent classes across the August 2025 recurrence and the BREAKWATER start, and seven months of age is only a proxy for that.

So the half-life generalized into a staleness class per predicate. Exponential decay fits only the labs and ctDNA. Which predicate gets which class is a mapping decision, so the table is a proposal for Richard.

The conflict rule I rejected. In the article’s own example, three assertions weeks apart have weights 0.9812, 0.9775 and 0.9738, and the answer turns on which source wrote last. Latest-wins is right only when the thing was measured again. For conflicting claims about the same state, authority decides and age does not, as with a live press release against the trial registry. A mis-parsed CA 19-9 is also newer than its neighbours.

Reading the code with the article’s question in mind, does every fact know when it was true?, turned up two gaps:

  • #701: the RGCC edges carry no draw date, and repeated observations collide. The insert ignores duplicates on a key with no time component.
  • #702: the LLM snapshot hands genomic alterations over undated, sorted by gene. That invites the VAF-as-trajectory misreading.

My first account of #701 was a reading of the code, and it was wrong in the details. I said row order picks the surviving draw arbitrarily, and that a drug whose class changed keeps two edges. Richard opened read-only prod access and the count told a sharper story:

  • The collision is not arbitrary. Older reports were loaded first and come back first, so her node keeps the oldest value of every repeated measurement.
  • RGCC. All 62 edges whose two draws differ carry the February 2025 score. Paclitaxel shows 75 where September measured 22, and doxorubicin 24 where it measured 79.
  • Alterations and expression follow the earliest report the same way.
  • The class inversion leaves no trace in the predicate. RGCC’s moderate and low grades both map to one predicate, so it is invisible there too. Only naltrexone, which RGCC grades in its natural-substances panel, ended up holding two predicates.

So the model’s input moves only at the predicate level, while every reader of the graph sees her as she was before the recurrence. It is also the inverse of 13.1’s latest-first fix, so the graph and the KGIA profile now describe her at different times. Reading the code found the mechanism; it took the count to find its direction.

One note on Maple itself. The session-start digest served a closed note next to the note that overturns it, a day apart. A half-life cannot separate those; only a supersession link can.