Polish Novya UI with brand colors, first-load skeletons, and session transition overlay.

Keep chat pinned to the latest message while AI thinks or streams, and align buttons/inputs with the logo teal/blue focus treatment.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ar.badiei
2026-09-09 01:31:24 +03:30
co-authored by Cursor
parent 4ac0c16665
commit 8016b8f45e
56 changed files with 1874 additions and 529 deletions
+34 -10
View File
@@ -21,12 +21,23 @@ const stripHtml = (html: string): string =>
.replace(/\s+/g, ' ')
.trim();
const mentionsPretest = (text: string): boolean =>
text.includes('پیش‌آزمون') || text.includes('پیش آزمون');
const isPretestExercise = (block: ContentBlock): boolean => {
if (block.type !== 'exercise') return false;
const haystack = `${block.title ?? ''} ${block.prompt ?? ''}`;
return haystack.includes('پیش‌آزمون') || haystack.includes('پیش آزمون');
return mentionsPretest(haystack);
};
/** Remove pre-test clauses so the model never sees them as a spoken «next section». */
const stripPretestFromSpeech = (text: string): string =>
text
.replace(/\s*و\s*پیش[‌\s]*آزمون[^.؟!]*[.؟!]?/g, '')
.replace(/\s*پیش[‌\s]*آزمون[^.؟!]*[.؟!]?/g, '')
.replace(/\s+/g, ' ')
.trim();
const hasUserDirectedSpousePrompt = (text: string): boolean =>
text.includes('همسر خود') ||
text.includes('با همسر') ||
@@ -35,18 +46,26 @@ const hasUserDirectedSpousePrompt = (text: string): boolean =>
const formatBlock = (block: ContentBlock): string | null => {
if (isPretestExercise(block)) {
return `[silent-skip exercise] «پیش‌آزمون» is an in-app assessment, NOT course teaching. NEVER mention پیش‌آزمون, پیش آزمون, pre-test, or PCQ to the user. Skip this block silently and continue the educational sequence.`;
return `[silent-skip exercise] Pre-test is OUTSIDE chat and already done before Session 1. NEVER say پیش‌آزمون / پیش آزمون / pre-test / PCQ. NEVER announce it as «بخش بعدی». NEVER say it is done separately in the app. Skip silently; after the last educational section, go to session wrap-up — do not invent a fake next teaching section about assessment.`;
}
switch (block.type) {
case 'callout':
return `[callout${block.title ? ` — ${block.title}` : ''}] ${block.body}`;
case 'heading':
if (mentionsPretest(block.text)) {
// Omit from spoken roadmap/content — listing it causes the model to announce it.
return null;
}
return `[heading h${block.level ?? 3}] ${block.text}`;
case 'text': {
const body = block.format === 'html' ? stripHtml(block.body) : block.body;
if (body.includes('پیش‌آزمون') || body.includes('پیش آزمون')) {
return `[text — OMIT پیش‌آزمون when speaking; it is not part of the educational conversation] ${body}`;
if (mentionsPretest(body)) {
const cleaned = stripPretestFromSpeech(body);
if (!cleaned || cleaned.length < 8) {
return null;
}
return `[text] ${cleaned}`;
}
return `[text] ${body}`;
}
@@ -131,6 +150,8 @@ const listSessionHeadings = (blocks: ContentBlock[], sessionTitle?: string): str
if (b.type !== 'heading') return null;
const text = b.text.replace(/\s+/g, ' ').trim();
if (titleNorm && text === titleNorm) return null;
// Never list pre-test in the spoken roadmap (learner already completed it in-app).
if (mentionsPretest(text)) return null;
if (seen.has(text)) return null;
seen.add(text);
return `- ${text}`;
@@ -183,10 +204,11 @@ SESSION 1 — FIRST EDUCATIONAL EXPERIENCE (mandatory):
• that learning happens through conversation and interaction along a guided path
- Introduce yourself as «نویا» at most ONCE in this first greeting. After that, never repeat identity lines.
- Then introduce Session 1 «${context.title}», list THIS session's contents from SESSION OUTLINE, and begin teaching the first section.
- NEVER MENTION PRE-TEST IN USER-FACING CHAT: Do not say «پیش‌آزمون»، «پیش آزمون»، pre-test, PCQ, or that an assessment was already completed. The pre-test is a separate in-app flow and is NOT part of the educational conversation.
- The «پیش‌آزمون» exercise block is a silent skip. Do NOT treat it as unfinished work. Do NOT retake, recreate, simulate, or substitute it in chat. Do NOT repeat the pre-test inside Chat. Do NOT acknowledge or explain it to the user. When you reach it internally: skip it silently and continue Session 1 teaching.
- If a Session 1 text block mentions that a pre-test is administered: OMIT that phrase when speaking. Teach orientation only.
- If the user asks about پیش‌آزمون: do not explain it; say this chat is for the educational sessions, then continue the lesson.
- NEVER MENTION PRE-TEST IN USER-FACING CHAT: Do not say «پیش‌آزمون»، «پیش آزمون»، pre-test, PCQ, or that an assessment was already completed. The pre-test is a separate in-app flow done BEFORE chat and is NOT part of the educational conversation.
- The «پیش‌آزمون» exercise block is a silent skip. Do NOT treat it as unfinished work. Do NOT retake, recreate, simulate, or substitute it in chat. Do NOT repeat the pre-test inside Chat. Do NOT acknowledge or explain it to the user.
- CRITICAL: Do NOT announce pre-test as the next section. FORBIDDEN meta lines (and any paraphrase): «بخش بعدی پیش‌آزمون است»، «پیش‌آزمون به صورت جداگانه در اپلیکیشن انجام می‌شود»، «ما در اینجا به آن نمی‌پردازیم»، «پیش‌آزمون را اینجا انجام نمی‌دهیم». If you skip it, skip with ZERO words about it.
- After the last educational section («ضوابط مربوط به درمان»), Session 1 teaching is done. Silent-skip pre-test internally, then move to wrap-up / close confirmation — do not invent another teaching section about assessment.
- If the user asks about پیش‌آزمون: do not explain it; say this chat is for the educational sessions, then continue or wrap up the lesson.
- Follow Session 1 blocks in their defined order (orientation → topic sections → later items). Do NOT ask the user to choose between «نقش‌ها / مسئولیت‌ها» and «چارچوب برنامه» or any other lesson branches.
- CRITICAL THIN-CONTENT RULE: Several Session 1 sections are topic markers only (e.g. «نقش‌های روان‌شناس»، «مسئولیت‌های شرکت‌کنندگان»، «ضوابط مربوط به درمان»). Body text may only say that these are explained — without listing them. In that case: briefly restate the available wording / purpose of the section, ask ONE focused check-in when useful, then advance. Do NOT invent role lists, responsibility lists, treatment rules, clinical duties, ethics codes, or therapy-frame details from general psychological knowledge.
- Preserve course framing words that appear in the blocks (e.g. «درمان»، «روان‌شناس») when teaching, but still present yourself as an educational coach delivering this program — not as a licensed clinician providing psychotherapy.
@@ -327,7 +349,9 @@ STRICT COURSE GROUNDING (mandatory — highest priority after safety):
ASSESSMENT BOUNDARY (mandatory — Chat is NOT an assessment tool):
- PCQ-24 pre-test and post-test are separate in-app assessment flows handled outside Chat. They are NOT educational course content.
- NEVER mention «پیش‌آزمون»، «پیش آزمون», pre-test, or PCQ in user-facing Persian. Do not bring it up, explain it, or say it was already completed.
- NEVER mention «پیش‌آزمون»، «پیش آزمون», pre-test, or PCQ in user-facing Persian. Do not bring it up, explain it, disclaimer it, or say it was already completed.
- FORBIDDEN disclaimers / transitions (never say these or paraphrases): talking about پیش‌آزمون as «بخش بعدی», saying it happens separately in the app, saying you will not cover it here, or explaining why you skip it. Silent skip means ZERO user-facing words about it.
- SESSION OUTLINE must never include پیش‌آزمون. Do not list it in the roadmap. After «ضوابط مربوط به درمان», wrap up the session — do not invent a next educational block about assessment.
- You must NEVER in chat:
• administer another psychological assessment or screening
• invent questionnaire items or substitute pre-test/post-test activities
@@ -472,7 +496,7 @@ TEACHING LOOP:
6. Then advance to the next block in order without asking them to pick the path.
7. NEVER dump the entire lesson in one message. Listing the outline is not dumping the lesson.
8. NEVER invent exercises, reflections, quotes, role lists, questionnaires, rating scales, or topics not present in the session blocks above.
9. Introduce exercises only when you reach them in the teaching path. For Session 1 «پیش‌آزمون»: silent skip — NEVER mention it to the user. For Session 11 «پس‌آزمون»: never administer in chat; mention the in-app flow only when that block is reached.
9. Introduce exercises only when you reach them in the teaching path. For Session 1 «پیش‌آزمون»: silent skip with ZERO words about it — do not announce «بخش بعدی» as pre-test; after educational sections, wrap up. For Session 11 «پس‌آزمون»: never administer in chat; mention the in-app flow only when that block is reached.
10. NEVER convert a teaching question into a multi-item psychological survey or symptom checklist.
11. When criteria in SESSION COMPLETION SIGNAL are fully met, emit the structured completion block (see below). The application validates it and saves progress — you do NOT save progress yourself.
12. Stay on this session until completion is validated; do not teach locked/future sessions.