@sokeai/cli 1.0.78 → 1.0.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/install.js +8 -0
- package/scripts/run.js +3 -2
- package/skills/mono/.workbuddy/memory/2026-09-01.md +2 -0
- package/skills/mono/.workbuddy/memory/MEMORY.md +4 -0
- package/skills/mono/ARCHITECTURE_AND_EXTENSION_GUIDE.md +572 -0
- package/skills/mono/README.md +2 -0
- package/skills/mono/SKILL.md +125 -119
- package/skills/mono/SKILL_MD_/344/274/230/345/214/226/346/226/271/346/241/210.md +478 -0
- package/skills/mono/references/modules/README.md +74 -0
- package/skills/mono/references/modules/soke-ai-coach-director/CHANGELOG.md +1 -1
- package/skills/mono/references/modules/soke-ai-coach-director/MODULE.md +12 -0
- package/skills/mono/references/modules/soke-ai-coach-director/README.md +4 -1
- package/skills/mono/references/modules/soke-ai-coach-director/coaching/prompt-engineer/parts/part1-basic.md +1 -1
- package/skills/mono/references/modules/soke-ai-coach-director/coaching/prompt-optimizer/prompt-optimizer.md +3 -3
- package/skills/mono/references/modules/soke-ai-coach-director/platform/adapters/README.md +4 -2
- package/skills/mono/references/modules/soke-ai-coach-director/platform/adapters/qclaw.md +3 -1
- package/skills/mono/references/modules/soke-ai-coach-director/platform/adapters/{wukong.md → qwen.md} +18 -18
- package/skills/mono/references/modules/soke-ai-coach-director/platform/adapters/workbuddy.md +1 -1
- package/skills/mono/references/modules/soke-ai-coach-director/platform/api-fallback.md +1 -1
- package/skills/mono/references/modules/soke-ai-coach-director/platform/interaction.md +1 -1
- package/skills/mono/references/modules/soke-ai-coach-director/platform/platform-support-matrix.md +28 -0
- package/skills/mono/references/modules/soke-ai-coach-director/platform/publish-gate.md +1 -0
- package/skills/mono/references/modules/soke-ai-coach-director/platform/soke-ai-training/soke-ai-training.md +5 -3
- package/skills/mono/references/modules/soke-ai-coach-director/platform/sync-engine.md +2 -2
- package/skills/mono/references/modules/soke-ai-coach-director/references/env-check.md +3 -0
- package/skills/mono/references/modules/soke-ai-coach-director/references/exec-handbook.md +7 -7
- package/skills/mono/references/modules/soke-ai-coach-director/references/exec-part1.md +5 -5
- package/skills/mono/references/modules/soke-ai-coach-director/references/platform-api-pitfalls.md +1 -1
- package/skills/mono/references/modules/soke-ai-coach-director/references/self-learning-engine.md +4 -0
- package/skills/mono/references/modules/soke-ai-coach-director/references/subs/part1/SOP.md +2 -2
- package/skills/mono/references/modules/soke-ai-coach-director/references/subs/publish/SOP.md +3 -3
- package/skills/mono/references/modules/soke-ai-coach-director/scripts/activator.sh +4 -0
- package/skills/mono/references/modules/soke-ai-coach-director/scripts/error-detector.sh +4 -0
- package/skills/mono/references/modules/soke-ai-coach-director/scripts/extract-skill.sh +7 -0
- package/skills/mono/references/modules/soke-ai-coach-director/scripts/gate_check.py +2 -0
- package/skills/mono/references/modules/soke-ai-coach-director/scripts/validate_operations.py +9 -2
- package/skills/mono/references/modules/soke-ai-training/MODULE.md +57 -7
- package/skills/mono/references/modules/soke-assign/MODULE.md +50 -11
- package/skills/mono/references/modules/soke-certificate/MODULE.md +47 -1
- package/skills/mono/references/modules/soke-course/CHANGELOG.md +93 -0
- package/skills/mono/references/modules/soke-course/MODULE.md +110 -352
- package/skills/mono/references/modules/soke-course/README.md +45 -291
- package/skills/mono/references/modules/soke-course/cli-facts.md +107 -0
- package/skills/mono/references/modules/soke-course/intent-cases.md +41 -0
- package/skills/mono/references/modules/soke-course/scripts/check_readiness.sh +45 -0
- package/skills/mono/references/modules/soke-course/sop-publish-check.md +46 -0
- package/skills/mono/references/modules/soke-course/subs/assign/SOP.md +40 -0
- package/skills/mono/references/modules/soke-course/subs/batch/SOP.md +96 -0
- package/skills/mono/references/modules/soke-course/{references/subs → subs}/category/SOP.md +18 -27
- package/skills/mono/references/modules/soke-course/subs/charge/SOP.md +22 -0
- package/skills/mono/references/modules/soke-course/subs/copy/SOP.md +35 -0
- package/skills/mono/references/modules/soke-course/subs/exam/SOP.md +39 -0
- package/skills/mono/references/modules/soke-course/subs/phase1-create/SOP.md +66 -0
- package/skills/mono/references/modules/soke-course/subs/phase2-lesson/SOP.md +34 -0
- package/skills/mono/references/modules/soke-course/subs/photo/SOP.md +26 -0
- package/skills/mono/references/modules/soke-course/subs/publish/SOP.md +26 -0
- package/skills/mono/references/modules/soke-course/subs/query/SOP.md +36 -0
- package/skills/mono/references/modules/soke-course/{references/subs → subs}/settings/SOP.md +3 -4
- package/skills/mono/references/modules/soke-course/subs/template/SOP.md +58 -0
- package/skills/mono/references/modules/soke-exam/MODULE.md +49 -1
- package/skills/mono/references/modules/soke-exam-question-pool/MODULE.md +45 -5
- package/skills/mono/references/modules/soke-learning-map/MODULE.md +51 -11
- package/skills/mono/references/modules/soke-learning-profile/MODULE.md +46 -3
- package/skills/mono/references/modules/soke-lesson/MODULE.md +34 -20
- package/skills/mono/references/modules/soke-material/MODULE.md +33 -19
- package/skills/mono/references/modules/soke-photo-gallery/MODULE.md +40 -20
- package/skills/mono/references/modules/soke-shared/MODULE.md +9 -0
- package/skills/mono/references/modules/soke-supervisor/MODULE.md +32 -1
- package/skills/mono/references/modules/soke-task/MODULE.md +48 -1
- package/skills/mono/references/modules/soke-training-demand/MODULE.md +38 -17
- package/skills/mono/references/shared/README.md +50 -0
- package/skills/mono/references/shared/async-task.md +30 -0
- package/skills/mono/references/shared/auth-check.md +57 -0
- package/skills/mono/references/shared/command-discovery.md +34 -0
- package/skills/mono/references/shared/environment-check.md +31 -0
- package/skills/mono/references/shared/error-handling.md +27 -0
- package/skills/mono/references/shared/file-input.md +31 -0
- package/skills/mono/references/shared/interaction.md +39 -0
- package/skills/mono/references/shared/object-context.md +51 -0
- package/skills/mono/references/shared/output-policy.md +39 -0
- package/skills/mono/references/shared/pagination.md +41 -0
- package/skills/mono/references/shared/rule-ownership.md +57 -0
- package/skills/mono/references/shared/state-machine.md +35 -0
- package/skills/mono/references/shared/write-guard.md +34 -0
- package/skills/mono/references/shared/write-verify.md +33 -0
- package/skills/mono/references/workflows/README.md +115 -0
- package/skills/mono/scripts/check_package.py +310 -0
- package/skills/mono/scripts/check_readiness.py +1 -1
- package/skills/mono/scripts/check_syntax.py +35 -0
- package/skills/mono/scripts/validate_operations.py +2 -2
- package/skills/mono//357/275/223/357/275/217/357/275/213/357/275/205/357/274/215/357/275/203/357/275/214/357/275/211/346/225/264/344/275/223/346/236/266/346/236/204.html +13 -0
- package/skills/multi/soke-ai-coach-director/README.md +3 -0
- package/skills/multi/soke-ai-coach-director/assets/LEARNINGS-TEMPLATE.md +1 -0
- package/skills/multi/soke-ai-coach-director/coaching/prompt-engineer/parts/part1-basic.md +1 -1
- package/skills/multi/soke-ai-coach-director/platform/publish-gate.md +1 -0
- package/skills/multi/soke-ai-coach-director/references/exec-handbook.md +5 -5
- package/skills/multi/soke-ai-coach-director/references/exec-part1.md +5 -5
- package/skills/multi/soke-ai-coach-director/references/platform-api-pitfalls.md +1 -1
- package/skills/multi/soke-ai-coach-director/references/self-improvement-examples.md +3 -0
- package/skills/multi/soke-ai-coach-director/references/self-learning-engine.md +4 -0
- package/skills/multi/soke-ai-coach-director/references/subs/part1/SOP.md +2 -2
- package/skills/multi/soke-ai-coach-director/scripts/activator.sh +4 -0
- package/skills/multi/soke-ai-coach-director/scripts/error-detector.sh +4 -0
- package/skills/multi/soke-ai-coach-director/scripts/extract-skill.sh +7 -0
- package/skills/multi/soke-ai-coach-director/scripts/gate_check.py +2 -0
- package/skills/multi/soke-ai-coach-director/scripts/validate_operations.py +9 -2
- package/skills/multi/soke-ai-training/SKILL.md +2 -0
- package/skills/multi/soke-course/.skill-metadata.yaml +40 -0
- package/skills/multi/soke-course/CHANGELOG.md +77 -0
- package/skills/multi/soke-course/README.md +27 -274
- package/skills/multi/soke-course/SKILL.md +135 -353
- package/skills/multi/soke-course/_user_meta.json +5 -0
- package/skills/multi/soke-course/agents/openai.yaml +1 -5
- package/skills/multi/soke-course/references/cli-facts.md +105 -0
- package/skills/multi/soke-course/references/examples.md +30 -454
- package/skills/multi/soke-course/references/intent-cases.md +65 -99
- package/skills/multi/soke-course/references/sop-full-workflow.md +81 -177
- package/skills/multi/soke-course/references/sop-lesson-types.md +21 -58
- package/skills/multi/soke-course/references/sop-publish-check.md +14 -71
- package/skills/multi/soke-course/references/subs/assign/SOP.md +37 -0
- package/skills/multi/soke-course/references/subs/category/SOP.md +18 -27
- package/skills/multi/soke-course/references/subs/exam/SOP.md +28 -0
- package/skills/multi/soke-course/references/subs/lesson/SOP.md +28 -0
- package/skills/multi/soke-course/references/subs/material/SOP.md +24 -0
- package/skills/multi/soke-course/references/subs/photo/SOP.md +23 -0
- package/skills/multi/soke-course/references/subs/publish/SOP.md +15 -157
- package/skills/multi/soke-course/references/subs/query/SOP.md +22 -151
- package/skills/multi/soke-course/references/subs/settings/SOP.md +3 -4
- package/skills/multi/soke-course/references/subs/template/SOP.md +37 -210
- package/skills/multi/soke-course/references/troubleshoot.md +37 -54
- package/skills/multi/soke-course/scripts/check_readiness.sh +45 -0
- package/skills/multi/soke-course/{references/installation.md → soke-cli-install-guide.md} +3 -0
- package/skills/mono/references/modules/soke-course/agents/openai.yaml +0 -7
- package/skills/mono/references/modules/soke-course/references/course-list-courses.md +0 -216
- package/skills/mono/references/modules/soke-course/references/examples.md +0 -480
- package/skills/mono/references/modules/soke-course/references/intent-cases.md +0 -99
- package/skills/mono/references/modules/soke-course/references/sop-full-workflow.md +0 -177
- package/skills/mono/references/modules/soke-course/references/sop-lesson-types.md +0 -66
- package/skills/mono/references/modules/soke-course/references/sop-publish-check.md +0 -76
- package/skills/mono/references/modules/soke-course/references/subs/ai/SOP.md +0 -153
- package/skills/mono/references/modules/soke-course/references/subs/charge/SOP.md +0 -107
- package/skills/mono/references/modules/soke-course/references/subs/copy/SOP.md +0 -80
- package/skills/mono/references/modules/soke-course/references/subs/publish/SOP.md +0 -168
- package/skills/mono/references/modules/soke-course/references/subs/query/SOP.md +0 -165
- package/skills/mono/references/modules/soke-course/references/subs/template/SOP.md +0 -223
- package/skills/mono/references/modules/soke-course/references/troubleshoot.md +0 -68
- package/skills/multi/soke-course/examples/create-basic.md +0 -70
- package/skills/multi/soke-course/references/course-list-courses.md +0 -216
- package/skills/multi/soke-course/references/dependencies/soke-assign.md +0 -103
- package/skills/multi/soke-course/references/dependencies/soke-lesson.md +0 -119
- package/skills/multi/soke-course/references/dependencies/soke-material.md +0 -105
- package/skills/multi/soke-course/references/shared.md +0 -185
- package/skills/multi/soke-course/references/subs/ai/SOP.md +0 -153
- package/skills/multi/soke-course/scripts/check_readiness.py +0 -87
- /package/skills/mono/references/{installation.md → shared/installation.md} +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# 跨模块工作流
|
|
2
|
+
|
|
3
|
+
这里存放跨业务模块的流程编排。模块自身的字段、命令和专项限制仍以对应模块文档为准。
|
|
4
|
+
|
|
5
|
+
## 使用规则
|
|
6
|
+
|
|
7
|
+
先按用户的核心动作选择一条工作流,再读取对应模块文档。不要因为出现“课程”“素材”或“学习”等名词,就自动进入完整创建流程。
|
|
8
|
+
|
|
9
|
+
## 通用前置
|
|
10
|
+
|
|
11
|
+
所有需要访问授客平台的流程统一遵循:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
environment-check → auth-check → 业务输入检查
|
|
15
|
+
→ 执行当前操作 → 提取真实 ID → 执行依赖该 ID 的后续操作
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- 环境检测见 `../shared/environment-check.md`。
|
|
19
|
+
- 登录与企业绑定见 `../shared/auth-check.md`。
|
|
20
|
+
- 纯本地输入检查可以在环境检测前准备,但平台操作必须先完成环境和登录验证。
|
|
21
|
+
- “提取真实 ID”是上传、创建或查询成功后的结果,不要求所有操作在执行前都已有 ID。
|
|
22
|
+
- 只在必要时加载具体模块文档,避免全量读取。
|
|
23
|
+
|
|
24
|
+
## 课程与素材工作流
|
|
25
|
+
|
|
26
|
+
### 仅上传素材
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
environment-check → auth-check → 文件检查 → 上传素材 → 返回素材真实 ID
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
适用于用户只要求把视频、音频或文档放入素材库,不创建课程或课件。
|
|
33
|
+
|
|
34
|
+
入口:`../modules/soke-material/MODULE.md`。
|
|
35
|
+
|
|
36
|
+
### 已有课程添加课件
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
environment-check → auth-check → 确认 course-id
|
|
40
|
+
→ 上传素材或选择已有素材 → 获取素材真实 ID
|
|
41
|
+
→ 创建课件 → 可选排序
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
入口:
|
|
45
|
+
|
|
46
|
+
- `../modules/soke-material/MODULE.md`
|
|
47
|
+
- `../modules/soke-lesson/MODULE.md`
|
|
48
|
+
|
|
49
|
+
### 从零创建并发布课程
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
environment-check → auth-check → 课程分类 → 创建课程
|
|
53
|
+
→ 上传/选择素材 → 创建课件 → 配置课程
|
|
54
|
+
→ 发布课程 → 指派学员
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
入口:
|
|
58
|
+
|
|
59
|
+
- `../modules/soke-course/MODULE.md`
|
|
60
|
+
- `../modules/soke-material/MODULE.md`
|
|
61
|
+
- `../modules/soke-lesson/MODULE.md`
|
|
62
|
+
- `../modules/soke-assign/MODULE.md`
|
|
63
|
+
|
|
64
|
+
### 命令前缀说明
|
|
65
|
+
|
|
66
|
+
本 Mono Skill 的 CLI 命令统一使用 `soke-cli` 前缀。执行前先用当前版本的帮助确认命令和参数,不要凭文档旧例猜测:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
soke-cli --help
|
|
70
|
+
soke-cli file --help
|
|
71
|
+
soke-cli course --help
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
课程相关示例:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
soke-cli file +upload --path "/absolute/path/to/file"
|
|
78
|
+
soke-cli course +lesson-create --course-id <course-id> --title "课件标题"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
若其他资料出现 `soke file ...`、`soke course ...` 或其他旧前缀,只能视为历史写法;实际执行时统一改用 `soke-cli`,并以当前 CLI 帮助为准。
|
|
82
|
+
|
|
83
|
+
## 课程工作流的选择判断
|
|
84
|
+
|
|
85
|
+
| 用户表达 | 应选择 |
|
|
86
|
+
|---|---|
|
|
87
|
+
| “上传文件”“把视频放素材库” | 仅上传素材 |
|
|
88
|
+
| “给这门课程添加视频/课件” | 已有课程添加课件 |
|
|
89
|
+
| “创建一门课程并上传课件” | 从零创建并发布课程;是否发布需另行确认 |
|
|
90
|
+
| “从素材库添加到课程” | 已有课程添加课件;不重复上传 |
|
|
91
|
+
|
|
92
|
+
注意:上传素材和创建课件是两个不同动作。素材上传成功返回的 `uuid`、`object` 等字段,必须原样传给课件创建流程;不能用文件名或自行编造的 ID 代替。
|
|
93
|
+
|
|
94
|
+
## 考试创建与成绩查询
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
题库分类 → 创建题库 → 创建试题 → 创建试卷 → 发布试卷 → 创建考试 → 指派 → 查询成绩
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
入口:`../modules/soke-exam/MODULE.md`。
|
|
101
|
+
|
|
102
|
+
## 学习地图与统计导出
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
地图分类 → 创建地图 → 查询课程 → 创建阶段 → 发布地图 → 指派 → 创建导出任务 → 查询任务状态
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
入口:`../modules/soke-learning-map/MODULE.md`;导出任务规则见 `../modules/soke-task/MODULE.md`。
|
|
109
|
+
|
|
110
|
+
## 规则
|
|
111
|
+
|
|
112
|
+
- 跨模块流程只传递 CLI 返回的真实 ID。
|
|
113
|
+
- 发布、指派、删除、批量写入和平台同步前必须取得明确确认。
|
|
114
|
+
- 前一步未成功或缺少真实 ID 时,不得推进下一步。
|
|
115
|
+
- 具体模块文档与当前 CLI `--help` 不一致时,以当前 CLI 为准。
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Run static quality checks for the standalone Mono Skill package."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import ast
|
|
7
|
+
import re
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
OLD_COMMAND_PATTERNS = (
|
|
13
|
+
r"(?<![-\w])soke\s+(?:file|course|exam|assign|api|learning-map)\b",
|
|
14
|
+
)
|
|
15
|
+
STALE_PATHS = (
|
|
16
|
+
"references/installation.md",
|
|
17
|
+
"./references/installation.md",
|
|
18
|
+
)
|
|
19
|
+
REQUIRED_MODULE_FILES = ("references/modules/README.md",)
|
|
20
|
+
ADAPTER_DIR = "references/modules/soke-ai-coach-director/platform/adapters"
|
|
21
|
+
ADAPTER_MATRIX = "references/modules/soke-ai-coach-director/platform/platform-support-matrix.md"
|
|
22
|
+
REQUIRED_ADAPTER_FILES = ("README.md", "workbuddy.md", "qwen.md", "zework.md", "qclaw.md")
|
|
23
|
+
ADAPTER_INDEX_MARKERS = {
|
|
24
|
+
"workbuddy.md": ("WorkBuddy", "workbuddy.md"),
|
|
25
|
+
"qwen.md": ("千问", "qwen.md"),
|
|
26
|
+
"zework.md": ("Zework", "zework.md"),
|
|
27
|
+
"qclaw.md": ("QClaw", "qclaw.md"),
|
|
28
|
+
}
|
|
29
|
+
MODULE_EXCLUSIONS = {"soke-shared"}
|
|
30
|
+
MODULE_CONTRACT_GROUPS = {
|
|
31
|
+
"responsibility": ("职责", "技能定位"),
|
|
32
|
+
"input": ("输入", "使用前提", "材料完整性检查", "输入完整性", "输入包", "材料缺口"),
|
|
33
|
+
"process": ("流程", "任务类型", "推荐同步", "创建型任务流程"),
|
|
34
|
+
"business-output": ("业务产出", "完成判定", "完成条件"),
|
|
35
|
+
"failure": ("失败", "降级", "异常", "缺失规则", "错误处理"),
|
|
36
|
+
"verification": ("验证", "检查清单", "回读", "核对", "质量闸门", "完成判定"),
|
|
37
|
+
"special-cases": ("业务特例", "注意", "关键硬规则"),
|
|
38
|
+
"output": ("输出", "完成摘要"),
|
|
39
|
+
}
|
|
40
|
+
ENTRY_BUSINESS_MARKERS = (
|
|
41
|
+
"conversation_steps",
|
|
42
|
+
"scoring_rule",
|
|
43
|
+
"ai_roles[]",
|
|
44
|
+
"base_updated_at",
|
|
45
|
+
"advisor_golden_script",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
REQUIRED_SHARED_FILES = (
|
|
49
|
+
"README.md",
|
|
50
|
+
"rule-ownership.md",
|
|
51
|
+
"installation.md",
|
|
52
|
+
"environment-check.md",
|
|
53
|
+
"auth-check.md",
|
|
54
|
+
"cli-basics.md",
|
|
55
|
+
"command-discovery.md",
|
|
56
|
+
"object-context.md",
|
|
57
|
+
"pagination.md",
|
|
58
|
+
"interaction.md",
|
|
59
|
+
"write-guard.md",
|
|
60
|
+
"output-policy.md",
|
|
61
|
+
"write-verify.md",
|
|
62
|
+
"async-task.md",
|
|
63
|
+
"file-input.md",
|
|
64
|
+
"state-machine.md",
|
|
65
|
+
"error-handling.md",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def check_links(package: Path) -> list[str]:
|
|
70
|
+
failures: list[str] = []
|
|
71
|
+
pattern = re.compile(r"\]\(([^)]+)\)")
|
|
72
|
+
for path in sorted(package.rglob("*.md")):
|
|
73
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
74
|
+
for link in pattern.findall(text):
|
|
75
|
+
if link.startswith(("http://", "https://", "#", "mailto:")):
|
|
76
|
+
continue
|
|
77
|
+
target = link.split("#", 1)[0]
|
|
78
|
+
if target and not (path.parent / target).exists():
|
|
79
|
+
failures.append(f"{path.relative_to(package)} -> {target}")
|
|
80
|
+
return failures
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def check_old_commands(package: Path) -> list[str]:
|
|
84
|
+
failures: list[str] = []
|
|
85
|
+
patterns = [re.compile(pattern) for pattern in OLD_COMMAND_PATTERNS]
|
|
86
|
+
for path in sorted(package.rglob("*.md")):
|
|
87
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
88
|
+
for line_number, line in enumerate(text.splitlines(), start=1):
|
|
89
|
+
if "历史写法" in line or "旧前缀" in line:
|
|
90
|
+
continue
|
|
91
|
+
if any(pattern.search(line) for pattern in patterns):
|
|
92
|
+
failures.append(f"{path.relative_to(package)}:{line_number}")
|
|
93
|
+
return failures
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def check_stale_paths(package: Path) -> list[str]:
|
|
97
|
+
failures: list[str] = []
|
|
98
|
+
for path in sorted(package.rglob("*.md")):
|
|
99
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
100
|
+
for line_number, line in enumerate(text.splitlines(), start=1):
|
|
101
|
+
for stale_path in STALE_PATHS:
|
|
102
|
+
if stale_path in line and "references/shared/installation.md" not in line:
|
|
103
|
+
failures.append(f"{path.relative_to(package)}:{line_number} contains {stale_path}")
|
|
104
|
+
return failures
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def check_shared_files(package: Path) -> list[str]:
|
|
108
|
+
shared = package / "references" / "shared"
|
|
109
|
+
return [f"references/shared/{name}" for name in REQUIRED_SHARED_FILES if not (shared / name).is_file()]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def check_modules(package: Path) -> list[str]:
|
|
113
|
+
failures: list[str] = []
|
|
114
|
+
modules = package / "references" / "modules"
|
|
115
|
+
shared_markers = ("shared/", "../shared/")
|
|
116
|
+
for path in sorted(modules.glob("*/MODULE.md")):
|
|
117
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
118
|
+
relative = str(path.relative_to(package))
|
|
119
|
+
if path.parent.name in MODULE_EXCLUSIONS:
|
|
120
|
+
continue
|
|
121
|
+
if not any(marker in text for marker in shared_markers):
|
|
122
|
+
failures.append(f"{relative}: missing shared entrypoint")
|
|
123
|
+
if not re.search(r"共享前置|共用前置|shared/", text, re.IGNORECASE):
|
|
124
|
+
failures.append(f"{relative}: missing shared entrypoint section")
|
|
125
|
+
headings = "\n".join(
|
|
126
|
+
line.lstrip("#").strip().lower()
|
|
127
|
+
for line in text.splitlines()
|
|
128
|
+
if re.match(r"^#{2,4}\s+|^\*\*[^*]+\*\*", line)
|
|
129
|
+
)
|
|
130
|
+
missing = [
|
|
131
|
+
name for name, markers in MODULE_CONTRACT_GROUPS.items()
|
|
132
|
+
if not any(marker.lower() in headings for marker in markers)
|
|
133
|
+
]
|
|
134
|
+
for name in missing:
|
|
135
|
+
failures.append(f"{relative}: missing contract group {name}")
|
|
136
|
+
return failures
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def check_route_consistency(package: Path) -> list[str]:
|
|
140
|
+
failures: list[str] = []
|
|
141
|
+
modules_dir = package / "references" / "modules"
|
|
142
|
+
index = modules_dir / "README.md"
|
|
143
|
+
entry = package / "SKILL.md"
|
|
144
|
+
if not index.is_file() or not entry.is_file():
|
|
145
|
+
return ["route-consistency: missing SKILL.md or modules README"]
|
|
146
|
+
module_names = {
|
|
147
|
+
path.parent.name
|
|
148
|
+
for path in modules_dir.glob("*/MODULE.md")
|
|
149
|
+
if path.parent.name not in MODULE_EXCLUSIONS
|
|
150
|
+
}
|
|
151
|
+
index_text = index.read_text(encoding="utf-8", errors="replace")
|
|
152
|
+
entry_text = entry.read_text(encoding="utf-8", errors="replace")
|
|
153
|
+
for name in sorted(module_names):
|
|
154
|
+
marker = f"`{name}`"
|
|
155
|
+
link_marker = f"modules/{name}/MODULE.md"
|
|
156
|
+
if marker not in index_text:
|
|
157
|
+
failures.append(f"modules/README.md: missing module {name}")
|
|
158
|
+
if link_marker not in entry_text:
|
|
159
|
+
failures.append(f"SKILL.md: missing route link for {name}")
|
|
160
|
+
return failures
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def check_entry_bloat(package: Path) -> list[str]:
|
|
164
|
+
failures: list[str] = []
|
|
165
|
+
entry = package / "SKILL.md"
|
|
166
|
+
if not entry.is_file():
|
|
167
|
+
return ["SKILL.md: missing entrypoint"]
|
|
168
|
+
text = entry.read_text(encoding="utf-8", errors="replace")
|
|
169
|
+
for marker in ENTRY_BUSINESS_MARKERS:
|
|
170
|
+
if marker in text:
|
|
171
|
+
failures.append(f"SKILL.md: contains module-specific marker {marker}")
|
|
172
|
+
return failures
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def check_required_module_files(package: Path) -> list[str]:
|
|
176
|
+
return [name for name in REQUIRED_MODULE_FILES if not (package / name).is_file()]
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def check_platform_adapters(package: Path) -> list[str]:
|
|
180
|
+
failures: list[str] = []
|
|
181
|
+
adapter_dir = package / ADAPTER_DIR
|
|
182
|
+
matrix = package / ADAPTER_MATRIX
|
|
183
|
+
if not matrix.is_file():
|
|
184
|
+
return [f"{ADAPTER_MATRIX}: missing support matrix"]
|
|
185
|
+
matrix_text = matrix.read_text(encoding="utf-8", errors="replace")
|
|
186
|
+
for name in REQUIRED_ADAPTER_FILES:
|
|
187
|
+
if not (adapter_dir / name).is_file():
|
|
188
|
+
failures.append(f"{ADAPTER_DIR}/{name}: missing adapter file")
|
|
189
|
+
index = adapter_dir / "README.md"
|
|
190
|
+
if index.is_file():
|
|
191
|
+
text = index.read_text(encoding="utf-8", errors="replace")
|
|
192
|
+
for filename, markers in ADAPTER_INDEX_MARKERS.items():
|
|
193
|
+
if all(marker not in text for marker in markers):
|
|
194
|
+
failures.append(f"{ADAPTER_DIR}/README.md: missing index entry for {filename}")
|
|
195
|
+
if filename not in matrix_text:
|
|
196
|
+
failures.append(f"{ADAPTER_MATRIX}: missing matrix entry for {filename}")
|
|
197
|
+
for path in sorted(adapter_dir.glob("*.md")):
|
|
198
|
+
if path.name == "README.md":
|
|
199
|
+
continue
|
|
200
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
201
|
+
relative = str(path.relative_to(package))
|
|
202
|
+
if "适配器" not in text:
|
|
203
|
+
failures.append(f"{relative}: missing adapter declaration")
|
|
204
|
+
if not any(marker in text for marker in ("运行环境检测", "适配器路由")):
|
|
205
|
+
failures.append(f"{relative}: missing environment routing section")
|
|
206
|
+
business_markers = ("exec-part", "conversation_steps")
|
|
207
|
+
if any(marker in text for marker in business_markers):
|
|
208
|
+
failures.append(f"{relative}: adapter contains business-layer rules")
|
|
209
|
+
return failures
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def check_shared_duplication(package: Path) -> list[str]:
|
|
213
|
+
failures: list[str] = []
|
|
214
|
+
modules = package / "references" / "modules"
|
|
215
|
+
patterns = (
|
|
216
|
+
("pagination", re.compile(r"(?:所有|通用|统一).{0,12}(?:分页|去重)")),
|
|
217
|
+
("interaction", re.compile(r"(?:所有|通用|统一).{0,12}(?:确认|选择)(?!分类|标签)")),
|
|
218
|
+
("output-policy", re.compile(r"(?:所有|通用|统一).{0,12}(?:脱敏|不回显|不显示)")),
|
|
219
|
+
("write-verify", re.compile(r"(?:所有|通用|统一).{0,12}(?:回读|幂等|重试前)")),
|
|
220
|
+
)
|
|
221
|
+
for path in sorted(modules.glob("*/MODULE.md")):
|
|
222
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
223
|
+
if path.parent.name == "soke-shared":
|
|
224
|
+
continue
|
|
225
|
+
for line_number, line in enumerate(text.splitlines(), start=1):
|
|
226
|
+
if "共享前置" in line or "按需加载" in line or "业务特有" in line:
|
|
227
|
+
continue
|
|
228
|
+
if "标签-分类严格绑定" in line or "标签来源仅限当前分类" in line:
|
|
229
|
+
continue
|
|
230
|
+
for name, pattern in patterns:
|
|
231
|
+
if pattern.search(line):
|
|
232
|
+
failures.append(f"{name}: {path.relative_to(package)}:{line_number}")
|
|
233
|
+
return failures
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def check_auth_duplication(package: Path) -> list[str]:
|
|
237
|
+
failures: list[str] = []
|
|
238
|
+
modules = package / "references" / "modules"
|
|
239
|
+
for path in sorted(modules.glob("*/MODULE.md")):
|
|
240
|
+
if path.parent.name == "soke-shared":
|
|
241
|
+
continue
|
|
242
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
243
|
+
lines = text.splitlines()
|
|
244
|
+
for line_number, line in enumerate(lines, start=1):
|
|
245
|
+
if "auth login" in line or "config show" in line:
|
|
246
|
+
context = "\n".join(lines[max(0, line_number - 3):line_number + 2])
|
|
247
|
+
if any(marker in context for marker in ("登录失败", "未登录", "认证错误", "重新登录", "按共享层", "参见共享")):
|
|
248
|
+
continue
|
|
249
|
+
if "共享前置" not in line and "按需加载" not in line and "兼容" not in line:
|
|
250
|
+
failures.append(f"{path.relative_to(package)}:{line_number}")
|
|
251
|
+
return failures
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def check_python(package: Path) -> list[str]:
|
|
255
|
+
failures: list[str] = []
|
|
256
|
+
for path in sorted(package.rglob("*.py")):
|
|
257
|
+
try:
|
|
258
|
+
ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
|
|
259
|
+
except (OSError, SyntaxError, UnicodeError) as exc:
|
|
260
|
+
failures.append(f"{path.relative_to(package)}: {exc}")
|
|
261
|
+
return failures
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def check_cache_files(package: Path) -> list[str]:
|
|
265
|
+
return [
|
|
266
|
+
str(path.relative_to(package))
|
|
267
|
+
for path in sorted(package.rglob("*"))
|
|
268
|
+
if path.is_file() and (path.suffix == ".pyc" or path.name == "__pycache__")
|
|
269
|
+
]
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def report(name: str, failures: list[str]) -> bool:
|
|
273
|
+
if failures:
|
|
274
|
+
print(f"FAIL {name} count={len(failures)}")
|
|
275
|
+
for failure in failures[:20]:
|
|
276
|
+
print(f" - {failure}")
|
|
277
|
+
if len(failures) > 20:
|
|
278
|
+
print(f" - ... {len(failures) - 20} more")
|
|
279
|
+
return False
|
|
280
|
+
print(f"PASS {name}")
|
|
281
|
+
return True
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def main() -> int:
|
|
285
|
+
package = Path(__file__).resolve().parent.parent
|
|
286
|
+
checks = (
|
|
287
|
+
("shared-files", check_shared_files(package)),
|
|
288
|
+
("module-index", check_required_module_files(package)),
|
|
289
|
+
("platform-adapters", check_platform_adapters(package)),
|
|
290
|
+
("markdown-links", check_links(package)),
|
|
291
|
+
("stale-paths", check_stale_paths(package)),
|
|
292
|
+
("command-prefix", check_old_commands(package)),
|
|
293
|
+
("module-contracts", check_modules(package)),
|
|
294
|
+
("route-consistency", check_route_consistency(package)),
|
|
295
|
+
("entry-bloat", check_entry_bloat(package)),
|
|
296
|
+
("auth-duplication", check_auth_duplication(package)),
|
|
297
|
+
("shared-duplication", check_shared_duplication(package)),
|
|
298
|
+
("python-syntax", check_python(package)),
|
|
299
|
+
("python-cache", check_cache_files(package)),
|
|
300
|
+
)
|
|
301
|
+
passed = all(report(name, failures) for name, failures in checks)
|
|
302
|
+
if passed:
|
|
303
|
+
print("PACKAGE_CHECK_PASS")
|
|
304
|
+
return 0
|
|
305
|
+
print("PACKAGE_CHECK_FAIL")
|
|
306
|
+
return 1
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
if __name__ == "__main__":
|
|
310
|
+
sys.exit(main())
|
|
@@ -11,7 +11,7 @@ from pathlib import Path
|
|
|
11
11
|
|
|
12
12
|
def main() -> int:
|
|
13
13
|
package = Path(__file__).resolve().parent.parent
|
|
14
|
-
guide = package / "references" / "installation.md"
|
|
14
|
+
guide = package / "references" / "shared" / "installation.md"
|
|
15
15
|
executable = shutil.which("soke-cli")
|
|
16
16
|
print("🔍 soke-cli Mono Skill — 环境检查")
|
|
17
17
|
print(f" {'✅' if guide.is_file() else '❌'} 安装指南")
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Check Python syntax without writing __pycache__ files."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import ast
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main() -> int:
|
|
12
|
+
package = Path(__file__).resolve().parent.parent
|
|
13
|
+
files = sorted(package.rglob("*.py"))
|
|
14
|
+
failures: list[tuple[Path, Exception]] = []
|
|
15
|
+
|
|
16
|
+
for path in files:
|
|
17
|
+
try:
|
|
18
|
+
source = path.read_text(encoding="utf-8")
|
|
19
|
+
ast.parse(source, filename=str(path))
|
|
20
|
+
except (OSError, SyntaxError, UnicodeError) as exc:
|
|
21
|
+
failures.append((path, exc))
|
|
22
|
+
print(f"FAIL {path}: {exc}")
|
|
23
|
+
else:
|
|
24
|
+
print(f"OK {path}")
|
|
25
|
+
|
|
26
|
+
if failures:
|
|
27
|
+
print(f"Python 语法检查失败:{len(failures)} 个文件")
|
|
28
|
+
return 1
|
|
29
|
+
|
|
30
|
+
print(f"Python 语法检查通过:{len(files)} 个文件(未写入 __pycache__)")
|
|
31
|
+
return 0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == "__main__":
|
|
35
|
+
sys.exit(main())
|
|
@@ -54,8 +54,8 @@ def validate_part1(data: dict) -> list[str]:
|
|
|
54
54
|
errors.append("key_points: ❌ 被写成数组,平台会接受但字段为空。改为分号拼接的单字符串")
|
|
55
55
|
|
|
56
56
|
# scene_lang
|
|
57
|
-
if data.get("scene_lang")
|
|
58
|
-
errors.append(f"scene_lang:
|
|
57
|
+
if data.get("scene_lang") not in {"zh", "tw", "en"}:
|
|
58
|
+
errors.append(f"scene_lang: 必须是 zh、tw 或 en,当前 {data.get('scene_lang')!r}")
|
|
59
59
|
|
|
60
60
|
# scenario_cover 或 cover_url(CLI 接受两者)
|
|
61
61
|
cover = data.get("scenario_cover") or data.get("cover_url")
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html><html lang="zh-CN" data-page-node-id="giwDng1lMQa5QKK8yCk6IX"><head data-page-node-id="TgEtDCFS1kvRuFzGYBlc2E"><meta charset="utf-8" data-page-node-id="JrkCtnBihQB8AD2kxMvJ6g"><meta name="viewport" content="width=device-width, initial-scale=1" data-page-node-id="2Sx1tfupCzGyrWFUsNMAlp"><title>Soke CLI Mono 架构与子技能开发指南</title><style>:root{--ink:#182230;--muted:#64748b;--line:#d8dee8;--paper:#fff;--bg:#f4f6f9;--blue:#2563eb;--blue-soft:#eaf1ff;--teal:#0f766e;--teal-soft:#e7f7f4;--amber:#b45309;--amber-soft:#fff4df;--rose:#be123c;--rose-soft:#fff0f3;--dark:#1e293b}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;line-height:1.65}.shell{display:grid;grid-template-columns:250px minmax(0,1fr);min-height:100vh}.side{position:sticky;top:0;height:100vh;padding:28px 20px;background:#172033;color:#dbe5f5}.brand{font-size:18px;font-weight:700;color:#fff;margin-bottom:4px}.version{font-size:12px;color:#9fb0ca;margin-bottom:25px}.side a{display:block;color:#b9c8dc;text-decoration:none;font-size:13px;padding:8px 10px;border-radius:6px;margin:2px 0}.side a:hover,.side a.active{background:#2b3b57;color:#fff}.main{max-width:1180px;width:100%;margin:0 auto;padding:52px 58px 80px}.hero{background:var(--paper);border:1px solid var(--line);border-radius:12px;padding:34px 38px;margin-bottom:26px}.eyebrow{font-size:12px;color:var(--blue);font-weight:700;letter-spacing:.04em}.hero h1{font-size:34px;line-height:1.2;margin:8px 0 14px;color:#111827}.hero p{max-width:760px;color:var(--muted);margin:0}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin:18px 0 28px}.card{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:20px}.card h3{margin:0 0 6px;font-size:16px}.card p{margin:0;color:var(--muted);font-size:13px}.section{margin:34px 0}.section h2{font-size:24px;margin:0 0 14px;padding-top:10px}.section h3{font-size:17px;margin:24px 0 8px}.lead{color:var(--muted)}.flow{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:16px 0;padding:18px;background:var(--blue-soft);border:1px solid #cbdcff;border-radius:8px}.step{background:#fff;border:1px solid #b9cdfb;border-radius:6px;padding:8px 12px;font-size:13px}.arrow{color:var(--blue);font-weight:700}.layer{display:grid;grid-template-columns:150px 1fr;gap:0;border:1px solid var(--line);border-radius:8px;overflow:hidden;margin:12px 0;background:#fff}.layer strong{padding:15px;background:var(--dark);color:#fff;font-size:14px}.layer span{padding:15px;color:var(--muted);font-size:14px}.callout{border-left:4px solid var(--blue);background:var(--blue-soft);padding:14px 18px;margin:15px 0;border-radius:0 7px 7px 0}.callout.teal{border-color:var(--teal);background:var(--teal-soft)}.callout.amber{border-color:var(--amber);background:var(--amber-soft)}table{width:100%;border-collapse:collapse;background:#fff;border:1px solid var(--line);border-radius:8px;overflow:hidden;font-size:13px;margin:14px 0}th,td{text-align:left;padding:11px 13px;border-bottom:1px solid var(--line);vertical-align:top}th{background:#f0f3f8;color:#334155;font-weight:700}tr:last-child td{border-bottom:0}code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em;background:#eef2f7;padding:2px 5px;border-radius:4px;color:#334155}pre{background:#111827;color:#dbeafe;padding:17px 19px;border-radius:8px;overflow:auto;font-size:13px;line-height:1.7}ul,ol{padding-left:23px}.check{list-style:none;padding:0}.check li{padding:6px 0}.check li:before{content:"□";color:var(--blue);font-weight:700;margin-right:9px}.footer{margin-top:42px;padding-top:22px;border-top:1px solid var(--line);color:var(--muted);font-size:12px}@media(max-width:850px){.shell{display:block}.side{position:static;height:auto;padding:16px}.side nav{display:flex;gap:4px;overflow:auto}.side a{white-space:nowrap}.main{padding:24px 16px 52px}.hero{padding:25px 22px}.hero h1{font-size:28px}.grid{grid-template-columns:1fr}.layer{grid-template-columns:1fr}.layer strong{padding-bottom:8px}.layer span{padding-top:8px}}</style></head><body data-page-node-id="hBr5gBr6y2g0GxZdAJIBNn"><div class="shell" data-page-node-id="8r8xclmvTJ0stdUtApgALA"><aside class="side" data-page-node-id="5ONDK7D3MujiLqBQFXqXxV"><div class="brand" data-page-node-id="LyyqHmlQ0znRHstqxkg8uD">Soke CLI Mono</div><div class="version" data-page-node-id="I4HNFqNSZhk3CVoAaZAMR3">架构与扩展指南 · v1.0</div><nav data-page-node-id="cl9a43syiqtRoZsHaKddLj"><a href="#overview" class="active" data-page-node-id="AzNoIvBUY0qcHwv2sZxiRs">总览</a><a href="#layers" data-page-node-id="EaoCUuW5vhGnggH1YVqrDq">分层架构</a><a href="#graph" data-page-node-id="TFcXoUSoOzGvuRS9njTeV2">业务图谱</a><a href="#new" data-page-node-id="pkKXQw7qqCamsGgyAbMWNr">新增子技能</a><a href="#team" data-page-node-id="dqKe24KB6DLi8Qj5DdukSx">多人协作</a><a href="#done" data-page-node-id="lVjPGaXoEvpQ4WSrFR2t7D">完成定义</a></nav></aside><main class="main" data-page-node-id="tOex177WSBnspCDCjHsJCv"><header class="hero" id="overview" data-page-node-id="3UGjuIWEj4o0iXCx0G99lk"><div class="eyebrow" data-page-node-id="aYpL00Bu7rv9BrCCPidycy">TEAM DEVELOPMENT REFERENCE</div><h1 data-page-node-id="dGZmzs6IwY8BLVr7OOlB0I">架构与子技能开发指南</h1><p data-page-node-id="boh94yFhpQnTkwonRRjEXJ">面向后续功能开发、多人协作和代码审查的长期参考。核心目标是让每个新需求都能找到清晰归属、唯一事实源和可验证的完成标准。</p></header><div class="grid" data-page-node-id="Acm2xC9pEYEwQEqC6c5Gni"><div class="card" data-page-node-id="0UvgYzmZnbAH6AXZ1Oa8hG"><h3 data-page-node-id="NY3MUpL80tB6vl579CZUbZ">共享规则</h3><p data-page-node-id="SOk4nQlvTOGAXAhjCQDALy">认证、分页、确认、脱敏、验证等跨模块能力。</p></div><div class="card" data-page-node-id="kn1upIYiqcDMH2OkvA1hSS"><h3 data-page-node-id="pgyuGX4a8iGSoKKtbK6Rvr">业务模块</h3><p data-page-node-id="YqvlC7LaEgkPwPEzFAlZgt">围绕业务对象组织职责、输入、流程和特例。</p></div><div class="card" data-page-node-id="goTUEHYIZH3lL5hcTFfNM2"><h3 data-page-node-id="p40svXjR8ThFBQD7Rfy2wM">质量闸门</h3><p data-page-node-id="4Z1PLUocPSTZXQd4fTrL3N">通过自动检查和真实场景验收保障交付质量。</p></div></div><section class="section" id="layers" data-page-node-id="WrEzMzBZNeSVVU8OCCABZF"><h2 data-page-node-id="qQyRaEezstNyTSFcrJEM78">分层架构</h2><p class="lead" data-page-node-id="VMoCI95gHJaGtRiMvwHu9Y">每一层只解决自己的问题,避免规则重复和职责越界。</p><div class="layer" data-page-node-id="ZquIm8qjzZpxZDFfWrsjtp"><strong data-page-node-id="0UnwLNokY6yKwRiQejMEFv">入口调度层</strong><span data-page-node-id="9FoMM8aGWJ8qE9Niuyiud0"><code data-page-node-id="WVTAfxdcThrBeumsF25QyV">SKILL.md</code>:意图识别、模块路由、读取顺序、确认边界。</span></div><div class="layer" data-page-node-id="BPDKv88dkLjA9e2FqtA0vo"><strong data-page-node-id="BAxiDWEIrzjxFzDFHYRap2">共享能力层</strong><span data-page-node-id="jMEOtirCFjiP1PHaDDgUZd"><code data-page-node-id="Nzz8FEIT8K3qDNL22VCnkA">references/shared/</code>:安装、认证、对象、分页、交互、写保护、输出、异步、错误。</span></div><div class="layer" data-page-node-id="pV68pHR0V0RG8DlYo9Pzv2"><strong data-page-node-id="OBAFgL33r6Sesm7v3GVsua">业务模块层</strong><span data-page-node-id="G9jvTLxXCn2nGzB656GWqB"><code data-page-node-id="r4siLY3OIFfxZcGzd3SXKU">references/modules/</code>:课程、考试、地图、指派、AI 教练、AI 陪练等业务对象。</span></div><div class="layer" data-page-node-id="puBHsQUhSCZ3SqT5rPP3bT"><strong data-page-node-id="Yd0rOYJliphPZFPTohknWz">工作流层</strong><span data-page-node-id="WdbekBCV3evDeSDLgIAxsO"><code data-page-node-id="HNTPA5Eh3FQQcw7iEKqa7H">references/workflows/</code>:描述多个模块之间的对象交接,不复制内部规则。</span></div><div class="layer" data-page-node-id="fx4t6yTIc9PpPpNErEJJvi"><strong data-page-node-id="6uuEY50GSP7dNsgzVEPCLO">平台适配层</strong><span data-page-node-id="Yj9BG5JuUyHOcV156k78Ht"><code data-page-node-id="LRjEQ1mmD928psOqv4FNK7">platform/adapters/</code>:WorkBuddy、千问、Zework、QClaw 和通用降级。</span></div><div class="layer" data-page-node-id="eEWvMfyJ6qihlf6oj7oVqc"><strong data-page-node-id="pRg52H4BScmpgbzAtWBFCe">质量保障层</strong><span data-page-node-id="BSRFRDfFZwjnFVqskhJZXp"><code data-page-node-id="87UBBuPG1tSRQRu6xUOq13">scripts/</code>:包结构、链接、命令、入口、矩阵和语法检查。</span></div><div class="callout" data-page-node-id="jpi21HFD5ArGFRDj4TpZkO"><strong data-page-node-id="73NNBGvzUWmj6jA3EsjxY5">边界原则:</strong>共享规则只定义通用约束,模块只保留业务差异,工作流只定义对象交接,适配器只处理平台差异。</div></section><section class="section" id="graph" data-page-node-id="UBY2g5sA518yL239SYyPSH"><h2 data-page-node-id="HTSDTz25YZM5wfeXtfmRU2">业务知识图谱</h2><h3 data-page-node-id="BcfOQ0TeSRkO3EaDQX0dNp">课程链路</h3><div class="flow" data-page-node-id="SAABExsHL0rkseJTGxFNPB"><span class="step" data-page-node-id="kk5VtxAltHqcZvIGOlJXSr">素材上传</span><span class="arrow" data-page-node-id="h8bB8jokSjiZMLKuHfzZIW">→</span><span class="step" data-page-node-id="CoEQpduHe84TDLuEwzyTaU">课件创建</span><span class="arrow" data-page-node-id="RFV8htB44MxH1HrNMyQeGG">→</span><span class="step" data-page-node-id="Tq5UqksDXnf3xV4dlhNePi">课程配置与发布</span><span class="arrow" data-page-node-id="nQ53pFphwEiSvIpoO6rcgF">→</span><span class="step" data-page-node-id="yxgMmWQrdw1XNiWFxOkp02">学习对象指派</span></div><p class="lead" data-page-node-id="nOxJUhGawHWGvHjviqSrOx"><code data-page-node-id="BBYVJc3EwUgdXUisriyW9d">soke-material</code> 的真实素材 ID 是 <code data-page-node-id="rnxqv6tcvvTMS74NvAZ5XW">soke-lesson</code> 的输入,发布后的课程再交给 <code data-page-node-id="s0lFjMwojqypqm4C62pVnn">soke-assign</code>。</p><h3 data-page-node-id="dEK570LEeRc6O99IDI0yu0">考试与学习路径</h3><div class="flow" data-page-node-id="y5GetxBR6zSLtcjaTxHjiq"><span class="step" data-page-node-id="1Syzp3AzpmduEF8aUR5DtM">题库与试卷</span><span class="arrow" data-page-node-id="cKaJlguetpZW8hhFge7xFd">→</span><span class="step" data-page-node-id="ZH475n1nMNulXcE8XzcLUn">考试发布</span><span class="arrow" data-page-node-id="CFCOOGw9zR1IGBSMhCJ11r">→</span><span class="step" data-page-node-id="yrTYvC20p7EnixQ5Gusga2">指派</span><span class="arrow" data-page-node-id="o2uVtTYVctYFPPwGG2kJWx">→</span><span class="step" data-page-node-id="cOQE6ahOb9IZlAJuAeDtVe">成绩或练习分析</span></div><h3 data-page-node-id="Lq3MOCPJJfBXJGReHAmja2">AI 链路</h3><div class="flow" data-page-node-id="BZiZKr3XGkrQEBUHxG7Y1Z"><span class="step" data-page-node-id="XCeJjqa1nn8HJY9CTroNts">原始材料</span><span class="arrow" data-page-node-id="VlIDpSLG3noC3Yxqb98Glb">→</span><span class="step" data-page-node-id="Ula23fEbhAIEGU4NHgnhDY">一次提炼</span><span class="arrow" data-page-node-id="bNUvLaXvVW0Fb3ISgrl6VX">→</span><span class="step" data-page-node-id="FuNtkwS2zoohT2nFQY5cJ1">AI 陪练 Part1-Part5</span><span class="arrow" data-page-node-id="6tkUw3juOuhOEmnwmJDB44">→</span><span class="step" data-page-node-id="D2BPoOFLO3a1Mhpop5fJ6W">同步、闸门、发布</span><span class="arrow" data-page-node-id="9kCNqqpiHmRegnX85jbGUG">→</span><span class="step" data-page-node-id="waGDjvCbVZMmkh7a3yDMjm">知识包绑定</span></div><div class="callout teal" data-page-node-id="4Ub1yxmifViToph92UiTQS"><strong data-page-node-id="aa1ACwJn3p0M7BoC8o4Erz">知识包边界:</strong><code data-page-node-id="VC4MnEmtAeMCkwwAwWdFCY">soke-ai-coach-director</code> 负责原始材料提炼和陪练场景,<code data-page-node-id="WdgNNU7q7hDFPv9PYdbHHr">soke-ai-training</code> 复用提炼稿,负责 source、entries、版本和绑定,不做二次提炼。</div></section><section class="section" id="new" data-page-node-id="3BhSyVEea9DDFkGKIhLav7"><h2 data-page-node-id="veQ7fpE9a2o68bTovtwCmc">新增子技能</h2><h3 data-page-node-id="rNA9c7dEXNzpo5wESzzjgE">先判断归属层</h3><table data-page-node-id="MjrVxqgaK3wuDfAwpPFDXd"><thead data-page-node-id="rZHJSPhWE0BjMUMGTujMYg"><tr data-page-node-id="LpWI0AFxJluOTNLbpGWLlF"><th data-page-node-id="WxmYuaPzKmZaNpG7vZq7Yv">需求特征</th><th data-page-node-id="EALHHpfARXtpiv3WcqFYVB">放置位置</th></tr></thead><tbody data-page-node-id="wwQVck3OzZbsd7ERBvktQd"><tr data-page-node-id="VW2mV6I3T8bZ0HunI7VXHx"><td data-page-node-id="txSxg19BthpJLLBqnXLB5S">多个模块复用的通用能力</td><td data-page-node-id="ua9wJeCGacPEYHKiwkobw7"><code data-page-node-id="V4fLhIofsUMEIc1E75Rbai">references/shared/</code></td></tr><tr data-page-node-id="NiIbpxXqfM3ksx3OJekCRV"><td data-page-node-id="HVkZ0oxfLaIuaCAA4yjwaw">已有业务对象的新动作</td><td data-page-node-id="pem6sF4Jmiy1WkrZKGvuBe">修改现有模块</td></tr><tr data-page-node-id="mrvucDZUNpvdEO70W8hCCB"><td data-page-node-id="OrQHsndeHbfeocPjFyVuVb">新的业务对象</td><td data-page-node-id="fvEhChEvSqWU0GGlGBBM1T">新建 <code data-page-node-id="exz5sElw7xTfBac3BDwvcd">references/modules/soke-xxx/</code></td></tr><tr data-page-node-id="HXB23MLSv8MXdAeggxvITF"><td data-page-node-id="C5SSrhIFAZe3Znvs6ezbYN">两个以上模块串联</td><td data-page-node-id="cEfpbLSiIz1dqg08axPzsp"><code data-page-node-id="CkyAIt1Twy8lxdAuKhd3Wr">references/workflows/</code></td></tr><tr data-page-node-id="ffX8mJchTVzF6pjAV5Uy52"><td data-page-node-id="lfct0GkdnJikF6ogyEQCtY">平台显示、交互或命令差异</td><td data-page-node-id="lTD1L9I2pipupC11Hvkv0O">平台适配器</td></tr><tr data-page-node-id="3ZnRT6zQJba6oqpJfS35O0"><td data-page-node-id="5T5GxguycDeaFu8veRfzEq">可自动验证的约束</td><td data-page-node-id="w9WheTCXbHDWQLK7JGsCRB"><code data-page-node-id="vtcMia9eiUdu8wBkFEClcB">scripts/</code></td></tr></tbody></table><h3 data-page-node-id="CnFEXrV2FcSlJYIY1NyOOx">九步开发法</h3><ol data-page-node-id="JPT9Afgja4CYKHHiZ3ASOk"><li data-page-node-id="vUWdepQ4eAfsYTj7DcBMgP">写清需求边界:谁、对什么对象、做什么动作、得到什么结果。</li><li data-page-node-id="RV0q98CrbpK0yfPRO9eYQi">确认对象与状态:输入、父对象、状态变化、真实 ID、幂等性。</li><li data-page-node-id="1jRWdA7U7yatwQy1GUt51V">选择归属层:共享、现有模块、新模块、工作流、适配器或检查器。</li><li data-page-node-id="TFJYlTQfud3L0EyDix9ali">查询当前 CLI 帮助:<code data-page-node-id="jaKE4bRQeuVqerBNJY6h4B">soke-cli --help</code>、父命令帮助、叶子命令帮助。</li><li data-page-node-id="qeSD6sjsnBIQup85QPzo9c">实现最小闭环:前置检查 → 查询 ID → 确认 → 执行 → 验证 → 输出。</li><li data-page-node-id="KoVn8FCWD5x5dpG1ca84eF">接入入口和索引:更新 <code data-page-node-id="GZ0n9GcaOGdUscdyfXMLd8">SKILL.md</code> 与模块责任矩阵。</li><li data-page-node-id="mg0fzV8lRAstYzmk5Gv5ER">补充专项规则:只保留字段、状态、红线和异常特例。</li><li data-page-node-id="f57PeavpPcGhPUFbqhDiTg">加入自动检查:文件、链接、路径、命令、入口、重复规则和语法。</li><li data-page-node-id="ybCqR9YkniRkQ7H5rrvirr">完成真实场景验收:从用户输入走到最终输出。</li></ol><h3 data-page-node-id="b7Gv8C2nZ9vYpdNGkjvotd">标准模块入口</h3><pre data-page-node-id="Jx1mY6zzNBowH3gFLnfoK0"># soke-new-feature
|
|
2
|
+
|
|
3
|
+
## 共享前置
|
|
4
|
+
## 职责
|
|
5
|
+
## 不负责
|
|
6
|
+
## 输入
|
|
7
|
+
## 流程
|
|
8
|
+
## 业务特例
|
|
9
|
+
## 输出</pre></section><section class="section" id="team" data-page-node-id="d3VYQLYzAt0eWlNh9qwSCk"><h2 data-page-node-id="GKpa9zUfBtABhUwkyE5U4M">多人协作</h2><table data-page-node-id="vCkaFp5zA8FYEJV09OwNtC"><thead data-page-node-id="V6tNCg56HMFb1OsKx9EDkT"><tr data-page-node-id="jhRvfzPBRR3BfSgpHZhidt"><th data-page-node-id="mtMSADRfBTrV9kiCcVfuSL">角色</th><th data-page-node-id="BItHgaKZ2ic54hHfm5uNuD">负责范围</th></tr></thead><tbody data-page-node-id="wUUpil19MMtAtg2ExHnCsw"><tr data-page-node-id="18dzPu19rkyz45Pe956Dr9"><td data-page-node-id="6hWvurXnqpkpP3oczaihWz">架构维护者</td><td data-page-node-id="XOnaYibc0axdhTmVWA5yIP"><code data-page-node-id="1CjIVrkctLqqxjOGG0K2Qv">SKILL.md</code>、共享规则、唯一来源矩阵</td></tr><tr data-page-node-id="4U4reJFx3exoSjh81Ivosy"><td data-page-node-id="AFMMnAKO31o3vYbofQSoD5">业务开发者</td><td data-page-node-id="ABGLaGTdcTPwuFWi4fXbGd">单个业务模块目录</td></tr><tr data-page-node-id="sfRUCkep3yCDGbGf580yWJ"><td data-page-node-id="Gr8SEsO5tT0vrR7xM1NnKJ">工作流开发者</td><td data-page-node-id="2V3C1U7PUGCkEzx2UmYIwJ">跨模块流程和交接契约</td></tr><tr data-page-node-id="a9zpBuZc25C4DQ0lY0JSB8"><td data-page-node-id="pLnqS4kDoshivWS8QEbWjF">平台开发者</td><td data-page-node-id="sTshb4uexItvlh03djXGKH">单个平台适配器和支持矩阵</td></tr><tr data-page-node-id="uvOhtksLZJ4OwntYvf7Jmj"><td data-page-node-id="qkv1v6AxB5usMPHDb3CmSv">质量维护者</td><td data-page-node-id="1lp7y28c0lgY9sLUIm3lMH"><code data-page-node-id="xPixrKQ0u94Wa9lgQ6qrRs">check_package.py</code> 和检查规则</td></tr><tr data-page-node-id="3UwFSLCZyudfKvGLB6ozbf"><td data-page-node-id="ox8UMqW0jeoTOEl9xNJ1Yp">验收人员</td><td data-page-node-id="8eAZRswAnsQx7iXacTOsm1">CLI 帮助、真实场景和回归验证</td></tr></tbody></table><div class="callout amber" data-page-node-id="Op4hjfdAUDptMW1G2P52Tq"><strong data-page-node-id="tR47VF8Rviw8d8yFYrw2rA">协作红线:</strong>同一时间尽量不要多人修改同一个入口文件。若两人同时修改共享规则、两个模块争夺同一对象,或检查器与业务特例冲突,应先建立唯一事实源再继续。</div><h3 data-page-node-id="ftuxYAUh0sS3UZG6mZo9RN">开发前声明</h3><pre data-page-node-id="gBRBGmUOegituWg62PME04">修改文件:
|
|
10
|
+
不修改文件:
|
|
11
|
+
依赖模块:
|
|
12
|
+
验收命令:</pre><h3 data-page-node-id="VVKHm4QGMGDAuAY82lydCw">合并前命令</h3><pre data-page-node-id="1NLuLCca9sAU7b7KumPjwc">/Users/edy/.workbuddy/binaries/python/versions/3.13.12/bin/python3 skills/mono/scripts/check_package.py
|
|
13
|
+
git diff --check</pre></section><section class="section" id="done" data-page-node-id="3xh6FXGiDSbZQ0bItCBHbp"><h2 data-page-node-id="u6IaLWDdr1LHqUK0vXr7Ds">完成定义</h2><ul class="check" data-page-node-id="wbba9yBsn76PFfdd8qUBJV"><li data-page-node-id="UkEAvj0Fim04MrAYkoJjqu">业务对象和职责边界已定义。</li><li data-page-node-id="LFOcoshvBfUKTSFcHIzvH5">归属层级已确定,不重复已有能力。</li><li data-page-node-id="2MxghxOszQ2XfrMPTOeqwj">模块入口符合标准结构。</li><li data-page-node-id="h46s2uKubsUfWH9EEywr5R">真实 ID 来源和状态变化明确。</li><li data-page-node-id="7bQn1ADDqSkgp85Fa55DUo">写操作有确认、验证和幂等策略。</li><li data-page-node-id="AtTYlRAova1jTvb0mSlL0A">入口路由、模块矩阵和工作流已更新。</li><li data-page-node-id="oCxHmNIk5myJfWb1OCtYXA">机器检查通过。</li><li data-page-node-id="P9MDiYmBAMuDEz2BBtR3Kr"><code data-page-node-id="IOqmxF6WOiBzFHfJCd5GUC">git diff --check</code> 通过。</li><li data-page-node-id="wxjf0ab6FEYAj9CCHunZNM">至少完成一条真实场景验收。</li><li data-page-node-id="9SwE0JW33gaVJFEPgcA8RZ">变更范围和剩余风险已记录。</li></ul><div class="footer" data-page-node-id="FxzHq4ATuOKVbwuW9IFovi">唯一原则:先判层级,再定边界;先定义对象,再选命令;先复用共享,再写特例;先完成闭环,再扩展异常。</div></section></main></div></body></html>
|
|
@@ -14,6 +14,7 @@ Corrections, insights, and knowledge gaps captured during development.
|
|
|
14
14
|
| `in_progress` | Actively being worked on |
|
|
15
15
|
| `resolved` | Issue fixed or knowledge integrated |
|
|
16
16
|
| `wont_fix` | Decided not to address (reason in Resolution) |
|
|
17
|
+
| `promoted` | Elevated to CLAUDE.md, AGENTS.md, or copilot-instructions.md |
|
|
17
18
|
| `promoted_to_skill` | Extracted as a reusable skill |
|
|
18
19
|
|
|
19
20
|
## Skill Extraction Fields
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
- 每条都能在 Part4 中找到对应评分维度
|
|
24
24
|
- 不写空泛价值观,必须写成可观察行为或明确结果
|
|
25
25
|
5. **考核关键点是 `step1-create.json.key_points` 的直接来源**:Part1 确认后生成 `step1-create.json` 时,必须将考核关键点拼接为单个字符串写入 `key_points`(多条用分号或编号拼接,不能是数组)
|
|
26
|
-
6. **`scene_lang`
|
|
26
|
+
6. **`scene_lang` 必须是语言代码**:仅支持 `zh`(简体中文)、`tw`(繁体中文)、`en`(英文)。→ 直接来源 `step1-create.json.scene_lang`
|
|
27
27
|
|
|
28
28
|
#### 推荐输出格式
|
|
29
29
|
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"description": "<场景描述全文,完整搬运不缩略>",
|
|
26
26
|
"tags": ["标签1", "标签2", "标签3"],
|
|
27
27
|
"key_points": "1) 考核点1;2) 考核点2;3) 考核点3",
|
|
28
|
-
"scene_lang": "
|
|
28
|
+
"scene_lang": "zh",
|
|
29
29
|
"scenario_cover": "https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png"
|
|
30
30
|
}
|
|
31
31
|
```
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
| `description` | string | Part1 场景描述全文,禁缩略 | 只写首句摘要 |
|
|
39
39
|
| `tags` | string[] | 3-5 个数组元素 | ❌ 逗号分隔字符串 |
|
|
40
40
|
| `key_points` | **string** | 多条用分号/编号拼成**单字符串** | ❌ 写成数组(平台会接受但字段为空) |
|
|
41
|
-
| `scene_lang` | string |
|
|
41
|
+
| `scene_lang` | string | 仅支持 `zh`、`tw`、`en`(分别为简体中文、繁体中文、英文) | ❌ `"简体中文"` / `"zh-CN"` / `"中文"` |
|
|
42
42
|
| `scenario_cover` | string | 固定默认图 URL | ❌ 占位/本地路径 |
|
|
43
43
|
|
|
44
44
|
### 提交前断言(Python 表达式)
|
|
@@ -48,7 +48,7 @@ assert isinstance(data["name"], str) and 1 <= len(data["name"]) <= 100
|
|
|
48
48
|
assert isinstance(data["description"], str) and len(data["description"]) >= 20
|
|
49
49
|
assert isinstance(data["tags"], list) and 3 <= len(data["tags"]) <= 5
|
|
50
50
|
assert isinstance(data["key_points"], str) and len(data["key_points"]) > 0 # 必须是字符串
|
|
51
|
-
assert data["scene_lang"]
|
|
51
|
+
assert data["scene_lang"] in {"zh", "tw", "en"}
|
|
52
52
|
assert data["scenario_cover"] == "https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png"
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -67,9 +67,9 @@ assert data["scenario_cover"] == "https://newsokeeditorcdn.soke.cn/public/ai/cov
|
|
|
67
67
|
"tags": "展会拓客,B2B销售,快速识别"
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
❌ 案例 C:scene_lang
|
|
70
|
+
❌ 案例 C:scene_lang 使用不支持的展示名称或区域码
|
|
71
71
|
{
|
|
72
|
-
"scene_lang": "
|
|
72
|
+
"scene_lang": "简体中文"
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
❌ 案例 D:封面留空或写占位 URL
|