Phase 02 · v1.0 · Shipped 2026-05-19

Missing-row visibility.

Make it impossible for a flow to silently produce no result. A flow that aborts mid-run or is skipped before validation emits a distinct, structured placeholder row, and Grafana/Slack surface aborted/skipped distinctly from event-misses. The foundation Phase 5's dry-run gate depends on.

Milestonev1.0 ScopeVIS-01..VIS-06 Depends onPhase 1
Phase boundary

Additive enum field + end-of-run reconciliation.

Not the matching change (Phases 5/6). Not capture changes (Phase 3). Not failureKind taxonomy (Phase 7, built on this phase's field). Strictly additive on the result contract.

Decisions

Four design questions accepted as recommended.

Q1 · Encoding

Single additive enum outcome field.

On both ReportDetailRow and ValidationResult: outcome: "validated" | "section-aborted" | "flow-skipped". Every existing field keeps its name, type, and meaning. The additive field Phase 7's failureKind will build on.

Q2 · passed on aborted/skipped

passed: false — pre-existing dashboards still flag.

outcome is the discriminator for why it failed (not run vs tracking missing). Old failure queries keep working.

Q3 · No-silent-drop guarantee

End-of-run reconciliation + per-section try/catch.

Compute the planned flow set per domain from config; diff against emitted reportDetailRows; for every planned flow with no emitted row, push a flow-skipped placeholder.

Wrap each per-section dispatch in bi-measurement.ts in try/catch; on throw, push a section-aborted row carrying short error summary, continue to next section.

Single writer helper emitOutcomeRow() in eventUtils.ts; keeps the singleton drain/reset contract intact.

Q4 · Grafana/Slack surfacing

Additive only — new outcome facet, no renames.

outcome becomes a queryable field in the OpenSearch/Grafana payload. New "⚠️ Aborted / Skipped flows" block in Slack, listed separately from event-miss.

Success criteria

UI hint: yes — surfacing tested with real flows.

  1. A thrown section emits exactly one section-aborted row carrying truncated error summary; run continues to the next section.
  2. End-of-run reconciliation emits one flow-skipped row per planned flow with no emitted result.
  3. Grafana panel/filter surfaces aborted/skipped distinctly from event-misses with no field renames.
  4. Slack report includes a dedicated "Aborted / Skipped flows" block.
  5. passed: false on aborted/skipped rows preserves existing failure-query behavior.
Files

What shipped.

modsrc/lib/Types.tsOutcome enum + optional outcome? field
modsrc/utils/eventUtils.tsemitOutcomeRow + reconcileMissingFlows
modsrc/bi-measurement.tsper-section try/catch + reconcile pass
modsrc/lib/slack.tsAborted/Skipped block
modgrafana-dashboard-with-viewport.jsonoutcome facet
newtests/missing-row-visibility.test.js
← PreviousPhase 1 · Config validation gate Next →Phase 3 · Capture integrity