Files

192 lines
9.9 KiB
TypeScript
Raw Permalink Normal View History

/**
* Dev check: Session 1 coach system prompt contains course context and teaching-style rules.
* Run: npx tsx --tsconfig tsconfig.json scripts/verify-coach-prompt.ts
*/
import { getSessionByOrder, PROGRAM_SESSION_COUNT } from '../src/data/program/sessions';
import {
buildCoachSystemPrompt,
buildCoachSessionStartCue,
COACH_SESSION_START_CUE
} from '../src/lib/aiCoach/buildCoachSystemPrompt';
const s = getSessionByOrder(1);
if (!s) throw new Error('Session 1 missing');
const s11 = getSessionByOrder(11);
if (!s11) throw new Error('Session 11 missing');
const ctx = {
sessionId: s.id,
order: s.order,
title: s.title,
description: s.description,
estimatedDurationMinutes: s.estimatedDurationMinutes,
objectivesHint: s.description,
blocks: s.blocks,
totalSessions: PROGRAM_SESSION_COUNT,
isFinalSession: s.order >= PROGRAM_SESSION_COUNT,
nextSessionUnlocksAt: null,
};
const prompt = buildCoachSystemPrompt(ctx);
const ctx11 = {
sessionId: s11.id,
order: s11.order,
title: s11.title,
description: s11.description,
estimatedDurationMinutes: s11.estimatedDurationMinutes,
objectivesHint: s11.description,
blocks: s11.blocks,
totalSessions: PROGRAM_SESSION_COUNT,
isFinalSession: true,
nextSessionUnlocksAt: null,
};
const prompt11 = buildCoachSystemPrompt(ctx11);
const startCue11 = buildCoachSessionStartCue(11);
const checks = {
// Existing course context & grounding
title: prompt.includes(s.title),
objective: prompt.includes(s.description),
exercise: prompt.includes('پیش‌آزمون'),
bansGenericHelp: prompt.includes('چه کمکی می‌تونم بکنم؟'),
hasOpeningRules: prompt.includes('SESSION OPENING'),
pretestNote: prompt.includes('NEVER MENTION PRE-TEST IN USER-FACING CHAT'),
groundingSection: prompt.includes('STRICT COURSE GROUNDING'),
assessmentBoundary: prompt.includes('ASSESSMENT BOUNDARY'),
noNewAssessment: prompt.includes('administer another psychological assessment'),
noInventQuestionnaire: prompt.includes('invent questionnaire items'),
forbiddenSymptomExamples: prompt.includes('در هفته گذشته چه میزان استرس'),
noInventRoles: prompt.includes('Do NOT invent role lists'),
noGuessGap: prompt.includes('Do not guess'),
noGenericPsychFill: prompt.includes('general psychological knowledge'),
thinContentRule: prompt.includes('CRITICAL THIN-CONTENT RULE'),
noSubstitutePretest: prompt.includes('Do NOT retake, recreate, simulate, or substitute'),
noRepeatPretestInChat: prompt.includes('Do NOT repeat the pre-test inside Chat'),
silentSkipPretest: prompt.includes('silent skip') || prompt.includes('silent-skip'),
omitPretestWhenSpeaking: prompt.includes('ZERO words about it'),
neverMentionPretestToUser: prompt.includes('NEVER mention «پیش‌آزمون»'),
noPretestNextSectionAnnounce: prompt.includes('Do NOT announce pre-test as the next section'),
noPretestAppDisclaimer: prompt.includes('به صورت جداگانه در اپلیکیشن انجام می‌شود'),
noPretestInOutline: !prompt.includes('SESSION OUTLINE') || !prompt.match(/SESSION OUTLINE[\s\S]*?- پیش‌آزمون/),
pretestStrippedFromIntroText: !prompt.includes('و پیش‌آزمون اجراء می‌شود'),
assessmentResultsRule: prompt.includes('do NOT invent interpretation'),
completionSignal: prompt.includes('SESSION COMPLETION SIGNAL'),
completionMarker: prompt.includes('COACH_SESSION_COMPLETE'),
// Teaching style — educational package introduction
educationalPackageIntro: prompt.includes('introduce the overall educational package'),
packageMultipleSessions: prompt.includes('multiple guided sessions'),
packageConversationLearning: prompt.includes('learning happens through conversation and interaction'),
// Teaching style — tone & language
informalColloquialTone: prompt.includes('informal, colloquial Persian'),
addressLearnerAsTo: prompt.includes('Address the learner with «تو»'),
teenFriendlyLanguage: prompt.includes('teenager'),
allLearnersTeenagers: prompt.includes('ALL learners are teenagers'),
teenAudienceSection: prompt.includes('TEEN AUDIENCE'),
noSpouseQuestion: prompt.includes('با همسر خود یک فعالیت نشاط‌آور'),
teenAdaptFriends: prompt.includes('friends, family, or classmates'),
simpleLanguageGuidance: prompt.includes('explain it simply'),
noChildishTone: prompt.includes('Do NOT be childish'),
// Teaching style — anti-over-questioning
antiOverQuestioning: prompt.includes('NOT an interviewer'),
forbiddenRepeatedQuestions: prompt.includes('نظرت چیست؟'),
noTopicChoice: prompt.includes('Do NOT ask the user to choose the next topic'),
noPermissionToContinue: prompt.includes('Do NOT ask permission to continue'),
// Teaching style — negative-answer handling
negativeAnswerHandling: prompt.includes('NEGATIVE / UNKNOWN ANSWERS'),
noInterrogateFurther: prompt.includes('Do NOT interrogate further'),
unknownAnswerExample: prompt.includes('نمی‌دانم'),
// Teaching style — section-end questions
sectionEndQuestion: prompt.includes('تا اینجا چیزی که گفتم، سؤالی داری؟'),
sectionEndNaturalBoundaries: prompt.includes('natural section boundaries'),
// Session 1 — no previous session
session1NoPreviousSession: prompt.includes('NO previous educational session'),
noReviewPreviousSession: prompt.includes('مرور جلسه قبل'),
// Teaching style — package identity & 11 sessions
iranianIslamicPackage: prompt.includes('بسته آموزشی مثبت‌نگر ایرانی ـ اسلامی'),
programOverviewSection: prompt.includes('PROGRAM OVERVIEW'),
elevenSessionsListed: prompt.includes('1. توجیه و آشناسازی') && prompt.includes('11. مرور و جمع‌بندی مطالب'),
// Teaching style — session outline then teach one by one
sessionOutlineSection: prompt.includes('SESSION OUTLINE'),
listThenTeach: prompt.includes('list these at session start as a short roadmap'),
// Teaching style — no identity repetition
noIdentityRepetition: prompt.includes('NO IDENTITY REPETITION'),
noRepeatNovyaHelp: prompt.includes('اینجام تا کمک کنم'),
// Teaching style — stay on path / other model
stayOnEducationalPath: prompt.includes('STAY ON THE EDUCATIONAL PATH'),
otherModelRedirect: prompt.includes('another model/assistant'),
// Teaching style — package overview only in Session 1
packageOverviewSession1Only: prompt.includes('Session 1 ONLY'),
startCueSession1Package: COACH_SESSION_START_CUE.includes('list the ۱۱ session titles ONCE'),
// Teaching style — message formatting
messageFormatting: prompt.includes('MESSAGE FORMATTING'),
chatgptLayout: prompt.includes('Write like ChatGPT'),
shortParagraphs: prompt.includes('1–2 short sentences per paragraph'),
occasionalEmoji: prompt.includes('EMOJI / STICKER-LIKE EXPRESSIONS'),
emojiHardLimit: prompt.includes('0–1 emoji per message'),
numberedListFormatting: prompt.includes('numbered list') || prompt.includes('numbered ۱'),
boldKeyPhrases: prompt.includes('double asterisks'),
headingOwnLine: prompt.includes('OWN separate line'),
headingNumberedFirstTime: prompt.includes('FIRST time you introduce a section title'),
plainTextHeadings: prompt.includes('NEVER use Markdown # / ## / ###'),
noVisibleHash: prompt.includes('NEVER show # ## ###'),
noVisibleAt: prompt.includes('NEVER show @ mentions'),
standardPersianPunctuation: prompt.includes('STANDARD PERSIAN PUNCTUATION'),
justifyFriendlyParagraphs: prompt.includes('justified') || prompt.includes('Write like ChatGPT'),
neverGenerateImages: prompt.includes('NEVER generate, attach, draw, or request images'),
formattingDoesNotChangeContent: prompt.includes('MUST NOT add, remove, or change educational content'),
formattingDoesNotChangeOrder: prompt.includes('MUST NOT change the teaching order'),
tablesOccasionalVariety: prompt.includes('TABLES (occasional variety)'),
// Teaching style — creative / lived elaboration
creativeElaboration: prompt.includes('CREATIVE ELABORATION'),
perfumeExample: prompt.includes('استفاده از عطر'),
scientificColor: prompt.includes('simple scientific'),
experientialThenQuote: prompt.includes('THEN present the course quote'),
// Session 11 final review (Session 11 prompt only)
session11ThreePartReview: prompt11.includes('THREE-PART GRADUAL REVIEW'),
session11NoDuplicatePhrases: prompt11.includes('NO DUPLICATE PHRASES'),
session11PriorSessionsReference: prompt11.includes('PRIOR SESSIONS REFERENCE'),
session11StartCueThreeParts: startCue11.includes('three parts'),
session11StartCueNoDuplicate: startCue11.includes('NEVER duplicate the session title'),
noRepetitionRule: prompt.includes('NO REPETITION (all sessions)'),
// Session start cue
startCue: COACH_SESSION_START_CUE.includes('[SESSION_START]'),
startCueEducationalPackage: COACH_SESSION_START_CUE.includes('بسته آموزشی مثبت‌نگر ایرانی ـ اسلامی'),
startCueInformalTone: COACH_SESSION_START_CUE.includes('informal colloquial Persian'),
startCueGrounding: COACH_SESSION_START_CUE.includes('Do not invent missing details'),
startCueNoAssessment: COACH_SESSION_START_CUE.includes('or assessments'),
startCueNoTopicChoice: COACH_SESSION_START_CUE.includes('Do not ask the user to choose topics'),
startCueNoOverQuestion: COACH_SESSION_START_CUE.includes('Do not over-question'),
startCueIranianIslamic: COACH_SESSION_START_CUE.includes('بسته آموزشی مثبت‌نگر ایرانی ـ اسلامی'),
startCueNeverPretest: COACH_SESSION_START_CUE.includes('NEVER mention پیش‌آزمون'),
startCueNoSpouse: COACH_SESSION_START_CUE.includes('NEVER ask about همسر'),
chars: prompt.length
};
console.log(JSON.stringify(checks, null, 2));
const failed = Object.entries(checks).filter(([k, v]) => k !== 'chars' && v !== true);
if (failed.length) {
console.error('Failed checks:', failed);
process.exit(1);
}
console.log('Session 1 coach prompt OK');
console.log('Session 11 coach prompt OK');