session-mechanism:接上「遇阻碍 ⇒ 置阻碍 ⇒ 机制暂停」+ 授权检查会话自解除孤儿锁

用户 10-09 两条令:
①「如果 工作区 项目机制 对应的会话异常 导致未解锁的情况下,可以授权 检查会话自解除孤儿锁」
②「其他类型 阻碍 遇到阻碍修改目标状态 暂停机制 让用户决策,不是有这个规则吗」

起因(contentm_agent 实测):一把域锁的持有者会话被 terminated、锁遗留未释放 ⇒ 目标第 4 步 blocked;
R9 一律禁删锁 ⇒ 检查会话连开 11 棒(约 5 小时)每棒都撞同一面墙、零派活,每 30 分钟一棒。
拆开看是三条腿互相锁死:闸③「队列非空」对一条 blocked 恒真;闸① 2026-10-04 收窄时把
sessions-ended 整条腿摘了出去(置了「阻碍」也照样建);结果检查 prompt 又明写「你没有改目标状态的出口」
⇒ 看得见的没权、有权的(目标检查要队列为空)看不见。

改动
- 新增 scripts/lock/orphan-lock.py:孤儿锁「判定 + 解除」的唯一执行面。
  判据查宿主库 sessions.status(只读 SQL):working 一律不动;terminated/error/archived 可解除;
  completed 须静默 >=30 分钟;查不到 sid / 库读不到一律不动(fail-closed)。
- collabd.py
  · 结果检查 prompt 开「一个」状态出口:--set-life 阻碍 --by "<会话名>" --check-why "<一句现状>"
    ("为什么"的旗标是 --check-why,不是 --why —— 后者是 --retire 的,写错会被静默忽略);
    同时把「写明阻碍」的两个出口钉死:台账 --report ... --state blocked --reason +
    NEED-USER.md 里明确喊「需用户介入」。
  · 闸① 改两档:queue-empty 原样(非「进行中」不建);sessions-ended「只拦『阻碍』」,
    「已完成」仍放行(不把 2026-10-04 修好的病搬回来)。docstring 五道闸 -> 六道闸。
  · 两条检查 prompt 都加了孤儿锁判定钩子(判「持有者已退出」才可自解除;判「活着」一律不动)。
- R9 条文加「唯一例外」:工作区 CODEBUDDY.md §3(定义处)、references/rules.md 新增 §10、SKILL.md,
  以及技能包与文档库两份 handoff-guard.sh 的「抢域锁失败」提示。
- selftest.py:新增两个用例(孤儿锁 16 项,含「working 不许动」的变异对照;阻碍档 6 项,
  含「已完成仍要建」的变异对照),并把写在两处的同一判据收成一处(改一处漏一处的实测教训)。
  全套 PASS 108 / FAIL 0。
- references/manifest.md:按「改完包必跑」重算(77 份文件,语法失败 0)。

不在本仓(各自仓内提交):工作区 CODEBUDDY.md、文档库 CODEBUDDY.md 与 07-scripts/handoff-guard.sh。
This commit is contained in:
admin committed 2026-10-09 07:24:14 +08:00
1 parent c36a3f4a50
commit c76f5be36c
7 files changed
+532 -29

No files matched your search

+23
View File
@@ -29,6 +29,10 @@
## 3 锁
- **开工先抢锁**(是"抢"不是"看");**抢不到 ⇒ 停手 + 报告**(红线 R9:⛔ 不删锁、⛔ 不接管)。
- 🔴 **R9 的唯一例外(用户 2026-10-09 授权)**:「工作区项目机制对应的会话**异常**导致未解锁 ⇒ **检查会话**可自解除**孤儿锁**」。
判据**不靠猜**:`scripts/lock/orphan-lock.py` 去宿主库 `sessions` 表读持有者真身状态 —— **只有**
`terminated`/`error`/`archived`,或 `completed` 且静默 ≥30 分钟 ⇒ 可解除;`working` ⇒ **一律不动**。
⛔ 唯一执行面就是这支脚本(`--dry-run` 先看;⛔ 别自己写 `rm -rf` 删锁);⛔ 例外**只给检查会话**、**只覆盖这一种情形**。
- 🔴 **默认一律带域**(`--domains <本工作区域>/`);⛔ 别省略 —— 省略=**全局独占**,别人连域锁都抢不了。
- 🔴 **只有真正"全平台共用"的改动**(配置 / 加解密 / 隔离 / 锁与钩子**本身**、技能文件)才用**独占**。
- 🔴 **释放必须反序且带会话名**:`--release` → `--release-exec "<会话名>"`;⛔ 不带名 ⇒ 拒释放。
@@ -89,3 +93,22 @@
(例:「本方法只出产品视角」+「曾因照英文商业框架产出而跑偏」)。
- ⛔ **别与"事实陈述"混**:「配置里不含本工作区」「该目录不含 `board.py`」是在**描述事实**,
不在本条管辖内 —— 一刀切会把它们误删。
## 10 🔴 遇阻碍 ⇒ 把目标状态改成「阻碍」⇒ 机制暂停 ⇒ 让用户决策(2026-10-09 用户令)
**口径**(用户原话:「**其他类型 阻碍 遇到阻碍修改目标状态 暂停机制 让用户决策**」):
阻碍**解不了**时,正确动作不是反复重试,而是**改目标状态把机制停住、交回用户**。
- **什么叫"阻碍"(三条全中)**:① 队列里那条 `blocked` **确认解不了**
(含跑过孤儿锁判定仍判「不动」的);② 它是在**等人**,不是等某个会话;③ 原因已写进台账与 `NEED-USER.md`。
- **谁去做**:🔴 **结果检查会话** —— 它是**唯一能看见 `blocked`** 的那条腿(靠"队列非空"触发);
「目标检查会话」虽有权改状态,却要**队列为空**才触发 ⇒ 队列里躺着 `blocked` 时它**永不触发**。
⇒ 不给结果检查这一个出口,两条腿会互相锁死、只剩空转(2026-10-09 `contentm_agent` 实测:
连开 **11 棒、约 5 小时、零派活**,每 30 分钟一棒)。
- **怎么做**:`collabd.py --set-life 阻碍 --by "<会话名>" --check-why "<一句现状>"`
⇒ 闸① 随即生效、**不再建检查棒**(这就是"暂停机制")。
⚠️ 「为什么」的旗标是 **`--check-why`**,⛔ 不是 `--why`(那是 `--retire` 的,写错会被**静默忽略**)。
⚠️ 写完**必须回读** `goal.json` 确认(本项目栽过「命令不存在却 rc=0 静默放行」)。
- **怎么恢复**:用户处置完 ⇒ **主会话**跑 `--set-life 进行中` ⇒ 机制自动复跑。
⛔ 阻碍时**不关**后台任务与协作程序(用户口径第②条),只是不派活、不建检查。
- ⛔ **别越界**:「已完成」不归结果检查 —— 那是「目标检查会话」的活(判据是完成度,不是队列)。