Git Commit Guard Hook¶
The git-commit-guard hook prevents commits containing ontology files unless the full encoding workflow has completed with all checkpoints approved.
Overview¶
| Attribute | Value |
|---|---|
| Hook Name | git-commit-guard |
| Script | hooks/scripts/git-commit-guard.py |
| Event | PreToolUse |
| Matcher | Bash |
| Blocking | Yes (when review not approved) |
| Timeout | 5000ms |
Purpose¶
The git commit guard ensures:
- Full Workflow Completion: All checkpoints must be approved before commit
- Review Requirement: Human review is mandatory for ontology changes
- Quality Assurance: Prevents premature commits of unvalidated encodings
- Audit Trail: Commits only after complete approval chain
Configuration¶
In hooks/hooks.json:
{
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/git-commit-guard.py \"$TOOL_INPUT\"",
"timeout": 5000
}
]
}
]
}
Behavior¶
Commit Allowed¶
When review checkpoint is approved:
{
"continue": true,
"message": "Git commit guard: Review approved\n Committing 3 ontology file(s)"
}
Non-Ontology Commit Allowed¶
When no ontology files are staged:
Non-Commit Command Allowed¶
When command is not a git commit:
Blocked: No Active Session¶
When ontology files staged but no session exists:
{
"continue": false,
"message": "BLOCKED: No Active Encoding Session\n\nCannot commit ontology files without approved encoding session.\n\nStaged ontology files:\n • mistaber/ontology/corpus/yd_87/base.lp\n • mistaber/ontology/corpus/yd_87/seif_3.lp\n\nThe encoding workflow requires:\n1. Corpus preparation → approval\n2. HLL encoding → approval\n3. Validation → approval\n4. Review → approval\n5. Then commit\n\nStart with: \"Prepare corpus for YD {siman}:{seif}\""
}
Blocked: Review Not Approved¶
When review checkpoint is not approved:
{
"continue": false,
"message": "BLOCKED: Review Not Approved\n\nCannot commit ontology files without approved review.\n\nStaged ontology files:\n • mistaber/ontology/corpus/yd_87/base.lp\n\nCurrent checkpoint status:\n • corpus-prep: approved\n • hll-encode: approved\n • validate: approved\n • review: pending_review\n\nComplete the remaining checkpoints before committing."
}
Command Detection¶
Git Commit Patterns¶
def is_git_commit_command(command: str) -> bool:
"""Check if command is a git commit."""
patterns = [
r'^git\s+commit\b', # Direct commit
r'&&\s*git\s+commit\b', # Chained after success
r';\s*git\s+commit\b', # Chained unconditionally
]
return any(re.search(pattern, command) for pattern in patterns)
Matched Commands:
| Command | Matched |
|---|---|
git commit -m "msg" |
Yes |
git add . && git commit -m "msg" |
Yes |
git status; git commit -m "msg" |
Yes |
git status |
No |
git push |
No |
echo "git commit" |
No |
Bash Input Parsing¶
def parse_bash_command(tool_input: str) -> str:
"""Extract bash command from tool input."""
try:
data = json.loads(tool_input)
return data.get("command", "")
except json.JSONDecodeError:
return tool_input
Ontology File Detection¶
Staged Files Check¶
def has_ontology_files_staged() -> bool:
"""Check if any ontology .lp files are staged for commit."""
result = subprocess.run(
["git", "diff", "--cached", "--name-only"],
capture_output=True,
text=True,
timeout=5
)
if result.returncode != 0:
return False
staged_files = result.stdout.strip().split('\n')
for file in staged_files:
if file.endswith('.lp') and 'ontology' in file:
return True
return False
Detection Criteria:
| File Path | Detected |
|---|---|
mistaber/ontology/corpus/yd_87/base.lp |
Yes |
mistaber/ontology/worlds/mechaber.lp |
Yes |
tests/test_data/example.lp |
No (not in ontology) |
mistaber/ontology/manifest.yaml |
No (not .lp) |
Get Staged Ontology Files¶
def get_staged_ontology_files() -> list[str]:
"""Get list of staged ontology files."""
result = subprocess.run(
["git", "diff", "--cached", "--name-only"],
capture_output=True,
text=True,
timeout=5
)
if result.returncode != 0:
return []
staged_files = result.stdout.strip().split('\n')
return [f for f in staged_files if f.endswith('.lp') and 'ontology' in f]
Checkpoint Validation¶
Required Checkpoints¶
The hook verifies:
- Session Exists: Active encoding session with
.mistaber-session.yaml - Review Approved: The
reviewcheckpoint hasstatus: approved - Validate Approved: The
validatecheckpoint hasstatus: approved
# Check checkpoint status
checkpoints = session.get("checkpoints", {})
review_status = checkpoints.get("review", {}).get("status", "not_started")
validate_status = checkpoints.get("validate", {}).get("status", "not_started")
if review_status != "approved":
# Block the commit
Checkpoint Status Matrix¶
| review | validate | Result |
|---|---|---|
| approved | approved | Commit allowed |
| approved | not approved | Blocked (validation and review) |
| not approved | approved | Blocked (review) |
| not approved | not approved | Blocked (validation and review) |
Implementation Flow¶
graph TD
A[Bash Command] --> B{Is Git Commit?}
B -->|No| C[Allow - Return]
B -->|Yes| D{Ontology Files Staged?}
D -->|No| E[Allow - Non-Ontology]
D -->|Yes| F{Session Exists?}
F -->|No| G[Block - No Session]
F -->|Yes| H{Review Approved?}
H -->|No| I{Validate Approved?}
I -->|Yes| J[Block - Review Missing]
I -->|No| K[Block - Both Missing]
H -->|Yes| L[Allow - Commit]
Error Messages¶
No Active Session¶
BLOCKED: No Active Encoding Session
Cannot commit ontology files without approved encoding session.
Staged ontology files:
• mistaber/ontology/corpus/yd_87/base.lp
• mistaber/ontology/corpus/yd_87/seif_3.lp
The encoding workflow requires:
1. Corpus preparation → approval
2. HLL encoding → approval
3. Validation → approval
4. Review → approval
5. Then commit
Start with: "Prepare corpus for YD {siman}:{seif}"
Review Not Approved¶
BLOCKED: Review Not Approved
Cannot commit ontology files without approved review.
Staged ontology files:
• mistaber/ontology/corpus/yd_87/base.lp
Current checkpoint status:
• corpus-prep: approved
• hll-encode: approved
• validate: approved
• review: pending_review
Complete the remaining checkpoints before committing.
Validation and Review Missing¶
BLOCKED: Validation And Review Not Approved
Cannot commit ontology files without approved validation and review.
Staged ontology files:
• mistaber/ontology/corpus/yd_87/base.lp
Current checkpoint status:
• corpus-prep: approved
• hll-encode: approved
• validate: not_started
• review: not_started
Complete the remaining checkpoints before committing.
Example Scenarios¶
Scenario 1: Complete Workflow¶
Session State:
current_phase: complete
target_seif: "YD:87:3"
checkpoints:
corpus-prep:
status: approved
hll-encode:
status: approved
validate:
status: approved
review:
status: approved
Command:
Result:
Scenario 2: Incomplete Workflow¶
Session State:
current_phase: validate
target_seif: "YD:87:3"
checkpoints:
corpus-prep:
status: approved
hll-encode:
status: approved
validate:
status: tests_passed
review:
status: not_started
Command:
Result: Blocked with review checkpoint message.
Scenario 3: Non-Ontology Commit¶
Staged Files:
Command:
Result: Allowed (no ontology files).
Scenario 4: Mixed Commit¶
Staged Files:
Session State: Review not approved.
Command:
Result: Blocked (contains ontology files, review not approved).
Debugging¶
Manual Testing¶
# Test non-commit command
echo '{"command": "git status"}' | \
python mistaber-skills/hooks/scripts/git-commit-guard.py | jq .
# Test commit without ontology files staged
git reset HEAD # Unstage all
echo '{"command": "git commit -m test"}' | \
python mistaber-skills/hooks/scripts/git-commit-guard.py | jq .
# Test with ontology files staged
git add mistaber/ontology/corpus/yd_87/base.lp
echo '{"command": "git commit -m test"}' | \
python mistaber-skills/hooks/scripts/git-commit-guard.py | jq .
Check Staged Files¶
# List all staged files
git diff --cached --name-only
# List staged ontology files
git diff --cached --name-only | grep -E '\.lp$' | grep ontology
Check Session State¶
# View checkpoint status
cat .mistaber-session.yaml | grep -A1 "status:"
# Check specific checkpoints
python -c "
import yaml
with open('.mistaber-session.yaml') as f:
s = yaml.safe_load(f)
for cp, data in s.get('checkpoints', {}).items():
print(f'{cp}: {data.get(\"status\", \"not_started\")}')
"
Common Issues¶
False Positive Block¶
Symptom: Commit blocked but workflow is complete.
Causes: - Session file not updated - Review status not set to "approved" - Wrong session file loaded
Solutions:
# Verify session state
cat .mistaber-session.yaml
# Check review status specifically
grep -A2 "review:" .mistaber-session.yaml
Ontology Files Not Detected¶
Symptom: Commit allowed when it should be blocked.
Causes: - Files not properly staged - Path doesn't contain "ontology" - File extension not ".lp"
Solutions:
# Verify staging
git status --short
# Check file paths
git diff --cached --name-only | grep -E '\.lp$'
Git Command Fails¶
Symptom: Hook returns error about git.
Causes: - Not in a git repository - Git not in PATH - Subprocess timeout
Solutions:
Bypass Options¶
Bypass Not Recommended
The commit guard exists to ensure encoding quality. Bypassing is strongly discouraged.
Emergency Manual Override¶
If absolutely necessary:
-
Temporarily approve review:
-
Disable hook temporarily: Comment out in
hooks.json. -
Use
--no-verifyflag:
Risk
Bypassing the commit guard means ontology changes have not been properly reviewed. This can introduce errors into the knowledge base.
Integration with Workflow¶
Commit Skill Integration¶
The commit skill calls git commit after verifying the workflow:
# Commit skill verifies internally, then calls
git add mistaber/ontology/corpus/yd_87/
git commit -m "feat(ontology): encode YD 87:3"
The hook provides a safety net even if the skill is bypassed.
Post-Commit Actions¶
After successful commit, the commit skill:
- Clears session state
- Archives artifacts
- Generates session report
Related Documentation¶
- Hooks Overview - All hooks
- Commit Skill - Commit workflow
- Phase Gate Hook - Checkpoint enforcement
- Review Skill - Review process