# Episode 2: Implement a save gate you can explain

Production decision, 2026-10-17: English AI-cloned owner narration with English captions and Arabic translated subtitles. The Egyptian Arabic blocks below provide localized translation source text; Arabic audio is deferred. Natural length estimate: 4–6 minutes, including useful demonstrations and exercises. Measure rehearsal; never pad to a minimum. No release day assigned.

## Slide 1: the proposed change

On screen: before and after file names, then the Episode 2 prompt. Label `Prepared implementation example`.

English:

We have a clear task and enough project context. Now we can ask for a small implementation. The prepared example starts with a function that runs every task it receives. The change adds one piece of retained state to decide whether another save can start. We'll inspect this code as if it were a proposed diff. The question is whether we can explain how it satisfies the contract, including the failure path and the lifetime of the state.

Egyptian Arabic:

عندنا مهمة واضحة وسياق كفاية عن المشروع. دلوقتي نقدر نطلب تنفيذ صغير. المثال المجهز بيبدأ بدالة بتشغّل كل مهمة بتوصلها. التعديل هيضيف حالة بتفضل موجودة، عشان تقرر هل ينفع يبدأ حفظ جديد. هنبص على الكود كأنه diff مقترح للمراجعة. المطلوب إننا نقدر نفسر هو بيحقق الشروط إزاي، بما فيها مسار الفشل، والحالة دي بتعيش قد إيه.


## Slide 2: admission before waiting

On screen: the first five lines of the corrected gate. Highlight `if (pending)` then `pending = true`, then the `await` lower down. Animate only the highlight.

English:

The gate first checks pending. If another task is already running, this call returns ignored. Otherwise it sets pending to true before awaiting the task. That order is the mechanism. A second call through the same gate sees the retained pending value and doesn't invoke another task. The result ignored is deliberate: this attempt didn't save anything. It isn't a promise that the first request succeeded, and the caller shouldn't display a fresh success message for it.

Egyptian Arabic:

البوابة بتراجع pending الأول. لو فيه مهمة شغالة، الاستدعاء ده بيرجع ignored. لو مفيش، بتخلي pending تساوي true قبل ما تستنى المهمة. الترتيب ده هو أساس الحل. استدعاء تاني من نفس البوابة هيشوف الحالة الموجودة، ومش هيبدأ مهمة جديدة. ونتيجة ignored مقصودة: المحاولة دي ما حفظتش حاجة. مش معناها إن الطلب الأول نجح، ومش المفروض نعرض بسببها رسالة نجاح جديدة.


## Slide 3: the way out after an error

On screen: `try / await task / finally / pending = false`. Show success and rejection paths reaching the same release line.

English:

The gate releases pending in finally. That line runs when the task finishes successfully and when it throws. We don't catch the error inside this pure gate, so rejection still reaches its caller. This separation lets the caller choose the user-facing message. If we reset pending only after the await, rejection could skip the reset and block every later attempt. A small fix must explain how the system recovers, not only how it handles the successful request.

Egyptian Arabic:

البوابة بترجع pending لـ false جوه finally. السطر ده بيشتغل لما المهمة تنجح، ولما ترمي خطأ. إحنا مش بنمسك الخطأ جوه البوابة، فبيوصل للي استدعاها. كده اللي بيستخدمها يقدر يختار الرسالة المناسبة للمستخدم. لو رجّعنا pending بعد await بس، الخطأ ممكن يعدّي السطر ده، وكل المحاولات بعدها تتقفل. لازم نفهم الإصلاح هيرجع الشغل إزاي بعد الفشل، زي ما بنفهم حالة النجاح.


## Slide 4: one owner retains the gate

On screen: `useRef(createSaveGate()).current` beside a counterexample creating the gate inside handlePress. Label the counterexample `Separate gate on each press`.

English:

The function alone isn't enough. Look at where its result is stored. In our React example, a ref retains the same gate for this mounted owner across renders. If we create a new gate inside every press handler call, each call starts with pending false and they won't block one another. A module-global gate would create another problem by making unrelated owners share a lock. We need the lifetime that matches the task: one gate for this owner.

Egyptian Arabic:

الدالة لوحدها مش كفاية. بص على المكان اللي بيحتفظ بالنتيجة بتاعتها. في مثال React، الـ ref بيحتفظ بنفس البوابة للمكان ده بين مرات الـ render. لو عملنا بوابة جديدة جوه كل استدعاء للضغط، كل واحدة هتبدأ بـ pending false، ومش هيمنعوا بعض. ولو خليناها عامة على مستوى الموديول، أماكن ملهاش علاقة هتتقفل مع بعض. إحنا محتاجين عمر يناسب المهمة: بوابة واحدة للمكان اللي ماسك الحفظ.


## Slide 5: what the person sees

On screen: illustrative idle, busy and error states, displayed sequentially. Show only four button props: title, loading, disabled, accessibilityState.

English:

The screen has a separate job: explain what's happening. The admitted task sets busy, clears an old error, then runs onSave. The existing button receives loading and disabled, and its label comes from the supplied translations. If saving fails, the caller displays a useful message and clears busy in finally. The gate controls admission; React state drives the visible feedback. Our supplied TSX illustrates that connection. It still needs the real project's components and native checks before it can be called a verified screen.

Egyptian Arabic:

الشاشة ليها دور تاني: توضح للمستخدم اللي بيحصل. المهمة اللي اتسمحلها تبدأ بتشغّل busy، وتمسح الخطأ القديم، وبعدين تنادي onSave. الزرار الموجود بياخد loading وdisabled، والنص جاي من الترجمة اللي اتبعتت. لو الحفظ فشل، اللي بيستدعيه يعرض رسالة مفيدة، ويرجع busy في finally. البوابة بتقرر مين يبدأ، وحالة React بتغيّر الشكل الظاهر. مثال TSX بيوضح الربط ده، ولسه محتاج مكونات المشروع وفحوصات على التطبيق الفعلي.


## Slide 6: two lines to inspect

On screen: Case B from [evaluation-cases.md](../sample/evaluation-cases.md). Pause 15 seconds. Then highlight the reset after await and move the explanation to finally.

English:

Try reviewing this shorter candidate. It sets pending before the task and resets it afterward. Where can it get stuck? Pause here and follow a rejection. When the await throws, execution skips the reset below it. The correction is to release the same retained state in finally. We also need to inspect where this candidate's pending variable lives. The visible code can show one issue while leaving another question unanswered. A good review states both, with the appropriate confidence.

Egyptian Arabic:

جرّب تراجع النسخة الأقصر دي. بتشغّل pending قبل المهمة، وبتقفلها بعدها. فين ممكن تتعلق؟ وقف هنا وامشي مع حالة الخطأ. لما await يرمي خطأ، التنفيذ هيتخطى سطر إعادة الحالة اللي بعده. التصحيح إننا نرجع نفس الحالة الموجودة في finally. وبرضه محتاجين نعرف pending دي عايشة فين. الكود الظاهر ممكن يثبت مشكلة، ويسيب سؤال تاني مفتوح. المراجعة الكويسة بتوضح الاتنين بدرجة التأكد المناسبة.


## Slide 7: a diff with a reason

On screen: `Admission`, `Ownership`, `Release`, `Feedback`. End on `Next: actual verification`.

English:

We can now explain the change without relying on the assistant's summary. Admission happens before awaiting. One owner retains the gate. Finally releases it, and the screen handles feedback through existing components. We can also state the limits: this doesn't implement server idempotency or define recovery after every network failure. Next we'll run the supplied checks and examine what their results establish. We'll start with the incomplete version so the test can demonstrate the defect it is meant to catch.

Egyptian Arabic:

كده نقدر نشرح التعديل من غير ما نعتمد على ملخص المساعد. السماح بالحفظ بيحصل قبل الانتظار. المكان اللي ماسك العملية بيحتفظ بالبوابة. وfinally بيفتحها تاني، والشاشة بتعرض الحالة بالمكونات الموجودة. وعارفين الحدود كمان: ده مش تنفيذ لـ server idempotency، ومش حل لكل نوع فشل في الشبكة. الدرس الجاي هنشغّل الفحوصات ونشوف نتائجها بتثبت إيه. هنبدأ بالنسخة الناقصة عشان الاختبار يورينا العيب اللي معمول عشانه.


## Recording and evidence

Slide cues are not narration. Use the matching task, context, implementation, verification, skill-authoring and evaluation prompts in [prompts.md](../sample/prompts.md). The exercise answers are in the spoken blocks and [evaluation answer key](../sample/review-skill/cases.md). Keep that answer key out of a real blind evaluation. Samples are teaching adaptations; no native app or actual AI evaluation result is claimed. Record slide by slide and time the selected takes.
