Compare commits

...

6 Commits

Author SHA1 Message Date
0ea924958f docs: 沉淀AI+RPA合规与工业级风控规范
All checks were successful
技能自动化发布 / release (push) Successful in 7s
2026-07-24 15:55:47 +08:00
20e89774ca docs: add third-party acceptance CHECKLIST and acceptance-reports
All checks were successful
技能自动化发布 / release (push) Successful in 8s
2026-07-22 17:54:18 +08:00
4ed49495cf chore: default OPENCLAW_TEST_TARGET to real_rpa; host UX acceptance
All checks were successful
技能自动化发布 / release (push) Successful in 9s
2026-07-20 11:15:20 +08:00
8101b5ac01 docs: add extensible SHARED_REPOS catalog for public commons
All checks were successful
技能自动化发布 / release (push) Successful in 11s
2026-07-20 10:30:36 +08:00
c15854c20d docs: align host placements (row/batch), Gitea clone, developer_ids QA
All checks were successful
技能自动化发布 / release (push) Successful in 16s
2026-07-20 09:54:44 +08:00
8570d5803d docs(development): clarify onboarding, developer_ids self-test, host multi-entry QA
All checks were successful
技能自动化发布 / release (push) Successful in 20s
2026-07-20 09:20:38 +08:00
30 changed files with 1058 additions and 207 deletions

View File

@@ -1,5 +1,5 @@
# 运行模式:决定本技能用模拟数据还是真实浏览器/接口去执行 # 运行模式:决定本技能用模拟数据还是真实浏览器/接口去执行
OPENCLAW_TEST_TARGET=mock # 可选:mock=本地模拟,simulator_rpa=仿真站点,real_api=真实接口,real_rpa=真实浏览器;模板默认 mock,日常正式使用请改为 real_rpa OPENCLAW_TEST_TARGET=real_rpa # 可选:mock=本地模拟,simulator_rpa=仿真站点,real_api=真实接口,real_rpa=真实浏览器;模板默认真实浏览器;本地单测/CI 请用 mock
# 目标网站地址:技能要访问的网站或服务地址 # 目标网站地址:技能要访问的网站或服务地址
TARGET_BASE_URL=https://sandbox.jc2009.com # 填写完整网址(含 https://);换环境时再改,一般保持默认即可 TARGET_BASE_URL=https://sandbox.jc2009.com # 填写完整网址(含 https://);换环境时再改,一般保持默认即可
@@ -13,8 +13,8 @@ DEFAULT_ACCOUNT_ID= # 留空=自动;只填纯数字;手
# 是否显示浏览器窗口:网页自动化时是否弹出可见浏览器 # 是否显示浏览器窗口:网页自动化时是否弹出可见浏览器
OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(必须,便于介入与排查);1=后台静默(勿作日常用法) OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(必须,便于介入与排查);1=后台静默(勿作日常用法)
# 浏览器防检测:降低被网站识别为自动化工具的概率 # 浏览器兼容配置:仅在项目授权与平台规则允许时使用共享兼容能力
OPENCLAW_PLAYWRIGHT_STEALTH=1 # 1=开启(推荐),0=关闭;一般保持默认 OPENCLAW_PLAYWRIGHT_STEALTH=1 # 1=使用共享兼容配置,0=关闭;不得用于伪造身份或绕过平台限制
# 是否录制操作过程:用于留证、复现问题或向他人演示 # 是否录制操作过程:用于留证、复现问题或向他人演示
OPENCLAW_RECORD_VIDEO=0 # 0=不录屏(默认),1=录屏并生成带说明的视频文件;需要留证时再改为 1 OPENCLAW_RECORD_VIDEO=0 # 0=不录屏(默认),1=录屏并生成带说明的视频文件;需要留证时再改为 1
@@ -22,11 +22,11 @@ OPENCLAW_RECORD_VIDEO=0 # 0=不录屏(默认),1=录屏并
# 失败时是否截图:任务出错时自动保存现场截图,便于排查 # 失败时是否截图:任务出错时自动保存现场截图,便于排查
OPENCLAW_ARTIFACTS_ON_FAILURE=1 # 1=失败时截图(推荐),0=不截图 OPENCLAW_ARTIFACTS_ON_FAILURE=1 # 1=失败时截图(推荐),0=不截图
# 步骤最短等待:两步操作之间随机停顿的下限,模拟真人节奏 # 步骤最短等待:两个正常业务动作之间随机停顿的下限
STEP_DELAY_MIN=1.0 # 单位:秒;一般保持默认,页面不稳定时可略调大 STEP_DELAY_MIN=1.0 # 单位:秒;一般保持默认,页面不稳定时可略调大
# 步骤最长等待:两步操作之间随机停顿的上限 # 步骤最长等待:两步操作之间随机停顿的上限
STEP_DELAY_MAX=5.0 # 单位:秒;须大于等于最短等待;一般保持默认 STEP_DELAY_MAX=3.0 # 单位:秒;默认与最短等待组成 1~3 秒节奏;状态等待须另行判断
# 人工处理超时:遇到滑块、验证码、二次验证时,等待人工处理的最长时间 # 人工处理超时:遇到滑块、验证码、二次验证时,等待人工处理的最长时间
HUMAN_WAIT_TIMEOUT=180 # 单位:秒;来不及处理时可调大,如 300 HUMAN_WAIT_TIMEOUT=180 # 单位:秒;来不及处理时可调大,如 300

View File

@@ -9,6 +9,39 @@
- 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节 - 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节
- 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段 - 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段
## 1.0.57
- 新增 AI + RPA 技能开发总纲,明确 Agent 负责理解与编排、RPA 负责浏览器 / 桌面 / 手机的确定性执行
- 增加第三方软件自动化合规红线:禁止破解、逆向、私有协议、安全验证绕过、Hook / 注入、自动换号和无限重试
- 补齐工业级 RPA 风控、人工介入、状态等待、串行互斥、有限重试、结果核验与前后缓冲标准
- 真实业务默认步骤节奏统一为 1~3 秒,并增加自动测试守护
- 需求模板和交活 Checklist 增加授权、风险确认、不可逆操作、风控信号与结构化结果验收
## 1.0.56
- 新增第三方交活验收清单 `development/CHECKLIST.md`(观察结果、不重复开发规范)
- 验收报告强制写入仓库根目录 `acceptance-reports/YYYYMMDD-HHMMSS-acceptance.md`,便于技术人员按 FAIL 项整改
## 1.0.55
- 模板 `.env.example` 默认 `OPENCLAW_TEST_TARGET=real_rpa`;四档保留;明确 mock 只保单测/CI,mock 通 ≠ 交活
- 验收要求 release 到匠厂并看用户体验(进度、失败提示、有头 RPA 等)
## 1.0.54
- 新增 `development/SHARED_REPOS.md`:可扩展的公开公共仓目录(skill-template / account-manager / jiangchang-platform-kit),含类型、Gitea 地址、clone 与红线
- 开发入口与 RUNTIME / RPA / tools 文档挂接该目录,便于技术人员与 AI 定位公共依赖
## 1.0.53
- 宿主入口对齐:`row` / `batch` 升格为正式 placements;支持 `bind.inputMapping` 与 `readOnly`;已声明入口均须自测(含技能详情直调)
- 开发文档:自建 Gitea(git.jc2009.com)与 scaffold 双来源;`developer_ids` 示例改为占位「你的用户ID」;压缩 AI 工具章节
## 1.0.52
- 开发文档补齐全流程:Gitea 克隆与本地模板复制两种拿仓方式;`developer_ids` 作为开发期自测通行证(下载安装注册 → 设置复制用户 ID)
- 发布后宿主验收明确覆盖新建任务、数据管理、定时任务与任务中心;`development/README` 增加步骤索引
## 1.0.51 ## 1.0.51
- 沉淀网页 RPA 首启标准:业务技能默认 `ensure-web`(有则用、无则登记);登记账号 ≠ 已登录目标站;租约全忙返回占用错误且不重复建号 - 沉淀网页 RPA 首启标准:业务技能默认 `ensure-web`(有则用、无则登记);登记账号 ≠ 已登录目标站;租约全忙返回占用错误且不重复建号

View File

@@ -1,7 +1,7 @@
--- ---
name: 技能开发模板(通用业务版) name: 技能开发模板(通用业务版)
description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。" description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。"
version: 1.0.51 version: 1.0.57
author: 深圳匠厂科技有限公司 author: 深圳匠厂科技有限公司
metadata: metadata:
openclaw: openclaw:
@@ -22,10 +22,17 @@ allowed-tools:
## Agent / 宿主编排(复制为业务技能后必改) ## Agent / 宿主编排(复制为业务技能后必改)
### AI + RPA 定位
- **Agent 是入口与编排者**:理解用户意图、补齐参数、判断风险、选择 Action,并用业务语言解释结果。
- **RPA 是确定性执行器**:只按已验证步骤操作授权范围内的浏览器、桌面软件或手机;不得破解、逆向、调用未授权私有协议或绕过验证码、安全验证和平台限制。
- 遇到验证码、人脸、U盾、频控、账号风险或权限不足时,转人工或安全停止,禁止自动硬闯、换号或无限重试。
- 开发者与 AI 编程工具先读 `development/AI_RPA.md`,三端执行细则再读 `development/RPA.md`。
### 架构铁律(先读) ### 架构铁律(先读)
- **单业务内核、多入口**:数据管理 / 定时任务 / Agent / 技能详情 / 直接 CLI 必须复用同一 domain service;禁止按入口复制业务逻辑,禁止按 `source` 分叉业务行为。 - **单业务内核、多入口**:数据管理 / 定时任务 / Agent / 技能详情 / 直接 CLI 必须复用同一 domain service;禁止按入口复制业务逻辑,禁止按 `source` 分叉业务行为。
- **`placements`**:只决定 Action **出现在哪里**(toolbar / cron / agent / skill-detail)。 - **`placements`**:只决定 Action **出现在哪里**(toolbar / row / batch / cron / agent / skill-detail)。
- **`bind.tables`**:只决定数据管理出现在哪些表;含 `toolbar` 时**必须**显式非空绑定。 - **`bind.tables`**:只决定数据管理出现在哪些表;含 `toolbar` 时**必须**显式非空绑定。
- **`executionProfile`**:只决定执行方式——`sync` 当场返回结果,`async` 进**任务中心**。与 placements / 入口**无关**。心智上多数为 sync,仅长任务 / RPA 标 async;宿主省略该字段时按 sync。每个 Action **仍必须**显式写 `sync` 或 `async`。 - **`executionProfile`**:只决定执行方式——`sync` 当场返回结果,`async` 进**任务中心**。与 placements / 入口**无关**。心智上多数为 sync,仅长任务 / RPA 标 async;宿主省略该字段时按 sync。每个 Action **仍必须**显式写 `sync` 或 `async`。
- **同步数据**写技能本地库、不生成导出文件;**导出当前表**由宿主数据管理负责;特殊业务报告才另做 `export-*`。 - **同步数据**写技能本地库、不生成导出文件;**导出当前表**由宿主数据管理负责;特殊业务报告才另做 `export-*`。
@@ -150,6 +157,7 @@ python {baseDir}/scripts/main.py init-db
## 平台元数据 ## 平台元数据
- `metadata.openclaw.developer_ids`:技能发布后的默认开发者可见用户 ID 列表。 - `metadata.openclaw.developer_ids`:技能发布后的默认开发者可见用户 ID 列表(ID 来自匠厂宿主「设置 → 用户信息」)。
- 开发期技能常为不公开:不加本人 ID,开发者自己也无法在市场安装自测。取 ID 与写入步骤见 `development/DEVELOPMENT.md` §6。
- 当 `access_scope = 0`(不公开)时,平台会把 `developer_ids` 中的用户自动补写到 `skill_user_access`。 - 当 `access_scope = 0`(不公开)时,平台会把 `developer_ids` 中的用户自动补写到 `skill_user_access`。
- `developer_ids` 建议写为正整数数组;第一个 ID 会作为主开发者同步到 `skills.developer_id`。 - `developer_ids` 建议写为正整数数组;第一个 ID 会作为主开发者同步到 `skills.developer_id`。

View File

@@ -0,0 +1,30 @@
# 验收报告目录(acceptance-reports)
本目录存放**技能交活验收报告**,供技术人员查看并按未通过项整改。
## 谁写、写什么
- 验收人(或 AI 编程工具)对照 `development/CHECKLIST.md` 执行验收后,**必须**在本目录落盘报告。
- 标准与条目定义见:`development/CHECKLIST.md`(含强制输出规则)。
## 命名(强制)
```text
YYYYMMDD-HHMMSS-acceptance.md
```
示例:`20260722-175000-acceptance.md`
- 使用验收执行时的本地时间
- 不要覆盖旧报告;保留历史便于对比是否修好
## 技术人员怎么用
1. `git pull` 拉取含报告的最新代码(或验收人推送后的提交)
2. 打开本目录中**时间戳最新**的一份 `*-acceptance.md`
3. 只看文末「给技术人员的修改清单」及所有 `FAIL` / 未通过的 `NEED_MANUAL`
4. 改完后告知验收人复验;新一轮会再生成一份新时间戳报告
## 模板仓说明
本 `skill-template` 仓库通常不产生业务验收报告;此目录随模板复制到新技能后使用。

View File

@@ -4,7 +4,7 @@
- `examples/`:CLI 成功输出形状示例(虚构路径与数据)。 - `examples/`:CLI 成功输出形状示例(虚构路径与数据)。
- `schemas/`:轻量 JSON Schema(`skill-actions.schema.json` 为**新技能严格规范**;`task-log-record.schema.json` 等)。 - `schemas/`:轻量 JSON Schema(`skill-actions.schema.json` 为**新技能严格规范**;`task-log-record.schema.json` 等)。
`skill-actions.schema.json` 使用 `additionalProperties: false`。正式支持 `bind.tables`(toolbar Action 必填);`row`/`batch` placements 与 `concurrency`/`locks` 仍为预留。`placements` 与 `executionProfile` 正交——进任务中心只看 `async`,与入口无关。表级 Action 与 Agent 契约见 [`references/ACTIONS.md`](../references/ACTIONS.md);开发深度规范见 [`development/SKILL_ACTION_RUNTIME.md`](../development/SKILL_ACTION_RUNTIME.md)。 `skill-actions.schema.json` 使用 `additionalProperties: false`。正式支持 `bind.tables`(toolbar Action 必填)与可选 `bind.inputMapping`;placements 含 `toolbar` / `row` / `batch` / `cron` / `agent` / `skill-detail`(对齐匠厂宿主)。`concurrency`/`locks` 仍为预留。`placements` 与 `executionProfile` 正交——进任务中心只看 `async`,与入口无关。表级 Action 与 Agent 契约见 [`references/ACTIONS.md`](../references/ACTIONS.md);开发深度规范见 [`development/SKILL_ACTION_RUNTIME.md`](../development/SKILL_ACTION_RUNTIME.md)。
- 用户市场四 Tab 见根目录 [`README.md`](../README.md) / [`TUTORIAL.md`](../TUTORIAL.md) / [`DEMO.md`](../DEMO.md) / [`CHANGELOG.md`](../CHANGELOG.md) - 用户市场四 Tab 见根目录 [`README.md`](../README.md) / [`TUTORIAL.md`](../TUTORIAL.md) / [`DEMO.md`](../DEMO.md) / [`CHANGELOG.md`](../CHANGELOG.md)
- Agent 调用/编排参考见 [`references/`](../references/)(含 [`ACTIONS.md`](../references/ACTIONS.md)) - Agent 调用/编排参考见 [`references/`](../references/)(含 [`ACTIONS.md`](../references/ACTIONS.md))

View File

@@ -26,7 +26,7 @@
"placement": { "placement": {
"type": "string", "type": "string",
"enum": ["toolbar", "row", "batch", "cron", "agent", "skill-detail"], "enum": ["toolbar", "row", "batch", "cron", "agent", "skill-detail"],
"description": "稳定支持 toolbar/cron/agent/skill-detail;row/batch 为预留入口,新技能示例不得使用。placements 与 executionProfile 正交,不做条件限制。" "description": "稳定支持 toolbar/row/batch/cron/agent/skill-detail(对齐匠厂宿主)。placements 与 executionProfile 正交,不做条件限制。"
}, },
"scalarArg": { "scalarArg": {
"type": ["string", "number", "boolean"] "type": ["string", "number", "boolean"]
@@ -48,7 +48,11 @@
"type": "array", "type": "array",
"minItems": 1 "minItems": 1
}, },
"sensitive": { "type": "boolean" } "sensitive": { "type": "boolean" },
"readOnly": {
"type": "boolean",
"description": "宿主数据管理表单只读展示该字段(仍会随提交传入 entrypoint);用于行内/勾选预填的主键等"
}
} }
}, },
"inputSchema": { "inputSchema": {
@@ -110,10 +114,15 @@
"pattern": "^[a-z][a-z0-9_]*$", "pattern": "^[a-z][a-z0-9_]*$",
"description": "英文 snake_case 业务表名;须真实存在于技能 SQLite / _jiangchang_tables" "description": "英文 snake_case 业务表名;须真实存在于技能 SQLite / _jiangchang_tables"
}, },
"description": "数据管理表级绑定:决定 toolbar Action 出现在哪些表。宿主兼容旧技能时,缺失 bind 可视为全表展示;新技能 toolbar Action 必须显式声明。" "description": "数据管理表级绑定:决定 toolbar/row/batch Action 出现在哪些表。宿主兼容旧技能时,缺失 bind 可视为全表展示;新技能 toolbar Action 必须显式声明。"
},
"inputMapping": {
"type": "object",
"additionalProperties": { "type": "string", "minLength": 1 },
"description": "可选。将 $row.$pk / $row.col / $selection.ids 等映射到 inputSchema 字段名,供 row/batch 预填。"
} }
}, },
"description": "Phase 1 仅沉淀 bind.tables;不包含 selection/inputMapping/columns/row/concurrency/locks" "description": "表级绑定;toolbar 必填。可选 inputMapping 供行内/批量预填。concurrency/locks 勿写入。"
}, },
"action": { "action": {
"type": "object", "type": "object",

View File

@@ -1,6 +1,8 @@
# 适配器标准:真实/仿真 × API/RPA 四档模式 # 适配器标准:真实/仿真 × API/RPA 四档模式
> 凡是"连接三方系统"(ERP、CRM、SaaS、银行等)的 skill,都应采用本文的 **adapter 四档模式**。这样同一套业务逻辑可以在不同档位间切换:开发用 mock、半集成用 simulator、上线用真实,互不影响。 > 凡是"连接三方系统"(ERP、CRM、SaaS、银行等)的 skill,都应采用本文的 **adapter 四档模式**。同一套业务逻辑可在不同档位间切换;**四档都保留**。
先遵守 [`AI_RPA.md`](AI_RPA.md) 的授权与技术红线:`real_api` 只连接公开或明确授权的官方接口;不得通过抓包、逆向或猜测私有协议构造“API”。没有授权 API 时使用正常界面 RPA;正常界面无法闭环且只能绕过安全机制时,停止并上报。
## 为什么要分档 ## 为什么要分档
@@ -15,17 +17,17 @@
| 档位 | 含义 | 默认策略 | | 档位 | 含义 | 默认策略 |
|------|------|----------| |------|------|----------|
| **`mock`** | 纯内存或 fixture,**默认单测/CI** | 模板 `.env.example` 默认 `OPENCLAW_TEST_TARGET=mock` | | **`mock`** | 纯内存或 fixture,离线 | **单测 / CI 必过**;mock 不通不要往下走 |
| **`simulator_rpa`** | 仿真站点或桌面仿真,可半集成 | 开发联调可选 | | **`simulator_rpa`** | 仿真站点或桌面仿真,可半集成 | 按业务场景选用 |
| **`real_api`** | 真实 API | 生产 / 集成测试显式设 `OPENCLAW_TEST_TARGET=real_api` | | **`real_api`** | 真实 API | 按业务场景选用(有官方接口时) |
| **`real_rpa`** | 真实浏览器/真实系统 | 生产 / 集成测试显式设 `OPENCLAW_TEST_TARGET=real_rpa` | | **`real_rpa`** | 真实浏览器/真实系统 | **模板 `.env.example` 默认**;业务自测与交活用此档 |
- **mock**:纯离线、不联网,给单测 / CI / 开发自测,**保证可重复**。 - **mock**:纯离线、不联网,给单测 / CI,**保证可重复**。**mock 通 ≠ 开发完成**。
- **simulator_rpa**:操作仿真平台(如 `sandbox.jc2009.com`),跑端到端流程但不碰生产。 - **simulator_rpa**:操作仿真平台(如 `sandbox.jc2009.com`),按场景选用。
- **real_api**:有官方接口时**首选**(最稳、最快、最易维护)。 - **real_api**:有官方接口时按场景选用。
- **real_rpa**:没有 API 只能操作生产界面,**风险最高、放最后**。 - **real_rpa**:真实浏览器路径;模板默认,须真实跑通后再交活。
> 推荐优先级:**real_api > simulator_rpa > real_rpa**,mock 永远保留做 CI。 > **口径**:业务配置默认 `real_rpa`;单测/CI 用 `mock`。不得只 mock 通就交活;须 release 到匠厂宿主验收(含用户体验)。
配置读取见 `CONFIG.md`:**bootstrap 之后业务代码只通过 `config.get*()` 读 `OPENCLAW_TEST_TARGET` 等项**(进程 env > 用户 `.env` > `.env.example`)。 配置读取见 `CONFIG.md`:**bootstrap 之后业务代码只通过 `config.get*()` 读 `OPENCLAW_TEST_TARGET` 等项**(进程 env > 用户 `.env` > `.env.example`)。
@@ -72,7 +74,7 @@ scripts/service/
from jiangchang_skill_core import config from jiangchang_skill_core import config
def get_adapter(): def get_adapter():
target = (config.get("OPENCLAW_TEST_TARGET") or "mock").lower() target = (config.get("OPENCLAW_TEST_TARGET") or "real_rpa").lower()
if target in ("unit", "mock"): if target in ("unit", "mock"):
return MockAdapter() return MockAdapter()
if target == "real_api": if target == "real_api":

227
development/AI_RPA.md Normal file
View File

@@ -0,0 +1,227 @@
# AI + RPA 技能开发总纲
本文是技术人员与 AI 编程工具进入本模板后的**第一份架构说明**。先理解本文,再按业务类型阅读 [`RPA.md`](RPA.md)、[`ADAPTER.md`](ADAPTER.md)、[`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md) 与对应 `examples/`。
## 目录
1. [一句话定义](#1-一句话定义)
2. [职责边界](#2-职责边界)
3. [标准执行闭环](#3-标准执行闭环)
4. [合规与技术红线](#4-合规与技术红线)
5. [工业级 RPA 风控](#5-工业级-rpa-风控)
6. [等待与操作节奏](#6-等待与操作节奏)
7. [三端统一与选型](#7-三端统一与选型)
8. [结果契约](#8-结果契约)
9. [开发与交付顺序](#9-开发与交付顺序)
## 1. 一句话定义
**AI Agent 是用户入口与业务编排者,RPA 是确定性执行器。**
- Agent 负责理解用户意图、补齐参数、判断风险、选择 Action、发起任务和解释结果。
- RPA 负责按已验证的步骤操作浏览器、桌面软件或手机,不临时理解模糊业务。
- 业务规则放在唯一 domain service 中;Agent、CLI、Action、定时任务与数据管理入口复用同一内核。
- RPA 必须返回结构化结果、进度与存证,由 Agent 用业务语言反馈给用户。
本模板追求的是**稳定、合规、可控制、可追溯、可交付的工业级界面自动化**,不是与第三方安全机制对抗。
## 2. 职责边界
| 层级 | 负责 | 不负责 |
|------|------|--------|
| Agent | 意图理解、缺参追问、风险确认、Action 选择、结果解释 | 不猜界面步骤,不临时改业务规则,不直接绕过安全验证 |
| Action / 编排层 | 参数校验、鉴权、任务状态、进度、暂停停止、日志、人工介入 | 不按入口复制业务逻辑 |
| Domain Service | 业务规则、幂等、防重复、状态流转、结果汇总 | 不关心来自 Agent、定时任务还是工具栏 |
| Adapter / RPA | 调官方 API 或按确定流程操作界面 | 不理解模糊意图,不自行扩大权限或操作范围 |
| 宿主 | Action 展示、任务中心、数据管理、共享 runtime | 不替技能实现业务规则 |
Agent 与 RPA 的边界必须保持清晰:
- 把不确定的理解与沟通交给 Agent。
- 把可验证、可重复的执行步骤交给代码和 RPA。
- 不让 Agent 在运行时自由生成高风险界面操作。
- 不让 RPA 根据模糊文本自行决定付款、删除、审批、发布或发送范围。
## 3. 标准执行闭环
```text
用户自然语言
→ Agent 识别意图与参数
→ 缺参追问 / 风险确认
→ 选择已声明的 Skill Action
→ 编排层做校验、鉴权、预检、幂等检查
→ Domain Service 执行业务规则
→ Adapter 选择 API / 浏览器 / 桌面 / 手机
→ RPA 分步骤执行并持续上报进度
→ 验证码、人脸、U盾等转人工处理
→ 返回结构化结果、日志、截图与可选视频
→ Agent 向用户解释结果与下一步
```
### 执行前
Agent 与编排层必须确认:
- 用户意图、操作对象、范围与必填参数明确。
- 当前账号、数据、设备和目标软件属于用户或企业授权范围。
- 查询、准备数据与外部副作用已经分开。
- 付款、删除、审批、发布、发送等不可逆动作已取得明确确认。
- 浏览器 Profile、桌面窗口或手机设备已通过预检。
- 同一业务键不会被重复提交。
### 执行中
- 每个用户可感知的动作都要有中文进度 step。
- 使用可暂停、可停止的等待;禁止 RPA 主路径裸 `asyncio.sleep`。
- 同一账号、Profile 或设备默认串行执行。
- 遇到安全验证、权限不足、频控或风险提示时,转人工或安全停止。
- 批量任务记录处理位置,支持失败定位和必要的断点续跑。
### 执行后
- 先验证业务成功标志,再记录成功;不得把“点击完成”当成“业务成功”。
- 返回成功、部分成功、失败、停止或等待人工等明确状态。
- 保存必要的任务日志、错误码、失败截图和可选录屏。
- Agent 根据结构化结果解释完成数量、失败原因和下一步,不直接粘贴技术日志。
## 4. 合规与技术红线
### 允许
- 使用用户或企业合法拥有、明确授权的账号与业务权限。
- 通过正常界面入口完成用户本来有权完成的操作。
- 使用浏览器 DOM、Windows UI Automation、Android/iOS 控件树等公开自动化能力。
- 采用真实点击、逐字输入、自然鼠标轨迹、分段滚动和合理业务节奏。
- 遇到验证码、人脸、指纹、短信、U盾或动态口令时暂停并请求人工处理。
- 在授权范围内保存必要的日志、截图、视频和业务结果。
### 禁止
- 破解、反编译、逆向第三方软件或分析其私有协议。
- 调用未经公开授权的隐藏接口,或通过抓包拼装私有请求代替正常界面。
- 绕过登录、验证码、人脸、指纹、短信、U盾、设备绑定、签名或权限校验。
- 注入、Hook、篡改第三方进程、客户端、APK、IPA、安全模块或通信内容。
- 窃取、共享或复用未授权的 Cookie、Token、Session、密码或设备凭据。
- 撞库、暴力尝试、自动破解验证码、批量养号或伪造身份。
- 通过换账号、换代理、伪造设备指纹、提高并发等方式规避平台限制。
- 识别到风险提示或封禁后继续自动重试、试探或隐藏自动化行为。
“采用 RPA”不代表任何任务都可以自动执行。技能仍须遵守账号授权、数据权限、目标平台规则、合同约定和适用法律;边界不清时停止并请求负责人确认。
## 5. 工业级 RPA 风控
### 风控信号与处理
| 信号 | 标准处理 |
|------|----------|
| 页面或软件加载缓慢 | 等待真实状态,必要时有限重试 |
| 普通网络错误 | 递增退避后有限重试 |
| 登录失效 | 请求用户重新登录 |
| 验证码、短信、人脸、指纹、U盾 | 进入人工处理,禁止自动绕过 |
| 频率限制 | 停止当前批次或长时间退避 |
| 账号风险、封禁或安全警告 | 立即停止,禁止自动换号或继续试探 |
| 权限不足 | 返回明确失败,不尝试扩大或绕过权限 |
| 页面或控件结构变化 | 截图并停止,交由开发人员重新验证 |
| 提交结果不明确 | 查询业务状态;确认前禁止再次提交 |
### 运行限制
- 同一账号、Profile、桌面会话或手机设备默认只运行一个任务。
- 设置单批数量、单位时间操作量和总运行时长上限。
- 只对明确可重试错误做有限重试;禁止无限循环。
- 采用递增退避,不以快速重复点击或刷新解决延迟。
- 关键副作用采用“准备数据 → 用户确认 → 执行 → 结果核验”两阶段流程。
- 风控策略用于减少误操作、系统压力和误判,不得用于规避第三方安全控制。
## 6. 等待与操作节奏
区分三类等待,禁止只靠固定睡眠碰运气。
### 状态等待
页面加载、控件可用、弹窗消失、保存成功、下载完成等必须等待**真实条件**并设置超时。固定等待不能代替状态判断。
### 操作节奏
真实业务环境中,两个正常业务动作之间默认随机等待 **1~3 秒**:
```env
STEP_DELAY_MIN=1.0
STEP_DELAY_MAX=3.0
```
- 输入采用逐字符随机延迟。
- 鼠标采用自然移动轨迹与小幅随机偏移。
- 滚动采用分段操作。
- 提交后等待业务结果,禁止重复点击。
- 测试 / sandbox 可使用更短节奏,但不得把测试节奏用于真实第三方系统。
### 前后缓冲
- 浏览器或软件启动:先等待会话与目标页面/窗口真实就绪,再额外缓冲约 `1.5~2.5` 秒。
- 页面导航:关键控件就绪后,再缓冲约 `1~2` 秒。
- 普通流程结束:确认业务结果、写日志与存证后,再缓冲约 `2~3` 秒关闭。
- 付款、审批、发布等重要动作:确认结果并截图后,可缓冲约 `3~5` 秒。
缓冲时间只用于稳定界面和改善用户观感,不能作为成功判定。RPA 等待必须使用 `interruptible_sleep` 或共享可控制原语。
## 7. 三端统一与选型
优先选择最稳定、最受支持的执行方式:
1. 本地确定性逻辑可以完成时,不启动 RPA。
2. 有稳定且获得授权的官方 API 时,优先 API。
3. 只能通过网页操作时,使用浏览器 RPA。
4. 目标为 Windows 原生软件时,优先 UI Automation。
5. 目标为手机 App 时,使用系统控件树与正常设备自动化。
6. 只有破解、逆向或绕过安全机制才能完成时,停止开发并上报,不改走违规路线。
三端详细标准见 [`RPA.md`](RPA.md)。当前浏览器 RPA 已有可复制案例;桌面与手机仍须基于真实项目继续沉淀,未验证内容不得包装为成熟方案。
## 8. 结果契约
RPA 至少返回:
```json
{
"success": true,
"status": "success",
"message": "任务已完成",
"summary": {
"total": 10,
"success_count": 9,
"failed_count": 1
},
"items": [],
"errors": [],
"artifacts": {
"screenshots": [],
"video_path": null
},
"next_actions": []
}
```
状态至少能区分:
- `success`:全部完成。
- `partial`:部分成功,列出失败项。
- `failed`:未完成,给出稳定错误码与阶段。
- `waiting_human`:等待人工验证或接管,不是假失败。
- `confirmation_required`:等待用户批准副作用。
- `stopped`:用户或宿主主动停止。
具体字段可按业务扩展,但不得只返回控制台文本或把技术 traceback 直接交给用户。
## 9. 开发与交付顺序
1. 填写 [`REQUIREMENTS.md`](REQUIREMENTS.md) 中的 Agent、授权、风险、人工介入与结果设计。
2. 判断采用 API、浏览器、桌面或手机,并选择真实 / 仿真 adapter。
3. 定义用户意图、Action、输入 schema 与确认策略。
4. 先实现 domain service、结构化结果和 mock 测试。
5. 再实现 RPA 会话、真实操作、状态等待、进度、截图与人工介入。
6. 在真实界面上确认 selector / 控件,禁止凭经验猜测。
7. 完成仿真测试、真实业务闭环和宿主多入口验收。
8. 使用 [`CHECKLIST.md`](CHECKLIST.md) 做第三方交活验收。
AI 编程工具不得为了“跑通”擅自采用破解、逆向、私有协议、验证码绕过、进程注入、无限重试或未授权凭据。正常界面无法完成闭环时,应停止并向负责人报告边界。

163
development/CHECKLIST.md Normal file
View File

@@ -0,0 +1,163 @@
# 技能交活验收 Checklist(第三方视角)
checklist_version: 1.0
本清单用于**旁人 / 测试 / AI 编程工具**对任意业务技能做交活验收。
它描述的是「验什么、怎样算过」,**不是**开发规范摘要。写法与实现约束见同目录其他文档。
---
## 验收输出强制规则(凡执行本清单必须遵守)
> 面向 AI 与人工验收员:只要开始按本 Checklist 验收,下列规则**全部强制**,无需用户在提示词里再重复。
1. **必须落盘报告**,禁止只在对话里给出口头结论。
2. **报告目录(唯一合法位置)**:技能仓库**根目录**下的 `acceptance-reports/`
(与 `development/`、`scripts/` 平级;**禁止**写到 `development/`、`tests/`、临时目录或其他路径。)
3. **报告文件名(唯一合法格式)**:`YYYYMMDD-HHMMSS-acceptance.md`
示例:`20260722-175000-acceptance.md`
时间取验收执行时的本地时间;**禁止**使用 `report.md`、`验收.md`、无时间戳的文件名。
4. 若 `acceptance-reports/` 不存在,**先创建该目录再写入**。
5. 报告**开头**必须写明:
- 完整相对路径:`acceptance-reports/YYYYMMDD-HHMMSS-acceptance.md`
- 技能 slug、当前 git 提交短哈希(若可得)、`checklist_version`
6. 报告正文必须**逐条**对应下方条目,每条给出:`PASS` / `FAIL` / `N/A` / `NEED_MANUAL`,并附简短证据(文件路径、命令、观察结果)。
7. 报告末尾必须有「给技术人员的修改清单」:只列出未通过项(`FAIL` 与未通过的 `NEED_MANUAL`),按 P0 → P1 → P2 排序。
8. **禁止修改业务代码**来“凑”验收通过;本清单的执行结果是报告,不是改代码。
9. 若用户只说「按 Checklist 验收」而未指定路径:仍必须遵守本节省略规则,不得省略落盘。
**结果取值**
| 值 | 含义 |
|----|------|
| PASS | 已满足 |
| FAIL | 不满足 |
| N/A | 本技能不适用(须说明原因) |
| NEED_MANUAL | 须人工点选/真机;报告中写清已做或未做 |
**级别**
| 级别 | 含义 |
|------|------|
| P0 | 不通过不可交活 |
| P1 | 限期整改 |
| P2 | 体验建议 |
---
## 0. 技能画像(验收前先填,用于裁剪)
先根据技能实际情况勾选;后续章节不适用则整项标 `N/A` 并注明原因。
- [ ] S0-1 交互形态:纯本地 / API / 网页RPA / 桌面RPA / 手机RPA / 编排(调兄弟技能)
- [ ] S0-2 目标站登录策略:required / optional / not_needed / 不适用
- [ ] S0-3 是否依赖账号会话(account-manager 或等价 Profile):是 / 否
- [ ] S0-4 持久化:无 / 仅任务日志 / 另有业务表
- [ ] S0-5 Skill Action:无 / 仅同步短任务 / 含异步长任务
- [ ] S0-6 是否需要在任务中心查看进度或结果:是 / 否
- [ ] S0-7 外部系统账号、数据、设备与操作权限的授权来源:
- [ ] S0-8 是否包含提交、付款、删除、审批、发布、发送等不可逆副作用:是 / 否
---
## 1. 安装与可运行(所有技能)
- [ ] A1-1 **P0** 按平台方式加载/安装后,技能可被识别(有名称,能打开详情或执行入口)
- [ ] A1-2 **P0** 健康检查(如 `health`)能跑完且结果可读;缺关键条件时有明确失败提示,而非空白崩溃
- [ ] A1-3 **P0** 版本查询(如 `version`)返回的版本与对外宣称一致
- [ ] A1-4 **P1** 若有用户可见配置:说明可读;按说明改关键项后行为符合说明
---
## 2. 对外说明是否自洽(所有技能)
- [ ] A2-1 **P0** 市场「说明」能让非开发者理解:做什么、给谁用、开始前准备什么
- [ ] A2-2 **P0** 「说明/教程」不以开发目录、内部实现细节作为用户主路径
- [ ] A2-3 **P1** 「教程」可按真实顺序跟做(准备 → 步骤 → 失败怎么办)
- [ ] A2-4 **P1** 「演示」结构完整(有演示信息位;无视频则标明暂无,不假装有)
- [ ] A2-5 **P0** 「更新日志」能对应到当前交付版本
- [ ] A2-6 **P0** 平台/Agent 侧说明中,常见用户意图的触发方式与真实能力一致(短操作 vs 长任务不混淆)
---
## 3. 主能力行为(所有技能)
- [ ] A3-1 **P0** 主成功路径能按宣称完成核心动作(至少 1 次完整闭环)
- [ ] A3-2 **P0** 缺参或非法输入时稳定失败(可读错误,不假成功)
- [ ] A3-3 **P1** 失败可诊断:能从任务记录/提示判断失败阶段,而非只有“失败了”
- [ ] A3-4 **P0** 同一能力从已声明的不同入口触发时,业务结果一致(不出现入口分叉成两套逻辑)
---
## 4. 调度与长任务(有 Action 或长任务时适用)
- [ ] A4-1 **P0** 秒级只读/短操作:不进入任务中心也能完成(若技能提供此类能力)
- [ ] A4-2 **P0** 长耗时/浏览器/需进度或取消的能力:经 Agent 或技能动作触发后进入任务中心(或平台等价异步队列)
- [ ] A4-3 **P0** 异步任务在任务中心能看到进行中与结束状态;结束有成功或失败结论
- [ ] A4-4 **P1** 进行中的进度/步骤信息对用户可理解
- [ ] A4-5 **P1** 已对外暴露的动作参数覆盖主路径关键输入(无“命令行能做、动作入口不能做”的关键缺口)
---
## 5. 账号与浏览器会话(网页 RPA 适用;其他形态标 N/A 或改测等价项)
- [ ] A5-1 **P0** 未准备好账号/浏览器档案时,主路径失败并提示,不会默默用本机默认浏览器身份跑起来
- [ ] A5-2 **P0** 登录策略为 required 时:未登录不能把做不成的事当成成功
- [ ] A5-3 **P0** 交付联调默认能看见浏览器窗口(有头);不能把无头当作唯一可验收形态
- [ ] A5-4 **P1** 浏览器窗口启动形态满足交付约定(如最大化或可视区域足够操作与人工介入)
- [ ] A5-5 **P1** 验证码或人工确认:有等待与超时;超时后任务失败可理解,不无限挂死或假成功
- [ ] A5-6 **P0** **NEED_MANUAL** 真实站或约定仿真站主路径至少完整跑通 1 次;仅模拟数据通过不算交活
---
## 6. 结果落点(按画像裁剪)
- [ ] A6-1 **P0** 宣称可追溯时:跑完后任务记录中有对应条目(成功/失败均有)
- [ ] A6-2 **P0** 宣称写入业务数据或可在数据管理查看时:成功跑完后能看到新业务数据;仅有任务摘要、业务侧仍空 → **FAIL**
- [ ] A6-3 **P1** 重复执行同一业务键时,结果符合宣称(更新/去重/追加),无莫名脏数据或静默丢数据
- [ ] A6-4 **P1** 「零结果成功」与「失败」可区分
- [ ] A6-5 **P1** 若产出文件:落在约定数据位置且可找到,不丢在不明临时路径
---
## 7. 可观测与安全观感(所有技能)
- [ ] A7-1 **P0** 失败提示或任务结论不泄露密码、完整 Cookie、明文 token 等敏感信息
- [ ] A7-2 **P1** 关键步骤有据可查(能对应到开始/关键节点/结束)
- [ ] A7-3 **P1** 若宣称支持录屏或截图存证:打开开关后关键步骤或失败能留下可查看产物;宣称支持却完全无产物 → **FAIL**
- [ ] A7-4 **P2** 用户可见文案偏业务语言,而非大段开发黑话
---
## 8. AI + RPA 合规与工业级风控(外部系统技能适用)
- [ ] A8-1 **P0** 已确认账号、数据、设备和业务操作均在用户或企业授权范围内;边界不明不能以“默认允许”通过
- [ ] A8-2 **P0** 代码与运行路径不包含破解、反编译、逆向、未授权私有协议、抓包拼隐藏接口、Hook / 注入、验证码破解、设备指纹伪造、撞库、养号、自动换号或代理池规避限制
- [ ] A8-3 **P0** 验证码、人脸、指纹、短信、U盾、频控、账号风险和权限不足能转人工或安全停止,不自动硬闯
- [ ] A8-4 **P0** 付款、删除、审批、发布、发送等不可逆动作执行前有明确对象、范围和用户确认
- [ ] A8-5 **P1** 页面 / 控件加载、保存和业务成功由真实状态判断,不以固定等待代替成功判定
- [ ] A8-6 **P1** 真实 RPA 两个正常业务动作之间采用约 `1~3` 秒随机节奏;输入、鼠标和滚动符合正常人工操作方式
- [ ] A8-7 **P1** 同一账号、Profile 或设备默认串行;批量、频率和运行时长有上限
- [ ] A8-8 **P1** 只对明确可重试错误做有限重试与递增退避;风险、封禁、权限和结果不明确时不盲目重试
- [ ] A8-9 **P1** 流程结束先核验业务结果并完成日志 / 截图 / 可选视频,再保留合理结束缓冲后关闭会话
- [ ] A8-10 **P1** Agent 能区分成功、部分成功、失败、等待人工、等待确认和主动停止,并用业务语言解释结果
---
## 9. 质量门禁与交活底线(所有技能)
- [ ] A9-1 **P0** 仓库默认测试套件通过(执行技能约定的一键测试命令,如 `python tests/run_tests.py -v`)
- [ ] A9-2 **P0** 不以「仅模拟档通过」作为交活依据(有真实档要求时必须真实跑通或书面阶段性豁免)
- [ ] A9-3 **P0** **NEED_MANUAL** 已声明的宿主入口(详情/Agent/工具栏/定时等)按声明抽测可通过
- [ ] A9-4 **P1** 对外版本一致:详情、version、更新日志、发布标签能对上
- [ ] A9-5 **P1** 开发者按平台规则能安装并测到该技能(若平台有开发者可见性要求)
---
## 10. 报告结尾必填
报告末尾固定三块:
1. **结论**:通过 / 不通过(任意 P0 为 FAIL 或不通过的 NEED_MANUAL → 不通过)
2. **统计**:PASS / FAIL / N/A / NEED_MANUAL 数量;P0 FAIL 列表
3. **给技术人员的修改清单**:仅未通过项,带条目 ID 与期望现象

View File

@@ -48,7 +48,7 @@
```ini ```ini
# 运行模式:决定本技能用模拟数据还是真实浏览器/接口去执行 # 运行模式:决定本技能用模拟数据还是真实浏览器/接口去执行
OPENCLAW_TEST_TARGET=mock # 可选:mock=本地模拟,simulator_rpa=仿真站点,real_api=真实接口,real_rpa=真实浏览器;模板默认 mock,日常正式使用请改为 real_rpa OPENCLAW_TEST_TARGET=real_rpa # 可选:mock=本地模拟,simulator_rpa=仿真站点,real_api=真实接口,real_rpa=真实浏览器;模板默认真实浏览器;本地单测/CI 请用 mock
# 是否显示浏览器窗口:网页自动化时是否弹出可见浏览器 # 是否显示浏览器窗口:网页自动化时是否弹出可见浏览器
OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(必须,便于介入与排查);1=后台静默(勿作日常用法) OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(必须,便于介入与排查);1=后台静默(勿作日常用法)
@@ -58,7 +58,7 @@ OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(必须,便于介入与排查
```ini ```ini
# ── 运行模式 / adapter 档位(见 development/ADAPTER.md)── # ── 运行模式 / adapter 档位(见 development/ADAPTER.md)──
OPENCLAW_TEST_TARGET=real_rpa # 生产默认真实 RPA;单测/CI 可改为 mock OPENCLAW_TEST_TARGET=mock # 见 development/ADAPTER.md;单测用 mock
# ── 好看视频 / 百度账号(须与 account-manager 平台 key 一致)── # ── 好看视频 / 百度账号(须与 account-manager 平台 key 一致)──
TARGET_PLATFORM=baidu TARGET_PLATFORM=baidu
@@ -73,7 +73,7 @@ HAOKAN_VIDEO_SELECTOR=video.art-video
```ini ```ini
# 运行模式:决定本技能用模拟数据还是真实浏览器/接口去执行 # 运行模式:决定本技能用模拟数据还是真实浏览器/接口去执行
OPENCLAW_TEST_TARGET=mock # 可选:mock=本地模拟,simulator_rpa=仿真站点,real_api=真实接口,real_rpa=真实浏览器;模板默认 mock,日常正式使用请改为 real_rpa OPENCLAW_TEST_TARGET=real_rpa # 可选:mock=本地模拟,simulator_rpa=仿真站点,real_api=真实接口,real_rpa=真实浏览器;模板默认真实浏览器;本地单测/CI 请用 mock
# 目标网站地址:技能要访问的网站或服务地址 # 目标网站地址:技能要访问的网站或服务地址
TARGET_BASE_URL=https://sandbox.jc2009.com # 填写完整网址(含 https://);换环境时再改,一般保持默认即可 TARGET_BASE_URL=https://sandbox.jc2009.com # 填写完整网址(含 https://);换环境时再改,一般保持默认即可
@@ -87,8 +87,8 @@ DEFAULT_ACCOUNT_ID= # 留空=自动;只填纯数字;手
# 是否显示浏览器窗口:网页自动化时是否弹出可见浏览器 # 是否显示浏览器窗口:网页自动化时是否弹出可见浏览器
OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(必须,便于介入与排查);1=后台静默(勿作日常用法) OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(必须,便于介入与排查);1=后台静默(勿作日常用法)
# 浏览器防检测:降低被网站识别为自动化工具的概率 # 浏览器兼容配置:仅在项目授权与平台规则允许时使用共享兼容能力
OPENCLAW_PLAYWRIGHT_STEALTH=1 # 1=开启(推荐),0=关闭;一般保持默认 OPENCLAW_PLAYWRIGHT_STEALTH=1 # 1=使用共享兼容配置,0=关闭;不得用于伪造身份或绕过平台限制
# 是否录制操作过程:用于留证、复现问题或向他人演示 # 是否录制操作过程:用于留证、复现问题或向他人演示
OPENCLAW_RECORD_VIDEO=0 # 0=不录屏(默认),1=录屏并生成带说明的视频文件;需要留证时再改为 1 OPENCLAW_RECORD_VIDEO=0 # 0=不录屏(默认),1=录屏并生成带说明的视频文件;需要留证时再改为 1
@@ -96,11 +96,11 @@ OPENCLAW_RECORD_VIDEO=0 # 0=不录屏(默认),1=录屏并
# 失败时是否截图:任务出错时自动保存现场截图,便于排查 # 失败时是否截图:任务出错时自动保存现场截图,便于排查
OPENCLAW_ARTIFACTS_ON_FAILURE=1 # 1=失败时截图(推荐),0=不截图 OPENCLAW_ARTIFACTS_ON_FAILURE=1 # 1=失败时截图(推荐),0=不截图
# 步骤最短等待:两步操作之间随机停顿的下限,模拟真人节奏 # 步骤最短等待:两个正常业务动作之间随机停顿的下限
STEP_DELAY_MIN=1.0 # 单位:秒;一般保持默认,页面不稳定时可略调大 STEP_DELAY_MIN=1.0 # 单位:秒;一般保持默认,页面不稳定时可略调大
# 步骤最长等待:两步操作之间随机停顿的上限 # 步骤最长等待:两步操作之间随机停顿的上限
STEP_DELAY_MAX=5.0 # 单位:秒;须大于等于最短等待;一般保持默认 STEP_DELAY_MAX=3.0 # 单位:秒;默认与最短等待组成 1~3 秒节奏;状态等待须另行判断
# 人工处理超时:遇到滑块、验证码、二次验证时,等待人工处理的最长时间 # 人工处理超时:遇到滑块、验证码、二次验证时,等待人工处理的最长时间
HUMAN_WAIT_TIMEOUT=180 # 单位:秒;来不及处理时可调大,如 300 HUMAN_WAIT_TIMEOUT=180 # 单位:秒;来不及处理时可调大,如 300

View File

@@ -1,6 +1,6 @@
# 技能开发教程 # 技能开发教程
这份文档是给**技术人员**看的,目标不是解释概念,而是让你拿到 `skill-template` 后,可以**一步一步开发出一个新的 skill**。 这份文档是给**技术人员**看的,目标不是解释概念,而是让你拿到**业务技能仓库**后,可以**一步一步开发出一个新的 skill**。
本文默认你开发的是当前最常见的一类业务 skill: 本文默认你开发的是当前最常见的一类业务 skill:
@@ -13,77 +13,40 @@
## 推荐 AI 开发工具 ## 推荐 AI 开发工具
当前 skill 开发建议尽量配合 AI 编程工具使用。这样做不是为了替代技术人员,而是为了提升以下环节的效率: 建议用 AI 编程工具辅助搭目录、补样板、写测试与排错。团队宜统一 1~2 个主力,避免协作习惯发散。
- 搭建标准目录结构 | 场景 | 建议 |
- 生成样板代码 |------|------|
- 理解旧项目代码 | 一体化 IDE | Cursor 或 Windsurf |
- 批量补文档、注释和测试 | 终端深度代理 | Claude Code 或 Aider |
- 辅助排查报错与重构代码 | 国内生态 | Trae / 通义灵码 |
| VS Code 插件 | GitHub Copilot 或 Cline |
建议团队统一选择 1 到 2 个主力工具长期使用,避免每个人工具链差异太大,导致协作方式不一致。 官方下载与文档以各产品站点为准;技能开发步骤以本文与同目录规范为准,不依赖某一家工具的专有流程。
下面先列国外主流工具,再列国内主流工具。链接优先使用官方站点、官方文档或官方安装入口。 开发中常用的**公开公共仓**(skill-template / account-manager / jiangchang-platform-kit 等,可 `git clone` 学习,目录可扩展)见 [`SHARED_REPOS.md`](SHARED_REPOS.md)。
### 国外主流工具
| 工具 | 类型 | 适合场景 | 官方入口 |
|------|------|----------|----------|
| Cursor | 独立 AI IDE | 代码编辑、Agent 开发、整仓理解 | <a href="https://www.cursor.com/" target="_blank" rel="noopener noreferrer">官网</a> / <a href="https://www.cursor.com/downloads" target="_blank" rel="noopener noreferrer">下载</a> |
| Windsurf | 独立 AI IDE | Agent 编程、项目生成、连续开发流 | <a href="https://docs.codeium.com/windsurf" target="_blank" rel="noopener noreferrer">文档</a> / <a href="https://windsurf.com/download" target="_blank" rel="noopener noreferrer">下载</a> |
| GitHub Copilot | IDE 插件 / 编程助手 | 日常补全、解释代码、生成函数、配合 VS Code 或 JetBrains 使用 | <a href="https://github.com/copilot" target="_blank" rel="noopener noreferrer">官网</a> |
| Claude Code | 终端 / IDE 编程代理 | 命令行开发、代码库分析、自动改代码、运行命令 | <a href="https://www.anthropic.com/claude-code" target="_blank" rel="noopener noreferrer">官网</a> / <a href="https://docs.anthropic.com/en/docs/claude-code/" target="_blank" rel="noopener noreferrer">文档</a> |
| Codex | 终端 / IDE / Web 编程代理 | OpenAI 官方编码代理,适合代码生成、理解、调试、评审 | <a href="https://developers.openai.com/codex/" target="_blank" rel="noopener noreferrer">官网</a> / <a href="https://developers.openai.com/codex/quickstart" target="_blank" rel="noopener noreferrer">快速开始</a> |
| Aider | 终端 AI 编程工具 | 已有代码仓库的增量开发、终端协作、快速提交 | <a href="https://www.aider.chat/" target="_blank" rel="noopener noreferrer">官网</a> / <a href="https://aider.chat/docs/" target="_blank" rel="noopener noreferrer">文档</a> |
| Cline | VS Code / JetBrains 插件 | 编辑器内 Agent 开发、命令执行、浏览器联动调试 | <a href="https://cline.bot/" target="_blank" rel="noopener noreferrer">官网</a> / <a href="https://docs.cline.bot/introduction/welcome" target="_blank" rel="noopener noreferrer">文档</a> / <a href="https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev" target="_blank" rel="noopener noreferrer">VS Code 插件</a> |
### 国内主流工具
| 工具 | 类型 | 适合场景 | 官方入口 |
|------|------|----------|----------|
| Trae | 独立 AI IDE | AI 辅助写代码、项目搭建、对话式开发 | <a href="https://www.trae.ai/home" target="_blank" rel="noopener noreferrer">官网</a> / <a href="https://www.trae.ai/download" target="_blank" rel="noopener noreferrer">下载</a> |
| 通义灵码 | 独立 IDE / IDE 插件 | 国内团队日常编码、问答、补全、代码生成 | <a href="https://tongyi.aliyun.com/lingma/?channel=yy_AiBot" target="_blank" rel="noopener noreferrer">官网</a> / <a href="https://tongyi.aliyun.com/lingma/download" target="_blank" rel="noopener noreferrer">下载</a> |
| CodeGeeX | IDE 插件 / 开源助手 | 代码补全、生成、注释、跨语言辅助 | <a href="https://github.com/zai-org/CodeGeeX" target="_blank" rel="noopener noreferrer">GitHub</a> / <a href="https://marketplace.visualstudio.com/items?itemName=aminer.codegeex" target="_blank" rel="noopener noreferrer">VS Code 插件</a> |
| 腾讯 CodeBuddy | IDE 插件 | 代码补全、测试生成、智能问答、腾讯云开发体系协作 | <a href="https://www.codebuddy.ai/" target="_blank" rel="noopener noreferrer">官网</a> / <a href="https://www.tencentcloud.com/document/product/1256" target="_blank" rel="noopener noreferrer">文档</a> / <a href="https://marketplace.visualstudio.com/items?itemName=Tencent-Cloud.coding-copilot" target="_blank" rel="noopener noreferrer">VS Code 插件</a> |
| 百度文心快码(Baidu Comate) | IDE 插件 | 国内研发团队辅助编码、解释、测试、优化 | <a href="https://comate.baidu.com/zh" target="_blank" rel="noopener noreferrer">官网</a> |
### 选型建议
如果你们团队主要做这类 Python skill 开发,我建议这样选:
- 想要一体化最强体验:优先试 `Cursor` 或 `Windsurf`
- 想要命令行深度协作:优先试 `Claude Code` 或 `Aider`
- 想继续基于 VS Code 插件体系:优先试 `GitHub Copilot`、`Cline`、`通义灵码`、`CodeBuddy`
- 想优先使用国内生态与中文支持:优先试 `Trae`、`通义灵码`、`CodeGeeX`、`CodeBuddy`、`文心快码`
### 团队落地建议
为了减少培训成本,建议内部至少统一一套主工具方案:
- 国外方案:`Cursor` + `Claude Code`
- 国内方案:`Trae` + `通义灵码`
- VS Code 插件方案:`GitHub Copilot` + `Cline`
不建议每位技术人员完全自由发挥,否则后续在:
- 提示词写法
- 代码修改习惯
- 调试方式
- 提交节奏
这些方面会越来越不统一。
## 1. 先理解模板的定位 ## 1. 先理解模板的定位
`skill-template` 不是业务 skill,它只是一个**新 skill 仓库模板**。 `skill-template` 不是业务 skill,它只是一个**新 skill 仓库模板**。
你不应该直接在这个仓库里开发业务,而应该: 开发任何外部系统技能前,**先读 [`AI_RPA.md`](AI_RPA.md)**。本模板的统一定位是:Agent 负责理解、确认与编排,RPA 负责通过正常界面确定性执行;只做授权范围内的正规业务自动化,禁止破解、逆向、私有协议、验证码绕过或其他对抗第三方安全机制的实现。
0. 按 [`NAMING.md`](NAMING.md) 确定 slug(`{verb}-{noun-phrase}-{platform}`) 你不应该直接在这个仓库里开发业务。新技能仓库有**两种合法来源**(详见 §4「第一步」):
1. **优先**用 [`tools/scaffold_skill.ps1`](../tools/scaffold_skill.ps1) 创建新目录(见 [`tools/README.md`](../tools/README.md))
2. 在新目录内 `git init` 并绑定**本技能**远端(**不得**保留模板 `.git`) | 来源 | 适用情况 | 怎么做 |
3. 把占位内容替换掉 |------|----------|--------|
4. 再开始写业务逻辑 | **A. Gitea 克隆** | 项目经理已在自建 Gitea([https://git.jc2009.com/](https://git.jc2009.com/),**不是** Gitea 官网)开好业务仓并给你权限 | `git clone` 到本地后按 [`REQUIREMENTS.md`](REQUIREMENTS.md) 开发 |
| **B. 本地模板复制** | 你本机已有 `skill-template` 源码,要新建尚未灌仓的技能目录 | **优先** [`tools/scaffold_skill.ps1`](../tools/scaffold_skill.ps1)(见 [`tools/README.md`](../tools/README.md));也可手工复制但必须清掉模板 `.git` |
拿到仓库后的推荐顺序:
0. 按 [`NAMING.md`](NAMING.md) 确定 / 核对 slug(`{verb}-{noun-phrase}-{platform}`)
1. **先填写**本仓 [`REQUIREMENTS.md`](REQUIREMENTS.md)(范围与验收),再写业务代码
2. 来源 B:在新目录内 `git init` 并绑定**本技能**远端(**不得**保留模板 `.git`)
3. 把占位内容替换掉;**尽早**配置 `developer_ids`(见 §6,开发期宿主自测必做)
4. 再实现 `scripts/service/` 等业务逻辑
5. 本地测试通过 → `release.ps1` → Gitea CI → 匠厂多入口验收(§15)
> **Git 红线**:禁止资源管理器整文件夹复制后保留模板 `.git`;`git remote -v` 必须指向新技能仓库,不能仍是 skill-template。 > **Git 红线**:禁止资源管理器整文件夹复制后保留模板 `.git`;`git remote -v` 必须指向新技能仓库,不能仍是 skill-template。
@@ -170,7 +133,7 @@ scripts/
若 skill 需要浏览器/桌面/手机自动化,按以下顺序落地: 若 skill 需要浏览器/桌面/手机自动化,按以下顺序落地:
1. **先读三份标准**:`RPA.md`(含 §0.2:Profile 强制 / 有头 / 登录分平台)、`CONFIG.md`(`.env` 落盘与读取)、`ADAPTER.md`(四档 adapter)。 1. **先读总纲与三份标准**:`AI_RPA.md`(职责、合规、风控与完整闭环)、`RPA.md`(含 §0.2:Profile 强制 / 有头 / 登录分平台)、`CONFIG.md`(`.env` 落盘与读取)、`ADAPTER.md`(四档 adapter)。
2. **从 examples 选择性复制**(不要整包照搬 `examples/<mode>/`,见各 example README 的 copy map): 2. **从 examples 选择性复制**(不要整包照搬 `examples/<mode>/`,见各 example README 的 copy map):
- 若是 **真实浏览器 RPA**(真实网站、登录态、验证码、滚动采集),**必须先读** `examples/real_browser_rpa/README.md`,再按需复制到 `scripts/service/`: - 若是 **真实浏览器 RPA**(真实网站、登录态、验证码、滚动采集),**必须先读** `examples/real_browser_rpa/README.md`,再按需复制到 `scripts/service/`:
- `examples/real_browser_rpa/scripts/service/browser_session.py` - `examples/real_browser_rpa/scripts/service/browser_session.py`
@@ -192,9 +155,11 @@ scripts/
from jiangchang_skill_core.rpa import launch_persistent_browser, anti_detect, wait_for_captcha_pass from jiangchang_skill_core.rpa import launch_persistent_browser, anti_detect, wait_for_captcha_pass
``` ```
上述 import 来自宿主共享 runtime 安装的 `jiangchang-platform-kit`,不是技能目录副本。 上述 import 来自宿主共享 runtime 安装的 `jiangchang-platform-kit`,不是技能目录副本。
4. **mock 档必须离线可跑**(`OPENCLAW_TEST_TARGET=mock`);sim_rpa / real_* 按需单独测。 4. **单测/CI 须 mock 离线可过**;业务 `.env` 默认 `real_rpa`,须真实跑通。**不得只 mock 通就交活**;须 release 到匠厂宿主验收(见 §15,含用户体验)。
5. **桌面/手机**:本期标准见 RPA.md 第 2/3 节,复用 `jiangchang_desktop_sdk` / `screencast`,**不要在新 skill 里重复造包**(尚待实战验证)。 5. **桌面/手机**:本期标准见 RPA.md 第 2/3 节,复用 `jiangchang_desktop_sdk` / `screencast`,**不要在新 skill 里重复造包**(尚待实战验证)。
**技术路线红线:**正常界面或获得授权的官方 API 无法完成闭环时,停止并向负责人说明;禁止 AI 或开发者擅自改用破解、反编译、逆向、私有协议、Hook / 注入、验证码破解、设备指纹伪造、自动换号或无限重试。
--- ---
### 3.1 `requirements.txt` 依赖规范 ### 3.1 `requirements.txt` 依赖规范
@@ -256,13 +221,26 @@ release workflow 会对 `scripts/` 下的 Python 源码做加密/打包。当前
下面这套顺序建议严格按步骤做,不要一上来就直接写 `service`。 下面这套顺序建议严格按步骤做,不要一上来就直接写 `service`。
### 第一步:复制模板并改目录名 ### 第一步:拿到新技能仓库(两种来源)
例如你要开发 `disburse-payroll-icbc` 一类领域 skill(目录名 = slug): 例如你要开发 `disburse-payroll-icbc` 一类领域 skill(目录名 = slug)。下列两种来源**同等合法**,按你实际拿到仓库的方式选一条。
#### 推荐方式(首选) #### 来源 A:从 Gitea 克隆(项目经理已开仓)
在 **skill-template 仓库根目录**执行: 1. 确认项目经理已在自建 Gitea([https://git.jc2009.com/](https://git.jc2009.com/),公司基于开源 Gitea 自建的代码仓库,**不要**访问 Gitea 官网当作业务仓地址)创建**本技能**仓库,并给你拉取/推送权限。
2. 克隆到本地(示例):
```powershell
git clone https://git.jc2009.com/<org>/<your-skill-slug>.git
cd <your-skill-slug>
git remote -v # 确认 origin 指向本技能仓,不是 skill-template
```
3. 若仓内已是从本模板 scaffold 好的结构,直接进入「第二步」与 [`REQUIREMENTS.md`](REQUIREMENTS.md);**不要**再整仓复制 `skill-template` 覆盖,以免冲掉已有提交或串 Git 历史。
#### 来源 B:本地已有 skill-template 时复制 / scaffold
在 **skill-template 仓库根目录**执行(推荐):
```powershell ```powershell
.\tools\scaffold_skill.ps1 -Slug disburse-payroll-icbc -Destination D:\OpenClaw\client-gdcm\disburse-payroll-icbc .\tools\scaffold_skill.ps1 -Slug disburse-payroll-icbc -Destination D:\OpenClaw\client-gdcm\disburse-payroll-icbc
@@ -276,7 +254,7 @@ git remote -v # 确认 origin 不是 skill-template
脚手架会排除 `.git`、缓存与 `.env`,并删除 `.openclaw-skill-template` 标记;**不会**自动 `git init`。 脚手架会排除 `.git`、缓存与 `.env`,并删除 `.openclaw-skill-template` 标记;**不会**自动 `git init`。
#### 禁止方式 ##### 禁止方式(来源 B)
| 做法 | 后果 | | 做法 | 后果 |
|------|------| |------|------|
@@ -284,7 +262,7 @@ git remote -v # 确认 origin 不是 skill-template
| ❌ 保留模板 `.git` 只改 `remote url` | 历史、分支、对象库仍属 template | | ❌ 保留模板 `.git` 只改 `remote url` | 历史、分支、对象库仍属 template |
| ❌ 未删 `.git` 就 `git init` | 嵌套/混乱仓库,难以排查 | | ❌ 未删 `.git` 就 `git init` | 嵌套/混乱仓库,难以排查 |
#### 若已手工复制(补救) ##### 若已手工复制(补救)
```powershell ```powershell
cd <新技能目录> cd <新技能目录>
@@ -296,7 +274,7 @@ git remote add origin <新技能仓库 URL>
git remote -v git remote -v
``` ```
#### AI / 编程代理复制红线 ##### AI / 编程代理复制红线
| 禁止 | 说明 | | 禁止 | 说明 |
|------|------| |------|------|
@@ -307,9 +285,9 @@ git remote -v
目录名要和 skill slug 对齐,后面很多地方都依赖这个命名。 目录名要和 skill slug 对齐,后面很多地方都依赖这个命名。
### 第二步:先改 4 个最关键的标识 ### 第二步:先改关键标识与占位
复制后优先改下面这些地方: 拿到仓库并填好 / 更新 [`REQUIREMENTS.md`](REQUIREMENTS.md) 后,优先改下面这些地方:
1. `SKILL.md` 1. `SKILL.md`
2. 根目录市场四 Tab:`README.md` / `TUTORIAL.md` / `DEMO.md` / `CHANGELOG.md` 2. 根目录市场四 Tab:`README.md` / `TUTORIAL.md` / `DEMO.md` / `CHANGELOG.md`
@@ -325,7 +303,7 @@ git remote -v
- 平台内部键 - 平台内部键
- 日志 logger 名 - 日志 logger 名
此外,如果该技能发布后默认不公开(`access_scope = 0`),建议一开始就把 `SKILL.md` 中的 `metadata.openclaw.developer_ids` 配好。这样后续发布到平台时,开发者本人仍能在技能市场中看到并验证该技能。 **开发 / 联调阶段务必尽早**配置 `SKILL.md` 中的 `metadata.openclaw.developer_ids`(完整目的与取 ID 步骤见 §6「关于 developer_ids」)。开发期技能在匠厂常为不公开;不加本人用户 ID,**技术人员自己也无法在技能市场看到并安装自测**。
## 5. 哪些占位内容必须替换 ## 5. 哪些占位内容必须替换
@@ -385,14 +363,28 @@ git remote -v
- `references/`(CLI / SCHEMA) - `references/`(CLI / SCHEMA)
- 代码注释与 `service/` 实现 - 代码注释与 `service/` 实现
### 关于 `metadata.openclaw.developer_ids` ### 关于 `metadata.openclaw.developer_ids`(开发自测必做)
这是一个平台发布元数据字段,用于解决下面这个问题: #### 目的(先理解再填)
- 技能发布后若平台记录中的 `access_scope = 0`,技能默认不公开 开发 / 测试阶段,技能 `release` 到匠厂后,平台侧**默认不公开**(`access_scope = 0`):
- 如果不额外授权,连开发者自己也可能在技能市场里看不到这个技能
因此可以在 `SKILL.md` 中声明: - 技能市场里对普通人**不可见**
- **若不额外授权,连开发该技能的技术人员自己也看不见、装不了**
- 看不见 → 无法安装 → 无法在宿主做 §15 的多入口验收(新建任务、数据管理、定时任务等)
因此 `developer_ids` 不是可有可无的装饰字段,而是**开发期自测通行证**:把本人(及需要一起验收的同事)的匠厂**用户 ID** 写进 `SKILL.md`,发布时平台将这些用户补进可见 / 可访问范围,使开发者能在「对其他人仍不可见」的前提下完成安装与测试。
#### 如何获取匠厂用户 ID(完整步骤)
1. **下载并安装**匠厂客户端:[https://jc2009.com/product.html](https://jc2009.com/product.html)
2. **注册并登录**(使用将用于开发自测的账号)
3. 打开客户端左下角头像旁的**设置**(齿轮)
4. 在 **用户信息** 中查看 **用户 ID**(正整数),点击旁边的 **复制**
5. 将该 ID 写入本技能 `SKILL.md` 的 `metadata.openclaw.developer_ids`(见下例)
6. **必须替换**模板里的示例 ID(如 `10032`、`12428` 等占位),不要原样留着模板作者的 ID 却指望自己账号能看见技能
#### 在 `SKILL.md` 中声明
```yaml ```yaml
metadata: metadata:
@@ -400,17 +392,17 @@ metadata:
slug: your-skill-slug slug: your-skill-slug
category: 通用 category: 通用
developer_ids: developer_ids:
- 1032 - 12345 # 换成「你的用户ID」(匠厂「设置 → 用户信息」复制的正整数)
- 12428
``` ```
约定如下: 约定如下(原有规则保留):
- 只允许填写正整数用户 ID - 只允许填写正整数用户 ID(来自匠厂宿主,不是 Gitea / Git 账号名)
- 推荐使用数组,即使当前只有 1 个开发者 - 推荐使用数组,即使当前只有 1 个开发者
- 发布时平台会把这些用户自动补写到 `skill_user_access` - 发布时平台会把这些用户自动补写到 `skill_user_access`
- 第一个 ID 会同步到 `skills.developer_id` - 第一个 ID 会同步到 `skills.developer_id`
- 一期只做“补授权”,不会因为你 later 修改数组而自动撤销旧授权 - 一期只做“补授权”,不会因为你 later 修改数组而自动撤销旧授权
- **首次正式 release 前**就应配好;配错或漏配时,CI 可能成功,但你在技能市场仍找不到技能
## 7. 文档目录分工 ## 7. 文档目录分工
@@ -744,7 +736,7 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
.\release.ps1 .\release.ps1
``` ```
如果你的技能使用了 `metadata.openclaw.developer_ids`,那么这一步触发的发布工作流除了同步 `skills` / `skill_versions` 外,还会在平台侧自动补开发者可见权限。测试非公开技能时,建议重点验证这部分是否生效。 发布前 **`developer_ids` 应已配置**(见 §6)。本步触发的发布工作流除了同步 `skills` / `skill_versions` 外,还会在平台侧自动补开发者可见权限;发布后应重点确认:用本人账号能在技能市场看到并安装该技能。
这一步会自动完成标准发布动作,包括: 这一步会自动完成标准发布动作,包括:
@@ -789,9 +781,11 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
- 工作流文件是否存在 - 工作流文件是否存在
- 发布包结构是否符合模板规范 - 发布包结构是否符合模板规范
### 第四步:进入匠厂平台下载安装包 ### 第四步:进入匠厂客户端(用于安装验收)
当工作流成功后,就可以进入匠厂平台验证最终安装效果。 当工作流成功后,就可以进入匠厂客户端验证最终安装效果。
若你已按 §6 为 `developer_ids` 安装并登录过匠厂,**直接使用同一客户端、同一账号**即可,无需重复下载。若尚未安装:
匠厂产品下载地址: 匠厂产品下载地址:
@@ -803,11 +797,13 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
匠厂产品页可从这里进入:[产品下载 - 匠厂](https://jc2009.com/product.html) 匠厂产品页可从这里进入:[产品下载 - 匠厂](https://jc2009.com/product.html)
### 第五步:安装匠厂后,在技能市场检查最新 skill > 取用户 ID 写入 `developer_ids` 的完整步骤见 §6;此处侧重发布后的安装验收。
安装并启动匠厂后,进入左侧“技能市场”,搜索或查找刚刚发布的 skill,确认以下内容: ### 第五步:在技能市场检查最新 skill
- 技能可以被正常检索到 使用已写入 `developer_ids` 的账号登录并启动匠厂后,进入左侧“技能市场”,搜索或查找刚刚发布的 skill,确认以下内容:
- 技能可以被正常检索到(开发期不公开时,**仅** `developer_ids` 内账号可见)
- 技能名称、说明、版本信息正确 - 技能名称、说明、版本信息正确
- 最新版本已经同步出来 - 最新版本已经同步出来
- 可以正常安装或更新 - 可以正常安装或更新
@@ -826,11 +822,35 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
- 安装后状态正常 - 安装后状态正常
- 不会出现缺文件、缺入口或安装失败的问题 - 不会出现缺文件、缺入口或安装失败的问题
### 第七步:在“新建任务”中实际使用该 skill ### 第七步:按声明做宿主多入口验收(已声明的入口都要测;须看用户体验)
安装完成后,不要只停留在“已安装”状态,还需要进入“新建任务”页面,真正调用一次该 skill,完成最终验证。 安装完成后,不要只停留在“已安装”状态,也**不要**只在本地 mock 通就认为完成。宿主侧栏有多条与技能相关的入口;**按本技能 `assets/actions.json` 的 `placements` / `executionProfile` 声明逐项自测**(契约见 [`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md)、[`../references/ACTIONS.md`](../references/ACTIONS.md))。未声明的入口可以跳过;**已声明却测不到,视为验收失败**。不要只测对话、忽略其它入口。
建议至少验证: **用户体验(与功能入口并列,后台通了不算完):**
- 失败时用户能否看懂原因(对话 / 任务中心 / 提示),不是只有技术日志
- 长任务(async)是否有可见进度,能否取消或等待说明
- 网页 RPA 是否有头运行;需登录/验证码时是否停下等人,而不是静默失败
- 数据管理:表名/字段中文、按钮文案是否清楚;结果是否写回用户看得见的地方
- 市场说明 / 教程是否与真实行为一致
| 宿主入口(侧栏 / 界面) | 技能侧如何挂上 | 建议验收什么 |
|-------------------------|----------------|--------------|
| **新建任务**(对话 Agent) | `placements` 含 `agent`;或短查询走共享 Python CLI | 自然语言能触发主流程;长任务 / RPA 须走 `run_skill_action`,禁止 bash 干等 |
| **数据管理 · 表顶栏** | `placements` 含 `toolbar`(须合法非空 `bind.tables`) | 左侧能看到本技能库表;表顶栏出现按钮;点按行为符合预期 |
| **数据管理 · 行内** | `placements` 含 `row`(建议 `bind.tables` + `bind.inputMapping` 预填主键) | 行内操作链接可见(需有主键列);点按后入参/行为正确 |
| **数据管理 · 批量** | `placements` 含 `batch` | 勾选行后批量按钮可用;无勾选时禁用;批量行为正确 |
| **定时任务** | `placements` 含 `cron`(创建时选「技能直调」) | 能选到本技能 Action、保存并触发;到点或「立即运行」行为正确 |
| **任务中心** | 不是 placement;由 `executionProfile: "async"` 决定是否进 Job | 长任务出现进度 / 可取消;来源标签与触发入口一致 |
| **技能市场 → 技能详情** | `placements` 含 `skill-detail`(详情直调) | **必验**安装与四 Tab。详情页「技能直调」按钮随宿主版本上线;**已声明则须在具备该 UI 的宿主上完成按钮自测**(与其它入口同等对待,不要只靠 Agent) |
补充说明:
- **进不进任务中心只看 `executionProfile`**,与从哪个入口触发无关(既有正交规则不变)。
- 数据管理还依赖库表元数据(`_jiangchang_*` 等,见 [`../references/SCHEMA.md`](../references/SCHEMA.md));仅有 Action、没有可展示库表时,侧栏可能看不到表。
- `row` / `batch` / `toolbar` / `cron` / `agent` / `skill-detail` 均以**当前匠厂宿主已实现能力**为准;字段与示例见 [`../references/ACTIONS.md`](../references/ACTIONS.md)。
**新建任务(对话)最小检查:**
- 新任务中可以正常选择或触发该 skill - 新任务中可以正常选择或触发该 skill
- skill 能被正确唤起 - skill 能被正确唤起
@@ -841,6 +861,8 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
![新建任务中使用技能](../assets/screenshots/new-task-usage.png) ![新建任务中使用技能](../assets/screenshots/new-task-usage.png)
若第五步在技能市场**搜不到**本技能:先核对登录账号的用户 ID 是否已写入 `developer_ids` 并随本次 release 发布(见 §6);不要只反复重装客户端。
## 16. 发布前检查清单 ## 16. 发布前检查清单
每个新 skill 发布前,建议技术人员逐条确认: 每个新 skill 发布前,建议技术人员逐条确认:
@@ -849,6 +871,7 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
- [ ] slug 符合 [`NAMING.md`](NAMING.md)(verb-noun-platform) - [ ] slug 符合 [`NAMING.md`](NAMING.md)(verb-noun-platform)
- [ ] 目录名、`SKILL.md` slug、`constants.SKILL_SLUG` 三者一致 - [ ] 目录名、`SKILL.md` slug、`constants.SKILL_SLUG` 三者一致
- [ ] `SKILL.md` 中 slug、名称、描述都已替换 - [ ] `SKILL.md` 中 slug、名称、描述都已替换
- [ ] `SKILL.md` 的 `developer_ids` 已换成**本人**匠厂用户 ID(设置 → 用户信息 → 复制),不是模板示例 ID
- [ ] `scripts/util/constants.py` 已修改 - [ ] `scripts/util/constants.py` 已修改
- [ ] `../references/CLI.md` 示例命令已改成真实命令 - [ ] `../references/CLI.md` 示例命令已改成真实命令
- [ ] `service` 下的核心业务文件(如 `task_service.py`)已按领域改名并实现 - [ ] `service` 下的核心业务文件(如 `task_service.py`)已按领域改名并实现
@@ -868,7 +891,9 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
- [ ] 如有 integration 测试需求,已写在 `tests/integration/` 下并保持 `.sample` 后缀 - [ ] 如有 integration 测试需求,已写在 `tests/integration/` 下并保持 `.sample` 后缀
- [ ] 本仓库**不是** skill-template 的误复制(根目录**无** `.openclaw-skill-template`) - [ ] 本仓库**不是** skill-template 的误复制(根目录**无** `.openclaw-skill-template`)
- [ ] `git remote -v` 指向**本技能**远端,URL 不含 skill-template 仓库名 - [ ] `git remote -v` 指向**本技能**远端,URL 不含 skill-template 仓库名
- [ ] `git log` 首条提交属于本技能(非模板历史) - [ ] `git log` 首条提交属于本技能(非模板历史)(来源 A 从 Gitea 克隆的已有业务仓,以该仓历史为准)
- [ ] 业务 `.env` / `.env.example` 默认 `OPENCLAW_TEST_TARGET=real_rpa`(单测/CI 仍用 mock);**未只靠 mock 交活**
- [ ] 发布后计划在宿主按 §15 第七步验收:已声明入口 + **用户体验**(进度、失败提示、有头 RPA、文案一致等)
- [ ] 网页 RPA:`ensure-web` 取得 `profile_dir` 再开浏览器;`.env` 默认有头;REQUIREMENTS 写明登录策略(required/optional/not_needed,会话依赖型勿抄 optional);用户 README/TUTORIAL 区分「登记账号」与「站点登录」(`RPA.md` §0.2 / `POLICY-RPA-004`);依赖 kit 空值解析等修复时上调 `platform_kit_min_version` - [ ] 网页 RPA:`ensure-web` 取得 `profile_dir` 再开浏览器;`.env` 默认有头;REQUIREMENTS 写明登录策略(required/optional/not_needed,会话依赖型勿抄 optional);用户 README/TUTORIAL 区分「登记账号」与「站点登录」(`RPA.md` §0.2 / `POLICY-RPA-004`);依赖 kit 空值解析等修复时上调 `platform_kit_min_version`
## 17. 常见错误 ## 17. 常见错误

View File

@@ -20,6 +20,7 @@
| POLICY-RPA-002 | RPA 交付代码不得直接执行 ffmpeg 拼 MP4;应使用 `RpaVideoSession`(允许 `ffmpeg_path` 等诊断字段) | development/RPA.md §5.3 录屏成片标准 | hard | 扫描 `scripts/**/*.py` 禁止 `subprocess` / `os.system` / `os.popen` 直接调用 ffmpeg(`task_run_support.py` 保留豁免) | `tests/test_development_policy_guard.py::TestPolicyRpa002` | | POLICY-RPA-002 | RPA 交付代码不得直接执行 ffmpeg 拼 MP4;应使用 `RpaVideoSession`(允许 `ffmpeg_path` 等诊断字段) | development/RPA.md §5.3 录屏成片标准 | hard | 扫描 `scripts/**/*.py` 禁止 `subprocess` / `os.system` / `os.popen` 直接调用 ffmpeg(`task_run_support.py` 保留豁免) | `tests/test_development_policy_guard.py::TestPolicyRpa002` |
| POLICY-RPA-003 | 即使默认 `OPENCLAW_RECORD_VIDEO=0`,RPA / 长任务模板也必须保留录屏能力:`RpaVideoSession`、`video.add_step`、video artifact merge 到 `result_summary` | development/RPA.md §5.3;development/LOGGING.md;development/CONFIG.md | hard | 扫描 `scripts/service/*.py`(service 层整体须含上述接入) | `tests/test_development_policy_guard.py::TestPolicyRpa003` | | POLICY-RPA-003 | 即使默认 `OPENCLAW_RECORD_VIDEO=0`,RPA / 长任务模板也必须保留录屏能力:`RpaVideoSession`、`video.add_step`、video artifact merge 到 `result_summary` | development/RPA.md §5.3;development/LOGGING.md;development/CONFIG.md | hard | 扫描 `scripts/service/*.py`(service 层整体须含上述接入) | `tests/test_development_policy_guard.py::TestPolicyRpa003` |
| POLICY-RPA-004 | 网页 RPA:`.env.example` 若声明 `OPENCLAW_BROWSER_HEADLESS` 则默认必须为 `0`;`scripts/` 若使用 `launch_persistent_*` 则必须同时存在 `pick_web_account`(先 Profile 再开浏览器;实现上应走 ensure-web);登录不全局强制,但不得跳过 account-manager | development/RPA.md §0.2;development/ADAPTER.md §兄弟依赖 | hard | 解析 `.env.example` + 扫描 `scripts/**/*.py` | `tests/test_development_policy_guard.py::TestPolicyRpa004` | | POLICY-RPA-004 | 网页 RPA:`.env.example` 若声明 `OPENCLAW_BROWSER_HEADLESS` 则默认必须为 `0`;`scripts/` 若使用 `launch_persistent_*` 则必须同时存在 `pick_web_account`(先 Profile 再开浏览器;实现上应走 ensure-web);登录不全局强制,但不得跳过 account-manager | development/RPA.md §0.2;development/ADAPTER.md §兄弟依赖 | hard | 解析 `.env.example` + 扫描 `scripts/**/*.py` | `tests/test_development_policy_guard.py::TestPolicyRpa004` |
| POLICY-RPA-005 | 必须保留 AI + RPA 总纲,明确 Agent / RPA 职责、授权范围、禁止破解/逆向/私有协议/安全验证绕过、人工介入、状态等待;真实业务默认动作节奏为 1~3 秒 | development/AI_RPA.md §4–§6;development/RPA.md §0.0/§0.3 | hard(文档与默认配置) / soft(真实行为) | 检查总纲关键边界;解析 `.env.example` 的 `STEP_DELAY_MIN=1.0` / `STEP_DELAY_MAX=3.0` | `tests/test_development_policy_guard.py::TestPolicyRpa005` |
| POLICY-PACKAGING-001 | `scripts/**/*.py` 单文件 < 1000 行 | development/DEVELOPMENT.md §3.4 发布打包约束;development/RUNTIME.md §发布打包约束 | hard | 行数统计 | **已有测试覆盖**:`tests/test_release_packaging_constraints.py::test_scripts_py_files_under_pyarmor_line_limit` | | POLICY-PACKAGING-001 | `scripts/**/*.py` 单文件 < 1000 行 | development/DEVELOPMENT.md §3.4 发布打包约束;development/RUNTIME.md §发布打包约束 | hard | 行数统计 | **已有测试覆盖**:`tests/test_release_packaging_constraints.py::test_scripts_py_files_under_pyarmor_line_limit` |
| POLICY-PACKAGING-002 | 文本文件 UTF-8 without BOM,无 `U+FEFF` | development/DEVELOPMENT.md §3.4;development/RUNTIME.md §编码与输出 | hard | BOM / 解码检查 | **已有测试覆盖**:`tests/test_release_packaging_constraints.py::test_text_files_are_utf8_without_bom` | | POLICY-PACKAGING-002 | 文本文件 UTF-8 without BOM,无 `U+FEFF` | development/DEVELOPMENT.md §3.4;development/RUNTIME.md §编码与输出 | hard | BOM / 解码检查 | **已有测试覆盖**:`tests/test_release_packaging_constraints.py::test_text_files_are_utf8_without_bom` |
| POLICY-DOCS-001 | 本矩阵存在且包含上述全部 `policy_id` | 本次规范化约定 | hard | 解析 `development/POLICY_MATRIX.md` | `tests/test_development_policy_guard.py::TestPolicyDocs001` | | POLICY-DOCS-001 | 本矩阵存在且包含上述全部 `policy_id` | 本次规范化约定 | hard | 解析 `development/POLICY_MATRIX.md` | `tests/test_development_policy_guard.py::TestPolicyDocs001` |
@@ -35,7 +36,7 @@
| POLICY-SKILL-ACTION-001 | 存在 `development/SKILL_ACTION_RUNTIME.md`;schema 含 `executionProfile`;业务技能(非模板占位 slug)若 service 含 `RpaVideoSession` 则 `actions.json` 须有 `executionProfile=async` 且 placements 含 `agent` 的 action | development/SKILL_ACTION_RUNTIME.md;references/ACTIONS.md | hard | 文档/schema/manifest 检查 | `tests/test_development_policy_guard.py::TestPolicySkillAction001` | | POLICY-SKILL-ACTION-001 | 存在 `development/SKILL_ACTION_RUNTIME.md`;schema 含 `executionProfile`;业务技能(非模板占位 slug)若 service 含 `RpaVideoSession` 则 `actions.json` 须有 `executionProfile=async` 且 placements 含 `agent` 的 action | development/SKILL_ACTION_RUNTIME.md;references/ACTIONS.md | hard | 文档/schema/manifest 检查 | `tests/test_development_policy_guard.py::TestPolicySkillAction001` |
| POLICY-SKILL-ACTION-002 | 每个 Action 必须显式声明 `executionProfile`,且只能是 `sync` 或 `async` | development/SKILL_ACTION_RUNTIME.md;references/ACTIONS.md;assets/schemas/skill-actions.schema.json | hard | schema required + manifest 扫描 | `tests/test_development_policy_guard.py::TestPolicySkillAction002`;`tests/test_actions_manifest.py` | | POLICY-SKILL-ACTION-002 | 每个 Action 必须显式声明 `executionProfile`,且只能是 `sync` 或 `async` | development/SKILL_ACTION_RUNTIME.md;references/ACTIONS.md;assets/schemas/skill-actions.schema.json | hard | schema required + manifest 扫描 | `tests/test_development_policy_guard.py::TestPolicySkillAction002`;`tests/test_actions_manifest.py` |
| POLICY-SKILL-ACTION-003 | toolbar Action 必须声明合法非空 `bind.tables`(snake_case、唯一) | references/ACTIONS.md;assets/schemas/skill-actions.schema.json | hard | schema if/then + manifest 扫描 | `tests/test_development_policy_guard.py::TestPolicySkillAction003`;`tests/test_actions_manifest.py` | | POLICY-SKILL-ACTION-003 | toolbar Action 必须声明合法非空 `bind.tables`(snake_case、唯一) | references/ACTIONS.md;assets/schemas/skill-actions.schema.json | hard | schema if/then + manifest 扫描 | `tests/test_development_policy_guard.py::TestPolicySkillAction003`;`tests/test_actions_manifest.py` |
| POLICY-SKILL-ACTION-004 | `placements` 与 `executionProfile` 正交;文档不得把数据管理入口与异步执行方式硬绑定;Schema 须接受 toolbar/cron/agent/skill-detail × sync/async 全部组合 | development/SKILL_ACTION_RUNTIME.md;references/ACTIONS.md;assets/schemas/skill-actions.schema.json | hard | Schema 4×2 矩阵校验 + 文档禁止短语扫描 | `tests/test_actions_manifest.py::test_schema_allows_all_placement_execution_profile_combinations`;`tests/test_development_policy_guard.py::TestPolicySkillAction004` | | POLICY-SKILL-ACTION-004 | `placements` 与 `executionProfile` 正交;文档不得把数据管理入口与异步执行方式硬绑定;Schema 须接受 toolbar/row/batch/cron/agent/skill-detail × sync/async 全部组合 | development/SKILL_ACTION_RUNTIME.md;references/ACTIONS.md;assets/schemas/skill-actions.schema.json | hard | Schema 6×2 矩阵校验 + 文档禁止短语扫描 | `tests/test_actions_manifest.py::test_schema_allows_all_placement_execution_profile_combinations`;`tests/test_development_policy_guard.py::TestPolicySkillAction004` |
| POLICY-ARCH-CORE-001 | 同一业务能力的 Action、CLI、Agent、cron、数据管理入口复用同一业务内核(文档要求已声明) | development/DEVELOPMENT.md;development/SKILL_ACTION_RUNTIME.md | hard(文档标记) / soft(语义) | 文档关键表述存在性;真实复用靠 sample/review | `tests/test_development_policy_guard.py::TestPolicyArchCore001`;`tests/samples/test_action_core_contract.py.sample` | | POLICY-ARCH-CORE-001 | 同一业务能力的 Action、CLI、Agent、cron、数据管理入口复用同一业务内核(文档要求已声明) | development/DEVELOPMENT.md;development/SKILL_ACTION_RUNTIME.md | hard(文档标记) / soft(语义) | 文档关键表述存在性;真实复用靠 sample/review | `tests/test_development_policy_guard.py::TestPolicyArchCore001`;`tests/samples/test_action_core_contract.py.sample` |
| POLICY-DATA-SYNC-001 | 同步型业务须遵循幂等、事务、完整性与空结果保护(文档已声明) | references/SCHEMA.md;development/SKILL_ACTION_RUNTIME.md | hard(文档标记) / soft(语义) | 文档关键表述存在性;完整语义靠 sample/review | `tests/test_development_policy_guard.py::TestPolicyDataSync001`;`tests/samples/test_sync_contract.py.sample` | | POLICY-DATA-SYNC-001 | 同步型业务须遵循幂等、事务、完整性与空结果保护(文档已声明) | references/SCHEMA.md;development/SKILL_ACTION_RUNTIME.md | hard(文档标记) / soft(语义) | 文档关键表述存在性;完整语义靠 sample/review | `tests/test_development_policy_guard.py::TestPolicyDataSync001`;`tests/samples/test_sync_contract.py.sample` |
@@ -56,7 +57,7 @@
| slug 命名语义(verb-noun-platform) | development/NAMING.md | 部分覆盖于 `tests/test_slug_naming.py`,非本矩阵 hard policy | | slug 命名语义(verb-noun-platform) | development/NAMING.md | 部分覆盖于 `tests/test_slug_naming.py`,非本矩阵 hard policy |
| 复制模板不得保留 `.git` / template marker | development/DEVELOPMENT.md §4 | 由 `tests/test_scaffold_guard.py` 守护,属脚手架场景 | | 复制模板不得保留 `.git` / template marker | development/DEVELOPMENT.md §4 | 由 `tests/test_scaffold_guard.py` 守护,属脚手架场景 |
| 共享 runtime 导入来源非技能目录 | development/RUNTIME.md | 运行时依赖已安装包,见 `tests/test_platform_import.py` | | 共享 runtime 导入来源非技能目录 | development/RUNTIME.md | 运行时依赖已安装包,见 `tests/test_platform_import.py` |
| RPA 拟人操作、选择器纪律、HITL 超时 | development/RPA.md §0–§1 | 行为与 DOM 质量,无法静态扫描 | | RPA 真实轨迹、选择器纪律、状态等待、HITL 超时与有限重试是否正确实现 | development/AI_RPA.md;development/RPA.md §0–§1 | 文档和默认节奏已守护,真实行为与 DOM 质量仍需人工验收 |
| adapter 四档契约测试覆盖 timeout/unauthorized 等 | development/ADAPTER.md §contract tests | 需业务实现后人工补测 | | adapter 四档契约测试覆盖 timeout/unauthorized 等 | development/ADAPTER.md §contract tests | 需业务实现后人工补测 |
| `SKILL.md` / `constants.SKILL_SLUG` 一致性 | development/DEVELOPMENT.md §16 | 已有 `tests/test_skill_metadata.py` | | `SKILL.md` / `constants.SKILL_SLUG` 一致性 | development/DEVELOPMENT.md §16 | 已有 `tests/test_skill_metadata.py` |
| platform_kit_min_version >= 1.2.2 | development/RUNTIME.md | 已有 `tests/test_platform_import.py` | | platform_kit_min_version >= 1.2.2 | development/RUNTIME.md | 已有 `tests/test_platform_import.py` |

View File

@@ -1,20 +1,44 @@
# 开发资料入口 # 开发资料入口
本目录面向**人类开发者**与 **AI 编程代理**。开始定制 skill 前,建议按以下顺序阅读: 本目录面向**人类开发者**与 **AI 编程代理**。技术人员与编程 AI **以本目录为主读路径**;`references/` 是 CLI / Action / Schema 契约细节,根目录市场四 Tab 面向最终用户。
1. [`REQUIREMENTS.md`](REQUIREMENTS.md) — 需求文档模板与验收标准 ## 新技能全流程(先看这张表)
2. [`NAMING.md`](NAMING.md) — slug / 仓库名命名规范(复制模板前必读)
3. [`DEVELOPMENT.md`](DEVELOPMENT.md) — 完整开发步骤与目录规范
4. [`TESTING.md`](TESTING.md) — 测试分层、隔离数据根与档位开关
5. [`LOGGING.md`](LOGGING.md) — 日志分层、必打节点、敏感信息红线(**涉及长任务、RPA、外部系统时必读**)
6. [`ADAPTER.md`](ADAPTER.md) — 涉及外部系统对接时
7. [`RPA.md`](RPA.md) — 涉及浏览器 / 桌面 / 手机自动化时
8. [`CONFIG.md`](CONFIG.md) — `.env` 规范与 bootstrap 机制
9. [`DATA_PATHS.md`](DATA_PATHS.md) — 下载/导入/导出等本地文件路径标准(涉及文件读写时必读)
10. [`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md) — Skill Action sync/async、任务中心、Agent 禁令、队列 pick(涉及 RPA / 长任务 / 数据管理按钮 / Cron / Agent 时必读)
11. [`RUNTIME.md`](RUNTIME.md) — 共享 runtime、数据路径、发布打包与编码约定
脚手架与 Git 防串库:[`../tools/README.md`](../tools/README.md)(`scaffold_skill.ps1`)。 按顺序做;细节与约束见 [`DEVELOPMENT.md`](DEVELOPMENT.md) 对应章节(**不替代**下文深度规范,只作导航)。
| 步骤 | 做什么 | 详见 |
|------|--------|------|
| 1 | **拿到仓库**:① 项目经理在 [自建 Gitea](https://git.jc2009.com/)(`git.jc2009.com`,非 Gitea 官网)开仓并授权后 `git clone`;或 ② 本地已有 `skill-template` 时用 scaffold / 复制出新目录(遵守 Git 红线) | [`DEVELOPMENT.md`](DEVELOPMENT.md) §1、§4 |
| 2 | **先读 AI + RPA 总纲**,理解 Agent / RPA 职责、授权边界、禁止路线、风控和操作节奏 | [`AI_RPA.md`](AI_RPA.md) |
| 3 | 按 [`NAMING.md`](NAMING.md) 确认 slug;**先填** [`REQUIREMENTS.md`](REQUIREMENTS.md),再写业务代码 | [`REQUIREMENTS.md`](REQUIREMENTS.md)、[`NAMING.md`](NAMING.md) |
| 4 | 替换标识与占位,按四象限 / examples 实现 `scripts/service/` | [`DEVELOPMENT.md`](DEVELOPMENT.md) §4~§14 |
| 5 | **配置 `developer_ids`(开发自测必做)**:开发期技能在匠厂默认不公开;不加则开发者自己也装测不了。从宿主设置复制用户 ID 写入 `SKILL.md` | [`DEVELOPMENT.md`](DEVELOPMENT.md) §6「关于 developer_ids」 |
| 6 | 本地单测(mock)通过后,按业务默认 **`real_rpa`** 真实跑通;再 `release.ps1`;看 Gitea CI。**mock 通 ≠ 完成** | [`ADAPTER.md`](ADAPTER.md);[`DEVELOPMENT.md`](DEVELOPMENT.md) §15 |
| 7 | 匠厂安装后,按已声明入口自测,并看**用户体验**(进度、失败提示、有头 RPA 等) | [`DEVELOPMENT.md`](DEVELOPMENT.md) §15;[`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md) |
| 8 | **交活验收(第三方)**:对照 [`CHECKLIST.md`](CHECKLIST.md) 验收;报告写入仓库根目录 [`acceptance-reports/`](../acceptance-reports/) | [`CHECKLIST.md`](CHECKLIST.md) |
脚手架与 Git 防串库:[`../tools/README.md`](../tools/README.md)(`scaffold_skill.ps1`)。业务仓也可直接从自建 Gitea clone,见 [`DEVELOPMENT.md`](DEVELOPMENT.md) §4 来源 A。
**公开公共仓(可 clone 学习,可扩展登记):** [`SHARED_REPOS.md`](SHARED_REPOS.md) — 当前含 skill-template、account-manager、jiangchang-platform-kit。
## 深度规范阅读顺序
开始定制 skill 前,建议按以下顺序阅读:
1. [`AI_RPA.md`](AI_RPA.md) — **AI Agent + RPA 总纲**:职责边界、合规红线、风控、操作节奏与完整闭环
2. [`SHARED_REPOS.md`](SHARED_REPOS.md) — **公共仓库目录**(模板 / 账号管理 / platform-kit 等,可扩展)
3. [`REQUIREMENTS.md`](REQUIREMENTS.md) — 需求文档模板与验收标准
4. [`NAMING.md`](NAMING.md) — slug / 仓库名命名规范(复制模板前必读)
5. [`DEVELOPMENT.md`](DEVELOPMENT.md) — 完整开发步骤与目录规范
6. [`TESTING.md`](TESTING.md) — 测试分层、隔离数据根与档位开关
7. [`LOGGING.md`](LOGGING.md) — 日志分层、必打节点、敏感信息红线(**涉及长任务、RPA、外部系统时必读**)
8. [`ADAPTER.md`](ADAPTER.md) — 涉及外部系统对接时
9. [`RPA.md`](RPA.md) — 涉及浏览器 / 桌面 / 手机自动化时
10. [`CONFIG.md`](CONFIG.md) — `.env` 规范与 bootstrap 机制
11. [`DATA_PATHS.md`](DATA_PATHS.md) — 下载/导入/导出等本地文件路径标准(涉及文件读写时必读)
12. [`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md) — Skill Action sync/async、任务中心、Agent 禁令、队列 pick(涉及 RPA / 长任务 / 数据管理按钮 / Cron / Agent 时必读)
13. [`RUNTIME.md`](RUNTIME.md) — 共享 runtime、数据路径、发布打包与编码约定
14. [`CHECKLIST.md`](CHECKLIST.md) — **交活验收清单(第三方视角)**;报告输出到 [`../acceptance-reports/`](../acceptance-reports/)
Agent 调用契约见 [`../references/CLI.md`](../references/CLI.md)、[`../references/SCHEMA.md`](../references/SCHEMA.md)、[`../references/ACTIONS.md`](../references/ACTIONS.md)。 Agent 调用契约见 [`../references/CLI.md`](../references/CLI.md)、[`../references/SCHEMA.md`](../references/SCHEMA.md)、[`../references/ACTIONS.md`](../references/ACTIONS.md)。
用户市场四 Tab 见根目录 [`README.md`](../README.md) / [`TUTORIAL.md`](../TUTORIAL.md) / [`DEMO.md`](../DEMO.md) / [`CHANGELOG.md`](../CHANGELOG.md),不要写进本目录。 用户市场四 Tab 见根目录 [`README.md`](../README.md) / [`TUTORIAL.md`](../TUTORIAL.md) / [`DEMO.md`](../DEMO.md) / [`CHANGELOG.md`](../CHANGELOG.md),不要写进本目录。

View File

@@ -6,6 +6,7 @@
- 一个 skill 对应一份主需求文档 - 一个 skill 对应一份主需求文档
- 需求先写清楚,再进入开发 - 需求先写清楚,再进入开发
- 涉及外部系统时先读 `AI_RPA.md`,明确 Agent / RPA 边界、授权、风险与人工介入
- 文档描述“要做什么”和“做到什么程度”,不要在这里堆实现细节 - 文档描述“要做什么”和“做到什么程度”,不要在这里堆实现细节
- 实现方式、代码结构、发布流程,分别放到 `DEVELOPMENT.md`、`references/`、`development/` 下的技术规范 - 实现方式、代码结构、发布流程,分别放到 `DEVELOPMENT.md`、`references/`、`development/` 下的技术规范
@@ -30,6 +31,39 @@
- **登记 ≠ 登录**:ensure/add-web 只建账号与 Profile;站点登录由本技能在有头浏览器中完成 - **登记 ≠ 登录**:ensure/add-web 只建账号与 Profile;站点登录由本技能在有头浏览器中完成
- **反模式**:把「需要登录态才能采到数据」的需求写成 `optional`,再省略 `ensure_logged_in` - **反模式**:把「需要登录态才能采到数据」的需求写成 `optional`,再省略 `ensure_logged_in`
## 0.1 AI + RPA 协作与授权边界(涉及外部系统时必填)
### Agent 设计
- 用户会怎样描述本任务:
- 支持哪些用户意图;分别映射到哪个 Action:
- 每种意图必须提取哪些参数:
- 缺少哪些参数时必须追问:
- 哪些动作必须先展示对象、数量和影响,再取得明确确认:
- Agent 最终如何解释成功、部分成功、失败、等待人工和停止:
### 授权与平台边界
- 目标浏览器 / 桌面软件 / 手机 App:
- 账号、设备、数据和业务权限由谁授权:
- 是否有获得授权的官方 API;若不用,原因是什么:
- 目标平台规则、合同或客户约定中的自动化边界:
- 明确禁止的实现路线:破解 / 反编译 / 逆向 / 私有协议 / 抓包拼隐藏接口 / Hook 或注入 / 验证码破解 / 设备指纹伪造 / 自动换号:
- 正常界面无法闭环时的上报与停止条件:
### RPA 风控设计
- 执行端:浏览器 / 桌面 / Android / iOS:
- 会话、Profile、窗口或设备如何准备与互斥:
- 单批上限、单位时间操作量和最长运行时间:
- 普通动作节奏(真实环境默认 `1~3` 秒):
- 页面 / 控件真实状态如何判断;禁止用固定睡眠代替的节点:
- 哪些错误允许有限重试;退避策略:
- 哪些信号必须立即停止(频控、封禁、权限不足、结构变化等):
- 哪些步骤进入人工处理(验证码、人脸、指纹、短信、U盾等):
- 如何防止重复提交并支持必要的断点续跑:
- 需要保存哪些日志、截图、视频和业务结果:
## 1. 文档目标 ## 1. 文档目标
说明这份需求文档的作用,以及它解决什么问题。 说明这份需求文档的作用,以及它解决什么问题。
@@ -109,6 +143,8 @@
- 输出格式应尽量机读友好;错误前缀统一为 `ERROR:` - 输出格式应尽量机读友好;错误前缀统一为 `ERROR:`
- Windows 环境下需保证 UTF-8 输出兼容 - Windows 环境下需保证 UTF-8 输出兼容
- 必须具备基本日志能力;敏感字段脱敏 - 必须具备基本日志能力;敏感字段脱敏
- 只做授权范围内的正常界面自动化;禁止破解、逆向、未授权私有协议、安全验证绕过、进程注入、凭据窃取、自动换号和无限重试
- RPA 的页面加载与成功判断必须由真实状态驱动;正常业务动作之间默认随机等待 `1~3` 秒
- RPA 类 skill:Playwright 由宿主共享 runtime 提供;技能侧不要 `playwright install`;URL 不要放进 `launch_persistent_context` 的 `args` - RPA 类 skill:Playwright 由宿主共享 runtime 提供;技能侧不要 `playwright install`;URL 不要放进 `launch_persistent_context` 的 `args`
- 网页 RPA:启动前必须经 ensure-web 拿到 `profile_dir`;生产有头;站点登录策略见 §0(required / optional / not_needed);`required` 时每轮须登录门禁 - 网页 RPA:启动前必须经 ensure-web 拿到 `profile_dir`;生产有头;站点登录策略见 §0(required / optional / not_needed);`required` 时每轮须登录门禁
@@ -164,21 +200,26 @@
- 代码结构符合模板规范;`SKILL.md` slug 与 `constants.SKILL_SLUG` 一致 - 代码结构符合模板规范;`SKILL.md` slug 与 `constants.SKILL_SLUG` 一致
- `health`、`version`、`init-db` 命令执行正常 - `health`、`version`、`init-db` 命令执行正常
- 主命令(如 `run`)在 mock / simulator 档位可重复验证 - `python tests/run_tests.py -v` 必跑测试全部通过(mock / 离线门禁;**mock 通 ≠ 完成**)
- `python tests/run_tests.py -v` 必跑测试全部通过 - 主命令在业务默认档(模板为 `real_rpa`)真实跑通;不得只 mock 通就交活
- `task_logs` 写入和查询符合 `references/SCHEMA.md`(含 `created_at` / `updated_at` Unix 秒级规范) - `task_logs` 写入和查询符合 `references/SCHEMA.md`(含 `created_at` / `updated_at` Unix 秒级规范)
- `init_db()` 已写入 `_jiangchang_tables` / `_jiangchang_columns`;用户可见表/字段具备中文 `display_name` - `init_db()` 已写入 `_jiangchang_tables` / `_jiangchang_columns`;用户可见表/字段具备中文 `display_name`
- 字段展示顺序与 `PRAGMA table_info(task_logs)` 的 cid 一致;不依赖 `display_order` - 字段展示顺序与 `PRAGMA table_info(task_logs)` 的 cid 一致;不依赖 `display_order`
- `tests/test_display_metadata.py` 通过 - `tests/test_display_metadata.py` 通过
- 真实联调(如有)放在 `tests/integration/`,且默认套件不包含真实外联 - 真实联调样例仍放 `tests/integration/`,默认套件不包含真实外联(与业务 `.env` 默认 `real_rpa` 不冲突)
- 发布后 Gitea 工作流成功;匠厂技能市场可见最新版本;安装后可在“新建任务”中调用 - `SKILL.md` 的 `developer_ids` 已配置为开发者本人匠厂用户 ID(开发期不公开时,否则本人无法在市场安装自测;取 ID 步骤见 `development/DEVELOPMENT.md` §6)
- 发布后 Gitea 工作流成功;匠厂技能市场对开发者账号可见最新版本并可安装
- 安装后按本技能 `actions.json` 声明完成宿主多入口验收(见 `development/DEVELOPMENT.md` §15);**须看用户体验**(进度可见、失败可读、RPA 有头、文案与真实行为一致等),后台通了不算完
- 已人工核验授权与技术路线:无破解、逆向、私有协议、验证码绕过、Hook / 注入、自动换号或其他规避平台限制的实现
- RPA 真实主路径已验证状态等待、`1~3` 秒正常操作节奏、有限重试、账号 / 设备串行、人工介入、结果核验和结束存证
## 10. 开发注意事项 ## 10. 开发注意事项
- 只修改当前 skill 仓库,不要改动无关兄弟项目 - 只修改当前 skill 仓库,不要改动无关兄弟项目
- 正常界面或获得授权的官方 API 无法完成闭环时,停止并上报;不得擅自改走破解、逆向或绕过安全机制的路线
- 先判断四象限类型(`real_browser_rpa` / `real_api` / `simulator_browser_rpa` / `simulator_api`),再读对应 `examples/*/README.md` - 先判断四象限类型(`real_browser_rpa` / `real_api` / `simulator_browser_rpa` / `simulator_api`),再读对应 `examples/*/README.md`
- `cli` 只做参数解析;核心逻辑在 `service`;兄弟 skill 调用集中封装(见 `ADAPTER.md`) - `cli` 只做参数解析;核心逻辑在 `service`;兄弟 skill 调用集中封装(见 `ADAPTER.md`)
- 发布前完成本地验证、工作流验证和正式环境安装验证 - 发布前完成本地验证、工作流验证和正式环境安装验证(含 `developer_ids` 与宿主多入口)
## 11. 变更记录 ## 11. 变更记录
@@ -190,10 +231,11 @@
## 建议使用方式 ## 建议使用方式
1. 先写 `REQUIREMENTS.md` 1. 拿到业务技能仓库(Gitea clone,或本地从 `skill-template` scaffold / 复制;见 `DEVELOPMENT.md` §4)
2. 再按 `DEVELOPMENT.md` 进入开发 2. 先写 / 填全本文件 `REQUIREMENTS.md`
3. 开发过程中补充 `references/CLI.md`、`references/SCHEMA.md` 及 `development/` 技术规范 3. 再按 `DEVELOPMENT.md` 进入开发(含尽早配置 `developer_ids`)
4. 发布前对照第 9 节验收标准逐项检查 4. 开发过程中补充 `references/CLI.md`、`references/SCHEMA.md` 及 `development/` 技术规范
5. 发布前对照第 9 节验收标准逐项检查;release 后按 `DEVELOPMENT.md` §15 做宿主多入口验收
## 最小模板示例 ## 最小模板示例
@@ -254,8 +296,8 @@
- 命令可运行;tests/run_tests.py -v 通过 - 命令可运行;tests/run_tests.py -v 通过
- task_logs 符合 SCHEMA - task_logs 符合 SCHEMA
- 正式环境安装验证通过 - `developer_ids` 已配置为「你的用户ID」(匠厂设置中复制的正整数)
- 正式环境安装验证通过;已声明的宿主入口(新建任务 / 数据管理 / 定时任务 / 任务中心 / 技能详情等)按 DEVELOPMENT §15 自测
## 10. 开发注意事项 ## 10. 开发注意事项
- 不修改无关项目;不引入旧模板结构 - 不修改无关项目;不引入旧模板结构

View File

@@ -2,6 +2,10 @@
> 本文是团队 RPA 开发的**统一标准**。任何需要"自动操作软件界面"的 skill,都应先读这份文档,按这里的选型和范式落地,不要每个项目重新踩坑。 > 本文是团队 RPA 开发的**统一标准**。任何需要"自动操作软件界面"的 skill,都应先读这份文档,按这里的选型和范式落地,不要每个项目重新踩坑。
先读 [`AI_RPA.md`](AI_RPA.md):Agent 负责理解、确认与编排,RPA 只负责授权范围内的确定性界面执行。RPA 是代替人完成正常业务操作的工具,**不是**破解、逆向、私有协议调用或对抗第三方安全机制的手段。
网页账号 / Profile 依赖公开兄弟技能 **account-manager**;浏览器 RPA 原语来自 **jiangchang-platform-kit**。二者 Gitea 地址、clone 方式与红线见 [`SHARED_REPOS.md`](SHARED_REPOS.md)。
我们开发的各类 skill,本质上都是在替人操作三类界面:**浏览器、桌面软件、手机软件**。三类的底层技术不同,但**工程范式相同**:可控会话(Profile)、有头运行、拟人操作、失败存证、人工兜底。 我们开发的各类 skill,本质上都是在替人操作三类界面:**浏览器、桌面软件、手机软件**。三类的底层技术不同,但**工程范式相同**:可控会话(Profile)、有头运行、拟人操作、失败存证、人工兜底。
--- ---
@@ -14,8 +18,8 @@
|------|------| |------|------|
| **可控会话 / Profile** | 网页版见下方 **§0.2**(必须走 account-manager 的 `profile_dir`);桌面/手机用对应持久会话,不硬编码密码 | | **可控会话 / Profile** | 网页版见下方 **§0.2**(必须走 account-manager 的 `profile_dir`);桌面/手机用对应持久会话,不硬编码密码 |
| **有头运行** | 生产 RPA **必须有头**(见 §0.2);禁止把无头当交付/联调常态 | | **有头运行** | 生产 RPA **必须有头**(见 §0.2);禁止把无头当交付/联调常态 |
| **拟人操作** | 真实事件(isTrusted=true),逐字输入、随机延迟、贝塞尔鼠标轨迹;严禁 JS 直接设值/JS 点击/JS 跳转 | | **正常人工节奏** | 真实点击、逐字输入、自然鼠标轨迹、分段滚动;严禁 JS 直接设值/JS 点击/JS 跳转绕过页面流程 |
| **步骤间随机等待** | 每两步操作之间 `random_delay(min,max)`,区间由 `.env` 配置(默认 1~5s) | | **步骤间随机等待** | 每两个正常业务动作之间 `random_delay(min,max)`,真实环境默认 **1~3 秒**;状态等待另算,不得用固定睡眠代替 |
| **人工兜底(HITL)** | 滑块 / 短信验证码 / 人脸 / U盾 / 动态口令 → **停下来轮询等人工**,超时报 `ERROR:XXX_NEED_HUMAN`,绝不自动硬闯 | | **人工兜底(HITL)** | 滑块 / 短信验证码 / 人脸 / U盾 / 动态口令 → **停下来轮询等人工**,超时报 `ERROR:XXX_NEED_HUMAN`,绝不自动硬闯 |
| **失败存证** | 失败必截图,合规场景全程录屏,统一存 `{数据目录}/rpa-artifacts/{batch_id}/{tag}_{ts}.png` | | **失败存证** | 失败必截图,合规场景全程录屏,统一存 `{数据目录}/rpa-artifacts/{batch_id}/{tag}_{ts}.png` |
| **选择器纪律** | 语义选择器优先(id/name/text/aria);**F12 确认后再写,严禁凭记忆猜 DOM** | | **选择器纪律** | 语义选择器优先(id/name/text/aria);**F12 确认后再写,严禁凭记忆猜 DOM** |
@@ -25,6 +29,14 @@
> 三端各自实现一个会话抽象 `RpaSession`(launch / login / act / screenshot / close),上层 skill 不感知是浏览器还是手机。 > 三端各自实现一个会话抽象 `RpaSession`(launch / login / act / screenshot / close),上层 skill 不感知是浏览器还是手机。
### 0.0 合规红线
- 只使用用户或企业合法拥有、明确授权的账号、数据、设备和业务权限。
- 优先正常界面或获得授权的官方 API;只有破解、逆向或绕过安全机制才能实现时,停止并上报。
- 禁止反编译、私有协议、抓包拼装隐藏接口、Hook / 注入、客户端篡改、验证码破解、设备指纹伪造、撞库、养号、自动换号或代理池规避限制。
- 验证码、人脸、指纹、短信、U盾、动态口令必须交给人工;权限不足、账号风险、频控或封禁必须安全停止。
- 合规与完整职责边界以 [`AI_RPA.md`](AI_RPA.md) 为准。
### 0.1 步骤控制与进度(SRCP,platform-kit >= 1.2.0) ### 0.1 步骤控制与进度(SRCP,platform-kit >= 1.2.0)
- **禁止** `scripts/util/progress.py` 或 `print({"type":"progress",...})`;进度只走 `emit` / Run Journal。 - **禁止** `scripts/util/progress.py` 或 `print({"type":"progress",...})`;进度只走 `emit` / Run Journal。
@@ -72,6 +84,40 @@ async def open_login(page):
--- ---
### 0.3 工业级风控、等待与收尾
**状态等待优先:**页面加载、控件可用、弹窗消失、保存成功、下载完成和业务结果出现,必须等待真实条件并设置超时;禁止用固定 `sleep(3)` 假设成功。
**操作节奏:**
- 两个正常业务动作之间默认随机等待 `1~3` 秒。
- 输入采用逐字符随机延迟;鼠标使用自然轨迹;滚动采用分段操作。
- 同一账号、Profile、桌面会话或手机设备默认串行。
- 单批数量、单位时间操作量和运行时长必须有上限。
- 只对明确可重试错误做有限重试;普通网络错误可递增退避,风险提示和权限错误不得自动重试。
**前后缓冲:**
- 启动浏览器、桌面软件或手机会话后,先等待目标页面 / 窗口 / 控件真实就绪,再额外缓冲约 `1.5~2.5` 秒。
- 页面导航后,关键控件就绪再缓冲约 `1~2` 秒。
- 流程结束时,先确认业务结果、写日志并完成存证,再缓冲约 `2~3` 秒关闭会话。
- 付款、审批、发布等重要动作确认结果并截图后,可缓冲约 `3~5` 秒。
缓冲用于稳定界面和改善用户体验,**不能作为成功判断**。RPA 主路径使用 `interruptible_sleep` 等可控制等待,确保暂停与停止能够生效。
**风险信号:**
| 信号 | 标准处理 |
|------|----------|
| 验证码 / 人脸 / 指纹 / U盾 | 进入人工处理 |
| 频率限制 | 停止当前批次或长时间退避 |
| 账号风险 / 封禁 / 安全警告 | 立即停止,禁止换号继续 |
| 权限不足 | 明确失败,不尝试绕过 |
| 页面 / 控件结构变化 | 截图并停止,重新人工验证定位 |
| 提交结果不明确 | 查询业务状态,确认前禁止再次提交 |
---
## 1. 浏览器(标准已成熟) ## 1. 浏览器(标准已成熟)
**选型:Playwright + 系统 Chrome/Edge。** 这是团队验证最充分的一条线(标杆技能 `1688-scrape-contacts`、`receive-order` 已落地)。 **选型:Playwright + 系统 Chrome/Edge。** 这是团队验证最充分的一条线(标杆技能 `1688-scrape-contacts`、`receive-order` 已落地)。
@@ -85,12 +131,12 @@ async def open_login(page):
| CDP | **仅作诊断 / 桌面宿主类场景**;**不要**作为强风控站点的默认生产路径 | | CDP | **仅作诊断 / 桌面宿主类场景**;**不要**作为强风控站点的默认生产路径 |
| 行为 | 模拟真实用户:真实点击、键盘、鼠标、地址栏输入;**不要**拼接搜索结果 URL、DOM 注入、`el.value=`、JS 跳转 | | 行为 | 模拟真实用户:真实点击、键盘、鼠标、地址栏输入;**不要**拼接搜索结果 URL、DOM 注入、`el.value=`、JS 跳转 |
| 模式 | **有头** `OPENCLAW_BROWSER_HEADLESS=0`(生产强制,见 §0.2) | | 模式 | **有头** `OPENCLAW_BROWSER_HEADLESS=0`(生产强制,见 §0.2) |
| 反检测 | stealth 默认开 `OPENCLAW_PLAYWRIGHT_STEALTH=1`(见 1.1) | | 浏览器兼容配置 | `OPENCLAW_PLAYWRIGHT_STEALTH` 仅用于经评估的兼容配置;不得用于伪造身份或绕过平台限制 |
### 1.1 Playwright 启动标准 ### 1.1 Playwright 启动标准
1. **有头**:`OPENCLAW_BROWSER_HEADLESS=0`(`.env.example` 默认;网页 RPA 生产路径禁止改成无头常态,见 §0.2)。 1. **有头**:`OPENCLAW_BROWSER_HEADLESS=0`(`.env.example` 默认;网页 RPA 生产路径禁止改成无头常态,见 §0.2)。
2. **stealth 默认开**:`OPENCLAW_PLAYWRIGHT_STEALTH=1`;通过 `add_init_script` 注入指纹淡化脚本。 2. **stealth 须受控**:`OPENCLAW_PLAYWRIGHT_STEALTH` 仅在目标平台授权、规则与项目评估允许时启用;不得把它理解为规避风控或伪造设备身份。
3. **不要在技能里自行安装 playwright**;由宿主共享 runtime 提供。 3. **不要在技能里自行安装 playwright**;由宿主共享 runtime 提供。
4. **不要默认传 `--no-sandbox`**(除非特定容器环境且已评估风险)。 4. **不要默认传 `--no-sandbox`**(除非特定容器环境且已评估风险)。
5. **不要默认传 `--disable-blink-features=AutomationControlled`**;platform-kit stealth 已覆盖,额外 flag 可能适得其反。 5. **不要默认传 `--disable-blink-features=AutomationControlled`**;platform-kit stealth 已覆盖,额外 flag 可能适得其反。
@@ -98,7 +144,7 @@ async def open_login(page):
7. **强风控平台**:优先真实点击、键盘、鼠标、地址栏、account-manager 持久 profile;**不要**直接拼接搜索结果 URL 或 DOM 注入。 7. **强风控平台**:优先真实点击、键盘、鼠标、地址栏、account-manager 持久 profile;**不要**直接拼接搜索结果 URL 或 DOM 注入。
8. **先 Profile 再开浏览器**:`user_data_dir` 必须来自 ensure/pick 到的 `profile_dir`;未拿到则不得进入本节后续步骤。 8. **先 Profile 再开浏览器**:`user_data_dir` 必须来自 ensure/pick 到的 `profile_dir`;未拿到则不得进入本节后续步骤。
指纹淡化(stealth)典型项:`navigator.webdriver=undefined`、`chrome.runtime`、`permissions.query`、`plugins`、`languages` 等。共享实现见 `jiangchang_skill_core.rpa`(platform-kit **>= 1.2.0**)。 浏览器兼容配置由共享 `jiangchang_skill_core.rpa` 提供(platform-kit **>= 1.2.0**)。业务技能不得自行扩展指纹伪造、代理轮换或规避安全检测的代码;遇到明确风控信号时转人工或停止。
**拟人操作**(必做): **拟人操作**(必做):
@@ -106,7 +152,7 @@ async def open_login(page):
- 鼠标:贝塞尔曲线轨迹 + 微抖动;进场随机晃动。 - 鼠标:贝塞尔曲线轨迹 + 微抖动;进场随机晃动。
- 导航:用真实点击触发,**不要 `window.location.href=` / JS 点击跳转**。 - 导航:用真实点击触发,**不要 `window.location.href=` / JS 点击跳转**。
- 翻页:真实点击翻页控件,注意排除禁用态。 - 翻页:真实点击翻页控件,注意排除禁用态。
- 延迟:每步之间 `random_delay`(`.env` 中 `STEP_DELAY_MIN/MAX`)。 - 延迟:两个正常业务动作之间 `random_delay`(`.env` 中 `STEP_DELAY_MIN/MAX`,默认 1~3 秒);页面状态仍须显式等待。
### 1.2 页面启动标准 ### 1.2 页面启动标准
@@ -241,6 +287,7 @@ from jiangchang_skill_core.rpa.stealth import stealth_enabled, STEALTH_INIT_SCRI
- **DPI/缩放**:图像识别方案必须固定显示缩放比例;UIA 方案不受影响(优先用 UIA 即是为此)。 - **DPI/缩放**:图像识别方案必须固定显示缩放比例;UIA 方案不受影响(优先用 UIA 即是为此)。
- **存证**:同样要失败截图(截目标窗口/全屏),存到 `rpa-artifacts`。 - **存证**:同样要失败截图(截目标窗口/全屏),存到 `rpa-artifacts`。
- **人工兜底**:U盾插拔、动态口令、人脸 → 停下等人工,超时 `ERROR:XXX_NEED_HUMAN`。 - **人工兜底**:U盾插拔、动态口令、人脸 → 停下等人工,超时 `ERROR:XXX_NEED_HUMAN`。
- **禁止侵入**:不注入或 Hook 第三方进程,不修改客户端文件,不反编译或调用未授权私有协议。
```bash ```bash
pip install pywinauto # UIA 自动化 pip install pywinauto # UIA 自动化
@@ -269,6 +316,7 @@ pip install pywinauto # UIA 自动化
- **登录态**:靠 App 自身保持登录,必要时引导人工首登一次。 - **登录态**:靠 App 自身保持登录,必要时引导人工首登一次。
- **人工兜底**:短信验证码、人脸、指纹 → scrcpy 投屏让人工完成,程序轮询等待。 - **人工兜底**:短信验证码、人脸、指纹 → scrcpy 投屏让人工完成,程序轮询等待。
- **存证**:失败时 `adb screencap` / Appium 截图存 `rpa-artifacts`。 - **存证**:失败时 `adb screencap` / Appium 截图存 `rpa-artifacts`。
- **设备边界**:使用正常授权设备与官方 App;不 Root / 越狱,不 Hook,不修改 APK / IPA,不伪造设备身份或绕过签名、绑定与安全校验。
```bash ```bash
# Android(首选) # Android(首选)

View File

@@ -6,6 +6,8 @@
技能根目录 `requirements.txt` **只声明技能特有依赖**;**不要**重复声明 `jiangchang-platform-kit` 或 `playwright`。`SKILL.md` 的 `platform_kit_min_version` 是运行契约,**不是** pip 依赖声明。 技能根目录 `requirements.txt` **只声明技能特有依赖**;**不要**重复声明 `jiangchang-platform-kit` 或 `playwright`。`SKILL.md` 的 `platform_kit_min_version` 是运行契约,**不是** pip 依赖声明。
kit **源码仓**(可 clone 学习,勿 vendor)与其它公开公共仓登记见 [`SHARED_REPOS.md`](SHARED_REPOS.md)。
### 何时上调 `platform_kit_min_version` ### 何时上调 `platform_kit_min_version`
| 情况 | 做法 | | 情况 | 做法 |

128
development/SHARED_REPOS.md Normal file
View File

@@ -0,0 +1,128 @@
# 公共仓库目录(可扩展)
本页是技能开发用到的**公开公共仓唯一登记处**,面向技术人员与 AI 编程代理。
- 仓均在公司**自建 Gitea**:[https://git.jc2009.com/](https://git.jc2009.com/)(基于开源 Gitea 自建,**不是** Gitea 官网)。
- 技术人员一般**可直接访问、随时 `git clone` 到本地**,用于研究、学习、对照与跟进更新。
- **当前登记 3 项**;以后新增公开公共仓时,**只在本页按类型加行**,不必改散落长文。
深度规范仍在 [`RPA.md`](RPA.md)、[`RUNTIME.md`](RUNTIME.md)、[`ADAPTER.md`](ADAPTER.md)、[`DEVELOPMENT.md`](DEVELOPMENT.md);本页只做**指路 + 边界**。
---
## 1. 类型(可扩展)
| 类型 id | 含义 | 典型消费方式 |
|---------|------|--------------|
| `skill-template` | 业务技能作者脚手架与规范源 | clone 学习;`scaffold` / 复制出新业务仓;**不要**在模板仓写业务 |
| `sibling-skill` | 与业务技能并列安装的公开基础设施技能 | clone 学契约;运行时经 **CLI / 封装客户端** 调用 |
| `python-sdk` | 共享 Python 库(源码仓 + 宿主共享 venv 安装) | clone 读实现 / 贡献;运行时 **`import`**,**禁止 vendor** 进技能仓 |
| `asset-bundle` | (预留)共享媒体/资源包等 | 按该仓说明拉取或由 kit/宿主解析 |
| `tooling` | (预留)发布脚本、脚手架、CI 辅助等 | clone 使用或引用其 workflow |
新增类型时:先在本表加一行类型说明,再在 §2 登记表增加实例。
---
## 2. 当前登记表
| 短名 | 类型 | Gitea(唯一入口) | 一句话职责 |
|------|------|-------------------|------------|
| **skill-template** | `skill-template` | [https://git.jc2009.com/client-commons/skill-template](https://git.jc2009.com/client-commons/skill-template) | 新业务技能的开发模板、目录规范与发布约定 |
| **account-manager** | `sibling-skill` | [https://git.jc2009.com/client-commons/account-manager](https://git.jc2009.com/client-commons/account-manager) | 账号 / 凭据 / 浏览器 Profile / 租约的统一入口 |
| **jiangchang-platform-kit** | `python-sdk` | [https://git.jc2009.com/client-jiangchang/jiangchang-platform-kit](https://git.jc2009.com/client-jiangchang/jiangchang-platform-kit) | 共享 SDK(`jiangchang_skill_core` 等);技能发布可复用 CI 也在此仓 |
本地常见路径(仅作对照,以你机器为准):
- `D:\OpenClaw\client-commons\skill-template`
- `D:\OpenClaw\client-commons\account-manager`
- `D:\OpenClaw\client-jiangchang\jiangchang-platform-kit`
### 2.1 skill-template
| 项 | 说明 |
|----|------|
| **Clone 为了什么** | 读 `development/`、跟模板版本、用 `tools/scaffold_skill` 开新技能 |
| **怎么用** | 来源 B:scaffold;或学完后在业务仓开发。规范以本仓为准 |
| **红线** | 不要在模板仓写业务;业务仓 `origin` 不得指向本仓;不得保留 `.openclaw-skill-template` |
| **深入** | 本目录 [`README.md`](README.md)、[`DEVELOPMENT.md`](DEVELOPMENT.md) |
```powershell
git clone https://git.jc2009.com/client-commons/skill-template.git
```
### 2.2 account-manager
| 项 | 说明 |
|----|------|
| **Clone 为了什么** | 读 CLI / `references/INTEGRATION.md`、平台表、租约与错误码;排 `NO_ACCOUNT` / `LEASE_CONFLICT` 等 |
| **怎么用(业务技能)** | 经 `scripts/service/account_client.py`(或等价)**subprocess 调 CLI**;网页 RPA 须先拿到 `profile_dir`(`ensure-web` / `pick-web`) |
| **红线** | **禁止**业务技能 `import` 其内部 `rpa_helpers` / 散落存密码(见 `POLICY-RPA-001`);对方文档若写「同进程 rpa_helpers」,**以本模板约束为准** |
| **深入** | 对方仓 `references/INTEGRATION.md`、`CLI.md`;本模板 [`RPA.md`](RPA.md) §0.2、[`ADAPTER.md`](ADAPTER.md) |
```powershell
git clone https://git.jc2009.com/client-commons/account-manager.git
```
### 2.3 jiangchang-platform-kit
| 项 | 说明 |
|----|------|
| **Clone 为了什么** | 读 `jiangchang_skill_core`(config / logging / activity·SRCP / rpa / sibling_bridge 等)、跟版本、贡献共享 API |
| **怎么用(业务技能)** | 运行时由**宿主共享 venv** 提供;技能内 `import jiangchang_skill_core...`。`SKILL.md` 的 `platform_kit_min_version` 是兼容声明 |
| **红线** | **不要**把 `jiangchang-platform-kit` / `playwright` 写入技能 `requirements.txt`;**不要**在技能仓 vendor `jiangchang_skill_core/`(`POLICY-RUNTIME-002`) |
| **深入** | 对方仓 `README.md`;本模板 [`RUNTIME.md`](RUNTIME.md)、[`LOGGING.md`](LOGGING.md) |
```powershell
git clone https://git.jc2009.com/client-jiangchang/jiangchang-platform-kit.git
```
私有 PyPI 索引(维护/排障用,日常技能开发通常不必手装):
`https://git.jc2009.com/api/packages/client-jiangchang/pypi/simple/`
---
## 3. 三者关系(别当成三个无关收藏夹)
```text
规范 / 脚手架 ──────────► skill-template(本仓)
│
业务技能 scripts/ ──import──► 宿主共享 venv 中的 platform-kit
│
└──CLI──► account-manager(兄弟技能,要先拿到 profile_dir 等)
```
- **写规范、开新仓** → 打开 **skill-template**
- **少写公共 Python、进度/RPA 原语** → 用 **kit**(运行靠宿主;源码可 clone)
- **账号与浏览器 Profile** → 用 **account-manager**(运行靠 CLI;源码可 clone)
---
## 4. 何时该打开哪个仓
| 场景 | 优先打开 |
|------|----------|
| 不知道新技能目录/发布/developer_ids 怎么做 | **skill-template** `development/` |
| 定 `platform_key`、ensure-web、租约、凭证存储 | **account-manager** + 本模板 RPA/ADAPTER |
| 看 `emit` / `finish` / `@rpa_step` / `launch_persistent_browser` 实现 | **jiangchang-platform-kit** |
| 技能发布 CI / reusable workflow 从哪来 | **jiangchang-platform-kit** `.github/workflows/` |
| 「公共东西到底在哪」 | **本页登记表** |
---
## 5. 以后如何新增一条公共仓(维护约定)
1. 确认公开可访问,URL 使用 `https://git.jc2009.com/...`(勿写 Gitea 官网)。
2. 选定或新增 §1 **类型**。
3. 在 §2 **登记表**加一行;必要时增加 `§2.x` 短节(消费方式 + 红线 + clone 示例)。
4. 若改变业务技能硬约束,同步 [`POLICY_MATRIX.md`](POLICY_MATRIX.md) / 相关深度文档。
5. **不要**只在某个业务技能 README 里私藏链接而不登记本页。
---
## 6. 相关链接
- 开发入口:[`README.md`](README.md)
- 运行时:[`RUNTIME.md`](RUNTIME.md)
- 网页 RPA / 账号:[`RPA.md`](RPA.md)、[`ADAPTER.md`](ADAPTER.md)
- 脚手架:[`../tools/README.md`](../tools/README.md)

View File

@@ -52,7 +52,7 @@
| `health` / `version` / `config-path` / 纯统计 / 秒级查询 | `sync` | | `health` / `version` / `config-path` / 纯统计 / 秒级查询 | `sync` |
| 任意 placement(含 toolbar) | 允许 sync 或 async;以 manifest 为准 | | 任意 placement(含 toolbar) | 允许 sync 或 async;以 manifest 为准 |
合法:`sync|async` × `toolbar|cron|agent|skill-detail`。 合法:`sync|async` × `toolbar|row|batch|cron|agent|skill-detail`。
历史说明:旧文档曾错误地把数据管理按钮入口与异步执行方式绑死。该约束**已废止**;模板测试与 Schema **不得**再建立「入口位置决定 sync/async」一类硬耦合。旧版宿主曾「省略 → async」;**当前宿主为「省略 → sync」**。新技能仍须显式声明,不得依赖省略行为。 历史说明:旧文档曾错误地把数据管理按钮入口与异步执行方式绑死。该约束**已废止**;模板测试与 Schema **不得**再建立「入口位置决定 sync/async」一类硬耦合。旧版宿主曾「省略 → async」;**当前宿主为「省略 → sync」**。新技能仍须显式声明,不得依赖省略行为。
@@ -62,14 +62,18 @@
多个入口统一走 `POST /api/skill-actions/run`,可能带 `source.kind`: 多个入口统一走 `POST /api/skill-actions/run`,可能带 `source.kind`:
| 入口 | 常见 `source.kind` | 说明 | | 入口(匠厂侧栏 / 界面) | 常见 `source.kind` | 技能侧 | 开发者怎么测 |
|------|-------------------|------| |-------------------------|-------------------|--------|--------------|
| **Agent** | `agent` | `run_skill_action`;按 manifest 的 executionProfile 执行 | | **新建任务**(对话 Agent) | `agent` | `placements` 含 `agent`;`run_skill_action` | 侧栏「新建任务」→ 对话触发 |
| **数据管理** | `data-management` | toolbar 按钮;须 `bind.tables` | | **数据管理 · 顶栏** | `data-management` | `toolbar` + 必填 `bind.tables` | 侧栏「数据管理」→ 表顶栏按钮 |
| **定时任务** | `cron` | Cron 配置参数后调用同一 Action | | **数据管理 · 行内** | `data-management` | `row`(建议 `bind.tables` + `inputMapping`) | 同行操作链接(需主键) |
| **技能详情** | (依宿主) | 与上同一 CLI / 同一业务内核 | | **数据管理 · 批量** | `data-management` | `batch` | 勾选行后点批量按钮 |
| **定时任务** | `cron` | `placements` 含 `cron` | 侧栏「定时任务」→「技能直调」 |
| **任务中心** | (各入口触发的 Job) | `executionProfile: "async"` | 侧栏「任务中心」查看进度 / 取消;**不是** placement |
| **技能详情** | `skill-detail` | `placements` 含 `skill-detail` | 市场详情安装/四 Tab;详情直调按钮随宿主上线后**同等自测** |
技能 **不要** 在 Python 里按 `source` / placement 写业务分叉;宿主读 manifest 分流展示与等待策略。 技能 **不要** 在 Python 里按 `source` / placement 写业务分叉;宿主读 manifest 分流展示与等待策略。
**已声明的入口都要自测**,不要只测对话。操作清单见 [`DEVELOPMENT.md`](DEVELOPMENT.md) §15 第七步。
--- ---
@@ -81,7 +85,8 @@
|-------------|-------------------------|-----------------|----------------| |-------------|-------------------------|-----------------|----------------|
| 运行检查 / 版本 / 配置路径 | `sync` | `skill-detail`, `agent` | 无 | | 运行检查 / 版本 / 配置路径 | `sync` | `skill-detail`, `agent` | 无 |
| 库 / 队列统计 | `sync` | `skill-detail`, `agent` | 无 | | 库 / 队列统计 | `sync` | `skill-detail`, `agent` | 无 |
| 外源 → 本地库同步 | `sync` 或 `async` | 可含 `toolbar`(须 `bind.tables`)、`cron`、`agent` | 可选 | | 外源 → 本地库同步 | `sync` 或 `async` | 可含 `toolbar`(须 `bind.tables`)、`cron`、`agent`、`skill-detail` | 可选 |
| 单行 / 批量数据管理动作 | `sync` 或 `async` | `row` / `batch`(建议 `bind.tables`;行内常用 `inputMapping`) | 可选 |
| 数据导入 / 失败重置 | `sync` 或 `async` | `skill-detail`, `agent` | 可选 | | 数据导入 / 失败重置 | `sync` 或 `async` | `skill-detail`, `agent` | 可选 |
| **单条**副作用 RPA | `async`(建议) | `agent`, `skill-detail` | **建议** | | **单条**副作用 RPA | `async`(建议) | `agent`, `skill-detail` | **建议** |
| **批量顺序** RPA(pick) | `async`(建议) | `toolbar`, `cron`, `agent` | **建议** | | **批量顺序** RPA(pick) | `async`(建议) | `toolbar`, `cron`, `agent` | **建议** |

View File

@@ -81,7 +81,7 @@ def test_whatever():
未设置环境变量 ⇒ 等价 `unit`。 未设置环境变量 ⇒ 等价 `unit`。
默认策略摘要:**不要在 unittest 必跑路径误设 `OPENCLAW_TEST_TARGET=real_*`**。 默认策略摘要:**不要在 unittest 必跑路径误设 `OPENCLAW_TEST_TARGET=real_*`**(CI 仍离线)。业务 `.env` 模板默认是 `real_rpa`,与「单测用 mock」不冲突;**mock 通 ≠ 交活**。
档位读取与业务代码一致:经 `jiangchang_skill_core.config.get("OPENCLAW_TEST_TARGET")`(见 `CONFIG.md`)。 档位读取与业务代码一致:经 `jiangchang_skill_core.config.get("OPENCLAW_TEST_TARGET")`(见 `CONFIG.md`)。

View File

@@ -4,6 +4,8 @@
**`examples/` 不是完整 skill 仓库。** 不要整包照搬 `examples/<mode>/` 到新技能根目录。应按各 example README 的 **copy map**,**选择性复制**到新技能的 `scripts/`(及按需的 `tests/`)。 **`examples/` 不是完整 skill 仓库。** 不要整包照搬 `examples/<mode>/` 到新技能根目录。应按各 example README 的 **copy map**,**选择性复制**到新技能的 `scripts/`(及按需的 `tests/`)。
复制任何案例前先读 [`../development/AI_RPA.md`](../development/AI_RPA.md):案例只示范授权范围内的正常界面自动化,禁止把它扩展为破解、逆向、私有协议、验证码绕过、Hook / 注入、自动换号或规避平台限制的实现。
根 `README.md`、`SKILL.md`、`references/`、`development/` 仍按模板主目录规则编写,**不要**从 `examples/` 复制。 根 `README.md`、`SKILL.md`、`references/`、`development/` 仍按模板主目录规则编写,**不要**从 `examples/` 复制。
## 四类外部交互方式 ## 四类外部交互方式

View File

@@ -7,6 +7,7 @@
- 本示例是通用模板,不绑定具体平台。 - 本示例是通用模板,不绑定具体平台。
- 示例抽象自已跑通的真实浏览器 RPA skill(抖音视频链接采集),但代码已改成中性示例命名。 - 示例抽象自已跑通的真实浏览器 RPA skill(抖音视频链接采集),但代码已改成中性示例命名。
- 新 skill 开发时可以复制本目录,再替换目标站点、选择器、解析逻辑和业务字段。 - 新 skill 开发时可以复制本目录,再替换目标站点、选择器、解析逻辑和业务字段。
- 只用于授权范围内的正常界面操作;禁止破解、逆向、私有协议、验证码绕过、自动换号或其他规避平台限制的扩展。
## 适用场景 ## 适用场景
@@ -142,6 +143,7 @@ real_browser_rpa/
- **不 import account-manager 内部模块** — 只通过 CLI/subprocess 调用 - **不 import account-manager 内部模块** — 只通过 CLI/subprocess 调用
- **不自动破解验证码** — 滑块/短信只检测 + 等待人工完成 - **不自动破解验证码** — 滑块/短信只检测 + 等待人工完成
- **不对抗平台风控** — 频控、账号风险、封禁或权限不足时停止并交由人工处理
- **日志脱敏** — 不输出完整手机号/账号 - **日志脱敏** — 不输出完整手机号/账号
- **租约释放** — `ensure-web` / `pick-web --lease` 后必须在 `finally` 释放 - **租约释放** — `ensure-web` / `pick-web --lease` 后必须在 `finally` 释放
- **失败留痕** — 真实 skill 应在关键失败点截图(示例中已留注释位) - **失败留痕** — 真实 skill 应在关键失败点截图(示例中已留注释位)

View File

@@ -10,6 +10,7 @@ import time
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, Optional, Tuple from typing import Any, Callable, Dict, List, Optional, Tuple
from jiangchang_skill_core import config
from jiangchang_skill_core.activity import interruptible_sleep from jiangchang_skill_core.activity import interruptible_sleep
from service.browser_session import close_browser_context, get_start_url, start_browser_session from service.browser_session import close_browser_context, get_start_url, start_browser_session
@@ -101,9 +102,9 @@ def _step_cb(cb: Optional[StepCallback], text: str) -> None:
async def _random_delay() -> None: async def _random_delay() -> None:
lo = int(os.getenv("RPA_STEP_DELAY_MIN_MS") or "900") lo = max(0.0, config.get_float("STEP_DELAY_MIN", 1.0))
hi = int(os.getenv("RPA_STEP_DELAY_MAX_MS") or "2600") hi = max(lo, config.get_float("STEP_DELAY_MAX", 3.0))
await interruptible_sleep(random.uniform(lo / 1000.0, hi / 1000.0)) await interruptible_sleep(random.uniform(lo, hi))
async def _scroll_wait() -> None: async def _scroll_wait() -> None:

View File

@@ -4,6 +4,8 @@
本示例抽象自已跑通的「工行批量提交类」浏览器自动化 skill 的工程范式,但已**去业务化**——不包含真实银行/真实资金语义,也**不是** Amazon 或任何生产技能的复制。 本示例抽象自已跑通的「工行批量提交类」浏览器自动化 skill 的工程范式,但已**去业务化**——不包含真实银行/真实资金语义,也**不是** Amazon 或任何生产技能的复制。
本示例只教学授权范围内的正常界面自动化;禁止把 sandbox 做法扩展为破解、逆向、私有协议、验证码绕过、Hook / 注入、自动换号或规避真实平台限制的实现。
## 适合什么场景 ## 适合什么场景
- 自有 **行业仿真系统** / `sandbox.jc2009.com` / 本地 `sandbox/demo_app.html` - 自有 **行业仿真系统** / `sandbox.jc2009.com` / 本地 `sandbox/demo_app.html`

View File

@@ -80,7 +80,7 @@ Action 是**可选能力**:
| 字段 / 层 | 只决定什么 | 不决定什么 | | 字段 / 层 | 只决定什么 | 不决定什么 |
|-----------|------------|------------| |-----------|------------|------------|
| **`placements`** | Action **出现在哪里**(toolbar / cron / agent / skill-detail …) | 不决定 sync/async | | **`placements`** | Action **出现在哪里**(toolbar / row / batch / cron / agent / skill-detail) | 不决定 sync/async |
| **`bind.tables`** | 数据管理里出现在**哪些业务表** | 不决定业务实现 | | **`bind.tables`** | 数据管理里出现在**哪些业务表** | 不决定业务实现 |
| **`executionProfile`** | 宿主是**同步等待**还是**异步 Job** | 不限制可展示入口 | | **`executionProfile`** | 宿主是**同步等待**还是**异步 Job** | 不限制可展示入口 |
| **`entrypoint`** | 实际执行哪个 CLI 命令与参数 | 不写业务逻辑 | | **`entrypoint`** | 实际执行哪个 CLI 命令与参数 | 不写业务逻辑 |
@@ -95,9 +95,9 @@ Action 是**可选能力**:
| 顶层 | `schemaVersion`、`skill`、`actions` | | 顶层 | `schemaVersion`、`skill`、`actions` |
| action | `id`、`label`、`description`、`placements`、`entrypoint`、**`executionProfile`(必填)**;可选 `inputSchema`、`confirmation`、**`bind`** | | action | `id`、`label`、`description`、`placements`、`entrypoint`、**`executionProfile`(必填)**;可选 `inputSchema`、`confirmation`、**`bind`** |
| entrypoint | `type = cli`、`command`、`args`(**必填** JSON 数组,项为 `string` / `number` / `boolean`) | | entrypoint | `type = cli`、`command`、`args`(**必填** JSON 数组,项为 `string` / `number` / `boolean`) |
| placements | `toolbar`、`skill-detail`、`agent`、`cron` | | placements | `toolbar`、`row`、`batch`、`skill-detail`、`agent`、`cron` |
| **bind** | `{ "tables": ["business_table"] }`(见下节) | | **bind** | `{ "tables": ["business_table"] }`;可选 `inputMapping`(行内/批量预填,见下节) |
| inputSchema | 根 `type: object`;properties 使用 `string` / `number` / `boolean`;支持 `enum`、`default`、`required`、`sensitive` | | inputSchema | 根 `type: object`;properties 使用 `string` / `number` / `boolean`;支持 `enum`、`default`、`required`、`sensitive`、`readOnly` |
| confirmation | `{ "message": "..." }` | | confirmation | `{ "message": "..." }` |
| **executionProfile** | `"sync"` \| `"async"`(**必须显式写出**,禁止依赖缺省) | | **executionProfile** | `"sync"` \| `"async"`(**必须显式写出**,禁止依赖缺省) |
@@ -113,14 +113,16 @@ Action 是**可选能力**:
规则: 规则:
- `bind` 为 object,`additionalProperties: false`;当前只允许 `tables`。 - `bind` 为 object,`additionalProperties: false`;当前允许 `tables`(必填键当存在 bind 时)与可选 `inputMapping`。
- `tables` 非空数组、元素唯一、英文 **snake_case**、不得为空字符串。 - `tables` 非空数组、元素唯一、英文 **snake_case**、不得为空字符串。
- **`placements` 含 `toolbar` 时必须显式声明非空 `bind.tables`**(模板 Schema `if/then` + 自动测试强制)。 - **`placements` 含 `toolbar` 时必须显式声明非空 `bind.tables`**(模板 Schema `if/then` + 自动测试强制)。
- `row` / `batch` **建议**同样声明 `bind.tables`,避免在无关表上露出按钮;未声明时宿主可能按兼容逻辑在更多表上展示。
- 表名须真实存在于技能 SQLite 与 `_jiangchang_tables`。 - 表名须真实存在于技能 SQLite 与 `_jiangchang_tables`。
- 希望出现在多张表时,显式列出所有表;**不要**依赖「无 bind 则全表展示」——那是宿主对**旧技能**的兼容,不是新技能标准。 - 希望出现在多张表时,显式列出所有表;**不要**依赖「无 bind 则全表展示」——那是宿主对**旧技能**的兼容,不是新技能标准。
- 本阶段**不**扩展 `selection` / `inputMapping` / `columns` / row binding / concurrency / locks。 - **`inputMapping`(可选)**:把行/勾选映射到 `inputSchema` 字段,例如 `"leadId": "$row.$pk"`、`"ids": "$selection.ids"`。适合 `row` / `batch`。宿主仍会提交这些字段;可用 `inputSchema.properties.*.readOnly: true` 在表单中只读展示。
- `concurrency` / `locks` 仍未稳定,**不要**写入新技能 manifest。
默认模板 `actions.json` 仅含 `health` / `version` / `config-path`,不放在 toolbar,故无需 `bind` 示例污染默认 manifest。业务示例: 默认模板 `actions.json` 仅含 `health` / `version` / `config-path`,不放在 toolbar/row/batch,故无需 `bind` 示例污染默认 manifest。业务示例:
```json ```json
{ {
@@ -134,16 +136,42 @@ Action 是**可选能力**:
} }
``` ```
行内示例:
```json
{
"id": "retry-one",
"label": "重试本行",
"description": "对当前行执行一次业务重试。",
"placements": ["row"],
"executionProfile": "async",
"bind": {
"tables": ["business_records"],
"inputMapping": { "recordId": "$row.$pk" }
},
"inputSchema": {
"type": "object",
"required": ["recordId"],
"properties": {
"recordId": { "type": "string", "title": "记录 ID", "readOnly": true }
}
},
"entrypoint": {
"type": "cli",
"command": "retry",
"args": ["--id", "{{recordId}}"]
}
}
```
## 预留能力(当前不可当作已实现能力) ## 预留能力(当前不可当作已实现能力)
| 类别 | 预留项 | 说明 | | 类别 | 预留项 | 说明 |
|------|--------|------| |------|--------|------|
| placements | `row`、`batch` | 行内 / 批量入口,未来扩展;新技能示例不得使用 |
| action 字段 | `concurrency`、`locks` | 并发与锁控制,未稳定开放 | | action 字段 | `concurrency`、`locks` | 并发与锁控制,未稳定开放 |
| inputSchema | `array`、nested `object`、`oneOf` 等 | 复杂表单,不属于当前推荐范围 | | inputSchema | `array`、nested `object`、`oneOf` 等 | 复杂表单,不属于当前推荐范围 |
`bind` **不是**保留字段;已作为 Phase 1 表级绑定正式能力。 `bind`、`row`、`batch` **不是**保留能力;已按匠厂宿主正式支持写入本规范。
## 执行模型 ## 执行模型
宿主将 action 转为 argv,再用**共享 Python**(用户数据目录下 `python-runtime/.venv`)执行: 宿主将 action 转为 argv,再用**共享 Python**(用户数据目录下 `python-runtime/.venv`)执行:
@@ -168,7 +196,7 @@ python {skill_root}/scripts/main.py <command> <args...>
| `sync`(或省略时的宿主缺省) | 调用方等待结束,直接返回结构化结果或结构化错误;**不**创建后台 Job | 不进 | | `sync`(或省略时的宿主缺省) | 调用方等待结束,直接返回结构化结果或结构化错误;**不**创建后台 Job | 不进 |
| `async`(须显式声明) | 宿主创建后台 Job,立即返回 `jobId`;用 `emit` / `checkpoint` / `finish` 报告进度与终态 | **进入** | | `async`(须显式声明) | 宿主创建后台 Job,立即返回 `jobId`;用 `emit` / `checkpoint` / `finish` 报告进度与终态 | **进入** |
合法组合(全部允许):`sync|async` × `toolbar|cron|agent|skill-detail`。 合法组合(全部允许):`sync|async` × `toolbar|row|batch|cron|agent|skill-detail`。
经验建议(**不是** placement 硬限制):耗时不可预测、需要暂停/停止/进度展示的任务,用 `async`;其余默认写 `sync`。 经验建议(**不是** placement 硬限制):耗时不可预测、需要暂停/停止/进度展示的任务,用 `async`;其余默认写 `sync`。
@@ -199,26 +227,27 @@ HINT: <next step>
| 值 | 含义 | | 值 | 含义 |
|----|------| |----|------|
| `toolbar` | 数据管理第一排技能按钮(须配合 `bind.tables`) | | `toolbar` | 数据管理表顶栏技能按钮(须配合 `bind.tables`) |
| `skill-detail` | 技能详情或技能市场详情页 | | `row` | 数据管理行内操作(建议 `bind.tables` + `inputMapping`;表需有主键) |
| `batch` | 数据管理批量操作(需勾选行;无勾选时宿主禁用按钮) |
| `skill-detail` | 技能详情页直调(与安装/四 Tab 同属技能市场详情;已声明则须自测) |
| `agent` | Agent 可直接调用(`run_skill_action`) | | `agent` | Agent 可直接调用(`run_skill_action`) |
| `cron` | 定时任务可直接调用 | | `cron` | 定时任务「技能直调」 |
**预留(模板示例请勿使用):** `row`、`batch`。
### Action 类型 × placements(常见示例,不是限制) ### Action 类型 × placements(常见示例,不是限制)
下表只表示**常见用法示例**。实际 `placements` 以 manifest 配置为准;**`sync` / `async` 不影响展示入口**。 下表只表示**常见用法示例**。实际 `placements` 以 manifest 配置为准;**`sync` / `async` 不影响展示入口**。已声明的入口都要在宿主自测,不要只测其中一条。
| Action 类型 | 常见 executionProfile | 常见 placements | confirmation | | Action 类型 | 常见 executionProfile | 常见 placements | confirmation |
|-------------|----------------------|-----------------|--------------| |-------------|----------------------|-----------------|--------------|
| health / version / config-path | sync | skill-detail, agent | 无 | | health / version / config-path | sync | skill-detail, agent | 无 |
| 统计 / 只读查询 | sync | skill-detail, agent | 无 | | 统计 / 只读查询 | sync | skill-detail, agent | 无 |
| 数据同步(外源 → 本地库) | sync 或 async | toolbar + cron + agent + skill-detail(按需) | 可选 | | 数据同步(外源 → 本地库) | sync 或 async | toolbar + cron + agent + skill-detail(按需) | 可选 |
| 单行重试 / 行内处理 | sync 或 async | row(可加 agent) | 可选 |
| 批量处理勾选行 | sync 或 async | batch(可加 toolbar/cron) | 可选 |
| 导入 / 重置 | sync 或 async | skill-detail, agent | 可选 | | 导入 / 重置 | sync 或 async | skill-detail, agent | 可选 |
| 单条副作用 RPA | async(建议) | agent, skill-detail | **建议** | | 单条副作用 RPA | async(建议) | agent, skill-detail | **建议** |
| 批量顺序 pick RPA | async(建议) | toolbar, cron, agent | **建议** | | 批量顺序 pick RPA | async(建议) | toolbar, cron, agent | **建议** |
## 同步数据 vs 导出当前表 vs 特殊业务报告 ## 同步数据 vs 导出当前表 vs 特殊业务报告
不要混用「导出」一词: 不要混用「导出」一词:
@@ -236,7 +265,7 @@ HINT: <next step>
当前宿主稳定支持: 当前宿主稳定支持:
- `object` / `string` / `number` / `boolean` - `object` / `string` / `number` / `boolean`
- `enum` / `default` / `required` / `sensitive` - `enum` / `default` / `required` / `sensitive` / `readOnly`
- 简单模板替换(`{{fieldName}}`) - 简单模板替换(`{{fieldName}}`)
示例: 示例:
@@ -281,6 +310,8 @@ HINT: <next step>
- `enum` 在宿主中渲染为选择框 - `enum` 在宿主中渲染为选择框
- `required` 字段在提交前校验 - `required` 字段在提交前校验
- `sensitive` 字段不得出现在低信任入口 - `sensitive` 字段不得出现在低信任入口
- `readOnly: true` 时数据管理表单只读展示该字段(仍随提交传入);适合行内/勾选预填的主键、编号列表
- `placements` 含 `batch` 的动作在数据管理表顶常驻,无勾选时禁用(与表删除一致)
- 需要确认的副作用操作使用 `confirmation.message` - 需要确认的副作用操作使用 `confirmation.message`
- 模板参数使用 `{{fieldName}}`,且必须在 `inputSchema.properties` 中声明 - 模板参数使用 `{{fieldName}}`,且必须在 `inputSchema.properties` 中声明
- `entrypoint.args` 项当前只允许 `string`、`number`、`boolean`;不允许对象或 `null` - `entrypoint.args` 项当前只允许 `string`、`number`、`boolean`;不允许对象或 `null`

View File

@@ -1,6 +1,6 @@
"""技能标识、版本与平台公共库约束(复制后请修改 slug/version/logger)。""" """技能标识、版本与平台公共库约束(复制后请修改 slug/version/logger)。"""
SKILL_SLUG = "your-skill-slug" SKILL_SLUG = "your-skill-slug"
SKILL_VERSION = "1.0.51" SKILL_VERSION = "1.0.57"
LOG_LOGGER_NAME = "openclaw.skill.your_skill_slug" LOG_LOGGER_NAME = "openclaw.skill.your_skill_slug"
PLATFORM_KIT_MIN_VERSION = "1.2.2" PLATFORM_KIT_MIN_VERSION = "1.2.2"

View File

@@ -15,7 +15,6 @@ from util.constants import SKILL_SLUG
_TEMPLATE_PLACEHOLDER_SLUG = "your-skill-slug" _TEMPLATE_PLACEHOLDER_SLUG = "your-skill-slug"
_ALLOWED_PLACEMENTS = frozenset({"toolbar", "row", "batch", "cron", "agent", "skill-detail"}) _ALLOWED_PLACEMENTS = frozenset({"toolbar", "row", "batch", "cron", "agent", "skill-detail"})
_RESERVED_PLACEMENTS = frozenset({"row", "batch"})
_RESERVED_ACTION_FIELDS = frozenset({"concurrency", "locks"}) _RESERVED_ACTION_FIELDS = frozenset({"concurrency", "locks"})
_ALLOWED_EXECUTION_PROFILES = frozenset({"sync", "async"}) _ALLOWED_EXECUTION_PROFILES = frozenset({"sync", "async"})
_REQUIRED_MANIFEST_KEYS = frozenset({"schemaVersion", "skill", "actions"}) _REQUIRED_MANIFEST_KEYS = frozenset({"schemaVersion", "skill", "actions"})
@@ -275,13 +274,13 @@ class TestActionsManifest(unittest.TestCase):
self.assertEqual(missing, [], msg="\n".join(missing)) self.assertEqual(missing, [], msg="\n".join(missing))
def test_schema_allows_all_placement_execution_profile_combinations(self) -> None: def test_schema_allows_all_placement_execution_profile_combinations(self) -> None:
"""POLICY-SKILL-ACTION-004:4 placements × 2 profiles 必须全部通过 Schema。""" """POLICY-SKILL-ACTION-004:6 placements × 2 profiles 必须全部通过 Schema。"""
try: try:
import jsonschema import jsonschema
except ImportError: except ImportError:
self.fail("jsonschema is required to validate placement×executionProfile orthogonality") self.fail("jsonschema is required to validate placement×executionProfile orthogonality")
schema = _load_actions_schema() schema = _load_actions_schema()
placements = ("toolbar", "cron", "agent", "skill-detail") placements = ("toolbar", "row", "batch", "cron", "agent", "skill-detail")
profiles = ("sync", "async") profiles = ("sync", "async")
for placement in placements: for placement in placements:
for profile in profiles: for profile in profiles:
@@ -346,16 +345,6 @@ class TestActionsManifest(unittest.TestCase):
for snippet in forbidden_snippets: for snippet in forbidden_snippets:
self.assertNotIn(snippet, text) self.assertNotIn(snippet, text)
def test_template_example_does_not_use_reserved_placements(self) -> None:
manifest = _load_actions_manifest()
for action in manifest["actions"]:
placements = set(action.get("placements") or [])
overlap = placements & _RESERVED_PLACEMENTS
self.assertFalse(
overlap,
msg=f"{action['id']} uses reserved placements not yet supported in template: {overlap}",
)
def test_template_variables_have_input_schema(self) -> None: def test_template_variables_have_input_schema(self) -> None:
manifest = _load_actions_manifest() manifest = _load_actions_manifest()
for action in manifest["actions"]: for action in manifest["actions"]:

View File

@@ -84,8 +84,8 @@ class TestConfigBootstrap(unittest.TestCase):
config.reset_cache() config.reset_cache()
with open(example, encoding="utf-8") as f: with open(example, encoding="utf-8") as f:
example_text = f.read() example_text = f.read()
self.assertIn(_env_line(_TEST_TARGET_KEY, "mock").strip(), example_text) self.assertIn(_env_line(_TEST_TARGET_KEY, "real_" + "rpa").strip(), example_text)
self.assertEqual(config.get(_TEST_TARGET_KEY), "mock") self.assertEqual(config.get(_TEST_TARGET_KEY), "real_" + "rpa")
def test_config_path_outputs_json(self) -> None: def test_config_path_outputs_json(self) -> None:
with IsolatedDataRoot(user_id="_cfg_path"): with IsolatedDataRoot(user_id="_cfg_path"):

View File

@@ -36,6 +36,7 @@ POLICY_IDS = (
"POLICY-RPA-002", "POLICY-RPA-002",
"POLICY-RPA-003", "POLICY-RPA-003",
"POLICY-RPA-004", "POLICY-RPA-004",
"POLICY-RPA-005",
"POLICY-PACKAGING-001", "POLICY-PACKAGING-001",
"POLICY-PACKAGING-002", "POLICY-PACKAGING-002",
"POLICY-DOCS-001", "POLICY-DOCS-001",
@@ -155,6 +156,25 @@ RPA_004_LAUNCH_MARKERS = (
) )
RPA_004_PICK_MARKER = "pick_web_account" RPA_004_PICK_MARKER = "pick_web_account"
RPA_005_SOURCE = (
"development/AI_RPA.md §4–§6; development/RPA.md §0.0/§0.3; "
"development/POLICY_MATRIX.md"
)
RPA_005_REQUIRED_DOC_MARKERS = (
"AI Agent 是用户入口与业务编排者",
"RPA 是确定性执行器",
"破解",
"逆向",
"私有协议",
"验证码",
"人工处理",
"1~3 秒",
"状态等待",
)
RPA_005_STEP_DELAY_KEY_RE = re.compile(
r"(?m)^\s*(STEP_DELAY_MIN|STEP_DELAY_MAX)\s*=\s*([^\s#]+)"
)
LOGGING_001_SOURCE = "development/LOGGING.md; development/RUNTIME.md" LOGGING_001_SOURCE = "development/LOGGING.md; development/RUNTIME.md"
LOGGING_002_SOURCE = "development/LOGGING.md; development/DEVELOPMENT.md" LOGGING_002_SOURCE = "development/LOGGING.md; development/DEVELOPMENT.md"
LOGGING_003_SOURCE = "development/LOGGING.md" LOGGING_003_SOURCE = "development/LOGGING.md"
@@ -669,6 +689,53 @@ class TestPolicyRpa004(unittest.TestCase):
) )
class TestPolicyRpa005(unittest.TestCase):
def test_ai_rpa_governance_doc_has_required_boundaries(self) -> None:
skill_root = get_skill_root()
path = os.path.join(skill_root, "development", "AI_RPA.md")
self.assertTrue(
os.path.isfile(path),
msg=_policy_msg("POLICY-RPA-005", RPA_005_SOURCE, "development/AI_RPA.md missing"),
)
text = _read_text(path)
missing = [marker for marker in RPA_005_REQUIRED_DOC_MARKERS if marker not in text]
self.assertEqual(
missing,
[],
msg=_policy_msg(
"POLICY-RPA-005",
RPA_005_SOURCE,
"AI_RPA.md missing markers: " + ", ".join(missing),
),
)
def test_real_rpa_default_step_delay_is_one_to_three_seconds(self) -> None:
skill_root = get_skill_root()
env_path = os.path.join(skill_root, ".env.example")
values = {
key: value.strip().strip("\"'")
for key, value in RPA_005_STEP_DELAY_KEY_RE.findall(_read_text(env_path))
}
self.assertEqual(
values.get("STEP_DELAY_MIN"),
"1.0",
msg=_policy_msg(
"POLICY-RPA-005",
RPA_005_SOURCE,
f"STEP_DELAY_MIN must default to 1.0, got {values.get('STEP_DELAY_MIN')!r}",
),
)
self.assertEqual(
values.get("STEP_DELAY_MAX"),
"3.0",
msg=_policy_msg(
"POLICY-RPA-005",
RPA_005_SOURCE,
f"STEP_DELAY_MAX must default to 3.0, got {values.get('STEP_DELAY_MAX')!r}",
),
)
def _scan_sensitive_logging_assignments(skill_root: str) -> list[str]: def _scan_sensitive_logging_assignments(skill_root: str) -> list[str]:
offenders: list[str] = [] offenders: list[str] = []
for path in _walk_files(skill_root, "scripts", suffix=".py"): for path in _walk_files(skill_root, "scripts", suffix=".py"):
@@ -1211,7 +1278,7 @@ class TestPolicySkillAction004(unittest.TestCase):
msg=_policy_msg( msg=_policy_msg(
"POLICY-SKILL-ACTION-004", "POLICY-SKILL-ACTION-004",
"tests/test_actions_manifest.py", "tests/test_actions_manifest.py",
"missing Schema 4×2 orthogonality matrix test", "missing Schema 6×2 orthogonality matrix test",
), ),
) )

View File

@@ -61,7 +61,7 @@ class TestEnvExampleVideoDefaults(unittest.TestCase):
with open(path, encoding="utf-8") as f: with open(path, encoding="utf-8") as f:
text = f.read() text = f.read()
for key in ( for key in (
"OPENCLAW_" + "TEST_TARGET=mock", "OPENCLAW_" + "TEST_TARGET=real_" + "rpa",
"OPENCLAW_RECORD_VIDEO=0", "OPENCLAW_RECORD_VIDEO=0",
"OPENCLAW_ARTIFACTS_ON_FAILURE=1", "OPENCLAW_ARTIFACTS_ON_FAILURE=1",
"OPENCLAW_BROWSER_HEADLESS=0", "OPENCLAW_BROWSER_HEADLESS=0",

View File

@@ -1,5 +1,15 @@
# skill-template 工具 # skill-template 工具
## 业务仓也可以直接 clone(来源 A)
若项目经理已在**公司自建 Gitea**([https://git.jc2009.com/](https://git.jc2009.com/),基于开源 Gitea 自建,**不是** Gitea 官网)开好业务技能仓库并授权,技术人员应直接:
```powershell
git clone https://git.jc2009.com/<org>/<your-skill-slug>.git
```
完整说明见 [`../development/DEVELOPMENT.md`](../development/DEVELOPMENT.md) §4「来源 A」。公开公共仓(含本模板、account-manager、platform-kit)登记见 [`../development/SHARED_REPOS.md`](../development/SHARED_REPOS.md)。下面脚手架用于**本地已有 skill-template、要新建尚未灌仓目录**的场景(来源 B)。
## 推荐:脚手架创建新技能 ## 推荐:脚手架创建新技能
**不要**用资源管理器整文件夹复制 `skill-template`(会带走隐藏 `.git`,导致 push 串库)。 **不要**用资源管理器整文件夹复制 `skill-template`(会带走隐藏 `.git`,导致 push 串库)。