diff --git a/business_production/_shared/feishu-embedded-sheet/SKILL.md b/business_production/_shared/feishu-embedded-sheet/SKILL.md
index 102432d..9644f8d 100644
--- a/business_production/_shared/feishu-embedded-sheet/SKILL.md
+++ b/business_production/_shared/feishu-embedded-sheet/SKILL.md
@@ -233,6 +233,120 @@ else:
write_range(f"F{row}:F{row}", [data[row]])
```
+## 读取后错行/乱行校验(强制执行)
+
+### 校验目标
+
+读取 Sheet 数据后,必须自动检测关键列之间的行号对齐关系,防止以下问题:
+- 组件配置(G列)写入了错误行,导致内容与组件名称(A列)错位
+- 英文台词(F列)写入了错误行,导致台词与角色(E列)错位
+- 批量写入时行号偏移导致整列数据整体下移/上移
+
+### 校验规则(剧本表格 A-I 列)
+
+#### 规则1:A列-G列 对齐校验(组件类型 vs 组件配置)
+
+```
+如果 A列[row] 是组件类型(匹配:对话朗读|对话挖空|对话选择|对话组句|对话表达|对话选读|图片单选|图片多选|信息拼词|看图选词|听力\S+|阅读\S+|写作\S+|口语\S+)
+ → G列[row] 必须非空(包含组件配置内容)
+
+如果 G列[row] 非空(包含组件配置内容)
+ → A列[row] 必须是组件类型(不能是 TL / 空 / 其他非组件标记)
+```
+
+#### 规则2:B列-G列 对齐校验(组件ID vs 组件配置)
+
+```
+如果 B列[row] 是数字(组件ID)
+ → G列[row] 必须非空
+
+如果 G列[row] 非空且包含 "【组件ID】" 标记
+ → 提取的组件ID 必须与 B列[row] 一致
+```
+
+#### 规则3:E列-F列 对齐校验(角色名 vs 英文台词)
+
+```
+如果 E列[row] 非空(有角色名)且 A列[row] 不是 TL / 空(非纯剧情行)
+ → F列[row] 建议非空(角色说话应有台词)
+ → 若 F列[row] 为空,标记为"疑似缺失"(可能是剧情描述行,需人工确认)
+```
+
+#### 规则4:G列 内容归属校验(防止配置写入非组件行)
+
+```
+扫描 G列 所有非空单元格:
+ 如果 G列[row] 包含组件配置特征("【任务标题】" / "【资源配置】" / "【互动内容】")
+ 且 A列[row] 为 TL / 空 / 非组件类型
+ → 标记为"错行":组件配置写入了非组件行
+```
+
+### 校验执行流程
+
+```python
+# 读取 Sheet 数据后立即执行
+def validate_sheet_alignment(rows):
+ errors = []
+ warnings = []
+
+ component_pattern = re.compile(
+ r'^(对话朗读|对话挖空|对话选择|对话组句|对话表达|对话选读|'
+ r'图片单选|图片多选|信息拼词|看图选词|'
+ r'听力\S+|阅读\S+|写作\S+|口语\S+)'
+ )
+
+ for i, row in enumerate(rows):
+ row_num = i + 1 # 1-indexed
+ a_val = row[0] if len(row) > 0 else None # A列:类型
+ b_val = row[1] if len(row) > 1 else None # B列:ID
+ e_val = row[4] if len(row) > 4 else None # E列:角色名
+ f_val = row[5] if len(row) > 5 else None # F列:英文台词
+ g_val = row[6] if len(row) > 6 else None # G列:组件配置
+
+ # 规则1:A-G 对齐
+ if a_val and component_pattern.match(str(a_val)):
+ if not g_val:
+ errors.append(f"行{row_num}: A列=[{a_val}] 但 G列为空,组件配置缺失")
+
+ if g_val and '【任务标题】' in str(g_val):
+ if not a_val or not component_pattern.match(str(a_val)):
+ errors.append(f"行{row_num}: G列有组件配置但 A列=[{a_val}] 非组件类型,疑似错行")
+
+ # 规则2:B-G 对齐
+ if b_val and str(b_val).isdigit():
+ if not g_val:
+ errors.append(f"行{row_num}: B列=[{b_val}] 但 G列为空,组件配置缺失")
+ elif '【组件ID】' in str(g_val):
+ g_id = extract_component_id(str(g_val))
+ if g_id and str(g_id) != str(b_val):
+ errors.append(f"行{row_num}: B列ID=[{b_val}] 与 G列组件ID=[{g_id}] 不一致")
+
+ # 规则3:E-F 对齐
+ if e_val and a_val and a_val not in ('TL', ''):
+ if not f_val:
+ warnings.append(f"行{row_num}: E列=[{e_val}] 但 F列为空,疑似台词缺失")
+
+ # 规则4:G列归属
+ if g_val and ('【任务标题】' in str(g_val) or '【互动内容】' in str(g_val)):
+ if not a_val or a_val in ('TL', ''):
+ errors.append(f"行{row_num}: G列有组件配置但 A列=[{a_val}],组件配置错行到非组件行")
+
+ return errors, warnings
+```
+
+### 校验结果处理
+
+| 级别 | 条件 | 处理方式 |
+|------|------|---------|
+| **错误 (Error)** | A-G 不对齐 / B-G ID不一致 / G列错行到非组件行 | 立即报告用户,附具体行号和错位内容,暂停后续写入操作 |
+| **警告 (Warning)** | E-F 疑似缺失 / 其他非关键不对齐 | 汇总报告,继续执行但标注"需人工确认" |
+
+### 校验触发时机
+
+1. **读取后立即校验**:任何读取 Sheet 数据的操作完成后,自动执行上述校验
+2. **写入前校验**:写入操作前,先读取目标区域,校验当前数据对齐状态
+3. **写入后回读校验**:写入完成后回读,再次执行对齐校验,确保写入未引入新错位
+
## 异常处理
| 错误码 | 含义 | 处理方式 |
diff --git a/business_production/组件生产/skills/dialogue-interaction-config/SKILL.md b/business_production/组件生产/skills/dialogue-interaction-config/SKILL.md
index f5f7f6d..60c1dad 100644
--- a/business_production/组件生产/skills/dialogue-interaction-config/SKILL.md
+++ b/business_production/组件生产/skills/dialogue-interaction-config/SKILL.md
@@ -31,18 +31,35 @@ metadata:
## 通用配置规则(所有对话类互动通用)
### 通用字段规范
+
+> ⚠️ **禁止字段**:G列组件内容中**禁止**出现 `【组件ID】`(B列已有)、`【知识点】`(H列已有)。
+
| 字段 | 要求 | 示例 |
|------|------|------|
| 【任务标题】 | 10字以内,清晰说明任务内容,避免使用"-",多部分用"(一)"标识 | 与调酒师对峙(一) |
-| 【情境引入】 | 每行一句对话,格式为`角色名: 对话内容`,无情境引入填"无" | User: He already ran away.
Piper: I didn't see him on my way here. |
-| 【后置对话】 | 每行一句对话,无后置对话填"无" | 无 |
-| 【资源配置】 | 无资源填"无";有资源时填写资源命名和出现时机:
1. 图片命名:`组件ID.png`
2. 音频命名:`组件ID.mp3`
3. 出现时机:可填【情境引入】/【互动内容】/【互动反馈】/【后置对话】,多时机并列 | 图片时机:
互动内容
互动反馈
音频载体:Pioneer Band |
+| 【情境引入】 | 每行一句对话,格式为`角色名: 对话内容`,无情境引入填"无"。🚫 **禁止编造**,必须来自台词池(组件行 F 列 + 后续连续 User 台词)。单句台词池且含知识点 → 填「无」 | User: He already ran away.
Piper: I didn't see him on my way here. |
+| 【后置对话】 | 每行一句对话,无后置对话填"无"。🚫 **禁止编造**,必须来自台词池。知识点之后无 User 台词 → 填「无」 | 无 |
+| 【资源配置】 | 无资源填"无";有资源时填写资源出现的时机(如"情境引入""互动内容"),多时机并列换行
🚫 禁止使用组件ID命名文件(如 `1224204.png`),文件名由下游系统自动生成
🚫 不需要"图片时机:""音频载体:"等前缀 | 情境引入
互动内容
互动反馈 |
| 【互动反馈】 | 分正确反馈和错误反馈,格式为`角色名: 反馈内容`,正确反馈非必填,无则填"无" | 正确 Piper: Thank you, my friend.
错误 Piper: I don't think so. |
---
## 知识点优先分配规则(强制执行)
+### 台词池规则(强制执行)
+
+**组件内容除【互动反馈】外,其余台词均来自台词池,禁止编造。**
+
+**台词池定义:** 组件行 F 列 + 后续连续 User 台词(到 TL / 下一组件截止)。
+
+**分配规则:**
+- 含知识点的台词 → 【互动内容】
+- 知识点之前的 User 台词 → 【情境引入】
+- 知识点之后的 User 台词 → 【后置对话】或选项反馈
+- 单句台词池且含知识点 → 【情境引入】填「无」
+
+> ⚠️ 核心互动不适用此规则。
+
### 核心原则
当组件中 User 有多句台词时,**【互动内容】必须是包含知识点的那句台词**。不包含知识点的台词,根据其与知识点台词的相对位置分配:
@@ -196,19 +213,16 @@ Piper: You're lying! It must be your mistake!
- 【互动反馈】:本类型不单独设置互动反馈字段,反馈内容已整合在互动内容的各选项中
- 【资源配置】:
- 类型为「对话选读」时,填写:`无`
- - 类型为「对话选读-配图」时,填写图片时机 + 音频载体(格式见下方示例)
- - 资源命名规范:图片文件名 `{组件ID}.png`,音频文件名 `{组件ID}.mp3`
+ - 类型为「对话选读-配图」时,填写资源出现时机(格式见下方示例)
+ - 资源描述出现时机(非文件名),文件名由下游系统自动生成
#### 示例(对话选读-配图)
```
【任务标题】加入搏斗俱乐部
【资源配置】
-图片时机:
互动内容
互动反馈
-音频载体:Pioneer Band
-
【情境引入】
Johnny: What do you think of the club?
diff --git a/business_production/组件生产/skills/info-interaction-config/SKILL.md b/business_production/组件生产/skills/info-interaction-config/SKILL.md
index 92a7487..44c9d68 100644
--- a/business_production/组件生产/skills/info-interaction-config/SKILL.md
+++ b/business_production/组件生产/skills/info-interaction-config/SKILL.md
@@ -16,8 +16,10 @@ metadata:
## 通用规则(6类共享)
+> ⚠️ **禁止字段**:G列组件内容中**禁止**出现 `【组件ID】`(B列已有)、`【知识点】`(H列已有)。
+
- 【任务标题】:中文口语化,10字以内,避免「-」,有序用「(一)」,含英文单词时前后留空格
-- 【资源配置】:图片文件名 = `{组件ID}.png`,不含音频配置
+- 【资源配置】:描述资源出现的时机(如"情境引入""互动内容"),非文件名。无资源填"无"。🚫 禁止使用组件ID命名文件(如 `1224204.png`),文件名由下游系统自动生成
- 【后置对话】:无则填「无」
---
@@ -41,7 +43,7 @@ metadata:
```
【任务标题】购买葡萄
【资源配置】
-图片文件名:0216002.png
+互动内容
【互动内容】
任务描述:请填入"葡萄"的正确的英文拼写
题干:G(2)pe
@@ -83,7 +85,7 @@ metadata:
```
【任务标题】填写信息表
【资源配置】
-图片文件名:0216002.png
+互动内容
【互动内容】
任务描述:请在空白处填入正确的单词,组成句子
选项1:is
@@ -115,7 +117,7 @@ metadata:
```
【任务标题】描述房间里的物品
【资源配置】
-图片文件名:0216002.png
+互动内容
【互动内容】
任务描述:请用英文描述图片中房间里的物品
参考词汇:sofa, window, door, table
@@ -148,7 +150,7 @@ metadata:
```
【任务标题】补全句子中的单词
【资源配置】
-图片文件名:0216002.png
+互动内容
【互动内容】
题干:The cat is sitting on the ___.
选项1:chair(正确)
@@ -183,7 +185,7 @@ metadata:
```
【任务标题】填入正确的单词
【资源配置】
-图片文件名:0216002.png
+互动内容
【互动内容】
题干:The ___ is on the desk.
答案:book
@@ -216,7 +218,7 @@ metadata:
```
【任务标题】补全这个句子
【资源配置】
-图片文件名:0216002.png
+互动内容
【互动内容】
题干:The boy ___ to school every day.
答案:The boy walks to school every day.
diff --git a/business_production/组件生产/skills/script-component-production/SKILL.md b/business_production/组件生产/skills/script-component-production/SKILL.md
index e43b4df..8845148 100644
--- a/business_production/组件生产/skills/script-component-production/SKILL.md
+++ b/business_production/组件生产/skills/script-component-production/SKILL.md
@@ -60,6 +60,22 @@ description: 剧本互动组件内容生产/审校/回填技能(不涉及JSON
- 识别嵌入的 Sheet token(如 `
| cType | ++ |
| cId | ++ |
| title | ++ |
| meaning | ++ |
| resourceMapping | ++ |
| question | ++ |
| imageInfo | ++ |
| optionList | ++ |
| answer | ++ |
| preDialog | ++ |
| tip | ++ |
| corFeedback | ++ |
| errFeedback | ++ |
| postDialog | ++ |
| cDesc | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| meaning | ++ |
| resourceMapping | ++ |
| question | ++ |
| imageInfo | ++ |
| optionList | ++ |
| answer | ++ |
| preDialog | ++ |
| tip | ++ |
| corFeedback | ++ |
| errFeedback | ++ |
| postDialog | ++ |
| cDesc | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| optionGroupList | ++ |
| corFeedback | ++ |
| errFeedback | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| optionGroupList | ++ |
| corFeedback | ++ |
| errFeedback | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| optionList | ++ |
| answer | ++ |
| tip | ++ |
| corFeedback | ++ |
| errFeedback | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cId | ++ |
| cType | ++ |
| title | ++ |
| taskDesc | ++ |
| sceneDesc | ++ |
| img | ++ |
| plotSummary | ++ |
| stemDesc | ++ |
| key | ++ |
| cDesc | ++ |
| inputType | ++ |
| passCondition | ++ |
| textList | ++ |
| learningPart | ++ |
| closing | ++ |
| title | ++ |
| taskDesc | ++ |
| sceneDesc | ++ |
| knowledge | ++ |
| passCondition | ++ |
| textList | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
``` +# 问题1: +Brainy: 你要在任务清单开头描述爸爸妈妈的身份,你想到可以说“爸爸妈妈是超棒的宇航员”,现在需要把句子补充完整:Mum and Dad are great ___. +用户选项: +(选项 A)astronauts [正确] + Brainy: 答对啦!astronauts是宇航员的复数形式,刚好对应主语Mum and Dad两个人,这句话完整表达了“爸爸妈妈是超棒的宇航员”的意思哦。 +(选项 B)teachers + Brainy: 不对哦,teachers是老师的意思,咱们要表达的是宇航员的身份,再试试呀。 +(选项 C)doctors + Brainy: 不对哦,doctors是医生的意思,和咱们要描述的宇航员身份不符,再想一想~ + +# 问题2: +Brainy: 介绍完爸爸妈妈的身份,你也想说说自己,要表达“我也是一名超棒的宇航员”,现在把句子补充完整:I am a ___ too! +用户选项: +(选项 A)astronaut + Brainy: 不对哦,这里还缺少“great(超棒的)”来修饰astronaut,没有完整表达出“超棒的宇航员”的意思,再试试呀。 +(选项 B)great astronaut [正确] + Brainy: 太棒了!great修饰astronaut,正好对应“超棒的宇航员”,完整表达了你想说的内容~ +(选项 C)astronauts + Brainy: 不对哦,astronauts是复数形式,前面有不定冠词a,后面要接可数名词单数,而且也缺少了“great”哦,再想一想。 + +# 问题3: +Brainy: 接下来你要在清单里说明爸爸妈妈有需要完成的工作,下面哪个句子是正确的表达呢? +用户选项: +(选项 A)Mum and Dad have jobs. [正确] + Brainy: 完全正确!这句话的意思是“爸爸妈妈有工作”,刚好符合你要表达的内容哦。 +(选项 B)Mum and Dad have suit. + Brainy: 不对哦,suit是“套装”的意思,而且语法也不正确,咱们要表达的是“有工作”,再试试呀。 +(选项 C)Mum and Dad have jogs. + Brainy: 不对哦,jogs是“慢跑”的意思,和咱们要表达的“工作”含义不符,再想一想~ + +# 问题4: +Brainy: 说完爸爸妈妈的工作,你也想说明自己也有任务要完成,要表达“我也有一份工作”,下面哪个句子是正确的? +用户选项: +(选项 A)I have an job too! + Brainy: 不对哦,job是以辅音音素开头的单词,前面要用不定冠词a而不是an,再试试呀。 +(选项 B)I have a job too! [正确] + Brainy: 太厉害啦!这句话准确表达了“我也有一份工作”的意思,语法和含义都完全正确~ +(选项 C)I job have a too! + Brainy: 不对哦,这个句子的语序是混乱的,正确的陈述句语序应该是主语+谓语+宾语+其他成分,再调整一下试试~ +```+
Mum and Dad are great astronauts. I am a great astronaut too! Mum and Dad have jobs. I have a job too! +(爸爸妈妈是很棒的宇航员。我也是一名很棒的宇航员!爸爸妈妈有工作。我也有一份工作!)+
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| img | ++ |
| question | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| optionList | ++ |
| answer | ++ |
| tip | ++ |
| corFeedback | ++ |
| errFeedback | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| optionList | ++ |
| answer | ++ |
| tip | ++ |
| corFeedback | ++ |
| errFeedback | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| optionList | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| question | ++ |
| postDialog | ++ |
| pushType | ++ |
| cType | ++ |
| cId | ++ |
| kpInfo | ++ |
| cType | ++ |
| cId | ++ |
| title | ++ |
| asrPrompt | ++ |
| resourceMapping | ++ |
| preDialog | ++ |
| imgShowTimingList | ++ |
| img | ++ |
| tip | ++ |
| corFeedback | ++ |
| errFeedback | ++ |
| question | ++ |
| example | ++ |
| postDialog | ++ |