mirror of
https://github.com/AgriciDaniel/claude-blog.git
synced 2026-09-19 03:32:21 +08:00
a330e1fc2c
Seventh-round hostile audit caught 18 file:line defects, including 4 HIGH- severity items. The most damning: install.sh / install.ps1 never copied the v1.8.0+ helpers (cognitive_load, discourse_research, load_untrusted_root, lint_prose, sync_flow). The "code-enforced" nonce defense announced in v1.8.3+ was structurally non-functional for any user installing via marketplace or curl-pipe. v1.8.6 closes this and adds an installer-sync regression test so the class of bug cannot recur silently. Honest framing: calibrated reachable ceiling is ~96/100. 100/100 is structurally unreachable per the asymptote analysis. Each round catches less; the score plateaus. v1.8.6 reaches the upper bound of what audit- driven hardening produces without architectural changes. HIGH findings closed - 7TH-AUDIT-001 install.sh/install.ps1 copy ALL scripts/*.py to ~/.claude/scripts/; uninstall.sh/uninstall.ps1 remove them - 7TH-AUDIT-002 docs/INSTALLATION.md rewritten from v1.7.0 baseline, enumerates all 29 sub-skills with introducing version - 7TH-AUDIT-003 10 stale sub-skill SKILL.md versions bumped to 1.8.6; test_version_coherence extended to cover every skills/*/SKILL.md - 7TH-AUDIT-004 install.sh + install.ps1 summary counts corrected (28->30 sub-skills, 27->29 user-invokable, 14->20 references) MEDIUM findings closed - 7TH-AUDIT-005 SUPPORT.md "12 commands" -> "29 user-facing commands" - 7TH-AUDIT-006 install.sh Python warning "3.12+" -> "3.11+" - 7TH-AUDIT-007 README dual test counts (103+, 124+) -> 130+ - 7TH-AUDIT-011 _read_citation_version strips YAML quotes - 7TH-AUDIT-012 CI version-coherence heredoc replaced with pytest call - 7TH-AUDIT-014 SKILL.md helper-path resolution checks installed location first, dev clone second, errors if neither resolves LOW findings closed - 7TH-AUDIT-013 lint_prose 4-backtick fence handling: closing fence must be >= opening length per CommonMark - 7TH-AUDIT-016 CONTRIBUTORS.md v1.8.1-v1.8.6 hostile-audit section - 7TH-AUDIT-017 pyproject.toml [project.urls] added Infrastructure - tests/test_installer_sync.py (new, 4 tests): asserts every scripts/*.py is shipped by install.sh + install.ps1 and removed by uninstall.sh + uninstall.ps1. - test_version_coherence extended: covers all 30 SKILL.md files. Tests - 136 pass + 0 skips (v1.8.5 was 130 + 0 skips). 6 new tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
118 lines
4.2 KiB
Python
118 lines
4.2 KiB
Python
"""Version-coherence regression test.
|
|
|
|
Asserts that the project version is the same string across all four
|
|
canonical surfaces: pyproject.toml, plugin.json, CITATION.cff, and the
|
|
orchestrator skills/blog/SKILL.md frontmatter.
|
|
|
|
Added v1.8.5 (6TH-AUDIT-010): the v1.8.4 release added the same check
|
|
as a CI YAML heredoc. Moving the check into pytest gives local devs the
|
|
same signal CI produces, so `pytest` before push catches the drift.
|
|
|
|
Stdlib + pytest only.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import re
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
def _read_pyproject_version() -> str | None:
|
|
text = (ROOT / "pyproject.toml").read_text(encoding="utf-8")
|
|
m = re.search(r'^version\s*=\s*"([^"]+)"', text, re.MULTILINE)
|
|
return m.group(1) if m else None
|
|
|
|
|
|
def _read_plugin_version() -> str | None:
|
|
with open(ROOT / ".claude-plugin" / "plugin.json", encoding="utf-8") as f:
|
|
return json.load(f).get("version")
|
|
|
|
|
|
def _read_citation_version() -> str | None:
|
|
"""Strip optional YAML single/double quotes (v1.8.6: 7TH-AUDIT-011)."""
|
|
text = (ROOT / "CITATION.cff").read_text(encoding="utf-8")
|
|
m = re.search(r'^version:\s*[\'"]?([0-9][^\'"\s]+)[\'"]?', text, re.MULTILINE)
|
|
return m.group(1) if m else None
|
|
|
|
|
|
def _read_skill_md_version() -> str | None:
|
|
text = (ROOT / "skills" / "blog" / "SKILL.md").read_text(encoding="utf-8")
|
|
m = re.search(r'^\s*version:\s*"?([^"\s]+)"?', text, re.MULTILINE)
|
|
return m.group(1) if m else None
|
|
|
|
|
|
def test_all_version_surfaces_aligned() -> None:
|
|
"""The same version string must appear in pyproject.toml,
|
|
plugin.json, CITATION.cff, and skills/blog/SKILL.md metadata.
|
|
|
|
v1.8.4 (5TH-AUDIT-001) found skills/blog/SKILL.md frozen at "1.8.0"
|
|
while every other surface had moved through 1.8.1, 1.8.2, 1.8.3.
|
|
This test prevents that recurring.
|
|
"""
|
|
versions = {
|
|
"pyproject.toml": _read_pyproject_version(),
|
|
".claude-plugin/plugin.json": _read_plugin_version(),
|
|
"CITATION.cff": _read_citation_version(),
|
|
"skills/blog/SKILL.md": _read_skill_md_version(),
|
|
}
|
|
# None should be missing.
|
|
missing = [k for k, v in versions.items() if v is None]
|
|
assert not missing, f"version field could not be extracted from: {missing}"
|
|
unique = set(versions.values())
|
|
assert len(unique) == 1, (
|
|
f"version surfaces disagree:\n"
|
|
+ "\n".join(f" {k}: {v!r}" for k, v in versions.items())
|
|
)
|
|
|
|
|
|
def test_version_string_matches_semver_pattern() -> None:
|
|
"""The shared version must be valid semver (X.Y.Z optional pre-release)."""
|
|
version = _read_pyproject_version()
|
|
assert version is not None
|
|
assert re.match(r"^\d+\.\d+\.\d+(-\S+)?$", version), (
|
|
f"version {version!r} does not match semver pattern X.Y.Z[-pre]"
|
|
)
|
|
|
|
|
|
def test_all_sub_skill_versions_match_project_version() -> None:
|
|
"""v1.8.6 (7TH-AUDIT-003): every skills/*/SKILL.md `version:` field
|
|
must equal the project version. Pre-v1.8.6, 10 sub-skill SKILL.md
|
|
files had stale per-skill versions (1.0.0, 1.4.0, 1.7.0) that were
|
|
never bumped through the v1.8.x cycle. The version-coherence test
|
|
only covered the orchestrator, missing all 10 sub-skill surfaces.
|
|
"""
|
|
target = _read_pyproject_version()
|
|
assert target is not None
|
|
skill_md_files = sorted((ROOT / "skills").glob("*/SKILL.md"))
|
|
assert len(skill_md_files) >= 30, (
|
|
f"unexpectedly few SKILL.md files: {len(skill_md_files)}"
|
|
)
|
|
mismatches = []
|
|
for f in skill_md_files:
|
|
text = f.read_text(encoding="utf-8")
|
|
# Match the YAML frontmatter version field; tolerate quote styles.
|
|
m = re.search(
|
|
r'^\s+version:\s*[\'"]?([0-9][^\'"\s]+)[\'"]?',
|
|
text, re.MULTILINE,
|
|
)
|
|
if m is None:
|
|
# Some SKILL.md files may not declare metadata.version at all;
|
|
# that is acceptable. We only flag drift, not absence.
|
|
continue
|
|
if m.group(1) != target:
|
|
mismatches.append((f.relative_to(ROOT), m.group(1)))
|
|
assert not mismatches, (
|
|
f"sub-skill SKILL.md versions disagree with pyproject.toml "
|
|
f"({target}):\n"
|
|
+ "\n".join(f" {p}: {v}" for p, v in mismatches)
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|