@sokeai/cli 1.0.79 → 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.
Files changed (128) hide show
  1. package/package.json +1 -1
  2. package/scripts/install.js +8 -0
  3. package/scripts/run.js +3 -2
  4. package/skills/mono/.workbuddy/memory/2026-09-01.md +2 -0
  5. package/skills/mono/.workbuddy/memory/MEMORY.md +4 -0
  6. package/skills/mono/ARCHITECTURE_AND_EXTENSION_GUIDE.md +572 -0
  7. package/skills/mono/README.md +2 -0
  8. package/skills/mono/SKILL.md +125 -119
  9. package/skills/mono/SKILL_MD_/344/274/230/345/214/226/346/226/271/346/241/210.md +478 -0
  10. package/skills/mono/references/modules/README.md +74 -0
  11. package/skills/mono/references/modules/soke-ai-coach-director/CHANGELOG.md +1 -1
  12. package/skills/mono/references/modules/soke-ai-coach-director/MODULE.md +12 -0
  13. package/skills/mono/references/modules/soke-ai-coach-director/README.md +1 -1
  14. package/skills/mono/references/modules/soke-ai-coach-director/coaching/prompt-optimizer/prompt-optimizer.md +3 -3
  15. package/skills/mono/references/modules/soke-ai-coach-director/platform/adapters/README.md +4 -2
  16. package/skills/mono/references/modules/soke-ai-coach-director/platform/adapters/qclaw.md +3 -1
  17. package/skills/mono/references/modules/soke-ai-coach-director/platform/adapters/{wukong.md → qwen.md} +18 -18
  18. package/skills/mono/references/modules/soke-ai-coach-director/platform/adapters/workbuddy.md +1 -1
  19. package/skills/mono/references/modules/soke-ai-coach-director/platform/api-fallback.md +1 -1
  20. package/skills/mono/references/modules/soke-ai-coach-director/platform/interaction.md +1 -1
  21. package/skills/mono/references/modules/soke-ai-coach-director/platform/platform-support-matrix.md +28 -0
  22. package/skills/mono/references/modules/soke-ai-coach-director/platform/soke-ai-training/soke-ai-training.md +5 -3
  23. package/skills/mono/references/modules/soke-ai-coach-director/platform/sync-engine.md +2 -2
  24. package/skills/mono/references/modules/soke-ai-coach-director/references/env-check.md +3 -0
  25. package/skills/mono/references/modules/soke-ai-coach-director/references/exec-handbook.md +2 -2
  26. package/skills/mono/references/modules/soke-ai-coach-director/references/subs/publish/SOP.md +3 -3
  27. package/skills/mono/references/modules/soke-ai-training/MODULE.md +55 -7
  28. package/skills/mono/references/modules/soke-assign/MODULE.md +50 -11
  29. package/skills/mono/references/modules/soke-certificate/MODULE.md +47 -1
  30. package/skills/mono/references/modules/soke-course/CHANGELOG.md +93 -0
  31. package/skills/mono/references/modules/soke-course/MODULE.md +110 -352
  32. package/skills/mono/references/modules/soke-course/README.md +45 -291
  33. package/skills/mono/references/modules/soke-course/cli-facts.md +107 -0
  34. package/skills/mono/references/modules/soke-course/intent-cases.md +41 -0
  35. package/skills/mono/references/modules/soke-course/scripts/check_readiness.sh +45 -0
  36. package/skills/mono/references/modules/soke-course/sop-publish-check.md +46 -0
  37. package/skills/mono/references/modules/soke-course/subs/assign/SOP.md +40 -0
  38. package/skills/mono/references/modules/soke-course/subs/batch/SOP.md +96 -0
  39. package/skills/mono/references/modules/soke-course/{references/subs → subs}/category/SOP.md +18 -27
  40. package/skills/mono/references/modules/soke-course/subs/charge/SOP.md +22 -0
  41. package/skills/mono/references/modules/soke-course/subs/copy/SOP.md +35 -0
  42. package/skills/mono/references/modules/soke-course/subs/exam/SOP.md +39 -0
  43. package/skills/mono/references/modules/soke-course/subs/phase1-create/SOP.md +66 -0
  44. package/skills/mono/references/modules/soke-course/subs/phase2-lesson/SOP.md +34 -0
  45. package/skills/mono/references/modules/soke-course/subs/photo/SOP.md +26 -0
  46. package/skills/mono/references/modules/soke-course/subs/publish/SOP.md +26 -0
  47. package/skills/mono/references/modules/soke-course/subs/query/SOP.md +36 -0
  48. package/skills/mono/references/modules/soke-course/{references/subs → subs}/settings/SOP.md +3 -4
  49. package/skills/mono/references/modules/soke-course/subs/template/SOP.md +58 -0
  50. package/skills/mono/references/modules/soke-exam/MODULE.md +49 -1
  51. package/skills/mono/references/modules/soke-exam-question-pool/MODULE.md +45 -5
  52. package/skills/mono/references/modules/soke-learning-map/MODULE.md +51 -11
  53. package/skills/mono/references/modules/soke-learning-profile/MODULE.md +46 -3
  54. package/skills/mono/references/modules/soke-lesson/MODULE.md +34 -20
  55. package/skills/mono/references/modules/soke-material/MODULE.md +33 -19
  56. package/skills/mono/references/modules/soke-photo-gallery/MODULE.md +40 -20
  57. package/skills/mono/references/modules/soke-shared/MODULE.md +9 -0
  58. package/skills/mono/references/modules/soke-supervisor/MODULE.md +32 -1
  59. package/skills/mono/references/modules/soke-task/MODULE.md +48 -1
  60. package/skills/mono/references/modules/soke-training-demand/MODULE.md +38 -17
  61. package/skills/mono/references/shared/README.md +50 -0
  62. package/skills/mono/references/shared/async-task.md +30 -0
  63. package/skills/mono/references/shared/auth-check.md +57 -0
  64. package/skills/mono/references/shared/command-discovery.md +34 -0
  65. package/skills/mono/references/shared/environment-check.md +31 -0
  66. package/skills/mono/references/shared/error-handling.md +27 -0
  67. package/skills/mono/references/shared/file-input.md +31 -0
  68. package/skills/mono/references/shared/interaction.md +39 -0
  69. package/skills/mono/references/shared/object-context.md +51 -0
  70. package/skills/mono/references/shared/output-policy.md +39 -0
  71. package/skills/mono/references/shared/pagination.md +41 -0
  72. package/skills/mono/references/shared/rule-ownership.md +57 -0
  73. package/skills/mono/references/shared/state-machine.md +35 -0
  74. package/skills/mono/references/shared/write-guard.md +34 -0
  75. package/skills/mono/references/shared/write-verify.md +33 -0
  76. package/skills/mono/references/workflows/README.md +115 -0
  77. package/skills/mono/scripts/check_package.py +310 -0
  78. package/skills/mono/scripts/check_readiness.py +1 -1
  79. package/skills/mono/scripts/check_syntax.py +35 -0
  80. 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
  81. package/skills/multi/soke-course/.skill-metadata.yaml +40 -0
  82. package/skills/multi/soke-course/CHANGELOG.md +77 -0
  83. package/skills/multi/soke-course/README.md +27 -274
  84. package/skills/multi/soke-course/SKILL.md +135 -353
  85. package/skills/multi/soke-course/_user_meta.json +5 -0
  86. package/skills/multi/soke-course/agents/openai.yaml +1 -5
  87. package/skills/multi/soke-course/references/cli-facts.md +105 -0
  88. package/skills/multi/soke-course/references/examples.md +30 -454
  89. package/skills/multi/soke-course/references/intent-cases.md +65 -99
  90. package/skills/multi/soke-course/references/sop-full-workflow.md +81 -177
  91. package/skills/multi/soke-course/references/sop-lesson-types.md +21 -58
  92. package/skills/multi/soke-course/references/sop-publish-check.md +14 -71
  93. package/skills/multi/soke-course/references/subs/assign/SOP.md +37 -0
  94. package/skills/multi/soke-course/references/subs/category/SOP.md +18 -27
  95. package/skills/multi/soke-course/references/subs/exam/SOP.md +28 -0
  96. package/skills/multi/soke-course/references/subs/lesson/SOP.md +28 -0
  97. package/skills/multi/soke-course/references/subs/material/SOP.md +24 -0
  98. package/skills/multi/soke-course/references/subs/photo/SOP.md +23 -0
  99. package/skills/multi/soke-course/references/subs/publish/SOP.md +15 -157
  100. package/skills/multi/soke-course/references/subs/query/SOP.md +22 -151
  101. package/skills/multi/soke-course/references/subs/settings/SOP.md +3 -4
  102. package/skills/multi/soke-course/references/subs/template/SOP.md +37 -210
  103. package/skills/multi/soke-course/references/troubleshoot.md +37 -54
  104. package/skills/multi/soke-course/scripts/check_readiness.sh +45 -0
  105. package/skills/multi/soke-course/{references/installation.md → soke-cli-install-guide.md} +3 -0
  106. package/skills/mono/references/modules/soke-course/agents/openai.yaml +0 -7
  107. package/skills/mono/references/modules/soke-course/references/course-list-courses.md +0 -216
  108. package/skills/mono/references/modules/soke-course/references/examples.md +0 -480
  109. package/skills/mono/references/modules/soke-course/references/intent-cases.md +0 -99
  110. package/skills/mono/references/modules/soke-course/references/sop-full-workflow.md +0 -177
  111. package/skills/mono/references/modules/soke-course/references/sop-lesson-types.md +0 -66
  112. package/skills/mono/references/modules/soke-course/references/sop-publish-check.md +0 -76
  113. package/skills/mono/references/modules/soke-course/references/subs/ai/SOP.md +0 -153
  114. package/skills/mono/references/modules/soke-course/references/subs/charge/SOP.md +0 -107
  115. package/skills/mono/references/modules/soke-course/references/subs/copy/SOP.md +0 -80
  116. package/skills/mono/references/modules/soke-course/references/subs/publish/SOP.md +0 -168
  117. package/skills/mono/references/modules/soke-course/references/subs/query/SOP.md +0 -165
  118. package/skills/mono/references/modules/soke-course/references/subs/template/SOP.md +0 -223
  119. package/skills/mono/references/modules/soke-course/references/troubleshoot.md +0 -68
  120. package/skills/multi/soke-course/examples/create-basic.md +0 -70
  121. package/skills/multi/soke-course/references/course-list-courses.md +0 -216
  122. package/skills/multi/soke-course/references/dependencies/soke-assign.md +0 -103
  123. package/skills/multi/soke-course/references/dependencies/soke-lesson.md +0 -119
  124. package/skills/multi/soke-course/references/dependencies/soke-material.md +0 -105
  125. package/skills/multi/soke-course/references/shared.md +0 -185
  126. package/skills/multi/soke-course/references/subs/ai/SOP.md +0 -153
  127. package/skills/multi/soke-course/scripts/check_readiness.py +0 -87
  128. /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())
@@ -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>
@@ -0,0 +1,40 @@
1
+ examples:
2
+ - id: create-and-publish
3
+ title:
4
+ zh: 创建课程并发布
5
+ description:
6
+ zh: 从零创建一门线上课,走完课件、发布全流程
7
+ prompt:
8
+ zh: |-
9
+ 帮我创建一门线上课:
10
+
11
+ 课程标题:{{课程标题}}
12
+ 课程分类:{{可选,分类名称}}
13
+
14
+ 创建完成后引导我添加课件并发布。
15
+ - id: add-courseware
16
+ title:
17
+ zh: 给课程加课件
18
+ description:
19
+ zh: 给已有课程添加视频/音频/文档/图片/小测验课件
20
+ prompt:
21
+ zh: |-
22
+ 给课程「{{课程名称}}」添加课件:
23
+
24
+ 素材:{{本地文件路径或"从素材库选择"或"小测验/图片"}}
25
+ - id: publish-and-assign
26
+ title:
27
+ zh: 发布并指派学员
28
+ description:
29
+ zh: 对已有课程执行发布校验、发布,并指派给部门
30
+ prompt:
31
+ zh: |-
32
+ 把课程「{{课程名称}}」发布,并指派给{{部门名称}},{{必修|选修}}。
33
+ - id: query-progress
34
+ title:
35
+ zh: 查学习进度
36
+ description:
37
+ zh: 查询课程完成率、学员进度、作业提交情况
38
+ prompt:
39
+ zh: |-
40
+ 看看课程「{{课程名称}}」的学习进度和完成率。
@@ -0,0 +1,77 @@
1
+ # 变更日志
2
+
3
+ ## v6.47.0 · 2026-09-01
4
+
5
+ - 移除单独的“回复格式:课程标题 A1B3C1”和固定编码示例。
6
+ - 改为自然语言提示用户直接提供课程标题、课件来源、分类、模板及本地文件路径。
7
+
8
+ ## v6.46.0 · 2026-09-01
9
+
10
+ - 固定单课程首轮输出顺序,确保标题、A 来源、B 分类、分类提示、C 模板和回复示例完整出现。
11
+ - 分类和模板统一使用“编码在名称前”的展示格式。
12
+ - 指派与发布改为两个连续弹窗:先确认是否指派,再确认是否发布。
13
+ - 指派弹窗固定为「1. 指派(推荐)/2. 不指派」;发布弹窗固定为「1. 发布/2. 不发布」。
14
+
15
+ ## v6.45.0 · 2026-09-01
16
+
17
+ - 统一单课程首轮输出顺序和格式。
18
+ - 分类、模板选项统一采用“编码在名称前”的展示方式。
19
+ - 指派弹窗固定顺序为“1. 指派(推荐)/2. 不指派”。
20
+ - 发布弹窗固定顺序为“1. 发布/2. 不发布”。
21
+
22
+ ## v6.44.0 · 2026-09-01
23
+
24
+ - 修复创建课程时 B 分类列表为空或使用占位内容的问题。
25
+ - 分类选择现在必须先拉取真实分类接口返回,再展示一级分类标题和 UUID。
26
+ - 统一分类字段为 `data.list[].title`、`uuid`、`parent_id`,不再使用未验证的 `name`/`id` 字段。
27
+ - 未确认的 `--parent-id`、`--level` 参数不得直接调用。
28
+
29
+ ## v6.43.0 · 2026-09-01
30
+
31
+ - 优化未登录处理:自动执行 `soke-cli auth login` 调用网页登录授权。
32
+ - 登录完成后自动回查「用户凭证」,失败或取消时停止后续写操作。
33
+ - 修正环境检查脚本对中文登录字段的识别。
34
+
35
+ ## v6.42.0 · 2026-09-01
36
+
37
+ - 优化“查看学习统计”入口:未指定课程时先展示已发布线上课前 20 个。
38
+ - 增加按课程标题模糊搜索和分页选择提示,选定课程后再查询统计。
39
+
40
+ ## v6.41.0 · 2026-09-01
41
+
42
+ - 优化对外分享元数据,移除残留英文示例。
43
+ - 增加已有课程操作不再弹模式选择的使用说明。
44
+
45
+ ## v6.40.0 · 2026-09-01
46
+
47
+ - 补齐关键 CLI 命令的最低返回字段契约。
48
+ - 增加批量目录扫描的隐藏文件、符号链接、大小写扩展名和空目录规则。
49
+ - 完善动作级中断恢复和批量结果记录要求。
50
+ - 清理分享元数据中的英文示例。
51
+
52
+ ## v6.39.0 · 2026-09-01
53
+
54
+ - 修复已有 `course-id`、目录路径与模式选择之间的路由冲突。
55
+ - 增加创建前查重、发布确认前二次状态查询和 Gate Check。
56
+ - 明确批量任务的单课失败隔离、超时回查、失败汇总和恢复位置。
57
+
58
+ ## v6.38.0 · 2026-09-01
59
+
60
+ - 统一为 5 阶段流程:创建、课件、设置、指派与发布、查询与维护。
61
+ - 统一执行顺序:课件 → 设置 → 指派 → Gate Check → 发布。
62
+ - 模板自动应用 CLI 支持的高级设置,后台能力标记为待办。
63
+ - 修正立即发布与定时发布的 Gate Check 和回查规则。
64
+ - 修正图片字段白名单、分类末级选择、素材库分页和 clock 分页字段。
65
+ - 增加写操作回查、批量失败隔离和中断恢复要求。
66
+ - 统一示例、排障文档和 WorkBuddy 安装路径。
67
+
68
+ ## 兼容性说明
69
+
70
+ - 命令参数以 `references/cli-facts.md` 为唯一事实源。
71
+ - 当前事实表实测版本为 `soke-cli v1.0.77`。
72
+ - 旧版示例中的“先发布后指派”流程不再适用。
73
+ - 未经 `--help` 或实际回归验证的参数,不得直接写入其他 SOP。
74
+
75
+ ## 历史版本
76
+
77
+ - v6.37.0 及更早版本的详细记录保留在版本发布包或内部备份中;对外分享包只保留当前版本和兼容性说明。