diff --git a/PROGRESS.md b/PROGRESS.md index 4c18cc4..3a73b16 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -23,6 +23,7 @@ ### 2026-06-09 +- **药3 复核:`/home/ubuntu/zcbot` 幽灵路径已于 06-03 修复,新任务不复现 + 加回归测试钉死**:接续高轮数烧 token 诊断收尾。证据链——失败 task `ab063233`(06-02 03:54)/`ff1686b7`(06-03 12:02)的首条 assistant 消息(idx1)tool_calls 里就带 `glob(path=/home/ubuntu/zcbot/workspace/users/<真实uid>/数据资源展示)`,**带真 uid 只可能来自当时的 system prompt**(messages 表无 system-role 行,系统提示运行时拼接不入库);两 task 均建于 06-03「system prompt 焊死宿主路径」修复前后。fs 工具在 docker 容器里跑(容器无此宿主路径)→ `[Error] base path not found`(`glob.execute` 对不存在 base 返此错,`_display` 对 user_root 外路径回绝对)→ 重试风暴(实测 51 次)。**复核当前代码**:docker 模式即便传 `tool_base=/home/ubuntu/zcbot` + 真 uid,拼出的 prompt 只含 `/workspace/`、不含宿主路径/uid/tmp(`agent_builder.py:223-250` docker 分支注入容器路径 + 删 cwd 行);prod 走 docker backend(RUN.md)。新增 `tests/test_system_prompt_paths.py`(2 例:docker 无宿主泄漏 + host 保留本地绝对路径,过)锁住修复防回归。**三味药全部收口**;药1 重复守卫此后还兜底任何同类风暴(同一 51 次会被摁到 ~5 次)。无功能代码改动,仅加测试。 - **ppt skill 补「信息设计纪律」+ 混合背景 + pptx 预览器(治"效果还是不太行",深读 pptmaster 后的二次修正)**:用户反馈卡片式 v2 仍不够好,拆其真实产物(`大模型与智能体介绍.pptx`)定位毛病=9 页 4 页雷同卡片网格(全卡=AI 味)、发展历程做成网格(该时间轴)、智能体平铺(该闭环)、图标 0.6 寸太小、投影到处加。**深读 pptmaster 的 executor-base/executor-consultant(-top)/shared-standards 后顿悟**:它像麦肯锡的真因是**信息设计纪律(~70%)**而非 SVG 渲染(~30%),而这些**全是 editable python-pptx 能做的**——之前纠结的"可编辑 vs SVG 转换器"搞错了轴(可编辑都落 DrawingML 同一天花板,转换器零视觉增益)。落地三层:① **信息内功**——`add_takeaway`(论断标题下一句话结论框)、`add_kpi` 加 `baseline+delta`(数据语境化:数字带对比基准+升降色 `GOOD/BAD`)、`add_source`(来源)、`add_toc`(贯通整宽目录);SKILL 策略阶段加论断式标题对照表 + page_rhythm(anchor/dense/**breathing 强制打破卡片网格**)+ 内容→版式映射写进逐页大纲。② **修我搞反的投影**——pptmaster"投影是克制":`add_card` 默认 `shadow=False`(平铺对等卡描发丝边不投影)、每页 ≤2-3 投影、一容器一手段不叠;quality_check 加绿=语义状态色豁免三色制。③ **组合件 + 工具**——`add_card_grid`(均衡网格,2 行改图标左置治"图标顶置挤溢出")/`add_timeline`/`add_cycle`;`render_bg.py`(无头 Chrome 渲杂志级 mesh 渐变背景图,**混合方案**:背景图+原生可编辑白字,封面/章节);**`pptx_preview.py`(把 .pptx 渲成 PNG 肉眼验观感)——quality_check 只查结构,预览补"好不好看",当场抓到 `set_text` 多行只给第一段上色的真 bug(封面副标题第二行变暗看不见)并修复**。验证:重排「大模型与智能体」为 10 页(节奏:封面/目录/章节 anchor · 网格/时间轴 dense · 大字 breathing · 章节/闭环/网格 · 致谢),逐页渲 PNG 亲眼验收均专业,quality_check 全过。改 `skills/ppt/{SKILL.md,references/{design_principles,layouts}.md,scripts/{pptx_helpers,quality_check}.py}` + 新增 `scripts/{render_bg,pptx_preview}.py` + `SKILL_LIST.md`。**未动**:SVG→原生转换器(论证为零增益不做)、live preview server、动画;fetch_icon 的 PNG 后端(cairosvg/svglib)本机未装,暂用种子库 PNG。 ### 2026-06-08 diff --git a/tests/test_system_prompt_paths.py b/tests/test_system_prompt_paths.py new file mode 100644 index 0000000..bd9c4e6 --- /dev/null +++ b/tests/test_system_prompt_paths.py @@ -0,0 +1,64 @@ +"""回归:docker backend 下 system prompt 必须注入容器路径,绝不泄漏宿主绝对路径 / uid。 + +背景(2026-06-03 修复 + 06-09 复核):fs/shell/run_python 在 docker backend 跑在容器里 +(`/users/` bind 到 `/workspace`)。早期 prompt 焊死宿主绝对路径 +(`/home/ubuntu/zcbot/workspace/users//`),LLM 据此 glob,容器内无此路径 → +`[Error] base path not found` → 重试风暴(实测单 task 51 次)。本测试锁住修复:docker 下 +prompt 只出现 `/workspace/`,不出现宿主路径 / uid。host 下仍用本地绝对路径(不回归)。 +""" +from __future__ import annotations + +import sys +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch +from uuid import UUID + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) + +from core.agent_builder import _build_system_prompt, load_config, user_root # noqa: E402 +from core.paths import ROOT # noqa: E402 +from core.skills import SkillRegistry # noqa: E402 + +_UID = UUID("6b14d2ab-7a6e-4d0b-8562-ea62a801e32c") +_TID = UUID("ab063233-7e90-4f57-9afe-3f7e47b13522") +_HOST_CWD = Path("/home/ubuntu/zcbot") # 模拟 prod 宿主启动目录 + + +def _build(backend: str) -> tuple[str, Path, Path]: + cfg = load_config() + skills = SkillRegistry(ROOT / cfg.get("skills_dir", "skills")) + tmp = tempfile.mkdtemp() + ws = Path(tmp) / "workspace" + wd = user_root(ws, _UID) / "数据资源展示" + wd.mkdir(parents=True, exist_ok=True) + with patch.dict("os.environ", {"ZCBOT_SANDBOX_BACKEND": backend}, clear=False): + prompt = _build_system_prompt( + cfg, skills, ws, _HOST_CWD, wd, _UID, _TID, "数据资源展示", "documents" + ) + return prompt, ws, wd + + +class TestSystemPromptPaths(unittest.TestCase): + def test_docker_prompt_uses_container_path_no_host_leak(self): + prompt, ws, wd = _build("docker") + # 容器路径在 + self.assertIn("/workspace/数据资源展示", prompt) + # 宿主路径 / tmp / uid 一律不泄漏 + self.assertNotIn("/home/ubuntu/zcbot", prompt) + self.assertNotIn(str(ws), prompt) + self.assertNotIn(str(wd), prompt) + self.assertNotIn(str(_UID), prompt) + # docker 下不应再出现「cwd: <宿主路径>」那一行 + self.assertNotIn(f"`{_HOST_CWD}`", prompt) + + def test_host_prompt_keeps_local_absolute_path(self): + prompt, ws, wd = _build("host") + # host backend 用本地绝对 task_dir(Windows dev / dogfood),不容器化 + self.assertIn(str(wd), prompt) + self.assertNotIn("/workspace/数据资源展示", prompt) + + +if __name__ == "__main__": + unittest.main()