phera-ra commited on
Commit
1ea06d3
·
verified ·
1 Parent(s): 753bfab

Add kit_health.py -- the check that proves the kit works

Browse files

Built 2026-08-01 and never uploaded. It verifies every part of the kit on three axes -- PRESENT (exists on disk), LOADS (opens/imports/answers), ANSWERS (produces a real result) -- because a weight file that exists but will not load, and a server that listens but returns nothing, both report "fine" to any check that stops at PRESENT.

It caught a private memory file staged for upload before it left the machine, and it is what verified the kit works from a clean directory with none of the author's environment around it.

Files changed (1) hide show
  1. kit_health.py +276 -0
kit_health.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """KIT HEALTH -- every part of this kit, checked in threes.
3
+
4
+ Six mechanisms in this project were once found doing nothing while reporting
5
+ success, and not one of them threw an error. Looked at together they always
6
+ failed in one of exactly three places:
7
+
8
+ PRESENT the thing exists on disk
9
+ LOADS it can actually be opened / imported / reached
10
+ ANSWERS it produces a real result when asked
11
+
12
+ A weight file that exists but will not load is dead. A server that listens but
13
+ returns nothing is dead. Both report "fine" to any check that stops at PRESENT,
14
+ which is why this checks all three and treats two-of-three as failure.
15
+
16
+ python kit_health.py full report
17
+ python kit_health.py --quiet only what is broken
18
+
19
+ Exit code 0 when everything is alive, 1 otherwise -- so it can gate a release.
20
+ """
21
+ from __future__ import annotations
22
+
23
+ import json
24
+ import os
25
+ import socket
26
+ import sys
27
+ import urllib.error
28
+ import urllib.request
29
+ from pathlib import Path
30
+
31
+ try:
32
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
33
+ except Exception:
34
+ pass
35
+
36
+ ROOT = Path(__file__).resolve().parent
37
+ QUIET = "--quiet" in sys.argv
38
+ PORT = int(os.getenv("COSMOS_KIT_PORT", "11501"))
39
+ HOST = f"http://127.0.0.1:{PORT}"
40
+
41
+ OK, DEAD, WARN = "OK", "DEAD", "warn"
42
+
43
+
44
+ # ── probes ──────────────────────────────────────────────────────────────────
45
+ def _port_open(port: int, timeout: float = 2.0) -> bool:
46
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
47
+ s.settimeout(timeout)
48
+ return s.connect_ex(("127.0.0.1", port)) == 0
49
+
50
+
51
+ def _get(path: str, timeout: float = 6.0):
52
+ try:
53
+ with urllib.request.urlopen(HOST + path, timeout=timeout) as r:
54
+ return json.loads(r.read() or b"{}")
55
+ except Exception:
56
+ return None
57
+
58
+
59
+ def _post(path: str, payload: dict, timeout: float = 90.0):
60
+ try:
61
+ req = urllib.request.Request(
62
+ HOST + path,
63
+ data=json.dumps(payload).encode("utf-8"),
64
+ headers={"Content-Type": "application/json"},
65
+ )
66
+ with urllib.request.urlopen(req, timeout=timeout) as r:
67
+ return json.loads(r.read() or b"{}")
68
+ except Exception:
69
+ return None
70
+
71
+
72
+ # ── the checks ──────────────────────────────────────────────────────────────
73
+ def check_python():
74
+ v = sys.version_info
75
+ present = OK if v >= (3, 9) else DEAD
76
+ try:
77
+ import torch # noqa: F401
78
+ loads = OK
79
+ detail = f"python {v.major}.{v.minor}.{v.micro}, torch {torch.__version__}"
80
+ except Exception as e:
81
+ return present, DEAD, DEAD, f"torch missing ({type(e).__name__}) -- pip install torch"
82
+ try:
83
+ import torch
84
+ t = torch.ones(4, 4) @ torch.ones(4, 4)
85
+ answers = OK if float(t.sum()) == 64.0 else DEAD
86
+ except Exception as e:
87
+ answers, detail = DEAD, f"torch cannot multiply: {type(e).__name__}"
88
+ return present, loads, answers, detail
89
+
90
+
91
+ def check_weight(name: str, filename: str):
92
+ p = ROOT / "weights" / filename
93
+ if not p.exists():
94
+ return DEAD, DEAD, DEAD, f"weights/{filename} is missing"
95
+ size = p.stat().st_size
96
+ try:
97
+ import torch
98
+ ck = torch.load(p, map_location="cpu", weights_only=False)
99
+ except Exception as e:
100
+ return OK, DEAD, DEAD, f"{size/1e6:.1f} MB but will not load: {type(e).__name__}"
101
+ sd = ck.get("model") or ck.get("state_dict") or ck if isinstance(ck, dict) else {}
102
+ n = 0
103
+ try:
104
+ n = sum(int(v.numel()) for v in sd.values() if hasattr(v, "numel"))
105
+ except Exception:
106
+ pass
107
+ if not n:
108
+ return OK, OK, DEAD, f"{size/1e6:.1f} MB, loads, but holds no tensors"
109
+ extra = ""
110
+ if isinstance(ck, dict):
111
+ step = ck.get("total_steps") or ck.get("step")
112
+ val = ck.get("val") or ck.get("val_loss")
113
+ bits = [b for b in (f"step {step:,}" if isinstance(step, int) else None,
114
+ f"val {val:.5f}" if isinstance(val, float) else None) if b]
115
+ extra = (" " + ", ".join(bits)) if bits else ""
116
+ return OK, OK, OK, f"{n:,} params, {size/1e6:.1f} MB{extra}"
117
+
118
+
119
+ def check_server():
120
+ present = OK if (ROOT / "serving" / "cosmos_serve.py").exists() else DEAD
121
+ if present == DEAD:
122
+ return present, DEAD, DEAD, "serving/cosmos_serve.py is missing"
123
+ if not _port_open(PORT):
124
+ return present, DEAD, DEAD, f"nothing listening on {PORT} -- menu option 3 starts it"
125
+ tags = _get("/api/tags")
126
+ if tags is None:
127
+ return present, DEAD, DEAD, f"port {PORT} is open but /api/tags does not answer"
128
+ names = [m.get("name", "") for m in tags.get("models", [])]
129
+ hers = [n for n in names if n.startswith(("cosmos-phos", "cosmos-cst", "cosmos-spark"))]
130
+ if not hers:
131
+ return present, OK, DEAD, f"{len(names)} models served, none of them hers"
132
+ return present, OK, OK, f"{len(hers)} of hers served: {', '.join(sorted(hers))}"
133
+
134
+
135
+ def check_voice():
136
+ """The one that matters: does she actually say anything back?"""
137
+ if not _port_open(PORT):
138
+ return DEAD, DEAD, DEAD, "server offline"
139
+ tags = _get("/api/tags") or {}
140
+ names = [m.get("name", "") for m in tags.get("models", [])]
141
+ hers = [n for n in names if n.startswith("cosmos-phos")] or \
142
+ [n for n in names if n.startswith(("cosmos-cst", "cosmos-spark"))]
143
+ if not hers:
144
+ return OK, DEAD, DEAD, "no model of hers to speak through"
145
+ model = hers[0]
146
+ r = _post("/api/chat", {
147
+ "model": model,
148
+ "messages": [{"role": "user", "content": "hello"}],
149
+ "stream": False,
150
+ "options": {"num_predict": 24},
151
+ })
152
+ if r is None:
153
+ return OK, OK, DEAD, f"{model} accepted no request (timeout or error)"
154
+ text = ((r.get("message") or {}).get("content") or r.get("response") or "").strip()
155
+ if not text:
156
+ return OK, OK, DEAD, f"{model} answered with an empty string"
157
+ snip = text.replace("\n", " ")[:58]
158
+ return OK, OK, OK, f"{model} said: \"{snip}{'...' if len(text) > 58 else ''}\""
159
+
160
+
161
+ def check_coder():
162
+ p = ROOT / "serving" / "cosmos_coder.py"
163
+ if not p.exists():
164
+ return DEAD, DEAD, DEAD, "serving/cosmos_coder.py is missing"
165
+ src = p.read_text(encoding="utf-8", errors="ignore")
166
+ loads = OK
167
+ try:
168
+ compile(src, str(p), "exec")
169
+ except SyntaxError as e:
170
+ return OK, DEAD, DEAD, f"will not compile: line {e.lineno}"
171
+ ws = ROOT / "workspace"
172
+ try:
173
+ ws.mkdir(exist_ok=True)
174
+ probe = ws / ".health_probe"
175
+ probe.write_text("ok", encoding="utf-8")
176
+ probe.unlink()
177
+ except Exception as e:
178
+ return OK, loads, DEAD, f"workspace not writable: {type(e).__name__}"
179
+ switching = "/model" in src and "/models" in src
180
+ if not switching:
181
+ return OK, loads, DEAD, "compiles, but has no /model switching"
182
+ return OK, loads, OK, "compiles, workspace writable, /model switching present"
183
+
184
+
185
+ def check_no_secrets():
186
+ """A release must not carry credentials. This is the gate that was skipped."""
187
+ cfg = ROOT / "genesis_engine" / "config.json"
188
+ if not cfg.exists():
189
+ return WARN, WARN, WARN, "genesis_engine/config.json absent (fine if intentional)"
190
+ try:
191
+ d = json.loads(cfg.read_text(encoding="utf-8"))
192
+ except Exception as e:
193
+ return OK, DEAD, DEAD, f"config.json will not parse: {type(e).__name__}"
194
+ filled = [k for k in ("ibm_token", "azure_connection_string")
195
+ if str(d.get(k) or "").strip()]
196
+ if filled:
197
+ return OK, OK, DEAD, f"CREDENTIAL PRESENT in config.json: {', '.join(filled)} -- do not upload"
198
+ forbidden = []
199
+ for pat in (".ledger_key", "oauth2_tokens.json", ".env", "credentials.json",
200
+ ".coder_history.jsonl", "memory.jsonl", "ledger.jsonl"):
201
+ forbidden += [p for p in ROOT.rglob(pat) if p.is_file()]
202
+ if forbidden:
203
+ rels = ", ".join(str(p.relative_to(ROOT)) for p in forbidden[:4])
204
+ return OK, OK, DEAD, f"private files staged: {rels}"
205
+ return OK, OK, OK, "no credentials, no private files staged"
206
+
207
+
208
+ def check_docs():
209
+ need = ["README.md", "START_HERE.md", "FINDINGS.md", "QUANTUM_CREATURE.md", "LICENSE.md"]
210
+ missing = [n for n in need if not (ROOT / n).exists()]
211
+ if missing:
212
+ return DEAD, DEAD, DEAD, f"missing: {', '.join(missing)}"
213
+ readme = (ROOT / "README.md").read_text(encoding="utf-8", errors="ignore")
214
+ head = readme[:2000].lower()
215
+ if "qwen" in head.split("## ")[0]:
216
+ return OK, OK, DEAD, "README leads with qwen instead of her own work"
217
+ if "phos" not in head:
218
+ return OK, OK, DEAD, "README does not lead with PHOS"
219
+ return OK, OK, OK, f"{len(need)} docs present, README leads with PHOS"
220
+
221
+
222
+ CHECKS = [
223
+ ("python + torch", check_python),
224
+ ("PHOS weights", lambda: check_weight("PHOS", "phos.pt")),
225
+ ("CST weights", lambda: check_weight("CST", "spark_cst.pt")),
226
+ ("quantum-born weights", lambda: check_weight("born", "cosmos_born.pt")),
227
+ ("her model server", check_server),
228
+ ("HER VOICE (round trip)", check_voice),
229
+ ("the coder", check_coder),
230
+ ("no secrets shipped", check_no_secrets),
231
+ ("docs + model card", check_docs),
232
+ ]
233
+
234
+
235
+ def main() -> int:
236
+ w = 76
237
+ print("=" * w)
238
+ print(" KIT HEALTH PRESENT -> LOADS -> ANSWERS")
239
+ print("=" * w)
240
+ print(" A part is alive only if all three hold. Two of three is exactly the")
241
+ print(" condition that lets a broken kit report that it is fine.\n")
242
+
243
+ bad = []
244
+ for name, fn in CHECKS:
245
+ try:
246
+ present, loads, answers, detail = fn()
247
+ except Exception as e:
248
+ present = loads = answers = DEAD
249
+ detail = f"check itself raised {type(e).__name__}: {e}"
250
+ trio = [present, loads, answers]
251
+ alive = all(t == OK for t in trio)
252
+ soft = all(t == WARN for t in trio)
253
+ if not alive and not soft:
254
+ bad.append((name, trio, detail))
255
+ if QUIET and (alive or soft):
256
+ continue
257
+ mark = "OK " if alive else ("~ " if soft else "XX ")
258
+ print(f" {mark} {name}")
259
+ print(f" PRESENT {present:<5} LOADS {loads:<5} ANSWERS {answers:<5} {detail}")
260
+
261
+ print("\n" + "=" * w)
262
+ print(f" {len(CHECKS) - len(bad)}/{len(CHECKS)} parts alive on all three")
263
+ if bad:
264
+ print("\n needs attention:")
265
+ for name, trio, detail in bad:
266
+ miss = [lbl for lbl, v in zip(("PRESENT", "LOADS", "ANSWERS"), trio) if v != OK]
267
+ print(f" - {name}: {', '.join(miss)}")
268
+ print(f" {detail}")
269
+ print("\n most failures here are fixed by menu option 3 (start her model server).")
270
+ return 1
271
+ print(" everything works. Nothing is quietly doing nothing.")
272
+ return 0
273
+
274
+
275
+ if __name__ == "__main__":
276
+ raise SystemExit(main())