feat: online verification, node removals, and knowledge browser
CI / quality (push) Canceled after 0s

Adds claim-bound online evidence records and citation verification scripts,
node removal transport/adapter, retrieval benchmark and owner-review tooling,
GraphCanvas/SourceDetail knowledge browser UI, and the ingest handoff helper.
Bumps the agents/gewu pack to the online-verification branch.
This commit is contained in:
vasily committed 2026-10-16 20:02:29 +08:00
1 parent a3156f4e08
commit 78033bb830
83 files changed
+13476 -1051

No files matched your search

+30
View File
@@ -11,6 +11,7 @@ import pytest
import yaml
from gewu.adapters.git_repository import GitCanonicalRepository
from gewu.adapters.sqlite_node_removals import SQLiteNodeRemovalStore
from gewu.adapters.sqlite_search import SQLiteSearchIndex
from gewu.application.identity import Principal
from gewu.application.search import CanonicalSearchService, SearchError
@@ -210,6 +211,7 @@ def test_assumption_and_limitation_claims_are_searchable_and_cited(tmp_path: Pat
query="assumptionspecific",
scope=Scope(projects=("dome-performance",), include_shared=False),
budget_tokens=50_000,
include_evidence=True,
),
principal=reader,
)
@@ -700,3 +702,31 @@ def test_neighbor_source_metadata_requires_an_ingested_for_scope(tmp_path: Path)
neighbor = cast(dict[str, object], response.data[0]["neighbor"])
assert neighbor["kind"] == "source"
assert cast(dict[str, object], neighbor["record"])["revision_id"] == SOURCE_REVISION.revision_id
def test_durable_node_removal_hides_from_search_and_returns_after_restore(tmp_path: Path) -> None:
repository = GitCanonicalRepository(tmp_path / "knowledge.git")
_publish_nodes(repository, tmp_path / "publishing", (NODE,))
removals = SQLiteNodeRemovalStore(tmp_path / "node-removals.sqlite3")
index = SQLiteSearchIndex(
tmp_path / "search.sqlite3", repository, node_removals_path=removals.path
)
service = CanonicalSearchService(
index=index,
project_ids_provider=lambda: PROJECTS.keys(),
canonical_head=repository.head,
)
principal = Principal(
"editor", "editor-key", frozenset({"editor"}), frozenset({NODE.project_id})
)
request = SearchRequest(
query=NODE.title,
scope=Scope(projects=(NODE.project_id,), include_shared=False),
budget_tokens=5000,
)
assert service.search(request, principal=principal).data
removals.request(NODE.project_id, NODE.node_id, NODE.title, "editor")
assert service.search(request, principal=principal).data == ()
removals.restore(NODE.project_id, NODE.node_id, "editor")
assert service.search(request, principal=principal).data