|
|
|
|
@@ -119,8 +119,17 @@ const QSCORE_TASK_SERVICE_REPLACEMENTS: Record<CuratorTaskType, CuratorServiceId
|
|
|
|
|
recovery: "roleplay-service",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const ACTIVE_CURATOR_SERVICES = new Set<CuratorServiceId>([
|
|
|
|
|
"interview-service",
|
|
|
|
|
"resume-service",
|
|
|
|
|
"roleplay-service",
|
|
|
|
|
"courses-service",
|
|
|
|
|
"matchmaking-service",
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
function curatorAssignableServiceId(serviceId: CuratorServiceId, taskType: CuratorTaskType): CuratorServiceId {
|
|
|
|
|
if (serviceId === "qscore-service") return QSCORE_TASK_SERVICE_REPLACEMENTS[taskType];
|
|
|
|
|
if (serviceId === "cover-letter-service") return "resume-service";
|
|
|
|
|
if (serviceId === "social-branding-service") return taskType === "practice" ? "roleplay-service" : "resume-service";
|
|
|
|
|
if (serviceId === "assessment-service") return "matchmaking-service";
|
|
|
|
|
return serviceId;
|
|
|
|
|
@@ -897,6 +906,73 @@ function seed(
|
|
|
|
|
return { taskType, serviceId: assignedServiceId, title: copy.title, subtitle: copy.subtitle, effort, qxImpact, cta: copy.cta, signals: copy.signals };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function curatorTaskCopyForService(task: TaskSeed, serviceId: CuratorServiceId): TaskSeed {
|
|
|
|
|
if (task.serviceId === serviceId && ACTIVE_CURATOR_SERVICES.has(serviceId)) return task;
|
|
|
|
|
|
|
|
|
|
if (serviceId === "resume-service") {
|
|
|
|
|
return {
|
|
|
|
|
...task,
|
|
|
|
|
serviceId,
|
|
|
|
|
title: task.title.replace(/social proof|social profile|public credibility|visibility|cover letter/gi, "resume proof"),
|
|
|
|
|
subtitle: task.subtitle.replace(/social proof|social profile|public credibility|visibility|public positioning|cover letter/gi, "resume proof"),
|
|
|
|
|
cta: "Open resume workspace",
|
|
|
|
|
signals: task.signals
|
|
|
|
|
.map((signal) => signal.replace(/public proof|social proof|social|public|visibility|cover letter/gi, "resume proof"))
|
|
|
|
|
.map((signal) => signal.replace(/\bresume proof\s+proof\b/gi, "resume proof")),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (serviceId === "matchmaking-service") {
|
|
|
|
|
return {
|
|
|
|
|
...task,
|
|
|
|
|
serviceId,
|
|
|
|
|
title: task.title
|
|
|
|
|
.replace(/Q Score|QScore|assessment|pathways/gi, "job matches")
|
|
|
|
|
.replace(/social proof|social profile|public credibility|visibility/gi, "job match"),
|
|
|
|
|
subtitle: task.subtitle
|
|
|
|
|
.replace(/Q Score|QScore|assessment service|assessment|pathways/gi, "job matching")
|
|
|
|
|
.replace(/social proof|social profile|public credibility|visibility|public positioning/gi, "job matching"),
|
|
|
|
|
cta: "View matches",
|
|
|
|
|
signals: task.signals.map((signal) => signal.replace(/q\s?score|assessment|social|public|visibility/gi, "job matching")),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (serviceId === "roleplay-service") {
|
|
|
|
|
return {
|
|
|
|
|
...task,
|
|
|
|
|
serviceId,
|
|
|
|
|
title: task.title.replace(/social proof|social profile|public credibility|visibility|Q Score|QScore/gi, "roleplay practice"),
|
|
|
|
|
subtitle: task.subtitle.replace(/social proof|social profile|public credibility|visibility|public positioning|Q Score|QScore/gi, "roleplay practice"),
|
|
|
|
|
cta: "Open roleplay preview",
|
|
|
|
|
signals: task.signals.map((signal) => signal.replace(/social|public|visibility|q\s?score/gi, "roleplay practice")),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (serviceId === "interview-service") {
|
|
|
|
|
return {
|
|
|
|
|
...task,
|
|
|
|
|
serviceId,
|
|
|
|
|
title: task.title.replace(/Q Score|QScore|assessment/gi, "interview practice"),
|
|
|
|
|
subtitle: task.subtitle.replace(/Q Score|QScore|assessment/gi, "interview practice"),
|
|
|
|
|
cta: "Open interview preview",
|
|
|
|
|
signals: task.signals.map((signal) => signal.replace(/q\s?score|assessment/gi, "interview practice")),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...task,
|
|
|
|
|
serviceId,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function normalizeActiveCuratorTaskSeed(task: TaskSeed): TaskSeed {
|
|
|
|
|
const assignedServiceId = curatorAssignableServiceId(task.serviceId, task.taskType);
|
|
|
|
|
if (ACTIVE_CURATOR_SERVICES.has(assignedServiceId)) {
|
|
|
|
|
return curatorTaskCopyForService(task, assignedServiceId);
|
|
|
|
|
}
|
|
|
|
|
return curatorTaskCopyForService(task, QSCORE_TASK_SERVICE_REPLACEMENTS[task.taskType]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function todayIso(date = new Date()) {
|
|
|
|
|
return date.toISOString().slice(0, 10);
|
|
|
|
|
}
|
|
|
|
|
@@ -1036,10 +1112,14 @@ function latestImprovementSignal(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function normalizeEventBackedTask(task: PlannedTask, planDay: PlanDaySeed, recentRows: Awaited<ReturnType<typeof loadRecentContextRows>>): PlannedTask {
|
|
|
|
|
const normalizedTask = normalizeActiveCuratorTaskSeed(task);
|
|
|
|
|
if (normalizedTask.serviceId !== task.serviceId) {
|
|
|
|
|
return makePlannedTask(normalizedTask, planDay.weekTheme, planDay.weekSummary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hasDirectServiceCompletion(task.serviceId)) return task;
|
|
|
|
|
|
|
|
|
|
if (task.taskType === "proof") {
|
|
|
|
|
if (task.serviceId === "social-branding-service") return task;
|
|
|
|
|
return makePlannedTask(
|
|
|
|
|
seed(
|
|
|
|
|
"proof",
|
|
|
|
|
@@ -1430,12 +1510,12 @@ function recoveryTaskSeed(previousDayIndex: number, openedIncompleteCount: numbe
|
|
|
|
|
: `${skippedCount} planned task${skippedCount === 1 ? "" : "s"} had no opened or completion events`;
|
|
|
|
|
return seed(
|
|
|
|
|
"recovery",
|
|
|
|
|
"qscore-service",
|
|
|
|
|
"roleplay-service",
|
|
|
|
|
`Recover Day ${previousDayIndex} momentum`,
|
|
|
|
|
`Yesterday's event trail shows ${reason}. Review the blocker, pick one constructive adjustment, and keep the streak aligned.`,
|
|
|
|
|
"5 min",
|
|
|
|
|
"+5 projected",
|
|
|
|
|
"Review Q Score",
|
|
|
|
|
"Open roleplay preview",
|
|
|
|
|
["recovery", "alignment", "event trail"],
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
@@ -1571,6 +1651,7 @@ function buildTask(
|
|
|
|
|
focusDate: string,
|
|
|
|
|
targetRole?: string,
|
|
|
|
|
): CuratorTask {
|
|
|
|
|
seedTask = normalizeActiveCuratorTaskSeed(seedTask);
|
|
|
|
|
const dayOfWeek = dayIndexInWeek(sprintStartDate, dayIndex);
|
|
|
|
|
const id = taskIdFor(sprintStartDate, dayIndex, seedTask.taskType);
|
|
|
|
|
const missionInstanceId = sprintIdFor(sprintStartDate);
|
|
|
|
|
|