权威统一:提问/排版格式与自决策判据都归位到会话机制包内

起因(用户):「提问拍板格式不应该在会话机制中吗,怎么跑到别的技能中去了」
病根=**权威声明分裂**:
  · SKILL.md:963 说 03 号是「内联副本」⇒ 隐指权威在 agent-operating-rules;
  · 而 03 号自己头部写着「**这份是权威源**」,且把它说的第②个消费者
    `scripts/apply-reply-rules.py` 写成了**不在本包**的路径。
  ⇒ 同一件事两处说法打架 ⇒ 改的人(我)会把改动做错地方。

处置(统一为「会话机制包内即权威」,与 02/04 两份的既有处置一致):
  ① 注入器归位:新增 `session-mechanism/scripts/apply-reply-rules.py`,默认读**包内** 03 号;
  ② 03 号头部改写:权威=本文件,两个消费者都在本包内;
  ③ `reply-style-guard.py` 第③级兜底从**别的技能**改回包内路径;
  ④ `agent-operating-rules/references/回复排版-核心块.md` 标注「副本·权威在会话机制」;
  ⑤ `dsh-decision/references/00-决策方法论.md` 标注「来源·权威在会话机制」;
  ⑥ SKILL.md:963 措辞由「内联副本」校正为「收进本包并定为权威」。

验收:注入器 `--check` 报权威源=包内 03 号且与 CODEBUDDY.md 一致;
      每轮注入 1183 字符(含「竖排」「变相征询」);
      **无 CODEBUDDY.md 的干净工作区也能取到**(1185 字符)⇒ 自包含成立。
This commit is contained in:
admin committed 2026-10-06 22:45:43 +08:00
1 parent 423b16004f
commit ea4e6d6d58
4 files changed
+173 -5

No files matched your search

+2 -1
View File
@@ -960,7 +960,8 @@ assets/ board.html design-tokens.css
⚠️ 逐文件清单 + 来源(provenance)⇒ `references/manifest.md`(**唯一权威**,⛔ 别按本树猜)。
**⛔ 已无必需外部依赖(2026-10-04)**:原先声明「依赖 `agent-operating-rules`」——现已把它的**排版核心块内联**为 `references/03-回复排版-核心块.md`、把 `_env.py` 的技能库识别特征改为**候选数组(首个=本包自己)** ⇒ **本包自包含**。📌 那个技能若同时装着,属**可选增强**(多了跨项目排版/去 AI 味的完整版),⛔ 不装也能跑。
**⛔ 已无必需外部依赖(2026-10-04)**:原先声明「依赖 `agent-operating-rules`」——现已把**排版核心块收进本包并定为权威** ⇒ `references/03-回复排版-核心块.md`
(2026-10-06 校正:原措辞是「内联副本」,与 03 号自称「权威源」打架 ⇒ 权威声明分裂)、把 `_env.py` 的技能库识别特征改为**候选数组(首个=本包自己)** ⇒ **本包自包含**。📌 那个技能若同时装着,属**可选增强**(多了跨项目排版/去 AI 味的完整版),⛔ 不装也能跑。
---
@@ -1,8 +1,11 @@
# 回复排版与格式 · 核心块(**机器可读 · 权威源**)
> **这份是权威源**(跨工作区、跨机器)。两个消费者:
> ① 钩子 `scripts/hooks/reply-style-guard.py` **每轮现读本块**注入会话;
> ② 注入器 `scripts/apply-reply-rules.py` 把它写进**各环境的规则文件**(`CODEBUDDY.md` / `AGENTS.md`)。
> 🔴🔴 **权威源 = 本文件**(`session-mechanism/references/03-回复排版-核心块.md`,跨工作区、跨机器)。
> **两个消费者(都在本包内)**:
> ① 钩子 `scripts/hooks/reply-style-guard.py` —— **每轮现读本块**注入会话(包内优先,②级回退);
> ② 注入器 `scripts/apply-reply-rules.py` —— 把它写进**各环境的规则文件**(`CODEBUDDY.md` / `AGENTS.md`)。
> ⚠️ `agent-operating-rules/references/回复排版-核心块.md` 是**同内容副本**,⛔ **改口径只改本文件**,
> 改完同步副本 + 用 ② 重生成各环境文件。
> ⛔ **不要在本文件之外再抄一份规则文本** —— 抄了就成第二真相源,两边必然漂。
> 用户令(2026-10-02):「所有会话中回复排版和格式要求和规则,也要整合到会话技能中,使用时配置到对应环境文件中」。
@@ -0,0 +1,162 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""apply-reply-rules.py —— 把「回复排版与格式」核心块**配置到目标环境的规则文件**里
🔴 2026-10-06:本脚本**归位到 session-mechanism**(原先只在 agent-operating-rules 里,
而 03 号核心块却自称权威源却指着一个不在本包的注入器 ⇒ 权威声明分裂)。
权威源 = 本包 `references/03-回复排版-核心块.md`(**唯一**)。
它解决什么
──────────
用户 2026-10-02 令(逐字):
「**所有会话中**回复排版和格式要求和规则,也要**整合到会话技能中**,
使用时**配置到对应环境文件中**」
⇒ 三层分工(⛔ 别混):
· **技能**(本脚本所在包 `agent-operating-rules`)=**权威源**,跨工作区、跨机器。
· **环境文件**(`CODEBUDDY.md` / `AGENTS.md`)=该环境的**落地配置**,由本脚本生成。
· **每个会话**=由钩子 `reply-style-guard.py` **每轮**把核心块注入(优先用本环境的落地副本)。
为什么需要"注入"这一步(⛔ 不只是钩子就够)
────────────────────────────────────────────
钩子管的是"**每一轮**紧贴用户消息",而环境文件管的是"**这个环境自己的规则**":
· 换机 / 换工作区时,钩子可能还没装,但规则文件先被读到 ⇒ 规则不能只活在钩子里;
· 环境可能有**本地定稿**(如某工作区把骨架改过)⇒ 落地副本是它自己的那份,钩子优先读它。
安全设计
────────
1. **只动标记块**:只替换 `<!-- REPLY-CORE:BEGIN --> … <!-- REPLY-CORE:END -->` 之间;
块外(人工撰写的解释 / 别的规则)**一字不动**。
2. **默认不建块**:目标里没有标记块时**只报告**(rc=1),要建得显式加 `--init`
(追加到文末,不改既有内容)—— 避免与人工撰写的内容重复成两处。
3. **单向**:核心块内容由**技能**决定,⛔ 不许反过来把环境文件当源。
⇒ 本地确实要改措辞 ⇒ 改技能里那份,再对所有环境重跑本脚本。
4. **回读校验**:写完复读并断言块在、长度变化符合预期;异常 ⇒ 不写盘。
用法
────
<python> apply-reply-rules.py # 默认目标 = 当前目录的 CODEBUDDY.md(只报告)
<python> apply-reply-rules.py --ws <工作区> # 目标 = <工作区>/CODEBUDDY.md
<python> apply-reply-rules.py --target <文件> # 指定环境文件(AGENTS.md 等)
<python> apply-reply-rules.py --check # 只校验:块在不在、是否与技能一致
<python> apply-reply-rules.py --apply # 真写(需先抢锁 —— 环境文件通常属机制层)
<python> apply-reply-rules.py --apply --init # 目标没有标记块时,追加建块
退出码:0 = 一致/成功|1 = 有差异 / 需要人看|2 = 用法或环境异常
"""
import hashlib
import io
import os
import re
import shutil
import sys
import time
HERE = os.path.dirname(os.path.abspath(__file__))
SKILL = os.path.dirname(HERE) # = <技能库>/agent-operating-rules
# 🔴 2026-10-06 本包内版本:权威源就在本包 ⇒ 默认读 `references/03-回复排版-核心块.md`
CORE = os.path.join(SKILL, 'references', '03-回复排版-核心块.md')
BEGIN = '<!-- REPLY-CORE:BEGIN'
END = '<!-- REPLY-CORE:END -->'
BANNER = ('<!-- BEGIN reply-core (generated by agent-operating-rules/scripts/'
'apply-reply-rules.py · 勿手改块内;要改口径改技能里那份再重跑本脚本) -->')
def rd(p, nl=''):
try:
return io.open(p, encoding='utf-8', newline=nl).read()
except OSError:
return ''
def md5s(s):
return hashlib.md5(s.encode('utf-8')).hexdigest()[:12]
def core_text():
t = rd(CORE)
if not t:
raise SystemExit('ERROR: 缺权威源 %s' % CORE)
i = t.find(BEGIN)
if i < 0:
raise SystemExit('ERROR: 权威源里没有 %s 标记' % BEGIN)
i = t.find('\n', i)
j = t.find(END, i + 1)
return t[i + 1:j].strip()
def block(body, bare=False):
if bare:
return BEGIN + ' (由 agent-operating-rules 技能生成) -->\n' + body + '\n' + END + '\n'
return (BEGIN + ' (由 agent-operating-rules 技能生成 · 与技能内那份同源) -->\n'
+ body + '\n' + END + '\n')
def cur_block(t):
i = t.find(BEGIN)
if i < 0:
return ''
i = t.find('\n', i)
j = t.find(END, i + 1)
if i < 0 or j < 0:
return ''
return t[i + 1:j].strip()
def main(argv):
tgt, apply_, init_, chk = '', '--apply' in argv, '--init' in argv, '--check' in argv
if '--target' in argv:
tgt = argv[argv.index('--target') + 1]
elif '--ws' in argv:
tgt = os.path.join(argv[argv.index('--ws') + 1], 'CODEBUDDY.md')
else:
tgt = os.path.join(os.getcwd(), 'CODEBUDDY.md')
tgt = os.path.normpath(tgt.replace('\\', '/'))
body = core_text()
t = rd(tgt)
print('权威源:%s(核心块 %d 字符 / md5=%s)' % (CORE, len(body), md5s(body)))
print('目标 :%s(%s)' % (tgt, '存在' if t else '**不存在**'))
if not t:
print('⛔ 目标文件不存在 ⇒ 停手(本脚本只在既有规则文件里注入,⛔ 不凭空造规则文件)')
return 2
have = cur_block(t)
if have:
same = have == body
print('块状态:已存在,与技能%s(正文 md5 %s vs %s)'
% ('**一致** ✅' if same else '**不一致** ⚠️', md5s(have), md5s(body)))
if chk:
return 0 if same else 1
if same and not apply_:
print('⇒ 无需改动')
return 0
else:
print('块状态:**没有标记块**')
if chk:
return 1
if not init_:
print('⇒ 默认**不建块**(避免与人工撰写内容重复成两处)。要建:加 --init(追加到文末)')
return 1
if not apply_:
print('⇒ 将写入(--apply 才真写):%s' % ('追加标记块' if not have else '替换块内内容'))
return 0
b = tgt + '.bak-replycore-' + time.strftime('%Y%m%d-%H%M%S')
shutil.copy2(tgt, b)
if have:
new = re.sub(re.escape(BEGIN) + r'.*?' + re.escape(END) + r'\n?',
block(body), t, flags=re.S)
else:
new = t.rstrip('\n') + '\n\n' + BANNER + '\n' + block(body)
io.open(tgt, 'w', encoding='utf-8', newline='').write(new)
back = rd(tgt)
assert cur_block(back) == body, '回读不符 ⇒ 已中止(备份 %s)' % b
print('✓ 已写入并回读校验通过(备份 %s)' % os.path.basename(b))
print(' ⚠️ 环境文件通常属机制层 ⇒ 本轮若没抢到锁,写入动作本身即违规;请用 --check 先看状态。')
return 0
if __name__ == '__main__':
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
raise SystemExit(main(sys.argv[1:]))
@@ -50,7 +50,9 @@ except Exception: # 🔴 找不到就报错(⛔ 不静默
% os.path.dirname(os.path.abspath(__file__)))
raise
CORE_REL = os.path.join('agent-operating-rules', 'references', '回复排版-核心块.md')
# 🔴 2026-10-06:第③级兜底原指向**另一个技能**(agent-operating-rules)⇒ 与「本包自包含」矛盾,
# 且权威已定为包内 03 号 ⇒ 这里指回包内;包内路径由第②级处理,本行只是 env 覆盖时的兜底。
CORE_REL = os.path.join('session-mechanism', 'references', '03-回复排版-核心块.md')
BEGIN = '<!-- REPLY-CORE:BEGIN'
END = '<!-- REPLY-CORE:END -->'
MAX_CHARS = 1400