feat(consult): split family into parents and children domains (engine still family)

parents (D12, 4/9 houses, Sun/Moon) and children (D7, 5th house, Jupiter,
PK) are plan/card domains with Chinese labels and the brief's aliases. They
send the family route contract to the engine and are rejected as a stored
session theme, so neither Python nor the chat_sessions.theme CHECK changes.
Methodology reports no strict checklist for them; must-use layers follow the
plan domain. Tests with 原值/新值/原因 where assertions changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-09-27 02:54:11 +08:00
co-authored by Claude Opus 5.5
parent 75a1844cdf
commit 5c65834dda
14 changed files with 301 additions and 28 deletions
+7 -1
View File
@@ -109,7 +109,13 @@ def test_source_parsers_keep_family_split_gap():
assert "D12" in layers["family"] and "D7" in layers["family"]
assert "父母" not in "".join(layers["family"])
assert routes["family"] is None
assert "family" not in must_use
# 原值:assert "family" not in must_use(调研时前端必用层没有 family)。
# 新值:family / parents / children 都有必用层,父母、子女有独立方法学条目(无命名清单)。
# 原因:TASK-consult-evidence-card-20260927 T2 按调研结论补齐;调研快照的「缺口」已修。
assert must_use["family"] == ["Formal Vargas D1–D60", "Narayana Dasha"]
assert must_use["parents"] == must_use["children"] == must_use["family"]
assert routes["parents"] is None and routes["children"] is None
assert "D12" in layers["parents"] and "D7" in layers["children"]
assert CARD_SPECS["parents"]["vargas"] == ["D12"]
assert CARD_SPECS["children"]["vargas"] == ["D7"]
+33 -5
View File
@@ -70,16 +70,44 @@ def test_typescript_registry_matches_python_canonical_domains_and_aliases() -> N
from pathlib import Path
source = (Path(__file__).resolve().parents[1] / "frontend/src/lib/consultation-domain-registry.ts").read_text()
# 原值:TS 领域 id == Python CANONICAL_DOMAINS,TS 别名表 == DOMAIN_ALIASES。
# 新值:TS 的引擎领域(consultationEngineDomainIds)== CANONICAL_DOMAINS;TS 另有两个
# 只作用于数据卡的子领域 parents / children,引擎侧一律按 family 计算
# (strictWorkflowRoute / workflowThemes 都是 family)。别名比较按「引擎领域」进行:
# Python 认识的每个别名,在 TS 里落到的领域的引擎路由必须等于 Python 的归一结果;
# TS 独有的别名(父母、孩子等)只能落在 parents / children。
# 原因:TASK-consult-evidence-card-20260927 D2,家庭拆父母 / 子女,但不改 Python 引擎。
engine_match = re.search(r"consultationEngineDomainIds = \[([\s\S]*?)\] as const", source)
assert engine_match is not None
assert tuple(re.findall(r'"([^"\n]+)"', engine_match.group(1))) == CANONICAL_DOMAINS
canonical_match = re.search(r"consultationDomainIds = \[([\s\S]*?)\] as const", source)
assert canonical_match is not None
typescript_domains = tuple(re.findall(r'"([^"\n]+)"', canonical_match.group(1)))
assert typescript_domains == CANONICAL_DOMAINS
card_only = ("parents", "children")
assert tuple(domain for domain in typescript_domains if domain not in card_only) == CANONICAL_DOMAINS
assert set(typescript_domains) - set(CANONICAL_DOMAINS) == set(card_only)
definitions = re.findall(r'\{ id: "([a-z]+)"[^\n]*?aliases: (\[[^\]]*\])', source)
assert tuple(domain for domain, _aliases in definitions) == CANONICAL_DOMAINS
definitions = re.findall(
r'\{ id: "([a-z]+)"[^\n]*?aliases: (\[[^\]]*\]), strictWorkflowRoute: "([a-z]+)", workflowThemes: (\[[^\]]*\])',
source,
)
assert tuple(domain for domain, _aliases, _route, _themes in definitions) == typescript_domains
engine_route: dict[str, str] = {}
typescript_aliases: dict[str, str] = {}
for domain, raw_aliases in definitions:
for domain, raw_aliases, route, raw_themes in definitions:
engine_route[domain] = route
if domain in card_only:
assert route == "family" and json.loads(raw_themes) == ["family"], domain
else:
assert route == domain and json.loads(raw_themes) == [domain], domain
for alias in json.loads(raw_aliases):
if alias != domain:
typescript_aliases[alias] = domain
assert typescript_aliases == DOMAIN_ALIASES
for alias, python_domain in DOMAIN_ALIASES.items():
assert alias in typescript_aliases or alias in typescript_domains, alias
ts_domain = typescript_aliases.get(alias, alias)
assert engine_route[ts_domain] == python_domain, alias
for alias, ts_domain in typescript_aliases.items():
if alias not in DOMAIN_ALIASES:
assert ts_domain in card_only, alias