diff --git a/CHANGELOG.md b/CHANGELOG.md index d2d60fd..f3cd9bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ - 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节 - 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段 +## 1.0.103 + +- 用户市场文档:说明/教程正文禁止与宿主页头、Tab 重复的文首一级标题;主分节统一用 `##` +- 更新 `TUTORIAL.md` / `README.md` 模板骨架、`TUTORIAL_SURFACES.md` §0.1、CHECKLIST A2-12 与契约测试 + ## 1.0.102 - 沉淀数据管理 Action「已选择」摘要契约:confirm/form 弹层由宿主默认展示勾选对象(#id + 可读标签);技能零改动即可用 diff --git a/README.md b/README.md index 9e716e2..c1108d5 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,8 @@ description: "用用户能理解的方式说明这个技能能做什么、适合 > frontmatter 的 `description` 必须是用户能看懂的一句话能力描述;**不得**写成 CLI、schema、references、development、契约或「如何开始使用」类教程承诺。 > **禁止**写入:分步操作(1/2/3)、Agent 示例话术块、「入口一/入口二」专章、逐步排障。这些一律写在根目录 `TUTORIAL.md`。 > 正文只回答:是什么、能做什么、适合谁、准备什么、得到什么、注意事项。完整契约见 `development/TUTORIAL_SURFACES.md` §1。 -> **复制后验收章节(标题可微调):**「能帮你做什么」「适合什么场景」「使用前需要准备什么」「怎么使用」「执行后你会得到什么」「注意事项」「常见问题」。 - -# 【技能名称】 +> **复制后验收章节(标题可微调):**「能帮你做什么」「适合什么场景」「使用前需要准备什么」「怎么使用」「执行后你会得到什么」「注意事项」「常见问题」。 +> **标题层级:** 宿主页头已有技能名——**禁止**文首再写 `# 技能名`;正文主分节用 `##`。 > 用一两句话说明这个技能帮助用户完成什么工作。 > 这里不要解释技术实现,要从用户的业务目标出发描述价值。 diff --git a/SKILL.md b/SKILL.md index 8b6e99a..35b8f6e 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,7 +1,7 @@ --- name: 技能开发模板(通用业务版) description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。" -version: 1.0.102 +version: 1.0.103 author: 深圳匠厂科技有限公司 metadata: openclaw: diff --git a/TUTORIAL.md b/TUTORIAL.md index 56e4b97..0536f4e 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -4,9 +4,8 @@ > 与根 `README.md`(技能说明)分工:README 讲「是什么 / 能做什么 / 边界」;本文讲「从哪个入口怎么用完」。 > **完整契约:** `development/TUTORIAL_SURFACES.md`(三入口结构、说明≠教程、skill-detail 不可作主路径)。 > **复制后验收章节(标题可微调,语义不可缺):**「本技能做什么」「开始前」「入口一:数据管理」「入口二:对话任务」「入口三:定时任务」「主能力对照表」「常见卡住怎么办」。 -> 若本技能 §0.1 未挂数据管理 / 对话 / 定时,对应入口节改为「不适用」并写一句理由(与 REQUIREMENTS 一致)。 - -# 【技能名称】· 使用教程 +> 若本技能 §0.1 未挂数据管理 / 对话 / 定时,对应入口节改为「不适用」并写一句理由(与 REQUIREMENTS 一致)。 +> **标题层级:** 宿主页头已有技能名、Tab 已有「使用教程」——**禁止**文首再写 `# 技能名 · 使用教程`;正文主分节用 `##`,步骤用 `###`。 本技能有两种**平行**的使用方式(按本技能入口定位填写;未挂的入口删掉或写不适用): diff --git a/development/CHECKLIST.md b/development/CHECKLIST.md index 8f9559a..5062f59 100644 --- a/development/CHECKLIST.md +++ b/development/CHECKLIST.md @@ -86,6 +86,7 @@ checklist_version: 1.0 - [ ] A2-9 **P0** 无 `cron` 时教程有「不需要定时」+ 理由;有 `cron` 时教程写清如何配置 - [ ] A2-10 **P1** 教程主能力对照表与 `actions.json` 的 `label` 一致 - [ ] A2-11 **P1** 若有数据管理主路径:准备/载入/导入类能力在对应表 **toolbar** 可见;教程**不以** skill-detail 为唯一主路径 +- [ ] A2-12 **P0** 说明/教程正文**不以** `# 技能名` 或 `# 技能名 · 使用教程` 开篇(宿主页头/Tab 已有);主分节用 `##`,不要把原 `##` 升成 `#`(见 `TUTORIAL_SURFACES.md` §0.1) --- diff --git a/development/DEVELOPMENT.md b/development/DEVELOPMENT.md index 348b742..3be971a 100644 --- a/development/DEVELOPMENT.md +++ b/development/DEVELOPMENT.md @@ -352,9 +352,9 @@ git remote -v | `DEMO.md` | 演示 | `demo_md` + frontmatter `demo_video_url` | | `CHANGELOG.md` | 更新日志 | 匹配当前 tag 版本的 `##` 小节 → `changelog` | -**`README.md`(说明 Tab)**:能力、场景、前置条件、结果形态、注意事项、概念类 FAQ。含 frontmatter `description`(**不要**写「如何开始使用」)。**禁止**分步操作、Agent 话术块、「入口一/二」专章、逐步排障——这些属教程。完整契约见 [`TUTORIAL_SURFACES.md`](TUTORIAL_SURFACES.md) §1。 +**`README.md`(说明 Tab)**:能力、场景、前置条件、结果形态、注意事项、概念类 FAQ。含 frontmatter `description`(**不要**写「如何开始使用」)。**禁止**分步操作、Agent 话术块、「入口一/二」专章、逐步排障——这些属教程。**禁止**文首再写 `# 技能名`(页头已有);正文主分节用 `##`。完整契约见 [`TUTORIAL_SURFACES.md`](TUTORIAL_SURFACES.md) §0.1 / §1。 -**`TUTORIAL.md`(教程 Tab)**:按 [`TUTORIAL_SURFACES.md`](TUTORIAL_SURFACES.md) 写三入口结构(数据管理 ∥ 对话;定时有则教、无则 N/A)+ 主能力对照表 + 常见卡住。步骤必须与 `REQUIREMENTS` §0.1、`actions.json` 及宿主真实 UI 对齐;**禁止**把仅 `skill-detail` 的 Action 写成用户主路径。不要写 CLI / 目录 / 开发规范。 +**`TUTORIAL.md`(教程 Tab)**:按 [`TUTORIAL_SURFACES.md`](TUTORIAL_SURFACES.md) 写三入口结构(数据管理 ∥ 对话;定时有则教、无则 N/A)+ 主能力对照表 + 常见卡住。步骤必须与 `REQUIREMENTS` §0.1、`actions.json` 及宿主真实 UI 对齐;**禁止**把仅 `skill-detail` 的 Action 写成用户主路径。**禁止**文首 `# 技能名 · 使用教程`;正文最高用 `##`。不要写 CLI / 目录 / 开发规范。 **`DEMO.md`**:演示视频与补充说明。frontmatter 必须含 `demo_video_url`(无视频时用 `""`);正文可选。 diff --git a/development/POLICY_MATRIX.md b/development/POLICY_MATRIX.md index e934b71..84ed0d0 100644 --- a/development/POLICY_MATRIX.md +++ b/development/POLICY_MATRIX.md @@ -41,7 +41,7 @@ | 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-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-TUTORIAL-001 | 存在 `development/TUTORIAL_SURFACES.md`;`TUTORIAL.md` 须含数据管理/对话/定时/对照表骨架;`README.md` 禁止「告诉 Agent」专章与入口专章;业务技能教程与 `actions.json` placements 对齐(无 cron 须声明不需要定时) | development/TUTORIAL_SURFACES.md;development/CHECKLIST.md A2-7~A2-11 | hard | 文档存在性 + 章节/反模式扫描 + placements 对齐 | `tests/test_tutorial_surfaces.py`;`tests/test_docs_standards.py::test_tutorial_surfaces_contract_doc_and_checklist` | +| POLICY-TUTORIAL-001 | 存在 `development/TUTORIAL_SURFACES.md`;`TUTORIAL.md` 须含数据管理/对话/定时/对照表骨架;`README.md` 禁止「告诉 Agent」专章与入口专章;说明/教程正文禁止与页头重复的 `#` H1(主分节用 `##`);业务技能教程与 `actions.json` placements 对齐(无 cron 须声明不需要定时) | development/TUTORIAL_SURFACES.md;development/CHECKLIST.md A2-7~A2-12 | hard | 文档存在性 + 章节/反模式扫描 + placements 对齐 | `tests/test_tutorial_surfaces.py`;`tests/test_docs_standards.py::test_tutorial_surfaces_contract_doc_and_checklist` | | 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` | diff --git a/development/TUTORIAL_SURFACES.md b/development/TUTORIAL_SURFACES.md index a60fc33..fa9e3c8 100644 --- a/development/TUTORIAL_SURFACES.md +++ b/development/TUTORIAL_SURFACES.md @@ -28,6 +28,23 @@ README.md(能力与边界;不写步骤) **铁律:** 说明就是说明,教程就是教程。**禁止**在 README 里写分步操作、Agent 话术块、排障「点哪里」;这些一律进 `TUTORIAL.md`。 +### 0.1 标题层级(说明 / 教程共用) + +宿主详情页**已经**展示技能名;「说明 / 使用教程」Tab(及数据管理右侧教程抽屉)**已经**标明文档类型。因此: + +| 层级 | 用途 | +|------|------| +| `#` | **正文不要用**(会与页头/Tab 标题重复抢视觉) | +| `##` | 主分节(能帮你做什么、入口一:数据管理…) | +| `###` | 分节内步骤 | + +**禁止:** + +- `README.md` 文首 `# 【技能名】` / `# 审计疑点辅助` 这类与页头重复的 H1 +- `TUTORIAL.md` 文首 `# 【技能名】· 使用教程` 这类与 Tab/抽屉标题重复的 H1 + +去掉重复 H1 后,**不要**把原来的 `##` 全部升成 `#`。 + --- ## 1. README.md(说明 Tab) @@ -36,7 +53,7 @@ README.md(能力与边界;不写步骤) | 问题 | 写法 | |------|------| -| 这是什么 | 标题 + 一两句价值 | +| 这是什么 | 开篇一两句价值(**普通段落或引用**,不要再写技能名 H1) | | 能做什么 | 3~6 条能力 bullet(**无步骤编号**) | | 适合谁 / 场景 | 业务语言 | | 使用前准备 | 安装、账号、权限等**前置条件**;不写「去哪张表点哪」 | @@ -60,7 +77,7 @@ README.md(能力与边界;不写步骤) ### 1.4 建议章节(标题可微调) ```text -# 【技能中文名】 +(开篇一两句价值;不要写 # 技能名) ## 这个技能能帮你做什么 ## 适合什么场景 ## 使用前需要准备什么 @@ -77,8 +94,7 @@ README.md(能力与边界;不写步骤) 复制业务技能后,**验收章节(标题可微调,语义不可缺)**: ```text -# 【技能中文名】· 使用教程 -(开篇:数据管理与对话平行;定时有/无一句) +(开篇:数据管理与对话平行;定时有/无一句。不要写 # 技能名 · 使用教程) ## 本技能做什么 ← 业务数据流(非 CLI/SQL) ## 开始前 diff --git a/scripts/util/constants.py b/scripts/util/constants.py index ef8aa26..881a0ac 100644 --- a/scripts/util/constants.py +++ b/scripts/util/constants.py @@ -1,6 +1,6 @@ """技能标识、版本与平台公共库约束(复制后请修改 slug/version/logger)。""" SKILL_SLUG = "your-skill-slug" -SKILL_VERSION = "1.0.102" +SKILL_VERSION = "1.0.103" LOG_LOGGER_NAME = "openclaw.skill.your_skill_slug" PLATFORM_KIT_MIN_VERSION = "1.2.11" diff --git a/tests/test_docs_standards.py b/tests/test_docs_standards.py index 20b1b33..07f8345 100644 --- a/tests/test_docs_standards.py +++ b/tests/test_docs_standards.py @@ -191,6 +191,7 @@ class TestDocsStandards(unittest.TestCase): checklist = self._read("development/CHECKLIST.md") self.assertIn("A2-7", checklist) self.assertIn("A2-8", checklist) + self.assertIn("A2-12", checklist) self.assertIn("TUTORIAL_SURFACES.md", checklist) def test_naming_md_exists_and_covers_standards(self) -> None: diff --git a/tests/test_tutorial_surfaces.py b/tests/test_tutorial_surfaces.py index 3ace442..e8db72c 100644 --- a/tests/test_tutorial_surfaces.py +++ b/tests/test_tutorial_surfaces.py @@ -84,9 +84,32 @@ class TestTutorialSurfacesContract(unittest.TestCase): "定时", "skill-detail", "对照表", + "正文不要用", + "禁止", ): self.assertIn(marker, text, msg=f"TUTORIAL_SURFACES.md missing {marker!r}") + def test_market_docs_forbid_redundant_page_h1(self) -> None: + """宿主已有技能名与 Tab 标题:说明/教程正文禁止再用 # 一级标题。""" + + def strip_fences(src: str) -> str: + return re.sub(r"```.*?```", "", src, flags=re.S) + + for rel in ("README.md", "TUTORIAL.md"): + body = strip_fences(_read(rel)) + # YAML frontmatter 里不应出现 ATX H1;正文亦禁止 # + self.assertIsNone( + re.search(r"(?m)^#\s+\S", body), + msg=( + f"{rel} must not use ATX H1 (# …); host already shows skill name / tab. " + "Use ## for sections (see TUTORIAL_SURFACES.md §0.1)." + ), + ) + self.assertIsNone( + re.search(r"(?m)^#\s+.·\s*使用教程\s*$", body), + msg=f"{rel} must not start sections with '# … · 使用教程'", + ) + def test_development_md_points_to_tutorial_surfaces(self) -> None: text = _read("development/DEVELOPMENT.md") self.assertIn(