> Development branch documentation · commit 327c05c78d2f528e4f4a679fcc7a77d9aa161f48
> Package versions: @zenfg/webgpu 0.1.0, @zenfg/snapshot 0.1.0, @zenfg/inspector 0.1.0, zenfg 0.1.0, zenfg-snapshot 0.1.0
> Source: https://github.com/uinosoft/zenfg/blob/327c05c78d2f528e4f4a679fcc7a77d9aa161f48/packages/inspector/GUIDE.md

# Inspector workbench guide

## Analyze and verify a frame

1. Capture an actual frame and inspect its graph, resource lifetimes, and diagnostics.
2. Check available CPU/GPU timings and their coverage. Locate the relevant passes
   and dependencies before deciding what to change.
3. Use the workbench's Snapshot JSON download or clipboard copy with the relevant
   graph declarations and renderer code for human or AI-assisted analysis. Include
   the observed problem and constraints; use pass names and resource IDs to make
   feedback precise. A Snapshot describes declared work, not shader behavior or
   an entire engine's internals.
4. Capture again after modifying the code. Compare the resulting structure and
   available measurements under comparable workload and device conditions.

This is an analysis workflow, not built-in AI integration or automatic optimization.
GPU timing depends on device support and node coverage; absent timing is not zero.
External-engine internals remain opaque. Snapshot does not include GPU resource
contents or replayable commands. The Inspector itself does not upload imported
snapshots; sharing exported data with another tool is a separate user action.

## Workbench behavior

The workbench provides Overview, Graph, Passes, Resources, Memory, and
Diagnostics views plus a selection Inspector. It supports live capture, direct
Snapshot replacement, file import, supported legacy migration, canonical
download, clipboard copy, filtering, sorting, group expansion, and graph
navigation.

The first capture opens Graph with no selection and the detail pane closed.
Subsequent captures preserve the current view, filters, and selection when the
same object still exists. Pass selection follows the node ID across retained and
culled states; removing the selected object clears selection and closes details.
These preferences, group expansion, and detail width belong to the current
Inspector instance and are not saved across sessions.

| View | Purpose |
| --- | --- |
| Overview | Full-width diagnostic counts, timing coverage, slowest pass, work counts, and memory estimates, with links to the relevant views. Capture metadata is expandable. |
| Graph | Frame Flow structure, searchable by pass, resource, group, or output, with explicit target location and a collapsible legend. |
| Passes | All, Retained, or Culled passes, filtered by kind and name/ID/group, with order and GPU sorting. The separate Group Hierarchy has its own expansion and path search. |
| Resources | Name/ID/group, type, and Transient/Imported/Surface filters, plus name, estimated size, and first-use sorting. Full descriptors and allocations remain in details. |
| Memory | Physical allocations and their logical resources, inclusive execution-slot lifetimes, search, allocation/size sorting, and All/Aliased/Single/Unallocated filters. |
| Diagnostics | Every captured error, warning, and informational message, including repeated codes. Severity and code/message filters precede expandable retention roots, culling reasons, and execution segments. |

Lists show the matching and total counts, retain continuous scrolling, and offer
**Clear filters**. Passes order retained work by execution order, then culled work
by recording order when available, falling back to capture order. Retained means
the compiler kept a pass; it does not itself prove GPU execution. Culled work has
no execution order, segment, or GPU timing. The Group Hierarchy arrows only change
that tree; **Show in Graph** is a separate action.

Diagnostics preserve capture order within each severity and offer separate
node and resource links when a message references both. Culled-node links work
the same way as retained-node links. The Diagnostics tab shows error/warning
counts. Source, frame, and capture time are available under **Capture information**
in Overview; an absent capture timestamp is shown as unknown. The collapsible
graph legend floats inside the canvas without changing its size or viewport.
Graph controls also float over the canvas. **Search** opens the search field;
**Escape** dismisses it. **Fit** frames the graph in the available viewport.

The selection pane has **Summary**, **Relations**, and **Raw** tabs. Summary
explains compilation status, timing coverage, accesses, allocation relationships,
and attached diagnostics. Relations distinguish access facts, dependencies,
output sources, and allocation membership. Raw shows the selected original
object and its JSON path in the canonical Snapshot, with field/value search,
folding, and copy of the complete object regardless of the current search. Legacy
imports explicitly identify their migrated canonical data. IDs can be copied
without their presentation labels.

Selecting an object opens its details on object views. Overview uses the full
width while retaining selection. The pane defaults to 300px and can be resized
from 300px to 480px while leaving at least 520px for the main view. Workspaces narrower than
828px use a modal drawer capped at 340px, with at least a 24px outside strip,
a backdrop, keyboard focus containment, and focus restoration when closed. The main content width determines table and information
layout; auxiliary table columns move into details when space is limited.
Arrow keys and Home/End switch tabs. Escape first dismisses the innermost active
menu or detail pane; the Examples host respects handled key events.

### Timing and memory interpretation

Timing labels distinguish not collected, partial coverage, complete coverage,
not applicable, and a measured zero. **Measured pass sum** is the sum of available
pass timings with its timed/eligible count; **GPU span** is displayed separately.
Opaque external work has no inferred duration. Passes is the comparison table
for individual timings; Diagnostics does not repeat it.

Memory numbers are estimates with different scopes:

| Metric | Meaning |
| --- | --- |
| Transient estimate | Declared estimated sizes of transient logical resources. |
| Logical capacity | Allocation capacity counted for each assigned logical transient resource. |
| Physical estimate | Estimated sizes of physical allocations in the allocation report. |
| Alias reuse | Logical capacity minus physical estimate, where both are known. |
| Pool retained | Producer-reported retained pool allocations, which may outlive this graph. |

An unavailable report is not zero. Unknown resource/allocation sizes remain
unknown, and partial summaries show the known-size coverage. A valid empty report
can contain real zero totals. None of these metrics is total GPU memory or a
measured peak. Memory summaries always cover the entire Snapshot; filters change
the visible rows and matching count only. A lifetime includes both first and last
execution slots. Tick positions, grid lines, and resource bars share one stable
Snapshot coordinate range; missing lifetimes have no bar.

### Frame Flow interaction

Graph is a single **Frame Flow** view: resource declarations → retained pass
dependencies → explicit resource outputs. Resource entrances belong to their
declaration groups; output roots remain top-level and use compiler-supplied final
producers and initial-content contributions. Culled passes remain in lists and
details, not in the graph. Collapsed groups aggregate relationships without
discarding their underlying semantics.
The **Declarations** toolbar toggle shows resource declaration entrances by default.
Turn it off to focus on pass dependencies and outputs: declaration entrances,
their relationships (including initial-content output edges), and resource-only
groups leave the layout. Pass dependencies and producer-to-output edges remain.
Outputs with known initial-content contributions show **With initial contents**
or **Initial contents only**; unavailable Legacy sources are not inferred.
The toggle persists across views and captures within this Inspector instance.
Changing it fits the updated graph while preserving selection and group expansion.
Resources, details, memory, and Snapshot data remain complete.

All nodes use single-line borders. Ordinary passes are rounded rectangles,
external submissions are cut-corner rectangles, resource entrances are ellipses,
and output roots are right-pointing tags. Declarations and outputs each have a
role colour independent of Buffer/Texture; pass categories have distinct colours.
Resources and Memory retain their resource-type colours. Hover and selection
change border emphasis, not shape, text colour, or fill.

Entrances show source/type first and the resource name second; outputs show their
purpose first and name second. Names are truncated to one line, with full names
available on hover and in details. Output ranges appear only to distinguish
different ranges of the same resource and purpose. Exact ranges and final sources
remain in hover/details. Semantic zoom hides auxiliary types and range summaries.
The grouped legend describes the whole snapshot's Frame Flow, including collapsed
objects, respects the Declarations toggle, and remains stable while groups expand/collapse. Culled-only categories
and unused resources do not add legend entries.

Category fills are opaque sRGB tints over the canvas: 18% in Storm and 8% in
Light. Theme-specific node text targets at least 7:1 contrast. Supporting text targets 4.5:1, and identifying
borders/symbols target 3:1 against their adjacent backgrounds. Automated checks
cover both official themes and interaction states; custom CSS colour overrides must
preserve these contrast relationships.

Solid edges represent declarations, values, and output sources; dashed edges
represent ordering-only relationships. Edges never carry labels. Hover provides
temporary hints: resource entrances and edges link only to visible entrances and
edges with the same logical resource ID, regardless of range. Passes, groups, and
output nodes only highlight themselves. These associations do not imply matching
ranges or a continuous dataflow path, and never substitute a collapsed group for
a hidden resource entrance.
Direct and linked hover use the same strong visual style. Selection uses a blue
outline without a glow. Hovering a Summary or Relations link previews its target
in the graph using the same rules, without changing selection or moving the view;
leaving the link or changing/closing the detail pane clears the preview.

Resource **Pass accesses** entries link only the pass name; access mode, write
contents, producesValue, and available ranges remain descriptive text. Pass details
use the same access facts. An access is not a graph
relationship and is not mapped to an arbitrary dependency edge.
Resource Relations also link to individual output roots by reason and range.

Clicking an entrance, edge, or Resources row selects the same logical resource,
including all its visible entrances and edges, but no passes, groups, or outputs.
An output still selects its Root. Its **View resource** action and other resource
links use the same resource selection. Changing to a different resource opens
Summary; selecting the current resource again preserves the active detail tab.
Selection does not switch workbench views, change filters, expand groups, or move
the viewport. A hidden entrance becomes selected when manually expanded; its
visible cross-group edges remain selected while it is hidden. Hover previews are
independent, with selection styling taking precedence, and never pin a tooltip.
Edge hints show only the resource and distinct relationship types, including
mixed types in aggregates. There is no independent edge detail or relationship list.
Double-clicking a group expands or collapses it without replacing selection;
single-click group selection waits briefly to distinguish that gesture.
Legacy outputs with unavailable
resolution remain visible but have no inferred source edges.

Explicit **Show in …** actions perform navigation: they switch views, clear
blocking filters, expand necessary ancestors, and scroll or center the target.
They close a narrow-host drawer so the target is visible. Graph search uses the
same explicit location behavior. Explicit resource location also turns Declarations
on; ordinary selection and hover never change the toggle. Failed location restores
the previous declaration and group settings. Objects absent from Frame Flow show an
explanation and a list-view action; locating an object does not bypass the graph
element budget. Ordinary selection and hover retain the behavior above.

Capture, import, and direct replacement share a revision counter so stale async
results cannot replace newer data. Failed or oversized imports leave the
current valid capture and UI state intact, and operation feedback can be expanded
to inspect the full failure reason. Views render their new capture on first
activation, and selection updates refresh only the active view and details.
Memory grouping and lifetime coordinates are cached per Snapshot; Raw is created
only when opened. Graph layout is lazy and is disabled
with an explanation when a capture exceeds `maxGraphElements`; the tabular and
raw views remain available.

Snapshot labels, URLs, extensions, and diagnostics are assigned through text
DOM APIs and are never executed as markup or code. The standalone Site page in
`apps/site/inspector` mounts this same package without adding duplicate controls.
