mirror of
https://github.com/dbl8005/sitrep-panel.git
synced 2026-08-24 07:29:11 +02:00
- 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.
96 lines
3.7 KiB
Python
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.")
|