CawPlan TestPoint Generate
跟随用户主语言生成文案;禁止同一段中英各写一遍。
Bootstrap
cawplan skill check
Workflow
归档后用例热交接(优先于 §1) — 本条为「马上生成测试用例」(或同义,见 cawplan-testcase-generate P2),且会话已有有效 binding(product_id + requirement_id)?
- 是 → 读
cawplan-testcase-generateskill,按 P2 热交接续跑(stop 本 skill 后续步骤)。 - 否 → 继续下方 §1。
1. Resolve target Requirement (entry priority)
On each generate test points request, resolve the target in this order (fall through until one row matches):
| Step | Condition | Action |
|---|---|---|
| P1 | This message has an explicit reference (Requirement link / requirement_id / switch to another Requirement) |
Cold handoff — rebind; ignore prior session binding |
| P2 | Hot-handoff phrasing matches and session has valid binding (product_id + requirement_id both present) |
Hot handoff — use current session binding |
| P3 | Session has a requirement draft (five-field draft from analysis) but no valid requirement_id (not saved yet) |
→ 框2「需求还没保存」 below. Do not call APIs or show a test-point table |
| 兜底 | None of the above (no link, no valid binding, no draft) | → 框1「锁定 Requirement」 below |
P2 话术(同义,须先满足有效 binding 才走热交接):马上生成测试点 / 生成测试点 / 补测试点 / 按上面那条 / 按上面那条生成测试点 / 接着刚才那条 等。
有效 binding = product_id and requirement_id both present in session. Phrasing alone without binding → fall through to P3 or 兜底.
框1 · 锁定 Requirement(入口 / 兜底)
触发:上表 兜底(无 Requirement 链接 / 无有效 binding / 无草稿)。P1 或有效 P2 → 不弹。
禁止在选项中出现「用刚归档那条」(属有效 P2 热交接,自动走)。
优先 AskUserQuestion(两个选项,每项须带 label + description;工具会自动追加 Other 自由输入行,标题/占位不可自定义——不要在 skill 里定义或手写 Other / 自由输入行;跟随会话语言整框二选一,不同时输出):
| 字段 | 中文值 | English value |
|---|---|---|
header |
锁定 Requirement | Lock Requirement |
question |
生成测试点前,先确定是哪条 Requirement? | Before generating test points, let's confirm which Requirement this is |
option 1 · label |
已有 Requirement 链接 | I have a Requirement link |
option 1 · description |
把链接发我 | Send me the link |
option 2 · label |
没有 Requirement | No Requirement yet |
option 2 · description |
马上生成并保存到 CawPlan | Generate and save to CawPlan now |
AskUserQuestion 不可用时 — 纯文字降级(逐字;跟随会话语言二选一,不同时输出):
锁定 Requirement
生成测试点前,先确定是哪条 Requirement?
1. 已有 Requirement 链接 —— 选这个,把 Requirement 链接发我
2. 没有 Requirement —— 马上生成并保存到 CawPlan
请回复序号,或直接粘贴 Requirement 链接、或直接说你想怎么做。
Lock Requirement
Before generating test points, let's confirm which Requirement this is
1. I have a Requirement link — pick this, then send me the link
2. No Requirement yet — generate and save to CawPlan now
Reply with a number, paste the Requirement link directly, or just tell me what you'd like to do.
落点:
- 选「已有 Requirement 链接」→ 请对方发 Requirement 链接(一句即可);拿到 Requirement 链接后(下条消息,或工具自动 Other 框里直接粘贴)→ 按下方 Portal URL 规则解析(只解析、不 fetch);仅
requirement_id缺product_id→ 用大白话追问补product_id或完整 Requirement 链接。无法解析为 Requirement 链接 → 复述两项,请重选或补 Requirement 链接。 - 选「没有 Requirement」→ 读
cawplan-requirement-analyzeskill,按 跨 skill 接力:会话写resume_intent = testpoint;有草稿则跳过分析直达归档闸,无草稿则从收素材开始。
框2 · 需求还没保存
触发:上表 P3(有需求草稿、无 requirement_id)。有效热交接 / 已给 Requirement 链接 → 不弹。
优先 AskUserQuestion(两个选项,每项须带 label + description;Other 行由工具自动追加,勿定义;跟随会话语言整框二选一,不同时输出):
| 字段 | 中文值 | English value |
|---|---|---|
header |
需求还没保存 | Requirement Not Saved Yet |
question |
这份需求还没保存到 CawPlan,先保存再来生成测试点 | This requirement hasn't been saved to CawPlan yet — save it first, then generate test points |
option 1 · label |
马上保存 | Save now |
option 1 · description |
存好再接着生成测试点 | Save it, then continue to generate test points |
option 2 · label |
先不保存 | Not yet |
option 2 · description |
先停一下,我再看看这份需求 | Pause for now, I'll review this requirement again |
AskUserQuestion 不可用时 — 纯文字降级(逐字;跟随会话语言二选一,不同时输出):
需求还没保存
这份需求还没保存到 CawPlan,先保存再来生成测试点
1. 马上保存 —— 存好再接着生成测试点
2. 先不保存 —— 先停一下,我再看看这份需求
请回复序号,或直接说你想怎么做。
Requirement Not Saved Yet
This requirement hasn't been saved to CawPlan yet — save it first, then generate test points
1. Save now — save it, then continue to generate test points
2. Not yet — pause for now, I'll review this requirement again
Reply with a number, or just tell me what you'd like to do.
落点:
- 「马上保存」→ 读
cawplan-requirement-analyzeskill,会话写resume_intent = testpoint,走保存/归档流程(确认闸照旧);SUCCESS后回到本 skill §2 refresh 续跑。 - 「先不保存」→ stop;保留草稿,不生成测试点。
- 若 SQA 用工具自动 Other 或自由回复 → 按内容判断(换目标 / 补充说明);无法理解则复述两项选项。
Portal URL (parse only — never fetch):
/product/{product_id}/qa-insights/test-suites/requirements/{requirement_id}
- Extract
product_id+requirement_idfrom the string only. - Forbidden:
cawplan api GET {url}, HTTP fetch, or any request to the portal path.
Only requirement_id, missing product_id: ask for product_id or a full Requirement link. Do not guess the product or scan product lists.
Rebind replaces the whole context (product_id, requirement_id, five fields, test-point stubs). One active Requirement at a time. Same requirement_id as current binding = refresh same row, not rebind. Contradictory messages (new URL + "还是刚才那条") → ask; do not guess.
跨 skill 接力
- 出站(框1「没有 Requirement」、框2「马上保存」):接力前写入
resume_intent = testpoint。 - 入站回归:需求分析归档
SUCCESS后,发起方从 §2 refresh 继续。 - A1 §6 引导入站:需求分析 §6 成功回执后 SQA 说「马上生成测试点」→ 有效 binding 下 P2 热交接,直跑 §2 refresh(无需再贴需求)。
- 出站回归(
resume_intent = testcase):测试点归档SUCCESS(或 §10count_matched确认已落库)后,若会话存在resume_intent = testcase,读取并清除resume_intent,读cawplan-testcase-generateskill 从其 §2 refresh 续跑;不追加 §9.5 用例引导;不停在本 skill 等下一条指令。 - 归档后用例引导:§9.5 成功回执末尾可选追加一句(见 §9.5 末尾引导);用户回「马上生成测试用例」→ 读
cawplan-testcase-generateskill(P2 热交接);不接茬则不重复提示。 - 框1「已有 Requirement 链接」解析成功 → 按 P1 冷交接继续,不弹框2。
2. Refresh before generate (always)
Before generating or supplementing test points (cold or hot), pull live data:
cawplan api GET /api/v1/public/openapi/product/<product_id>/qa/requirements/<requirement_id>
Use data directly for the five fields + url (single QARequirement object; no list filter).
cawplan api GET /api/v1/public/openapi/product/<product_id>/qa/requirements/<requirement_id>/testpoints
Record data.test_points.length as count_before (session state ③). This is the baseline testpoints reconcile needs if an archive comes back UNKNOWN — the command refuses to derive it, because a second GET could pick up rows someone else added in between and silently corrupt the comparison. Re-record it on every refresh; a stale baseline is worse than none.
| Result | Action |
|---|---|
Requirement found (code: SUCCESS) |
Use latest five fields silently; do not diff against chat cache |
Requirement missing (404 or explicit not-found) |
Report "这条 Requirement 已不存在" / "This Requirement no longer exists"(跟随会话语言二选一); do not generate from stale context |
Use five fields for generation only. Do not track module_tree_node_id, review_status, or ticket_id for A2 logic.
3. Incremental gate (§9.3)
Check in this order (library-empty check first — do not evaluate intent wording before this):
testpointsis empty → generate directly. Do not ask, regardless of how vague the phrasing is (e.g. "生成测试点" alone). This is the most common case (first-time generation) and must never fall into step 2.testpointsis non-empty and intent is vague ("生成测试点" only, no indication of supplement vs. review) → stop and ask:- Supplement a few more on top of existing?
- Show what's already archived first?
testpointsis non-empty and intent is clear ("再补两条并发的" / "看看已有的") → proceed directly.
4. Read coverage references (required)
Before discovering obligations, use the file-reading tool to read both files completely; do not rely on memory or hardcoded rules in this skill. Do not enter Step 1 until both reads have returned successfully. If either file cannot be read, stop and report the missing reference instead of generating a draft.
references/coverage-dimensions.md— discovery knowledge used in Steps 1–2.references/review-checklist.md— terminal checklist applied only in Step 5; reading it here does not make it a second generator.
After both reads succeed, go straight to Step 5. Do not call any tool and do not pause for confirmation between finishing these reads and starting Step 5 — in particular, do not call AskUserQuestion here; there is nothing to ask at this point.
5. Generate test points (no write)
目标顺序:覆盖完整度优先(Recall > Precision);允许多生成可删的方向性测试点,但红线 0 永远优先。先把候选完整展开,再统一分流与收敛;不得在发现阶段挑“代表性场景”。
候选先各自独立列出,逐条判断最终归入测试点或存疑;不需要另建状态表、账本字段或覆盖矩阵——来源判断随手做,不建表,也不呈现、不落库。
Step 1 — 发现
将五字段逐句完整读到末尾,按对象、操作、关系、约束、变化、不变量拆出彼此独立的验证候选;已发现若干项也不得提前收尾。
对每个命中的值、状态、条件、来源、角色、适用层级、前后变化与不受影响对象分别发现候选。若多个分区可能有不同结果,先分别列出,不得先合并——是否属于同一验证目标、是否应合并成一行是 Step 4 的判断,本步骤只管展开不管收敛,不得因为"反正最后会合并"就提前用一句话跨分区、跨对象归纳掉候选。 排除性/口径声明句必须单独展开:五字段中出现"仅统计 X,不与 Y 合并"「不包含 / 不影响 / 独立于 / 与…无关」这类没有显式动作、只是在给某个概念划边界或排除歧义的句子时,不得因为它读起来像背景说明或定义就跳过——必须单独产出一条候选,验证"该口径/边界在实际行为中确实被遵守"(例如"其他类型端口的连接数变化不应影响图片上限判断")。
逐项使用
references/coverage-dimensions.md的路径类型和 A→B→C→D 变化轴作为发现提示。C/D 八轴必须逐项读到,不能因需求无关键词提前停止;是否有正面排除证据在 Step 3 统一判断。基本盘方向只要与功能形态相符就进入候选:正常主路径;外部输入的异常;存在范围时的合法边界;存在取消/撤销/回退时的逆向。需求没写失败细节不等于不适用。
五字段完全无法形成操作 + 方向性预期时停止并请 SQA 补充;薄但可测时继续,缺口进入存疑。
停止后话术(纯文字,逐字;跟随会话语言二选一,不同时输出):
这份需求的信息还不够生成测试点(缺操作或预期方向),麻烦补充一下具体是做什么、期望什么结果,我再继续。 This requirement doesn't have enough detail to generate test points yet (missing the operation or expected direction) — please add what it does and what's expected, and I'll continue.
Step 2 — 补齐关系分区与有意义组合
- 若需求存在真实关系语义,按
coverage-dimensions.md的关系知识补齐分区候选;不得只覆盖需求举出的单侧关系(数量比较通常检查< / = / >,具体预期仍由 Step 3 按证据分流)。 - 两个因素组合后,只要可能改变可用性、结果、状态、副作用、反馈、影响范围或恢复行为,就展开组合候选;默认只检查二元组合,只有需求明确三因素联动、或任一二元检查都无法表达风险时才展开三元组合。
- 禁止无意义全量笛卡尔积;仅“同时出现”但不会改变行为的因素不组合。拿不准是否影响行为时,保留该组合候选交 Step 3 分流,不得静默丢弃。
Step 3 — 每项按证据分流
每条候选最终且只能归入以下一类:
- 测试点:方向唯一,能在不编造细节的前提下写出“操作/条件 + 方向性预期”。只是“要不要纳入本轮”未拍板,但功能形态明显适用时,也生成方向性测试点,并在标题末尾加“(范围待确认)”。
- 存疑:存在多种合理实现或预期;缺少必要触发条件;或必须补充具体规则后才能断言。格式为:〔指向哪〕+〔为什么疑〕+〔建议动作〕。
- 排除:仅限五字段明确列入 out_of_scope、功能形态直接正面证明不可能成立,或类型/状态/业务约束明确不可达;记录简短理由。不得用“需求没提”“感觉不重要”“已有相似点”作为排除理由。
C/D 不对称硬规则:对 幂等 / 并发 / 一致性 / 存量兼容 / 环境兼容 / 性能 / 安全审计 / 可观测 八轴逐项应用 coverage-dimensions.md 的正面形态门槛。只有门槛正面证明不适用时才可排除;否则该轴必须贡献至少一条“测试点”或“存疑”。多轴指向同一缺口时可合并存疑文案,但不得因此遗漏轴名或去向。A/B 轴若功能形态明确不涉及可不产生候选。
红线 0 — 防臆造(最高优先级):
- 标题只能使用五字段已有的具体事实,以及“应成功 / 应失败 / 应拦截 / 应有明确反馈”等方向性预期。
- 五字段未提供时,禁止编造具体数值、阈值、次数、超时时长、文案、错误码、产品隐藏规则或实现方式。
- 若候选只有具体部分缺证据,优先拆成“方向性测试点 + 具体细节存疑”;不得因细节未知把可测方向整项丢掉。
- 五字段已给出的数值、枚举、文案或规则可以直接使用。
- Recall 优先只允许增加有依据的方向,不允许增加虚构细节。
存疑纪律:
- “素材未提及 / 需补充”不能单独构成存疑;必须指出具体覆盖方向、缺少的决策及建议动作。
- 多种合理实现(如入口隐藏或点击后拦截)必须存疑,不猜其中一种。
- 产品特有联动、隐藏规则、跨功能归属和主观体验只能作为能力边界提示,不得假装已覆盖。
Step 4 — 全部分流后统一收敛
只有所有候选都完成 Step 3 后,才允许生成最终标题、合并和批内去重。**禁止用 representative 场景替代候选。**数量由覆盖空间决定,无固定上下限。
颗粒度与合并规则:
- 一行 = 一个 verification goal(测什么),不写前置条件 + 步骤序列 + 逐值 Expected;可执行脚本属于 A3。候选的颗粒度允许比最终 Test Point 更细——Step 1 展开的多条候选合并成一行,是本步骤的正常产出,不是发现阶段的失败。
- 合并判据(先判差异性质,再判是否同一行为):
- 两条候选的差异,是否仅来自同一个 verification goal 下的 partition 取值(具体对象/位置如首位/中间/末位、比较关系取值
< / = / >、边界值、输入值、状态值,以及套餐/权限/状态本身就是该 goal 要覆盖的分区时,例如"免费版/付费版执行同一操作,结果应保持一致")?- 操作类型(删除/新增/替换/提交……)相同、只是作用对象不同(作用在哪个位置/哪一项)→ 属于 partition。
- 前置条件是否可并入 partition,看它是否引入了不同的产品行为或规则:若只是同一行为在不同前置下的结果一致性验证,前置就是 partition;若前置改变了被验证的产品行为本身(例如付费版解锁了免费版完全没有的功能分支),则不是。
- 只要有任一处差异不满足"仅来自 partition 取值"(操作类型不同、被验证的属性/行为不同、前置引入了新的产品行为)→ 不得合并,不得为了凑合并重新定义"这也算一种分区"。
- 确认是 partition-only 差异后,把具体取值抽换成占位符做语义层面(非字符串层面)比较:抽掉 partition、归一化措辞后,是否仍在验证同一对象上的同一产品行为/属性?是则合并;归一化后发现对象或行为其实不同,退回不合并。
- 不得先认定"最终想合并成一行"再倒推着把不同验证目标包装成同一 goal 的分区;必须先判差异性质,再决定要不要合并,不能反过来。
- 两条候选的差异,是否仅来自同一个 verification goal 下的 partition 取值(具体对象/位置如首位/中间/末位、比较关系取值
- 仅测试数据不同的同一目标合并为一行,并在标题中列全关键值/状态/位置/条件/来源/范围;默认项不可省略。 口径/边界声明类候选默认不合并:由 Step 1「排除性/口径声明句」规则产生的候选(如"某类统计口径不与其他类型合并"),默认保留独立成行,除非能明确证明合并后的标题仍完整保留该口径的验证意图。拿不准时优先保留独立条目,不得为了表格简洁或凑数硬合并导致该口径的验证意图消失。
- 合并守恒:合并不得改变最终归类;每条合并前的测试点候选都必须映射到至少一条最终标题,且能从标题反查其关键分区。做不到就不合并(详细复查见 §6「上限三方向 + 分区值列全」及
references/review-checklist.md§三)。 - 批内去重只处理本轮无 id 草稿。不得按语义删除已归档行;跨批仅以 id 区分。增量展示可由“已存 N + 新增 M”的整体集合证明覆盖,但归档仍只提交 M。
- 为每条最终测试点填写
group、tags、priority;标签规则以coverage-dimensions.md为准。
标题形态:前置条件 + 被测行为 + 方向性预期;一个标题只表达一个验证目标。
Good: Free plan 已有 50 个 workflow 时再 Duplicate 应提示超过上限且无法复制
Good: 选择各 Duration 挡位(5s/10s/15s,含默认 15s)后,导出视频时长应与所选挡位一致
Bad: 测试复制功能
Bad: 打开配置 → 分别选择各挡位 → 逐档导出并检查(这是 A3 步骤)
Priority rules(每条测试点必填):
| 判断依据 | priority |
|---|---|
| 正向主路径,或涉及资金、权限、数据丢失风险 | HIGH(默认档) |
| 核心链路的异常 / 边界 | MEDIUM |
| 非核心、辅助性、UI 细节 | LOW |
- AI 不主动生成 CRITICAL;SQA 可在修订时指定。
- priority 必须逐字符等于 CRITICAL / HIGH / MEDIUM / LOW 之一。
- 存疑不是测试点,不需要 priority。
6. Step 5 — 覆盖闭合与一次需求特异性反查
Step 4 形成草稿后、首次呈现前执行一次。若 Step 1 判定五字段完全不可测,则跳过。
对照 §4 已完整读取的 references/review-checklist.md 从头到尾走一遍(不得跳过,也不得凭记忆替代):逐条检查覆盖闭合(来源 / 关系分区 / 行为组合 / 去向)、收敛守恒(合并映射、标题可反查)、红线与输出契约;发现缺口就补候选并回 Step 3 分流,发现错合并就拆回独立标题。以下四项是本轮最容易漏、必须显式确认的重点,不因为已过完清单就跳过:
- C/D 八轴每轴都有去向:幂等/并发/一致性/存量兼容/环境兼容/性能/安全审计/可观测,逐轴确认要么有正面排除证据,要么已归入测试点或存疑,不留空轴。
- 上限三方向 + 分区值列全:涉及比较或配置/容量切换的候选,
< / = / >(或变小/不变/变大)三态是否齐全;已合并标题里的具体分区值(位置、状态、比较结果等)是否逐字保留,没有被"任意/某个/某种"这类抽象词糊掉。 - 红线 0 不越界:所有标题只用五字段已有事实和方向性预期,没有编造数值、次数、文案、错误码。
- 输出契约:每条测试点一个目标、合法主标签、priority 枚举正确、英文会话用术语表词、补充标签至多一个且只在 tags[1]。
完成后一次需求特异性反查:丢开清单,把五字段原文与草稿并排重读一遍,只问"这份表最可能漏掉哪项本需求特有的风险",剩余特异性语句扫到末尾;新发现项走 Step 3 分流,再做一次来源/去向/合并守恒确认即可,不必再次通读整份清单。
Incremental scope:闭合时用“已归档 N + 本轮新增 M”整体判断覆盖,已有标题可承接候选;只为缺口生成 M,绝不修改或重发 N。只在本轮首次呈现前执行一次,SQA 修订后不自动重跑,除非明确要求重新生成。
Internal only, one version:不得输出候选、排除理由、检查过程、勾选表或来源标记。完成五步后只向 SQA 呈现一版最终表;本阶段新增行仍是 AI 原稿,归档时 is_edited 为 false。
7. Present to SQA
输出纪律:呈现时只给「哪条需求 + 表」(首批加「草稿」、增量按状态列区分);禁止复述内部过程——不得出现「轴遍历 / 自查 / 覆盖维度清单 / 已按…完成 / 五字段已读取 / 核对完毕」等字样。第一句直接进正题。
开场(〔需求名〕 = summary → truncate function_description → requirement_id,与保存确认等处显示名规则一致):
首批(库为空,逐字;跟随会话语言二选一,不同时输出):
需求「〔需求名〕」的测试点草稿如下(这条之前还没有测试点): Draft test points for requirement "〔需求名〕" (no existing test points yet):
增量(库里已有,逐字;跟随会话语言二选一,不同时输出):
需求「〔需求名〕」的测试点如下(已有的标「已存」、本轮新增标「新增」): Test points for requirement "〔需求名〕" (existing ones marked "Saved," new ones this round marked "New"):
紧接下方分节表;不要在开场前另加覆盖面叙述或其它过程说明。
测试点清单 — 按
group分节呈现(硬性要求,每次必做)禁止把全部测试点挤进一张无分节的连续表。即使
group字段已在各行有值,也不得只靠N.M序号暗示分组——必须先打出组标题行,再跟该组的小表。分节规则(仅排序与分表呈现;不改
group取值或分组逻辑):- 按各行已有
group字段归并;空group→ 组名显示为未分组,且永远排在最后一节。 - 节序号 N = 第 N 组(从 1 起);组内行序号 N.M(M 从 1 递增)。
每一节固定两块输出(节与节之间空一行):
**N. {组名}** | 序号 | 标题 | 标签 | 优先级 | |------|------|------|--------| | N.1 | … | … | … | | N.2 | … | … | … |- 组标题格式(硬性):单独一行,形如
**1. 分享创建**、**2. 权限与访问控制**。{组名}= 该节group字段原文(空则用未分组)。每一组都必须有标题行——单组时也输出**1. …**,不得省略。 - 每节一张小表:表内只放该
group的行;禁止跨组合并成一张大表。 - 每次呈现都要分节:首次生成、SQA 修订后重展、增量合并展示——规则相同,组标题不可漏。
- 组内顺序不变:加
优先级列不改组内行序,不按 priority 重排。
列定义:
- First batch (library empty):
序号 | 标题 | 标签 | 优先级— no status column; no row bolding. - Incremental (library has archived rows):
序号 | 标题 | 标签 | 优先级 | 状态— see rules below. - 已存行(无
priority字段的老数据):优先级列显示—,不臆造、不补算。
- 按各行已有
存疑清单 after all group sections (§5): 〔指向哪〕+〔为什么疑〕+〔建议动作〕; no coverage checkbox matrix. If none: say so explicitly.
尾巴(草稿表 + 存疑清单之后,逐字;首次呈现与 §8 修订后重展均输出;不做弹框;跟随会话语言二选一,不同时输出):
要改就直接说(增删,或改标题/标签/分组);没问题就说一声「保存到 CawPlan」。 Just tell me if you want changes (add/remove, or edit title/tags/group); if it looks good, say "save to CawPlan."
Do not state draft totals before save (no 共 N 条草稿, no N in save prompts). SQA reviews the tables; the only count SQA sees is in the post-POST success receipt (§9.5).
Incremental merged display (only when library already has test points — N archived + M new drafts):
Per §7 step 1: one section per group (group title line + small table). Within each group, merge archived + new into one table; continuous numbering (archived first in API order, new drafts appended). 存疑清单覆盖 full N+M set(不要另加覆盖面叙述)。Archive only drafts without id; edit/delete archived rows → Test Suites UI.
Distinguish 新增 vs 已存 (two means — status column is required; bold is optional):
- Status column (primary, plain text):
已存(hasid, read-only) or新增(this round's draft, noid). This column alone must make the distinction clear even if other formatting fails. - Bold entire rows (enhancement): status
新增→ bold all five cells (**…**);已存rows not bold. May write🆕 新增in the status column.
No count summary after tables — do not write 本轮新增 M 条 / 其余 K 条为已存 / 共 N 条 (agents cannot reliably count rows; see Rules Index · Draft totals). Optional non-numeric footer after all group sections(跟随会话语言二选一,不同时输出): 已存的标「已存」(只读,改/删请去 Test Suites 后台);「新增」为本轮新测试点,确认后只保存新增的。 / Items marked "Saved" are read-only here (edit/delete via the Test Suites console); items marked "New" are this round's new test points — only the new ones will be saved once confirmed.
Rendering discipline:
- Group title lines are a hard requirement — same priority as the incremental status column. Never skip them to save space or because
groupis already on each row internally. - Bold and emoji in tables are enhancements only — some clients may not render
**or emoji inside tables. Status column text (incremental) and group title lines must carry meaning without relying on table-only formatting. - Never rely on bold/emoji alone to tell 新增 from 已存.
8. Revise from SQA feedback
Natural language: add / delete drafts / edit title, tags, group / adopt 存疑 items. Ambiguous edits → ask.
Adopting 存疑 → new test-point rows counts as a revision round (same as add): re-show full table, recompute 序号.
After any revision round → re-show the full 分节清单 (every group title + per-group table, §7 step 1) with recomputed numbers; refresh 存疑 as needed; re-output §7 尾巴. Prompt: review by title content, not old numbers only (§4.4).
SQA insists on keeping two similar rows → keep both; do not re-run §2.2 merge on those rows.
Never auto-save. "看着不错" ≠ save → ask e.g. 要现在保存,还是再调调? / Save now, or keep adjusting?(跟随会话语言二选一) — no draft count in this prompt.
原稿 = 本轮完成 Step 5 后首次呈现给 SQA 的完整表;五步内部草稿不计。Step 5 补充行属于原稿。Track which draft rows SQA touched for is_edited (§9).
9. Archive (write — explicit confirm only)
Proceed only when SQA clearly says 保存 / 存 / 入库 / 保存到 CawPlan.
Save confirm (§9.4) before POST — AskUserQuestion; no draft count. AskUserQuestion 无「框上正文」字段 → 先输出一行路径正文,再弹框(勿把路径塞进 question)。
〔需求名〕 = summary → truncate function_description → requirement_id.
首批保存
框上方正文(逐字,填入 〔需求名〕;跟随会话语言二选一,不同时输出):
将测试点保存到需求「〔需求名〕」下。 These test points will be saved under requirement "〔需求名〕."
优先 AskUserQuestion(两个选项,每项须带 label + description;工具若自动追加 Other 行,勿在 skill 里定义 Other;跟随会话语言整框二选一,不同时输出):
| 字段 | 中文值 | English value |
|---|---|---|
header |
确认保存 | Confirm Save |
question |
确认保存这批测试点? | Confirm saving this batch of test points? |
option 1 · label |
确认保存 | Confirm save |
option 1 · description |
存到 CawPlan | Save it to CawPlan |
option 2 · label |
先不保存 | Not yet |
option 2 · description |
先留着草稿 | Keep it as a draft for now |
AskUserQuestion 不可用时 — 纯文字降级(逐字;跟随会话语言二选一,不同时输出):
将测试点保存到需求「〔需求名〕」下。 确认保存这批测试点? 1. 确认保存 2. 先不保存(回序号)
These test points will be saved under requirement "〔需求名〕." Confirm saving this batch of test points? 1. Confirm save 2. Not yet (reply with a number)
增量保存(库里已有,仅存本轮新增)
框上方正文(逐字,填入 〔需求名〕;跟随会话语言二选一,不同时输出):
将本轮新测试点保存到需求「〔需求名〕」下(已存的不动)。 This round's new test points will be saved under requirement "〔需求名〕" (existing ones are untouched).
优先 AskUserQuestion(两个选项,每项须带 label + description;工具若自动追加 Other 行,勿在 skill 里定义 Other;跟随会话语言整框二选一,不同时输出):
| 字段 | 中文值 | English value |
|---|---|---|
header |
确认保存 | Confirm Save |
question |
确认保存本轮新测试点? | Confirm saving this round's new test points? |
option 1 · label |
确认保存 | Confirm save |
option 1 · description |
存到 CawPlan | Save it to CawPlan |
option 2 · label |
先不保存 | Not yet |
option 2 · description |
先留着草稿 | Keep it as a draft for now |
AskUserQuestion 不可用时 — 纯文字降级(逐字;跟随会话语言二选一,不同时输出):
将本轮新测试点保存到需求「〔需求名〕」下(已存的不动)。 确认保存本轮新测试点? 1. 确认保存 2. 先不保存(回序号)
This round's new test points will be saved under requirement "〔需求名〕" (existing ones are untouched). Confirm saving this round's new test points? 1. Confirm save 2. Not yet (reply with a number)
「先不保存」回执(纯文字,逐字;跟随会话语言二选一,不同时输出):
好的,先不保存。测试点草稿还在,你可以继续改;想好了说一声「保存到 CawPlan」。 Okay, not saving for now. The test point draft is still here — keep editing, and just say "save to CawPlan" when you're ready.
Before POST: build test_points from the last full table in display order — one body entry per draft row without id, same order as shown. Do not skip or duplicate rows.
POST only drafts without id, in display order:
cawplan qa-insights testpoints archive <product_id> <requirement_id> \
--body-file <path> # {"test_points":[{"title":"...","tags":["边界"],"group":"...","priority":"HIGH","is_edited":false}]}
Never pipe this command through head/tail/other output-truncating filters (e.g. ... | head -30) — the full stdout JSON receipt is the only source for the outcome branch below and for the archived-count downstream (Test points added in QA daily reports). A truncated receipt can't be parsed and silently counts as zero, even when the batch actually landed.
Body per item (skill/agent): only title, tags, group, priority, is_edited. priority is required, one of CRITICAL / HIGH / MEDIUM / LOW (§5 Priority rules) — the command hard-rejects a missing or invalid value. The Skill/agent must not submit category_code manually. The CLI injects is_ai_generated: true and category_code on each item before POST — do not put either field in --body-file. category_code is calculated once, only when the test point is created; later Skill-side changes to tags do not trigger recalculation, and the stored category_code remains unchanged. The command rejects the batch and sends nothing if an item carries anything else (an id here usually means an already-archived row is being re-posted).
is_edited: false if untouched since 原稿 (includes rows added during Step 5 — AI-generated, no source tag); true if SQA edited or added (including adopting 存疑). Incremental batch: only for new M drafts vs their 原稿; archived N rows excluded. The command passes this through verbatim — it never infers the value, so getting it right is this skill's job.
Branch on outcome:
outcome |
Action |
|---|---|
SUCCESS |
The command already verified the envelope and that the returned count equals what was sent. Store api.data.test_points[].id as session stubs (§10); do not list them to SQA → success receipt (§9.5) |
FAILURE |
Report error.message honestly (§9.6). validation = the body was built wrong; fix and resend. Do not fake success, do not blind-retry |
UNKNOWN |
The batch may or may not have landed. Never re-archive on a guess → §10 |
Success receipt (§9.5) — only place SQA sees a count. Two lines when url is present; otherwise line 1 only. Use N = body.test_points.length (or response test_points.length on SUCCESS). 〔需求名〕 = summary → truncate function_description → requirement_id.
- Line 1(逐字;跟随会话语言二选一):
已保存 N 条测试点到需求「〔需求名〕」下。/Saved N test points under requirement "〔需求名〕." - Line 2(仅当 refresh 返回非空
url;单独一行,不接到 line 1 句末;逐字;跟随会话语言二选一):Requirement 链接:{url}/Requirement link: {url}
If url is missing or null — output line 1 only; say nothing about links — never construct portal URLs, never note that url was unavailable.
Forbidden in success receipt: per-row tables; title lists; id lists; re-generated or summarized titles; any line about missing url (e.g. "未返回 url"/"无法附 Requirement 链接"); apology or post-hoc recount explanations (e.g. "之前误算成 13 条").
§9.5 末尾引导(可选追加) — 满足全部条件时,在成功回执最后另起一行逐字追加(不弹框、不追问、仅本轮一次;跟随会话语言二选一,不同时输出):
想继续生成测试用例?说「马上生成测试用例」,我会在当前会话直接生成。 Want to generate test cases next? Say "generate test cases now" and I'll do it right in this session.
追加条件(须同时满足):
- 本轮测试点归档结果为
SUCCESS(含 §10count_matched确认已落库后下接 §9.5 式回执) - 会话无
resume_intent(非跨 skill 入站接力后的自动出站回归) - 非「先不保存」回执路径
- 非保存失败 / UNKNOWN /
pending_write未定态
不追加:保存失败、结果未定、先不保存;出站 resume_intent = testcase 自动回流 cawplan-testcase-generate(已自动续跑,无需再引导)。SQA 未接茬、去做别的 → 顺其自然,不重复提示。
用户接茬:SQA 说「马上生成测试用例」→ 以会话 product_id + requirement_id 读 cawplan-testcase-generate skill,当前会话 P2 热交接直跑 §2 refresh,无需再贴需求或测试点。
On failure → report error.message (and api.code / api.msg when present) honestly (§9.6). Do not fake success or blind-retry.
10. UNKNOWN write outcome (§9.4)
Archive returned outcome: UNKNOWN → set write_outcome = UNKNOWN, then run:
cawplan qa-insights testpoints reconcile <product_id> <requirement_id> \
--count-before <§2 刷新时记录的基线> --batch-size <本批条数>
--count-before is the baseline recorded at the §2 refresh, before the archive. The command will not guess it. Read-only — it never writes.
Same rule as §9: never pipe this command through head/tail/other output-truncating filters — the full stdout JSON receipt is what the reconcile.decision branch below reads.
reconcile.decision |
Action |
|---|---|
count_matched |
The batch already landed. Tell SQA it is saved; clear UNKNOWN; merge stubs on the next refresh. Do not archive again. → 下接 §9.5 成功回执(含末尾引导,条件同 §9.5) |
retry_same_batch |
Nothing landed. Read-back, then archive the same batch — not a regenerated one. |
count_unexpected |
The count is neither unchanged nor +batch. Someone may have appended concurrently, or the data is inconsistent. Stop and ask SQA to check Test Suites; archive nothing. |
Never re-archive a batch on ambiguity.
11. Archived row edits
SQA wants to change/delete a row with id → direct them to Test Suites UI. A2 only appends; no PATCH/DELETE.
Session state (in-conversation only)
① Binding: product_id, requirement_id, five-field snapshot, url.
② Work set: 原稿 snapshot; touched-row marks; current drafts; archived stubs from last refresh.
③ Write: pending_write after save confirm; write_outcome SUCCESS / failure / UNKNOWN.
Refresh binding + stubs before each generate. Rebind clears all. After successful archive, merge new ids into stubs; new supplement round gets a new 原稿 for the M drafts.
Walkthrough example (workflow Duplicate — requirement 019fb63e-d5ad-7cb7-8b5f-761ceeb50c0a)
五字段(节选):workflow 项目 Duplicate;入口为项目卡片更多菜单;正常预期为生成副本、列表可见、新窗口打开;约束含仅 workflow 类型、他人分享不可复制、命名 Copy of xxx、125 字符上限、素材一并复制、Free plan 50 个上限等。
obligation 发现(节选):本人拥有 / 他人分享、workflow / 其他类型、成功复制、命名与素材保持、50 个数量边界、125 字符长度边界、连续触发幂等、列表写后可见等先分别进入同一清单;50 个配额与并发操作可能改变结果,因此保留组合 obligation。C/D 其余轴若未被形态门槛正面排除,均归入测试点或存疑,不维护独立判轴表。
批内去重示例:已有「Free plan 达 50 个 workflow 时 Duplicate 应提示超限」→ 不再单独生成「第 51 次点击 Duplicate 仍提示超限」(同验证目标,仅状态不同)。
样例测试点(草稿):
1. 复制与命名
| 序号 | 标题 | 标签 | 优先级 |
|---|---|---|---|
| 1.1 | 本人拥有的 workflow 项目点击 Duplicate 后应在列表出现名为「Copy of 原项目名」的副本 | 正向 |
HIGH |
| 1.2 | Free plan 账号已有 50 个 workflow 时再 Duplicate 应提示超过最大限制且无法复制 | 边界 |
MEDIUM |
| 1.3 | 连续快速点击 Duplicate 应仅创建一份副本 | 幂等 |
HIGH |
| 1.4 | Duplicate 进行中应有进行中态,且完成前入口不可重复触发 | 交互反馈 |
LOW |
存疑(节选;不同缺口不合并):
- 约束未明确 AD Video / Story 类型是否隐藏 Duplicate 入口——建议在需求
out_of_scope标明,或确认 UI 层入口不可见即可。 - 〔并发 × 50 个上限〕并发 Duplicate 可能改变配额判断与创建结果,但需求未给出并发预期——建议确认是否纳入,并补充应拦截还是允许部分成功。
- 〔存量兼容〕改动既有 workflow 能力,但老项目或历史数据表现未明确——建议确认本次兼容范围。
- 〔环境兼容〕功能经 Web 客户端发起,但网络中断后的反馈与恢复方向未明确——建议确认是否覆盖弱网 / 中断恢复。
其余未被形态门槛正面排除的 C/D obligation 也必须各有测试点或存疑去向;本节只展示标题格式,不表示已静默排除。
Walkthrough example (login — baseline vs 红线 0)
五字段(节选):账号 + 密码登录;入口为登录页;正常预期为登录成功并进入首页;约束未写账户锁定策略。
生成(草稿):
1. 登录校验
| 序号 | 标题 | 标签 | 优先级 |
|---|---|---|---|
| 1.1 | 正确账号和密码登录应成功并进入预期页面 | 正向 |
HIGH |
| 1.2 | 错误账号或密码登录应失败并给出明确提示 | 异常 |
MEDIUM |
存疑(可选一条):连续登录失败是否触发账户锁定 — 五字段未写策略,请确认是否在本次范围内。
不生成:「第 3 次失败锁定账户」「提示应为『用户名或密码错误』」等需具体次数/文案的测点(红线 0)。
Walkthrough example (video config — granularity / Duration merge)
五字段(节选):导出前可在视频配置面板设置 Duration 挡位 5s / 10s / 15s(默认 15s)与 Resolution;正常预期为导出视频时长与所选 Duration 一致;约束未写 4K 是否需要付费套餐。
颗粒度:Duration 三挡 → 一条列全值、不拆三条、不塞步骤 — 见 §5 Step 4 与 Good/Bad 示例。若五字段写明「4K 仅付费套餐可用」→ 4K 与普通分辨率是不同前置/预期 → 单独成条或进存疑。
样例测试点(草稿,节选):
1. 导出与时长
| 序号 | 标题 | 标签 | 优先级 |
|---|---|---|---|
| 1.1 | 选择各 Duration 挡位(5s/10s/15s,含默认 15s)后,导出视频时长应与所选挡位一致 | 正向 |
HIGH |
Rules Index
Authoritative rules live in Workflow; this section is navigation only. On conflict: 红线 0 > Recall 优先 > 收敛规则。
| Rule | Authority |
|---|---|
| 红线 0 — 防臆造 | §5 Step 3 红线 0 + §6 输出契约检查 |
| Obligation discovery | §5 Step 1–2; knowledge → references/coverage-dimensions.md |
| Disposition / C-D asymmetry | §5 Step 3 |
| Granularity + merge conservation | §5 Step 4; recheck → §6 |
| Priority — 每条测试点必填 CRITICAL/HIGH/MEDIUM/LOW | §5 Priority rules |
| 存疑清单 — format & discipline | §5 存疑清单纪律; presentation → §7 step 3 |
| Double closure + requirement-specific review | §6 Step 5; output checks → references/review-checklist.md |
| Presentation — 分节、状态列 | §7 |
| Draft totals — SQA 只看保存后条数 | §7 · §9.5 · §9 save confirm(禁草稿/保存前计数) |
| Archive / confirm / receipt | §9; UNKNOWN → §10 (testpoints reconcile, needs count_before from §2) |
| Cross-batch identity / batch-internal dedup | §10 (id stubs); batch-internal → §5 Step 4 |
| API | Writes → cawplan qa-insights (§9 archive, §10 reconcile); reads → cawplan api GET (§2); references/CAWPLAN_OPEN_API.md §15 |
| Trigger boundary | §1 决策树 P3 → 框2;兜底 → 框1;ticket URL without test-point intent → not this skill |
| Failures | §9 On failure; keep drafts |
Output & Confirmation
- Generate / revise (no archive) → §5–§7
- Save confirm + POST → §9; UNKNOWN reconcile → §10
References
references/CAWPLAN_OPEN_API.mdreferences/coverage-dimensions.mdreferences/review-checklist.md