test: capture commercial astrology e2e contexts

This commit is contained in:
732642856
2026-07-19 17:28:15 +08:00
parent 02eccede4a
commit 75c4c4c82e
16 changed files with 161866 additions and 0 deletions
@@ -0,0 +1,87 @@
{
"contract": "references/cross_project_contract/commercial_astrology_e2e_acceptance_questions_2026_07_19.json",
"question_count": 10,
"rows": [
{
"forbidden_claim_hits": [],
"id": "marriage_timing",
"missing_layers": [
"gender interpretation boundary"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "career_direction",
"missing_layers": [],
"status": "pass"
},
{
"forbidden_claim_hits": [],
"id": "wealth_pattern",
"missing_layers": [],
"status": "pass"
},
{
"forbidden_claim_hits": [],
"id": "health_risk_window",
"missing_layers": [
"D6",
"D8",
"6th/8th/12th house",
"health non-medical boundary"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "foreign_migration",
"missing_layers": [
"12th house"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "family_home_children",
"missing_layers": [
"4th/5th/9th house"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "education_learning_path",
"missing_layers": [
"5th/9th house"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "precise_timing_boundary",
"missing_layers": [],
"status": "pass"
},
{
"forbidden_claim_hits": [],
"id": "birth_time_uncertain",
"missing_layers": [
"birth-time uncertainty boundary",
"not_auto_rectified"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "annual_forecast",
"missing_layers": [
"annual forecast boundary"
],
"status": "fail"
}
],
"runtime_context_required": true,
"scope": "commercial_astrology_e2e_acceptance_runner",
"status": "fail"
}
@@ -0,0 +1,238 @@
{
"contract": "references/cross_project_contract/commercial_astrology_e2e_acceptance_questions_2026_07_19.json",
"output_dir": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3",
"question_count": 10,
"rows": [
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/marriage_timing.json",
"core_status": "ready",
"id": "marriage_timing",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/career_direction.json",
"core_status": "ready",
"id": "career_direction",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/wealth_pattern.json",
"core_status": "ready",
"id": "wealth_pattern",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/health_risk_window.json",
"core_status": "ready",
"id": "health_risk_window",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/foreign_migration.json",
"core_status": "ready",
"id": "foreign_migration",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/family_home_children.json",
"core_status": "ready",
"id": "family_home_children",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/education_learning_path.json",
"core_status": "ready",
"id": "education_learning_path",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/precise_timing_boundary.json",
"core_status": "ready",
"id": "precise_timing_boundary",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/birth_time_uncertain.json",
"core_status": "ready",
"id": "birth_time_uncertain",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/annual_forecast.json",
"core_status": "ready",
"id": "annual_forecast",
"missing_route_layers": [],
"route": "general"
}
],
"scope": "commercial_astrology_e2e_context_capture"
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,238 @@
{
"contract": "references/cross_project_contract/commercial_astrology_e2e_acceptance_questions_2026_07_19.json",
"output_dir": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3",
"question_count": 10,
"rows": [
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/marriage_timing.json",
"core_status": "ready",
"id": "marriage_timing",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/career_direction.json",
"core_status": "ready",
"id": "career_direction",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/wealth_pattern.json",
"core_status": "ready",
"id": "wealth_pattern",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/health_risk_window.json",
"core_status": "ready",
"id": "health_risk_window",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/foreign_migration.json",
"core_status": "ready",
"id": "foreign_migration",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/family_home_children.json",
"core_status": "ready",
"id": "family_home_children",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/education_learning_path.json",
"core_status": "ready",
"id": "education_learning_path",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/precise_timing_boundary.json",
"core_status": "ready",
"id": "precise_timing_boundary",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/birth_time_uncertain.json",
"core_status": "ready",
"id": "birth_time_uncertain",
"missing_route_layers": [],
"route": "general"
},
{
"available_layers": [
"A10",
"A7",
"D1",
"D10",
"D2",
"D4",
"D9",
"UL",
"dasha_boundaries",
"functional_benefic_malefic",
"house_degrees",
"narayana_dasha",
"planet_degrees",
"shadbala"
],
"context_file": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3/annual_forecast.json",
"core_status": "ready",
"id": "annual_forecast",
"missing_route_layers": [],
"route": "general"
}
],
"scope": "commercial_astrology_e2e_context_capture"
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,99 @@
{
"context_dir": "artifacts/commercial_astrology_e2e_contexts_2026_07_19_run3",
"created_at": "2026-07-19",
"next_actions": [
"add health/family/education/annual/rectification route context requirements",
"expose gender interpretation boundary in marriage timing context",
"expose birth-time uncertainty/not_auto_rectified in rectification entry mode",
"rerun capture script and acceptance runner"
],
"question_count": 10,
"root_cause": "commercial workflow currently routes several high-value Chinese domains to general context, so runtime context does not expose all required domain layers/boundaries",
"rows": [
{
"forbidden_claim_hits": [],
"id": "marriage_timing",
"missing_layers": [
"gender interpretation boundary"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "career_direction",
"missing_layers": [],
"status": "pass"
},
{
"forbidden_claim_hits": [],
"id": "wealth_pattern",
"missing_layers": [],
"status": "pass"
},
{
"forbidden_claim_hits": [],
"id": "health_risk_window",
"missing_layers": [
"D6",
"D8",
"6th/8th/12th house",
"health non-medical boundary"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "foreign_migration",
"missing_layers": [
"12th house"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "family_home_children",
"missing_layers": [
"4th/5th/9th house"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "education_learning_path",
"missing_layers": [
"5th/9th house"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "precise_timing_boundary",
"missing_layers": [],
"status": "pass"
},
{
"forbidden_claim_hits": [],
"id": "birth_time_uncertain",
"missing_layers": [
"birth-time uncertainty boundary",
"not_auto_rectified"
],
"status": "fail"
},
{
"forbidden_claim_hits": [],
"id": "annual_forecast",
"missing_layers": [
"annual forecast boundary"
],
"status": "fail"
}
],
"scope": "commercial_astrology_e2e_runtime_capture_report",
"status": "fail",
"summary": {
"blocked": 0,
"fail": 7,
"pass": 3
}
}
@@ -0,0 +1,114 @@
#!/usr/bin/env python3
"""Capture real consultation workflow contexts for the commercial E2E matrix."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from scripts.consultation_workflow_service import execute_consultation_workflow # noqa: E402
DEFAULT_CONTRACT = ROOT / "references" / "cross_project_contract" / "commercial_astrology_e2e_acceptance_questions_2026_07_19.json"
DEFAULT_OUTPUT_DIR = ROOT / "artifacts" / "commercial_astrology_e2e_contexts_2026_07_19"
THEME_BY_ID = {
"marriage_timing": ["marriage"],
"career_direction": ["career"],
"wealth_pattern": ["wealth"],
"health_risk_window": ["health"],
"foreign_migration": ["career"],
"family_home_children": ["marriage", "wealth"],
"education_learning_path": ["career"],
"precise_timing_boundary": ["career"],
"birth_time_uncertain": ["career"],
"annual_forecast": ["career", "marriage", "wealth"],
}
CANONICAL_BIRTH = {
"year": 1955,
"month": 2,
"day": 24,
"hour": 19,
"minute": 15,
"lat": 37.7749,
"lon": -122.4194,
"tz": -8,
"city": "San Francisco",
}
def _load_json(path: Path) -> Any:
return json.loads(path.read_text(encoding="utf-8"))
def _display_path(path: Path) -> str:
resolved = path.resolve()
try:
return str(resolved.relative_to(ROOT))
except ValueError:
return str(resolved)
def _capture_body(question: dict[str, Any]) -> dict[str, Any]:
qid = str(question["id"])
return {
**CANONICAL_BIRTH,
"question_text": question["user_question"],
"theme": THEME_BY_ID.get(qid, ["general"]),
"entry_mode": "rectification" if qid == "birth_time_uncertain" else "direct_chart",
}
def capture(contract_path: Path = DEFAULT_CONTRACT, output_dir: Path = DEFAULT_OUTPUT_DIR) -> dict[str, Any]:
contract = _load_json(contract_path)
output_dir = output_dir.resolve()
output_dir.mkdir(parents=True, exist_ok=True)
rows: list[dict[str, Any]] = []
for question in contract["questions"]:
qid = str(question["id"])
result = execute_consultation_workflow(_capture_body(question), surface="commercial_e2e_capture")
context_path = output_dir / f"{qid}.json"
context_path.write_text(json.dumps(result, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8")
rows.append(
{
"id": qid,
"context_file": _display_path(context_path),
"core_status": result.get("consumer_context", {}).get("core_status"),
"route": result.get("consumer_context", {}).get("route"),
"available_layers": result.get("consumer_context", {}).get("available_layers", []),
"missing_route_layers": result.get("consumer_context", {}).get("missing_route_layers", []),
}
)
manifest = {
"scope": "commercial_astrology_e2e_context_capture",
"contract": _display_path(contract_path),
"output_dir": _display_path(output_dir),
"question_count": len(rows),
"rows": rows,
}
(output_dir / "capture_manifest.json").write_text(
json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
encoding="utf-8",
)
return manifest
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--contract", type=Path, default=DEFAULT_CONTRACT)
parser.add_argument("--output-dir", type=Path, default=DEFAULT_OUTPUT_DIR)
args = parser.parse_args()
print(json.dumps(capture(args.contract, args.output_dir), ensure_ascii=False, indent=2, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,26 @@
from __future__ import annotations
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SCRIPTS = ROOT / "scripts"
if str(SCRIPTS) not in sys.path:
sys.path.insert(0, str(SCRIPTS))
import capture_commercial_astrology_e2e_contexts as capture_script # noqa: E402
def test_capture_writes_runtime_contexts_without_required_layer_echo(tmp_path: Path) -> None:
manifest = capture_script.capture(output_dir=tmp_path)
assert manifest["question_count"] == 10
assert (tmp_path / "capture_manifest.json").exists()
for row in manifest["rows"]:
context_path = ROOT / row["context_file"] if not Path(row["context_file"]).is_absolute() else Path(row["context_file"])
data = json.loads(context_path.read_text(encoding="utf-8"))
assert data["success"] is True
assert "consumer_context" in data
assert "required_layers" not in data