session-mechanism:init_workspace 两处本机适配回补(副本场景起不来)

背景:这两处 2026-10-09 已在某台机器的工作副本上验证通过,但没随仓发布;
2026-10-12 那台机器按「以仓库为准」覆盖本地后,修复丢失。现按仓规补回仓库版。

一、副本场景 SK 回落技能源
  原:SK = Path(__file__).resolve().parent ⇒ 副本(<工作区>/.workbuddy/collab/)下
      没有 hooks/ ⇒ ⑤ 自检加载 hooks/_env.py 直接 FileNotFoundError,整段自检作废。
  现:加 _resolve_skill_dir(),先判 <sk>/hooks/_env.py 在不在;不在就依次到
      CODEBUDDY_CONFIG_DIR 与 ~/.workbuddy 下的 skills/session-mechanism/scripts 找,
      取第一个命中;两处都没有 ⇒ 原样返回,让报错照常暴露(不静默跳过)。
      只拼相对片段,不写盘符字面量(与「脚本是脚本、配置是配置」相容)。

二、collabd --where 归属判据认反斜杠
  原:_ws_ok = ("COLLABD_CONFIG" in 输出) or (ws_s in 输出) ⇒ 恒为 False:
      ① 输出里没有 COLLABD_CONFIG 字样(它写「配置来源」);
      ② 输出全反斜杠,而 ws_s 是正斜杠形态。
      结果这条自检永远打印 ⛔(即便工作区其实认得)。
  现:改「两端都认」—— 正斜杠原样 / 反斜杠形态 / 反斜杠形态经 normcase 归一后
      出现在同样归一的输出里,任一命中即通过。

验证(本机实跑,改动前后各一次)
  · 副本场景 e2e:改前 ⑤ 打印「⚠️ 自检跑不了:FileNotFoundError」;
                  改后 ⑤ 全量跑通,`collabd --where` 认这个工作区 = ✅(rc=0)。
  · 对照脚本:改前 SK=副本目录、hooks/_env.py 不存在、加载 FileNotFoundError;
              改后 SK=技能源、加载 OK。判据 旧=False / 新=True。
  · scripts/selftest.py:改前 110/0、改后 110/0(无回归)。
  · install.py --manifest:77 份文件,语法失败 0。
This commit is contained in:
admin committed 2026-10-12 10:26:05 +08:00
1 parent 051482168f
commit c9e8f0fbb0
1 file changed
+45 -1
+45 -1
View File
@@ -32,6 +32,40 @@ SK = Path(__file__).resolve().parent
DEFAULT_TITLE = "检查会话协作是否运行正常 + 协作机制问题排查与修复"
def _resolve_skill_dir(sk: Path) -> Path:
"""🔴 副本场景 ⇒ **回落找技能源**(2026-10-12 补)。
为什么需要:本脚本会被 `deploy_code.py` 分发成**各工作区的副本**
(`<工作区>/.workbuddy/collab/init_workspace.py`),而副本目录里**只有脚本、没有 `hooks/`**
⇒ ⑤ 自检要加载 `hooks/_env.py` 时直接 `FileNotFoundError`(整段自检作废)。
判据:先看 `<sk>/hooks/_env.py` 在不在 —— 不在就依次到下面两处找,
取**第一个命中**的目录当技能源:
① `CODEBUDDY_CONFIG_DIR` 下的 `skills/session-mechanism/scripts`
(机制里由 `supervise-launch.py` 在进程内设,故副本被常驻拉起时必然命中)
② `~/.workbuddy` 下的 `skills/session-mechanism/scripts`
两处都不命中 ⇒ **原样返回**,让报错照常暴露出来(⛔ 不静默跳过)。
⚠️ 只拼**相对片段**,⛔ 不写任何盘符字面量(2026-10-11 起「脚本是脚本、配置是配置」,
本机专属路径归各技能包自己的 `env/`)。
"""
if (sk / "hooks" / "_env.py").is_file():
return sk
_cands = []
_cfg = os.environ.get("CODEBUDDY_CONFIG_DIR")
if _cfg:
_cands.append(Path(_cfg) / "skills" / "session-mechanism" / "scripts")
_cands.append(Path(os.path.expanduser("~/.workbuddy")) / "skills" / "session-mechanism" / "scripts")
for _c in _cands:
if (_c / "hooks" / "_env.py").is_file():
return _c
return sk
# 🔴 副本场景回落到技能源(理由见 `_resolve_skill_dir` 的 docstring)
SK = _resolve_skill_dir(SK)
@@ -349,7 +383,17 @@ def main() -> int:
_r2 = subprocess.run([a.python, str(_cd), "--where"], env=env, cwd=str(ws),
capture_output=True, timeout=120)
_o2 = _r2.stdout.decode("utf-8", "replace")
_ws_ok = ("COLLABD_CONFIG" in _o2) or (ws_s in _o2)
# 🔴 2026-10-12 修:原判据的两个条件在本机**恒为 False** ——
# ① `collabd --where` 的输出里**没有** `COLLABD_CONFIG` 字样(它写的是「配置来源」);
# ② 输出里全是**反斜杠**,而 `ws_s` 是**正斜杠**形态。
# ⇒ 自检永远打印 ⛔(即便这个工作区其实**认得**),是本条自检的假阴性。
# 现改为**两端都认**,满足任一条即算通过:正斜杠原样出现;反斜杠形态出现;
# 该反斜杠形态经 `normcase` 归一后出现在**同样归一过**的输出里
# (Windows 下 `normcase` 同时折大小写与斜杠 ⇒ 兜住大小写/斜杠两种差异)。
_ws_bs = ws_s.replace("/", "\\")
_ws_ok = (("COLLABD_CONFIG" in _o2) or (ws_s in _o2)
or (_ws_bs in _o2)
or (os.path.normcase(_ws_bs) in os.path.normcase(_o2)))
print(" `collabd --where` 认这个工作区 = %s(rc=%s)" % ("✅" if _ws_ok else "⛔", _r2.returncode))
# 🔴🔴 2026-10-06 收敛(P0-74):载体从 `start-supervise.ps1` 换成 **`supervise-launch.py`**。
# ⇒ 自检一并改:**不再验 ps1、不再验 UTF-8 BOM、不再验模板变量填完没** ——