feat(v2): T10 rollup + prefix cache 前缀稳定性(--cache-reuse 对齐)

This commit is contained in:
tzt
2026-08-30 21:16:02 +08:00
parent c874382130
commit ff7e1bc8de
3 changed files with 90 additions and 1 deletions
+72
View File
@@ -0,0 +1,72 @@
"""T10 rollup + prefix cache 前缀稳定性测试。
验证交流文本的"恒定前缀"version/request_id/query/meta/brief)在写入
progress/issues/decisions 后保持不变 —— 这是 llama-server --cache-reuse
命中、降低 prefill 开销的前提(D2 / 6.2 / T10)。
"""
import json
from router_system.workspace import Workspace
BRIEF = {
"goal": "实现快排",
"constraints": ["标准库"],
"tags": ["code"],
"acceptance": [{"id": "a1", "check": "可运行", "machine_checkable": True}],
"plan": [{"id": "s1", "task": "实现", "deps": [], "done_criteria": "可运行"}],
}
def _ws():
ws = Workspace.new("abc123def456", "写个快排")
ws.apply_brief(BRIEF)
return ws
def test_prefix_stable_across_writes():
ws = _ws()
sig0 = ws.prefix_signature()
ws.add_progress("s1", "done", "完成", "a://s1.py")
ws.add_issue("s1", "a://f.py#L1", "obs", "exp", "try", "ask")
ws.add_decision("i1", "reply")
ws.mark_round()
ws.add_budget(input_tokens=100, output_tokens=20)
assert ws.prefix_signature() == sig0 # 前缀不随写操作变化
def test_prefix_changes_with_brief():
ws = _ws()
sig = ws.prefix_signature()
ws2 = Workspace.new("abc123def456", "写个快排")
ws2.apply_brief({**BRIEF, "goal": "不同的目标"})
assert ws2.prefix_signature() != sig
def test_prefix_changes_with_query():
ws = _ws()
sig = ws.prefix_signature()
ws2 = Workspace.new("abc123def456", "另一个问题")
ws2.apply_brief(BRIEF)
assert ws2.prefix_signature() != sig
def test_rollup_keeps_prefix_stable():
ws = _ws()
ws.add_progress("s1", "done", "ok", "a://s1.py")
sig_before = ws.prefix_signature()
ws.rollup()
assert ws.prefix_signature() == sig_before
def test_serialized_leading_is_stable():
ws = _ws()
head_before = _leading_json(ws)
ws.add_progress("s1", "done", "ok", "a://s1.py")
ws.add_issue("s1", "a://f.py#L1", "obs", "exp", "try", "ask")
assert _leading_json(ws) == head_before
def _leading_json(ws: Workspace) -> str:
d = ws.data
stable = {k: d.get(k) for k in ("version", "request_id", "query", "meta", "brief")}
return json.dumps(stable, ensure_ascii=False, sort_keys=True)