60 lines
2.5 KiB
Python
60 lines
2.5 KiB
Python
|
|
"""PreToolUse hook on matcher 'Edit|Write|MultiEdit': if no Skill was
|
||
|
|
invoked yet in this session, inject an additionalContext reminder.
|
||
|
|
Silent on failure. Never blocks (no permissionDecision). Reminder text
|
||
|
|
has two variants - one for CLAUDE.md edits, one for other files."""
|
||
|
|
import json
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
import tempfile
|
||
|
|
|
||
|
|
|
||
|
|
REMINDER_CLAUDE_MD = (
|
||
|
|
"REMINDER (skill-discipline hook): Edit/Write по CLAUDE.md без вызова Skill в этой сессии. "
|
||
|
|
"Правки CLAUDE.md обязаны идти через `claude-md-management` skill (CLAUDE.md §5 п.10): "
|
||
|
|
"/claude-md-management:claude-md-improver для structural/audit правок или "
|
||
|
|
"/claude-md-management:revise-claude-md для capture session learnings. "
|
||
|
|
"Прямой Edit по CLAUDE.md — нарушение даже на тривиальных правках. "
|
||
|
|
"Если правишь не CLAUDE.md, а .md файл с похожим именем — игнорируй reminder."
|
||
|
|
)
|
||
|
|
|
||
|
|
REMINDER_GENERAL = (
|
||
|
|
"REMINDER (skill-discipline hook): Edit/Write вызван без предшествующего Skill в этой сессии. "
|
||
|
|
"Если задача попадает под Pravila §12.2 — TDD/debug/brainstorm/plan/verify-before-completion/code-review/parallel-agents/worktree/finishing-branch/subagent/writing-skills "
|
||
|
|
"— инвокируй соответствующий superpowers skill через Skill tool ПЕРЕД продолжением. "
|
||
|
|
"Если задача — Q&A/чтение/навигация/мета-вопрос/тривиальная правка вне §12.2 — игнорируй reminder и продолжай."
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> None:
|
||
|
|
try:
|
||
|
|
data = json.load(sys.stdin)
|
||
|
|
except Exception:
|
||
|
|
return
|
||
|
|
|
||
|
|
sid = data.get("session_id") or "unknown"
|
||
|
|
flag = os.path.join(tempfile.gettempdir(), f"claude-skill-{sid}.flag")
|
||
|
|
|
||
|
|
if os.path.exists(flag):
|
||
|
|
return
|
||
|
|
|
||
|
|
tool_input = data.get("tool_input") or {}
|
||
|
|
file_path = (tool_input.get("file_path") or "").replace("\\", "/")
|
||
|
|
is_claude_md = file_path.endswith("/CLAUDE.md") or file_path == "CLAUDE.md"
|
||
|
|
|
||
|
|
msg = REMINDER_CLAUDE_MD if is_claude_md else REMINDER_GENERAL
|
||
|
|
|
||
|
|
out = {
|
||
|
|
"hookSpecificOutput": {
|
||
|
|
"hookEventName": "PreToolUse",
|
||
|
|
"additionalContext": msg,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
try:
|
||
|
|
sys.stdout.write(json.dumps(out, ensure_ascii=True))
|
||
|
|
except Exception:
|
||
|
|
return
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|