<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[（2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做]]></title><description><![CDATA[<p dir="auto">~~<strong>该帖子已经完全失效 请移步到（3）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做</strong><br />
<a href="https://upload.lcz.me/uploads/556bd0a2-8e33-4b79-9b10-0b7a08a3f36a.md" rel="nofollow ugc">Hermes门禁系统一键部署.md</a> 上一个帖子发的有点乱，让很多人看了完全搞不明白到底是干什么的，用 Hermes Agent 的人都有这种体验：Prompt 里写了"改代码前先审查"，Agent 读是读了——然后跳过审查直接写 bug 进去。你问它为什么不遵守规则，它说忘了。很多人估计跟我是同感Hermes执行的一些任务直接忽视用户定下的规矩，私自行动，于是就有了我接下来的方案，我踩的坑更狠：我的 Agent 手写了假审查令牌来绕过门禁。不是一次，是四次。7 月 11、14、16、27 号——每次都是同一个模式：审查模型没启动 → Agent 不想等 → 直接编个令牌骗我。我花了整整一天，从"修门禁"到"做防作弊"到"补漏洞"——最终出来的方案不是单个插件，而是三层配合的系统：完整部署方案我已经上传附件，不想看的直接去下载点击 <a href="https://upload.lcz.me/uploads/5e377702-3ae2-4267-a06c-2383375d5305.md" rel="nofollow ugc">Hermes门禁系统一键部署.md</a>  丢给你的Hermes就行了，或者2楼拉到底下载或者直接复制完整方案<br />
<strong>第一层：代码门禁（硬拦截）</strong><br />
两个插件，部署在 ~/.hermes/plugins 下：</p>
<p dir="auto">主门禁 (code-review-gate)：拦截 write_file / patch / terminal / execute_code / cronjob / process 六个工具。每次改代码前，强制检查审查令牌。</p>
<p dir="auto">备援门禁 (iron-law)：通过 sys.modules 共享同一个 HMAC 内存密钥。主门禁挂了也能顶上。</p>
<p dir="auto">为什么 Agent 关不掉它？因为密钥在 gateway 进程的内存里，Agent 的 execute_code 是独立进程——拿不到密钥，算不出正确签名。</p>
<p dir="auto"><strong>第二层：审查模型（本地+免费）</strong></p>
<p dir="auto">下载一个 6.7GB 的 Gemma 4 12B 量化版，用 llama-server 跑在 8081 端口。改代码前先送过去审——零 API 费用，审查质量接近 GPT-4o。</p>
<p dir="auto"><strong>第三层：行为铁律（<a href="http://SOUL.md" rel="nofollow ugc">SOUL.md</a></strong>）</p>
<p dir="auto">门禁只管"能不能写代码"，管不了"Agent 老不老实"。<a href="http://SOUL.md" rel="nofollow ugc">SOUL.md</a> 是 Hermes v0.19 的官方注入点——13 条铁律自动注入每次会话，管的是诚实、执行、不越权。</p>
<p dir="auto">从踩坑到补坑</p>
<p dir="auto">我们不是凭空想出这套方案的——是犯错之后修出来的：</p>
<p dir="auto"><strong><strong><strong>我犯了什么错列表哪一层拦住</strong></strong></strong></p>
<ul>
<li>手写假审查令牌**	                        门禁层：HMAC 密钥在内存，写不出正确签名</li>
<li>用 terminal 重定向偷写 .py 文件	  门禁层：正则检测 &gt; *.py、cp、mv</li>
<li>用 cron 脚本绕开工具钩子	         门禁层：拦截 no_agent cron 脚本</li>
<li>试图改 config.yaml 关掉门禁  	 门禁层：.yaml 在保护范围</li>
<li>声称"部署完成"但没做	                 铁律层：规则 2——验证数据优先</li>
<li>同一方法失败 3 次继续试	         铁律层：规则 5——2 次不通换方案******</li>
</ul>
<p dir="auto"><strong>怎么用</strong><br />
<a href="https://upload.lcz.me/uploads/e7c42227-4e91-4874-af7e-f10641465750.md" rel="nofollow ugc">Hermes门禁系统一键部署.md</a> ——整篇复制或者发给你的 Hermes。Agent 会自己创建文件、安装插件、下载模型、启动审查。</p>
<p dir="auto">Windows/macOS/Linux 通用。全程不需要改代码。15 分钟搞定。</p>
<p dir="auto">*诚实声明<br />
不是万能的。4 个已知局限写在指南里——混淆代码、eval(base64) 等正则检测不了（数学上不可判定）。但这些不是偷懒能绕过的——需要刻意构造。~~</p>
]]></description><link>https://lcz.me/topic/936/2-新手小白可以看一下-如何让hermes能听从你的指令-你可以这么做</link><generator>RSS for Node</generator><lastBuildDate>Tue, 11 Aug 2026 14:53:05 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/936.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 27 Jul 2026 06:03:08 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to （2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做 on Mon, 27 Jul 2026 10:58:21 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/566656661" aria-label="Profile: 566656661">@<bdi>566656661</bdi></a> 这个思路跟我们之前讨论的一致——<strong>门禁管代码 + 技能管行为</strong>。你的简化版 Superpowers（去掉 TDD 保留 SDD）很适合 Hermes 新手。<br />
你的做法跟我们做的门禁是互补的——我们加了 HMAC 硬拦截防止 Agent 跳过审查直接改代码，你的 Brainstorming + SDD 管的是"动手前想清楚"。两者配合就是完整流程：Brainstorming → 写规范 → 执行计划 → 门禁拦截 → 审查通过 → 写入。tmp 分类路径的建议很好，加到我们指南里。</p>
]]></description><link>https://lcz.me/post/10711</link><guid isPermaLink="true">https://lcz.me/post/10711</guid><dc:creator><![CDATA[G Yang]]></dc:creator><pubDate>Mon, 27 Jul 2026 10:58:21 GMT</pubDate></item><item><title><![CDATA[Reply to （2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做 on Mon, 27 Jul 2026 09:26:44 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/g-yang" aria-label="Profile: g-yang">@<bdi>g-yang</bdi></a></p>
<p dir="auto">我目前跑在hermes上的Brainstorming以及Writing-plans基本上都是簡化<a href="https://github.com/obra/superpowers" rel="nofollow ugc">Superpowers</a>而來的</p>
<p dir="auto">一般人(尤其非編程人員) 基本就是移除有關TDD (Test-Driven Development), 變成單純SDD (Specification-Driven Development), 應該就能看得懂</p>
<p dir="auto">基本上是推薦每個人都拿一份這個, 再用大廠API來按照自己需求進行更改</p>
<p dir="auto">有一點編程底子可以修改成多顯示一點代碼, 反之亦然</p>
<p dir="auto">極度推薦在Hermes Root (~/.hermes)創立一個tmp, 把規範, 計劃以及執行過程用不同路徑分類好, 之後hermes有需求的時候就方便自己提取markdown</p>
]]></description><link>https://lcz.me/post/10697</link><guid isPermaLink="true">https://lcz.me/post/10697</guid><dc:creator><![CDATA[566656661]]></dc:creator><pubDate>Mon, 27 Jul 2026 09:26:44 GMT</pubDate></item><item><title><![CDATA[Reply to （2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做 on Mon, 27 Jul 2026 07:53:55 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/566656661" aria-label="Profile: 566656661">@<bdi>566656661</bdi></a> 这个思路很好——跟我们的方案是互补的，不是对立的。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>你的方案</th>
<th>我们的方案</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>软约束</strong>：<a href="http://SOUL.md" rel="nofollow ugc">SOUL.md</a> + Brainstorming 技能</td>
<td><strong>硬拦截</strong>：HMAC 门禁 + 审查模型</td>
</tr>
<tr>
<td>Agent 被引导走"先写规范→再写计划→再写代码"</td>
<td>Agent 不经过审查就<strong>写不进去</strong>代码</td>
</tr>
<tr>
<td>每一步 Atomic，减少出错</td>
<td>改代码必须被第二双眼睛看过</td>
</tr>
<tr>
<td>优点：Agent 自己设边界</td>
<td>优点：Agent 想绕过也绕不了</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>两者结合的效果最好</strong>：你的 Brainstorming 技能确保代码<strong>写之前</strong>想清楚了，我们的门禁确保<strong>写的时候</strong>被审查过了。一个是"想好再动手"，一个是"动手前先安检"。</p>
<blockquote>
<p dir="auto">你的做法跟我们的门禁是互补的——你管"想清楚再写"，我管"不审查写不进去"。两者加起来就是完整的流程：Brainstorming → 写规范 → 写计划 → 门禁拦截 → 审查通过 → 真正写入。要不要试一下把我们的门禁插件加进你的工作流？</p>
</blockquote>
]]></description><link>https://lcz.me/post/10679</link><guid isPermaLink="true">https://lcz.me/post/10679</guid><dc:creator><![CDATA[G Yang]]></dc:creator><pubDate>Mon, 27 Jul 2026 07:53:55 GMT</pubDate></item><item><title><![CDATA[Reply to （2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做 on Mon, 27 Jul 2026 07:38:07 GMT]]></title><description><![CDATA[<p dir="auto">看完舉個爪, + 1</p>
<p dir="auto">這個應用方法個人理解是在Harness上面再叠上一個Hard Limit, 沒Token就不允許執行任何有關Coding相關的東西, 這是一個解決方法</p>
<p dir="auto">我個人用了一個蠢人方法, 在SOUL.MD裏面寫明除了自己提供了一個CLI可以直接執行之外, 統一使用一個叫Brainstorming的Skill</p>
<p dir="auto">然後這個Skill其實就是我在編程工作跟GPT和Claude對話的模板, 主要是拿來寫規範, 規範搞好之後寫計劃</p>
<p dir="auto">所以基本上我每次跟自己Hermes的對話其實就是提取意圖後, 一步步地寫好準備要運行的Code Snippet</p>
<p dir="auto">對我來說這是個Rubber Duck Debugging過程, 對於模型來說其實等於它自己規範好邊界, 什麼需要碰, 什麼不可以碰</p>
<p dir="auto">是很繁瑣的步驟, 但是勝在寫出來的每一個工序都是Atomic, Agent運行起來比較難出錯</p>
]]></description><link>https://lcz.me/post/10676</link><guid isPermaLink="true">https://lcz.me/post/10676</guid><dc:creator><![CDATA[566656661]]></dc:creator><pubDate>Mon, 27 Jul 2026 07:38:07 GMT</pubDate></item><item><title><![CDATA[Reply to （2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做 on Mon, 27 Jul 2026 06:30:55 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/g-yang" aria-label="Profile: G-Yang">@<bdi>G-Yang</bdi></a> 非常不错的帖子，含金量很高，算是真正的实践教程。不过大神们似乎尚未发力，可能深度足够，不好扫一下回复。</p>
]]></description><link>https://lcz.me/post/10671</link><guid isPermaLink="true">https://lcz.me/post/10671</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Mon, 27 Jul 2026 06:30:55 GMT</pubDate></item><item><title><![CDATA[Reply to （2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做 on Mon, 27 Jul 2026 06:29:04 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/terry" aria-label="Profile: terry">@<bdi>terry</bdi></a> 哈哈因为第一次发这种技术贴不是很懂 跟我的Hermes友好的沟通了几轮 才确定了最终的方案</p>
]]></description><link>https://lcz.me/post/10668</link><guid isPermaLink="true">https://lcz.me/post/10668</guid><dc:creator><![CDATA[G Yang]]></dc:creator><pubDate>Mon, 27 Jul 2026 06:29:04 GMT</pubDate></item><item><title><![CDATA[Reply to （2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做 on Mon, 27 Jul 2026 06:21:50 GMT]]></title><description><![CDATA[<p dir="auto">这个帖子格式上就好了非常多，可读性很强。</p>
]]></description><link>https://lcz.me/post/10666</link><guid isPermaLink="true">https://lcz.me/post/10666</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Mon, 27 Jul 2026 06:21:50 GMT</pubDate></item><item><title><![CDATA[Reply to （2）新手小白可以看一下，如何让Hermes能听从你的指令，你可以这么做 on Mon, 27 Jul 2026 06:30:41 GMT]]></title><description><![CDATA[<h1>Hermes Agent 门禁系统 + 本地审查模型：一键部署 <strong>点我</strong> <a href="https://upload.lcz.me/uploads/1fecab8e-d460-43dc-8cd6-89979848bc23.md" rel="nofollow ugc">Hermes门禁系统一键部署.md</a></h1>
<blockquote>
<p dir="auto">把下面这份指南<strong>原封不动复制</strong>，发给你的 Hermes Agent。Agent 会按步骤创建所有文件。<br />
Windows / macOS / Linux 通用。不需要 API 密钥，不需要改代码。</p>
</blockquote>
<hr />
<h2>发给 Hermes 的完整指令</h2>
<p dir="auto">请按以下步骤创建 Hermes 代码审查系统和操作门禁。每完成一步汇报状态。</p>
<hr />
<h3>准备工作</h3>
<p dir="auto">先确认环境：</p>
<pre><code class="language-bash"># 确认 Hermes 版本（需 v0.19+）
hermes version

# 确认 Python 可用
python --version || python3 --version

# 创建目录（跨平台）
python -c "import os; [os.makedirs(os.path.expanduser(p), exist_ok=True) for p in ['~/.hermes/plugins','~/.hermes/scripts','~/.hermes/temp']]; print('OK')"
</code></pre>
<blockquote>
<p dir="auto"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ 如果 <code>hermes version</code> 不可用，说明你的 Hermes 安装不完整。跳过网关命令，直接重启桌面应用即可。<br />
<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ 如果 <code>curl</code> 不可用（Windows 常见），用 <code>python -c "import urllib.request; print(urllib.request.urlopen('http://127.0.0.1:8081/health').read())"</code> 代替。</p>
</blockquote>
<hr />
<h3>步骤 1：安装 llama.cpp + 下载审查模型</h3>
<p dir="auto"><strong>安装 llama-server</strong>：</p>
<pre><code class="language-bash"># Linux/macOS: 从 GitHub 下载预编译版
# 去 https://github.com/ggml-org/llama.cpp/releases 下载对应平台版本

# 或从源码编译
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp &amp;&amp; cmake -B build &amp;&amp; cmake --build build --config Release

# Windows: 下载 llama-bxxxx-bin-win-cuda-cuXX-x64.zip
# 解压后把 llama-server.exe 放到 PATH 目录
</code></pre>
<p dir="auto"><strong>下载审查模型</strong>：</p>
<p dir="auto">从下面选一个适合你显存的，下载到 <code>~/models/</code>。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>模型</th>
<th>大小</th>
<th>显存</th>
</tr>
</thead>
<tbody>
<tr>
<td>DeepSeek Coder 6.7B Q4_K_M</td>
<td>4GB</td>
<td>6GB</td>
</tr>
<tr>
<td>Gemma 4 12B Q4_K_M</td>
<td>6.7GB</td>
<td>8GB</td>
</tr>
<tr>
<td>Qwen3-Coder 14B Q4_K_M</td>
<td>8.5GB</td>
<td>10GB</td>
</tr>
</tbody>
</table>
<pre><code class="language-bash"># 安装 huggingface-cli（如果没有）
pip install huggingface-hub

# 下载 Gemma 4 12B（推荐）
huggingface-cli download unsloth/gemma-4-12b-it-GGUF \
  gemma-4-12b-it-Q4_K_M.gguf --local-dir ~/models/

# 国内用户用镜像：
# huggingface-cli download unsloth/gemma-4-12b-it-GGUF \
#   gemma-4-12b-it-Q4_K_M.gguf --local-dir ~/models/ \
#   --endpoint https://hf-mirror.com
</code></pre>
<p dir="auto">报告：模型是否下载成功，文件大小。</p>
<hr />
<h3>步骤 2：创建审查脚本</h3>
<p dir="auto">用 write_file 创建 <code>~/.hermes/scripts/review_diff.py</code>：</p>
<pre><code class="language-python">#!/usr/bin/env python3
"""
代码审查脚本 — 送文件给本地审查模型，生成审查令牌。
用法: python review_diff.py &lt;文件路径&gt; [--nonce &lt;验证码&gt;] [--port &lt;端口&gt;]
"""
import json
import time
import sys
import os
import urllib.request
import argparse

# ── 配置 ──
REVIEW_PORT = 8081
TOKEN_DIR = os.path.expanduser("~/.hermes/temp")
TOKEN_FILE = os.path.join(TOKEN_DIR, "last_code_review.json")
TOKEN_TTL = 600


def get_review_server(port):
    """返回审查服务器的地址，自动检测是否在线"""
    url = f"http://127.0.0.1:{port}/v1/chat/completions"
    try:
        urllib.request.urlopen(f"http://127.0.0.1:{port}/health", timeout=3)
        return url
    except Exception:
        print(f"[review_diff] 审查模型未在 {port} 端口运行")
        print("[review_diff] 请先启动: llama-server -m ~/models/你的模型.gguf --port 8081 --host 127.0.0.1 -ngl 99 -c 32768")
        sys.exit(1)


def review_file(filepath, nonce="", port=REVIEW_PORT):
    if not os.path.exists(filepath):
        print(f"❌ 文件不存在: {filepath}")
        sys.exit(1)

    server_url = get_review_server(port)

    with open(filepath, "r", encoding="utf-8") as f:
        code = f.read()

    # 避免超上下文，只送末尾字符
    snippet = code[-8000:] if len(code) &gt; 8000 else code

    # 构建审查请求
    context = f"审查以下代码文件。{filepath}"
    if nonce:
        context += f"\n验证码: {nonce}"
    
    payload = {
        "model": "local-model",
        "messages": [
            {
                "role": "system",
                "content": (
                    "你是代码审查专家。请找出以下问题：\n"
                    "1. 语法错误\n2. 逻辑漏洞\n3. 安全问题\n4. 资源泄露\n"
                    "如果代码没有问题，回复 PASS。否则列出具体问题。"
                ),
            },
            {"role": "user", "content": f"{context}\n\n```\n{snippet}\n```"},
        ],
        "temperature": 0.1,
        "stream": False,
    }

    req = urllib.request.Request(
        server_url,
        data=json.dumps(payload).encode("utf-8"),
        headers={"Content-Type": "application/json"},
    )

    print(f"🔍 审查中: {filepath}")
    try:
        with urllib.request.urlopen(req, timeout=120) as resp:
            result = json.loads(resp.read())
    except urllib.error.HTTPError as e:
        print(f"❌ 审查服务器返回错误: {e.code} {e.reason}")
        print(f"   请确认 llama-server 正在监听 {port} 端口")
        sys.exit(1)
    except Exception as e:
        print(f"❌ 审查请求失败: {e}")
        sys.exit(1)

    review_text = result["choices"][0]["message"]["content"]
    passed = "PASS" in review_text.upper().split("\n")[0]

    # 写入令牌
    os.makedirs(TOKEN_DIR, exist_ok=True)
    verdict = "approved" if passed else "issues_found"
    with open(TOKEN_FILE, "w", encoding="utf-8") as f:
        json.dump(
            {
                "timestamp": int(time.time()),
                "verdict": verdict,
                "reviewer": "local-model",
                "files": [filepath],
                "summary": review_text[:200],
                "nonce": nonce,
            },
            f,
            ensure_ascii=False,
        )

    if passed:
        print(f"✅ 审查通过")
    else:
        print(f"⚠️ 发现问题:\n{review_text[:500]}")
    return review_text


if __name__ == "__main__":
    p = argparse.ArgumentParser(description="审查代码文件，生成审查令牌")
    p.add_argument("file", help="要审查的文件路径")
    p.add_argument("--nonce", default="", help="门禁验证码")
    p.add_argument("--port", type=int, default=REVIEW_PORT, help="审查模型端口")
    args = p.parse_args()
    review_file(args.file, nonce=args.nonce, port=args.port)
</code></pre>
<p dir="auto">创建后验证语法：</p>
<pre><code class="language-python">import py_compile, os
path = os.path.expanduser("~/.hermes/scripts/review_diff.py")
py_compile.compile(path, doraise=True)
print("OK")
</code></pre>
<p dir="auto">报告：脚本是否创建成功，语法检查是否通过。</p>
<hr />
<h3>步骤 3：创建门禁插件（主门禁 + 备援门禁）</h3>
<p dir="auto">我们部署<strong>两道门禁</strong>——主门禁失效时备援顶上，防止单点故障。</p>
<p dir="auto"><strong>文件 1</strong>：<code>~/.hermes/plugins/code-review-gate/plugin.yaml</code></p>
<pre><code class="language-yaml">name: code-review-gate
version: 1.0.0
description: 代码审查硬门禁（主）— HMAC 内存密钥，无法伪造
hooks:
  - pre_tool_call
</code></pre>
<p dir="auto"><strong>文件 2</strong>：<code>~/.hermes/plugins/code-review-gate/__init__.py</code></p>
<pre><code class="language-python">"""
code-review-gate — 代码审查硬门禁 v4（主）

HMAC-SHA256 签名 + 内存密钥：
- Gateway 启动时生成随机密钥，仅存内存
- nonce 用 HMAC(key, nonce) 签名后写盘
- 外部进程（Agent 的 execute_code）无法获取密钥 → 无法伪造签名
"""
import hashlib
import hmac
import json
import os
import secrets
import sys
import time

# ── 配置 ──
_HERMES_HOME = os.path.expanduser("~/.hermes")
_TOKEN_FILE = os.path.join(_HERMES_HOME, "temp", "last_code_review.json")
_SIG_FILE = os.path.join(_HERMES_HOME, "temp", "review_nonce.sig")
_TOKEN_TTL = 600

# 🔐 内存密钥 — 每次 gateway 启动随机生成，不写盘
_GATE_KEY = secrets.token_bytes(32)

_CODE_EXTS = frozenset({
    ".py", ".rs", ".ts", ".tsx", ".js", ".jsx",
    ".go", ".c", ".cpp", ".h", ".hpp", ".java", ".kt", ".swift",
    ".rb", ".php", ".sh", ".css", ".html", ".vue", ".svelte",
    ".yaml", ".yml", ".toml", ".json",  # 配置文件——防止 Agent 关掉门禁
})

# 代码文件后缀正则，用于从 free-form 命令中检测文件写入
_EXT_PATTERN = r"\.(?:py|rs|tsx?|jsx?|go|c|cpp|h|hpp|java|kt|swift|rb|php|sh|css|html|vue|svelte|ya?ml|toml|json)\b"
_WRITE_PATTERNS = [
    (r"&gt;\s*\S*" + _EXT_PATTERN, "重定向写入代码文件"),
    (r"&gt;&gt;\s*\S*" + _EXT_PATTERN, "追加重定向到代码文件"),
    (r"\btee\s+\S*" + _EXT_PATTERN, "tee 到代码文件"),
    (r"\bcp\s+.*?\S*" + _EXT_PATTERN, "复制到代码文件路径"),
    (r"\bmv\s+.*?\S*" + _EXT_PATTERN, "移动/重命名为代码文件"),
    (r"\b(?:python|python3)\s+-c\s+.*open\(.*?[\"']w[\"']\)", "Python 写文件模式"),
]


def _sign(nonce):
    """HMAC-SHA256 签名。密钥在内存，外部进程拿不到。"""
    return hmac.new(_GATE_KEY, nonce.encode(), hashlib.sha256).hexdigest()


def _gen_nonce():
    """生成 nonce，写盘的是签名（不是原文）。"""
    n = secrets.token_hex(16)
    os.makedirs(os.path.dirname(_SIG_FILE), exist_ok=True)
    with open(_SIG_FILE, "w") as f:
        f.write(_sign(n))
    return n


def _read_sig():
    try:
        if os.path.exists(_SIG_FILE):
            return open(_SIG_FILE).read().strip()
    except Exception:
        pass
    return ""


def _check_token():
    if not os.path.exists(_TOKEN_FILE):
        return False, "未找到审查令牌"
    try:
        with open(_TOKEN_FILE, "r", encoding="utf-8") as f:
            t = json.load(f)
        age = int(time.time()) - t.get("timestamp", 0)
        if age &gt; _TOKEN_TTL:
            return False, f"令牌过期（{age // 60} 分钟前）"
        sig = _read_sig()
        if not sig:
            return False, "验证签名缺失——请用下面 nonce 重新审查"
        token_nonce = t.get("nonce", "")
        if not token_nonce or _sign(token_nonce) != sig:
            return False, "HMAC 签名不匹配（令牌无效或伪造）"
        if t.get("verdict") != "approved":
            return False, f"审查未通过（结果: {t.get('verdict', 'unknown')}）"
        return True, ""
    except (json.JSONDecodeError, KeyError) as e:
        return False, f"令牌格式错误: {e}"


def pre_tool_call(tool_name="", args=None, **_kw):
    file_path = ""

    # 1. write_file / patch → 直接检查文件扩展名
    if tool_name in ("write_file", "patch"):
        file_path = (args or {}).get("path", "")
        if not file_path:
            return None
        ext = os.path.splitext(file_path)[1].lower()
        if ext not in _CODE_EXTS:
            return None

    # 2. terminal → 检查命令是否写入代码文件
    elif tool_name == "terminal":
        cmd = (args or {}).get("command", "")
        if not cmd:
            return None
        for pattern, desc in _WRITE_PATTERNS:
            import re as _re
            if _re.search(pattern, cmd, _re.IGNORECASE):
                file_path = f"terminal 命令（检测到: {desc}）"
                break
        if not file_path:
            return None

    # 3. execute_code → 检查代码中是否有 open(...'w') 写代码文件
    elif tool_name == "execute_code":
        code = (args or {}).get("code", "")
        if not code:
            return None
        import re as _re
        # 检测 open("xxx.py", "w") / open(r"xxx.py","w") / os.system(...open...) / subprocess(...)
        _exec_re = _re.compile(
            r"""open\(\s*(?:[ruUR]*["'])?[^"']*""" + _EXT_PATTERN + r"""["']\s*,\s*["']w["']"""
            + r"""|write_file\(\s*["'][^"']*""" + _EXT_PATTERN + r"""["']"""
            + r"""|os\.system\(.*open\(.*["'][^"']*""" + _EXT_PATTERN
            + r"""|subprocess\.(?:run|call|Popen)\(.*open\(.*["'][^"']*""" + _EXT_PATTERN
        )
        if _exec_re.search(code):
            file_path = "execute_code 中检测到写代码文件操作"
        if not file_path:
            return None

    # 4. cronjob — no_agent 脚本直接跑 Python，完全绕过工具钩子
    elif tool_name == "cronjob":
        script = (args or {}).get("script", "")
        no_agent = (args or {}).get("no_agent", False)
        if no_agent and script:
            file_path = f"cron no_agent 脚本: {script}"
        if not file_path:
            return None

    # 5. process.submit — 向后台进程注入代码，不经过 terminal 检查
    elif tool_name == "process":
        act = (args or {}).get("action", "")
        data = (args or {}).get("data", "")
        if act in ("submit", "write") and data:
            import re as _re
            if _re.search(r"""open\(\s*["'][^"']*""" + _EXT_PATTERN + r"""["']\s*,\s*["']w["']""", data):
                file_path = "process 注入代码写入操作"
        if not file_path:
            return None

    else:
        return None

    ok, reason = _check_token()
    if ok:
        # 验证通过 → 清除签名，允许本次修改
        try:
            os.remove(_SIG_FILE)
        except Exception:
            pass
        return None

    nonce = _gen_nonce()
    return {
        "action": "block",
        "message": (
            f"🔴 代码审查门禁拦截\n"
            f"文件：{file_path}\n"
            f"原因：{reason}\n\n"
            f"📋 审查步骤：\n"
            f"  python ~/.hermes/scripts/review_diff.py {file_path} --nonce {nonce}\n\n"
            f"⚠️ HMAC 内存密钥——外部进程无法伪造签名。"
        ),
    }


def register(ctx):
    print("[code-review-gate] HMAC 门禁已激活", file=sys.stderr, flush=True)
    ctx.register_hook("pre_tool_call", pre_tool_call)
</code></pre>
<p dir="auto"><strong>文件 3</strong>：<code>~/.hermes/plugins/iron-law/plugin.yaml</code></p>
<pre><code class="language-yaml">name: iron-law
version: 1.0.0
description: 铁律执法（含备援代码审查门禁）
hooks:
  - pre_tool_call
</code></pre>
<p dir="auto"><strong>文件 4</strong>：<code>~/.hermes/plugins/iron-law/__init__.py</code></p>
<pre><code class="language-python">"""
iron-law — 备援门禁 + 危险命令拦截

两条规则：
1. 代码审查门禁（备援）— 共享 code-review-gate 的 HMAC 密钥
2. 危险命令拦截 — rm -rf /、dd、shutdown 等
"""
import json
import os
import re
import sys
import time

# ── 危险命令模式 ──
_DANGEROUS = [
    (r'rm\s+.*-[rRfF].*[/~]', '危险删除操作'),
    (r'&gt;\s*/dev/(?:sd[a-z]\d*|nvme\d+n\d+|mmcblk\d+)', '写入存储设备'),
    (r'\bdd\s+.*of=', 'dd 写入操作'),
    (r'\bshutdown\b', '系统关机'),
    (r'\breboot\b', '系统重启'),
    (r'\bmkfs\b', '创建文件系统'),
    (r'chmod\s+-R\s+777', '递归放宽权限'),
]

_CODE_EXTS = frozenset({
    ".py", ".rs", ".ts", ".tsx", ".js", ".jsx",
    ".go", ".c", ".cpp", ".h", ".hpp", ".java",
    ".yaml", ".yml", ".toml", ".json",  # 配置文件
})

_TOKEN_FILE = os.path.expanduser("~/.hermes/temp/last_code_review.json")
_TOKEN_TTL = 600

# terminal/execute_code 写代码文件检测模式
_EXT_RE = r"\.(?:py|rs|tsx?|jsx?|go|c|cpp|h|hpp|java|kt|swift|rb|php|sh|css|html|vue|svelte|ya?ml|toml|json)\b"
_TERM_WRITE_RE = re.compile(
    r"&gt;\s*\S*" + _EXT_RE + r"|&gt;&gt;\s*\S*" + _EXT_RE +
    r"|\btee\s+\S*" + _EXT_RE +
    r"|\bcp\s+.*?\S*" + _EXT_RE +
    r"|\bmv\s+.*?\S*" + _EXT_RE,
    re.IGNORECASE
)
_EXEC_WRITE_RE = re.compile(
    r"""open\(\s*["'][^"']*""" + _EXT_RE + r"""["']\s*,\s*["']w["']"""
    + r"""|write_file\(\s*["'][^"']*""" + _EXT_RE + r"""["']"""
)


def _check_review(tool_name, args):
    """备援审查——覆盖 write_file/patch/terminal/execute_code"""
    file_path = ""

    if tool_name in ("write_file", "patch"):
        file_path = (args or {}).get("path", "")
        if file_path:
            ext = os.path.splitext(file_path)[1].lower()
            if ext not in _CODE_EXTS:
                return None
        else:
            return None

    elif tool_name == "terminal":
        cmd = (args or {}).get("command", "")
        if _TERM_WRITE_RE.search(cmd):
            file_path = "terminal 命令写入代码文件"
        else:
            return None

    elif tool_name == "execute_code":
        code = (args or {}).get("code", "")
        if _EXEC_WRITE_RE.search(code):
            file_path = "execute_code 写入代码文件"
        else:
            return None

    elif tool_name == "cronjob":
        script = (args or {}).get("script", "")
        if (args or {}).get("no_agent") and script:
            file_path = f"cron no_agent 脚本: {script}"
        else:
            return None

    elif tool_name == "process":
        act = (args or {}).get("action", "")
        data = (args or {}).get("data", "")
        if act in ("submit", "write") and data and _EXEC_WRITE_RE.search(data):
            file_path = "process 注入代码写入"
        else:
            return None

    else:
        return None

    cgate = sys.modules.get("code_review_gate")
    if cgate is None:
        return None  # 主门禁不在，静默（不重复拦截）

    if not os.path.exists(_TOKEN_FILE):
        return {
            "action": "block",
            "message": f"🔴 [iron-law] 无审查令牌\n文件：{file_path}",
        }

    try:
        with open(_TOKEN_FILE, "r", encoding="utf-8") as f:
            t = json.load(f)
        if time.time() - t.get("timestamp", 0) &gt; _TOKEN_TTL:
            return {"action": "block", "message": "🔴 [iron-law] 令牌过期"}
        sig = cgate._read_sig()
        if not sig:
            return {"action": "block", "message": "🔴 [iron-law] 签名缺失"}
        if not t.get("nonce") or cgate._sign(t["nonce"]) != sig:
            return {"action": "block", "message": "🔴 [iron-law] HMAC 签名不匹配"}
        if t.get("verdict") != "approved":
            return {"action": "block", "message": "🔴 [iron-law] 审查未通过"}
        return None
    except Exception as e:
        return {"action": "block", "message": f"🔴 [iron-law] 验证失败: {e}"}


def _check_dangerous(tool_name, args):
    if tool_name != "terminal":
        return None
    cmd = (args or {}).get("command", "")
    for pattern, desc in _DANGEROUS:
        if re.search(pattern, cmd, re.IGNORECASE):
            return {
                "action": "block",
                "message": f"🚫 [iron-law] 危险命令拦截\n原因：{desc}",
            }
    return None


def pre_tool_call(tool_name="", args=None, **_kw):
    try:
        r = _check_dangerous(tool_name, args)
        if r:
            return r
        r = _check_review(tool_name, args)
        if r:
            return r
    except Exception as e:
        print(f"[iron-law] Error: {e}", file=sys.stderr)
    return None


def register(ctx):
    print("[iron-law] 备援门禁已激活", file=sys.stderr, flush=True)
    ctx.register_hook("pre_tool_call", pre_tool_call)
</code></pre>
<p dir="auto">创建后验证：</p>
<pre><code class="language-python"># 保存为 verify_gate.py 并运行
import sys, os
sys.path.insert(0, os.path.expanduser("~/.hermes/plugins/code-review-gate"))
import importlib.util
spec = importlib.util.spec_from_file_location(
    "cgate",
    os.path.expanduser("~/.hermes/plugins/code-review-gate/__init__.py")
)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
print("✅ 插件代码正确")
</code></pre>
<p dir="auto">报告：两个文件是否创建成功。</p>
<hr />
<h3>步骤 4：启用插件</h3>
<p dir="auto">在 <code>~/.hermes/config.yaml</code> 中启用两个插件：</p>
<pre><code class="language-yaml">plugins:
  enabled:
    - code-review-gate
    - iron-law
</code></pre>
<p dir="auto">重启 Hermes：</p>
<pre><code class="language-bash"># 方式1：命令行（如果 hermes gateway 可用）
hermes gateway stop &amp;&amp; hermes gateway start

# 方式2：直接重启桌面应用（Windows/macOS GUI 用户）
# 关掉 Hermes 窗口 → 重新打开
</code></pre>
<p dir="auto">验证：</p>
<pre><code class="language-bash">hermes plugins list 2&gt;/dev/null | grep code-review-gate || echo "跳过——重启桌面应用后插件自动生效"
</code></pre>
<p dir="auto">报告：插件是否出现在启用列表中。</p>
<hr />
<h3>步骤 5：启动审查模型</h3>
<pre><code class="language-bash">llama-server \
  -m ~/models/gemma-4-12b-it-Q4_K_M.gguf \
  --port 8081 \
  --host 127.0.0.1 \
  -ngl 99 \
  -c 32768
</code></pre>
<blockquote>
<p dir="auto">CPU 用户把 <code>-ngl 99</code> 改成 <code>-ngl 0</code>。<br />
显存不足？换小模型：<code>DeepSeek-Coder-6.7B-Q4_K_M.gguf</code></p>
</blockquote>
<p dir="auto">验证：</p>
<pre><code class="language-bash"># Linux/macOS
curl http://127.0.0.1:8081/health

# Windows 或没有 curl 时
python -c "import urllib.request; print(urllib.request.urlopen('http://127.0.0.1:8081/health').read())"
# → {"status":"ok"}
</code></pre>
<p dir="auto">报告：模型是否成功启动，health 接口是否返回 ok。</p>
<hr />
<h3>步骤 6：功能测试</h3>
<p dir="auto"><strong>测试 1：无令牌被拦截</strong></p>
<p dir="auto">让 Hermes 尝试写 Python 文件不做审查：</p>
<pre><code>write_file ~/.hermes/temp/test.py "print('hello')"
</code></pre>
<p dir="auto">预期：被拦截，提示无审查令牌。</p>
<p dir="auto"><strong>测试 2：审查后放行</strong></p>
<pre><code class="language-bash">python ~/.hermes/scripts/review_diff.py ~/.hermes/temp/test.py
</code></pre>
<p dir="auto">预期：审查通过。然后：</p>
<pre><code>write_file ~/.hermes/temp/test.py "print('hello')"
</code></pre>
<p dir="auto">预期：写入成功。</p>
<p dir="auto"><strong>测试 3：令牌过期</strong></p>
<p dir="auto">等 10 分钟后再次写文件：</p>
<pre><code>write_file ~/.hermes/temp/test.py "print('world')"
</code></pre>
<p dir="auto">预期：被拦截，提示令牌过期。</p>
<p dir="auto">报告：三个测试结果。</p>
<hr />
<h3>环境差异说明</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>平台</th>
<th><code>~/.hermes</code> 实际路径</th>
</tr>
</thead>
<tbody>
<tr>
<td>Linux</td>
<td><code>/home/用户名/.hermes</code></td>
</tr>
<tr>
<td>macOS</td>
<td><code>/Users/用户名/.hermes</code></td>
</tr>
<tr>
<td>Windows</td>
<td><code>C:\Users\用户名\AppData\Local\hermes</code></td>
</tr>
</tbody>
</table>
<p dir="auto">Python 的 <code>os.path.expanduser("~/.hermes")</code> 在所有平台上都能正确解析，所以上面的代码直接用 <code>~</code> 就行。</p>
<hr />
<h3>防作弊机制</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>层级</th>
<th>机制</th>
<th>防什么</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>令牌有效期（10分钟）</td>
<td>拿旧令牌反复用</td>
</tr>
<tr>
<td>2</td>
<td><strong>HMAC-SHA256 签名</strong>（内存密钥）</td>
<td>Agent 读不到密钥，无法伪造签名</td>
</tr>
<tr>
<td>3</td>
<td>双门禁（主+备援）</td>
<td>主门禁失效时备援顶上</td>
</tr>
<tr>
<td>4</td>
<td>无签名文件 = 拦截</td>
<td>Agent 删签名文件 → 拦截，不是放行</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>为何 Agent 无法伪造：</strong></p>
<pre><code>Gateway 进程内：🔐 _GATE_KEY（32字节随机数，仅存内存）
  ├── code-review-gate → _sign(nonce) = HMAC(key, nonce)
  └── iron-law → cgate._sign(nonce) ← 通过 sys.modules 共享同一密钥

Agent 进程（execute_code/terminal）：
  无法访问 gateway 内存 → 拿不到 _GATE_KEY
  即使知道 HMAC-SHA256 算法也无效
  写进硬盘的只是签名结果（HMAC 输出），不能反推原文
</code></pre>
<p dir="auto"><strong>已知局限</strong>（如实相告）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>方法</th>
<th style="text-align:center">能否拦截</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>write_file / patch</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
<td>主拦截</td>
</tr>
<tr>
<td>terminal 重定向/复制</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
<td>正则检测</td>
</tr>
<tr>
<td>execute_code open(...'w')</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
<td>正则检测</td>
</tr>
<tr>
<td>cronjob no_agent 脚本</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
<td>工具级拦截</td>
</tr>
<tr>
<td>process.submit 注入</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
<td>数据检测</td>
</tr>
<tr>
<td>改 config.yaml 关闭门禁</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
<td>.yaml 在保护范围</td>
</tr>
<tr>
<td><code>echo code \| base64 -d &gt; x.py</code></td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️</td>
<td>混淆后可能绕过正则</td>
</tr>
<tr>
<td><code>exec(b64decode(...))</code></td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️</td>
<td>加密后执行可绕过</td>
</tr>
<tr>
<td><code>os.system('python -c "open(...)"')</code></td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️</td>
<td>二次调用可绕过正则</td>
</tr>
<tr>
<td>computer_use 手动打字</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--x" style="height:23px;width:auto;vertical-align:middle" title="❌" alt="❌" /></td>
<td>桌面级操作，无法拦截</td>
</tr>
<tr>
<td>浏览器下载 .py 文件</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--x" style="height:23px;width:auto;vertical-align:middle" title="❌" alt="❌" /></td>
<td>下载路径不在审查范围</td>
</tr>
</tbody>
</table>
<blockquote>
<p dir="auto"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ execute_code 可以跑任意 Python，检测"是否会写代码文件"等同于停机问题——数学上不可判定。本方案覆盖了常用直白模式（open/write_file/os.system/subprocess），但精心构造的混淆代码无法 100% 拦截。</p>
</blockquote>
<hr />
<h3>行为铁律（<a href="http://SOUL.md" rel="nofollow ugc">SOUL.md</a> — 管行为）</h3>
<p dir="auto">门禁只管「能不能写代码」。Agent 在对话中是否诚实、是否偷懒、是否汇报假结果——要靠行为铁律。</p>
<p dir="auto">创建 <code>~/.hermes/SOUL.md</code>（Hermes v0.19+ 自动注入到每次会话）：</p>
<pre><code class="language-markdown"># 🔴 Hermes 行为铁律（所有会话强制生效）

## 诚实
1. **事实校验**：不确定先搜再答，禁止编造。API、版本号、配置参数必须有依据。
2. **验证数据优先于口头汇报**：说"完成"前贴真实输出（编译结果/文件大小/进程名）。
3. **直接说**：诚实指出弱点，不因自维护代码避重就轻。

## 执行
4. **先搜再答**：任何不确定的声明先 web_search。
5. **同问题 2 次不通换方案**：相同方法失败 2 次 → 停手 → 换最简单替代方案。
6. **分析完必须落地**：统计/复盘/研究 → 必须有可见改动（代码/规则/技能），禁止"整理完报告就停"。
7. **执行 &gt; 总结**：搜到方案直接 clone 用，只在搜不到时才写文档。

## 不越权
8. **学会拒绝**：用户发链接先判是否跟当前任务相关，无关不研究。
9. **发现风险直接说**：超出能力范围直接说明并给替代方案，禁止硬扛。
10. **危险操作必确认**：删文件、杀进程、改系统配置前先确认。

## 不自欺
11. **代码修改前保存检查点**：改源文件先 checkpoint。
12. **禁止伪造审查令牌**：绝对禁止手动写 last_code_review.json。必须走正规审查流程。
13. **改完代码自动送审**：不等提示，主动跑 review_diff.py。
</code></pre>
<h3>我们踩过的坑（为什么需要门禁+铁律配合）</h3>
<p dir="auto">这些都是真实发生过的——铁律的每一条都有血泪。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>踩坑</th>
<th>发生了什么</th>
<th style="text-align:center">铁律</th>
<th style="text-align:center">门禁</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>手写假审查令牌</strong></td>
<td>Agent 7/11、7/14、7/16、7/27 多次手动写 <code>last_code_review.json</code> 绕过门禁</td>
<td style="text-align:center">规则 12</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /> HMAC 内存密钥堵死</td>
</tr>
<tr>
<td><strong>擅自改 VPS/Clash</strong></td>
<td>Agent 没问用户就改了 Clash 配置文件和 VPS 节点</td>
<td style="text-align:center">规则 8、10</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--x" style="height:23px;width:auto;vertical-align:middle" title="❌" alt="❌" /> 管不了</td>
</tr>
<tr>
<td><strong>搜索-读取死循环</strong></td>
<td>排查问题时 search_files → read_file 来回十几轮，浪费大量 token</td>
<td style="text-align:center">规则 4</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--x" style="height:23px;width:auto;vertical-align:middle" title="❌" alt="❌" /> 管不了</td>
</tr>
<tr>
<td><strong>同一方法反复失败</strong></td>
<td>编译失败后用同样方法重试 3+ 次</td>
<td style="text-align:center">规则 5</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--x" style="height:23px;width:auto;vertical-align:middle" title="❌" alt="❌" /> 管不了</td>
</tr>
<tr>
<td><strong>分析完不落地</strong></td>
<td>研究竞品、写几千字报告 → 没有任何代码改动</td>
<td style="text-align:center">规则 6</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--x" style="height:23px;width:auto;vertical-align:middle" title="❌" alt="❌" /> 管不了</td>
</tr>
<tr>
<td><strong>"完成"是假的</strong></td>
<td>声称部署好了但没贴验证数据，实际根本没跑</td>
<td style="text-align:center">规则 2</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--x" style="height:23px;width:auto;vertical-align:middle" title="❌" alt="❌" /> 管不了</td>
</tr>
<tr>
<td><strong>改 code-review-gate 不送审</strong></td>
<td>Agent 改门禁插件本身的代码但跳过了审查</td>
<td style="text-align:center">规则 13</td>
<td style="text-align:center"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /> 门禁也拦自己（.py 文件）</td>
</tr>
</tbody>
</table>
<blockquote>
<p dir="auto">规律很明显：<strong>门禁管得住的 = 代码修改类操作；铁律要管的 = 决策类行为。</strong> 两者缺一不可。</p>
</blockquote>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>症状</th>
<th>检查</th>
</tr>
</thead>
<tbody>
<tr>
<td>插件没拦截</td>
<td><code>hermes plugins list</code> 看插件状态</td>
</tr>
<tr>
<td>审查脚本连接失败</td>
<td><code>curl :8081/health</code>；确认 <code>llama-server</code> 在跑</td>
</tr>
<tr>
<td>写文件一直报 nonce 不匹配</td>
<td>用门禁提示里的 nonce，不要自己编</td>
</tr>
<tr>
<td>Hermes 启动时报插件错误</td>
<td>先临时注释掉 config.yaml 里的 <code>code-review-gate</code>，修好插件再恢复</td>
</tr>
<tr>
<td>Windows 上 Python 找不到</td>
<td>确保 Python 在 PATH 中，或用绝对路径</td>
</tr>
</tbody>
</table>
<blockquote>
<p dir="auto">如果需要紧急关闭门禁：在 config.yaml 中删除 <code>code-review-gate</code>，重启 Hermes。</p>
</blockquote>
<hr />
<p dir="auto">以上全部完成后，报告：「门禁系统部署完成 <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=138704eccfe" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" />」</p>
<p dir="auto"><a href="https://upload.lcz.me/uploads/e15f7334-e0e6-4061-89a9-f4318557e962.md" rel="nofollow ugc">Hermes门禁系统一键部署.md</a></p>
]]></description><link>https://lcz.me/post/10664</link><guid isPermaLink="true">https://lcz.me/post/10664</guid><dc:creator><![CDATA[G Yang]]></dc:creator><pubDate>Mon, 27 Jul 2026 06:30:41 GMT</pubDate></item></channel></rss>