changesBetween
What changed from one version of a definition to another: the definitions the newer reaches that the older doesn't whose own code changed (not those only re-hashed for what they use), by name now (or as they were called, with their hash, when no longer named). The definition itself is among them when its own code changed.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; export function changesBetween(cb: Codebase, before: string, after: string): string[] { const reach = (from: string) => { const seen = new Set<string>(); const todo = [from]; while (todo.length) { const h = todo.pop()!; if (seen.has(h)) continue; seen.add(h); for (const d of cb.store.getDef(h)?.deps ?? []) if (d.ref.startsWith("#")) todo.push(d.ref.slice(1)); } return seen; }; const old = reach(before); const fresh = new Set([...reach(after)].filter((h) => !old.has(h))); // its own code changed: nothing it uses is new, but what's in its own cycle const own = [...fresh].filter((h) => { const rec = cb.store.getDef(h); return !(rec?.deps ?? []).some( (d) => d.ref.startsWith("#") && fresh.has(d.ref.slice(1)) && cb.store.getDef(d.ref.slice(1))?.componentHash !== rec?.componentHash, ); }); return own.map((h) => { const named = cb.store.pathsOf(h)[0]; return named ?? `${cb.store.getDef(h)?.nameHint ?? "?"} (#${h.slice(0, 8)})`; }); }