امنیت، هویت، استقرار و تابآوری · فصل ۹ — Resource، Provider، Cost و Organizational Failure · 130
Scope Creep و Custom Fork
failure را بعد از وقوع و بهصورت موردی تحلیل میکند و هنوز detection، containment و repair path از قبل طراحی نشده است. موضوع جاری: «Scope Creep و Custom Fork». میتواند failure family «Scope Creep و Custom Fork» را بازتولید/تشخیص دهد و detection، containment و recovery مناسب را تعیین کند.
خلاصهٔ درس
failure را بعد از وقوع و بهصورت موردی تحلیل میکند و هنوز detection، containment و repair path از قبل طراحی نشده است. موضوع جاری: «Scope Creep و Custom Fork».
میتواند failure family «Scope Creep و Custom Fork» را بازتولید/تشخیص دهد و detection، containment و recovery مناسب را تعیین کند.
خروجی این درس
میتواند failure family «Scope Creep و Custom Fork» را بازتولید/تشخیص دهد و detection، containment و recovery مناسب را تعیین کند.
1. شکست اصلی: مرز محصول گم میشود و fork تبدیل به محصول دوم میشود
Scope creep وقتی خطرناک میشود که requirementهای جدید بدون تصمیم صریح درباره baseline، هزینه و acceptance criteria وارد کار شوند. اگر بخشی از این تغییرها فقط داخل یک customer fork باقی بمانند، تیم عملاً دو مسیر محصول را نگه میدارد: upstream اصلی و نسخه سفارشی. خود fork خطا نیست؛ failure زمانی است که هیچ قرارداد روشن برای scope، sync، ownership، test delta و بازگشت به upstream وجود نداشته باشد.
2. Fork ذاتاً بدهی فنی نیست
Git و GitHub fork را یک الگوی مشروع همکاری میدانند. یک fork میتواند کوتاهمدت، آزمایشی، قراردادی یا حتی عمداً طولانیعمر باشد. بنابراین وجود fork، تعداد commitها یا merge conflict بهتنهایی diagnosis نیست. باید بپرسید چه چیزی در fork منحصربهفرد است، چرا وجود دارد، چه کسی نگهش میدارد و چه شرطی آن را دوباره با upstream همگرا یا رسماً مستقل میکند.
3. Baseline scope را قبل از شمارش changeها قفل کنید
اگر baseline اولیه معلوم نباشد، «سه درخواست اضافه» ممکن است scope creep یا تکامل طبیعی محصول باشد. baseline باید حداقل capabilityهای تعهدشده، acceptance criteria و مرجع approval را مشخص کند. هر delta بعدی باید با یکی از وضعیتهای APPROVED، REJECTED، DEFERRED یا UNKNOWN ثبت شود. تغییر مبهم را نباید بعداً بهعنوان requirement تاریخی قطعی بازنویسی کرد.
4. Re-baselining تکامل محصول را از scope creep جدا میکند
Requirement جدید وقتی scope creep نیست که هزینه، acceptance criteria، owner و baseline جدید صریحاً تأیید شده باشند. اگر تیم تصمیم گرفته محصول حالا هشت capability دارد، baseline را واقعاً بهروزرسانی کنید. برعکس، اگر requirement فقط از گفتوگو یا فشار مشتری وارد sprint شده و هیچ تصمیم ثبتشدهای ندارد، implementation موفق هم approval را ثابت نمیکند.
5. Divergence را با ahead/behind شروع کنید، نه با آن تمام کنید
ahead و behind دو signal مفیدند اما quality metric کامل نیستند. Forkی که 100 commit عقب است ولی unique code ندارد ممکن است با یک sync ساده بسته شود. Forkی که فقط سه commit تفاوت دارد اما authorization core را patch کرده و regression suite جدا میخواهد، میتواند maintenance risk بزرگتری داشته باشد. تعداد commit باید کنار conflict surface و patch semantics خوانده شود.
6. Conflict surface مهمتر از conflict count است
یک conflict در README با conflict در authorization، persistence یا security-sensitive subsystem یکسان نیست. Record باید مشخص کند upstream patch کجا با custom code همپوشانی دارد و آیا conflict صرفاً syntactic است یا behavior را تغییر میدهد. security patch که همان subsystem سفارشی را لمس میکند باید review و test مستقل را فعال کند، حتی اگر total divergence کم باشد.
7. Duplicated tests هزینه نگهداری پنهان را آشکار میکنند
وقتی fork test matrix جدا دارد، هر upstream release دو سؤال ایجاد میکند: آیا upstream tests هنوز کافیاند و آیا custom behavior regression جدیدی دارد؟ duplication همیشه بد نیست؛ requirement قراردادی ممکن است test delta جدا بخواهد. اما ownership، trigger و retirement condition آن باید روشن باشد. test suite بیمالک نشانهای از forkی است که از کنترل governance خارج شده است.
8. Maintenance owner باید اختیار و obligation هر دو را داشته باشد
نام یک نفر در README کافی نیست. owner باید مسئول sync cadence، conflict triage، security-patch intake، regression evidence و تصمیم reintegration/sunset باشد. اگر هیچکس obligation نگهداری را نپذیرفته، fork عملاً unowned است حتی اگر نویسنده اصلی هنوز در تیم باشد. owner همچنین باید بداند چه زمانی escalation به product/architecture review لازم است.
9. Configuration و extension point قبل از permanent fork بررسی میشوند
اگر نیاز مشتری با configuration، feature flag، plugin/extension interface یا policy layer قابل جداسازی است، این مسیر معمولاً divergence کمتری از patch مستقیم core دارد. اما انتقال code به extension بهتنهایی closure نیست؛ baseline و approval هم باید بهروزرسانی شوند و sync-and-test probe باید نشان دهد upstream بدون patch اختصاصی قابل جذب است.
10. Bounded maintained fork هم میتواند تصمیم درست باشد
گاهی requirement قراردادی یا isolation واقعی اجازه reintegration کامل نمیدهد. در این حالت fork میتواند BOUNDED_MAINTAINED_FORK باشد: baseline روشن، delta محدود، owner مشخص، sync cadence، dedicated tests و condition برای revisit دارد. هدف درس حذف همه forkها نیست؛ هدف حذف forkهای بیمرز و بیمالک است.
11. Containment، recovery و closure را قاطی نکنید
Freeze کردن custom work جدید containment است. ساخت extension point یا sync کردن upstream recovery است. closure فقط وقتی قوی است که baseline و approved delta ثبت شده باشند، fork state قابل توضیح باشد، owner و test delta معلوم باشند و یک sync-and-test closure probe تکرارپذیر وجود داشته باشد. یک merge موفق بهتنهایی علت failure یا سلامت آینده را ثابت نمیکند.
12. Scope Drift & Fork Divergence Control Record v1
Record این درس حداقل baseline_scope، approved_delta، acceptance_criteria، unplanned_work، customization_count، upstream_head، fork_head، ahead_count، behind_count، conflict_surface، duplicated_tests، upgrade_cost، maintenance_owner، reintegration_path، sunset_condition و closure_sync_test را نگه میدارد. هر claim باید OBSERVED، AUTHORITY، INFERRED یا UNKNOWN باشد.
13. Classification: CONTROLLED، OPEN، CUSTOM_FORK_RISK یا SCOPE_CREEP_AND_CUSTOM_FORK
CONTROLLED_EVOLUTION یعنی baseline و change governance روشن است و maintenance path متناسب است. SCOPE_GOVERNANCE_OPEN یعنی baseline یا approval هنوز بسته نشده. CUSTOM_FORK_RISK یعنی fork—even با scope approved—بهخاطر conflict surface، duplicated tests یا ownership weak ریسک مستقل دارد. SCOPE_CREEP_AND_CUSTOM_FORK وقتی است که scope مبهم/غیرتأییدشده همزمان با divergence و maintenance burden انباشته شده باشد.
14. Lab: هشت fixture و 64 assertion
Lab هشت حالت دارد: scope creep با fork بلندعمر، تکامل approved بدون fork، fork بسیار behind ولی بدون unique code، fork سه-commit روی authorization، extension migration بدون re-baseline، product evolution با re-baseline کامل، fork قراردادی bounded، و upstream security patch که با custom subsystem برخورد دارد. برای هر case هشت خروجی قطعی سنجیده میشود: baseline state، approval state، fork state، divergence state، maintenance state، recovery path، classification و decision؛ در مجموع 64 assertion.
15. Exit checklist و انتقال
قبل از خروج، baseline را صریح کنید؛ هر delta را با approval و acceptance criteria bind کنید؛ ahead/behind را همراه semantics و conflict surface بخوانید؛ duplicated tests و owner را ثبت کنید؛ configuration/extension را قبل از permanent core patch بررسی کنید؛ برای fork لازم sync cadence و revisit/sunset condition بسازید؛ و closure را با sync-and-test probe اثبات کنید. سپس transfer fixture را از صفر بازسازی کنید: فقط یک requirement مشتری باقی مانده و باید بهدلایل قراردادی isolated باشد. تصمیم بگیرید fork bounded هنوز لازم است یا supported extension همان requirement را با divergence کمتر حفظ میکند.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
Q1 retrieval
Why is a fork not automatically technical debt?
Q2 application
A fork is 100 commits behind but has no unique commits and syncs cleanly. What is the bounded interpretation?
Q3 diagnosis
A fork differs by only three commits, but they patch authorization core and require a separate regression suite. Why can it still be high risk?
Q4 decision
When is a maintained customer fork acceptable?
Q5 transfer
One contractual requirement must remain isolated. What should be tested before keeping the fork?
ملاکهای ارزیابی (rubric)
A sufficient response identifies the baseline scope and approved deltas, distinguishes product evolution from uncontrolled expansion, interprets ahead/behind together with conflict semantics, records duplicate-test and ownership burden, preserves UNKNOWN state, and chooses a bounded sync, re-baseline, extension, maintained-fork, reintegration, or sunset path. Transfer must be rebuilt from the changed contractual requirement rather than copying the original classification.
منابع و تازگی
مطالعهٔ موارد (case studies)
تصاویر درس
فایلهای آزمایشگاه
Implement the bounded evaluator in starter.py for the eight supplied synthetic scope/fork cases. No network calls are needed. Keep baseline scope, approved change, fork state, divergence, semantic conflict surface, duplicate tests, maintenance ownership, and recovery path as separate evidence dimensions. Fork existence or raw ahead/behind counts are never sufficient by themselves. Preserve OPEN state when approval evidence is incomplete, and distinguish a bounded maintained fork from uncontrolled product divergence.
Run python run_checks.py to verify fixture shape before implementing the evaluator.
رسانه و اسلایدهای درس
فایلهای آموزشی (دانلود)