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
@@ -1,8 +1,7 @@
"""Versioned runtime operation contracts and dynamic fragment schemas."""
"""Versioned runtime operation contracts for the Authoring compiler."""
from __future__ import annotations
from copy import deepcopy
from hashlib import sha256
import json
from typing import Any
@@ -15,25 +14,6 @@ class OperationContractError(ValueError):
pass
SEMANTIC_PREFLIGHT_NAMES = frozenset({
"sketch_workplane",
"profile_non_self_intersecting",
"host_face_exists",
"hole_positions_on_host_plane",
"cut_exit_distance",
"requires_active_solid",
"revolve_axis_on_sketch",
"reference_plane_nonzero_normal",
"reference_axis_nonzero_direction",
"selected_edges_exist",
"source_features_exist",
"mirror_plane_exists",
"loft_profiles_exist",
"loft_profiles_closed",
"loft_profiles_single_region",
})
def canonical_hash(value: dict[str, Any]) -> str:
return sha256(json.dumps(value, ensure_ascii=True, sort_keys=True, separators=(",", ":")).encode("utf-8")).hexdigest()
@@ -58,10 +38,16 @@ def _is_closed(schema: Any) -> bool:
return True
def is_authoring_schema_closed(schema: Any) -> bool:
"""Whether an operation can safely be exposed in the Authoring whitelist."""
return _is_closed(schema)
def validate_operation_contract(contract: dict[str, Any]) -> None:
required = {
"atomic_id", "contract_version", "fragment_shape", "author_params_schema", "selector_policy",
"server_injected_paths", "reference_policy", "semantic_preflight", "candidate_verifiers",
"runtime_capability",
}
if not required.issubset(contract) or set(contract) - required - {"contract_hash", "registry_revision"}:
raise OperationContractError("Operation contract has unknown or missing fields")
@@ -111,113 +97,43 @@ def validate_operation_contract(contract: dict[str, Any]) -> None:
if reference["mode"] == "snapshot_bound":
if set(reference) != {"mode", "slot", "token_kind", "min_items", "max_items", "snapshot_bound"}:
raise OperationContractError("Snapshot-bound reference policy is invalid")
if not isinstance(reference["slot"], str) or not reference["slot"].startswith("params.") or reference["token_kind"] != "feature" or not isinstance(reference["min_items"], int) or not isinstance(reference["max_items"], int) or not 1 <= reference["min_items"] <= reference["max_items"] <= 64 or reference["snapshot_bound"] is not True:
raise OperationContractError("Snapshot-bound reference policy has invalid bounds")
reference_name = reference["slot"].removeprefix("params.")
properties = params.get("properties") if isinstance(params.get("properties"), dict) else {}
reference_schema = properties.get(reference_name)
required_params = params.get("required") if isinstance(params.get("required"), list) else []
slot = reference["slot"]
if (
not isinstance(reference_schema, dict)
or reference_schema.get("type") != "array"
or not isinstance(reference_schema.get("items"), dict)
or reference_name not in required_params
not isinstance(slot, str)
or (slot != "feature.selectors" and not slot.startswith("params."))
or reference["token_kind"] not in {"face", "edge", "plane", "axis", "body", "feature"}
or not isinstance(reference["min_items"], int)
or not isinstance(reference["max_items"], int)
or not 0 <= reference["min_items"] <= reference["max_items"] <= 64
or reference["snapshot_bound"] is not True
):
raise OperationContractError("Snapshot-bound reference slot must be a required author array")
raise OperationContractError("Snapshot-bound reference policy has invalid bounds")
if slot == "feature.selectors":
if shape["selector_tokens"] != "required" or selector["token_kind"] != reference["token_kind"]:
raise OperationContractError("Feature selector reference policy disagrees with selector policy")
else:
reference_name = slot.removeprefix("params.")
properties = params.get("properties") if isinstance(params.get("properties"), dict) else {}
reference_schema = properties.get(reference_name)
if not isinstance(reference_schema, dict) or reference_schema.get("type") not in {"array", "string"}:
raise OperationContractError("Snapshot-bound reference slot is absent from author params schema")
if reference_schema.get("type") == "string" and reference["max_items"] > 1:
raise OperationContractError("Scalar snapshot-bound reference must allow at most one item")
if not isinstance(contract["semantic_preflight"], list) or not all(isinstance(item, str) and item for item in contract["semantic_preflight"]):
raise OperationContractError("Operation semantic preflight is invalid")
if len(set(contract["semantic_preflight"])) != len(contract["semantic_preflight"]) or set(contract["semantic_preflight"]) - SEMANTIC_PREFLIGHT_NAMES:
raise OperationContractError("Operation semantic preflight names are unknown or duplicated")
if len(set(contract["semantic_preflight"])) != len(contract["semantic_preflight"]):
raise OperationContractError("Operation semantic preflight names are duplicated")
if not isinstance(contract["candidate_verifiers"], list) or not all(isinstance(item, str) and item for item in contract["candidate_verifiers"]):
raise OperationContractError("Operation candidate_verifiers are invalid")
if len(set(contract["candidate_verifiers"])) != len(contract["candidate_verifiers"]):
raise OperationContractError("Operation candidate verifiers are duplicated")
def fragment_schema(contract: dict[str, Any], *, selector_tokens: list[str], reference_tokens: list[str] | None = None, root_xy_datum: bool = False) -> dict[str, Any]:
"""Build the one-operation schema exposed for one pending action."""
validate_operation_contract(contract)
shape = contract["fragment_shape"]
params = deepcopy(contract["author_params_schema"])
reference = contract["reference_policy"]
if reference["mode"] == "snapshot_bound":
slot = str(reference["slot"]).removeprefix("params.")
items = params.get("properties", {}).get(slot, {}).get("items") if isinstance(params.get("properties"), dict) else None
if not isinstance(items, dict):
raise OperationContractError("Snapshot-bound reference slot is absent from author params schema")
items.clear()
items.update({"enum": reference_tokens or []})
feature_properties: dict[str, Any] = {
"atomic_id": {"const": contract["atomic_id"]},
"params": params,
runtime_capability = contract["runtime_capability"]
required_capability_flags = {
"body_mutating", "requires_active_body", "replayable", "requires_selector", "open_profile_ok",
}
feature_required = ["atomic_id", "params"]
if shape["selector_tokens"] == "required":
policy = contract["selector_policy"]
feature_properties["selector_tokens"] = {
"type": "array", "items": {"enum": selector_tokens}, "minItems": policy["min_items"],
"maxItems": policy["max_items"], "uniqueItems": True,
"description": (
"Required author input. Copy the opaque selector token returned by the current topology "
"snapshot here; do not omit it and do not put a host face in params. The server resolves this "
"token into the host selector after schema validation."
),
}
feature_required.append("selector_tokens")
feature = {
"type": "object",
"description": (
"One atomic feature. selector_tokens, when present, is an author-supplied topology token array "
"rather than a server-filled params field."
),
"properties": feature_properties,
"required": feature_required,
"additionalProperties": False,
}
properties: dict[str, Any] = {"feature": feature}
required = ["feature"]
if shape["sketch"] == "required":
properties["sketch"] = _sketch_schema(root_xy_datum=root_xy_datum and contract["atomic_id"] in {"extrude_add_blind", "extrude_add_two_sided"})
required.insert(0, "sketch")
schema = {"$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": properties, "required": required, "additionalProperties": False}
Draft202012Validator.check_schema(schema)
return schema
def validate_fragment(contract: dict[str, Any], fragment: Any, *, selector_tokens: list[str], reference_tokens: list[str] | None = None, root_xy_datum: bool = False) -> list[dict[str, str]]:
schema = fragment_schema(contract, selector_tokens=selector_tokens, reference_tokens=reference_tokens, root_xy_datum=root_xy_datum)
return [
{"path": "/" + "/".join(str(part) for part in error.absolute_path), "message": error.message}
for error in sorted(Draft202012Validator(schema).iter_errors(fragment), key=lambda item: (list(item.absolute_path), item.message))
]
def _point(size: int) -> dict[str, Any]:
return {"type": "array", "items": {"type": "number"}, "minItems": size, "maxItems": size}
def _sketch_schema(*, root_xy_datum: bool = False) -> dict[str, Any]:
point2 = _point(2)
point3 = _point(3)
workplane = {
"type": "object",
"description": "origin_mm is the world position of sketch local (0,0); profile coordinates are local to this plane. normal is positive extrusion direction and x_dir is local +X in world coordinates.",
"properties": {"origin_mm": point3, "x_dir": deepcopy(point3), "normal": deepcopy(point3)},
"required": ["origin_mm", "x_dir", "normal"],
"additionalProperties": False,
}
if root_xy_datum:
workplane["description"] += " Root extrusion uses fixed world XY datum: origin X/Y are 0, normal is +Z, x_dir is +X. Only origin Z is task-defined."
workplane["properties"] = {
"origin_mm": {"type": "array", "prefixItems": [{"const": 0}, {"const": 0}, {"type": "number"}], "items": False, "minItems": 3, "maxItems": 3},
"x_dir": {"const": [1, 0, 0]},
"normal": {"const": [0, 0, 1]},
}
profile = {
"oneOf": [
{"type": "object", "properties": {"type": {"const": "circle"}, "center": deepcopy(point2), "radius_mm": {"type": "number", "exclusiveMinimum": 0}}, "required": ["type", "radius_mm"], "additionalProperties": False},
{"type": "object", "properties": {"type": {"const": "polygon"}, "vertices": {"type": "array", "minItems": 3, "items": deepcopy(point2)}}, "required": ["type", "vertices"], "additionalProperties": False},
{"type": "object", "properties": {"type": {"const": "analytic_contours"}, "contours": {"type": "array", "minItems": 1, "maxItems": 8, "items": {"type": "object", "properties": {"role": {"enum": ["outer", "inner"]}, "closed": {"const": True}, "segments": {"type": "array", "minItems": 1, "items": {"oneOf": [{"type": "object", "properties": {"type": {"const": "line"}, "start": deepcopy(point2), "end": deepcopy(point2)}, "required": ["type", "start", "end"], "additionalProperties": False}, {"type": "object", "properties": {"type": {"const": "circle"}, "center": deepcopy(point2), "radius_mm": {"type": "number", "exclusiveMinimum": 0}}, "required": ["type", "center", "radius_mm"], "additionalProperties": False}, {"type": "object", "properties": {"type": {"const": "arc"}, "start": deepcopy(point2), "end": deepcopy(point2), "center": deepcopy(point2), "radius_mm": {"type": "number", "exclusiveMinimum": 0}, "clockwise": {"type": "boolean"}}, "required": ["type", "start", "end", "center", "radius_mm"], "additionalProperties": False}]}}}, "required": ["role", "closed", "segments"], "additionalProperties": False}}}, "required": ["type", "contours"], "additionalProperties": False},
]
}
return {"type": "object", "properties": {"workplane": workplane, "profile": profile}, "required": ["workplane", "profile"], "additionalProperties": False}
if (
not isinstance(runtime_capability, dict)
or set(runtime_capability) != required_capability_flags
or not all(isinstance(value, bool) for value in runtime_capability.values())
):
raise OperationContractError("Operation runtime capability is invalid")