按用户令提交:把此前未纳管的 9 个技能目录一并入库

用户令逐字:「E:/ProgramData/.workbuddy/skills  提交仓库是指的这里」——
即本目录就是仓库(2026-10-07 已在本目录建仓,见当日日志 §22),本轮把余下未纳管的 9 个技能一并提交。

本次入库(9 个技能,46 个文件):
1、`AI HOT`
2、`draw-ui`
3、`dsh-diagnose`
4、`dsh-knowledge`
5、`dsh-local-env`
6、`dsh-opensource-release`
7、`dsh-workflow`
8、`oil-motion`
9、`skills-security-check`

提交前核对:
· **凭据类扫描**(`*.env` / `*token*` / `*.key` / `*secret*` / `*.pem`)⇒ **零命中** ✓;
· 体积合计约 20 MB(`draw-ui` 12M + `oil-motion` 6.5M 是大头,形态为配图/素材 ——
  仓库 `.gitignore` 里明写「`assets/*.png` 是内容不是产物」⇒ 属刻意入库);
· 运行产物仍按既定规则排除(`__pycache__` / `logs/` / `tmp/` / `.venv/` / `*.egg-info` / `uv.lock` / `.workbuddy/`)。
This commit is contained in:
admin committed 2026-10-08 22:29:08 +08:00
1 parent d26c844f64
commit e03465c398
46 files changed
+7558

No files matched your search

@@ -0,0 +1,244 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""resident-rules.py —— 「常驻规则」的可移植化:快照 / 校验 / 注入 / 环境自检
为什么需要它
────────────
项目常驻规则写在**工作区**的 `CODEBUDDY.md`(每会话自动注入 ⇒ 动作前必然生效)。
但它是**工作区文件**:换电脑 / 换工作区路径 ⇒ 规则直接消失,而"技能"才是**可移植层**。
本脚本 + 同目录 `references/常驻规则-快照.md` 把两者接起来:
CODEBUDDY.md(工作区·权威·动作前生效)
│ --snapshot(抽取 §1/§3/§4/§5/§6/§8 全文)
▼
references/常驻规则-快照.md(技能内·可移植·随技能走)
│ --check / --inject(到新环境的 CODEBUDDY.md)
▼
新环境的 CODEBUDDY.md
设计红线(避免造"第二真相源")
──────────────────────────────
1. **权威方向单向**:`CODEBUDDY.md` 是权威,快照是**它的副本**(`--snapshot` 生成,不手改)。
2. **默认只报不改**:`--check` 只报告差异(退出码 1)—— 与文档库「体检只报不改」同规。
3. **注入只动标记块**:`--inject` 只替换 `<!-- BEGIN resident-rules … --> … <!-- END -->` 之间的内容;
首次注入**不自动建块**(除非 `--init`),避免与人工撰写的内容重复成两处。
4. **区分环境无关 / 环境相关**:环境相关项(绝对路径 / IP / hooks 路径 / 工具位置)
注入后**必须按新环境核对** —— 脚本给「待核清单」,不假装能自动配好。
用法
────
python3 resident-rules.py --snapshot # 由 CODEBUDDY.md 重生成技能内快照
python3 resident-rules.py --check [--goal <CODEBUDDY.md>] # 校验目标环境(默认只报,rc=1 = 有差异)
python3 resident-rules.py --env-check # 环境自检:路径 / hooks / 锁脚本 / 工作区
python3 resident-rules.py --inject [--goal <CODEBUDDY.md>] [--init] # 注入(需已存在标记块)
退出码:0 = 一致/成功;1 = 有差异(未改任何文件);2 = 用法/环境异常
"""
import io
import json
import os
import re
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
# 🔴 2026-10-02 修路径推导(原 `SKILL = dirname(HERE)` 少算一层 ⇒ **快照一直写错目录**):
# 脚本实际位于 `<dsh-local-env>/references/dsh-env-bootstrap/`(`dsh-env-bootstrap` 已并入本包)
# ⇒ 原写法把 `SKILL` 算成 `<dsh-local-env>/references`,快照被写到
# `<...>/references/references/常驻规则-快照.md`(**没人读的幽灵路径**),
# 而真正的快照(脚本同目录那份)**从 2026-09-28 起再没更新过** ——
# 表现为「脚本报 ✓ 已生成」,但 CODEBUDDY.md 新加的 §📐 回复排版**进不去快照**(静默失效族)。
SKILL = os.path.dirname(os.path.dirname(HERE)) # 包根 = <dsh-local-env>
SNAP = os.path.join(HERE, '常驻规则-快照.md') # 与脚本同目录(快照真实所在)
DEFAULT_GOAL = r'E:/ProgramData/AIProject/ai1net-dsh-server/CODEBUDDY.md'
# 要随技能走的章节("动作前必须生效"的那些 + 事故级事实)
SECTIONS = ['## 1. 提问判据', '## 3. 红线', '## 4. 提交边界', '## 5. 规划与执行分离',
'## 6. 并发纪律', '## 8. ']
# ★骨架锚点:这几条丢了就等于规则没了 —— 校验时逐条查存在性(短语取自权威文件)
ANCHORS = [
# 🔴 2026-10-02 校正探针措辞(原 4 条**逐字探针**与 CODEBUDDY.md 现行措辞失配 ⇒ 每次 --check
# 都报 4 处假缺失:A2 / R7-边界 / U27 / L1)。真因=CODEBUDDY.md 在 10-01 被**压缩改写**
# (同一语义换了写法),而探针仍按旧版逐字比 ⇒ **假警报**:会让人以为"规则丢了"、
# 跑去"补"一遍 ⇒ 造出重复的第二份规则。探针**仍是逐字**(保持"能验原文还在"的价值),
# 只是跟上现行措辞;⛔ 不要改成宽松模糊匹配(那会让它恒真 ⇒ 变成空判据)。
('A1', '只问「超过现有判断方法边界」的问题'),
('A2', '禁用征询句收尾'), # 原「禁止用…」→ 现行 CODEBUDDY.md §1 用「禁用」
('A3', '四件或七件套必跑', '占位'), # 由下方 canary 覆盖
('R7', '禁未经确认的批量 / 全仓写入'),
('R7-边界', 'R7 只管「不是我的 lane」'), # 原「R7 只适用于…」→ 现行 §红线表用「只管」
('R9', '绝对禁止「人工删锁 / 接管」'),
('R11', '只做正向迭代'),
('U27', '要解决问题,不将就妥协'), # 原「目标不打折,路径取最小代价」= U27 的上游原话,
# CODEBUDDY.md 里落的是这句(同一判据的现行表述)
('L1', '抢到之前不要动文件'), # 原「先抢全局执行锁」→ 现行 §动作前三条的逐字
('L2', '锁的生命周期 = 任务的生命周期'),
# 🔴 2026-10-02 加:回复排版「强遵循」探针(用户令「所有会话…整合到会话技能中」)
('F1', '强遵循'),
('F2', '已完成的大类放最前'),
('F3', '**表格** / **长散文** / **碎标签堆叠**'),
]
MARK_BEGIN = '<!-- BEGIN resident-rules (generated by skills/dsh-env-bootstrap · 勿手改块内) -->'
MARK_END = '<!-- END resident-rules -->'
# 环境相关项:注入/换机后**必须按新环境核对**(不是"自动配好")
ENV_ITEMS = [
('工作区根', r'E:/ProgramData/AIProject/ai1net-dsh-server'),
('文档库', r'D:/github/dsh_shenxian/dsh-server-docs'),
('代码仓', r'D:/github/dsh_shenxian'),
('备份目录', r'/opt/dsh/backups'),
('服务器', 'bt-server(47.77.182.89,SSH **22**;别名里的 32022 已失效)'),
]
def rd(p):
try:
return io.open(p, encoding='utf-8', newline='').read()
except OSError:
return ''
def section_of(text, head):
"""取 `head` 章节到下一个同级 `## ` 之间的内容(含标题行)。"""
i = text.index(head)
m = re.search(r'^## ', text[i + len(head):], re.M)
return text[i:i + len(head) + (m.start() if m else len(text) - i - len(head))].rstrip() + '\n'
def snapshot(src):
t = rd(src)
if not t:
raise SystemExit('ERROR: 读不到源文件 %s' % src)
parts = []
for h in SECTIONS:
if h == '## 3. 红线':
h = '## 3. 红线 R1' # 实际标题含编号,用前缀匹配
i = t.find(h)
if i < 0:
continue
j = t.find('\n## 4.', i)
parts.append(t[i:j if j > 0 else len(t)].rstrip() + '\n')
continue
if t.find(h) < 0:
parts.append('<!-- 源文件里没有 `%s` 章节 -->\n' % h)
continue
parts.append(section_of(t, h))
body = '\n---\n\n'.join(parts)
head = ('# 常驻规则 · 可移植快照(由 `scripts/resident-rules.py --snapshot` 生成,勿手改)\n\n'
'> **这是「工作区 `CODEBUDDY.md` 关键章节」的副本**,随技能走 ⇒ 换电脑 / 换工作区也能带走。\n'
'> ⚠️ **权威方向单向**:`CODEBUDDY.md` 是权威,本文件是它的副本(重生成用 `--snapshot`)。\n'
'> ⚠️ **环境相关项**(绝对路径 / IP / hooks 路径 / 工具位置)注入后**必须按新环境核对**:见文末「待核清单」。\n\n'
'## 骨架锚点(校验用;丢了就等于规则没了)\n\n')
anch = '\n'.join('- `%s` — %s' % (k, v) for k, v, *_ in
[(a[0], a[1]) for a in ANCHORS]) + '\n'
tail = ('\n---\n\n## 待核清单(换环境后逐项核对,脚本不代改)\n\n'
+ '\n'.join('- [ ] **%s** %s' % (k, v) for k, v in ENV_ITEMS) + '\n')
out = head + anch + '\n---\n\n' + body + tail
os.makedirs(os.path.dirname(SNAP), exist_ok=True)
io.open(SNAP, 'w', encoding='utf-8', newline='\n').write(out)
return len(out), len(parts)
def check(goal):
t = rd(goal)
if not t:
print('ERROR: 读不到目标 %s' % goal)
return 2
snap = rd(SNAP)
if not snap:
print('ERROR: 缺少技能内快照(先跑 --snapshot)')
return 2
print('=== 常驻规则校验|目标 = %s ===' % goal)
bad = 0
for a in ANCHORS:
k, phrase = a[0], a[1]
if phrase.startswith('四件或七件套'):
ok = ('七件套' in t) or ('四件套' in t)
else:
ok = phrase in t
print(' %-10s %s %s' % (k, '✓' if ok else '✗ 缺失', phrase[:40]))
bad += 0 if ok else 1
sec_ok = sum(1 for h in ('## 1. 提问判据', '## 3. 红线', '## 4. 提交边界',
'## 5. 规划与执行分离', '## 6. 并发纪律') if h in t)
print(' 章节存在性:%d/5' % sec_ok)
bad += 5 - sec_ok
print('结论:%s' % ('✅ 关键规则齐备' if bad == 0 else '⚠️ 有 %d 处缺失/漂移 ⇒ 用 --inject(或人工补齐)' % bad))
return 1 if bad else 0
def env_check():
print('=== 环境自检(换机后逐项确认)===')
bad = 0
for k, v in ENV_ITEMS:
if k in ('服务器', '备份目录'):
print(' %-8s %-52s (需 ssh 侧核对)' % (k, v))
continue
ex = os.path.exists(v)
print(' %-8s %-52s %s' % (k, v, '✓ 存在' if ex else '✗ 不存在'))
bad += 0 if ex else 1
# hooks 里的绝对路径(工作区搬迁后最常见的坑)
st = r'E:/ProgramData/.workbuddy/settings.json'
if not os.path.exists(st):
st = os.path.expanduser('~/.workbuddy/settings.json')
try:
h = json.loads(rd(st)).get('hooks', {})
except Exception:
h = {}
cmds = [x.get('command', '') for v in h.values() for it in v for x in it.get('hooks', [])
if x.get('type') == 'command']
print(' hooks 命令 %d 条:' % len(cmds))
for c in cmds:
paths = re.findall(r'[A-Za-z]:/[^\s"]+?\.(?:py|sh|exe)', c)
miss = [q for q in paths if not os.path.exists(q.replace('/', os.sep))]
flag = '✗ 路径失效' if miss else '✓'
print(' %s %s' % (flag, c[:100]))
bad += 1 if miss else 0
return 1 if bad else 0
def inject(goal, init=False):
t = rd(goal)
if not t:
print('ERROR: 读不到目标 %s' % goal)
return 2
snap = rd(SNAP)
if not snap:
print('ERROR: 缺少技能内快照(先跑 --snapshot)')
return 2
body = snap.split('## 待核清单', 1)[0]
block = MARK_BEGIN + '\n' + body.strip() + '\n' + MARK_END + '\n'
if MARK_BEGIN in t:
new = re.sub(re.escape(MARK_BEGIN) + r'.*?' + re.escape(MARK_END) + r'\n?',
block, t, flags=re.S)
io.open(goal, 'w', encoding='utf-8', newline='').write(new)
print('✓ 已替换标记块内内容(块外人工内容未动)')
return 0
if not init:
print('⚠️ 目标里没有标记块 ⇒ **不自动注入**(避免与人工撰写的内容重复成两处)。\n'
' 要建立标记块并注入:加 --init(会**追加**到目标文末,不动既有内容)')
return 1
io.open(goal, 'w', encoding='utf-8', newline='').write(t.rstrip('\n') + '\n\n' + block)
print('✓ 已追加标记块(既有内容未动);建议随后人工去重并 `--check`')
return 0
def main(argv):
goal = DEFAULT_GOAL
if '--goal' in argv:
goal = argv[argv.index('--goal') + 1]
if '--snapshot' in argv:
n, k = snapshot(goal)
print('✓ 已由 %s 生成快照:%d 字符 / %d 个章节 → %s' % (goal, n, k, os.path.relpath(SNAP, SKILL)))
return 0
if '--env-check' in argv:
return env_check()
if '--inject' in argv:
return inject(goal, init=('--init' in argv))
if '--check' in argv:
return check(goal)
print(__doc__)
return 2
if __name__ == '__main__':
raise SystemExit(main(sys.argv[1:]))
@@ -0,0 +1,124 @@
# 常驻规则 · 可移植快照(由 `scripts/resident-rules.py --snapshot` 生成,勿手改)
> **这是「工作区 `CODEBUDDY.md` 关键章节」的副本**,随技能走 ⇒ 换电脑 / 换工作区也能带走。
> ⚠️ **权威方向单向**:`CODEBUDDY.md` 是权威,本文件是它的副本(重生成用 `--snapshot`)。
> ⚠️ **环境相关项**(绝对路径 / IP / hooks 路径 / 工具位置)注入后**必须按新环境核对**:见文末「待核清单」。
## 骨架锚点(校验用;丢了就等于规则没了)
- `A1` — 只问「超过现有判断方法边界」的问题
- `A2` — 禁用征询句收尾
- `A3` — 四件或七件套必跑
- `R7` — 禁未经确认的批量 / 全仓写入
- `R7-边界` — R7 只管「不是我的 lane」
- `R9` — 绝对禁止「人工删锁 / 接管」
- `R11` — 只做正向迭代
- `U27` — 要解决问题,不将就妥协
- `L1` — 抢到之前不要动文件
- `L2` — 锁的生命周期 = 任务的生命周期
- `F1` — 强遵循
- `F2` — 已完成的大类放最前
- `F3` — **表格** / **长散文** / **碎标签堆叠**
---
## 1. 提问判据(唯一一条)
> **只问「超过现有判断方法边界」的问题。**(用户原话)
- **边界内 ⇒ 自决,不要问**:技术选型 / 实现路径 / 命名与数据结构 / 调参 / 部署与同步 / 排查方法 / 版本依赖 / 兼容降级 / 方案取舍 / 文档技术内容。**「部署上线」属此项 ⇒ 做完即上线,不要问**;生产变更**直接做**、只需**动手前一句话说明**(判据 ⇒ **R8**;详 A1/A2)。
- **边界外 ⇒ 必须问**:① 业务目标与优先级 ② 花钱与资源承诺 ③ 对外承诺 ④ 需用户提供的凭据或审批 ⑤ 无客观优劣的偏好 ⑥ 影响面超出本平台 ⑦ 红线门禁 ⑧ 判不准。
- 🔴 **讨论技术不谈法规**:⛔ 不引条文当论据 / 不提合规风险 / 不写进方案与验收判据;**只在你问起、或对象就是"对外承诺 / 资质 / 合同"时才谈**(详 A3)。
- **判据**:有没有**客观可判的优劣**?有 ⇒ 自决,没有 ⇒ 问。**上抛门槛 = 存在真取舍**:候选**只有优点或只有缺点 ⇒ 自己拍掉**;各有优劣才上抛,且**逐项写优点 + 缺点**(详 A4)。
- ⛔ **不许捆包**:要问红线**只问那一句**;技术方案自己定好、当**已定项**陈述。
- ⛔ **禁用征询句收尾**(「要我…吗 / 请确认 / 你看怎么办」)⇒ 按三问重判(真门禁?已定的事又问?真取舍?),没命中就**删掉、自己做完**(详 A5)。
- 🔴 **上抛 / 待拍板内容必须自包含(发送前就按规范写)**:⛔ **作用域 = 一切「要用户拿主意」的输出**(提问 · 末尾待拍板清单 · 候选 · 表格盘点 —— 换形态不豁免)。四要素:① **问题** —— 一句话说清要决定什么(⛔ 不用指代)② **说明** —— 为什么要你定("影响谁 / 断多久 / 花多少钱")③ 每候选写**优点 + 缺点**,末行给**倾向** ④ 一轮一问;⛔ 不出现包名 / 路径 / 变量名 / 类名(详 A6)。
**📐 回复排版(🔴 2026-10-01 用户定稿 · 本条覆盖旧版;六轮迭代后定下,照抄即可,⛔ 别自己另发明)**
- **骨架**:`# 大类`(**已完成** / **待处理任务**)分节 → `## 任务名` 分事 → 每件事写两段:**当前状态** + **待处理事项**。
🔴 **大类标题必须比任务名大一号**(2026-10-01 用户加)—— 大类别用**一级标题 `#`**、字号最大;任务名用**二级标题 `##`**;⛔ 不许大类与任务名同号(同为 `##` ⇒ 层级压平、看不出哪几件事属于同一个大类)。
- **当前状态**:每条一个**圆点**(`- `),**用一句陈述句说重点**;复杂情况、依据、细节放**句末圆括号**里。
- **待处理事项**:用**序号**(`1、2、3、`,不是 `1.`);每条写完整句子,可以不止一句。
- **附件**:本板块若有文件要展示或引用,写在**该板块最末**一行(`附件:<路径>`)。
- **大类顺序**:**已完成的大类放最前**,`待处理任务` 放**最后**。
- **三禁**:⛔ **表格**(=省略讲理,人要来回跳读)|⛔ **长散文**(不是写小说,整篇不分段=没版式)|⛔ **碎标签堆叠**(`- ` 碎片 + 加粗小标题 + `⇒` 串句)。
- 🔴 **强遵循(2026-10-02 · 机制保障见 `session-mechanism` 技能(内 `references/作业规矩/`))**:本节=**每轮硬约束**,命中三禁任一条 ⇒ 该条回复**作废重写**。机器可读副本由技能注入在下方标记块;**每轮注入**由钩子 `reply-style-guard.py` 承担;本环境侧另有逐字探针(`resident-rules.py --check`)。
- 🔴 **用户原话(五条 · 每次纠正改一版,合起来才是完整口径)**:
①「**为什么回复的内容 那么人机 把我都看抑郁了,禁止用表格,全部用文字排版**」
②「**不是只用句子就行了 要排版 不是让你写小说**」
③「**排版不清晰,要有大标题小标题 小标题 多项要段落排版**」+「**段落还有序号**」
④「**当前状态:内容如果有多条情况 按无序段落排版**」+「**圆点符号 无序段落每个段落前要加**」+「**当前状态 每个段落用 一句陈述句说重点,有复杂情况可以放在末尾()中**」
⑤「**如果有对应附件需要展示或引用 放在对应板块 最后**」
⑥「**已完成 待处理任务 这些大类别 用更大字体标题**」(2026-10-01 12:12)
- ⚠️ 本条**只管「给人读的回复」**;注释/日志/解析用字段不受限(给程序读的随便)。
- 🎯 **要解决问题,不将就妥协**(降级 / 延期 / 静默兜底**都不算解决**);🟢 **只做正向迭代**(= R11)(详 A8)。
- 🔀 **冲突裁决序**:① **R8** → ② **§1 边界内自决清单** → ③ **其余红线**(R5 / R7 / R9 / R10 **永远硬约束**);⛔ **冲突 ≠ 门禁**。**上抛前必答三问**:对象是我们自己的资源吗?查证过关键不确定点吗?第一名明显更优吗?任一"是" ⇒ 自决(详 A9)。
---
---
## 3. 红线 R1–R11(任一条命中 ⇒ **先停手**;效率论证不构成豁免)
| # | 禁令 / 判据 |
|---|---|
| **R1** | **不自动升级 dsh** —— 升级须走独立"测试 → 评估 → 修复"流程 |
| **R2** | **不改官方 dsh 主程序与缓存** —— `@deepseek-ai/dsh` **零改动**;扩展只走 profile 层官方插件机制 |
| **R3** | **client bundle 禁 `exports.default`** —— 只导出 `apply` + `inject` |
| **R4** | **不用真实账号测登录** —— 用临时 session(`mksess.cjs` 直插),用完即删 |
| **R5** | **权限只准收窄** —— 凡**扩大**(新挂载 / 放开遮蔽 / 暴露平台目录或 env / 放宽 nft / 提档位)⇒ 先出「权限影响评估」并取得确认 |
| **R6** | **先查已有资产再动手** —— 可用技能 → 本机 / 项目已有技能与记忆 → "本机已有的能否满足" |
| **R7** | **禁未经确认的批量 / 全仓写入** —— 只做被明确要求的事;额外发现**先报告后动手**;禁全库遍历·通配符改写 / 批量权限·换行符改动 / `cp -r` 覆盖 / `git add -A`;**>10 文件 ⇒ 先出清单 + 确认**;**本机不是沙箱**(scp 会传导到生产) |
| **R7-边界** | **R7 只管「不是我的 lane」**:**我 lane 内细节**(部署 / 重启 / 改配置 / 跑自己的脚本 / 改自己的插件)⇒ **直接做,⛔ 别拿 R7 挡箭牌去问**;**别人的 / 归属不明** ⇒ **只报告、不动手**。🔑 判据看**归属**,不看"是不是平台组件" |
| **R8** | **生产变更**:`47.77.182.89` 是**开发环境服务器** ⇒ 重启 / 停 scope / drain / 改配额·env / nginx·nft **直接做**。两条自律:**动手前一句话说明**在动什么 + **不可逆操作**(删数据 / 迁 DB / 清目录)**先报清单** |
| **R9** | **⛔⛔ 绝对禁止「人工删锁 / 接管」** —— 不得删 `交接单/.exec-lock` / `.doing-*`、不得以「持有者疑似已死 / 卡住」为由**单方面接管**;锁**只能由持有者自己释放**(guard 那句「或确认接管后人工删锁」**不构成授权**)。**抢不到锁唯一合规 = 停手 + 报告用户**(**处置权只属用户本人**) |
| **R10** | **⛔ 绝不以 root(或非该实例 uid)运行 / 触碰用户实例的东西** —— ① 验证 / 冒烟 / 探针**必须以该 uid 运行**或进 bwrap 沙箱,⛔ **禁 root 直跑 profile** ② 确需 root ⇒ **收尾必** `find <home> -user root -exec chown <uid>:<uid> {} +` ③ 实例起不来**先看属主 / EACCES,别先怀疑 OOM** |
| **R11** | **⛔ 只做正向迭代** —— 判据(十维:目标 / 方向 / 架构 / 功能 / 性能 / 安全 / 交互 / UI / 便利性 / 扩展性):是否让**任一维净变差**?**命中 ⇒ 立即停下复盘**:写清劣化在哪维、代价多大 → 找**保住正向收益**的做法 → **拿不出 ⇒ 立即停止、只报告**。⛔ 禁三种伪装:说成"必要代价" / "后续再优化" / 藏进交付不写 |
> **R5 / R7-边界 / R8 / R9 / R10 / R11 的解释段 · 事故全过程 · 用户原话 ⇒ 【详】§B-1…§B-5。**
---
---
## 4. 提交边界
**未明确要求 ⇒ 不 commit / 不 push / 不同步仓库**;用户说了才做,且**只 add 自己改的文件**。⛔ **三类禁止入库**(2026-09-21 用户明令):`tmp/` |**中间产物**(`_tmp_seq*/`、`_中间产物*/`)|`$DOC\05-交接单/` 下的**会话交接单**。
- ⛔ **别用 `git status` 判"交接单要不要提交"**(被 ignore ⇒ 不出现,属**预期行为**);确需入库只能显式 `git add -f` 并说明理由。⚠️ 已跟踪的 `05-交接单/README.md`、`archive/**` 不受影响。
- ✅ **落点与入库解耦**:交接单**照旧写** `05-交接单/`(8 段模板不变)只是**不进 Git**;中间产物**一律留 `tmp/` 内**。🔴 **提交前自查** `git diff --cached --name-only` 出现三类中任一 ⇒ **立即 `git reset`**。
---
## 5. 规划与执行分离
规划会话**只产出交接单**(`$DOC\05-交接单/`,8 段必填:目标 / 只读前置 / 范围 / 决策点 / 步骤 / 验收 / 回滚 / 回报格式),**不 ssh、不改码、不重启、不 scp**;落地交另一个执行会话(**不读其上下文**)。
---
## 6. 并发纪律(多会话并行是常态 · 命令与实证全文【详】§C)
- 共享文件**只用 Edit 精确片段替换**(失败 = 天然冲突检测),**禁整文件 Write 覆盖**。**并行度按「冲突域是否重叠」定**:域不重叠 ⇒ **可真并行**;⚠️ **机制层(`config`·`crypto`·`isolation`·`index`·`scripts`·`CODEBUDDY.md`·锁与钩子本身)必须独占**。
- **🔒 开工门禁**:先跑 `bash $DOC\07-scripts\preflight-lock.sh "<会话名>" <目标文件...>` 判可锁定范围。【A】可独立锁 /【B】秒级独占 /【E】机制层 /【C】共享 /【D】未归类。⛔ **【D】或【E】非空 ⇒ `rc=1` 拒开工**(D = 先归类再动;**E = 机制层全平台共用 ⇒ 仅当确认无其他会话在跑才可独占开工**)。
- **三把锁 + 两把秒级锁**(全文【详】§C):**域锁**(默认)`--claim-exec "<会话名>" --domains <域键>`,域键 = `<锚点段>/<下一段>`、多个用逗号|**不带 `--domains` ⇒ 退化独占**(**机制层必走**)|`--claim`|服务器侧 `op-lock.sh claim`;秒级 `--claim-skeleton`(改机制层 / 领迁移号)、`--claim-publish`(commit / push / scp / build)。**完工一律反序释放**(先 `--release`,最后 `--release-exec "<会话名>"` —— ⛔ 不带会话名 ⇒ **拒绝释放**)。🔴 **域键判据 shell 与 hook 两侧必须逐字一致**(`_ANCHOR_SEGS` ⇄ `_DOMAIN_SEGS`),⛔ 改一侧 ⇒ **域锁静默失效(假绿)**。
- 🔍 **抢锁必须"校验结果"不能"看输出"**:① **检查退出码**(不接管道)② 复读 `.locks/<会话名>/DOMAINS` 或 `.exec-lock/OWNER` **并断言是自己的**。⛔ 用 `| grep` 截尾 = **grep 吃掉退出码,也吃掉"抢不到"**。⚠️ `rc=1` 两因分清:域冲突(**停手**)vs `.gate` 占用(**重试**)。⚠️ **「无锁」=「你快去抢」**;⛔ **抢不到就是终点** ⇒ 处置见 **R9**(等释放或报告用户)。
- ✅ **锁只约束「写」不约束「读」**(读文档 / 读码 / 只读命令随时可做);⚠️ **会改本地状态的命令不算"读"**(`git fetch`/`checkout`/`stash`/`reset`/`switch`)⇒ **要持锁**。🔓 **释放时机 = 交付闭环走完**(台账 → 四件套 → commit → 推送 + 对账 → 归档),**不是"改完就放"**(释放一律带会话名:`--release-exec "<会话名>"`,⛔ 不带名 ⇒ 拒绝释放);**要等用户拍板 ⇒ 先释放再等**。🔒 **锁的生命周期 = 任务的生命周期**,⛔ **禁"抢到锁、做一半、不解锁就结束回合"**。**结束语必须对锁状态负责**(写明"已释放",或点名锁仍在谁手上 + 原因 + 下一步)。
- 推送前复跑对账:**「仅本地」里有不在你清单的文件 ⇒ 立刻停手**(幽灵文件);基线数字**必须带取数时间 + 复核命令**。
- **`settings.json` 的 `hooks` 段 = 多会话共享** ⇒ **只能 Edit 增删条目,禁整段覆盖**(覆盖顶层键 = 静默抹掉别人的钩子);**用户级 `MEMORY.md` 同理**。⚠️ **hook =「会话启动时快照」**(对在跑的会话无效 ⇒ 须**完全重启**,**关窗 ≠ 退出**);⚠️ **脚本路径失配 = fail-closed**(Write/Edit 全被拒)⇒ 迁移 / 改名后**第一件事 = 核对 hooks 绝对路径**;兜底 **钩子不拦 Bash**。
---
## 8. 会导致事故的实测事实(6 条速查 · 详解 ⇒ 【详】§E)
> 🔴 **速查(详情 + 后果 ⇒ 【详】§E)**:① 权限档位只在开会话时播种 ② 插件「禁用」= 真卸载 ③ 配额 384 MiB / V8 堆按宿主算 ④ 业务插件只走门户候选池 ⑤ home 写文件走 `UserFs` ⑥ PG 身份键 = `id`。
---
---
## 待核清单(换环境后逐项核对,脚本不代改)
- [ ] **工作区根** E:/ProgramData/AIProject/ai1net-dsh-server
- [ ] **文档库** D:/github/dsh_shenxian/dsh-server-docs
- [ ] **代码仓** D:/github/dsh_shenxian
- [ ] **备份目录** /opt/dsh/backups
- [ ] **服务器** bt-server(47.77.182.89,SSH **22**;别名里的 32022 已失效)