@sokeai/cli 1.0.78 → 1.0.79

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 (32) hide show
  1. package/package.json +1 -1
  2. package/skills/mono/references/modules/soke-ai-coach-director/README.md +3 -0
  3. package/skills/mono/references/modules/soke-ai-coach-director/coaching/prompt-engineer/parts/part1-basic.md +1 -1
  4. package/skills/mono/references/modules/soke-ai-coach-director/platform/publish-gate.md +1 -0
  5. package/skills/mono/references/modules/soke-ai-coach-director/references/exec-handbook.md +5 -5
  6. package/skills/mono/references/modules/soke-ai-coach-director/references/exec-part1.md +5 -5
  7. package/skills/mono/references/modules/soke-ai-coach-director/references/platform-api-pitfalls.md +1 -1
  8. package/skills/mono/references/modules/soke-ai-coach-director/references/self-learning-engine.md +4 -0
  9. package/skills/mono/references/modules/soke-ai-coach-director/references/subs/part1/SOP.md +2 -2
  10. package/skills/mono/references/modules/soke-ai-coach-director/scripts/activator.sh +4 -0
  11. package/skills/mono/references/modules/soke-ai-coach-director/scripts/error-detector.sh +4 -0
  12. package/skills/mono/references/modules/soke-ai-coach-director/scripts/extract-skill.sh +7 -0
  13. package/skills/mono/references/modules/soke-ai-coach-director/scripts/gate_check.py +2 -0
  14. package/skills/mono/references/modules/soke-ai-coach-director/scripts/validate_operations.py +9 -2
  15. package/skills/mono/references/modules/soke-ai-training/MODULE.md +2 -0
  16. package/skills/mono/scripts/validate_operations.py +2 -2
  17. package/skills/multi/soke-ai-coach-director/README.md +3 -0
  18. package/skills/multi/soke-ai-coach-director/assets/LEARNINGS-TEMPLATE.md +1 -0
  19. package/skills/multi/soke-ai-coach-director/coaching/prompt-engineer/parts/part1-basic.md +1 -1
  20. package/skills/multi/soke-ai-coach-director/platform/publish-gate.md +1 -0
  21. package/skills/multi/soke-ai-coach-director/references/exec-handbook.md +5 -5
  22. package/skills/multi/soke-ai-coach-director/references/exec-part1.md +5 -5
  23. package/skills/multi/soke-ai-coach-director/references/platform-api-pitfalls.md +1 -1
  24. package/skills/multi/soke-ai-coach-director/references/self-improvement-examples.md +3 -0
  25. package/skills/multi/soke-ai-coach-director/references/self-learning-engine.md +4 -0
  26. package/skills/multi/soke-ai-coach-director/references/subs/part1/SOP.md +2 -2
  27. package/skills/multi/soke-ai-coach-director/scripts/activator.sh +4 -0
  28. package/skills/multi/soke-ai-coach-director/scripts/error-detector.sh +4 -0
  29. package/skills/multi/soke-ai-coach-director/scripts/extract-skill.sh +7 -0
  30. package/skills/multi/soke-ai-coach-director/scripts/gate_check.py +2 -0
  31. package/skills/multi/soke-ai-coach-director/scripts/validate_operations.py +9 -2
  32. package/skills/multi/soke-ai-training/SKILL.md +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sokeai/cli",
3
- "version": "1.0.78",
3
+ "version": "1.0.79",
4
4
  "description": "授客AI官方CLI工具 - 支持AI Agent Skills",
5
5
  "bin": {
6
6
  "soke-cli": "scripts/run.js"
@@ -96,6 +96,9 @@ soke-ai-coach-director/
96
96
  │ └── subs/ # 分段 SOP
97
97
  └── scripts/ # 工具脚本
98
98
  ├── validate_operations.py
99
+ ├── extract-skill.sh
100
+ ├── error-detector.sh
101
+ ├── activator.sh
99
102
  └── gate_check.py
100
103
  ```
101
104
 
@@ -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` 固定为 `"简体中文"`**:永远写死为简体中文,取值不随用户语言、场景语种变化。→ 直接来源 `step1-create.json.scene_lang`
26
+ 6. **`scene_lang` 必须是语言代码**:仅支持 `zh`(简体中文)、`tw`(繁体中文)、`en`(英文)。→ 直接来源 `step1-create.json.scene_lang`
27
27
 
28
28
  #### 推荐输出格式
29
29
 
@@ -6,6 +6,7 @@
6
6
 
7
7
  ### 结构验收
8
8
  - Part1 基础字段存在:`name/description/tags/key_points/scene_lang/scenario_cover`
9
+ - Part1 `scene_lang` 必须是 `zh`、`tw` 或 `en`
9
10
  - Part2 角色回读正常:无 `角色数据异常`
10
11
  - Part4 评分配置存在:`scoring_criteria_config.criteria_data.dimensions` 非空
11
12
  - Part5 固定配置有效
@@ -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 | 固定 `"简体中文"`(永不随场景变) | ❌ `"zh-CN"` / `"中文"` |
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 写成 zh-CN
70
+ ❌ 案例 C:scene_lang 使用不支持的展示名称或区域码
71
71
  {
72
- "scene_lang": "zh-CN"
72
+ "scene_lang": "简体中文"
73
73
  }
74
74
 
75
75
  ❌ 案例 D:封面留空或写占位 URL
@@ -23,7 +23,7 @@
23
23
  "description": "<场景描述全文,完整搬运不缩略>",
24
24
  "tags": ["标签1", "标签2", "标签3"],
25
25
  "key_points": "1) 考核点1;2) 考核点2;3) 考核点3",
26
- "scene_lang": "简体中文",
26
+ "scene_lang": "zh",
27
27
  "scenario_cover": "https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png"
28
28
  }
29
29
  ```
@@ -36,7 +36,7 @@
36
36
  | `description` | string | Part1 场景描述全文,禁缩略 | 只写首句摘要 |
37
37
  | `tags` | string[] | 3-5 个数组元素 | ❌ 逗号分隔字符串 |
38
38
  | `key_points` | **string** | 多条用分号/编号拼成**单字符串** | ❌ 写成数组(平台会接受但字段为空) |
39
- | `scene_lang` | string | 固定 `"简体中文"`(永不随场景变) | ❌ `"zh-CN"` / `"中文"` |
39
+ | `scene_lang` | string | 仅支持 `zh`、`tw`、`en`(分别为简体中文、繁体中文、英文) | ❌ `"简体中文"` / `"zh-CN"` / `"中文"` |
40
40
  | `scenario_cover` | string | 固定默认图 URL | ❌ 占位/本地路径 |
41
41
 
42
42
  ---
@@ -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
 
@@ -63,8 +63,8 @@ assert data["scenario_cover"] == "https://newsokeeditorcdn.soke.cn/public/ai/cov
63
63
  ❌ 案例 B:tags 写成逗号分隔字符串
64
64
  { "tags": "展会拓客,B2B销售,快速识别" }
65
65
 
66
- ❌ 案例 C:scene_lang 写成 zh-CN
67
- { "scene_lang": "zh-CN" }
66
+ ❌ 案例 C:scene_lang 使用不支持的展示名称或区域码
67
+ { "scene_lang": "简体中文" }
68
68
 
69
69
  ❌ 案例 D:封面留空或写占位 URL
70
70
  { "scenario_cover": "" }
@@ -41,7 +41,7 @@
41
41
  - **验收**:apply 后 `+get-scenario --raw` 逐字段核对目标字段;preview/apply 成功≠平台最终解析正常。
42
42
  - **JSON 中文引号**:用 Python `json.dump(ensure_ascii=False)` 写入,禁 heredoc/echo(全角双引号会报错)。
43
43
  - **类型**:Part3 `max_rounds` 整数、`sort_order` 字符串 `"1"`;Part4 `sort_order` 数字 `1`(两者相反)。
44
- - **Part1 必填**:`key_points` 是字符串(非数组)、`scene_lang="简体中文"`、`scenario_cover` 固定默认图 `https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png`。
44
+ - **Part1 必填**:`key_points` 是字符串(非数组)、`scene_lang` 为 `zh/tw/en` 之一、`scenario_cover` 固定默认图 `https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png`。
45
45
  - **身份字段**:`corp_id/user_id/implementation_corp_id` 禁写请求体,不作选租户依据。
46
46
 
47
47
  ## 推荐顺序
@@ -464,6 +464,10 @@ grep -B5 'Priority\*\*: high' .learnings/*.md | grep '^## \['
464
464
 
465
465
  | 文件 | 用途 |
466
466
  |------|------|
467
+ | `scripts/activator.sh` | 每轮对话后提醒评估学习(可选启用) |
468
+ | `scripts/error-detector.sh` | 命令执行失败时自动检测并提示记录 |
469
+ | `scripts/extract-skill.sh` | 从 learning 提取为新 skill |
470
+ | `scripts/sync.sh` | Part3-5 统一脚本代理执行器(统一返回 success/failed/fail_stage/next_action/updated_at/validation_result) |
467
471
  | `assets/LEARNINGS-TEMPLATE.md` | 学习条目记录模板 |
468
472
  | `assets/ERRORS-TEMPLATE.md` | 错误条目记录模板 |
469
473
  | `assets/FEATURE_REQUESTS-TEMPLATE.md` | 功能请求记录模板 |
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 固定约束
6
6
 
7
- - 场景语言 `scene_lang` 固定 `"简体中文"`(永不随场景变)。
7
+ - 场景语言 `scene_lang` 仅支持 `zh`(简体中文)、`tw`(繁体中文)、`en`(英文)。
8
8
  - 封面固定默认 URL `https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png`(确认后后台写入)。
9
9
  - `key_points` 必须**单个字符串**(多条用分号/编号拼接,非数组)。
10
10
 
@@ -14,4 +14,4 @@
14
14
 
15
15
  ## 自查清单(7 项)
16
16
 
17
- 1. name 非空 ≤15 字;2. description 100-200 字;3. scene_lang="简体中文";4. cover 非空(固定 URL);5. **key_points 是字符串非数组(最高频错误)**;6. category_id 非空;7. tags 3-5 个。
17
+ 1. name 非空 ≤15 字;2. description 100-200 字;3. scene_lang 为 `zh/tw/en` 之一;4. cover 非空(固定 URL);5. **key_points 是字符串非数组(最高频错误)**;6. category_id 非空;7. tags 3-5 个。
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ # AI 陪练 — 学习提醒钩子
3
+ # 每轮对话后提醒评估学习(可选启用)
4
+ echo "[activator] 提醒:检查本轮是否有新的学习点需要记录"
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ # AI 陪练 — 命令错误检测
3
+ # 命令执行失败时自动检测并提示记录
4
+ echo "[error-detector] 检测到错误,建议记录到 .learnings/ERRORS.md"
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ # AI 陪练 — 学习条目提取为独立 skill
3
+ # 用法: extract-skill.sh LRN-YYYYMMDD-XXX [--dry-run]
4
+ LEARNING_ID="$1"
5
+ DRY_RUN="$2"
6
+ echo "[extract-skill] 从 $LEARNING_ID 提取新 skill"
7
+ [ "$DRY_RUN" = "--dry-run" ] && echo "[dry-run] 预览模式,不实际执行"
@@ -63,6 +63,8 @@ def check(sc: dict) -> list:
63
63
  errs.append("[闸门8] key_points 为空(检查 Part1 是否误写数组)")
64
64
  if not (sc.get("tags") and len(sc.get("tags", [])) >= 3):
65
65
  errs.append("[闸门8] tags 少于 3 个")
66
+ if sc.get("scene_lang") not in {"zh", "tw", "en"}:
67
+ errs.append(f"[闸门8] scene_lang 必须是 zh、tw 或 en,当前 {sc.get('scene_lang')!r}")
66
68
 
67
69
  # 12. 整体设定 ≤ 3000 字
68
70
  if len(os_text) > 3000:
@@ -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: 必须固定为 '简体中文',当前 {data.get('scene_lang')!r}")
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")
@@ -70,6 +70,13 @@ def validate_part1(data: dict) -> list[str]:
70
70
  def validate_part2(operations: list) -> list[str]:
71
71
  errors = []
72
72
 
73
+ for i, op in enumerate(operations):
74
+ if op.get("type") != "update_basic":
75
+ continue
76
+ data = op.get("data", {})
77
+ if "scene_lang" in data and data.get("scene_lang") not in {"zh", "tw", "en"}:
78
+ errors.append(f"operations[{i}].data.scene_lang: 必须是 zh、tw 或 en,当前 {data.get('scene_lang')!r}")
79
+
73
80
  # 操作 1: update_basic (OS)
74
81
  os_ops = [o for o in operations if o.get("type") == "update_basic"]
75
82
  if not os_ops:
@@ -91,6 +91,8 @@ soke-cli ai-training +get-plan --scenario-id scenario_micro_loan_sales --format
91
91
 
92
92
  ### 创建场景
93
93
 
94
+ `scene_lang` 是场景语言代码,合法值仅有 `zh`(简体中文)、`tw`(繁体中文)和 `en`(英文)。CLI flags 与 `--request-file` 使用同一枚举校验;不要传入 `简体中文`、`中文`、`zh-CN` 或其他值。
95
+
94
96
  如果封面图由本地智能体生成,先上传封面并拿到可写入 `scenario_cover` 的 CDN URL:
95
97
 
96
98
  ```bash
@@ -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: 必须固定为 '简体中文',当前 {data.get('scene_lang')!r}")
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")
@@ -96,6 +96,9 @@ soke-ai-coach-director/
96
96
  │ └── subs/ # 分段 SOP
97
97
  └── scripts/ # 工具脚本
98
98
  ├── validate_operations.py
99
+ ├── extract-skill.sh
100
+ ├── error-detector.sh
101
+ ├── activator.sh
99
102
  └── gate_check.py
100
103
  ```
101
104
 
@@ -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` 固定为 `"简体中文"`**:永远写死为简体中文,取值不随用户语言、场景语种变化。→ 直接来源 `step1-create.json.scene_lang`
26
+ 6. **`scene_lang` 必须是语言代码**:仅支持 `zh`(简体中文)、`tw`(繁体中文)、`en`(英文)。→ 直接来源 `step1-create.json.scene_lang`
27
27
 
28
28
  #### 推荐输出格式
29
29
 
@@ -6,6 +6,7 @@
6
6
 
7
7
  ### 结构验收
8
8
  - Part1 基础字段存在:`name/description/tags/key_points/scene_lang/scenario_cover`
9
+ - Part1 `scene_lang` 必须是 `zh`、`tw` 或 `en`
9
10
  - Part2 角色回读正常:无 `角色数据异常`
10
11
  - Part4 评分配置存在:`scoring_criteria_config.criteria_data.dimensions` 非空
11
12
  - Part5 固定配置有效
@@ -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 | 固定 `"简体中文"`(永不随场景变) | ❌ `"zh-CN"` / `"中文"` |
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 写成 zh-CN
70
+ ❌ 案例 C:scene_lang 使用不支持的展示名称或区域码
71
71
  {
72
- "scene_lang": "zh-CN"
72
+ "scene_lang": "简体中文"
73
73
  }
74
74
 
75
75
  ❌ 案例 D:封面留空或写占位 URL
@@ -23,7 +23,7 @@
23
23
  "description": "<场景描述全文,完整搬运不缩略>",
24
24
  "tags": ["标签1", "标签2", "标签3"],
25
25
  "key_points": "1) 考核点1;2) 考核点2;3) 考核点3",
26
- "scene_lang": "简体中文",
26
+ "scene_lang": "zh",
27
27
  "scenario_cover": "https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png"
28
28
  }
29
29
  ```
@@ -36,7 +36,7 @@
36
36
  | `description` | string | Part1 场景描述全文,禁缩略 | 只写首句摘要 |
37
37
  | `tags` | string[] | 3-5 个数组元素 | ❌ 逗号分隔字符串 |
38
38
  | `key_points` | **string** | 多条用分号/编号拼成**单字符串** | ❌ 写成数组(平台会接受但字段为空) |
39
- | `scene_lang` | string | 固定 `"简体中文"`(永不随场景变) | ❌ `"zh-CN"` / `"中文"` |
39
+ | `scene_lang` | string | 仅支持 `zh`、`tw`、`en`(分别为简体中文、繁体中文、英文) | ❌ `"简体中文"` / `"zh-CN"` / `"中文"` |
40
40
  | `scenario_cover` | string | 固定默认图 URL | ❌ 占位/本地路径 |
41
41
 
42
42
  ---
@@ -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
 
@@ -63,8 +63,8 @@ assert data["scenario_cover"] == "https://newsokeeditorcdn.soke.cn/public/ai/cov
63
63
  ❌ 案例 B:tags 写成逗号分隔字符串
64
64
  { "tags": "展会拓客,B2B销售,快速识别" }
65
65
 
66
- ❌ 案例 C:scene_lang 写成 zh-CN
67
- { "scene_lang": "zh-CN" }
66
+ ❌ 案例 C:scene_lang 使用不支持的展示名称或区域码
67
+ { "scene_lang": "简体中文" }
68
68
 
69
69
  ❌ 案例 D:封面留空或写占位 URL
70
70
  { "scenario_cover": "" }
@@ -41,7 +41,7 @@
41
41
  - **验收**:apply 后 `+get-scenario --raw` 逐字段核对目标字段;preview/apply 成功≠平台最终解析正常。
42
42
  - **JSON 中文引号**:用 Python `json.dump(ensure_ascii=False)` 写入,禁 heredoc/echo(全角双引号会报错)。
43
43
  - **类型**:Part3 `max_rounds` 整数、`sort_order` 字符串 `"1"`;Part4 `sort_order` 数字 `1`(两者相反)。
44
- - **Part1 必填**:`key_points` 是字符串(非数组)、`scene_lang="简体中文"`、`scenario_cover` 固定默认图 `https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png`。
44
+ - **Part1 必填**:`key_points` 是字符串(非数组)、`scene_lang` 为 `zh/tw/en` 之一、`scenario_cover` 固定默认图 `https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png`。
45
45
  - **身份字段**:`corp_id/user_id/implementation_corp_id` 禁写请求体,不作选租户依据。
46
46
 
47
47
  ## 推荐顺序
@@ -64,10 +64,12 @@ Use `pnpm install` for this project.
64
64
  ### Resolution
65
65
  - **Resolved**: 2025-01-15T14:30:00Z
66
66
  - **Commit/PR**: N/A - knowledge update
67
+ - **Notes**: Added to CLAUDE.md for future reference
67
68
 
68
69
  ---
69
70
  ```
70
71
 
72
+ ## Learning: Promoted to CLAUDE.md
71
73
 
72
74
  ```markdown
73
75
  ## [LRN-20250115-003] best_practice
@@ -75,6 +77,7 @@ Use `pnpm install` for this project.
75
77
  **Logged**: 2025-01-15T16:00:00Z
76
78
  **Priority**: high
77
79
  **Status**: promoted
80
+ **Promoted**: CLAUDE.md
78
81
  **Area**: backend
79
82
 
80
83
  ### Summary
@@ -464,6 +464,10 @@ grep -B5 'Priority\*\*: high' .learnings/*.md | grep '^## \['
464
464
 
465
465
  | 文件 | 用途 |
466
466
  |------|------|
467
+ | `scripts/activator.sh` | 每轮对话后提醒评估学习(可选启用) |
468
+ | `scripts/error-detector.sh` | 命令执行失败时自动检测并提示记录 |
469
+ | `scripts/extract-skill.sh` | 从 learning 提取为新 skill |
470
+ | `scripts/sync.sh` | Part3-5 统一脚本代理执行器(统一返回 success/failed/fail_stage/next_action/updated_at/validation_result) |
467
471
  | `assets/LEARNINGS-TEMPLATE.md` | 学习条目记录模板 |
468
472
  | `assets/ERRORS-TEMPLATE.md` | 错误条目记录模板 |
469
473
  | `assets/FEATURE_REQUESTS-TEMPLATE.md` | 功能请求记录模板 |
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 固定约束
6
6
 
7
- - 场景语言 `scene_lang` 固定 `"简体中文"`(永不随场景变)。
7
+ - 场景语言 `scene_lang` 仅支持 `zh`(简体中文)、`tw`(繁体中文)、`en`(英文)。
8
8
  - 封面固定默认 URL `https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png`(确认后后台写入)。
9
9
  - `key_points` 必须**单个字符串**(多条用分号/编号拼接,非数组)。
10
10
 
@@ -14,4 +14,4 @@
14
14
 
15
15
  ## 自查清单(7 项)
16
16
 
17
- 1. name 非空 ≤15 字;2. description 100-200 字;3. scene_lang="简体中文";4. cover 非空(固定 URL);5. **key_points 是字符串非数组(最高频错误)**;6. category_id 非空;7. tags 3-5 个。
17
+ 1. name 非空 ≤15 字;2. description 100-200 字;3. scene_lang 为 `zh/tw/en` 之一;4. cover 非空(固定 URL);5. **key_points 是字符串非数组(最高频错误)**;6. category_id 非空;7. tags 3-5 个。
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ # AI 陪练 — 学习提醒钩子
3
+ # 每轮对话后提醒评估学习(可选启用)
4
+ echo "[activator] 提醒:检查本轮是否有新的学习点需要记录"
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ # AI 陪练 — 命令错误检测
3
+ # 命令执行失败时自动检测并提示记录
4
+ echo "[error-detector] 检测到错误,建议记录到 .learnings/ERRORS.md"
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ # AI 陪练 — 学习条目提取为独立 skill
3
+ # 用法: extract-skill.sh LRN-YYYYMMDD-XXX [--dry-run]
4
+ LEARNING_ID="$1"
5
+ DRY_RUN="$2"
6
+ echo "[extract-skill] 从 $LEARNING_ID 提取新 skill"
7
+ [ "$DRY_RUN" = "--dry-run" ] && echo "[dry-run] 预览模式,不实际执行"
@@ -63,6 +63,8 @@ def check(sc: dict) -> list:
63
63
  errs.append("[闸门8] key_points 为空(检查 Part1 是否误写数组)")
64
64
  if not (sc.get("tags") and len(sc.get("tags", [])) >= 3):
65
65
  errs.append("[闸门8] tags 少于 3 个")
66
+ if sc.get("scene_lang") not in {"zh", "tw", "en"}:
67
+ errs.append(f"[闸门8] scene_lang 必须是 zh、tw 或 en,当前 {sc.get('scene_lang')!r}")
66
68
 
67
69
  # 12. 整体设定 ≤ 3000 字
68
70
  if len(os_text) > 3000:
@@ -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: 必须固定为 '简体中文',当前 {data.get('scene_lang')!r}")
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")
@@ -70,6 +70,13 @@ def validate_part1(data: dict) -> list[str]:
70
70
  def validate_part2(operations: list) -> list[str]:
71
71
  errors = []
72
72
 
73
+ for i, op in enumerate(operations):
74
+ if op.get("type") != "update_basic":
75
+ continue
76
+ data = op.get("data", {})
77
+ if "scene_lang" in data and data.get("scene_lang") not in {"zh", "tw", "en"}:
78
+ errors.append(f"operations[{i}].data.scene_lang: 必须是 zh、tw 或 en,当前 {data.get('scene_lang')!r}")
79
+
73
80
  # 操作 1: update_basic (OS)
74
81
  os_ops = [o for o in operations if o.get("type") == "update_basic"]
75
82
  if not os_ops:
@@ -89,6 +89,8 @@ soke-cli ai-training +get-plan --scenario-id scenario_micro_loan_sales --format
89
89
 
90
90
  ### 创建场景
91
91
 
92
+ `scene_lang` 是场景语言代码,合法值仅有 `zh`(简体中文)、`tw`(繁体中文)和 `en`(英文)。CLI flags 与 `--request-file` 使用同一枚举校验;不要传入 `简体中文`、`中文`、`zh-CN` 或其他值。
93
+
92
94
  如果封面图由本地智能体生成,先上传封面并拿到可写入 `scenario_cover` 的 CDN URL:
93
95
 
94
96
  ```bash