Production Engineering
Use evaluation, observability, deployment, and evidence to prove the system is reliable under real constraints.
How do we prove reliability and complete deployment, portfolio evidence, and interview communication?Concept calibration
Verification & Evaluation
- What it is
- Use tests, schemas, citations, state, and acceptance rules to verify outputs, then measure system behavior across datasets.
- What it is not
- It is not asking a model for another opinion about its own output; verification must resolve to externally inspectable evidence.
Observability
- What it is
- Use structured logs, traces, metrics, and version data to explain what happened during a system run.
- What it is not
- It is not just terminal output; logs without correlation IDs, state transitions, and privacy boundaries are hard to diagnose.
Harness
- What it is
- The runtime control environment that hosts models, tools, state, permissions, logs, budgets, human approval, and recovery.
- What it is not
- It can constrain risk and preserve evidence, but it cannot directly prevent model hallucinations.
Evaluation, Observability, Deployment & Reliability
Build eval sets, tracing, quality and cost metrics, deployment, rollback, and incident drills.
Python 3.12 · pytest · Pydantic · SQLite · deterministic MockConcept calibration\n\nPut the concepts used in this module back inside their engineering boundaries before you work with the code.\n\n\n\n### Verification & Evaluation evaluation\n\n- What it is: Verification checks one result with tests, schemas, citations, state, or acceptance rules; evaluation measures behavior across runs with datasets and metrics.\n- What it is not: It is not asking the model for another opinion about its own answer; pass or fail must resolve to externally inspectable evidence.\n- Relationship to adjacent concepts: The agent loop relies on verification to stop, RAG needs layered evaluation, planning needs node acceptance, and observability supplies run records.\n- Where it lives in HeatStack Forge: Forge preserves contract tests and evidence for each run, then compares quality, latency, cost, permission, and recovery across fixed scenarios.\n- Typical misuse and correction: A common misuse treats one aggregate score as the whole conclusion. Define layered metrics, failure samples, and version baselines, then review product risk.\n\n### Observability observability\n\n- What it is: Structured logs, traces, metrics, state transitions, and version information that explain a run and support failure diagnosis and version comparison.\n- What it is not: It is not merely terminal output or unlimited input recording; logs without correlation IDs, state transitions, or privacy boundaries are hard to diagnose and may leak data.\n- Relationship to adjacent concepts: The harness emits runtime events, the agent loop and tool calls form traces, evaluation aggregates metrics, and memory and recovery depend on versioned records.\n- Where it lives in HeatStack Forge: Forge creates an operation_id for each task and records stage, tool, latency, cost, error class, state change, and evidence path while filtering sensitive data.\n- Typical misuse and correction: A common misuse adds logs only after failure. Define events and correlation fields with the contract, then use fault injection to prove the timeline can be reconstructed.\n\n### Harness harness\n\n- What it is: The runtime control environment that hosts models, tools, state, permissions, logs, budgets, human approval, isolation, and recovery.\n- What it is not: It can reduce risk, reject actions, and preserve evidence, but it cannot guarantee that model output is always correct or replace domain acceptance checks.\n- Relationship to adjacent concepts: The agent loop runs inside the harness; tool, memory, and MCP connections obey its policies; observability records execution and evaluation judges behavior.\n- Where it lives in HeatStack Forge: The Forge harness manages workspace, tools, approval queue, budget, checkpoints, audit logs, and rollback, separating model suggestions from real side effects.\n- Typical misuse and correction: A common misuse treats a system prompt as a security boundary. Enforce permissions, paths, network access, secrets, budgets, and rollback outside the model.\n\n
Define evaluation cases with stable IDs, inputs, and acceptance criteria while rejecting duplicates
Start with a concrete problem
Evaluation cases need stable identifiers, otherwise duplicates break traceability
You are building an evaluation dataset to hold multiple evaluation cases. Each case contains an input and an expected output used to verify system behavior.
If two cases share the same case_id, later statistics and tracing become ambiguous: you cannot tell which input produced which result, and you might accidentally overwrite an existing case.
Currently, EvalDataset.validate() only checks that the version and case list are non-empty; it does not check that case_id values are unique.
Therefore, when test_duplicate_case_ids_are_rejected constructs two cases with case_id “same”, validate() does not raise an exception, causing the test to fail.
Make a prediction
In EvalDataset.validate(), besides checking that version and cases are non-empty, what additional check is needed to reject duplicate case IDs?
- Check that every case’s expected field is non-empty
- Check that all case_id values are unique
- Check that version starts with ‘v’
- Check that input contains specific keys
Reasoning guide: The correct answer is to check that all case_id values are unique. The test test_duplicate_case_ids_are_rejected expects a ValueError containing “unique” when two cases have the same ID. Other checks may be useful but are not required by this test.
What it is
An evaluation dataset is a versioned collection of unique cases
EvalDataset contains a version string and a tuple of cases, each with a unique case_id, input, and expected output.
The validate() method checks dataset integrity before use: version and cases are non-empty, case IDs are unique, and each case’s expected is non-empty.
Unique IDs are stable identifiers for evaluation cases, ensuring each case can be independently tracked and referenced.
What it is not
An evaluation dataset does not execute evaluations or compute metrics
It only stores and validates case definitions; it does not run models or compare outputs.
It does not guarantee that case content is business-correct, only that it satisfies structural constraints.
It is not a database; it does not automatically persist or provide query interfaces.
How it relates to neighboring concepts
Relationship between EvalCase and EvalDataset
EvalCase is a single evaluation case containing case_id, input, and expected.
EvalDataset aggregates multiple EvalCase objects and adds version information.
The validate() method iterates over all cases, checking ID uniqueness and non-empty expected to ensure the dataset is usable.
Boundary decision for this stage: When a dataset contains duplicate case_id values, validate() must raise a ValueError because duplicate IDs make evaluation results untraceable.
Compute accuracy, citation coverage, and tool success from case-level results while retaining denominators
Start with a concrete problem
How can we aggregate meaningful overall quality metrics from multiple case results?
You already have the CaseResult dataclass that records pass status, citation requirements, and tool calls for a single case, but there is no function yet to aggregate these case results into overall quality metrics.
If you manually compute accuracy and citation coverage, it is error-prone, and when a metric has no applicable cases (for example, no citation requirements), a zero denominator leads to division by zero or an incorrect zero score.
In this stage you need to implement the summarize() function that takes a tuple of CaseResult objects and returns a dictionary containing case count, accuracy, citation coverage, and tool success, while correctly handling zero denominators.
Make a prediction
Before implementing summarize(), predict: when a metric’s denominator is zero (for example, no citation requirements), what value should that metric return?
- Return 0.0 because there are no successful cases
- Return 1.0 to indicate the metric is not applicable and should be considered successful
- Raise an exception because it cannot be computed
- Return None to indicate missing data
Reasoning guide: The correct answer is to return 1.0. A zero denominator means there are no applicable cases for that metric, so the system should not be penalized; this vacuous truth semantics is common in quality metrics, for example citation coverage should be considered fully satisfied when no citations are required.
What it is
What quality metric aggregation is
Quality metric aggregation is the process of combining discrete case-level results (pass/fail, valid citations, successful tool calls) into overall ratios, while preserving each metric’s denominator (total applicable cases) to reflect system performance in relevant scenarios.
The summarize() function takes a tuple of CaseResult objects and returns a dictionary where accuracy is the proportion of correct cases, citation_coverage is the proportion of valid citations out of required citations, and tool_success is the proportion of successful tool calls out of attempted calls.
What it is not
What quality metric aggregation is not
It is not a detailed review of individual cases or a subjective evaluation of model output; it only performs arithmetic aggregation based on structured fields already recorded in CaseResult.
It does not involve tracing, budgets, or any runtime context, and it does not decide whether cases should be included; those decisions are made by the upstream evaluation process.
How it relates to neighboring concepts
Relationship to other concepts
CaseResult is the input dataclass, summarize() consumes it and produces a metrics dictionary; ratio() is a helper function that safely computes ratios, handling zero denominators.
These metrics provide data for later observability dashboards and evaluation reports, but they do not themselves produce logs or traces.
Boundary decision for this stage: When the denominator is zero, the metric should return 1.0 (vacuous truth) rather than 0.0 or raising an exception, because zero applicable cases means there is no failure and the system should not be penalized.
Aggregate run cost and latency and produce an actionable release gate for budget violations
Start with a concrete problem
How can we determine if a run is within cost and latency budgets?
Before release, we need a clear budget-checking function that takes actual cost, actual latency, and a budget object, and returns the names of dimensions that exceed the budget.
The codebase currently lacks the forge/reliability/budgets.py file, so tests fail at import time.
The test test_over_budget_dimensions_are_named expects that when cost 1.5 exceeds budget 1.0, the function returns ('cost',), while test_exact_budget_is_allowed expects an empty tuple when cost 1.0 and latency 1000 exactly equal the budget.
You need to create the file, define the Budget dataclass and check_budget function, and ensure the comparison logic is correct.
Make a prediction
If the actual cost exactly equals the budget limit, what should check_budget return?
- A tuple containing ‘cost’, because reaching the limit means exceeding the budget
- An empty tuple, because being equal to the limit is still within the allowed range
- A tuple containing ‘latency’, because latency might also equal the limit
- Raise an exception, because equality is a boundary case
Reasoning guide: The budget limit is the maximum allowed value; being equal to it means not exceeding, so it should not be considered a violation. Returning an empty tuple indicates all dimensions are within budget.
What it is
What budget checking is
Budget checking is a pure function that compares actual measurements against budget limits and returns the names of all dimensions that exceed the budget.
It only performs numeric comparison and does not involve release gates or rollback decisions.
A violation occurs only when the actual value is strictly greater than the limit; equality is allowed.
What it is not
What budget checking is not
It is not a release gate system; it does not automatically block deployment or trigger rollback.
It does not handle negative inputs; negative measurements should be considered invalid and raise an exception.
It does not modify the budget object or measurements; it only returns the violating dimensions.
How it relates to neighboring concepts
Relationships with other components
The Budget dataclass defines the budget limits, and check_budget uses these limits for comparison.
The test file tests/test_stage.py imports Budget and check_budget to verify their behavior.
This module is independent of the tracing module but may be called by the release process in the future.
Boundary decision for this stage: Budget checking only compares numbers, not release gates or rollback; negative inputs should raise an exception, and equality to the limit is allowed.
Bind evaluation, migration, and security checks to an immutable release manifest before promotion
Start with a concrete problem
A release candidate missing the security gate is promoted
The file forge/reliability/deployment.py does not exist yet, so both tests in tests/test_stage.py fail at import with ModuleNotFoundError: No module named 'forge.reliability.deployment'.
Even if we create the file and implement a simple promote function that only checks for a version and returns a promotion string, test_missing_security_gate_blocks_promotion will still fail because a manifest lacking the security gate is incorrectly labeled as promoted.
You need to implement an immutable ReleaseManifest dataclass and a promote function that validates the release identity (non-empty version and artifact SHA256 length 64) and checks that all required gates (tests, evaluation, security, migration) are present, otherwise raising a ValueError containing the missing gate names.
Make a prediction
When implementing the promote function, what happens if you only check that manifest.version is non-empty and then return the promotion string?
- Both tests pass because having a version is sufficient for promotion.
test_complete_release_is_promotedpasses, buttest_missing_security_gate_blocks_promotionfails because a manifest missing the security gate is incorrectly promoted.- Both tests fail because an exception should be raised when the security gate is missing.
test_missing_security_gate_blocks_promotionpasses, buttest_complete_release_is_promotedfails.
Reasoning guide: The correct answer is the second option. Checking only for a version does not prevent a manifest missing the security gate from being promoted, so the second test fails. You need to compare passed_gates with the required gate set and raise a ValueError when gates are missing.
What it is
What release promotion gates are
Release promotion gates are a set comparison between an immutable release manifest (ReleaseManifest) and a required gate set (REQUIRED_GATES).
The promote function first validates the release identity (non-empty version and artifact SHA256 length 64), then computes missing gates = required gates - passed gates, and if the missing set is non-empty it raises a ValueError containing the missing gate names; otherwise it returns a promotion string starting with promoted:.
What it is not
What release promotion gates are not
Release promotion gates do not perform actual deployment, rollback, or any infrastructure operations; they only check whether the gate set is complete.
They are also not a comprehensive evaluation of release quality; they only verify that all required gates have passed, without caring about specific metrics or scores within each gate.
How it relates to neighboring concepts
Relationship to other concepts
Release promotion gates build on the reliability checking ideas from the Stage 04 budgets module, but focus on pre-release gate set validation.
They relate to observability because promotion decisions should be based on observable run records and test results, not on the model’s subjective judgment.
They complement the Harness’s isolation and permission controls: the Harness handles runtime security, while release promotion gates handle static pre-release gate checks.
Boundary decision for this stage: Release promotion only checks the gate set, not actual deployment or rollback; if any required gate is missing, it must raise an exception to block promotion.
Compare baseline and canary error/latency metrics and recommend rollback under explicit thresholds
Start with a concrete problem
When should an automatic rollback be recommended for a canary version?
When deploying a new version, we typically route a small portion of traffic to a canary instance and observe its health metrics.
If the canary’s error rate or latency is significantly higher than the baseline, the system should automatically recommend a rollback rather than waiting for manual judgment.
However, statistical fluctuations in small samples are large, and triggering a rollback based on only a few requests would cause false alarms and waste deployment resources.
Therefore, we need to implement a function that, given a minimum sample size, compares baseline and canary error rates and latency, and provides a rollback recommendation.
Make a prediction
When implementing the rollback decision function, which approach is most reasonable?
- Immediately roll back if the canary error rate is higher than baseline, without considering sample size.
- First check if the canary request count meets the minimum sample size; if not, return insufficient sample, otherwise compare error rate and latency.
- Only compare latency, ignoring error rate, because latency better reflects user experience.
- Let the model decide whether to roll back regardless of metrics.
Reasoning guide: The correct approach is to first check the minimum sample size to avoid false rollbacks due to small-sample statistical fluctuations; then compare error rate and latency against thresholds.
What it is
What the rollback decision function is
The rollback decision function is a pure function that takes baseline health metrics, canary health metrics, and a minimum request count, and returns whether rollback is needed along with a tuple of reasons.
It uses explicit threshold rules: error rate exceeding twice the baseline and at least 2%, or latency exceeding 1.5 times the baseline, triggers a rollback recommendation.
The function does not perform the actual rollback; it only provides the decision basis for upper-level systems to take action.
What it is not
What the rollback decision function is not
It is not an operation that actually performs a rollback; it does not modify deployment state or send notifications.
It is not a statistical testing tool; it does not compute confidence intervals or perform hypothesis testing, only simple threshold comparisons.
It does not collect metric data; the input health metrics are provided by external systems.
How it relates to neighboring concepts
Relationship with other components
The function depends on the Health data class, which encapsulates request count, error count, and p95 latency.
It is directly called by two test cases in tests/test_stage.py to verify its behavior.
In the deployment pipeline, this function sits in the canary analysis phase and provides decisions for subsequent rollback operations.
Boundary decision for this stage: Rollback decisions are based only on health metrics, not actual rollback or incident recording; when the sample size is insufficient, return an insufficient-sample state to avoid misjudgment.
Record detection, mitigation, recovery, and review timestamps while validating recovery objectives and evidence
Start with a concrete problem
Why is an ordered timeline a prerequisite for trustworthy recovery metrics?
In an incident drill, the four timestamps for detection, mitigation, recovery, and review must be recorded in chronological order; otherwise, the computed recovery time is meaningless.
The file forge/reliability/incident_drill.py does not exist yet, so the tests fail immediately when importing DrillRecord and verify_drill; therefore, the module must be created from scratch.
If we only compute recovered_at - detected_at without checking timestamp order, an impossible sequence like detected_at=100, mitigated_at=80 would be accepted, leading to a false recovery objective judgment.
This stage requires implementing verify_drill(), which must validate that the timeline is monotonically increasing and evidence is non-empty before computing recovery time and judging the objective.
Make a prediction
When implementing verify_drill(), what should the function do if the timestamps are out of order?
- Still compute recovery time but return
objectiveMet=False - Raise a
ValueErrorand reject the record - Automatically reorder the timestamps and then compute
- Ignore the order issue and only check if evidence is empty
Reasoning guide: The correct approach is to raise a ValueError, because timeline order is a prerequisite for the validity of recovery metrics and cannot be silently corrected or ignored.
What it is
What incident drill verification is
Incident drill verification is a pure function that takes a DrillRecord and a recovery objective in seconds, returning a dictionary with recovery seconds and whether the objective was met.
It first checks that the four timestamps are monotonically increasing, then checks that the evidence tuple is non-empty, and only then computes recovery time and compares it to the objective.
This verification depends only on input data and does not involve actual deployment or rollback operations, so it can be safely used for drill review.
What it is not
What incident drill verification is not
It is not an actual incident response system; it does not trigger alerts or execute rollbacks, only performs static checks on drill records.
It does not generate timestamps or evidence; those must be provided by external systems, and verification only judges their plausibility.
It does not guarantee that the recovery objective is met; it objectively computes and returns a boolean based on the input data.
How it relates to neighboring concepts
Relationship to other components
DrillRecord is the data carrier, using dataclass(frozen=True) to ensure immutability and prevent accidental modification during verification.
verify_drill() depends on the fields of DrillRecord but is independent of any storage or network layer, making it easy to unit test.
This module sits alongside other reliability components like rollback.py, collectively forming an incident handling toolkit, but this stage focuses only on verification logic.
Boundary decision for this stage: The verification function must reject invalid input before computing any metrics; otherwise, subsequent metrics would be built on untrustworthy data.
Complete the chapter
Create an observable release covering quality, latency, cost, failure, and rollback.
Local lab self-check
- Not started
- 2Reading
- 3Lab downloaded
- 4Test result read
- 5Local check passed
verification.json is parsed only in this browser and is never uploaded. This checks the lab contract; it is not server certification or third-party endorsement.
Concept calibration and one-week review
Three questions check the chapter's boundaries, delivery evidence, and recovery path. Answers stay in this browser.