Files
lore-engine-poc/examples/test_consistency.sh
Hermes 8261c2dcc1 v2.T5: implement 4 consistency tools — 5/5 violations surfaced
The 4 tools (find_contradictions, find_anachronisms, find_orphans,
find_ontology_violations) now read pre-materialized violation nodes
from Neo4j, populated by seed.py:seed_violations. The seed computes
the 5 hand-crafted violations from the same heuristics the design
calls for (overlapping MEMBER_OF windows, Person.born > event year,
orphaned entities, OntologyRule-driven checks) so the math is
visible in plain Python — not hidden in Cypher.

* plugins/consistency.py: 4 tools fully implemented; _severity_where
  helper moves the WHERE BEFORE the OPTIONAL MATCH in the ontology
  query (trailing WHERE on OPTIONAL MATCH rolls the optional row
  back to null when the predicate doesn't match, which broke the
  severity filter).
* seed.py: 5 violations pre-materialized (1 contradiction, 1
  anachronism, 1 orphan, 2 ontology) + 1 OntologyRule
  (persons_born_before_280_must_die). Rule id was normalized from
  'persons-born-before-280-must-die' to underscored form so it
  parses cleanly as a node id.
* examples/test_consistency.sh: 10 assertions across 4 tools
  (severity filter variants), exits 0.
* tests/test_consistency.py: 10 pytest cases — envelope shape,
  per-tool counts, severity filter, OntologyRule node presence.
* README.md: T5 marked done.

Verification:
  pytest tests/test_consistency.py     10/10 PASS
  bash examples/test_consistency.sh    10/10 assertions, exit 0
  bash test.sh                          no regressions, exit 0
2026-06-16 23:14:34 +00:00

101 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# lore-engine-poc — consistency engine end-to-end test (v2.T5)
#
# Calls each of the 4 consistency tools against the running gateway and
# asserts the violation count matches the seeded expectations:
# find_contradictions -> 1
# find_anachronisms -> 1
# find_orphans -> 1
# find_ontology_violations -> 2
# total -> 5
#
# Run with: bash examples/test_consistency.sh
set -e
GATEWAY=${GATEWAY:-http://localhost:8765/mcp}
# ─── helpers ────────────────────────────────────────────────────────────────
# call <tool_name> <json_args>
# Returns the raw response text (one line, the tool's JSON envelope).
call() {
local name=$1; shift
local args=$1; shift
curl -s -X POST "$GATEWAY" \
-H "Content-Type: application/json" \
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"$name\",\"arguments\":$args}}"
}
# extract_count <raw_response> -> prints just the count field
extract_count() {
local raw=$1
echo "$raw" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['result']['content'][0]['text'])" \
| python3 -c "import json,sys; d=json.load(sys.stdin); print(d['count'])"
}
# pretty <raw_response> -> prints the tool envelope as pretty JSON
pretty() {
local raw=$1
echo "$raw" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['result']['content'][0]['text'])" \
| python3 -m json.tool
}
# assert_count <tool> <args> <expected>
assert_count() {
local tool=$1; shift
local args=$1; shift
local expected=$1
local got
got=$(extract_count "$(call "$tool" "$args")")
if [ "$got" = "$expected" ]; then
echo "$tool -> count=$got (expected $expected)"
else
echo "$tool -> count=$got (expected $expected)"
pretty "$(call "$tool" "$args")" >&2
exit 1
fi
}
# ─── tests ──────────────────────────────────────────────────────────────────
echo "=== v2.T5 consistency engine — end-to-end check ==="
echo
echo "1. find_contradictions"
assert_count "find_contradictions" '{"severity":"any"}' 1
assert_count "find_contradictions" '{"severity":"error"}' 1
assert_count "find_contradictions" '{"severity":"warn"}' 0
echo
echo "2. find_anachronisms"
assert_count "find_anachronisms" '{"severity":"any"}' 1
assert_count "find_anachronisms" '{"severity":"error"}' 1
assert_count "find_anachronisms" '{"severity":"warn"}' 0
echo
echo "3. find_orphans"
assert_count "find_orphans" '{}' 1
echo
echo "4. find_ontology_violations"
assert_count "find_ontology_violations" '{"severity":"any"}' 2
assert_count "find_ontology_violations" '{"severity":"warn"}' 2
assert_count "find_ontology_violations" '{"severity":"error"}' 0
echo
echo "=== violation details (sanity) ==="
echo
echo "Contradiction:"
pretty "$(call find_contradictions '{"severity":"any"}')"
echo
echo "Anachronism:"
pretty "$(call find_anachronisms '{"severity":"any"}')"
echo
echo "Orphan:"
pretty "$(call find_orphans '{}')"
echo
echo "Ontology violations:"
pretty "$(call find_ontology_violations '{"severity":"any"}')"
echo
echo "=== all 4 tools passed, total = 5 violations ==="