docs: help pages, probe reference and session docs updated for the three new features

- 08-trigger.txt: names all four condition shapes and the buffer search; fixes the first
  paragraph and 'How to reach it' to match what the panel actually contains (fix 3).
- 10-measurements.txt: adds a Statistics bullet — one observation per recompute, what
  resets the history, what does not (fix 3).
- probe-readings.md: re-quotes condition-probe lines with level2= and mode= fields;
  corrects leg-2 window geometry (0.2 s / 10 % pre, not 1.0 s / 50 %); moves the
  wide-window reason to legs 1 and 3; fixes the search-probe scheduling note
  (search_probe calls condition_probe directly; do not also set CONDITION_MS) (fix 6).
- verification.md: corrects shape-2 window geometry to match the code (fix 7).
- invariants-session-and-export.md, README.md: document the measure_stats session key —
  position, type, default false (fix 8).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-10-08 11:19:19 +02:00
1 parent 090b6bb57d
commit 728e7fbda5
6 files changed
+62 -22

No files matched your search

+5 -2
View File
@@ -374,6 +374,7 @@ per-signal gain and offset:
```toml
window_s = 2
plots = 1
measure_stats = false
[[plot]]
signals = ["Ch1", "", "", ""]
@@ -384,7 +385,8 @@ gain = 2
offset = 0.5
```
It is written (400 ms after the last change, and flushed on close) whenever the
It also stores `measure_stats` (the measurements statistics toggle, a boolean, absent means
`false`). It is written (400 ms after the last change, and flushed on close) whenever the
window, the layout, a drop or a calibration changes, and applied once, when the
first CONFIG names the signals -- signal *names* are the identity, because a
CONFIG renumbers and an enable/disable rebuilds the channel list. Signals the
@@ -685,7 +687,8 @@ modes are unchanged, and only the question "did an event happen at this sample"
because that is the first sample at which the width is known. `<` a width shorter than the
signal's own pulses is the glitch trigger: nothing but a runt satisfies it.
- **window** — the signal entering or leaving a band between two levels. A band is two levels,
so the panel refuses a zero-width one rather than quietly degrading to an edge.
so the panel refuses a zero-width one: it reduces the condition to a float-equality test,
which on a real-valued signal never fires.
- **dropout** — the *absence* of a crossing for longer than a timeout. One event per outage:
the condition re-arms only when a crossing returns.
+3 -1
View File
@@ -9,7 +9,9 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
signals**, **the chosen trace colours** (`[[color]]`, `name` + `rgb = "#RRGGBB"` — only the
*overrides*, so a stream's new signals still take the positional palette and a saved session does
not freeze a colour that is meant to follow the signal list), **the math channels with their
graphs** and **the measurements pane**. Signal identity
graphs**, **the measurements pane**, and **`measure_stats`** — the measurements statistics
toggle; written as a bare top-level boolean (`measure_stats = true/false`), defaults to `false`
when absent. Signal identity
is the *name* throughout (a CONFIG renumbers channels), 'enabled' is read off the channels the
model built -- an enabled signal is exactly one that produced a channel -- and `apply_layout()`
installs the graphs **before** assigning the rows, since a row may hold a math channel's name and
+23 -13
View File
@@ -600,32 +600,40 @@ Four legs, selected by `UDPSCOPE_PROBE_CONDITION_SHAPE`. Every leg prints one li
[condition-probe] type=T cmp=C width=W t0=T0 measured=M at0=A earlier=E level2=L2 mode=D
```
Measured readings (`--rate 10000 --freq 5`, each on a fresh port):
Measured readings (`--rate 10000 --freq 5`, each on a fresh port). Shape 0's `level2=` and
`mode=` fields are from the `[search-probe]` run in `.superpowers/sdd/progress.md`; shapes 1–3
were measured before those fields were added and their `level2=0.500000 mode=2` is read from
the probe arm code (`condition_probe_arm` always sets `level2` to `0.5` and the mode after a
latch is `Held=2`):
```
shape=0 type=1 cmp=0 width=0.010000 t0=1.842100 measured=0.002000 at0=nan earlier=nan
shape=1 type=1 cmp=1 width=0.010000 t0=2.160100 measured=0.200000 at0=nan earlier=nan
shape=2 type=2 cmp=0 width=0.010000 t0=1.706700 measured=nan at0=-0.500907 earlier=-0.498185
shape=3 type=3 cmp=0 width=0.010000 t0=4.120200 measured=0.300100 at0=nan earlier=nan
shape=0 type=1 cmp=0 width=0.010000 t0=1.710000 measured=0.004000 at0=nan earlier=nan level2=0.500000 mode=2
shape=1 type=1 cmp=1 width=0.010000 t0=2.160100 measured=0.200000 at0=nan earlier=nan level2=0.500000 mode=2
shape=2 type=2 cmp=0 width=0.010000 t0=1.706700 measured=nan at0=-0.500907 earlier=-0.498185 level2=0.500000 mode=2
shape=3 type=3 cmp=0 width=0.010000 t0=4.120200 measured=0.300100 at0=nan earlier=nan level2=0.500000 mode=2
```
`measured` is the reading, not a phase. It is the pulse width read back from the held snapshot's
own stamps, which are edge-relative: the snapshot is the ground truth, not the mock's absolute
clock. Three things are worth knowing before calling a reading wrong:
- **Leg 0**: `measured=0.002` is the injected glitch width. A `measured` near the signal's own
half-period means the width qualifier did not qualify — the trigger caught a normal edge instead
of the runt.
- **Leg 0**: `measured=0.004` is the injected glitch width (here the search-probe run used
`--glitch-width 0.004`; the earlier standalone probe run read `0.002` with `--glitch-width 0.002`).
A `measured` near the signal's own half-period means the width qualifier did not qualify — the
trigger caught a normal edge instead of the runt.
- **Leg 1**: `measured=0.200` is an ordinary square half-period; every square pulse satisfies
`> 0.010`.
`> 0.010`. **Use a 1.0 s window with 50 % pre** so the opening edge of a 0.2 s pulse lies within
the pre window.
- **Leg 2**: `at0` must lie **outside** `[-0.5, +0.5]` and `earlier` **inside** it — those are the
two sample values around the band crossing. The probe prints `nan` for any field a leg cannot
measure. **This leg uses `sine`**, not `square`: the square is exactly ±1 and has no sample
inside the `[-0.5, +0.5]` band, so a window condition on the square can never fire. **Use a
1.0 s window with 50 % pre** or the probe cannot reach the opening edge of a 0.2 s pulse.
inside the `[-0.5, +0.5]` band, so a window condition on the square can never fire. This leg
uses a **0.2 s window with 10 % pre** — short enough to capture the crossing, because the event
is the band exit, which lands at x = 0 in the held snapshot.
- **Leg 3**: `measured=0.300` is the dropout timeout. **This leg also uses `sine`**. A timeout of
0.050 s against a sine crossing zero every 0.1 s latches on a healthy signal, so use 0.300 s
or longer; **use a 1.0 s window with 50 % pre** as for leg 2.
or longer; **use a 1.0 s window with 50 % pre** so the last crossing before the outage lies
within the pre window.
The channel-selection line `[condition-probe] <name>=<index> of <N> channels` is printed before
the trigger fires; if the channel is not found this reads `-1` and the probe fails immediately.
@@ -664,7 +672,9 @@ phase=2 … n=1 mean=-4.84467e-14 | n=1 mean=0.63662 | n=1 mean=2 | n=1 mean=1
## `[search-probe]`
`UDPSCOPE_PROBE_SEARCH_MS`, scheduled after `UDPSCOPE_PROBE_CONDITION_MS`. Run with
`UDPSCOPE_PROBE_SEARCH_MS`. The handler calls `condition_probe()` directly — the condition is
set in exactly one place for both the live trigger and the search, so `UDPSCOPE_PROBE_CONDITION_MS`
must **not** also be set (two arms on the same port race). Run with
`--rate 2000 --batch 64 --freq 5 --glitch-at 0.25 --glitch-width 0.004` and
`UDPSCOPE_EXIT_AFTER_MS=12000`.
+4 -3
View File
@@ -180,9 +180,10 @@ precedent, not an exception.
- `UDPSCOPE_PROBE_CONDITION_MS` — arms a qualified trigger against the mock and reports the latched
`t0`, the measured pulse or band width, and sample values for the window condition. Schedules its
own arm and report stages. `UDPSCOPE_PROBE_CONDITION_SHAPE` picks the leg: `0` pulse width `<`
(the glitch, the default, needs `--glitch-at`/`--glitch-width`), `1` pulse width `>`, `2` window
(uses `sine` with a 1.0 s window and 50 % pre), `3` dropout (needs `--quiet-at`; also uses
`sine` with a 1.0 s window and 50 % pre).
(the glitch, the default, needs `--glitch-at`/`--glitch-width`), `1` pulse width `>` (uses a
1.0 s window and 50 % pre so the opening edge of a 0.2 s pulse is captured), `2` window
(uses `sine` with a 0.2 s window and 10 % pre), `3` dropout (needs `--quiet-at`; uses `sine`
with a 1.0 s window and 50 % pre so the last crossing before the outage is captured).
- `UDPSCOPE_PROBE_STATS_MS` — reports every measurement's accumulator (`n`, mean, sd, lo, hi),
pauses, reports again with `dn=` per measurement, then resets and reports a third time. Three
phases: `phase=0`, `phase=1` (after pause) and `phase=2` (after Reset). Needs
+21 -3
View File
@@ -1,13 +1,16 @@
<b>Trigger</b>
The trigger watches one signal for an edge through a level and captures a window around it.
The trigger watches one signal for a condition and captures a window around it. The
<b>Shape</b> dropdown chooses what counts as an event; the arming, hold-off, pre/post window
and Normal/Single mode are the same for all four shapes.
The captured window is frozen on screen until you re-arm.
<b>How to reach it</b>
The trigger button in the toolbar (<tt>t</tt>) reveals the trigger panel: the signal, the level,
the edge (rising, falling, either), the mode (Normal or Single) and the pre-trigger share.
<b>Arm</b> starts watching; <tt>a</tt> arms and disarms from the keyboard.
the shape, the edge (rising, falling, either), the mode (Normal or Single) and the pre-trigger
share. <b>Arm</b> starts watching; <tt>a</tt> arms and disarms from the keyboard.
<b>Search the buffer</b> is at the foot of the same panel.
<b>Worth knowing</b>
@@ -27,6 +30,21 @@ the edge (rising, falling, either), the mode (Normal or Single) and the pre-trig
• The trigger reads the <b>stored</b> signal — decimated and averaged — not the wire signal.
A spike narrower than one decimation group is filtered away rather than triggering on data
the buffer does not contain.
• The four shapes: <b>edge</b> — a crossing of the level in the chosen direction, the classic
behaviour. <b>Pulse width</b> — a crossing and its return, qualified by how long the excursion
lasted: less than, greater than, within or outside a pair of widths; the event is timed at the
closing edge. <b>Window</b> — the signal entering or leaving a band between two levels; the
panel keeps the two levels at least one increment apart, because a zero-width band reduces the
condition to a float-equality test that never fires on a real-valued signal. <b>Dropout</b> —
the absence of a crossing for longer than a timeout; one event per outage, re-arms when a
crossing returns.
• The shape's own rows are the only ones shown; the rest are hidden, so the panel never offers
a pulse width to a window trigger.
• <b>Search the buffer</b> runs the same condition over the whole retained ring and lists every
place it holds. The arrows step through hits; each step pauses on the hit, centred, exactly as
the Pause button does. Up to 16 hits in the visible window are marked on every row; when there
are more the panel says how many and suggests zooming in. The search uses the trigger's own
condition, set in one place, so a hit is by construction an instant the trigger would have fired.
<b>Example</b>
+6
View File
@@ -45,6 +45,12 @@ set, with <b>Save</b> and <b>Delete</b>.
small value is <tt>0.00</tt>.
• Cost is bounded by reading the summary pyramid the producer already maintains, not the raw
window. The values are still exact: a bucket's sum is a sum.
• <b>Statistics</b> adds a second line to every measurement showing <tt>n</tt>, the mean, the
standard deviation and the range. Each observation is one <i>recompute</i> of the pane, so
<tt>n</tt> counts windows measured, not samples — a mean frequency over many windows is what
that claims to be. <b>Reset</b> clears every accumulator and starts fresh. A change of display
window, a CONFIG or a measurement edit also resets; a pause, a resume, a zoom, a pan and the
toggle itself do not, so turning the line off to read the plot and back on again keeps the history.
<b>Example</b>