Skip to content

fix(sandbox): prevent concurrent ble.sh cache collisions - #1183

Draft
evanlowe wants to merge 1 commit into
volcengine:mainfrom
evanlowe:fix/studio-blesh-cache
Draft

evanlowe wants to merge 1 commit into
volcengine:mainfrom
evanlowe:fix/studio-blesh-cache

Conversation

@evanlowe

Copy link
Copy Markdown
Contributor

一句话描述

修复工作区多个终端首次启动时,ble.sh 共用临时缓存文件导致的 mv: cannot stat ... .part 报错。全量和增量镜像构建统一应用进程独立的临时缓存文件名,保留 Bash、高亮、快捷键和最终共享缓存。

Spec 自查

前端

  • SPEC-FE 已遵守本次改动涉及的前端 spec,包括前端开发规范与代码工程约定;例如新增页面核对组件复用和双主题
    结果与依据:通过:已阅读目标仓库 frontend/SPEC.md,按适用的 Python 验证、最小改动和错误处理要求执行;没有 React UI 变更。

  • FE-01 禁止用「·」「|」等符号罗列文字;提示文字使用自然表达、分组、留白或换行,同类属性的多个值使用组件库 Label,例如 Agent 的多个 skills 分别用独立 Label 展示
    结果与依据:不适用:仅修改沙箱镜像的 Python 构建脚本与回归测试,没有页面、组件、布局、样式或文案变更。

  • FE-02 所有元素必须光学对齐,位置有明确的布局依据,不能随意放置;例如按钮图标与文字视觉居中
    结果与依据:不适用:仅修改沙箱镜像的 Python 构建脚本与回归测试,没有页面、组件、布局、样式或文案变更。

  • FE-03 严禁将文字按钮与普通按钮并排放置;例如定时任务详情的「刷新」与「编辑」「停用」「删除」统一使用次按钮,「立即执行」使用主按钮
    结果与依据:不适用:仅修改沙箱镜像的 Python 构建脚本与回归测试,没有页面、组件、布局、样式或文案变更。

  • FE-04 用户未明确要求时,不生成 muted 小字描述或说明,不把用户提示词当作描述、说明或附加信息;例如不在创建表单下添加流程解释,也不将开发要求复述为页面副标题
    结果与依据:不适用:仅修改沙箱镜像的 Python 构建脚本与回归测试,没有页面、组件、布局、样式或文案变更。

  • FE-05 所有 EmptyState 和 ErrorState 必须在所属区域的可用内容区内上下左右视觉居中,不能贴在顶部;图标、标题、说明和操作作为整体居中,并扣除固定标题、页签、工具栏及底部操作栏,例如详情页加载失败时,错误提示与重试按钮应位于当前页签内容区中央
    结果与依据:不适用:仅修改沙箱镜像的 Python 构建脚本与回归测试,没有页面、组件、布局、样式或文案变更。

  • FE-06 开发前必须按 skills/ux-reviewer/SKILL.md 完成 UX 审查,交付前必须按 skills/ui-polish/SKILL.md 完成 UI 视觉打磨;例如说明用户目标、主操作、关键状态、页签语义、loading / disabled 反馈、双主题视觉依据和截图位置
    结果与依据:不适用:仅修改沙箱镜像的 Python 构建脚本与回归测试,没有页面、组件、布局、样式或文案变更。

  • FE-07 严禁未经客户明确同意新增或收紧任何限制性逻辑,包括限流、大小限制和校验;例如新增搜索长度、文件大小或字符白名单限制前,先说明规则和影响并获得客户同意,PR 写明同意依据
    结果与依据:通过:未增加用户侧限流、大小限制或输入约束;仅校验固定版本插件的待修复代码。

  • FE-08 任何超出用户字面要求的实现或开发,必须在动手前询问用户并获得明确同意,严禁擅自作主或先开发再补问;例如为功能额外添加限流、加密、安全加固、性能优化、向前兼容性处理前,先说明内容和影响并获得同意,PR 写明实施前同意依据
    结果与依据:通过:范围限定为已确认的镜像源码与当前工作区缓存修复,没有额外功能。

  • FE-09 默认情况下,前端界面文字和代码注释尽量不添加句号,尤其不要给很短的一句话添加句号;例如提示写「保存成功」、注释写「保留用户选择」,末尾不加句号
    结果与依据:不适用:仅修改沙箱镜像的 Python 构建脚本与回归测试,没有页面、组件、布局、样式或文案变更。

  • FE-10 所有涉及前端的变更,改动完成后都必须向用户提供改动后实际运行界面的截图;例如修改按钮文案后,截取修改后的页面并提供给用户
    结果与依据:通过:已提供当前工作区新终端运行截图,确认修复版插件加载和 echo ok 执行正常;没有页面视觉变化。

  • FE-11 任何前端代码改动都必须在修改前向用户提供文件表与 API 表,说明目的与基本流程,按授权规则执行,新增范围先补充汇报;PR 按相同表头列出实际改动,文件表只列代码文件,排除文档和测试相关文件;例如只修按钮状态也先列表说明文件与现有 API,没有 API 变化时明确说明,并记录用户同意或直接执行授权
    结果与依据:通过:修改前已列明三个镜像源码文件和本次不涉及 API,并说明缓存修复流程;当前工作区用户目录方案已补充说明。2026-10-24 已确认同时修复镜像源码和当前工作区,随后要求提交 Draft PR。

  • FE-12 所有错误必须向用户与 Agent 完整透出实际失败步骤、对象、原始原因及已有定位信息,严禁统一报错、截断或只提示查看日志;例如切换技能版本后,下载被拒绝、文件解析失败与名称重复分别显示实际版本和具体原因
    结果与依据:不适用:没有 UI 错误处理变更;文件读写异常继续传播,固定插件代码不符合预期时明确失败。

  • FE-13 图标与文字同行组合时,大小必须一致或协调,严禁图标渲染宽度或高度超过相邻文字的实际字号,并保持光学对齐;例如 14px 文字不得搭配 16px 图标,加载、错误和禁用状态同样适用
    结果与依据:不适用:仅修改沙箱镜像的 Python 构建脚本与回归测试,没有页面、组件、布局、样式或文案变更。

后端

  • SPEC-BE 已遵守本次改动涉及的后端 spec;例如新增接口核对鉴权和错误响应
    结果与依据:通过:按目标仓库 Python 脚本要求执行;无业务后端接口。15 项镜像测试、Ruff、Pyright、全仓 pre-commit 均通过。

  • BE-01 核心功能独占文件,同一资源的增删改查接口可集中;例如镜像构建放在 build_image.py,不混入应用管理
    结果与依据:通过:缓存修复集中在 runtime/ble_cache.py,安装和增量构建入口只调用该函数。

  • BE-02 文件和函数按中文业务动作直译为英文,无上下文也能读懂;例如创建 APP 用 create_app.py、create_app,不用 registry_app、app_manager;检查沙箱用 check_sandbox.py,不用 sandbox.py
    结果与依据:通过:patch_blesh 直接表达修复对象;沿用镜像模块现有构建脚本命名。

  • BE-03 同一主体的能力归入独立目录,不与其他主体平铺;例如 repo/list_repo.py、repo/download_repo.py
    结果与依据:通过:全部实现保留在 frontend/sandbox-image/runtime/ 所属模块。

  • BE-04 文件名区分具体职责或实现;例如 download_repo_zip.py 与 clone_repo.py 区分下载和克隆
    结果与依据:通过:ble_cache.py 表达插件缓存修复职责,安装和增量更新沿用原入口。

  • BE-05 内部从定义模块导入,不经 init.py 中转;例如 from repo.download_repo import download_repo
    结果与依据:通过:两个入口均直接 from ble_cache import patch_blesh,没有 init.py 中转。

  • BE-06 区分公开入口与私有实现,包外不用私有实现;例如调用 download_repo,不调用内部 _build_url
    结果与依据:通过:构建入口仅调用 patch_blesh,未访问私有实现。

  • BE-07 测试目录对应源码,通过公开接口验证行为,只模拟外部边界;例如 app/repo.py 对应 tests/test_repo.py,模拟 HTTP 检查下载内容
    结果与依据:通过:tests/test_ble_cache.py 调用 patch_blesh;并发回归使用真实 Bash 子进程验证管道写入和重命名冲突。

  • BE-08 目录和文件用小写下划线,分别说明主体范围、职责或实现;例如 repo/download_repo_zip.py
    结果与依据:通过:新增 Python 模块和测试采用小写下划线;未重命名已有 install-image.py、refresh-editor.py。

  • BE-09 函数用小写下划线,表达动作和对象,私有函数不用含糊缩写;例如 create_app、_validate_state,不用 _prep
    结果与依据:通过:新增函数 patch_blesh 按动作与对象命名。

  • BE-10 参数与变量表意、区分单复数,布尔值说明条件或开关,常量用大写下划线;例如 repo/repos、is_ready、MAX_RETRIES
    结果与依据:通过:path、content、temporary、updated 等变量反映用途;没有配置开关或额外状态。

  • BE-11 按既有依赖方向调用明确接口,核心不反向依赖入口;例如 api.py 调用 create_app,不能反向导入
    结果与依据:通过:安装与增量更新入口依赖缓存修复模块,修复模块不反向导入入口。

  • BE-12 尽早失败,停止后续业务步骤并完成清理与回滚;例如无权限不创建资源,仍清理临时文件
    结果与依据:通过:固定源码不匹配时不写入;通过同目录临时文件原子替换,finally 清理临时文件。

  • BE-13 兜底须有条件和替代行为,不把权限、超时或非法数据当作缺失,不用默认值掩盖失败;例如确认缺失且允许时才创建,403 报错
    结果与依据:通过:不添加兜底;原始读写异常继续抛出,已修复源码可重复执行。

  • BE-14 兜底失败保留原因,重试限定范围和次数,取消不兜底;例如超时最多重试两次;测试覆盖超时读缓存、403 不读缓存、缓存失效仍报原始错误
    结果与依据:不适用:没有网络请求、重试或兜底流程。

  • BE-15 类型错误先修复,必要的忽略限定到具体行和错误并说明原因;例如 SDK 声明有误时只忽略该调用,不关闭整个文件检查
    结果与依据:通过:改动 Python 文件 Pyright 为 0 errors,没有新增类型忽略。

  • BE-16 cast 必须有类型成立的依据,不能代替数据校验;例如未知 HTTP 响应先校验,不能直接 cast 为业务对象
    结果与依据:不适用:没有 cast 或未知对象反序列化。

  • BE-17 纯类型调整不改变运行行为;例如补注解不新增会拒绝合法输入的异常分支
    结果与依据:不适用:本次是缓存并发行为修复,不是纯类型调整。

  • BE-18 未知字段处理遵循已获客户同意的契约,存储及协议模型遵守兼容约定,不默认新增拒绝;例如客户明确同意后才拒绝拼错的 timout 字段,旧记录新增字段不一律拒绝
    结果与依据:不适用:没有业务 HTTP 接口、协议模型、存储字段或对外参数变化。

  • BE-19 业务目录按照业务设计,而非技术走向;通用能力放进 common/,业务逻辑放进对应业务目录;例如通用沙箱连接归 common/,技能开发流程归技能业务目录
    结果与依据:通过:修复归属既有沙箱镜像模块,不增设跨业务层或无关目录。

  • BE-20 严禁未经客户明确同意新增或收紧任何限制性逻辑,包括限流、大小限制和校验;例如新增请求限流、内容大小或技能标识校验前,先说明规则和影响并获得客户同意,PR 写明同意依据
    结果与依据:通过:未增加用户侧约束;固定插件源码匹配属于已说明的修复流程,避免错误修改其他版本。

  • BE-21 任何超出用户字面要求的实现或开发,必须在动手前询问用户并获得明确同意,严禁擅自作主或先开发再补问;例如为功能额外添加限流、加密、安全加固、性能优化、向前兼容性处理前,先说明内容和影响并获得同意,PR 写明实施前同意依据
    结果与依据:通过:仅落实已确认的缓存修复;未构建或发布镜像,未增加其他功能。

  • BE-22 任何后端代码改动都必须在修改前向用户提供文件表与 API 表,说明目的与基本流程,按授权规则执行,新增范围先补充汇报;PR 按相同表头列出实际改动,文件表只列代码文件,排除文档和测试相关文件;例如修复现有接口也先列表说明处理文件与接口行为,没有 API 变化时明确说明,并记录用户同意或直接执行授权
    结果与依据:通过:实施前已提供代码文件表、API 表和流程说明;2026-10-24 确认镜像源码与当前工作区修复范围,本 PR 仅包含镜像源码、测试和说明文档。

  • BE-23 默认情况下,代码注释尽量不添加句号,尤其不要给很短的一句话添加句号;例如注释写「保留原始错误便于定位问题」,末尾不加句号
    结果与依据:通过:沿用目标仓库英文注释规则;未改动其他项目的注释约定。

  • BE-24 所有错误必须完整传递实际失败步骤、对象、原始原因、异常因果链及已有定位信息,严禁统一报错或丢弃底层诊断,供人和 Agent 快速排查;例如技能下载、解析、重名与子进程失败分别保留版本、实际原因及适用的错误码、追踪号或退出信息,不能统一返回技能加载失败
    结果与依据:通过:未捕获或替换底层读写异常;仅对固定插件代码不匹配给出明确错误,没有日志截断。

E2E

  • SPEC-E2E 已遵守本次改动涉及的浏览器 E2E 用例规范,包括用例维护、新增时机与实跑验证;例如新开用户入口核对是否补 case
    结果与依据:通过:未捕获或替换底层读写异常;仅对固定插件代码不匹配给出明确错误,没有日志截断。

  • E2E-01 命中新开用户入口、跨页 ≥3 页主流程或 UI regression bug 任一情形时在同一个 commit 内新增对应 e2e case;均未命中时在本项依据里显式声明理由,例如纯内部重构无 UI 行为变更
    结果与依据:不适用:未新增用户入口、跨页流程或 UI 回归;以真实 Bash 并发回归覆盖根因,并验证新终端加载修复。

  • E2E-02 改动已有 case 覆盖的 Steps 可见文案、路由 URL、Preconditions 依赖的后端行为、Setup 使用的接口或断言的区域结构时,同步更新对应 e2e/cases/<area>/*.md 并递增 case_version;例如抽屉从「工具」拆成「技能」+「应用」时更新 Expected
    结果与依据:不适用:未改变已有页面文案、路由、接口或区域结构。

  • E2E-03 下线 case 覆盖的页面、路由或入口时在同一个 commit 内删除对应 case 文件;功能迁移到新路径则在同一个 commit 内更新 case 到新路径,不保留永远 blocked 的孤儿 case
    结果与依据:不适用:没有下线页面、路由或入口。

  • E2E-04 新增或修改的 case 已用具备 BUA / CUA 能力的 Agent 本地实跑并通过,或由本人在浏览器按 Steps 走完整条路径,并在详细描述中附一句话实跑证据;只过 npm run check:e2e 不算完成
    结果与依据:不适用:没有新增或修改浏览器 case;已在当前工作区新建终端,确认修复函数加载并成功执行 echo ok。

详细描述

改动的文件

目录&文件名 为什么改动 改动了什么
frontend/sandbox-image/runtime/ble_cache.py 多个 Shell 共用临时缓存文件 将临时文件名按进程区分,限定修复范围,支持重复执行并原子替换
frontend/sandbox-image/runtime/install-image.py 新镜像需包含修复 安装 ble.sh 后应用缓存修复
frontend/sandbox-image/runtime/refresh-editor.py 增量镜像更新需包含修复 在增量更新流程应用相同修复

改动的 API

API 名称 API 用来做什么 为什么改动 改动了什么
本次不涉及 API 不适用 不适用 不适用

验证结果

  • python3 -m unittest discover -s frontend/sandbox-image/tests -v:15 项通过,包括原始并发冲突复现、修复后的并发写入、重复执行、权限保留和异常源码不修改。
  • 改动 Python 文件 Ruff、Pyright:通过。
  • pre-commit run --all-files:通过,含格式、密钥扫描和依赖策略检查。
  • git diff --cached --check:通过。
  • 当前工作区:新终端加载修复后的插件,echo ok 正常执行。
  • 完整 Docker 构建、发布和广泛应用回归尚未执行;本 PR 保持 Draft,未发布新镜像。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant