diff --git a/session-mechanism/scripts/hooks/wb-result-hook.py b/session-mechanism/scripts/hooks/wb-result-hook.py index 961a03c..df35156 100644 --- a/session-mechanism/scripts/hooks/wb-result-hook.py +++ b/session-mechanism/scripts/hooks/wb-result-hook.py @@ -63,6 +63,40 @@ LEDGER_MAX = 8 * 1024 * 1024 # 8 MiB 就停写(留痕,不删) # ⇒ 本脚本 spawn 的一切子进程**一律隐窗**(非 Windows 上该标志无意义 ⇒ 取 0)。 HIDE = 0x08000000 if os.name == "nt" else 0 # CREATE_NO_WINDOW + +def _sm_load_roots(): + """把本包 `env/roots.env` 注入进程 env(宿主已有的**不动** ⇒ `setdefault`)。 + + 🔴 2026-10-14(用户令:「会话技能中 能用相对路径的都要用相对路径」): + 本文件原先把「大项目根」写死成 `e:/programdata/aiproject/`(盘符 + 用户名写进代码) + ⇒ 换机 / 换用户目录就全错,而**域外过滤会静默走偏**(把自家会话判成"域外")。 + 判据分两半: + · **能**从本包位置推出来的(`scripts/`、`boards/` 这类)⇒ 从 `__file__` 上跳推导; + · **不能**的(大项目根 —— 技能包在配置目录下,跟它没有任何相对关系) + ⇒ 读本包 `env/roots.env` 的 `DSH_AIROOT`(`install.py` 生成,不入库)。 + ⚠️ 本文件在 `scripts/hooks/` ⇒ 到包根要上跳**三级**。 + """ + _here = os.path.dirname(os.path.abspath(__file__)) + for _up in range(6): + _base = os.path.normpath(os.path.join(_here, *([".."] * _up))) + for _rel in (("env", "roots.env"), ("roots.env",)): + _p = os.path.join(_base, *_rel) + if os.path.isfile(_p): + try: + with open(_p, encoding="utf-8") as _f: + for _ln in _f: + _ln = _ln.strip() + if _ln and not _ln.startswith("#") and "=" in _ln: + _k, _v = _ln.split("=", 1) + os.environ.setdefault(_k.strip(), _v.strip()) + except Exception: + pass + return _p + return "" + + +_sm_load_roots() + # --------------------------------------------------------------------------- # 🔴 工作区根**靠上溯发现**,⛔ 不靠"脚本在第几层"(2026-09-28 实测 bug) # 事故:脚本原在 `交付物/`,用 `WS = dirname(dirname(__file__))` 正好对; @@ -112,7 +146,10 @@ LINE_WS = { # ⚠️ 改这里**必须同步** wb-sup "ai1net-dsh-anywhere": "手机接入线", "ai1net_ui": "ai1net_ui", } -CARE_PREFIX = "e:/programdata/aiproject/" # 大项目根:域外一律不读转录 +CARE_PREFIX = ((os.environ.get("DSH_AIROOT") or "").replace("\\", "/").strip("/") + "/").lower() \ + if (os.environ.get("DSH_AIROOT") or "").strip() else "" # 大项目根:域外一律不读转录 +# ⚠️ 2026-10-14:原写死 `e:/programdata/aiproject/` ⇒ 改为从 `DSH_AIROOT`(`env/roots.env`)推导。 +# 取不到 ⇒ **空串**,由 `classify()` 在真正要用时**如实报错 + 留痕**(⛔ 不许静默把全部会话判成域外)。 SKIPPED = os.path.join(INBOX, "skipped.jsonl") if INBOX else "" # --------------------------------------------------------------------------- @@ -408,7 +445,16 @@ def classify(cwd: str): if not cwd: return "outside", "?" c = cwd if cwd.endswith("/") else cwd + "/" - if not c.startswith(CARE_PREFIX): + if not CARE_PREFIX: + # 🔴 2026-10-14:推不出大项目根 ⇒ **如实报错 + 留痕**,⛔ 不许静默把全部会话判成域外 + # (静默与"本机真没有相关会话"表现一样,最难查)。 + try: + sys.stderr.write("[wb-result-hook] ⛔ 推不出大项目根(`DSH_AIROOT` 空且 `env/roots.env` 缺它)" + "⇒ 无法判 scope。请跑一次 `python install.py --apply --workspace <本区>`\n") + except Exception: + pass + return "outside", (cwd.rstrip("/").split("/")[-1] or "?") + if not c.lower().startswith(CARE_PREFIX): return "outside", (cwd.rstrip("/").split("/")[-1] or "?") rest = c[len(CARE_PREFIX):].strip("/") seg = rest.split("/", 1)[0] if rest else "?" diff --git a/session-mechanism/scripts/selftest.py b/session-mechanism/scripts/selftest.py index 82dfa19..d8cd05d 100644 --- a/session-mechanism/scripts/selftest.py +++ b/session-mechanism/scripts/selftest.py @@ -6872,7 +6872,7 @@ def t_board_render_runs_clean(): "acceptance": {"A1-真": "过(自测)", "A2-假": "待达标(自测)", "_说明": "说明行 ⛔ 不进分母"}}, "project": {"short": "自测", "title": "自测目标", "id": "st-1", - "main_sid8": "st123456", "workspace": "E:/selftest", + "main_sid8": "st123456", "workspace": "__selftest_ws__", "criteria": ["自测判据"], "topics": ["自测类别"], "topics_source": {"kind": "declared", "at": "自测", "by": "自测"}, "main_by_topic": {}},