Spaces:
Running
Running
| /* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| THE DECISION TRACE (2026-08-01) | |
| A reviewing scientist asked for "a function where the entire decision | |
| process is shown" β numbered steps, each with an objective, a rationale, a | |
| status and a result. The cockpit rail already renders every one of those | |
| events. It renders them as a river: ten minutes into a run, "what did it | |
| actually do, and why did it do that" is unanswerable, because the answer | |
| scrolled off the top and the transcript is interleaved with prose. | |
| So this invents no instrumentation. Every field below comes out of the | |
| orchestrator's existing event stream (dee/core/orchestrator.py `_emit`): | |
| kind fields this file reads | |
| ββββββββββββ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| user text β the goal, or a mid-run correction | |
| text text β the model's own words BEFORE a call, | |
| which is the only honest "rationale" | |
| available β see _pendingWhy | |
| plan steps[{step,status}]β the agent's own decomposition | |
| tool_call id,name,verb,args,at | |
| tool_result id,ok,summary,error,at | |
| ask question,options | |
| compacted note | |
| error error | |
| checkpoint / done β run outcome, not a step | |
| Two things this deliberately does NOT do: | |
| β’ It does not time steps in the browser. Every event carries a server | |
| `at` (unix seconds, 3dp), so a step's duration is result.at β call.at β | |
| real, and still correct after a reload replays the run from seq 0. A | |
| client-side stopwatch would show nothing on replay, or worse, show the | |
| replay's own duration and pass it off as the step's. | |
| β’ It does not synthesise a reason. If the model said nothing before a | |
| call, the row says so and offers the active plan step instead, labelled | |
| as the plan rather than quoted as the model's reasoning. | |
| Public surface (cockpit.js is the only caller): | |
| TDTrace.push(ev) one orchestrator event, in order | |
| TDTrace.reset() new/switched run | |
| TDTrace.setMeta({...}) cost + context + status from the poll | |
| TDTrace.count() number of steps, for the entry-point button | |
| TDTrace.open/close/toggle/isOpen | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| (function () { | |
| "use strict"; | |
| /* ββ state βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| var entries = []; // ordered trace entries (see push) | |
| var byId = {}; // tool_call id β its entry | |
| var goal = ""; | |
| var meta = { cost: 0, ctxUsed: 0, ctxLimit: 0, status: "" }; | |
| var planRev = 0; | |
| var lastPlan = null; // most recent plan steps, for the fallback reason | |
| var pendingWhy = []; // assistant prose since the previous step | |
| var els = null; | |
| var isOpen = false; | |
| function esc(s) { | |
| return String(s == null ? "" : s) | |
| .replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") | |
| .replace(/"/g, """); | |
| } | |
| /* ββ ingest ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| /* Never let a malformed event break the rail. applyEvent calls this | |
| inline, so a throw here would kill the transcript too. */ | |
| function push(ev) { | |
| try { _push(ev); } catch (e) { /* a trace row is never worth a dead run */ } | |
| if (isOpen) render(); | |
| } | |
| function _push(ev) { | |
| if (!ev || !ev.kind) return; | |
| switch (ev.kind) { | |
| case "user": | |
| // The FIRST user turn is the goal; everything after it is a | |
| // course correction, and which one it was is exactly what a | |
| // reader of a finished run needs to know. | |
| if (!goal) { goal = ev.text || ""; return; } | |
| pendingWhy = []; | |
| entries.push({ t: "steer", label: "Course correction", | |
| text: ev.text || "" }); | |
| return; | |
| case "text": | |
| if (ev.text) pendingWhy.push(String(ev.text)); | |
| return; | |
| case "plan": | |
| planRev++; | |
| lastPlan = ev.steps || []; | |
| entries.push({ t: "plan", rev: planRev, steps: lastPlan.slice() }); | |
| pendingWhy = []; | |
| return; | |
| case "tool_call": { | |
| var e = { | |
| t: "tool", | |
| id: ev.id || "", | |
| name: ev.name || "", | |
| verb: ev.verb || ev.name || "step", | |
| args: ev.args || {}, | |
| at: typeof ev.at === "number" ? ev.at : null, | |
| status: "run", | |
| why: pendingWhy.join("\n\n").trim(), | |
| // Snapshot the plan step that was active AT THIS MOMENT. | |
| // Reading it later would attribute a step to whatever the | |
| // plan says now, which is a different claim. | |
| planStep: _activePlanStep(), | |
| }; | |
| pendingWhy = []; | |
| entries.push(e); | |
| if (e.id) byId[e.id] = e; | |
| return; | |
| } | |
| case "tool_result": { | |
| var target = ev.id ? byId[ev.id] : null; | |
| if (!target) { | |
| // A result with no matching call (older transcript, or a | |
| // truncated replay). Record it rather than dropping it. | |
| target = { t: "tool", name: ev.name || "", verb: ev.name || "step", | |
| args: {}, at: null, why: "", planStep: "" }; | |
| entries.push(target); | |
| } | |
| target.status = ev.ok ? "ok" : "fail"; | |
| target.summary = ev.summary || ""; | |
| target.error = ev.error || ""; | |
| target.resultKind = ev.result_kind || ""; | |
| target.endAt = typeof ev.at === "number" ? ev.at : null; | |
| return; | |
| } | |
| case "ask": | |
| entries.push({ t: "ask", question: ev.question || "", | |
| options: ev.options || [] }); | |
| pendingWhy = []; | |
| return; | |
| // The runtime stopped a call that would change the user's data and | |
| // handed the decision over. In a record of "what did it do and | |
| // why", that is not a footnote β it is the moment a human decided, | |
| // and the reason a later step either exists or doesn't. The | |
| // tool row itself is already in `entries` (tool_call is emitted | |
| // before the gate), so this marks WHY it is sitting there | |
| // unfinished until the answer lands. | |
| case "confirm": | |
| if (ev.id && byId[ev.id]) byId[ev.id].status = "held"; | |
| entries.push({ t: "confirm", id: ev.id || "", | |
| verb: ev.verb || ev.name || "this action", | |
| detail: ev.detail || "" }); | |
| pendingWhy = []; | |
| return; | |
| case "compacted": | |
| entries.push({ t: "compacted", note: ev.note || "" }); | |
| return; | |
| // A sequence was removed from a reply because it traced to | |
| // nothing this run retrieved. In a methods record this is the | |
| // opposite of a footnote: it is the runtime documenting that the | |
| // agent tried to answer from memory and was not allowed to. | |
| case "provenance": | |
| entries.push({ t: "provenance", | |
| withheld: ev.withheld || [] }); | |
| return; | |
| case "error": | |
| entries.push({ t: "error", text: ev.error || "" }); | |
| return; | |
| case "checkpoint": | |
| meta.checkpoint = true; | |
| return; | |
| case "done": | |
| meta.done = true; | |
| return; | |
| default: | |
| return; | |
| } | |
| } | |
| function _activePlanStep() { | |
| if (!lastPlan || !lastPlan.length) return ""; | |
| for (var i = 0; i < lastPlan.length; i++) { | |
| if (lastPlan[i].status === "active") return lastPlan[i].step || ""; | |
| } | |
| for (var j = 0; j < lastPlan.length; j++) { | |
| if ((lastPlan[j].status || "pending") === "pending") return lastPlan[j].step || ""; | |
| } | |
| return ""; | |
| } | |
| function reset() { | |
| entries = []; byId = {}; goal = ""; planRev = 0; lastPlan = null; | |
| pendingWhy = []; | |
| meta = { cost: 0, ctxUsed: 0, ctxLimit: 0, status: "" }; | |
| if (isOpen) render(); | |
| } | |
| function setMeta(m) { | |
| if (!m) return; | |
| if (typeof m.cost === "number") meta.cost = m.cost; | |
| if (typeof m.ctxUsed === "number") meta.ctxUsed = m.ctxUsed; | |
| if (typeof m.ctxLimit === "number") meta.ctxLimit = m.ctxLimit; | |
| if (typeof m.status === "string") meta.status = m.status; | |
| if (typeof m.title === "string") meta.title = m.title; | |
| if (isOpen) render(); | |
| } | |
| function count() { | |
| return entries.length; | |
| } | |
| /* ββ formatting ββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| function secs(a, b) { | |
| if (typeof a !== "number" || typeof b !== "number") return ""; | |
| var d = Math.max(0, b - a); | |
| if (d < 60) return (d < 10 ? d.toFixed(1) : Math.round(d)) + "s"; | |
| return Math.floor(d / 60) + "m " + Math.round(d % 60) + "s"; | |
| } | |
| /* Arguments the agent actually passed. The server already strips | |
| `sequence` before emitting, so nothing here can leak a construct; the | |
| remaining values are short scalars (gene, organism, k, host). Anything | |
| structured is summarised rather than dumped β a trace row is a record, | |
| not a JSON viewer. */ | |
| function argRows(args) { | |
| var keys = Object.keys(args || {}); | |
| if (!keys.length) return ""; | |
| var out = ""; | |
| for (var i = 0; i < keys.length; i++) { | |
| var k = keys[i], v = args[k]; | |
| var txt; | |
| if (v == null) continue; | |
| if (Array.isArray(v)) txt = v.length + " item" + (v.length === 1 ? "" : "s"); | |
| else if (typeof v === "object") txt = "(object)"; | |
| else { | |
| txt = String(v); | |
| if (txt.length > 160) txt = txt.slice(0, 160) + "β¦"; | |
| } | |
| out += "<dt>" + esc(k) + "</dt><dd>" + esc(txt) + "</dd>"; | |
| } | |
| return out ? '<dl class="td-step-kv">' + out + "</dl>" : ""; | |
| } | |
| function argSummary(args) { | |
| var order = ["gene_symbol", "organism", "text", "target", "host", "property", "k"]; | |
| var bits = []; | |
| for (var i = 0; i < order.length; i++) { | |
| var v = (args || {})[order[i]]; | |
| if (v == null || typeof v === "object") continue; | |
| var s = String(v); | |
| if (!s || s.length > 48) continue; | |
| bits.push(order[i] === "k" ? "k=" + s : s); | |
| } | |
| return bits.join(" Β· "); | |
| } | |
| // "held" is not "running". A step waiting on the user has not stalled and | |
| // is not costing anything β saying "running" next to it would misreport | |
| // the one state where nothing is happening on purpose. | |
| var STATUS_WORD = { ok: "done", fail: "failed", run: "running", | |
| held: "waiting on you" }; | |
| function toolRow(e, n) { | |
| var cls = e.status === "ok" ? "td-step--ok" | |
| : e.status === "fail" ? "td-step--fail" : "td-step--run"; | |
| var el = secs(e.at, e.endAt); | |
| var args = argSummary(e.args); | |
| var why = e.why | |
| ? '<p>' + esc(e.why) + "</p>" | |
| : (e.planStep | |
| ? '<p class="td-muted">The model called this without narrating it. ' | |
| + "The plan step active at the time was: " + esc(e.planStep) + "</p>" | |
| : '<p class="td-muted">The model called this without narrating it, ' | |
| + "and no plan was set.</p>"); | |
| var result; | |
| if (e.status === "held") { | |
| result = '<p class="td-muted">Not run β this one changes your saved ' | |
| + "work, so it is waiting for you to approve it.</p>"; | |
| } else if (e.status === "run") { | |
| result = '<p class="td-muted">Still running.</p>'; | |
| } else if (e.status === "fail") { | |
| result = "<p>" + esc(e.error || "Failed.") + "</p>" | |
| + (e.resultKind ? '<p class="td-muted">' + esc(e.resultKind) + "</p>" : ""); | |
| } else { | |
| result = e.summary ? "<p>" + esc(e.summary) + "</p>" | |
| : '<p class="td-muted">Completed; the tool returned no summary line.</p>'; | |
| } | |
| return '<li class="td-step ' + cls + '"><details><summary>' | |
| + '<span class="td-step-n">' + n + "</span>" | |
| + '<span class="td-step-main">' | |
| + '<span class="td-step-obj">' + esc(e.verb) + "</span>" | |
| + (args ? '<span class="td-step-args">' + esc(args) + "</span>" : "") | |
| + "</span>" | |
| + '<span class="td-step-status">' + esc(STATUS_WORD[e.status] || e.status) + "</span>" | |
| + '<span class="td-step-t">' + esc(el) + "</span>" | |
| + "</summary>" | |
| + '<div class="td-step-detail">' | |
| + '<p class="td-step-lbl">Objective</p><p>' + esc(e.verb) | |
| + (e.name ? " β tool <code>" + esc(e.name) + "</code>" : "") + "</p>" | |
| + '<p class="td-step-lbl">Rationale</p>' + why | |
| + (argRows(e.args) ? '<p class="td-step-lbl">Inputs</p>' + argRows(e.args) : "") | |
| + '<p class="td-step-lbl">Result</p>' + result | |
| + "</div></details></li>"; | |
| } | |
| function plainRow(n, title, sub, body, cls) { | |
| return '<li class="td-step ' + (cls || "") + '"><details><summary>' | |
| + '<span class="td-step-n">' + n + "</span>" | |
| + '<span class="td-step-main"><span class="td-step-obj">' + esc(title) + "</span>" | |
| + (sub ? '<span class="td-step-args">' + esc(sub) + "</span>" : "") | |
| + "</span>" | |
| + '<span class="td-step-status">note</span>' | |
| + '<span class="td-step-t"></span>' | |
| + "</summary>" | |
| + '<div class="td-step-detail">' + body + "</div></details></li>"; | |
| } | |
| var PLAN_GLYPH = { done: "β", active: "βΈ", skipped: "β", pending: "β" }; | |
| function planRow(e, n) { | |
| var items = ""; | |
| for (var i = 0; i < e.steps.length; i++) { | |
| var st = e.steps[i].status || "pending"; | |
| items += '<li class="td-plan--' + esc(st) + '">' | |
| + '<span class="td-plan-g">' + (PLAN_GLYPH[st] || "β") + "</span>" | |
| + "<span>" + esc(e.steps[i].step || "") + "</span></li>"; | |
| } | |
| var done = 0; | |
| for (var j = 0; j < e.steps.length; j++) if (e.steps[j].status === "done") done++; | |
| return plainRow( | |
| n, | |
| e.rev === 1 ? "Set out a plan" : "Revised the plan (revision " + e.rev + ")", | |
| e.steps.length + " step" + (e.steps.length === 1 ? "" : "s") + " Β· " + done + " done", | |
| '<p class="td-step-lbl">Plan at this point</p><ul class="td-plan">' + items + "</ul>"); | |
| } | |
| function render() { | |
| if (!els) return; | |
| var rows = ""; | |
| var n = 0; | |
| for (var i = 0; i < entries.length; i++) { | |
| var e = entries[i]; | |
| n++; | |
| if (e.t === "tool") rows += toolRow(e, n); | |
| else if (e.t === "plan") rows += planRow(e, n); | |
| else if (e.t === "steer") { | |
| rows += plainRow(n, "You steered the run", "", | |
| '<p class="td-step-lbl">What you said</p><p>' + esc(e.text) + "</p>" | |
| + '<p class="td-step-lbl">Effect</p><p class="td-muted">Applied at the ' | |
| + "next step boundary, so at most one tool call was already in flight.</p>"); | |
| } else if (e.t === "ask") { | |
| rows += plainRow(n, "Asked you a question", "run parked", | |
| '<p class="td-step-lbl">Question</p><p>' + esc(e.question) + "</p>" | |
| + (e.options.length | |
| ? '<p class="td-step-lbl">Options offered</p><p>' | |
| + esc(e.options.join(" Β· ")) + "</p>" : "")); | |
| } else if (e.t === "confirm") { | |
| rows += plainRow(n, "Stopped for your approval", "run parked", | |
| '<p class="td-step-lbl">Action held</p><p>' + esc(e.verb) + "</p>" | |
| + (e.detail ? '<p class="td-step-lbl">What it would do</p><p>' | |
| + esc(e.detail) + "</p>" : "") | |
| + '<p class="td-step-lbl">Why</p><p class="td-muted">This tool changes ' | |
| + "your saved work, so the runtime does not let the agent decide on its " | |
| + "own. The step above stays unfinished until you answer.</p>"); | |
| } else if (e.t === "compacted") { | |
| rows += plainRow(n, "Condensed earlier steps", "context limit", | |
| '<p class="td-step-lbl">Why</p><p>Earlier messages were replaced by a ' | |
| + "deterministic digest to stay inside the context window. The original " | |
| + "goal is pinned and never condensed.</p>" | |
| + (e.note ? '<p class="td-step-lbl">Digest</p><p>' + esc(e.note) + "</p>" : "")); | |
| } else if (e.t === "provenance") { | |
| rows += plainRow(n, "Withheld an unsourced sequence", | |
| (e.withheld || []).join(", ") + " nt/aa", | |
| '<p class="td-step-lbl">Why</p><p>The reply contained a sequence ' | |
| + "that did not come from any tool result in this run, from you, or " | |
| + "from the bench β which means it came from the model's memory. " | |
| + "Recalled sequences are wrong, so it was removed rather than shown. " | |
| + "Anything quoted elsewhere in this record was retrieved.</p>"); | |
| } else if (e.t === "error") { | |
| rows += plainRow(n, "Run error", "", '<p>' + esc(e.text) + "</p>", "td-step--fail"); | |
| } else { n--; } | |
| } | |
| els.list.innerHTML = rows; | |
| els.empty.hidden = !!rows; | |
| if (!rows) { | |
| els.empty.textContent = goal | |
| ? "This run has not taken a step yet." | |
| : "No run yet. Ask Turing for something and every step it takes will be recorded here."; | |
| } | |
| els.sub.textContent = n === 0 | |
| ? "Every step of the current run, held still." | |
| : n + " step" + (n === 1 ? "" : "s") + " in this run" | |
| + (meta.done ? " Β· finished" : meta.status === "running" ? " Β· still running" : ""); | |
| var facts = ""; | |
| if (goal) { | |
| facts += '<p class="td-trace-goal"><b>Goal</b>' + esc(goal) + "</p>"; | |
| } | |
| facts += '<ul class="td-trace-facts">'; | |
| // The two numbers the rail shows as "context 0% Β· $0.11", written out. | |
| if (meta.ctxLimit) { | |
| var pct = meta.ctxUsed / meta.ctxLimit * 100; | |
| facts += "<li><b>Context used:</b> " + fmtTokens(meta.ctxUsed) + " of " | |
| + fmtTokens(meta.ctxLimit) + " tokens (" | |
| + (pct >= 1 ? Math.round(pct) : pct.toFixed(1)) + "%) β how much of the " | |
| + "model's window this conversation occupies. When it fills, earlier steps " | |
| + "are condensed rather than dropped.</li>"; | |
| } | |
| if (meta.cost) { | |
| facts += "<li><b>Model cost so far:</b> $" + meta.cost.toFixed(4) | |
| + " β what this run has spent on model calls. Compute run on this " | |
| + "server (scoring, folding, guide design) is not billed per call.</li>"; | |
| } | |
| facts += "</ul>"; | |
| els.meta.innerHTML = facts; | |
| } | |
| function fmtTokens(n) { | |
| n = Number(n) || 0; | |
| if (n >= 1000000) return (n / 1000000).toFixed(n % 1000000 === 0 ? 0 : 2) + "M"; | |
| if (n >= 1000) return (n / 1000).toFixed(n >= 100000 ? 0 : 1) + "k"; | |
| return String(n); | |
| } | |
| /* ββ mount βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| function mount() { | |
| if (els) return els; | |
| var root = document.createElement("div"); | |
| root.className = "td-trace"; | |
| root.id = "tdTrace"; | |
| root.hidden = true; | |
| root.innerHTML = | |
| '<button type="button" class="td-trace-scrim" data-close aria-label="Close decision trace"></button>' + | |
| '<section class="td-trace-panel" role="dialog" aria-labelledby="tdTraceTitle">' + | |
| '<header class="td-trace-head">' + | |
| "<div>" + | |
| '<h2 id="tdTraceTitle">Decision trace</h2>' + | |
| '<p class="td-trace-sub" id="tdTraceSub"></p>' + | |
| "</div>" + | |
| '<button type="button" class="td-trace-x" data-close aria-label="Close decision trace">×</button>' + | |
| "</header>" + | |
| '<div class="td-trace-meta" id="tdTraceMeta"></div>' + | |
| '<ol class="td-trace-list" id="tdTraceList"></ol>' + | |
| '<p class="td-trace-empty" id="tdTraceEmpty"></p>' + | |
| '<p class="td-trace-foot">Built from the run\'s own event log β the same events ' + | |
| "the rail renders. Every step, input and result below is what the orchestrator " + | |
| "recorded; nothing here is reconstructed after the fact.</p>" + | |
| "</section>"; | |
| document.body.appendChild(root); | |
| els = { | |
| root: root, | |
| list: root.querySelector("#tdTraceList"), | |
| empty: root.querySelector("#tdTraceEmpty"), | |
| sub: root.querySelector("#tdTraceSub"), | |
| meta: root.querySelector("#tdTraceMeta"), | |
| }; | |
| [].forEach.call(root.querySelectorAll("[data-close]"), function (b) { | |
| b.addEventListener("click", close); | |
| }); | |
| document.addEventListener("keydown", function (e) { | |
| if (e.key === "Escape" && isOpen) close(); | |
| }); | |
| return els; | |
| } | |
| function open() { | |
| mount(); | |
| isOpen = true; | |
| els.root.hidden = false; | |
| render(); | |
| // The list is the scrollable region; a re-open should show the top of | |
| // the run, not wherever it was left. | |
| els.list.scrollTop = 0; | |
| } | |
| function close() { | |
| if (!els) return; | |
| isOpen = false; | |
| els.root.hidden = true; | |
| } | |
| function toggle() { if (isOpen) close(); else open(); } | |
| window.TDTrace = { | |
| push: push, | |
| reset: reset, | |
| setMeta: setMeta, | |
| count: count, | |
| open: open, | |
| close: close, | |
| toggle: toggle, | |
| isOpen: function () { return isOpen; }, | |
| }; | |
| })(); | |