File size: 5,881 Bytes
17135b7
 
 
 
 
 
 
 
 
 
50154fa
 
 
 
17135b7
 
 
 
50154fa
 
 
 
 
 
 
 
 
17135b7
 
 
 
 
 
 
 
 
 
 
 
 
50154fa
17135b7
50154fa
17135b7
 
50154fa
 
17135b7
 
 
 
 
50154fa
 
17135b7
 
 
 
 
 
50154fa
 
 
 
 
 
17135b7
 
 
 
 
50154fa
 
 
 
 
17135b7
50154fa
17135b7
 
 
 
 
 
 
 
50154fa
 
17135b7
50154fa
17135b7
 
 
 
 
 
50154fa
 
17135b7
 
 
50154fa
17135b7
 
 
 
 
 
 
 
50154fa
17135b7
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"""Does `--ckpt-repo` actually choose the repo the publisher reads its weights from?

Hard-coding `Cion-lab/ounce100m-ckpt` as the only source was harmless while that repo existed and there was one
model. It is not harmless now: a second run publishing to its own repo would still resolve `latest.json` from
the first run's -- i.e. publish one model's weights under another model's card -- and since that repo has been
deleted the failure arrives as a confusing 404 instead of a wrong answer.

Why a 404 cannot be the test. A traceback prints the failing *source line*, which contains the literal
`{a.ckpt_repo}`, not the URL it resolved to. "It died" therefore says nothing about which repo it asked for,
and a probe asserting on that text would pass whether or not the fix works. So the decisive read is the
publisher's own `ckpt latest.json -> {...}` print, which names the repo it fetched -- that needs a repo which
answers. The kernel creates a throwaway **private** dataset repo holding nothing but
`latest.json = {"step": 0, "path_in_repo": "final"}`, reads that name back out of the publisher's stdout, and
deletes the repo in a `finally`.

Four cases, free CPU, nothing published:
  1  static  -- the fetch is built from the argument; no fetch is built from the constant.
  2  help    -- `--help` lists `--ckpt-repo`.
  3  positive-- the new file, told to read the temp repo, prints that repo's name and step 0, and stops before
                any upload (the temp repo has no `final/`, which is the expected place for it to stop).
  4  contrast-- the old file at REV `55f23ef5` rejects `--ckpt-repo` outright (argparse rc 2), so case 3 is
                evidence about this change and not about something that was always true.

Layout matters: the publisher resolves `ounce100m_credentials` from its own grandparent directory
(`sys.path.insert(0, dirname(dirname(__file__)))`), and a subprocess is a fresh interpreter that inherits
nothing this kernel puts on `sys.path` -- so both copies go exactly where Phase 5 put them,
`<work>/build/publish_model.py` beside `<work>/ounce100m_credentials.py`. (E-056 was this same bug.)
"""
import hashlib
import io
import json
import os
import subprocess
import sys
import urllib.request

CODE = "Cion-lab/ounce100m-code"
NEW_REV = "dd1b6b94cc90ae6deff94e0990d58da64c6637f1"
NEW_SHA = "d1f3c4eb2b80cd4bff35c1b1b90a67ec6204dd753e09f354673d0812cc231e01"
OLD_REV = "55f23ef5d0e8e6a60adad23bf8a2ffffc6bc7580"
CRED_SHA = "6525f62f03f2d73650a1eb4f70fcb52d1194caad4ca88b2d8bd8fd54f88339b6"
TMP = "Cion-lab/ounce100m-p7-probe-tmp"
WORK = "/kaggle/working"


def fetch(rev, path):
    url = f"https://huggingface.co/{CODE}/resolve/{rev}/{path}"
    return urllib.request.urlopen(url, timeout=120).read()


def report(R, why=""):
    print("PROBE_JSON_BEGIN\n" + json.dumps(R, indent=1) + "\nPROBE_JSON_END", flush=True)
    oks = [v for k, v in R.items() if k.startswith("case")]
    ok = bool(oks) and all(oks)
    print(f"VERDICT PUBLISH_SOURCE {'PASS' if ok else 'FAIL'} {why}", flush=True)
    return ok


R = {}
try:
    for d in ("build", "build_old"):
        os.makedirs(os.path.join(WORK, d), exist_ok=True)
    cb = fetch(NEW_REV, "ounce100m_credentials.py")
    assert hashlib.sha256(cb).hexdigest() == CRED_SHA, "credentials module is not the Phase 5 bytes"
    open(os.path.join(WORK, "ounce100m_credentials.py"), "wb").write(cb)
    sys.path.insert(0, WORK)
    import ounce100m_credentials
    ounce100m_credentials.install(verify=True)
    from huggingface_hub import HfApi
    api = HfApi()

    nb = fetch(NEW_REV, "build/publish_model.py")
    R["pinned_bytes_ok"] = hashlib.sha256(nb).hexdigest() == NEW_SHA
    assert R["pinned_bytes_ok"], "the pinned publisher is not the bytes this probe was written against"
    newp = os.path.join(WORK, "build", "publish_model.py")
    oldp = os.path.join(WORK, "build_old", "publish_model.py")
    open(newp, "wb").write(nb)
    open(oldp, "wb").write(fetch(OLD_REV, "build/publish_model.py"))

    src = nb.decode("utf-8")
    R["case1_static_arg_wired"] = "datasets/{a.ckpt_repo}/resolve/main/latest.json" in src
    R["case1_static_no_constant_fetch"] = ("datasets/{CKPT}/resolve" not in src
                                           and "snapshot_download(CKPT" not in src)
    R["case2_help_lists_flag"] = "--ckpt-repo" in subprocess.run(
        [sys.executable, newp, "--help"], capture_output=True, text=True).stdout

    tok = os.environ["HF_TOKEN"]
    api.create_repo(repo_id=TMP, repo_type="dataset", private=True, exist_ok=True, token=tok)
    api.upload_file(path_or_fileobj=io.BytesIO(json.dumps({"step": 0, "path_in_repo": "final"}).encode()),
                    path_in_repo="latest.json", repo_id=TMP, repo_type="dataset", token=tok)
    made = True

    r = subprocess.run([sys.executable, newp, "--dry-run", "--ckpt-repo", TMP],
                       capture_output=True, text=True)
    out = r.stdout + r.stderr
    R["case3_names_the_repo_it_was_given"] = f"'repo': '{TMP}'" in out
    R["case3_read_the_pointer"] = "'step': 0" in out
    R["case3_stopped_before_upload"] = r.returncode != 0 and "uploading" not in out
    ro = subprocess.run([sys.executable, oldp, "--dry-run", "--ckpt-repo", TMP],
                        capture_output=True, text=True)
    R["case4_old_file_rejects_the_flag"] = ro.returncode == 2 and "unrecognized arguments" in ro.stderr
    R["observed_tail"] = out.strip().splitlines()[-1][:160] if out.strip() else ""
except Exception as e:
    R["aborted"] = f"{type(e).__name__}: {str(e)[:200]}"
finally:
    if locals().get("made"):
        try:
            api.delete_repo(repo_id=TMP, repo_type="dataset")
            R["temp_repo_deleted"] = True
        except Exception as e:
            R["temp_repo_deleted"] = f"FAILED {type(e).__name__} -- delete {TMP} by hand"

sys.exit(0 if report(R, R.get("aborted", "")) else 1)