feat(repository): assert brand SVGs parse as well-formed XML

The two canonical brand SVGs were invalid XML for months and nothing noticed. standards/repository/check.sh asserted they exist and banned a bare year in the copyright line, but never that they parse. There is no xmllint anywhere in scripts/, justfile, or .gitlab-ci.yml.

This is the architectural half of the fix that just landed. That MR repaired the instances; this stops the class recurring.

Why a new primitive rather than a regex

None of the nine existing check primitives can express "this file parses as XML". check_file_contains and check_file_lacks are grep -E over raw text, so the only expressible version is a regex banning the one byte sequence we already know about (-- inside a comment). That refights the last bug and catches none of the next ones: unclosed tags, bad entities, mismatched quoting.

So this adds a tenth primitive, following _lib.sh's own documented process for a vocabulary extension rather than bypassing the whitelist:

check_xml_wellformed(path)
  PASS   xmllint --noout succeeds
  FAIL   file missing or malformed
  SKIP   xmllint absent

The SKIP-on-absent-tool posture matches the three existing primitives that need external tools (check_toml_key, check_json_key, check_gitlab_setting). Added to scripts/guard-checks.sh's PRIMITIVES whitelist; just guard passes with 0 violations across all 22 check.sh files.

Wired into standards/repository/check.sh for avatar.svg, hero.svg and favicon.svg.

Red-then-green, at the primitive level

A check that cannot fail is the defect this estate keeps finding, so this one was proven both directions rather than read:

  • red — sourced _lib.sh against the pre-fix canonical hero.svg and avatar.svg: FAIL on both, PASS on favicon.svg, which was never broken
  • green — same check against the fixed files: PASS on all three
  • integrationjust check-one STANDARD=repository now reports 17 passed, 0 failed, 0 skipped, up from 14. The three new assertions fire rather than skip.

xmllint had to be added to one job, and only one

xmllint is present on macOS via system libxml2 but absent from the CI image. libxml2-utils provides it on alpine:3.24.

Added to the self-conformance job only. That is the job that actually runs just check via check-with-deviations.sh against this repo's own SVGs. The validate job never calls any check.sh, only the validate-* scripts, so it needed no change and adding the package there would have installed something nothing uses.

Also in here

CHANGELOG.md records the primitive. Two pieces of adjacent doc drift found while editing the same list: README.md's check-primitives table was already missing applies_when_file from an earlier addition, and standards/repository/SKILL.md's manual rsvg-convert validation step now notes the automated equivalent.

Flagged, not fixed

_lib_need() in _lib.sh is dead code. It is defined and documented as the tool-presence-check convention, but no primitive calls it; all three that need external tools use inline command -v plus _skip. This predates the change. I followed the working pattern rather than the documented-but-unused one, and left the mismatch alone so this MR stays scoped.

Merge request reports

Loading