Files
dsh_ai1net_server/交付物/会话哑掉线-收尾报告-20261001.md
admin c1b5e4d966 chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 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/ 知识文件,按口径入库)
2026-10-10 23:13:22 +08:00

9.0 KiB
Raw Permalink Blame History

会话哑掉线 · 收尾报告(2026-10-01)

线:多会话协作机制 · 会话哑掉 | 本棒会话:345e6839(自动化 · 阈值交接棒) 范围:上棒遗留 4 项(一件一件做,做完即停) | 并发锁:本轮持全局独占(机制层),已释放

一、结论(先读)

# 遗留项 结果
1 selftest.py 补「会话哑掉」回归用例 ✅ 已补 2 条;python selftest.py PASS 37 / FAIL 0(基线 35 + 新增 2)
2 board_ext.py 清退役文案 ✅ 已清 2 处(详见 §三)
3 已哑主会话 f8a792ab 的归属 ⛔ 未动 —— 取证后判不准,按任务书报用户(详见 §四)
4 报告 + 释放锁 ✅ 本报告 + 锁已 --release-exec

二、遗留 1:回归用例(⛔ 不碰生产)

新增到 ~/.workbuddy/skills/multi-session-collab/scripts/selftest.py:

用例 判据
哑会话:诊断日志 ≥ 9.5 MiB ⇒ _deaf_sids() 判哑 ① ≥9.5 MiB 判哑 ② 9,499,999 B(差 1 字节)不判哑(边界)③ KB 级不判哑 ④ 结果恰好只有那一条
哑会话:投递命中已哑目标 ⇒ skipped=target-deaf ① 判读=target-deaf ② 投递台账零增量 ③ 已把喊话落到 NEED-USER.md

怎么做到不碰生产:_deaf_sids() 每次调用现读 CODEBUDDY_CONFIG_DIR ⇒ 用例把它临时指到 tmp/selftest/fake-cfg/(用 truncate 建稀疏文件拿到 10 MiB 体积读数,不真写),跑完 finally 还原 (_db() 也读这变量,不还原会把后面的用例一起带偏)。元用例「本测试不碰生产」仍全绿。

三、遗留 2:board_ext.py 清掉的 2 处退役文案

文件:E:/ProgramData/AIProject/ai1net-dsh-server/.workbuddy/collab/board_ext.py

处 原文 改成 为什么
文件头 「手机接入」线的看板扩展 「本机协作」的看板扩展 「手机接入」是已退役线名(用户 2026-09-30:「后面也不叫手机接入」);现行目标名=goal.json 的「本机协作」
chip① 标题 dsh-client · 设备接入 · 本地中转 :20090 dsh-plugin-ai1net · 设备接入 · 本地中转 :20090 dsh-client 在此是退役包名:原 @dsh-client/device-shim 已退役,2026-09-29 归并进 dsh-plugin-ai1net/lib/device-access.js(模块⑥「设备接入」)⇒ 换成现承载方真名

验证:py_compile 过;直调 build() 打印面向用户文案 ⇒ 「手机接入」0 命中、「垫片」0 命中,chip① 已显示新系统名。 保留未动(判据=有客观可判的取舍,⛔ 不擅自扩大):

  • 「本地中转」是 2026-09-30「说人话」批量替换有意定下的说法(术语对照表 | 本地反代 | 「本地中转」 |)⇒ ⛔ 改回去会推翻那次决定。
  • chip② dsh-client · 覆盖网络节点 · 中继客户端 属另一条组件(覆盖网络线),其系统名本轮未取证 ⇒ ⛔ 不确定不改。
  • :20090 裸端口是真读数(netstat/日志真值),⛔ 不是抽象词 ⇒ 保留。

四、遗留 3:f8a792ab 归属 —— ⛔ 未动,报用户

取证(只读):

会话 标题 状态 诊断日志
f8a792ab 检查多会话协作机制并修复问题 completed(08:55) 今天 10.0 MB ⇒ 已哑 🔴
a202550c 主控 · 唤醒机制线 · … completed(07:13) 昨天 10.0 MB 🔴/今天 4.2 MB(已轮转恢复)
345e6839 主控 · 协作机制 · 阈值交接收尾 working 1.8 MB ✅
  • 协作登记 collabd-state.json 里 roles.main = f8a792ab(陈旧,它已结束且已哑)。
  • 本会话 345e6839 就是唯一带「主控」前缀的活会话,而它是自动化会话(is_background_automation=1,用户看不见、不可接续)。

⇒ 工作区当前没有任何「活的且可接续」的候选主会话 ⇒ 改认谁都是错的(把通知投给用户看不见的会话 = 比现在更糟)。 ⇒ 按任务书「判不准 ⇒ 报用户,⛔ 不要自己动」:本轮未改 roles、未归档任何会话(宿主库 sessions 属活库,⛔ 更不碰)。

🔴 需用户拍板的一件事(下一节单列)。

五、本轮新发现(不在清单内,⛔ 未动手,仅登记)

_deaf_sids() 扫的是 今天+昨天 两个日期目录。而宿主日志是按天分目录(logs/<日期>/sdk/conversations/), 昨天的文件是历史、永远不会再增长 ⇒ 任何「昨天撞过 10 MiB 上限、今天已正常轮转」的会话,会被永久判哑。

  • 实证:a202550c 昨天 10,485,758 B、今天 4,354,629 B(宿主今天仍在写它) ⇒ 它没哑,却仍被判哑。
  • 后果是方向相反的新假绿:本该投递的目标被拦下 ⇒ 通知落空。09:12 那条 NEED-USER(称 a202550c 已哑)即由此而来。
  • 判据收窄的取舍(留给下一棒/用户):只认最新一天(今天)—— 好处是消除上述假阳性;代价是「跨天后还没写过日志」的会话当天扫不到(它当天没写 = 也没在增长,影响有限)。
  • ⛔ 本轮未改:超出 4 项清单,且属机制层(改后须重跑 selftest)。

六、上一棒改动清单(⛔ 未 commit)

文件 改动
~/.workbuddy/skills/multi-session-collab/scripts/selftest.py +2 用例(+_fake_cfg/_with_fake_cfg 工具 + DEAF_MIB 常量)
…/.workbuddy/collab/board_ext.py 2 处退役文案

锁状态:上一棒持全局独占 → 已 --release-exec "会话哑掉收尾"。

七、本棒(接续会话)已修:_deaf_sids() 永久判哑(2026-10-01 09:2x–09:4x)

来源:本线接续会话(上一棒 345e6839 达阈值按 §1.5 G 开的接续会话,顶替主会话职能)。 锁:机制层 ⇒ 全局独占。

改了什么(~/.workbuddy/skills/multi-session-collab/scripts/collabd.py::_deaf_sids()):

旧 新
判据 今天+昨天 任一 ≥9.5 MiB ⇒ 判哑 每个会话取它最新一天那份日志 ≥9.5 MiB ⇒ 判哑
  • 🔴 旧写法的病:宿主会话日志按天分目录、昨天那份永不再增长 ⇒「昨天撞过上限、今天已正常轮转」的会话被永久判哑 ⇒ 本该投出去的唤醒被静默拦下(方向相反的新假绿)。
  • ⚠️ 今天的兜底保留:某会话今天没有日志(宿主今天没写过它)⇒ 仍退到昨天那份判 —— 比"直接放行"保守。

生产数据实测(只读,⛔ 未跑 --tick):

  • 旧判据 7 条哑 → 新判据 6 条哑;唯一被收窄掉的正是 a202550c(昨天 10.49 MB / 今天 4.35 MB,宿主仍在写)✅
  • f8a792ab(今日 10,485,715 B)仍判哑 ✅ —— 第一轮那道闸没有被削掉。
  • 副作用面=零:主会话解析(旧 vs 新)结果逐字相同(5f607d3e · prefix:主控)。

回归用例(scripts/selftest.py):+1 条「只认最新一天」(昨 10 MB/今 4.2 MB ⇒ ⛔ 不判哑;今天才撞上限 ⇒ 判哑;只有昨天 ⇒ 仍判哑;含精确集合断言)。

  • _fake_cfg() 增 day_offset(0=今天 / 1=昨天);_prepare() 每轮清空 tmp/selftest/fake-cfg(防"第二轮才红"的跨轮污染)。
  • ✅ python selftest.py ⇒ PASS 38 / FAIL 0(基线 37 + 新增 1);连跑两次均绿。

顺带修掉一条环境假红(⛔ 与本次改动无关,是既有用例的前提覆盖不全):「僵尸对账」用例只靠 adopted 反推前提的一半, 而僵尸分支的完整前提是「除观察者外无人在跑」∧「无 IN_PROGRESS 运行」 ⇒ 自动化会话跑本自测时,它自己的 automation run 必然 IN_PROGRESS ⇒ 前提不成立却不 SKIP ⇒ 必然假红(实测:收窄前整套 36/1,只有本条红)。 ⇒ 照该用例既有的"前提不成立就 SKIP"姿势补上后一半(纯测试侧,⛔ 未动生产逻辑)。

七-b 本棒改动清单(⛔ 未 commit)

文件 改动
multi-session-collab/scripts/collabd.py _deaf_sids() 判据收窄为「每个会话只认最新一天」
multi-session-collab/scripts/selftest.py +1 用例「只认最新一天」;_fake_cfg(day_offset);_prepare() 清 fake-cfg;僵尸用例补 SKIP 前提

⛔ 未做(不属本棒清单,如实挂着):未 commit/push(未获指令);未把技能本机→服务器单向推(改的是技能, 两处落点 ~/.workbuddy/skills/ 与服务器副本需 md5 双端一致,留给后续按 §1.5 B 阶段 5 处理)。

锁状态:本棒持全局独占(机制层 --claim-exec "5f607d3e")→ 已 --release-exec "5f607d3e";服务器侧那把 storyforge-e2e 操作锁属他人,按 R9 未动。