METRICS = {"backends": "backends", "renewals": "buyers", "eligible": "buyers", "runway": "months"}
def valid_iso(value):
    parts = value.split("-") if type(value) is str else []
    return len(parts) == 3 and [len(part) for part in parts] == [4, 2, 2] and all(part.isdigit() for part in parts)
def memo_decision(memo, as_of):
    errors = []
    evidence = memo.get("evidence", [])
    for index, row in enumerate(evidence):
        if row.get("kind") not in {"fact", "company-claim", "analyst-inference"} or not row.get("source_id"):
            errors.append(f"evidence_{index}_provenance")
        if not valid_iso(row.get("date", "")) or row.get("date", "") > as_of:
            errors.append(f"evidence_{index}_date")
        age = row.get("age", {})
        if type(age.get("value")) is not int or age.get("unit") != "days":
            errors.append(f"evidence_{index}_age_schema")
        elif age["value"] > row.get("max_age_days", -1):
            errors.append(f"evidence_{index}_stale")
    for name, unit in METRICS.items():
        item = memo.get(name, {})
        if type(item.get("value")) is not int or item.get("unit") != unit:
            errors.append(name + "_schema")
    if type(memo.get("funded")) is not bool or not memo.get("conflict_record"):
        errors.append("funding_or_conflict_record")
    failed = []
    if not errors:
        if memo["backends"]["value"] < 2:
            failed.append("portability")
        if memo["renewals"]["value"] < 3:
            failed.append("renewals")
        if not memo["funded"]:
            failed.append("financing")
    return {"decision": "invalid" if errors else ("wait" if failed else "partner"),
            "errors": sorted(set(errors)), "failed_gates": failed}
memo = {"scenario": "anonymized tooling-company base case",
        "evidence": [{"claim": "two backend runs passed", "kind": "fact",
                      "source_id": "scenario:portability-log", "date": "2026-08-10",
                      "age": {"value": 4, "unit": "days"}, "max_age_days": 90},
                     {"claim": "three of four eligible buyers renewed", "kind": "company-claim",
                      "source_id": "scenario:renewal-ledger", "date": "2026-08-01",
                      "age": {"value": 13, "unit": "days"}, "max_age_days": 90},
                     {"claim": "partnering is bounded", "kind": "analyst-inference",
                      "source_id": "scenario:memo-analysis", "date": "2026-08-14",
                      "age": {"value": 0, "unit": "days"}, "max_age_days": 90}],
        "backends": {"value": 2, "unit": "backends"}, "renewals": {"value": 3, "unit": "buyers"},
        "eligible": {"value": 4, "unit": "buyers"}, "runway": {"value": 18, "unit": "months"},
        "funded": True, "conflict_record": "analyst has no financial interest"}
base_result = memo_decision(memo, "2026-08-14")
bad_evidence = [{key: value for key, value in memo["evidence"][0].items() if key != "source_id"}, *memo["evidence"][1:]]
bad_result = memo_decision({**memo, "evidence": bad_evidence}, "2026-08-14")
portability_result = memo_decision({**memo, "backends": {"value": 1, "unit": "backends"}}, "2026-08-14")
renewal_result = memo_decision({**memo, "renewals": {"value": 2, "unit": "buyers"}}, "2026-08-14")
assert base_result["decision"] == "partner"
assert bad_result["decision"] == "invalid" and "evidence_0_provenance" in bad_result["errors"]
assert portability_result["failed_gates"] == ["portability"] and renewal_result["failed_gates"] == ["renewals"]
print(f"PASS: 86 company memo base={base_result['decision']} invalid={bad_result['errors']} portability={portability_result['decision']} renewals={renewal_result['decision']}")
