import os, re, json, subprocess, glob
REPO = os.path.expanduser("~/social-autoposter"); os.chdir(REPO)
all_py = {os.path.basename(p) for p in glob.glob("scripts/*.py")}

entry_surfaces = glob.glob("skill/*.sh") + glob.glob("skill/lib/*.sh")
entry_surfaces += ["SKILL.md", "setup/SKILL.md", "bin/cli.js"]
entry_surfaces += glob.glob("mcp/dist/*.js") + glob.glob("mcp/*.mjs")

ref_re = re.compile(r"scripts/([A-Za-z0-9_]+)\.py")
def refs_in_text(txt):
    return {m+".py" for m in ref_re.findall(txt) if (m+".py") in all_py}

entries, surface_hits = set(), {}
for s in entry_surfaces:
    if not os.path.exists(s): continue
    txt = open(s, encoding="utf-8", errors="ignore").read()
    # strip // comments for js, # comments for md is harder; keep simple: count all refs but mark cli.js comment lines
    for fn in refs_in_text(txt):
        entries.add(fn); surface_hits.setdefault(fn,set()).add(s)

imp_res = [re.compile(r"^\s*import\s+([A-Za-z0-9_]+)", re.M),
           re.compile(r"^\s*from\s+([A-Za-z0-9_]+)\s+import", re.M),
           re.compile(r"^\s*from\s+scripts\s+import\s+([A-Za-z0-9_,\s]+)", re.M),
           re.compile(r"^\s*from\s+scripts\.([A-Za-z0-9_]+)\s+import", re.M),
           re.compile(r"^\s*import\s+scripts\.([A-Za-z0-9_]+)", re.M)]
def expand(fn):
    path=os.path.join("scripts",fn)
    if not os.path.exists(path): return set()
    txt=open(path,encoding="utf-8",errors="ignore").read()
    found=set()
    for rx in imp_res:
        for g in rx.findall(txt):
            for name in re.split(r"[,\s]+",g):
                name=name.strip()
                if name and (name+".py") in all_py: found.add(name+".py")
    found |= refs_in_text(txt)   # NEW: intra-python subprocess scripts/X.py refs
    # follow symlink targets too (update_stats.py -> stats.py)
    if os.path.islink(path):
        tgt=os.path.basename(os.readlink(path))
        if tgt in all_py: found.add(tgt)
    return found

closure=set(entries); stack=list(entries)
while stack:
    for d in expand(stack.pop()):
        if d not in closure: closure.add(d); stack.append(d)

out=subprocess.run(["npm","pack","--dry-run","--json"],capture_output=True,text=True)
shipped=sorted(os.path.basename(f["path"]) for f in json.loads(out.stdout)[0]["files"] if f["path"].startswith("scripts/") and f["path"].endswith(".py"))
drop=sorted(set(shipped)-closure); keep=sorted(set(shipped)&closure)
print("entries:",len(entries),"| closure:",len(closure),"| shipped:",len(shipped))
print(f"\n=== KEEP (shipped & needed): {len(keep)}")
print(f"=== DROP (shipped but unreferenced anywhere consumer): {len(drop)}")
for d in drop:
    if d=="_compute_allowlist.py": continue
    print("   -",d)
open("/tmp/keep.txt","w").write("\n".join(k for k in keep if k!="_compute_allowlist.py"))
open("/tmp/drop.txt","w").write("\n".join(d for d in drop if d!="_compute_allowlist.py"))
