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
101 lines
3.3 KiB
Bash
Executable File
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 ==="
|