[
	{
		"comment": "[rtk] 自动代理高频 bash 命令",
		"tool": "bash",
		"action": "rewrite",
		"pattern": "^(git\\s+(status|log|diff)|cargo\\s+(test|build|clippy)|pytest)\\b",
		"flags": "",
		"reason": "rtk command rewrite：自动加 rtk 前缀压缩输出",
		"enabled": true
	},
	{
		"comment": "[Python] 编辑后必须格式检查 + 跑测试",
		"hook": "tool_result",
		"tool": "edit",
		"action": "notify",
		"conditions": [
			{
				"field": "path",
				"pattern": "\\.py$",
				"flags": ""
			}
		],
		"reason": "编辑了 Python 文件，必须：1) 运行 ruff check <file> 做格式检查；2) 跑覆盖该代码的单元测试（如无测试则先补充），修复所有测试问题确保通过。",
		"enabled": true
	},
	{
		"comment": "[settings] 禁止 bash 写入 settings.json",
		"hook": "tool_result",
		"tool": "write",
		"action": "notify",
		"conditions": [
			{
				"field": "command",
				"pattern": "(>>|>|tee|sed\\s+-i|cp\\s|mv\\s).*settings\\.json|settings\\.json\\s*(>>|>)"
			}
		],
		"reason": "直接编辑 settings.json 曾导致配置丢失（119行变3行）。必须使用 patchSettingsSectionWithBackup 或 settings_rollback。",
		"enabled": true
	},
	{
		"comment": "[Rust] 编辑/写入后必须格式检查 + 跑测试",
		"hook": "tool_result",
		"tool": "edit|write",
		"action": "notify",
		"conditions": [
			{
				"field": "path",
				"pattern": "\\.rs$",
				"flags": ""
			}
		],
		"reason": "编辑了 Rust 文件，必须：1) 运行 cargo clippy 做格式和 lint 检查；2) 跑覆盖该代码的单元测试（如无测试则先补充），修复所有测试问题确保通过。",
		"enabled": true
	},
	{
		"comment": "[TypeScript] 编辑/写入后必须跑测试",
		"hook": "tool_result",
		"tool": "edit|write",
		"action": "notify",
		"conditions": [
			{
				"field": "path",
				"pattern": "\\.ts$",
				"flags": ""
			}
		],
		"reason": "编辑了 TypeScript 文件，必须跑覆盖该代码的单元测试（如无测试则先补充），修复所有测试问题确保通过。",
		"enabled": true
	},
	{
		"comment": "收尾规则 — agent_end 时提醒 commit + 记忆 + 总结，commit 必须带 session ID",
		"hook": "agent_end",
		"action": "notify",
		"check": "has_edits",
		"reason": "⚠️  shepherd: 检测到文件编辑，执行收尾工作：\n1️⃣ **Git commit**：如有未提交的 git 改动 → git add + git commit。**⚠️ commit message 末尾必须加 `session:${PI_SESSION_ID}`** — 这是硬性要求，不是建议。session ID 用于会话分析和 roadmap 追踪，缺少会导致无法追溯。格式示例：`feat: xxx session:019e71c9-b340-7fae-a330-98d837e72099`\n2️⃣ **记忆更新**：如有值得记住的知识 → memory_update\n3️⃣ **会话总结**：简要总结本次会话做了什么",
		"stopReason": [
			"stop"
		],
		"enabled": true
	},
	{
		"comment": "[memory] git commit 后提醒更新记忆",
		"hook": "tool_result",
		"tool": "bash",
		"pattern": "git\\s+commit",
		"action": "steer",
		"reason": "📝 刚执行了 git commit。检查本轮是否有值得跨会话保留的知识（架构决策、踩坑教训、结论），如果有 → 用 memory_update 工具写入。用法：①先调 memory_index 看已有文件，判断重复/合并/新建；②调 memory_update(fileName, content, scope) 一步写入文件+更新索引。fileName 格式：topic--kw1,kw2,kw3.md。scope：L1=跨项目通用，L2=项目级（默认）。单文件不超 200 行。如果没有新知识则忽略。",
		"subagent": false,
		"requireSuccess": true,
		"enabled": true
	},
	{
		"comment": "[arch] enforce-read-over-bash-cat：bash 中 cat|head/tail 读文件时强制用 read 工具",
		"enabled": true,
		"tool": "bash",
		"pattern": "\\bcat\\b.*\\|\\s*(\\bhead\\b|\\btail\\b)",
		"flags": "",
		"action": "notify",
		"reason": "bash cat|head/tail 读文件不如用 read 工具——read 支持 offset/limit 参数精确读取指定行范围，还保留 Tab 字符、自动标准化 CRLF，比管道拼接更可靠。",
		"hook": "tool_call"
	},
	{
		"comment": "[debug] 工具反复出错时提醒翻记忆",
		"hook": "tool_result",
		"action": "steer",
		"state": {
			"countKind": "errors",
			"gte": 5
		},
		"reason": "🔍 **工具反复出错**：连续失败 2 次，翻看 .pi/memory/ 目录下的记忆文件，看是否已有踩坑记录。",
		"enabled": true,
		"subagent": false
	},
	{
		"comment": "[dev] 编辑/写入扩展代码时提醒参考规范",
		"hook": "tool_result",
		"tool": "edit|write",
		"conditions": [
			{
				"field": "path",
				"pattern": "extensions/.*\\.ts$"
			}
		],
		"action": "steer",
		"reason": "📝 编辑/写入了扩展代码。如果尚未阅读扩展开发规范，请先 read 根目录或项目目录下 extensions/README.md；如果已阅读且有新知识，更新到该文件。已阅读且无新知识则无视。",
		"requireSuccess": true,
		"subagent": false,
		"enabled": true
	},
	{
		"comment": "[dev] 编辑/写入扩展代码后提醒跑 typecheck",
		"hook": "tool_result",
		"tool": "edit|write",
		"conditions": [
			{
				"field": "path",
				"pattern": "extensions/.*\\.ts$"
			}
		],
		"action": "steer",
		"reason": "📝 编辑/写入了扩展 TypeScript 代码。请运行 `cd extensions && bash check.sh <扩展名> --typecheck` 确认无类型错误。如果已跑过则无视。",
		"requireSuccess": true,
		"subagent": false,
		"enabled": true
	},
	{
		"comment": "[TS] 禁止空格缩进 — TS 文件必须用 Tab",
		"hook": "tool_call",
		"tool": "edit|write",
		"action": "notify",
		"conditions": [
			{
				"field": "path",
				"pattern": "\\.ts$"
			},
			{
				"field": "text",
				"pattern": "\\n  [\\S ]"
			}
		],
		"reason": "❌ TS 文件要求 Tab 缩进，不是空格。请用 Tab 缩进重写代码。",
		"enabled": true
	},
	{
		"comment": "[Python] 禁止 Tab 缩进 — Python 必须用 4 空格",
		"hook": "tool_call",
		"tool": "edit|write",
		"action": "notify",
		"conditions": [
			{
				"field": "path",
				"pattern": "\\.py$"
			},
			{
				"field": "text",
				"pattern": "\\n\\t"
			}
		],
		"reason": "❌ Python 文件禁止 Tab 缩进，必须用 4 空格（PEP 8）。",
		"enabled": true
	},
	{
		"comment": "[Rust] 禁止 Tab 缩进 — Rust 必须用 4 空格",
		"hook": "tool_call",
		"tool": "edit|write",
		"action": "notify",
		"conditions": [
			{
				"field": "path",
				"pattern": "\\.rs$"
			},
			{
				"field": "text",
				"pattern": "\\n\\t"
			}
		],
		"reason": "❌ Rust 文件禁止 Tab 缩进，必须用 4 空格（rustfmt）。",
		"enabled": true
	},
	{
		"comment": "[code-graph] grep 搜代码符号时推荐用 code-graph",
		"hook": "tool_result",
		"tool": "grep",
		"action": "notify",
		"pattern": ".",
		"flags": "s",
		"reason": "推荐用 code-graph 替代 grep 搜代码——code-graph 理解 AST 语义，能按符号名、调用链、引用关系精准定位，比 grep 逐行匹配快得多且不漏不误报。选工具方法：①模糊搜索 → semantic_code_search（默认首选）；②精确符号名 → get_ast_node；③引用追踪 → find_references；④调用链 → get_call_graph；⑤模块结构 → module_overview。grep 仅适合搜字面量字符串（TODO、配置值、错误消息）。如果当前搜索的就是字面量字符串则忽略此提醒。如果目标目录没有被 code-graph 索引（搜索返回空结果），调用 setup_codegraph({ directory: \"目标目录路径\" }) 一键建索引。",
		"requiresTools": [
			"code_graph_semantic_code_search"
		],
		"enabled": true
	},
	{
		"comment": "[code-graph] bash grep/rg 搜代码文件时推荐用 pi grep 或 code-graph",
		"hook": "tool_result",
		"tool": "bash",
		"action": "notify",
		"pattern": "\\b(grep|rg)\\b.*\\.(py|rs|ts|js|toml)(?=[\\s'\"|)]|$)",
		"flags": "",
		"reason": "💡 bash grep 搜代码文件不如用 pi 内置 grep 工具或 code-graph MCP 工具——code-graph 理解 AST 语义，能精准匹配符号名和调用关系。选工具：①模糊搜索 → semantic_code_search；②精确符号 → get_ast_node；③引用追踪 → find_references；④调用链 → get_call_graph。如果搜的是字面量字符串（TODO、配置值）则忽略。如果目标目录没有被 code-graph 索引，调用 setup_codegraph({ directory: \"目标目录路径\" }) 一键建索引。",
		"enabled": true
	},
	{
		"comment": "[code-graph] 工具报索引错误时提醒重建索引",
		"hook": "tool_result",
		"tool": "grep",
		"action": "notify",
		"conditions": [
			{
				"field": "path",
				"pattern": "\\.(ts|js|py|rs)$"
			}
		],
		"reason": "💡 搜代码文件推荐用 code-graph。如果 code-graph 返回空结果，可能是目标目录没有被索引。调用 setup_codegraph({ directory: \"目标目录路径\" }) 一键建索引（软链接+增量索引，当前会话即刻可搜）。用法参考 code-graph 技能：semantic_code_search（模糊搜索）、get_ast_node（精确符号）、get_call_graph（调用链）、module_overview（模块结构）。",
		"enabled": true
	},
	{
		"comment": "[deps] 编辑/写入 package.json 时提醒依赖合规检查",
		"hook": "tool_result",
		"tool": "edit|write",
		"action": "notify",
		"conditions": [
			{
				"field": "path",
				"pattern": "package\\.json$"
			}
		],
		"reason": "📦 编辑了 package.json 依赖字段。请对照 DEPENDENCY-GUIDE.md 检查合规性：① pi SDK 必须放 peerDependencies + optionalDependencies，禁止放 dependencies/devDependencies；② shared-utils 运行时引用放 dependencies（开发放 devDependencies）；③ 检查 files 白名单是否存在；④ 添加新依赖后运行 scan-deps.sh 验证无嵌套/版本冲突。",
		"enabled": true
	},
	{
		"comment": "[通用] 脚本执行失败时提醒先 --help",
		"hook": "tool_result",
		"tool": "bash",
		"action": "steer",
		"pattern": "(python|uv run python) .+(scripts|tools|bin)/",
		"state": {
			"countKind": "errors",
			"gte": 1
		},
		"reason": "💡 脚本执行失败。在盲目调参重试之前，先运行 `uv run python <脚本路径> --help` 查看用法说明和参数格式，避免反复试错浪费时间。",
		"subagent": false,
		"requireSuccess": false,
		"enabled": true
	},
	{
		"comment": "[roadmap] 禁止直接编辑/写入 roadmap JSON — 必须用 roadmap 工具",
		"hook": "tool_call",
		"tool": "edit|write",
		"action": "block",
		"conditions": [
			{
				"field": "path",
				"pattern": "\\.roadmap\\.json$|\\broadmap/roadmap\\.json$"
			}
		],
		"reason": "⛔ 禁止直接编辑 roadmap JSON！请用 roadmap 工具操作（自动处理时间戳/ID分配/状态级联/归档/doing同步）：\n查看：roadmap_list（列表）、roadmap_show（详情）、roadmap_next（待办）\n创建：roadmap_plan（完整JSON创建/更新）、roadmap_create + roadmap_add_epic/story/task（逐步构建）\n修改：roadmap_update(roadmapId, item_id, {status/title/description/priority}) — 更新单个项\n完成：roadmap_done(roadmapId, taskId) — 标记完成并级联更新\n归档：roadmap_archive(roadmapId) — 归档已完成项\n直接改 JSON 会绕过这些机制导致数据不一致。",
		"enabled": true
	},
	{
		"comment": "[roadmap] 禁止通过 bash/python 脚本直接读写 roadmap JSON — 必须用 roadmap 工具",
		"hook": "tool_call",
		"tool": "bash",
		"action": "block",
		"conditions": [
			{
				"field": "command",
				"pattern": "((roadmap\\.json|\\.roadmap\\.json)[\\s\\S]*(open\\(|json\\.load|json\\.dump|write|sed|awk|jq|cat))|((open\\(|json\\.load|json\\.dump|write|sed|awk|jq|cat)[\\s\\S]*(roadmap\\.json|\\.roadmap\\.json))"
			}
		],
		"reason": "⛔ 禁止通过 bash/python 脚本直接读写 roadmap JSON！请用 roadmap 工具操作（自动处理时间戳/ID分配/状态级联/归档/doing同步）：\n查看：roadmap_list（列表）、roadmap_show（详情）、roadmap_next（待办）\n创建：roadmap_plan（完整JSON创建/更新）、roadmap_create + roadmap_add_epic/story/task（逐步构建）\n修改：roadmap_update(roadmapId, item_id, {status/title/description/priority}) — 更新单个项\n完成：roadmap_done(roadmapId, taskId) — 标记完成并级联更新\n归档：roadmap_archive(roadmapId) — 归档已完成项\n直接碰底层 JSON 会绕过这些机制导致数据不一致。",
		"enabled": true
	},
	{
		"comment": "[settings] 禁止 edit/write settings.json — 必须用 patchSettingsSectionWithBackup",
		"reason": "直接编辑 settings.json 曾导致配置丢失（119 行变 3 行）。必须使用 patchSettingsSectionWithBackup 或 settings_rollback。",
		"tool": "edit|write",
		"hook": "tool_call",
		"action": "block",
		"message": "⛔ 禁止直接 edit settings.json！使用 patchSettingsSectionWithBackup() 安全修改，或 settings_rollback 回滚。",
		"conditions": [
			{
				"field": "path",
				"pattern": "settings\\.json$|settings\\.json\\.bak"
			}
		]
	},
	{
		"action": "block",
		"comment": "[settings] 禁止 bash 直接修改 settings.json — 必须用 patchSettingsSectionWithBackup 或 settings_rollback",
		"conditions": [
			{
				"field": "command",
				"pattern": "^(?!.*\\b(git|grep|find|ls|cat|head|tail|diff|test|python3.*json\\.load)\\b).*settings\\.json",
				"flags": "s"
			}
		],
		"hook": "tool_call",
		"message": "⛔ 禁止通过 bash 修改 settings.json！使用 patchSettingsSectionWithBackup() 安全修改，或 settings_rollback 回滚。",
		"reason": "禁止通过 bash 直接写入 settings.json（如 echo > / sed -i / python 写入），但允许 git 操作（status/diff/reset/checkout/restore/add/rm/log）和只读命令（grep/find/ls/cat/head/tail/diff/test/python3 解析读取）",
		"tool": "bash"
	},
	{
		"comment": "[git] commit 成功后提醒 push",
		"reason": "项目已有远程仓库 origin，commit 后应同步推送避免本地积压",
		"trigger": "bash",
		"event": "tool_result",
		"condition": "bash command contains 'git commit' and exit code is 0",
		"action": "notify",
		"message": "commit 成功。检查是否有远程仓库（git remote），有的话立即 git push 同步到远程。"
	}
]