loginowskid commited on
Commit
d4776d0
·
1 Parent(s): 5c23a4e

Spec drift detection @0041177

Browse files
tools/hf_space/runner.py CHANGED
@@ -1056,6 +1056,71 @@ def _foundation_sha() -> str:
1056
  return os.environ.get("SIMREADY_FOUNDATIONS_COMMIT", "unpinned")
1057
 
1058
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1059
  def _validator_version() -> str:
1060
  """Version of the simready-validate package that ships in this Space."""
1061
  try:
@@ -1316,6 +1381,23 @@ def run(
1316
  summary="validator produced no result (unified streaming path returned None)",
1317
  results_json={}, report_path=out_dir, pr_url=None,
1318
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1319
  results_path.write_text(json.dumps(streamed), encoding="utf-8")
1320
  results_json = streamed
1321
  status, summary = _summarize(results_json)
 
1056
  return os.environ.get("SIMREADY_FOUNDATIONS_COMMIT", "unpinned")
1057
 
1058
 
1059
+ # Path to the spec-sync state file. The state file declares which
1060
+ # foundation commit our hardcoded validator rules were last aligned
1061
+ # against. The Space's checkout includes the file at this relative
1062
+ # path (tools/spec_sync/state.json in the repo).
1063
+ _SPEC_SYNC_STATE_FILE = Path(__file__).resolve().parents[2] / "tools" / "spec_sync" / "state.json"
1064
+
1065
+
1066
+ def _check_foundation_spec_drift() -> dict:
1067
+ """Check whether NVIDIA/simready-foundation has new commits to its
1068
+ spec dir since we last synced our hardcoded rules.
1069
+
1070
+ Cheap event-driven drift detection (one GitHub API call per run,
1071
+ soft-fails on errors). The validator surfaces drift in results.json
1072
+ so the dashboard can warn operators that hardcoded rules may be
1073
+ stale relative to the source of truth. Auto-update is the
1074
+ follow-up step (spec-sync workflow opens a PR to refresh rules).
1075
+
1076
+ Returns a dict the dashboard renders; never raises.
1077
+ """
1078
+ out: dict = {"checked": False}
1079
+ try:
1080
+ if not _SPEC_SYNC_STATE_FILE.is_file():
1081
+ out["reason"] = "state file missing"
1082
+ return out
1083
+ state = json.loads(_SPEC_SYNC_STATE_FILE.read_text(encoding="utf-8"))
1084
+ last_sync_sha = state.get("foundation_commit_sha") or ""
1085
+ last_sync_at = state.get("synced_at") or ""
1086
+ watched_path = state.get("watched_path") or "nv_core/sr_specs/docs"
1087
+ repo = state.get("foundation_repo") or "NVIDIA/simready-foundation"
1088
+ except Exception as e:
1089
+ out["reason"] = f"could not read state: {type(e).__name__}: {e}"
1090
+ return out
1091
+ try:
1092
+ import urllib.request
1093
+ url = (f"https://api.github.com/repos/{repo}/commits"
1094
+ f"?path={watched_path}&per_page=1")
1095
+ req = urllib.request.Request(url)
1096
+ req.add_header("Accept", "application/vnd.github.v3+json")
1097
+ token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_VALIDATOR_TOKEN")
1098
+ if token:
1099
+ req.add_header("Authorization", f"Bearer {token}")
1100
+ with urllib.request.urlopen(req, timeout=8) as resp:
1101
+ data = json.loads(resp.read())
1102
+ except Exception as e:
1103
+ out["reason"] = f"github api: {type(e).__name__}: {e}"
1104
+ return out
1105
+ if not isinstance(data, list) or not data:
1106
+ out["reason"] = "no commit data"
1107
+ return out
1108
+ current = data[0] or {}
1109
+ current_sha = current.get("sha") or ""
1110
+ current_at = (current.get("commit") or {}).get("committer", {}).get("date") or ""
1111
+ drifted = bool(current_sha) and current_sha != last_sync_sha
1112
+ return {
1113
+ "checked": True,
1114
+ "drifted": drifted,
1115
+ "current_sha": current_sha,
1116
+ "current_at": current_at,
1117
+ "last_sync_sha": last_sync_sha,
1118
+ "last_sync_at": last_sync_at,
1119
+ "repo": repo,
1120
+ "watched_path": watched_path,
1121
+ }
1122
+
1123
+
1124
  def _validator_version() -> str:
1125
  """Version of the simready-validate package that ships in this Space."""
1126
  try:
 
1381
  summary="validator produced no result (unified streaming path returned None)",
1382
  results_json={}, report_path=out_dir, pr_url=None,
1383
  )
1384
+ # Event-driven foundation spec drift check. One GitHub API
1385
+ # call per run; soft-fails so network hiccups don't block
1386
+ # validation. The dashboard renders a notice if drifted=true.
1387
+ drift = _check_foundation_spec_drift()
1388
+ if drift.get("checked"):
1389
+ if drift.get("drifted"):
1390
+ out(f" ⚠ spec drift: foundation HEAD={drift.get('current_sha', '')[:8]} "
1391
+ f"@ {drift.get('current_at', '')}, last synced "
1392
+ f"{drift.get('last_sync_sha', '')[:8]} @ {drift.get('last_sync_at', '')} "
1393
+ f"— hardcoded rules may be stale; run spec-sync to refresh")
1394
+ else:
1395
+ out(f" spec sync: in sync with foundation HEAD "
1396
+ f"{drift.get('current_sha', '')[:8]}")
1397
+ else:
1398
+ out(f" spec sync: skipped ({drift.get('reason', 'unknown')})")
1399
+ streamed["spec_drift"] = drift
1400
+
1401
  results_path.write_text(json.dumps(streamed), encoding="utf-8")
1402
  results_json = streamed
1403
  status, summary = _summarize(results_json)
tools/spec_sync/state.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_doc": "Drift state for NVIDIA/simready-foundation specs. The validator hits the GitHub API on every run; if the latest commit touching nv_core/sr_specs/docs differs from foundation_commit_sha below, the validator surfaces a 'spec drift' warning and (future) triggers the spec-sync workflow to auto-update hardcoded rules.",
3
+ "foundation_repo": "NVIDIA/simready-foundation",
4
+ "watched_path": "nv_core/sr_specs/docs",
5
+ "foundation_commit_sha": "805d2c50179a9878c89b0f41baaa0ecafe47c3d7",
6
+ "synced_at": "2026-06-02T00:00:00Z",
7
+ "synced_by": "initial-setup",
8
+ "rules_pinned_against": [
9
+ "AA.002 supported-file-types (validate.py:_AA_002_ALLOWED)"
10
+ ]
11
+ }