test(prompt): 锁住 docker 下 system prompt 不漏宿主路径(药3 复核收口)
高轮数烧 token 诊断的最后一味:复核「不停 glob /home/ubuntu/zcbot」幽灵路径。 证据链确认是 2026-06-03「system prompt 焊死宿主路径」那个 bug 的历史残影—— 失败 task(ab063233 06-02 / ff1686b7 06-03)首条 assistant tool_calls 即带宿主 路径+真 uid(只可能来自当时运行时拼接的 system prompt;messages 表无 system-role 行),两者均建于修复前后。fs 工具在 docker 容器跑、容器无此宿主路径 → base path not found → 重试风暴(实测 51 次)。 复核当前代码:docker 模式即便传 tool_base=/home/ubuntu/zcbot + 真 uid,prompt 只含 /workspace/<wd>、不漏宿主路径/uid/tmp(agent_builder.py docker 分支)。 新增 tests/test_system_prompt_paths.py(2 例)钉死防回归。三味药全部收口; 药1 重复守卫此后兜底同类风暴。无功能代码改动。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f2c6f2e2f4
commit
087980d027
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
### 2026-06-09
|
### 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/<wd>`、不含宿主路径/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。
|
- **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
|
### 2026-06-08
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
"""回归:docker backend 下 system prompt 必须注入容器路径,绝不泄漏宿主绝对路径 / uid。
|
||||||
|
|
||||||
|
背景(2026-06-03 修复 + 06-09 复核):fs/shell/run_python 在 docker backend 跑在容器里
|
||||||
|
(`<workspace>/users/<uid>` bind 到 `/workspace`)。早期 prompt 焊死宿主绝对路径
|
||||||
|
(`/home/ubuntu/zcbot/workspace/users/<uid>/<wd>`),LLM 据此 glob,容器内无此路径 →
|
||||||
|
`[Error] base path not found` → 重试风暴(实测单 task 51 次)。本测试锁住修复:docker 下
|
||||||
|
prompt 只出现 `/workspace/<wd>`,不出现宿主路径 / 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()
|
||||||
Loading…
Reference in New Issue