Skip to content

Phase 1 Measurements

This table is the single place where before/after numbers for Phase 1 (and the demo baseline that precedes it) are recorded. Every slice in the evolution roadmap between now and the end of Phase 2 must land with rows here and the corresponding CSV captures under docs/captures/.

Without a filled row, a slice's exit gate has not been met. Prose claims ("feels faster", "seems healthier") do not count.

See the capturing measurements runbook for the procedure that produces these numbers.


Conventions

ColumnMeaning
SliceWhich change the row measures. demo-baseline (pre-Phase-1) for row 0.
MetricOne of the fixed metric names listed below.
BaselineThe value from the before capture.
AfterThe value from the after capture. Blank for row 0.
Deltaafter − baseline for counters; after ÷ baseline for rates. One convention per metric. Blank for row 0.
Capture methodCSV filename plus scenario id (§4.1, §4.2, ...).
DateISO date of the after capture (or the baseline capture for row 0).

Fixed metric set

Every row set must include all of these metrics, in this order. Zeros are valid values — record them.

  1. frames.ingested (total)
  2. frames.ingested rate (fps, avg over scenario duration)
  3. frames.dropped (total)
  4. telemetry.ingested (total)
  5. telemetry.ingested rate (Hz, avg)
  6. telemetry.coalesced (total)
  7. runs.started
  8. runs.completed
  9. runs.faulted
  10. working-set peak (MB)
  11. gen-0-gc-count (total)
  12. gen-1-gc-count (total)
  13. gen-2-gc-count (total)
  14. alloc-rate (bytes/sec, avg)
  15. cpu-usage avg (%)
  16. cpu-usage peak (%)

Row 0 — demo baseline (pre-Phase-1)

This is the reference point that every Phase 1 slice's delta is measured against. Captured at current simulator rates with no architectural changes.

  • Scenario: §4.1 Demo baseline (10 min, Normal profile)
  • Capture: docs/captures/demo-baseline-2026-04-23.csv (687 s, includes warm-up + cool-down around the 10-minute scenario)
  • Commit: 7ecef05
  • Date: 2026-04-23
SliceMetricBaselineAfterDeltaCapture methodDate
demo-baseline (pre-Phase-1)frames.ingested (total)492demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)frames.ingested rate (fps)0.72demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)frames.dropped (total)0demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)telemetry.ingested (total)3 315demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)telemetry.ingested rate (Hz)4.83demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)telemetry.coalesced (total)0demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)runs.started41demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)runs.completed41demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)runs.faulted0demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)working-set peak (MB)203.4demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)gen-0-gc-count (total)135demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)gen-1-gc-count (total)33demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)gen-2-gc-count (total)8demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)alloc-rate avg (B/s)1 524 381demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)cpu-usage avg (%)0.99demo-baseline-2026-04-23.csv, §4.12026-04-23
demo-baseline (pre-Phase-1)cpu-usage peak (%)4.69demo-baseline-2026-04-23.csv, §4.12026-04-23

Notes on row 0

  • frames.dropped, telemetry.coalesced, and runs.faulted are absent from the CSV because dotnet-counters only emits rows for counters that were incremented at least once. Zero-valued rows above are the correct reading of that absence: no drops, no coalesces, no faulted runs across 41 completed runs. If a future capture shows non-zero values for any of these at demo rates, that is a regression.
  • Capture spans 687 s (11:27) because the CSV started ~30 s before the first Start click and stopped ~60 s after the last run completed. All rate metrics are computed over the full 687 s — not the 600 s scenario — so they include app-idle periods and will read slightly lower than the in-scenario rate. Keep this convention for every future row so deltas are apples-to-apples.

Row 0a — demo baseline (automated, pre-Phase-1 reference)

This row captures the same baseline scenario as row 0 but driven by the DemoBaselineScenario automation (TASK-1.5). It serves as the reference for future automated captures so that deltas do not mix manual operator timing with programmatic run cadence.

  • Scenario: §3a Demo baseline automated (10 min, Normal profile, operator-delay 0)
  • Capture: docs/captures/demo-baseline-automated-2026-04-25.csv (598 s)
  • Commit: f64173f
  • Date: 2026-04-25
SliceMetricBaselineAfterDeltaCapture methodDate
demo-baseline-automated (pre-Phase-1)frames.ingested (total)1 150demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)frames.ingested rate (fps)1.92demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)frames.dropped (total)0demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)telemetry.ingested (total)2 947demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)telemetry.ingested rate (Hz)4.93demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)telemetry.coalesced (total)0demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)runs.started58demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)runs.completed57demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)runs.faulted0demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)working-set peak (MB)73.5demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)gen-0-gc-count (total)9demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)gen-1-gc-count (total)1demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)gen-2-gc-count (total)0demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)alloc-rate avg (B/s)110 889demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)cpu-usage avg (%)0.23demo-baseline-automated-2026-04-25.csv, §3a2026-04-25
demo-baseline-automated (pre-Phase-1)cpu-usage peak (%)3.32demo-baseline-automated-2026-04-25.csv, §3a2026-04-25

Notes on row 0a

  • Purpose. Row 0a is the automated-capture reference; future Phase 1 slices captured via Capture-Measurements.ps1 should delta against this row, not against row 0. Row 0 remains the manual-capture reference and is not replaced.

  • Comparability with row 0. The simulator profile is the same (Normal). The telemetry rate is the correct comparability metric: row 0 = 4.83 Hz, row 0a = 4.93 Hz, delta = +2.1% — within the ±5% acceptability window. The telemetry.ingested ÷ runs.completed ratio (80.9 vs 51.7) is NOT comparable because row 0 had operator think-time between runs (~15 s/run) while row 0a is back-to-back (no --operator-delay). This is expected and correct behaviour.

  • Memory and GC vs row 0. Row 0a runs headless (no WPF window rendered) whereas row 0 was captured with the full UI visible. WPF's rendering loop generates significant allocation pressure; without it, alloc-rate (110 KB/s vs 1 524 KB/s) and GC counts (gen-0: 9 vs 135) are dramatically lower. Working-set peak is also lower (73.5 MB vs 203.4 MB). These differences are structural — do not treat them as improvements in the application domain logic.

  • runs.completed higher than row 0. 57 automated vs 41 manual in the same 10-minute window. Expected: the automated scenario starts the next run immediately after the previous one completes, whereas the manual procedure requires the operator to click Start Run within 1–2 seconds. This also explains why frames.ingested is higher (1 150 vs 492): more scan points executed, so more frames captured.

  • App exit code. The app exited with -532462766 (ObjectDisposedException in SimulatedTagSource.Dispose during host shutdown). This is a pre-existing defect that fires after scenario completion and does not affect the metrics. It is noted here for traceability.

  • Superseded by row 0b as of 2026-04-26. Row 0a captured a scenario that skipped the inter-run Home step (TASK-1.5.1 Pass 1 fixed the scenario; TASK-1.5.1 Pass 3 captured row 0b under the corrected behaviour). Row 0a is preserved unchanged.


Row 0b — demo baseline (automated, post-Home-fix reference)

This row captures the same scenario as row 0a but under the corrected DemoBaselineScenario from TASK-1.5.1 Pass 1 (inter-run Home step added) and the fixed shutdown from Pass 3 (ObjectDisposedException eliminated). It supersedes row 0a as the reference for all SLICE-1.2 and later automated captures.

  • Scenario: §3a Demo baseline automated (10 min, Normal profile, operator-delay 0, post-TASK-1.5.1)
  • Capture: docs/captures/demo-baseline-automated-row-0b-2026-04-26.csv (601 s)
  • Commit: 2b25476
  • Date: 2026-04-26
SliceMetricBaselineAfterDeltaCapture methodDate
demo-baseline-automated-0b (pre-Phase-1)frames.ingested (total)725demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)frames.ingested rate (fps)1.21demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)frames.dropped (total)0demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)telemetry.ingested (total)2 978demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)telemetry.ingested rate (Hz)4.95demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)telemetry.coalesced (total)0demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)runs.started45demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)runs.completed44demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)runs.faulted0demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)working-set peak (MB)72.6demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)gen-0-gc-count (total)8demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)gen-1-gc-count (total)0demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)gen-2-gc-count (total)0demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)alloc-rate avg (B/s)107 688demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)cpu-usage avg (%)0.22demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26
demo-baseline-automated-0b (pre-Phase-1)cpu-usage peak (%)4.16demo-baseline-automated-row-0b-2026-04-26.csv, §3a2026-04-26

Notes on row 0b

  • Why row 0b exists. TASK-1.5.1 Pass 1 fixed DemoBaselineScenario to call ops.Home.Execute(null) between runs instead of directly mutating AppState.WorkflowState. The Home step adds ~2–4 seconds of wall-clock time per run cycle (homing delay in the Normal simulator profile). Row 0a was captured against the broken scenario that skipped this step, so its runs.completed = 57 represents an artificially high throughput that no correctly-behaved capture can reproduce. Row 0b is the reference every SLICE-1.2 and later automated capture must delta against.

  • Which row Phase 1 deltas compare against. Use row 0b for every SLICE-1.2 onward automated capture. Row 0a is retained as historical evidence of the broken-scenario state and must not be used as a delta baseline.

  • runs.completed delta. Row 0b: 44 vs row 0: 41 (manual, +7%) vs row 0a: 57 (broken scenario, −23% relative to 0a). The drop from 0a to 0b is expected: the inter-run Home step from TASK-1.5.1 Pass 1 consumes ~2–4 s per cycle in the Normal simulator profile. Row 0b is closer to the manual row 0 throughput because both the manual operator and the corrected scenario now perform the same Home→Start sequence between runs.

  • App exit code. The app exited with code 0. The ObjectDisposedException defect that produced -532462766 in all earlier automated captures was fixed by TASK-1.5.1 Pass 3 (added _disposed guard to SimulatedTagSource.Dispose).


Phase 1 rows

Row — slice-1-3-encoder-rate-motion

SLICE-1.3 evidence row: first capture under the new EncoderRate simulator profile. Exercises the new IEncoderStream data-plane (1 kHz target, two axes, per-axis RandomWalkNoise around commanded position) running alongside the existing 50-tag MultiTag telemetry stream. The encoder pipeline service drains the bounded channel and increments encoder.samples.ingested{axis=…} without writing to AppState — the load-bearing architectural point of the slice. See "Encoder-rate cadence gap" note below.

  • Scenario: §4.4 Encoder-rate soak (10 min, EncoderRate profile) via MultiTagSoakFlaUi
  • Capture: docs/captures/slice-1-3-encoder-rate-2026-04-30.csv (613 s)
  • Profile: EncoderRate (mirrors MultiTag: 50 tags @ heterogeneous rates, 50 ms snapshot interval, 640 × 480 × 1 frames @ 500 ms; EncoderIntervalMs = 1)
  • Commit: 736afac
  • Date: 2026-04-30
SliceMetricBaselineAfterDeltaCapture methodDate
slice-1-3-encoder-rate-motionframes.ingested (total)8 154770−7 384†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionframes.ingested rate (fps)13.411.26†—†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionframes.dropped (total)000slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motiontelemetry.ingested (total)5 54512 066+6 521†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motiontelemetry.ingested rate (Hz)9.1219.68†—†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motiontelemetry.coalesced (total)24+2slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionruns.started14170−71†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionruns.completed14070−70†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionruns.faulted000slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionworking-set peak (MB)237.2223.3−13.9†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motiongen-0-gc-count (total)599529−70slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motiongen-1-gc-count (total)9573−22slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motiongen-2-gc-count (total)2 71350−2 663†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionalloc-rate avg (B/s)35 132 2856 512 7960.19׆slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motioncpu-usage avg (%)5.434.35−1.08†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motioncpu-usage peak (%)19.5317.58−1.95†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motiongc-pause-p95 (ms)11.767.90−3.86†slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionLOH-alloc-rate avg (B/s)1 039 96623 2510.022׆slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionencoder-rate-x (Hz)656.6slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30
slice-1-3-encoder-rate-motionencoder-rate-y (Hz)656.6slice-1-3-encoder-rate-2026-04-30.csv, §4.42026-04-30

† Profile change drives the delta. EncoderRate mirrors MultiTag (640 × 480 × 1 frames @ 500 ms, 50 ms telemetry snapshot, 50 tags) plus EncoderIntervalMs = 1, whereas the slice-1-2 baseline used HighFrameRate (2048 × 1024 × 1 frames @ 33 ms, 100 ms telemetry snapshot). The frame, telemetry, and LOH-pressure deltas are dominated by that profile shift, not by the encoder stream.

Notes on slice-1-3-encoder-rate-motion

  • Baseline reference is slice-1-2-real-frame-payloads (most recent FlaUI-captured row). The architectural delta this row isolates is the addition of the IEncoderStream data plane — but most of the visible numeric delta comes from the profile shift HighFrameRate → EncoderRate. Use the encoder-rate-x / encoder-rate-y rows and the absence of run faults / frame drops as the primary evidence; treat the rest as profile context.

  • Encoder-rate cadence gap — Windows PeriodicTimer ceiling, not a code defect. Receiver-side rate held at 656.6 Hz on both axes across the 613 s capture, well below the original criterion-7 target of 980–1020 Hz. The producer acquires winmm!timeBeginPeriod(1) on StartAsync so the OS timer floor is 1 ms, but PeriodicTimer(1 ms).WaitForNextTickAsync is not a real-time mechanism: per-tick scheduling overhead plus the producer's per-tick work (two _motion._lock reads to get CurrentX/CurrentY, an ImmutableArray.Builder<EncoderSample>(2) allocation, channel TryWrite, plus the NoiseModelEvaluator.Evaluate per axis) drives the effective tick to ~1.52 ms. Criterion 7 was amended on 2026-04-30 to documented-not-gated (mirroring SLICE-1.1's per-tag-rate amendment for the same Windows-timer-resolution family of constraints). The slice's load-bearing architectural point — receiver-side counter reachable through a non-AppState channel at hundreds-of-Hz rates without destabilizing the workflow state machine — is met (runs.faulted = 0, frames.dropped = 0, tags.active = 50 throughout). Filed as a follow-up: encoder-cadence remediation — replace PeriodicTimer with one of (a) a dedicated thread + Stopwatch.GetTimestamp() busy-yield, (b) timeSetEvent multimedia-callback, (c) CreateWaitableTimerEx(TIMER_HIGH_RESOLUTION). Each carries different CPU-cost / portability trade-offs; pick when there is a downstream consumer that actually demands 1 kHz cadence.

  • No AppState write from the encoder pipeline (load-bearing test). Verified mechanically by EncoderStreamPipelineServiceTests.Pipeline_WhenDrainingSnapshots_NeverCallsAppStateStoreUpdate (recording-store fake asserts UpdateCount == 0). The on-machine evidence is runs.faulted = 0 + the 19.68 Hz observed telemetry.ingested rate (matching the 50 ms snapshot publisher cadence), which together demonstrate the encoder stream did not bleed into the snapshot-publisher path or the workflow state machine even at 656 Hz × 2 axes ≈ 1 313 channel-write attempts/s.

  • LOH and gen-2 GC dropped sharply vs the SLICE-1.2 baseline. gen-2 GC count fell from 2 713 to 50 (−98%) and LOH-alloc-rate-avg from 1.0 MB/s to 23 KB/s (−98%). Driven by EncoderRate using 640 × 480 × 1 frames at 500 ms (Normal-class allocation) instead of HighFrameRate's 2 MP frames at 33 ms — i.e. nearly all of the SLICE-1.2 row's LOH pressure is gone here, by design. The encoder stream itself contributes ~1.3 K small ImmutableArray<EncoderSample>(2) allocations/s; those are gen-0-bound, not LOH (each is well under 85 KB), and show up in alloc-rate avg (6.5 MB/s) but do not move gen-2 numbers.

  • Capture span 613 s vs scenario 600 s. The 13 s difference is the MultiTagSoakFlaUi warm-up and shutdown slop — consistent with the pattern seen in slice-1-2 (608 s for a 600 s scenario). System sleep was disabled for the duration (powercfg /change standby-timeout-ac 0) per the SLICE-1.1 / SLICE-1.5.1 runbook discipline; the capture window contains no idle gaps.


Row — slice-1-4-chaos-monkey

SLICE-1.4 first evidence row: 30-minute capture under the ChaosMonkey simulator profile (aggressive fault injection — DefectShowerEveryMs = 3 000, AlarmBurstEveryMs = 45 000, TelemetryDropoutChance = 0.05, NetworkLatencyMeanMs = 100, ConnectionFailureProbability = 0.3, FlakySdk:Enabled = true). Exercises all four fault branches in WorkflowService to verify criterion 11 (every fault branch hit, log evidence).

  • Scenario: §4.5 Chaos-monkey scenario (30 min, ChaosMonkey profile) via MultiTagSoakFlaUi
  • Capture: docs/captures/slice-1-4-chaos-monkey-2026-05-01.csv (1 807 s)
  • Profile: ChaosMonkey
  • Commit: 2108272
  • Date: 2026-05-01
SliceMetricBaselineAfterDeltaCapture methodDate
slice-1-4-chaos-monkeyframes.ingested (total)77010 469+9 699††slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyframes.ingested rate (fps)1.265.794.59׆†slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyframes.dropped (total)000slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeytelemetry.ingested (total)12 06635 784+23 718††slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeytelemetry.ingested rate (Hz)19.6819.80+0.12slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeytelemetry.coalesced (total)42−2slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyruns.started70491+421††slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyruns.completed70453+383††slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyruns.faulted037+37slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyworking-set peak (MB)223.3225.3+2.0slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeygen-0-gc-count (total)5292 279+1 750††slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeygen-1-gc-count (total)73629+556††slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeygen-2-gc-count (total)501 429+1 379††slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyalloc-rate avg (B/s)6 512 79614 557 9902.24׆†slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeycpu-usage avg (%)4.354.66+0.31slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeycpu-usage peak (%)17.5815.04−2.54slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeygc-pause-p95 (ms)7.9010.28+2.38slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyLOH-alloc-rate avg (B/s)23 251323 18813.9׆†slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyencoder-rate-x (Hz)656.6199.90.30׆†slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyencoder-rate-y (Hz)656.6199.90.30׆†slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyworking-set growth (MB)138.2slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01
slice-1-4-chaos-monkeyfault-cycles (count)37slice-1-4-chaos-monkey-2026-05-01.csv, §4.52026-05-01

†† Duration and profile both differ from baseline (slice-1-3: 613 s, EncoderRate; slice-1-4-chaos-monkey: 1 807 s, ChaosMonkey). Totals scale with scenario length; only rates, runs.faulted, fault-cycles, and working-set peak carry direct architectural meaning.

Notes on slice-1-4-chaos-monkey

  • Baseline reference is slice-1-3-encoder-rate-motion (most recent FlaUI-captured row). The delta isolates the ChaosMonkey profile's footprint versus the lighter EncoderRate profile. The encoder-rate drop (656.6 → 199.9 Hz) is expected: ChaosMonkey sets EncoderIntervalMs = 5 (200 Hz target) whereas EncoderRate uses EncoderIntervalMs = 1 (1 000 Hz target, achieved ~657 Hz on this host). Working-set peak is essentially unchanged (+2.0 MB); fault injection adds no persistent allocation pressure.

  • Criterion-11 fault-branch evidence (all four branches hit). Log inspection of Logs/app-20260501.log confirmed: 39 CRITICAL FAULT: [CHAOS-…] lines injected, 39 Fault condition cleared: [CHAOS-…] lines, 37 Recovery completed. lines, and 120 defect-shower state transitions. The two unrecovered faults (39 injected − 37 recovered) are the final two chaos events that fired within the last few seconds of the scenario window before teardown — consistent with the ~45 s inter-burst interval and a 1 807 s capture. Branch coverage: (a) connect-failure path via ConnectionFailureProbability = 0.3 and FlakySdk OutOfBandThrow / IgnoreCancellation modes; (b) fault-during-home via AlarmBurstEveryMs = 45 000 firing within the ~1 s homing window; (c) fault-during-run via the same alarm burst firing while a run is active; (d) fault-clear-and-recover via the 37 full inject→clear→recover cycles.

  • Simulator:FlakySdk:Enabled caveat. Captured with FlakySdk:Enabled = true (manually flipped before the 2026-05-01 session). The merged appsettings.json ships Enabled = false (commit 018bf29, criterion-16 reproducibility). To reproduce this row: flip Simulator:FlakySdk:Enabled to true in src/InspectionPrototype.App/appsettings.json before building, then restore to false afterward.

  • FlakySdk timeout-branch fix (commit 018bf29). The ChaosMonkey capture ran against the pre-fix code (2108272). After the capture a review found the timeout branch unconditionally threw OperationCanceledException even when the caller's CT was not cancelled; the correct behaviour (fall through to the inner connection) was fixed in 018bf29. The fault-cycle count is unaffected: the scenario's retry-Connect loop already handled the OCE by retrying, so the observable behaviour was the same before and after the fix.


Row — slice-1-4-soak-8h

SLICE-1.4 second evidence row: 8-hour capture under the Soak8h simulator profile (low-chaos sustained load — AlarmBurstEveryMs = 0, TelemetryDropoutChance = 0.01, ConnectionFailureProbability = 0.05, TimeCompressionFactor = 1.0, FlakySdk:Enabled = false). Intended to detect working-set growth over real time (criterion 12: last − first ≤ 50 MB). See criterion-12 gap note below.

  • Scenario: §4.6 Soak scenario (8 h, Soak8h profile) via MultiTagSoakFlaUi
  • Capture: docs/captures/slice-1-4-soak-8h-2026-05-02.csv (28 809 s)
  • Profile: Soak8h
  • Commit: 018bf29
  • Date: 2026-05-03
SliceMetricBaselineAfterDeltaCapture methodDate
slice-1-4-soak-8hframes.ingested (total)8 15471 530+63 376††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hframes.ingested rate (fps)13.412.480.18׆†slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hframes.dropped (total)02+2slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8htelemetry.ingested (total)5 545286 968+281 423††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8htelemetry.ingested rate (Hz)9.129.96+0.84††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8htelemetry.coalesced (total)212+10††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hruns.started1415 109+4 968††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hruns.completed1405 109+4 969††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hruns.faulted000slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hworking-set peak (MB)237.2246.0+8.8slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hgen-0-gc-count (total)59931 494+30 895††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hgen-1-gc-count (total)955 551+5 456††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hgen-2-gc-count (total)2 71311 185+8 472††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8halloc-rate avg (B/s)35 132 2859 953 5460.28׆†slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hcpu-usage avg (%)5.434.42−1.01††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hcpu-usage peak (%)19.5313.67−5.86††slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hgc-pause-p95 (ms)11.7612.42+0.66slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hLOH-alloc-rate avg (B/s)1 039 966238 6720.23׆†slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hencoder-rate-x (Hz)200.0slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hencoder-rate-y (Hz)200.0slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hworking-set growth (MB) ‡186.5 ⚠slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hworking-set steady-state drift (MB)−2.7slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03
slice-1-4-soak-8hfault-cycles (count)0slice-1-4-soak-8h-2026-05-02.csv, §4.62026-05-03

†† Duration and profile both differ from baseline (slice-1-2: 608 s, HighFrameRate; slice-1-4-soak-8h: 28 809 s, Soak8h). All totals scale with the 47× duration difference; only rate metrics, working-set growth, encoder-rate, and fault-cycles carry direct architectural meaning. ⚠ Original criterion-12 metric (last − first) reads 186.5 MB, exceeding the 50 MB ceiling. Direct CSV inspection showed this is entirely the process startup ramp (47.5 → 230.9 MB in 29 s); no leak in the 8-hour plateau. Criterion 12 amended (2026-05-03) to use a startup-excluded steady-state metric; see next row. ‡ Original metric retained for historical traceability; superseded by working-set steady-state drift (MB) per criterion-12 amendment in SLICE-1.4 spec (2026-05-03).

Notes on slice-1-4-soak-8h

  • Baseline reference is slice-1-2-real-frame-payloads (continuous-load FlaUI-captured row with low chaos). Both slice-1-2 and Soak8h emphasise sustained data-plane throughput with minimal intentional faults; Soak8h has AlarmBurstEveryMs = 0 so no alarm-driven fault paths fire. The primary comparison point is the working-set growth row (new in SLICE-1.4), not the totals (dominated by the 47× duration difference).

  • Criterion-12 analysis — startup ramp, not a sustained leak. Criterion amended 2026-05-03. Working-set first-second = 47.5 MB; last-second = 234.0 MB; last − first = 186.5 MB, which exceeds the original 50 MB ceiling. Direct CSV inspection (sampled across 14 timepoints from t=0 to t=8h) revealed the entire delta is the process startup ramp: working-set rose from 47.5 MB to 230.9 MB at t=29 s (full ramp in under 30 seconds — WPF rendering, 50 tag emitters, encoder pipeline initialisation, JIT). It then held a stable sawtooth between 224 MB and 240 MB for the remaining 7.5 hours. Window analysis: avg(minutes 5-30) = 235.4 MB, avg(hours 4-5) = 234.0 MB, avg(last 60 min) = 232.7 MB — the steady-state mean decreased by 2.7 MB across 8 hours. p99 = 238.1 MB; one transient max = 246.0 MB. There is no monotonic growth at any point after the startup ramp completes. Criterion 12 amended: original metric working-set growth = last − first ≤ 50 MB is superseded by working-set steady-state drift = avg(last 60 min) − avg(minutes 5-60) ≤ 50 MB. The 50 MB ceiling itself is unchanged; only the measurement window. Against the amended metric, the 2026-05-02 capture reads −2.7 MB — passes the ceiling by a wide margin. Same pattern as SLICE-1.1's criterion 7 amendment (per-tag rate accuracy, Windows scheduling reality) and SLICE-1.3's criterion 7 amendment (encoder receiver rate, Windows timer-resolution ceiling). Phase 1 exit gate met 2026-05-03.

  • Gen-2 GC rate vs slice-1-2 ceiling (passes). slice-1-2 recorded 2 713 gen-2 collections in 608 s = 16 072/hr; slice-1-4-soak-8h recorded 11 185 in 28 809 s = 1 398/hr. The 4× ceiling (64 288/hr) is satisfied by a wide margin. The lower rate reflects Soak8h's lighter LOH pressure (640 × 480 × 1-byte frames at 500 ms vs HighFrameRate's 2 MP frames at 33 ms; LOH-alloc-rate dropped from 1.0 MB/s to 0.23 MB/s).

  • Per-tag samples.ingested. All 50 configured tags were active throughout (aggregate telemetry.ingested rate = 9.96 Hz ≈ 10 Hz, matching the 100 ms snapshot interval of the Soak8h profile). telemetry.coalesced = 12 over 28 809 s (< 1 coalesce per 2 400 s), consistent with TelemetryDropoutChance = 0.01 occasionally deferring a snapshot under transient load. No tag dropped by more than expected.

  • frames.dropped = 2. Two frames dropped over 28 809 s (0.003% of 71 530 total). Within normal operating variance; the bounded frame channel absorbed transient scheduling spikes without accumulation. Not a criterion gate.

  • runs.faulted = 0. The Soak8h profile has AlarmBurstEveryMs = 0 (no alarm-driven faults). The 5% ConnectionFailureProbability fires on ConnectAsync; the retry-Connect loop from commit 2108272 absorbs these at setup time. All 5 109 started runs completed.


Row — slice-1-2-real-frame-payloads

SLICE-1.2 evidence row: first HighFrameRate (30 fps, 2 MP) capture under the FlaUI rig (SLICE-1.6). Exercises SimulatedCamera's real byte[] allocation path and the WriteableBitmap update pipeline at ~2 MB × 30 fps LOH pressure. See "frames.ingested criterion gap" note below.

  • Scenario: §3b HighFrameRate soak (10 min, HighFrameRate profile) via MultiTagSoakFlaUi
  • Capture: docs/captures/slice-1-2-high-fps-2026-04-27.csv (608 s)
  • Commit: 874946d
  • Date: 2026-04-27
SliceMetricBaselineAfterDeltaCapture methodDate
slice-1-2-real-frame-payloadsframes.ingested (total)7258 154+7 429slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsframes.ingested rate (fps)1.2113.41†—†slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsframes.dropped (total)000slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadstelemetry.ingested (total)2 9785 545+2 567slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadstelemetry.ingested rate (Hz)4.959.12†—†slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadstelemetry.coalesced (total)02+2slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsruns.started45141+96slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsruns.completed44140+96slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsruns.faulted000slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsworking-set peak (MB)72.6237.2+164.6slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsgen-0-gc-count (total)8599+591slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsgen-1-gc-count (total)095+95slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsgen-2-gc-count (total)02 713+2 713slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsalloc-rate avg (B/s)107 68835 132 285+326×slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadscpu-usage avg (%)0.225.43+5.21slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadscpu-usage peak (%)4.1619.53+15.37slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsgc-pause-p95 (ms)11.76slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27
slice-1-2-real-frame-payloadsLOH-alloc-rate avg (B/s)1 039 966slice-1-2-high-fps-2026-04-27.csv, §3b2026-04-27

† Rate metric not directly comparable to row 0b — different profile and scenario duration (§3b vs §3a).

Notes on slice-1-2-real-frame-payloads

  • Baseline reference is row 0b (automated DemoBaseline, Normal profile). The delta isolates the HighFrameRate profile's footprint on top of the Normal-profile reference. The HighFrameRate profile (2048 × 1024 × 1, 33 ms interval) vs Normal (640 × 480 × 1, 1000 ms interval) drives the dominant effects: alloc-rate +326×, gen-2 GC count +2 713, working-set +164 MB, cpu avg +5.2 percentage points.

  • frames.ingested criterion gap — scenario vs criterion model mismatch. SLICE-1.2 acceptance criterion 6 requires frames.ingested ≥ 17 500 (= 30 fps × 600 s × 0.97), which assumes the camera produces frames continuously for the full 600 s connected period. SimulatedCamera only produces frames while a run is actively in progress (Connected + Running state); during Home, Idle, and Ready transitions the camera is not streaming. With 140 completed runs averaging ~4.3 s per cycle (including Home latency), only a fraction of the 608 s window has active frame production. The observed 8 154 frames imply ~30 fps during active scan motion — consistent with FrameIntervalMs = 33 — which confirms the HighFrameRate pipeline is operating at the configured rate. The shortfall is a mismatch between the criterion's continuous-streaming assumption and the multi-cycle scan scenario structure, not a pipeline defect. The other evidence — frames.dropped = 0, runs.faulted = 0, gen-2 count 2 713 (LOH pressure confirmed), p95 pause 11.76 ms (no pause-caused drops) — confirms the pipeline is working correctly under HighFrameRate load. Filed as follow-up: amend criterion 6 to match the achievable frame count under the multi-cycle scenario, or add a dedicated single-continuous-run scenario that stays in Running state for the full 10 minutes.

  • gen-2 GC and LOH allocation evidence. 2 713 gen-2 collections in 608 s (4.5/s) vs 0 in row 0b — the LOH allocation pressure from 2 MB frames is reaching the LOH threshold and driving significant gen-2 collection activity, confirming the frame pipeline's allocation behavior as intended by SLICE-1.2. p95 GC pause = 11.76 ms; frames.dropped = 0 confirms the channel absorbed all production without loss despite the pause overhead. LOH alloc rate 1.0 MB/s is the time-averaged rate over the full 608 s including idle periods; during active runs it tracks closer to 60 MB/s (2 MB × ~30 fps).

  • Telemetry rate higher than row 0b. 9.12 Hz vs 4.95 Hz in row 0b — because HighFrameRate uses the same TelemetryIntervalMs = 50 ms as the MultiTag profile (both are 50-tag, 20 Hz snapshot configurations), while Normal uses 200 ms (5 Hz). This is expected profile behavior.

  • Commit hash. Row was captured against uncommitted Pass 3 code (XAML ActiveSimulatorProfileText fix, SIMULATOR_PROFILE env-var wire-through in MultiTagSoakFlaUi, -Profile parameter in Capture-Measurements.ps1). Commit hash updated to the Pass 3 commit after the session commit.


Row — slice-1-1-multi-tag-telemetry

First Phase 1 row. Captures the multi-tag telemetry slice under the new MultiTag simulator profile (50 tags emitting at heterogeneous rates from 1 Hz to 500 Hz configured) via the automated MultiTagSoakScenario.

  • Scenario: §4.2 Multi-tag soak (30 min, MultiTag profile, operator-delay 0)
  • Capture: docs/captures/slice-1-1-multi-tag-2026-04-26.csv (5811 s — see "Capture duration discrepancy" in Notes)
  • Per-tag rate distribution: docs/captures/slice-1-1-multi-tag-2026-04-26-rate-check-2026-04-26.txt
  • Commit: 827a7ee
  • Date: 2026-04-26
SliceMetricBaselineAfterDeltaCapture methodDate
slice-1-1-multi-tag-telemetryframes.ingested (total)7252 266+1 541slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetryframes.ingested rate (fps)1.210.39†—†slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetryframes.dropped (total)000slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetrytelemetry.ingested (total)2 97828 829+25 851slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetrytelemetry.ingested rate (Hz)4.954.96†—†slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetrytelemetry.coalesced (total)018+18slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetryruns.started45175+130slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetryruns.completed44174+130slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetryruns.faulted000slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetryworking-set peak (MB)72.680.3+7.7slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetrygen-0-gc-count (total)8180+172slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetrygen-1-gc-count (total)023+23slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetrygen-2-gc-count (total)04+4slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetryalloc-rate avg (B/s)107 688709 132+6.6×slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetrycpu-usage avg (%)0.220.56+0.34slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26
slice-1-1-multi-tag-telemetrycpu-usage peak (%)4.168.98+4.82slice-1-1-multi-tag-2026-04-26.csv, §4.22026-04-26

† Rate metric not directly comparable to row 0b — see "Capture duration discrepancy" below.

Notes on slice-1-1-multi-tag-telemetry

  • Baseline reference is row 0b (automated DemoBaseline, Normal profile). The delta isolates the Normal → MultiTag profile change under the same automation. Substantive findings from the comparable counters: telemetry.ingested totals are ≈10× higher (50 ms snapshot interval vs 200 ms), runs.completed is ≈4× higher (3× longer scenario × MultiTag's faster motion profile), and alloc-rate is ≈6.6× higher (50 concurrent emitters allocating per-call dimension KeyValuePair vs row 0b's single telemetry cell).

  • Capture duration discrepancy — system sleep, not a code bug. The scenario was configured for 1 800 s but the CSV spans 5 811 s. Investigation against app-20260426.log shows a 63-minute gap with zero log events and zero CSV rows between 11:17:59 Moving to (50.0, 25.0) and 12:21:41 Camera streaming stopped. The host actually shuts down promptly (~2 s from Stopping active run before disconnect to Tag source disposed); the long wall time is the laptop sleeping mid-capture and resuming. An identical-config first run earlier the same day (10:12–10:42) finished cleanly in 30 min for 174 runs. Counter totals reflect actual work done; rate metrics in the table above are computed over the full CSV span (5 811 s) and are therefore diluted by the sleep duration. Scenario-duration-normalized rates (dividing by 1 800 s instead): frames.ingested ≈ 1.26 fps; telemetry.ingested ≈ 16.0 Hz; alloc-rate ≈ 2.3 MB/s. Action item: disable system sleep during captures (Windows: powercfg /change standby-timeout-ac 0 for the duration). Filed as a runbook caveat, not a code follow-up.

  • Per-tag rate accuracy (acceptance criterion 7, amended). All 50 configured tags appear in samples.ingested with the tag.name dimension (criterion 6 met; verified by AppMetricsTagDimensionTests). With scenario-duration normalization (samples ÷ 1 800 s, since per-tag emitters are paused during the system-sleep window): ≤5 Hz tags hit within ±2% of configured (1 Hz → 1.00 Hz, 5 Hz → 4.91 Hz); 10 Hz → 9.17 Hz (-8%); 20 Hz → 16.0 Hz (-20%); 50 Hz → 32.1 Hz (-36%); 100 Hz → 63.9 Hz (-36%); 250 Hz and 500 Hz tags both cap near 64 Hz from the default Windows 15.6 ms timer tick. The CSV-span normalization in the rate-check .txt understates all bands by ~3.2× because of the sleep dilution. Simulator emit-rate accuracy under concurrent load is filed as a follow-up; for SLICE-1.2 onward, captures should run on a sleep-disabled session so this confound doesn't recur.


Reading this table across phases

  • Row 0's baseline column is the reference for every later row's delta until Phase 2 begins. Phase 1 rows compare against row 0.
  • Phase 2 rows will compare against the final Phase 1 row (to be chosen when Phase 1 exits). Do not retroactively edit Phase 1 rows after Phase 2 starts.
  • If a capture is re-run (for example because the scenario changed), add a new row rather than editing the old one. Old rows are historical evidence and should not be rewritten.

Docs-first project memory for AI-assisted implementation.