CR-2026-03-25: Claude Code AsciiDoc Attribute Validation Hook
Change Summary
| Field | Value |
|---|---|
Change ID |
CR-2026-03-25-claude-code-hooks-001 |
Requested By |
Self (PRJ-claude-code-features) |
Target Date |
2026-03-25 |
Systems Affected |
|
Risk Level |
Medium (workflow impact on failure) |
Rollback Time |
< 1 minute (restore backup) |
Change Window |
Any (personal development environment) |
Category |
Normal (follows full process) |
Business Justification
Problem Statement
AsciiDoc files in the domus-* documentation ecosystem use Antora attributes ({attribute-name}) defined in antora.yml. When Claude Code edits .adoc files, undefined attributes cause:
-
Build warnings - Antora logs "skipping reference to missing attribute"
-
Broken rendering - Literal
{attribute-name}appears instead of value -
Delayed detection - Errors found at build time, not edit time
-
Rework cycles - Must stop, identify, fix, rebuild, verify
Root Cause History
| Incident | Impact | Resolution Time |
|---|---|---|
RCA-2026-02-26-001 |
6 missing attributes across 3 files |
45 minutes |
RCA-2026-03-19-001 |
Relative xrefs in nested directories |
30 minutes |
Ad-hoc occurrences |
~2 per week average |
15-30 minutes each |
Benefits (Quantified)
| Benefit | Measurement | Value |
|---|---|---|
Error prevention |
Catch undefined attrs at edit time |
~2 incidents/week × 30 min = 1 hour/week saved |
Reduced context switches |
No need to stop work, debug, rebuild |
Improved focus and flow state |
Documentation quality |
Guaranteed attribute resolution |
Zero broken renders from attrs |
Learning reinforcement |
Immediate feedback on patterns |
Faster antora.yml familiarity |
ROI Estimate: 1 hour/week × 52 weeks = 52 hours/year recovered
Technical Specification
Hook Architecture
Claude Code hooks execute shell commands at defined lifecycle events. This change adds a PostToolUse hook for the Edit tool targeting .adoc files.
Environment Variables
| Variable | Description |
|---|---|
|
JSON string containing tool arguments (includes |
|
Full |
|
Tool that triggered the hook (e.g., "Edit") |
|
Result of tool execution (PostToolUse only) |
Exit Code Semantics
| Code | Meaning | Behavior |
|---|---|---|
|
Success (may include warnings) |
Tool execution proceeds/completes |
|
Script error |
Logged, tool continues |
|
Blocking error (with JSON) |
Tool execution blocked, user sees message |
This hook uses exit 0 for all cases (including warnings) to avoid blocking edits. Warnings are informational, not blocking.
Official Documentation
Anthropic Claude Code Hooks
| Resource | URL |
|---|---|
Hooks User Guide |
|
hooks.json Schema |
|
Best Practices |
|
Example Hooks |
hooks.json Schema Reference
{
"hooks": {
"<HookEvent>": [
{
"matcher": "<tool-name-regex>",
"hooks": [
{
"type": "command",
"command": "<shell-command>",
"timeout": <seconds>
}
]
}
]
}
}
Valid <HookEvent> values:
-
PreToolUse- Before tool execution -
PostToolUse- After tool execution -
SessionStart- When Claude Code session begins -
UserPromptSubmit- When user submits prompt
Risk Analysis
Risk Matrix
| Risk | Description | Probability | Impact | Mitigation |
|---|---|---|---|---|
Hook timeout |
Validation takes >5s, delays edits |
Low |
Low |
5s timeout configured; typical execution <1s |
False positives |
Built-in attrs flagged as undefined |
Medium |
Low |
80+ built-in attrs whitelisted in script |
antora.yml not found |
File outside Antora structure |
Medium |
None |
Graceful skip with debug logging |
Hook script error |
Syntax or logic bug in validator |
Low |
Low |
Exit 0 on error; test suite validates |
Workflow disruption |
Excessive warnings annoying |
Low |
Low |
Warnings are informational only |
Impact Assessment
| Scenario | Impact |
|---|---|
During change |
None - configuration update only |
After change - success |
~1s added to |
After change - failure |
Rollback to backup; <1 minute recovery |
Worst case |
Hook causes Edit operations to hang; kill hook process, restore backup |
Pre-Change Checklist
Prerequisites
-
Backup strategy documented (SessionStart hook creates daily backups)
-
Rollback procedure documented below
-
Validation script created and tested
-
Test suite created with 5 test cases
-
D2 diagram created with animation
-
Current hooks.json captured (Phase 1)
Current State
| Metric | Pre-Change Value |
|---|---|
Total hook events configured |
4 (PreToolUse, PostToolUse, UserPromptSubmit, SessionStart) |
PostToolUse Edit hooks |
1 (shellcheck for .sh files) |
AsciiDoc validation |
None |
Backup location |
|
Implementation Procedure
Phase 1: Capture Current State
# Create timestamped backup
cp ~/.claude/hooks.json ~/.claude/backups/hooks.json.$(date +%Y%m%d-%H%M%S).bak
# Verify backup
ls -la ~/.claude/backups/hooks.json.*.bak | tail -1
# Capture current hook count
jq '.PostToolUse | length' ~/.claude/hooks.json
Expected output: 1 (existing shellcheck hook)
Phase 2: Install Validation Script
The validation script has been pre-created at ~/.claude/hooks/validate-asciidoc-attrs.sh.
# Verify script exists and is executable
ls -la ~/.claude/hooks/validate-asciidoc-attrs.sh
# Run test suite
~/.claude/hooks/test-validate-asciidoc-attrs.sh
Expected: All 5 tests pass
Phase 3: Update hooks.json
Add AsciiDoc attribute validator to existing PostToolUse Edit hooks array.
Before (existing shellcheck only):
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "FILE_PATH=$(echo \"$ARGUMENTS\" | grep -o '\"file_path\":\"[^\"]*\"' | cut -d'\"' -f4); if [ -n \"$FILE_PATH\" ]; then case \"$FILE_PATH\" in *.sh|*.bash|*.zsh) if command -v shellcheck >/dev/null 2>&1; then shellcheck \"$FILE_PATH\" 2>&1 | head -10 || echo \"ShellCheck: no issues\"; else echo \"ShellCheck: not installed\"; fi ;; *) echo \"Validation: skipped (not a shell script)\" ;; esac; fi",
"timeout": 10
}
]
}
]
After (shellcheck + adoc validator):
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "FILE_PATH=$(echo \"$ARGUMENTS\" | grep -o '\"file_path\":\"[^\"]*\"' | cut -d'\"' -f4); if [ -n \"$FILE_PATH\" ]; then case \"$FILE_PATH\" in *.sh|*.bash|*.zsh) if command -v shellcheck >/dev/null 2>&1; then shellcheck \"$FILE_PATH\" 2>&1 | head -10 || echo \"ShellCheck: no issues\"; else echo \"ShellCheck: not installed\"; fi ;; *) echo \"Validation: skipped (not a shell script)\" ;; esac; fi",
"timeout": 10
},
{
"type": "command",
"command": "~/.claude/hooks/validate-asciidoc-attrs.sh",
"timeout": 5
}
]
}
]
Phase 4: Verify Configuration
# Validate JSON syntax
jq . ~/.claude/hooks.json > /dev/null && echo "JSON valid"
# Count PostToolUse Edit hooks
jq '.PostToolUse[0].hooks | length' ~/.claude/hooks.json
Expected: 2 (shellcheck + adoc validator)
Phase 5: Functional Testing
| Test | Action | Expected Result |
|---|---|---|
Test 1 |
Edit a |
No warning displayed |
Test 2 |
Edit a |
"WARNING: Undefined AsciiDoc attributes: {nonexistent-attr}" |
Test 3 |
Edit a |
No validation (skipped) |
Test 4 |
Edit a |
ShellCheck warnings displayed (existing behavior) |
Post-Change Validation
State Comparison
| Metric | Pre-Change | Post-Change |
|---|---|---|
Total hook events |
4 |
4 (unchanged) |
PostToolUse Edit hooks |
1 |
2 |
AsciiDoc validation |
None |
Active |
Edit operation time (typical) |
~100ms |
~1.1s (validation adds ~1s) |
Monitoring Checklist
-
No hook timeout errors in Claude Code output
-
Edit operations complete normally
-
Valid
.adocfiles show no warnings -
Invalid
.adocfiles show appropriate warnings -
ShellCheck still works for
.shfiles
Rollback Procedure
Trigger Conditions
Initiate rollback if ANY of:
-
Hook causes Edit operations to fail or hang
-
False positive rate >50% (valid files flagged)
-
Hook timeout delays workflow significantly
-
Unexpected errors in Claude Code output
Rollback Steps
# 1. List available backups
ls -la ~/.claude/backups/hooks.json.*.bak | tail -5
# 2. Restore most recent backup (replace TIMESTAMP)
cp ~/.claude/backups/hooks.json.YYYYMMDD-HHMMSS.bak ~/.claude/hooks.json
# 3. Verify restoration
jq '.PostToolUse[0].hooks | length' ~/.claude/hooks.json
# Expected: 1
# 4. Restart Claude Code session (exit and re-enter)
Rollback Verification
-
hooks.json restored to previous state
-
PostToolUse Edit hooks = 1
-
Edit operations work without validation
-
No unexpected warnings
Scope Management
In Scope
-
PostToolUse hook for Edit tool on
.adocfiles -
Attribute validation against
antora.yml -
Warning output for undefined attributes
-
Built-in attribute whitelist
Out of Scope (Future CRs)
-
xref validation (requires parsing, different approach)
-
Real-time antora.yml caching
-
Integration with Antora build process
-
MCP server for attribute lookup
Amendment Process
If scope changes are required during implementation:
-
Document the proposed change in this CR under "Amendments" section
-
Assess impact on timeline, risk, and benefits
-
Approve minor changes (self-approval for low-risk)
-
Escalate major changes to new CR
Amendments
No amendments at this time.
Sign-Off
| Role | Name | Date |
|---|---|---|
Author |
Evan Rosado |
2026-03-25 |
Technical Review |
Claude (AI) |
2026-03-25 |
Approval |
Evan Rosado |
2026-03-25 |
Lessons Learned
To be completed post-implementation.
Questions to Answer
-
Did the hook catch any real issues during normal workflow?
-
Was the 5s timeout sufficient?
-
Any unexpected false positives?
-
Should this approach extend to other validation types?
Appendix A: Validation Script
Full source: ~/.claude/hooks/validate-asciidoc-attrs.sh
| Feature | Implementation |
|---|---|
File type check |
|
Attribute extraction |
|
antora.yml discovery |
Walk up directory tree, fallback to git root |
Built-in whitelist |
80+ standard AsciiDoc attributes |
Output |
WARNING message with attribute list |
Appendix B: Test Suite
Full source: ~/.claude/hooks/test-validate-asciidoc-attrs.sh
| Test Case | Input | Expected |
|---|---|---|
Non-.adoc file |
|
Skip (PASS) |
Valid attributes |
File with |
No warning (PASS) |
Invalid attributes |
File with |
WARNING displayed (PASS) |
No attributes |
Plain .adoc file |
No warning (PASS) |
Built-in attributes |
File with |
No warning (PASS) |
Related Documentation
-
PRJ-claude-code-features - Parent project
-
RCA-2026-02-26 - Missing attributes incident