Files
Jyotisha/tests/test_user_invocation_acceptance_contract.py
T
Jesse_Chen 2415e751fe chore(repo): make the release gate reproducible and clean product URLs
PyJHora absence is now partial, tests write research manifests to tmp, the registry allows experimental_variant, and product links point at the Gitea repo. Early logs move to docs/history.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-03 16:55:26 +08:00

171 lines
5.5 KiB
Python

from __future__ import annotations
import json
import os
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def test_skill_and_plugin_default_to_guided_topics_when_user_has_no_question() -> None:
skill = (ROOT / "SKILL.md").read_text(encoding="utf-8")
readme = (ROOT / "README.md").read_text(encoding="utf-8")
plugin = json.loads((ROOT / ".codex-plugin" / "plugin.json").read_text(encoding="utf-8"))
default_prompt = "\n".join(plugin["interface"]["defaultPrompt"])
for text in (skill, readme, default_prompt):
assert "guided_topics" in text
assert "strict_workflow" in text
assert "evidence_packet" in text or "evidence packet" in text
assert "Technique Audit Table" in text
assert "scripts/user_invocation_acceptance_check.py" in text
assert "不要反问" in skill
assert "不要要求用户自己想问题" in default_prompt
assert "raw_response" in default_prompt
def test_user_entrypoint_can_start_from_guided_topics_prompt() -> None:
completed = subprocess.run(
[
sys.executable,
"scripts/vedastro_user_entrypoint.py",
"--year",
"2000",
"--month",
"1",
"--day",
"1",
"--hour",
"12",
"--minute",
"0",
"--lat",
"0.0",
"--lon",
"0.0",
"--tz",
"0",
"--question",
"请先生成 guided_topics 并推荐我最值得看的问题",
"--themes",
"career,marriage,wealth",
"--reference-date",
"2026-07-06",
"--format",
"json",
],
cwd=ROOT,
text=True,
capture_output=True,
timeout=120,
check=False,
env={
**os.environ,
"JYOTISH_SKIP_LOCAL_ENV": "1",
"VEDASTRO_API_ENDPOINT": "",
"VEDASTRO_ENABLE_NETWORK": "",
"VEDASTRO_TIMEOUT_SECONDS": "",
},
)
assert completed.returncode == 0, completed.stderr or completed.stdout
report = json.loads(completed.stdout)
assert report["strict_workflow"]["triggered"] is True
assert report["strict_workflow"]["routes_available"]
assert report["runtime_mode"]["expected_fallback_status"] in {
"none_if_official_endpoint_responds",
"official_snapshot_budget_exhausted_or_endpoint_blocked",
}
assert report["honesty_boundary"]["all_641_methods_executed"] is False
assert report["input"]["question"] == "请先生成 guided_topics 并推荐我最值得看的问题"
def test_fixture_dasha_timeline_rejects_workbuddy_regression_claims() -> None:
# 原值=依赖引擎默认岁差;新值=显式 lahiri;原因=夹具日期是 Lahiri 口径。
base = [
sys.executable,
"scripts/jyotish_engine.py",
"dasha",
"--year",
"2000",
"--month",
"1",
"--day",
"1",
"--hour",
"12",
"--minute",
"0",
"--lat",
"0.0",
"--lon",
"0.0",
"--tz",
"0",
"--years",
"45",
"--ayanamsa",
"lahiri",
]
observed = {}
for today in ("2014-06-15", "2024-03-01", "2027-03-01"):
completed = subprocess.run(
[*base, "--today", today],
cwd=ROOT,
text=True,
capture_output=True,
timeout=60,
check=False,
)
assert completed.returncode == 0, completed.stderr or completed.stdout
current = json.loads(completed.stdout)["current_dasha"]
observed[today] = (
current["mahadasha"],
current["antardasha"]["lord"],
current["antardasha"]["start"],
current["antardasha"]["end"],
)
assert observed["2014-06-15"] == ("Jupiter", "Rahu", "2014-04-27", "2016-09-20")
assert observed["2024-03-01"] == ("Saturn", "Venus", "2023-07-12", "2026-09-11")
assert observed["2027-03-01"] == ("Saturn", "Sun", "2026-09-11", "2027-08-24")
def test_one_command_user_invocation_acceptance_check() -> None:
completed = subprocess.run(
[sys.executable, "scripts/user_invocation_acceptance_check.py"],
cwd=ROOT,
text=True,
capture_output=True,
timeout=240,
check=False,
)
assert completed.returncode == 0, completed.stderr or completed.stdout
report = json.loads(completed.stdout)
# 原值=status 必须 pass;新值=pass 或 partial;原因=PyJHora 缺席是外部参照降级,不应把验收检查打成 fail
assert report["status"] in {"pass", "partial"}
assert report["checks"]["user_invocation_tests"] is True
assert report["checks"]["guided_topics_entrypoint"] is True
assert report["checks"]["external_adapter_diagnostics"] is True
assert report["external_adapter_status"] in {"pass", "partial", "complete"}
def test_missing_reference_engine_is_partial_not_fail() -> None:
from scripts.user_invocation_acceptance_check import resolve_acceptance_status
assert resolve_acceptance_status([], {"engines": {"PyJHora/JHora": {"status": "available"}}}) == "pass"
assert (
resolve_acceptance_status(
[],
{"engines": {"PyJHora/JHora": {"missing_dependency": "pyjhora"}}},
)
== "partial"
)
assert resolve_acceptance_status(["user_invocation_pytest_failed"], {"engines": {}}) == "fail"