fix(kg): reject partial ISO dates to avoid silent empty result sets
Per qodo-ai review on PR #1167: sanitize_iso_date() previously accepted YYYY and YYYY-MM, but KnowledgeGraph.query_entity() compares valid_from/ valid_to TEXT columns lexicographically against as_of. Lexicographic comparison treats '2026-01-01' as greater than '2026' (because '-' > end-of-string), so partial as_of values silently excluded valid facts — re-introducing the silent-empty-results problem this PR was meant to fix. Tighten _ISO_DATE_RE to require YYYY-MM-DD only. Update docstring and error message accordingly. Invert the two test cases that asserted partials were accepted.
This commit is contained in:
@@ -223,12 +223,16 @@ def test_kg_value_rejects_over_length():
|
||||
# --- sanitize_iso_date ---
|
||||
|
||||
|
||||
def test_iso_date_accepts_year_only():
|
||||
assert sanitize_iso_date("2026") == "2026"
|
||||
def test_iso_date_rejects_year_only():
|
||||
# Partial dates re-introduce silent empty result sets via lexicographic
|
||||
# TEXT comparison in KG queries (e.g. "2026-01-01" <= "2026" is False).
|
||||
with pytest.raises(ValueError):
|
||||
sanitize_iso_date("2026")
|
||||
|
||||
|
||||
def test_iso_date_accepts_year_month():
|
||||
assert sanitize_iso_date("2026-03") == "2026-03"
|
||||
def test_iso_date_rejects_year_month():
|
||||
with pytest.raises(ValueError):
|
||||
sanitize_iso_date("2026-03")
|
||||
|
||||
|
||||
def test_iso_date_accepts_full_date():
|
||||
|
||||
@@ -702,14 +702,21 @@ class TestKGTools:
|
||||
assert result["success"] is False
|
||||
assert "ended" in result["error"]
|
||||
|
||||
def test_kg_query_accepts_partial_iso_dates(self, monkeypatch, config, palace_path, seeded_kg):
|
||||
def test_kg_query_rejects_partial_iso_dates(self, monkeypatch, config, palace_path, seeded_kg):
|
||||
_patch_mcp_server(monkeypatch, config, seeded_kg)
|
||||
from mempalace.mcp_server import tool_kg_query
|
||||
|
||||
# YYYY and YYYY-MM are valid ISO-8601 forms — must not be rejected.
|
||||
for value in ("2026", "2026-03", "2026-03-15"):
|
||||
# Partial ISO dates are rejected: KG queries compare TEXT dates
|
||||
# lexicographically, so "2026-01-01" <= "2026" is False, which
|
||||
# silently excludes facts. Reject at the boundary — only YYYY-MM-DD
|
||||
# produces correct results.
|
||||
for value in ("2026", "2026-03"):
|
||||
result = tool_kg_query(entity="Max", as_of=value)
|
||||
assert "error" not in result, f"rejected valid date {value!r}: {result}"
|
||||
assert "error" in result, f"accepted partial date {value!r}: {result}"
|
||||
|
||||
# Full ISO-8601 dates still pass.
|
||||
result = tool_kg_query(entity="Max", as_of="2026-03-15")
|
||||
assert "error" not in result, f"rejected valid date: {result}"
|
||||
|
||||
|
||||
# ── Diary Tools ─────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user