release: v0.20 Codex-ready skill-driven core

This commit is contained in:
kai
2026-05-07 08:21:28 +08:00
parent 0644a68ecc
commit 68e45bcf41
45 changed files with 3005 additions and 157 deletions
+98
View File
@@ -68,6 +68,10 @@ def test_research_build_briefs_does_not_overwrite_existing_packets(tmp_path: Pat
"evidence_items": [{"source_id": "src_001", "summary": "证据"}],
"counter_evidence": [{"claim": "限制", "source_ids": ["src_002"]}],
"source_ids": ["src_001", "src_002"],
"sources": [
{"id": "src_001", "title": "来源1", "url": "https://example.com/1"},
{"id": "src_002", "title": "来源2", "url": "https://example.com/2"},
],
"source_quality_notes": ["src_001 Tier 1"],
"open_questions": [],
"raw_quotes_or_notes": [],
@@ -80,6 +84,28 @@ def test_research_build_briefs_does_not_overwrite_existing_packets(tmp_path: Pat
assert "真实证据不能被 skeleton 覆盖" in packet_path.read_text(encoding="utf-8")
def test_codex_native_profile_does_not_claim_python_core_model_execution(tmp_path: Path) -> None:
project = tmp_path / "project"
(project / "phase1").mkdir(parents=True)
(project / "manifest.json").write_text(
'{"research_method": "mckinsey_market", "phase1": {"approved": true}, "phase2": {}}\n',
encoding="utf-8",
)
(project / "phase1/framework.md").write_text(
"## 第1章 临床证据正在重塑需求判断\n\n研究思路。",
encoding="utf-8",
)
args = dr.build_parser().parse_args(["research", str(project), "--profile", "codex_native", "--execute-packets"])
try:
dr.cmd_research(args)
except SystemExit as exc:
assert "not Codex App built-in models" in str(exc)
else:
raise AssertionError("codex_native must not execute through Python external clients")
def test_packet_state_counts_ignores_stale_errors_for_ready_packets(tmp_path: Path) -> None:
project = tmp_path / "project"
(project / "phase2/packets").mkdir(parents=True)
@@ -184,6 +210,30 @@ def test_init_and_frame_create_executable_python_core_project(tmp_path: Path) ->
assert "中文" in framework
def test_frame_can_preserve_existing_outline(tmp_path: Path) -> None:
project = tmp_path / "custom-outline"
(project / "phase1").mkdir(parents=True)
(project / "manifest.json").write_text(
'{"topic": "自定义研究", "research_method": "mckinsey_market", "target_words": 12000, "phase1": {}}\n',
encoding="utf-8",
)
(project / "phase1/framework.md").write_text(
"## 第1章 第一条自定义主线\n\n## 第2章 第二条自定义主线\n\n## 第3章 第三条自定义主线\n\n"
"## 第4章 第四条自定义主线\n\n## 第5章 第五条自定义主线\n\n## 第6章 第六条自定义主线\n\n"
"## 第7章 第七条自定义主线\n\n## 第8章 第八条自定义主线\n",
encoding="utf-8",
)
args = dr.build_parser().parse_args(["frame", str(project), "--preserve-existing-outline"])
assert dr.cmd_frame(args) == 0
framework = (project / "phase1/framework.md").read_text(encoding="utf-8")
brief = json.loads((project / "phase1/research_brief.json").read_text(encoding="utf-8"))
assert "第一条自定义主线" in framework
assert "本章要解决的问题" in framework
assert brief["chapter_planning"][0]["title"] == "第一条自定义主线"
def test_review_writes_phase3_critique(tmp_path: Path) -> None:
project = tmp_path / "project"
(project / "phase1").mkdir(parents=True)
@@ -205,6 +255,54 @@ def test_review_writes_phase3_critique(tmp_path: Path) -> None:
assert "src_001" in text
def test_review_model_dry_run_exposes_opus_context_plan(tmp_path: Path, capsys) -> None:
project = tmp_path / "project"
project.mkdir()
(project / "manifest.json").write_text('{"topic": "测试项目"}\n', encoding="utf-8")
args = dr.build_parser().parse_args(["review", str(project), "--model-review", "--dry-run"])
assert dr.cmd_review(args) == 0
out = capsys.readouterr().out
assert "zenmux-anthropic/claude-opus-4-7" in out
assert "review_context_opus_4_7.md" in out
def test_finalize_polish_dry_run_uses_polish_source_argument(tmp_path: Path, capsys) -> None:
project = tmp_path / "project"
(project / "phase4").mkdir(parents=True)
(project / "manifest.json").write_text(
'{"model_profile": "medium", "phase4": {}}\n',
encoding="utf-8",
)
(project / "phase4/final_zh.md").write_text("# 中文终稿\n", encoding="utf-8")
args = dr.build_parser().parse_args(["finalize", str(project), "--polish", "--dry-run"])
assert dr.cmd_finalize(args) == 0
out = capsys.readouterr().out
assert "scripts/polish.py" in out
assert "--source phase4/final_zh.md" in out
assert "--input phase4/final_zh.md" not in out.split("scripts/polish.py", 1)[1]
def test_finalize_number_citations_dry_run_builds_numbered_markdown(tmp_path: Path, capsys) -> None:
project = tmp_path / "project"
(project / "phase4").mkdir(parents=True)
(project / "manifest.json").write_text(
'{"model_profile": "medium", "phase4": {}}\n',
encoding="utf-8",
)
(project / "phase4/final_zh.md").write_text("# 中文终稿\n\n正文。[src_001]\n", encoding="utf-8")
args = dr.build_parser().parse_args(["finalize", str(project), "--number-citations", "--dry-run"])
assert dr.cmd_finalize(args) == 0
out = capsys.readouterr().out
assert "scripts/number_citations.py" in out
assert "--input phase4/final_zh_numbered.md" in out
def test_run_new_topic_initializes_and_frames_project(tmp_path: Path) -> None:
args = dr.build_parser().parse_args(
[