clanker / app /trace_view.py
deucebucket's picture
fix: rank trace contributors by deviation from neutral (drop neutral words like 'i')
0bf920b verified
Raw
History Blame Contribute Delete
2.87 kB
"""Shape compute_vadug's raw trace into display + audit data.
trace entries look like {word, role, coeff, v, a, d, u, g} (per-word deltas);
trace['structures'] is a list of StructureMatch (has .name or str()).
"""
from __future__ import annotations
_INERT = {None, "", "GAS", "CONNECTOR"}
def _struct_names(structures) -> list[str]:
out = []
for s in structures or []:
out.append(getattr(s, "pattern", None) or getattr(s, "name", None) or str(s))
return out
def shape_trace(trace: dict) -> dict:
"""Shape raw trace into display and audit data.
Args:
trace: raw trace dict from compute_vadug with 'trace' list and 'structures'
Returns:
Shaped trace dict with:
- words: list of per-word entries with role and dimension deltas
- structures: list of matched pattern names
- contributors: top 5 words by absolute impact
- unknown_tokens: alpha words with inert roles and zero movement
- suspected_gap: bool, True if very few words fired
"""
entries = trace.get("trace", []) or []
words = []
unknown = []
for e in entries:
role = e.get("role")
dv = int(e.get("v", 0))
da = int(e.get("a", 0))
dd = int(e.get("d", 0))
du = int(e.get("u", 0))
dg = int(e.get("g", 0))
words.append({
"word": e.get("word", ""),
"role": role or "GAS",
"dv": dv,
"da": da,
"dd": dd,
"du": du,
"dg": dg,
})
# Check if word moved
moved = any(abs(x) > 0 for x in [dv, da, dd, du, dg])
# Flag as unknown: alpha word, inert role, no movement
if role in _INERT and not moved and e.get("word", "").isalpha():
unknown.append(e.get("word", ""))
# Top 5 contributors by DEVIATION from neutral (128 for v/a/d/g, 0 for u —
# these per-word values are absolute force-target coords, not deltas). Ranking
# by deviation (not raw coord sum) keeps strongly-negative words from sorting
# last, and drops neutral function words ("i", "to") that carry no force so
# they don't appear as "top contributors".
def _dev(w):
return (abs(w["dv"] - 128) + abs(w["da"] - 128) + abs(w["dd"] - 128)
+ abs(w["du"]) + abs(w["dg"] - 128))
contributors = sorted(
[w for w in words if _dev(w) > 3],
key=_dev,
reverse=True,
)[:5]
# Flag suspected gaps: few words actually fired
fired = [w for w in words if w["role"] not in _INERT]
suspected_gap = len(words) >= 3 and len(fired) <= max(1, len(words) // 5)
return {
"words": words,
"structures": _struct_names(trace.get("structures")),
"contributors": contributors,
"unknown_tokens": unknown,
"suspected_gap": suspected_gap,
}