بازگشت به مهندسی مدرن و کار با هوش مصنوعی · فصل ۵ — Shell، Workspace، Lockfile و Build Closure · 24

Turborepo task graph and cache evidence

Model Turborepo task dependencies and cache inputs/outputs so cache hits are evidence of a declared fingerprint, not proof of correctness. می‌تواند «Turborepo Task Graph و Cache» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.

Turborepo Task Graph و Cache — fa-IR

Lesson summary

Model Turborepo task dependencies and cache inputs/outputs so cache hits are evidence of a declared fingerprint, not proof of correctness.

می‌تواند «Turborepo Task Graph و Cache» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.

This lesson produces

می‌تواند «Turborepo Task Graph و Cache» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.

Who it is for

Foundation

Explicit boundary map, worked baseline, evidence prompts, and a safe local fixture.

Repair

Diagnose one misconception, reduce the fixture, rerun the relevant probe, then restore the full case.

Experienced

Skip command walkthroughs; require artifact, mutation evidence, tradeoff judgment, and residual-risk statement.

Prerequisites

A fast cache hit can still restore the wrong artifact

A small workspace has a library build and an application verification task. The build writes an artifact that depends on the source file and APP_FLAVOR. The first run is a cache miss and the second is a hit. Then APP_FLAVOR changes, but the variable is not declared as a task environment input. Turborepo can legitimately reuse the old fingerprint while the intended artifact has changed.

Your deliverable is Task Graph & Cache Contract v1. It records the declared task DAG, file/config inputs, relevant environment, declared outputs, predicted invalidation, observed cache state, an independent artifact oracle, and the bounded decision. A cache hit is evidence that the configured fingerprint matched; it is not an independent proof that an omitted semantic input was irrelevant.

Three routes, one evidence bar

On the Foundation route, draw the task edge and fingerprint boundary before running anything. On the Repair route, isolate one missing edge or input and rerun only the probe that distinguishes it. On the Experienced / Fast Path, skip command walkthroughs, but keep the task graph, tool/runtime identity, mutation evidence, artifact oracle, and residual risk.

Before a command, write the evidence question: “Which task must finish first?”, “Which value must change the cache key?”, or “Which files must be restored on a hit?”. The command answers that bounded question only.

Mental model: DAG → fingerprint → cache → output → oracle

Keep five boundaries separate:

  1. Task DAG. dependsOn declares prerequisites. Package layout or naming conventions are not evidence of execution order.
  2. Fingerprint inputs. Source/config files and task configuration contribute to the task hash. Explicit inputs can narrow or extend file influence.
  3. Environment inputs. A task that reads an environment variable needs that semantic dependency represented in env or another appropriate declared boundary if a value change must invalidate cache.
  4. Declared outputs. outputs tells Turborepo which task files are cacheable/restorable. A log replay is not the same thing as restoring a produced artifact.
  5. Independent oracle. The oracle computes what the artifact should contain from the intended inputs without consulting Turborepo cache metadata. It can therefore reject a misleading green cache result.

The cache is a memoization layer over the declared model. If the model omits a real input, the cache can behave exactly as configured and still return an artifact that is stale for the engineering intent.

Build Task Graph & Cache Contract v1

For each material task/probe, record: task, declared_dependencies, declared_inputs, relevant_env, declared_outputs, baseline_cache_state, mutation, predicted_invalidation, observed_cache_state, artifact_oracle, decision, and residual_boundary.

Use evidence labels consistently:

  • OBSERVED: a config field, command output, file/hash, or oracle result you actually inspected;
  • INFERRED: a bounded conclusion derived from those observations;
  • UNKNOWN: evidence is unavailable or contradictory.

A prediction made before the run matters. If every miss or hit is explained only after seeing it, you have not demonstrated a usable cache model.

What current Turborepo configuration means for this lesson

Current official Turborepo documentation describes cache reuse as fingerprint/hash matching over task inputs and relevant repository/configuration state. It documents dependsOn as the task dependency relationship, env as environment variables that affect a task hash, inputs as file globs used to decide relevant package changes, and outputs as file globs whose produced files can be cached and restored.

This lesson uses only that bounded surface. Newer configuration capabilities can evolve; they do not expand the lesson claim. The critical reasoning remains: if the task consumes APP_FLAVOR but that value is outside the fingerprint, changing it may not invalidate the cached result. If dist/** is not declared as an output, a cache hit cannot be treated as evidence that those files were restored.

Turborepo also assumes cacheable tasks are deterministic with respect to the inputs it knows. The independent oracle exists precisely because “known to the cache” and “semantically relevant to the intended artifact” can diverge.

Worked example: miss → hit → misleading hit → repair

Baseline. @tol003/core#build reads src/source.txt and APP_FLAVOR, writes dist/artifact.json, and declares dist/** as output. With the same source and flavor, the first run should be a miss and the next identical run can be a hit. The oracle recomputes the expected JSON from the source hash and flavor.

Undeclared-env mutation. Keep the source unchanged, change APP_FLAVOR=vanilla to APP_FLAVOR=chocolate, and leave APP_FLAVOR outside the task env declaration. The prediction is that the cache key may remain reusable. If an old vanilla artifact is restored, the cache signal can still be green while the independent oracle fails.

Repair. Add APP_FLAVOR to the build task's declared environment inputs. Repeat the chocolate run. The changed value now belongs to the fingerprint boundary, so the prediction changes to invalidation/miss followed by an artifact that passes the oracle.

Graph mutation. @tol003/checker#verify consumes the core artifact. With dependsOn: ["^build"], the upstream build is part of the task graph. Remove that edge and run verify from a clean fixture. The correct conclusion comes from the declared graph and observed artifact availability, not from an assumed package order.

Four shortcuts that create false confidence

“Hit means correct.” Repair: compare the restored artifact against an oracle that derives expected content from the intended inputs.

“Only source files matter.” Repair: list non-source semantic inputs such as APP_FLAVOR; mutate one value while keeping source unchanged.

“The package dependency makes the task order obvious.” Repair: cite the task edge. Package dependencies and task dependencies are related but are not interchangeable declarations.

“Higher hit rate is always better.” Repair: evaluate stale-output risk before narrowing inputs. A lower hit rate can be the correct price for a truthful fingerprint.

For experienced engineers: treat cache configuration as a reviewable contract

In a real monorepo, review task configuration alongside the code that consumes configuration, environment, generated files, and artifacts. When a build starts reading a new env variable, the cache contract should be reviewed in the same change. When a task begins consuming an upstream generated artifact, review both the dependency edge and the input/output boundary.

Use dry-run or graph inspection as evidence about the declared plan, then use actual execution and artifact checks as evidence about runtime behavior. CI cache telemetry is useful for performance, but hit-rate alone cannot detect a semantic input that was never declared.

Remote cache can improve sharing across developers and CI, but it adds identity, trust, credential, and network boundaries that are intentionally outside this local lesson.

Reuse versus stale-output risk

A broader fingerprint causes more invalidation and usually fewer hits, but it reduces the chance that a meaningful change is ignored. A narrower fingerprint can improve reuse only when you understand exactly what the task consumes. The engineering goal is not maximal hit rate; it is a declared model whose reuse boundary matches the task's real semantics closely enough for the claim being made.

Declaring every environment variable or every repository file is also not automatically good design. It can destroy useful reuse and hide which inputs actually matter. Prefer the smallest complete boundary you can defend with mutation evidence.

Lab: predict first, mutate one boundary at a time

Use the packaged local fixture TOL003-LAB1. python setup_fixture.py creates a working copy only inside the lab directory. The fixture contains two workspace packages, turbo.json, deterministic Node scripts, a local artifact oracle, mutation helpers, and a runner that uses an existing turbo binary without downloading one.

Record the baseline config and runtime identity. In an environment where Turborepo CLI is available, run the baseline build twice with the same APP_FLAVOR, then change only the flavor while it remains undeclared. Compare the artifact with artifact_oracle.py. Reset, declare APP_FLAVOR in the task env, and repeat. Separately remove the verify task dependency edge and test from a clean fixture. Reset between independent mutations.

If turbo is unavailable, record TURBO_UNAVAILABLE as missing runtime evidence. Do not replace the missing observation with a simulated hit/miss.

Minimum defensible evidence

A defensible Task Graph & Cache Contract contains the exact task config, runtime/tool identity, a pre-run hit/miss prediction, observed cache state when executable, artifact file/hash or content, independent oracle result, mutation response, and a bounded decision.

The decision should distinguish at least GRAPH_EDGE, FINGERPRINT_INPUT, ENV_INPUT, OUTPUT_RESTORE, RUNTIME_OR_TOOL_CONTEXT, and UNKNOWN_OR_MULTIPLE. If config and observation disagree, preserve the contradiction and reduce the probe. Do not turn a successful command into a claim about application correctness, remote-cache integrity, package-lock closure, or full toolchain reproducibility.

Assessment: diagnosis, decision, application, transfer

AS1 — Diagnosis: a build is a cache hit after APP_FLAVOR changes, but the artifact still contains the old flavor. Locate the smallest missing evidence boundary and reject at least one alternative explanation.

AS2 — Decision: a team shows a high cache-hit rate and a declared output, but no environment/input inventory or independent artifact oracle. Decide ACCEPT, REJECT, or DEFER for Task Graph & Cache Contract v1 and state residual risk.

AS3 — Application: execute the local fixture where Turborepo is available, complete the evidence table, and run the undeclared-env and task-edge mutations independently.

AS4 — Transfer: a new consume task reads a generated file and REGION. Without a supplied answer sequence, decide which graph/input/env/output declarations must change, predict invalidations, and state what remains unproven.

Source and freshness boundary

The tool-specific claims are bounded to current official Turborepo documentation verified on 2026-09-08. The caching guide still describes fingerprint-based reuse, cached task outputs, task inputs, and the assumption that cacheable tasks are deterministic relative to known inputs. The configuration reference still documents dependsOn, env, inputs, and outputs as the relevant declaration surfaces used here.

The Bible review-due date is 2026-10-17. Turborepo configuration can evolve; this lesson does not project newer or experimental fields into its core claim. The method-level conclusion is durable: declare the real task boundary, predict invalidation, mutate one input at a time, and verify artifacts independently.

For this lab only, the runner fixes two execution controls: --env-mode=loose makes the intentionally undeclared APP_FLAVOR visible to the task without adding it to the declared hash, and --cache=local:rw,remote: prevents remote-cache provenance from entering the observation. These are controlled lab conditions, not a production recommendation.

Assessment

There is no answer key in this lesson pack; answer it yourself and mark honestly. "Needs review" sends the lesson to your review queue.

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.

lesson ✗AI ✗notes ✗

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.

lesson ✗AI ✗notes ✗

AS3 application

Execute the local fixture where Turborepo is available, complete the evidence table, and run undeclared-env plus task-edge mutations independently.

lesson ✗AI ✗notes ✗

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.

lesson ✗AI ✗notes ✗
Assessment 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.

References & freshness

·
fingerprint-based cache reuse, task outputs, task inputs, deterministic-task assumption
·
dependsOn, env, inputs, outputs only

Case studies

Lab files

  1. Run python setup_fixture.py.
  2. Run python inspect_context.py and record runtime/config identity.
  3. Before each Turborepo run, write the predicted graph/cache result in task_graph_cache_contract.csv.
  4. Where turbo is already installed, run python run_turbo_probe.py vanilla build twice, then python run_turbo_probe.py chocolate build while APP_FLAVOR is still undeclared. Run python artifact_oracle.py chocolate. The runner deliberately uses --env-mode=loose so the undeclared value reaches the task but remains outside the declared hash boundary; it also uses local-only cache (local:rw,remote:).
  5. Reset; use python mutate_fixture.py declare-env; repeat the flavor mutation and oracle check.
  6. Reset; use python mutate_fixture.py remove-dependency-edge; run verify from clean state and classify only the supported boundary.

The runner never downloads Turborepo. TURBO_UNAVAILABLE is missing runtime evidence, not a simulated cache result.

Execution-boundary note: loose environment mode is a controlled teaching condition for this omitted-input counterexample, not a production recommendation. Record resolved Turbo/Node/Python identity and the local-only cache scope from inspect_context.py.

Lesson media & slides

MAKNOW_TOL-003_DECISION_EVIDENCE_TABLE_v1.0.0.svg
DECISION EVIDENCE TABLE v1.0.0.svg
MAKNOW_TOL-003_FAILURE_REPAIR_v1.0.0.svg
FAILURE REPAIR v1.0.0.svg
MAKNOW_TOL-003_PRIMARY_MODEL_v1.0.0.svg
PRIMARY MODEL v1.0.0.svg
MAKNOW_TOL-003_WORKED_EXAMPLE_v1.0.0.svg
WORKED EXAMPLE v1.0.0.svg

Teaching files (download)

XLSXTask Graph and Cache Contract v1 v1.0.0.xlsxTeaching files (download)
DOCXTask Graph Cache Contract v1 WORKSHEET v1.0.0.docxTeaching files (download)
PDFTask Graph Cache Contract v1 WORKSHEET v1.0.0.pdfTeaching files (download)