{
  "methodology_version": "0.1.0-draft",
  "methodology_url": "./methodology.md",
  "price_basis": "dealer_asking",
  "b": 0.87,
  "segments": {
    "trucks": {
      "label": "Trucks",
      "k": 0.056,
      "five_year_depreciation_pct": 34.2,
      "three_year_depreciation_pct": 27.1
    },
    "hybrids": {
      "label": "Hybrids",
      "k": 0.060,
      "five_year_depreciation_pct": 35.4,
      "three_year_depreciation_pct": null
    },
    "sedans_non_luxury": {
      "label": "Sedans - non-luxury",
      "k": 0.064,
      "five_year_depreciation_pct": 36.8,
      "three_year_depreciation_pct": null
    },
    "sedans_all": {
      "label": "Sedans - all",
      "k": 0.071,
      "five_year_depreciation_pct": 38.9,
      "three_year_depreciation_pct": 29.9
    },
    "suvs": {
      "label": "SUVs",
      "k": 0.091,
      "five_year_depreciation_pct": 44.9,
      "three_year_depreciation_pct": 32.7
    },
    "luxury": {
      "label": "Luxury (sedans)",
      "k": 0.103,
      "five_year_depreciation_pct": 48.1,
      "three_year_depreciation_pct": null
    },
    "evs": {
      "label": "EVs",
      "k": 0.142,
      "five_year_depreciation_pct": 57.2,
      "three_year_depreciation_pct": null
    }
  },
  "source": {
    "five_year": {
      "citation": "iSeeCars 2026 \"Cars That Hold Their Value\" study",
      "url": "https://www.iseecars.com/cars-that-hold-their-value-study"
    },
    "three_year": {
      "citation": "iSeeCars car-color resale study",
      "url": "https://www.iseecars.com/car-color-study"
    },
    "basis": "dealer asking price (listing-aggregated)",
    "retrieved_date": "2026-08-04"
  },

  "valid_age_range": {
    "default_mode_min_age_years": 1.0,
    "anchor_mode_min_purchase_age_years": 1.0,
    "_comment": "Below this, no estimate — see methodology.md 'Valid age range'. In anchor mode, purchase_age is always <= age_now, so a vehicle failing the default-mode floor necessarily fails the anchor-mode floor too; the two checks are independent but never disagree in that direction."
  },

  "mileage_table": {
    "anchors": [
      {"age_years": 0, "annual_rate": 12000},
      {"age_years": 5, "annual_rate": 12000},
      {"age_years": 9, "annual_rate": 7800}
    ],
    "post_anchor_annual_rate": 7800,
    "interpolation_5_to_9yr": "linear",
    "source": {
      "citation": "National Household Travel Survey (NHTS) via DOE/Argonne, 2017 data",
      "basis_note": "12,000 mi/yr (age 0-5) is stated in the source as a floor, not an exact average. 5-9yr linear interpolation is our own bridge across a gap the source doesn't cover directly.",
      "retrieved_date": "2026-08-04"
    }
  },

  "u_terms": {
    "u_base": {
      "no_anchor": 0.17,
      "with_anchor": 0.0,
      "derivation": "Argonne (private-party basis, ~44.5% 5yr retention) vs. iSeeCars (dealer-asking basis, 63.2% 5yr retention for non-luxury sedans): midpoint 53.85%, half-gap 9.35pp, 9.35/53.85 ~ 17%. Our judgment for how to apply the gap, not an externally-sourced percentage."
    },
    "u_extrapolation": {
      "bands": [
        {"min_years": 2.0, "max_years": 8.0, "value": 0.0},
        {"min_years": 1.0, "max_years": 2.0, "value": 0.08},
        {"min_years": 8.0, "max_years": 12.0, "value": 0.08},
        {"min_years": 12.0, "max_years": null, "value": 0.18}
      ],
      "_comment": "Below 1.0yr is not a band -- it's the valid_age_range floor (decline). Applies to effective_age_now in both default and anchor mode."
    },
    "u_segment_ambiguity": {
      "clean": 0.0,
      "fallback_nearby": 0.10,
      "unmapped": 0.20,
      "_comment": "Bucket-wrongness only -- unaffected by whether the input that drove assignment was VIN-verified or self-reported. See u_input_provenance for that orthogonal axis; the two add, they are not one ranked tier."
    },
    "u_input_provenance": {
      "vin_decoded": 0.0,
      "not_vin_decoded": 0.05,
      "_comment": "Independent of u_segment_ambiguity. 0% when segment assignment was driven by VIN-decoded body_class/electrification_level; 5% when driven by user-supplied body_style/powertrain, OR when neither is available yet (nothing self-reported is not more trustworthy than something self-reported). 5% chosen to match u_condition_unknown's existing placeholder magnitude -- same category of number: our judgment, no external basis, applied to unverified/uncollected input. Additive with u_segment_ambiguity: a self-reported luxury SUV carries fallback_nearby (0.10) + not_vin_decoded (0.05) = 0.15, correctly wider than a VIN-verified luxury SUV's 0.10 + 0.0 = 0.10."
    },
    "u_condition_unknown": 0.05,
    "u_anchor_noise": {
      "no_anchor": 0.0,
      "with_anchor": 0.15
    },
    "u_anchor_purchase_age": {
      "bands": [
        {"min_years": 2.0, "max_years": null, "value": 0.0},
        {"min_years": 1.0, "max_years": 2.0, "value": 0.08}
      ],
      "_comment": "Anchor-mode only. Below 1.0yr is the anchor_mode_min_purchase_age_years floor (anchor declines, falls back to default mode)."
    }
  },

  "luxury_makes": [
    "BMW", "MERCEDES-BENZ", "MERCEDES BENZ", "AUDI", "LEXUS", "ACURA",
    "INFINITI", "CADILLAC", "LINCOLN", "GENESIS", "VOLVO", "JAGUAR",
    "LAND ROVER", "PORSCHE", "ALFA ROMEO", "MASERATI", "BENTLEY",
    "ROLLS-ROYCE", "ASTON MARTIN"
  ],

  "out_of_population": {
    "_comment": "Vehicles outside the population the 7 segments were fitted on (iSeeCars excludes heavy-duty trucks/vans, discontinued, and low-volume models -- see methodology.md segment table source note). Two independent signals, combined with OR:",
    "excluded_body_classes": [
      "Fire Apparatus", "Bus", "Bus - School Bus", "Ambulance", "Trailer",
      "Truck-Tractor", "Street Sweeper", "Streetcar/Trolley", "Motorhome",
      "Limousine"
    ],
    "excluded_body_class_prefixes": [
      "Incomplete", "Motorcycle - ", "Off-Road Vehicle - "
    ],
    "excluded_body_classes_note": "VIN path only (adapters.base.VehicleSpec.body_class, from vPIC BodyClass -- see adapters/vpic_taxonomy.py's vocabulary warning for why this is a different field from VehicleType). Dropdown/free-text paths never populate body_class, so this check never fires for them.",
    "excluded_makes": [],
    "excluded_makes_status": "NOT POPULATED -- tried and rejected for this version, not merely not-yet-built. scripts/build_excluded_makes.py sweeps NHTSA's manufacturer registry (GetManufacturerDetails), matched by exact Mfr_CommonName == make name, excluding a make when every declared Passenger Car/MPV VehicleTypes entry has a GVWR floor above 14,000 lb or it declares neither type. On the full 406-make sweep (raw evidence: data/excluded_makes_sweep.json, gitignored) this produced confirmed false positives on TOYOTA, JEEP, and RAM: Toyota/Jeep's exact-matched registry entries have an entirely empty VehicleTypes declaration (data sparsity at the corporate-entity level, not a real heavy-only signal), and Ram's exact-matched entry resolves to Mfr_Name 'THAT TRUCK AND VAN' -- an unrelated small business, apparently mislabeled in NHTSA's self-submitted registry (data corruption, not sparsity, and not mechanically detectable). Blocking a Toyota or Jeep valuation is worse than the gap this was meant to close, so the make-level signal ships empty rather than partially-applied. Out-of-population detection for dropdown/free-text is not available in this version -- documented limitation, not silently absorbed. VIN path is unaffected (excluded_body_classes above is independent and reliable)."
  }
}
