14 KiB
1
这里有个需求单: llm-markdown-intake-normalizer.md
我们之前打造了fix-title,但是这个技能不好用,必须由我指定从哪开始,下沉几层,不智能。
打造fix-title的主要原因就是ChatGPT回复后,复制出来的标题错乱;同时我还有记录讨论过程的习惯:
# 1 --- 表示第一个回合
xxx --- 我的输入
## GPT --- 表示第一个回合 GPT的回复
### --- GPT回复就需要默认从三个###开始了,这样有下沉的需求
现在发现,GPT回复时,有时候用一个#,有时候用##不稳定;而且出现了## 后面继续用#的情况。
这不是python代码能解决的,必须有语义理解。
我期望,将fix-title升级成具有语义理解能力的skill,可以真正修复标题。
谈谈你对问题的理解,有什么问题?
我理解这个问题不是“标题下沉”,而是“把 GPT 输出重新还原成可用文档结构”。现有 fix-title 只是固定把 # 加深几层,适合简单粘贴块;但你现在遇到的是 GPT 自己在一个回复里混用 #、##、###,甚至后面又跳回 #。这必须判断“这个标题在语义上是文档标题、一级章节、子章节、另一个 artifact,还是助手废话”,不能靠统一加 ## 解决。
我会把需求拆成两个层次:
-
fix-title的真实升级目标:修复“讨论记录里的 GPT 回复”- 外层
# 1、## GPT是记录结构,不能动。 - GPT 回复内部默认应从
###开始。 - 如果回复里出现
# 一、...、## 1. ...、后面又# 二、...,要按语义重排为###/####/#####。 - 这类场景更像“semantic heading repair”。
- 外层
-
需求单 的更大目标:清洗
video-workbench的 GPT intake- 不只修标题,还要识别助手闲聊、重复粘贴、多 artifact 拼接、非 canonical 内容。
- 输出应是
intake-clean/和 cleaning report,而不是直接改原始intake/。 - 这更像新 Skill:
normalize-llm-markdown-intake。
我的技术判断:不是“完全不能用 Python”,而是不能让 Python 独立做语义判断。合理架构应该是混合式:
- Python 负责安全解析、保护代码块/表格/引用、列出 heading map、执行确定性改写、生成 diff/report。
- Codex/LLM 负责语义判断:哪个标题是真标题、哪个是章节、哪个是新 artifact、哪个是助手过渡语。
- Skill 负责规定流程、模式、输出约束和人工确认门槛。
关键问题是:要不要把这两个场景放进同一个 fix-title?我的倾向是不要硬塞。保留 fix-title 作为低层工具,新增或重命名一个语义 Skill 更稳;否则 fix-title 这个名字会误导未来 Codex 继续把它当“标题加深脚本”。
我现在最需要你定的是一个边界问题:你希望这次优先解决哪一个?
- A. 升级
fix-title,主攻“讨论记录中 GPT 回复标题错乱”的语义修复。 - B. 按需求单新建
normalize-llm-markdown-intake,主攻video-workbench/projects/*/intake/的批量清洗。 - C. 两者都做:
fix-title变成低层兼容工具,新 Skill 调用/复用它,但用户以后主要用新 Skill。
我推荐 C,但第一轮实现应以 B 的需求单为验收主线,顺手把 fix-title 标记成低层工具或兼容入口。这样不会继续在一个名字很小的 Skill 里堆一个很大的语义清洗系统。
2
旧的fix-title 没有被用起来,这个技能已经没有存在的意义了。
我做了两个样例文件,一个是讨论稿,一个是成果稿/intake稿,及这两个稿子的修复稿,你可以对比着看:
-
讨论稿,有问题的:
C:\Users\wangq\Documents\Codex\knowledge-vault\discussions\technology\Codex\4.Skills\fix-title\fix文档标题样例-讨论稿.md -
讨论稿,修复后的:
C:\Users\wangq\Documents\Codex\knowledge-vault\discussions\technology\Codex\4.Skills\fix-title\fix文档标题样例-讨论稿-fixed.md -
成果稿,有问题的:
C:\Users\wangq\Documents\Codex\knowledge-vault\discussions\technology\Codex\4.Skills\fix-title\fix文档标题样例-intake稿.md -
成果稿,修复后的:
C:\Users\wangq\Documents\Codex\knowledge-vault\discussions\technology\Codex\4.Skills\fix-title\fix文档标题样例-intake稿-fixed.md
在样例文件中,只放了二级标题的错误及修复,这个是递归的,所有下面的子标题都需要修复,这个必须要有语义理解能力,纯python这种干不了。
你先更深刻的理解问题。
我看完四个样例后,问题比“标题级别错了”更准确地说是:
GPT 粘贴文本丢失了它本来应该服从的容器结构,导致 Markdown 的 # 层级不能直接信任。
在讨论稿里,真实结构是:
# 回合
## 用户/任务/指令
## GPT
### GPT 回复里的一级内容
#### GPT 回复里的二级内容
所以 讨论稿样例 里,## GPT 后面的 ## 1.xxxx 实际不是和 ## GPT 平级,而是 ## GPT 的子内容,修复后变成 ### 1.xxxx。第二回合里更明显:原文 # 1.xxxx、# 2.xxx、## 3.xxx 三个在语义上都是 GPT 回复内部的同级章节,所以修复后统一为 ###,而不是保留原始的 # / ## 差异。
在 intake/成果稿里,真实结构变成:
# 文档根标题
## 成果稿内部一级章节
### 成果稿内部二级章节
所以 intake 样例 中同样的 # 1.xxxx,正确目标不是 ###,而是 ##。这说明同一个原始标题错误,在不同文档模式下有不同修复结果。旧 fix-title 的固定加深模型天然不可能成立。
我现在的深层理解是:这个 Skill 要做的不是“修改标题符号”,而是先判断文档类型和语义容器,再重建标题树。
核心规则应该是:
- 讨论稿:保护外层记录结构,比如
# 1、# 2、## 任务、## 指令、## GPT;只修复 GPT 回复块内部标题。 - intake/成果稿:保护唯一文档根标题;把后续误用的
#修复为根标题下的章节。 - 原始
#数量只是弱信号,不能当真;编号、段落位置、容器标题、上下文语义才是主信号。 - 修复必须递归:一旦判断某个标题是父级,它下面的子标题也要按新的父级重新挂载。
- 不能只做“整体下沉 N 级”,因为有些标题需要下沉,有些需要保持,有些甚至要从错误的子级拉平成同级。
- Python 可以负责保护代码块、扫描标题、生成 diff/report,但最终“这个标题语义上属于哪一层”必须由 Codex/LLM 判断。
这也意味着旧 fix-title 确实可以废掉。它解决的是一个不存在的理想化问题:假设 GPT 输出只差一个固定偏移量。真实问题是 GPT 输出的标题树本身不可信,需要语义重建。
我还有一个关键问题:未来成果稿/intake 稿里,如果开头是 # GPT的回复,你希望默认保留它作为根标题,还是当正文里出现更真实的 artifact 标题时,把根标题替换成那个 artifact 标题?这个会影响 Skill 的默认修复策略。
3
我给的样例稿子,实际上做了简化——缺少内容,只能通过标题;而GPT的回复是上下文紧密关联的,不然人也没法判别了。 所以粗浅的上下文语义理解上,LLM做起来没问题。
未来成果稿/intake 稿里,如果开头是
# GPT的回复
这种可能性不存在,intake稿都是我手工放进去的;而# GPT的回复 是我手工加的。
如果确实出现了,那就按成果稿的逻辑,该咋办咋办——默认最上面是文档标题,全部修复一遍;即使错了,也是我的问题,skill不背锅。
我放了两个文档,这个都是真实的文档,供你将来测试用:
- 讨论稿:
C:\Users\wangq\Documents\Codex\skills-vault\tmp\测试用-在路上-策划导演.md - 成果稿:
C:\Users\wangq\Documents\Codex\skills-vault\tmp\测试用-阶段三-MV 总纲.md
这个skill,可以跑这两个文档,测试结果也放到tmp/下,不要覆盖原文档,我可以人工配合检查。
还有问题么,可以开始重构这个fix-title了么?
可以,已经重构完并安装到可用 Skill 面了。
旧的固定下沉脚本已移除,fix-title 现在改成“语义判断 + 安全执行”的模式:Codex 先读全文判断讨论稿/成果稿结构,再写一份 line-level JSON heading plan,脚本只按计划改标题层级、保护 fenced code block、输出 fixed 文件和 report。核心文件是 SKILL.md 和 semantic_heading_repair.py。
我也把安装面同步了:C:\Users\wangq\.agents\skills\fix-title。旧安装版备份到了:
C:\Users\wangq\.agents\skills\fix-title.backup-20260623121809
样例输出放在 tmp/,没有覆盖原文件:
- 讨论稿 fixed: 测试用-在路上-策划导演.fixed.md
- 讨论稿 report: 测试用-在路上-策划导演.heading-report.md
- 成果稿 fixed: 测试用-阶段三-MV 总纲.fixed.md
- 成果稿 report: 测试用-阶段三-MV 总纲.heading-report.md
验证结果:
conda run -n skills-vault python -B -m unittest discover -s skills\fix-title\tests -v通过,4 个测试。conda run -n skills-vault python -B scripts\quick_validate.py skills\fix-title通过。git diff --check没有 whitespace error,只有 Windows CRLF 提示。- 样例结构检查:成果稿 fixed 只剩 1 个真实 H1;讨论稿 fixed 只剩
# 1 / # 2 / # 3三个回合 H1。
有一个真实样例细节:讨论稿后段有 fenced Markdown 示例边界不稳定,部分示例标题被 Markdown 解析成了正文标题。我按“仍属于第 3 回合 GPT 回复”的语义修了可见标题;代码块内部标题没有动。
4
我检查了修复的结果,很满意。
我有个问题,修文档这个:
- 之前python,不占用会话窗口
- 现在LLM,会占用会话窗口,而且这个又比较独立,不依赖于上下文
- 我们是否可以包装成一个独立的子会话或子Agent,还是必须调用方自己做?
- 在输入时可以允许调用方传入文件数组
我们还需要做后续的一些完善:
- 之前的fix-title是支持Cli的,我觉得这次,输入1文件路径数组,输入2是成果/还是讨论稿,就够了吧
- 配套的规则、说明等完善
没有新的阻塞问题,可以开始做二期。
我的判断:
-
可以包装成子 Agent,而且应该这么做。
这个任务上下文独立、会消耗窗口、产物也清晰,适合“主会话薄调度,子 Agent 修文档”。当前 Codex 也确实有spawn_agent能力,所以 Skill 可以写成:如果调用环境支持子 Agent,默认把批量修复委派出去;主会话只传files[] + mode + output_dir,最后验收 fixed/report。 -
CLI 仍然要保留,但不能假装纯 Python 能完成语义修复。
更准确的 CLI 分两层:- Python CLI:批量 inspect、生成 heading-map、应用 JSON plan、产出 report。
- Agent CLI/Skill 入口:接受
files[]和mode=discussion|artifact,由 LLM/子 Agent 读文档并写 plan,再调用 Python CLI 落盘。
我建议二期设计这样落:
-
SKILL.md增加 “Batch / Delegated Workflow”:- 输入:文件路径数组、模式、输出目录。
- 默认不覆盖原文。
- 如果支持子 Agent,主会话生成一个委派 prompt,让子 Agent 完成修复。
- 如果不支持子 Agent,当前调用方自己执行同一流程。
-
semantic_heading_repair.py增加批量辅助命令:inspect-batch --mode discussion|artifact --output-dir ... file1.md file2.md- 为每个文件生成 heading map 和 plan 模板。
- 保留
apply的严格校验。
-
规则完善:
- 讨论稿:保护回合标题和用户区,只修 GPT 回复块。
- 成果稿:首个 H1 默认是文档标题,后续递归修。
- 子 Agent 产物必须包括 fixed 文件、heading report、计划 JSON。
- 主会话不得把“子 Agent 说修好了”当证据,必须看文件/报告。
如果你确认这个设计,我下一步直接改:测试先行,补 batch CLI、补 Skill 子 Agent 委派规则、再跑你那两个样例回归。
5
我实际使用skill,都是Agentic:
- VS Code Copilot
- Cluade Code
- Codex
- OpenClaw
CLI 只保留Agent Cli即可。去掉python Cli
如果支持子 Agent,主会话生成一个委派 prompt,让子 Agent 完成修复。 如果不支持子 Agent,当前调用方自己执行同一流程。
增加上子会话(Thread),这个也可以避免会话窗口撑爆;Codex也支持这种方式。
其他都同意。
可以继续了。