Skip to content

fix(tests): guard validate-content.sh git tag call against non-git env (#233)#234

Merged
pitimon merged 1 commit into
mainfrom
fix/233-validate-content-no-git-guard
May 24, 2026
Merged

fix(tests): guard validate-content.sh git tag call against non-git env (#233)#234
pitimon merged 1 commit into
mainfrom
fix/233-validate-content-no-git-guard

Conversation

@pitimon
Copy link
Copy Markdown
Owner

@pitimon pitimon commented May 24, 2026

Summary

One-line guard fix at tests/validate-content.sh:654. Adds || echo "" after the sort -V so the git tag -l exit 128 in non-git environments can't propagate through pipefail and abort the script before the intended WARN-and-skip fallback at lines 655-656.

Closes #233.

Root cause (verbatim from issue)

set -euo pipefail + command substitution + git tag -l exit 128 + pipefail = script aborts at the assignment, before the if [ -z "$all_tags" ] fallback can fire. 2>/dev/null suppresses stderr but not the exit code.

Defense-in-depth scan (H1)

Grepped both validators for git command-substitutions:

File:line Status
tests/validate-structure.sh:797 git describe --tags --abbrev=0 ... || echo "" ✓ guarded
tests/validate-structure.sh:803 git diff --name-only ... || echo "" ✓ guarded
tests/validate-content.sh:654 git tag -l ... | sort -V ✗ unguarded — this PR

Line 654 was the only unguarded git command-substitution across both validators. The issue author's claim ("the only git call missing that \|\| echo "" guard") verified independently.

Verification

Reproduce (pre-fix)cp -R full repo tree to non-git temp dir, then:

$ bash tests/validate-content.sh > out.log 2>&1; echo "exit=$?"
exit=128
$ grep "=== Summary ===" out.log
(no match — script aborted)

Post-fix, same non-git tree:

$ bash tests/validate-content.sh > out.log 2>&1; echo "exit=$?"
exit=0
$ grep -A4 "=== Summary ===" out.log
=== Summary ===
PASS: 267
FAIL: 0
WARN: 2     # 1 pre-existing + 1 new "git tag history unavailable"

In-repo (tagged checkout, regression check):

  • tests/validate-content.sh → 269 PASS / 0 FAIL / 1 WARN (unchanged from v2.18.3)
  • tests/validate-structure.sh → 358 PASS / 0 FAIL (unchanged)

Doctrine

tests/** is contributor-doctrine per ADR-019 line 88 — no version bump, no CHANGELOG, no SKILL-EFFECTIVENESS update. Check 27 confirms.

The fix is consumer-affecting in practice (consumers running the shipped self-test see exit 128 instead of a clean WARN). The ADR-019 classification is unchanged — the path stays contributor-doctrine because the script is shipped for verification, not runtime, and the WARN message is unambiguous. If this becomes a recurring "tests/** affects consumers" pattern, a future ADR can refine the classification.

Secondary note (LOW / by-design)

The issue raised a secondary question about guides/anthropic-engineering-doctrine-audit.md citing 3 maintainer-local ~/.claude/lessons/... paths. This is by-design — the guide self-describes as a "defensive citation surface" for contributors/maintainers, and the lessons it cites are reflection artifacts that don't ship with the plugin. Each contributor's own ~/.claude/lessons/ accumulates via /reflect. No code change needed; addressed in the issue comment.

Test plan

  • Reproduce exit=128 pre-fix in non-git temp dir
  • Confirm exit=0 + Summary block post-fix in same non-git tree
  • Confirm in-repo behavior unchanged (269 PASS / 0 FAIL / 1 WARN)
  • tests/validate-structure.sh unchanged (358 PASS / 0 FAIL)
  • Grep both validators for any other unguarded git calls — none found
  • CI green

#233)

`tests/validate-content.sh:654` calls `git tag -l "v2.*"` inside a command
substitution. Under `set -euo pipefail`, when run outside a git checkout
the call exits 128; `2>/dev/null` suppresses stderr but not the exit code,
and pipefail propagates it through the pipeline. The assignment then
carries that status and errexit aborts the script — before the intended
fallback at line 655-656 can run.

The sibling `tests/validate-structure.sh` already guards every git
command-substitution with `|| echo ""` (lines 797, 803). validate-content.sh
line 654 was the only unguarded call across both validators.

Reproduce: non-git tree, exit 128, no `=== Summary ===` block printed.
With guard: exit 0, "git tag history unavailable" WARN fires, sub-checks E+F
skip cleanly, summary reports `PASS: 267 / FAIL: 0 / WARN: 2 / ALL CHECKS PASSED`.

In-repo behavior unchanged: 269 PASS / 0 FAIL / 1 WARN.

Tier per ADR-019 line 88: `tests/**` is contributor-doctrine — no version
bump, no CHANGELOG entry.

Closes #233
@pitimon pitimon merged commit d0fea70 into main May 24, 2026
1 check passed
@pitimon pitimon deleted the fix/233-validate-content-no-git-guard branch May 24, 2026 13:51
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.

validate-content.sh aborts (exit 128, no Summary) outside a tagged git checkout — missing || echo "" guard on git-tag call (v2.18.3)

1 participant