feat(sequence): combined fragments (alt/opt/loop) + OAuth example (#13)
Expand type-sequence.md with fragment frames, async open arrowheads, complexity budget, and anti-patterns. Add bearer+refresh special examples (light/dark/full) without changing the cold-cache trio. Wire README/SKILL budget and a verify script that drives lint-skin.py. Co-authored-by: wolf10drc <alaa@golead.io>
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Structural + skin-lint verification for sequence combined-fragment work.
|
||||
|
||||
Drives the real shipped artifacts (type-sequence.md, oauth examples, lint-skin.py).
|
||||
Exit 0 only when all gates pass. Intended for local/PR checks alongside:
|
||||
python scripts/lint-skin.py --all --baseline
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
TYPE_SEQ = ROOT / "skills/diagram-design/references/type-sequence.md"
|
||||
ASSETS = ROOT / "skills/diagram-design/assets"
|
||||
COLD = [
|
||||
ASSETS / "example-sequence.html",
|
||||
ASSETS / "example-sequence-dark.html",
|
||||
ASSETS / "example-sequence-full.html",
|
||||
]
|
||||
OAUTH = [
|
||||
ASSETS / "example-sequence-oauth.html",
|
||||
ASSETS / "example-sequence-oauth-dark.html",
|
||||
ASSETS / "example-sequence-oauth-full.html",
|
||||
]
|
||||
LINT = ROOT / "scripts/lint-skin.py"
|
||||
|
||||
|
||||
def fail(msg: str) -> None:
|
||||
print(f"FAIL: {msg}", file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
def ok(msg: str) -> None:
|
||||
print(f"OK: {msg}")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if not TYPE_SEQ.is_file():
|
||||
fail(f"missing {TYPE_SEQ}")
|
||||
|
||||
text = TYPE_SEQ.read_text(encoding="utf-8")
|
||||
required_sections = [
|
||||
"## Combined fragments",
|
||||
"### Open arrowhead (async)",
|
||||
"## Complexity budget",
|
||||
"## Anti-patterns",
|
||||
"arrow-open",
|
||||
]
|
||||
for needle in required_sections:
|
||||
if needle not in text:
|
||||
fail(f"type-sequence.md missing {needle!r}")
|
||||
for op in ("ALT", "OPT", "LOOP"):
|
||||
if op not in text:
|
||||
fail(f"type-sequence.md missing operator {op}")
|
||||
if "[token valid]" not in text and "guard" not in text.lower():
|
||||
fail("type-sequence.md missing guard documentation")
|
||||
ok("type-sequence.md fragments + async + budget present")
|
||||
|
||||
for path in COLD:
|
||||
if not path.is_file():
|
||||
fail(f"cold-cache example missing: {path.name}")
|
||||
body = path.read_text(encoding="utf-8")
|
||||
if "cold cache" not in body.lower() and "Article request" not in body:
|
||||
fail(f"{path.name} no longer looks like the cold-cache example")
|
||||
if "ALT" in body and "example-sequence-oauth" not in path.name:
|
||||
# cold-cache must not grow an ALT frame (special example only)
|
||||
# allow the word only in unrelated comments; require no ALT operator tab content
|
||||
if re.search(r">ALT<", body):
|
||||
fail(f"{path.name} unexpectedly contains ALT fragment tab")
|
||||
ok("cold-cache sequence trio intact (no ALT tab)")
|
||||
|
||||
for path in OAUTH:
|
||||
if not path.is_file():
|
||||
fail(f"oauth example missing: {path.name}")
|
||||
body = path.read_text(encoding="utf-8")
|
||||
if ">ALT<" not in body and ">ALT</text>" not in body:
|
||||
# tab text is ALT
|
||||
if not re.search(r">\s*ALT\s*<", body):
|
||||
fail(f"{path.name} missing ALT operator label")
|
||||
if "[token valid]" not in body:
|
||||
fail(f"{path.name} missing [token valid] guard")
|
||||
if "[else" not in body and "[else · 401]" not in body:
|
||||
fail(f"{path.name} missing else-region guard")
|
||||
if "arrow-open" not in body:
|
||||
fail(f"{path.name} missing arrow-open async marker")
|
||||
if "Bearer" not in body and "BEARER" not in body:
|
||||
fail(f"{path.name} missing bearer call")
|
||||
ok("oauth trio has ALT two-region structure + async open")
|
||||
|
||||
# Drive real skin linter entry point on new files
|
||||
cmd = [
|
||||
sys.executable,
|
||||
str(LINT),
|
||||
*[str(p) for p in OAUTH],
|
||||
]
|
||||
proc = subprocess.run(cmd, cwd=ROOT, capture_output=True, text=True)
|
||||
print(proc.stdout, end="")
|
||||
if proc.stderr:
|
||||
print(proc.stderr, end="", file=sys.stderr)
|
||||
if proc.returncode != 0:
|
||||
fail(f"lint-skin.py failed on oauth examples (exit {proc.returncode})")
|
||||
if "0 finding(s)" not in proc.stdout:
|
||||
fail("lint-skin.py did not report 0 findings on oauth examples")
|
||||
ok("lint-skin.py clean on oauth examples")
|
||||
|
||||
# Full repo gate
|
||||
proc2 = subprocess.run(
|
||||
[sys.executable, str(LINT), "--all", "--baseline"],
|
||||
cwd=ROOT,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
print(proc2.stdout, end="")
|
||||
if proc2.returncode != 0:
|
||||
fail(f"lint-skin.py --all --baseline failed (exit {proc2.returncode})")
|
||||
if "0 finding(s)" not in proc2.stdout:
|
||||
fail("lint-skin.py --all --baseline did not report 0 findings")
|
||||
ok("lint-skin.py --all --baseline green")
|
||||
|
||||
print("ALL GATES PASSED")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user