release: v0.20 Codex-ready skill-driven core
This commit is contained in:
@@ -11,7 +11,7 @@ if str(REPO_ROOT) not in sys.path:
|
||||
from scripts.runtime.roles import resolve_runtime_profile
|
||||
from scripts.runtime.sources import append_packet_sources, rebuild_sources_from_packets
|
||||
from scripts.runtime.tasks import TaskCard
|
||||
from scripts.runtime.workers import PacketWorker, build_search_context
|
||||
from scripts.runtime.workers import PacketWorker, build_material_context, build_route_query, build_search_context, normalize_packet_against_context
|
||||
|
||||
|
||||
class FakeSearchProvider:
|
||||
@@ -57,6 +57,66 @@ def test_build_search_context_assigns_stable_source_ids() -> None:
|
||||
assert context["routes_used"] == ["scholar", "general"]
|
||||
|
||||
|
||||
def test_fda_route_query_uses_english_axis_terms_not_chinese_title() -> None:
|
||||
card = TaskCard(
|
||||
task_id="ch10-fda_enforcement_precedents",
|
||||
chapter_ids=["ch10"],
|
||||
topic_axis="fda_enforcement_precedents",
|
||||
questions=["立即纠偏、体系补强、能力建设三层整改路线图必须绑定 owner、关闭证据和复核机制"],
|
||||
search_routes=["fda"],
|
||||
output_packet="phase2/packets/ch10-fda_enforcement_precedents.json",
|
||||
chapter_title="立即纠偏、体系补强、能力建设三层整改路线图必须绑定 owner、关闭证据和复核机制",
|
||||
)
|
||||
|
||||
query = build_route_query(card, "fda")
|
||||
|
||||
assert "立即纠偏" not in query
|
||||
assert "CAPA" in query
|
||||
assert "remediation" in query
|
||||
assert "verification evidence" in query
|
||||
|
||||
|
||||
def test_integrated_scholar_query_does_not_leak_internal_axis_or_cjk_punctuation() -> None:
|
||||
card = TaskCard(
|
||||
task_id="ch07-chapter_integrated",
|
||||
chapter_ids=["ch07"],
|
||||
topic_axis="chapter_integrated",
|
||||
questions=["人员能力:培训有效性比培训记录更关键"],
|
||||
search_routes=["scholar"],
|
||||
output_packet="phase2/packets/ch07-chapter_integrated.json",
|
||||
chapter_title="人员能力:培训有效性比培训记录更关键",
|
||||
)
|
||||
|
||||
query = build_route_query(card, "scholar")
|
||||
|
||||
assert "chapter_integrated" not in query
|
||||
assert "、" not in query
|
||||
assert " " not in query
|
||||
assert "training" in query
|
||||
assert "quality" in query
|
||||
assert not any("\u4e00" <= char <= "\u9fff" for char in query)
|
||||
|
||||
|
||||
def test_evidence_route_query_is_short_english_candidate_evidence_query() -> None:
|
||||
card = TaskCard(
|
||||
task_id="ch08-chapter_integrated",
|
||||
chapter_ids=["ch08"],
|
||||
topic_axis="chapter_integrated",
|
||||
questions=["运营管理需要建立跨部门节奏、问题升级、指标看板和管理层 review"],
|
||||
search_routes=["evidence"],
|
||||
output_packet="phase2/packets/ch08-chapter_integrated.json",
|
||||
chapter_title="运营管理需要建立跨部门节奏、问题升级、指标看板和管理层 review",
|
||||
)
|
||||
|
||||
query = build_route_query(card, "evidence")
|
||||
|
||||
assert "evidence" in query
|
||||
assert "quality" in query
|
||||
assert "operations" in query
|
||||
assert "运营管理" not in query
|
||||
assert not any("\u4e00" <= char <= "\u9fff" for char in query)
|
||||
|
||||
|
||||
def test_packet_worker_includes_search_context_in_prompt() -> None:
|
||||
context = build_search_context(sample_card(), FakeSearchProvider(), num_results_per_route=1)
|
||||
response = {
|
||||
@@ -79,7 +139,71 @@ def test_packet_worker_includes_search_context_in_prompt() -> None:
|
||||
assert "candidate_sources" in fake.calls[0]["user"]
|
||||
|
||||
|
||||
def test_append_packet_sources_dedupes_by_url(tmp_path: Path) -> None:
|
||||
def test_normalize_packet_fills_source_ids_and_sources_from_context() -> None:
|
||||
context = {
|
||||
"candidate_sources": [
|
||||
{"id": "src_a", "title": "A", "url": "https://example.com/a", "tier": "Tier 2", "score": 7}
|
||||
]
|
||||
}
|
||||
packet = {
|
||||
"task_id": "ch01",
|
||||
"claims": [{"claim": "判断", "source_ids": ["src_a"]}],
|
||||
"evidence_items": [{"source_id": "src_a", "summary": "证据"}],
|
||||
"counter_evidence": [{"claim": "反方", "source_ids": ["src_a"]}],
|
||||
"source_quality_notes": [],
|
||||
"open_questions": [],
|
||||
"raw_quotes_or_notes": [],
|
||||
}
|
||||
|
||||
normalized = normalize_packet_against_context(packet, context, None)
|
||||
|
||||
assert normalized["source_ids"] == ["src_a"]
|
||||
assert normalized["sources"] == context["candidate_sources"]
|
||||
|
||||
|
||||
def test_material_context_is_loaded_and_allowed_as_source(tmp_path: Path) -> None:
|
||||
project = tmp_path / "project"
|
||||
material = project / "phase0/extracted/audit.md"
|
||||
material.parent.mkdir(parents=True)
|
||||
material.write_text("白帆现场发现:偏差调查未闭环。", encoding="utf-8")
|
||||
card = TaskCard(
|
||||
task_id="ch01-chapter_integrated",
|
||||
chapter_ids=["ch01"],
|
||||
topic_axis="chapter_integrated",
|
||||
questions=["q"],
|
||||
search_routes=[],
|
||||
output_packet="phase2/packets/ch01-chapter_integrated.json",
|
||||
allowed_materials=["phase0/extracted/audit.md"],
|
||||
)
|
||||
context = build_material_context(card, project)
|
||||
response = {
|
||||
"task_id": "ch01-chapter_integrated",
|
||||
"claims": [{"claim": "现场材料显示偏差调查需要补强", "source_ids": [context["materials"][0]["source_id"]]}],
|
||||
"evidence_items": [{"source_id": context["materials"][0]["source_id"], "summary": "偏差调查未闭环。"}],
|
||||
"counter_evidence": [{"claim": "需与完整审计报告交叉确认", "source_ids": [context["materials"][0]["source_id"]]}],
|
||||
"source_ids": [context["materials"][0]["source_id"]],
|
||||
"sources": [
|
||||
{
|
||||
"id": context["materials"][0]["source_id"],
|
||||
"title": "audit.md",
|
||||
"url": "phase0/extracted/audit.md",
|
||||
"tier": "local_material",
|
||||
}
|
||||
],
|
||||
"source_quality_notes": ["本地材料作为起点证据"],
|
||||
"open_questions": [],
|
||||
"raw_quotes_or_notes": ["白帆现场发现:偏差调查未闭环。"],
|
||||
}
|
||||
fake = FakeClient(response)
|
||||
role = resolve_runtime_profile(profile="medium").role_for_task("evidence_packet")
|
||||
|
||||
packet = PacketWorker(role=role, client=fake, project_root=project).run(card)
|
||||
|
||||
assert packet["source_ids"] == [context["materials"][0]["source_id"]]
|
||||
assert "白帆现场发现" in fake.calls[0]["user"]
|
||||
|
||||
|
||||
def test_append_packet_sources_preserves_distinct_source_ids_for_same_url(tmp_path: Path) -> None:
|
||||
packet = {
|
||||
"sources": [
|
||||
{"id": "src_a", "title": "A", "url": "https://example.com/a", "tier": "Tier 2", "score": 7},
|
||||
@@ -89,11 +213,11 @@ def test_append_packet_sources_dedupes_by_url(tmp_path: Path) -> None:
|
||||
|
||||
written = append_packet_sources(tmp_path / "sources.jsonl", packet)
|
||||
|
||||
assert written == 1
|
||||
assert len((tmp_path / "sources.jsonl").read_text(encoding="utf-8").splitlines()) == 1
|
||||
assert written == 2
|
||||
assert len((tmp_path / "sources.jsonl").read_text(encoding="utf-8").splitlines()) == 2
|
||||
|
||||
|
||||
def test_rebuild_sources_from_packets_dedupes_manual_packets(tmp_path: Path) -> None:
|
||||
def test_rebuild_sources_from_packets_preserves_distinct_source_ids(tmp_path: Path) -> None:
|
||||
project = tmp_path / "project"
|
||||
packets = project / "phase2" / "packets"
|
||||
packets.mkdir(parents=True)
|
||||
@@ -109,7 +233,34 @@ def test_rebuild_sources_from_packets_dedupes_manual_packets(tmp_path: Path) ->
|
||||
count = rebuild_sources_from_packets(project)
|
||||
|
||||
lines = (project / "phase2" / "sources.jsonl").read_text(encoding="utf-8").splitlines()
|
||||
assert count == 2
|
||||
assert len(lines) == 2
|
||||
assert count == 3
|
||||
assert len(lines) == 3
|
||||
assert "src_001" in lines[0]
|
||||
assert "src_003" in lines[1]
|
||||
assert "src_002" in lines[1]
|
||||
assert "src_003" in lines[2]
|
||||
|
||||
|
||||
def test_rebuild_sources_preserves_cache_metadata(tmp_path: Path) -> None:
|
||||
project = tmp_path / "project"
|
||||
packets = project / "phase2" / "packets"
|
||||
packets.mkdir(parents=True)
|
||||
source = {"id": "src_001", "title": "A", "url": "https://example.com/a"}
|
||||
(packets / "ch01-a.json").write_text(json.dumps({"sources": [source]}, ensure_ascii=False), encoding="utf-8")
|
||||
(project / "phase2/sources.jsonl").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
**source,
|
||||
"cached_text_path": "phase2/source_cache/md/src_001.md",
|
||||
"cache_status": "fetched",
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
+ "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
rebuild_sources_from_packets(project)
|
||||
|
||||
row = json.loads((project / "phase2/sources.jsonl").read_text(encoding="utf-8"))
|
||||
assert row["cached_text_path"] == "phase2/source_cache/md/src_001.md"
|
||||
assert row["cache_status"] == "fetched"
|
||||
|
||||
Reference in New Issue
Block a user