feat(skills): add React and Vite tool expertise

Squash-merge verified React and Vite expertise at exact head d4fd6cf70d. Required validate and paired evaluation checks passed; advisory droid review had no blocking findings.
This commit is contained in:
Magnus Hedemark
2026-09-01 20:05:58 -04:00
committed by GitHub
parent 035e58d3e3
commit befe2e26fc
22 changed files with 864 additions and 2 deletions
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""Bounded, read-only diagnostics for React/Vite projects."""
import argparse
import json
import re
import sys
from pathlib import Path
MAX_BYTES = 512 * 1024
TEXT_FILES = ("package.json", "vite.config.js", "vite.config.ts", "vite.config.mjs", "vite.config.cjs", "tsconfig.json")
def read_text(root, name):
path = root / name
try:
if not path.is_file() or path.stat().st_size > MAX_BYTES:
return None
return path.read_text(encoding="utf-8")
except (OSError, UnicodeError):
return None
def diagnose(root):
result = {"project": str(root), "checks": [], "warnings": []}
package_text = read_text(root, "package.json")
package = None
if package_text is None:
result["warnings"].append("package.json is missing or exceeds the read limit")
else:
try:
package = json.loads(package_text)
if not isinstance(package, dict):
raise ValueError("not an object")
deps = {**package.get("dependencies", {}), **package.get("devDependencies", {})}
result["checks"].append({"name": "package-json", "status": "ok"})
result["checks"].append({"name": "react-dependencies", "status": "ok" if "react" in deps and "react-dom" in deps else "warning"})
except (ValueError, TypeError, json.JSONDecodeError):
result["warnings"].append("package.json is not valid JSON")
config_name = next((name for name in TEXT_FILES[1:5] if read_text(root, name) is not None), None)
result["checks"].append({"name": "vite-config", "status": "ok" if config_name else "info", "file": config_name})
source_files = []
for directory in (root / "src", root / "app"):
if directory.is_dir():
source_files.extend(p for p in directory.rglob("*") if p.is_file() and p.suffix in {".jsx", ".tsx", ".js", ".ts"})
result["checks"].append({"name": "source-entry", "status": "ok" if source_files else "warning", "file_count": len(source_files)})
env_names = set()
for path in root.glob(".env*"):
text = read_text(root, path.name) or ""
env_names.update(re.findall(r"^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=", text, re.MULTILINE))
result["checks"].append({"name": "public-env-names", "status": "ok", "names": sorted(n for n in env_names if n.startswith("VITE_"))})
if any(not n.startswith("VITE_") for n in env_names):
result["warnings"].append(".env files contain non-public names; keep them server-side and never import secrets into client code")
lockfiles = [name for name in ("package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock") if (root / name).is_file()]
result["checks"].append({"name": "lockfile", "status": "ok" if lockfiles else "warning", "files": lockfiles})
return result
def main(argv=None):
parser = argparse.ArgumentParser(description="Read-only React/Vite project diagnostics")
parser.add_argument("project", nargs="?", default=".")
parser.add_argument("--json", action="store_true", dest="as_json")
args = parser.parse_args(argv)
root = Path(args.project).expanduser().resolve()
if not root.is_dir():
print("ERROR: project directory does not exist", file=sys.stderr)
return 2
result = diagnose(root)
if args.as_json:
print(json.dumps(result, sort_keys=True))
else:
print("React/Vite doctor: " + result["project"])
for check in result["checks"]:
print("- {name}: {status}".format(**check))
for warning in result["warnings"]:
print("WARNING: " + warning)
return 0
if __name__ == "__main__":
sys.exit(main())
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""Offline tests for the read-only React doctor."""
import json
import os
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
SCRIPT = Path(__file__).with_name("react-doctor.py")
class DoctorTests(unittest.TestCase):
def run_doctor(self, root, *args):
return subprocess.run([sys.executable, str(SCRIPT), *args, str(root)], capture_output=True, text=True)
def test_json_reports_react_vite_signals_without_values(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
(root / "package.json").write_text(json.dumps({"dependencies": {"react": "18", "react-dom": "18"}}), encoding="utf-8")
(root / "vite.config.ts").write_text("export default {}", encoding="utf-8")
(root / "src").mkdir()
(root / "src/App.tsx").write_text("export default function App() {}", encoding="utf-8")
(root / ".env.local").write_text("VITE_PUBLIC=visible\nSECRET=do-not-print\n", encoding="utf-8")
output = self.run_doctor(root, "--json")
self.assertEqual(output.returncode, 0)
report = json.loads(output.stdout)
self.assertEqual(report["checks"][0]["status"], "ok")
env_check = next(check for check in report["checks"] if check["name"] == "public-env-names")
self.assertIn("VITE_PUBLIC", env_check["names"])
self.assertNotIn("do-not-print", output.stdout)
def test_missing_project_is_usage_error(self):
output = self.run_doctor(Path("/definitely/not/a/project"))
self.assertEqual(output.returncode, 2)
self.assertIn("does not exist", output.stderr)
def test_malformed_package_is_reported(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
(root / "package.json").write_text("{broken", encoding="utf-8")
output = self.run_doctor(root, "--json")
self.assertEqual(output.returncode, 0)
self.assertTrue(any("not valid JSON" in warning for warning in json.loads(output.stdout)["warnings"]))
def test_help_is_available(self):
output = subprocess.run([sys.executable, str(SCRIPT), "--help"], capture_output=True, text=True)
self.assertEqual(output.returncode, 0)
self.assertIn("read-only", output.stdout.lower())
if __name__ == "__main__":
unittest.main()