FIELDS = {"budget_evidence": str, "proof_cycle": dict, "service_intensity": dict,
          "reusable_asset": str, "expiry": str, "hardware_trigger": str, "source_id": str}
def select(wedges, maximum_days, maximum_hours):
    errors = []
    eligible = []
    for name, wedge in wedges.items():
        missing = [field for field, kind in FIELDS.items()
                   if field not in wedge or type(wedge[field]) is not kind or not wedge[field]]
        days, hours = wedge.get("proof_cycle", {}), wedge.get("service_intensity", {})
        if type(days.get("value")) is not int or days.get("unit") != "days":
            missing.append("proof_cycle_schema")
        if type(hours.get("value")) is not int or hours.get("unit") != "hours/customer":
            missing.append("service_intensity_schema")
        if missing:
            errors.append(name + ":" + ",".join(sorted(set(missing))))
        elif days["value"] <= maximum_days and hours["value"] <= maximum_hours:
            eligible.append(name)
    return {"decision": "invalid" if errors else (eligible[0] if len(eligible) == 1 else "no-wedge"),
            "errors": errors, "eligible": sorted(eligible)}
wedges = {
    "benchmark-service": {"budget_evidence": "signed paid discovery", "proof_cycle": {"value": 30, "unit": "days"},
                          "service_intensity": {"value": 30, "unit": "hours/customer"},
                          "reusable_asset": "workload and result schema", "expiry": "2027-02-14",
                          "hardware_trigger": "two portable backends", "source_id": "scenario:buyer-LOI"},
    "bespoke-consulting": {"budget_evidence": "approved project", "proof_cycle": {"value": 90, "unit": "days"},
                           "service_intensity": {"value": 160, "unit": "hours/customer"},
                           "reusable_asset": "customer-only report", "expiry": "2026-11-14",
                           "hardware_trigger": "none before renewal", "source_id": "scenario:SOW"},
    "future-optimizer": {"budget_evidence": "no current budget", "proof_cycle": {"value": 365, "unit": "days"},
                         "service_intensity": {"value": 80, "unit": "hours/customer"},
                         "reusable_asset": "prototype", "expiry": "2026-11-14",
                         "hardware_trigger": "logical resource gate", "source_id": "scenario:interviews"}}
base_result = select(wedges, 60, 60)
bad_wedges = {**wedges, "benchmark-service": {key: value for key, value in wedges["benchmark-service"].items() if key != "expiry"}}
bad_result = select(bad_wedges, 60, 60)
tight_result = select(wedges, 60, 20)
assert base_result["decision"] == "benchmark-service" and base_result["eligible"] == ["benchmark-service"]
assert bad_result["decision"] == "invalid" and "expiry" in bad_result["errors"][0]
assert tight_result["decision"] == "no-wedge" and tight_result["eligible"] == []
print(f"PASS: 79 wedge workbook selected={base_result['decision']} invalid={bad_result['errors']} hours20={tight_result['decision']}")
