Cascade Visualization

console cascade scoring debugging

Cascade Visualization

The cascade viewer shows event cascades as interactive tree structures, so you can see the chain of effects produced by a single event. Each time an event fires in the scoring engine, the console captures the resulting cascade of rule evaluations, variable changes, and child events.

Demo

The screenshot below is a real capture from the live scoring engine: the root is the switch event that fired, and the children are the effects its .cade handlers actually produced — score contributions, variable changes, and the events those handlers emitted.

cade — cascade viewer
Loading the cade engine…
move · collapse/expand · space toggle · [] step cascade history

The sections below document the viewer as it appears in the console.

Opening the Viewer

Toggle the cascade viewer with F7 (or Ctrl+E). After triggering an event, the cascade is captured automatically:

cade:debug> trigger device.Bumper1.activated
Event cascade captured. Press F7 to view.

The viewer replaces the main content area while it is open. Press F7 again to return.

You can also jump straight to a cascade from the Events tab: put the cursor on an event and press c.

Commands

The cascade command has three subcommands:

cade:debug> cascade last            # summarize (or load) the most recent cascade
cade:debug> cascade export          # write the current cascade to JSON
cade:debug> cascade export run1.json
cade:debug> cascade depth           # show the current capture depth
cade:debug> cascade depth 5         # set capture depth (1–10)

cascade last prints a summary — timestamp, duration in microseconds, event count, and score change:

cade:debug> cascade last
Last Event Cascade:
  Timestamp:    12:13:44.205
  Duration:     3750μs
  Event Count:  5
  Score Change: +5000

When the TUI viewer is open, cascade last loads that cascade into the viewer instead and reports ✓ Last cascade loaded. Use Ctrl+E to view.

cascade depth controls how many levels deep the engine captures. Values outside 110 are rejected.

Note: cascade export and cascade depth act on the TUI cascade viewer, so they only take effect in TUI mode. In pipe mode they do nothing. Export is JSON only; with no filename it writes cascade_<YYYYMMDD_HHMMSS>.json in the working directory.

Reading the Tree

A captured cascade looks like this:

🏆 switch_hit:left_orbit
Trigger: switch_hit:left_orbit | Depth: 3 | Queue: 2

switch_hit:left_orbit Total: 3750μs | Events: 5 | Score: +5000 | Mult: x3
└─▼ switch_hit:left_orbit [5000  5000] +5000
  ├─   award_bonus [bonus:1000]
  ├─  play_sound:orbit_hit
  └─▼  update_multiplier [x1  x3]
    └─   flash_lights:orbit

Score Breakdown:
  switch_hit:left_orbit: 5000
Total: 5000
──────────────────────────────────────────────────────────────────
 Node: switch_hit:left_orbit | Type: scoring | Duration: 2500μs | Score: +5000 | Calc: 5000 | Children: 3 (expanded) | Changes: score

For simpler cascades (single event, no children), the header shows device context instead of depth:

Trigger: device.Bumper1.activated | Device: switch | Key: Bumper1

device.Bumper1.activated Total: 4μs | Events: 1 | Score: +1000
└─  device.Bumper1.activated [1000  1000] +1000

Score Breakdown:
  device.Bumper1.activated: 1000
Total: 1000

Header Line

FieldMeaning
TriggerEvent name that started the cascade
Device / KeyDevice type and key (single-event captures)
DepthNumber of levels in the cascade tree
QueuePending child events not yet expanded

Summary Line

FieldMeaning
TotalWall-clock duration for the whole cascade
EventsNumber of nodes in the tree
ScoreTotal points awarded by the cascade
MultActive multiplier (shown when it changes during the cascade)

Node Line

Each node line is assembled from these parts, in order:

PartMeaning
/ Expanded / collapsed (leaves show neither)
IconEvent-type icon — 🎯 scoring, ✖️ multiplier, 🔄 combo, 🔊 sound, 📊 variable, generic. Only with emoji mode on (Alt+E)
NameThe event or effect name, colored by event type
prefixThe node is a future effect — queued by its parent but not yet run. Rendered dim
BadgeScore contribution, variable change, or future-effect marker
[…]Timing — see below
(pending)The cascade is still in flight
+N / -NPoints gained or lost at this node

Connectors are ├─ for intermediate children and └─ for the last child.

Timing

Per-node duration renders in brackets, scaled to the magnitude:

DurationRendered as
Under 1000 μs[450μs]
Under 1 s[12.4ms]
1 s and above[1.05s]

Anything over 10 ms is highlighted in a warning color, and with emoji mode on is prefixed 🐢. Anything under 100 μs is prefixed . A collapsed node shows the summed duration of its whole branch with a trailing Σ.

Press t to hide or show timing; compact mode (c) suppresses it too.

Detail Bar

The line below the divider describes the selected node:

FieldMeaning
NodeSelected node name
Typescoring, effect, sound, or system
DurationTime spent in this node
ScorePoints awarded by this node
CalcCalculated expression value (before any score modifier)
ChildrenChild count and expanded/collapsed state
ChangesVariables touched by this node, comma-separated

Keyboard Shortcuts

Navigation

KeyAction
/ k, / jMove to previous / next node
/ h, / lCollapse / expand the selected node
Space or EnterToggle expand/collapse
g / GJump to first / last node
E / CExpand all / collapse all
19Expand the tree to that depth level
[ / ]Step backward / forward through the cascade history buffer

Display Toggles

KeyAction
tShow/hide per-node timing
TToggle the timeline
mToggle the minimap
bToggle the breadcrumb trail
cToggle compact mode
PToggle the performance analysis overlay
Alt+EToggle emoji icons
Ctrl+HHide / show future-effect nodes
Ctrl+DToggle the details pane

Search, Export, Replay

KeyAction
/ or Ctrl+FStart a search
n / NNext / previous match
Ctrl+/ or EscClear the search
Ctrl+AToggle auto-update (jump to latest cascade on capture)
Ctrl+EExport the current cascade to JSON
Ctrl+REnter or exit replay mode
pPlay the sound for a selected sound node

Replay Mode

Press Ctrl+R to step through a cascade event by event. Replay adds a playback bar and remaps a few keys:

KeyAction
SpacePlay / pause
/ Step one event backward / forward
+ or =Double playback speed
-Halve playback speed
Home / EndJump to first / last event
EscExit replay mode

Performance Analysis

Press P to overlay bottleneck analysis on the cascade. The overlay reports:

Overview — total duration, event count, max depth, average duration, score change, and a per-type event distribution with counts and percentages.

Critical Path — the longest chain of sequential operations, numbered and indented by depth. Steps over 20 ms are flagged critical, over 5 ms medium.

Bottlenecks — the nodes consuming the most time, each with the path that reaches it. Severity is keyed to the share of total cascade time: over 50%, over 25%, and over 10%.

Timing Anomalies — entries marked HIGH, MEDIUM, or LOW, each with a suggestion.

Optimization Suggestions — concrete recommendations, each with an impact and difficulty rating. The suggestions you may see are:

  • Parallelize child operations
  • Optimize dominant bottleneck
  • Cache or pre-compute slow operation
  • Investigate timing anomalies
  • Reduce cascade depth

The cascade buffer stores the 100 most recent cascades, so [ and ] let you step back through recent history and compare runs by eye.

Filtering Events

The cascade viewer itself offers free-text search (/) rather than structured filters. For structured filtering, use the Events tab (F2), whose filter bar accepts space-separated clauses that are ANDed together:

type:scoring score>100
name:switch_* duration>1ms
kind:cascade complete:true
ClauseAccepts
type:scoring, multiplier, combo, sound, variable, generic
kind:cascade, signal
name:Substring, or a glob when it contains * or ?
complete:true/yes/1 or false/no/0
score: duration: events:Numeric comparison with >, <, or = (e.g. duration>1ms)

A bare word with no prefix is treated as a case-insensitive substring match on the event name. See Panels for the Events tab reference.