fix(rectification): keep hour-window tail clusters and lock the search window (BUG-623, BUG-624, BUG-625)
Independent Staging Quality Gate / validate (push) Successful in 17m15s
Independent Staging Quality Gate / publish (push) Successful in 2m15s

Hour windows no longer drop later signature clusters. Credible range uses cluster coverage, and a mid-session spoken birth window gets a fixed reply without calling the model.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-09 20:45:11 +08:00
co-authored by Cursor
parent a31a5e2426
commit 6008c07c81
41 changed files with 1164 additions and 44 deletions
@@ -2,7 +2,7 @@ import { applyProbeOutcome, outcomeByMinuteForAnswer } from "./apply-probe-outco
import type { TransitionSignLookup } from "./sign-from-transitions.ts";
import { clusterRangeFor, clusterEquivalentCandidates } from "./cluster-candidates.ts";
import { evaluateConvergence, holdoutStillRanksFirst, rankActive } from "./convergence-evaluator.ts";
import { unionStillValidRange } from "./credible-range.ts";
import { rangeFromTimes, unionStillValidRange } from "./credible-range.ts";
import { entropyFromScores, normalizeScores } from "./entropy.ts";
import { selectHighestGainProbe } from "./select-probe.ts";
import { holdoutDomainYears, holdoutEventIds, stickyHoldoutEvents } from "./split-holdout.ts";
@@ -22,8 +22,16 @@ export type EngineCandidateInput = Readonly<{
id: string;
time: string;
relative_support: number;
cluster_times?: readonly string[];
cluster_start?: string;
cluster_end?: string;
}>;
function engineClusterRange(item: EngineCandidateInput): readonly [string, string] | null {
if (item.cluster_start && item.cluster_end) return [item.cluster_start, item.cluster_end];
return item.cluster_times?.length ? rangeFromTimes(item.cluster_times) : null;
}
export type EngineEventInput = Readonly<{
id: string;
domain: string;
@@ -126,7 +134,7 @@ export function buildInferenceState(input: {
return {
id: item.id,
time: item.time,
cluster_range: clusterRangeFor(clusters, item.id, item.time),
cluster_range: engineClusterRange(item) ?? clusterRangeFor(clusters, item.id, item.time),
prior_score: trainingPrior[item.id] ?? 0,
posterior_score: scores[item.id] ?? 0,
probability: eliminated.has(item.id) ? 0 : probabilities[item.id] ?? 0,
@@ -254,6 +262,8 @@ export function replayInferenceState(
id: item.id,
time: item.time,
relative_support: item.prior_score,
cluster_start: item.cluster_range[0],
cluster_end: item.cluster_range[1],
})),
events: state.events,
probes: state.probes,
@@ -348,6 +358,8 @@ function rebuildWithAnswers(state: InferenceState, incoming: readonly ProbeAnswe
id: item.id,
time: item.time,
relative_support: item.prior_score,
cluster_start: item.cluster_range[0],
cluster_end: item.cluster_range[1],
})),
events: state.events,
probes: state.probes,