Cion-lab commited on
Commit
50154fa
·
verified ·
1 Parent(s): 17135b7

p7 probe: prove --ckpt-repo chooses the publisher's weight source

Browse files
Files changed (1) hide show
  1. kernels/p7_probe_publish_source.py +38 -28
kernels/p7_probe_publish_source.py CHANGED
@@ -8,18 +8,23 @@ deleted the failure arrives as a confusing 404 instead of a wrong answer.
8
  Why a 404 cannot be the test. A traceback prints the failing *source line*, which contains the literal
9
  `{a.ckpt_repo}`, not the URL it resolved to. "It died" therefore says nothing about which repo it asked for,
10
  and a probe asserting on that text would pass whether or not the fix works. So the decisive read is the
11
- publisher's own `ckpt latest.json -> {...}` print, which names the repo it fetched -- that needs a repo that
12
- answers. The kernel therefore creates a throwaway **private** dataset repo containing nothing but
13
- `latest.json = {"step": 0, "path_in_repo": "final"}`, reads that dict back out of the publisher's stdout, and
14
- deletes the repo in a `finally`. If the constant still won, the print would name `ounce100m-ckpt` and the fetch
15
- would 404, and the assertion fails for the right reason.
16
 
17
  Four cases, free CPU, nothing published:
18
  1 static -- the fetch is built from the argument; no fetch is built from the constant.
19
  2 help -- `--help` lists `--ckpt-repo`.
20
- 3 positive-- the new file, told to read the temp repo, prints that repo's name and step 0.
21
- 4 contrast-- the old file at REV `55f23ef5` rejects `--ckpt-repo` outright (rc 2, argparse), so case 3 is
22
- evidence about the change and not about something that was always true.
 
 
 
 
 
 
23
  """
24
  import hashlib
25
  import io
@@ -33,37 +38,44 @@ CODE = "Cion-lab/ounce100m-code"
33
  NEW_REV = "dd1b6b94cc90ae6deff94e0990d58da64c6637f1"
34
  NEW_SHA = "d1f3c4eb2b80cd4bff35c1b1b90a67ec6204dd753e09f354673d0812cc231e01"
35
  OLD_REV = "55f23ef5d0e8e6a60adad23bf8a2ffffc6bc7580"
 
36
  TMP = "Cion-lab/ounce100m-p7-probe-tmp"
 
37
 
38
 
39
- def fetch(rev):
40
- url = f"https://huggingface.co/{CODE}/resolve/{rev}/build/publish_model.py"
41
  return urllib.request.urlopen(url, timeout=120).read()
42
 
43
 
44
  def report(R, why=""):
45
  print("PROBE_JSON_BEGIN\n" + json.dumps(R, indent=1) + "\nPROBE_JSON_END", flush=True)
46
- ok = all(v for k, v in R.items() if k.startswith("case"))
 
47
  print(f"VERDICT PUBLISH_SOURCE {'PASS' if ok else 'FAIL'} {why}", flush=True)
48
  return ok
49
 
50
 
51
  R = {}
52
  try:
53
- sys.path.insert(0, "/kaggle/working/lib")
 
 
 
 
 
54
  import ounce100m_credentials
55
  ounce100m_credentials.install(verify=True)
56
  from huggingface_hub import HfApi
57
  api = HfApi()
58
 
59
- os.makedirs("/kaggle/working/lib", exist_ok=True)
60
- newp, oldp = "/kaggle/working/pub_new.py", "/kaggle/working/pub_old.py"
61
- nb = fetch(NEW_REV)
 
 
62
  open(newp, "wb").write(nb)
63
- got = hashlib.sha256(nb).hexdigest()
64
- R["fetched"] = f"{NEW_REV[:10]} sha_ok={got == NEW_SHA}"
65
- assert got == NEW_SHA, "the pinned publisher bytes are not what this probe was written against"
66
- open(oldp, "wb").write(fetch(OLD_REV))
67
 
68
  src = nb.decode("utf-8")
69
  R["case1_static_arg_wired"] = "datasets/{a.ckpt_repo}/resolve/main/latest.json" in src
@@ -72,24 +84,22 @@ try:
72
  R["case2_help_lists_flag"] = "--ckpt-repo" in subprocess.run(
73
  [sys.executable, newp, "--help"], capture_output=True, text=True).stdout
74
 
75
- api.create_repo(repo_id=TMP, repo_type="dataset", private=True, exist_ok=True,
76
- token=os.environ["HF_TOKEN"])
77
  api.upload_file(path_or_fileobj=io.BytesIO(json.dumps({"step": 0, "path_in_repo": "final"}).encode()),
78
- path_in_repo="latest.json", repo_id=TMP, repo_type="dataset", token=os.environ["HF_TOKEN"])
79
  made = True
80
 
81
  r = subprocess.run([sys.executable, newp, "--dry-run", "--ckpt-repo", TMP],
82
  capture_output=True, text=True)
83
  out = r.stdout + r.stderr
84
  R["case3_names_the_repo_it_was_given"] = f"'repo': '{TMP}'" in out
85
- R["case3_read_the_pointer"] = "'step': 0" in out and "path_in_repo" in out
86
- # It then looks for `final/`, which the temp repo does not have: stopping there is the expected outcome,
87
- # and it is what proves no upload was attempted.
88
- R["case3_stopped_before_upload"] = r.returncode != 0 and "upload" not in out.lower()
89
-
90
  ro = subprocess.run([sys.executable, oldp, "--dry-run", "--ckpt-repo", TMP],
91
  capture_output=True, text=True)
92
  R["case4_old_file_rejects_the_flag"] = ro.returncode == 2 and "unrecognized arguments" in ro.stderr
 
93
  except Exception as e:
94
  R["aborted"] = f"{type(e).__name__}: {str(e)[:200]}"
95
  finally:
@@ -98,6 +108,6 @@ finally:
98
  api.delete_repo(repo_id=TMP, repo_type="dataset")
99
  R["temp_repo_deleted"] = True
100
  except Exception as e:
101
- R["temp_repo_deleted"] = f"FAILED {type(e).__name__} -- remove {TMP} by hand"
102
 
103
  sys.exit(0 if report(R, R.get("aborted", "")) else 1)
 
8
  Why a 404 cannot be the test. A traceback prints the failing *source line*, which contains the literal
9
  `{a.ckpt_repo}`, not the URL it resolved to. "It died" therefore says nothing about which repo it asked for,
10
  and a probe asserting on that text would pass whether or not the fix works. So the decisive read is the
11
+ publisher's own `ckpt latest.json -> {...}` print, which names the repo it fetched -- that needs a repo which
12
+ answers. The kernel creates a throwaway **private** dataset repo holding nothing but
13
+ `latest.json = {"step": 0, "path_in_repo": "final"}`, reads that name back out of the publisher's stdout, and
14
+ deletes the repo in a `finally`.
 
15
 
16
  Four cases, free CPU, nothing published:
17
  1 static -- the fetch is built from the argument; no fetch is built from the constant.
18
  2 help -- `--help` lists `--ckpt-repo`.
19
+ 3 positive-- the new file, told to read the temp repo, prints that repo's name and step 0, and stops before
20
+ any upload (the temp repo has no `final/`, which is the expected place for it to stop).
21
+ 4 contrast-- the old file at REV `55f23ef5` rejects `--ckpt-repo` outright (argparse rc 2), so case 3 is
22
+ evidence about this change and not about something that was always true.
23
+
24
+ Layout matters: the publisher resolves `ounce100m_credentials` from its own grandparent directory
25
+ (`sys.path.insert(0, dirname(dirname(__file__)))`), and a subprocess is a fresh interpreter that inherits
26
+ nothing this kernel puts on `sys.path` -- so both copies go exactly where Phase 5 put them,
27
+ `<work>/build/publish_model.py` beside `<work>/ounce100m_credentials.py`. (E-056 was this same bug.)
28
  """
29
  import hashlib
30
  import io
 
38
  NEW_REV = "dd1b6b94cc90ae6deff94e0990d58da64c6637f1"
39
  NEW_SHA = "d1f3c4eb2b80cd4bff35c1b1b90a67ec6204dd753e09f354673d0812cc231e01"
40
  OLD_REV = "55f23ef5d0e8e6a60adad23bf8a2ffffc6bc7580"
41
+ CRED_SHA = "6525f62f03f2d73650a1eb4f70fcb52d1194caad4ca88b2d8bd8fd54f88339b6"
42
  TMP = "Cion-lab/ounce100m-p7-probe-tmp"
43
+ WORK = "/kaggle/working"
44
 
45
 
46
+ def fetch(rev, path):
47
+ url = f"https://huggingface.co/{CODE}/resolve/{rev}/{path}"
48
  return urllib.request.urlopen(url, timeout=120).read()
49
 
50
 
51
  def report(R, why=""):
52
  print("PROBE_JSON_BEGIN\n" + json.dumps(R, indent=1) + "\nPROBE_JSON_END", flush=True)
53
+ oks = [v for k, v in R.items() if k.startswith("case")]
54
+ ok = bool(oks) and all(oks)
55
  print(f"VERDICT PUBLISH_SOURCE {'PASS' if ok else 'FAIL'} {why}", flush=True)
56
  return ok
57
 
58
 
59
  R = {}
60
  try:
61
+ for d in ("build", "build_old"):
62
+ os.makedirs(os.path.join(WORK, d), exist_ok=True)
63
+ cb = fetch(NEW_REV, "ounce100m_credentials.py")
64
+ assert hashlib.sha256(cb).hexdigest() == CRED_SHA, "credentials module is not the Phase 5 bytes"
65
+ open(os.path.join(WORK, "ounce100m_credentials.py"), "wb").write(cb)
66
+ sys.path.insert(0, WORK)
67
  import ounce100m_credentials
68
  ounce100m_credentials.install(verify=True)
69
  from huggingface_hub import HfApi
70
  api = HfApi()
71
 
72
+ nb = fetch(NEW_REV, "build/publish_model.py")
73
+ R["pinned_bytes_ok"] = hashlib.sha256(nb).hexdigest() == NEW_SHA
74
+ assert R["pinned_bytes_ok"], "the pinned publisher is not the bytes this probe was written against"
75
+ newp = os.path.join(WORK, "build", "publish_model.py")
76
+ oldp = os.path.join(WORK, "build_old", "publish_model.py")
77
  open(newp, "wb").write(nb)
78
+ open(oldp, "wb").write(fetch(OLD_REV, "build/publish_model.py"))
 
 
 
79
 
80
  src = nb.decode("utf-8")
81
  R["case1_static_arg_wired"] = "datasets/{a.ckpt_repo}/resolve/main/latest.json" in src
 
84
  R["case2_help_lists_flag"] = "--ckpt-repo" in subprocess.run(
85
  [sys.executable, newp, "--help"], capture_output=True, text=True).stdout
86
 
87
+ tok = os.environ["HF_TOKEN"]
88
+ api.create_repo(repo_id=TMP, repo_type="dataset", private=True, exist_ok=True, token=tok)
89
  api.upload_file(path_or_fileobj=io.BytesIO(json.dumps({"step": 0, "path_in_repo": "final"}).encode()),
90
+ path_in_repo="latest.json", repo_id=TMP, repo_type="dataset", token=tok)
91
  made = True
92
 
93
  r = subprocess.run([sys.executable, newp, "--dry-run", "--ckpt-repo", TMP],
94
  capture_output=True, text=True)
95
  out = r.stdout + r.stderr
96
  R["case3_names_the_repo_it_was_given"] = f"'repo': '{TMP}'" in out
97
+ R["case3_read_the_pointer"] = "'step': 0" in out
98
+ R["case3_stopped_before_upload"] = r.returncode != 0 and "uploading" not in out
 
 
 
99
  ro = subprocess.run([sys.executable, oldp, "--dry-run", "--ckpt-repo", TMP],
100
  capture_output=True, text=True)
101
  R["case4_old_file_rejects_the_flag"] = ro.returncode == 2 and "unrecognized arguments" in ro.stderr
102
+ R["observed_tail"] = out.strip().splitlines()[-1][:160] if out.strip() else ""
103
  except Exception as e:
104
  R["aborted"] = f"{type(e).__name__}: {str(e)[:200]}"
105
  finally:
 
108
  api.delete_repo(repo_id=TMP, repo_type="dataset")
109
  R["temp_repo_deleted"] = True
110
  except Exception as e:
111
+ R["temp_repo_deleted"] = f"FAILED {type(e).__name__} -- delete {TMP} by hand"
112
 
113
  sys.exit(0 if report(R, R.get("aborted", "")) else 1)