بازگشت به مهندسی مدرن و کار با هوش مصنوعی · فصل ۵ — Shell، Workspace، Lockfile و Build Closure · 24
Turborepo Task Graph و Cache
میتواند «Turborepo Task Graph و Cache» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.
خلاصهٔ درس
میتواند «Turborepo Task Graph و Cache» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.
خروجی این درس
میتواند «Turborepo Task Graph و Cache» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.
یک Cache Hit سریع میتواند artifact اشتباه را برگرداند
یک workspace کوچک یک build برای library و یک task برای verification دارد. build خروجیای میسازد که هم به source file و هم به APP_FLAVOR وابسته است. اجرای اول cache miss است و اجرای دوم hit میشود. بعد APP_FLAVOR تغییر میکند، اما این متغیر در environment inputهای task declare نشده است. در این حالت Turborepo میتواند همان fingerprint قبلی را معتبر بداند، در حالی که artifact مورد انتظار عوض شده است.
خروجی این درس Task Graph & Cache Contract v1 است. این artifact باید task DAG اعلامشده، file/config inputها، environment مرتبط، outputهای declareشده، پیشبینی invalidation، cache state مشاهدهشده، artifact oracle مستقل و تصمیم محدود را ثبت کند. Cache hit فقط evidence این است که fingerprint پیکربندیشده match شده؛ مستقل از آن ثابت نمیکند input معناییِ declareنشده بیاثر بوده است.
سه مسیر، یک سطح evidence
در مسیر Foundation قبل از اجرا edgeهای task و مرز fingerprint را صریح رسم کن. در Repair فقط یک edge یا input ناقص را جدا کن و probe مربوط به همان مرز را تکرار کن. در Experienced / Fast Path walkthrough فرمانها حذف میشود، اما task graph، tool/runtime identity، mutation evidence، artifact oracle و residual risk باقی میمانند.
قبل از command سؤال evidence را بنویس: «کدام task باید اول تمام شود؟»، «تغییر کدام value باید cache key را عوض کند؟» یا «روی hit کدام fileها باید restore شوند؟». command فقط همان سؤال محدود را جواب میدهد.
مدل ذهنی: DAG → fingerprint → cache → output → oracle
پنج مرز را از هم جدا نگه دار:
- Task DAG:
dependsOnprerequisiteهای task را declare میکند. layout packageها یا convention نامگذاری evidence ترتیب اجرا نیست. - Fingerprint inputs: source/config fileها و task configuration در hash اثر میگذارند.
inputsمیتواند مرز fileهای مؤثر را مشخصتر کند. - Environment inputs: اگر task از یک environment variable استفاده میکند و تغییر آن باید cache را invalidate کند، این dependency معنایی باید در
envیا مرز declareشده مناسب قرار بگیرد. - Declared outputs:
outputsمشخص میکند کدام fileهای تولیدشده cache/restore میشوند. replay شدن log با restore شدن artifact یکی نیست. - Independent oracle: oracle از inputهای مورد انتظار artifact صحیح را مستقل از cache metadata محاسبه میکند؛ بنابراین میتواند یک green signal گمراهکننده را رد کند.
Cache یک memoization layer روی مدل declareشده است. اگر مدل یک input واقعی را جا بیندازد، cache ممکن است کاملاً مطابق configuration رفتار کند و باز هم برای intent مهندسی artifact stale برگرداند.
Task Graph & Cache Contract v1 را بساز
برای هر task/probe مهم این فیلدها را ثبت کن: task، declared_dependencies، declared_inputs، relevant_env، declared_outputs، baseline_cache_state، mutation، predicted_invalidation، observed_cache_state، artifact_oracle، decision و residual_boundary.
سه state را دقیق استفاده کن:
OBSERVED: config field، command output، file/hash یا oracle result که واقعاً دیدهای؛INFERRED: conclusion محدود ساختهشده از observationها؛UNKNOWN: evidence در دسترس نیست یا contradiction حل نشده است.
prediction را قبل از اجرا ثبت کن. اگر بعد از دیدن هر hit/miss فقط توضیحی برای آن بسازی، هنوز یک cache model قابل استفاده نشان ندادهای.
معنی configuration جاری Turborepo برای این درس
مستندات رسمی جاری Turborepo cache reuse را بر اساس fingerprint/hash task inputها و state مرتبط repository/configuration توضیح میدهند. همان reference، dependsOn را برای dependency task، env را برای environment variableهای مؤثر بر task hash، inputs را برای file globهای مؤثر و outputs را برای fileهای تولیدشده قابل cache/restore مستند میکند.
این درس فقط همین سطح محدود را مصرف میکند. قابلیتهای جدیدتر configuration ممکن است تغییر کنند و scope این درس را توسعه نمیدهند. reasoning اصلی ثابت است: اگر task از APP_FLAVOR استفاده کند اما آن variable بیرون fingerprint باشد، تغییرش ممکن است cached result را invalidate نکند. اگر dist/** output declare نشده باشد، cache hit evidence restore شدن آن fileها نیست.
Turborepo برای taskهای cacheable فرض میکند output نسبت به inputهایی که میشناسد deterministic است. oracle مستقل برای همین لازم است: «input شناختهشده برای cache» همیشه با «input معنایی لازم برای artifact مورد انتظار» یکسان نیست.
مثال کارشده: miss → hit → hit گمراهکننده → repair
Baseline: @tol003/core#build از src/source.txt و APP_FLAVOR استفاده میکند، dist/artifact.json میسازد و dist/** را output اعلام میکند. با source و flavor یکسان، اجرای اول باید miss و اجرای تکراری میتواند hit باشد. oracle JSON مورد انتظار را از source hash و flavor دوباره محاسبه میکند.
Undeclared-env mutation: source را ثابت نگه دار، APP_FLAVOR=vanilla را به APP_FLAVOR=chocolate تغییر بده، ولی APP_FLAVOR را هنوز در env declare نکن. prediction این است که cache key ممکن است reusable بماند. اگر artifact قدیمی vanilla restore شد، cache signal میتواند سبز باشد ولی oracle fail کند.
Repair: APP_FLAVOR را به environment inputهای build اضافه کن و chocolate run را تکرار کن. حالا تغییر value داخل fingerprint boundary قرار میگیرد، پس prediction به invalidation/miss تغییر میکند و artifact باید oracle را pass کند.
Graph mutation: @tol003/checker#verify artifact core را مصرف میکند. با dependsOn: ["^build"]، upstream build داخل task graph است. edge را حذف کن و verify را از fixture تمیز اجرا کن. conclusion باید از graph declareشده و artifact availability بیاید، نه از تصور ترتیب packageها.
چهار میانبُر که confidence کاذب میسازند
«Hit یعنی درست است.» repair: artifact restoreشده را با oracle مستقل مقایسه کن.
«فقط source file مهم است.» repair: inputهای غیر source مثل APP_FLAVOR را لیست کن و یک value را بدون تغییر source mutate کن.
«package dependency ترتیب task را واضح میکند.» repair: task edge را cite کن. package dependency و task dependency declaration یکسان نیستند.
«هرچه hit rate بیشتر باشد بهتر است.» repair: قبل از narrow کردن inputs، stale-output risk را ارزیابی کن. گاهی miss بیشتر هزینه لازم برای fingerprint صادقانه است.
برای مهندس باتجربه: cache configuration را contract قابل review ببین
در monorepo واقعی، task configuration را کنار codeی review کن که config، environment، generated file و artifact را مصرف میکند. وقتی build شروع به خواندن env جدید میکند، cache contract باید در همان change review شود. وقتی task یک generated artifact upstream را مصرف میکند، هم dependency edge و هم input/output boundary را بازبینی کن.
از dry-run یا graph inspection بهعنوان evidence declared plan استفاده کن و از execution واقعی و artifact check بهعنوان evidence runtime behavior. telemetry cache در CI برای performance مفید است، اما hit-rate بهتنهایی input معنایی declareنشده را کشف نمیکند.
Remote cache میتواند sharing را بهتر کند، اما identity، trust، credential و network boundary جدید میآورد که عمداً خارج از این lesson محلی هستند.
reuse در برابر stale-output risk
Fingerprint گستردهتر invalidation بیشتری ایجاد میکند و معمولاً hit کمتر میدهد، اما احتمال نادیدهگرفتن change مهم را کم میکند. fingerprint باریکتر فقط وقتی reuse بهتری میدهد که دقیقاً بدانیم task چه inputهایی را مصرف میکند. هدف engineering بیشترین hit rate نیست؛ هدف مدل declareشدهای است که reuse boundary آن با semantics واقعی task برای claim موردنظر همراستا باشد.
Declare کردن همه environment variableها یا همه fileهای repository هم لزوماً طراحی خوبی نیست؛ میتواند reuse مفید را نابود و inputهای واقعی را پنهان کند. کوچکترین boundary کامل و قابل دفاع با mutation evidence را انتخاب کن.
Lab: اول prediction، بعد هر بار یک mutation
از fixture محلی TOL003-LAB1 استفاده کن. python setup_fixture.py فقط داخل lab یک working copy میسازد. fixture شامل دو workspace package، turbo.json، Node scriptهای deterministic، artifact oracle محلی، mutation helper و runnerی است که فقط از turbo موجود استفاده میکند و چیزی download نمیکند.
baseline config و runtime identity را ثبت کن. در محیطی که Turborepo CLI در دسترس است، build را دو بار با APP_FLAVOR یکسان اجرا کن، بعد فقط flavor را تغییر بده در حالی که هنوز declare نشده است. artifact را با artifact_oracle.py مقایسه کن. reset کن، APP_FLAVOR را در env declare کن و دوباره اجرا کن. جداگانه dependency edge مربوط به verify را حذف و از fixture تمیز تست کن. بین mutationها reset انجام بده.
اگر turbo وجود ندارد، TURBO_UNAVAILABLE را بهعنوان missing runtime evidence ثبت کن. hit/miss شبیهسازیشده را جای observation واقعی ننویس.
حداقل evidence قابل دفاع
Task Graph & Cache Contract دفاعپذیر باید exact task config، runtime/tool identity، prediction قبل از اجرا، observed cache state در صورت executable بودن، artifact file/hash یا content، independent oracle result، mutation response و bounded decision داشته باشد.
decision باید حداقل بین GRAPH_EDGE، FINGERPRINT_INPUT، ENV_INPUT، OUTPUT_RESTORE، RUNTIME_OR_TOOL_CONTEXT و UNKNOWN_OR_MULTIPLE تفاوت بگذارد. اگر config با observation contradiction دارد، contradiction را نگه دار و probe را کوچکتر کن. command موفق را به application correctness، remote-cache integrity، package-lock closure یا full toolchain reproducibility تبدیل نکن.
Assessment: diagnosis، decision، application و transfer
AS1 — Diagnosis: بعد از تغییر APP_FLAVOR build cache hit میشود اما artifact flavor قدیمی را دارد. کوچکترین missing evidence boundary را مشخص کن و حداقل یک alternative را رد کن.
AS2 — Decision: تیم hit-rate بالا و output declareشده دارد، اما environment/input inventory یا artifact oracle مستقل ندارد. برای Task Graph & Cache Contract v1 تصمیم ACCEPT، REJECT یا DEFER بده و residual risk را ثبت کن.
AS3 — Application: در محیطی که Turborepo موجود است fixture baseline را اجرا کن، evidence table را کامل کن و mutationهای undeclared-env و task-edge را مستقل انجام بده.
AS4 — Transfer: task جدید consume یک generated file و REGION را میخواند. بدون sequence جواب آماده، مشخص کن کدام graph/input/env/output declarationها باید تغییر کنند، invalidationها را پیشبینی کن و بگو چه چیزی هنوز اثبات نشده است.
مرز source و freshness
claimهای tool-specific به مستندات رسمی جاری Turborepo که در 2026-09-08 بررسی شدهاند محدود هستند. caching guide همچنان fingerprint-based reuse، task outputهای cacheشده، task inputها و فرض deterministic بودن taskهای cacheable نسبت به inputهای شناختهشده را توضیح میدهد. configuration reference نیز dependsOn، env، inputs و outputs را بهعنوان declaration surfaceهای مورد استفاده این درس مستند میکند.
review-due Bible برابر 2026-10-17 است. Turborepo میتواند قابلیتهای جدید configuration اضافه کند؛ این lesson آنها را به core claim تزریق نمیکند. conclusion روشی ثابت میماند: task boundary واقعی را declare کن، invalidation را پیشبینی کن، هر بار فقط یک input را mutate کن و artifact را مستقل verify کن.
در این lab فقط، runner دو کنترل اجرا را صریح میکند: --env-mode=loose باعث میشود APP_FLAVOR عمداً declareنشده به task برسد بدون آنکه خودبهخود داخل hash declare شود، و --cache=local:rw,remote: provenance مربوط به remote cache را از observation حذف میکند. اینها شرط کنترلشدهی آزمایشاند، نه توصیه production.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
AS1 diagnosis
APP_FLAVOR changes, the build reports a cache hit, but the artifact still contains the old flavor. Diagnose the smallest missing evidence boundary and name the deciding observation.
AS2 decision
A team shows a high cache-hit rate and declared outputs but has no environment/input inventory or independent artifact oracle. Decide ACCEPT, REJECT, or DEFER for Task Graph & Cache Contract v1.
AS3 application
Execute the local fixture where Turborepo is available, complete the evidence table, and run undeclared-env plus task-edge mutations independently.
AS4 transfer
A new consume task reads a generated file and REGION. Decide which graph/input/env/output declarations must change and prove invalidation without sequence hints.
ملاکهای ارزیابی (rubric)
- Boundary correctness — critical: identifies graph/fingerprint/output/oracle boundary without expanding the claim.
- Evidence traceability — critical: every material conclusion resolves to config, command output, file/hash, oracle, or explicit UNKNOWN.
- Mutation robustness — critical: prediction and decision change correctly under one targeted mutation.
- Transfer and residual risk: adapts the method to generated-file + REGION context and states what remains unproven.
Any cache-hit-as-correctness claim, invented Turborepo runtime observation, or missing independent oracle on the stale-artifact probe is blocking.
منابع و تازگی
مطالعهٔ موارد (case studies)
فایلهای آزمایشگاه
python setup_fixture.pyرا اجرا کن.- با
python inspect_context.pyهویت runtime/config را ثبت کن. - قبل از هر اجرای Turborepo، prediction مربوط به graph/cache را در
task_graph_cache_contract.csvبنویس. - در محیطی که
turboاز قبل نصب است، build را دو بار با vanilla و سپس یک بار با chocolate در حالیکهAPP_FLAVORهنوز declare نشده اجرا کن؛ بعدpython artifact_oracle.py chocolateرا اجرا کن. - reset کن؛
python mutate_fixture.py declare-envرا اجرا کن و flavor mutation + oracle را تکرار کن. - reset کن؛
python mutate_fixture.py remove-dependency-edgeرا اجرا کن؛ verify را از clean state اجرا و فقط کوچکترین boundary پشتیبانیشده را classify کن.
Runner هیچ Turborepoای download نمیکند. TURBO_UNAVAILABLE یعنی runtime evidence موجود نیست، نه اینکه نتیجه cache شبیهسازی شود.
یادداشت مرز اجرا: runner عمداً از --env-mode=loose استفاده میکند تا مقدار declareنشده به task برسد ولی هنوز داخل hash declare نشده باشد؛ cache نیز فقط local با local:rw,remote: است. این یک شرط کنترلشده برای counterexample آموزشی است، نه توصیه production. هویت دقیق Turbo/Node/Python و cache scope را از inspect_context.py ثبت کن.
رسانه و اسلایدهای درس
فایلهای آموزشی (دانلود)