STAGES = ("target_property", "computed_result", "synthesized_phase",
          "cycling_validation", "operating_outcome")
def inspect_chain(dossier, minimum_cycles):
    errors = []
    if type(dossier.get("scenario")) is not str or not dossier.get("source_ids"):
        errors.append("scenario_or_sources")
    links = dossier.get("links", {})
    for stage in STAGES:
        row = links.get(stage)
        if type(row) is not dict or type(row.get("evidenced")) is not bool:
            errors.append(stage + "_schema")
        elif type(row.get("value")) in (int, float) and not row.get("unit"):
            errors.append(stage + "_unit")
    if not dossier.get("classical_baseline"):
        errors.append("classical_baseline")
    first_gap = next((stage for stage in STAGES if not links.get(stage, {}).get("evidenced")), None)
    cycles = links.get("cycling_validation", {}).get("value", 0)
    decision = "invalid" if errors else (
        "product-test" if first_gap is None and cycles >= minimum_cycles else "scientific-option")
    return {"decision": decision, "errors": sorted(set(errors)),
            "first_gap": first_gap, "validated_cycles": cycles}
dossier = {"scenario": "layered cathode claim chain", "source_ids": ["quantum-chemistry-review"],
           "classical_baseline": "DFT plus measured incumbent cathode",
           "links": {
               "target_property": {"evidenced": True, "value": 220, "unit": "mAh/g"},
               "computed_result": {"evidenced": True, "value": 0.18, "unit": "eV"},
               "synthesized_phase": {"evidenced": True, "value": 1, "unit": "sample"},
               "cycling_validation": {"evidenced": False, "value": 0, "unit": "cycles"},
               "operating_outcome": {"evidenced": False, "value": 0, "unit": "pack tests"}}}
base_result = inspect_chain(dossier, 100)
bad = {**dossier, "links": {**dossier["links"],
       "computed_result": {"evidenced": True, "value": 0.18, "unit": ""}}}
bad_result = inspect_chain(bad, 100)
validated = {**dossier, "links": {name: {**row, "evidenced": True,
             "value": 120 if name == "cycling_validation" else row["value"]}
             for name, row in dossier["links"].items()}}
validated_result = inspect_chain(validated, 100)
assert base_result["first_gap"] == "cycling_validation" and base_result["decision"] == "scientific-option"
assert bad_result["decision"] == "invalid" and "computed_result_unit" in bad_result["errors"]
assert validated_result["decision"] == "product-test"
print(f"PASS: 66 materials chain gap={base_result['first_gap']} invalid={bad_result['errors']} validated={validated_result['validated_cycles']}cycles decision={validated_result['decision']}")
