#!/usr/bin/env python3 """Validate the child-local VISION package candidate manifest and docs.""" from __future__ import annotations import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] CURRENT_TOOLS = [ "vision.image_analyze", "vision.image_generate", "vision.palette_extract", "vision.background_cutout", ] PLANNED_TOOLS = [ "vision.ocr_read", "vision.screenshot_observe", "vision.browser_observe", "vision.document_layout_read", "vision.chart_read", "vision.table_read", "vision.diagram_read", "vision.object_detect", "vision.visual_ground", "vision.segment", "vision.video_read", "vision.image_edit", ] ROUTE_TOOLS = { "POST /vlm/analyze": "vision.image_analyze", "POST /flux/render": "vision.image_generate", "POST /palette/extract": "vision.palette_extract", "POST /rembg/cutout": "vision.background_cutout", } def main() -> int: errors: list[str] = [] required = [ "CONTEXT.md", "docs/VISION-PACKAGE-CANDIDATE.md", "candidate-manifests/vision-package-candidate.json", ] for rel in required: if not (ROOT / rel).exists(): errors.append(f"missing:{rel}") manifest_path = ROOT / "candidate-manifests/vision-package-candidate.json" manifest = _read_json(manifest_path, errors) if manifest: _expect(manifest.get("canonical_sense") == "VISION", "canonical_sense_not_vision", errors) _expect( manifest.get("status") == "candidate_only_not_seed_installed", "status_not_candidate_only", errors, ) _expect(manifest.get("current_tool_candidates") == CURRENT_TOOLS, "current_tools_mismatch", errors) _expect(manifest.get("planned_tool_candidates") == PLANNED_TOOLS, "planned_tools_mismatch", errors) route_map = { item.get("route"): item.get("tool_id") for item in manifest.get("current_route_adapters", []) } _expect(route_map == ROUTE_TOOLS, "route_tool_map_mismatch", errors) grant_policy = manifest.get("grant_policy", {}) _expect(grant_policy.get("wildcard_grant_allowed") is False, "wildcard_grant_allowed", errors) _expect( grant_policy.get("package_default_grants_all_tools") is False, "package_default_grants_all_tools", errors, ) _expect(grant_policy.get("tool_grants_are_granular") is True, "tool_grants_not_granular", errors) for key, value in manifest.get("non_authorization", {}).items(): if value is not False: errors.append(f"non_authorization_enabled:{key}") forbidden = set(manifest.get("forbidden_research_owned_capabilities", [])) for capability in ("web_search", "fetch_page", "extract_pdf", "deep_research", "research_synthesis"): if capability not in forbidden: errors.append(f"missing_forbidden_research_capability:{capability}") _check_snippets( "docs/VISION-PACKAGE-CANDIDATE.md", [ "Research reads sources; Vision sees media", "No Core promotion", "wildcard grant", "`vision.image_analyze`", "`vision.video_read`", ], errors, ) _check_snippets( "CONTEXT.md", ["Visual Evidence", "Research Handoff", "BTE Compatibility Surface"], errors, ) result = { "ok": not errors, "validator": "vision-package-candidate-v1", "checked": required, "errors": errors, "warnings": [], } print(json.dumps(result, indent=2, sort_keys=True)) return 0 if result["ok"] else 1 def _read_json(path: Path, errors: list[str]) -> dict | None: if not path.exists(): return None try: return json.loads(path.read_text(encoding="utf-8")) except json.JSONDecodeError as exc: errors.append(f"{path.relative_to(ROOT)}:json:{exc}") return None def _check_snippets(rel: str, snippets: list[str], errors: list[str]) -> None: path = ROOT / rel if not path.exists(): return text = path.read_text(encoding="utf-8") for snippet in snippets: if snippet not in text: errors.append(f"{rel}:missing:{snippet}") def _expect(condition: bool, error: str, errors: list[str]) -> None: if not condition: errors.append(error) if __name__ == "__main__": raise SystemExit(main())