Phase Gate Hook¶
The phase-gate hook prevents out-of-order writes to ontology files by verifying the appropriate checkpoint has been approved before allowing file modifications.
Overview¶
| Attribute | Value |
|---|---|
| Hook Name | phase-gate |
| Script | hooks/scripts/phase-gate.py |
| Event | PreToolUse |
| Matcher | Write|Edit |
| Blocking | Yes (when checkpoint not approved) |
| Timeout | 5000ms |
Purpose¶
The phase gate hook ensures:
- Workflow Order: Encoding cannot proceed without corpus approval
- Session Tracking: Active session must exist before writing ontology files
- Checkpoint Enforcement: Each phase requires explicit human approval
Configuration¶
In hooks/hooks.json:
{
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "python ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/phase-gate.py \"$TOOL_INPUT\"",
"timeout": 5000
}
]
}
]
}
Behavior¶
Allowed Operations¶
The hook allows writes when:
- File is NOT an ontology
.lpfile - File is an ontology file AND required checkpoint is approved
Blocked: No Active Session¶
When no .mistaber-session.yaml exists:
{
"continue": false,
"message": "BLOCKED: No Active Encoding Session\n\nCannot write to ontology file: mistaber/ontology/corpus/yd_87/base.lp\n\nYou must start an encoding session first:\n1. Invoke the corpus-prep skill\n2. Complete corpus preparation\n3. Get human approval at checkpoint\n\nStart with: \"Prepare corpus for YD {siman}:{seif}\""
}
Blocked: Checkpoint Not Approved¶
When required checkpoint is not approved:
{
"continue": false,
"message": "BLOCKED: Checkpoint Not Approved\n\nCannot write to: mistaber/ontology/corpus/yd_87/seif_3.lp\n\nRequired checkpoint: corpus-prep\nCurrent status: pending_review\n\nThe encoding workflow requires human approval at each checkpoint.\nComplete the corpus-prep phase and get approval before proceeding."
}
File Pattern Detection¶
Ontology File Detection¶
def is_ontology_file(file_path: str) -> bool:
"""Check if file is an ontology .lp file."""
path = Path(file_path)
return (
path.suffix == ".lp" and
"ontology" in str(path) and
"corpus" in str(path)
)
Matches:
- mistaber/ontology/corpus/yd_87/base.lp
- mistaber/ontology/corpus/yd_88/seif_1.lp
Does NOT Match:
- mistaber/ontology/worlds/mechaber.lp (worlds, not corpus)
- tests/test_data/example.lp (not in ontology)
- mistaber/ontology/corpus/manifest.yaml (not .lp)
Seif File Detection¶
def is_seif_file(file_path: str) -> bool:
"""Check if file is a seif encoding file."""
path = Path(file_path)
return (
path.suffix == ".lp" and
"seif_" in path.name
)
Checkpoint Requirements¶
Checkpoint Mapping¶
def get_required_checkpoint(file_path: str) -> str | None:
"""Determine which checkpoint must be approved to write this file."""
if is_seif_file(file_path):
return "corpus-prep" # Must have corpus-prep approved
return None
Phase-to-Checkpoint Table¶
| File Pattern | Required Checkpoint |
|---|---|
corpus/*/seif_*.lp |
corpus-prep |
corpus/*/base.lp |
corpus-prep |
| Other .lp files | None (allowed) |
Implementation Details¶
Input Parsing¶
def parse_tool_input(tool_input: str) -> dict:
"""Parse tool input to extract file path."""
try:
data = json.loads(tool_input)
return data
except json.JSONDecodeError:
# Try to extract file_path from string representation
match = re.search(r'file_path["\s:]+([^\s"]+)', tool_input)
if match:
return {"file_path": match.group(1)}
return {}
Session State Check¶
def main():
tool_input = sys.argv[1] if len(sys.argv) > 1 else "{}"
data = parse_tool_input(tool_input)
file_path = data.get("file_path", "")
# Only check ontology .lp files
if not is_ontology_file(file_path):
return allow()
# Check required checkpoint
required_checkpoint = get_required_checkpoint(file_path)
if required_checkpoint is None:
return allow()
# Load session state
session = load_session_state()
if session is None:
return block_no_session(file_path)
# Check checkpoint status
checkpoints = session.get("checkpoints", {})
checkpoint_data = checkpoints.get(required_checkpoint, {})
status = checkpoint_data.get("status", "not_started")
if status != "approved":
return block_checkpoint_not_approved(file_path, required_checkpoint, status)
# Checkpoint approved - allow the write
return allow_with_message(f"Phase gate: {required_checkpoint} approved")
Session State Format¶
The hook reads checkpoint status from .mistaber-session.yaml:
checkpoints:
corpus-prep:
status: approved # Required for ontology writes
approved_by: human
timestamp: 2026-01-25T10:30:00Z
hll-encode:
status: pending_review
validate:
status: not_started
review:
status: not_started
Status Values¶
| Status | Can Write? | Description |
|---|---|---|
approved |
Yes | Checkpoint passed |
pending_review |
No | Awaiting approval |
not_started |
No | Phase not begun |
in_progress |
No | Phase executing |
Error Messages¶
No Session¶
BLOCKED: No Active Encoding Session
Cannot write to ontology file: {file_path}
You must start an encoding session first:
1. Invoke the corpus-prep skill
2. Complete corpus preparation
3. Get human approval at checkpoint
Start with: "Prepare corpus for YD {siman}:{seif}"
Checkpoint Not Approved¶
BLOCKED: Checkpoint Not Approved
Cannot write to: {file_path}
Required checkpoint: {checkpoint}
Current status: {status}
The encoding workflow requires human approval at each checkpoint.
Complete the {checkpoint} phase and get approval before proceeding.
Workflow Enforcement¶
Enforced Order¶
graph LR
A[Start] -->|No writes allowed| B[corpus-prep]
B -->|Checkpoint 1| C{Approved?}
C -->|No| B
C -->|Yes| D[Ontology writes allowed]
D --> E[hll-encode]
What Gets Blocked¶
| Attempt | Result |
|---|---|
| Write seif file without session | BLOCKED |
| Write seif file with pending_review | BLOCKED |
| Write seif file with approved | ALLOWED |
| Write non-ontology file | ALLOWED |
| Edit existing ontology file | Uses same rules |
Bypass Options¶
Bypass Not Recommended
The phase gate exists to ensure encoding quality. Bypassing is strongly discouraged.
Emergency Manual Override¶
If absolutely necessary, temporarily edit the session state:
Or temporarily disable the hook in hooks.json.
Debugging¶
Manual Testing¶
# Test with non-ontology file
echo '{"file_path": "test.py"}' | \
python mistaber-skills/hooks/scripts/phase-gate.py | jq .
# Test with ontology file (no session)
rm -f .mistaber-session.yaml
echo '{"file_path": "mistaber/ontology/corpus/yd_87/seif_1.lp"}' | \
python mistaber-skills/hooks/scripts/phase-gate.py | jq .
# Test with approved checkpoint
cat > .mistaber-session.yaml << 'EOF'
checkpoints:
corpus-prep:
status: approved
EOF
echo '{"file_path": "mistaber/ontology/corpus/yd_87/seif_1.lp"}' | \
python mistaber-skills/hooks/scripts/phase-gate.py | jq .
Common Issues¶
False Positive Blocks¶
Symptom: Legitimate write blocked.
Causes: - Session file corrupted - Wrong working directory - Checkpoint status not updated
Solutions:
File Pattern Not Matching¶
Symptom: Ontology file not detected.
Causes: - Different path structure - Missing "ontology" or "corpus" in path
Solutions: Check file path matches expected pattern:
Related Documentation¶
- Hooks Overview - All hooks
- Encoding Guard - HLL validation
- Git Commit Guard - Commit enforcement
- Session Init - Session state loading