From 77cf90e40bd3db1fd134f9f7b7d0c302272425e9 Mon Sep 17 00:00:00 2001 From: Yashas Date: Thu, 17 Sep 2026 12:26:49 +0530 Subject: [PATCH] =?UTF-8?q?fix:=20a=20review=20window=20needs=20a=20baseli?= =?UTF-8?q?ne=20=E2=80=94=20say=20which=20one,=20refuse=20ones=20that=20ha?= =?UTF-8?q?ve=20none?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - charter: a window starting before the data or longer than 12 weeks is split (last 6 weeks vs the 8 before); REVIEWED always names the compared periods, never the requested span or the whole table - Run review: shows the data's span, previews the exact recent and baseline periods, blocks a window whose baseline would fall before the first claim, and sends 'data as of' only when no window end is given Co-Authored-By: Claude Fable 5.1 --- src/screens/RunReviewScreen.tsx | 34 ++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/screens/RunReviewScreen.tsx b/src/screens/RunReviewScreen.tsx index 97c1951..6fba93a 100644 --- a/src/screens/RunReviewScreen.tsx +++ b/src/screens/RunReviewScreen.tsx @@ -1,7 +1,9 @@ import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Brain, CalendarRange, Database, Radar } from 'lucide-react'; -import { useZino } from '../api/provider'; +import { useQuery, useZino } from '../api/provider'; +import { addDays } from '../api/charts'; +import { str } from '../format'; import { ACT, LAKEHOUSE, QUIET_MORNING_AS_OF, WORKFLOW } from '../api/config'; import { Button, Card, ErrorNote, Input, Label } from '../components/core'; import { shortDate } from '../format'; @@ -28,14 +30,29 @@ export function RunReviewScreen() { const [from, setFrom] = useState(''); const [to, setTo] = useState(''); + // The data's own span, so a window cannot be set where there is nothing to + // compare: a start before the first claim leaves no baseline, and a run on + // such a window would have to improvise one. + const stats = useQuery(() => client.rows('dni-rv-lakehouse-tables', { limit: 10 }), []); + const claimsStats = stats.data?.find((r) => str(r.table_name) === 'claims'); + const dataFrom = str(claimsStats?.from_date).slice(0, 10) || null; + const dataTo = str(claimsStats?.to_date).slice(0, 10) || null; + // The window Ava will actually use, so the reviewer sees it before pressing Run. const effectiveTo = to || asOf; + const weeks = from && effectiveTo ? Math.round((new Date(effectiveTo).getTime() - new Date(from).getTime()) / 604800000) : null; + const split = weeks != null && weeks > 12; + const recentFrom = split && effectiveTo ? addDays(effectiveTo, -41) : from || (effectiveTo ? addDays(effectiveTo, -41) : ''); + const baseFrom = recentFrom ? addDays(recentFrom, -56) : ''; + const baseTo = recentFrom ? addDays(recentFrom, -1) : ''; const dateErr = from && effectiveTo && from > effectiveTo ? 'The window must start before it ends.' : to && asOf && to > asOf ? '"Window to" cannot be after "data as of".' - : null; + : dataFrom && baseFrom && baseFrom < dataFrom + ? `The 8-week baseline before ${shortDate(recentFrom)} needs data from ${shortDate(baseFrom)}, but the data begins ${shortDate(dataFrom)}. Start the window on or after ${shortDate(addDays(dataFrom, 56))}.` + : null; async function run(custom: boolean) { setBusy(custom ? 'custom' : 'now'); @@ -45,7 +62,8 @@ export function RunReviewScreen() { // reviewer set, so a plain run is a genuinely empty submission. const data: Record = {}; if (custom) { - if (asOf) data.review_as_of__review = asOf; + // "Window to" is the ceiling; "data as of" only matters when no window end is given. + if (asOf && !to) data.review_as_of__review = asOf; if (from) data.review_from__review = from; if (to) data.review_to__review = to; } @@ -121,6 +139,7 @@ export function RunReviewScreen() {

Replay a past morning, or point the review at a specific period. Leave a date blank to use the default. + {dataFrom && dataTo ? ` Data available ${shortDate(dataFrom)} – ${shortDate(dataTo)}, ${dataTo.slice(0, 4)}.` : ''}

@@ -150,11 +169,12 @@ export function RunReviewScreen() { <> Ava will compare{' '} - {from ? shortDate(from) : effectiveTo ? '6 weeks before' : 'the last 6 weeks'} - {from || effectiveTo ? ` – ${effectiveTo ? shortDate(effectiveTo) : 'latest data'}` : ''} + {recentFrom ? `${shortDate(recentFrom)} – ${shortDate(effectiveTo)}` : 'the last 6 weeks'} {' '} - against the 8 weeks before it - {asOf ? `, treating ${shortDate(asOf)} as the latest date` : ''}. + against{' '} + {baseFrom ? `${shortDate(baseFrom)} – ${shortDate(baseTo)}` : 'the 8 weeks before'} + {effectiveTo ? `, ignoring anything after ${shortDate(effectiveTo)}` : ''}. + {split ? ` A window longer than 12 weeks has no baseline of its own, so its last 6 weeks are compared with the 8 before them.` : ''} )}