Files
dsh_ai1net_server/dsh-server-docs/04-调整方案/69-并发治理落地-commit常态化与服务器侧锁.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

70 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 69 · 并发治理落地(T04):文档库 commit 常态化 + 服务器侧操作锁 + 权限统一
- 日期:2026-09-12
- 触发:用户「多 AI 会话同时执行迭代服务器项目,解决冲突」+ 当日 **3 次实证事故**(两通道并行改同一批文件致内容丢失;规划会话把已归档文件推回服务器制造"幽灵文件";T03 占位 2.5 小时未回填台账)
- 结论一句话:**把"多会话并行"从「靠人记得」变成「靠工具判据」** —— 文档库留下 git 路标、服务器侧加显式操作锁、两级锁进预检脚本,冲突在动手前就能被判定。
- 状态:✅ **已完成**(2026-09-12 15:10,`exec-session-C` 执行;单子 `交接单/T04` 已归档)
> **TL;DR**|文档冲突靠 `git status`/mtime 还能看出来,**服务器态变更看不出来**(`systemctl` 不会告诉你 10 分钟前谁重启过)→ 必须靠显式锁。本档记录这套机制的最终形态与验证证据。
---
## 一、问题(为什么必须做)
| 风险面 | 实证 | 原有防护 |
|---|---|---|
| **文档冲突** | 同日两次「两会话并行改同一批文件」造成内容丢失;编号 37/38 各被两份档案占用 | `handoff-guard.sh` 单级锁 + 全局锁(本档同日加) |
| **文档无路标** | 文档库此前**长期不提交** —— 没有 commit 就无法用 merge 发现撞车 | 本档:commit 常态化 |
| **服务器态无互斥** | 重启 `dshs` 引发用户掉线(档案 58/59 两次报障);改实例 env / 批量铺插件同样无人知会 | 本档:服务器侧操作锁 |
| **代码侧无路标** | 服务器 `/opt/dshs` 有 **13 项未提交**、HEAD 停在 `ebe8075`(档案 56)→ 两小时改造只存在于磁盘,误 `checkout` 即丢 | 本档:代码库留路标 |
## 二、改动(四项,逐条可复现)
| # | 动作 | 落地物 |
|---|---|---|
| ① | **文档库 commit 常态化** | `f14d4e1`(收口:登记档案 57–68 + 6 处记账修正)、`229a762`(补提交积压 13 项)→ `git status --short` **0 项** |
| ② | **服务器侧第二把锁** | `/opt/dsh/state/.op-lock/`(root **700**,内含使用约定 `README`);工具 `scripts/op-lock.sh {claim\|release\|status}`;`handoff-guard.sh` 新增**【1d】**分支 |
| ③ | **权限统一** | `/opt/dsh/docs/交接单` **755 → 700**;`README.md`/`T01`/`T03`/`T04` **→ 600**(对照 `04-调整方案` = 700) |
| ④ | **服务器代码库留路标** | `/opt/dshs`:`ebe8075` → **`06e63ac`**(13 项逐条 add,**禁 `-A`**),`status --short` = 0 |
| ⑤ | **对账工具降噪**(本轮副作用修复) | `docs-sync-check.sh` 的 `find` 增加 `! -path './交接单/.doing-*' ! -path './交接单/.exec-lock*'` —— 此前**只要有人持锁,对账就恒判「仅本地 ❌」**(锁标记被当成内容差异);与 `handoff-guard.sh`【2】的过滤规则对齐 |
**两级锁的分工**(不要混用):
- 本机 **`.exec-lock`(粗)** = 同一时刻只允许一个执行会话动「文档 / 代码 / 服务器」;
- 本机 **`.doing-<单>`(细)** = 这个单归谁做;
- 服务器 **`.op-lock/<操作名>`(生产态)** = 谁正在动线上(跨机可见)。
- **顺序:先抢 `.exec-lock` → 再占 `.op-lock`**;完工反序释放。
## 三、验证(命令 + 期望)
| 项 | 命令 | 结果 |
|---|---|---|
| 文档库路标 | `git -C dsh-server-docs status --short` | **空** ✅ |
| 锁脚本往返 | `bash scripts/op-lock.sh claim t1` → `status` → `release t1` | 占位成功 → `🔴 t1` + OWNER 详情 → 释放后「无人占用 ✓」 ✅ |
| guard 两态 | `bash scripts/handoff-guard.sh`(无锁 / 造锁) | 「✓ 无平台操作锁」/「⚠ 有会话正在动线上 + 🔴 + OWNER」并置 `VERDICT=1` ✅ |
| 权限 | `ssh bt-server 'stat -c "%a %n" /opt/dsh/docs/交接单 /opt/dsh/docs/交接单/*.md'` | `700` + 四份 `600` ✅ |
| 代码路标 | `ssh bt-server 'git -C /opt/dshs log --oneline -1; git -C /opt/dshs status --short \| wc -l'` | `06e63ac` / `0` ✅ |
| 文档审计 | `python scripts/docs-audit.py` | 退出码 **0**、无悬空引用 ✅ |
| 双端一致 | `bash scripts/docs-sync-check.sh` | **一致 122 / 不一致 0 / 仅本地 0 / 仅服务器 0 → ✅**(含清掉锁标记造成的假 ❌)|
**过程中修掉一个自身 bug**:guard 【1d】初版用 `ls | grep -v '^README$'` 取结果,**空结果时 grep 返回 1** → 被判成"服务器不可达(离线)"(假阴性:明明没锁却提示离线)。已改为远端 `|| true` + `__NOLOCKDIR__` 哨兵区分「无锁 / 目录缺失 / 不可达」三态。
## 四、红线遵守
- **R7(禁批量写入)**:代码库 13 项**逐条 add**,未用 `git add -A`;未做任何 chown;未整目录覆盖。
- **R8(中断在线用户须先知会)**:本单**零重启、零停机** —— 只做 git 提交、建目录、`chmod`、新增脚本。实测执行时**服务器无在线实例**(`systemctl list-units "dsh-*.scope"` 为空)。
- **未 push**:文档库与代码库均**只做本机/服务器本地提交**,推送仍待用户明确指令。
- **未改平台运行代码**:本单零功能代码改动(只新增运维工具脚本)。
## 五、回滚
- **提交**:`git reset --soft HEAD~1`(保留工作区);**不要** `--hard`。
- **权限**:`chmod 755 /opt/dsh/docs/交接单 && chmod 644 /opt/dsh/docs/交接单/README.md && chmod 600 /opt/dsh/docs/交接单/T0*.md`。
- **锁**:`rm -rf /opt/dsh/state/.op-lock` + 删 `scripts/op-lock.sh` + 去掉 guard 的【1d】段 + `交接单/README §六` 改回"提案"。
## 六、遗留(未做,需另行决策)
1. **交接单目录属主未统一** —— 目录与 `README`/`T01`/`T03` 属主为 `197108:197121`,只有 `T04` 是 `root:root`。本单只授权 `chmod`;`chown` 属批量写(R7)→ 需单独确认。**影响**:`700` 对该 uid 仍是可读的,未达成"真 root-only"。
2. **本机代码镜像未同步** —— `D:\github\dsh_shenxian` HEAD = `0e141a4`(含 `3567226`)**且自身有 10+ 项未提交** → 与服务器工作区**双向分叉**,`merge --ff-only` 不可能。属"两仓内容取舍"决策,留待用户决定。
3. **`handoff-guard.sh` 未接 CI/cron** —— 目前靠"开工前手动跑",未强制。
4. **服务器侧无操作审计** —— 本档只做互斥,不记录"谁在何时做了什么"。