fix: harden skill template contracts and scaffolding
All checks were successful
技能自动化发布 / release (push) Successful in 4s
All checks were successful
技能自动化发布 / release (push) Successful in 4s
Align scaffold slug replacement, Action manifest strict boundaries, metadata prune API, field permission validation, and task_logs readonly semantics with documented template contracts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,6 +4,17 @@
|
||||
|
||||
**边界:** 用户市场说明见根目录 [`README.md`](../README.md);CLI 参数与错误码细节见 [`CLI.md`](CLI.md)。
|
||||
|
||||
## 模板严格规范 vs 宿主向后兼容
|
||||
|
||||
| 角色 | 定位 |
|
||||
|------|------|
|
||||
| **skill-template** | 新技能推荐的**严格规范**:必填字段、明确类型、`additionalProperties: false` |
|
||||
| **宿主运行时** | **向后兼容**的历史 manifest 解析器:可能接受部分缺省字段(如 `description`、`placements`、`entrypoint.args`、input property `type`) |
|
||||
|
||||
**新技能不应依赖宿主缺省行为。** 复制模板后按 [`assets/schemas/skill-actions.schema.json`](../assets/schemas/skill-actions.schema.json) 与本文完整填写 manifest。
|
||||
|
||||
JSON Schema 使用 `additionalProperties: false` 表达模板严格边界;这与宿主共享类型中的可选字段并不矛盾——宿主为兼容旧技能可能更宽松,模板为防漂移要求更严。
|
||||
|
||||
## Action 是否必需
|
||||
|
||||
Action 是**可选能力**:
|
||||
@@ -33,6 +44,29 @@ Action 是**可选能力**:
|
||||
|
||||
模板最小示例见 [`assets/actions.json`](../assets/actions.json);JSON Schema 见 [`assets/schemas/skill-actions.schema.json`](../assets/schemas/skill-actions.schema.json)。
|
||||
|
||||
## Phase 1 当前稳定支持(新技能应只使用这些)
|
||||
|
||||
| 层级 | 稳定字段 / 能力 |
|
||||
|------|----------------|
|
||||
| 顶层 | `schemaVersion`、`skill`、`actions` |
|
||||
| action | `id`、`label`、`description`、`placements`、`entrypoint`;可选 `inputSchema`、`confirmation` |
|
||||
| entrypoint | `type = cli`、`command`、`args`(**必填** JSON 数组,项为 `string` / `number` / `boolean`) |
|
||||
| placements | `toolbar`、`skill-detail`、`agent`、`cron` |
|
||||
| inputSchema | 根 `type: object`;properties 使用 `string` / `number` / `boolean`;支持 `enum`、`default`、`required`、`sensitive` |
|
||||
| confirmation | `{ "message": "..." }` |
|
||||
|
||||
## 预留能力(当前不可当作已实现能力)
|
||||
|
||||
以下在宿主共享类型或 Schema 枚举中可能出现,但 **Phase 1 Runtime 尚未完整支持**,**新模板示例不得使用**:
|
||||
|
||||
| 类别 | 预留项 | 说明 |
|
||||
|------|--------|------|
|
||||
| placements | `row`、`batch` | 行内 / 批量入口,未来扩展 |
|
||||
| action 字段 | `bind`、`concurrency`、`locks` | 绑定、并发与锁控制,宿主后续实现 |
|
||||
| inputSchema | `array`、nested `object`、`oneOf` 等 | 复杂表单与联合类型,不属于当前推荐模板范围 |
|
||||
|
||||
可以在文档或 Schema 枚举中保留这些值供未来对齐,但不要让技能作者误以为它们已经可执行。
|
||||
|
||||
## 执行模型
|
||||
|
||||
宿主将 action 转为 argv,再执行:
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
| [`SKILL.md`](../SKILL.md) | LLM / OpenClaw 平台技能入口 |
|
||||
| [`CLI.md`](CLI.md) | 命令行入口、参数与调用契约 |
|
||||
| [`SCHEMA.md`](SCHEMA.md) | 本地 SQLite 与数据管理展示契约 |
|
||||
| [`ACTIONS.md`](ACTIONS.md) | Skill Action manifest 与宿主入口契约 |
|
||||
| [`ACTIONS.md`](ACTIONS.md) | Skill Action manifest(**可选**能力)与宿主入口契约 |
|
||||
| [`../development/`](../development/) | 开发、测试、技术规范(给开发者 / AI 编程代理) |
|
||||
|
||||
按需阅读:编排任务时优先 `CLI.md`;解析结构化字段时读 `SCHEMA.md`;配置宿主按钮/定时任务/Agent 入口时读 `ACTIONS.md`;运行时环境细节见 `../development/RUNTIME.md`。
|
||||
|
||||
@@ -236,6 +236,16 @@ readonly = 0
|
||||
|
||||
### 模板默认:`task_logs`
|
||||
|
||||
`task_logs` 是技能内部**系统自动写入**的任务审计日志(由 `task_logs_repository` INSERT/UPDATE),不是供用户在宿主数据管理中手工维护的业务表。
|
||||
|
||||
权限设计:
|
||||
|
||||
| 层级 | 值 | 说明 |
|
||||
|------|-----|------|
|
||||
| 表级 `readonly` | `1` | 宿主数据管理只读展示,不提供新增/编辑/删除表单 |
|
||||
| 所有业务字段 `editable` | `0` | 含 `task_type`、`status`、`error_msg`、`result_summary` 等 |
|
||||
| 技能内部 repository | 正常 INSERT/UPDATE | 元数据权限只约束宿主 UI,不限制技能代码写库 |
|
||||
|
||||
物理定义(权威顺序):
|
||||
|
||||
```sql
|
||||
@@ -258,17 +268,17 @@ CREATE TABLE IF NOT EXISTS task_logs (
|
||||
| 物理字段 | 中文名 | editable |
|
||||
|----------|--------|----------|
|
||||
| id | 编号 | 0 |
|
||||
| task_type | 任务类型 | 1 |
|
||||
| target_id | 目标编号 | 1 |
|
||||
| input_id | 输入编号 | 1 |
|
||||
| input_title | 输入标题 | 1 |
|
||||
| status | 状态 | 1 |
|
||||
| error_msg | 错误信息 | 1 |
|
||||
| result_summary | 结果摘要 | 1 |
|
||||
| task_type | 任务类型 | 0 |
|
||||
| target_id | 目标编号 | 0 |
|
||||
| input_id | 输入编号 | 0 |
|
||||
| input_title | 输入标题 | 0 |
|
||||
| status | 状态 | 0 |
|
||||
| error_msg | 错误信息 | 0 |
|
||||
| result_summary | 结果摘要 | 0 |
|
||||
| created_at | 创建时间 | 0 |
|
||||
| updated_at | 更新时间 | 0 |
|
||||
|
||||
表中文名:**任务日志**;表级 `readonly = 0`。
|
||||
表中文名:**任务日志**;表级 `readonly = 1`(宿主只读;技能 repository 仍可写入)。
|
||||
|
||||
### 通用示例:`demo_items`(测试 fixture 参考)
|
||||
|
||||
@@ -325,8 +335,41 @@ CREATE TABLE demo_items (
|
||||
实现 helper:
|
||||
|
||||
- `upsert_table_metadata` / `upsert_column_metadata` — 幂等写入
|
||||
- `seed_column_metadata_batch` — 批量 upsert;**可选**传入 `valid_column_names` 时在 upsert 后自动 prune
|
||||
- `prune_stale_column_metadata` — 清理已删除物理字段的元数据
|
||||
|
||||
### 新增业务表时如何初始化
|
||||
|
||||
1. 在 `connection.py`(或迁移脚本)中 `CREATE TABLE` 真实物理表。
|
||||
2. 用 `PRAGMA table_info` 或 `list_physical_column_names` 取得**真实物理字段列表**(顺序以 `cid` 为准)。
|
||||
3. 调用 `upsert_table_metadata` 写入表级元数据。
|
||||
4. 调用 `seed_column_metadata_batch`,并传入 `valid_column_names=physical_column_names`:
|
||||
|
||||
```python
|
||||
from db.display_metadata import list_physical_column_names, seed_column_metadata_batch, upsert_table_metadata
|
||||
|
||||
physical = list_physical_column_names(cursor, "demo_items")
|
||||
upsert_table_metadata(cursor, table_name="demo_items", display_name="示例记录", readonly=0)
|
||||
seed_column_metadata_batch(
|
||||
cursor,
|
||||
table_name="demo_items",
|
||||
columns=DEMO_ITEMS_COLUMN_METADATA,
|
||||
valid_column_names=physical,
|
||||
)
|
||||
```
|
||||
|
||||
传入 `valid_column_names` 时:先 upsert,再删除不在物理表中的陈旧 `_jiangchang_columns` 行。
|
||||
|
||||
### 字段删除或重命名时如何清理
|
||||
|
||||
1. 在 DDL / 迁移中完成物理字段删除或重命名。
|
||||
2. 重新执行 `seed_column_metadata_batch(..., valid_column_names=当前物理字段列表)`,自动 prune 旧字段元数据。
|
||||
3. 或单独调用 `prune_stale_column_metadata(cursor, table_name, valid_column_names)`。
|
||||
|
||||
**不传入 `valid_column_names` 时不会自动 prune**——模板不会猜测真实物理字段,避免误删;文档与实现均以此为准。
|
||||
|
||||
不要直接修改用户真实数据库作为迁移方式;元数据初始化必须使用真实物理字段列表。
|
||||
|
||||
## 中文命名质量
|
||||
|
||||
- 使用普通用户能理解的业务用语:`task_logs` → **任务日志**,`error_msg` → **错误信息**。
|
||||
|
||||
Reference in New Issue
Block a user