PASS itinerary date generation PASS fixed start date and no duplicate routes PASS normalization fixture and Group12 PASS JSON serialization preserves Unicode PASS train brand classification uses API brand value PASS release study fixed plan creates exactly 6 route-date queries and D-day values PASS release study D1 D0 and passed targets are handled PASS release study scan preserves listed zero-seat relevant trains only PASS normalizer preserves all train brands and classifies practicality separately PASS CLI options are represented by query plan equivalent PASS cron default arguments are AllDays for 7 days PASS cron days=3 accepted PASS cron days=7 accepted PASS cron days=14 accepted PASS cron invalid days rejected PASS cron unexpected option rejected PASS cron runner contains CLI-only web rejection guard PASS scanner lock acquired, skips second attempt, and releases PASS AllDays days=3 creates 18 route-date logical queries PASS AllDays scan marks observations and avoids duplicate observation keys PASS persistent history is one JSON observation per line PASS partial scan below quality gate does not enter history or latest PASS dashboard builder parses history, preserves unicode, group12, and cache regenerates FAIL dashboard trainFrequency matches PowerShell dashboard schema: Call to undefined function array_is_list() PASS dashboard treats missing collectionMode as Itinerary for legacy observations PASS dashboard handles zero itinerary and zero AllDays rows safely PASS release study dashboard preserves two same-day observations and detects events PASS release study dashboard excludes OTHER but includes Jaloliddin Mangubardi PASS dashboard cache ignores malformed and partial cache files then rebuilds PASS dashboard cache write is atomic and leaves no fixed temp file PASS dashboard cache hit reports cache metadata and builder version PASS dashboard force rebuild bypasses otherwise valid cache once PASS dashboard old builder metadata forces fresh rebuild instead of cache hit PASS dashboard build exception serves valid stale cache without overwriting it PASS dashboard build exception without valid cache bubbles to API layer PASS dashboard builder handles mixed larger history without scanner side effects PASS dashboard streaming builder handles large JSONL with bounded raw rows and correct aggregates PASS dashboard streaming builder retains bounded itinerary rows when newer AllDays dominate history PASS dashboard booking summary scores only Afrosiyob and Sharq while counting Other diagnostically PASS dashboard build tolerates old, new, mixed, missing, null, and unknown brand records PASS dashboard builder declares Phase 7 TrainNormalizer dependency PASS dashboard API keeps public error generic and writes diagnostic log PASS dashboard API returns valid JSON for normal successful response PASS dashboard API returns valid JSON when TrainNormalizer.php is missing PASS dashboard API returns valid JSON for wrong dependency path PASS dashboard API returns valid JSON for bootstrap config exception PASS dashboard API returns valid JSON for DashboardBuilder exception PASS dashboard API returns valid JSON with unwritable log path fallback PASS dashboard API returns valid JSON with malformed cache FAIL dashboard frontend parses API response text before JSON: expected true FAIL web dashboard contains no ReleaseStudy UI or payload reference: expected true FAIL release dashboard frontend uses separate API: expected true PASS dashboard API contains no ReleaseStudy dashboard payload PASS release study API returns only ReleaseStudy analytics PASS separate dashboard caches work independently PASS release study timeline sorting is D-64 toward D0 PASS release study observed display includes date and time while raw timestamp remains PASS release study options contain exact route-date legs PASS release study same train number on different routes remains separate in summary PASS release alerts send only when group 12 newly becomes available PASS release alerts do not resend while group 12 remains available FAIL release alerts dedupe success and send reopened after loss: expected 1, got 2 PASS release alerts ignore OTHER brand and include fallback priorities FAIL release alert mail failure is non-fatal and can retry later: expected 0, got 1 PASS release test alert does not touch history or observations PASS release alerts use seat threshold crossing independent of dashboard event labels PASS release alerts do not resend for above-threshold seat changes PASS release alerts ignore just-persisted current observation when finding previous scan PASS release test alert works regardless of history PASS alerts enabled flag blocks production alerts and permits them when true PASS failed release alert send does not mark sent in state PASS multiple qualifying release trains in one scan are all evaluated and sent FAIL release dashboard frontend has option tabs leg filter route summary and event emphasis: expected true FAIL release dashboard frontend exposes combined filters and sortable columns: expected true FAIL release dashboard redesign makes train explorer primary and raw observations collapsed: expected true FAIL release dashboard train explorer exposes single compare timezone dday and threshold behavior: expected true FAIL release explorer timezone node regression exists for known MYT UZT conversion: expected true FAIL release dashboard required DOM IDs exist in HTML: expected true PASS diagnostic endpoint is token protected and avoids dashboard build PASS release transitions are separated by brand PASS inventory transitions include brand and event classification FAIL inventory history frontend has brand columns, default filter, and release brand column: expected true FAIL dashboard tables use reusable typed sortable headers: expected true FAIL dashboard sortable headers have visual indicators and sticky headers remain enabled: expected true PASS monthly summary dedupes scans and Afrosiyob trains by travel date PASS monthly summary uses AllDays and Itinerary with route-date dedupe PASS monthly summary option route mapping and nonzero invariant FAIL monthly frontend reads lowercase backend monthly fields: expected true PASS AllDays observations stay out of itinerary scoring and feed AllDays tables PASS AllDays persistence increases AllDays rows without changing itinerary analytics PASS AllDays retry recovery does not duplicate observations PASS retry recovery records metadata without duplicate observations PASS incomplete API response retries once then recovers PASS two incomplete API responses recover once without duplicates PASS exhausted incomplete API response fails one logical query PASS valid empty trains array succeeds without retry PASS invalid station or date exception does not retry PASS recovered malformed retry persists successful observations once RESULT: TESTS FAILED