@lark-apaas/coding-miaoda-sandbox-skills 0.1.0-dev.942e73f → 0.1.0-dev.b12eab4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,6 +47,8 @@ SELECT * FROM rds_ai.list_model();
47
47
 
48
48
  按业务需求选定模型,取其 `model_name` 作为第二个参数。
49
49
 
50
+ ⚠️ **模型可用性由租户管理后台管控。** `list_model()` 返回的是平台预置清单;管理员下架或停用其中某个模型后,平台自动在其余可用预置模型中选择,业务 SQL 无需改动。因此除非用户明确要求锁定模型,否则不传 `model_name`;锁定的模型被停用时,加工结果可能出现风格波动。预置模型全部不可用时调用直接失败,处置见「关键注意事项」。
51
+
50
52
  ## 实现步骤
51
53
 
52
54
  以下 SQL 使用 `tickets` / `priority` 作为示例。Agent 生成实际方案时,必须替换成用户应用里的真实表名、字段名、主键和 `task_kind`。
@@ -378,10 +380,11 @@ LIMIT 20;
378
380
  | ❌ 业务事务路径(同步 trigger / 大批量 UPDATE)里直接调 `rds_ai.ai_query` | HTTP 调用会因网络抖动、限流、超时、模型异常抛错,阻塞业务写入、占锁并产生大额模型调用 | trigger 只入队,模型调用统一由 `ai_run_pending_jobs()` 的 EXCEPTION 块兜住;批量场景先小样本验证,再经 `ai_job` 分批处理 |
379
381
  | ❌ 422 / `quota_exceeded` 报错后继续重试 | 当前应用 AI 调用额度已用完,重试只会继续报错 | 任务直接置 `failed`、停止入队,续费后批量重跑;提示用户「AI 调用额度已耗尽,请联系应用 Owner 在控制台续费或升级套餐后再试」 |
380
382
  | ❌ 429 / `rate_limit_exceeded` 报错后原速重跑 | 调用过于密集触发限流 | 保持重试 + 指数退避;调小 `ai_run_pending_jobs` 单次批量、放慢 worker 节奏;提示用户「AI 调用过于频繁触发了限流,已自动放慢节奏,稍后会继续跑完」 |
383
+ | ❌ 500 / `model_unavailable` 报错后继续重试或继续入队 | 租户预置模型已被全部下架或停用,平台无模型可选,重试不会恢复 | 任务置 `failed` 并停止入队;提示用户「当前租户无可用 AI 模型,请联系租户管理员恢复后再试」;模型恢复后重跑失败任务即可 |
381
384
  | ❌ prompt 不约束输出格式 | 解释性文本会作为脏值写回业务表 | 分类任务写清枚举值并在 SQL 函数里校验结果;JSON 抽取写清 JSON schema |
382
385
  | ❌ trigger 只靠 `UPDATE OF <col>` 判断变化 | 无关更新会重复入队、重复消耗 | 函数里再用 `IS NOT DISTINCT FROM` 判断源字段变化 |
383
386
 
384
- `rds_ai.ai_query` 抛错时,PG 错误信息通常带 HTTP 状态码或 `quota_exceeded` / `rate_limit_exceeded` 关键字;失败任务停在 `ai_job` 表,错误码可从 `error_message` 字段读出供 UI 展示和告警归类。
387
+ `rds_ai.ai_query` 抛错时,PG 错误信息通常带 HTTP 状态码(422 / 429 / 500)或 `quota_exceeded` / `rate_limit_exceeded` / `model_unavailable` 关键字;失败任务停在 `ai_job` 表,错误码可从 `error_message` 字段读出供 UI 展示和告警归类。
385
388
 
386
389
  **禁止**的写法(会阻塞业务写入事务):
387
390
 
@@ -57,6 +57,8 @@ SELECT rds_ai.ai_embed('你好')::vector;
57
57
  -- → vector(1024)
58
58
  ```
59
59
 
60
+ ⚠️ **模型可用性由租户管理后台管控。** embedding 仅此一个模型、无备选,管理员将其下架或停用后 `rds_ai.ai_embed` 即不可用,调用报 `model_unavailable`(处置见「关键注意事项」)。
61
+
60
62
  ## 实现步骤
61
63
 
62
64
  以下 SQL 使用 `products` / `embedding` 作为示例。Agent 生成实际方案时,必须替换成用户应用里的真实表名、字段名、主键、返回列和索引名。
@@ -281,14 +283,15 @@ LIMIT 10;
281
283
 
282
284
  ## 关键注意事项
283
285
 
284
- ### ⚠️ ai_embed 报错优先看状态码:422 (额度不足) / 429 (限流)
286
+ ### ⚠️ ai_embed 报错优先看状态码:422 (额度不足) / 429 (限流) / 500 (无可用模型)
285
287
 
286
- `rds_ai.ai_embed` 抛错时,PG 错误信息里通常会带 HTTP 状态码或 `quota_exceeded` / `rate_limit_exceeded` 关键字。识别后给用户的提示要分开:
288
+ `rds_ai.ai_embed` 抛错时,PG 错误信息里通常会带 HTTP 状态码或 `quota_exceeded` / `rate_limit_exceeded` / `model_unavailable` 关键字。识别后给用户的提示要分开:
287
289
 
288
290
  - **422 / quota_exceeded** — 当前应用的 AI 调用额度已用完。提示用户:「AI 调用额度已耗尽,请联系应用 Owner 在控制台续费或升级套餐后再试」。**不要重试**,重试只会继续报错。
289
291
  - **429 / rate_limit_exceeded** — 调用过于密集触发限流。提示用户:「AI 调用过于频繁触发了限流,稍后再试,或调小回填批次 / 降低并发即可恢复」。**可重试**,建议指数退避。
292
+ - **500 / model_unavailable** — 租户预置的 embedding 模型已被管理员下架或停用,且无备选模型。提示用户:「当前租户无可用 AI 模型,请联系租户管理员恢复后再试」。**不要重试**,模型恢复后重跑存量回填即可。
290
293
 
291
- trigger 已经用 `EXCEPTION WHEN OTHERS THEN NEW.embedding := NULL` 兜住单条失败,业务写入不会回滚;后续走存量回填补齐。批量回填(步骤 7)建议捕获错误码:遇到 422 立刻停止整批并提示续费,遇到 429 退避后续跑。
294
+ trigger 已经用 `EXCEPTION WHEN OTHERS THEN NEW.embedding := NULL` 兜住单条失败,业务写入不会回滚;后续走存量回填补齐。批量回填(步骤 7)建议捕获错误码:遇到 422 立刻停止整批并提示续费,遇到 429 退避后续跑,遇到 500 停整批并提示联系租户管理员。
292
295
 
293
296
  ### ⚠️ 同步 trigger 调 rds_ai.ai_embed 必须 BEGIN/EXCEPTION 兜底
294
297
 
@@ -4,11 +4,65 @@ description: 派发 E2E 子 agent(Task subagent_type="E2E")前**必读**—
4
4
  steering: true
5
5
  steering-topic: testing
6
6
  gate-tools:
7
+ - tool: visual_check
7
8
  - tool: task
8
9
  when:
9
10
  subagent_type: E2E
10
11
  ---
12
+ {% if visualCheckEnabled %}
13
+ # 检查与验证:工具选择指南
14
+
15
+ 静态页面检查和功能验收使用不同工具。向用户只说「页面检查」或「用浏览器操作验证」,不要解释内部工具或 agent 名称。
16
+
17
+ ## 决策规则
18
+
19
+ ```
20
+ 用户想确认应用是否正常
21
+ ├─ 明确要求验证后端接口 / API / 请求响应 → api_request
22
+ ├─ 只检查静态视觉结果(白屏、布局、样式、文案、图片)→ visual_check
23
+ └─ 交互 / 业务流程 / 数据 / 网络 → Task(subagent_type="E2E")
24
+ ```
25
+
26
+ - **静态视觉检查**:调用 `visual_check`,一条路由一次调用;互不依赖的路由可同时发起。它只检查指定路由的最终静态画面,不用来点击、填写、提交或验证接口。
27
+ - **功能验收**:交互 / 业务流程 / 数据 / 网络都派 `Task(subagent_type="E2E")`。E2E 一律按标准语义执行,调用时不要额外指定运行方式。
28
+ - **接口验收**:只在用户明确要检查接口、API、请求或响应时调用 `api_request`;完成浏览器验收后不追加接口调用。
29
+ - **E2E 不可用时(Legacy)**:Task 的 `subagent_type` 没有 E2E 选项时,交互、业务、数据和网络验收改用 `api_request`、读代码和读运行时日志;不要尝试派 E2E。静态视觉仍使用 `visual_check`。
30
+
31
+ ## 调用方式
32
+
33
+ ```js
34
+ visual_check({
35
+ relative_path: "<路由相对路径>",
36
+ // prompt: "<可选:需核对的白屏、布局、样式、文案或图片结果>",
37
+ })
38
+ ```
39
+
40
+ `relative_path` 只填一个路由。一条路由检查完成后再根据结果决定是否修复;多个互不依赖的路由可以分别同时调用。
11
41
 
42
+ ```js
43
+ Task({
44
+ subagent_type: "E2E",
45
+ {% if e2eSemanticPlan %}
46
+ agent_options: { test_plan_file_path: ".spark/e2e-test/standard/<语义名>.json" },
47
+ {% endif %}
48
+ description: "验收<功能名称>",
49
+ prompt: "执行<具体交互或业务闭环>,断言<可观察终态>。",
50
+ })
51
+ ```
52
+
53
+ {% if e2eSemanticPlan %}
54
+ ### 验收计划文件
55
+
56
+ 先读可能覆盖当前需求的 `.spark/e2e-test/standard/<语义名>.json`;有变化则更新同一文件,换功能或页面则新建。计划只包含交互、业务、数据和网络的可观察终态;`prompt` 只说明本轮执行范围和 Case 编号。
57
+ {% endif %}
58
+
59
+ ## 验收要求
60
+
61
+ - 视觉检查写清可观察结果,例如「首页标题完整可见、卡片两列排列、主图不是裂图」,不要只写「看起来正常」。
62
+ - 功能验收必须走到终态:提交后记录出现、跳转后内容正确、删除后记录消失或 AI 输出出现;不要停在弹窗、按钮或表单字段出现。
63
+ - 写操作和资源加载要核对网络结果;非 2xx、空结果、错误兜底或白屏都应报失败。
64
+ - 不测试登录、认证、CAPTCHA,或会造成真实外部副作用的行为。
65
+ {% else %}
12
66
  # 检查与验证:工具选择指南
13
67
 
14
68
  根据用户意图选择正确的派遣方式:派遣 E2E 子 agent(通过 `Task(subagent_type="E2E")` 打开浏览器操作一遍)或调用 `api_request`(直接请求后端接口)。
@@ -29,32 +83,34 @@ gate-tools:
29
83
  ├─ Task 工具定义的 subagent_type 选项里没有 E2E(E2E 被关闭/不可用,非"本轮没派过")→ api_request(接口级验收)+ 读代码/读日志兜底,不要尝试派 E2E
30
84
  ├─ 明确要求验证「后端接口」「API 返回值」「请求响应」 → api_request
31
85
  └─ 其他所有情况 → Task(subagent_type="E2E")(打开浏览器,以用户视角操作应用)
32
- ├─ 只看视觉(白屏/布局/样式/文案)→ agent_options.mode: "lite"
33
- └─ 涉及交互/业务流程/数据 → 不传或 agent_options.mode: "standard"
86
+ ├─ 基础视觉验证(白屏/布局/样式/文案)→ agent_options.mode: "lite"(只截图看视觉)
87
+ └─ 用户明确要求验证交互/业务流程/数据(点击/填写/提交/走一遍流程)→ agent_options.mode: "standard"
34
88
  ```
35
89
 
36
90
  - **E2E 不可用时改走 api_request(最高优先,先于下面所有规则判断)**:当 Task 工具定义的 subagent_type 选项里没有 E2E(用户关闭了浏览器验收 / 环境不支持;判断依据是工具定义中是否含 E2E 选项,不是"本轮有没有派过 E2E")时,下面"模糊需求一律派遣 E2E"不再适用——改用 `api_request` 做接口级验收,配合读代码 / 读运行时日志确认核心链路,**不要尝试派 E2E、也不要空等**;此时验收范围收敛到接口与数据层可判定结果,视觉类目标顺延到非核心降级范围
37
91
  - **模糊需求一律派遣 E2E**(仅当 E2E 可用):未明确提到「接口」「API」「后端」时必须派遣 E2E,不要主动选择 `api_request`
92
+ - **基础视觉验证走 lite,standard 需用户明确要求功能测试**:用户没有主动要求跑具体功能(只说"看看有没有问题"这类模糊需求也算没主动要求)时,显式传 `agent_options.mode: "lite"`;只有用户明确要验证交互 / 业务流程 / 数据(点击、填写、提交、走一遍流程等)时才显式传 `agent_options.mode: "standard"`
38
93
  - **`api_request` 仅限显式请求**:仅当明确提到接口 / API / 后端 / 请求 / 响应、且意图是验证接口逻辑而非页面功能时才使用
39
94
  - **E2E 结束后禁止追加 `api_request`**:浏览器操作的结果即为最终结果,**严禁**再自动补充验证
40
95
 
41
96
  ### E2E 的 mode 选择
42
97
 
43
- 通过 `agent_options.mode` 指定,**可选参数**,不传或非 `lite` 一律按 `standard` 处理:
98
+ 通过 `agent_options.mode` 指定,**必填参数**,且只允许 `lite` 或 `standard`;缺失或非法时 E2E 会拒绝执行:
44
99
 
45
100
  | mode | 适用场景 | 行为 | 总超时 | 录屏 |
46
101
  |------|---------|------|-------|------|
47
- | `standard`(缺省) | 涉及业务流程、数据流、交互后状态变化 | 完整交互(点击/输入/滚动/提交)+ Network 验证 + 录制 | 5 分钟 | ✅ |
48
- | `lite` | 只看视觉渲染(CSS/布局/文案/图标)或快速冒烟 | 仅 `open` / `goto` / `wait` / `snapshot` / `screenshot`,**禁止** `click` / `fill` / `type` / `scroll` / `select` / `press` / `drag` / `hover` | 2 分钟 | ❌ |
102
+ | `lite` | 基础视觉验证(白屏/布局/样式/文案)或快速冒烟 | 仅 `open` / `goto` / `wait` / `snapshot` / `screenshot`,**禁止** `click` / `fill` / `type` / `scroll` / `select` / `press` / `drag` / `hover` | 5 分钟 | ❌ |
103
+ | `standard` | **仅当用户明确要求**验证业务流程、数据流、交互后状态变化 | 完整交互(点击/输入/滚动/提交)+ Network 验证 + 录制 | 5 分钟 | ✅ |
49
104
 
50
- **仅改 CSS / 文案 / 图标 / 布局**(无事件处理、无状态、无数据获取)应直接选 `lite`——更快且 token 消耗显著低,不要默认走 standard 浪费配额;但 `lite` 不能触发 popup / toast / 提交后状态切换等需要操作的现象。testRequirements 里出现"点击"、"填写"、"提交"等动词,**禁止** `lite`,必须 `standard`。
105
+ **每次派发都必须显式传 mode**。基础视觉验证传 `lite`;`lite` 不能触发 popup / toast / 提交后状态切换等需要操作的现象。**用户明确要求跑功能**(testRequirements 里出现"点击"、"填写"、"提交"等动词,或用户直接要求验证某功能)时,传 `standard`。
51
106
 
52
107
  ## 工具选择速查表
53
108
 
54
109
  | 用户表达 | 选择 | 原因 |
55
110
  | --- | --- | --- |
56
- | "检查一下页面" / "看看有没有问题" / "走一遍流程" / "哪里出问题了" / "试试能不能用" / "XX 不好使" | E2E(standard) | 打开浏览器以用户视角操作 / 复现 |
57
- | "刚改了 CSS,看看样式对不对" | E2E(lite) | 仅视觉巡检,省时省 token |
111
+ | "检查一下页面" / "看看有没有问题" / "哪里出问题了" / "试试能不能用" / "XX 不好使" | E2E(显式 `mode: "lite"`) | 未主动要求跑功能,执行基础视觉验证 |
112
+ | "刚改了 CSS,看看样式对不对" | E2E(lite) | 仅视觉巡检 |
113
+ | "点提交试试能不能成功" / "帮我把下单流程走一遍" / "走一遍流程" / "验证一下这个功能" | E2E(standard) | 用户明确要求功能 / 交互验证 |
58
114
  | "测试一下这个接口的返回值对不对" / "调一下后端 API 看看响应" | `api_request` | 明确指定接口验证 |
59
115
 
60
116
  ## 派遣 E2E 时的 prompt / 用例规范
@@ -63,6 +119,25 @@ gate-tools:
63
119
 
64
120
  > **核心原则:agent 只「机械执行 + 报判断」,不做推理。** 判定标准全写死在断言里——别让它自己推断"该测什么"或定义"什么算正常 / 好看"。它的活只有:执行动作 → 看现象 → 报通过 / 不通过。
65
121
 
122
+ {% if e2eSemanticPlan %}
123
+ ### 验收计划文件:先写文件,再派发(首次与后续同一套)
124
+
125
+ 每次派发都必须带 `agent_options.test_plan_file_path`,不传不执行。**两种 mode 各一份卷**,目录必须与派发 mode 一致(串卷不执行):standard 卷写 `.spark/e2e-test/standard/<语义名>.json`(含点击 / 输入 / 提交),lite 卷写 `.spark/e2e-test/lite/<语义名>.json`(只放看得见的检查点)。
126
+
127
+ 1. **先看已有的**:`glob .spark/e2e-test/<mode>/*.json` → **读**可能覆盖本需求的那份(没读过不要传)
128
+ 2. **改还是新建**:同需求用例有变化 → 编辑那份;换了功能 / 页面 → 新建一份
129
+ 3. **派发**:`prompt` 只说跑哪些(`跑 Case 1、2` / `复测 p0 和 p1` / `测试全部用例`),**不点名默认只跑 p0**
130
+
131
+ 格式(一条用例一行,优先级小写,每卷 ≤10 条):
132
+
133
+ ```json
134
+ {"cases":[{"id":1,"priority":"p0","description":"打开首页,预期工单列表渲染出至少 1 行"}]}
135
+ ```
136
+
137
+ - **用例正文只写在计划文件里**:本模式下 `prompt` 不写 `## 测试用例`(下面示例里的用例正文改为写进卷),只留应用结构与本次范围——两处都写会让计划外用例一条不跑、报告却全绿
138
+ - **复测只点名、不删用例**:「只传 failed + 未完成的 Case」指在 `prompt` 里点名,不是从卷里删掉已通过的用例
139
+ {% endif %}
140
+
66
141
  ### 调用结构
67
142
 
68
143
  ```js
@@ -215,6 +290,9 @@ E2E 派遣是**昂贵操作**(每次消耗大量 token + 时间)。E2E agent
215
290
  | E2E 完成后又调 `api_request` 补充验证 | 浏览器操作结果即为最终结果,不追加 |
216
291
  | 用户说"看看有没有 bug"就同时调两个 | 只派遣 E2E |
217
292
  | 用户说"检查接口"时派遣 E2E | 明确提到接口时用 `api_request` |
293
+ | 派发 E2E 时不传 `mode` | 每次都显式传 `lite` 或 `standard`;缺失或非法时不会执行 |
294
+ | 用户没主动要求跑功能,却传 `standard` | 显式传 `lite`;仅用户明确要求交互 / 功能验证才传 `standard` |
218
295
  | 仅改 CSS / 文案,仍走 `standard` | 优先用 `lite`,速度快、token 消耗低 |
219
296
  | 达到停止条件(≥3 轮 / 同一错误未改代码连续失败)仍继续派 E2E | 停止派遣,转为根因分析(读代码 / 查日志) |
220
297
  | 复测时全量重测 / 白屏直接再派一轮 | 只传 failed + 未完成的 Case;白屏先重启 devServer 再复测 |
298
+ {% endif -%}
@@ -4,11 +4,64 @@ description: 派发 E2E 子 agent(Task subagent_type="E2E")前**必读**—
4
4
  steering: true
5
5
  steering-topic: testing
6
6
  gate-tools:
7
+ - tool: visual_check
7
8
  - tool: task
8
9
  when:
9
10
  subagent_type: E2E
10
11
  ---
12
+ {% if visualCheckEnabled %}
13
+ # 检查与验证:工具选择指南
14
+
15
+ 静态页面检查和功能验收使用不同工具。向用户只说「页面检查」或「用浏览器操作验证」,不要解释内部工具或 agent 名称。
16
+
17
+ ## 决策规则
18
+
19
+ ```
20
+ 用户想确认应用是否正常
21
+ ├─ 明确要求验证后端接口 / API / 请求响应 → api_request
22
+ ├─ 只检查静态视觉结果(白屏、布局、样式、文案、图片)→ visual_check
23
+ └─ 交互 / 业务流程 / 数据 / 网络 → Task(subagent_type="E2E")
24
+ ```
25
+
26
+ - **静态视觉检查**:调用 `visual_check`,一条路由一次调用;互不依赖的路由可同时发起。它只检查指定路由的最终静态画面,不用来点击、填写、提交或验证接口。
27
+ - **功能验收**:交互 / 业务流程 / 数据 / 网络都派 `Task(subagent_type="E2E")`。E2E 一律按标准语义执行,调用时不要额外指定运行方式。
28
+ - **接口验收**:只在用户明确要检查接口、API、请求或响应时调用 `api_request`;完成浏览器验收后不追加接口调用。
29
+
30
+ ## 调用方式
31
+
32
+ ```js
33
+ visual_check({
34
+ relative_path: "<路由相对路径>",
35
+ // prompt: "<可选:需核对的白屏、布局、样式、文案或图片结果>",
36
+ })
37
+ ```
38
+
39
+ `relative_path` 只填一个路由。一条路由检查完成后再根据结果决定是否修复;多个互不依赖的路由可以分别同时调用。
40
+
41
+ ```js
42
+ Task({
43
+ subagent_type: "E2E",
44
+ {% if e2eSemanticPlan %}
45
+ agent_options: { test_plan_file_path: ".spark/e2e-test/standard/<语义名>.json" },
46
+ {% endif %}
47
+ description: "验收<功能名称>",
48
+ prompt: "执行<具体交互或业务闭环>,断言<可观察终态>。",
49
+ })
50
+ ```
51
+
52
+ {% if e2eSemanticPlan %}
53
+ ### 验收计划文件
54
+
55
+ 先读可能覆盖当前需求的 `.spark/e2e-test/standard/<语义名>.json`;有变化则更新同一文件,换功能或页面则新建。计划只包含交互、业务、数据和网络的可观察终态;`prompt` 只说明本轮执行范围和 Case 编号。
56
+ {% endif %}
11
57
 
58
+ ## 验收要求
59
+
60
+ - 视觉检查写清可观察结果,例如「首页标题完整可见、卡片两列排列、主图不是裂图」,不要只写「看起来正常」。
61
+ - 功能验收必须走到终态:提交后记录出现、跳转后内容正确、删除后记录消失或 AI 输出出现;不要停在弹窗、按钮或表单字段出现。
62
+ - 写操作和资源加载要核对网络结果;非 2xx、空结果、错误兜底或白屏都应报失败。
63
+ - 不测试登录、认证、CAPTCHA,或会造成真实外部副作用的行为。
64
+ {% else %}
12
65
  # 检查与验证:工具选择指南
13
66
 
14
67
  根据用户意图选择正确的派遣方式:派遣 E2E 子 agent(通过 `Task(subagent_type="E2E")` 打开浏览器操作一遍)或调用 `api_request`(直接请求后端接口)。
@@ -28,39 +81,221 @@ gate-tools:
28
81
  用户想确认应用是否正常
29
82
  ├─ 明确要求验证「后端接口」「API 返回值」「请求响应」 → api_request
30
83
  └─ 其他所有情况 → Task(subagent_type="E2E")(打开浏览器,以用户视角操作应用)
31
- ├─ 只看视觉(白屏/布局/样式/文案)→ agent_options.mode: "lite"
32
- └─ 涉及交互/业务流程/数据 → 不传或 agent_options.mode: "standard"
84
+ ├─ 基础视觉验证(白屏/布局/样式/文案)→ agent_options.mode: "lite"(只截图看视觉)
85
+ └─ 用户明确要求验证交互/业务流程/数据(点击/填写/提交/走一遍流程)→ agent_options.mode: "standard"
33
86
  ```
34
87
 
35
88
  - **模糊需求一律派遣 E2E**:未明确提到「接口」「API」「后端」时必须派遣 E2E,不要主动选择 `api_request`
89
+ - **基础视觉验证走 lite,standard 需用户明确要求功能测试**:用户没有主动要求跑具体功能(只说"看看有没有问题"这类模糊需求也算没主动要求)时,显式传 `agent_options.mode: "lite"`;只有用户明确要验证交互 / 业务流程 / 数据(点击、填写、提交、走一遍流程等)时才显式传 `agent_options.mode: "standard"`
36
90
  - **`api_request` 仅限显式请求**:仅当明确提到接口 / API / 后端 / 请求 / 响应、且意图是验证接口逻辑而非页面功能时才使用
37
91
  - **E2E 结束后禁止追加 `api_request`**:浏览器操作的结果即为最终结果,**严禁**再自动补充验证
38
92
 
39
93
  ### E2E 的 mode 选择
40
94
 
41
- 通过 `agent_options.mode` 指定,**可选参数**,不传或非 `lite` 一律按 `standard` 处理:
95
+ 通过 `agent_options.mode` 指定,**必填参数**,且只允许 `lite` 或 `standard`;缺失或非法时 E2E 会拒绝执行:
42
96
 
43
97
  | mode | 适用场景 | 行为 | 总超时 | 录屏 |
44
98
  |------|---------|------|-------|------|
45
- | `standard`(缺省) | 涉及业务流程、数据流、交互后状态变化 | 完整交互(点击/输入/滚动/提交)+ Network 验证 + 录制 | 5 分钟 | ✅ |
46
- | `lite` | 只看视觉渲染(CSS/布局/文案/图标)或快速冒烟 | 仅 `open` / `goto` / `wait` / `snapshot` / `screenshot`,**禁止** `click` / `fill` / `type` / `scroll` / `select` / `press` / `drag` / `hover` | 2 分钟 | ❌ |
99
+ | `lite` | 基础视觉验证(白屏/布局/样式/文案)或快速冒烟 | 仅 `open` / `goto` / `wait` / `snapshot` / `screenshot`,**禁止** `click` / `fill` / `type` / `scroll` / `select` / `press` / `drag` / `hover` | 5 分钟 | ❌ |
100
+ | `standard` | **仅当用户明确要求**验证业务流程、数据流、交互后状态变化 | 完整交互(点击/输入/滚动/提交)+ Network 验证 + 录制 | 5 分钟 | ✅ |
47
101
 
48
- **仅改 CSS / 文案 / 图标 / 布局**(无事件处理、无状态、无数据获取)应直接选 `lite`——更快且 token 消耗显著低,不要默认走 standard 浪费配额;但 `lite` 不能触发 popup / toast / 提交后状态切换等需要操作的现象。testRequirements 里出现"点击"、"填写"、"提交"等动词,**禁止** `lite`,必须 `standard`。
102
+ **每次派发都必须显式传 mode**。基础视觉验证传 `lite`;`lite` 不能触发 popup / toast / 提交后状态切换等需要操作的现象。**用户明确要求跑功能**({% if e2eStructuredCases %}用例{% else %}testRequirements{% endif %} 里出现"点击"、"填写"、"提交"等动词,或用户直接要求验证某功能)时,传 `standard`。
49
103
 
50
104
  ## 工具选择速查表
51
105
 
52
106
  | 用户表达 | 选择 | 原因 |
53
107
  | --- | --- | --- |
54
- | "检查一下页面" / "看看有没有问题" / "走一遍流程" / "哪里出问题了" / "试试能不能用" / "XX 不好使" | E2E(standard) | 打开浏览器以用户视角操作 / 复现 |
55
- | "刚改了 CSS,看看样式对不对" | E2E(lite) | 仅视觉巡检,省时省 token |
108
+ | "检查一下页面" / "看看有没有问题" / "哪里出问题了" / "试试能不能用" / "XX 不好使" | E2E(显式 `mode: "lite"`) | 未主动要求跑功能,执行基础视觉验证 |
109
+ | "刚改了 CSS,看看样式对不对" | E2E(lite) | 仅视觉巡检 |
110
+ | "点提交试试能不能成功" / "帮我把下单流程走一遍" / "走一遍流程" / "验证一下这个功能" | E2E(standard) | 用户明确要求功能 / 交互验证 |
56
111
  | "测试一下这个接口的返回值对不对" / "调一下后端 API 看看响应" | `api_request` | 明确指定接口验证 |
57
112
 
113
+ {% if e2eStructuredCases %}
114
+ ## 派遣 E2E:用例经 agent_options.cases 传入
115
+
116
+ E2E 只执行你派发的用例清单、不自己规划。用例一律通过 `agent_options.cases` 传入;`prompt` 只留概述 + 应用结构 + 特殊上下文,**不写 `## 测试用例` 段**:
117
+
118
+ ```js
119
+ task({
120
+ subagent_type: "E2E",
121
+ agent_options: {
122
+ mode: "standard",
123
+ cases: [
124
+ { description: "创建一条订单并提交,预期订单出现在列表中", priority: "p0", source: "agent" },
125
+ { description: "按状态筛选订单列表,预期列表只展示所选状态的记录", priority: "p0", source: "user" }, // 用户点名
126
+ ],
127
+ },
128
+ description: "验收订单模块",
129
+ prompt: "对<应用一句话描述>进行验收。## 应用结构\n- <页面> (<路由>) — <职责>",
130
+ })
131
+ ```
132
+
133
+ **规划纪律(自主规划部分,≤6~7 条):**
134
+
135
+ | 规则 | 说明 |
136
+ |------|------|
137
+ | 主业务闭环 1 条 | 跨页多步流程**全场限 1 条**,选最能代表应用价值的链路 |
138
+ | 关键写路径为预算主体 | 提交 / 状态变更 / 删除 / 上传导出——静默失败高发、严重度最高 |
139
+ | 数据展示正确性 | 尽量与页面访问合并在同一用例内验证 |
140
+ | 有网络请求信号的交互 | 筛选 / 查询 / 搜索可以测;**无网络信号的纯前端状态切换(展开折叠/悬浮)不要生成** |
141
+ | 不占名额的项 | 页面可达性 / 首屏健康(E2E 访问页面时顺带检查);纯视觉样式细节(不生成独立用例) |
142
+ | 权限 / 角色 | 仅当应用有登录 / 角色功能时生成 |
143
+
144
+ - `description` 固定表达 **「<具体动作>,预期<可观测结果>」**,禁止模糊词(正常 / 没问题 / 大致可用)
145
+ - `priority`:`p0` **仅限**核心业务主链路(**至多 1~2 条**)与用户点名项(点名项一律 p0);`p1` = 其余保留场景;**不要生成 p2**。p0 标多了,后续复用回归会按默认范围全量重跑,复测成本失控
146
+ - `source`:用户点名的**具体功能**标 `"user"`(复用必跑、可突破预算,硬上限 12);自主规划标 `"agent"`。「走查问题」「全面测试」等**整体性请求不算点名**——那是测试动机,用例仍属自主规划,全部标 `"agent"`
147
+ - **复用回归**:传首跑返回的 `test_plan_file_path`;定向复测用 `agent_options.retest_case_ids: [<用例编号>]` 指定本轮要跑的用例(只列要复测的,别全量重跑);用户新点名项经 `cases`(source:"user")附加即可追加进计划
148
+ - 下方「用例复杂度约束」「断言可观察化」「跑到终态」「工具能力外」各节对 description 同样适用
149
+
150
+ ## 用例(cases[].description)编写规范
151
+
152
+ description 越具体结果越可信;含糊需求只会让 agent 瞎点一通。
153
+
154
+ > **核心原则:E2E 只「机械执行 + 报判断」,不做推理。** 判定标准全写死在 description 里——别让它自己推断"该测什么"或定义"什么算正常 / 好看"。它的活只有:执行动作 → 看现象 → 报通过 / 不通过。
155
+
156
+ - **可定位 + 二元判定**:动作指到具体对象(可见文本,如「发布新帖」按钮);预期给非黑即白判据(出现 / 消失 / 等于 / ≥N / 含某文案),不写"正常""是否合理 / 美观"(见下方对照)
157
+ - **独立可重入**:删除 / 提交等副作用操作走「取消」或验证后还原,不污染后续用例
158
+
159
+ ### 用例复杂度约束(必跑到终态)
160
+
161
+ 每条用例必须**跑到最终可观测结果**,「打开弹窗 / 看到字段 / 按钮存在」都只是中间态,不算验证。
162
+
163
+ - **跑到终态**:提交后出现在列表 / 跳转后内容正确 / 删除后从列表消失
164
+ - **AI 功能看到输出**:翻译 / 摘要 / 生成等核心卖点,须断言到 AI 产出的内容,不停在"AI 弹窗打开"
165
+ - **主链路 + AI 都覆盖**,不因"非主链路"遗漏
166
+ - **用例总数见上方规划纪律(≤6~7,用户点名可突破,硬上限 12)**
167
+ - **不碰登录 / 认证**:应用无登录逻辑,禁止登录 / 注册 / OAuth / CAPTCHA 相关用例
168
+
169
+ | ❌ 停在中间状态 | ✅ 跑到最终结果 |
170
+ |------|------|
171
+ | 打开预约弹窗,验证表单字段 | 填写表单全部字段并提交,预约出现在管理列表中 |
172
+ | 验证翻译弹窗是否正常打开 | 点翻译选目标语言确认,内容区域显示翻译后的文本 |
173
+ | 删除确认对话框是否出现 | 点确认后,记录从列表中消失 |
174
+ | 验证课程信息"完整"展示 | 详情页显示课程名、章节列表、≥1 条学员案例 |
175
+
176
+ ### 断言可观察化对照
177
+
178
+ | ❌ 含糊(agent 无法核对) | ✅ 可观察 |
179
+ |------|------|
180
+ | "页面正常加载" | "页面包含「创作配置」标题" |
181
+ | "按钮可用" | "「一键生成」按钮处于可点击态" |
182
+ | "跳转成功" | "URL 变为 /materials" |
183
+ | "有数据" | "表格中至少展示 3 行数据" |
184
+ | "弹窗出现" | "弹出详情弹窗,展示标题、正文、配图" |
185
+ | "样式好看" | "卡片使用圆角 + 微投影,整体为暖色调" |
186
+
187
+ ### 预期结果写可观察终态,网络核验交给执行器(最易漏检,必读)
188
+
189
+ UI 快照「看起来正常」是最大假阴来源——接口 500、图片 404、失败 toast 都不一定改变页面结构。结构化链路下职责分离:**description 只写可观察的业务终态,不要点名具体接口路径**——写操作触发的全部业务请求(含 `/api/capability/*` 异步链路)由执行器自动全量核验响应码(非 2xx 即 failed),无需也不应在用例里指定查哪个接口。
190
+
191
+ | 漏检模式 | ❌ 错误的 description | ✅ 正确的 description |
192
+ |------|------|------|
193
+ | 停在中间态 | 「打开预约弹窗,预期表单字段完整」 | 「填写并提交预约,预期出现在管理列表中」(提交触发的接口核验由执行器覆盖) |
194
+ | 把 toast 当终态 | 「提交后预期出现成功提示」 | 「提交后预期记录出现在列表中」(toast 瞬时易漏、且不代表后端成功) |
195
+ | 图片指望快照 | 「预期页面有配图」 | 「预期核心区域图片真实渲染(非裂图)」(资源加载失败执行器按健康检查记录) |
196
+
197
+ ### 禁止编写工具能力外的用例(否则只会产生「假失败」)
198
+
199
+ E2E agent 只在离散时刻抓快照 / 截图,**看不到瞬时过程、不逐帧解析动画、不能在导航前改写流量**。下列现象超出工具能力,写成断言只会被报成"失败(工具能力限制)"——属于无效 Case,**从源头就不要写**:
200
+
201
+ | ❌ 工具看不到的现象 | 为什么看不到 | ✅ 改成可观察的终态断言 |
202
+ |------|------|------|
203
+ | 骨架屏 / loading 占位符 | 它是过场态,本就不该当验证目标——数据回来就消失,根本不要去看它 | 直接断言加载完成后的真实内容出现(内容在 = 加载链路通) |
204
+ | toast / 轻提示一闪而过("提交成功""已复制") | 几秒自动消失,离散快照常错过 | 改断它代表的**真实结果**(记录进列表 / 状态切换),权威判据是 network 响应码(非 2xx 即 failed);无明显终态时用 network 调用或重载后持久态代替,**绝不把 toast 当断言对象** |
205
+ | CSS 动画 / 过渡 / 滚动是否"流畅""有动效" | 截图是静态帧,不逐帧评估动画播放 | 断言动画**结束后的状态**(元素已展开 / 已隐藏 / 已就位) |
206
+ | 靠拦截 / mock 网络返回来造错误(如"让接口返回 500 看兜底") | 工具不能在页面加载前注入拦截或改写响应 | 只验真实响应;要看错误兜底需后端真异常或用真实异常数据,不靠伪造流量 |
207
+
208
+ 预期结果若是瞬时中间态 / toast 本身 / 动效本身 / 需伪造网络的分支——改写成稳定终态断言,或直接删掉。
209
+
210
+ ### 建议覆盖维度
211
+
212
+ 覆盖维度(按实际功能裁剪):
213
+
214
+ | 维度 | 典型用例 |
215
+ |------|-----------|
216
+ | 页面加载 / 初始空状态 | 打开后标题、表单、空状态引导文案是否就位 |
217
+ | 表单交互 / 输入校验 | 输入前按钮禁用 → 输入后变可点击;选择器值更新 |
218
+ | 导航切换 | 点击 tab → URL 变化 → 内容正确 → 可返回 |
219
+ | 详情查看 | 点击查看 → 弹窗展示内容 → 关闭 → 回到列表 |
220
+ | 危险操作确认 | 点击删除 → 确认弹窗 → 点取消 → 记录未删除 |
221
+ | AI 功能(核心卖点) | 触发翻译 / 摘要 / 智能生成 → 断言 AI 实际输出的内容出现 |
222
+ | 视觉一致性 | 配色、圆角/投影、响应式单列堆叠 |
223
+
224
+ ## E2E 轮数与复测策略
225
+
226
+ E2E 派遣是**昂贵操作**(每次消耗大量 token + 时间)。E2E agent 只负责暴露问题,**不负责定位根因**。
227
+
228
+ **每次任务执行**的 E2E 总派遣上限 **3 轮**(同一应用内多次任务分别计算):
229
+
230
+ | 轮次 | 派发内容 | 说明 |
231
+ |------|----------|------|
232
+ | 第 1 轮 | `agent_options.cases` 全量用例(规划纪律 ≤6~7 条) | 首次全面验收,返回固化计划文件路径 |
233
+ | 第 2 轮 | `test_plan_file_path` + `retest_case_ids: [失败用例编号]` | 定向复测,**不要重传全量 cases、不要把未失败用例列进 retest_case_ids** |
234
+ | 第 3 轮 | 同上,仅列仍 failed 的编号 | 最后一次机会 |
235
+ | 第 4 轮起 | 禁止再派遣 E2E | 转为根因分析模式 |
236
+
237
+ **定向复测规则**:
238
+ - 已通过的用例最多复测 1 次:担心修复引入回归时可将其编号纳入 `retest_case_ids`,同一用例累计通过 2 次后不再纳入
239
+ - 如果上一轮因超时中断,E2E 会返回"已测通过/已测失败/未完成"三组——已测通过的结果可信不需重测,`retest_case_ids` 只列"失败"和"未完成"的编号
240
+
241
+ **白屏 / 整页打不开 → 复测前先重启 devServer**:白屏多为 **devServer 编译挂死 / HMR 卡住**,非代码 bug,直接再派只会重复白屏、白吃一轮配额。顺序:**① 重启 devServer → ② 查编译输出 / runtime-log 确认无报错(不派 E2E)→ ③ 再正常复测**;真要肉眼确认用 `lite` 截图,别用 standard 探活。
242
+
243
+ **测试范围**:首轮用例数按上方规划纪律(≤6~7),必须含主业务闭环。禁止测试有真实副作用的功能(发送飞书消息、飞书建群)。
244
+
245
+ **停止派遣 E2E 的触发条件**(满足任一即停止):
246
+
247
+ | 条件 | 说明 |
248
+ |------|------|
249
+ | 已派遣 ≥ 3 轮 | 硬上限 |
250
+ | 同一用例**未经代码修改**连续失败 ≥ 2 次 | 修复后重试不算连续 |
251
+ | 本次错误信息与上次完全一致 | 说明修复未命中根因 |
252
+
253
+ 达到上限后仍有 failed:在 commit_task 结果中标注未通过的用例,继续推进后续任务。
254
+
255
+ **停止后的行动**(按优先级执行):
256
+
257
+ 1. **查后端日志**:若涉及数据/接口错误,用日志查询工具排查 traceid / 服务端日志
258
+ 2. **直接读代码**:根据 E2E 报告的 URL 和 problem 定位源文件,人工分析根因
259
+ 3. **重启 dev server**:白屏 / 打不开时按上方「白屏 → 复测前先重启 devServer」流程处理
260
+ 4. **告知用户**:列出已尝试的修复 + 失败现象,请求补充上下文
261
+
262
+ ## Common Mistakes
263
+
264
+ | 错误 | 正确做法 |
265
+ | ------------------------------------- | ------------------------------------- |
266
+ | 用户说"测一下"就调 `api_request` | 默认派遣 E2E(打开浏览器操作) |
267
+ | E2E 完成后又调 `api_request` 补充验证 | 浏览器操作结果即为最终结果,不追加 |
268
+ | 用户说"看看有没有 bug"就同时调两个 | 只派遣 E2E |
269
+ | 用户说"检查接口"时派遣 E2E | 明确提到接口时用 `api_request` |
270
+ | 仅改 CSS / 文案,仍走 `standard` | 优先用 `lite`,速度快、token 消耗低 |
271
+ | 达到停止条件(≥3 轮 / 同一错误未改代码连续失败)仍继续派 E2E | 停止派遣,转为根因分析(读代码 / 查日志) |
272
+ | 复测时重传全量 cases / 白屏直接再派一轮 | 复测传 `test_plan_file_path` + `retest_case_ids`(只列 failed + 未完成的编号);白屏先重启 devServer 再复测 |
273
+ {% else %}
58
274
  ## 派遣 E2E 时的 prompt / 用例规范
59
275
 
60
276
  `prompt` 不是一句话需求,而是一份**结构化验收脚本**。Case 越具体结果越可信;含糊需求只会让 agent 瞎点一通。
61
277
 
62
278
  > **核心原则:agent 只「机械执行 + 报判断」,不做推理。** 判定标准全写死在断言里——别让它自己推断"该测什么"或定义"什么算正常 / 好看"。它的活只有:执行动作 → 看现象 → 报通过 / 不通过。
63
279
 
280
+ {% if e2eSemanticPlan %}
281
+ ### 验收计划文件:先写文件,再派发(首次与后续同一套)
282
+
283
+ 每次派发都必须带 `agent_options.test_plan_file_path`,不传不执行。**两种 mode 各一份卷**,目录必须与派发 mode 一致(串卷不执行):standard 卷写 `.spark/e2e-test/standard/<语义名>.json`(含点击 / 输入 / 提交),lite 卷写 `.spark/e2e-test/lite/<语义名>.json`(只放看得见的检查点)。
284
+
285
+ 1. **先看已有的**:`glob .spark/e2e-test/<mode>/*.json` → **读**可能覆盖本需求的那份(没读过不要传)
286
+ 2. **改还是新建**:同需求用例有变化 → 编辑那份;换了功能 / 页面 → 新建一份
287
+ 3. **派发**:`prompt` 只说跑哪些(`跑 Case 1、2` / `复测 p0 和 p1` / `测试全部用例`),**不点名默认只跑 p0**
288
+
289
+ 格式(一条用例一行,优先级小写,每卷 ≤10 条):
290
+
291
+ ```json
292
+ {"cases":[{"id":1,"priority":"p0","description":"打开首页,预期工单列表渲染出至少 1 行"}]}
293
+ ```
294
+
295
+ - **用例正文只写在计划文件里**:本模式下 `prompt` 不写 `## 测试用例`(下面示例里的用例正文改为写进卷),只留应用结构与本次范围——两处都写会让计划外用例一条不跑、报告却全绿
296
+ - **复测只点名、不删用例**:「只传 failed + 未完成的 Case」指在 `prompt` 里点名,不是从卷里删掉已通过的用例
297
+ {% endif %}
298
+
64
299
  ### 调用结构
65
300
 
66
301
  ```js
@@ -213,6 +448,10 @@ E2E 派遣是**昂贵操作**(每次消耗大量 token + 时间)。E2E agent
213
448
  | E2E 完成后又调 `api_request` 补充验证 | 浏览器操作结果即为最终结果,不追加 |
214
449
  | 用户说"看看有没有 bug"就同时调两个 | 只派遣 E2E |
215
450
  | 用户说"检查接口"时派遣 E2E | 明确提到接口时用 `api_request` |
451
+ | 派发 E2E 时不传 `mode` | 每次都显式传 `lite` 或 `standard`;缺失或非法时不会执行 |
452
+ | 用户没主动要求跑功能,却传 `standard` | 显式传 `lite`;仅用户明确要求交互 / 功能验证才传 `standard` |
216
453
  | 仅改 CSS / 文案,仍走 `standard` | 优先用 `lite`,速度快、token 消耗低 |
217
454
  | 达到停止条件(≥3 轮 / 同一错误未改代码连续失败)仍继续派 E2E | 停止派遣,转为根因分析(读代码 / 查日志) |
218
455
  | 复测时全量重测 / 白屏直接再派一轮 | 只传 failed + 未完成的 Case;白屏先重启 devServer 再复测 |
456
+ {% endif %}
457
+ {% endif -%}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-miaoda-sandbox-skills",
3
- "version": "0.1.0-dev.942e73f",
3
+ "version": "0.1.0-dev.b12eab4",
4
4
  "description": "Miaoda 合并沙箱 skills 包(包含原 miaoda-skills 的 miaoda / miaoda-modern / miaoda-design / shared 四条业务线);发布公网 npm,随沙箱运行时经 update-skills 同步到 .agent/skills/",
5
5
  "type": "module",
6
6
  "files": [