- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次) - .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…), 目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪 - .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/) - .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*) - .gitignore 补:备份件(*.bak-*) - 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
guard/ —— 本工作区专用的 hook 副本(已于 2026-09-22 退役挂载)
🔴 2026-09-22 状态变更:本目录的两条挂载已撤下
退役原因:本目录的存在理由(源脚本作用域写死成单工作区)已被消除。 用户 2026-09-22 拍板「B」后,源脚本
dsh-server-docs/scripts/{skill,stop-dialog}-guard.py自己改成了多作用域(_SCOPES_DEFAULT含aliyun-dsh-server+dsh-ai1net-desktop, 且支持 envDSH_GUARD_SCOPES)⇒ 源脚本单条即可覆盖本工作区。若两套继续并存 ⇒ 本工作区每轮收到两份完全相同的注入指令 (2026-09-22 实测:副本与源脚本在同一秒各写一条
HIT,时间戳逐字相同)。 ⇒ 已从全局settings.json的hooks.UserPromptSubmit撤下本目录的 2 条。 备份:E:/ProgramData/.workbuddy/settings.json.bak-20260922-061649-retire-desktop-replica⛔ 本目录保留作"回滚锚点"与历史记录,未删除。 需要重新启用时: 把本目录两条 command 加回
settings.json的hooks.UserPromptSubmit,并完全重启 WorkBuddy。 ⚠️ 重新启用前请先确认源脚本的_SCOPES_DEFAULT不再含dsh-ai1net-desktop(否则又会双注入)。下面 §1–§9 是退役前的历史说明,保留供追溯。
本目录是
dsh-ai1net-desktop的 hook 作用域副本,2026-09-17 建立。 ⛔ 不要手改skill-load-guard.py/stop-dialog-guard.py—— 它们是生成物,下次同步即被覆盖。要改就改源脚本。
1. 为什么要有这个目录(历史)
源项目 aliyun-dsh-server 的两个 hook 脚本把作用域写死成单个工作区:
SCOPE = 'aliyun-dsh-server'
...
if SCOPE not in tp: return # stop-dialog-guard.py
if not workdir or SCOPE not in workdir: return # skill-load-guard.py
⇒ 本工作区被一律判为"作用域外",这两条钩子静默空转(日志里 in_scope=False)。
按用户 2026-09-17 的决定:不改源项目脚本(那是别人的 lane,且在全局执行锁保护下), 改为在本工作区新建副本 + 同步机制。
第 3 条脚本
bash-output-guard.py不在本目录 —— 它没有任何作用域门禁,对所有工作空间生效,无需副本。lock-guard-hook.py按文件路径(文档库 / 代码仓)判定,与本工作区无关。
2. 三个文件
| 文件 | 角色 |
|---|---|
sync-scoped-guards.py |
同步器(手写、可改):读源脚本 → 只变换「作用域」那一层 → 写副本 |
skill-load-guard.py |
副本(生成物)—— 用户点名方法时注入"必须加载技能" |
stop-dialog-guard.py |
副本(生成物)—— 注入收尾征询句纠正 / 分级水位 / 门禁·路径自检 |
状态文件:.guard-sync-state(记录每个副本对应的源脚本指纹,用于判定是否需要重新生成)。
3. 同步机制(三重,正常情况下无需人工介入)
| # | 触发 | 动作 |
|---|---|---|
| 1 | 自动(主路径) | 副本每次被宿主调用时执行 self_refresh() ⇒ 比对源脚本指纹 ⇒ 有变化就地重新生成。⚠️ 带廉价前置判断:只在本工作区的会话里才真跑,其他工作区直接 return(不 spawn 子进程、不留痕) |
| 2 | 手动 | "<python>" sync-scoped-guards.py(--force 无视指纹强制重生成) |
| 3 | 检查 | "<python>" sync-scoped-guards.py --check —— 只报状态、不写盘 |
因为副本自己会在每次调用时自检,不需要额外的定时任务(等价的"持续同步",比"定期同步"更及时且零成本)。
4. 变换规则(只动作用域,其余逐字保留)
SCOPE = '<单值>'→ 提升为文件头的_scopes()/_in_scope()(可用 envDSH_GUARD_SCOPES覆盖,逗号分隔)SCOPE not in <expr>→not _in_scope(<expr>)SCOPE in <expr>→_in_scope(<expr>)- 在
if __name__ == '__main__':前挂一行self_refresh()
叠加修正 C1(本工作区专有,幂等):源脚本 session_budget() 在「文件超大 / 不存在」两个分支
return None, None(2 值),而正常分支 3 值、调用处按 3 值解包 ⇒ 转录缺失时抛 ValueError。
源项目因作用域提前 return 而从未暴露;本工作区打通作用域后即成为每轮可达路径 ⇒ 生成时补齐为 3 值。
(源脚本若自行修复,本规则自动失效,不会重复动手。)
5. 安全设计
- 生成后再校验:
ast.parse通过 + 变换后不得残留裸SCOPE⇒ 才落盘 - 原子替换:写
.tmp后os.replace(并发调用不会读到半截文件) - 失败不动盘:源文件缺失 / 变换失配 / 语法不过 ⇒ 保留旧副本 + 非零退出码,绝不写坏
- 只读源项目:只读源脚本、只写本目录;⛔ 永不修改源项目
- 跨工作区零副作用:
self_refresh()有前置判断;副本的 scope 判定会让其他工作区直接 return
6. 挂在哪儿 / 怎么生效
两条副本已追加进全局配置 E:\ProgramData\.workbuddy\settings.json 的 hooks.UserPromptSubmit
(现有 2 条源项目脚本之后,共 4 条)。备份:settings.json.bak-20260917-guard。
⚠️ hooks 是应用启动时的快照 ⇒ 新增条目必须完全重启 WorkBuddy(关窗 ≠ 退出)才加载。 (但脚本内容的改动不需要重启 —— 每次调用都现读磁盘。)
本工作区配套:.workbuddy/stop-guard-mode = inject(缺省 probe 只记日志、不注入提醒)。
7. 常见操作
PY="E:/ProgramData/.workbuddy/binaries/python/versions/3.13.12/python.exe"
G="E:/ProgramData/AI技能/dsh-ai1net-desktop/.workbuddy/guard"
"$PY" "$G/sync-scoped-guards.py" --check # 看状态
"$PY" "$G/sync-scoped-guards.py" # 同步(源变才动)
"$PY" "$G/sync-scoped-guards.py" --force # 强制重生成
回滚(三档,从轻到重):
- 临时收窄:设 env
DSH_GUARD_SCOPES=aliyun-dsh-server - 单点急停:本工作区建
.workbuddy/skill-guard.disabled,或设 envDSH_STOP_GUARD_OFF=1 - 彻底卸载:把
settings.json里那两条 command 删掉(或整体用.bak-20260917-guard还原),再删本目录
8. 扩展:再加一个工作区
在源脚本里扩展(推荐,一份实现)只改 3 处定义 + 判定;
或用本目录的方式:把新工作区加进 TARGETS 之外的 —— 只需把该工作区的路径标记传给生成器:
DSH_GUARD_WS_MARK=新工作区名 "$PY" "$G/sync-scoped-guards.py"
⛔ 若采用后者,不要原地覆盖本目录(会串作用域)—— 复制整个 guard/ 到新工作区的 .workbuddy/ 下再生成。