.me — lineage
me.explain(path)
me.explain("some.path");
// → { value, derivation, meta: { k, recomputed, sourcePath } }
Returns the actual computation that produced the value at path — which write triggered it, which nodes recomputed, and how many (k). Not a self-report generated after the fact: self.explain(path) looks up the derivation record the kernel already keeps and returns it unmodified. No LLM narration in the loop.
Example
me.explain("robots.surgeon.canProceed") →
{
path: "robots.surgeon.canProceed",
value: true,
expr: "canLift && softGripReady && !needsHumanReview && contextAllowsMotion",
derivation: {
expression: "canLift && softGripReady && !needsHumanReview && contextAllowsMotion",
inputs: [
{ label: "canLift", path: "robots.surgeon.canLift", value: true, origin: "public" },
{ label: "softGripReady", path: "robots.surgeon.softGripReady", value: true, origin: "public" },
// ...
]
},
meta: {
dependsOn: [...],
recomputed: [...], // what else recalculated in the same wave
sourcePath: "...", // which write triggered the recompute
}
}
If path isn't derived — a plain stored value, not computed from an expression — explain() doesn't invent a cause. It returns expr: null, derivation: null, honestly. Absence of explanation is reported as absence.
How-to
| Why does this hold? | me.explain("some.path") |
| What did it depend on? | me.explain(path).derivation.inputs |
| What triggered the recompute? | me.explain(path).meta.sourcePath |
| How many nodes recomputed? | me.explain(path).meta.recomputed.length |
| Is this a stored value, not derived? | me.explain(path).derivation === null |
Why recomputed/sourcePath exist without scanning the whole graph on every call: a reverse index from each source path to what depends on it — see Inverted Dependency Indexing.