master-skill 0.10.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/GEMINI.md +1 -1
- package/README.md +84 -336
- package/README_EN.md +108 -321
- package/bin/cli.mjs +249 -9
- package/gemini-extension.json +1 -1
- package/hooks/session-start +68 -74
- package/hooks/session_start.py +152 -0
- package/package.json +6 -2
- package/prebuilt/{compare → compare-masters}/SKILL.md +21 -2
- package/prebuilt/master-ajahn-chah/meta.json +6 -0
- package/prebuilt/master-ajahn-chah/tests/fidelity.jsonl +6 -6
- package/prebuilt/master-atisha/tests/fidelity.jsonl +4 -4
- package/prebuilt/master-curriculum/SKILL.md +1 -1
- package/prebuilt/master-curriculum/references/tiantai.md +1 -1
- package/prebuilt/master-debate/SKILL.md +15 -3
- package/prebuilt/master-fazang/tests/fidelity.jsonl +2 -2
- package/prebuilt/master-help/SKILL.md +94 -0
- package/prebuilt/master-help/tests/fidelity.jsonl +10 -0
- package/prebuilt/master-huineng/tests/fidelity.jsonl +4 -4
- package/prebuilt/master-kumarajiva/meta.json +14 -3
- package/prebuilt/master-kumarajiva/tests/fidelity.jsonl +3 -3
- package/prebuilt/master-mahasi-sayadaw/tests/fidelity.jsonl +4 -4
- package/prebuilt/master-milarepa/tests/fidelity.jsonl +3 -3
- package/prebuilt/master-nagarjuna/meta.json +19 -4
- package/prebuilt/master-nagarjuna/tests/fidelity.jsonl +6 -6
- package/prebuilt/master-ouyi/meta.json +5 -0
- package/prebuilt/master-ouyi/references/teaching.md +3 -3
- package/prebuilt/master-ouyi/tests/fidelity.jsonl +3 -3
- package/prebuilt/master-tsongkhapa/meta.json +32 -5
- package/prebuilt/master-tsongkhapa/tests/fidelity.jsonl +2 -2
- package/prebuilt/master-xuanzang/tests/fidelity.jsonl +3 -3
- package/prebuilt/master-xuyun/tests/fidelity.jsonl +6 -6
- package/prebuilt/master-zhiyi/meta.json +2 -2
- package/prebuilt/master-zhiyi/tests/fidelity.jsonl +2 -2
- package/references/teaching-modes.md +8 -1
- package/routing.json +209 -0
- package/scripts/check-audit-ignores.py +105 -0
- package/scripts/check-eval-sdk-surface.py +142 -0
- package/scripts/check-gate-liveness.py +421 -0
- package/scripts/reaudit-report.py +163 -0
- package/scripts/regrade-report.py +157 -0
- package/scripts/smoke-eval-sdk.py +174 -0
- package/scripts/test-fidelity.py +992 -89
- package/scripts/validate-citation-references.py +150 -0
- package/scripts/validate-citation-templates.py +176 -0
- package/scripts/validate-fidelity.py +6 -1
- package/scripts/validate-fixture-terms.py +127 -0
- package/scripts/validate-routing.py +254 -0
- package/scripts/validate.py +63 -36
- package/scripts/verify-adjudication.py +316 -0
- package/scripts/verify_citations.py +739 -39
- package/skill-catalog.json +83 -20
- package/tools/cross_reference.py +44 -10
- package/tools/fojin-known-absent.json +14 -0
- package/tools/fojin_bridge.py +138 -8
- package/tools/rag_query.py +45 -2
- package/tools/skill_writer.py +50 -7
- package/tools/verify_sources.py +240 -15
- package/hooks/tests/test_run_hook.sh +0 -114
- package/hooks/tests/test_run_hook_cmd.sh +0 -94
- package/hooks/tests/test_session_start.sh +0 -149
- package/scripts/tests/test_check_manifest_versions.py +0 -217
- package/scripts/tests/test_debate_protocol.py +0 -159
- package/scripts/tests/test_injection_hardening.py +0 -174
- package/scripts/tests/test_select_fidelity_smoke.py +0 -142
- package/scripts/tests/test_validate_citation_contract.py +0 -408
- package/scripts/tests/test_validate_cross_critique.py +0 -149
- package/scripts/tests/test_validate_curriculum_sources.py +0 -144
- package/scripts/tests/test_validate_fidelity.py +0 -59
- package/scripts/tests/test_validate_lore_triggers_content.py +0 -372
- package/scripts/tests/test_validate_persona_fidelity.py +0 -317
- package/scripts/tests/test_validate_promptfoo_configs.py +0 -386
- package/scripts/tests/test_validate_workflow.py +0 -265
- /package/prebuilt/{compare → compare-masters}/tests/fidelity.jsonl +0 -0
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
"""Tests for validate-cross-critique.py."""
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
import json
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
import importlib.util
|
|
8
|
-
import sys
|
|
9
|
-
|
|
10
|
-
import pytest
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def _load_module():
|
|
14
|
-
spec_path = Path(__file__).resolve().parents[1] / "validate-cross-critique.py"
|
|
15
|
-
spec = importlib.util.spec_from_file_location("vcc", spec_path)
|
|
16
|
-
mod = importlib.util.module_from_spec(spec)
|
|
17
|
-
sys.modules["vcc"] = mod
|
|
18
|
-
spec.loader.exec_module(mod)
|
|
19
|
-
return mod
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def _write_master(prebuilt: Path, slug: str, sources: list[dict], cross_critique=None):
|
|
23
|
-
d = prebuilt / f"master-{slug}"
|
|
24
|
-
d.mkdir(parents=True, exist_ok=True)
|
|
25
|
-
data = {"slug": slug, "sources": sources}
|
|
26
|
-
if cross_critique is not None:
|
|
27
|
-
data["cross_critique"] = cross_critique
|
|
28
|
-
(d / "meta.json").write_text(json.dumps(data), encoding="utf-8")
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@pytest.fixture
|
|
32
|
-
def fake_tree(tmp_path):
|
|
33
|
-
prebuilt = tmp_path / "prebuilt"
|
|
34
|
-
# build enough masters to satisfy required_pairs in tests that need them
|
|
35
|
-
for slug in [
|
|
36
|
-
"huineng", "yinguang", "kumarajiva", "xuanzang", "zhiyi",
|
|
37
|
-
"tsongkhapa", "ajahn-chah", "mahasi-sayadaw", "atisha", "ouyi",
|
|
38
|
-
]:
|
|
39
|
-
_write_master(prebuilt, slug, [{"type": "cbeta", "id": "T00n0001", "title": "demo"}])
|
|
40
|
-
return prebuilt
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def test_empty_cross_critique_is_ok(fake_tree):
|
|
44
|
-
vcc = _load_module()
|
|
45
|
-
# No master has cross_critique; structural check passes,
|
|
46
|
-
# but required_pairs check still fails (no coverage).
|
|
47
|
-
errors = vcc.validate(fake_tree, check_coverage=False)
|
|
48
|
-
assert errors == []
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def test_well_formed_entry_passes(fake_tree):
|
|
52
|
-
vcc = _load_module()
|
|
53
|
-
_write_master(fake_tree, "huineng",
|
|
54
|
-
[{"type": "cbeta", "id": "T48n2008", "title": "坛经"}],
|
|
55
|
-
cross_critique=[
|
|
56
|
-
{"target_master": "yinguang", "position": "对净土:本性弥陀唯心净土,何曾离自心。", "citation": "T48n2008"},
|
|
57
|
-
])
|
|
58
|
-
errors = vcc.validate(fake_tree, check_coverage=False)
|
|
59
|
-
# Only the huineng→yinguang structural check should pass.
|
|
60
|
-
huineng_errors = [e for e in errors if "huineng" in e]
|
|
61
|
-
assert huineng_errors == []
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def test_missing_required_field(fake_tree):
|
|
65
|
-
vcc = _load_module()
|
|
66
|
-
_write_master(fake_tree, "huineng",
|
|
67
|
-
[{"type": "cbeta", "id": "T48n2008", "title": "坛经"}],
|
|
68
|
-
cross_critique=[{"target_master": "yinguang"}]) # no position, no citation
|
|
69
|
-
errors = vcc.validate(fake_tree, check_coverage=False)
|
|
70
|
-
assert any("position" in e for e in errors)
|
|
71
|
-
assert any("citation" in e for e in errors)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def test_cannot_target_self(fake_tree):
|
|
75
|
-
vcc = _load_module()
|
|
76
|
-
_write_master(fake_tree, "huineng",
|
|
77
|
-
[{"type": "cbeta", "id": "T48n2008", "title": "坛经"}],
|
|
78
|
-
cross_critique=[{"target_master": "huineng", "position": "x" * 50, "citation": "T48n2008"}])
|
|
79
|
-
errors = vcc.validate(fake_tree, check_coverage=False)
|
|
80
|
-
assert any("self" in e.lower() for e in errors)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def test_cannot_target_meta_skill(fake_tree):
|
|
84
|
-
vcc = _load_module()
|
|
85
|
-
_write_master(fake_tree, "huineng",
|
|
86
|
-
[{"type": "cbeta", "id": "T48n2008", "title": "坛经"}],
|
|
87
|
-
cross_critique=[{"target_master": "curriculum", "position": "x" * 50, "citation": "T48n2008"}])
|
|
88
|
-
errors = vcc.validate(fake_tree, check_coverage=False)
|
|
89
|
-
assert any("meta-skill" in e or "curriculum" in e for e in errors)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def test_unknown_target_master(fake_tree):
|
|
93
|
-
vcc = _load_module()
|
|
94
|
-
_write_master(fake_tree, "huineng",
|
|
95
|
-
[{"type": "cbeta", "id": "T48n2008", "title": "坛经"}],
|
|
96
|
-
cross_critique=[{"target_master": "ghost", "position": "x" * 50, "citation": "T48n2008"}])
|
|
97
|
-
errors = vcc.validate(fake_tree, check_coverage=False)
|
|
98
|
-
assert any("ghost" in e for e in errors)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def test_citation_not_in_own_sources(fake_tree):
|
|
102
|
-
vcc = _load_module()
|
|
103
|
-
_write_master(fake_tree, "huineng",
|
|
104
|
-
[{"type": "cbeta", "id": "T48n2008", "title": "坛经"}],
|
|
105
|
-
cross_critique=[{"target_master": "yinguang", "position": "x" * 50, "citation": "T99n9999"}])
|
|
106
|
-
errors = vcc.validate(fake_tree, check_coverage=False)
|
|
107
|
-
assert any("T99n9999" in e for e in errors)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def test_position_length_bounds(fake_tree):
|
|
111
|
-
vcc = _load_module()
|
|
112
|
-
_write_master(fake_tree, "huineng",
|
|
113
|
-
[{"type": "cbeta", "id": "T48n2008", "title": "坛经"}],
|
|
114
|
-
cross_critique=[
|
|
115
|
-
{"target_master": "yinguang", "position": "短", "citation": "T48n2008"}, # < 10
|
|
116
|
-
{"target_master": "zhiyi", "position": "x" * 400, "citation": "T48n2008"}, # > 300
|
|
117
|
-
])
|
|
118
|
-
errors = vcc.validate(fake_tree, check_coverage=False)
|
|
119
|
-
assert any("length" in e for e in errors)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def test_coverage_fails_when_pairs_missing(fake_tree):
|
|
123
|
-
vcc = _load_module()
|
|
124
|
-
errors = vcc.validate(fake_tree, check_coverage=True)
|
|
125
|
-
# Should report all 16 missing critique entries.
|
|
126
|
-
missing_errors = [e for e in errors if "missing critique" in e]
|
|
127
|
-
assert len(missing_errors) == 16
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def test_coverage_succeeds_with_full_pairs(fake_tree):
|
|
131
|
-
vcc = _load_module()
|
|
132
|
-
pairs = [
|
|
133
|
-
("huineng", "yinguang"), ("yinguang", "huineng"),
|
|
134
|
-
("kumarajiva", "xuanzang"), ("xuanzang", "kumarajiva"),
|
|
135
|
-
("huineng", "zhiyi"), ("zhiyi", "huineng"),
|
|
136
|
-
("tsongkhapa", "huineng"), ("huineng", "tsongkhapa"),
|
|
137
|
-
("ajahn-chah", "mahasi-sayadaw"), ("mahasi-sayadaw", "ajahn-chah"),
|
|
138
|
-
("atisha", "huineng"), ("huineng", "atisha"),
|
|
139
|
-
("ouyi", "yinguang"), ("yinguang", "ouyi"),
|
|
140
|
-
("ouyi", "tsongkhapa"), ("tsongkhapa", "ouyi"),
|
|
141
|
-
]
|
|
142
|
-
by_slug: dict[str, list[dict]] = {}
|
|
143
|
-
for src, tgt in pairs:
|
|
144
|
-
by_slug.setdefault(src, []).append(
|
|
145
|
-
{"target_master": tgt, "position": "x" * 50, "citation": "T00n0001"})
|
|
146
|
-
for slug, cc in by_slug.items():
|
|
147
|
-
_write_master(fake_tree, slug, [{"type": "cbeta", "id": "T00n0001", "title": "demo"}], cc)
|
|
148
|
-
errors = vcc.validate(fake_tree, check_coverage=True)
|
|
149
|
-
assert errors == []
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
"""Tests for validate-curriculum-sources.py.
|
|
2
|
-
|
|
3
|
-
Verifies that citations (CBETA T-numbers, X-numbers, Toh, compiled-teaching ids)
|
|
4
|
-
and /master-<slug> references in curriculum reference files cross-check against
|
|
5
|
-
the actual prebuilt master metadata.
|
|
6
|
-
"""
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import json
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
|
|
12
|
-
import pytest
|
|
13
|
-
|
|
14
|
-
import importlib.util
|
|
15
|
-
import sys
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def _load_module():
|
|
19
|
-
spec_path = Path(__file__).resolve().parents[1] / "validate-curriculum-sources.py"
|
|
20
|
-
spec = importlib.util.spec_from_file_location("vcs", spec_path)
|
|
21
|
-
mod = importlib.util.module_from_spec(spec)
|
|
22
|
-
sys.modules["vcs"] = mod
|
|
23
|
-
spec.loader.exec_module(mod)
|
|
24
|
-
return mod
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@pytest.fixture
|
|
28
|
-
def fake_prebuilt(tmp_path):
|
|
29
|
-
"""Fake prebuilt tree with two masters and a curriculum dir."""
|
|
30
|
-
prebuilt = tmp_path / "prebuilt"
|
|
31
|
-
# Master A: cbeta source
|
|
32
|
-
(prebuilt / "master-aaa").mkdir(parents=True)
|
|
33
|
-
(prebuilt / "master-aaa" / "meta.json").write_text(json.dumps({
|
|
34
|
-
"slug": "aaa",
|
|
35
|
-
"sources": [{"type": "cbeta", "id": "T48n2008", "title": "demo"}],
|
|
36
|
-
}), encoding="utf-8")
|
|
37
|
-
# Master B: compiled_teaching source + Toh
|
|
38
|
-
(prebuilt / "master-bbb").mkdir(parents=True)
|
|
39
|
-
(prebuilt / "master-bbb" / "meta.json").write_text(json.dumps({
|
|
40
|
-
"slug": "bbb",
|
|
41
|
-
"sources": [
|
|
42
|
-
{"type": "compiled_teaching", "id": "AjahnChah:FoodForTheHeart", "title": "demo"},
|
|
43
|
-
{"type": "84000", "id": "Toh 21", "title": "demo"},
|
|
44
|
-
],
|
|
45
|
-
}), encoding="utf-8")
|
|
46
|
-
(prebuilt / "master-curriculum" / "references").mkdir(parents=True)
|
|
47
|
-
return prebuilt
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_extract_citations_finds_T_numbers():
|
|
51
|
-
vcs = _load_module()
|
|
52
|
-
text = "See 《坛经》【T48n2008】 for details."
|
|
53
|
-
assert "T48n2008" in vcs.extract_citations(text)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def test_extract_citations_finds_Toh():
|
|
57
|
-
vcs = _load_module()
|
|
58
|
-
text = "藏文藏经 Toh 21 心经..."
|
|
59
|
-
assert "Toh 21" in vcs.extract_citations(text)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def test_extract_citations_finds_compiled_teaching():
|
|
63
|
-
vcs = _load_module()
|
|
64
|
-
text = "见 AjahnChah:FoodForTheHeart ..."
|
|
65
|
-
assert "AjahnChah:FoodForTheHeart" in vcs.extract_citations(text)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def test_extract_master_slugs():
|
|
69
|
-
vcs = _load_module()
|
|
70
|
-
text = "推荐 master:/master-aaa ;交叉 /master-bbb 。"
|
|
71
|
-
assert vcs.extract_master_slugs(text) == {"aaa", "bbb"}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def test_collect_known_citations(fake_prebuilt):
|
|
75
|
-
vcs = _load_module()
|
|
76
|
-
known = vcs.collect_known_citations(fake_prebuilt)
|
|
77
|
-
assert "T48n2008" in known
|
|
78
|
-
assert "AjahnChah:FoodForTheHeart" in known
|
|
79
|
-
assert "Toh 21" in known
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def test_validate_pass(fake_prebuilt):
|
|
83
|
-
vcs = _load_module()
|
|
84
|
-
ref = fake_prebuilt / "master-curriculum" / "references" / "ok.md"
|
|
85
|
-
ref.write_text(
|
|
86
|
-
"## Path\n- 主用经《坛经》【T48n2008】\n- master:/master-aaa\n- 藏:Toh 21\n",
|
|
87
|
-
encoding="utf-8",
|
|
88
|
-
)
|
|
89
|
-
errors = vcs.validate(fake_prebuilt)
|
|
90
|
-
assert errors == []
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def test_validate_fails_on_fabricated_citation(fake_prebuilt):
|
|
94
|
-
vcs = _load_module()
|
|
95
|
-
ref = fake_prebuilt / "master-curriculum" / "references" / "bad.md"
|
|
96
|
-
ref.write_text("【T99n9999】 fake\n", encoding="utf-8")
|
|
97
|
-
errors = vcs.validate(fake_prebuilt)
|
|
98
|
-
assert any("T99n9999" in e for e in errors)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def test_validate_fails_on_unknown_master_slug(fake_prebuilt):
|
|
102
|
-
vcs = _load_module()
|
|
103
|
-
ref = fake_prebuilt / "master-curriculum" / "references" / "bad.md"
|
|
104
|
-
ref.write_text("/master-ghost\n", encoding="utf-8")
|
|
105
|
-
errors = vcs.validate(fake_prebuilt)
|
|
106
|
-
assert any("ghost" in e for e in errors)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def test_validate_ignores_meta_skill_slugs(fake_prebuilt):
|
|
110
|
-
"""/master-curriculum and /master-debate are meta-skills suppressed via
|
|
111
|
-
META_SKILL_SLUGS. /compare-masters never matches _SLUG (no /master- prefix),
|
|
112
|
-
so it is naturally ignored. None of these may raise validate errors."""
|
|
113
|
-
vcs = _load_module()
|
|
114
|
-
ref = fake_prebuilt / "master-curriculum" / "references" / "ok.md"
|
|
115
|
-
ref.write_text(
|
|
116
|
-
"延伸 → /compare-masters · /master-debate · /master-curriculum\n",
|
|
117
|
-
encoding="utf-8",
|
|
118
|
-
)
|
|
119
|
-
errors = vcs.validate(fake_prebuilt)
|
|
120
|
-
assert errors == []
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def test_validate_returns_error_when_refs_dir_missing(tmp_path):
|
|
124
|
-
vcs = _load_module()
|
|
125
|
-
prebuilt = tmp_path / "prebuilt"
|
|
126
|
-
prebuilt.mkdir()
|
|
127
|
-
# curriculum/references missing
|
|
128
|
-
errors = vcs.validate(prebuilt)
|
|
129
|
-
assert len(errors) == 1
|
|
130
|
-
assert "references dir not found" in errors[0]
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
def test_extract_citations_finds_hyphenated_compiled_teaching():
|
|
134
|
-
vcs = _load_module()
|
|
135
|
-
text = "PTS:DN-Comm 注释 / BDRC:Pha-chos-Bu-chos"
|
|
136
|
-
cits = vcs.extract_citations(text)
|
|
137
|
-
assert "PTS:DN-Comm" in cits
|
|
138
|
-
assert "BDRC:Pha-chos-Bu-chos" in cits
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def test_extract_citations_finds_Toh_with_colon():
|
|
142
|
-
vcs = _load_module()
|
|
143
|
-
text = "见 Toh:3948"
|
|
144
|
-
assert "Toh:3948" in vcs.extract_citations(text)
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import importlib.util
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
MODULE_PATH = Path(__file__).resolve().parents[1] / "validate-fidelity.py"
|
|
6
|
-
SPEC = importlib.util.spec_from_file_location("validate_fidelity", MODULE_PATH)
|
|
7
|
-
validate_fidelity = importlib.util.module_from_spec(SPEC)
|
|
8
|
-
SPEC.loader.exec_module(validate_fidelity)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def _write_fixture(tmp_path: Path, master_name: str, cases: list[dict]) -> Path:
|
|
12
|
-
master_dir = tmp_path / master_name
|
|
13
|
-
tests_dir = master_dir / "tests"
|
|
14
|
-
tests_dir.mkdir(parents=True)
|
|
15
|
-
payload = "\n".join(json.dumps(case, ensure_ascii=False) for case in cases) + "\n"
|
|
16
|
-
(tests_dir / "fidelity.jsonl").write_text(payload, encoding="utf-8")
|
|
17
|
-
return master_dir
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def test_compare_requires_framework_output_sections(tmp_path):
|
|
21
|
-
master_dir = _write_fixture(
|
|
22
|
-
tmp_path,
|
|
23
|
-
"compare",
|
|
24
|
-
[
|
|
25
|
-
{
|
|
26
|
-
"q": "禅和净怎么比较?",
|
|
27
|
-
"must_select_masters": ["huineng", "yinguang"],
|
|
28
|
-
"must_have_sections": ["分歧雷达"],
|
|
29
|
-
}
|
|
30
|
-
for _ in range(5)
|
|
31
|
-
],
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
errors = validate_fidelity.validate_master(master_dir)
|
|
35
|
-
|
|
36
|
-
assert any("共同点" in error for error in errors)
|
|
37
|
-
assert any("引用来源" in error for error in errors)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def test_compare_accepts_required_framework_output_sections(tmp_path):
|
|
41
|
-
case = {
|
|
42
|
-
"q": "禅和净怎么比较?",
|
|
43
|
-
"must_select_masters": ["huineng", "yinguang"],
|
|
44
|
-
"must_have_sections": sorted(validate_fidelity.COMPARE_REQUIRED_SECTIONS),
|
|
45
|
-
}
|
|
46
|
-
cases = [case.copy() for _ in range(5)]
|
|
47
|
-
cases.append(
|
|
48
|
-
{
|
|
49
|
-
"q": "哪个更好?",
|
|
50
|
-
"test_type": "boundary",
|
|
51
|
-
"boundary": "sectarian_judgment",
|
|
52
|
-
"must_not_contain": ["更好"],
|
|
53
|
-
}
|
|
54
|
-
)
|
|
55
|
-
master_dir = _write_fixture(tmp_path, "compare", cases)
|
|
56
|
-
|
|
57
|
-
errors = validate_fidelity.validate_master(master_dir)
|
|
58
|
-
|
|
59
|
-
assert errors == []
|