fix(curator): preserve active sprint on reads
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
decideCuratorSprintReconciliation,
|
||||
resolveCuratorSprintAccess,
|
||||
shouldReconcileCuratorSprint,
|
||||
shouldRebaseCuratorSprintForOnboardingContext,
|
||||
} from "../src/v1/curator/curator-store.js";
|
||||
import { templateSetFor, trialDaysFor } from "../src/v1/curator/task-registry.js";
|
||||
|
||||
@@ -51,6 +52,26 @@ const startDate = "2026-07-13";
|
||||
const studentFingerprint = curatorSprintPlanFingerprint({ startDate, variantId: "student_recent_grad", durationDays: 2, access: "trial" });
|
||||
const experiencedFingerprint = curatorSprintPlanFingerprint({ startDate, variantId: "experienced_professional", durationDays: 2, access: "trial" });
|
||||
const experiencedPlan = curatorSprintTaskPlan({ startDate, variantId: "experienced_professional", durationDays: 2, access: "trial" });
|
||||
assert.equal(
|
||||
shouldRebaseCuratorSprintForOnboardingContext({
|
||||
existingStartDate: "2026-07-14",
|
||||
focusDate: "2026-07-15",
|
||||
onboardingContextProvided: true,
|
||||
existingCompatible: true,
|
||||
}),
|
||||
false,
|
||||
"a normal sprint read with onboarding context must preserve the active sprint across days",
|
||||
);
|
||||
assert.equal(
|
||||
shouldRebaseCuratorSprintForOnboardingContext({
|
||||
existingStartDate: "2026-07-14",
|
||||
focusDate: "2026-07-15",
|
||||
onboardingContextProvided: true,
|
||||
existingCompatible: false,
|
||||
}),
|
||||
true,
|
||||
"changed onboarding compatibility may replace the existing sprint without resetting its calendar identity",
|
||||
);
|
||||
assert.notEqual(studentFingerprint, experiencedFingerprint, "ICP changes must change the compatibility fingerprint");
|
||||
assert.equal(shouldReconcileCuratorSprint(
|
||||
{ access: "trial", durationDays: 2, variantId: "student_recent_grad", planFingerprint: studentFingerprint },
|
||||
|
||||
@@ -141,6 +141,20 @@ export function decideCuratorSprintReconciliation(
|
||||
};
|
||||
}
|
||||
|
||||
export function shouldRebaseCuratorSprintForOnboardingContext(input: {
|
||||
existingStartDate?: string;
|
||||
focusDate: string;
|
||||
onboardingContextProvided: boolean;
|
||||
existingCompatible: boolean;
|
||||
}) {
|
||||
return Boolean(
|
||||
input.onboardingContextProvided
|
||||
&& input.existingStartDate
|
||||
&& input.existingStartDate !== input.focusDate
|
||||
&& !input.existingCompatible,
|
||||
);
|
||||
}
|
||||
|
||||
function accessChoiceFromContext(context: Record<string, unknown> | undefined): "trial" | "full" | undefined {
|
||||
const preferences = context && context.preferences && typeof context.preferences === "object" && !Array.isArray(context.preferences)
|
||||
? context.preferences as Record<string, unknown>
|
||||
@@ -751,7 +765,16 @@ async function loadSprintState(
|
||||
const existingDuration = latestPayload?.durationDays === 7 ? 7 : latestPayload?.durationDays === 2 ? 2 : undefined;
|
||||
const existingAccess = latestPayload?.access === "full" ? "full" : latestPayload?.access === "trial" ? "trial" : undefined;
|
||||
const existingFingerprint = typeof latestPayload?.planFingerprint === "string" ? latestPayload.planFingerprint : undefined;
|
||||
const rebaseExistingForCompletion = Boolean(onboardingContextOverride && existingStartDate && existingStartDate !== todayDate);
|
||||
const existingCompatible = Boolean(
|
||||
existingStartDate && existingVersion === CURATOR_PLAN_VERSION && existingVariant
|
||||
&& existingDuration === desired.durationDays && existingAccess === desired.access,
|
||||
);
|
||||
const rebaseExistingForCompletion = shouldRebaseCuratorSprintForOnboardingContext({
|
||||
existingStartDate,
|
||||
focusDate: todayDate,
|
||||
onboardingContextProvided: Boolean(onboardingContextOverride),
|
||||
existingCompatible,
|
||||
});
|
||||
const reuseDecision = existingStartDate && existingVersion && existingDuration && existingAccess
|
||||
? resolveAgedTrialReuse({
|
||||
existing: { startDate: existingStartDate, version: existingVersion, durationDays: existingDuration, access: existingAccess },
|
||||
|
||||
Reference in New Issue
Block a user