Files

89 lines
7.1 KiB
Markdown
Raw Permalink Normal View History

# 投递链路 · 错名修复 与「跟进会话长活」口径落地(复核单)
- **线名**:多会话协作机制 · 投递链路(「投不进跟进会话」)
- **本棒**:会话名 `投递链路真因修复` | 2026-10-02 10:0x–10:3x
- **上游**:`接续包_投递链路真因_20261002.md`(md5 `fe714700f43a9ad3c9f6de6ef3c1fd6a`,开工前重算一致 ✅)
- **锁**:改机制层 ⇒ 全程持**全局独占锁**,**收口已释放**(`--release-exec` 回执「已释放全局执行锁」)
---
## 一、结论
1. **P1① 已修** —— 投递「错名」:`_deliver_str` 把 `follow_for_topic()` **已经算准的 `why` 丢掉了**,
把「**有跟进会话、只是都不在跑**」记成 `no-follow-session`(**字面与事实相反**)。
⇒ 已改为**透传 `why`**,`follow-not-live` 与 `no-follow-session` **分开记档**;喊用户文案同步分档。**⛔ 只改可读性,未改行为。**
2. **P1② 已落地(文档层)** —— 按**用户 2026-10-02 09:59 口径**更正:那条「⛔ 禁止把长跑服务放进会话后台任务」
属**过度泛化**;真因是**跟进当时跑在主会话上、与用户发消息抢占轮次**,而解法本来就是**把它独立成一条会话**。
⇒ **跟进独立之后,它自己挂长活载体不再影响用户 ⇒ 允许**,「跟进会话长期活着」=**默认形态**已写入唯一权威文档。
---
## 二、P1① 改了什么(`collabd.py`)
| 项 | 内容 |
|---|---|
| 落点 | `~/.workbuddy/skills/session-mechanism/scripts/collabd.py`,原 `_deliver_str` 的 `if g is None:` 分支 |
| 改法 | `_why = _rft.get("why")` ⇒ `info["skipped"] = _why`;加**兜底**(值不在两个已知档时按 `_want` 是否为空回退)⇒ **⛔ 不制造新档位** |
| 文案 | 按 `why` 分档;`no-follow-session` 再分「**一条 `[跟进]` 都没有**」与「**有 N 条、但都不属这个类别**」(旧文案对第二种会撒谎) |
| 改前依赖核查 | `board.py` **零命中**(仅 `board.html` 注释提函数名)|`goalctl.py:581-583` **两值都已登记**(⛔ 无未登记值风险)|`selftest.py:1006` 断言两串仍在源码里 ⇒ **不破** |
**自证**:`selftest.py` ⇒ **PASS 47 / FAIL 0**(新增 1 例)。
**新增钉死用例**:`selftest.py::投递:错名修复 —— why 透传…`(4 项)—— 临时替 `follow_for_topic`/`need_user` + 补网关口令过 `no-token` 闸,构造「有候选·都不活」与「真·无候选」两种前提。
🔴 **反证(防恒真假绿)**:把修复临时回退成硬编码 ⇒ 该用例**变红**(PASS 46 / FAIL 1)⇒ 已还原并复跑回绿,`TEMP-FALSIFY` 残留 **0**。
**只读现场取证**(`tmp/_why_probe_20261002.py`,⛔ 不取锁、不投递)—— 今天这条路径**仍复现**:
```
_goal_topics() = ['会话协作自检','机制排查与修复']
_scan_follows() = sids=6 by_topic=['会话协作自检','机制排查与修复']
_live_sids() = 2 条
topic='会话协作自检' -> sid=- why='follow-not-live' cand=['57f58ecf'] all=6
topic='机制排查与修复' -> sid=- why='follow-not-live' cand=['6ab1463e'] all=6
topic='' -> sid=- why='follow-not-live' cand=['57f58ecf'] all=6
```
⇒ 这三个 `follow-not-live` **修复前都会被错记成 `no-follow-session`** —— 与接续包 §1 的六层判读链完全吻合。
---
## 三、P1② 落地了什么(`references/architecture.md`,协作机制**唯一权威**)
> 用户原话(逐字):「那是因为之前**跟进就是跑在主会话的**,用户发消息和跟进一起处理会卡,所以才把跟进**独立成一个会话**专门处理」
- ⚠️ **一处纠偏**:接续包写「改**文档库** `02-架构设计/` 定稿」——实查 `D:\github\dsh_shenxian\dsh-server-docs\02-架构设计\` **只有 3 份**(README/分库与权威存储/覆盖网络),**没有协作机制定稿** ⇒ 真正的权威是技能内的 `references/architecture.md`,改动落在这里。
| # | 改动 | 位置 |
|---|---|---|
| ① | 「当前结论」节**加一行**(跟进会话长期活着 = 默认形态) | 表内(原第④类那行之后) |
| ② | 原那条禁令**收窄对象**:禁区=「**用户会在上面发消息的那条会话(主会话)**」,⛔ 不是「会话后台任务」这个形态本身 | 原 `:142` |
| ③ | **新增 §2.3.0e**:默认形态 + **载体优先级表**(常驻程序 > 会话后台任务)+ 后台任务**两个已知代价** + 与 `--supervise` 的**分工表** | 新节 |
| ④ | §4 那条禁令**同步收窄**(⛔ 防「同一事实两处打架」) | 原 §4「第四种」 |
顺手纠正同行一处**过时表述**:「第④类=尚未落地(全库零命中)」⇒ 改为「✅ 解析层已落地(`[跟进]`⇒`role='follow'`)」。
**新判据(一句)**:**「谁把跟进会话带回来」= 自动化**(只有它能开会话);**「谁叫醒它、谁投给它」= 常驻投递**。两者 ⛔ **不可互替** ⇒ 那条"带回来"的排期必须一直在册。
**后台任务两个代价(已写明)**:① 该会话**自己的 idle 钩子被静默压制**(实测被僵尸任务压 6h20m、零日志)② **会话结束即被宿主回收**(历次 8/12/20 分钟)。
---
## 四、⛔ 未处置(下一棒 / 待拍板)
| # | 项 | 状态 |
|---|---|---|
| P2③ | `tmp/supervise-inbox/` 下 `goal.json`/`queue.json` 等被批量清空的来源(`_collabd.log` **零清理记录** ⇒ 外部动作)⇒ 建议给删除动作**加留痕** | ⛔ 未做 |
| P2④ | `S6` 排期 prompt 仍写「每条都有**周期性自动化**作时钟」=旧口径(今已改常驻承担) | ⛔ 未做 |
| P2⑤ | 会话堆积:`automations` **只新建不复用** ⇒ 每轮堆一条(用户 10-02 已抱怨);曾列两方向(取消独立跟进角色/允许协作程序直插 `automations` 行=**双红线**) | 🔴 **待用户拍板,⛔ 不擅改** |
| 新发现 | `references/rules.md:44`、`collab-detail.md:788`、`pitfalls.md P1(613)` 仍带**同款过度泛化**的"别用会话后台任务"表述(与本次修订后口径不一致)⇒ 属**教训记录**,按规矩应**加状态块指向 §2.3.0e**、⛔ 不改正文 | ⛔ 留给下一棒 |
| 记忆 | `.workbuddy/memory/MEMORY.md` **7,988 字符**(上限 **7,650**)⇒ 本棒只做**净减 5**(原 7,993),🔴 **仍超上限,需后续腾挪** | ⚠️ 已知 |
---
## 五、收尾自判 ⇒ 已派下一棒
`tmp/supervise-inbox/advance.md`:「**可派 S5**」+「**S7 在等 S5**」;任务图 S5=`todo`、
S6/S8/S9=`done`、**S7 唯一阻塞项就是 S5** ⇒ 收尾自判判定**有缺口**,已写一行 `automations`:
- **下一棒**:`[协作]-[机制排查与修复]-S5 修主会话可响应`
- **id**:`3872e203-18b9-4a28-8ff8-7b488345c997`(**只来自工具返回值**)
- **排期**:一次性 · 收口 + 4 分钟(`2026-10-02T10:31`)|**工作区** `E:/ProgramData/AIProject/ai1net-dsh-server`
- **节点**:S5「修:主会话可响应」(验收 **V2**;现状 `--tick` 恒判 `target-deaf`)⇒ 完成后派 **S7**(全量验收 V1–V7)