Skip to content

Commit 99b40dd

Browse files
authored
Integrate V6 typed RigProgram, CanonicalRig V2 and Skin V2 contracts (#363)
Mainline migration, unchanged canonical source blobs, 13 tests and ten green PR checks. No trained model, runtime execution, source admission or product release authority.
1 parent 369f739 commit 99b40dd

10 files changed

Lines changed: 1672 additions & 0 deletions
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: v6-main-contract-integration-v1
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'compiler/realsas_compiler_core/rig_program_ir_v1.py'
7+
- 'compiler/realsas_compiler_core/rig_constraint_schema_v1.py'
8+
- 'compiler/realsas_compiler_core/skin_code_ir_v1.py'
9+
- 'compiler/realsas_compiler_core/canonical_rig_ir_v2.py'
10+
- 'compiler/realsas_compiler_core/canonical_skin_ir_v2.py'
11+
- 'tests/compiler/test_control_ready_rig_v2.py'
12+
- 'tests/compiler/test_rig_program_causal_linear_v1.py'
13+
- 'tests/compiler/test_v6_typed_rig_skin_main_integration_v1.py'
14+
- '.github/workflows/v6_main_contract_integration_v1.yml'
15+
workflow_dispatch:
16+
17+
permissions:
18+
contents: read
19+
20+
concurrency:
21+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
22+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
23+
24+
jobs:
25+
typed-canonical-contract-courts:
26+
runs-on: ubuntu-latest
27+
timeout-minutes: 20
28+
steps:
29+
- uses: actions/checkout@v4
30+
- uses: actions/setup-python@v5
31+
with:
32+
python-version: '3.11'
33+
- name: Install deterministic compiler testing requirements
34+
run: python -m pip install --no-input --progress-bar off -r requirements/mainline-ci.txt
35+
- name: Compile imported contracts
36+
run: |
37+
python -m py_compile \
38+
compiler/realsas_compiler_core/rig_program_ir_v1.py \
39+
compiler/realsas_compiler_core/rig_constraint_schema_v1.py \
40+
compiler/realsas_compiler_core/skin_code_ir_v1.py \
41+
compiler/realsas_compiler_core/canonical_rig_ir_v2.py \
42+
compiler/realsas_compiler_core/canonical_skin_ir_v2.py
43+
- name: Independently verify existing V6 and main integration regressions
44+
run: |
45+
python -m pytest -q \
46+
tests/compiler/test_control_ready_rig_v2.py \
47+
tests/compiler/test_rig_program_causal_linear_v1.py \
48+
tests/compiler/test_v6_typed_rig_skin_main_integration_v1.py
49+
- name: Typed contracts do not mint product or training authority
50+
run: |
51+
python - <<'PY'
52+
from compiler.realsas_compiler_core.rig_program_ir_v1 import RigProgramProposalIR
53+
from compiler.realsas_compiler_core.canonical_skin_ir_v2 import CanonicalSkinIRV2
54+
from compiler.realsas_compiler_core.rig_constraint_schema_v1 import RIG_CONSTRAINT_OPERATOR_IDS_V1
55+
assert RigProgramProposalIR.__module__.endswith('rig_program_ir_v1')
56+
assert CanonicalSkinIRV2.__module__.endswith('canonical_skin_ir_v2')
57+
assert len(RIG_CONSTRAINT_OPERATOR_IDS_V1) == 5
58+
print('PASS_V6_TYPED_CONTRACTS_NO_MODEL_RELEASE_NO_RUNTIME_EXECUTOR')
59+
PY

‎compiler/realsas_compiler_core/canonical_rig_ir_v2.py‎

Lines changed: 333 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
from __future__ import annotations
2+
3+
"""Canonical Skin v2 for control-ready rigs.
4+
5+
Skin authority binds Mesh + Rig deform-structure identity, not the full animator
6+
control program. A controller-only edit therefore does not invalidate weights;
7+
rest/deform structure changes still do. Learned RealSaS skin codes remain proposal
8+
evidence and are decoded before this Compiler boundary by the admitted MIRA codec.
9+
"""
10+
11+
from dataclasses import asdict, dataclass, field, replace
12+
import math
13+
from typing import Any, Mapping
14+
15+
from .canonical_mesh_ir_v1 import CanonicalMeshIR, canonical_mesh_lineage_hash_v1
16+
from .canonical_rig_ir_v2 import CanonicalRigIRV2, canonical_rig_lineage_hash_v2
17+
from .carrier_skin_v1 import QualifiedCarrierSkinIR
18+
from .hashing import content_sha256
19+
from .types import QualificationError
20+
21+
Json = dict[str, Any]
22+
23+
24+
@dataclass(frozen=True)
25+
class CanonicalSkinRowIRV2:
26+
canonical_mesh_vertex_id: str
27+
influences: tuple[tuple[str, float], ...]
28+
source_carrier_vertex_id: str
29+
metadata: Json = field(default_factory=dict)
30+
31+
32+
@dataclass(frozen=True)
33+
class CanonicalSkinIRV2:
34+
rows: tuple[CanonicalSkinRowIRV2, ...]
35+
mesh_lineage_hash: str
36+
deform_structure_hash: str
37+
mesh_carrier_evidence_hash: str
38+
mesh_carrier_topology_hash: str
39+
mesh_carrier_geometry_hash: str
40+
carrier_skin_qualification_hash: str
41+
skin_code_proposal_hash: str
42+
skin_codec_architecture_id: str
43+
skin_codec_checkpoint_hash: str
44+
skin_lineage_hash: str
45+
schema_version: str = "RealSaS.CanonicalSkinIR.v2"
46+
metadata: Json = field(default_factory=dict)
47+
48+
def to_dict(self) -> dict:
49+
return asdict(self)
50+
51+
52+
def canonical_skin_lineage_hash_v2(value: CanonicalSkinIRV2) -> str:
53+
payload = value.to_dict()
54+
payload.pop("skin_lineage_hash", None)
55+
return content_sha256(payload)
56+
57+
58+
def _qualified_skin_hash(value: QualifiedCarrierSkinIR) -> str:
59+
return content_sha256({
60+
"carrier_evidence_hash": value.carrier_evidence_hash,
61+
"carrier_topology_hash": value.carrier_topology_hash,
62+
"carrier_geometry_hash": value.carrier_geometry_hash,
63+
"skeleton_binding_hash": value.skeleton_binding_hash,
64+
"rows": [row.to_dict() for row in value.rows],
65+
"qualification_report": value.qualification_report,
66+
"metadata": value.metadata,
67+
})
68+
69+
70+
def mint_canonical_skin_v2(
71+
mesh: CanonicalMeshIR,
72+
rig: CanonicalRigIRV2,
73+
*,
74+
qualified_skin: QualifiedCarrierSkinIR,
75+
skin_code_proposal_hash: str,
76+
skin_codec_architecture_id: str,
77+
skin_codec_checkpoint_hash: str,
78+
) -> CanonicalSkinIRV2:
79+
if mesh.mesh_lineage_hash != canonical_mesh_lineage_hash_v1(mesh):
80+
raise QualificationError("CANONICAL_SKIN_V2_MESH_LINEAGE_DRIFT")
81+
if mesh.metadata.get("authority") != "COMPILER_CANONICAL_MESH":
82+
raise QualificationError("CANONICAL_SKIN_V2_MESH_AUTHORITY_DRIFT")
83+
if rig.rig_lineage_hash != canonical_rig_lineage_hash_v2(rig):
84+
raise QualificationError("CANONICAL_SKIN_V2_RIG_LINEAGE_DRIFT")
85+
if rig.metadata.get("authority") != "COMPILER_CANONICAL_RIG":
86+
raise QualificationError("CANONICAL_SKIN_V2_RIG_AUTHORITY_DRIFT")
87+
if rig.mesh_lineage_hash != mesh.mesh_lineage_hash:
88+
raise QualificationError("CANONICAL_SKIN_V2_RIG_MESH_PARENT_DRIFT")
89+
90+
qualified_hash = _qualified_skin_hash(qualified_skin)
91+
if qualified_skin.skin_lineage_hash != qualified_hash:
92+
raise QualificationError("CANONICAL_SKIN_V2_QUALIFIED_HASH_DRIFT")
93+
if qualified_skin.carrier_evidence_hash != mesh.carrier_evidence_hash:
94+
raise QualificationError("CANONICAL_SKIN_V2_CARRIER_EVIDENCE_DRIFT")
95+
if qualified_skin.carrier_topology_hash != mesh.carrier_topology_hash:
96+
raise QualificationError("CANONICAL_SKIN_V2_CARRIER_TOPOLOGY_DRIFT")
97+
if qualified_skin.carrier_geometry_hash != mesh.carrier_geometry_hash:
98+
raise QualificationError("CANONICAL_SKIN_V2_CARRIER_GEOMETRY_DRIFT")
99+
if qualified_skin.skeleton_binding_hash != rig.deform_structure_hash:
100+
raise QualificationError("CANONICAL_SKIN_V2_DEFORM_STRUCTURE_BINDING_DRIFT")
101+
report = dict(qualified_skin.qualification_report or {})
102+
if report.get("status") != "PASS_DIRECT_CARRIER_SKIN":
103+
raise QualificationError("CANONICAL_SKIN_V2_QUALIFICATION_NOT_PASS")
104+
105+
code_hash = str(skin_code_proposal_hash).strip()
106+
codec_id = str(skin_codec_architecture_id).strip()
107+
codec_hash = str(skin_codec_checkpoint_hash).strip()
108+
if len(code_hash) < 8 or not codec_id or len(codec_hash) < 8:
109+
raise QualificationError("CANONICAL_SKIN_V2_CODEC_PROVENANCE_REQUIRED")
110+
111+
mesh_by_source = {str(v.source_candidate_vertex_id): v for v in mesh.vertices}
112+
joint_ids = {str(j.canonical_joint_id) for j in rig.joints}
113+
if len(mesh_by_source) != len(mesh.vertices) or not joint_ids:
114+
raise QualificationError("CANONICAL_SKIN_V2_PARENT_DOMAIN_INVALID")
115+
rows: list[CanonicalSkinRowIRV2] = []
116+
seen: set[str] = set()
117+
for row in qualified_skin.rows:
118+
source_id = str(row.carrier_vertex_id)
119+
vertex = mesh_by_source.get(source_id)
120+
if vertex is None:
121+
raise QualificationError("CANONICAL_SKIN_V2_CARRIER_VERTEX_UNKNOWN")
122+
vid = str(vertex.canonical_mesh_vertex_id)
123+
if vid in seen:
124+
raise QualificationError("CANONICAL_SKIN_V2_DUPLICATE_VERTEX")
125+
seen.add(vid)
126+
influences = tuple((str(jid), float(w)) for jid, w in row.influences)
127+
if not influences or any(jid not in joint_ids for jid, _ in influences):
128+
raise QualificationError("CANONICAL_SKIN_V2_JOINT_UNKNOWN")
129+
if any((not math.isfinite(w)) or w < 0.0 for _, w in influences):
130+
raise QualificationError("CANONICAL_SKIN_V2_WEIGHT_INVALID")
131+
if abs(sum(w for _, w in influences) - 1.0) > 1e-6:
132+
raise QualificationError("CANONICAL_SKIN_V2_SIMPLEX_DRIFT")
133+
rows.append(CanonicalSkinRowIRV2(
134+
canonical_mesh_vertex_id=vid,
135+
influences=influences,
136+
source_carrier_vertex_id=source_id,
137+
metadata={"decoded_from_discrete_skin_representation": True},
138+
))
139+
if seen != {str(v.canonical_mesh_vertex_id) for v in mesh.vertices}:
140+
raise QualificationError("CANONICAL_SKIN_V2_MESH_COVERAGE_DRIFT")
141+
142+
value = CanonicalSkinIRV2(
143+
rows=tuple(rows),
144+
mesh_lineage_hash=mesh.mesh_lineage_hash,
145+
deform_structure_hash=rig.deform_structure_hash,
146+
mesh_carrier_evidence_hash=mesh.carrier_evidence_hash,
147+
mesh_carrier_topology_hash=mesh.carrier_topology_hash,
148+
mesh_carrier_geometry_hash=mesh.carrier_geometry_hash,
149+
carrier_skin_qualification_hash=qualified_hash,
150+
skin_code_proposal_hash=code_hash,
151+
skin_codec_architecture_id=codec_id,
152+
skin_codec_checkpoint_hash=codec_hash,
153+
skin_lineage_hash="",
154+
metadata={
155+
"authority": "COMPILER_CANONICAL_SKIN",
156+
"canonical_parents": ["CANONICAL_MESH", "CANONICAL_RIG_DEFORM_STRUCTURE"],
157+
"full_rig_lineage_is_not_skin_parent": True,
158+
"control_program_mutation_invalidates_skin": False,
159+
"deform_structure_mutation_invalidates_skin": True,
160+
"mesh_mutation_invalidates_skin": True,
161+
"skin_code_decode_is_model_owned": True,
162+
"compiler_code_search_or_repair_performed": False,
163+
},
164+
)
165+
return replace(value, skin_lineage_hash=canonical_skin_lineage_hash_v2(value))
166+
167+
168+
def canonical_skin_from_dict_v2(payload: Mapping[str, Any]) -> CanonicalSkinIRV2:
169+
schema = str(payload.get("schema_version") or payload.get("schema") or "")
170+
if schema != "RealSaS.CanonicalSkinIR.v2":
171+
raise QualificationError("CANONICAL_SKIN_V2_SCHEMA_DRIFT")
172+
rows = tuple(CanonicalSkinRowIRV2(
173+
canonical_mesh_vertex_id=str(x["canonical_mesh_vertex_id"]),
174+
influences=tuple((str(j), float(w)) for j, w in x.get("influences") or ()),
175+
source_carrier_vertex_id=str(x["source_carrier_vertex_id"]),
176+
metadata=dict(x.get("metadata") or {}),
177+
) for x in payload.get("rows") or ())
178+
value = CanonicalSkinIRV2(
179+
rows=rows,
180+
mesh_lineage_hash=str(payload["mesh_lineage_hash"]),
181+
deform_structure_hash=str(payload["deform_structure_hash"]),
182+
mesh_carrier_evidence_hash=str(payload["mesh_carrier_evidence_hash"]),
183+
mesh_carrier_topology_hash=str(payload["mesh_carrier_topology_hash"]),
184+
mesh_carrier_geometry_hash=str(payload["mesh_carrier_geometry_hash"]),
185+
carrier_skin_qualification_hash=str(payload["carrier_skin_qualification_hash"]),
186+
skin_code_proposal_hash=str(payload["skin_code_proposal_hash"]),
187+
skin_codec_architecture_id=str(payload["skin_codec_architecture_id"]),
188+
skin_codec_checkpoint_hash=str(payload["skin_codec_checkpoint_hash"]),
189+
skin_lineage_hash=str(payload["skin_lineage_hash"]),
190+
schema_version=schema,
191+
metadata=dict(payload.get("metadata") or {}),
192+
)
193+
if value.skin_lineage_hash != canonical_skin_lineage_hash_v2(value):
194+
raise QualificationError("CANONICAL_SKIN_V2_LINEAGE_HASH_DRIFT")
195+
return value
196+
197+
198+
__all__ = [
199+
"CanonicalSkinIRV2", "CanonicalSkinRowIRV2", "canonical_skin_from_dict_v2",
200+
"canonical_skin_lineage_hash_v2", "mint_canonical_skin_v2",
201+
]
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from __future__ import annotations
2+
3+
"""Typed executable constraint vocabulary shared by AXIS, Compiler and Mechanics.
4+
5+
An operator is admitted only when the runtime has enough canonical information to
6+
execute it deterministically. Unsupported production-rig concepts (for example a
7+
PATH constraint without a canonical path/curve object) are deliberately absent
8+
rather than represented by a name with no semantics.
9+
"""
10+
11+
from dataclasses import dataclass
12+
from typing import Mapping, Any
13+
import math
14+
15+
from .types import QualificationError
16+
17+
18+
@dataclass(frozen=True)
19+
class RigConstraintOperatorSchemaV1:
20+
operator_id: str
21+
min_control_inputs: int
22+
max_control_inputs: int
23+
min_joint_outputs: int
24+
max_joint_outputs: int
25+
chain_requirement: str # REQUIRED | OPTIONAL | FORBIDDEN
26+
parameter_names: tuple[str, ...]
27+
28+
29+
RIG_CONSTRAINT_OPERATOR_SCHEMAS_V1: tuple[RigConstraintOperatorSchemaV1, ...] = (
30+
RigConstraintOperatorSchemaV1(
31+
"IK", 1, 2, 0, 256, "REQUIRED",
32+
("p0", "p1", "p2", "p3"), # weight, pole_weight, max_stretch, softness
33+
),
34+
RigConstraintOperatorSchemaV1(
35+
"AIM", 1, 1, 1, 256, "FORBIDDEN",
36+
("p0", "p1", "p2", "p3"), # weight, roll, reserved, reserved
37+
),
38+
RigConstraintOperatorSchemaV1(
39+
"FOLLOW", 1, 1, 1, 256, "OPTIONAL",
40+
("p0", "p1", "p2", "p3"), # translation/rotation blend controls
41+
),
42+
RigConstraintOperatorSchemaV1(
43+
"COPY_TRANSFORM", 1, 1, 1, 256, "FORBIDDEN",
44+
("p0", "p1", "p2", "p3"),
45+
),
46+
RigConstraintOperatorSchemaV1(
47+
"STRETCH", 1, 1, 0, 256, "REQUIRED",
48+
("p0", "p1", "p2", "p3"), # weight, max_ratio, reserved, reserved
49+
),
50+
)
51+
52+
RIG_CONSTRAINT_OPERATOR_IDS_V1 = tuple(x.operator_id for x in RIG_CONSTRAINT_OPERATOR_SCHEMAS_V1)
53+
_SCHEMA_BY_ID = {x.operator_id: x for x in RIG_CONSTRAINT_OPERATOR_SCHEMAS_V1}
54+
55+
56+
def rig_constraint_operator_schema_v1(operator_id: str) -> RigConstraintOperatorSchemaV1:
57+
try:
58+
return _SCHEMA_BY_ID[str(operator_id)]
59+
except KeyError as exc:
60+
raise QualificationError(f"RIG_CONSTRAINT_OPERATOR_UNSUPPORTED:{operator_id}") from exc
61+
62+
63+
def validate_rig_constraint_operator_v1(
64+
*,
65+
operator_id: str,
66+
input_control_count: int,
67+
output_joint_count: int,
68+
has_chain: bool,
69+
parameters: Mapping[str, Any],
70+
) -> None:
71+
schema = rig_constraint_operator_schema_v1(operator_id)
72+
if not schema.min_control_inputs <= int(input_control_count) <= schema.max_control_inputs:
73+
raise QualificationError(f"RIG_CONSTRAINT_CONTROL_ARITY:{schema.operator_id}")
74+
if not schema.min_joint_outputs <= int(output_joint_count) <= schema.max_joint_outputs:
75+
raise QualificationError(f"RIG_CONSTRAINT_OUTPUT_ARITY:{schema.operator_id}")
76+
if schema.chain_requirement == "REQUIRED" and not has_chain:
77+
raise QualificationError(f"RIG_CONSTRAINT_CHAIN_REQUIRED:{schema.operator_id}")
78+
if schema.chain_requirement == "FORBIDDEN" and has_chain:
79+
raise QualificationError(f"RIG_CONSTRAINT_CHAIN_FORBIDDEN:{schema.operator_id}")
80+
keys = set(map(str, parameters))
81+
allowed = set(schema.parameter_names)
82+
if not keys.issubset(allowed):
83+
raise QualificationError(f"RIG_CONSTRAINT_PARAMETER_UNSUPPORTED:{schema.operator_id}")
84+
for key, value in parameters.items():
85+
try:
86+
scalar = float(value)
87+
except (TypeError, ValueError) as exc:
88+
raise QualificationError(f"RIG_CONSTRAINT_PARAMETER_NONNUMERIC:{schema.operator_id}:{key}") from exc
89+
if not math.isfinite(scalar):
90+
raise QualificationError(f"RIG_CONSTRAINT_PARAMETER_NONFINITE:{schema.operator_id}:{key}")
91+
92+
93+
__all__ = [
94+
"RIG_CONSTRAINT_OPERATOR_IDS_V1",
95+
"RIG_CONSTRAINT_OPERATOR_SCHEMAS_V1",
96+
"RigConstraintOperatorSchemaV1",
97+
"rig_constraint_operator_schema_v1",
98+
"validate_rig_constraint_operator_v1",
99+
]

0 commit comments

Comments
 (0)