# سند ۳۰ — اسپرینت محتوای موج ۲ (واژه‌ها و داستان‌ها)

**نسخه:** 1.11.0 · **تاریخ:** ۲۰۲۶-۰۹-۲۶ · **مرجع:** docs/29 §۲.۲ · **ممیزی مبنا:** docs/27 §۵

## ۱. هدف و نتیجه

| سنجه | قبل | بعد | پذیرش ۲۹ |
|---|---|---|---|
| واژه‌ها (۵ زبان) | ۳۰۹ | **۷۱۹** (+۴۱۰) | ~۷۰۰ ✓ |
| داستان‌ها | ۳۴ | **۷۵** (+۴۱) | — |
| پوشش داستانی حروف | ناقص | **۱۰۰٪** (هر حرف هر پک ≥۱ داستان کانونی) | ✓ |
| حروف با <۵ واژه‌ی شروع‌شونده | فارسی ۱۹/۳۲ | **۰** (با ۶ استثنای مستند) | ✓ |

هر زبان: fa ۱۷۷ واژه/۱۴ داستان · en ۱۳۶/۱۴ · nl ۱۲۵/۱۵ · tr ۱۴۱/۱۶ · ar ۱۴۰/۱۶.

## ۲. ابزار (تکرارپذیر و امن)

- **`scripts/content-data.mjs`** — منبع یگانه‌ی محتوای جدید: WORDS (۵ زبان) + STORIES (۴۱ داستان موج ۲).
- **`scripts/content-sprint.mjs`** — مولد/اعتبارسنج: واژه‌ها با `parseWordText` تجزیه و با قواعد `PackLoader.validate`/`Stories.validate` تأیید می‌شوند؛ آستانه‌ی «≥۵ واژه‌ی شروع‌شونده» با فهرست استثنا چک می‌شود؛ گارد پوشش داستانی ۱۰۰٪؛ خروجی گزارش `.tmp-content-report.json`. **ایدمپوتنت است** (متن تکراری رد، داستان تکراری skip، version فقط یک‌بار bump) و در حالت `--dry` هیچ‌چیز نمی‌نویسد؛ در خطای اعتبارسنجی **هیچ فایلی بازنویسی نمی‌شود**.
- id واژه‌ها یکتا و آوانگاری‌شده (fa/ar با TRANSLIT، بقیه latinId) · difficulty طولی: ≤۳→۱ · ۴→۲ · ≥۵→۳.

## ۳. قواعد داده که این اسپرینت تثبیت کرد

- **طول واژه/توکن داستان ≤۸ حرف** — سقف `parseWordText` (hamburger/jellyfish/xylophone و توکن‌های بلندِ ترکی رد شدند و جایگزین شدند).
- **ء مستقل در پک عربی مجاز نیست** (نویسه‌ی ناشناخته) — دَواء/حمراء/الغناء حذف/جایگزین شدند.
- نرمال‌سازی یکتایی متن: حذف حرکت‌گذاری [\u064B-\u065F\u0670\u0640] · ي→ی · ك→ک · [أإآ]→ا · lowercase.
- قواعد validate پاس‌شده: ارجاع حروف معتبر · id یکتا · requiredMastery ۱..۴ · ۲..۶ جمله با توکن‌های تجزیه‌پذیر · ۲..۴ گزینه‌ی سؤال + پاسخ معتبر.

## ۴. استثناهای آستانه (مستند و در تست‌ها قفل شده)

| استثنا | تعداد | دلیل |
|---|---|---|
| en X | ۱ (x-ray) | هیچ واژه‌ی انگلیسی کودکانه با X آغاز نمی‌شود |
| nl X | ۱ (xylofoon) | مانند بالا |
| nl Q | ۳ | واژه‌ی هلندی با Q بسیار کمیاب است |
| nl Y | ۴ | کم‌بود واژه‌های آغازشونده با Y (یای هلندی) |
| tr Ğ | ۰ | **هیچ واژه‌ی ترکی با ğ آغاز نمی‌شود** (تنها در میان‌واژه) |

کم‌واژه‌ترین حرف هر پک: fa ۵ · en ۱(X) · nl ۱(X) · tr ۰(Ğ) · ar ۵.

## ۵. بازبینی انسانی الزامی (ممیزی ۲۷ §۶/۳)

**۴۰ واژه دارای پرچم ⚑ بازبینی** (واژه‌های تصویرپذیری/آشنایی‌شان برای ۴-۶ سال قطعی نیست — عمدتاً حروف نادر: fa ث/ذ/ژ/ظ/ض/و · en Q/X · nl I/Q/U/X · tr Ğ/U/İ/ı):

فهرست کامل در ضمیمه‌ی [`30-annex-content-report.json`](30-annex-content-report.json) (کلید `flagged` — اسنپ‌شات ثابت این اسپرینت؛ بازتولید زنده: `node scripts/content-sprint.mjs --dry`) — نمونه: fa ثروت/ثمر/ثریا/ذوق/ژست/ژتون/ظریف/وانت · en question/quilt/x-ray · nl iglo/inktvis/uil/uno · tr ıhlamur/umut/uçak.

**وضعیت ۱.13.0 — حل‌شده ✅:** بازبینی به نیابت کاربر انجام شد (جدول تصمیم در docs/33 §۶-۷). نتیجه: **۳۹ واژه تأیید** · تنها جایگزینی `umut` (انتزاعی) → `uçurtma` 🪁 (بادبادک، d3، ۷ حرف، id `tr_ucurtma`). فهرست تأییدها در `REVIEWED_WORDS` اسکریپت content-sprint ثبت شد تا پرچم‌ها **۰** شوند و واژه‌ی جدید هم‌خانواده‌ی حروف نادر در آینده به‌صورت خودکار پرچم بخورد. جمع کل: **۷۱۹ واژه** (fa 177 · en 136 · nl 125 · tr 141 · ar 140) · داستان‌ها از umut استفاده نمی‌کردند (جایگزینی امن) · packs **34/34** · story **19/19**. **تأیید نهایی کاربر در جلسه‌ی بعدی گرفته شود** (آیتم فقط-کاربر).

**اقدام (تاریخی):** در جلسه‌ی بعدی با کاربر مرور و تأیید/جایگزینی شود؛ تا آن‌زمان این واژه‌ها در پک هستند ولی در گزارش پایلوت از آمار آن‌ها جدا نگه‌داری نشده (قابلیت فیلتر ⚑ در content-sprint موجود است).

## ۶. تست‌ها و گیت‌ها

- `tests/packs.test.js` +۲: آستانه‌ی ≥۵ با استثناها · کل ≥۷۰۰ و هر پک ≥۱۲۰.
- `tests/story.test.js` +۲: پوشش داستانی ۱۰۰٪ · کل ≥۷۰ و هر زبان ≥۱۴؛ تست قدیمی «تعداد دقیق ۳۴» به کفِ پوشش تبدیل شد (نیت: قابل‌دستیابی بودن نشان قصه‌خوان).
- `tests/e2e.mjs`: شمارنده‌ی اتاق جوایز از hardcoded «۱ / ۶» به مقایسه با فایل داده (aria-valuenow/max) تغییر کرد.
- **اجرای کامل این نوبت:** واحد/یکپارچه **۲۱۶/۲۱۶** · e2e **۲۵/۲۵** · Lighthouse (میانه‌ی ۳): کارایی **۸۴** (≥۸۳) · a11y ۱۰۰ · BP ۱۰۰ · SEO ۱۰۰.
- نسخه: 1.11.0 (بافت کش SW با تغییر داده‌ها لازم شد).
- **1.13.0:** umut→uçurtma در tr.json (+۱ واژه) · content-sprint پرچم ۰ · فهرست کامل تغییرات در CHANGELOG.

## ۷. درس‌آموخته‌های فرایند

- جایگزینی سراسری نسخه می‌تواند وابستگی‌ها را خراب کند (better-sqlite3@^11.10.0 → ^11.11.0 شد و نصب شکست) — ترمیم شد؛ درستش: فقط فیلد `version`.
- شکست یک استپ e2e قبل از بازگشت به نقشه، استپ‌های بعدی را آبشاری می‌کُشد — علت ۹ شکست اولیه فقط انتظار کهنه‌ی «۱ / ۶» بود.
