1. Rewind Markers (vertical event lines)

A rewind event is a structural discontinuity — it deserves a visual “snap” in the waveform.

Add this inside our D3 useEffect after drawing the Q‑metric lines:#

// --- REWIND MARKERS ---
rewinds.forEach((rw) => {
  const xPos = x(rw.from_step);
 
  svg.append("line")
    .attr("x1", xPos)
    .attr("x2", xPos)
    .attr("y1", 10)
    .attr("y2", height - 20)
    .attr("stroke", "#d62728")
    .attr("stroke-width", 1.5)
    .attr("stroke-dasharray", "4 2");
 
  svg.append("text")
    .attr("x", xPos + 3)
    .attr("y", 20)
    .text("rewind")
    .style("font-size", "9px")
    .style("fill", "#d62728");
});

Result#

We get red dashed vertical lines marking rewind points, with a tiny label.
This makes corridor “snapbacks” visible at a glance.


2. Spec Threshold Overlays (CorridorSpec → horizontal lines)#

Thresholds are structural boundaries — they should appear as horizontal guide rails.

Assuming we pass spec: CorridorSpec into the component:

// --- SPEC THRESHOLDS ---
const thresholds = [
  { key: "semantic_drift", value: spec.max_semantic_drift, color: "#1f77b4" },
  { key: "tool_entropy", value: spec.max_tool_entropy, color: "#ff7f0e" },
  { key: "latency_drift", value: spec.max_latency_drift, color: "#2ca02c" },
  { key: "retry_ratio", value: spec.max_retry_ratio, color: "#9467bd" },
];
 
thresholds.forEach((t) => {
  const yPos = y(t.value);
 
  svg.append("line")
    .attr("x1", 40)
    .attr("x2", width - 10)
    .attr("y1", yPos)
    .attr("y2", yPos)
    .attr("stroke", t.color)
    .attr("stroke-width", 1)
    .attr("stroke-dasharray", "3 3");
 
  svg.append("text")
    .attr("x", 45)
    .attr("y", yPos - 4)
    .text(`${t.key} max`)
    .style("font-size", "9px")
    .style("fill", t.color);
});

Result#

Each Q‑metric now has a visual safety envelope.
When the waveform crosses a threshold, we can see the corridor destabilizing in real time.


3. Mini‑Map (overview + zoom/pan)#

This is the “VCD‑viewer‑style” mini‑map: a compressed overview of the entire corridor with a draggable viewport.

Add a second SVG below the main waveform:#

<svg ref={miniRef} width={600} height={40} className="border rounded bg-gray-50" />

In the D3 useEffect, after drawing the main panel:#

// --- MINI-MAP ---
const mini = d3.select(miniRef.current);
mini.selectAll("*").remove();
 
const miniX = d3.scaleLinear()
  .domain(x.domain())
  .range([40, width - 10]);
 
// Draw compressed drift line
const miniLine = d3.line<CorridorQEvent>()
  .x((d) => miniX(d.step_id))
  .y((d) => 20 - d.semantic_drift * 15);
 
mini.append("path")
  .datum(qHistory)
  .attr("fill", "none")
  .attr("stroke", "#1f77b4")
  .attr("stroke-width", 0.8)
  .attr("d", miniLine as any);
 
// Draggable viewport rectangle
const viewport = mini.append("rect")
  .attr("x", miniX(x.domain()[0]))
  .attr("y", 0)
  .attr("width", 80)
  .attr("height", 40)
  .attr("fill", "rgba(0,0,255,0.1)")
  .attr("stroke", "#1f77b4")
  .call(
    d3.drag().on("drag", (event) => {
      const newX = Math.max(40, Math.min(width - 90, event.x));
      viewport.attr("x", newX);
 
      // Update main chart zoom
      const start = miniX.invert(newX);
      const end = miniX.invert(newX + 80);
      x.domain([start, end]);
 
      // Redraw main chart
      svg.selectAll("*").remove();
      drawMainChart(); // wrap your main drawing logic in a function
    })
  );

Result#

We now have:

  • a compressed overview of the entire corridor
  • a draggable viewport that controls zoom/pan
  • a main waveform that updates as we drag

This is exactly how waveform viewers like GTKWave, Vivado, and Chrome DevTools operate.


What we’ve built now#

We’ve effectively created:

  • rewind‑aware waveforms
  • safety‑envelope overlays
  • a corridor mini‑map with interactive zoom

This is no longer “just a viewer” — it’s a Corridor Instrumentation Console, the first of its kind.