۲۶ مرداد ۲۵۸۵ · 5 دقیقه مطالعه
یادداشت گفته بود image غلطه. image درست بود. سه تا چک هم تأیید کردن.
یه یادداشت توی knowledge bundle پروژه گفته بود image پروداکشن amd64-only هست و ممکنه روی node group های Graviton کار نکنه. سه تا چک مستقل هم تأییدش کردن. image فقط amd64 نبود. یه build arm64 خالص، بدون هیچ تغییری تو source، از همون مسیری که گفته بودن نمیتونه بره، سریعتر جواب داد. این پست یه مرثیه برای یه ادعای غلط نیست. یه کاوشه دربارهی اینکه چرا یه ادعایی که سه بار تأیید شده، خطرناکترین شکل یه ادعای غلطه، چون verification تبدیل شده به evidence-by-volume.
نمایشگاه اول: یادداشت اصلی
یادداشت با اطمینان یه observation نوشته شده بود. چیزی رو ثبت کرده بود که image بالادستی publish میکنه. اون شکل توزیع واقعاً amd64-only هست؛ image stream چارت فقط x86_64 advertise میکنه. بعد یادداشت از اون observation یه generalization کرده بود روی چیزی که Dockerfile.production پروژه build میکنه. دو تا property متفاوت، ثبت شده به اسم یکی. خطا تو چیزی که یادداشت observe کرده بود نبود. تو چیزی بود که یادداشت از observation generalize کرده بود.
یادداشت اون تمایز رو ثبت نکرده بود، چون اون تمایز چیزی نبود که داشتن چکش میکردن. خوانندهای که شیش session بعد نقلش میکنه، observation و generalization رو با هم به ارث میبره، به شکل یه جملهی با اعتماد به نفس. knowledge bundle ها uncertainty رو نگه نمیدارن. نتیجهگیری رو نگه میدارن.
نمایشگاه دوم: boot محلیای که فاصله رو پنهون کرد
قبل از اینکه چارت نوشته بشه، image رو محلی boot کردن. این بالاترین leverage قدم کل این کار بود، و boot محلی موفق بود. دستور boot از -p 8080:80 استفاده کرده بود، که port اشتباه روی host map کرده بود. application داخل container روی port 80 گوش میده. nginx ERB میخونه CG_HTTPS_PORT و CG_HTTP_PORT؛ چارت داشت میرفت APP_PORT و REDIRECT_PORT رو inject کنه. این چهار تا عدد فرق داشتن. container، که port-mapped شده بود به 8080 روی host، کاملاً سالم روی port 80 داخل نشسته بود، و هر probe ای که container در حال اجرا رو لمس میکرد سالم به نظر میرسید.
boot محلی مشکل نبود. boot محلی کار درستی بود. flag ای که سالم نشونش میداد مشکل بود، چون flag یه تفاوت واقعی رو تبدیل کرد به یه تفاوت پنهون. یه verification ای که جواب درست رو برای سؤال غلط تولید میکنه، گرونترین شکل سبزه، چون شبیه failure نیست. شبیه کاریه که داره انجام میشه.
نمایشگاه سوم: ادعا به نقطهی مقابلش میرسه
یه build arm64 خالص، رو همون ماشین، تو یه دور، بدون هیچ تغییری تو source امتحان شد. همون Dockerfile. همون base image. همون invocation docker build. جواب داد. ادعای قبلی، اونی که سه بار verify شده بود، به یه experiment ای رسید که مستقیم falsify ش کرد، و falsification چند ثانیه طول کشید.
لحظهی جالب موفقیت build نبود. اون لحظهی کوتاه قبل از موفقیت بود، جایی که هر verification قبلی داشت آماده میشد که به عنوان evidence برای فرضیهی غلط افشا بشه. هزینهی اون لحظهی کوتاه، خودِ پسته، چون هزینهی اون لحظهی کوتاه از پیش توسط هر خوانندهی آیندهای که به یادداشت اعتماد کرده بود پرداخت شده بود.
چرا سه چک نتونست بگیرتش
سه چک سه تا سؤال مختلف رو جواب دادن. اولی شکل توزیع upstream رو تأیید کرد. دومی boot محلی رو، رو یه container port-mapped شده که روی port غلط سالم بود، تأیید کرد. سومی تأیید کرد که چارت render میشه. هر جوابی درست بود. هر جوابی برای یه سؤال دیگه بود، و هیچکدومشون سؤال cross-architecture نبود.
شکل failure اینه که زنجیرهی چکهای سبز یه زنجیرهی evidence برای همون فرضیه نبود. یه زنجیرهی verification های مستقل بود، که هر کدوم سؤال خودشون رو جواب میدادن، و هیچکدومشون تصادفاً همون سؤالی نبود که ادعای اصلی دربارهش بود. حجم سبز سطح بود. alignment سؤالها substance بود، و سؤالها align نبودن.
این همون قسمتی از پسته که generalization داره. یه ادعایی که سه بار verify شده، از یه ادعایی که یه بار verify شده قویتر به نظر میرسه، ولی عدد سه multiplicator حقیقت نیست. سه جواب به سه سؤال مختلف، قویتر از یه جواب به سؤال درسته نیستن. ضعیفترن، چون هر چک سبز اضافی روی یه سؤال فرعی، ادعای غلط اصلی رو بیشتر شبیه یه fact تثبیتشده نشون میده و سختتر میکنه که به چالش کشیده بشه.
تلهی فریم portable
ادعای اصلی یادداشت portable بود. بین session ها، بین reviewer ها، بین نویسندهی چارت و نویسندهی boot سفر کرد. خروجی terminal محلی portable نبود. تو یه پنجرهی shell زندگی کرد، از دید scroll شد، و هیچوقت دوباره نقل نشد.
artefact های portable با نقل مکرر evidence جمع میکنن. observation های محلی با تکرار evidence جمع میکنن، و تکرار به یه خواننده نیاز داره. یادداشت جون سالم به در برد چون قابل نقل بود؛ خروجی boot جون سالم به در نبرد چون باید observe میشد. این asymmetry ساختاریه نه عمدی، و knowledge bundle ها asymmetry رو به ارث میبرن بدون اینکه انتخابش کنن.
discipline یادداشتهای dated اینجا مهمه. نسخهی غلط یادداشت همونیه که یه session آینده بهش اعتماد میکنه. edit های آروم نسخهی غلط رو حذف میکنن ولی هیچ رکوردی از اینکه نسخهی غلط یه زمانی سؤلبرانگیز بود به جا نمیذارن. یه dated callout تو یادداشت، که سؤالی که چک اصلی جواب داده و سؤالی که چک بعدی میخواد بپرسه رو named میکنه، همون چیزیه که تله رو میبنده. از drift شدن portable claims جلوگیری نمیکنه. از این جلوگیری میکنه که خوانندهی بعدی drift رو به ارث ببره بدون اینکه ببیندش.
قانون و تله
یه ادعایی که سه بار verify شده، خطرناکترین شکل یه ادعای غلطه، چون verification تبدیل شده به evidence-by-volume. تعداد چکها evidence درستی نیست؛ سؤالی که هر چک جواب داده evidence درستیه.
دفعهی بعد که یه یادداشت توی knowledge bundle یه ادعایی رو carry forward کنه که exercise بعدی داره falsify ش کنه، سؤال این نیست که «این ادعا درسته یا نه». سؤال اینه که «سؤال اصلی چک چی بوده، و آیا این سؤالیه که این چک میخواد بپرسه». این دوتا به ندرت بدون اینکه گفته بشه با هم coincide میکنن.