AWS Builder Workshop

Build with Kiro: Etch Process Window Risk Test Automation Workshop

Workshop Series

AWS Factory Automation Portal

Duration: 2 hours
Audience: Professional developers building semiconductor process-control services and test automation
Primary AWS AI service: Kiro
Workshop focus: Kiro-assisted test design, edge-case generation, and review for etch process-window risk code
Standalone outcome: Developers build a test-first workflow using Kiro to validate etch chamber risk mapping, process-window drift events, automation control slip, and non-regression of existing factory events.


Summary

This workshop guides developers through Kiro-assisted test automation for etch process-window risk mapping. Participants create test-first plans, implement a TypeScript mapper, strengthen weak generated tests, cover missing fields, timeline semantics, multi-factor arrays, and non-regression behavior, while preserving direct source telemetry. Additional labs address boundary-value review and debugging guidance without adding calculations or broad refactoring to production persistence learning exercises safely.


1. Workshop Goal

This workshop adds hands-on developer labs focused on Kiro-assisted testing. Instead of building a full application, developers use Kiro to expand tests around an etch process-window risk mapper. The labs teach how to ask Kiro for meaningful tests, identify weak generated tests, improve coverage, and protect event semantics.

The scenario focuses on a plasma etch chamber where pressure, RF power variation, endpoint signal stability, gas flow, and chamber temperature can approach process-control boundaries. The code examples persist direct source values for later process-engineering analysis.


2. Learning Objectives

Developers will learn to:

  1. Use Kiro to generate a test plan before implementation.
  2. Build a TypeScript mapper for etch process-window risk events.
  3. Generate tests for positive cases, negative cases, missing fields, timeline fields, and multi-factor arrays.
  4. Ask Kiro to critique weak tests.
  5. Add table-free readable test cases for professional developers.
  6. Use review prompts to keep tests aligned with manufacturing risk.

3. Lab Agenda

Time Lab Developer output
0:00-0:10 Lab 1: Test-first spec Test plan from Kiro
0:10-0:25 Lab 2: Etch mapper etchRiskMapper.ts
0:25-0:45 Lab 3: Core tests Positive and negative tests
0:45-1:05 Lab 4: Weak test critique Kiro review output
1:05-1:25 Lab 5: Edge-case tests Missing fields and empty factors
1:25-1:40 Lab 6: Timeline tests Event, compute, and factor time
1:40-1:52 Lab 7: Non-regression tests Existing factory event behavior
1:52-2:00 Lab 8: Final coverage review PASS/FAIL coverage report

4. Lab 1 — Kiro Test-First Prompt

Prompt rule 1

Prompt goal: Ask Kiro for test coverage before implementation.

Create a test plan for an etch process-window risk mapper. The mapper should return records only for ETCH_PROCESS_WINDOW_RISK events and return null for unrelated factory events.

AI generative result: Kiro may generate a simple happy-path test and one unrelated event test.

Explanation: This is a reasonable start but not enough for a semiconductor process-risk feature.

Why result is not good: It may miss multi-factor array handling, optional-field behavior, time semantics, and preservation of source telemetry values.

Prompt rule 2

Why rule 2 can fix previous issue: This expands the test plan to include process-engineering risks.

Expand the test plan. Include two risk_factors, missing risk_factors, missing optional fields, distinct event_time and risk_compute_time, distinct factor_time, and rejection of EQUIPMENT_ALARM and AUTOMATION_CONTROL_COMMAND.

AI generative result: Kiro should produce a stronger test plan with coverage categories.

Explanation: The test plan now reflects real event-stream edge cases.

System design decision

  1. Test-first development helps developers define behavior before accepting generated implementation. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. Factory events are often incomplete or partially populated, so optional-field tests are required. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. Time semantics must be tested because event ordering is critical for incident analysis. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

5. Lab 2 — Generate Etch Risk Mapper

Prompt sample

Create src/etchRiskMapper.ts. Return null unless event_type is ETCH_PROCESS_WINDOW_RISK. For eligible events, return one riskSummary and one riskFactor per risk_factors array item. Store direct source values or null. Do not calculate or convert values.

Expected code

export type EtchRiskRecordSet = {
    riskSummary: Record<string, string | null>;
    riskFactors: Record<string, string | null>[];
};

export function mapEtchRiskEvent(message: any): EtchRiskRecordSet | null {
    if (message?.event_type !== "ETCH_PROCESS_WINDOW_RISK") {
        return null;
    }

    const riskSummary = {
        risk_event_id: message.risk_event_id || null,
        fab_id: message.fab_id || null,
        tool_id: message.tool_id || null,
        chamber_id: message.chamber_id || null,
        wafer_lot_id: message.wafer_lot_id || null,
        recipe_version: message.recipe_version || null,
        process_step: message.process_step || null,
        process_window_risk_level: message.process_window_risk_level || null,
        etch_uniformity_risk: message.etch_uniformity_risk || null,
        drift_velocity: message.drift_velocity || null,
        yield_exposure_level: message.yield_exposure_level || null,
        automation_control_slip_probability: message.automation_control_slip_probability || null,
        event_time: message.event_time || null,
        risk_compute_time: message.risk_compute_time || null
    };

    const riskFactors = (message?.risk_factors || []).map((factor: any) => ({
        factor_id: factor.factor_id || null,
        risk_event_id: message.risk_event_id || null,
        sensor_name: factor.sensor_name || null,
        sensor_value: factor.sensor_value || null,
        control_boundary: factor.control_boundary || null,
        unit: factor.unit || null,
        risk_contribution: factor.risk_contribution || null,
        factor_time: factor.factor_time || null
    }));

    return { riskSummary, riskFactors };
}

Business logic explanation: The mapper captures etch process-window risk evidence for later process engineering analysis.

Code logic explanation: It uses exact event matching, creates a summary, maps all risk factors, and preserves source values.

Expected result: Eligible events return records; unrelated events return null.

System design decision

  1. Exact event matching avoids processing unrelated factory events. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. Source-string storage keeps telemetry comparable with stream messages. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. A mapper-only lab isolates testing from database concerns. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

6. Lab 3 — Core Tests

Prompt sample

Generate Vitest tests for mapEtchRiskEvent. Include one eligible event with two risk_factors and one unrelated equipment alarm.

Expected test code

import { describe, expect, it } from "vitest";
import { mapEtchRiskEvent } from "../src/etchRiskMapper.js";

describe("mapEtchRiskEvent core behavior", () => {
    it("maps etch process-window risk event with two factors", () => {
        const result = mapEtchRiskEvent({
            event_type: "ETCH_PROCESS_WINDOW_RISK",
            risk_event_id: "etch_risk_evt_001",
            fab_id: "FAB-HK-ADV-01",
            tool_id: "ETCH-CHAMBER-12",
            chamber_id: "CHAMBER-B",
            wafer_lot_id: "LOT-HPC-55210",
            recipe_version: "ETCH-7NM-R19",
            process_step: "PLASMA_ETCH",
            process_window_risk_level: "HIGH",
            etch_uniformity_risk: "ELEVATED",
            drift_velocity: "0.041",
            yield_exposure_level: "ELEVATED",
            automation_control_slip_probability: "0.67",
            event_time: "2026-06-26T10:20:00+08:00",
            risk_compute_time: "2026-06-26T10:20:02+08:00",
            risk_factors: [
                {
                    factor_id: "etch_factor_pressure_001",
                    sensor_name: "chamber_pressure",
                    sensor_value: "14.8",
                    control_boundary: "15.0",
                    unit: "mTorr",
                    risk_contribution: "HIGH",
                    factor_time: "2026-06-26T10:19:58+08:00"
                },
                {
                    factor_id: "etch_factor_rf_002",
                    sensor_name: "rf_power_variation",
                    sensor_value: "2.7",
                    control_boundary: "3.0",
                    unit: "percent",
                    risk_contribution: "MEDIUM",
                    factor_time: "2026-06-26T10:19:59+08:00"
                }
            ]
        });

        expect(result?.riskSummary.risk_event_id).toBe("etch_risk_evt_001");
        expect(result?.riskFactors).toHaveLength(2);
        expect(result?.riskFactors[0].risk_event_id).toBe("etch_risk_evt_001");
    });

    it("returns null for equipment alarm", () => {
        expect(mapEtchRiskEvent({ event_type: "EQUIPMENT_ALARM" })).toBeNull();
    });
});

Business logic explanation: These tests cover the main positive path and rejection of an unrelated event.

Code logic explanation: The tests call the mapper directly and inspect the returned record set.

Expected result: Tests pass.

System design decision

  1. A two-factor positive test proves array handling. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. An alarm negative test protects unrelated operational event semantics. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. Direct mapper tests are fast and deterministic. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

7. Lab 4 — Weak Test Critique

Developer task

Ask Kiro to review a weak test.

Weak test

it("works", () => {
    const result = mapEtchRiskEvent({ event_type: "ETCH_PROCESS_WINDOW_RISK" });
    expect(result).toBeTruthy();
});

Prompt sample

Review this test for an etch process-window risk mapper. Explain why it is weak and suggest better assertions.

Expected Kiro result

The test is weak because it only checks that a result exists. It does not verify summary fields, factor records, parent-child linkage, optional-field behavior, or time semantics.
Better assertions should check risk_event_id, factor count, factor risk_event_id linkage, event_time, risk_compute_time, and null handling for optional fields.

Business logic explanation: A truthy assertion does not prove that process-risk data is useful for investigation.

Code logic explanation: The test fails to inspect mapping output.

Expected result: Developers replace weak assertions with field-level checks.

System design decision

  1. Test quality matters more than test count. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. Field-level assertions protect the persistence contract. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. Kiro review can teach developers to improve generated tests. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

8. Lab 5 — Missing Field and Empty Factor Tests

Prompt sample

Add tests for missing optional fields and missing risk_factors. The mapper should return a summary with null optional fields and zero factors.

Expected tests

it("stores null for missing optional etch summary fields", () => {
    const result = mapEtchRiskEvent({
        event_type: "ETCH_PROCESS_WINDOW_RISK",
        risk_event_id: "etch_missing_fields",
        risk_factors: []
    });

    expect(result?.riskSummary.fab_id).toBeNull();
    expect(result?.riskSummary.tool_id).toBeNull();
    expect(result?.riskSummary.chamber_id).toBeNull();
    expect(result?.riskFactors).toHaveLength(0);
});

it("handles missing risk_factors as zero factors", () => {
    const result = mapEtchRiskEvent({
        event_type: "ETCH_PROCESS_WINDOW_RISK",
        risk_event_id: "etch_no_factors"
    });

    expect(result?.riskSummary.risk_event_id).toBe("etch_no_factors");
    expect(result?.riskFactors).toHaveLength(0);
});

Business logic explanation: Real-time manufacturing events may be incomplete, but an eligible risk event should still be traceable.

Code logic explanation: Optional fields use null fallback, and missing arrays use an empty array fallback.

Expected result: Tests pass without changing mapper code.

System design decision

  1. Optional-field tests prevent accidental strict validation. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. Missing array tests protect runtime stability. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. Null storage keeps missing source data explicit. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

9. Lab 6 — Timeline Tests

Prompt sample

Add a test that proves event_time, risk_compute_time, and factor_time remain separate. Do not merge or rename time fields.

Expected test

it("keeps etch risk timeline fields separate", () => {
    const result = mapEtchRiskEvent({
        event_type: "ETCH_PROCESS_WINDOW_RISK",
        risk_event_id: "etch_timeline_001",
        event_time: "2026-06-26T10:20:00+08:00",
        risk_compute_time: "2026-06-26T10:20:02+08:00",
        risk_factors: [
            {
                factor_id: "factor_time_001",
                factor_time: "2026-06-26T10:19:58+08:00"
            }
        ]
    });

    expect(result?.riskSummary.event_time).toBe("2026-06-26T10:20:00+08:00");
    expect(result?.riskSummary.risk_compute_time).toBe("2026-06-26T10:20:02+08:00");
    expect(result?.riskFactors[0].factor_time).toBe("2026-06-26T10:19:58+08:00");
});

Business logic explanation: Time separation is required to understand whether sensor risk appeared before stream computation and before automation response.

Code logic explanation: The mapper preserves each time field separately.

Expected result: The test passes.

System design decision

  1. Timeline accuracy is critical for root-cause analysis. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. Separate time fields expose stream-processing delay. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. Tests prevent future refactors from collapsing time concepts. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

10. Lab 7 — Existing Factory Logic Non-Regression

Developer task

Create a small handler that calls the mapper and delegates unrelated events.

Expected code

import { mapEtchRiskEvent } from "./etchRiskMapper.js";

export async function runExistingFactoryLogic(message: any): Promise<string> {
    if (message?.event_type === "EQUIPMENT_ALARM") {
        return "equipment-alarm-processed";
    }

    if (message?.event_type === "AUTOMATION_CONTROL_COMMAND") {
        return "automation-command-processed";
    }

    return "ignored-by-existing-factory-logic";
}

export async function handleEtchRiskMessage(rawMessage: string): Promise<string> {
    const message = JSON.parse(rawMessage);
    const records = mapEtchRiskEvent(message);

    if (records) {
        return "etch-process-window-risk-mapped";
    }

    return runExistingFactoryLogic(message);
}

Business logic explanation: The handler protects existing event behavior while adding etch-risk mapping.

Code logic explanation: The mapper determines eligibility. Ineligible messages go to existing logic.

Expected result: Equipment alarms and automation commands keep their original responses.

Non-regression tests

it("keeps automation command behavior unchanged", async () => {
    const result = await handleEtchRiskMessage(JSON.stringify({
        event_type: "AUTOMATION_CONTROL_COMMAND"
    }));

    expect(result).toBe("automation-command-processed");
});

System design decision

  1. Non-regression tests protect production event routing. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. Mapping eligibility should not change alarm or control command handling. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. A small handler demonstrates integration without database complexity. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

11. Lab 8 — Final Kiro Coverage Review

Prompt sample

Review the etch process-window risk mapper, handler, and tests. Return PASS or FAIL. Check positive events, unrelated events, missing fields, missing risk_factors, timeline fields, and non-regression behavior. Suggest minimal patches only.

Expected Kiro result

PASS
- Positive event with two factors is tested.
- Equipment alarm and automation command behavior are protected.
- Missing optional fields and missing risk_factors are tested.
- Timeline fields remain separate.
- No source values are converted or calculated.

12. Completion Checklist

  • Test-first plan created.
  • Etch risk mapper generated.
  • Core tests added.
  • Weak test critique completed.
  • Optional-field tests added.
  • Timeline tests added.
  • Existing factory logic non-regression test added.
  • Final Kiro coverage review completed.

13. Lab 9 — Boundary Value Review for Etch Sensors

Prompt sample

Create an additional test review checklist for etch sensor values that are near process-control boundaries. Do not calculate new risk values. Check only that source values and control boundaries remain stored as strings.

Expected Kiro result

Additional checklist:
- chamber_pressure source value is stored directly.
- rf_power_variation source value is stored directly.
- control_boundary is stored directly.
- unit is preserved.
- risk_contribution is stored from the source event.
- No value is converted to Number.
- No derived distance-to-boundary field is created.

Business logic explanation: Etch chamber sensors may be close to limits, but the persistence layer should not reinterpret or recalculate the values.

Code logic explanation: The mapper stores sensor values and boundaries as source strings. Any calculation should be implemented in a separate analytical layer.

Expected result: Kiro identifies conversion or calculation as a review concern.

System design decision

  1. Boundary analysis is important, but persistence and analytics should remain separate. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. Source-value preservation allows process engineers to compare stored records with stream events. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. Avoiding derived fields keeps the mapper simple and reviewable. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

14. Lab 10 — Generate a Developer Debugging Guide

Prompt sample

Create a short developer debugging guide for failing etch risk mapper tests. Include failures for wrong event eligibility, missing factor linkage, collapsed time fields, and accidental value conversion.

Expected Kiro result

Debugging guide:
1. If unrelated events return records, check exact event_type matching.
2. If factor linkage fails, check that each factor uses the parent risk_event_id.
3. If timeline tests fail, check event_time, risk_compute_time, and factor_time field names.
4. If value tests fail, remove Number conversion or normalization helpers.
5. If missing risk_factors crashes, use message?.risk_factors || [].

Business logic explanation: Developers need quick troubleshooting steps when generated code fails meaningful factory-risk tests.

Code logic explanation: Each debugging step maps a test failure to a likely code issue.

Expected result: Developers can repair the mapper without broad refactoring.

System design decision

  1. Debugging guidance accelerates learning during hands-on labs. This is a system-design choice because etch process-window risk testing needs narrow contracts that developers can reason about during save-time, test-time, and review-time feedback. The decision keeps the lab focused on observable behavior instead of broad implementation taste, so learners can connect one rule to one operational failure mode without adding unnecessary platform complexity.
  2. Failure modes should map to operational requirements. For etch process-window risk testing, the architecture should preserve source evidence and existing event behavior before optimizing developer convenience. This point makes the boundary explicit: generated assistance may propose changes, but the system remains accountable to traceability, reproducibility, and production non-regression. The result is easier to audit and safer to evolve.
  3. Repair advice should stay minimal to avoid changing validated behavior. The final design point turns the lab action into a durable engineering practice for etch process-window risk testing. It explains how the chosen boundary supports team review, future maintenance, and controlled rollout. By keeping the action minimal and measurable, developers can improve the workflow without hiding risk inside large refactors or implicit assumptions.

Additional Hands-on Developer Labs for Advanced Developers

These additional labs extend the etch process-window risk test automation workshop without repeating the earlier mapper, core tests, weak-test critique, optional-field tests, timeline tests, non-regression handler, boundary review, or debugging guide. The new focus is mutation-style test review, fixture design, contract snapshots, parser hardening, and CI-quality reporting for advanced developers.

15. Lab 11 — Mutation-Style Review of Test Strength

Developer task

Ask Kiro to propose deliberate one-line code mutations and identify which tests should fail. Do not apply the mutations permanently.

Prompt sample

For the etch process-window risk mapper tests, propose mutation-style checks. Include mutations for event eligibility, factor parent linkage, missing risk_factors handling, timeline field mapping, and accidental Number conversion. For each mutation, name the test that should fail.

Expected Kiro result

# Mutation-Style Test Review

## Mutation 1 — Broaden event eligibility
Change:
`message?.event_type !== "ETCH_PROCESS_WINDOW_RISK"`
To:
`!message?.event_type?.includes("RISK")`

Expected failing test:
- returns null for equipment alarm or unrelated factory event

## Mutation 2 — Break parent linkage
Change:
`risk_event_id: message.risk_event_id || null`
To:
`risk_event_id: factor.risk_event_id || null`

Expected failing test:
- maps etch process-window risk event with two factors

## Mutation 3 — Remove missing array fallback
Change:
`message?.risk_factors || []`
To:
`message.risk_factors`

Expected failing test:
- handles missing risk_factors as zero factors

## Mutation 4 — Collapse timeline fields
Change:
`risk_compute_time: message.risk_compute_time || null`
To:
`risk_compute_time: message.event_time || null`

Expected failing test:
- keeps etch risk timeline fields separate

## Mutation 5 — Convert source values
Change:
`sensor_value: factor.sensor_value || null`
To:
`sensor_value: Number(factor.sensor_value || 0)`

Expected failing test:
- preserves etch sensor source values as strings

Business logic explanation: Mutation-style review proves that tests detect dangerous changes instead of only passing the current implementation.
Code logic explanation: Each proposed mutation maps to an existing or newly required assertion.
Expected result: Developers discover weak spots in their test suite before production code changes.

System design decision

  • Mutation-style review validates test intent without introducing a mutation-testing framework into the workshop.
  • Each mutation represents an operationally meaningful failure mode.
  • The lab keeps changes temporary so the production mapper remains simple and traceable.

16. Lab 12 — Reusable Etch Event Fixture Builder

Developer task

Create a test fixture builder that reduces copy-paste while keeping source values explicit.

Prompt sample

Create a Vitest fixture helper for ETCH_PROCESS_WINDOW_RISK events. It should return a complete event with two risk_factors and allow shallow overrides for summary fields and risk_factors. Do not hide important source values behind random data.

Expected fixture helper

export function buildEtchRiskEvent(overrides: Record<string, any> = {}) {
  return {
    event_type: "ETCH_PROCESS_WINDOW_RISK",
    risk_event_id: "etch_fixture_evt_001",
    fab_id: "FAB-HK-ADV-01",
    tool_id: "ETCH-CHAMBER-12",
    chamber_id: "CHAMBER-B",
    wafer_lot_id: "LOT-HPC-55210",
    recipe_version: "ETCH-7NM-R19",
    process_step: "PLASMA_ETCH",
    process_window_risk_level: "HIGH",
    etch_uniformity_risk: "ELEVATED",
    drift_velocity: "0.041",
    yield_exposure_level: "ELEVATED",
    automation_control_slip_probability: "0.67",
    event_time: "2026-06-26T10:20:00+08:00",
    risk_compute_time: "2026-06-26T10:20:02+08:00",
    risk_factors: [
      {
        factor_id: "etch_fixture_pressure_001",
        sensor_name: "chamber_pressure",
        sensor_value: "14.8",
        control_boundary: "15.0",
        unit: "mTorr",
        risk_contribution: "HIGH",
        factor_time: "2026-06-26T10:19:58+08:00"
      },
      {
        factor_id: "etch_fixture_rf_002",
        sensor_name: "rf_power_variation",
        sensor_value: "2.7",
        control_boundary: "3.0",
        unit: "percent",
        risk_contribution: "MEDIUM",
        factor_time: "2026-06-26T10:19:59+08:00"
      }
    ],
    ...overrides
  };
}

Business logic explanation: Fixture builders reduce test maintenance while preserving realistic etch process context.
Code logic explanation: The helper uses deterministic values and explicit overrides instead of generated test data.
Expected result: Advanced tests become shorter without losing source-field visibility.

System design decision

  • Deterministic fixtures prevent flaky tests and make failures easier to review.
  • Explicit source values keep process-engineering context visible in tests.
  • Shallow overrides are enough for this mapper because nested factor changes should stay obvious in individual tests.

17. Lab 13 — Contract Snapshot Without Full Payload Storage

Developer task

Create a contract-style assertion for output field names. The goal is to verify the mapper output shape without snapshotting or storing the full input payload.

Prompt sample

Generate a contract test for mapEtchRiskEvent that verifies the riskSummary field names and riskFactor field names. Do not snapshot the full source event and do not store the raw payload.

Expected test

it("exposes the expected etch risk persistence contract", () => {
  const result = mapEtchRiskEvent({
    event_type: "ETCH_PROCESS_WINDOW_RISK",
    risk_event_id: "etch_contract_001",
    risk_factors: [{ factor_id: "factor_contract_001" }]
  });

  expect(Object.keys(result?.riskSummary || {}).sort()).toEqual([
    "automation_control_slip_probability",
    "chamber_id",
    "drift_velocity",
    "etch_uniformity_risk",
    "event_time",
    "fab_id",
    "process_step",
    "process_window_risk_level",
    "recipe_version",
    "risk_compute_time",
    "risk_event_id",
    "tool_id",
    "wafer_lot_id",
    "yield_exposure_level"
  ].sort());

  expect(Object.keys(result?.riskFactors[0] || {}).sort()).toEqual([
    "control_boundary",
    "factor_id",
    "factor_time",
    "risk_contribution",
    "risk_event_id",
    "sensor_name",
    "sensor_value",
    "unit"
  ].sort());
});

Business logic explanation: Contract tests protect downstream persistence expectations without encouraging raw payload storage.
Code logic explanation: The test asserts output keys only, leaving source values to field-level tests.
Expected result: Field additions, removals, or renames are visible during test review.

System design decision

  • Contract tests are useful when downstream storage expects a stable shape.
  • Snapshotting the full event would conflict with the persistence lesson and make review noisy.
  • Field-name assertions complement value-level tests rather than replacing them.

18. Lab 14 — Malformed JSON Handler Test

Developer task

Add a small handler-level test for malformed JSON input. Keep the mapper unchanged.

Prompt sample

Add a handler-level test for malformed JSON in the etch risk message handler. The handler should return a controlled parse-error result or throw a documented error. Do not change the mapper and do not add broad error handling to field mapping.

Expected Kiro result

export async function handleEtchRiskMessage(rawMessage: string): Promise<string> {
  let message: any;
  try {
    message = JSON.parse(rawMessage);
  } catch {
    return "invalid-json-message";
  }

  const records = mapEtchRiskEvent(message);
  if (records) {
    return "etch-process-window-risk-mapped";
  }
  return runExistingFactoryLogic(message);
}
it("returns a controlled result for malformed JSON", async () => {
  await expect(handleEtchRiskMessage("{not-valid-json")).resolves.toBe("invalid-json-message");
});

Business logic explanation: Event-stream consumers should fail predictably on malformed transport data while keeping valid event mapping rules simple.
Code logic explanation: JSON parsing belongs at the handler boundary, not inside the pure mapper.
Expected result: Invalid transport input is handled separately from process-risk mapping.

System design decision

  • Parser hardening belongs at the system boundary.
  • The mapper should remain focused on eligible event mapping and direct source-field preservation.
  • A documented error result helps operators distinguish malformed input from unrelated factory events.

19. Lab 15 — CI Coverage Gate Report Prompt

Developer task

Ask Kiro to turn the test expectations into a CI-readable review summary.

Prompt sample

Create a CI coverage gate report template for etch process-window risk tests. Include mapper contract, positive event, negative factory events, missing fields, timeline fields, malformed JSON handler behavior, and value-preservation checks. The report should be concise and use PASS/FAIL/N/A.

Expected Kiro result

# Etch Risk CI Coverage Gate Report

## Mapper contract
- Output field contract: PASS/FAIL/N/A
- Exact event eligibility: PASS/FAIL/N/A

## Event behavior
- Eligible ETCH_PROCESS_WINDOW_RISK maps one summary: PASS/FAIL/N/A
- Multiple risk_factors map multiple factor records: PASS/FAIL/N/A
- EQUIPMENT_ALARM returns null or delegates unchanged: PASS/FAIL/N/A
- AUTOMATION_CONTROL_COMMAND delegates unchanged: PASS/FAIL/N/A

## Edge cases
- Missing optional summary fields stored as null: PASS/FAIL/N/A
- Missing risk_factors returns zero factors: PASS/FAIL/N/A
- Malformed JSON handled at boundary: PASS/FAIL/N/A

## Semantics
- event_time and risk_compute_time remain separate: PASS/FAIL/N/A
- factor_time remains factor-level: PASS/FAIL/N/A
- Sensor values and control boundaries remain strings: PASS/FAIL/N/A

## Decision
- Overall gate: PASS/FAIL
- Blocking reason if FAIL:

Business logic explanation: CI reports make test coverage expectations visible to reviewers without requiring them to inspect every test file manually.
Code logic explanation: The report summarizes test outcomes and does not introduce new mapper behavior.
Expected result: Pull requests communicate etch-risk test readiness clearly.

System design decision

  • CI summaries improve reviewer efficiency for advanced test suites.
  • PASS/FAIL/N/A avoids ambiguous prose in automated review output.
  • Coverage gates should report evidence, while human reviewers still evaluate design judgment.

20. Advanced Labs Completion Checklist

  • Mutation-style review completed and weak assertions identified.
  • Reusable deterministic fixture builder created.
  • Contract field-name test added without raw payload snapshotting.
  • Malformed JSON behavior tested at the handler boundary.
  • CI coverage gate report template created.