integrate ganjihong engine refactor

This commit is contained in:
2026-09-09 18:41:56 +08:00
parent cf9cd0366a
commit 21a5185926
116 changed files with 3596 additions and 12259 deletions
+19 -4
View File
@@ -84,6 +84,19 @@ def _mappings(value: Any):
yield from _mappings(child)
def _contract_selectors(node: FeaturePlanNode, contract: dict[str, Any] | None) -> list[dict[str, Any]]:
"""Read only the selector slot declared by the operation contract."""
slot = str((contract or {}).get("selector_slot") or "")
if slot == "feature.selectors":
values = node.selectors
elif slot.startswith("params.") and slot.count(".") == 1:
value = node.params.get(slot.removeprefix("params."))
values = value if isinstance(value, list) else [value]
else:
values = []
return [value for value in values if isinstance(value, dict)]
def _transform_member_sources(params: dict[str, Any]) -> set[str]:
"""Return internal body-member keys named by a transform contract."""
source_ids = {str(value) for value in params.get("source_feature_ids") or ()}
@@ -545,18 +558,20 @@ class CapabilityAnalyzer:
"Loft currently requires exactly one outer profile without holes",
sketch_id=sketch_id,
))
contract_selectors = _contract_selectors(node, contract)
contract_selector_ids = {id(selector) for selector in contract_selectors}
for selector in _mappings(params):
if selector.get("output_role") is not None:
if selector.get("output_role") is not None and id(selector) not in contract_selector_ids:
blockers.append(self._blocker(
node.feature_id,
"unsupported_output_role_selector_context",
"Feature output role selectors are only supported in feature.selectors",
"Feature output role selector is outside the operation contract slot",
))
for selector_index, selector in enumerate(node.selectors):
for selector_index, selector in enumerate(contract_selectors):
if selector.get("output_role") is None:
continue
required.append("selector:feature_output_role")
if contract is None or contract.get("selector_slot") != "feature.selectors" or contract.get("selector_token_kind") != "face":
if contract is None or not contract.get("selector_slot") or contract.get("selector_token_kind") != "face":
blockers.append(self._blocker(
node.feature_id,
"unsupported_output_role_selector",