Compare commits

...

3 Commits

Author SHA1 Message Date
de127d7e71 docs: codify free PyArmor Trial packaging guidance
All checks were successful
技能自动化发布 / release (push) Successful in 14s
2026-10-13 15:55:44 +08:00
1e2f94dd10 docs: Excel import template dropdowns from column metadata
All checks were successful
技能自动化发布 / release (push) Successful in 24s
2026-10-12 21:09:49 +08:00
72817f6cdd Release v1.0.123: document cron empty-selection branch for selectionMode optional
All checks were successful
技能自动化发布 / release (push) Successful in 6s
2026-10-07 14:33:01 +08:00
14 changed files with 71 additions and 18 deletions

View File

@@ -9,6 +9,22 @@
- 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节
- 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段
## 1.0.125
- 固化免费 PyArmor Trial 发布约定:行数门槛是预防线;实际失败时按日志定位模块并按职责拆分,保留兼容门面,以 Gitea Trial 加密结果验收
- 记录 field_locator 拆分后同一免费 Trial 链路成功的复盘案例;不使用未经验证的统一字节数阈值
## 1.0.124
- 沉淀宿主能力:Excel 导入模板按列元数据自动加下拉(有可选集合的列展示 label;CSV 无下拉);技能只需声明 `_jiangchang_columns` 选项即可受益
- 更新 `references/SCHEMA.md`「宿主负责」与 `options_json` 说明
## 1.0.123
- 沉淀 `selectionMode: optional` 在**定时任务等无表勾选入口**的宿主约定:配置页按无勾选分支,隐藏空「编号列表」、只保留数量字段;勿为 cron 再拆 Action
- 更新 ACTIONS / CHECKLIST A4-9 / RUNTIME / DEVELOPMENT 验收表;门禁用例覆盖关键表述
## 1.0.122
- 沉淀 Action **静态枚举中文 label**:`enum` + **`enumNames`**,或绑列复用列 `options_json` 数组

View File

@@ -1,7 +1,7 @@
---
name: 技能开发模板(通用业务版)
description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。"
version: 1.0.122
version: 1.0.125
author: 深圳匠厂科技有限公司
metadata:
openclaw:
@@ -38,7 +38,7 @@ allowed-tools:
- **数据管理**:既是 **UI 执行面**(点按钮走与对话相同的闭环),也是数据与过程可见;不是「只读库」。
- **`placements`**:只决定 Action **出现在哪里**(toolbar / row / batch / cron / agent / skill-detail)。其中 `row` 表示**行级入口**(宿主可呈现为操作列、行右键、行内「⋯」等;技能配什么就显示什么,无独立菜单 DSL)。数据管理技能按钮顺序见 `actions` **数组相对顺序**(详见 `references/ACTIONS.md`),无独立 sortOrder。
- **`bind.tables`**:只决定数据管理出现在哪些表;含 `toolbar` 时**必须**显式非空绑定。
- **`bind.selectionMode`(可选)**:表勾选如何驱动 Action(`required` / `none` / `optional`);省略由宿主推断。同一能力勿拆两个同义顶栏按钮,见 `references/ACTIONS.md`。
- **`bind.selectionMode`(可选)**:表勾选如何驱动 Action(`required` / `none` / `optional`);省略由宿主推断。同一能力勿拆两个同义顶栏按钮;定时任务配置页按无勾选分支隐藏 `$selection.ids`,见 `references/ACTIONS.md`。
- **`bind.visibleWhen`(可选)**:`row` 菜单/按钮按当前行列值显隐(如仅已采用可入队);省略则始终显示。≠ 表单字段 `visibleWhen`,≠ Policy L3。见 `references/ACTIONS.md`「行菜单显隐」。
- **用户可见文案**:数据管理弹窗 / 任务中心文案须全中文产品用语;勿把 `pickCount`、`async`、`pending`、CLI 子命令写进弹窗(见 `references/ACTIONS.md`「用户可见文案」)。
- **`executionProfile`**:只决定执行方式——`sync` 当场返回结果,`async` 进**任务中心**。与 placements / 入口**无关**。心智上多数为 sync,仅长任务 / RPA 标 async;宿主省略该字段时按 sync。每个 Action **仍必须**显式写 `sync` 或 `async`。

View File

@@ -13,5 +13,5 @@
- `visible-when-action.example.json`:Action 参数字段条件显隐 `visibleWhen` 形状参考(互斥模式联动;见 `references/ACTIONS.md`「字段条件显隐」;≠ `bind.visibleWhen`,≠ Policy L3)。
- `bind-visible-when-row.action.example.json`:行菜单显隐 `bind.visibleWhen` 形状参考(按当前行状态显示/隐藏行按钮;见 `references/ACTIONS.md`「行菜单显隐」)。
- `selection-label-column.action.example.json`:选择摘要 `bind.labelColumn` 形状参考(见 `references/ACTIONS.md`「选择摘要」)。
- `selection-mode-optional.action.example.json`:`bind.selectionMode: "optional"` 智能勾选/按数量合并形状参考;用户可见文案为口语中文(见 `references/ACTIONS.md`「勾选驱动模式」「用户可见文案」)。
- `selection-mode-optional.action.example.json`:`bind.selectionMode: "optional"` 智能勾选/按数量合并形状参考(含 `cron`:配置页按无勾选分支,只见数量字段);用户可见文案为口语中文(见 `references/ACTIONS.md`「勾选驱动模式」「用户可见文案」)。
- `replaces-create.action.example.json` / `replaces-update.action.example.json` / `replaces-delete.action.example.json` / `replaces-import.action.example.json`:数据管理默认按钮接管(`replaces`)形状参考;**import 时 UI 仍用宿主「导入数据」面板**,确认后调技能写库(见 `references/ACTIONS.md`「`replaces`」)。

View File

@@ -111,7 +111,7 @@ checklist_version: 1.0
- [ ] A4-6 **P0** 若 Action 需引用业务行(话术/平台/账号等):参数为 Lookup 下拉(**不是**手填内部编号);同库用 `local_sql`(内联或绑列),跨技能用 **`skill_cli`**(勿在本库造镜像缓存表);可选「自动」可留空提交(见 `references/ACTIONS.md`)
- [ ] A4-7 **P1** 若 Action 有互斥采集/操作模式(如「按关键词 / 按主页」):用 `inputSchema` 字段级 **`visibleWhen`** 联动显隐,勿只靠 `description` 灰字说明「仅某某时填写」(见 `references/ACTIONS.md`;勿与 **`bind.visibleWhen`** 行菜单、Policy L3 混淆)
- [ ] A4-8 **P1** 行内/勾选打开的 `form`:有「已选择」时参数区不应再重复映射主键(`inputMapping` + `readOnly`);需要强制露出时用 `revealInForm`,**禁止**用表单 `visibleWhen` 藏主键(会不提交)
- [ ] A4-9 **P1** 若同一能力既支持「勾选处理」又支持「按数量从队列领取」:用一个 Action + `bind.selectionMode: "optional"`(勿拆两个同义顶栏按钮);无勾选可点、有勾选显示「已选择」、空选数量字段用 `pickCount` 等约定名(见 `references/ACTIONS.md`)
- [ ] A4-9 **P1** 若同一能力既支持「勾选处理」又支持「按数量从队列领取」:用一个 Action + `bind.selectionMode: "optional"`(勿拆两个同义顶栏 / cron 按钮);无勾选可点、有勾选显示「已选择」、空选数量字段用 `pickCount` 等约定名;**定时任务配置页**只应出现数量字段、不应出现空的「编号列表」(见 `references/ACTIONS.md`)
- [ ] A4-10 **P0** 数据管理弹窗与任务失败文案:全中文产品用语;禁止在 `description` / `confirmation.message` / 参数 `description` / 用户向 `message` 写英文字段名、CLI 子命令、`async`/`pending`/`status=` 等(Agent 路由放 `SKILL.md`;见 `references/ACTIONS.md`「用户可见文案」)
- [ ] A4-11 **P1** 若行操作应按业务状态显隐(如仅待确认可「采用」、仅已采用可「加入待写」):用 **`bind.visibleWhen`**(对当前行列值求值;存库原始值如 `approved`);勿指望 Policy L3;CLI 侧仍须校验状态(见 `references/ACTIONS.md`「行菜单显隐」)
- [ ] A4-12 **P1** 若要在表单里翻页勾选一批业务行(文章、平台等):用 Lookup **`presentation: "paged_table"`**(仍是 `display_type: lookup`,勿新造类型);`skill_cli` 的 stdout 为一行 `{"items","total"}`,0 条也成功退出;该列表命令不要在入口加载整包 platform-kit 或 Playwright(见 `references/ACTIONS.md`「分页勾选小表」)

View File

@@ -213,6 +213,14 @@ release workflow 会对 `scripts/` 下的 Python 源码做加密/打包。当前
- 不要把完整 RPA 主流程、DOM 选择器、数据库、CLI、日志全部堆进一个大文件。
- 正确做法是拆分到 `scripts/cli/`、`scripts/service/`、`scripts/db/`、`scripts/util/`。
以上行数是预防性硬门槛,**不是 Trial 加密成功的充分条件**。PyArmor Trial 对具体源码模块的限制不能用一个未经验证的字节数阈值代替;即使文件低于 1000 行,实际加密仍可能因单个模块过大或过于复杂而失败。免费模式下的处理约定:
1. 以 Gitea release workflow 使用的 Trial 加密步骤和目标平台为准做实际验证;查看日志确认失败发生在哪个 `.py` 文件,不以本地行数检查通过推断加密一定成功。
2. 若日志指出某个模块加密失败(例如 Trial license / big script 一类限制),按职责把该模块拆成更小的实现模块;原文件保留为兼容门面,重导出原有公开函数、类或常量,避免改坏已有 import 路径。
3. 拆分后先跑完整测试,再升补丁版本并 release;检查 Gitea job 中所有 Python 模块均已加密、加密包成功生成/上传且 job 最终成功。失败时继续针对日志定位的模块拆分并重新验证,不放宽免费模式、不猜统一字节上限。
模板案例:得一智慧审单的 `field_locator.py` 在免费 Trial 加密阶段失败;按职责拆分为多个实现模块并保留原文件兼容门面后,同一免费 Trial 发布链路成功。这个案例用于说明应对**具体失败模块做职责拆分并复验**,不作为其他技能的固定文件字节数阈值。
`examples/` 里的 Python 示例也建议保持模块化,但**行数限制不作为 examples 的发布硬约束**;不要对 README、HTML、测试数据等文档/资源套用 PyArmor 行数规则。
**文本编码(UTF-8 without BOM)**
@@ -928,7 +936,7 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
| **数据管理 · HTML 报告** | 壳子页放 `assets/html/pages/*.html`;快照写出 `html/*.html` 并提供 `render-html` | 壳子装完即现、右键无「重新生成」;快照可重新生成;页面 `jiangchang.call` 能拿到 JSON |
| **数据管理 · 行级** | `placements` 含 `row`(建议 `bind.tables` + `bind.inputMapping` 预填主键) | 操作列和/或行右键(及可选「⋯」)出现本技能行级 Action(需有主键列);点按后入参/行为与壳无关、均正确 |
| **数据管理 · 批量** | `placements` 含 `batch` | 勾选行后批量按钮可用;无勾选时禁用;批量行为正确 |
| **定时任务** | `placements` 含 `cron`(创建时选「技能直调」) | 能选到本技能 Action、保存并触发;到点或「立即运行」行为正确 |
| **定时任务** | `placements` 含 `cron`(创建时选「技能直调」) | 能选到本技能 Action、保存并触发;到点或「立即运行」行为正确;`selectionMode: optional` 时参数区只见数量字段、不见空「编号列表」 |
| **任务中心** | 不是 placement;由 `executionProfile: "async"` 决定是否进 Job | 长任务出现进度 / 可取消;来源标签与触发入口一致 |
| **技能市场 → 技能详情** | `placements` 含 `skill-detail`(详情直调) | **必验**安装与四 Tab。详情页「技能直调」按钮随宿主版本上线;**已声明则须在具备该 UI 的宿主上完成按钮自测**(与其它入口同等对待,不要只靠 Agent) |

View File

@@ -24,7 +24,7 @@
| 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-RPA-006 | 浏览器 RPA 必须保留 account-manager 生命周期标准;所有样例账号选择路径都须返回非空 `profile_dir + lease_token`,指定数字账号 ID 不得退化为无租约 `account get` | development/ACCOUNT_MANAGER.md;development/ADAPTER.md §兄弟依赖;development/RPA.md §0.2 | hard | 检查标准文档关键标记;扫描真实/仿真 `account_client.py` 的指定 ID 带租约实现并禁止空租约赋值 | `tests/test_development_policy_guard.py::TestPolicyRpa006` |
| POLICY-RPA-007 | 网页 RPA 启动须 `no_viewport=True` + `--start-maximized`;禁止 `viewport=None`、CDP/JS 中途改窗;`RPA.md` §1.2.1 须保留窗口标准 | development/RPA.md §1.2.1;development/RPA_BROWSER.md §4;examples/real_browser_rpa | hard | 文档标记 + 扫描含 `launch_persistent_*` 的 Python 禁止模式;校验 real_browser 示例 | `tests/test_development_policy_guard.py::TestPolicyRpa007` |
| 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 行;该门槛不保证 Trial 加密成功。免费 Trial 实际失败时按报错模块拆分职责、保留兼容门面,并以 Gitea 实际加密 job 成功作为发布验收 | development/DEVELOPMENT.md §3.4 发布打包约束;development/RUNTIME.md §发布打包约束 | hard | 行数测试 + Trial 发布 job 结果 | **已有测试覆盖**:`tests/test_release_packaging_constraints.py::test_scripts_py_files_under_pyarmor_line_limit`、`test_trial_packaging_guidance_is_documented`;实际加密由 Gitea release workflow 验证 |
| 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-RELEASE-001 | 发布 tag(去掉前缀)必须等于 `SKILL.md` 的 `version:` 且等于 `scripts/util/constants.py` 的 `SKILL_VERSION`;`release.ps1` 打 tag 前硬失败,不自动改写字段 | development/DEVELOPMENT.md §15 发布;宿主市场「最新版本」来自 tag、「当前版本」来自包内 `SKILL.md` | hard | `release.ps1` 门禁 + 日常版本字段对齐测试 | `release.ps1`(`Assert-SkillReleaseVersionAlignment`);`tests/test_development_policy_guard.py::TestPolicyRelease001`;`tests/test_skill_metadata.py::test_skill_version_alignment` |
| POLICY-DOCS-001 | 本矩阵存在且包含上述全部 `policy_id` | 本次规范化约定 | hard | 解析 `development/POLICY_MATRIX.md` | `tests/test_development_policy_guard.py::TestPolicyDocs001` |

View File

@@ -140,6 +140,8 @@ RPA 录屏成片(`RpaVideoSession`)、ffmpeg 路径、背景音乐探测均
release workflow 加密 `scripts/` 源码时,可能运行在 PyArmor 免费/试用模式:
- `scripts/**/*.py` 单文件必须 **< 1000 行**(`>= 1000` 可能在 CI 失败);推荐 **< 900 行**。
- 接近上限时拆分到 `cli/`、`service/`、`db/`、`util/`,不要把 RPA 主流程、选择器、DB、CLI 堆进单文件。
- `scripts/**/*.py` 单文件必须 **< 1000 行**(`>= 1000` 可能在 CI 失败);推荐 **< 900 行**。这是预防性硬门槛,不代表低于该行数就一定能被 Trial 加密。
- 模块应按职责拆分到 `cli/`、`service/`、`db/`、`util/`;不要把 RPA 主流程、选择器、DB、CLI 堆进单文件。发现某个文件在免费 Trial 加密时报错时,按报错定位该文件并继续拆分其职责,重新走实际加密验证;不要通过猜测统一的源码字节数阈值代替验证。
- 拆分已有模块时,尽量保留原模块作为兼容门面(re-export / 委托到新模块),避免破坏现有 import 路径;先跑测试,再发布验证。
- 发布验收以 Gitea release workflow 中实际的 PyArmor Trial 加密结果为准:确认全部 `scripts/**/*.py` 均成功加密、加密包成功生成/上传且 job 成功。若 PyArmor 步骤失败,不得把版本视为已发布成功;按日志中的失败文件拆分、升补丁版本并重新 release。
- 此行数限制**仅适用于** `scripts/**/*.py`;不限制 README 等文档行数,也不把 examples 里的 HTML/README 纳入 PyArmor 行数约束。

View File

@@ -21,7 +21,7 @@
1. **宿主管调度,技能管业务** — 不自行实现任务中心 / Job 轮询 / 后台守护进程。
2. **单业务内核、多入口** — 数据管理、定时任务、Agent、技能详情与直接 CLI 复用同一 domain service;禁止按入口复制业务逻辑。
3. **五职责正交** — `placements` / `bind.tables` / `executionProfile` / `entrypoint` / domain service 各管一事(见 ACTIONS.md)。可选第六轴 **policy**(见 `references/POLICY.md`):未启用 = L0 与今日一致。可选 **`hostEffects` / `steps`**(见 ACTIONS.md):数据管理交互前后的 UI/级联编排;省略 = 不额外改 UI(匠厂宿主 ≥2.8.5)。可选 **`hoverHint`**(见 ACTIONS.md):数据管理工具栏悬停;省略 = 不显示,不回退说明或确认黄条。可选 **表单 `visibleWhen`**(见 ACTIONS.md):Action 参数表单字段条件显隐;省略 = 字段始终平铺;**勿与** **`bind.visibleWhen`**(行菜单)或 Policy L3 混淆;**勿**用其藏映射主键。可选 **`pathRoot`**(见 ACTIONS.md):`file`/`directory` 原生选路对话框起始目录(相对技能数据根;省略默认 `{skill_data}/input`)。可选 **`bind.labelColumn`**(见 ACTIONS.md):选择摘要可读标签列;省略 = 宿主常见列名启发。可选 **`bind.selectionMode`**(见 ACTIONS.md):表勾选如何驱动 Action(`required` / `none` / `optional`);省略 = 宿主按 `$selection.ids` / `batch` 推断。可选 **`bind.visibleWhen`**(见 ACTIONS.md「行菜单显隐」):`row` 菜单按当前行列值显隐;省略 = 始终显示。可选 **`revealInForm`**(见 ACTIONS.md):有「已选择」时仍强制显示某 `readOnly` 字段;省略 = 映射只读默认不占 form 参数区(仍提交)。可选 **`cellPresentation`**(见 `references/CELL_PRESENTATION.md`):单元格/整行/整列/区域语义标色;省略 = P0。**用户可见文案**(见 ACTIONS.md「用户可见文案」):弹窗 `description` / 确认黄条 / 参数说明 / 任务失败 `message` 须全中文产品用语;Agent 路由勿塞进弹窗。
3. **五职责正交** — `placements` / `bind.tables` / `executionProfile` / `entrypoint` / domain service 各管一事(见 ACTIONS.md)。可选第六轴 **policy**(见 `references/POLICY.md`):未启用 = L0 与今日一致。可选 **`hostEffects` / `steps`**(见 ACTIONS.md):数据管理交互前后的 UI/级联编排;省略 = 不额外改 UI(匠厂宿主 ≥2.8.5)。可选 **`hoverHint`**(见 ACTIONS.md):数据管理工具栏悬停;省略 = 不显示,不回退说明或确认黄条。可选 **表单 `visibleWhen`**(见 ACTIONS.md):Action 参数表单字段条件显隐;省略 = 字段始终平铺;**勿与** **`bind.visibleWhen`**(行菜单)或 Policy L3 混淆;**勿**用其藏映射主键。可选 **`pathRoot`**(见 ACTIONS.md):`file`/`directory` 原生选路对话框起始目录(相对技能数据根;省略默认 `{skill_data}/input`)。可选 **`bind.labelColumn`**(见 ACTIONS.md):选择摘要可读标签列;省略 = 宿主常见列名启发。可选 **`bind.selectionMode`**(见 ACTIONS.md):表勾选如何驱动 Action(`required` / `none` / `optional`);省略 = 宿主按 `$selection.ids` / `batch` 推断;**定时任务等无表勾选入口按无勾选分支**(隐藏 `$selection.ids`,保留 `pickCount`)。可选 **`bind.visibleWhen`**(见 ACTIONS.md「行菜单显隐」):`row` 菜单按当前行列值显隐;省略 = 始终显示。可选 **`revealInForm`**(见 ACTIONS.md):有「已选择」时仍强制显示某 `readOnly` 字段;省略 = 映射只读默认不占 form 参数区(仍提交)。可选 **`cellPresentation`**(见 `references/CELL_PRESENTATION.md`):单元格/整行/整列/区域语义标色;省略 = P0。**用户可见文案**(见 ACTIONS.md「用户可见文案」):弹窗 `description` / 确认黄条 / 参数说明 / 任务失败 `message` 须全中文产品用语;Agent 路由勿塞进弹窗。
4. **长耗时建议 async** — 开浏览器、RPA、HTTP 大文件下载等建议 `executionProfile: "async"`,进**任务中心**;这是对**方法**的选择,**不**限制可以出现在哪些 placement / 入口。
5. **Agent:短 CLI / 长 Action** — 短查询可用共享 Python bash CLI;长任务 / RPA **禁止** `exec` + `process poll`,必须 `run_skill_action`。
6. **进度走 Journal** — `emit` / `video.add_step` → Run Journal;UI / Skill Run Card / 任务中心展示;**不靠 stdout 流**。

View File

@@ -32,7 +32,7 @@
- Skill Action manifest:`assets/actions.json` 结构、CLI 映射、placements 与 inputSchema 守护(见 `test_actions_manifest.py`);
- 标准时间字段:`created_at` / `updated_at` 默认值、trigger 维护与 `datetime_unix_seconds` 元数据(见 `test_timestamp_columns.py`);
- **adapter profile**:[`tests/test_adapter_profile_policy.py`](../tests/test_adapter_profile_policy.py) + [`adapter_test_utils`](../tests/adapter_test_utils.py) ——验证在未授权情况下绝不误判开启真实网络/RPA。
- **发布打包守护**:[`tests/test_release_packaging_constraints.py`](../tests/test_release_packaging_constraints.py) ——`scripts/**/*.py` 单文件 < 1000 行、文本文件 UTF-8 without BOM。
- **发布打包守护**:[`tests/test_release_packaging_constraints.py`](../tests/test_release_packaging_constraints.py) ——`scripts/**/*.py` 单文件 < 1000 行、PyArmor Trial 拆分/实际发布验证约定、文本文件 UTF-8 without BOM。行数通过只表示通过预防性门槛;免费 Trial 是否能加密成功仍以 Gitea 实际加密 job 为准。
- **开发规范守护(hard policy)**:[`tests/test_development_policy_guard.py`](../tests/test_development_policy_guard.py) ——规则索引见 [`development/POLICY_MATRIX.md`](POLICY_MATRIX.md),只执行可机器检测的 hard 规则。
- **slug 语义**:[`tests/test_slug_naming.py`](../tests/test_slug_naming.py) ——动词-名词命名;平台可选,`default` 不再作为占位。
- **HTML 报告壳**:[`tests/test_html_page_service.py`](../tests/test_html_page_service.py) 守护 `assets/html/example-report.html` 的数据管理 iframe 预览布局基线,并守护 ACTIONS.md 里的壳子页目录 `assets/html/pages` 与 `jiangchang.call`。业务技能若有自定义 `assets/html/*.html` 或 `pages/*.html`,建议在自有仓库加同类静态断言(见 `references/ACTIONS.md`「宿主预览布局」)。不要把 `example-report.html` 放进 `pages/`。

View File

@@ -197,7 +197,8 @@ Action 是否提供、挂哪些 `placements`,由本技能 **入口定位表**
3. 空选数量字段名约定(宿主按字段名识别,保守列表):`pickCount` / `maxLeads` / `maxCount` / `takeCount` / `pick`。
4. `entrypoint.args` 可同时写 `--ids {{itemIds}}` 与 `--pick {{pickCount}}`;缺值的 `--flag` + 空串由宿主压缩掉,不会留下脏 argv。
5. 有勾选时隐藏数量字段;无勾选时隐藏 `$selection.ids` 映射字段(`$row.*` 行上下文不受影响)。
6. **不要**为同一能力再挂第二个 toolbar 按钮。
6. **定时任务 / 技能详情等无表勾选入口**:宿主须按「无勾选」分支渲染与保存——只展示 `pickCount` 等数量字段,**不**画出空的「编号列表」类 `$selection.ids` 映射只读框;保存的 `actionInput` 也不应再带上空 `itemIds`。不要为 cron 再拆第二个 Action。
7. **不要**为同一能力再挂第二个 toolbar 按钮。
示例:[`assets/examples/selection-mode-optional.action.example.json`](../assets/examples/selection-mode-optional.action.example.json)。
@@ -515,7 +516,7 @@ Action 是否提供、挂哪些 `placements`,由本技能 **入口定位表**
**边界:**
- **cron 配置**:仍展示可编辑参数;`confirmation.message` 可作为配置页风险提示(由宿主决定)。
- **cron 配置**:仍展示可编辑参数;`confirmation.message` 可作为配置页风险提示(由宿主决定)。若 Action 为 `selectionMode: "optional"`(或 `none`),配置页按**无表勾选**分支:隐藏 `$selection.ids` 映射字段,只保留数量等可编辑参数(见上文「勾选驱动模式」第 6 点)。
- **cron 触发 / agent**:忽略 `interaction`(无人值守 / 模型填参);`confirmation` 对 agent 仍作 `requiresConfirmation` 元数据。
- 不要用 `interaction: "direct"` 掩盖需要用户填写的可编辑字段——宿主在 `auto` 下会因可编辑参数回落到 `form`;显式 `direct` + 可编辑字段时参数取 default/预填,作者须自觉。
@@ -1389,7 +1390,7 @@ CRUD 侧宿主义务与禁止事项见 [`SCHEMA.md`](SCHEMA.md)「表单与展
若还需要默认篇数,可在同一 `properties` 里为 `pickCount` 增加 `"default": 1`、`"minimum": 1`。
与 **`bind.selectionMode: "optional"`** 联用时:无勾选弹层展示 `pickCount`;有勾选则隐藏 `pickCount`、提交 `$selection.ids`。不要再拆第二个「只 pick / 只勾选」toolbar 按钮。见上文「勾选驱动模式」。
与 **`bind.selectionMode: "optional"`** 联用时:无勾选弹层展示 `pickCount`;有勾选则隐藏 `pickCount`、提交 `$selection.ids`。定时任务配置页同无勾选分支(不展示空「编号列表」)。不要再拆第二个「只 pick / 只勾选」toolbar / cron 按钮。见上文「勾选驱动模式」。
约定:

View File

@@ -37,6 +37,7 @@
- 不根据具体技能名称写特殊逻辑
- 可在技能安装/更新成功后静默调用 `python scripts/main.py init-db` 做幂等 ensure(内部即 `init_db()`);失败不影响安装结果
- 若技能启用了单元格呈现(见 [`CELL_PRESENTATION.md`](CELL_PRESENTATION.md)),读取旁路呈现数据并为格子 / 行 / 列 / 区域映射语义样式(`tone`);不猜测业务规则;整行色只涂表格行,不铺到详情字段
- **导入模板下拉(宿主能力)**:下载「Excel 模板」时,宿主按本表可导入列的元数据自动加 Excel 数据有效性下拉——凡列已有可选集合(`options_json` 静态枚举、schema 已解析的 lookup 选项、未写 options 的 `boolean` 默认「是/否」等)即加下拉;无选项的列仍为自由文本。下拉展示 **label**;导入写库时宿主(或 `replaces: import` 技能)再 **label → value**。CSV 模板**不能**带下拉,可选值仍写在导入弹窗「可导入字段说明」与 Excel「填写说明」页。技能**无需**自备带下拉的模板文件;把字段选项声明在 `_jiangchang_columns` 即可让所有技能受益。宿主不按技能名写死「只支持某几种业务字段」。
## 初始化入口
@@ -671,7 +672,7 @@ CREATE TABLE demo_items (
## 枚举字段 options_json
`options_json` 支持两种形态:
`options_json` 支持两种形态。正确声明后,数据管理「新增/编辑」下拉、列筛选、**以及 Excel 导入模板下拉**共用同一套选项(见上文「宿主负责」中的导入模板下拉)。
### 1)静态枚举(数组)

View File

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

View File

@@ -498,6 +498,7 @@ class TestDocsStandards(unittest.TestCase):
self.assertIn("revealInForm", checklist)
self.assertIn("A4-9", checklist)
self.assertIn("selectionMode", checklist)
self.assertIn("定时任务配置页", checklist)
self.assertIn("A4-10", checklist)
self.assertIn("A4-11", checklist)
self.assertIn("bind.visibleWhen", checklist)
@@ -508,11 +509,14 @@ class TestDocsStandards(unittest.TestCase):
self.assertIn("selectionMode", runtime)
self.assertIn("bind.visibleWhen", runtime)
self.assertIn("用户可见文案", runtime)
self.assertIn("无表勾选入口按无勾选分支", runtime)
actions = self._read("references/ACTIONS.md")
self.assertIn("用户可见文案", actions)
self.assertIn("双受众", actions)
self.assertIn("行菜单显隐", actions)
self.assertIn("bind.visibleWhen", actions)
self.assertIn("无表勾选入口", actions)
self.assertIn("编号列表", actions)
def test_guarded_docs_do_not_reference_amazon_implementation(self) -> None:
forbidden = (

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
"""发布打包守护:PyArmor 单文件行数与 UTF-8 without BOM。"""
"""发布打包守护:PyArmor Trial 约定、单文件行数与 UTF-8 without BOM。"""
from __future__ import annotations
import os
@@ -89,6 +89,26 @@ def _iter_scripts_py_files(skill_root: str) -> list[str]:
class TestReleasePackagingConstraints(unittest.TestCase):
def test_trial_packaging_guidance_is_documented(self) -> None:
skill_root = get_skill_root()
runtime_path = os.path.join(skill_root, "development", "RUNTIME.md")
development_path = os.path.join(skill_root, "development", "DEVELOPMENT.md")
with open(runtime_path, encoding="utf-8") as f:
runtime = f.read()
with open(development_path, encoding="utf-8") as f:
development = f.read()
required_guidance = {
"free/trial mode": (runtime + development, "Trial"),
"line limit is not sufficient": (runtime + development, "不是 Trial 加密成功的充分条件"),
"split the failing module by responsibility": (runtime + development, "按职责"),
"preserve compatibility imports": (runtime + development, "兼容门面"),
"verify real release encryption": (runtime + development, "实际加密"),
"inspect Gitea release result": (runtime + development, "Gitea"),
}
missing = [label for label, (text, needle) in required_guidance.items() if needle not in text]
self.assertEqual(missing, [], msg=f"Missing PyArmor Trial guidance: {missing}")
def test_scripts_py_files_under_pyarmor_line_limit(self) -> None:
skill_root = get_skill_root()
offenders: list[str] = []
@@ -104,8 +124,9 @@ class TestReleasePackagingConstraints(unittest.TestCase):
offenders,
[],
msg=(
"PyArmor trial/free mode may fail when a single Python file reaches "
f"{SCRIPTS_MAX_LINES} lines; split this file into smaller modules. "
"PyArmor trial/free mode has a preventive single-file line guard; "
"passing it does not guarantee Trial encryption succeeds. Split any "
"module identified by the actual Trial release error. "
f"Recommended keep each file < {SCRIPTS_RECOMMENDED_MAX_LINES} lines. "
f"Offenders: {offenders}"
),