From b1f399e9a971e724a6e08d90192393f83e014516 Mon Sep 17 00:00:00 2001 From: Abhirup Banerjee <139776126+ovhirup@users.noreply.github.com> Date: Thu, 1 Oct 2026 22:25:32 +0530 Subject: [PATCH 1/2] Check that every rev reference agrees with the policy block A rev bump touched several places CI did not check. Add a stdlib-only step that reads the rev from inside the policy block and requires the frontmatter policy-rev, the step-4 text, evals cases 1 and 2, and each port's README rev to agree with their sources. Line 50 no longer hard-codes the rev, so a bump needs no workflow edit. Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/validate.yml | 52 +++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index bb1550a..0f4df97 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -47,7 +47,7 @@ jobs: grep -qE '^[[:space:]]*author:' "$S" || { echo "::error::frontmatter author missing"; exit 1; } [ "$(grep -cx -- '' "$S")" -eq 1 ] || { echo "::error::SKILL.md must contain exactly one whole-line opening marker"; exit 1; } [ "$(grep -cx -- '' "$S")" -eq 1 ] || { echo "::error::SKILL.md must contain exactly one whole-line closing marker"; exit 1; } - [ "$(grep -cx -- '' "$S")" -eq 1 ] || { echo "::error::SKILL.md must contain exactly one whole-line policy-rev: 5 comment"; exit 1; } + [ "$(grep -cxE -- '' "$S")" -eq 1 ] || { echo "::error::SKILL.md must contain exactly one whole-line policy-rev comment"; exit 1; } for h in Prompt Context Harness Loop Graph; do awk '/^$/,/^$/' "$S" | grep -q "^### $h" || { echo "::error::policy block missing the $h layer"; exit 1; } done @@ -86,6 +86,56 @@ jobs: PY echo "frontmatter OK" + - name: Revision references agree + run: | + python3 - <<'PY' + import json, re, sys, pathlib + bad = [] + def lines(p): return pathlib.Path(p).read_text().splitlines() + def region(ls, start, end, path): + if ls.count(start) != 1 or ls.count(end) != 1: + bad.append(f"{path} needs exactly one whole-line {start} and {end}"); return [] + return ls[ls.index(start) + 1:ls.index(end)] + def one(ls, pattern, what): + hits = [m.group(1) for m in map(re.compile(pattern).fullmatch, ls) if m] + if len(hits) != 1: + bad.append(f"{what}: expected exactly one, found {len(hits)}"); return None + return hits[0] + S = "plugins/stackwich/skills/stackwich/SKILL.md" + s = lines(S) + rev = one(region(s, "", "", S), r"", f"{S} policy-rev comment inside the block") + fm = s[1:s.index("---", 1)] if s[:1] == ["---"] and "---" in s[1:] else [] + meta = one(fm, r"\s+policy-rev: (\d+)", f"{S} frontmatter metadata.policy-rev") + h = "## 4. Verify the install" + i = s.index(h) if h in s else len(s) + j = next((k for k in range(i + 1, len(s)) if s[k].startswith("## ")), len(s)) + step4 = one(s[i + 1:j], r"2\. `policy-rev: (\d+)` is present inside the block.*", f"{S} step 4 check 2") + for label, val in (("frontmatter metadata.policy-rev", meta), ("step 4 check 2", step4)): + if None not in (rev, val) and val != rev: + bad.append(f"{S} {label} is {val}, but the block's policy-rev comment is {rev}") + evals = {e["id"]: e for e in json.loads(pathlib.Path("evals/evals.json").read_text())["evals"]} + for cid in (1, 2): + case = evals.get(cid, {}) + found = {n for t in [case.get("expected_output", ""), *case.get("assertions", [])] for n in re.findall(r"policy-rev:? (\d+)", t)} + if not found: + bad.append(f"evals/evals.json case {cid} names no policy-rev number") + for n in sorted(found - {rev}): + bad.append(f"evals/evals.json case {cid} says policy-rev {n}, but the block says {rev}") + for port, path, readme, a, b in ( + ("grok", "grok/SKILL.md", "grok/README.md", "", ""), + ("codex", "codex/references/templates.md", "codex/README.md", "", "")): + prev = one(region(lines(path), a, b, path), rf"", f"{path} stackwich-{port}-rev comment inside the block") + said = re.findall(rf"`stackwich-{port}-rev (\d+)`", pathlib.Path(readme).read_text()) + if len(said) != 1: + bad.append(f"{readme}: expected exactly one `stackwich-{port}-rev N` mention, found {len(said)}") + elif prev is not None and said[0] != prev: + bad.append(f"{readme} says stackwich-{port}-rev {said[0]}, but {path} says {prev}") + for msg in bad: + print(f"::error::{msg}") + sys.exit(1 if bad else 0) + PY + echo "revisions OK" + - name: Agent assets present and well-formed run: | A=plugins/stackwich/skills/stackwich/assets From c433e6b4d7c9cf0fca13eaa162f6f2d76dd52f91 Mon Sep 17 00:00:00 2001 From: Abhirup Banerjee <139776126+ovhirup@users.noreply.github.com> Date: Thu, 1 Oct 2026 22:31:59 +0530 Subject: [PATCH 2/2] Anchor the frontmatter policy-rev check under metadata: The revision step matched any indented "policy-rev: N" line anywhere in the SKILL.md frontmatter, so moving it under another mapping still passed. Require exactly one whole-line "metadata:" key in the frontmatter and exactly one " policy-rev: N" among its directly indented lines, with clear errors when either is missing or duplicated. Still stdlib-only. Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/validate.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 0f4df97..b6f751f 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -105,7 +105,12 @@ jobs: s = lines(S) rev = one(region(s, "", "", S), r"", f"{S} policy-rev comment inside the block") fm = s[1:s.index("---", 1)] if s[:1] == ["---"] and "---" in s[1:] else [] - meta = one(fm, r"\s+policy-rev: (\d+)", f"{S} frontmatter metadata.policy-rev") + md = [k for k, x in enumerate(fm) if x == "metadata:"] + if len(md) != 1: + bad.append(f"{S} frontmatter needs exactly one whole-line metadata: key, found {len(md)}"); meta = None + else: + e = next((k for k in range(md[0] + 1, len(fm)) if fm[k].strip() and not fm[k][0].isspace()), len(fm)) + meta = one(fm[md[0] + 1:e], r" policy-rev: (\d+)", f"{S} frontmatter policy-rev directly under metadata") h = "## 4. Verify the install" i = s.index(h) if h in s else len(s) j = next((k for k in range(i + 1, len(s)) if s[k].startswith("## ")), len(s))