Skip to content

Commit bf1dfc3

Browse files
committed
Preserve accepted depth and prioritize feature-local evidence in completion campaigns
1 parent 5831699 commit bf1dfc3

18 files changed

Lines changed: 38637 additions & 22 deletions

‎doc/architecture/SPEC/kb_service.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,8 @@ architecture/guide;同一调用独立判定各新增维度的 faithful/non_con
558558

559559
`DepthContext.build` 接收 requested facets、previous review 与 evidence round;按入口、
560560
调用方/被调函数、配置 use site、异常分支和具体断言选择完整范围内的有界切片。
561+
生产证据依次优先声明入口、功能实现、直接依赖和调用方,分别保留功能与关联代码预算,
562+
并分配文件预算避免大型通用调用方挤占入口。可证明的小型调用链两端先完整提供;文件数不设四个的上限。
561563
测试索引包含嵌套第一方 SDK/前端套件,优先直接入口引用与实际调用;无关包标记不作为
562564
验证入口。固定前四文件、两个测试及前 180 行不再构成检索上限。动态关联只作为未知。
563565
保存生成前的完整 payload 与规范化 prompt 摘要,中断裁判复用完成的草稿;每个缺口
@@ -575,6 +577,7 @@ proof `basis` 缺省 supported,旧区块不改写。verified_absent 当前只
575577
批次遍历完成分别记录。提取前复核结构覆盖;结构门槛不足先阻断,不消耗模型调用。
576578
结构覆盖与深度门槛均须满足才能发布。深度未达标 dry run 为 partial,保存预览但步骤不成功;发布阻断。
577579
执行 API 的 feature_ids 只限定调度范围;审计仍包含完整政策中的所有功能和维度。
580+
显式列表保留执行顺序并纳入输入摘要;零深度功能仍优先,之后按列表顺序开展首轮。
578581
并行批次各自保留检查点,合并认可页面后须重新通过全量验收,不能发布分组的部分结果。
579582
独立 source audit 使用相同门槛。原生认可审计读取实际 archived model_call 输入输出,
580583
核对最终区块与源码 pin、三个 yes 和不同模型家族;不能信任只有 receipt 字段的报告。

‎eval/knowledge-depth/assemble_depth_campaign.py‎

Lines changed: 284 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#!/usr/bin/env python3
2+
"""Audit actual bounded Direct context for every feature in one frozen KB tree.
3+
4+
Facet status here describes intact served metadata. Source verification and
5+
native approval are separate audits; these probes do not measure PR bug recall.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
import argparse
11+
import hashlib
12+
import json
13+
import re
14+
from pathlib import Path
15+
16+
import yaml
17+
18+
from infermatrix_copilot.direct_routing import direct_review_plan
19+
from infermatrix_copilot.kb_service.knowledge_coverage import load_policy, policy_path
20+
from infermatrix_copilot.kb_service.knowledge_depth import FACETS, depth_page
21+
from infermatrix_copilot.knowledge_service.lifecycle import depth_sections
22+
from infermatrix_copilot.knowledge_view import KnowledgeView, build_manifest
23+
24+
PROBES = ("description_and_paths", "query_only", "paths_only")
25+
26+
27+
def _hash(text: str) -> str:
28+
return hashlib.sha256(text.encode("utf-8")).hexdigest()
29+
30+
31+
def _document(document: dict, view: KnowledgeView, pin: str, problems: list[str], label: str) -> dict:
32+
raw = view.read_text(document["path"])
33+
sections = {row["facet"]: row for row in depth_sections(raw)}
34+
content = document["content"]
35+
included = document["included_facets"]
36+
available = document["available_facets"]
37+
expected = set(sections)
38+
if set(available) != expected or len(available) != len(expected) or len(set(included)) != len(included):
39+
problems.append(f"{label}: delivered facet metadata differs from the intact page")
40+
if not set(included) <= expected:
41+
problems.append(f"{label}: included facets are not available")
42+
if document.get("facet_basis") != {facet: row["basis"] for facet, row in sections.items()}:
43+
problems.append(f"{label}: delivered basis differs from the intact page")
44+
if document.get("included_facet_basis") != {facet: sections[facet]["basis"] for facet in included if facet in sections}:
45+
problems.append(f"{label}: delivered injected basis differs from the actual included facets")
46+
if document.get("verified_gaps") != {facet: row["gap_label"] for facet, row in sections.items() if row["gap_label"]}:
47+
problems.append(f"{label}: delivered gap labels differ from the intact page")
48+
if document.get("not_injected_facets") != [facet for facet in available if facet not in included]:
49+
problems.append(f"{label}: uninjected facet metadata differs from selection")
50+
missing = [facet for facet in FACETS if facet not in expected] if document["feature"] else []
51+
if document["missing_facets"] != missing:
52+
problems.append(f"{label}: missing facet metadata differs from the intact page")
53+
if len(content) > 3000:
54+
problems.append(f"{label}: document exceeds 3000 characters")
55+
if any(row["pin"] != pin for row in sections.values()):
56+
problems.append(f"{label}: served depth has another source pin")
57+
facet_states = {}
58+
for facet in FACETS:
59+
section = sections.get(facet)
60+
injection = "not_injected"
61+
if facet in included and section:
62+
if section["content"].strip() in content:
63+
injection = "full"
64+
elif content.strip() and len(included) == 1 and section["content"].strip().startswith(content.rstrip()):
65+
injection = "partial"
66+
else:
67+
problems.append(f"{label}: declared injected facet {facet} is absent from actual content")
68+
facet_states[facet] = {"status": section["basis"] if section else "unknown", "injection": injection,
69+
"gap_label": section["gap_label"] if section else None}
70+
return {**document, "content_sha256": _hash(content), "page_sha256": _hash(raw),
71+
"content_chars": len(content), "facet_states": facet_states}
72+
73+
74+
def audit_retrieval(root: Path, repo: str, pin: str, *, require_depth: bool = False) -> dict:
75+
if not re.fullmatch(r"[0-9a-f]{40}", pin):
76+
raise ValueError("retrieval audit requires a full pinned source SHA")
77+
root = root.resolve()
78+
knowledge = root / "knowledge"
79+
manifest = yaml.safe_load((root / f"adapters/{repo}/manifest.yaml").read_text())
80+
repo_dir = manifest["knowledge"]["repo_subdir"]
81+
policy_file = root / policy_path(repo)
82+
policy_text = policy_file.read_text()
83+
policy = load_policy(policy_text, repo_dir)
84+
frozen = build_manifest(knowledge, "depth-retrieval-audit")
85+
view = KnowledgeView(root=knowledge, snapshot=f"depth-retrieval-audit-{frozen['tree_sha256']}", files=frozen["files"])
86+
cases, problems, feature_status = [], [], {}
87+
for feature in policy.features:
88+
page = depth_page(feature)
89+
rows = depth_sections(view.read_text(page)) if page in view.files else []
90+
rows = [row for row in rows if row["feature"] == feature.id]
91+
available = {row["facet"]: row["basis"] for row in rows}
92+
feature_status[feature.id] = {"page": page, "entry_points": list(feature.entry_points),
93+
"facets": {facet: available.get(facet, "unknown") for facet in FACETS}}
94+
if require_depth and not available:
95+
problems.append(f"{feature.id}: no intact depth available")
96+
for probe in PROBES:
97+
changed = list(feature.entry_points) if probe != "query_only" else []
98+
title = f"{feature.title} {feature.id}" if probe != "paths_only" else ""
99+
plan = direct_review_plan(repo_dir.removeprefix("repos/"), title=title, changed_files=changed, view=view)
100+
related = plan["related_knowledge"]
101+
label = f"{feature.id}/{probe}"
102+
documents = [_document(d, view, pin, problems, label) for d in related["documents"]]
103+
if any(not d["path"].startswith(repo_dir + "/") for d in documents):
104+
problems.append(f"{label}: automatic context escaped the selected repository")
105+
actual_chars = sum(len(d["content"]) for d in documents)
106+
if len(documents) > 2 or actual_chars > 6000 or actual_chars != related["content_chars"]:
107+
problems.append(f"{label}: actual context violates the two-page/6000-character contract")
108+
if len({d["feature"] or d["path"] for d in documents}) != len(documents):
109+
problems.append(f"{label}: duplicate feature selected")
110+
hit = next((d for d in documents if d["feature"] == feature.id), None)
111+
delivered_depth = bool(hit and any(s["injection"] != "not_injected" for s in hit["facet_states"].values()))
112+
if probe != "paths_only" and (not hit or (available and (hit["path"] != page or not delivered_depth))):
113+
problems.append(f"{label}: feature depth absent from actual Direct context")
114+
followups = plan["navigation_policy"]["related_document_read_paths"]
115+
if followups != [d["path"] for d in documents if d["more_available"]]:
116+
problems.append(f"{label}: followup paths differ from the selected incomplete documents")
117+
cases.append({"feature": feature.id, "probe": probe, "changed_files": changed, "query": title,
118+
"feature_hit": bool(hit), "depth_hit": delivered_depth,
119+
"content_chars": actual_chars, "documents": documents,
120+
"followup_read_paths": followups, "execution_budget": plan["execution_budget"],
121+
"facet_injection": {facet: hit["facet_states"][facet]["injection"] if hit else "not_injected"
122+
for facet in FACETS}})
123+
if build_manifest(knowledge, frozen["snapshot"])["files"] != frozen["files"] or policy_file.read_text() != policy_text:
124+
problems.append("knowledge or policy changed during the frozen retrieval audit")
125+
statuses = ("supported", "verified_absent", "unknown")
126+
summary = {"total_features": len(policy.features), "total_facets": len(policy.features) * len(FACETS),
127+
"features_with_intact_depth": sum(any(s != "unknown" for s in f["facets"].values()) for f in feature_status.values()),
128+
"available_facet_status": {s: sum(status == s for f in feature_status.values() for status in f["facets"].values())
129+
for s in statuses}, "probes": {}}
130+
for probe in PROBES:
131+
selected = [case for case in cases if case["probe"] == probe]
132+
summary["probes"][probe] = {"cases": len(selected), "feature_hits": sum(c["feature_hit"] for c in selected),
133+
"depth_hits": sum(c["depth_hit"] for c in selected),
134+
"max_documents": max((len(c["documents"]) for c in selected), default=0),
135+
"max_content_chars": max((c["content_chars"] for c in selected), default=0),
136+
"target_feature_injection": {s: sum(state == s for c in selected for state in c["facet_injection"].values())
137+
for s in ("full", "partial", "not_injected")}}
138+
return {"summary": summary, "problems": problems, "features": feature_status, "cases": cases,
139+
"provenance": {"source_pin": pin, "policy_sha256": _hash(policy_text),
140+
"knowledge_tree_sha256": view.tree_sha256, "snapshot_files": len(view.files)},
141+
"limits": "Statuses describe intact served metadata, not independent source/native approval. "
142+
"Full and partial injection are counted separately from available knowledge. "
143+
"Paths-only misses are diagnostic when entry points overlap. Catalog delivery does not "
144+
"establish PR bug recall, review quality, verified behavior or passing tests."}
145+
146+
147+
def main() -> int:
148+
parser = argparse.ArgumentParser(description=__doc__)
149+
parser.add_argument("--root", type=Path, default=Path.cwd())
150+
parser.add_argument("--repo", required=True)
151+
parser.add_argument("--pin", required=True)
152+
parser.add_argument("--snapshot-commit", help="Full commit SHA identifying the caller's read-only Git export")
153+
parser.add_argument("--require-depth", action="store_true")
154+
parser.add_argument("--report", type=Path)
155+
args = parser.parse_args()
156+
if args.snapshot_commit and not re.fullmatch(r"[0-9a-f]{40}", args.snapshot_commit):
157+
parser.error("snapshot commit must be a full SHA")
158+
if args.report and args.report.resolve().is_relative_to((args.root / "knowledge").resolve()):
159+
parser.error("retrieval evidence belongs outside product knowledge")
160+
report = audit_retrieval(args.root, args.repo, args.pin, require_depth=args.require_depth)
161+
if args.snapshot_commit:
162+
report["provenance"]["declared_snapshot_commit"] = args.snapshot_commit
163+
report["notes"] = ["The caller identifies this read-only Git export with declared_snapshot_commit; "
164+
"the audit independently binds its actual files with knowledge_tree_sha256."]
165+
if args.report:
166+
args.report.parent.mkdir(parents=True, exist_ok=True)
167+
args.report.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
168+
print(json.dumps({"summary": report["summary"], "problems": report["problems"]}, ensure_ascii=False, indent=2))
169+
return int(bool(report["problems"]))
170+
171+
172+
if __name__ == "__main__":
173+
raise SystemExit(main())

0 commit comments

Comments
 (0)