specimba commited on
Commit
dc6756e
·
verified ·
1 Parent(s): 2ef5999

Deploy PR5 scan gate hardening 1cca102

Browse files
README.md CHANGED
@@ -92,17 +92,18 @@ Public demo mode excludes private, commercial-uncleared, and research-only helpe
92
  | <=32B models | Public stack is 11.42B: FLUX.2 Klein 4B + LocateAnything 3.83B + MiniCPM-V 1.30B + Nemotron Parse 0.94B + MiniCPM5 1.08B + FunctionGemma 0.27B. |
93
  | Off Brand | Custom command-center UI, dense inspector, workflow graph, wardrobe/lore drawer, and provider cards. |
94
  | Best Agent | Multi-step prompt, generation, scan, judge, checkpoint, export workflow. |
95
- | OpenBMB | Claimed only when MiniCPM-V returns judge evidence in an export packet. |
96
- | NVIDIA | Claimed only when Nemotron returns evidence in an export packet. LocateAnything remains visible but is not the Nemotron claim by itself. |
97
  | OpenAI Codex | Development branch and PR include Codex-authored implementation commits. |
98
  | Demo / social | Add final links here before submission: `DEMO_VIDEO_URL` and `SOCIAL_POST_URL`. |
99
 
100
- Tiny Titan can be claimed for the public demo stack because the active public models are each <=4B. The stronger FLUX.2 Klein 9B and OFFELLIA/Gemma stack remains private research only.
101
 
102
  ## Local Setup
103
 
104
  ```powershell
105
  python -m pip install -r requirements.txt
 
106
  python app.py
107
  ```
108
 
@@ -112,6 +113,7 @@ The app reads `NEXUS_PORT` or `PORT` when present, otherwise it launches on `786
112
 
113
  ```powershell
114
  python -m compileall app.py src tests
 
115
  $env:PYTEST_DISABLE_PLUGIN_AUTOLOAD='1'
116
  python -m pytest -q tests -p no:cacheprovider --basetemp=C:\tmp\pytest-nvw-full
117
  ```
 
92
  | <=32B models | Public stack is 11.42B: FLUX.2 Klein 4B + LocateAnything 3.83B + MiniCPM-V 1.30B + Nemotron Parse 0.94B + MiniCPM5 1.08B + FunctionGemma 0.27B. |
93
  | Off Brand | Custom command-center UI, dense inspector, workflow graph, wardrobe/lore drawer, and provider cards. |
94
  | Best Agent | Multi-step prompt, generation, scan, judge, checkpoint, export workflow. |
95
+ | OpenBMB | Claimed only when MiniCPM-V returns success status in an export packet. |
96
+ | NVIDIA | Claimed only when Nemotron returns success status in an export packet. LocateAnything remains visible but is not the Nemotron claim by itself. |
97
  | OpenAI Codex | Development branch and PR include Codex-authored implementation commits. |
98
  | Demo / social | Add final links here before submission: `DEMO_VIDEO_URL` and `SOCIAL_POST_URL`. |
99
 
100
+ Tiny Titan can be claimed only from a successful public-demo export packet because the active public models are each <=4B. The stronger FLUX.2 Klein 9B and OFFELLIA/Gemma stack remains private research only.
101
 
102
  ## Local Setup
103
 
104
  ```powershell
105
  python -m pip install -r requirements.txt
106
+ $env:NEXUS_DISABLE_REAL_HF='1'
107
  python app.py
108
  ```
109
 
 
113
 
114
  ```powershell
115
  python -m compileall app.py src tests
116
+ $env:NEXUS_DISABLE_REAL_HF='1'
117
  $env:PYTEST_DISABLE_PLUGIN_AUTOLOAD='1'
118
  python -m pytest -q tests -p no:cacheprovider --basetemp=C:\tmp\pytest-nvw-full
119
  ```
app.py CHANGED
@@ -77,6 +77,20 @@ def _file_path(uploaded: Any) -> str | None:
77
  return str(path) if path else None
78
 
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  def _checkpoint_seed(checkpoint_id: str) -> int:
81
  suffix = "".join(char for char in checkpoint_id[-8:] if char in "0123456789abcdefABCDEF")
82
  if not suffix:
@@ -133,7 +147,7 @@ def run_weave(
133
  )
134
  reference_scan = scan_file(_file_path(upload))
135
  generation = generate_flux_image(run.refined_prompt.refined, seed=_checkpoint_seed(run.checkpoint.checkpoint_id))
136
- generated_scan = scan_file(generation.output_path) if generation.output_path else reference_scan
137
  minicpm = judge_with_minicpm(
138
  prompt=run.refined_prompt.refined,
139
  image_path=generation.output_path,
@@ -278,25 +292,32 @@ def scan_reference(
278
  active_section: str,
279
  operator_state: dict[str, Any] | None,
280
  ) -> tuple[Any, ...]:
281
- scan = scan_file(_file_path(upload))
 
 
 
282
  minicpm = None
283
- if run is not None:
284
- generated_path = ((operator_state or {}).get("generation") or {}).get("output_path")
285
  minicpm = judge_with_minicpm(
286
  prompt=getattr(getattr(run, "refined_prompt", None), "refined", DEFAULT_PROMPT),
287
- image_path=generated_path or _file_path(upload),
288
- scan=scan,
289
  wardrobe_summary=_wardrobe_summary(run),
290
  )
291
  next_state = {
292
- **(operator_state or _default_operator_state()),
293
  **({"reference_judge": minicpm.to_dict()} if minicpm else {}),
294
- "reference_scan": scan,
295
- "export": scan.get("export_gate", "pending"),
296
- "message": "Reference scan complete. Export gate is clear." if scan.get("export_gate") == "clear" else "Reference scan requires review before export.",
 
 
 
 
 
297
  }
298
- rendered = _render_stateful(run, adult_mode, scan, active_section, next_state)
299
- return (*rendered, scan)
300
 
301
 
302
  def approve_checkpoint(
@@ -306,12 +327,13 @@ def approve_checkpoint(
306
  active_section: str,
307
  operator_state: dict[str, Any] | None,
308
  ) -> tuple[Any, ...]:
309
- scan = scan or scan_file(None)
 
310
  if run is None:
311
  next_state = {**_default_operator_state(), "provider_state": "blocked", "message": "No run exists yet. Run Active Weave first."}
312
- elif not ((operator_state or {}).get("generation") or {}).get("output_path"):
313
  next_state = {
314
- **(operator_state or _default_operator_state()),
315
  "provider_state": "blocked",
316
  "checkpoint": "pending",
317
  "message": "Checkpoint blocked: no generated artifact exists yet.",
@@ -319,9 +341,10 @@ def approve_checkpoint(
319
  else:
320
  export_state = scan.get("export_gate", "pending")
321
  next_state = {
322
- **(operator_state or _default_operator_state()),
323
  "provider_state": "export_ready" if export_state == "clear" else "checkpointed",
324
  "checkpoint": "approved",
 
325
  "export": export_state,
326
  "message": "Checkpoint approved. Export is ready after clear ST3GG scan." if export_state == "clear" else "Checkpoint approved, but export still waits on ST3GG review.",
327
  }
@@ -335,12 +358,14 @@ def export_packet(
335
  active_section: str,
336
  operator_state: dict[str, Any] | None,
337
  ) -> tuple[Any, ...]:
338
- scan = scan or scan_file(None)
339
  state = operator_state or _default_operator_state()
 
340
  if run is None:
341
  next_state = {**state, "provider_state": "blocked", "export": "blocked", "message": "Export blocked: no active run packet exists."}
342
  elif state.get("checkpoint") != "approved":
343
  next_state = {**state, "provider_state": "blocked", "export": "blocked", "message": "Export blocked: human checkpoint has not been approved."}
 
 
344
  elif scan.get("export_gate") != "clear":
345
  next_state = {**state, "provider_state": "blocked", "export": scan.get("export_gate", "blocked"), "message": "Export blocked: ST3GG gate is not clear."}
346
  else:
 
77
  return str(path) if path else None
78
 
79
 
80
+ def _generated_output_path(operator_state: dict[str, Any] | None) -> str | None:
81
+ generation = (operator_state or {}).get("generation") or {}
82
+ output_path = generation.get("output_path")
83
+ return str(output_path) if output_path else None
84
+
85
+
86
+ def _authoritative_generated_scan(operator_state: dict[str, Any] | None) -> dict[str, Any]:
87
+ output_path = _generated_output_path(operator_state)
88
+ if output_path:
89
+ return scan_file(output_path)
90
+ stored_scan = (operator_state or {}).get("generated_scan")
91
+ return stored_scan if isinstance(stored_scan, dict) else scan_file(None)
92
+
93
+
94
  def _checkpoint_seed(checkpoint_id: str) -> int:
95
  suffix = "".join(char for char in checkpoint_id[-8:] if char in "0123456789abcdefABCDEF")
96
  if not suffix:
 
147
  )
148
  reference_scan = scan_file(_file_path(upload))
149
  generation = generate_flux_image(run.refined_prompt.refined, seed=_checkpoint_seed(run.checkpoint.checkpoint_id))
150
+ generated_scan = scan_file(generation.output_path) if generation.output_path else scan_file(None)
151
  minicpm = judge_with_minicpm(
152
  prompt=run.refined_prompt.refined,
153
  image_path=generation.output_path,
 
292
  active_section: str,
293
  operator_state: dict[str, Any] | None,
294
  ) -> tuple[Any, ...]:
295
+ state = operator_state or _default_operator_state()
296
+ reference_path = _file_path(upload)
297
+ reference_scan = scan_file(reference_path)
298
+ generated_scan = _authoritative_generated_scan(state)
299
  minicpm = None
300
+ if run is not None and reference_path:
 
301
  minicpm = judge_with_minicpm(
302
  prompt=getattr(getattr(run, "refined_prompt", None), "refined", DEFAULT_PROMPT),
303
+ image_path=reference_path,
304
+ scan=reference_scan,
305
  wardrobe_summary=_wardrobe_summary(run),
306
  )
307
  next_state = {
308
+ **state,
309
  **({"reference_judge": minicpm.to_dict()} if minicpm else {}),
310
+ "reference_scan": reference_scan,
311
+ "reference_export_gate": reference_scan.get("export_gate", "pending"),
312
+ "export": state.get("export", generated_scan.get("export_gate", "pending")),
313
+ "message": (
314
+ "Reference scan complete. Generated artifact export gate is unchanged."
315
+ if reference_scan.get("export_gate") == "clear"
316
+ else "Reference scan requires review. Generated artifact export gate is unchanged."
317
+ ),
318
  }
319
+ rendered = _render_stateful(run, adult_mode, generated_scan, active_section, next_state)
320
+ return (*rendered, generated_scan)
321
 
322
 
323
  def approve_checkpoint(
 
327
  active_section: str,
328
  operator_state: dict[str, Any] | None,
329
  ) -> tuple[Any, ...]:
330
+ state = operator_state or _default_operator_state()
331
+ scan = _authoritative_generated_scan(state)
332
  if run is None:
333
  next_state = {**_default_operator_state(), "provider_state": "blocked", "message": "No run exists yet. Run Active Weave first."}
334
+ elif not _generated_output_path(state):
335
  next_state = {
336
+ **state,
337
  "provider_state": "blocked",
338
  "checkpoint": "pending",
339
  "message": "Checkpoint blocked: no generated artifact exists yet.",
 
341
  else:
342
  export_state = scan.get("export_gate", "pending")
343
  next_state = {
344
+ **state,
345
  "provider_state": "export_ready" if export_state == "clear" else "checkpointed",
346
  "checkpoint": "approved",
347
+ "generated_scan": scan,
348
  "export": export_state,
349
  "message": "Checkpoint approved. Export is ready after clear ST3GG scan." if export_state == "clear" else "Checkpoint approved, but export still waits on ST3GG review.",
350
  }
 
358
  active_section: str,
359
  operator_state: dict[str, Any] | None,
360
  ) -> tuple[Any, ...]:
 
361
  state = operator_state or _default_operator_state()
362
+ scan = _authoritative_generated_scan(state)
363
  if run is None:
364
  next_state = {**state, "provider_state": "blocked", "export": "blocked", "message": "Export blocked: no active run packet exists."}
365
  elif state.get("checkpoint") != "approved":
366
  next_state = {**state, "provider_state": "blocked", "export": "blocked", "message": "Export blocked: human checkpoint has not been approved."}
367
+ elif not _generated_output_path(state):
368
+ next_state = {**state, "provider_state": "blocked", "export": "blocked", "message": "Export blocked: no generated artifact exists."}
369
  elif scan.get("export_gate") != "clear":
370
  next_state = {**state, "provider_state": "blocked", "export": scan.get("export_gate", "blocked"), "message": "Export blocked: ST3GG gate is not clear."}
371
  else:
docs/HANDOFF_FINAL_HACKATHON.md CHANGED
@@ -26,8 +26,8 @@ Do not paste these into chat, commits, logs, or export packets.
26
 
27
  ```powershell
28
  python -m compileall app.py src tests
29
- python -c "import app; print('app import ok')"
30
  $env:NEXUS_DISABLE_REAL_HF='1'
 
31
  $env:PYTEST_DISABLE_PLUGIN_AUTOLOAD='1'
32
  python -m pytest -q tests -p no:cacheprovider
33
  hf auth whoami --format json
@@ -51,7 +51,7 @@ Avoid pytest `--basetemp=C:\tmp` in this Windows sandbox if `tmp_path` fixtures
51
  - OpenBMB prize claim requires `minicpm_judge.status == "success"` in an export packet.
52
  - NVIDIA prize claim requires `nemotron_evidence.status == "success"` in an export packet.
53
  - LocateAnything supports the grounding story but does not replace Nemotron for the NVIDIA prize.
54
- - Tiny Titan can be claimed for the public demo stack because each active public model is <=4B.
55
  - FLUX.2 Klein 9B and OFFELLIA/Gemma remain private research options only.
56
  - Modal is not claimed unless a real Modal job runs and is documented.
57
 
 
26
 
27
  ```powershell
28
  python -m compileall app.py src tests
 
29
  $env:NEXUS_DISABLE_REAL_HF='1'
30
+ python -c "import app; print('app import ok')"
31
  $env:PYTEST_DISABLE_PLUGIN_AUTOLOAD='1'
32
  python -m pytest -q tests -p no:cacheprovider
33
  hf auth whoami --format json
 
51
  - OpenBMB prize claim requires `minicpm_judge.status == "success"` in an export packet.
52
  - NVIDIA prize claim requires `nemotron_evidence.status == "success"` in an export packet.
53
  - LocateAnything supports the grounding story but does not replace Nemotron for the NVIDIA prize.
54
+ - Tiny Titan can be claimed only from a successful public-demo export packet because each active public model is <=4B.
55
  - FLUX.2 Klein 9B and OFFELLIA/Gemma remain private research options only.
56
  - Modal is not claimed unless a real Modal job runs and is documented.
57
 
src/nexus_visual_weaver/exporter.py CHANGED
@@ -10,6 +10,43 @@ from typing import Any
10
 
11
  from .catalog import active_stack, parameter_budget
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  def export_root() -> Path:
15
  requested = os.environ.get("NEXUS_EXPORT_DIR")
@@ -18,14 +55,15 @@ def export_root() -> Path:
18
  candidates.append(Path("/data/nexus_visual_weaver/exports"))
19
  candidates.append(Path("outputs/exports"))
20
  for candidate in candidates:
21
- if candidate is None:
 
22
  continue
23
  try:
24
- candidate.mkdir(parents=True, exist_ok=True)
25
- return candidate
26
  except OSError:
27
  continue
28
- fallback = Path("outputs/exports")
29
  fallback.mkdir(parents=True, exist_ok=True)
30
  return fallback
31
 
@@ -38,17 +76,22 @@ def write_export_packet(
38
  adult_mode: bool,
39
  ) -> dict[str, Any]:
40
  run_id = getattr(getattr(run, "checkpoint", None), "checkpoint_id", f"nw-{int(time.time())}")
41
- stack = active_stack(adult_mode)
 
 
42
  generation = dict(operator_state.get("generation") or {})
43
  generation.pop("hf_token_present", None)
 
 
 
44
  packet = {
45
  "schema": "nexus_visual_weaver.export_packet.v1",
46
  "run_id": run_id,
47
  "created_at_epoch": int(time.time()),
48
- "adult_mode": bool(adult_mode),
49
  "prompt": getattr(getattr(run, "request", None), "prompt", ""),
50
  "refined_prompt": getattr(getattr(run, "refined_prompt", None), "refined", ""),
51
- "artifact": (operator_state.get("generation") or {}).get("output_path"),
52
  "generation": generation,
53
  "st3gg_scan": scan,
54
  "minicpm_judge": operator_state.get("minicpm_judge") or {},
@@ -68,9 +111,9 @@ def write_export_packet(
68
  }
69
  for model in stack
70
  ],
71
- "parameter_budget": parameter_budget(stack),
72
  "hackathon_claims": {
73
- "build_small_32b": parameter_budget(stack)["status"] == "pass",
74
  "gradio_space": True,
75
  "off_brand_custom_ui": True,
76
  "openbmb_lane": (operator_state.get("minicpm_judge") or {}).get("status") == "success",
 
10
 
11
  from .catalog import active_stack, parameter_budget
12
 
13
+ REPO_ROOT = Path(__file__).resolve().parents[2]
14
+ ALLOWED_LOCAL_EXPORT_ROOTS = (
15
+ REPO_ROOT / "outputs",
16
+ REPO_ROOT / ".pi",
17
+ REPO_ROOT / ".codex",
18
+ )
19
+
20
+
21
+ def _is_within(path: Path, root: Path) -> bool:
22
+ try:
23
+ path.relative_to(root)
24
+ return True
25
+ except ValueError:
26
+ return False
27
+
28
+
29
+ def _safe_export_candidate(candidate: Path) -> Path | None:
30
+ if not candidate.is_absolute():
31
+ candidate = REPO_ROOT / candidate
32
+ resolved = candidate.resolve(strict=False)
33
+ src_root = (REPO_ROOT / "src").resolve(strict=False)
34
+ if resolved == src_root or _is_within(resolved, src_root):
35
+ return None
36
+
37
+ allowed_roots = [root.resolve(strict=False) for root in ALLOWED_LOCAL_EXPORT_ROOTS]
38
+ if Path("/data").exists():
39
+ allowed_roots.append(Path("/data/nexus_visual_weaver").resolve(strict=False))
40
+ if any(resolved == root or _is_within(resolved, root) for root in allowed_roots):
41
+ return resolved
42
+ return None
43
+
44
+
45
+ def _artifact_name(output_path: Any) -> str | None:
46
+ if not output_path:
47
+ return None
48
+ return Path(str(output_path)).name
49
+
50
 
51
  def export_root() -> Path:
52
  requested = os.environ.get("NEXUS_EXPORT_DIR")
 
55
  candidates.append(Path("/data/nexus_visual_weaver/exports"))
56
  candidates.append(Path("outputs/exports"))
57
  for candidate in candidates:
58
+ safe_candidate = _safe_export_candidate(candidate)
59
+ if safe_candidate is None:
60
  continue
61
  try:
62
+ safe_candidate.mkdir(parents=True, exist_ok=True)
63
+ return safe_candidate
64
  except OSError:
65
  continue
66
+ fallback = (REPO_ROOT / "outputs/exports").resolve(strict=False)
67
  fallback.mkdir(parents=True, exist_ok=True)
68
  return fallback
69
 
 
76
  adult_mode: bool,
77
  ) -> dict[str, Any]:
78
  run_id = getattr(getattr(run, "checkpoint", None), "checkpoint_id", f"nw-{int(time.time())}")
79
+ run_adult_mode = bool(getattr(getattr(run, "request", None), "adult_mode", adult_mode))
80
+ stack = list(getattr(run, "model_stack", None) or active_stack(run_adult_mode))
81
+ budget = parameter_budget(stack)
82
  generation = dict(operator_state.get("generation") or {})
83
  generation.pop("hf_token_present", None)
84
+ artifact = _artifact_name(generation.get("output_path"))
85
+ if "output_path" in generation:
86
+ generation["output_path"] = artifact
87
  packet = {
88
  "schema": "nexus_visual_weaver.export_packet.v1",
89
  "run_id": run_id,
90
  "created_at_epoch": int(time.time()),
91
+ "adult_mode": run_adult_mode,
92
  "prompt": getattr(getattr(run, "request", None), "prompt", ""),
93
  "refined_prompt": getattr(getattr(run, "refined_prompt", None), "refined", ""),
94
+ "artifact": artifact,
95
  "generation": generation,
96
  "st3gg_scan": scan,
97
  "minicpm_judge": operator_state.get("minicpm_judge") or {},
 
111
  }
112
  for model in stack
113
  ],
114
+ "parameter_budget": budget,
115
  "hackathon_claims": {
116
+ "build_small_32b": budget["status"] == "pass",
117
  "gradio_space": True,
118
  "off_brand_custom_ui": True,
119
  "openbmb_lane": (operator_state.get("minicpm_judge") or {}).get("status") == "success",
src/nexus_visual_weaver/provider_runtime.py CHANGED
@@ -7,6 +7,7 @@ import json
7
  import os
8
  import time
9
  import urllib.error
 
10
  import urllib.request
11
  from dataclasses import asdict, dataclass
12
  from pathlib import Path
@@ -56,6 +57,9 @@ def _image_data_url(path: str | None) -> str | None:
56
 
57
 
58
  def _post_json(url: str, token: str, payload: dict[str, Any], timeout: float) -> dict[str, Any]:
 
 
 
59
  body = json.dumps(payload).encode("utf-8")
60
  request = urllib.request.Request(
61
  url,
 
7
  import os
8
  import time
9
  import urllib.error
10
+ import urllib.parse
11
  import urllib.request
12
  from dataclasses import asdict, dataclass
13
  from pathlib import Path
 
57
 
58
 
59
  def _post_json(url: str, token: str, payload: dict[str, Any], timeout: float) -> dict[str, Any]:
60
+ parsed = urllib.parse.urlparse(url)
61
+ if parsed.scheme not in {"http", "https"} or not parsed.netloc:
62
+ raise ValueError(f"Invalid URL: expected http(s) URL with host, got {url!r}.")
63
  body = json.dumps(payload).encode("utf-8")
64
  request = urllib.request.Request(
65
  url,
src/nexus_visual_weaver/render.py CHANGED
@@ -48,6 +48,31 @@ def _env_configured(*names: str) -> bool:
48
  return any(bool(os.environ.get(name)) for name in names)
49
 
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  def _space_runtime_status() -> dict[str, str]:
52
  space_id = os.environ.get("SPACE_ID") or os.environ.get("HF_SPACE_ID") or "local-preview"
53
  hardware = os.environ.get("SPACE_HARDWARE") or os.environ.get("NEXUS_SPACE_HARDWARE") or "ZeroGPU"
@@ -55,9 +80,9 @@ def _space_runtime_status() -> dict[str, str]:
55
  configured = []
56
  if _env_configured("HF_TOKEN", "HUGGING_FACE_HUB_TOKEN"):
57
  configured.append("HF")
58
- if _env_configured("MINICPM_API_KEY", "OPENBMB_API_KEY"):
59
  configured.append("MiniCPM")
60
- if _env_configured("NEMOTRON_API_KEY", "NVIDIA_API_KEY"):
61
  configured.append("Nemotron")
62
  if _env_configured("FAL_KEY", "NETLIFY_AUTH_TOKEN", "OPENAI_API_KEY", "MODAL_TOKEN_ID"):
63
  configured.append("optional")
@@ -106,12 +131,12 @@ def render_trust_strip(scan: dict | None = None, operator_state: dict | None = N
106
  status = str(scan.get("status", "idle")).upper()
107
  export_gate = str(scan.get("export_gate", "pending")).upper()
108
  checkpoint = str(operator_state.get("checkpoint", "pending")).replace("_", " ").title()
109
- findings = scan.get("findings") or ["No upload selected. Always-on scanner ready."]
110
- actions = scan.get("purification_actions") or [
111
  "strip metadata before export",
112
  "truncate PNG after IEND when needed",
113
  "run LSB statistical review",
114
- ]
115
  tone = _scan_status_tone(str(scan.get("status", "idle")))
116
  return f"""
117
  <section class="nw-trust-strip">
@@ -460,7 +485,7 @@ def render_operations_panel(
460
  ("ST3GG state", f"{scan_status} / export {export_gate}"),
461
  (
462
  "Findings",
463
- "; ".join(str(item) for item in (scan.get("findings") or [])[:2])
464
  or ("No findings." if scan_status != "IDLE" else "No upload selected."),
465
  ),
466
  ("Public export", "Consent, provenance, metadata, age, dataset, and payload gates stay active."),
@@ -563,8 +588,8 @@ def render_provider_cards(relay_status: dict | None = None, adult_mode: bool = F
563
  relay_status = relay_status or {}
564
  decisions = relay_status.get("decisions", [])
565
  optional_statuses = {
566
- "openbmb": "configured" if _env_configured("MINICPM_API_KEY", "OPENBMB_API_KEY") else "missing secret",
567
- "nvidia": "configured" if _env_configured("NEMOTRON_API_KEY", "NVIDIA_API_KEY") else "missing secret",
568
  "fal": "configured" if _env_configured("FAL_KEY") else "blocked",
569
  "netlify": "configured" if _env_configured("NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID", "OPENAI_BASE_URL") else "blocked",
570
  "cloudflare": "configured" if _env_configured("CLOUDFLARE_API_TOKEN", "CF_ACCOUNT_ID") else "blocked",
@@ -664,10 +689,10 @@ def render_inspector(
664
  ("NVIDIA Nemotron", "nvidia/NVIDIA-Nemotron-Parse-v1.2", nemotron),
665
  ]
666
  )
667
- findings = scan.get("findings") or []
668
- actions = scan.get("purification_actions") or ["metadata strip ready", "IEND truncation ready", "LSB review ready"]
669
- finding_rows = "".join(f"<li>{escape(str(item))}</li>" for item in findings[:4]) or "<li>No upload selected. Scanner ready.</li>"
670
- action_rows = "".join(f"<li>{escape(str(item))}</li>" for item in actions[:4])
671
  export_gate = str(scan.get("export_gate", "pending")).upper()
672
  return f"""
673
  <aside class="nw-panel nw-inspector">
 
48
  return any(bool(os.environ.get(name)) for name in names)
49
 
50
 
51
+ def _provider_configured(base_url_name: str, *key_names: str) -> bool:
52
+ return bool(os.environ.get(base_url_name)) and _env_configured(*key_names)
53
+
54
+
55
+ _SCAN_REDACTION_TERMS = (
56
+ "payload",
57
+ "payload_excerpt",
58
+ "hidden content",
59
+ "recovered",
60
+ "raw byte",
61
+ "base64",
62
+ "hex dump",
63
+ )
64
+
65
+
66
+ def _redact_scan_text(value: object) -> str:
67
+ text = str(value)
68
+ lowered = text.lower()
69
+ if any(term in lowered for term in _SCAN_REDACTION_TERMS):
70
+ return "Redacted scan detail; review the gated ST3GG evidence packet."
71
+ if len(text) > 180:
72
+ return text[:177] + "..."
73
+ return text
74
+
75
+
76
  def _space_runtime_status() -> dict[str, str]:
77
  space_id = os.environ.get("SPACE_ID") or os.environ.get("HF_SPACE_ID") or "local-preview"
78
  hardware = os.environ.get("SPACE_HARDWARE") or os.environ.get("NEXUS_SPACE_HARDWARE") or "ZeroGPU"
 
80
  configured = []
81
  if _env_configured("HF_TOKEN", "HUGGING_FACE_HUB_TOKEN"):
82
  configured.append("HF")
83
+ if _provider_configured("MINICPM_BASE_URL", "MINICPM_API_KEY", "OPENBMB_API_KEY"):
84
  configured.append("MiniCPM")
85
+ if _provider_configured("NEMOTRON_BASE_URL", "NEMOTRON_API_KEY", "NVIDIA_API_KEY"):
86
  configured.append("Nemotron")
87
  if _env_configured("FAL_KEY", "NETLIFY_AUTH_TOKEN", "OPENAI_API_KEY", "MODAL_TOKEN_ID"):
88
  configured.append("optional")
 
131
  status = str(scan.get("status", "idle")).upper()
132
  export_gate = str(scan.get("export_gate", "pending")).upper()
133
  checkpoint = str(operator_state.get("checkpoint", "pending")).replace("_", " ").title()
134
+ findings = [_redact_scan_text(item) for item in (scan.get("findings") or ["No upload selected. Always-on scanner ready."])]
135
+ actions = [_redact_scan_text(item) for item in (scan.get("purification_actions") or [
136
  "strip metadata before export",
137
  "truncate PNG after IEND when needed",
138
  "run LSB statistical review",
139
+ ])]
140
  tone = _scan_status_tone(str(scan.get("status", "idle")))
141
  return f"""
142
  <section class="nw-trust-strip">
 
485
  ("ST3GG state", f"{scan_status} / export {export_gate}"),
486
  (
487
  "Findings",
488
+ "; ".join(_redact_scan_text(item) for item in (scan.get("findings") or [])[:2])
489
  or ("No findings." if scan_status != "IDLE" else "No upload selected."),
490
  ),
491
  ("Public export", "Consent, provenance, metadata, age, dataset, and payload gates stay active."),
 
588
  relay_status = relay_status or {}
589
  decisions = relay_status.get("decisions", [])
590
  optional_statuses = {
591
+ "openbmb": "configured" if _provider_configured("MINICPM_BASE_URL", "MINICPM_API_KEY", "OPENBMB_API_KEY") else "missing secret",
592
+ "nvidia": "configured" if _provider_configured("NEMOTRON_BASE_URL", "NEMOTRON_API_KEY", "NVIDIA_API_KEY") else "missing secret",
593
  "fal": "configured" if _env_configured("FAL_KEY") else "blocked",
594
  "netlify": "configured" if _env_configured("NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID", "OPENAI_BASE_URL") else "blocked",
595
  "cloudflare": "configured" if _env_configured("CLOUDFLARE_API_TOKEN", "CF_ACCOUNT_ID") else "blocked",
 
689
  ("NVIDIA Nemotron", "nvidia/NVIDIA-Nemotron-Parse-v1.2", nemotron),
690
  ]
691
  )
692
+ findings = [_redact_scan_text(item) for item in (scan.get("findings") or [])]
693
+ actions = [_redact_scan_text(item) for item in (scan.get("purification_actions") or ["metadata strip ready", "IEND truncation ready", "LSB review ready"])]
694
+ finding_rows = "".join(f"<li>{escape(item)}</li>" for item in findings[:4]) or "<li>No upload selected. Scanner ready.</li>"
695
+ action_rows = "".join(f"<li>{escape(item)}</li>" for item in actions[:4])
696
  export_gate = str(scan.get("export_gate", "pending")).upper()
697
  return f"""
698
  <aside class="nw-panel nw-inspector">
tests/test_app_callbacks.py CHANGED
@@ -1,4 +1,86 @@
1
  import app
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
 
4
  def test_run_weave_returns_stateful_dashboard_packet() -> None:
@@ -18,6 +100,8 @@ def test_run_weave_returns_stateful_dashboard_packet() -> None:
18
 
19
 
20
  def test_operator_actions_transition_checkpoint_export_and_stop() -> None:
 
 
21
  result = app.run_weave(
22
  "gothic patent leather platform boots, crimson hardware",
23
  "Strict",
@@ -27,7 +111,10 @@ def test_operator_actions_transition_checkpoint_export_and_stop() -> None:
27
  "Forge",
28
  )
29
  run = result[13]
30
- operator_state = {**result[15], "generation": {**result[15]["generation"], "output_path": "outputs/test-generated-artifact.png"}}
 
 
 
31
  clean_scan = {"status": "pass", "export_gate": "clear", "findings": [], "purification_actions": []}
32
 
33
  approved = app.approve_checkpoint(run, False, clean_scan, "Forge", operator_state)
@@ -59,6 +146,66 @@ def test_export_blocks_without_checkpoint() -> None:
59
  assert "checkpoint" in blocked[13]["message"].lower()
60
 
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  def test_checkpoint_blocks_without_generated_artifact() -> None:
63
  result = app.run_weave(
64
  "gothic patent leather platform boots, crimson hardware",
 
1
  import app
2
+ from nexus_visual_weaver.planner import build_command_center_run
3
+
4
+
5
+ # --- _checkpoint_seed tests ---
6
+
7
+ def test_checkpoint_seed_parses_valid_hex_suffix() -> None:
8
+ # "nw-" prefix + "abcdef12" -> int("abcdef12", 16) % 1_000_000
9
+ checkpoint_id = "nw-abcdef12"
10
+ result = app._checkpoint_seed(checkpoint_id)
11
+ assert result == int("abcdef12", 16) % 1_000_000
12
+
13
+
14
+ def test_checkpoint_seed_handles_empty_suffix() -> None:
15
+ assert app._checkpoint_seed("") == 0
16
+ assert app._checkpoint_seed("nw-") == 0
17
+
18
+
19
+ def test_checkpoint_seed_handles_non_hex_suffix() -> None:
20
+ # No hex chars -> return 0
21
+ result = app._checkpoint_seed("nw-zzzzzzzz")
22
+ assert result == 0
23
+
24
+
25
+ def test_checkpoint_seed_ignores_non_hex_chars_in_last_8() -> None:
26
+ # Strips non-hex: "abc-xyz" -> only "abcef" are hex in the last 8 chars ("-xyz" strips to "abc")
27
+ # "0000000g" -> only "0000000" are valid hex
28
+ result = app._checkpoint_seed("0000000g")
29
+ assert result == int("0000000", 16) % 1_000_000
30
+ assert result == 0
31
+
32
+
33
+ def test_checkpoint_seed_returns_value_within_range() -> None:
34
+ checkpoint_id = "nw-deadbeef"
35
+ result = app._checkpoint_seed(checkpoint_id)
36
+ assert 0 <= result < 1_000_000
37
+
38
+
39
+ def test_checkpoint_seed_uses_only_last_8_chars() -> None:
40
+ # Long checkpoint id: only last 8 chars considered
41
+ # "nw-aabbccddee11223344" -> last 8 is "11223344"
42
+ result = app._checkpoint_seed("nw-aabbccddee11223344")
43
+ assert result == int("11223344", 16) % 1_000_000
44
+
45
+
46
+ # --- _wardrobe_summary tests ---
47
+
48
+ def test_wardrobe_summary_returns_string_with_slot_fields() -> None:
49
+ run = build_command_center_run("gothic patent leather platform boots, crimson hardware")
50
+ summary = app._wardrobe_summary(run)
51
+
52
+ # Summary is a semicolon-delimited string of slot info
53
+ assert isinstance(summary, str)
54
+ assert len(summary) > 0
55
+ # Should contain material= and palette= from slot info
56
+ assert "material=" in summary
57
+ assert "palette=" in summary
58
+ assert "locked=" in summary
59
+
60
+
61
+ def test_wardrobe_summary_handles_run_with_no_outfit() -> None:
62
+ class FakeRun:
63
+ outfit = None
64
+
65
+ summary = app._wardrobe_summary(FakeRun())
66
+ assert summary == ""
67
+
68
+
69
+ def test_wardrobe_summary_handles_none_run() -> None:
70
+ # Pass something with no outfit attribute
71
+ class Empty:
72
+ pass
73
+
74
+ summary = app._wardrobe_summary(Empty())
75
+ assert summary == ""
76
+
77
+
78
+ def test_wardrobe_summary_includes_slot_names() -> None:
79
+ run = build_command_center_run("dark couture archivist, patent leather, platform boots")
80
+ summary = app._wardrobe_summary(run)
81
+
82
+ # Slot names like footwear, outerwear, upper_body should appear
83
+ assert any(slot_name in summary for slot_name in ["footwear", "outerwear", "upper_body", "jewelry"])
84
 
85
 
86
  def test_run_weave_returns_stateful_dashboard_packet() -> None:
 
100
 
101
 
102
  def test_operator_actions_transition_checkpoint_export_and_stop() -> None:
103
+ from pathlib import Path
104
+
105
  result = app.run_weave(
106
  "gothic patent leather platform boots, crimson hardware",
107
  "Strict",
 
111
  "Forge",
112
  )
113
  run = result[13]
114
+ artifact_path = Path("outputs/test-generated-artifact.png")
115
+ artifact_path.parent.mkdir(parents=True, exist_ok=True)
116
+ artifact_path.write_bytes(b"\x89PNG\r\n\x1a\n" + b"\x00" * 100)
117
+ operator_state = {**result[15], "generation": {**result[15]["generation"], "output_path": str(artifact_path)}}
118
  clean_scan = {"status": "pass", "export_gate": "clear", "findings": [], "purification_actions": []}
119
 
120
  approved = app.approve_checkpoint(run, False, clean_scan, "Forge", operator_state)
 
146
  assert "checkpoint" in blocked[13]["message"].lower()
147
 
148
 
149
+ def test_reference_scan_cannot_clear_blocked_generated_artifact() -> None:
150
+ base = app.ROOT / "outputs" / "test-app-callbacks"
151
+ base.mkdir(parents=True, exist_ok=True)
152
+ blocked_artifact = base / "blocked-generated.png"
153
+ blocked_artifact.write_bytes(
154
+ b"\x89PNG\r\n\x1a\n"
155
+ b"\x00\x00\x00\rIEND\xaeB`\x82"
156
+ b"NEXUS_TRAILING_PAYLOAD"
157
+ )
158
+ clean_reference = base / "clean-reference.png"
159
+ clean_reference.write_bytes(b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIEND\xaeB`\x82")
160
+ run = build_command_center_run("gothic patent leather platform boots")
161
+ state = {
162
+ "provider_state": "checkpointed",
163
+ "checkpoint": "pending_review",
164
+ "export": "blocked",
165
+ "generation": {"status": "success", "output_path": str(blocked_artifact)},
166
+ "generated_scan": app.scan_file(str(blocked_artifact)),
167
+ }
168
+
169
+ scanned = app.scan_reference(run, False, str(clean_reference), "Forge", state)
170
+ assert scanned[13]["reference_scan"]["export_gate"] == "clear"
171
+ assert scanned[13]["export"] == "blocked"
172
+ assert scanned[15]["export_gate"] == "blocked"
173
+
174
+ approved = app.approve_checkpoint(run, False, scanned[15], "Forge", scanned[13])
175
+ assert approved[13]["provider_state"] == "checkpointed"
176
+ assert approved[13]["export"] == "blocked"
177
+
178
+
179
+ def test_blocked_reference_scan_does_not_block_clear_generated_artifact() -> None:
180
+ base = app.ROOT / "outputs" / "test-app-callbacks"
181
+ base.mkdir(parents=True, exist_ok=True)
182
+ generated = base / "clear-generated.png"
183
+ generated.write_bytes(b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIEND\xaeB`\x82")
184
+ blocked_reference = base / "blocked-reference.png"
185
+ blocked_reference.write_bytes(
186
+ b"\x89PNG\r\n\x1a\n"
187
+ b"\x00\x00\x00\rIEND\xaeB`\x82"
188
+ b"NEXUS_TRAILING_PAYLOAD"
189
+ )
190
+ run = build_command_center_run("gothic patent leather platform boots")
191
+ state = {
192
+ "provider_state": "checkpointed",
193
+ "checkpoint": "pending_review",
194
+ "export": "clear",
195
+ "generation": {"status": "success", "output_path": str(generated)},
196
+ "generated_scan": app.scan_file(str(generated)),
197
+ }
198
+
199
+ scanned = app.scan_reference(run, False, str(blocked_reference), "Forge", state)
200
+ assert scanned[13]["reference_scan"]["export_gate"] == "blocked"
201
+ assert scanned[13]["export"] == "clear"
202
+ assert scanned[15]["export_gate"] == "clear"
203
+
204
+ approved = app.approve_checkpoint(run, False, scanned[15], "Forge", scanned[13])
205
+ assert approved[13]["provider_state"] == "export_ready"
206
+ assert approved[13]["export"] == "clear"
207
+
208
+
209
  def test_checkpoint_blocks_without_generated_artifact() -> None:
210
  result = app.run_weave(
211
  "gothic patent leather platform boots, crimson hardware",
tests/test_command_center.py CHANGED
@@ -1,10 +1,26 @@
1
  from pathlib import Path
2
 
3
- from nexus_visual_weaver.catalog import active_stack, catalog_summary, filter_catalog, parameter_budget
 
 
 
 
 
 
 
4
  from nexus_visual_weaver.grounding import inspect_outfit
5
  from nexus_visual_weaver.model_relay import WeaverModelRelay
6
  from nexus_visual_weaver.planner import build_command_center_run
7
- from nexus_visual_weaver.render import render_command_header, render_dashboard_regions, render_operations_panel
 
 
 
 
 
 
 
 
 
8
  from nexus_visual_weaver.security import scan_file
9
  from nexus_visual_weaver.taste import refine_prompt, score_prompt
10
  from nexus_visual_weaver.wardrobe import build_outfit_graph
@@ -218,3 +234,283 @@ def test_catalog_summary_reflects_adult_scope() -> None:
218
  assert default_summary["adult_catalog"] == "hidden"
219
  assert adult_summary["adult_catalog"] == "enabled"
220
  assert adult_summary["models_visible"] > default_summary["models_visible"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from pathlib import Path
2
 
3
+ from nexus_visual_weaver.catalog import (
4
+ DEFAULT_ACTIVE_STACK,
5
+ PRIVATE_RESEARCH_STACK,
6
+ active_stack,
7
+ catalog_summary,
8
+ filter_catalog,
9
+ parameter_budget,
10
+ )
11
  from nexus_visual_weaver.grounding import inspect_outfit
12
  from nexus_visual_weaver.model_relay import WeaverModelRelay
13
  from nexus_visual_weaver.planner import build_command_center_run
14
+ from nexus_visual_weaver.render import (
15
+ render_command_header,
16
+ render_dashboard_regions,
17
+ render_inspector,
18
+ render_operations_panel,
19
+ render_provider_cards,
20
+ render_topbar,
21
+ render_trust_strip,
22
+ )
23
+ from nexus_visual_weaver.schema import ModelCandidate
24
  from nexus_visual_weaver.security import scan_file
25
  from nexus_visual_weaver.taste import refine_prompt, score_prompt
26
  from nexus_visual_weaver.wardrobe import build_outfit_graph
 
234
  assert default_summary["adult_catalog"] == "hidden"
235
  assert adult_summary["adult_catalog"] == "enabled"
236
  assert adult_summary["models_visible"] > default_summary["models_visible"]
237
+
238
+
239
+ # --- render_trust_strip tests ---
240
+
241
+ def test_render_trust_strip_defaults_to_idle_state() -> None:
242
+ html = render_trust_strip()
243
+
244
+ assert "TRUST MODEL" in html
245
+ assert "Generation is not export." in html
246
+ assert "ST3GG IDLE" in html
247
+ assert "EXPORT PENDING" in html
248
+ assert "Clean PNG -> pass." in html
249
+ assert "FIXTURE EVIDENCE" in html
250
+
251
+
252
+ def test_render_trust_strip_pass_scan_shows_clear_export() -> None:
253
+ scan = {"status": "pass", "export_gate": "clear", "findings": ["all checks passed"], "purification_actions": ["none needed"]}
254
+ html = render_trust_strip(scan=scan)
255
+
256
+ assert "ST3GG PASS" in html
257
+ assert "EXPORT CLEAR" in html
258
+ assert "all checks passed" in html
259
+
260
+
261
+ def test_render_trust_strip_review_scan_shows_blocked_export() -> None:
262
+ scan = {"status": "review", "export_gate": "blocked", "findings": ["trailing data after IEND"], "purification_actions": ["truncate PNG"]}
263
+ html = render_trust_strip(scan=scan)
264
+
265
+ assert "ST3GG REVIEW" in html
266
+ assert "EXPORT BLOCKED" in html
267
+ assert "trailing data after IEND" in html
268
+
269
+
270
+ def test_render_trust_strip_redacts_payload_details() -> None:
271
+ scan = {
272
+ "status": "review",
273
+ "export_gate": "blocked",
274
+ "findings": ["payload excerpt: deadbeef hidden content recovered"],
275
+ "purification_actions": ["raw byte hex dump should stay quarantined"],
276
+ }
277
+ html = render_trust_strip(scan=scan)
278
+
279
+ assert "Redacted scan detail" in html
280
+ assert "deadbeef" not in html
281
+ assert "hex dump" not in html
282
+
283
+
284
+ def test_render_trust_strip_approved_checkpoint_shows_pass() -> None:
285
+ operator_state = {"checkpoint": "approved", "provider_state": "export_ready"}
286
+ html = render_trust_strip(operator_state=operator_state)
287
+
288
+ assert "CHECKPOINT APPROVED" in html
289
+
290
+
291
+ def test_render_trust_strip_pending_review_checkpoint_label() -> None:
292
+ operator_state = {"checkpoint": "pending_review"}
293
+ html = render_trust_strip(operator_state=operator_state)
294
+
295
+ assert "CHECKPOINT PENDING REVIEW" in html
296
+
297
+
298
+ # --- render_topbar tests ---
299
+
300
+ def test_render_topbar_includes_trust_strip() -> None:
301
+ html = render_topbar()
302
+
303
+ assert "TRUST MODEL" in html
304
+ assert "nw-trust-strip" in html
305
+
306
+
307
+ def test_render_topbar_with_scan_passes_to_trust_strip() -> None:
308
+ scan = {"status": "pass", "export_gate": "clear", "findings": ["no issues"], "purification_actions": []}
309
+ html = render_topbar(scan=scan)
310
+
311
+ assert "ST3GG PASS" in html
312
+ assert "EXPORT CLEAR" in html
313
+
314
+
315
+ def test_render_topbar_with_operator_state_shows_checkpoint() -> None:
316
+ operator_state = {"checkpoint": "approved"}
317
+ html = render_topbar(operator_state=operator_state)
318
+
319
+ assert "CHECKPOINT APPROVED" in html
320
+
321
+
322
+ def test_render_topbar_default_scan_shows_fixture_evidence() -> None:
323
+ html = render_topbar()
324
+
325
+ assert "Clean PNG -> pass." in html
326
+ assert "PNG trailing bytes -> blocked." in html
327
+
328
+
329
+ # --- render_inspector sponsor evidence tests ---
330
+
331
+ def test_render_inspector_shows_sponsor_evidence_section() -> None:
332
+ html = render_inspector()
333
+
334
+ assert "Sponsor Evidence" in html
335
+ assert "OpenBMB MiniCPM" in html
336
+ assert "NVIDIA Nemotron" in html
337
+
338
+
339
+ def test_render_inspector_with_missing_secret_shows_pending() -> None:
340
+ operator_state = {
341
+ "minicpm_judge": {"status": "missing_secret", "repo_id": "openbmb/MiniCPM-V-4.6"},
342
+ "nemotron_evidence": {"status": "missing_secret", "repo_id": "nvidia/NVIDIA-Nemotron-Parse-v1.2"},
343
+ }
344
+ html = render_inspector(operator_state=operator_state)
345
+
346
+ assert "MISSING_SECRET" in html
347
+
348
+
349
+ def test_render_inspector_with_success_judge_shows_success_status() -> None:
350
+ operator_state = {
351
+ "minicpm_judge": {"status": "success", "repo_id": "openbmb/MiniCPM-V-4.6"},
352
+ "nemotron_evidence": {"status": "success", "repo_id": "nvidia/NVIDIA-Nemotron-Parse-v1.2"},
353
+ }
354
+ html = render_inspector(operator_state=operator_state)
355
+
356
+ assert html.count("SUCCESS") >= 2
357
+
358
+
359
+ def test_render_inspector_shows_default_stack_label_without_run() -> None:
360
+ html = render_inspector()
361
+
362
+ assert "FLUX.2 4B / MiniCPM / LocateAnything" in html
363
+
364
+
365
+ # --- render_provider_cards sponsor lane tests ---
366
+
367
+ def test_render_provider_cards_shows_openbmb_and_nvidia_entries() -> None:
368
+ html = render_provider_cards()
369
+
370
+ assert "Openbmb" in html or "openbmb" in html.lower()
371
+ assert "Nvidia" in html or "nvidia" in html.lower()
372
+
373
+
374
+ def test_render_provider_cards_shows_sponsor_lane_badge_for_openbmb(monkeypatch) -> None:
375
+ monkeypatch.setenv("MINICPM_API_KEY", "test-key")
376
+ monkeypatch.setenv("MINICPM_BASE_URL", "https://minicpm.example.test")
377
+ html = render_provider_cards()
378
+
379
+ assert "SPONSOR LANE" in html
380
+
381
+
382
+ def test_render_provider_cards_shows_missing_secret_for_unconfigured_sponsor(monkeypatch) -> None:
383
+ monkeypatch.delenv("MINICPM_API_KEY", raising=False)
384
+ monkeypatch.delenv("OPENBMB_API_KEY", raising=False)
385
+ monkeypatch.delenv("NEMOTRON_API_KEY", raising=False)
386
+ monkeypatch.delenv("NVIDIA_API_KEY", raising=False)
387
+ html = render_provider_cards()
388
+
389
+ assert "MISSING SECRET" in html
390
+
391
+
392
+ def test_render_provider_cards_configured_openbmb_shows_configured(monkeypatch) -> None:
393
+ monkeypatch.setenv("MINICPM_API_KEY", "test-key")
394
+ monkeypatch.delenv("MINICPM_BASE_URL", raising=False)
395
+ monkeypatch.delenv("NEMOTRON_API_KEY", raising=False)
396
+ monkeypatch.delenv("NVIDIA_API_KEY", raising=False)
397
+ monkeypatch.delenv("NEMOTRON_BASE_URL", raising=False)
398
+ monkeypatch.delenv("FAL_KEY", raising=False)
399
+ monkeypatch.delenv("NETLIFY_AUTH_TOKEN", raising=False)
400
+ monkeypatch.delenv("OPENAI_BASE_URL", raising=False)
401
+ monkeypatch.delenv("CLOUDFLARE_API_TOKEN", raising=False)
402
+ html = render_provider_cards()
403
+
404
+ assert "CONFIGURED" not in html
405
+ assert "MISSING SECRET" in html
406
+
407
+
408
+ def test_render_provider_cards_configured_openbmb_requires_key_and_base_url(monkeypatch) -> None:
409
+ monkeypatch.setenv("MINICPM_API_KEY", "test-key")
410
+ monkeypatch.setenv("MINICPM_BASE_URL", "https://minicpm.example.test")
411
+ html = render_provider_cards()
412
+
413
+ assert "CONFIGURED" in html
414
+
415
+
416
+ def test_render_operations_and_inspector_redact_payload_details() -> None:
417
+ scan = {
418
+ "status": "review",
419
+ "export_gate": "blocked",
420
+ "findings": ["payload excerpt: recovered hidden content"],
421
+ "purification_actions": ["base64 raw bytes quarantined"],
422
+ }
423
+
424
+ operations = render_operations_panel(active_section="Security", scan=scan)
425
+ inspector = render_inspector(scan=scan)
426
+
427
+ assert "Redacted scan detail" in operations
428
+ assert "Redacted scan detail" in inspector
429
+ assert "recovered hidden content" not in operations
430
+ assert "base64 raw bytes" not in inspector
431
+
432
+
433
+ # --- catalog public_demo field tests ---
434
+
435
+ def test_filter_catalog_excludes_flux_9b_in_public_mode() -> None:
436
+ models, _ = filter_catalog(False)
437
+ repo_ids = {model.repo_id for model in models}
438
+
439
+ assert "black-forest-labs/FLUX.2-klein-9B" not in repo_ids
440
+
441
+
442
+ def test_filter_catalog_includes_flux_9b_in_adult_mode() -> None:
443
+ models, _ = filter_catalog(True)
444
+ repo_ids = {model.repo_id for model in models}
445
+
446
+ assert "black-forest-labs/FLUX.2-klein-9B" in repo_ids
447
+
448
+
449
+ def test_filter_catalog_excludes_offellia_in_public_mode() -> None:
450
+ models, _ = filter_catalog(False)
451
+ repo_ids = {model.repo_id for model in models}
452
+
453
+ assert not any("OFFELLIA" in repo_id for repo_id in repo_ids)
454
+
455
+
456
+ def test_active_stack_uses_private_research_stack_in_adult_mode() -> None:
457
+ stack = active_stack(True)
458
+ repo_ids = {model.repo_id for model in stack}
459
+
460
+ assert "black-forest-labs/FLUX.2-klein-9B" in repo_ids
461
+ assert "black-forest-labs/FLUX.2-klein-4B" not in repo_ids
462
+
463
+
464
+ def test_private_research_stack_constant_contains_9b_and_offellia() -> None:
465
+ assert "black-forest-labs/FLUX.2-klein-9B" in PRIVATE_RESEARCH_STACK
466
+ assert "Brunobkr/OFFELLIA_Q4_0_gemma-4-12B-it.gguf" in PRIVATE_RESEARCH_STACK
467
+
468
+
469
+ def test_default_active_stack_constant_uses_4b_and_sponsor_models() -> None:
470
+ assert "black-forest-labs/FLUX.2-klein-4B" in DEFAULT_ACTIVE_STACK
471
+ assert "openbmb/MiniCPM-V-4.6" in DEFAULT_ACTIVE_STACK
472
+ assert "nvidia/NVIDIA-Nemotron-Parse-v1.2" in DEFAULT_ACTIVE_STACK
473
+ assert "black-forest-labs/FLUX.2-klein-9B" not in DEFAULT_ACTIVE_STACK
474
+
475
+
476
+ # --- schema ModelCandidate public_demo tests ---
477
+
478
+ def test_model_candidate_public_demo_defaults_to_true() -> None:
479
+ candidate = ModelCandidate(
480
+ repo_id="test/model",
481
+ role="test_role",
482
+ task="text-to-image",
483
+ params_b=1.0,
484
+ runtime="local",
485
+ license="apache-2.0",
486
+ )
487
+ assert candidate.public_demo is True
488
+
489
+
490
+ def test_model_candidate_public_demo_can_be_set_false() -> None:
491
+ candidate = ModelCandidate(
492
+ repo_id="test/private-model",
493
+ role="private_role",
494
+ task="text-to-image",
495
+ params_b=9.0,
496
+ runtime="gated provider",
497
+ license="other",
498
+ public_demo=False,
499
+ )
500
+ assert candidate.public_demo is False
501
+
502
+
503
+ def test_public_demo_false_models_are_excluded_from_public_filter() -> None:
504
+ private = ModelCandidate(
505
+ repo_id="test/hidden-model",
506
+ role="private",
507
+ task="text-to-image",
508
+ params_b=2.0,
509
+ runtime="local",
510
+ license="other",
511
+ public_demo=False,
512
+ )
513
+ # public_demo=False should mean filter_catalog(False) excludes it
514
+ # The catalog-level test: verify FLUX 9B (public_demo=False) is absent
515
+ models_public, _ = filter_catalog(False)
516
+ assert all(m.public_demo for m in models_public)
tests/test_exporter.py CHANGED
@@ -1,15 +1,11 @@
1
  import json
2
  from pathlib import Path
3
 
4
- from nexus_visual_weaver.exporter import write_export_packet
5
  from nexus_visual_weaver.planner import build_command_center_run
6
 
7
 
8
- def test_write_export_packet_records_evidence_without_secrets(monkeypatch) -> None:
9
- export_dir = Path("outputs/test-exports")
10
- monkeypatch.setenv("NEXUS_EXPORT_DIR", str(export_dir))
11
- run = build_command_center_run("gothic couture archivist, platform boots")
12
- scan = {"status": "pass", "export_gate": "clear", "findings": [], "purification_actions": []}
13
  state = {
14
  "provider_state": "export_ready",
15
  "checkpoint": "approved",
@@ -18,6 +14,16 @@ def test_write_export_packet_records_evidence_without_secrets(monkeypatch) -> No
18
  "minicpm_judge": {"status": "success", "repo_id": "openbmb/MiniCPM-V-4.6"},
19
  "nemotron_evidence": {"status": "missing_secret", "repo_id": "nvidia/NVIDIA-Nemotron-Parse-v1.2"},
20
  }
 
 
 
 
 
 
 
 
 
 
21
 
22
  result = write_export_packet(run=run, scan=scan, operator_state=state, adult_mode=False)
23
  payload = json.loads(Path(result["path"]).read_text(encoding="utf-8"))
@@ -27,3 +33,154 @@ def test_write_export_packet_records_evidence_without_secrets(monkeypatch) -> No
27
  assert payload["hackathon_claims"]["nvidia_nemotron_lane"] is False
28
  assert payload["parameter_budget"]["status"] == "pass"
29
  assert "token" not in json.dumps(payload).lower()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import json
2
  from pathlib import Path
3
 
4
+ from nexus_visual_weaver.exporter import export_root, write_export_packet
5
  from nexus_visual_weaver.planner import build_command_center_run
6
 
7
 
8
+ def _make_base_state(**overrides):
 
 
 
 
9
  state = {
10
  "provider_state": "export_ready",
11
  "checkpoint": "approved",
 
14
  "minicpm_judge": {"status": "success", "repo_id": "openbmb/MiniCPM-V-4.6"},
15
  "nemotron_evidence": {"status": "missing_secret", "repo_id": "nvidia/NVIDIA-Nemotron-Parse-v1.2"},
16
  }
17
+ state.update(overrides)
18
+ return state
19
+
20
+
21
+ def test_write_export_packet_records_evidence_without_secrets(monkeypatch) -> None:
22
+ export_dir = Path("outputs/test-exports")
23
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", str(export_dir))
24
+ run = build_command_center_run("gothic couture archivist, platform boots")
25
+ scan = {"status": "pass", "export_gate": "clear", "findings": [], "purification_actions": []}
26
+ state = _make_base_state()
27
 
28
  result = write_export_packet(run=run, scan=scan, operator_state=state, adult_mode=False)
29
  payload = json.loads(Path(result["path"]).read_text(encoding="utf-8"))
 
33
  assert payload["hackathon_claims"]["nvidia_nemotron_lane"] is False
34
  assert payload["parameter_budget"]["status"] == "pass"
35
  assert "token" not in json.dumps(payload).lower()
36
+ assert payload["artifact"] == "artifact.png"
37
+ assert payload["generation"]["output_path"] == "artifact.png"
38
+ assert "/data/" not in json.dumps(payload)
39
+
40
+
41
+ def test_export_packet_has_correct_schema_version(monkeypatch) -> None:
42
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", "outputs/test-exports")
43
+ run = build_command_center_run("dark couture brief")
44
+ scan = {"status": "pass", "export_gate": "clear"}
45
+ state = _make_base_state()
46
+
47
+ result = write_export_packet(run=run, scan=scan, operator_state=state, adult_mode=False)
48
+ payload = json.loads(Path(result["path"]).read_text(encoding="utf-8"))
49
+
50
+ assert payload["schema"] == "nexus_visual_weaver.export_packet.v1"
51
+
52
+
53
+ def test_export_packet_stores_adult_mode_flag(monkeypatch) -> None:
54
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", "outputs/test-exports")
55
+ run_public = build_command_center_run("dark couture brief", adult_mode=False)
56
+ run_private = build_command_center_run("dark couture brief", adult_mode=True)
57
+ scan = {"status": "pass", "export_gate": "clear"}
58
+
59
+ result_public = write_export_packet(run=run_public, scan=scan, operator_state=_make_base_state(), adult_mode=True)
60
+ result_private = write_export_packet(run=run_private, scan=scan, operator_state=_make_base_state(), adult_mode=False)
61
+
62
+ public_payload = json.loads(Path(result_public["path"]).read_text(encoding="utf-8"))
63
+ private_payload = json.loads(Path(result_private["path"]).read_text(encoding="utf-8"))
64
+
65
+ assert public_payload["adult_mode"] is False
66
+ assert private_payload["adult_mode"] is True
67
+ assert public_payload["model_stack"][0]["repo_id"] == run_public.model_stack[0].repo_id
68
+ assert private_payload["model_stack"][0]["repo_id"] == run_private.model_stack[0].repo_id
69
+
70
+
71
+ def test_export_packet_removes_hf_token_from_generation(monkeypatch) -> None:
72
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", "outputs/test-exports")
73
+ run = build_command_center_run("gothic platform boots brief")
74
+ scan = {"status": "pass", "export_gate": "clear"}
75
+ state = _make_base_state(
76
+ generation={"status": "success", "output_path": "/data/artifact.png", "hf_token_present": True},
77
+ )
78
+
79
+ result = write_export_packet(run=run, scan=scan, operator_state=state, adult_mode=False)
80
+ payload = json.loads(Path(result["path"]).read_text(encoding="utf-8"))
81
+
82
+ assert "hf_token_present" not in payload["generation"]
83
+ assert "token" not in json.dumps(payload).lower()
84
+
85
+
86
+ def test_export_packet_hackathon_claims_both_success(monkeypatch) -> None:
87
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", "outputs/test-exports")
88
+ run = build_command_center_run("couture archivist brief")
89
+ scan = {"status": "pass", "export_gate": "clear"}
90
+ state = _make_base_state(
91
+ minicpm_judge={"status": "success"},
92
+ nemotron_evidence={"status": "success"},
93
+ )
94
+
95
+ result = write_export_packet(run=run, scan=scan, operator_state=state, adult_mode=False)
96
+ payload = json.loads(Path(result["path"]).read_text(encoding="utf-8"))
97
+
98
+ assert payload["hackathon_claims"]["openbmb_lane"] is True
99
+ assert payload["hackathon_claims"]["nvidia_nemotron_lane"] is True
100
+ assert payload["hackathon_claims"]["gradio_space"] is True
101
+ assert payload["hackathon_claims"]["off_brand_custom_ui"] is True
102
+
103
+
104
+ def test_export_packet_hackathon_claims_st3gg_export_gate(monkeypatch) -> None:
105
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", "outputs/test-exports")
106
+ run_clear = build_command_center_run("scan gate test brief clear")
107
+ run_blocked = build_command_center_run("scan gate test brief blocked")
108
+ scan_clear = {"status": "pass", "export_gate": "clear"}
109
+ scan_blocked = {"status": "review", "export_gate": "blocked"}
110
+
111
+ result_clear = write_export_packet(run=run_clear, scan=scan_clear, operator_state=_make_base_state(), adult_mode=False)
112
+ result_blocked = write_export_packet(run=run_blocked, scan=scan_blocked, operator_state=_make_base_state(), adult_mode=False)
113
+
114
+ payload_clear = json.loads(Path(result_clear["path"]).read_text(encoding="utf-8"))
115
+ payload_blocked = json.loads(Path(result_blocked["path"]).read_text(encoding="utf-8"))
116
+
117
+ assert payload_clear["hackathon_claims"]["st3gg_export_gate"] == "clear"
118
+ assert payload_blocked["hackathon_claims"]["st3gg_export_gate"] == "blocked"
119
+
120
+
121
+ def test_export_packet_includes_model_stack_and_prompts(monkeypatch) -> None:
122
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", "outputs/test-exports")
123
+ run = build_command_center_run("raven archivist couture brief")
124
+ scan = {"status": "pass", "export_gate": "clear"}
125
+
126
+ result = write_export_packet(run=run, scan=scan, operator_state=_make_base_state(), adult_mode=False)
127
+ payload = json.loads(Path(result["path"]).read_text(encoding="utf-8"))
128
+
129
+ assert isinstance(payload["model_stack"], list)
130
+ assert len(payload["model_stack"]) > 0
131
+ assert all("repo_id" in entry and "params_b" in entry for entry in payload["model_stack"])
132
+ assert isinstance(payload["prompt"], str)
133
+ assert isinstance(payload["refined_prompt"], str)
134
+ assert isinstance(payload["created_at_epoch"], int)
135
+
136
+
137
+ def test_export_root_uses_nexus_export_dir_env(monkeypatch) -> None:
138
+ custom_dir = Path("outputs/test-exports/custom_export")
139
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", str(custom_dir))
140
+
141
+ root = export_root()
142
+
143
+ assert root == custom_dir.resolve()
144
+ assert root.is_dir()
145
+
146
+
147
+ def test_export_root_rejects_src_export_dir(monkeypatch) -> None:
148
+ unsafe_dir = Path("src/nexus_visual_weaver/export-leak")
149
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", str(unsafe_dir))
150
+
151
+ root = export_root()
152
+
153
+ src_root = (Path.cwd() / "src").resolve()
154
+ assert root != src_root
155
+ assert src_root not in root.parents
156
+ assert not unsafe_dir.exists()
157
+
158
+
159
+ def test_export_root_falls_back_to_outputs_when_no_env(monkeypatch) -> None:
160
+ monkeypatch.delenv("NEXUS_EXPORT_DIR", raising=False)
161
+ # Patch /data so it is not seen as existing
162
+ import nexus_visual_weaver.exporter as exporter_mod
163
+ original_exists = Path.exists
164
+
165
+ def patched_exists(self):
166
+ if str(self) == "/data":
167
+ return False
168
+ return original_exists(self)
169
+
170
+ monkeypatch.setattr(Path, "exists", patched_exists)
171
+
172
+ root = export_root()
173
+ assert "outputs" in str(root) or "exports" in str(root)
174
+
175
+
176
+ def test_export_packet_returns_both_path_and_packet(monkeypatch) -> None:
177
+ monkeypatch.setenv("NEXUS_EXPORT_DIR", "outputs/test-exports")
178
+ run = build_command_center_run("return structure brief")
179
+ scan = {"status": "pass", "export_gate": "clear"}
180
+
181
+ result = write_export_packet(run=run, scan=scan, operator_state=_make_base_state(), adult_mode=False)
182
+
183
+ assert "path" in result
184
+ assert "packet" in result
185
+ assert isinstance(result["packet"], dict)
186
+ assert result["packet"]["schema"] == "nexus_visual_weaver.export_packet.v1"
tests/test_model_relay.py CHANGED
@@ -138,3 +138,79 @@ def test_optional_external_gateways_are_registered_but_excluded_by_default() ->
138
  assert relay.records["netflix-void-modal"].health == "healthy"
139
  assert relay.records["netlify-ai-gateway-helper"].health == "excluded"
140
  assert relay.records["fal-media-adapter"].health == "excluded"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  assert relay.records["netflix-void-modal"].health == "healthy"
139
  assert relay.records["netlify-ai-gateway-helper"].health == "excluded"
140
  assert relay.records["fal-media-adapter"].health == "excluded"
141
+
142
+
143
+ def test_minicpm_v46_is_registered_in_taste_judge_lane() -> None:
144
+ relay = WeaverModelRelay()
145
+
146
+ record = relay.records["minicpm-v46-visual-judge"]
147
+
148
+ assert record.lane == "taste_judge"
149
+ assert record.repo_id == "openbmb/MiniCPM-V-4.6"
150
+ assert record.provider == "openbmb"
151
+ assert record.params_b == 1.30
152
+ assert record.license_gate == "apache-2.0"
153
+ assert record.health == "healthy"
154
+
155
+
156
+ def test_nemotron_parse_is_registered_in_taste_judge_lane() -> None:
157
+ relay = WeaverModelRelay()
158
+
159
+ record = relay.records["nemotron-parse-v12-evidence"]
160
+
161
+ assert record.lane == "taste_judge"
162
+ assert record.repo_id == "nvidia/NVIDIA-Nemotron-Parse-v1.2"
163
+ assert record.provider == "hf_nvidia"
164
+ assert record.params_b == 0.94
165
+ assert record.health == "healthy"
166
+
167
+
168
+ def test_nemotron_nano_is_registered_as_fallback_for_parse() -> None:
169
+ relay = WeaverModelRelay()
170
+
171
+ parse_record = relay.records["nemotron-parse-v12-evidence"]
172
+ nano_record = relay.records["nemotron-nano-4b-gguf-evidence"]
173
+
174
+ assert "nemotron-nano-4b-gguf-evidence" in (parse_record.fallback_chain or ())
175
+ assert nano_record.repo_id == "nvidia/NVIDIA-Nemotron-3-Nano-4B-GGUF"
176
+ assert nano_record.lane == "taste_judge"
177
+ assert nano_record.params_b == 3.97
178
+
179
+
180
+ def test_private_image_research_lane_is_rotatable() -> None:
181
+ from nexus_visual_weaver.model_relay import PINNED_LANES, ROTATABLE_LANES
182
+
183
+ assert "private_image_research" not in PINNED_LANES
184
+ assert "private_image_research" in ROTATABLE_LANES
185
+
186
+
187
+ def test_flux2_klein_4b_is_pinned_with_apache_license() -> None:
188
+ relay = WeaverModelRelay()
189
+
190
+ record = relay.records["flux2-klein-4b-public"]
191
+
192
+ assert record.lane == "image_generation"
193
+ assert record.pinned is True
194
+ assert record.params_b == 4.0
195
+ assert record.license_gate == "apache-2.0"
196
+ assert record.repo_id == "black-forest-labs/FLUX.2-klein-4B"
197
+
198
+
199
+ def test_flux2_klein_9b_is_not_pinned_and_in_private_research() -> None:
200
+ relay = WeaverModelRelay()
201
+
202
+ record = relay.records["flux2-klein-9b-private"]
203
+
204
+ assert record.lane == "private_image_research"
205
+ assert record.pinned is False
206
+ assert record.params_b == 9.0
207
+ assert record.license_gate == "review_required"
208
+
209
+
210
+ def test_minicpm_has_fallback_chain_configured() -> None:
211
+ relay = WeaverModelRelay()
212
+
213
+ record = relay.records["minicpm-v46-visual-judge"]
214
+
215
+ assert record.fallback_chain is not None
216
+ assert len(record.fallback_chain) > 0
tests/test_provider_runtime.py CHANGED
@@ -1,6 +1,18 @@
1
  from PIL import Image
2
 
3
- from nexus_visual_weaver.provider_runtime import judge_with_minicpm, judge_with_nemotron
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
 
6
  def test_minicpm_reports_missing_secret(monkeypatch) -> None:
@@ -70,3 +82,302 @@ def test_nemotron_reports_missing_secret(monkeypatch) -> None:
70
  assert result.status == "missing_secret"
71
  assert result.provider == "NVIDIA"
72
  assert "Nemotron" in result.message
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from PIL import Image
2
 
3
+ from nexus_visual_weaver.provider_runtime import (
4
+ NEMOTRON_NANO_REPO_ID,
5
+ NEMOTRON_PARSE_REPO_ID,
6
+ OPENBMB_REPO_ID,
7
+ ProviderJudgeResult,
8
+ _extract_content,
9
+ _image_data_url,
10
+ _post_json,
11
+ _safe_json_from_text,
12
+ _short_error,
13
+ judge_with_minicpm,
14
+ judge_with_nemotron,
15
+ )
16
 
17
 
18
  def test_minicpm_reports_missing_secret(monkeypatch) -> None:
 
82
  assert result.status == "missing_secret"
83
  assert result.provider == "NVIDIA"
84
  assert "Nemotron" in result.message
85
+
86
+
87
+ # --- _short_error tests ---
88
+
89
+ def test_short_error_prefixes_class_name() -> None:
90
+ exc = ValueError("something went wrong")
91
+ result = _short_error(exc)
92
+ assert result.startswith("ValueError:")
93
+ assert "something went wrong" in result
94
+
95
+
96
+ def test_short_error_truncates_long_messages() -> None:
97
+ long_message = "x" * 500
98
+ exc = RuntimeError(long_message)
99
+ result = _short_error(exc)
100
+ assert len(result) <= len("RuntimeError: ") + 360
101
+ assert result.endswith("...")
102
+
103
+
104
+ def test_short_error_collapses_newlines() -> None:
105
+ exc = OSError("line one\nline two\nline three")
106
+ result = _short_error(exc)
107
+ assert "\n" not in result
108
+ assert "line one" in result
109
+
110
+
111
+ # --- _image_data_url tests ---
112
+
113
+ def test_image_data_url_returns_none_for_none_path() -> None:
114
+ assert _image_data_url(None) is None
115
+
116
+
117
+ def test_image_data_url_returns_none_for_missing_file() -> None:
118
+ assert _image_data_url("/nonexistent/path/to/image.png") is None
119
+
120
+
121
+ def test_image_data_url_encodes_png_as_base64() -> None:
122
+ image_path = "outputs/test-img-data-url.png"
123
+ Image.new("RGB", (4, 4), color=(0, 0, 0)).save(image_path)
124
+
125
+ result = _image_data_url(image_path)
126
+
127
+ assert result is not None
128
+ assert result.startswith("data:image/png;base64,")
129
+
130
+
131
+ def test_image_data_url_uses_jpeg_mime_for_jpg() -> None:
132
+ image_path = "outputs/test-img-data-url.jpg"
133
+ Image.new("RGB", (4, 4), color=(0, 0, 0)).save(image_path)
134
+
135
+ result = _image_data_url(image_path)
136
+
137
+ assert result is not None
138
+ assert result.startswith("data:image/jpeg;base64,")
139
+
140
+
141
+ # --- _extract_content tests ---
142
+
143
+ def test_extract_content_returns_string_from_choices() -> None:
144
+ response = {"choices": [{"message": {"content": "hello world"}}]}
145
+ assert _extract_content(response) == "hello world"
146
+
147
+
148
+ def test_extract_content_returns_empty_for_no_choices() -> None:
149
+ assert _extract_content({"choices": []}) == ""
150
+ assert _extract_content({}) == ""
151
+
152
+
153
+ def test_extract_content_serializes_non_string_content() -> None:
154
+ response = {"choices": [{"message": {"content": {"key": "value"}}}]}
155
+ result = _extract_content(response)
156
+ assert "key" in result
157
+ assert "value" in result
158
+
159
+
160
+ # --- _safe_json_from_text tests ---
161
+
162
+ def test_safe_json_from_text_parses_valid_json() -> None:
163
+ text = '{"status": "pass", "score": 0.9}'
164
+ result = _safe_json_from_text(text)
165
+ assert result == {"status": "pass", "score": 0.9}
166
+
167
+
168
+ def test_safe_json_from_text_returns_empty_dict_for_empty_string() -> None:
169
+ assert _safe_json_from_text("") == {}
170
+ assert _safe_json_from_text(" ") == {}
171
+
172
+
173
+ def test_safe_json_from_text_falls_back_on_invalid_json() -> None:
174
+ text = "this is not valid json"
175
+ result = _safe_json_from_text(text)
176
+ assert "raw_summary" in result
177
+ assert "this is not valid json" in result["raw_summary"]
178
+
179
+
180
+ def test_safe_json_from_text_extracts_embedded_json() -> None:
181
+ text = 'Some prefix text {"result": "ok"} trailing text'
182
+ result = _safe_json_from_text(text)
183
+ assert result == {"result": "ok"}
184
+
185
+
186
+ def test_safe_json_from_text_truncates_fallback_to_1200_chars() -> None:
187
+ long_text = "not json " + "x" * 2000
188
+ result = _safe_json_from_text(long_text)
189
+ assert "raw_summary" in result
190
+ assert len(result["raw_summary"]) <= 1200
191
+
192
+
193
+ # --- ProviderJudgeResult.to_dict tests ---
194
+
195
+ def test_provider_judge_result_to_dict_contains_all_fields() -> None:
196
+ result = ProviderJudgeResult(
197
+ status="success",
198
+ provider_state="configured",
199
+ provider="OpenBMB",
200
+ repo_id=OPENBMB_REPO_ID,
201
+ model="MiniCPM-V-4.6",
202
+ message="judge returned evidence",
203
+ evidence={"overall_status": "pass"},
204
+ latency_seconds=1.23,
205
+ )
206
+ d = result.to_dict()
207
+
208
+ assert d["status"] == "success"
209
+ assert d["provider_state"] == "configured"
210
+ assert d["provider"] == "OpenBMB"
211
+ assert d["repo_id"] == OPENBMB_REPO_ID
212
+ assert d["model"] == "MiniCPM-V-4.6"
213
+ assert d["latency_seconds"] == 1.23
214
+ assert d["evidence"]["overall_status"] == "pass"
215
+
216
+
217
+ # --- nemotron success/failure tests ---
218
+
219
+ def test_nemotron_success_with_mocked_post(monkeypatch) -> None:
220
+ monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test")
221
+ monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token")
222
+
223
+ def fake_post(url, token, payload, timeout):
224
+ assert "Nemotron" in payload["model"] or "nemotron" in payload["model"]
225
+ return {"choices": [{"message": {"content": '{"final_claim_status":"pass","structured_parse":"ok"}'}}]}
226
+
227
+ monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post)
228
+
229
+ result = judge_with_nemotron(
230
+ prompt="gothic couture brief",
231
+ run_packet={"checkpoint": {"checkpoint_id": "nw-test-123"}},
232
+ minicpm_result={"status": "success"},
233
+ )
234
+
235
+ assert result.status == "success"
236
+ assert result.provider == "NVIDIA"
237
+ assert result.evidence["final_claim_status"] == "pass"
238
+ assert result.latency_seconds is not None
239
+
240
+
241
+ def test_nemotron_failed_api_call_returns_failed_status(monkeypatch) -> None:
242
+ import urllib.error
243
+
244
+ monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test")
245
+ monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token")
246
+
247
+ def fake_post(url, token, payload, timeout):
248
+ raise urllib.error.URLError("connection refused")
249
+
250
+ monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post)
251
+
252
+ result = judge_with_nemotron(
253
+ prompt="brief",
254
+ run_packet={"id": "nw-fail"},
255
+ )
256
+
257
+ assert result.status == "failed"
258
+ assert result.provider_state == "failed"
259
+ assert "URLError" in result.message or "connection" in result.message.lower()
260
+ assert result.evidence.get("configured") is True
261
+
262
+
263
+ def test_minicpm_failed_api_call_returns_failed_status(monkeypatch) -> None:
264
+ import urllib.error
265
+
266
+ image_path = "outputs/test-minicpm-fail.png"
267
+ Image.new("RGB", (4, 4), color=(0, 0, 0)).save(image_path)
268
+ monkeypatch.setenv("MINICPM_BASE_URL", "http://minicpm.test")
269
+ monkeypatch.setenv("MINICPM_API_KEY", "test-token")
270
+
271
+ def fake_post(url, token, payload, timeout):
272
+ raise urllib.error.URLError("network unreachable")
273
+
274
+ monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post)
275
+
276
+ result = judge_with_minicpm(
277
+ prompt="gothic couture",
278
+ image_path=image_path,
279
+ scan={"export_gate": "clear"},
280
+ wardrobe_summary="platform boots",
281
+ )
282
+
283
+ assert result.status == "failed"
284
+ assert result.provider_state == "failed"
285
+ assert result.provider == "OpenBMB"
286
+ assert result.evidence.get("configured") is True
287
+
288
+
289
+ def test_nemotron_uses_parse_repo_id_for_parse_model(monkeypatch) -> None:
290
+ monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test")
291
+ monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token")
292
+ monkeypatch.setenv("NEMOTRON_MODEL", "nvidia/NVIDIA-Nemotron-Parse-v1.2")
293
+
294
+ def fake_post(url, token, payload, timeout):
295
+ return {"choices": [{"message": {"content": "{}"}}]}
296
+
297
+ monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post)
298
+
299
+ result = judge_with_nemotron(prompt="brief", run_packet={})
300
+
301
+ assert result.repo_id == NEMOTRON_PARSE_REPO_ID
302
+
303
+
304
+ def test_nemotron_uses_nano_repo_id_for_non_parse_model(monkeypatch) -> None:
305
+ monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test")
306
+ monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token")
307
+ monkeypatch.setenv("NEMOTRON_MODEL", "nvidia/NVIDIA-Nemotron-3-Nano-4B-GGUF")
308
+
309
+ def fake_post(url, token, payload, timeout):
310
+ return {"choices": [{"message": {"content": "{}"}}]}
311
+
312
+ monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post)
313
+
314
+ result = judge_with_nemotron(prompt="brief", run_packet={})
315
+
316
+ assert result.repo_id == NEMOTRON_NANO_REPO_ID
317
+
318
+
319
+ def test_minicpm_uses_openbmb_api_key_as_fallback(monkeypatch) -> None:
320
+ monkeypatch.setenv("MINICPM_BASE_URL", "http://minicpm.test")
321
+ monkeypatch.delenv("MINICPM_API_KEY", raising=False)
322
+ monkeypatch.setenv("OPENBMB_API_KEY", "openbmb-fallback-token")
323
+
324
+ image_path = "outputs/test-openbmb-key.png"
325
+ Image.new("RGB", (4, 4), color=(0, 0, 0)).save(image_path)
326
+
327
+ captured = {}
328
+
329
+ def fake_post(url, token, payload, timeout):
330
+ captured["token"] = token
331
+ return {"choices": [{"message": {"content": '{"status": "ok"}'}}]}
332
+
333
+ monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post)
334
+
335
+ result = judge_with_minicpm(
336
+ prompt="test",
337
+ image_path=image_path,
338
+ scan={},
339
+ wardrobe_summary="",
340
+ )
341
+
342
+ assert result.status == "success"
343
+ assert captured["token"] == "openbmb-fallback-token"
344
+
345
+
346
+ def test_nemotron_uses_nvidia_api_key_as_fallback(monkeypatch) -> None:
347
+ monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test")
348
+ monkeypatch.delenv("NEMOTRON_API_KEY", raising=False)
349
+ monkeypatch.setenv("NVIDIA_API_KEY", "nvidia-fallback-token")
350
+
351
+ captured = {}
352
+
353
+ def fake_post(url, token, payload, timeout):
354
+ captured["token"] = token
355
+ return {"choices": [{"message": {"content": "{}"}}]}
356
+
357
+ monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post)
358
+
359
+ result = judge_with_nemotron(prompt="brief", run_packet={})
360
+
361
+ assert result.status == "success"
362
+ assert captured["token"] == "nvidia-fallback-token"
363
+
364
+
365
+ def test_post_json_rejects_unsupported_url_schemes_before_urlopen(monkeypatch) -> None:
366
+ called = False
367
+
368
+ def fake_urlopen(*args, **kwargs):
369
+ nonlocal called
370
+ called = True
371
+ raise AssertionError("urlopen should not be called for invalid schemes")
372
+
373
+ monkeypatch.setattr("urllib.request.urlopen", fake_urlopen)
374
+
375
+ for url in ["file:///tmp/payload.json", "ftp://example.test/api", "http:///missing-host"]:
376
+ try:
377
+ _post_json(url, "token", {"ok": True}, 1.0)
378
+ except ValueError as exc:
379
+ assert "Invalid URL" in str(exc)
380
+ else:
381
+ raise AssertionError(f"{url} should have been rejected")
382
+
383
+ assert called is False