修复单目录查询变更遗漏的 CI 测试
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled

更新 OpenAPI 派生 MCP 工具数量及总数断言
将图片编辑工具链夹具改为单目录读取并验证目录请求
补充单目录合同的 MCP 与工具层定向验证入口
This commit is contained in:
2026-10-03 13:36:49 +08:00
parent a265bda534
commit df0402170c
3 changed files with 11 additions and 6 deletions
@@ -3464,14 +3464,16 @@ mod tests {
"title": "工具链远端画布"
}]}}),
);
} else if route.starts_with("/api/editor/assets/library") {
} else if request_line.starts_with(&format!(
"GET /api/editor/assets/folders/{TOOL_CHAIN_ASSET_FOLDER_ID} "
)) {
tool_chain_write_json(
&mut stream,
"200 OK",
json!({"data": {"library": {"folders": [{
json!({"data": {"folder": {
"folderId": TOOL_CHAIN_ASSET_FOLDER_ID,
"label": "工具链远端目录"
}]}}}),
}}}),
);
} else if request_line.starts_with(expected_submission) {
tool_chain_write_json(
@@ -4017,6 +4019,9 @@ mod tests {
);
assert_eq!(requests.len(), 6, "{requests:?}");
assert!(requests.iter().any(|request| request.starts_with(&format!(
"GET /api/editor/assets/folders/{TOOL_CHAIN_ASSET_FOLDER_ID} "
))));
let submission = requests
.iter()
.find(|request| request.starts_with("POST /api/editor/images/edits "))
@@ -949,7 +949,7 @@ Agent Runtime 负责:
- 素材生成准备的目录确认采用单目录读取:站内 `GET /api/editor/assets/folders/{folderId}` 与开发者 `GET /api/external/v1/editor/assets/folders/{folderId}` 返回现有 `{folder: ...}` 数据结构,后端按目录主键读取并校验 owner,不读取账户素材、不创建默认目录、不执行媒体修复。External 入口要求 `editor:asset` scope;缺失目录返回 404,越权返回 403,未认证返回 401。原素材库快照及目录创建、修改、删除接口的合同不变;不修改持久化表结构。先部署新增后端接口,再发布依赖该接口的客户端;新客户端不回退完整素材库。
- 已有当前账号项目 binding 或恢复 partial 的目录身份时,在新的生成准备中按该 ID 确认目录并核对响应 ID;合法空目录也可继续。首次没有可复用目录身份时直接沿用稳定幂等创建和冻结正文,不先列举素材库,不按同名认领目录。partial 继续只承载中间恢复进度,成功写入完整 binding 后删除;既有生成账本的 `prepared / accepted / legacy-completed` 恢复仍使用冻结快照,不重新查询或创建目录。
- 单目录查询超时、断网、服务异常、鉴权失效、越权或会话切换时停止准备并保留现有 binding / 恢复证据,不解释为目录缺失、不自动 POST 新目录。明确 404 时提示绑定目录不存在并停止,不用原键复活目录、不换键重建或重发生成;自动重新绑定与素材分页、关键词筛选、按素材 ID 导入不属于该行为。验证覆盖全库不可用而单目录正常、空目录、首次建绑、缺失与越权、查询失败及切号,并保留并发单次创建、创建响应丢失、冻结正文及生成账本恢复回归。
- 单目录合同的定向验证使用 AGC Rust `external_canvas_context`、`canvas_generation_tests`、`project::resource_editor::tests` 与 `background_removal_tests`,后端使用 `external_editor` 和 `protected_route_matrix_keeps_auth_methods_and_head_behavior`;`npm run check:editor-idempotency-procedures` 在独立 SpacetimeDB 中验证真实目录读取、归属、删除与只读行为,host 单测不能代替该运行时证据。
- 单目录合同的定向验证使用 AGC Rust `external_canvas_context`、`canvas_generation_tests`、`project::resource_editor::tests`、`background_removal_tests` 与 `direct_tools_mcp::tests`,工具链 HTTP 夹具按单目录 GET 返回 `data.folder`;后端使用 `external_editor`、`external_mcp` 和 `protected_route_matrix_keeps_auth_methods_and_head_behavior`,覆盖 OpenAPI 自动增加单目录 MCP 工具后的目录数量及名称唯一性。`npm run check:editor-idempotency-procedures` 在独立 SpacetimeDB 中验证真实目录读取、归属、删除与只读行为,host 单测不能代替该运行时证据。
- 当前 binding wire schema 为 v2,payload fingerprint 必填。已落盘的 v1 project/resource JSON 只能经独立严格 wire 结构读取,在 lookup key、principal、本地 source、远端字段、对象键、时间和尺寸等不变量全部通过后重算指纹并原子回写 v2。不得用 `serde(default)` 把未知或篡改文档混入迁移。
- 已完成的本地正式资源以本地文件和 manifest asset 身份为权威。切换账号后,当前账号没有资源 binding 时,必须从本地字节上传、confirm 并登记到当前账号的远端项目后再编辑或派生;任何请求都不得把旧账号的 `canvasProjectId / resourceId / objectKey` 与新账号 Token 组合。新绑定不得覆盖历史来源,也不得迁移或删除旧账号远端对象。已经 `prepared / accepted / running` 的生成或编辑 operation 仍冻结原 principal、原正文和原 operation;切换账号只能停止恢复并保留对账证据,不能改绑、重放或重复扣费。
- 远端提交返回 `operationId` 后先持久化 accepted 身份,再在每次 poll、download 和本地 commit 前复验冻结会话;同步本地 commit 持有冻结会话租约,使切号只能发生在完整安装前或安装后。Tauri 手工生成同样使用稳定的 durable operation slot,不得使用进程内临时幂等键。历史资源编辑账本从 manifest 远端 resource ID 迁移到本地 asset ID 时,只允许在本地 asset、路径和内容摘要仍一致时兼容旧指纹,新请求不得恢复信任 manifest 远端 ID。
@@ -30,7 +30,7 @@ fn prepare(
#[test]
fn semantic_catalog_adds_fifteen_tools_without_replacing_legacy_tools() {
assert_eq!(TOOLS.len(), 15);
assert_eq!(MCP_OPERATIONS.len(), 29);
assert_eq!(MCP_OPERATIONS.len(), 30);
let legacy = MCP_OPERATIONS
.iter()
.map(mcp_operation_tool)
@@ -52,7 +52,7 @@ fn semantic_catalog_adds_fifteen_tools_without_replacing_legacy_tools() {
.is_some_and(|text| !text.is_empty())
);
}
assert_eq!(names.len(), 44);
assert_eq!(names.len(), 45);
}
#[test]