How diagram cells are counted
When you run stigGenerateHtml, stig produces a fixed-shape grid of diagrams per activity. The grid is the cross-product of 5 axes. This page documents what each axis means, how many values it can take, and how the per-activity cell count is derived — so you can read the lifecycle log and reason about what's enabled vs. what's generated.
The 5 axes
# | Axis | Values | Count | Where it's decided |
|---|---|---|---|---|
1 |
|
| 3 | Which |
2 |
|
| 2 | How fine the cfg slicing is — one cfg per group, or one per leaf |
3 |
|
| 2 | One cfg combines all sinks, or one cfg per individual sink |
4 |
|
| 5 max | Rendering only — derived from a single |
5 |
|
| 3 max | Rendering only — same |
Axes 1–3 are input axes — each combination drives one cfg.json (input to the analyzer) and one analysis.json (output from the analyzer). Axes 4–5 are output axes — each analysis.json is rendered into multiple cells from the same data.
Theoretical total
where N is the number of configured one_sink slugs in the activity (+1 covers the literal all_sinks slug). The merge_mode axis is absorbed into (1 + N) — all_sinks is one slug, one_sink is N slugs.
The runtime log first prints the full enum cross-product as analyses × diagramTypes × summaryTypes. It then subtracts diagram types disabled by DSL and invalid axis pairs. Today detailed_per_segment is valid only with data_flow_diagram, and detailed_per_ir_instruction is valid only with control_flow_diagram. Data-flow diagrams render summarized and detailed_per_segment; control-flow diagrams render summarized and detailed_per_ir_instruction.
Worked example — example_activity
Configured sinks: 9 cascading sinks in cascadingFailuresAnalysis, 14 data-flow sinks in dataAndControlFlowAnalysis.
Today the activity only uses per_leaf (no per_group) and only two of the three analysis kinds:
analysis_type | depth | merge_mode | slugs | analysis.json count |
|---|---|---|---|---|
data_and_control_flow_analysis | per_leaf | one_sink | 14 sinks | 14 |
data_and_control_flow_analysis | per_leaf | all_sinks | 1 ( | 1 |
cascading_failure_analysis | per_leaf | one_sink | 9 sinks | 9 |
cascading_failure_analysis | per_leaf | all_sinks | 1 ( | 1 |
With the default DCF/CAS diagram toggles (data_flow_diagram and control_flow_diagram enabled, combined disabled), each analysis renders four valid interactive cells:
data_flow_diagram:summarized,detailed_per_segmentcontrol_flow_diagram:summarized,detailed_per_ir_instruction
Plugging into the formula per (analysis_type, depth):
Equivalently in axis-product form (which is how the runtime log phrases it):
If you set showCombinedDataAndControlFlowDiagrams = false in the DSL (turning off diagram_type = combined_data_and_control_flow_diagram for both DCF and CAS), the combined cells stay disabled. The combined diagram type currently has only the summarized summary type in the matrix:
What each summary_type shows
The same analysis.json data, rendered at multiple granularities:
detailed_per_ir_instruction— every LLVM instruction in the selected rendered control-flow view is one node. Edges come from the analyzer ICFG. This summary type is not generated for data-flow diagrams unless a future analyzer schema emits exact IR-to-IR data-flow edges. For a non-trivial leaf this can be 100+ nodes.detailed_per_segment— data-flow only. Each analyzersinks[].dataFlowDAG.segments[]entry is one node; its tooltip lists the ordered IR instructions belonging to that segment. One IR can appear in multiple segment tooltips because segments are DAG metadata, not strict parents.summarized— instructions are folded into their enclosing function. For data flow, source-to-sink relations are contracted over the analyzer segment DAG. For control flow, relations are contracted over ICFG paths. This is the high-level "which functions are on the path" view.
Both come from the same analyzer run; the fan-out is pure rendering — no extra analyzer cost.
Reading the lifecycle log
At the end of stigAnalysisP7GenerateDiagrams you'll see a summary line like:
What each number means:
source files: 25— number ofanalysis.jsonfiles the task found understigAnalysisP6RunAnalyzer/analyzer/….analyses: X with content, Y empty— of those, how many produced at least one rendered Vista node fromcontrolFlowGraphor per-sinkdataFlowDAGcontent. The "empty" ones get surfaced separately in the## Empty analysessection ofdiagrams.md(see.no-data.txtmarkers).rendered N cells— successful renders of (analysis × diagram_type × summary_type).skipped cells: M disabled by DSL— cells that were never attempted because the user's DSL turned off the diagram_type for the analysis kind.invalid axis combinations: M diagrams— enum combinations that are intentionally not rendered, currentlydetailed_per_segmentwith any non-data-flow diagram type anddetailed_per_ir_instructionwith any non-control-flow diagram type.K empty after transform— cells where the analysis had data butTransform.transform(diagramType, summaryType)pruned it to zero nodes. This is the case the diagram-completeness validator fails on (severity gated byfailAt), because the input had data but the renderer produced nothing — a real loss of signal.
rendered + disabled-by-DSL + empty-after-transform + (cells from empty analyses) should equal the theoretical total for the cfg inventory shown above.