Skip to content

feat(#72): add CI typography gate for outward-facing docs - #78

Merged
jsirish merged 2 commits into
mainfrom
claude/ci-typography-check
Sep 1, 2026
Merged

feat(#72): add CI typography gate for outward-facing docs#78
jsirish merged 2 commits into
mainfrom
claude/ci-typography-check

Conversation

@jsirish

@jsirish jsirish commented Sep 1, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds a git grep-based typography check to CI's shell job (Linux leg), mirrored in .local-ci.json: fails the build on em/en-dashes or curly quotes in README.md, docs/*.md, docs/index.html, and the plugin marketplace description.
  • Fixes the one live violation: an em-dash in .claude-plugin/marketplace.json's description.
  • Mechanizes the existing no-em-dash writing-style rule instead of relying on review to catch a regression.

Note: the .local-ci.json entry uses literal Unicode characters in its bracket class rather than \x{...} hex escapes — local-ci's custom-check extraction round-trips each command through jq's @tsv, which escapes embedded backslashes, and the doubled backslash silently breaks the PCRE hex-escape when re-parsed. ci.yml's own step is unaffected (Actions runs it directly) and keeps the \x{...} form to avoid a literal em-dash in the workflow file itself.

Closes #72

Test plan

  • local-ci --strict — all checks pass (186/186 hook test assertions unaffected, typography check passes)
  • sh tests/run.sh — 186/186
  • Live-verified: staged a deliberate em-dash in README.md, confirmed the check fails (both the raw git grep command and through the actual local-ci.sh runner), then reverted
  • Confirmed the fix for the .local-ci.json escaping bug by running the check through the real local-ci.sh custom-check driver, not just testing the shell command by hand

🤖 Generated with Claude Code

https://claude.ai/code/session_019VuUKvqH3q511w8xVd4VFY

jsirish and others added 2 commits September 1, 2026 14:24
Mechanizes the existing no-em-dash writing-style rule so it can't
regress silently: a git grep step in the shell CI job (mirrored in
.local-ci.json) fails the build on em/en-dashes or curly quotes in
README.md, docs/*.md, docs/index.html, and the plugin marketplace
description. Fixed the one live violation, in
.claude-plugin/marketplace.json's description.

The .local-ci.json entry uses literal Unicode characters in the
bracket class rather than \x{...} hex escapes: local-ci's custom-check
extraction pipes each check's "run" field through jq's @TSV, which
escapes embedded backslashes for safe TSV framing, and the downstream
`read -r` + `bash -c` preserves that doubling literally inside the
command's own single-quoted argument - turning \x{2014} into \\x{2014}
and silently breaking the PCRE hex-escape into a bogus literal
character class. Caught by actually running the check through
local-ci.sh (not just testing the command by hand) and comparing the
output against a byte-count sanity check. ci.yml's own step is
unaffected (GitHub Actions runs it directly, no jq round-trip) and
keeps the \x{...} form specifically to avoid pasting a literal
em-dash into the workflow file itself.

Closes #72

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VuUKvqH3q511w8xVd4VFY
…UTF-8 locale)

git grep -P only enables PCRE2's UTF mode under a UTF-8 locale
codeset; \x{2013} exceeds PCRE2's 8-bit max outside one, so under
e.g. LC_ALL=C the pattern fails to COMPILE (rc=128) rather than
finding zero matches (rc=1). The prior `if git grep ...; then FAIL;
fi` treated that compile failure identically to "no match found" and
passed clean - a gate whose entire point is "can't regress silently"
had a silent-pass failure mode of its own.

ci.yml: pins LC_ALL=C.UTF-8 on the invocation and checks the exit
code explicitly (0 = matches found = fail; 1 = clean; anything else =
the check itself broke = fail loud, never silent-pass).

.local-ci.json: same fix, and closes the mirror-image bug the
reviewer also found - the literal-Unicode-character bracket class
(needed there to route around the @TSV double-escaping bug from the
prior commit) degrades to a raw BYTE class outside a UTF-8 locale
under LC_ALL=C, over-matching unrelated multi-byte sequences (verified:
40 false positives on docs/REFERENCE.md's box-drawing tree chars).

Verified live through the actual local-ci.sh custom-check driver, not
just by hand: normal pass, a staged regression still fails correctly,
and the explicit rc-check was exercised directly under a broken locale.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VuUKvqH3q511w8xVd4VFY
@jsirish
jsirish merged commit 77c4262 into main Sep 1, 2026
4 checks passed
@jsirish
jsirish deleted the claude/ci-typography-check branch September 1, 2026 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI: fail on non-ASCII em/en-dashes and curly quotes in tracked text files

1 participant