Files
skills-win/claude-brain/scripts/split_tasks.py
T
2026-10-15 01:59:40 +08:00

90 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""把大脑决策文件 Rnn-brain.md 里的 `### Tk` 各节原样抽成 Rnn-Tk-task.md。
用法:
python split_tasks.py <运行目录>/R04-brain.md
规则(与 SKILL.md / templates.md 一致):
- 只抽取 "## 任务" 与 "## 向用户提问" 之间的 `### Tk` 节,正文一字不改。
- 模型取该节 "- 模型:" 行;写了 fable 则改回 opus(Fable 只属于大脑),并在 stdout 提示。
- 报告路径优先取该节 "- 报告格式:" 行里反引号中的路径(大脑常自己指定文件名);
大脑用 `...\\` 省略了目录前缀时,用运行目录补全;没写则用默认 Rnn-Tk-report.md。
- 末尾追加 worker 报告格式模板。
输出: 每个任务一行 "Tk <model> <task-file> <report-path>",供调度员直接派 worker。
"""
import re
import sys
from pathlib import Path
REPORT_TEMPLATE = '''
---
## 报告格式
写到 `{report}`,结构如下:
```
# {rnd}-{tk} 报告
- 结论: 完成 | 部分完成 | 失败 | 受阻
- 模型: {model}
## 做了什么
<按步骤列出>
## 改动的文件
<路径 + 一句话说明;没有就写"无">
## 证据
<关键命令及输出摘录、测量值、测试结果、日志片段>
## 验收标准逐条
1. <标准> —— 满足/不满足,证据: ...
## 问题与建议
<遇到的意外、任务单没覆盖到需要大脑决定的点>
```
验收标准要求的各张表、设计说明、数值结果放在"证据"一节或其后的独立小节中。
'''
def main(path: str) -> None:
brain = Path(path).resolve()
rundir = brain.parent
rnd = brain.stem.split('-')[0] # R04 / R02b
text = brain.read_text(encoding='utf-8')
if '## 任务' not in text:
sys.exit('决策文件里没有 "## 任务" 节')
body = text.split('## 任务', 1)[1]
for stop in ('## 向用户提问', '## 总结'):
if stop in body:
body = body.split(stop, 1)[0]
parts = re.split(r'(?m)^### (T\w+)\s*$', body)
if len(parts) < 3:
sys.exit('没有找到任何 "### Tk" 节')
for i in range(1, len(parts), 2):
tk, sec = parts[i], parts[i + 1].strip('\n')
m = re.search(r'-\s*模型:\s*(\w+)', sec)
model = m.group(1).lower() if m else 'opus'
if model == 'fable':
print(f'[warn] {tk} 指定了 fable,改回 opus(Fable 只属于大脑)', file=sys.stderr)
model = 'opus'
rep = None
m = re.search(r'-\s*报告格式:.*?`([^`]+\.md)`', sec)
if m:
rep = m.group(1)
if rep.startswith('...'):
rep = str(rundir / Path(rep.replace('...', '').lstrip('\\/')).name)
elif not Path(rep).is_absolute():
rep = str(rundir / rep)
if not rep:
rep = str(rundir / f'{rnd}-{tk}-report.md')
out = (f'# {rnd}-{tk} 任务单(模型: {model})\n\n### {tk}\n{sec}\n'
+ REPORT_TEMPLATE.format(report=rep, rnd=rnd, tk=tk, model=model))
task_file = rundir / f'{rnd}-{tk}-task.md'
task_file.write_text(out, encoding='utf-8')
print(f'{tk} {model} {task_file} {rep}')
if __name__ == '__main__':
if len(sys.argv) != 2:
sys.exit(__doc__)
main(sys.argv[1])