30ef6afea7
The upstream interview playbook and evidence thresholds resolve task 0. Upstream stops and reports when evidence is thin — fewer than three dated events, fewer than two domains, or a tie — while this repo treats the same kind of thresholds as a confirmation gate and keeps asking when they are not met. Its label ladder has no confirmed rung at all, and every contract test asserts candidate_range_not_birth_time_truth. Task 1 capped the interview by round count, which is half of it. Task 6 adds the evidence-state stop rules, reframes exhausted as a normal delivery, adopts the upstream label ladder and closing wording, and keeps the 4/3 confirmation gate separate from the 3/2 delivery floor. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
272 lines
9.5 KiB
Python
272 lines
9.5 KiB
Python
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
SKILL = REPO_ROOT / "skills" / "jyotish-birth-time-rectification"
|
|
if not SKILL.is_dir():
|
|
SKILL = Path("/Users/wuyongnaren/.workbuddy/skills/jyotish-birth-time-rectification")
|
|
|
|
|
|
def test_rectification_skill_resources_and_portable_contract_exist() -> None:
|
|
skill_text = (SKILL / "SKILL.md").read_text(encoding="utf-8")
|
|
for relative_path in (
|
|
"references/main_repository_router.md",
|
|
"references/interview_playbook.md",
|
|
"references/evidence_thresholds.md",
|
|
"references/api_reference.md",
|
|
"references/manual_test_prompts.md",
|
|
"references/testing_playbook.md",
|
|
"references/adapter_integration_guide.md",
|
|
"references/public_distribution_checklist.md",
|
|
"assets/rectification_session_template.md",
|
|
"scripts/example.py",
|
|
):
|
|
assert (SKILL / relative_path).is_file(), relative_path
|
|
assert relative_path in skill_text
|
|
|
|
for required_term in (
|
|
"standalone_core",
|
|
"adapter_enhanced",
|
|
"main_repository_enhanced",
|
|
"range / block / unknown",
|
|
"Vimshottari + Narayana",
|
|
"Functional Benefic/Malefic",
|
|
"MEVG",
|
|
"Real Case Calibration",
|
|
"候选时间段",
|
|
"临时代表时间",
|
|
"唯一真实出生分钟",
|
|
"高置信候选",
|
|
"Require no fixed repository path",
|
|
"manual_test_prompts.md",
|
|
"testing_playbook.md",
|
|
"adapter_integration_guide.md",
|
|
"public_distribution_checklist.md",
|
|
):
|
|
assert required_term in skill_text
|
|
|
|
assert "/Users/wuyongnaren/Documents/印度占星" not in skill_text
|
|
|
|
|
|
def test_router_and_thresholds_define_portable_modes_and_caps() -> None:
|
|
router = (SKILL / "references/main_repository_router.md").read_text(encoding="utf-8")
|
|
for required_term in (
|
|
"standalone_core",
|
|
"adapter_enhanced",
|
|
"main_repository_enhanced",
|
|
"supports",
|
|
"conflicts",
|
|
"executed",
|
|
"blocked",
|
|
"not_applicable",
|
|
):
|
|
assert required_term in router
|
|
assert "/Users/wuyongnaren/Documents/印度占星" not in router
|
|
assert ".venv" not in router
|
|
|
|
thresholds = (SKILL / "references/evidence_thresholds.md").read_text(encoding="utf-8")
|
|
assert "manual_pattern_consensus" in thresholds
|
|
assert "高置信候选" in thresholds
|
|
assert "不等于唯一真实出生分钟" in thresholds
|
|
assert "standalone_core" in thresholds
|
|
|
|
|
|
def test_template_and_api_reference_preserve_audit_and_portability() -> None:
|
|
template = (SKILL / "assets/rectification_session_template.md").read_text(encoding="utf-8")
|
|
for heading in (
|
|
"Runtime mode",
|
|
"supports",
|
|
"conflicts",
|
|
"Functional Benefic/Malefic (optional)",
|
|
"External evidence / MEVG / Real Case (optional)",
|
|
):
|
|
assert heading in template
|
|
|
|
api_reference = (SKILL / "references/api_reference.md").read_text(encoding="utf-8")
|
|
for term in (
|
|
"route",
|
|
"known_time",
|
|
"known_block",
|
|
"adapters",
|
|
"repository_root",
|
|
"main_repository_enhanced",
|
|
"candidate_range_not_birth_time_truth",
|
|
):
|
|
assert term in api_reference
|
|
assert "/Users/wuyongnaren/Documents/印度占星" not in api_reference
|
|
|
|
|
|
def test_scaffold_runs_standalone_and_returns_candidate_only_receipt() -> None:
|
|
request = {
|
|
"route": "range",
|
|
"known_time": {"start": "14:00", "end": "16:00"},
|
|
"events": [
|
|
{
|
|
"id": "career-1",
|
|
"domain": "career",
|
|
"date": "2019-07",
|
|
"precision": "month",
|
|
"reliability": "high",
|
|
"supports": ["middle", "late"],
|
|
"conflicts": ["early"],
|
|
"note": "工作结构变化后责任显著增加",
|
|
},
|
|
{
|
|
"id": "relationship-1",
|
|
"domain": "relationship",
|
|
"date": "2016-10-03",
|
|
"precision": "day",
|
|
"reliability": "high",
|
|
"supports": ["middle"],
|
|
"conflicts": ["early"],
|
|
"note": "关系进入与承诺加强",
|
|
},
|
|
{
|
|
"id": "relocation-1",
|
|
"domain": "relocation",
|
|
"date": "2014",
|
|
"precision": "year",
|
|
"reliability": "medium",
|
|
"supports": ["late"],
|
|
"conflicts": [],
|
|
"note": "离乡发展",
|
|
},
|
|
],
|
|
}
|
|
result = subprocess.run(
|
|
[sys.executable, str(SKILL / "scripts/example.py")],
|
|
input=json.dumps(request),
|
|
text=True,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
receipt = json.loads(result.stdout)
|
|
assert receipt["claim_status"] == "candidate_range_not_birth_time_truth"
|
|
assert receipt["summary"]["claim_status"] == "candidate_range_not_birth_time_truth"
|
|
assert receipt["runtime_mode"] == "standalone_core"
|
|
assert receipt["summary"]["confidence_label"] in {"medium", "manual_pattern_consensus"}
|
|
assert receipt["candidate_result"]["candidate_range"]["representative_time"]
|
|
|
|
|
|
def test_scaffold_can_report_adapter_enhanced_without_fixed_repo_path() -> None:
|
|
request = {
|
|
"route": "unknown",
|
|
"events": [
|
|
{
|
|
"id": "career-1",
|
|
"domain": "career",
|
|
"date": "2020-05",
|
|
"precision": "month",
|
|
"reliability": "high",
|
|
"supports": ["afternoon"],
|
|
"conflicts": ["night"],
|
|
"note": "职业方向明显切换",
|
|
},
|
|
{
|
|
"id": "relationship-1",
|
|
"domain": "relationship",
|
|
"date": "2018-09",
|
|
"precision": "month",
|
|
"reliability": "high",
|
|
"supports": ["afternoon"],
|
|
"conflicts": ["morning"],
|
|
"note": "稳定关系建立",
|
|
},
|
|
{
|
|
"id": "education-1",
|
|
"domain": "education",
|
|
"date": "2012",
|
|
"precision": "year",
|
|
"reliability": "medium",
|
|
"supports": ["afternoon"],
|
|
"conflicts": [],
|
|
"note": "学习方向变化",
|
|
},
|
|
],
|
|
"adapters": [
|
|
{
|
|
"name": "user_vimshottari_engine",
|
|
"type": "calculator",
|
|
"location": "./tools/rectify.py",
|
|
"status": "executed",
|
|
"summary": "Vimshottari and Narayana both prefer afternoon",
|
|
"raw_result_ref": "outputs/rectify-afternoon.json",
|
|
}
|
|
],
|
|
}
|
|
result = subprocess.run(
|
|
[sys.executable, str(SKILL / "scripts/example.py")],
|
|
input=json.dumps(request),
|
|
text=True,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
receipt = json.loads(result.stdout)
|
|
assert receipt["runtime_mode"] == "adapter_enhanced"
|
|
assert receipt["summary"]["confidence_label"] == "single_adapter_support"
|
|
assert receipt["audit_appendix"]["adapter_statuses"][0]["status"] == "executed"
|
|
|
|
|
|
def test_scaffold_main_repository_enhanced_can_execute_with_minimal_valid_payload() -> None:
|
|
request = {
|
|
"runtime_mode": "main_repository_enhanced",
|
|
"repository_root": "/Users/wuyongnaren/Documents/印度占星",
|
|
"request": {
|
|
"birth_date": "1993-04-17",
|
|
"start_time": "14:29",
|
|
"end_time": "14:31",
|
|
"lat": 36.683333,
|
|
"lon": 114.35,
|
|
"tz": 8,
|
|
"events": [
|
|
{"id": "edu-1", "domain": "education", "date": "2011-09", "precision": "month"},
|
|
{"id": "career-1", "domain": "career", "date": "2019-07-01", "precision": "day"},
|
|
{"id": "rel-1", "domain": "relationship", "date": "2021", "precision": "year"}
|
|
]
|
|
}
|
|
}
|
|
result = subprocess.run(
|
|
[sys.executable, str(SKILL / "scripts/example.py")],
|
|
input=json.dumps(request),
|
|
text=True,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
receipt = json.loads(result.stdout)
|
|
assert receipt["runtime_mode"] == "main_repository_enhanced"
|
|
assert receipt["claim_status"] == "candidate_range_not_birth_time_truth"
|
|
assert receipt["summary"]["claim_status"] == "candidate_range_not_birth_time_truth"
|
|
|
|
|
|
def test_scaffold_main_repository_enhanced_returns_structured_block_when_fields_missing() -> None:
|
|
request = {
|
|
"runtime_mode": "main_repository_enhanced",
|
|
"repository_root": "/Users/wuyongnaren/Documents/印度占星",
|
|
"request": {
|
|
"events": [
|
|
{
|
|
"date": "2020-05",
|
|
"category": "career",
|
|
"description": "职业方向明显切换",
|
|
"confidence": "high"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
result = subprocess.run(
|
|
[sys.executable, str(SKILL / "scripts/example.py")],
|
|
input=json.dumps(request),
|
|
text=True,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
receipt = json.loads(result.stdout)
|
|
assert receipt["runtime_mode"] == "main_repository_enhanced"
|
|
assert receipt["claim_status"] == "candidate_range_not_birth_time_truth"
|
|
assert receipt["candidate_result"]["status"] == "blocked"
|
|
assert receipt["candidate_result"]["reason"] == "missing_required_fields"
|
|
assert "birth_date" in receipt["candidate_result"]["missing_fields"]
|