Domain: Inventory & Supply Chain

Using `supply_chain_data.csv` in this folder, compute a forensic stress-analysis summary from the actual local data.

Definitions:

- For each row, compute `unit_revenue = Revenue generated / Number of products sold`.
- For each row, compute `cbr = (Manufacturing costs + Shipping costs + Costs) / Revenue generated`.
- Build the lagged dataset by grouping rows by `Product type`, then sorting each group by the actual `Lead time` column in ascending order. If multiple rows in the same product type have the same `Lead time`, preserve their original file order.
- Within each sorted `Product type` group, compute the lag-1 CBR difference as `current cbr - previous cbr`. Exclude the first row of each group because it has no previous row.
- On the full post-lag dataset, z-score the lagged CBR differences using the global mean and the population standard deviation (`ddof=0`).
- Define `sas = z_lagged_cbr_difference * Defect rates`.
- Define a row as critically amplified if its `sas` is strictly greater than the global 90th percentile of all post-lag `sas` values, using Type 7 / linear interpolation.
- For the Spearman correlation, use average ranks for ties.
- For the coefficient of variation, use the population standard deviation divided by the mean.
- For the mean absolute deviation, compute it about the mean.
- For the percentile rank of the maximum critical `sas`, use:

`100 * (# of post-lag sas values <= that maximum sas) / (post-lag row count)`

After restricting to only critically amplified rows, return a single JSON object with exactly these keys:

- `critically_amplified_count`
- `median_unit_revenue`
- `lead_time_iqr`
- `shipping_cost_mad_about_mean`
- `spearman_unit_revenue_vs_defect_rates`
- `p_fail_given_critical`
- `max_sas`
- `max_sas_percentile_rank`
- `unit_revenue_cv`

Output rules:

- `critically_amplified_count` must be an integer.
- Every other value must be a string rounded to exactly three decimal places using round-half-to-even.
- Return only the JSON object and no extra text.

Grading rubric:
criterion: The final answer is a single JSON object with exactly these keys: critically_amplified_count, median_unit_revenue, lead_time_iqr, shipping_cost_mad_about_mean, spearman_unit_revenue_vs_defect_rates, p_fail_given_critical, max_sas, max_sas_percentile_rank, and unit_revenue_cv.
weight: 10
criterion: The critically amplified row count is exactly 10.
weight: 10
criterion: The median_unit_revenue is exactly '6.216' and the lead_time_iqr is exactly '5.500'.
weight: 15
criterion: The shipping_cost_mad_about_mean is exactly '2.368' and the p_fail_given_critical is exactly '0.200'.
weight: 15
criterion: The spearman_unit_revenue_vs_defect_rates is exactly '-0.067' and the unit_revenue_cv is exactly '0.677'.
weight: 15
criterion: The max_sas is exactly '11.702' and the max_sas_percentile_rank is exactly '100.000'.
weight: 15
criterion: The solution uses the actual Lead time column for within-product sorting, the global Type 7 90th-percentile SAS threshold, the strict greater-than rule for critical rows, and round-half-to-even formatting to three decimals for every non-count output.
weight: 20

Golden answer:
```python
import csv
import json
import math
from pathlib import Path
from statistics import median


def mean(values):
    return sum(values) / len(values)


def quantile_type7(values, p):
    xs = sorted(values)
    n = len(xs)
    if n == 1:
        return xs[0]
    h = (n - 1) * p + 1
    j = int(math.floor(h))
    g = h - j
    if j <= 1:
        return xs[0]
    if j >= n:
        return xs[-1]
    return xs[j - 1] + g * (xs[j] - xs[j - 1])


def population_std(values):
    m = mean(values)
    return math.sqrt(sum((x - m) ** 2 for x in values) / len(values))


def mad_about_mean(values):
    m = mean(values)
    return sum(abs(x - m) for x in values) / len(values)


def average_ranks(values):
    order = sorted(range(len(values)), key=lambda i: values[i])
    ranks = [0.0] * len(values)
    i = 0
    while i < len(values):
        j = i
        current = values[order[i]]
        while j < len(values) and values[order[j]] == current:
            j += 1
        avg_rank = (i + 1 + j) / 2.0
        for k in range(i, j):
            ranks[order[k]] = avg_rank
        i = j
    return ranks


def pearson(x, y):
    mx = mean(x)
    my = mean(y)
    num = sum((a - mx) * (b - my) for a, b in zip(x, y))
    den_x = math.sqrt(sum((a - mx) ** 2 for a in x))
    den_y = math.sqrt(sum((b - my) ** 2 for b in y))
    return num / (den_x * den_y)


def spearman(x, y):
    return pearson(average_ranks(x), average_ranks(y))


def fmt(value):
    return f"{value:.3f}"


path = Path(__file__).with_name("supply_chain_data.csv")
with path.open(newline="", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

for row in rows:
    revenue = float(row["Revenue generated"])
    sold = float(row["Number of products sold"])
    manufacturing = float(row["Manufacturing costs"])
    shipping = float(row["Shipping costs"])
    costs = float(row["Costs"])
    row["unit_revenue"] = revenue / sold
    row["cbr"] = (manufacturing + shipping + costs) / revenue

indexed_rows = list(enumerate(rows))
indexed_rows.sort(key=lambda item: (item[1]["Product type"], float(item[1]["Lead time"]), item[0]))

post_lag = []
previous_cbr = {}
for _, row in indexed_rows:
    product_type = row["Product type"]
    cbr = row["cbr"]
    if product_type in previous_cbr:
        record = dict(row)
        record["lagged_cbr_difference"] = cbr - previous_cbr[product_type]
        post_lag.append(record)
    previous_cbr[product_type] = cbr

lag_values = [row["lagged_cbr_difference"] for row in post_lag]
lag_mean = mean(lag_values)
lag_std = population_std(lag_values)

for row in post_lag:
    z_value = (row["lagged_cbr_difference"] - lag_mean) / lag_std
    row["sas"] = z_value * float(row["Defect rates"])

sas_values = [row["sas"] for row in post_lag]
sas_p90 = quantile_type7(sas_values, 0.9)
critical_rows = [row for row in post_lag if row["sas"] > sas_p90]

unit_revenues = [row["unit_revenue"] for row in critical_rows]
lead_times = [float(row["Lead time"]) for row in critical_rows]
shipping_costs = [float(row["Shipping costs"]) for row in critical_rows]
defect_rates = [float(row["Defect rates"]) for row in critical_rows]
max_sas = max(row["sas"] for row in critical_rows)

result = {
    "critically_amplified_count": len(critical_rows),
    "median_unit_revenue": fmt(median(unit_revenues)),
    "lead_time_iqr": fmt(quantile_type7(lead_times, 0.75) - quantile_type7(lead_times, 0.25)),
    "shipping_cost_mad_about_mean": fmt(mad_about_mean(shipping_costs)),
    "spearman_unit_revenue_vs_defect_rates": fmt(spearman(unit_revenues, defect_rates)),
    "p_fail_given_critical": fmt(sum(1 for row in critical_rows if row["Inspection results"] == "Fail") / len(critical_rows)),
    "max_sas": fmt(max_sas),
    "max_sas_percentile_rank": fmt(100.0 * sum(1 for value in sas_values if value <= max_sas) / len(sas_values)),
    "unit_revenue_cv": fmt(population_std(unit_revenues) / mean(unit_revenues)),
}

print(json.dumps(result, ensure_ascii=True))
```

Reasoning:

- The actual local file contains both `Lead times` and `Lead time`; this task uses the explicit `Lead time` column for the within-product ordering step.
- The lagged dataset contains 97 rows after dropping the first sorted row from each product type.
- The critical set is defined from the global SAS distribution on those 97 rows, using the Type 7 90th percentile and a strict `>` comparison.
- The final outputs are then computed only on the 10 critical rows.
- All non-count outputs are formatted to three decimals with Python formatting, which uses round-half-to-even.

Verified result:

```json
{"critically_amplified_count": 10, "median_unit_revenue": "6.216", "lead_time_iqr": "5.500", "shipping_cost_mad_about_mean": "2.368", "spearman_unit_revenue_vs_defect_rates": "-0.067", "p_fail_given_critical": "0.200", "max_sas": "11.702", "max_sas_percentile_rank": "100.000", "unit_revenue_cv": "0.677"}
```