Files
dsh_shenxian/dsh-server-docs/04-调整方案/125-会话接续机制-问题复盘与修复.md
T
admin 04776af4b1 docs: 工作区根项目文档批量入仓(04-调整方案 113–128 / 交接单 T09–T21 / ops / archive)
起因:用户 2026-09-17 明确「所有文档都要同步,都放在开发仓库 docs 对应文件夹下」。
判据:工作区根 *.md 中在仓库(git ls-files --quotepath=false)搜不到的那些。

入仓 33 份(一律复制,工作区根原件保留不动,避免引用断链):
- 04-调整方案/113–128(16 份 · 原子占号后落盘):覆盖网络 传输方案取舍 / 应用场景与待完善清单 /
  插件化vs改内核 / 问题逐条推演 / 参数表与观测口径;会合中继拆分取证与改造方案;
  集群化改造方案 Manager-Worker;跨节点迁移与节点自举;项目代码分层范式与迭代风险评估;
  搬运与共享重建方案 guest w47→w106;方案规划方法提炼;文档无效信息审计报告;
  会话接续机制复盘与修复;会话接续规范;dsh 客户端化部署方案;dsh 桌面客户端开发方案
- 交接单/archive/交接单-已完成/T09–T21(13 份 · 覆盖网络线已完成单归档)
- ops/(2 份运行态指针:接续入口 / 接续包 · 覆盖网络线)
- archive/(2 份临时与内部简报)

已排除(无需重复入仓):覆盖网络线 10 份方案正文已入档案 103–112(文件名不同)。

登记:INDEX.md §二 新增 04-113–128 共 16 行 + §四 追加 T09–T21 说明 + 机器摘要行刷新
(⛔ 未跑 docs-index-stats.py --write:该脚本会按 \r\n 归一化全文件行尾,故改为字节级单行替换);
README.md 追加 1 条入仓指针;docs-manifest.json 复跑 scripts/docs-manifest.py 刷新。

验收:工作区根 47 份 .md —— 同名已入仓 8 / 本次内容一致 29 / 已知改名映射 10 / 未入仓 0;
git status 待提交清单只含本次新增与登记 3 件(未涉 src/ 与 relay 代码面)。
2026-09-17 18:24:19 +08:00

10 KiB
Raw Blame History

会话接续机制 · 问题复盘与修复(2026-09-16)

结论一行:机制本身(规范 §3.1.1 / §3.1.2 / §3.2.1)没错,错在它没有被接上 —— ① 真正跑的那条自动化 prompt 没带"开机四步";② 硬环节的注入文案还停在"请用户开新会话",从不提 automation_update;③ 开机第一屏有可能喂过期事实。 触发:用户 2026-09-16 14:41 原话「决策方法 之前建立的机制有问题,看看自动任务新建的会话对话记录」。 取证范围:~/.workbuddy/projects/e-ProgramData-AI技能-aliyun-dsh-server/{3814f5fb,e265f0cd,478eef8c,d48a9be8}.jsonl + workbuddy.db(automations / automation_runs / session_usage)+ state.py 实跑 + stop-dialog-guard.py 源码。


一、今天的自动任务新建会话 —— 花了多少、干了什么

会话 自动化 轮 工具调用 积分 用户当场说了什么
3814f5fb 归档接续 5d1dc22c @10:20 2 65 21.34 「是否知道那个会话创建了这个你,是否有执行那个会话待处理的任务」
e265f0cd 接续(优化版) 4a3d815b @10:45 1 32 8.93 —
478eef8c 决策方法-2 218e5b11 @11:10 5 191 74.80 机制就是在这一条里定的(14 条用户发言)
d48a9be8 S1 落地 d30f3cf7 @14:32 2 40 9.37 「是不是应该先确认待执行的任务有哪些 再去执行,不确定你搞清楚情况没有」
合计 328 114.44
  • 积分口径 = 转录 rawUsage.credit 逐次求和;与 session_usage.credit_json 三处完全吻合(d48a9be8 9.37 / e265f0cd 8.93 / b08b1c35 33.71),两个独立数据源对上 ⇒ 数字可信。
  • 用户观察「自动任务新建的会话,提一轮就 7、8 个积分」成立:e265f0cd 单轮 8.93、d48a9be8 首轮 5.28。
  • d30f3cf7 立项时的验收口径是与基线 b08b1c35(77 次 / 11.17 分)对比,目标 ≤10 次 / ≈1 分(见 478eef8c A72)。实测 40 次 / 9.37 分 ⇒ 未达标。

二、四个真问题(按严重度)

D1 🔴 生成自动化 prompt 的那一步没接上机制 —— 主因

规范 §3.2.1 要求 prompt 写死"开机四步 + 工具调用上限"。实际跑在 d48a9be8 上的那条 prompt:

  • ✅ 有「本轮只做一件事,做完即停」「取证最多 3 条」(§3.2.1 ④⑤)
  • ❌ 没有接续包路径、没有校验命令、没有「先跑 state.py」
  • ❌ 反而把整段 S1 技术细节(≈1.2 KB)抄了进去 —— 而细节的单一来源本是 交接单_覆盖网络落地执行_20260916.md

⇒ 结果:新会话手里既没有"从哪接班",也没有"上限是几次",只能自己从零探索。同一件事被写了两遍(prompt 与交接单),真源被架空。

D2 🔴 开机顺序反了 —— 用户看到的就是这一步

d48a9be8 的 40 次调用里:

  • [01] 读 automation memory(不存在,首次运行)
  • [02]–[15] 读交接单、读架构文档、抢锁、10 次连续读码探索
  • [16]–[36] 改码 → build/test → scp → 重启 → 验收 → 写记忆 → 清临时文件
  • [37] 才第一次跑 state.py;[39] 才第一次读 交接单/README.md §一(待执行清单)

⇒ 机制设计的第 0 步(1 次调用代替十几轮探索)被排到了倒数第 4 步。用户当场质问「是不是应该先确认待执行的任务有哪些再去执行」,AI 也在下一轮自认「顺序错了」。 ⚠️ 补充:state.py 确实能给出答案 —— 它的 [入口] 段 14:43 实跑就写着"3) ✅ S0 已完成 …… 5) 下一步 = 按交接单执行 S1"。跑对了就不会有这一问。

D3 🔴 硬环节的注入文案停在旧版 —— 自动接续没有触发源

scripts/stop-dialog-guard.py 三级(≥30 万)注入原文(修复前):

③ 然后明确告知用户「请开新会话,接续点在 X」,**由用户开**(钩子无法自动创建会话)。

而规范 §3.2.2 画的链路里,第三段是 [软] 模型调 automation_update 登记一次性任务(+2 分钟)。 ⇒ 钩子从不要求模型登记自动化 ⇒ 这条"软"环节连提示都没有,全凭模型自觉。今天 4 条自动化全是会话内临场手写 prompt 的结果 —— 这正是 D1 的来源。

D4 🟡 开机第一屏可能喂已被推翻的事实

state.py 的 [收口] 段是"今日日志原文摘录",机械取最后一个含「接续/收口」的章节。实测 14:43 输出里带着两条当天已被勘误的说法:

  • 「两个『定时』自动化仍在按钟点烧钱」—— 实为 09-12 / 09-13 已软删除、早已停摆;
  • 「转录里的 rawUsage 字段为空 {}」—— 实为有值(本次积分就是这么算出来的)。

另外 state.py 的 [入口] 文件名写死为覆盖网络线那一份 ⇒ 换工作线后会静默展示旧线的待办。

D5 🟢 一次性 automation 的 memory.md 是死重量

宿主系统提示强制"先读 automation memory.md、收尾写回"。但一次性任务只跑一次 ⇒ 首轮必然读不到(d48a9be8 [01] 就是白跑一次),写回的那份永不再被读。已知设计面,无法改宿主,只能靠 prompt 一句"该文件不存在属正常"省掉一次调用。


三、已落地的修复(本轮,全部在我们自己的资源上,可推翻)

# 文件 改了什么
F1 会话接续规范_20260916.md §3.1.2 新增第 0 步:先跑 state.py(1 次调用拿到 [锁]/[git]/[入口=待办+接续包位置]/[收口])⇒ 回答"我该接谁的班"
F2 会话接续规范_20260916.md §3.2 新增硬约束 「⛔ prompt 里不许复制任务细节」(会造第二漂移源 + 挤掉开机四步),附 d48a9be8 实测
F3 会话接续规范_20260916.md §3.2.1 模板首行加 ⓪ 先跑 state.py
F4 dsh-server-docs/scripts/stop-dialog-guard.py 三级注入 ③④ 改为:登记一次性 automation(照 §3.2.1 模板)→ 做不到才让用户开
F5 state.py ① [收口] 加"日志原文摘录、可能已被推翻、以 MEMORY.md 状态层为准"护栏;② [入口] 改为自动取最新的 接续入口_*.md,不再写死

✅ 验证:stop-dialog-guard.py py_compile 通过、新文案渲染正确;state.py 实跑通过(护栏行已出现在过期说法之前,[入口] 动态解析正常)。


四、重测结果(14:55 一次性自动化,已跑完,达标)

口径 失败轮 d48a9be8(14:32) 重测 d5398c7d(14:55)
工具调用 40 次 6 次 ✅(预算 ≤8、验收线 ≤10)
积分 9.37 1.69 ⚠️(目标"≈1 分"未完全达到,但比失败轮省 82%)
是否先跑 state.py 第 37 次调用才跑 第 2 次(第 1 次是宿主强制的 automation memory,文件不存在)
是否先确认待执行清单 第 39 次才读到 首屏即由 state.py 的 [入口] 段给出,并复述了"未完成/下一步"

重测会话自报的两处可再省:① 用带 emoji 的完整标题串 grep 未命中、要用子串再 tail(多 1 次);② ⓪ 与 ① 是同一命令,本可合并(多 1 次)⇒ 理想路径 4 次。 ⇒ 机制已闭环:改动只落"接不下班"这一侧,效果可归因。剩余可选项见 §四-2。


五、还没做 / 需要条件的

  1. prompt 生成仍未强约束:现在靠"模型记得照模板写"。要彻底硬起来,需要一个 gen-continuation-prompt.py <接续包> 生成器 + 钩子文案里写死"照它的输出原文"(本轮未做,属新造工具)。
  2. state.py 的 [入口] 只覆盖"最新一份接续入口",多条工作线并行时仍会漏(当前只有一条线,够用)。
  3. D5 无法从我们这侧解决(宿主行为),已记录,不列为待办。
  4. state.py 的 [收口] 护栏只是"提醒",不是"过滤" —— 更彻底的做法是让它只摘"判据/结论"行、或与 MEMORY.md 状态层比对;本轮先用最低成本方式止血。

六、多线并行会不会冲突(2026-09-16 15:2x · 用户提问)

用户原话:「假如多个会话都要新建会话,新会话全都执行这个口令吗,会不会冲突」

会 —— 三种形态,真正会咬人的是 ①。

# 形态 机制现状 处置
① 串线 —— 口令不带线名,而 state.py [入口] 原只取"最新一份接续入口" ⇒ 多个新会话都跑同一条线,另一条线没人跑 🔴 真会发生(今天只有一条线,属潜伏) 口令必带线名;[入口] 已改为列全各线
② 抢锁 —— 同时动手只有一个抢到,输家"停手"白烧一轮 ✅ 全局锁兜底,不会同时改 读前置可并行(都只读);输家只报告
③ 共享文件互覆 —— 日志 / MEMORY.md / 文档库 / 代码仓全平台共用 ⚠️ 靠纪律(实测今日日志有 15 个接续点/收口章节) 只追加自己的小节(小节名带线名)

已修(3 处)

  • state.py:[入口] 列全所有 接续入口_*.md(多线时打 ⚠️"只走你自己那条");[收口] 追加"最近 3 个接续点标题";末尾直接打印带线名的口令。
  • 规范 新增 §3.4「多线并行:怎么不打架」(三形态表 + 四条硬规则:一线一份接续入口 / 口令必锚线名 / 同一时刻只许一个自动会话动手 / 抢不到锁=正常信号只报告)。
  • 规范 §3.2 硬要求 四条 → 五条(新增"prompt 必须锚定线名");§3.2.1 模板 ⓪ 改为"按 [入口] 里**「<线名>」那一行**定位接续包"。

新口令(state.py 末行自动打印,直接抄给新会话)

跑 `state.py`,按 覆盖网络线 那段 §2 第 1 条开工

⇒ 单线时它和旧口令等价;多线时这一步就决定了新会话走哪条线,不会串。 ⛔ 反过来:automation_update 的 prompt 里只写"按 §2 第 1 条开工"= 埋雷(多线起来的那天才会炸,且很难归因)。