auto backup: 2026-05-30 08:10:01

This commit is contained in:
ai_member_only 2026-05-30 08:10:01 +08:00
parent 21d4e0622d
commit 734068fef9
37 changed files with 111604 additions and 48 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -94,6 +94,10 @@ def match_component_type(type_text: str) -> dict:
has_image = True has_image = True
text = text.replace("+图片", "").strip() text = text.replace("+图片", "").strip()
# 剥离任意"-"前缀(如 "核心互动-听力选择" → "听力选择""-配图"/"+图片"已在上方处理)
if '-' in text:
text = text.split('-', 1)[1].strip()
# 优先匹配中互动 # 优先匹配中互动
if text in MID_INTERACTION_TYPES: if text in MID_INTERACTION_TYPES:
info = MID_INTERACTION_TYPES[text] info = MID_INTERACTION_TYPES[text]

View File

@ -243,10 +243,29 @@ def extract_component_id(type_cell):
# --- 策略3: 经典单行格式只有一行ID在第二行--- # --- 策略3: 经典单行格式只有一行ID在第二行---
if cId is None and len(lines) >= 2: if cId is None and len(lines) >= 2:
id_candidate = lines[1] id_candidate = lines[1]
if re.match(r'^\d+$', id_candidate): if re.match(r'^\d{5,}$', id_candidate):
cId = id_candidate cId = id_candidate
type_part = lines[0] type_part = lines[0]
# --- 策略4: 单行 "【核心互动X】N" 格式 (如 "【核心互动写作】15") ---
if cId is None and len(lines) == 1:
m = re.match(r'^[【\[]\s*核心互动[:]\s*(.+?)[】\]]\s*(\d{1,4})$', lines[0])
if m:
type_part = m.group(1).strip()
cId = m.group(2)
# --- 策略5: 单行 "类型名N" 格式 (如 "对话朗读1", "图片多选3", "对话挖空11") ---
if cId is None and len(lines) == 1:
m = re.match(r'^(.+?)(\d{1,4})$', lines[0])
if m:
candidate = m.group(1).strip()
cId = m.group(2)
# 仅当候选类型包含中文且不在非组件标记中
if re.search(r'[\u4e00-\u9fff]', candidate) and candidate not in non_component_markers:
type_part = candidate
else:
cId = None
# 如果依然无 type_part用第一行 # 如果依然无 type_part用第一行
if type_part is None and lines: if type_part is None and lines:
type_part = lines[0] type_part = lines[0]
@ -391,41 +410,146 @@ def extract_section_character_map(markdown):
# Parse table rows # Parse table rows
rows = re.findall(r'<lark-tr>(.*?)</lark-tr>', table_html, re.DOTALL) rows = re.findall(r'<lark-tr>(.*?)</lark-tr>', table_html, re.DOTALL)
char_pattern = re.compile(r'(\d{2,})[-_]([A-Za-z]{2,})') char_pattern = re.compile(r'(\d{2,})[-_]([A-Za-z]{2,}(?:[(][^)]+[)])?)')
section_range_pattern = re.compile(r'S(\d+)(?:\s*-\s*S(\d+))?', re.IGNORECASE) section_range_pattern = re.compile(r'S(\d+)(?:\s*-\s*S(\d+))?', re.IGNORECASE)
# Mode 2: separate columns "Vicky" | "658"
name_only_pattern = re.compile(r'^[A-Za-z]{2,}(?:[(][^)]+[)])?$')
id_only_pattern = re.compile(r'^\d{2,}$')
entries = [] entries = []
current_sections = [] # carry forward from previous row if empty current_sections = [] # carry forward from previous row if empty
# Auto-detect table format by checking first data row
# Mode 1: "658-Vicky" in one cell (char_pattern matches)
# Mode 2: "Vicky" | "658" separate columns (name_only + id_only)
# Within mode 1, also detect swapped (char, section) column order
table_mode = None # "combined" or "separate"
swapped = False
for row_html in rows:
cells = re.findall(r'<lark-td>(.*?)</lark-td>', row_html, re.DOTALL)
if len(cells) < 2:
continue
c0, c1 = cells[0].strip(), cells[1].strip()
if not c0 and not c1:
continue
# Check mode 2 first: separate name and id columns
if name_only_pattern.match(c0) and id_only_pattern.match(c1):
table_mode = "separate"
logger.info("角色-section表格格式为分列 (名称 | ID),自动适配")
break
if id_only_pattern.match(c0) and name_only_pattern.match(c1):
table_mode = "separate_swapped"
logger.info("角色-section表格格式为分列 (ID | 名称),自动适配")
break
# Check mode 1: combined pattern
if char_pattern.search(c0) or char_pattern.search(c1):
table_mode = "combined"
if char_pattern.search(c0) and not char_pattern.search(c1):
swapped = True
logger.info("角色-section表格列序为 (角色, section),自动交换")
break
break
for row_html in rows: for row_html in rows:
cells = re.findall(r'<lark-td>(.*?)</lark-td>', row_html, re.DOTALL) cells = re.findall(r'<lark-td>(.*?)</lark-td>', row_html, re.DOTALL)
if len(cells) < 2: if len(cells) < 2:
continue continue
section_cell = cells[0].strip() if table_mode == "separate":
char_cell = cells[1].strip() # Mode 2: col 0 = name, col 1 = id, col 2 (if exists) = section
name_cell, id_cell = cells[0].strip(), cells[1].strip()
# Parse section range section_cell = cells[2].strip() if len(cells) > 2 else ""
if section_cell: char_name = name_cell
sections = [] # Normalize Chinese brackets
for sm in section_range_pattern.finditer(section_cell): char_name = char_name.replace('', '(').replace('', ')')
start = int(sm.group(1)) # Capitalize base name, preserve case inside parens
end = int(sm.group(2)) if sm.group(2) else start paren_idx = char_name.find('(')
for s in range(start, end + 1): if paren_idx > 0:
sections.append(f"S{s}") char_name = char_name[:paren_idx].capitalize() + char_name[paren_idx:]
if sections: else:
current_sections = sections char_name = char_name.capitalize()
if not char_name or not id_cell:
# Parse character continue
char_match = char_pattern.search(char_cell) char_id = int(id_cell)
if char_match: # Parse section range if present
char_id = int(char_match.group(1)) if section_cell:
char_name = char_match.group(2).capitalize() sections = []
for sm in section_range_pattern.finditer(section_cell):
start = int(sm.group(1))
end = int(sm.group(2)) if sm.group(2) else start
for s in range(start, end + 1):
sections.append(f"S{s}")
if sections:
current_sections = sections
entries.append({ entries.append({
"sections": list(current_sections), "sections": list(current_sections),
"characters": {char_name: char_id}, "characters": {char_name: char_id},
}) })
elif table_mode == "separate_swapped":
# Mode 2 swapped: col 0 = id, col 1 = name
id_cell, name_cell = cells[0].strip(), cells[1].strip()
section_cell = cells[2].strip() if len(cells) > 2 else ""
char_name = name_cell
char_name = char_name.replace('', '(').replace('', ')')
paren_idx = char_name.find('(')
if paren_idx > 0:
char_name = char_name[:paren_idx].capitalize() + char_name[paren_idx:]
else:
char_name = char_name.capitalize()
if not char_name or not id_cell:
continue
char_id = int(id_cell)
if section_cell:
sections = []
for sm in section_range_pattern.finditer(section_cell):
start = int(sm.group(1))
end = int(sm.group(2)) if sm.group(2) else start
for s in range(start, end + 1):
sections.append(f"S{s}")
if sections:
current_sections = sections
entries.append({
"sections": list(current_sections),
"characters": {char_name: char_id},
})
else:
# Mode 1: combined pattern in one cell
if swapped:
char_cell, section_cell = cells[0].strip(), cells[1].strip()
else:
section_cell, char_cell = cells[0].strip(), cells[1].strip()
# Parse section range
if section_cell:
sections = []
for sm in section_range_pattern.finditer(section_cell):
start = int(sm.group(1))
end = int(sm.group(2)) if sm.group(2) else start
for s in range(start, end + 1):
sections.append(f"S{s}")
if sections:
current_sections = sections
# Parse character (capture optional parenthetical suffix like "MayNoDiDi")
char_match = char_pattern.search(char_cell)
if char_match:
char_id = int(char_match.group(1))
raw_name = char_match.group(2)
# Normalize Chinese brackets to ASCII for consistency
raw_name = raw_name.replace('', '(').replace('', ')')
# Capitalize the base name but preserve case inside parentheses
paren_idx = raw_name.find('(')
if paren_idx > 0:
char_name = raw_name[:paren_idx].capitalize() + raw_name[paren_idx:]
else:
char_name = raw_name.capitalize()
entries.append({
"sections": list(current_sections),
"characters": {char_name: char_id},
})
logger.info(f"提取角色-section对应: {len(entries)} 条记录") logger.info(f"提取角色-section对应: {len(entries)} 条记录")
return entries return entries
@ -479,7 +603,7 @@ def extract_character_map(sheet_rows):
char_map = {} char_map = {}
# 正则匹配 "数字-名字" 或 "数字_名字" 模式 # 正则匹配 "数字-名字" 或 "数字_名字" 模式
# 名字至少2个字母避免匹配 L1_S02 之类的剧本标记 # 名字至少2个字母避免匹配 L1_S02 之类的剧本标记
pattern = re.compile(r'(\d{2,})[-_]([A-Za-z]{2,})') pattern = re.compile(r'(\d{2,})[-_]([A-Za-z]{2,}(?:[(][^)]+[)])?)')
for row in sheet_rows[:30]: # 角色表通常在前 30 行 for row in sheet_rows[:30]: # 角色表通常在前 30 行
for cell in row: for cell in row:
@ -491,8 +615,13 @@ def extract_character_map(sheet_rows):
# 过滤掉明显不是角色名的(纯大写短标记如 "TA" # 过滤掉明显不是角色名的(纯大写短标记如 "TA"
if len(char_name) <= 2 and char_name.isupper(): if len(char_name) <= 2 and char_name.isupper():
continue continue
# 统一首字母大写 # 统一首字母大写,标准化括号
normalized = char_name.capitalize() raw = char_name.replace('', '(').replace('', ')')
paren_idx = raw.find('(')
if paren_idx > 0:
normalized = raw[:paren_idx].capitalize() + raw[paren_idx:]
else:
normalized = raw.capitalize()
if normalized not in char_map: if normalized not in char_map:
char_map[normalized] = char_id char_map[normalized] = char_id
@ -573,6 +702,12 @@ def parse_sheet_rows(sheet_rows, llm_client=None):
type_cell = row[type_col] if len(row) > type_col else None type_cell = row[type_col] if len(row) > type_col else None
comp_info = extract_component_id_with_llm_fallback(type_cell, llm_client) comp_info = extract_component_id_with_llm_fallback(type_cell, llm_client)
# 如果类型列提取的cId是短序号<5位如1/2/3但有独立ID列优先用独立ID列覆盖
if comp_info is not None and id_col is not None and len(comp_info.get("cId", "")) < 5:
raw_id = str(row[id_col]).strip() if len(row) > id_col and row[id_col] else ""
if raw_id and re.match(r'^\d{5,}$', raw_id):
comp_info["cId"] = raw_id
# 如果类型列没有嵌入式ID但有独立ID列且类型名是纯中文组件名 # 如果类型列没有嵌入式ID但有独立ID列且类型名是纯中文组件名
if comp_info is None and id_col is not None: if comp_info is None and id_col is not None:
raw_cell = str(row[id_col]).strip() if len(row) > id_col and row[id_col] else "" raw_cell = str(row[id_col]).strip() if len(row) > id_col and row[id_col] else ""

View File

@ -197,7 +197,7 @@ def _ensure_proxy_running():
return proxy_url return proxy_url
def process_script(wiki_url_or_token, db_path=None, dry_run=False): def process_script(wiki_url_or_token, db_path=None, dry_run=False, target_cids=None):
""" """
端到端处理一个剧本文档 端到端处理一个剧本文档
@ -205,6 +205,7 @@ def process_script(wiki_url_or_token, db_path=None, dry_run=False):
wiki_url_or_token: 飞书 wiki URL wiki_token wiki_url_or_token: 飞书 wiki URL wiki_token
db_path: SQLite 数据库路径默认使用 db/components.db db_path: SQLite 数据库路径默认使用 db/components.db
dry_run: 如果为 True只生成不写入DB dry_run: 如果为 True只生成不写入DB
target_cids: 可选的组件 ID 集合仅处理这些 ID 的组件
Returns: Returns:
dict: 处理报告 dict: 处理报告
@ -280,11 +281,25 @@ def process_script(wiki_url_or_token, db_path=None, dry_run=False):
parsed = best_parsed parsed = best_parsed
character_map = parsed["character_map"] character_map = parsed["character_map"]
section_char_map = parsed.get("section_char_map", []) section_char_map = parsed.get("section_char_map", [])
# 如果 sheet 中没有角色信息,从 section_char_map 中合并
if not character_map and section_char_map:
for entry in section_char_map:
for name, cid in (entry.get("characters", {})).items():
if name not in character_map:
character_map[name] = cid
if character_map:
logger.info(f"从 section_char_map 合并角色映射: {character_map}")
components = parsed["components"] components = parsed["components"]
# 更新 doc_data 中的 sheet_rows 为匹配到的那个 # 更新 doc_data 中的 sheet_rows 为匹配到的那个
if best_sheet_rows is not None: if best_sheet_rows is not None:
doc_data["sheet_rows"] = best_sheet_rows doc_data["sheet_rows"] = best_sheet_rows
report["total_components"] = len(components) report["total_components"] = len(components)
if target_cids:
target_set = set(int(c) if isinstance(c, str) else c for c in target_cids)
components = [c for c in components if int(c.get("cId", 0)) in target_set]
logger.info(f"按 --cids 过滤后: {len(components)} 个组件, 目标ID: {target_set}")
report["total_components"] = len(components)
logger.info(f"最终识别到 {len(components)} 个组件, 角色映射: {character_map}, section映射: {len(section_char_map)}") logger.info(f"最终识别到 {len(components)} 个组件, 角色映射: {character_map}, section映射: {len(section_char_map)}")
# Step 3: 初始化DB # Step 3: 初始化DB
@ -292,8 +307,17 @@ def process_script(wiki_url_or_token, db_path=None, dry_run=False):
init_db() init_db()
logger.info(f"数据库已初始化") logger.info(f"数据库已初始化")
if not components:
logger.warning("没有组件需要处理")
report["success"] = 0
report["failed"] = 0
report["skipped"] = 0
report["results"] = []
return report
# Step 4: 并行组件生成 # Step 4: 并行组件生成
logger.info(f"=== Step 3: 并行组件生成 jsonData/kpInfo (workers=4) ===") max_workers = min(4, len(components))
logger.info(f"=== Step 3: 并行组件生成 jsonData/kpInfo (workers={max_workers}) ===")
# 提取元数据 # 提取元数据
metadata = parsed.get("metadata", {}) metadata = parsed.get("metadata", {})
@ -668,6 +692,13 @@ if __name__ == "__main__":
if idx + 1 < len(sys.argv): if idx + 1 < len(sys.argv):
limit = int(sys.argv[idx + 1]) limit = int(sys.argv[idx + 1])
# 支持 --cids 1218101,1218102 参数按组件ID过滤
target_cids = None
if "--cids" in sys.argv:
idx = sys.argv.index("--cids")
if idx + 1 < len(sys.argv):
target_cids = set(int(c) for c in sys.argv[idx + 1].split(",") if c.strip())
# 支持 --send-to <user_id> 参数 # 支持 --send-to <user_id> 参数
send_to_user = None send_to_user = None
if "--send-to" in sys.argv: if "--send-to" in sys.argv:
@ -692,7 +723,7 @@ if __name__ == "__main__":
parse_script.parse_script_from_sheet = limited_parse parse_script.parse_script_from_sheet = limited_parse
globals()["parse_script_from_sheet"] = limited_parse globals()["parse_script_from_sheet"] = limited_parse
report = process_script(wiki_input, dry_run=dry_run) report = process_script(wiki_input, dry_run=dry_run, target_cids=target_cids)
# 输出日志和HTML路径 # 输出日志和HTML路径
if report.get("log_path"): if report.get("log_path"):

View File

@ -76,3 +76,6 @@
{"type":"memory.recall.recorded","timestamp":"2026-05-28T03:07:46.098Z","query":"6题 刘彦江 看图拼词 imgMakeWord","resultCount":1,"results":[{"path":"memory/2026-05-12.md","startLine":137,"endLine":149,"score":1}]} {"type":"memory.recall.recorded","timestamp":"2026-05-28T03:07:46.098Z","query":"6题 刘彦江 看图拼词 imgMakeWord","resultCount":1,"results":[{"path":"memory/2026-05-12.md","startLine":137,"endLine":149,"score":1}]}
{"type":"memory.recall.recorded","timestamp":"2026-05-28T03:08:15.128Z","query":"看图拼词 imgMakeWord 样例 6题 刘彦江 2026-05-25","resultCount":1,"results":[{"path":"memory/2026-05-07.md","startLine":1,"endLine":20,"score":1}]} {"type":"memory.recall.recorded","timestamp":"2026-05-28T03:08:15.128Z","query":"看图拼词 imgMakeWord 样例 6题 刘彦江 2026-05-25","resultCount":1,"results":[{"path":"memory/2026-05-07.md","startLine":1,"endLine":20,"score":1}]}
{"type":"memory.recall.recorded","timestamp":"2026-05-28T10:04:34.024Z","query":"李若松 身份 user_id","resultCount":2,"results":[{"path":"memory/2026-04-30.md","startLine":50,"endLine":63,"score":1},{"path":"memory/2026-05-08.md","startLine":18,"endLine":38,"score":1}]} {"type":"memory.recall.recorded","timestamp":"2026-05-28T10:04:34.024Z","query":"李若松 身份 user_id","resultCount":2,"results":[{"path":"memory/2026-04-30.md","startLine":50,"endLine":63,"score":1},{"path":"memory/2026-05-08.md","startLine":18,"endLine":38,"score":1}]}
{"type":"memory.recall.recorded","timestamp":"2026-05-29T00:23:17.391Z","query":"输出文本和JSON 题型 单元挑战 questionSet 看图组词 单词释义","resultCount":1,"results":[{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1}]}
{"type":"memory.recall.recorded","timestamp":"2026-05-29T00:23:17.392Z","query":"reading_pic_makeWord reading_word_definition listening_listenWrite reading_select_cloze 修正","resultCount":5,"results":[{"path":"memory/2026-05-07.md","startLine":1,"endLine":20,"score":1},{"path":"memory/2026-05-11.md","startLine":1,"endLine":25,"score":1},{"path":"memory/2026-05-17.md","startLine":19,"endLine":41,"score":1},{"path":"memory/2026-05-12.md","startLine":170,"endLine":193,"score":1},{"path":"memory/2026-05-21.md","startLine":52,"endLine":67,"score":1}]}
{"type":"memory.recall.recorded","timestamp":"2026-05-29T02:33:30.526Z","query":"梁晨 l1_pedagogy_rules pedagogy rules JS文件","resultCount":6,"results":[{"path":"memory/2026-05-26.md","startLine":130,"endLine":166,"score":1},{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1},{"path":"memory/2026-05-25.md","startLine":283,"endLine":302,"score":1},{"path":"memory/2026-05-25.md","startLine":118,"endLine":137,"score":1},{"path":"memory/2026-05-28.md","startLine":60,"endLine":66,"score":1},{"path":"memory/2026-05-20.md","startLine":1,"endLine":31,"score":1}]}

View File

@ -1,6 +1,6 @@
{ {
"version": 1, "version": 1,
"updatedAt": "2026-05-28T10:04:34.024Z", "updatedAt": "2026-05-29T02:33:30.526Z",
"entries": { "entries": {
"memory:memory/2026-05-07.md:57:74": { "memory:memory/2026-05-07.md:57:74": {
"key": "memory:memory/2026-05-07.md:57:74", "key": "memory:memory/2026-05-07.md:57:74",
@ -117,13 +117,13 @@
"endLine": 20, "endLine": 20,
"source": "memory", "source": "memory",
"snippet": "# 2026-05-07 工作日志 ## 会话记录 ### 刘彦江 (ou_5af74c1fb96042e33cc0f16b5ca02cf4) — 单元挑战新增3个题型 - **时间:** 11:19 ~ 11:28 - **需求:** 单元挑战新增3个题型阅读看图回答题reading_pic_qa、阅读看图判断题reading_pic_judge、写作看图回答题writing_pic_qa - **状态:** ✅ 已完成题型规范落地 - **交付内容:** 1. 创建3个题型SKILL.md - `reading/common/reading_pic_qa/SKILL.md` — 阅读看图回答题(共享大图+多题Yes/No判断 - `reading/common/reading_pic_judge/SKILL.md` — 阅读看图判断题(每题独立配图+Yes/No判断 - `writing/common/writing_pic_qa/SKILL.md` — 写作看图回答题(看图+提示答案开头+填空) 2. 更新 `MEMORY.md` 全题型阶段归属规则 3. 明确题型JSON结构、难度等级A/B/C/D四级、能力标签、校验规则 - **关键决策:** 3个题型均为 L1&L2 共用通过难度参数区分阶段reading_pic_qa 共享大图reading_pic_judge 每题独立配图 ### 李应瑛 (ou_1bd7317ae2ccfeb57e1132028847279e) — 单词表对比请求", "snippet": "# 2026-05-07 工作日志 ## 会话记录 ### 刘彦江 (ou_5af74c1fb96042e33cc0f16b5ca02cf4) — 单元挑战新增3个题型 - **时间:** 11:19 ~ 11:28 - **需求:** 单元挑战新增3个题型阅读看图回答题reading_pic_qa、阅读看图判断题reading_pic_judge、写作看图回答题writing_pic_qa - **状态:** ✅ 已完成题型规范落地 - **交付内容:** 1. 创建3个题型SKILL.md - `reading/common/reading_pic_qa/SKILL.md` — 阅读看图回答题(共享大图+多题Yes/No判断 - `reading/common/reading_pic_judge/SKILL.md` — 阅读看图判断题(每题独立配图+Yes/No判断 - `writing/common/writing_pic_qa/SKILL.md` — 写作看图回答题(看图+提示答案开头+填空) 2. 更新 `MEMORY.md` 全题型阶段归属规则 3. 明确题型JSON结构、难度等级A/B/C/D四级、能力标签、校验规则 - **关键决策:** 3个题型均为 L1&L2 共用通过难度参数区分阶段reading_pic_qa 共享大图reading_pic_judge 每题独立配图 ### 李应瑛 (ou_1bd7317ae2ccfeb57e1132028847279e) — 单词表对比请求",
"recallCount": 11, "recallCount": 12,
"dailyCount": 0, "dailyCount": 0,
"groundedCount": 0, "groundedCount": 0,
"totalScore": 11, "totalScore": 12,
"maxScore": 1, "maxScore": 1,
"firstRecalledAt": "2026-05-08T01:18:18.412Z", "firstRecalledAt": "2026-05-08T01:18:18.412Z",
"lastRecalledAt": "2026-05-28T03:08:15.128Z", "lastRecalledAt": "2026-05-29T00:23:17.392Z",
"queryHashes": [ "queryHashes": [
"390d35f8d143", "390d35f8d143",
"fd4c9b7de37b", "fd4c9b7de37b",
@ -135,7 +135,8 @@
"d592c9ed5e0a", "d592c9ed5e0a",
"5f858a7d5e0b", "5f858a7d5e0b",
"ab90b7e9cde8", "ab90b7e9cde8",
"fbf96ac9320e" "fbf96ac9320e",
"bd790c7e2a35"
], ],
"recallDays": [ "recallDays": [
"2026-05-08", "2026-05-08",
@ -145,7 +146,8 @@
"2026-05-14", "2026-05-14",
"2026-05-17", "2026-05-17",
"2026-05-26", "2026-05-26",
"2026-05-28" "2026-05-28",
"2026-05-29"
], ],
"conceptTags": [ "conceptTags": [
"reading-pic-qa", "reading-pic-qa",
@ -795,25 +797,27 @@
"endLine": 193, "endLine": 193,
"source": "memory", "source": "memory",
"snippet": "- 每个题型cType + bitable 定位 + JSON 字段表 + 结构特点 + 与同类题型的差异说明 #### 发现 - 写作互动和邮件组句 cType 相同(`core_writing_questionMakeSentence`),通过 textInfo 区分素材 - 口语快答/妙问 JSON 结构几乎相同,差异在 prompt 配置和对话样例内容 - 合作阅读和合作听力的核心差异:`textData.text[]` ↔ `textData.audio[]` - meaning 标签(合作阅读)为开放型自由文本,非受控词表 #### 产出文件 - `skills/bitable-reader/SKILL.md` — 通用 bitable 读取技能164行 - `skills/core-content-json-standard/SKILL.md` — 全题型 JSON 标准 v2.0393行 - `scripts/audit_core_reading_S0.py` — 合作阅读 S0 审校脚本(含审校发现) # 2026-05-12 工作日志 ## 会话记录 ### 刘彦江 — 021301-021801 图片描述修正 + 技能更新09:35 ~ 09:45 - **问题:** 021301-021801 信息匹配题的图片描述缺少 `【Notice Type】` 标签 - **处理:** 批量更新6条记录的图片描述字段全部10个标签验证通过 - **脚本:** `scripts/fix_matchInfo_0213_0218_desc.py`", "snippet": "- 每个题型cType + bitable 定位 + JSON 字段表 + 结构特点 + 与同类题型的差异说明 #### 发现 - 写作互动和邮件组句 cType 相同(`core_writing_questionMakeSentence`),通过 textInfo 区分素材 - 口语快答/妙问 JSON 结构几乎相同,差异在 prompt 配置和对话样例内容 - 合作阅读和合作听力的核心差异:`textData.text[]` ↔ `textData.audio[]` - meaning 标签(合作阅读)为开放型自由文本,非受控词表 #### 产出文件 - `skills/bitable-reader/SKILL.md` — 通用 bitable 读取技能164行 - `skills/core-content-json-standard/SKILL.md` — 全题型 JSON 标准 v2.0393行 - `scripts/audit_core_reading_S0.py` — 合作阅读 S0 审校脚本(含审校发现) # 2026-05-12 工作日志 ## 会话记录 ### 刘彦江 — 021301-021801 图片描述修正 + 技能更新09:35 ~ 09:45 - **问题:** 021301-021801 信息匹配题的图片描述缺少 `【Notice Type】` 标签 - **处理:** 批量更新6条记录的图片描述字段全部10个标签验证通过 - **脚本:** `scripts/fix_matchInfo_0213_0218_desc.py`",
"recallCount": 5, "recallCount": 6,
"dailyCount": 0, "dailyCount": 0,
"groundedCount": 0, "groundedCount": 0,
"totalScore": 5, "totalScore": 6,
"maxScore": 1, "maxScore": 1,
"firstRecalledAt": "2026-05-14T02:49:02.264Z", "firstRecalledAt": "2026-05-14T02:49:02.264Z",
"lastRecalledAt": "2026-05-22T07:04:01.804Z", "lastRecalledAt": "2026-05-29T00:23:17.392Z",
"queryHashes": [ "queryHashes": [
"d592c9ed5e0a", "d592c9ed5e0a",
"5f858a7d5e0b", "5f858a7d5e0b",
"34bf2e5fbdee", "34bf2e5fbdee",
"3f9471df9e50", "3f9471df9e50",
"d13d58b4704a" "d13d58b4704a",
"bd790c7e2a35"
], ],
"recallDays": [ "recallDays": [
"2026-05-14", "2026-05-14",
"2026-05-17", "2026-05-17",
"2026-05-19", "2026-05-19",
"2026-05-22" "2026-05-22",
"2026-05-29"
], ],
"conceptTags": [ "conceptTags": [
"口语快答/妙问", "口语快答/妙问",
@ -1031,20 +1035,22 @@
"endLine": 41, "endLine": 41,
"source": "memory", "source": "memory",
"snippet": "- `raw_content` API 不暴露此类嵌入 Sheet需通过 blocks API 查找 `block_type=30` 的 grid_column 节点来发现 sheet token - 该文档含 2 个嵌入 Sheet`zbfYO4`(知识点区)和 `Nr3Ovs`243 行 × 8 列脚本表) ### 已完成的组件回填14/14 对话组件) | 组件类型 | 数量 | 所用 skill | |---------|:--:|-----------| | 对话朗读 | 6 | dialogue-reading-config | | 对话朗读-配图 | 2 | dialogue-reading-config | | 对话挖空 | 2 | dialogue-fill-in-blanks-config | | 对话挖空-配图 | 1 | dialogue-fill-in-blanks-config | | 对话选择-配图 | 1 | dialogue-choose-config | | 对话选读 | 1 | **dialogue-selective-reading-config新建** | | 对话组句 | 1 | dialogue-sentence-building-config | ### Skill 库补全 - **新建 skill**`~/.openclaw/workspace-xiaoyan/skills/dialogue-selective-reading-config/SKILL.md` - 格式来源:`dialogue-inter", "snippet": "- `raw_content` API 不暴露此类嵌入 Sheet需通过 blocks API 查找 `block_type=30` 的 grid_column 节点来发现 sheet token - 该文档含 2 个嵌入 Sheet`zbfYO4`(知识点区)和 `Nr3Ovs`243 行 × 8 列脚本表) ### 已完成的组件回填14/14 对话组件) | 组件类型 | 数量 | 所用 skill | |---------|:--:|-----------| | 对话朗读 | 6 | dialogue-reading-config | | 对话朗读-配图 | 2 | dialogue-reading-config | | 对话挖空 | 2 | dialogue-fill-in-blanks-config | | 对话挖空-配图 | 1 | dialogue-fill-in-blanks-config | | 对话选择-配图 | 1 | dialogue-choose-config | | 对话选读 | 1 | **dialogue-selective-reading-config新建** | | 对话组句 | 1 | dialogue-sentence-building-config | ### Skill 库补全 - **新建 skill**`~/.openclaw/workspace-xiaoyan/skills/dialogue-selective-reading-config/SKILL.md` - 格式来源:`dialogue-inter",
"recallCount": 2, "recallCount": 3,
"dailyCount": 0, "dailyCount": 0,
"groundedCount": 0, "groundedCount": 0,
"totalScore": 2, "totalScore": 3,
"maxScore": 1, "maxScore": 1,
"firstRecalledAt": "2026-05-18T02:42:25.325Z", "firstRecalledAt": "2026-05-18T02:42:25.325Z",
"lastRecalledAt": "2026-05-21T02:47:59.335Z", "lastRecalledAt": "2026-05-29T00:23:17.392Z",
"queryHashes": [ "queryHashes": [
"eb45753e9aa6", "eb45753e9aa6",
"09344f87b646" "09344f87b646",
"bd790c7e2a35"
], ],
"recallDays": [ "recallDays": [
"2026-05-18", "2026-05-18",
"2026-05-21" "2026-05-21",
"2026-05-29"
], ],
"conceptTags": [ "conceptTags": [
"raw-content", "raw-content",
@ -1957,20 +1963,22 @@
"endLine": 31, "endLine": 31,
"source": "memory", "source": "memory",
"snippet": "# 2026-05-20 工作日志 ## [童瑶] L1-S2-U17-L2 迟到的包裹 — 英文台词润色 - 134行对话台词全部润色完成写入H列 - S2标准句长≤8词、英式拼写、口语化、知识点保留 - 详情见 `business_production/英文台词/memory/2026-05-20.md` ## [童瑶] L1-S2-U17-L1 摩托怪客 — 组件配置JSON - 16个互动组件14个成功生成JSON2个跳过 - 跳过:图片无序多选(注册表无匹配)、阅读理解(核心互动未注册) - HTML报告已通过飞书Bot发送给童瑶 ## [童瑶] L1-S2-U17-L4 捉迷藏 — 组件生产第111行起 - **文档**: SAadwW8YaiObl8k4op3c6vs8nqb | **Sheet**: wMQVyV | **Spreadsheet**: It4AsFkC7hXHc4te9yUcyLHRnOe - 从第111行起识别9个互动组件全部完成F列回填最终验证通过 - 最终组件行及对应关系: | 行号 | 组件类型 | 组件ID | |------|---------|--------| | 111 | 对话选择-配图 | 1217408 | | 119 | 对话选择-配图 | 1217409 | | 127 | 对话挖空-配图 | 1217410 | | 130 | 对话组句-配图 | 1217411 | | 141 | 对话组句-配图 | 1217412 | | 150 | 看图拼词 | 1217413 | | 166 | 对话", "snippet": "# 2026-05-20 工作日志 ## [童瑶] L1-S2-U17-L2 迟到的包裹 — 英文台词润色 - 134行对话台词全部润色完成写入H列 - S2标准句长≤8词、英式拼写、口语化、知识点保留 - 详情见 `business_production/英文台词/memory/2026-05-20.md` ## [童瑶] L1-S2-U17-L1 摩托怪客 — 组件配置JSON - 16个互动组件14个成功生成JSON2个跳过 - 跳过:图片无序多选(注册表无匹配)、阅读理解(核心互动未注册) - HTML报告已通过飞书Bot发送给童瑶 ## [童瑶] L1-S2-U17-L4 捉迷藏 — 组件生产第111行起 - **文档**: SAadwW8YaiObl8k4op3c6vs8nqb | **Sheet**: wMQVyV | **Spreadsheet**: It4AsFkC7hXHc4te9yUcyLHRnOe - 从第111行起识别9个互动组件全部完成F列回填最终验证通过 - 最终组件行及对应关系: | 行号 | 组件类型 | 组件ID | |------|---------|--------| | 111 | 对话选择-配图 | 1217408 | | 119 | 对话选择-配图 | 1217409 | | 127 | 对话挖空-配图 | 1217410 | | 130 | 对话组句-配图 | 1217411 | | 141 | 对话组句-配图 | 1217412 | | 150 | 看图拼词 | 1217413 | | 166 | 对话",
"recallCount": 2, "recallCount": 3,
"dailyCount": 0, "dailyCount": 0,
"groundedCount": 0, "groundedCount": 0,
"totalScore": 2, "totalScore": 3,
"maxScore": 1, "maxScore": 1,
"firstRecalledAt": "2026-05-21T07:31:52.322Z", "firstRecalledAt": "2026-05-21T07:31:52.322Z",
"lastRecalledAt": "2026-05-27T07:13:57.033Z", "lastRecalledAt": "2026-05-29T02:33:30.526Z",
"queryHashes": [ "queryHashes": [
"03b71fab8fb9", "03b71fab8fb9",
"62070213f719" "62070213f719",
"4aa0ef719160"
], ],
"recallDays": [ "recallDays": [
"2026-05-21", "2026-05-21",
"2026-05-27" "2026-05-27",
"2026-05-29"
], ],
"conceptTags": [ "conceptTags": [
"l1-s2-u17-l2", "l1-s2-u17-l2",
@ -2639,6 +2647,224 @@
"对话挖空-配图", "对话挖空-配图",
"对话选择-配图" "对话选择-配图"
] ]
},
"memory:memory/2026-05-28.md:46:62": {
"key": "memory:memory/2026-05-28.md:46:62",
"path": "memory/2026-05-28.md",
"startLine": 46,
"endLine": 62,
"source": "memory",
"snippet": "- B级规则听力句子 5-8 词(均 7 词),每组 3 张同类物品不同属性图片 - 能力标签:显性事实理解|关键词识别 ×2 + 基础语境理解|场景/物品/动作识别 ## 梁辰user_id: ou_28f02dcada1193913cfbb6310f8daf07— HTML 诊断页面教研规则 JS 文件 - 用户有一个 L1 关卡诊断工作台 HTML 页面(部署在腾讯云空间),当前只做数量级统计,缺少教研规则校验 - 需求:提供可嵌入 HTML 的前端 JS 校验规则文件,使诊断有据可依 - 输出:`output/l1_pedagogy_rules.js`42KB包含 8 个校验维度: 1. 词汇超纲检测(基于 L1/L2 词库) 2. 英式拼写检测color→colour 等 115 组映射) 3. Markdown 标记检测(`**`/`#`/`>` 等) 4. 标点规范检测(全角混入、``、`!!!` 5. 题型-阶段匹配校验20 种题型对应的 L1/L2 阶段映射) 6. 台词质量分析(句子长度、负面评价) 7. 知识点曝光度 8. 句型合规检测 - 接入方式:`<script src=\"l1_pedagogy_rules.js\"></script>` + 调用 `PedagogyRules.validate(summary, level)` - 数据源L1 词库 147 词(过滤 enabled=true、L2 词库 52 词、L1 句型 8 个、L2 句型(从 437MB bitable 导出中提取唯一结",
"recallCount": 2,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 2,
"maxScore": 1,
"firstRecalledAt": "2026-05-29T00:23:17.391Z",
"lastRecalledAt": "2026-05-29T02:33:30.526Z",
"queryHashes": [
"c1d4076205e1",
"4aa0ef719160"
],
"recallDays": [
"2026-05-29"
],
"conceptTags": [
"5-8",
"场景/物品/动作识别",
"user-id",
"output/l1-pedagogy-rules.js",
"l1/l2",
"题型-阶段匹配校验",
"l1-pedagogy-rules.js",
"pedagogyrules.validate"
]
},
"memory:memory/2026-05-11.md:1:25": {
"key": "memory:memory/2026-05-11.md:1:25",
"path": "memory/2026-05-11.md",
"startLine": 1,
"endLine": 25,
"source": "memory",
"snippet": "### 刘彦江 — reading_pic_judge 看图判断题批量生产4套17:28 ~ 17:35 - **需求:** 4套 reading_pic_judgeL1 A级能力标签 图文匹配 - **题型特点:** 每题独立配图questionImagefirst/second双题组包裹 - **状态:** ✅ 已完成4套全部入库+图片描述回填验证通过 - **脚本:** `scripts/batch_reading_pic_judge.py`、`scripts/update_pic_judge_descriptions.py` | ID | 题组1 | 题组2 | Y/N | 图片描述 | |----|-------|-------|-----|---------| | 121301 | home/house/sofa/cupboard/bedroom | zoo/hippo/bear/jeans/sock | 3Y2N | ✅ 596chars | | 121401 | student/school/teacher/crayon/board | mat/letter/desk/schoolbag/handbag | 3Y2N | ✅ 562chars | | 121501 | body/head/mouth/ear/friend | camera/boy/girl/skateboarding/skateboard | 3Y2N | ✅ 553chars | | 121601 | summer/autumn/winter/cold/spring |",
"recallCount": 1,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 1,
"maxScore": 1,
"firstRecalledAt": "2026-05-29T00:23:17.392Z",
"lastRecalledAt": "2026-05-29T00:23:17.392Z",
"queryHashes": [
"bd790c7e2a35"
],
"recallDays": [
"2026-05-29"
],
"conceptTags": [
"reading-pic-judge",
"first/second双题组包裹",
"y/n",
"home/house/sofa/cupboard/bedroom",
"zoo/hippo/bear/jeans/sock",
"body/head/mouth/ear/friend",
"summer/autumn/winter/cold/spring",
"彦江"
]
},
"memory:memory/2026-05-21.md:52:67": {
"key": "memory:memory/2026-05-21.md:52:67",
"path": "memory/2026-05-21.md",
"startLine": 52,
"endLine": 67,
"source": "memory",
"snippet": "- 共 17 个互动行:对话朗读-配图(6) / 对话朗读(1) / 对话挖空-配图(1) / 对话挖空(4) / 对话选择-配图(1) / 对话选读(2) / 对话组句-配图(1) / 对话组句(1) / 看图说话(1) #### 组件类型 A 列取值与技能映射(新增类型) | A列类型 | 对应技能 | 备注 | |---------|---------|------| | 对话朗读 / 对话朗读-配图 | dialogue-reading-config | -配图需加图片时机和音频载体 | | 对话挖空 / 对话挖空-配图 | dialogue-fill-in-blanks-config | 同上 | | 对话选择 / 对话选择-配图 | dialogue-choose-config | 同上 | | **对话选读** | dialogue-selective-reading-config | 开放表达,无正确选项,每选项必带反馈 | | **对话组句** | dialogue-sentence-building-config | 单词排序组句,含答案+辅助信息 | | **看图说话** | dialogue-image-description-config | 导览配置+对话配置含Q&A/通过规则/示例对话 | #### 类型区别关键点 - **对话选择 vs 对话选读**:前者有对错判断(正确选项标注),后者开放表达(无正确选项,每选项均带反馈) - **对话挖空**`___` 必需三下划线选项2-3个反馈角色非 User - **对话组句**:选项为独立",
"recallCount": 1,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 1,
"maxScore": 1,
"firstRecalledAt": "2026-05-29T00:23:17.392Z",
"lastRecalledAt": "2026-05-29T00:23:17.392Z",
"queryHashes": [
"bd790c7e2a35"
],
"recallDays": [
"2026-05-29"
],
"conceptTags": [
"对话朗读-配图",
"对话挖空-配图",
"对话选择-配图",
"对话组句-配图",
"dialogue-reading-config",
"dialogue-fill-in-blanks-config",
"dialogue-choose-config",
"a/通过规则/示例对话"
]
},
"memory:memory/2026-05-26.md:130:166": {
"key": "memory:memory/2026-05-26.md:130:166",
"path": "memory/2026-05-26.md",
"startLine": 130,
"endLine": 166,
"source": "memory",
"snippet": "## 英文台词生产 [童瑶] — L1-S2-U20 全系列 ### L1-S2-U20-L1 冠军计划 - **文档:** `EbkUwEjaticOkHknf0icsQ2Yn4Q` | Sheet `6aqvM2` - 对话 148 行,写入 E 列 ✅ ### L1-S2-U20-L2 发球大战 - **文档:** `BvSyw1vlfiwCr5kjkPmcUYXynZd` | Sheet `wMQVyV` - 对话 135 行,写入 F 列 ✅ ### L1-S2-U20-L3 曲棍球练习赛 - **文档:** `MrsAwcYq2iCy7Tkk3dkclS0mnlg` | Sheet `6aqvM2` - 对话 149 行28 行修改,写入 F 列 ✅ - 知识点hockey/interesting/one/try + `have a try`/`One...the other...` ### L1-S2-U20-L4 网球明星 - **文档:** `GT4awLQx9iOfWHk00ZFcHQzbnzT` | Sheet `wMQVyV` - 对话 112 行26 行修改,写入 F 列 ✅ - 知识点tennis/tennis racket/bounce/wave + `wave(s) to`/`Hit the ball!` ### L1-S2-U20-L5 足球接力赛 - **文档:** `VEGwwoVdTiFu00koNoOc1MGhnec` | Sheet `AV1gO0` - 对话 137 行28 行修改,写入 F 列 ✅ - 知识点:",
"recallCount": 1,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 1,
"maxScore": 1,
"firstRecalledAt": "2026-05-29T02:33:30.526Z",
"lastRecalledAt": "2026-05-29T02:33:30.526Z",
"queryHashes": [
"4aa0ef719160"
],
"recallDays": [
"2026-05-29"
],
"conceptTags": [
"l1-s2-u20",
"l1-s2-u20-l1",
"l1-s2-u20-l2",
"l1-s2-u20-l3",
"hockey/interesting/one/try",
"l1-s2-u20-l4",
"tennis/tennis",
"racket/bounce/wave"
]
},
"memory:memory/2026-05-25.md:283:302": {
"key": "memory:memory/2026-05-25.md:283:302",
"path": "memory/2026-05-25.md",
"startLine": 283,
"endLine": 302,
"source": "memory",
"snippet": "- 14 阶段 4 科目全部重写,目标文档: `W5Vjw2fLiiCqfck0Mfzc0xkrnte` - L2 阶段1-2 阅读/写作从\"无\"补为实际技能点(刘彦江确认\"L2 阶段1-2 阅读和写作都是有题型的\" - L1 阶段1 阅读/写作也从\"无\"补为实际技能点 - 0 个\"无\",全量覆盖 - 生成脚本: `tmp/build_skill_points.py` ## 生产覆盖范围修正 [刘彦江] - L1 生产到 **U16**(非 U33 - L2 生产到 **U29**(非 U16 - 已同步更新 `business_knowledge/单元挑战全貌.md` ## 单元挑战全貌文档 [刘彦江] - 创建 `business_knowledge/单元挑战全貌.md` - 覆盖九大板块业务定位、阶段划分、题型体系18种、能力标签45个、生产流程ID规则/标准/写入陷阱、审校体系7+4项检查、生产覆盖现状、模块关联、快速链接 ## L1/L2 难度等级映射 [刘彦江] ✅已确认 - L1-A: Starters入门+基础 (U1-U16) | L1-B: Starters达标 (U17-U24) | L1-C: Movers入门+基础 (U25-U40) | L1-D: Movers达标 (U41-U48) - L2-A: Flyers入门+基础 (U1-U12) | L2-B: Flyers达标 (U13-U18) | L2-C: KET入门+基础 (U19-U30) | L2-D: KET强化+高位+达标 (U31-U48) - 已写入",
"recallCount": 1,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 1,
"maxScore": 1,
"firstRecalledAt": "2026-05-29T02:33:30.526Z",
"lastRecalledAt": "2026-05-29T02:33:30.526Z",
"queryHashes": [
"4aa0ef719160"
],
"recallDays": [
"2026-05-29"
],
"conceptTags": [
"阶段1-2",
"阅读/写作从",
"阅读/写作也从",
"tmp/build-skill-points.py",
"business-knowledge/单元挑战全貌.md",
"id规则/标准/写入陷阱",
"l1/l2",
"l1-a"
]
},
"memory:memory/2026-05-25.md:118:137": {
"key": "memory:memory/2026-05-25.md:118:137",
"path": "memory/2026-05-25.md",
"startLine": 118,
"endLine": 137,
"source": "memory",
"snippet": "- 生成脚本: `tmp/build_skill_points.py` ## 生产覆盖范围修正 [刘彦江] - L1 生产到 **U16**(非 U33 - L2 生产到 **U29**(非 U16 - 已同步更新 `business_knowledge/单元挑战全貌.md` ## 单元挑战全貌文档 [刘彦江] - 创建 `business_knowledge/单元挑战全貌.md` - 覆盖九大板块业务定位、阶段划分、题型体系18种、能力标签45个、生产流程ID规则/标准/写入陷阱、审校体系7+4项检查、生产覆盖现状、模块关联、快速链接 ## L1/L2 难度等级映射 [刘彦江] ✅已确认 - L1-A: Starters入门+基础 (U1-U16) | L1-B: Starters达标 (U17-U24) | L1-C: Movers入门+基础 (U25-U40) | L1-D: Movers达标 (U41-U48) - L2-A: Flyers入门+基础 (U1-U12) | L2-B: Flyers达标 (U13-U18) | L2-C: KET入门+基础 (U19-U30) | L2-D: KET强化+高位+达标 (U31-U48) - 已写入 `business_knowledge/单元挑战全貌.md` §5.3 # 2026-05-25 工作日志 ## 组件配置 pipeline单独重试 cId=1217214 - [童瑶] 请求单独重试 pipeline 中的失败组件 cId=1217214听力拖拽 / core_listenin",
"recallCount": 1,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 1,
"maxScore": 1,
"firstRecalledAt": "2026-05-29T02:33:30.526Z",
"lastRecalledAt": "2026-05-29T02:33:30.526Z",
"queryHashes": [
"4aa0ef719160"
],
"recallDays": [
"2026-05-29"
],
"conceptTags": [
"tmp/build-skill-points.py",
"business-knowledge/单元挑战全貌.md",
"id规则/标准/写入陷阱",
"l1/l2",
"l1-a",
"u1-u16",
"l1-b",
"u17-u24"
]
},
"memory:memory/2026-05-28.md:60:66": {
"key": "memory:memory/2026-05-28.md:60:66",
"path": "memory/2026-05-28.md",
"startLine": 60,
"endLine": 66,
"source": "memory",
"snippet": "8. 句型合规检测 - 接入方式:`<script src=\"l1_pedagogy_rules.js\"></script>` + 调用 `PedagogyRules.validate(summary, level)` - 数据源L1 词库 147 词(过滤 enabled=true、L2 词库 52 词、L1 句型 8 个、L2 句型(从 437MB bitable 导出中提取唯一结构) - 技术注意L2_pattern_list.json 体积 437MB1,082,450 条记录),直接嵌入前端不可行,已提取唯一句型结构后嵌入 - 所有 6 个测试用例通过 - 用户后续想尝试其他对接方式API 模式 / 飞书 Bot 联动 / CI 集成)",
"recallCount": 1,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 1,
"maxScore": 1,
"firstRecalledAt": "2026-05-29T02:33:30.526Z",
"lastRecalledAt": "2026-05-29T02:33:30.526Z",
"queryHashes": [
"4aa0ef719160"
],
"recallDays": [
"2026-05-29"
],
"conceptTags": [
"l1-pedagogy-rules.js",
"pedagogyrules.validate",
"l2-pattern-list.json",
"句型",
"检测",
"方式",
"script",
"src"
]
} }
} }
} }

15
memory/2026-05-29-1111.md Normal file
View File

@ -0,0 +1,15 @@
# Session: 2026-05-29 11:11:18 GMT+8
- **Session Key**: agent:xiaoyan:feishu:direct:ou_8b79b7f711e42a4004f3f3c225a1a99c
- **Session ID**: 06d2876f-1302-4e15-946e-da689c2788bb
- **Source**: feishu
## Conversation Summary
user: 组件配置-json https://makee-interactive.feishu.cn/wiki/KNAZwTYXsib2Ijk6BrGciRelnSf?from=from_copylink
assistant: 张昆鹏,开始处理。执行 pipeline
assistant: 处理被中断了,重跑一次,加大超时。

28
memory/2026-05-29-1120.md Normal file
View File

@ -0,0 +1,28 @@
# Session: 2026-05-29 11:20:57 GMT+8
- **Session Key**: agent:xiaoyan:feishu:direct:ou_8b79b7f711e42a4004f3f3c225a1a99c
- **Session ID**: 14f433f3-d123-4c62-8331-096fb7992bbf
- **Source**: feishu
## Conversation Summary
user: 组件配置-json https://makee-interactive.feishu.cn/wiki/KNAZwTYXsib2Ijk6BrGciRelnSf?from=from_copylink
assistant: 根据 `interactive-component-json` 技能,执行组件配置 JSON 生成流水线。
张昆鹏(技术负责人,`7f5cd711`),开始处理。
assistant: ✅ 处理完成!**L1-S2-U18-L2 登龙秘笈** — 17/17 组件全部生成成功HTML 报告已通过飞书 Bot 发送给你。
| 类型 | 数量 | 状态 |
|------|------|------|
| 对话朗读 (mid_dialog_repeat) | 5 | ✅ |
| 对话挖空 (mid_dialog_fillin) | 4 | ✅ |
| 对话组句 (mid_dialog_sentence) | 2 | ✅ |
| 对话选读 (mid_dialog_select) | 2 | ✅ |
| 对话选择 (mid_dialog_choose) | 1 | ✅ |
| 对话表达 (mid_dialog_express) | 1 | ✅ |
| 图片单选 (mid_image_choose) | 1 | ✅ |
| 听力选择 (core_listening_choose) | 1 | ✅ |
⚠️ 部分组件的知识点未在 MySQL 词库中匹配到(如 `blackboard`、`Take... as an example.`、`... in line.` 等),建议确认这些知识点在词库中的录入情况。

30
memory/2026-05-29-1125.md Normal file
View File

@ -0,0 +1,30 @@
# Session: 2026-05-29 11:25:02 GMT+8
- **Session Key**: agent:xiaoyan:feishu:direct:ou_8b79b7f711e42a4004f3f3c225a1a99c
- **Session ID**: 2bc6e1f4-5d44-4513-ba43-7decd534dcc1
- **Source**: feishu
## Conversation Summary
user: 组件配置-json https://makee-interactive.feishu.cn/wiki/KNAZwTYXsib2Ijk6BrGciRelnSf?from=from_copylink
assistant: 张昆鹏技术负责人正在启动组件配置JSON生成流水线。
assistant: 处理完成!**L1-S2-U18-L2 登龙秘笈** — 17/17 组件全部生成成功HTML 报告已发送给你。
| 组件类型 | 数量 | 状态 |
|----------|------|------|
| 对话朗读 (mid_dialog_repeat) | 5 | ✅ |
| 对话挖空 (mid_dialog_fillin) | 4 | ✅ |
| 对话选读 (mid_dialog_select) | 2 | ✅ |
| 对话组句 (mid_dialog_sentence) | 2 | ✅ |
| 对话选择 (mid_dialog_choose) | 1 | ✅ |
| 对话表达 (mid_dialog_express) | 1 | ✅ |
| 图片单选 (mid_image_choose) | 1 | ✅ |
| 核心互动-听力选择 (core_listening_choose) | 1 | ✅ |
⚠️ 注意:部分知识点的 kpId 未匹配到(如 `blackboard`、`Take... as an example.` 等),需手动核对知识点关联。
user: cId全部错误
assistant: 让我查看原始 sheet 数据和生成的 cId定位问题。

13
memory/2026-05-29.md Normal file
View File

@ -0,0 +1,13 @@
## [梁晨] L1 Pedagogy Rules v4.0.0 交付
- 在 v3 基础上新增 5 个校验维度(来自 16 个教研 skill 规则提取):
6. 组件合规性12 种题型规则,来自 11 个 dialogue/info config skills
7. 字段完整性7 项自动检查,来自 audit_l1_config
8. 掌握度预测W_i×M_i 加权公式,来自 knowledge-mastery-calculator
9. 格式规范(标题/Markdown/标点/英式拼写/价值观,来自全量文本规范)
10. 语法检测(三单/主谓一致/双重否定,来自 audit_l1_config
- 输出:`output/l1_pedagogy_rules_v4.js`59KB
- 数据L1 147 词、L2 52 词、L1 8 句型、L2 1 句型、89 组英式拼写映射、12 种题型规则
- 已通过飞书 Bot 发送给梁晨
- API 兼容 v3不加 options 参数即为原行为;加 component/componentExposures 启用新维度
- 能力边界:内容质量诊断(第一层筛选),不是全链路归因(看不到 UX/服务端/学生侧因素)

File diff suppressed because one or more lines are too long