Files
sitrep-panel/scripts/validate-package.py
T
dbl8005 3e4d4c46da feat: v1.1.0 redesign — light default, real toggle, kanban board, sticky nav
- Theme is now a manual toggle (real sun/moon SVG icons, not glyphs that
  don't render consistently), persisted to localStorage, defaults to light
  on first visit. No more silent OS-based auto-switching.
- Small wordmark + mark in a thin top bar so the page is recognizable as
  sitrep-panel, not just the task title.
- Status board rewritten as four kanban-style columns (to do / in progress
  / done / blocked) with live counts, instead of a loose wrap of
  identically-styled cards.
- Every section gets a one-line description of its purpose.
- Sticky section nav with scroll-spy highlighting — real wayfinding without
  hiding any content behind a click, since the whole point is to be
  glanceable.
- Log entries use a proper timeline rail (dot + connecting line) instead of
  a colored border-left accent.
- Palette rebuilt in OKLCH with neutrals tinted toward the accent hue.

Updates the SKILL.md/AGENTS.md protocol and validator for the new
column-based board markup and entry structure.
2026-08-23 00:47:27 +03:00

96 lines
3.7 KiB
Python

#!/usr/bin/env python3
"""Check sitrep-panel's package files without external dependencies."""
from __future__ import annotations
import ast
import json
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
SKILL = (ROOT / "SKILL.md").read_text(encoding="utf-8")
README = (ROOT / "README.md").read_text(encoding="utf-8")
AGENTS = (ROOT / "AGENTS.md").read_text(encoding="utf-8")
TEMPLATE = (ROOT / "assets" / "template.html").read_text(encoding="utf-8")
PLUGIN = json.loads((ROOT / ".claude-plugin" / "plugin.json").read_text(encoding="utf-8"))
MARKETPLACE = json.loads((ROOT / ".claude-plugin" / "marketplace.json").read_text(encoding="utf-8"))
SERVE_PY = (ROOT / "scripts" / "serve.py").read_text(encoding="utf-8")
def require_match(match: re.Match[str] | None, message: str) -> re.Match[str]:
if match is None:
raise SystemExit(message)
return match
def require(condition: bool, message: str) -> None:
if not condition:
raise SystemExit(message)
# --- SKILL.md frontmatter ---------------------------------------------------
yaml_metadata = require_match(
re.match(r"\A---\n(.*?)\n---\n", SKILL, re.DOTALL),
"SKILL.md must begin with YAML metadata",
).group(1)
require(
re.search(r"(?m)^name:\s*sitrep-panel\s*$", yaml_metadata) is not None,
"SKILL.md metadata must set name: sitrep-panel",
)
require(
re.search(r"(?m)^description:", yaml_metadata) is not None,
"SKILL.md metadata must set a description",
)
require(
re.search(r"(?m)^license:\s*MIT\s*$", yaml_metadata) is not None,
"SKILL.md metadata must set license: MIT",
)
skill_version = require_match(
re.search(r'(?m)^\s+version:\s*["\']([^"\']+)["\']\s*$', yaml_metadata),
"Add metadata.version to SKILL.md",
).group(1)
# --- version consistency across README / plugin.json / marketplace.json ---
readme_version = require_match(
re.search(r"(?m)^- \*\*([0-9]+\.[0-9]+\.[0-9]+)\*\*", README),
"Add a version entry to README.md's Versions section",
).group(1)
require(
skill_version == readme_version == PLUGIN["version"],
f"Version mismatch: SKILL.md={skill_version} README.md={readme_version} plugin.json={PLUGIN['version']}",
)
require(PLUGIN["name"] == "sitrep-panel", "plugin.json name must be sitrep-panel")
require(PLUGIN["license"] == "MIT", "plugin.json license must be MIT")
require(
any(p["name"] == "sitrep-panel" for p in MARKETPLACE["plugins"]),
"marketplace.json must list a sitrep-panel plugin entry",
)
# --- AGENTS.md exists and isn't a stub --------------------------------------
require(len(AGENTS.strip()) > 200, "AGENTS.md looks empty or too short")
# --- template.html has the ids the SKILL.md protocol depends on ------------
for element_id in (
"board", "board-todo", "board-progress", "board-done", "board-blocked",
"current-work-body", "shots-body", "entries", "updated-badge",
"theme-toggle", "section-nav",
):
require(f'id="{element_id}"' in TEMPLATE, f'template.html is missing id="{element_id}"')
for token in ("{{TITLE}}", "{{SUBTITLE}}"):
require(token in TEMPLATE, f"template.html is missing the {token} placeholder")
require("meta.json" in TEMPLATE, "template.html must poll meta.json for live-reload")
require("data-theme" in TEMPLATE, "template.html must support a manual light/dark toggle")
# --- serve.py is at least syntactically valid Python ------------------------
try:
ast.parse(SERVE_PY, filename="scripts/serve.py")
except SyntaxError as exc: # pragma: no cover - fails loud on purpose
raise SystemExit(f"scripts/serve.py has a syntax error: {exc}") from exc
require("SERVING http://localhost" in SERVE_PY, "serve.py must print the SERVING line callers parse")
print("sitrep-panel package checks passed.")