Restatement RiskSearchAskWhat happened (2021–23)How it works

SPECIFICITY, INC. (SPTY, CIK 1840102, Services-Advertising Agencies)

re-run · ask a question about this company

Did the stock fall, and when? (Item 4.02 notices)

0.520.034.02 2026-05-262025-112025-122026-022026-032026-052026-062026-082026-092026-10

Daily adjusted closes, Yahoo Finance chart endpoint (unofficial), adjusted close; best-effort, may be wrong or missing. Returns run from the last close before day 0 to the close N trading days later. 'Minus IWM' subtracts the Russell 2000 ETF's return over the same dates. Descriptive only: not a prediction and not a causal estimate.

8-K filed 2026-05-26, accepted 2026-05-22 21:41 ET (after the 4:00 pm close, so day 0 is the next trading day) — notice
Day 0 = 2026-05-26; base = last close before day 0 (2026-05-22, 0.28).

Window (trading days)Dates (close to close)RawMinus IWM
day 02026-05-22 → 2026-05-26+0.0%-1.9%
0–12026-05-22 → 2026-05-27-15.4%-17.2%
0–52026-05-22 → 2026-06-02+71.4%+69.1%
0–302026-05-22 → 2026-07-09-10.7%-15.2%

No other 8-K (besides exhibits) filed between the day before the notice and day 0.

Securities class actions after the notice

CourtListener RECAP docket search (caption names the company; securities nature of suit, '10b-5' or 'Securities Exchange Act'). A docket may concern a different matter; open it. A miss is not proof there is no suit.

Explanation (model, from the reference numbers)

SPECIFICITY, INC. (SPTY, CIK 1840102) — plain summary:

Restatement history. Three relevant filings: an 8-K Item 4.02 (filed 2026-05-26) signaling non-reliance on previously issued financials; a 10-K/A (filed 2026-06-05) restating FY2025; and an earlier 10-Q/A (filed 2022-12-29) for Q3 2022.

What changed. The 10-K/A vs. the original 10-K (filed 2026-03-31) shows FY2025 net loss widened from $(473,147) to $(554,067) (+17%), COGS up ~5% to $650,188, and operating cash outflow worsening from $(89,807) to $(149,371) (−66%). Separately, the Q3 2023 10-Q as re-filed 2025-04-23 shows revenue cut ~5% (Q3 alone −15%), COGS nearly doubled for the quarter, and depreciation halved — consistent with the 2022 10-Q/A pattern of prior-period corrections. Balance-sheet deltas also appear between the FY2025 10-K and the 2026-08-19 10-Q (current liabilities +10.6%, convertible notes current +27%), which may be reclassification or recast rather than restatement — the filings themselves will say which.

Screens. M-score and F-score could not be computed — insufficient XBRL data (missing SGA and receivables; long-term debt imputed as zero). These are published academic screens approximated from XBRL, not the SEC's non-public Accounting Quality Model, and a score would be a screen, not a prediction.

Benford. 123 values from the 10-K/A show nonconformity (MAD 0.0413, chi² 17.65) — a red-flag indicator only, not evidence of anything.

SEC scrutiny. The SEC does not "audit" companies; scrutiny comes via Corp Fin filing reviews (CORRESP/UPLOAD letters) or, rarely, Enforcement. Here: no comment letters on file and no AAER name matches — no evidence of a filing review.

Cross-check note. Our delta count (56) missed one delta found in the reference set (57); no value mismatches. The reference numbers are used as authoritative.
The SEC does not "audit" companies. Scrutiny comes as Corp Fin filing review (comment letters) and, rarely, an Enforcement inquiry. M-score (Beneish 1999) and F-score (Dechow et al. 2011) are published academic screens approximated on SEC XBRL data — not the SEC's non-public Accounting Quality Model. A screen is not a prediction.

Screens (fiscal year ending 2025-12-31)

Beneish M-score: — (flag above −1.78; insufficient_data)
Same screen on numbers as first reported: —
Dechow F-score: — (flag at ≥ 1.0; insufficient_data)
Benford MAD: 0.0413 n=123, Nigrini: nonconformity

123456789
bars: observed first digits; red line: Benford expected

Missing-data notes

  • M-score not computed — missing: receivables, sga
  • M-score imputation: ltd=0 (no long-term debt tag)
  • F-score not computed — missing: receivables
  • F-score inputs treated as 0 (no XBRL fact): debt_issued, inventory, lt_investments, ltd, st_investments

Model's sandboxed calculation vs reference code

1 check(s) failed: 1 wrong value(s), 0 not reported by the model. The reference numbers are used everywhere on this page.

MetricReferenceModel
M-score——match
F-score——match
Benford MAD0.04130.0413match
deltas (count)57.000056.0000MISMATCH (wrong value)

What changed between filings (57 line-item/periods, since 2022)

Original = earliest filed value for that period; restated = latest. Changes can be restatement, reclassification or recast — read the filings.

ItemXBRL tagPeriodOriginalLatestChange
current_assetsAssetsCurrent → 2025-12-31$5,534
10-K 2026-03-31
$5,737
10-Q 2026-08-19
+3.7%
current_liabilitiesLiabilitiesCurrent → 2025-12-31$1.14M
10-K 2026-03-31
$1.26M
10-Q 2026-08-19
+10.6%
total_liabilitiesLiabilities → 2025-12-31$2.14M
10-K 2026-03-31
$2.26M
10-Q 2026-08-19
+5.7%
debt_currentConvertibleNotesPayableCurrent → 2025-12-31$429,736
10-K 2026-03-31
$546,010
10-Q 2026-08-19
+27.1%
cashCashAndCashEquivalentsAtCarryingValue → 2025-12-31$1,784
10-K 2026-03-31
$1,987
10-Q 2026-08-19
+11.4%
cogsCostOfRevenue2025-01-01 → 2025-12-31$618,803
10-K 2026-03-31
$650,188
10-K/A 2026-06-05
+5.1%
net_incomeNetIncomeLoss2025-01-01 → 2025-12-31−$473,147
10-K 2026-03-31
−$554,067
10-K/A 2026-06-05
-17.1%
cfoNetCashProvidedByUsedInOperatingActivities2025-01-01 → 2025-12-31−$89,807
10-K 2026-03-31
−$149,371
10-K/A 2026-06-05
-66.3%
stock_issuedProceedsFromIssuanceOfCommonStock2023-01-01 → 2023-12-31$290,502
10-K 2025-03-03
$49,253
10-K 2025-06-24
-83.0%
revenueRevenues2023-01-01 → 2023-09-30$805,317
10-Q 2023-11-20
$765,232
10-Q 2025-04-23
-5.0%
revenueRevenues2023-07-01 → 2023-09-30$320,271
10-Q 2023-11-20
$270,888
10-Q 2025-04-23
-15.4%
cogsCostOfRevenue2023-01-01 → 2023-09-30$263,825
10-Q 2023-11-20
$379,724
10-Q 2025-04-23
+43.9%
cogsCostOfRevenue2023-07-01 → 2023-09-30$26,625
10-Q 2023-11-20
$53,374
10-Q 2025-04-23
+100.5%
depreciationDepreciation2023-01-01 → 2023-09-30$7,834
10-Q 2023-11-20
$3,895
10-Q 2025-04-23
-50.3%
cashCashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents → 2023-09-30$5,317
10-Q 2023-11-20
$4,555
10-Q 2025-04-23
-14.3%
net_incomeNetIncomeLoss2023-01-01 → 2023-09-30−$874,855
10-Q 2023-11-20
−$635,445
10-Q 2025-04-23
+27.4%
net_incomeNetIncomeLoss2023-07-01 → 2023-09-30$52,466
10-Q 2023-11-20
−$64,597
10-Q 2025-04-23
-223.1%
cfoNetCashProvidedByUsedInOperatingActivities2023-01-01 → 2023-09-30−$645,831
10-Q 2023-11-20
−$421,604
10-Q 2025-04-23
+34.7%
stock_issuedProceedsFromIssuanceOfCommonStock2023-01-01 → 2023-09-30$175,000
10-Q 2023-11-20
$49,253
10-Q 2025-04-23
-71.9%
revenueRevenues2023-01-01 → 2023-06-30$485,046
10-Q 2023-08-04
$494,344
10-Q 2025-04-23
+1.9%
revenueRevenues2023-04-01 → 2023-06-30$279,188
10-Q 2023-08-04
$287,983
10-Q 2025-04-23
+3.1%
cogsCostOfRevenue2023-01-01 → 2023-06-30$237,200
10-Q 2023-08-04
$326,350
10-Q 2025-04-23
+37.6%
cogsCostOfRevenue2023-04-01 → 2023-06-30$142,995
10-Q 2023-08-04
$200,522
10-Q 2025-04-23
+40.2%
depreciationDepreciation2023-01-01 → 2023-06-30$5,194
10-Q 2023-08-04
$2,597
10-Q 2025-04-23
-50.0%
net_incomeNetIncomeLoss2023-01-01 → 2023-06-30−$927,321
10-Q 2023-08-04
−$570,848
10-Q 2025-04-23
+38.4%
net_incomeNetIncomeLoss2023-04-01 → 2023-06-30−$433,253
10-Q 2023-08-04
−$330,498
10-Q 2025-04-23
+23.7%
cfoNetCashProvidedByUsedInOperatingActivities2023-01-01 → 2023-06-30−$558,727
10-Q 2023-08-04
−$455,030
10-Q 2025-04-23
+18.6%
stock_issuedProceedsFromIssuanceOfCommonStock2023-01-01 → 2023-06-30$75,000
10-Q 2023-08-04
$49,253
10-Q 2025-04-23
-34.3%
revenueRevenues2023-01-01 → 2023-03-31$231,118
10-Q 2023-05-18
$206,361
10-Q 2025-04-17
-10.7%
cogsCostOfRevenue2023-01-01 → 2023-03-31$94,205
10-Q 2023-05-18
$125,828
10-Q 2025-04-17
+33.6%
depreciationDepreciation2023-01-01 → 2023-03-31$2,583
10-Q 2023-05-18
$1,298
10-Q 2025-04-17
-49.8%
cashCashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents → 2023-03-31$50,089
10-Q 2023-05-18
$32,329
10-Q 2025-04-17
-35.5%
net_incomeNetIncomeLoss2023-01-01 → 2023-03-31−$468,808
10-Q 2023-05-18
−$240,350
10-Q 2025-04-17
+48.7%
cfoNetCashProvidedByUsedInOperatingActivities2023-01-01 → 2023-03-31−$326,932
10-Q 2023-05-18
−$307,646
10-Q 2025-04-17
+5.9%
revenueRevenues2022-01-01 → 2022-12-31$1.15M
10-K 2023-03-30
$1.18M
10-K 2025-03-03
+3.0%
cogsCostOfRevenue2022-01-01 → 2022-12-31$592,102
10-K 2023-03-30
$765,888
10-K 2025-03-03
+29.3%
receivablesAccountsReceivableNetCurrent → 2022-12-31$8,182
10-K 2023-03-30
$5,000
10-K 2025-03-03
-38.9%
current_assetsAssetsCurrent → 2022-12-31$266,375
10-K 2023-03-30
$30,178
10-K 2025-03-03
-88.7%
ppePropertyPlantAndEquipmentNet → 2022-12-31$70,722
10-K 2023-03-30
$10,739
10-K 2025-03-03
-84.8%
depreciationDepreciation2022-01-01 → 2022-12-31$9,982
10-K 2023-03-30
$4,546
10-K 2025-03-03
-54.5%
total_assetsAssets → 2022-12-31$401,729
10-K 2023-03-30
$160,557
10-K 2025-03-03
-60.0%
current_liabilitiesLiabilitiesCurrent → 2022-12-31$369,343
10-K 2023-03-30
$384,589
10-K 2025-03-03
+4.1%
total_liabilitiesLiabilities → 2022-12-31$1.39M
10-K 2023-03-30
$1.41M
10-K 2025-03-03
+1.2%
net_incomeNetIncomeLoss2022-01-01 → 2022-12-31−$4.34M
10-K 2023-03-30
−$3.78M
10-K 2025-03-03
+13.0%
cfoNetCashProvidedByUsedInOperatingActivities2022-01-01 → 2022-12-31−$2.04M
10-K 2023-03-30
−$2.00M
10-K 2025-03-03
+1.7%
revenueRevenues2022-01-01 → 2022-09-30$933,821
10-Q 2022-11-21
$649,510
10-Q 2023-11-20
-30.4%
revenueRevenues2022-07-01 → 2022-09-30$662,971
10-Q 2022-11-21
$378,660
10-Q 2023-11-20
-42.9%
cogsCostOfRevenue2022-01-01 → 2022-09-30$489,760
10-Q 2022-11-21
$261,250
10-Q 2023-11-20
-46.7%
cogsCostOfRevenue2022-07-01 → 2022-09-30$338,870
10-Q 2022-11-21
$110,360
10-Q 2023-11-20
-67.4%
depreciationDepreciation2022-01-01 → 2022-09-30$7,342
10-Q 2022-11-21
$4,769
10-Q 2023-11-20
-35.0%
cashCashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents → 2022-09-30$172,594
10-Q 2022-11-21
$26,140
10-Q 2023-11-20
-84.9%
net_incomeNetIncomeLoss2022-07-01 → 2022-09-30−$949,525
10-Q 2022-11-21
−$576,923
10-Q 2023-11-20
+39.2%
cfoNetCashProvidedByUsedInOperatingActivities2022-01-01 → 2022-09-30−$1.71M
10-Q 2022-11-21
−$1.12M
10-Q 2023-11-20
+34.4%
stock_issuedProceedsFromIssuanceOfCommonStock2022-01-01 → 2022-09-30$1.26M
10-Q 2022-11-21
$471,967
10-Q 2023-11-20
-62.6%
current_assetsAssetsCurrent → 2022-09-30$213,226
10-Q 2022-11-21
$584,595
10-Q/A 2022-12-29
+174.2%
total_assetsAssets → 2022-09-30$361,499
10-Q 2022-11-21
$732,868
10-Q/A 2022-12-29
+102.7%
net_incomeNetIncomeLoss2022-01-01 → 2022-09-30−$2.28M
10-Q 2022-11-21
−$3.51M
10-Q/A 2022-12-29
-53.6%

Non-reliance (8-K 4.02) and amended filings

FiledFormItems
2026-06-0510-K/Aopen
2026-05-268-K4.02open
2022-12-2910-Q/Aopen

SEC comment-letter correspondence (CORRESP / UPLOAD)

Shows a filing review happened; content not summarized here.

2022-09-21CORRESPopen
2022-09-20UPLOADopen
2022-05-27CORRESPopen
2022-05-27UPLOADopen
2021-09-14CORRESPopen
2021-09-03UPLOADopen
2021-08-13UPLOADopen
2021-07-21UPLOADopen

AAER (enforcement release) name match

  • No AAER whose respondent name matches this company (exact normalized name; individuals charged alone would not match).

Sandbox attempt log

Attempt 1: no_code — model replied without code; asked again.
reply
sst = (dWC + dNCO + dFIN) / avgTA if avgTA else None
    ch_rec = (rec_t2 - rec_p2) / avgTA if avgTA else None
    ch_inv = (inv_t - inv_p) / avgTA if avgTA else None
    soft = (ta_t - ppe_t2 - cash_t) / ta_t if ta_t else None
    cs_t = rev_t2 - (rec_t2 - rec_p2)
    cs_p = (rev_p2 - (rec_p2 - rec_pp)) if rec_pp is not None else rev_p2
    ch_cs = (cs_t - cs_p) / cs_p if cs_p else None
    avgTA_p = (ta_p + ta_pp) / 2 if (ta_p is not None and ta_pp is not None) else None
    ch_roa = (ni_t2 / avgTA - ni_p2 / avgTA_p) if (avgTA and avgTA_p) else None
    issue = 1 if (si_t > 0 or di_t > 0) else 0

    f_vars = {"avgTA": avgTA, "rsst_acc": rsst, "ch_rec": ch_rec, "ch_inv": ch_inv,
              "soft_assets": soft, "ch_cs": ch_cs, "ch_roa": ch_roa, "issue": issue}
    if any(v is None for v in [rsst, ch_rec, ch_inv, soft, ch_cs, ch_roa]):
        f_score = None
    else:
        x = (-7.893 + 0.790 * rsst + 2.518 * ch_rec + 1.191 * ch_inv
             + 1.979 * soft + 0.171 * ch_cs - 0.932 * ch_roa + 1.029 * issue)
        f_score = (math.exp(x) / (1 + math.exp(x))) / 0.0037
except Exception:
    f_score = None

# ---------------- 4. Benford ----------------
accns = {}
for tag, node in USGAAP.items():
    for unit, fs in node.get("units", {}).items():
        if unit != "USD":
            continue
        for f in fs:
            form = f.get("form", "")
            if form in ("10-K", "10-K/A") and f.get("accn"):
                accns[f["accn"]] = f
best = None
for accn, f in accns.items():
    if best is None or (f.get("filed", "") > best[1].get("filed", "")):
        best = (accn, f)
benford = None
if best:
    accn = best[0]
    seen = set()
    vals = []
    for tag, node in USGAAP.items():
        for f in node.get("units", {}).get("USD", []):
            if f.get("accn") != accn:
                continue
            v = abs(f["val"])
            if v < 10:
                continue
            key = (tag, f.get("start"), f["end"])
            if key in seen:
                continue
            seen.add(key)
            vals.append(v)
    n = len(vals)
    if n:
        counts = {d_: 0 for d_ in range(1, 10)}
        for v in vals:
            counts[int(str(v)[0])] += 1
        mad = sum(abs(counts[d_] / n - math.log10(1 + 1 / d_)) for d_ in range(1, 10)) / 9
        benford = {"accession": accn, "form": best[1].get("form"), "filed": best[1].get("filed"),
                   "n": n, "mad": mad}

# ---------------- 5. restatement filings ----------------
notices = []
for f in FIL:
    form = f.get("form", "")
    items = f.get("items") or ""
    if form == "8-K" and "4.02" in str(items):
        notices.append(f)
    elif form in ("10-K/A", "10-Q/A"):
        notices.append(f)
notices.sort(key=lambda x: x.get("filed", ""))
first_402 = min((f["filed"] for f in notices if f.get("form") == "8-K"), default=None)
resp = [f for f in FIL if f.get("form") in ("CORRESP", "UPLOAD")
        and first_402 and f.get("filed", "") > first_402]

result = {
Attempt 2: ok · exit 0 · 0.68s in sandbox · container rr-sbx-16feec7df7 removed
code the model wrote (11842 chars)
import json, math
from datetime import date, datetime

def D(s):
    return datetime.strptime(s, "%Y-%m-%d").date()

CF = json.load(open("/data/companyfacts.json"))
FILINGS = json.load(open("/data/filings.json")).get("filings", [])
TAG_MAP = json.load(open("/data/tag_map.json"))
AVAIL = json.load(open("/data/available_tags.json"))

USGAAP = CF.get("facts", {}).get("us-gaap", {})

def facts_of(tag):
    try:
        return USGAAP[tag]["units"]["USD"]
    except Exception:
        return []

INSTANT = {'cash','current_assets','current_liabilities','debt_current','inventory',
           'lt_investments','ltd','ppe','receivables','st_investments','total_assets','total_liabilities'}

FY = {"t": "2025-12-31", "p": "2024-12-31", "pp": "2023-12-31"}

def _match(f, target, instant, annual_only):
    try:
        end = D(f["end"])
    except Exception:
        return False
    if abs((end - target).days) > 10:
        return False
    has_start = "start" in f
    if instant:
        return not has_start
    if not has_start:
        return False
    dur = (end - D(f["start"])).days
    if annual_only and not (350 <= dur <= 380):
        return False
    return True

def _pick(cands):
    cands = sorted(cands, key=lambda x: (x.get("filed", ""), x.get("accn", "")))
    return cands[-1]

def _single(item, endstr, instant, annual_only):
    target = D(endstr)
    for tag in TAG_MAP.get(item, []):
        if "+" in tag:
            continue
        cands = [f for f in facts_of(tag) if _match(f, target, instant, annual_only)]
        if cands:
            return _pick(cands)["val"], tag
    return None, None

def _combo(item, endstr, instant, annual_only):
    target = D(endstr)
    for spec in TAG_MAP.get(item, []):
        if "+" not in spec:
            continue
        parts = spec.split("+")
        per_filing = {}
        ok = True
        for tag in parts:
            cands = [f for f in facts_of(tag) if _match(f, target, instant, annual_only)]
            if not cands:
                ok = False
                break
            best = _pick(cands)
            key = (best.get("filed", ""), best.get("accn", ""))
            per_filing.setdefault(key, {})[tag] = best["val"]
        if ok and per_filing:
            key = max(per_filing)
            if len(per_filing[key]) == len(parts):
                return sum(per_filing[key].values()), spec
    return None, None

def get_annual(item, endstr):
    if item in INSTANT:
        v, t = _single(item, endstr, True, False)
        if v is None:
            v, t = _combo(item, endstr, True, False)
        return v, t
    v, t = _single(item, endstr, False, True)
    if v is None:
        v, t = _combo(item, endstr, False, True)
    return v, t

def get_flow_any(item, endstr):
    v, t = _single(item, endstr, False, False)
    if v is None:
        v, t = _combo(item, endstr, False, False)
    return v, t

# ---------------- 1. deltas ----------------
deltas = []
for item, tags in TAG_MAP.items():
    for tag in tags:
        if "+" in tag:
            continue
        groups = {}
        for f in facts_of(tag):
            try:
                end = D(f["end"])
            except Exception:
                continue
            if end < D("2022-01-01"):
                continue
            groups.setdefault((f.get("start"), f["end"]), []).append(f)
        for (start, end), fs in groups.items():
            if len({f["val"] for f in fs}) < 2:
                continue
            fs = sorted(fs, key=lambda x: (x.get("filed", ""), x.get("accn", "")))
            orig, rest = fs[0], fs[-1]
            o, r = orig["val"], rest["val"]
            if o == 0:
                continue
            pct = (r - o) / abs(o)
            if abs(pct) < 0.005:
                continue
            deltas.append({"item": item, "tag": tag, "start": start, "end": end,
                           "original": o, "original_form": orig.get("form"),
                           "restated": r, "restated_form": rest.get("form"),
                           "restated_filed": rest.get("filed"), "pct_change": pct})
deltas.sort(key=lambda x: (x["item"], x["end"] or "", x["start"] or ""))

# ---------------- 2. Beneish ----------------
def div(a, b):
    if a is None or b in (None, 0):
        return None
    return a / b

V = {}
missing = []
for item in ["revenue", "cogs", "sga", "depreciation", "net_income", "cfo"]:
    for per in ("t", "p"):
        if per == "p" and item in ("net_income", "cfo", "depreciation"):
            continue
        val, _ = get_annual(item, FY[per])
        V[f"{item}_{per}"] = val
        if val is None:
            missing.append(f"{item}_{per}")
for item in ["receivables", "current_assets", "ppe", "total_assets",
             "current_liabilities", "ltd"]:
    for per in ("t", "p"):
        val, _ = get_annual(item, FY[per])
        V[f"{item}_{per}"] = val
        if val is None and item != "ltd":
            missing.append(f"{item}_{per}")

imputed = []
m_score = None
ratios = {}
try:
    rec_t, rec_p = V["receivables_t"], V["receivables_p"]
    rev_t, rev_p = V["revenue_t"], V["revenue_p"]
    cogs_t, cogs_p = V["cogs_t"], V["cogs_p"]
    ca_t, ca_p = V["current_assets_t"], V["current_assets_p"]
    ppe_t, ppe_p = V["ppe_t"], V["ppe_p"]
    ta_t, ta_p = V["total_assets_t"], V["total_assets_p"]
    cl_t, cl_p = V["current_liabilities_t"], V["current_liabilities_p"]
    ltd_t = V["ltd_t"] if V["ltd_t"] is not None else 0
    ltd_p = V["ltd_p"] if V["ltd_p"] is not None else 0
    ni_t, cfo_t = V["net_income_t"], V["cfo_t"]
    dep_t, dep_p = V["depreciation_t"], V["depreciation_p"]
    sga_t, sga_p = V["sga_t"], V["sga_p"]

    DSRI = div(div(rec_t, rev_t), div(rec_p, rev_p))
    gm_t = div(rev_t - cogs_t, rev_t)
    gm_p = div(rev_p - cogs_p, rev_p)
    GMI = div(gm_p, gm_t)
    AQI = div(1 - div(ca_t + ppe_t, ta_t), 1 - div(ca_p + ppe_p, ta_p))
    SGI = div(rev_t, rev_p)
    if dep_t is None or dep_p is None or not ppe_t or not ppe_p:
        DEPI = 1.0; imputed.append("DEPI")
    else:
        DEPI = div(div(dep_p, dep_p + ppe_p), div(dep_t, dep_t + ppe_t))
    if sga_t is None or sga_p is None:
        SGAI = 1.0; imputed.append("SGAI")
    else:
        SGAI = div(div(sga_t, rev_t), div(sga_p, rev_p))
    LVGI = div(div(cl_t + ltd_t, ta_t), div(cl_p + ltd_p, ta_p))
    TATA = div(ni_t - cfo_t, ta_t)
    ratios = {"DSRI": DSRI, "GMI": GMI, "AQI": AQI, "SGI": SGI,
              "DEPI": DEPI, "SGAI": SGAI, "LVGI": LVGI, "TATA": TATA}
    bad = [k for k, v in ratios.items() if v is None and k not in ("DEPI", "SGAI")]
    if bad:
        m_score = None
        missing = sorted(set(missing) | set(bad))
    else:
        m_score = (-4.84 + 0.920*DSRI + 0.528*GMI + 0.404*AQI + 0.892*SGI
                   + 0.115*DEPI - 0.172*SGAI + 4.679*TATA - 0.327*LVGI)
except Exception:
    m_score = None

# ---------------- 3. Dechow F-score ----------------
def g(item, per):
    return get_annual(item, FY[per])[0]

def z(v):
    return 0 if v is None else v

f_vars = {}
f_score = None
try:
    ta_t, ta_p, ta_pp = g("total_assets", "t"), g("total_assets", "p"), g("total_assets", "pp")
    ca_t, ca_p = g("current_assets", "t"), g("current_assets", "p")
    cash_t, cash_p = g("cash", "t"), g("cash", "p")
    sti_t, sti_p = z(g("st_investments", "t")), z(g("st_investments", "p"))
    lti_t, lti_p = z(g("lt_investments", "t")), z(g("lt_investments", "p"))
    cl_t, cl_p = g("current_liabilities", "t"), g("current_liabilities", "p")
    dc_t, dc_p = z(g("debt_current", "t")), z(g("debt_current", "p"))
    ltd_t2, ltd_p2 = z(g("ltd", "t")), z(g("ltd", "p"))
    tl_t, tl_p = g("total_liabilities", "t"), g("total_liabilities", "p")
    ppe_t2, ppe_p2 = g("ppe", "t"), g("ppe", "p")
    inv_t, inv_p = z(g("inventory", "t")), z(g("inventory", "p"))
    rec_t2, rec_p2 = g("receivables", "t"), g("receivables", "p")
    rec_pp = g("receivables", "pp")
    rev_t2, rev_p2 = g("revenue", "t"), g("revenue", "p")
    ni_t2, ni_p2 = g("net_income", "t"), g("net_income", "p")
    si_t = z(get_flow_any("stock_issued", FY["t"])[0]) if TAG_MAP.get("stock_issued") else 0
    di_t = z(get_flow_any("debt_issued", FY["t"])[0]) if TAG_MAP.get("debt_issued") else 0

    avgTA = (ta_t + ta_p) / 2
    dWC = ((ca_t - cash_t - sti_t) - (cl_t - dc_t)) - ((ca_p - cash_p - sti_p) - (cl_p - dc_p))
    dNCO = ((ta_t - ca_t - lti_t) - (tl_t - cl_t - ltd_t2)) - ((ta_p - ca_p - lti_p) - (tl_p - cl_p - ltd_p2))
    dFIN = ((sti_t + lti_t) - (ltd_t2 + dc_t)) - ((sti_p + lti_p) - (ltd_p2 + dc_p))
    rsst = (dWC + dNCO + dFIN) / avgTA
    ch_rec = (rec_t2 - rec_p2) / avgTA
    ch_inv = (inv_t - inv_p) / avgTA
    soft = (ta_t - ppe_t2 - cash_t) / ta_t
    cs_t = rev_t2 - (rec_t2 - rec_p2)
    cs_p = (rev_p2 - (rec_p2 - rec_pp)) if rec_pp is not None else rev_p2
    ch_cs = (cs_t - cs_p) / cs_p
    avgTA_p = (ta_p + ta_pp) / 2
    ch_roa = ni_t2 / avgTA - ni_p2 / avgTA_p
    issue = 1 if (si_t > 0 or di_t > 0) else 0
    f_vars = {"avgTA": avgTA, "rsst_acc": rsst, "ch_rec": ch_rec, "ch_inv": ch_inv,
              "soft_assets": soft, "ch_cs": ch_cs, "ch_roa": ch_roa, "issue": issue}
    x = (-7.893 + 0.790*rsst + 2.518*ch_rec + 1.191*ch_inv + 1.979*soft
         + 0.171*ch_cs - 0.932*ch_roa + 1.029*issue)
    f_score = (math.exp(x) / (1 + math.exp(x))) / 0.0037
except Exception:
    f_score = None

# ---------------- 4. Benford ----------------
accn_info = {}
for tag, node in USGAAP.items():
    for f in node.get("units", {}).get("USD", []):
        if f.get("form") in ("10-K", "10-K/A") and f.get("accn"):
            cur = accn_info.get(f["accn"])
            if cur is None or f.get("filed", "") > cur.get("filed", ""):
                accn_info[f["accn"]] = f
benford = None
if accn_info:
    accn = max(accn_info, key=lambda a: accn_info[a].get("filed", ""))
    seen, vals = set(), []
    for tag, node in USGAAP.items():
        for f in node.get("units", {}).get("USD", []):
            if f.get("accn") != accn:
                continue
            v = abs(f["val"])
            if v < 10:
                continue
            key = (tag, f.get("start"), f["end"])
            if key in seen:
                continue
            seen.add(key)
            vals.append(v)
    n = len(vals)
    if n:
        counts = {d: 0 for d in range(1, 10)}
        for v in vals:
            counts[int(str(v)[0])] += 1
        mad = sum(abs(counts[d]/n - math.log10(1 + 1/d)) for d in range(1, 10)) / 9
        benford = {"accession": accn, "form": accn_info[accn].get("form"),
                   "filed": accn_info[accn].get("filed"), "n": n, "mad": mad}

# ---------------- 5. restatement filings ----------------
notices = []
for f in FILINGS:
    form = f.get("form", "")
    items = str(f.get("items") or "")
    if (form == "8-K" and "4.02" in items) or form in ("10-K/A", "10-Q/A"):
        notices.append({"form": form, "filed": f.get("filed"), "url": f.get("url"), "items": f.get("items")})
notices.sort(key=lambda x: x.get("filed") or "")
first_402 = min((n["filed"] for n in notices if n["form"] == "8-K" and n.get("filed")), default=None)
resp = [{"form": f.get("form"), "filed": f.get("filed"), "url": f.get("url")}
        for f in FILINGS
        if f.get("form") in ("CORRESP", "UPLOAD") and first_402
        and (f.get("filed") or "") > first_402]

result = {
    "deltas": deltas,
    "beneish": {"m_score": m_score, "ratios": ratios, "imputed": imputed,
                "missing": sorted(set(missing)) if m_score is None else []},
    "dechow_f": {"f_score": f_score, "variables": f_vars},
    "benford": benford,
    "restatement_filings": {"notices": notices,
                            "corresp_upload_after_first_402": resp,
                            "count_corresp_upload": len(resp)},
}
json.dump(result, open("/out/result.json", "w"), indent=2, default=str)
stdout / stderr