Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

Commit 0a8a30e

Browse files
authored
feat(scouts): widen runs window from 24h to 3 days (#2659)
1 parent ad099ba commit 0a8a30e

5 files changed

Lines changed: 40 additions & 17 deletions

File tree

‎packages/core/src/scouts/scoutRunsWindow.test.ts‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
fetchScoutRunsWindow,
55
SCOUT_RUNS_WINDOW_HOURS,
66
type ScoutRunsClient,
7+
type ScoutRunsWindow,
78
scoutRunsWindowLabel,
89
} from "./scoutRunsWindow";
910

@@ -115,11 +116,23 @@ describe("fetchScoutRunsWindow", () => {
115116
});
116117

117118
describe("scoutRunsWindowLabel", () => {
118-
it("names the window and flags truncation", () => {
119-
expect(scoutRunsWindowLabel({ runs: [], complete: true })).toBe("last 24h");
120-
expect(scoutRunsWindowLabel({ runs: [], complete: false })).toBe(
121-
"last 24h · truncated",
122-
);
123-
expect(scoutRunsWindowLabel(undefined)).toBe("last 24h");
119+
it.each([
120+
{
121+
name: "complete window",
122+
window: { runs: [], complete: true } as ScoutRunsWindow,
123+
expected: "last 3 days",
124+
},
125+
{
126+
name: "truncated window",
127+
window: { runs: [], complete: false } as ScoutRunsWindow,
128+
expected: "last 3 days · truncated",
129+
},
130+
{
131+
name: "undefined window",
132+
window: undefined,
133+
expected: "last 3 days",
134+
},
135+
])("names the $name", ({ window, expected }) => {
136+
expect(scoutRunsWindowLabel(window)).toBe(expected);
124137
});
125138
});

‎packages/core/src/scouts/scoutRunsWindow.ts‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,17 @@ import type {
1010
* pattern). A fixed window gives users a stable frame for every number;
1111
* "the most recent 100 runs" does not.
1212
*/
13-
export const SCOUT_RUNS_WINDOW_HOURS = 24;
13+
export const SCOUT_RUNS_WINDOW_HOURS = 72;
14+
15+
/**
16+
* Human-friendly span the window covers, e.g. "3 days" or "24h". Reads as days
17+
* when the window is a whole number of days, otherwise falls back to hours.
18+
*/
19+
export const SCOUT_RUNS_WINDOW_SPAN = (() => {
20+
if (SCOUT_RUNS_WINDOW_HOURS % 24 !== 0) return `${SCOUT_RUNS_WINDOW_HOURS}h`;
21+
const days = SCOUT_RUNS_WINDOW_HOURS / 24;
22+
return `${days} day${days === 1 ? "" : "s"}`;
23+
})();
1424

1525
const PAGE_LIMIT = 100;
1626
const MAX_PAGES = 10;
@@ -29,9 +39,9 @@ export interface ScoutRunsWindow {
2939
complete: boolean;
3040
}
3141

32-
/** Label for stats derived from a window, e.g. "last 24h". */
42+
/** Label for stats derived from a window, e.g. "last 3 days". */
3343
export function scoutRunsWindowLabel(window?: ScoutRunsWindow): string {
34-
const base = `last ${SCOUT_RUNS_WINDOW_HOURS}h`;
44+
const base = `last ${SCOUT_RUNS_WINDOW_SPAN}`;
3545
return window && !window.complete ? `${base} · truncated` : base;
3646
}
3747

‎packages/ui/src/features/scouts/components/ScoutDetailView.tsx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
scoutSkillNameFromSlug,
1818
} from "@posthog/core/scouts/scoutPresentation";
1919
import {
20-
SCOUT_RUNS_WINDOW_HOURS,
20+
SCOUT_RUNS_WINDOW_SPAN,
2121
scoutRunsWindowLabel,
2222
} from "@posthog/core/scouts/scoutRunsWindow";
2323
import { ANALYTICS_EVENTS } from "@posthog/shared";
@@ -85,7 +85,7 @@ export function ScoutDetailView({
8585

8686
const config = configs?.find((entry) => entry.skill_name === skillName);
8787
// The runs endpoint has no skill_name filter yet (scouts-ui api gap 1), so
88-
// select this scout's runs from the 24-hour fleet window client-side.
88+
// select this scout's runs from the fleet window client-side.
8989
const scoutRuns = useMemo(
9090
() =>
9191
(runsWindow?.runs ?? []).filter((run) => run.skill_name === skillName),
@@ -232,7 +232,7 @@ export function ScoutDetailView({
232232
{scoutRuns.length > 0
233233
? `No runs match this filter in the ${scoutRunsWindowLabel(runsWindow)}.`
234234
: runsWindow && !runsWindow.complete
235-
? `No runs fetched in the last ${SCOUT_RUNS_WINDOW_HOURS} hours – the fleet window was truncated before it could cover this scout, so runs may exist beyond what was fetched.`
235+
? `No runs fetched in the last ${SCOUT_RUNS_WINDOW_SPAN} – the fleet window was truncated before it could cover this scout, so runs may exist beyond what was fetched.`
236236
: `No runs in the ${scoutRunsWindowLabel(runsWindow)}.`}
237237
</Text>
238238
) : (
@@ -245,7 +245,7 @@ export function ScoutDetailView({
245245

246246
<Text className="text-[12px] text-gray-10">
247247
Showing this scout&apos;s runs from the last{" "}
248-
{SCOUT_RUNS_WINDOW_HOURS} hours.
248+
{SCOUT_RUNS_WINDOW_SPAN}.
249249
</Text>
250250
</Flex>
251251
</Flex>

‎packages/ui/src/features/scouts/components/ScoutsFleetSection.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
SCOUT_RECENT_SIGNALS_PROMPT,
1919
} from "@posthog/core/scouts/scoutPrompts";
2020
import {
21-
SCOUT_RUNS_WINDOW_HOURS,
21+
SCOUT_RUNS_WINDOW_SPAN,
2222
scoutRunsWindowLabel,
2323
} from "@posthog/core/scouts/scoutRunsWindow";
2424
import type { ScoutChatType } from "@posthog/shared";
@@ -241,8 +241,8 @@ function ScoutsFleetList({ configs }: { configs: ScoutConfig[] }) {
241241

242242
<Flex direction="column" gap="1">
243243
<Text className="text-[12px] text-gray-10">
244-
Run counts and emitted totals cover the last {SCOUT_RUNS_WINDOW_HOURS}{" "}
245-
hours of fleet runs. New scouts are created as{" "}
244+
Run counts and emitted totals cover the last {SCOUT_RUNS_WINDOW_SPAN}{" "}
245+
of fleet runs. New scouts are created as{" "}
246246
<span className="font-mono text-[11px]">signals-scout-*</span> skills
247247
in your PostHog project.
248248
</Text>

‎packages/ui/src/features/scouts/hooks/useScoutRuns.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useAuthStateValue } from "../../auth/store";
77
import { scoutQueryKeys } from "./scoutQueryKeys";
88

99
/**
10-
* Fleet-wide scout runs from the last 24 hours (newest first), assembled in
10+
* Fleet-wide scout runs from the recent window (newest first), assembled in
1111
* core by walking the backend's 100-row pages. The backend has no per-scout
1212
* filter yet (scouts-ui api gap 1), so per-scout views filter this window
1313
* client-side. `complete` is false if pagination had to stop early.

0 commit comments

Comments
 (0)