first
This commit is contained in:
+309
@@ -0,0 +1,309 @@
|
||||
#!/bin/bash
|
||||
# Regression: build-graph-data.sh should upgrade edge type from default EXTRACTED
|
||||
# to explicit INFERRED / AMBIGUOUS when the same (from, to) pair is referenced
|
||||
# multiple times within a single source file.
|
||||
#
|
||||
# Motivates fix for:
|
||||
# scripts/build-graph-data.sh edge-merge awk block —
|
||||
# previously the condition `saved_conf[key] == ""` was always false once the
|
||||
# key had been seen (because the ternary in the same branch always filled
|
||||
# it with "EXTRACTED" or the current conf), so the first occurrence locked
|
||||
# the edge type forever. Any later `<!-- confidence: INFERRED -->` annotation
|
||||
# on the same [[link]] in subsequent lines was silently ignored.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
SCRIPT="$REPO_ROOT/scripts/build-graph-data.sh"
|
||||
|
||||
fail() {
|
||||
echo "FAIL: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
test_explicit_confidence_overrides_default_on_same_page() {
|
||||
local tmp_dir
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' RETURN
|
||||
|
||||
mkdir -p "$tmp_dir/wiki/entities"
|
||||
|
||||
# A.md: first reference to B has no annotation (default EXTRACTED),
|
||||
# later reference in the 相关页面 list carries explicit INFERRED.
|
||||
# Before the fix, first occurrence locks type to EXTRACTED forever.
|
||||
cat > "$tmp_dir/wiki/entities/A.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# A
|
||||
|
||||
正文中提到 [[B]] 是一个相关的模块。
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[B]] <!-- confidence: INFERRED --> — 推断关联
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/B.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# B
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[A]] <!-- confidence: INFERRED --> — 推断关联
|
||||
EOF
|
||||
|
||||
# Minimal purpose.md so build-graph-data doesn't bail
|
||||
cat > "$tmp_dir/purpose.md" <<'EOF'
|
||||
# 研究目的
|
||||
test
|
||||
EOF
|
||||
|
||||
LLM_WIKI_TEST_MODE=1 \
|
||||
bash "$SCRIPT" "$tmp_dir" "$tmp_dir/graph-data.json" > /dev/null 2>&1 \
|
||||
|| fail "build-graph-data.sh should succeed on fixture"
|
||||
|
||||
local a_to_b_type b_to_a_type
|
||||
a_to_b_type=$(jq -r '.edges[] | select(.from == "A" and .to == "B") | .type' "$tmp_dir/graph-data.json")
|
||||
b_to_a_type=$(jq -r '.edges[] | select(.from == "B" and .to == "A") | .type' "$tmp_dir/graph-data.json")
|
||||
|
||||
[ "$a_to_b_type" = "INFERRED" ] \
|
||||
|| fail "A→B should be INFERRED after merging (default + explicit INFERRED on same page), got: $a_to_b_type"
|
||||
|
||||
[ "$b_to_a_type" = "INFERRED" ] \
|
||||
|| fail "B→A should be INFERRED (only one reference, explicitly annotated), got: $b_to_a_type"
|
||||
}
|
||||
|
||||
test_ambiguous_overrides_default_when_mixed() {
|
||||
local tmp_dir
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' RETURN
|
||||
|
||||
mkdir -p "$tmp_dir/wiki/entities"
|
||||
|
||||
# X.md references Y multiple times: plain body + AMBIGUOUS annotation
|
||||
cat > "$tmp_dir/wiki/entities/X.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# X
|
||||
|
||||
See [[Y]] in context.
|
||||
Also mention [[Y]] again.
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[Y]] <!-- confidence: AMBIGUOUS --> — 待确认
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/Y.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# Y
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[X]]
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/purpose.md" <<'EOF'
|
||||
# 研究目的
|
||||
test
|
||||
EOF
|
||||
|
||||
LLM_WIKI_TEST_MODE=1 \
|
||||
bash "$SCRIPT" "$tmp_dir" "$tmp_dir/graph-data.json" > /dev/null 2>&1 \
|
||||
|| fail "build-graph-data.sh should succeed on fixture"
|
||||
|
||||
local x_to_y_type
|
||||
x_to_y_type=$(jq -r '.edges[] | select(.from == "X" and .to == "Y") | .type' "$tmp_dir/graph-data.json")
|
||||
|
||||
[ "$x_to_y_type" = "AMBIGUOUS" ] \
|
||||
|| fail "X→Y should be AMBIGUOUS (default + default + AMBIGUOUS merge), got: $x_to_y_type"
|
||||
}
|
||||
|
||||
test_default_extracted_when_no_annotation() {
|
||||
local tmp_dir
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' RETURN
|
||||
|
||||
mkdir -p "$tmp_dir/wiki/entities"
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/P.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# P
|
||||
|
||||
See [[Q]].
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[Q]]
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/Q.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# Q
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[P]]
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/purpose.md" <<'EOF'
|
||||
# 研究目的
|
||||
test
|
||||
EOF
|
||||
|
||||
LLM_WIKI_TEST_MODE=1 \
|
||||
bash "$SCRIPT" "$tmp_dir" "$tmp_dir/graph-data.json" > /dev/null 2>&1 \
|
||||
|| fail "build-graph-data.sh should succeed on fixture"
|
||||
|
||||
local p_to_q_type
|
||||
p_to_q_type=$(jq -r '.edges[] | select(.from == "P" and .to == "Q") | .type' "$tmp_dir/graph-data.json")
|
||||
|
||||
[ "$p_to_q_type" = "EXTRACTED" ] \
|
||||
|| fail "P→Q should default to EXTRACTED when no annotation exists, got: $p_to_q_type"
|
||||
}
|
||||
|
||||
test_first_explicit_wins_among_multiple_explicit() {
|
||||
# When two different explicit confidence values appear for the same
|
||||
# (from, to) pair within the same page, the first-seen one should win
|
||||
# (stable + deterministic). This keeps semantics aligned with the
|
||||
# existing "first occurrence" comment in the awk block.
|
||||
local tmp_dir
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' RETURN
|
||||
|
||||
mkdir -p "$tmp_dir/wiki/entities"
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/M.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# M
|
||||
|
||||
See [[N]] <!-- confidence: INFERRED --> in the body.
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[N]] <!-- confidence: AMBIGUOUS --> — should NOT override INFERRED
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/N.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# N
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[M]]
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/purpose.md" <<'EOF'
|
||||
# 研究目的
|
||||
test
|
||||
EOF
|
||||
|
||||
LLM_WIKI_TEST_MODE=1 \
|
||||
bash "$SCRIPT" "$tmp_dir" "$tmp_dir/graph-data.json" > /dev/null 2>&1 \
|
||||
|| fail "build-graph-data.sh should succeed on fixture"
|
||||
|
||||
local m_to_n_type
|
||||
m_to_n_type=$(jq -r '.edges[] | select(.from == "M" and .to == "N") | .type' "$tmp_dir/graph-data.json")
|
||||
|
||||
[ "$m_to_n_type" = "INFERRED" ] \
|
||||
|| fail "M→N should keep first explicit INFERRED, got: $m_to_n_type"
|
||||
}
|
||||
|
||||
test_edge_contract_separates_relation_type_and_confidence() {
|
||||
local tmp_dir
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' RETURN
|
||||
|
||||
mkdir -p "$tmp_dir/wiki/entities"
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/A.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# A
|
||||
|
||||
See [[B]] without labels first.
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [[B]] <!-- relation: 实现 --> <!-- confidence: INFERRED --> — explicit contract
|
||||
- [[C]] — default contract
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/B.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# B
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/wiki/entities/C.md" <<'EOF'
|
||||
---
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# C
|
||||
EOF
|
||||
|
||||
cat > "$tmp_dir/purpose.md" <<'EOF'
|
||||
# 研究目的
|
||||
test
|
||||
EOF
|
||||
|
||||
LLM_WIKI_TEST_MODE=1 \
|
||||
bash "$SCRIPT" "$tmp_dir" "$tmp_dir/graph-data.json" > /dev/null 2>&1 \
|
||||
|| fail "build-graph-data.sh should succeed on relation contract fixture"
|
||||
|
||||
local a_to_b_type a_to_b_confidence a_to_b_relation
|
||||
a_to_b_type=$(jq -r '.edges[] | select(.from == "A" and .to == "B") | .type' "$tmp_dir/graph-data.json")
|
||||
a_to_b_confidence=$(jq -r '.edges[] | select(.from == "A" and .to == "B") | .confidence' "$tmp_dir/graph-data.json")
|
||||
a_to_b_relation=$(jq -r '.edges[] | select(.from == "A" and .to == "B") | .relation_type' "$tmp_dir/graph-data.json")
|
||||
|
||||
[ "$a_to_b_type" = "INFERRED" ] \
|
||||
|| fail "A→B legacy type should remain INFERRED for compatibility, got: $a_to_b_type"
|
||||
[ "$a_to_b_confidence" = "INFERRED" ] \
|
||||
|| fail "A→B confidence should be INFERRED, got: $a_to_b_confidence"
|
||||
[ "$a_to_b_relation" = "实现" ] \
|
||||
|| fail "A→B relation_type should be 实现, got: $a_to_b_relation"
|
||||
|
||||
local a_to_c_confidence a_to_c_relation
|
||||
a_to_c_confidence=$(jq -r '.edges[] | select(.from == "A" and .to == "C") | .confidence' "$tmp_dir/graph-data.json")
|
||||
a_to_c_relation=$(jq -r '.edges[] | select(.from == "A" and .to == "C") | .relation_type' "$tmp_dir/graph-data.json")
|
||||
|
||||
[ "$a_to_c_confidence" = "EXTRACTED" ] \
|
||||
|| fail "A→C confidence should default to EXTRACTED, got: $a_to_c_confidence"
|
||||
[ "$a_to_c_relation" = "依赖" ] \
|
||||
|| fail "A→C relation_type should default to 依赖, got: $a_to_c_relation"
|
||||
}
|
||||
|
||||
test_explicit_confidence_overrides_default_on_same_page
|
||||
test_ambiguous_overrides_default_when_mixed
|
||||
test_default_extracted_when_no_annotation
|
||||
test_first_explicit_wins_among_multiple_explicit
|
||||
test_edge_contract_separates_relation_type_and_confidence
|
||||
|
||||
echo "PASS: graph-data-confidence-merge.regression-1"
|
||||
Reference in New Issue
Block a user