یک مغایرت بحرانی قیمت در Staging، سی دقیقه پیش از انتشار کشف شده است. نسخه به Production نرسیده، کاربری آسیب ندیده و تیم می‌گوید «خوش‌شانس بودیم». آیا این فقط یک باگِ بسته‌شده است؟ نه. اگر فاصلهٔ میان کنترل‌های مورد انتظار و چیزی که واقعاً جلوی انتشار را گرفت ثبت نشود، تیم نمی‌داند دفعهٔ بعد هم همان مانع عمل می‌کند یا نه.

این راهنما یک Near-Miss Learning Loop برای نرم‌افزار می‌سازد: Trigger → Event Packet → Timeline → Potential Impact → Barrier Map → Causal Hypotheses → Actions → Verification → Learning Decision. هدف یافتن مقصر، اثبات یک «علت ریشه‌ای» واحد یا ادعای تضمین عدم تکرار نیست؛ هدف تبدیل یک خطرِ به‌موقع‌مهارشده به شواهد و کنترل قابل‌آزمون است.

پاسخ کوتاه: Near Miss نرم‌افزاری را چگونه بررسی کنیم؟

ابتدا ثابت کنید چه رخ داده و چه رخ نداده است. سپس Timeline را از شواهد هم‌زمان بسازید، پیامد بالقوه را با برچسب Counterfactual و دامنهٔ عدم‌قطعیت بیان کنید، کنترل‌های مورد انتظار و کنترلِ واقعاً مؤثر را روی Barrier Map بگذارید و چند فرضیهٔ علّیِ ابطال‌پذیر بسازید. اقدام باید به Gap مشخص وصل باشد، مالک نقش، موعد، معیار پذیرش و روش Verification داشته باشد. گزارش پس از Review منتشر می‌شود؛ پروندهٔ یادگیری فقط وقتی بسته می‌شود که نتیجهٔ اقدامات سنجیده و Decision ثبت شده باشد.

  • Fact: رخداد مشاهده‌شده با زمان، منبع و شناسهٔ قابل‌بازیابی.
  • Inference: تفسیر موقت از چند Fact که ممکن است تغییر کند.
  • Counterfactual: برآورد مشروط از اینکه اگر مانع عمل نمی‌کرد چه می‌شد؛ نه خسارت واقعی.
  • Barrier: کنترل پیشگیرانه، آشکارساز، مهارکننده یا بازیابی‌کننده با شواهد اجرای واقعی.
  • Learning closure: تصمیم مستند پس از Verification؛ نه صرفاً پایان جلسه یا بستن تیکت.

Near Miss در نرم‌افزار چیست؟

Near Miss یا «نزدیک‌به‌حادثه» رویدادی است که ظرفیت ایجاد پیامد نامطلوب داشت، اما پیش از رسیدن آن پیامد به محدودهٔ تعریف‌شده مهار شد. در نرم‌افزار، این محدوده می‌تواند Production، کاربر، دادهٔ واقعی، SLO یا تعهد قراردادی باشد. یافتن هر نقص پیش از انتشار Near Miss نیست؛ شدت بالقوه، فاصلهٔ کم تا Exposure و شکست یا دورزدن کنترل‌های مورد انتظار باید از آستانهٔ مصوب عبور کند.

وضعیتآنچه رخ دادهمسیر اصلی
Defect عادینقص در محل و زمان مورد انتظار تست پیدا شده استچرخهٔ مدیریت نقص
Near Missپیامد نرسیده، اما کنترل‌های مورد انتظار Gap داشته‌اند یا Catch دیر/اتفاقی بوده استLearning Review همین مقاله
Incidentاثر واقعی در Production، کاربر، داده یا خدمت رخ داده استIncident response و سپس Postmortem
Security Escapeیافتهٔ امنیتی از کنترل مورد انتظار عبور کرده استتحلیل رخنهٔ امنیتی
Retrospectiveمرور دوره‌ای روش کار تیم، نه یک Event خاصSprint Retrospective

چرا «نزدیک بود فاجعه شود» یک داده نیست؟

«فاجعه»، «میلیون‌ها کاربر» و «ضرر هنگفت» بدون مدل Exposure و شواهد، زبان هیجانی‌اند. بگویید Build کدام بود، چه رفتار نامطلوبی دیده شد، مسیر انتشار در چه مرحله‌ای متوقف شد، آیا Production exposure صفر بودنش اثبات شده و دامنهٔ بالقوه با چه فرض‌هایی محاسبه شده است. این دقت ارزش رویداد را کم نمی‌کند؛ از تصمیم‌های گران مبتنی بر ترس جلوگیری می‌کند.

Postmortem چه نسبتی با Near Miss دارد؟

Postmortem یک محصول یادگیریِ مکتوب و بازبینی‌شده برای Event مهم است. کتاب رسمی Google SRE دربارهٔ فرهنگ Postmortem بر معیار ازپیش‌تعریف‌شده، ثبت Incident، عوامل مشارکت‌کننده، اقدام پیشگیرانه و اشتراک آموخته‌ها تأکید می‌کند. این مقاله همان انضباط را آگاهانه به Near Missهای نرم‌افزاری تعمیم می‌دهد؛ این تعمیم، تعریف رسمی گوگل از Near Miss نیست.

مرز با RCA، تریاژ و Retrospective را حفظ کنید

تریاژ دربارهٔ Disposition نقص تصمیم می‌گیرد؛ جلسهٔ تریاژ باگ مسیر Fix، Defer، Duplicate یا Reject را مالک است. تحلیل علت ریشه‌ای مجموعه‌ای از تکنیک‌های آزمون فرضیهٔ علّی است. Retrospective الگوی دوره‌ای بهبود تیم است. Near-Miss Review یک Event خاص را از Trigger تا اثربخشی اقدام دنبال می‌کند و می‌تواند RCA را به‌عنوان یک زیرکار فراخوانی کند.

خروجی واقعی Review چیست؟

خروجی، یک صورت‌جلسهٔ طولانی نیست. حداقل باید Event Packet نسخه‌دار، Timeline مبتنی بر شواهد، Impact واقعی و بالقوهٔ جدا، Barrier Map، فرضیه‌ها و وضعیتشان، Action Register، Approval، Distribution policy و برنامهٔ Verification داشته باشید. هر ادعا باید به Evidence locator یا برچسب «نامعلوم» متصل باشد.

آستانهٔ آغاز Review را پیشاپیش تعریف کنید

اگر تصمیم به Review به شهرت فرد یا فشار همان روز وابسته باشد، رویدادهای مشابه رفتار متفاوت می‌گیرند. آستانه را پیش از رویداد تصویب و هر فصل بازبینی کنید. ذی‌نفع نیز باید بتواند Review درخواست کند، اما پذیرش یا رد درخواست با دلیل ثبت شود.

Trigger نمونهEvidence لازمسطح Review
امکان آسیب داده یا پول واقعی، بدون Exposureمسیر داده/تراکنش و نقطهٔ مهارکامل
دورزدن دو Barrier مستقلاجرای کنترل، Waiver و Catchکامل
توقف Release یا Rollback پیش از ExposureRelease log و Approvalکامل یا سبک بر اساس Severity
تکرار الگوی مشابه در ۳۰ روزCluster ID و Eventهای مرتبطمرور خوشه‌ای
نقص در همان لایهٔ مورد انتظار یافت شدهTest result و Defectمدیریت نقص؛ بدون Review مستقل

Severity بالقوه را با Probability یکی نگیرید

پیامد بالقوه می‌تواند شدید باشد، اما احتمال عبور یا دامنهٔ Exposure نامعلوم بماند. یک ماتریس ساده Severity × Proximity × Barrier degradation برای اولویت Review مفید است، ولی عدد حاصل «ریسک واقعی» یا خسارت مالی نیست. مدل، نسخه، مالک و محدودیت‌هایش را کنار امتیاز نگه دارید.

Review Charter را پیش از دعوت جلسه بنویسید

Charter باید Event ID، سؤال تصمیم، بازهٔ زمانی، سیستم‌ها، موارد خارج از دامنه، سطح محرمانگی، تسهیلگر، Approver، مهلت Draft و معیار Closure را مشخص کند. سؤال خوب این نیست که «چه کسی اشتباه کرد؟»؛ سؤال خوب این است: «کدام شرایط و Barrierها اجازه دادند CH-۸۴۲ تا Release gate پیش برود و کدام تغییر قابل‌سنجش این مسیر را کوتاه می‌کند؟»

review_id: NMR-2026-042
event_id: NM-IRR-042
decision_question: reduce_late_detection_of_discount_combinations
window: 2026-08-10T08:00:00+03:30/2026-08-10T16:00:00+03:30
in_scope: [pricing-service, checkout-web, release-pipeline]
out_of_scope: [performance, production-impact-claim]
classification: internal-redacted
facilitator_role: reliability-facilitator
approver_role: engineering-manager
draft_due: 2026-08-12
closure_rule: verified_actions_and_learning_decision

اختیارها را از مشارکت جدا کنید

نقشمسئولیتاختیار ندارد
Incident/Event ownerEvent Packet و دسترسی به Evidenceتأیید یک‌نفرهٔ روایت
Facilitatorزمان، قواعد، تفکیک Fact از inferenceتحمیل علت یا Action
Evidence custodianحفظ، Redaction و locatorتغییر منبع خام
Subject-matter expertفرضیه و نقد فنیپنهان‌کردن Alternative
Action owner roleDelivery و Evidence پذیرشSelf-verify در کنترل پرریسک
Approverتصویب انتشار گزارش/Closureبازنویسی Fact بدون Evidence

امنیت روانی و پاسخ‌گویی متضاد نیستند

Blameless یعنی رفتار افراد را در زمینهٔ اطلاعات، ابزار، فشار و محدودیت همان لحظه بررسی کنید و متن را روی «چه شد» نگه دارید، نه برچسب شخصیت. این اصل مصونیت از سیاست منابع انسانی، تخلف عمدی، آزار، تقلب یا الزام قانونی نیست. چنین موضوعی باید با حداقل افشای لازم به مسیر مستقل HR، حقوقی یا امنیتی ارجاع شود؛ Learning Review جای بازجویی نیست.

Evidence Hold کوتاه و متناسب ایجاد کنید

پیش از چرخش لاگ یا حذف Artifact، بازهٔ محدود Evidence را حفظ کنید: Deployment record، commit/PR، CI result، feature flag، TestRail run، alert و decision receipt. Secret، Token، دادهٔ پرداخت و PII را در سند مشترک کپی نکنید؛ locator کنترل‌شده، هش، سطح دسترسی و Retention کافی است. Snapshot بدون زمان و نسخه ارزش کمی دارد.

Event Packet؛ قرارداد ورودی Review

فیلدنمونهخطای رایج
Event/Change/BuildNM-IRR-042 / CH-842 / b271عبارت مبهم «نسخهٔ جدید»
Observed behaviordiscount_total=-۱۲۰۰۰۰ در سناریوی C-۱۷«قیمت خراب بود»
Environment/configstaging-tehran / pricing-rules:v43حذف Fingerprint
Detectionmanual-smoke-۷۷ در ۱۵:۱۲نسبت‌دادن به «QA» بدون Run
Containmentrelease gate HOLD در ۱۵:۱۸یکی‌گرفتن Catch و Containment
Actual exposureproduction deploy=۰؛ transaction=۰فرض صفر بدون log
Unknownsرفتار نسخه روی cache قدیمیپرکردن شکاف با حدس

Timeline را از حافظه نسازید

هر ردیف Timeline باید زمان با Zone، Actor از نوع نقش یا سیستم، Event، Source locator و Confidence داشته باشد. زمان گفتگو می‌تواند زمان «گزارش» باشد، نه زمان «وقوع». ساعت CI، Git، Jira و پیام‌رسان ممکن است Drift داشته باشند؛ ساعت مرجع و Offset را ثبت کنید و ترتیب نامطمئن را قطعی ننویسید.

زمان تهرانرویدادمنبعConfidence
14:06Build b271 ساخته شدci/build/271بالا
14:21integration-pricing در وضعیت skipped ثبت شدci/job/991بالا
14:37Waiver W-۱۹ بدون امضای دوم وارد Gate شدrelease/w19بالا
15:12سناریوی C-۱۷ اختلاف قیمت نشان دادtr/run/77بالا
15:18Release در وضعیت HOLD قرار گرفتgate/decision/512بالا
15:44Production deployment صفر تأیید شدdeploy/audit/204بالا

Fact، inference و Unknown را در متن نشانه‌گذاری کنید

عبارتنوع درستچرا
Job در CI برابر skipped بودFactArtifact هم‌زمان دارد
فشار زمان باعث Waiver شدHypothesisنیازمند شواهد تصمیم و Alternative است
اگر منتشر می‌شد همهٔ کاربران زیان می‌دیدندCounterfactual ضعیفExposure و eligibility معلوم نیست
هیچ نسخه‌ای به Production نرفتFact مشروطبا deployment audit و بازهٔ مشخص
اثر cache قدیمیUnknownRun شاهد وجود ندارد

Actual Impact را پیش از Potential Impact بنویسید

در مثال ما Actual Impact این است: انتشار ۴۶ دقیقه متوقف شد، سه نقش درگیر شدند، Production deploy و تراکنش واقعی مرتبط صفر بود. Potential Impact باید جدا بیاید: «اگر b271 با rules:v43 منتشر می‌شد، سفارش‌های واجد ترکیب C-۱۷ ممکن بود مبلغ منفی ببینند». اندازهٔ جمعیت، مدت Exposure و واکنش Gate هنوز پارامترند؛ پس رقم مالی قطعی نداریم.

Counterfactual را قابل‌ممیزی کنید

potential_exposure = eligible_orders_per_hour
                   × assumed_exposure_hours
                   × affected_path_share

label: counterfactual_estimate
range: [low, central, high]
assumptions:
  - b271 would pass the remaining gate
  - rules:v43 would be active for eligible traffic
excluded:
  - user retry and support intervention
  - emergency rollback latency
decision_use: prioritize_review_only

این مدل برای اولویت‌گذاری است، نه ثبت خسارت. اگر دادهٔ ورودی قابل اتکا نیست، «نامعلوم» بهتر از عدد دقیقِ ساختگی است. سناریوی worst case را با expected case ترکیب نکنید.

Catch Point با Expected Detection Point فرق دارد

کشف در Smoke دستی یک موفقیت واقعی است، اما اگر کنترل طراحی‌شده برای این ریسک Decision Table در Requirement review یا integration check بوده، Catch دیرهنگام Gap را پاک نمی‌کند. فاصلهٔ «اولین نقطه‌ای که می‌توانستیم با هزینهٔ معقول کشف کنیم» تا «نقطهٔ کشف واقعی» را ثبت کنید؛ آن را به عملکرد فردی تبدیل نکنید.

Barrier Map را حول Claim بسازید

BarrierهدفExpectedActualEvidence
Requirement example tableپیشگیری از ابهام ترکیب تخفیفC-01..C-24C-۱۷ غایبreq/842:v8
Unit propertyمبلغ نهایی هرگز منفی نباشداجرا روی PRProperty وجود نداشتrepo/pr/842
Integration matrixترکیب Rule و categoryrequiredskippedci/job/991
Waiver controlپذیرش آگاهانهٔ Gapدو امضا + expiryیک امضاrelease/w19
Manual smokeSample مسیر حیاتیC-01,C-07,C-17C-۱۷ failure؛ Catchtr/run/77
Release gateمهار نسخهBlock on criticalHOLDgate/512

کنترل مستقل را از کنترل هم‌بسته تشخیص دهید

سه Test که از یک Example، Oracle و Dataset مشترک تغذیه می‌شوند سه Barrier مستقل نیستند. Failure mode مشترک را ثبت کنید: Specification source، Generator، محیط، Approver یا Credential. استقلال نسبی یعنی شکست یک منبع، همهٔ کنترل‌ها را هم‌زمان کور نکند. مقالهٔ تستر به‌عنوان شبکهٔ ایمنی طراحی Protection Control و Handoff را عمیق‌تر پوشش می‌دهد.

Lucky Catch را پاداش دهید، اما کنترل اعلام نکنید

اگر تستر خارج از Script یک ترکیب را امتحان کرده و نقص را یافته، مشاهده و Escalation ارزشمند است. بااین‌حال «دقت تستر» کنترل تکرارپذیر نیست. ابتدا Catch را incidental علامت بزنید؛ سپس اگر ارزش دارد آن را به Property، Example، Monitor یا Gate با مالک و Verification تبدیل کنید.

پنج چرا را صورت‌جلسهٔ حقیقت نکنید

تعداد «چرا» جادویی نیست و آخرین پاسخ الزاماً Root cause نیست. پاسخ‌هایی مثل «نیازمندی ناقص بود» خود به فرضیه نیاز دارند: چه Requirement claimی غایب بود، چه Reviewی انتظار می‌رفت، آیا نبود آن Claim برای ایجاد رفتار کافی بود و چه شاهد خلافی داریم؟ روش‌های کامل‌تر، Evidence و Alternative را در راهنمای RCA دنبال کنید.

فرضیهٔ علّی باید ابطال‌پذیر باشد

IDفرضیهSupportingDisconfirming testوضعیت
H1نبود C-۱۷ در Rule example باعث نبود Oracle مشترک شدreq:v8 و Testها C-۱۷ ندارندبررسی منبع دیگری که C-۱۷ را الزام کرده باشدsupported-limited
H2Config متفاوت Staging رفتار را ساخته استاختلاف محیط محتمل بودReplay با همان Artifact و config تولیدrejected-by-replay
H3Cache قدیمی عامل اصلی استگزارش شفاهیRun سرد/گرم با traceunsupported
H4Waiver تک‌امضایی اجازهٔ پیشروی با Gap را دادW-۱۹ و Gate logبازسازی Gate با policy مصوبsupported

عامل مشارکت‌کننده را با علت کافی یکی نگیرید

Deadline، خستگی، تغییر Specification، وابستگی ناپایدار و نبود Test data می‌توانند شرایط مشارکت‌کننده باشند. برای هر کدام Mechanism بنویسید: «چگونه این شرط احتمال یا شدت را تغییر داد؟» اگر حذف عامل به‌تنهایی جلوی مسیر را نمی‌گیرد، آن را علت کافی ننامید. مدل چندعاملی معمولاً از داستان خطی صادقانه‌تر است.

«خطای انسانی» نقطهٔ شروع است، نه پایان

اگر فرد Waiver را با یک امضا ثبت کرد، بپرسید UI چگونه آن را پذیرفت، Policy چه ابهامی داشت، فشار Queue چه بود، Feedback کجا غایب بود و کنترل دوم چرا مستقل نبود. هم‌زمان Action را به «بیشتر دقت کنید» تقلیل ندهید. تغییر رفتار فقط وقتی معتبر است که شرایط اجرا، Feedback و سنجش دارد.

جلسهٔ Review را پس از تثبیت شواهد برگزار کنید

Draft اولیه و Evidence index را پیش‌خوانی کنید. جلسه برای خواندن لاگ از صفر نیست؛ برای حل اختلاف، ثبت Unknown، نقد فرضیه و انتخاب Action است. افراد درگیر فرصت اصلاح Fact داشته باشند، اما حذف روایت نامطلوب نیازمند Evidence باشد. زمان جلسه و تعداد شرکت‌کننده را با پیچیدگی متناسب کنید.

دستور جلسهٔ ۷۵ دقیقه‌ای

  1. ۵ دقیقه: Charter، قواعد و Decision question.
  2. ۱۰ دقیقه: Actual impact، containment و Unknownها.
  3. ۱۵ دقیقه: Timeline؛ فقط اختلاف‌های Evidence.
  4. ۱۵ دقیقه: Barrier Map و Catch point.
  5. ۱۵ دقیقه: فرضیه‌ها، شاهد موافق و آزمون خلاف.
  6. ۱۰ دقیقه: Action options، do-nothing و trade-off.
  7. ۵ دقیقه: Decision، مالک‌ها، Review due و موارد باز.

Facilitation را قابل مشاهده کنید

Facilitator باید جمله‌های سرزنش‌آمیز را به سؤال سیستمی بازنویسی کند، صدای نقش‌های کم‌قدرت را فعالانه بگیرد و disagreement را حذف نکند. عبارت‌های مفید: «منبع این گزاره چیست؟»، «در همان لحظه چه اطلاعاتی در دسترس بود؟»، «چه شاهدی نظر ما را عوض می‌کند؟» و «این اقدام کدام Failure mode را می‌شکند؟»

Action را از Gap استخراج کنید، نه از هیجان جلسه

نوع Actionنمونه برای NM-IRR-۰۴۲Verification
PreventProperty مبلغ نهایی ≥ ۰ برای Generator ترکیب‌هاSeedهای مرزی + mutation شاهد
DetectIntegration matrix برای Rule × category۲۴ Case و failure injection
ContainGate مانع Waiver تک‌امضایی شودPolicy test در CI
MitigateFeature flag با kill switch نقش‌محورGame day بدون Production data
Investigateاثر cache در Build مشابهReplay و trace مقایسه‌ای
Learnجست‌وجوی همان Rule gap در دو سرویسCluster review و ثبت نتیجه

Action Contract کامل بنویسید

action_id: AI-042-03
risk_link: BARRIER-WAIVER-02
type: contain
change: reject waiver unless two distinct roles approve before expiry
owner_role: release-platform-owner
due_at: 2026-08-20T17:00:00+03:30
priority: P1
acceptance:
  - single_signature_fixture == blocked
  - expired_waiver_fixture == blocked
  - valid_two_role_fixture == allowed
verification_owner_role: qa-governance-reviewer
evidence_due: 2026-08-21
rollback: feature_flag gate_policy_v2=false
status: accepted_not_verified

«بهبود تست‌ها» Action نیست. فعل، Object، Boundary، معیار پذیرش و Evidence لازم است. مالک را با Role ثبت کنید تا جابه‌جایی فرد Action را یتیم نکند؛ سامانهٔ کار می‌تواند فرد فعلی را resolve کند.

اقدام بزرگ‌تر همیشه بهتر نیست

بازنویسی کامل سرویس ممکن است سال‌ها طول بکشد و Failure mode را هم هدف نگیرد. Optionها را بر کاهش Risk، زمان تا اثر، Blast radius تغییر، هزینهٔ نگهداشت و قابلیت بازگشت مقایسه کنید. یک کنترل کوچکِ قابل‌سنجش همراه با Investigation می‌تواند از پروژهٔ مبهم مؤثرتر باشد.

اقدامات پیشگیرانه و مهارکننده را متوازن کنید

فقط افزودن Alert، کشف را بهتر می‌کند اما وقوع را کم نمی‌کند؛ فقط افزودن Test ممکن است در برابر Unknown unknown کافی نباشد. برای Risk مهم، ترکیبی متناسب از Prevent، Detect و Contain بسازید و استقلال نسبی آن‌ها را بررسی کنید. همهٔ Actionها الزامی نیستند؛ دلیل انتخاب و رد Optionها را نگه دارید.

Verification را هنگام پذیرش Action طراحی کنید

Done در Jira اثربخشی نیست. مشخص کنید چه Fixture یا Runی Failure mode را بازآفرینی می‌کند، چه Control runی False positive را می‌سنجد، چه کسی مستقل بررسی می‌کند و Evidence تا چه زمانی معتبر است. اگر Test جدید همیشه سبز است ولی Fault injection آن را قرمز نمی‌کند، کنترل هنوز اثبات نشده است.

Recurrence را با شناسهٔ الگو بسنجید

«همان Incident تکرار نشد» می‌تواند ناشی از ترافیک کم یا تغییر محصول باشد. برای Failure mode یک Pattern ID و تعریف Match بسازید: همان Rule family، همان Barrier gap یا همان Waiver path. Detection coverage و exposure opportunity را کنار recurrence نگه دارید؛ صفر بدون Opportunity شاهد اثربخشی نیست.

Closure دو مرحله دارد

مرحلهشرطتصمیم‌های مجاز
Review publicationFact review، Redaction، فرضیه/Unknown، Action acceptance و ApprovalPUBLISH / HOLD / REVISE
Learning closureVerification، residual risk، overdue disposition و recurrence windowADOPT / ADAPT / REPLACE / ACCEPT-RISK / REOPEN

جلسه می‌تواند تمام شود و گزارش منتشر شود، درحالی‌که Learning هنوز باز است. این تفکیک مانع می‌شود تیم برای رسیدن به آمار Closure، Actionهای بی‌شاهد را بسته اعلام کند.

Decision Receipt را فراموش نکنید

decision_id: LD-042
as_of: 2026-09-15T12:00:00+03:30
review_revision: 3
verified: [AI-042-01, AI-042-03]
adapt: [AI-042-02]
residual_risk: cache_path_not_replayed
risk_acceptor_role: product-engineering-director
next_review: 2026-10-15
decision: ADAPT
evidence_manifest: em://near-miss/042/v3

گزارش را نسخه‌دار و قابل اصلاح منتشر کنید

Header باید status، revision، last reviewed، owners، sensitivity و correction policy داشته باشد. اگر Evidence جدید H1 را رد کرد، نسخهٔ قبلی را بی‌صدا ویرایش نکنید؛ Correction با دلیل و زمان اضافه کنید و مصرف‌کنندگان تصمیم را خبر دهید. لینک منبع کنترل‌شده از Screenshot جداافتاده بهتر است.

اشتراک‌گذاری گسترده با افشای گسترده یکی نیست

Audience را بر اساس نیاز یادگیری تعریف کنید. نسخهٔ عمومی داخلی می‌تواند نام اشخاص، پیام خصوصی، Customer identifier، Secret، جزئیات exploit و دادهٔ حساس تجاری را Redact کند و درعین‌حال Timeline، Barrier gap و Action را حفظ کند. اصل کمینه‌سازی داده و Retention سازمان را رعایت کنید.

Postmortem خوب باید بازبینی و پیگیری شود

فصل عملی Google SRE دربارهٔ Postmortem توضیح می‌دهد که Action مبهم، بدون اولویت یا بدون Tracking به‌آسانی فراموش می‌شود و بستن Actionها باید به‌اندازهٔ نوشتن گزارش ارزش داشته باشد. در این چارچوب، Review کیفیت سند و Follow-up کیفیت کنترل دو Gate جدا هستند.

متریک‌ها را برای یادگیری طراحی کنید، نه رتبه‌بندی افراد

MetricDenominator/تعریفCountermetric
Time to draftTrigger تا Draft آمادهٔ Reviewنرخ Correction پس از انتشار
Action verification rateVerified / actionهای سررسیدشدهنرخ Verification بی‌اثر در fault injection
Late detection distanceمرحلهٔ Expected تا Actual catchهزینه و Flakiness کنترل افزوده
Pattern recurrenceEvent match / exposure opportunityDetection coverage drift
Reporting propensityNear miss ثبت‌شده در واحد فرصتناشناس‌بودن/امنیت روانی Survey
Overdue riskAction عقب‌افتاده وزن‌دهی‌شده با RiskFeature delay و operational load

افزایش تعداد Near Miss لزوماً بد نیست

پس از ایجاد کانال امن، گزارش‌ها ممکن است زیاد شوند؛ این می‌تواند Visibility بهتر باشد، نه Reliability بدتر. تعداد خام را KPI کاهش ندهید، وگرنه تیم رویدادها را پنهان یا طبقه‌بندی را بازی می‌کند. Severity mix، opportunity، reporting propensity و عبور واقعی از Barrier را با هم بخوانید.

Dashboard بدون Decision contract خطرناک است

هر نمودار باید owner، refresh، data delay، denominator، exclusion و اقدام ناشی از Threshold داشته باشد. مثلاً اگر overdue P1 بیش از دو شد، چه کسی ظرفیت Release را بازتخصیص می‌دهد؟ برای بستن حلقهٔ پیام تا تصمیم می‌توانید از پروتکل ارتباط ریسک کیفیت استفاده کنید.

ضدالگوهای رایج Postmortem

ضدالگوپیامداصلاح
Hero storyوابستگی به فرد و پنهان‌شدن GapCatch را قدردانی؛ Barrier را تکرارپذیر کنید
یک Root cause قطعیحذف Alternative و عوامل هم‌بستهHypothesis register و disconfirming test
Impact خیالی دقیقاولویت‌گذاری هیجانیActual/Counterfactual جدا با range
Action «آموزش بیشتر»پایداری کم و Verification مبهمشرایط، Feedback و کنترل سیستمی
Close با پایان جلسهAction یتیمدو Closure و Decision receipt
انتشار log خامنشت PII/SecretEvidence locator و Redaction
رتبه‌بندی تیم با تعداد Eventکم‌گزارشی و GamingMetric + countermetric + opportunity

نمونهٔ عملی: باگ قیمت‌گذاری پیش از Release

در NM-IRR-۰۴۲، Build b271 برای ترکیب تخفیف عضویت و گروه کالای جدید مبلغ منفی تولید کرد. Smoke دستی آن را یافت و Gate انتشار را متوقف کرد. Audit نشان داد ۰ Deployment و ۰ تراکنش Production رخ داده؛ پس خسارت کاربر ادعا نشد. Review دو Gap را supported دانست: نبود Contract سناریوی C-۱۷ و Waiver تک‌امضایی. فرضیهٔ Config با Replay رد شد و اثر Cache باز ماند.

تیم چهار Action پیشنهاد کرد، اما سه مورد را پذیرفت: Property قیمت نامنفی، Matrix بیست‌وچهارحالته و Gate دو‌نقشی. «جلسهٔ آموزشی عمومی» به دلیل Mechanism و معیار ضعیف رد شد. برای پوشش آزمون‌ها، ادعای «۱۰۰٪» مطرح نشد؛ قرارداد مخرج و استثنا باید طبق راهنمای Coverage Claim جدا ثبت شود.

آزمایش تکرارپذیر: ممیزی بستهٔ Near Miss

Fixture زیر عمداً گزارش را «آمادهٔ بستن» اعلام می‌کند، درحالی‌که Actionها فقط accepted هستند، Evidence بالقوه برچسب ندارد، یک Barrier منبع ندارد و H3 آزمون خلاف ندارد. Validator باید به‌جای اعتماد به summary، Gapها را بازگرداند.

{
  "review_id": "NMR-2026-042",
  "actual_exposure": {"production_deploys": 0, "transactions": 0, "evidence": "deploy/audit/204"},
  "potential_impact": {"value": 920000000, "label": "", "assumptions": []},
  "timeline": [{"at": "2026-08-10T15:12:00+03:30", "event": "C-17 failed", "source": "tr/run/77"}],
  "barriers": [
    {"id": "B1", "expected": "required", "actual": "skipped", "evidence": "ci/job/991"},
    {"id": "B2", "expected": "two signatures", "actual": "one signature", "evidence": ""}
  ],
  "hypotheses": [
    {"id": "H1", "support": ["req/842:v8"], "disconfirming_test": "search alternative contract"},
    {"id": "H3", "support": ["interview/note/3"], "disconfirming_test": ""}
  ],
  "actions": [
    {"id": "A1", "risk_link": "B1", "owner_role": "qa-platform-owner", "due": "2026-08-20", "acceptance": ["24 cases pass"], "verification_evidence": "", "status": "accepted"},
    {"id": "A2", "risk_link": "B2", "owner_role": "release-owner", "due": "2026-08-20", "acceptance": ["single signer blocked"], "verification_evidence": "", "status": "accepted"}
  ],
  "declared": "READY_FOR_LEARNING_CLOSURE"
}
const fs = require('node:fs');
const r = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
const findings = [];
const add = (rule, path, msg) => findings.push({ rule, path, msg });

if (!r.review_id) add('IDENTITY', 'review_id', 'missing review identity');
if (!r.actual_exposure?.evidence) add('ACTUAL_EVIDENCE', 'actual_exposure', 'actual impact lacks evidence');
if (r.potential_impact && r.potential_impact.label !== 'counterfactual_estimate')
  add('COUNTERFACTUAL_LABEL', 'potential_impact.label', 'potential impact must be labeled');
if (r.potential_impact && !(r.potential_impact.assumptions || []).length)
  add('COUNTERFACTUAL_ASSUMPTIONS', 'potential_impact.assumptions', 'assumptions are empty');

for (const [i, x] of (r.timeline || []).entries()) {
  if (!x.at || !x.source) add('TIMELINE_EVIDENCE', `timeline[${i}]`, 'time/source required');
}
for (const [i, b] of (r.barriers || []).entries()) {
  if (!b.expected || !b.actual || !b.evidence)
    add('BARRIER_CONTRACT', `barriers[${i}]`, 'expected/actual/evidence required');
}
for (const [i, h] of (r.hypotheses || []).entries()) {
  if (!(h.support || []).length || !h.disconfirming_test)
    add('HYPOTHESIS_TEST', `hypotheses[${i}]`, 'support and disconfirming test required');
}
for (const [i, a] of (r.actions || []).entries()) {
  for (const key of ['risk_link', 'owner_role', 'due', 'verification_evidence'])
    if (!a[key]) add('ACTION_CONTRACT', `actions[${i}].${key}`, `${key} required`);
  if (!(a.acceptance || []).length) add('ACTION_ACCEPTANCE', `actions[${i}]`, 'acceptance required');
}
const verified = (r.actions || []).length > 0 && r.actions.every(a => a.status === 'verified');
const computed = findings.length === 0 && verified
  ? 'READY_FOR_LEARNING_CLOSURE' : 'HOLD';
if (r.declared !== computed) add('DECISION_MISMATCH', 'declared', `${r.declared} != ${computed}`);

console.log(JSON.stringify({ computed, count: findings.length, findings }, null, 2));
process.exitCode = findings.length ? 2 : 0;

اجرا:

node audit-near-miss.js near-miss.json
# computed: HOLD
# findings: COUNTERFACTUAL_LABEL, COUNTERFACTUAL_ASSUMPTIONS,
# BARRIER_CONTRACT, HYPOTHESIS_TEST, ACTION_CONTRACT × 2,
# DECISION_MISMATCH

پس از افزودن label و فرض‌ها، locator کنترل، آزمون Replay برای H3 و Evidence مستقل هر دو Action، status آن‌ها verified می‌شود. اجرای دوباره باید count=۰ و READY_FOR_LEARNING_CLOSURE بدهد. این ابزار کیفیت داده را بررسی می‌کند؛ درستی رابطهٔ علّی را خودکار اثبات نمی‌کند.

چک‌لیست پیش از انتشار گزارش

  • Trigger، Scope، Decision question و Approver روشن است.
  • Actual impact از Potential impact جدا و Counterfactual برچسب‌دار است.
  • Timeline برای هر ردیف time zone، source و confidence دارد.
  • Expected و Actual هر Barrier با Evidence مقایسه شده است.
  • Catch دیرهنگام یا اتفاقی به‌عنوان کنترل پایدار جا زده نشده است.
  • فرضیه‌ها شاهد موافق، آزمون خلاف و وضعیت دارند.
  • Actionها به Gap وصل و دارای owner role، due، acceptance و verification هستند.
  • PII، Secret و دادهٔ حساس Redact و دسترسی کنترل شده است.
  • Review publication و Learning closure دو Decision جدا دارند.
  • Correction policy، recurrence window و next review ثبت شده است.

نسخهٔ سبک برای تیم کوچک

برای Near Miss متوسط، یک صفحه کافی است: Event/actual impact، شش ردیف Timeline، سه Barrier، دو فرضیه، حداکثر سه Action و تاریخ Verification. نقش‌ها می‌توانند روی یک نفر جمع شوند، اما Self-approval برای Risk بالا را مشخص و یک Reviewer دوم تعیین کنید. سبک‌بودن به معنی حذف Evidence و Closure نیست.

نسخهٔ سازمانی و چندتیمی

برای سامانهٔ چندتیمی، taxonomy مشترک Event/Barrier/Pattern، مخزن قابل جست‌وجو، دسترسی لایه‌ای، Action sync با Issue tracker و Review board دوره‌ای لازم می‌شود. Deadline محلی را به ظرفیت واقعی وصل کنید و Action مشترک را به چند تیکت متناقض تکثیر نکنید؛ یک source of truth و مصرف‌کنندگان مشخص داشته باشید.

AI در Postmortem چه کار کند و چه کار نکند؟

AI می‌تواند Timeline candidate را از منابع مجاز مرتب، PII candidate را علامت، Eventهای مشابه را بازیابی و Action مبهم را هشدار دهد. نباید log گمشده بسازد، نیت فرد را حدس بزند، علت را قطعی اعلام کند، Severity یا Risk acceptance را خودمختار تصویب کند یا دادهٔ محرمانه را به سرویس بدون قرارداد بفرستد. خروجی مدل باید source، confidence و reviewer انسانی داشته باشد.

برنامهٔ اجرایی ۳۰روزه

بازهکارخروجی قابل مشاهده
روز ۱–۳تعریف Trigger، taxonomy و sensitivityPolicy v1 و دو مثال مرزی
روز ۴–۷ساخت Template و Evidence indexFixture کامل/ناقص
روز ۸–۱۲انتخاب Facilitator و اجرای Dry runیافته‌های Facilitation
روز ۱۳–۱۸Pilot روی یک Near Miss واقعیِ RedactشدهDraft، Review و Action register
روز ۱۹–۲۴اتصال Action به Tracker و Reminderمالک، موعد و escalation
روز ۲۵–۳۰Verification و Retro روی خود فرایندADOPT/ADAPT/STOP و Policy v2

جمع‌بندی

ارزش Near Miss در ترسِ «چه می‌شد اگر» نیست؛ در مشاهدهٔ کم‌هزینه‌ترِ مسیر شکست است. یک Postmortem قابل اتکا Fact را از حدس جدا می‌کند، Actual را با Counterfactual مخلوط نمی‌کند، Lucky catch را Barrier پایدار نمی‌نامد و از چند فرضیه به Action قابل‌Verification می‌رسد. اگر گزارش منتشر شد اما Action سنجیده نشد، یادگیری هنوز بسته نشده است.

سؤالات متداول دربارهٔ Near Miss و Postmortem

آیا هر باگ بحرانی پیش از انتشار Near Miss است؟

خیر. اگر نقص در لایه و زمان مورد انتظار پیدا شده، چرخهٔ عادی Defect کافی است. Near Miss زمانی معنا دارد که Potential severity، نزدیکی به Exposure، تضعیف Barrier یا Catch دیر/اتفاقی از Trigger مصوب عبور کند.

Postmortem بدون سرزنش یعنی هیچ‌کس پاسخ‌گو نیست؟

خیر. مالکیت Action، Approval و موعد کاملاً روشن است؛ اما رفتار در Context بررسی می‌شود و گزارش روی سیستم و شواهد تمرکز دارد. تخلف عمدی یا موضوع HR/حقوقی به مسیر مستقل می‌رود.

آیا جلسهٔ پنج چرا برای بستن Review کافی است؟

خیر. ۵ Whys می‌تواند فرضیه بسازد، اما Closure به Timeline، Evidence، Alternative، Barrier gap، Action contract و Verification نیاز دارد. تعداد چراها عمق یا صحت علّی را تضمین نمی‌کند.

اگر هیچ کاربری آسیب ندیده، Impact را چه بنویسیم؟

Actual impact را دقیق بنویسید: مثلاً صفر Deployment و تراکنش Production، ۴۶ دقیقه تأخیر و هزینهٔ عملیاتی محدود. پیامد بالقوه را جدا، مشروط، Rangeدار و با برچسب counterfactual ثبت کنید.

چه زمانی پروندهٔ یادگیری بسته می‌شود؟

وقتی Actionهای لازم Verification شده، Action ناموفق Adapt یا Replace شده، Risk باقی‌مانده صاحب اختیار دارد و Decision receipt با Evidence manifest ثبت شده است. انتشار گزارش فقط Closure مرحلهٔ اول است.

دیدگاهتان را بنویسید