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.
49 lines
1.9 KiB
Python
49 lines
1.9 KiB
Python
from datetime import UTC, datetime, timedelta
|
|
|
|
import pytest
|
|
|
|
from gewu.adapters.sqlite_node_removals import RemovalConflict, SQLiteNodeRemovalStore
|
|
|
|
|
|
def test_removed_node_is_hidden_until_restored_and_restore_window_is_seven_days(tmp_path) -> None:
|
|
store = SQLiteNodeRemovalStore(tmp_path / "node-removals.sqlite3")
|
|
removed = store.request("dome", "node-a", "A node", "editor")
|
|
|
|
assert store.is_hidden("dome", "node-a")
|
|
assert store.list_restorable("dome") == (removed,)
|
|
restore_window = datetime.fromisoformat(removed.restore_until) - datetime.fromisoformat(
|
|
removed.requested_at
|
|
)
|
|
assert restore_window == timedelta(days=7)
|
|
|
|
restored = store.restore("dome", "node-a", "editor")
|
|
assert restored == removed
|
|
assert not store.is_hidden("dome", "node-a")
|
|
assert store.list_restorable("dome") == ()
|
|
|
|
|
|
def test_expired_removal_stays_hidden_and_cannot_be_restored(tmp_path) -> None:
|
|
store = SQLiteNodeRemovalStore(tmp_path / "node-removals.sqlite3")
|
|
removed = store.request("dome", "node-a", "A node", "editor")
|
|
with store._connect() as connection:
|
|
connection.execute(
|
|
"UPDATE node_removals SET restore_until=? WHERE removal_id=?",
|
|
((datetime.now(UTC) - timedelta(seconds=1)).isoformat(), removed.removal_id),
|
|
)
|
|
|
|
assert store.is_hidden("dome", "node-a")
|
|
assert store.list_restorable("dome") == ()
|
|
with pytest.raises(RemovalConflict, match="expired"):
|
|
store.restore("dome", "node-a", "editor")
|
|
|
|
|
|
def test_removal_survives_store_reopen_and_duplicate_removal_is_rejected(tmp_path) -> None:
|
|
path = tmp_path / "node-removals.sqlite3"
|
|
store = SQLiteNodeRemovalStore(path)
|
|
store.request("dome", "node-a", "A node", "editor")
|
|
reopened = SQLiteNodeRemovalStore(path)
|
|
|
|
assert reopened.is_hidden("dome", "node-a")
|
|
with pytest.raises(RemovalConflict):
|
|
reopened.request("dome", "node-a", "A node", "editor")
|