Skip to content

Commit c2fe833

Browse files
tzhouamclaude
andcommitted
Record the knowledge snapshot on every Direct review plan
A review should record which knowledge it was served, so a finding can be traced to the exact rules that were active (the knowledge service now swaps snapshots at runtime). - DirectReviewPlan gains knowledge_snapshot (the activated snapshot id, "packaged", or "unverified") and knowledge_tree_sha256 (the manifest tree hash of a verified snapshot, else empty). Every document read under the plan's review_context_id comes from that same snapshot. Both fields default to empty, so existing callers are unaffected. - KnowledgeView.public_snapshot never exposes a development tree's absolute path. The old diagnostics value "unverified:/abs/path" leaked it into plans; diagnostics.knowledge_snapshot now uses the public form too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent deb2b98 commit c2fe833

7 files changed

Lines changed: 51 additions & 1 deletion

File tree

‎doc/architecture/SPEC/knowledge_view.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ stdlib + `.sdk._resources`。叶子模块。
3131

3232
## 测试
3333
`test_knowledge_view_routing.py`。
34+
35+
## 2026-09-28 可记录的快照标识
36+
`public_snapshot`:激活快照 ID、`packaged` 或 `unverified`(开发树的绝对路径不外泄);`tree_sha256`:已验证快照
37+
按清单重算的树哈希。`direct_routing` 的 `diagnostics.knowledge_snapshot` 与 SDK 计划都使用它们。

‎doc/architecture/SPEC/sdk.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,8 @@ Direct 1.1 / Strict 1.3 accept typed `CarriedFinding` inputs (unique IDs, source
128128
## 2026-09-28 trace/1 导出
129129
`sdk.v1` 导出 `TraceStore`、`TRACE_SCHEMA`、`trace_context`、`redact`(见 `trace_store.md`),RB 用同一 schema
130130
记录 review 的模型调用、判定与结果;导入它们不加载 `config`/`contract`/`mcp_server` 等私有模块。
131+
132+
## 2026-09-28 计划携带知识快照
133+
`DirectReviewPlan` 新增 `knowledge_snapshot`(激活快照 ID、`packaged` 或 `unverified`,从不暴露开发树路径)
134+
与 `knowledge_tree_sha256`(已验证快照的清单树哈希,否则为空)。同一 `review_context_id` 下的文档读取都来自这份
135+
快照,RB 应随每次 review 记录这两个值。

‎src/infermatrix_copilot/direct_routing.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ def direct_review_plan(
687687
"if_missing": "partial_review",
688688
},
689689
"diagnostics": {
690-
"knowledge_snapshot": view.snapshot,
690+
"knowledge_snapshot": view.public_snapshot,
691691
"timing_ms": {
692692
"routing": route_ms,
693693
"execution_budget": budget_ms,

‎src/infermatrix_copilot/knowledge_view.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,22 @@ def current(cls) -> "KnowledgeView":
6262
def verified(self) -> bool:
6363
return self.files is not None
6464

65+
@property
66+
def public_snapshot(self) -> str:
67+
"""The snapshot id safe to record anywhere: the activated snapshot's id,
68+
``packaged``, or ``unverified`` (a development tree's path is never exposed)."""
69+
return "unverified" if self.snapshot.startswith("unverified:") else self.snapshot
70+
71+
@property
72+
def tree_sha256(self) -> str:
73+
"""The manifest tree hash of a verified snapshot ("" otherwise)."""
74+
if self.files is None:
75+
return ""
76+
tree = hashlib.sha256()
77+
for rel in sorted(self.files):
78+
tree.update(f"{rel}\0{self.files[rel]}\n".encode("utf-8"))
79+
return tree.hexdigest()
80+
6581
def relative(self, path: str | Path) -> str:
6682
"""Return the knowledge-relative id of an absolute path inside this view."""
6783
try:

‎src/infermatrix_copilot/sdk/v1/direct.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,8 @@ def plan(self, request: DirectReviewRequest) -> DirectReviewPlan:
378378
completion_gate=completion_gate,
379379
diagnostics=dict(raw.get("diagnostics") or {}),
380380
carried_findings=request.carried_findings,
381+
knowledge_snapshot=view.public_snapshot,
382+
knowledge_tree_sha256=view.tree_sha256,
381383
)
382384
self._remember_context(review_context_id, expected_head, carried, view)
383385
return plan

‎src/infermatrix_copilot/sdk/v1/models.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,10 @@ class DirectReviewPlan(_Serializable):
250250
completion_gate: dict[str, Any]
251251
diagnostics: dict[str, Any] = field(default_factory=dict)
252252
carried_findings: tuple[CarriedFinding, ...] = ()
253+
# which knowledge this plan (and every document read under its
254+
# review_context_id) was served from: record it with the review
255+
knowledge_snapshot: str = ""
256+
knowledge_tree_sha256: str = ""
253257

254258
FeedbackStatus = Literal[
255259
"checked", "disabled", "unavailable", "not_applicable"

‎test/test_knowledge_view_routing.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ def test_sdk_completion_pins_the_plan_snapshot(tmp_path, monkeypatch):
207207
changed_paths=(ChangedPath(path="vllm_omni/core/sched/a.py"),),
208208
))
209209
assert plan.diagnostics["knowledge_snapshot"] == "e" * 40
210+
assert plan.knowledge_snapshot == "e" * 40
211+
manifest = json.loads((old / "MANIFEST.json").read_text())
212+
assert plan.knowledge_tree_sha256 == manifest["tree_sha256"]
213+
assert plan.to_dict()["knowledge_snapshot"] == "e" * 40
210214

211215
tmp_link = tmp_path / "active.tmp"
212216
tmp_link.symlink_to(new)
@@ -220,6 +224,21 @@ def test_sdk_completion_pins_the_plan_snapshot(tmp_path, monkeypatch):
220224
assert "provider resources changed after the review context was issued" not in decision.missing
221225

222226

227+
def test_plans_from_a_development_tree_never_expose_its_path(tmp_path, monkeypatch):
228+
from infermatrix_copilot.sdk.v1 import ChangedPath, DirectClient, DirectReviewRequest, RepositoryRef
229+
230+
root = _copy_tree(tmp_path)
231+
monkeypatch.setenv(KNOWLEDGE_ROOT_ENV, str(root))
232+
_load_view.cache_clear()
233+
plan = DirectClient().plan(DirectReviewRequest(
234+
review_id="r3", repository=RepositoryRef(alias="vllm-omni"), pr_number=3,
235+
expected_head_sha="3" * 40, title="scheduler fix", body="",
236+
changed_paths=(ChangedPath(path="vllm_omni/core/sched/a.py"),),
237+
))
238+
assert plan.knowledge_snapshot == "unverified" and plan.knowledge_tree_sha256 == ""
239+
assert str(tmp_path) not in json.dumps(plan.to_dict())
240+
241+
223242
def test_sdk_document_reads_follow_the_plan_snapshot(tmp_path, monkeypatch):
224243
from infermatrix_copilot.sdk.v1 import (
225244
ChangedPath, DirectClient, DirectReviewRequest, RepositoryRef,

0 commit comments

Comments
 (0)