feat: close builder mutation and roundtrip evidence gaps
This commit is contained in:
@@ -25,12 +25,22 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
|
"loft",
|
||||||
|
"pipe",
|
||||||
"revolution",
|
"revolution",
|
||||||
"groove",
|
"groove",
|
||||||
"fillet",
|
"fillet",
|
||||||
"chamfer"
|
"chamfer",
|
||||||
|
"hole",
|
||||||
|
"draft",
|
||||||
|
"thickness",
|
||||||
|
"linear-pattern",
|
||||||
|
"polar-pattern",
|
||||||
|
"mirrored",
|
||||||
|
"multi-transform"
|
||||||
],
|
],
|
||||||
"transport": "step-text"
|
"transport": "step-text"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,14 +25,22 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
|
"loft",
|
||||||
|
"pipe",
|
||||||
"revolution",
|
"revolution",
|
||||||
"groove",
|
"groove",
|
||||||
"fillet",
|
"fillet",
|
||||||
"chamfer",
|
"chamfer",
|
||||||
"hole",
|
"hole",
|
||||||
"draft"
|
"draft",
|
||||||
|
"thickness",
|
||||||
|
"linear-pattern",
|
||||||
|
"polar-pattern",
|
||||||
|
"mirrored",
|
||||||
|
"multi-transform"
|
||||||
],
|
],
|
||||||
"transport": "step-text"
|
"transport": "step-text"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,11 +25,22 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
|
"loft",
|
||||||
|
"pipe",
|
||||||
"revolution",
|
"revolution",
|
||||||
"groove",
|
"groove",
|
||||||
"fillet"
|
"fillet",
|
||||||
|
"chamfer",
|
||||||
|
"hole",
|
||||||
|
"draft",
|
||||||
|
"thickness",
|
||||||
|
"linear-pattern",
|
||||||
|
"polar-pattern",
|
||||||
|
"mirrored",
|
||||||
|
"multi-transform"
|
||||||
],
|
],
|
||||||
"transport": "step-text"
|
"transport": "step-text"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
"loft",
|
"loft",
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
|
"loft",
|
||||||
|
"pipe",
|
||||||
"revolution",
|
"revolution",
|
||||||
"groove",
|
"groove",
|
||||||
"fillet",
|
"fillet",
|
||||||
@@ -33,7 +36,10 @@
|
|||||||
"hole",
|
"hole",
|
||||||
"draft",
|
"draft",
|
||||||
"thickness",
|
"thickness",
|
||||||
"linear-pattern"
|
"linear-pattern",
|
||||||
|
"polar-pattern",
|
||||||
|
"mirrored",
|
||||||
|
"multi-transform"
|
||||||
],
|
],
|
||||||
"transport": "step-text"
|
"transport": "step-text"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,9 +24,11 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
"loft",
|
"loft",
|
||||||
|
"pipe",
|
||||||
"revolution",
|
"revolution",
|
||||||
"groove",
|
"groove",
|
||||||
"fillet",
|
"fillet",
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
|
"loft",
|
||||||
|
"pipe",
|
||||||
"revolution",
|
"revolution",
|
||||||
"groove",
|
"groove",
|
||||||
"fillet",
|
"fillet",
|
||||||
@@ -35,7 +38,8 @@
|
|||||||
"thickness",
|
"thickness",
|
||||||
"linear-pattern",
|
"linear-pattern",
|
||||||
"polar-pattern",
|
"polar-pattern",
|
||||||
"mirrored"
|
"mirrored",
|
||||||
|
"multi-transform"
|
||||||
],
|
],
|
||||||
"transport": "step-text"
|
"transport": "step-text"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
"loft",
|
"loft",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
"loft",
|
"loft",
|
||||||
@@ -43,10 +44,10 @@
|
|||||||
"transport": "step-text"
|
"transport": "step-text"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"recordCount": 28,
|
"recordCount": 18,
|
||||||
"relations": {
|
"relations": {
|
||||||
"modified": 1,
|
"modified": 1,
|
||||||
"generated": 27,
|
"generated": 17,
|
||||||
"deleted": 0
|
"deleted": 0
|
||||||
},
|
},
|
||||||
"sourceObjects": [
|
"sourceObjects": [
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
|
"loft",
|
||||||
|
"pipe",
|
||||||
"revolution",
|
"revolution",
|
||||||
"groove",
|
"groove",
|
||||||
"fillet",
|
"fillet",
|
||||||
@@ -34,7 +37,9 @@
|
|||||||
"draft",
|
"draft",
|
||||||
"thickness",
|
"thickness",
|
||||||
"linear-pattern",
|
"linear-pattern",
|
||||||
"polar-pattern"
|
"polar-pattern",
|
||||||
|
"mirrored",
|
||||||
|
"multi-transform"
|
||||||
],
|
],
|
||||||
"transport": "step-text"
|
"transport": "step-text"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,15 +25,22 @@
|
|||||||
"fuse",
|
"fuse",
|
||||||
"cut",
|
"cut",
|
||||||
"common",
|
"common",
|
||||||
|
"rotate",
|
||||||
"pad",
|
"pad",
|
||||||
"pocket",
|
"pocket",
|
||||||
|
"loft",
|
||||||
|
"pipe",
|
||||||
"revolution",
|
"revolution",
|
||||||
"groove",
|
"groove",
|
||||||
"fillet",
|
"fillet",
|
||||||
"chamfer",
|
"chamfer",
|
||||||
"hole",
|
"hole",
|
||||||
"draft",
|
"draft",
|
||||||
"thickness"
|
"thickness",
|
||||||
|
"linear-pattern",
|
||||||
|
"polar-pattern",
|
||||||
|
"mirrored",
|
||||||
|
"multi-transform"
|
||||||
],
|
],
|
||||||
"transport": "step-text"
|
"transport": "step-text"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -97,7 +97,7 @@
|
|||||||
"status": "explicit-runtime-contract",
|
"status": "explicit-runtime-contract",
|
||||||
"mappedNameRef": "optional provider evidence; final-shape-only stages are marked and cannot mint FreeCAD tokens",
|
"mappedNameRef": "optional provider evidence; final-shape-only stages are marked and cannot mint FreeCAD tokens",
|
||||||
"stringHasher": "optional opaque native table; validated and preserved losslessly",
|
"stringHasher": "optional opaque native table; validated and preserved losslessly",
|
||||||
"exactBlockers": ["private FreeCAD token algorithm", "missing native builder stage", "non-unique isomorphic source"]
|
"exactBlockers": ["browser FreeCAD private token callback ABI", "browser builder naming evidence transport", "non-unique isomorphic source"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserWorker": {
|
"browserWorker": {
|
||||||
@@ -124,13 +124,13 @@
|
|||||||
"verification": { "level": "experimental", "provider": "FreeCADCmd 1.1.1 native headless Part oracle", "operations": ["locked-source-commit", "reproducible-native-build", "declarative-golden-contract", "part-geometry-replay", "numeric-tolerance-comparison", "execution-plan-validation", "source-inventory-validation", "type-property-inventory-validation"] }
|
"verification": { "level": "experimental", "provider": "FreeCADCmd 1.1.1 native headless Part oracle", "operations": ["locked-source-commit", "reproducible-native-build", "declarative-golden-contract", "part-geometry-replay", "numeric-tolerance-comparison", "execution-plan-validation", "source-inventory-validation", "type-property-inventory-validation"] }
|
||||||
},
|
},
|
||||||
"systemExactEvaluation": {
|
"systemExactEvaluation": {
|
||||||
"evaluatedAt": "2026-08-09",
|
"evaluatedAt": "2026-08-10",
|
||||||
"exact": false,
|
"exact": false,
|
||||||
"featureExactCount": 0,
|
"featureExactCount": 0,
|
||||||
"plan": "config/freecad-web-exact-parity-plan.json",
|
"plan": "config/freecad-web-exact-parity-plan.json",
|
||||||
"promotionTask": "EX-REL-01",
|
"promotionTask": "EX-REL-01",
|
||||||
"taskStatus": { "completed": 1, "inProgress": 37, "pending": 14, "blocked": 0 },
|
"taskStatus": { "completed": 2, "inProgress": 36, "pending": 14, "blocked": 0 },
|
||||||
"blockers": ["private FreeCAD token algorithm", "missing native builder stage", "non-unique isomorphic source"]
|
"blockers": ["browser FreeCAD private token callback ABI", "browser builder naming evidence transport", "non-unique isomorphic source"]
|
||||||
},
|
},
|
||||||
"rules": [
|
"rules": [
|
||||||
"UI status does not imply geometry or file compatibility.",
|
"UI status does not imply geometry or file compatibility.",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
1203
config/freecad-core-parameter-mutation-oracle.json
Normal file
1203
config/freecad-core-parameter-mutation-oracle.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
|||||||
"freecad-web-freecad",
|
"freecad-web-freecad",
|
||||||
"web-freecad-web"
|
"web-freecad-web"
|
||||||
],
|
],
|
||||||
"scenarioCount": 22,
|
"scenarioCount": 23,
|
||||||
"scenarios": [
|
"scenarios": [
|
||||||
{
|
{
|
||||||
"id": "proxy-byte-preservation",
|
"id": "proxy-byte-preservation",
|
||||||
@@ -560,6 +560,68 @@
|
|||||||
"resavedShapeAvailable": true
|
"resavedShapeAvailable": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "part-cut-through-hole",
|
||||||
|
"direction": "web-freecad-web",
|
||||||
|
"stages": [
|
||||||
|
"web-model",
|
||||||
|
"web-write",
|
||||||
|
"freecad-open",
|
||||||
|
"freecad-recompute",
|
||||||
|
"freecad-resave",
|
||||||
|
"web-inspect"
|
||||||
|
],
|
||||||
|
"domains": [
|
||||||
|
"objectTree",
|
||||||
|
"properties",
|
||||||
|
"shape",
|
||||||
|
"resources"
|
||||||
|
],
|
||||||
|
"freecadVersion": "1.1.1",
|
||||||
|
"status": "pass",
|
||||||
|
"differences": [],
|
||||||
|
"evidence": {
|
||||||
|
"typeId": "Part::Cut",
|
||||||
|
"solidCount": 1,
|
||||||
|
"faceCount": 7,
|
||||||
|
"volume": 3717.256661176918,
|
||||||
|
"boundingBox": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"propertyCount": 3,
|
||||||
|
"properties": {
|
||||||
|
"Base": "Base",
|
||||||
|
"Refine": false,
|
||||||
|
"Tool": "HoleTool"
|
||||||
|
},
|
||||||
|
"toolPlacement": {
|
||||||
|
"position": {
|
||||||
|
"x": 10,
|
||||||
|
"y": 10,
|
||||||
|
"z": -1
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"axis": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 1
|
||||||
|
},
|
||||||
|
"angle": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"refine": false,
|
||||||
|
"resavedShapeAvailable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "part-sphere-trim",
|
"id": "part-sphere-trim",
|
||||||
"direction": "web-freecad-web",
|
"direction": "web-freecad-web",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -141,6 +141,108 @@
|
|||||||
"expected": "success",
|
"expected": "success",
|
||||||
"faces": 6,
|
"faces": 6,
|
||||||
"id": "part-extrusion-success",
|
"id": "part-extrusion-success",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 62,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "9d30d34ebc7b7c4d817dceb14aa8283acaef95ec72b06dcbbb29adbd075c2221",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 30
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
7
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 82,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
7
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "810f0b359958485b84d4404172ded10352418bf1877248604cfbe14262ecc4a5",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 42
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "Part::Extrusion",
|
||||||
|
"featureName": "Extrusion",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Dir",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 62,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "9d30d34ebc7b7c4d817dceb14aa8283acaef95ec72b06dcbbb29adbd075c2221",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 30
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"observed": "success",
|
"observed": "success",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"shapeNull": false,
|
"shapeNull": false,
|
||||||
@@ -161,6 +263,96 @@
|
|||||||
"expected": "success",
|
"expected": "success",
|
||||||
"faces": 4,
|
"faces": 4,
|
||||||
"id": "part-revolution-success",
|
"id": "part-revolution-success",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": 360,
|
||||||
|
"shape": {
|
||||||
|
"area": 150.79644737231007,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
4,
|
||||||
|
2,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-4,
|
||||||
|
0,
|
||||||
|
-4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "1006818e02e479865c719ba5a8b6a513e3595dc36cbb618b8ea8f44770a80eee",
|
||||||
|
"edges": 6,
|
||||||
|
"faces": 4,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 4,
|
||||||
|
"volume": 75.398223686155
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": false,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": 270,
|
||||||
|
"shape": {
|
||||||
|
"area": 121.09733552923257,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
4,
|
||||||
|
2,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-4,
|
||||||
|
0,
|
||||||
|
-4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "9426f11d00c01396b73f44bc342d021a3779b0ff9d5a81bc78529f80edb589cb",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 56.54866776461628
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "Part::Revolution",
|
||||||
|
"featureName": "Revolution",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Angle",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": 360,
|
||||||
|
"shape": {
|
||||||
|
"area": 150.79644737231007,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
4,
|
||||||
|
2,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-4,
|
||||||
|
0,
|
||||||
|
-4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "ec773a4c293bac1ffc7dfbb42ab648361eb9926779d8d79d00ba037fb01bbe19",
|
||||||
|
"edges": 6,
|
||||||
|
"faces": 4,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 4,
|
||||||
|
"volume": 75.398223686155
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"observed": "success",
|
"observed": "success",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"shapeNull": false,
|
"shapeNull": false,
|
||||||
@@ -181,6 +373,96 @@
|
|||||||
"expected": "success",
|
"expected": "success",
|
||||||
"faces": 6,
|
"faces": 6,
|
||||||
"id": "part-loft-success",
|
"id": "part-loft-success",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": false,
|
||||||
|
"shape": {
|
||||||
|
"area": 81.18823416311344,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2,
|
||||||
|
-2,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "efec0c6cf3b8907f16c071ffeed11238b8e5a9f8f60e40fad225eb418ff33f7b",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 46.666666666666664
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": false,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": true,
|
||||||
|
"shape": {
|
||||||
|
"area": 81.18823416311344,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2,
|
||||||
|
-2,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "9542e7469b051c053c1c425ffa5d246194661675e16ff0dcc046bce6b2527df1",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 46.666666666666664
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "Part::Loft",
|
||||||
|
"featureName": "Loft",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Ruled",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": false,
|
||||||
|
"shape": {
|
||||||
|
"area": 81.18823416311344,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2,
|
||||||
|
-2,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "bb0a25834e30e135551532aba7398c66e7de32e79ca07d4b3cd07268ace94ee5",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 46.666666666666664
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"observed": "success",
|
"observed": "success",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"shapeNull": false,
|
"shapeNull": false,
|
||||||
@@ -201,6 +483,111 @@
|
|||||||
"expected": "success",
|
"expected": "success",
|
||||||
"faces": 6,
|
"faces": 6,
|
||||||
"id": "part-sweep-success",
|
"id": "part-sweep-success",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "Section",
|
||||||
|
"typeId": "Part::Feature"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 56,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "5c1241164480ab824c8e107694158117e7d5854ca62985d1123a33853d6d5e58",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 23.999999999999996
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "EditedSection",
|
||||||
|
"typeId": "Part::Feature"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 40.5,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
0.75,
|
||||||
|
0.75,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.75,
|
||||||
|
-0.75,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "5fcac1094e1a5fd89bdc44c7ebe60e3a80060bba5a28852875d55869b3a96ee7",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 13.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "Part::Sweep",
|
||||||
|
"featureName": "Sweep",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Sections",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "Section",
|
||||||
|
"typeId": "Part::Feature"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 56,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "5c1241164480ab824c8e107694158117e7d5854ca62985d1123a33853d6d5e58",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 23.999999999999996
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"observed": "success",
|
"observed": "success",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"shapeNull": false,
|
"shapeNull": false,
|
||||||
@@ -221,6 +608,114 @@
|
|||||||
"expected": "success",
|
"expected": "success",
|
||||||
"faces": 7,
|
"faces": 7,
|
||||||
"id": "part-fillet-success",
|
"id": "part-fillet-success",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 372.99557428756424,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
8,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2.220446049250313e-16,
|
||||||
|
-2.220446049250313e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "53dbc555b86be7f2e989af3dd696ee01a611a4d7eb6b8d4fd1d379d351e8f73d",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 478.7123889803846
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
0.5,
|
||||||
|
0.5
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 374.6050880620834,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
8,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1.1102230246251565e-16,
|
||||||
|
-1.1102230246251565e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "25428228208a7ddd0b814f828c566d9ce99916c2ab86277d7eadf83dcba05aa7",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 479.6780972450962
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "Part::Fillet",
|
||||||
|
"featureName": "Fillet",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Edges",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 372.99557428756424,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
8,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2.220446049250313e-16,
|
||||||
|
-2.220446049250313e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "53dbc555b86be7f2e989af3dd696ee01a611a4d7eb6b8d4fd1d379d351e8f73d",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 478.7123889803846
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"observed": "success",
|
"observed": "success",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"shapeNull": false,
|
"shapeNull": false,
|
||||||
@@ -241,6 +736,114 @@
|
|||||||
"expected": "success",
|
"expected": "success",
|
||||||
"faces": 7,
|
"faces": 7,
|
||||||
"id": "part-chamfer-success",
|
"id": "part-chamfer-success",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 371.4852813742385,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
8,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1.6653345369377348e-16,
|
||||||
|
-1.6653345369377348e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "53ed2773aca1555789f3cca4fbb6b95e76ca92e40b1f423d53bfe39da21bbca6",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 476.9999999999999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
0.5,
|
||||||
|
0.5
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 373.99264068711926,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
8,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-8.326672684688674e-17,
|
||||||
|
-8.326672684688674e-17,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "ac5a85fa3d48a6595c1458a80fa22b6618c3c4203c3c5995a92cd2349fa262c5",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 479.25
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "Part::Chamfer",
|
||||||
|
"featureName": "Chamfer",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Edges",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 371.4852813742385,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
8,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1.6653345369377348e-16,
|
||||||
|
-1.6653345369377348e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "53ed2773aca1555789f3cca4fbb6b95e76ca92e40b1f423d53bfe39da21bbca6",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 476.9999999999999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"observed": "success",
|
"observed": "success",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"shapeNull": false,
|
"shapeNull": false,
|
||||||
|
|||||||
@@ -16,6 +16,105 @@
|
|||||||
},
|
},
|
||||||
"faces": 6,
|
"faces": 6,
|
||||||
"id": "pad-tapered",
|
"id": "pad-tapered",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 5
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 128.85239231084472,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
2.43744331762962,
|
||||||
|
2.43744331762962,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2.43744331762962,
|
||||||
|
-2.43744331762962,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "f5a07a59b273c128018d781af423bf016a2b0d17dc6dd59619460e37ca72de96",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 98.77344374611019
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": false,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 6
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 150.51432170708637,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
2.524931981155544,
|
||||||
|
2.524931981155544,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2.524931981155544,
|
||||||
|
-2.524931981155544,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "1987bd297acc648dc0d43f7703d68a0c8005a45056a3274c5f0240b1b46b9679",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 123.40116377418519
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Pad",
|
||||||
|
"featureName": "Pad",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Length",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 5
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 128.85239231084472,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
2.43744331762962,
|
||||||
|
2.43744331762962,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2.43744331762962,
|
||||||
|
-2.43744331762962,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "b5c1d71797f05ed2b2c51400de81047759f684a2c14d65d57acdc035aa3512e7",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 98.77344374611019
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"solids": 1,
|
"solids": 1,
|
||||||
"status": "Valid",
|
"status": "Valid",
|
||||||
@@ -36,6 +135,105 @@
|
|||||||
},
|
},
|
||||||
"faces": 10,
|
"faces": 10,
|
||||||
"id": "pocket-tapered",
|
"id": "pocket-tapered",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 10
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 735.999242011454,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
5,
|
||||||
|
5,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-5,
|
||||||
|
-5,
|
||||||
|
-5
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "ae401e5db6c23acc7d0fe23896ac08a0c27d6ed73df32953b1a9b15349f0b7bd",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 10,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 810.4374375507407
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": false,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 8
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 741.80522810493,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
5,
|
||||||
|
5,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-5,
|
||||||
|
-5,
|
||||||
|
-5
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "20aedff38ad1468a1eb669a71e9ad4ab45f1b211bfc81a41caf50b4cd39a03b3",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 11,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 853.2880812300241
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Pocket",
|
||||||
|
"featureName": "Pocket",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Length",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 10
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 735.999242011454,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
5,
|
||||||
|
5,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-5,
|
||||||
|
-5,
|
||||||
|
-5
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "56193a107c590c262642369e26467a690c0267174d47e2905f590280bf91d523",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 10,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 810.4374375507407
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"solids": 1,
|
"solids": 1,
|
||||||
"status": "Valid",
|
"status": "Valid",
|
||||||
|
|||||||
@@ -5,6 +5,105 @@
|
|||||||
"edges": 15,
|
"edges": 15,
|
||||||
"faces": 7,
|
"faces": 7,
|
||||||
"id": "fillet-selected-edge",
|
"id": "fillet-selected-edge",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 595.2787595947437,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2.220446049250313e-16,
|
||||||
|
-2.220446049250313e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "98c5a880b0bea84194e75f61c08114d8e8885fec88ffa3effc6f3da5063d7421",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 997.8539816339743
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 0.5
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 597.746680715673,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1.1102230246251565e-16,
|
||||||
|
-1.1102230246251565e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "03ec60b398de6e54bb2198d3a81b27abf5968b4479b66a794c18047aeea72946",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 999.4634954084936
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Fillet",
|
||||||
|
"featureName": "Fillet",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Radius",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 595.2787595947437,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2.220446049250313e-16,
|
||||||
|
-2.220446049250313e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "98c5a880b0bea84194e75f61c08114d8e8885fec88ffa3effc6f3da5063d7421",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 997.8539816339743
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"selection": [
|
"selection": [
|
||||||
"Edge1"
|
"Edge1"
|
||||||
@@ -18,6 +117,105 @@
|
|||||||
"edges": 15,
|
"edges": 15,
|
||||||
"faces": 7,
|
"faces": 7,
|
||||||
"id": "chamfer-selected-edge",
|
"id": "chamfer-selected-edge",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 593.1421356237308,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1.6653345369377348e-16,
|
||||||
|
-1.6653345369377348e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "d67242a11006664458599a9b2e13b2f9f4857699041bfe30bf33c2c2f774403a",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 994.9999999999998
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 0.5
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 596.8210678118654,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-8.326672684688674e-17,
|
||||||
|
-8.326672684688674e-17,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "51fb428868d98f40f7acbf91f018323d500315c167b8b8195a07f17c5b681258",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 998.75
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Chamfer",
|
||||||
|
"featureName": "Chamfer",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Size",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 593.1421356237308,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1.6653345369377348e-16,
|
||||||
|
-1.6653345369377348e-16,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "d67242a11006664458599a9b2e13b2f9f4857699041bfe30bf33c2c2f774403a",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 994.9999999999998
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"selection": [
|
"selection": [
|
||||||
"Edge1"
|
"Edge1"
|
||||||
@@ -31,6 +229,105 @@
|
|||||||
"edges": 12,
|
"edges": 12,
|
||||||
"faces": 6,
|
"faces": 6,
|
||||||
"id": "draft-selected-face",
|
"id": "draft-selected-face",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 45
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 841.4213562373093,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10.000000000000002,
|
||||||
|
10,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "fdc7c4775ef559c6309bbb2d1a31065a49e6d70455372f8fda595568fe46dfa4",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 1499.9999999999998
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 30
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 730.9401076758501,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
15.773502691896255
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "be5a1c93837a915d46279a1c5e40fbf46c0f921db4064f97ef568fbae9d3408e",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 1288.6751345948126
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Draft",
|
||||||
|
"featureName": "Draft",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Angle",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 45
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 841.4213562373093,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10.000000000000002,
|
||||||
|
10,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "fdc7c4775ef559c6309bbb2d1a31065a49e6d70455372f8fda595568fe46dfa4",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 1499.9999999999998
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"reversed": true,
|
"reversed": true,
|
||||||
"selection": [
|
"selection": [
|
||||||
@@ -46,6 +343,105 @@
|
|||||||
"elementMapSize": 51,
|
"elementMapSize": 51,
|
||||||
"faces": 11,
|
"faces": 11,
|
||||||
"id": "thickness-selected-face",
|
"id": "thickness-selected-face",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 887.9999999999999,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "747d92b1cf08109f59d9a972e6e14be9f09691263866f7eafbbdcee940390c4e",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 11,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 423.99999999999983
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 0.8
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 909.1199999999998,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "31e712785de8577559f0ce4584ced599fc69b3cbf9a508ab3eec24f2ab324952",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 11,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 350.8479999999998
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Thickness",
|
||||||
|
"featureName": "Thickness",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Value",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 887.9999999999999,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "747d92b1cf08109f59d9a972e6e14be9f09691263866f7eafbbdcee940390c4e",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 11,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 423.99999999999983
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"reversed": true,
|
"reversed": true,
|
||||||
"selection": [
|
"selection": [
|
||||||
|
|||||||
@@ -4,6 +4,96 @@
|
|||||||
{
|
{
|
||||||
"faces": 6,
|
"faces": 6,
|
||||||
"id": "additive-loft",
|
"id": "additive-loft",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": false,
|
||||||
|
"shape": {
|
||||||
|
"area": 7.23606797749979,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "0ab177609a66575afff2f36237fdf271e5a95e8fb738c91101648533e01c6642",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": false,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": true,
|
||||||
|
"shape": {
|
||||||
|
"area": 7.23606797749979,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "8a243d5c346dcb96da932fea88d54513c36e697b99cd36a90c892100e1f7b337",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::AdditiveLoft",
|
||||||
|
"featureName": "AdditiveLoft",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Ruled",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": false,
|
||||||
|
"shape": {
|
||||||
|
"area": 7.23606797749979,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "9cf30242b4b3776be5256d587155eb9781d7cc7534bbb60f125830fde83686c6",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"solids": 1,
|
"solids": 1,
|
||||||
"status": "Valid",
|
"status": "Valid",
|
||||||
@@ -13,6 +103,126 @@
|
|||||||
{
|
{
|
||||||
"faces": 5,
|
"faces": 5,
|
||||||
"id": "subtractive-loft",
|
"id": "subtractive-loft",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Section",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[
|
||||||
|
""
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 7.236067977499789,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "c90d78028b450759ca50298c18e98d5cfee774d1e453d6c133f5b748fa01c78a",
|
||||||
|
"edges": 9,
|
||||||
|
"faces": 5,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 6,
|
||||||
|
"volume": 0.9999999999999994
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "EditedSection",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[
|
||||||
|
""
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 9.348113056667211,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "21e5dda76ba93b30769b6f0b5d01006f43f92bb1012559f7a6ffdf5b25b8dc44",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 1.2135416666666667
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::SubtractiveLoft",
|
||||||
|
"featureName": "SubtractiveLoft",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Sections",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Section",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[
|
||||||
|
""
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 7.236067977499789,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "c90d78028b450759ca50298c18e98d5cfee774d1e453d6c133f5b748fa01c78a",
|
||||||
|
"edges": 9,
|
||||||
|
"faces": 5,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 6,
|
||||||
|
"volume": 0.9999999999999994
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"solids": 1,
|
"solids": 1,
|
||||||
"status": "Valid",
|
"status": "Valid",
|
||||||
@@ -22,6 +232,114 @@
|
|||||||
{
|
{
|
||||||
"faces": 3,
|
"faces": 3,
|
||||||
"id": "additive-pipe",
|
"id": "additive-pipe",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "Profile",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 12.566370614359169,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1.0000000000000002,
|
||||||
|
1.0000000000000002
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
-2.220446049250313e-16
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "82aa44aafac3cd8d51197e46391c039ae2a26b90e99df2f805e453de776dfcd8",
|
||||||
|
"edges": 3,
|
||||||
|
"faces": 3,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 2,
|
||||||
|
"volume": 3.1415926535897927
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "EditedProfile",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 8.246680715673207,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
0.75,
|
||||||
|
0.7500000000000002,
|
||||||
|
1.0000000000000002
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.75,
|
||||||
|
-0.75,
|
||||||
|
-1.6653345369377348e-16
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "452964b54d47c78e21e540fbd17b33e1a449fefd3607583204dd840d0761ca1f",
|
||||||
|
"edges": 3,
|
||||||
|
"faces": 3,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 2,
|
||||||
|
"volume": 1.7671458676442584
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::AdditivePipe",
|
||||||
|
"featureName": "AdditivePipe",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Profile",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "Profile",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 12.566370614359169,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1.0000000000000002,
|
||||||
|
1.0000000000000002
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
-2.220446049250313e-16
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "82aa44aafac3cd8d51197e46391c039ae2a26b90e99df2f805e453de776dfcd8",
|
||||||
|
"edges": 3,
|
||||||
|
"faces": 3,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 2,
|
||||||
|
"volume": 3.1415926535897927
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"solids": 1,
|
"solids": 1,
|
||||||
"status": "Valid",
|
"status": "Valid",
|
||||||
@@ -32,6 +350,114 @@
|
|||||||
{
|
{
|
||||||
"faces": 7,
|
"faces": 7,
|
||||||
"id": "subtractive-pipe",
|
"id": "subtractive-pipe",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "Profile",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 239.99999999999997,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
5,
|
||||||
|
5,
|
||||||
|
1.0000000000000002
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-5,
|
||||||
|
-5,
|
||||||
|
-2.220446049250313e-16
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "85644672cbbe548cbc5c063dc5e63feda7f149eb6a9b1446cba89f456945180b",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 96.8584073464102
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "EditedProfile",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 241.17809724509615,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
5,
|
||||||
|
5,
|
||||||
|
1.0000000000000002
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-5,
|
||||||
|
-5,
|
||||||
|
-1.6653345369377348e-16
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "1bca636a2f0deffa3ba317f7000dc245a9eaaa3d79bd800d1cbe80b6d3bb6b16",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 98.23285413235574
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::SubtractivePipe",
|
||||||
|
"featureName": "SubtractivePipe",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Profile",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": [
|
||||||
|
{
|
||||||
|
"name": "Profile",
|
||||||
|
"typeId": "Sketcher::SketchObject"
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
"shape": {
|
||||||
|
"area": 239.99999999999997,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
5,
|
||||||
|
5,
|
||||||
|
1.0000000000000002
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-5,
|
||||||
|
-5,
|
||||||
|
-2.220446049250313e-16
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "85644672cbbe548cbc5c063dc5e63feda7f149eb6a9b1446cba89f456945180b",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 7,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 96.8584073464102
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"solids": 1,
|
"solids": 1,
|
||||||
"status": "Valid",
|
"status": "Valid",
|
||||||
|
|||||||
@@ -4,6 +4,105 @@
|
|||||||
{
|
{
|
||||||
"faces": 4,
|
"faces": 4,
|
||||||
"id": "partdesign-revolution",
|
"id": "partdesign-revolution",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 360
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 150.79644737231007,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-4,
|
||||||
|
-4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "4e10234851bc71948ff0e12cfe337f7cf1f9f177d80991186faccb42bb09f84d",
|
||||||
|
"edges": 6,
|
||||||
|
"faces": 4,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 4,
|
||||||
|
"volume": 75.39822368615502
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": false,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 270
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 121.09733552923255,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-4,
|
||||||
|
-4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "99a870ec07e78b9c0903bee67373a8f4051c5651629db1149aeab3bc3be9d3d7",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 56.54866776461628
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Revolution",
|
||||||
|
"featureName": "Revolution",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Angle",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 360
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 150.79644737231007,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-4,
|
||||||
|
-4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "1fe389e236a01afd10442aacb43772d81f3910bde25b215d191d62d69eaa8c64",
|
||||||
|
"edges": 6,
|
||||||
|
"faces": 4,
|
||||||
|
"shapeType": "Solid",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 4,
|
||||||
|
"volume": 75.39822368615502
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"operation": "revolution",
|
"operation": "revolution",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"shapeNull": false,
|
"shapeNull": false,
|
||||||
@@ -16,6 +115,105 @@
|
|||||||
{
|
{
|
||||||
"faces": 10,
|
"faces": 10,
|
||||||
"id": "partdesign-groove",
|
"id": "partdesign-groove",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 180
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 610.137166941154,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "a71b46178c908477d71f6d08b4c922184abcc8426114c3e4315c50fbd8b17b87",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 10,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 995.2876110196153
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": false,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 120
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 610.137166941154,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "7d3dfb277849d5bdd4eed46a50b16c88c84830727893b452ec327c016aa93de1",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 10,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 995.2876110196153
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Groove",
|
||||||
|
"featureName": "Groove",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Angle",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: deg (0,0,0,0,0,0,0,1) [Angle]",
|
||||||
|
"value": 180
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 610.137166941154,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "6795afbb4bb89669697e47396335aa79cb12cb2aa14f1cade543a63894d6287f",
|
||||||
|
"edges": 24,
|
||||||
|
"faces": 10,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 16,
|
||||||
|
"volume": 995.2876110196153
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"operation": "groove",
|
"operation": "groove",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"shapeNull": false,
|
"shapeNull": false,
|
||||||
|
|||||||
@@ -7,6 +7,96 @@
|
|||||||
"faces": 21,
|
"faces": 21,
|
||||||
"id": "linear-feature-list",
|
"id": "linear-feature-list",
|
||||||
"length": 12,
|
"length": 12,
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": 3,
|
||||||
|
"shape": {
|
||||||
|
"area": 568,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
10,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "f5b90a00cb51e89b5d6cf1457a8b877ba0609d9053a31fb478070765f3ffc446",
|
||||||
|
"edges": 48,
|
||||||
|
"faces": 21,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 32,
|
||||||
|
"volume": 423.99999999999994
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": 4,
|
||||||
|
"shape": {
|
||||||
|
"area": 584,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
10,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "44b0867df8d01e7725a337741c5fabab336a9928cc4ddcd5674b386e14ddfb99",
|
||||||
|
"edges": 60,
|
||||||
|
"faces": 26,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 40,
|
||||||
|
"volume": 431.99999999999983
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::LinearPattern",
|
||||||
|
"featureName": "LinearPattern",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Occurrences",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": 3,
|
||||||
|
"shape": {
|
||||||
|
"area": 568,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
10,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "f5b90a00cb51e89b5d6cf1457a8b877ba0609d9053a31fb478070765f3ffc446",
|
||||||
|
"edges": 48,
|
||||||
|
"faces": 21,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 32,
|
||||||
|
"volume": 423.99999999999994
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"occurrences": 3,
|
"occurrences": 3,
|
||||||
"originals": [
|
"originals": [
|
||||||
"Boss"
|
"Boss"
|
||||||
@@ -22,6 +112,96 @@
|
|||||||
"edges": 28,
|
"edges": 28,
|
||||||
"faces": 12,
|
"faces": 12,
|
||||||
"id": "mirrored-feature-list",
|
"id": "mirrored-feature-list",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": true,
|
||||||
|
"shape": {
|
||||||
|
"area": 552,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
10,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "f09f9f5ab8be73c2eb76c3410c969e93044fb6beb01feec52d2d239da62d3c2e",
|
||||||
|
"edges": 28,
|
||||||
|
"faces": 12,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 18,
|
||||||
|
"volume": 416.00000000000006
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": false,
|
||||||
|
"shape": {
|
||||||
|
"area": 552,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
10,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "b978620d2a6f99e90e96dbc7f20b19169bea51ce2f4d22bfc620e55d62ccdeaa",
|
||||||
|
"edges": 33,
|
||||||
|
"faces": 15,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 20,
|
||||||
|
"volume": 415.99999999999983
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Mirrored",
|
||||||
|
"featureName": "Mirrored",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Refine",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": true,
|
||||||
|
"shape": {
|
||||||
|
"area": 552,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
10,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-2,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "f09f9f5ab8be73c2eb76c3410c969e93044fb6beb01feec52d2d239da62d3c2e",
|
||||||
|
"edges": 28,
|
||||||
|
"faces": 12,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 18,
|
||||||
|
"volume": 416.00000000000006
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"originals": [
|
"originals": [
|
||||||
"Boss"
|
"Boss"
|
||||||
],
|
],
|
||||||
@@ -39,6 +219,96 @@
|
|||||||
"edges": 12,
|
"edges": 12,
|
||||||
"faces": 6,
|
"faces": 6,
|
||||||
"id": "polar-feature-list",
|
"id": "polar-feature-list",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": 4,
|
||||||
|
"shape": {
|
||||||
|
"area": 1599.9999999999998,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10.000000000000002
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
-10.000000000000002,
|
||||||
|
-10.000000000000002
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "4dd67348ece295122be98bed65a93e8362e46d5d9dd5b6a88589a388537b73d7",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 3999.999999999999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": 3,
|
||||||
|
"shape": {
|
||||||
|
"area": 1799.9999999999998,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
-13.660254037844387,
|
||||||
|
-13.660254037844389
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "5127ab274986196eb89f32f2c697f83dbac753c05519b484449305370496c8c5",
|
||||||
|
"edges": 34,
|
||||||
|
"faces": 18,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 3,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 20,
|
||||||
|
"volume": 2999.9999999999995
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::PolarPattern",
|
||||||
|
"featureName": "PolarPattern",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Occurrences",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": 4,
|
||||||
|
"shape": {
|
||||||
|
"area": 1599.9999999999998,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10.000000000000002
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
-10.000000000000002,
|
||||||
|
-10.000000000000002
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "4dd67348ece295122be98bed65a93e8362e46d5d9dd5b6a88589a388537b73d7",
|
||||||
|
"edges": 12,
|
||||||
|
"faces": 6,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 8,
|
||||||
|
"volume": 3999.999999999999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"occurrences": 4,
|
"occurrences": 4,
|
||||||
"originals": [
|
"originals": [
|
||||||
"Box"
|
"Box"
|
||||||
@@ -54,6 +324,105 @@
|
|||||||
"edges": 36,
|
"edges": 36,
|
||||||
"faces": 14,
|
"faces": 14,
|
||||||
"id": "multi-transform-feature-list",
|
"id": "multi-transform-feature-list",
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 20
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 6400,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
30,
|
||||||
|
30,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-30,
|
||||||
|
-30.000000000000004,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "3e82460ae12922bd68d58ca6c48ad7ba2f034c4157e8f2da8a2bd9683ed83697",
|
||||||
|
"edges": 36,
|
||||||
|
"faces": 14,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 24,
|
||||||
|
"volume": 19999.999999999996
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": false,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 15
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 5200,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-25,
|
||||||
|
-25.000000000000004,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "c1e5e2ac391062149b8da2328ecb93a5bc71f166e1edea8157a30a51d53375dd",
|
||||||
|
"edges": 36,
|
||||||
|
"faces": 14,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 24,
|
||||||
|
"volume": 15999.999999999998
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::MultiTransform",
|
||||||
|
"featureName": "MultiTransform",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Transformations[1].Length",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 20
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 6400,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
30,
|
||||||
|
30,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-30,
|
||||||
|
-30.000000000000004,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "2a2bfeadec439a2a70d2a49da618de7c63d202f7b70a0adb8ad5d0a161bc7fae",
|
||||||
|
"edges": 36,
|
||||||
|
"faces": 14,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 24,
|
||||||
|
"volume": 19999.999999999996
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"originals": [
|
"originals": [
|
||||||
"Pad"
|
"Pad"
|
||||||
],
|
],
|
||||||
@@ -75,6 +444,105 @@
|
|||||||
"faces": 8,
|
"faces": 8,
|
||||||
"id": "iso-m6-tap-drill",
|
"id": "iso-m6-tap-drill",
|
||||||
"modeled": false,
|
"modeled": false,
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 5
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 1725.6637061435915,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "6157506ee1ceae966d58b98f729adbd4dffb585f1e9e52547e30d442af73efd3",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 8,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 3842.92036732051
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 6.5
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 1763.362817986669,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "a8ad05315c3d555a9ad9b764e243b4001b56401e9fab846aeb145ceb0fea42f6",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 8,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 3734.5354207716614
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Hole",
|
||||||
|
"featureName": "Hole",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Diameter",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 5
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 1725.6637061435915,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "6157506ee1ceae966d58b98f729adbd4dffb585f1e9e52547e30d442af73efd3",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 8,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 3842.92036732051
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"properties": [
|
"properties": [
|
||||||
"AddSubShape",
|
"AddSubShape",
|
||||||
@@ -148,6 +616,105 @@
|
|||||||
"faces": 36,
|
"faces": 36,
|
||||||
"id": "iso-m6-modeled-thread",
|
"id": "iso-m6-modeled-thread",
|
||||||
"modeled": true,
|
"modeled": true,
|
||||||
|
"mutation": {
|
||||||
|
"before": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 5.026
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 1791.0956620316247,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
10.5625
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "6affadc3a81dcbbe31ed1dc1e3539abd7b2fd3b280773d2f4445076ff5732fce",
|
||||||
|
"edges": 75,
|
||||||
|
"faces": 36,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 42,
|
||||||
|
"volume": 3820.1907618181585
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brepStable": true,
|
||||||
|
"edited": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 6.5
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 1763.362817986669,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "a8ad05315c3d555a9ad9b764e243b4001b56401e9fab846aeb145ceb0fea42f6",
|
||||||
|
"edges": 15,
|
||||||
|
"faces": 8,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 10,
|
||||||
|
"volume": 3734.5354207716614
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"familyId": "PartDesign::Hole",
|
||||||
|
"featureName": "Hole",
|
||||||
|
"parameterChanged": true,
|
||||||
|
"propertyPath": "Diameter",
|
||||||
|
"restored": {
|
||||||
|
"parameterSnapshot": {
|
||||||
|
"unit": "Unit: mm (1,0,0,0,0,0,0,0) [Length]",
|
||||||
|
"value": 5.026
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"area": 1791.0956620316247,
|
||||||
|
"bounds": {
|
||||||
|
"max": [
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
10.5625
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brepSha256": "6affadc3a81dcbbe31ed1dc1e3539abd7b2fd3b280773d2f4445076ff5732fce",
|
||||||
|
"edges": 75,
|
||||||
|
"faces": 36,
|
||||||
|
"shapeType": "Compound",
|
||||||
|
"solids": 1,
|
||||||
|
"valid": true,
|
||||||
|
"vertices": 42,
|
||||||
|
"volume": 3820.1907618181585
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restoredExactly": true,
|
||||||
|
"restoredGeometrically": true,
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"shapeChanged": true,
|
||||||
|
"status": "pass"
|
||||||
|
},
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"properties": [
|
"properties": [
|
||||||
"AddSubShape",
|
"AddSubShape",
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
"tasks": [
|
"tasks": [
|
||||||
{ "id": "EX-KER-01", "title": "Match OCCT construction, validation, tolerances and failure diagnostics", "priority": "P0", "status": "in_progress", "dependencies": ["EX-ORA-02"], "deliverables": ["Per-operation native differential", "Tolerance and placement contract", "Failure-code map"], "acceptance": ["Shape validity, topology, mass properties and diagnostics match locked FreeCAD fixtures", "Worker ownership returns to zero after every case"], "evidence": ["check:browser-occt", "check:chrome-geometry-features"], "exactBlockedBy": ["Not all FreeCAD builder flags and failure branches are represented"] },
|
{ "id": "EX-KER-01", "title": "Match OCCT construction, validation, tolerances and failure diagnostics", "priority": "P0", "status": "in_progress", "dependencies": ["EX-ORA-02"], "deliverables": ["Per-operation native differential", "Tolerance and placement contract", "Failure-code map"], "acceptance": ["Shape validity, topology, mass properties and diagnostics match locked FreeCAD fixtures", "Worker ownership returns to zero after every case"], "evidence": ["check:browser-occt", "check:chrome-geometry-features"], "exactBlockedBy": ["Not all FreeCAD builder flags and failure branches are represented"] },
|
||||||
{ "id": "EX-TSN-00", "title": "Fail closed when native naming or builder evidence is absent", "priority": "P0", "status": "completed", "dependencies": [], "deliverables": ["Runtime naming evidence contract", "final-shape-only and ambiguous persistence", "ElementMap2 writer evidence guard"], "acceptance": ["Final geometry cannot mint a private FreeCAD token", "Unproven stage relations and isomorphic sources cannot become stable"], "evidence": ["check:freecad-native-naming-evidence", "check:freecad-exact-history-elementmap-gate"], "exactBlockedBy": [] },
|
{ "id": "EX-TSN-00", "title": "Fail closed when native naming or builder evidence is absent", "priority": "P0", "status": "completed", "dependencies": [], "deliverables": ["Runtime naming evidence contract", "final-shape-only and ambiguous persistence", "ElementMap2 writer evidence guard"], "acceptance": ["Final geometry cannot mint a private FreeCAD token", "Unproven stage relations and isomorphic sources cannot become stable"], "evidence": ["check:freecad-native-naming-evidence", "check:freecad-exact-history-elementmap-gate"], "exactBlockedBy": [] },
|
||||||
{ "id": "EX-TSN-01", "title": "Capture native stage Shape and Generated/Modified/Deleted for every builder", "priority": "P0", "status": "in_progress", "dependencies": ["EX-KER-01", "EX-TSN-00"], "deliverables": ["All builder-stage captures", "Multi-input and one-to-many lineage", "Local feature recompute history"], "acceptance": ["Every feature result relation has a producing native stage", "No final-result index is applied to an intermediate Shape"], "evidence": ["check:freecad-composite-history-elementmap", "check:chrome-native-history"], "exactBlockedBy": ["Some providers still return only a final Shape"] },
|
{ "id": "EX-TSN-01", "title": "Capture native stage Shape and Generated/Modified/Deleted for every builder", "priority": "P0", "status": "completed", "dependencies": ["EX-KER-01", "EX-TSN-00"], "deliverables": ["All builder-stage captures", "Multi-input and one-to-many lineage", "Local feature recompute history"], "acceptance": ["Every feature result relation has a producing native stage", "No final-result index is applied to an intermediate Shape"], "evidence": ["check:freecad-composite-history-elementmap", "check:freecad-tsn-stage-evidence"], "exactBlockedBy": [] },
|
||||||
{ "id": "EX-TSN-02", "title": "Expose native MappedNameRef and StringHasher decisions for every feature", "priority": "P0", "status": "pending", "dependencies": ["EX-TSN-01"], "deliverables": ["Native naming callback ABI", "Per-stage StringHasher evidence", "Lossless ElementMap2 token generation"], "acceptance": ["All new tokens originate in native evidence", "FreeCAD round-trip names remain byte and semantic stable"], "evidence": ["check:freecad-native-naming-evidence"], "exactBlockedBy": ["FreeCAD private naming callbacks are not exposed for every builder"] },
|
{ "id": "EX-TSN-02", "title": "Expose native MappedNameRef and StringHasher decisions for every feature", "priority": "P0", "status": "pending", "dependencies": ["EX-TSN-01"], "deliverables": ["Native naming callback ABI", "Per-stage StringHasher evidence", "Lossless ElementMap2 token generation"], "acceptance": ["All new tokens originate in native evidence", "FreeCAD round-trip names remain byte and semantic stable"], "evidence": ["check:freecad-native-naming-evidence"], "exactBlockedBy": ["FreeCAD private naming callbacks are not exposed for every builder"] },
|
||||||
{ "id": "EX-TSN-03", "title": "Resolve isomorphic topology only from unique native provenance", "priority": "P0", "status": "in_progress", "dependencies": ["EX-TSN-01", "EX-TSN-02"], "deliverables": ["Symmetric Boolean corpus", "Candidate provenance graph", "Ambiguity repair lifecycle"], "acceptance": ["Unique native sources resolve deterministically", "Non-unique sources remain ambiguous across save, undo and recompute"], "evidence": ["test:topology-replay", "check:freecad-exact-history-elementmap-gate"], "exactBlockedBy": ["Symmetric cases without unique native provenance remain intentionally ambiguous"] },
|
{ "id": "EX-TSN-03", "title": "Resolve isomorphic topology only from unique native provenance", "priority": "P0", "status": "in_progress", "dependencies": ["EX-TSN-01", "EX-TSN-02"], "deliverables": ["Symmetric Boolean corpus", "Candidate provenance graph", "Ambiguity repair lifecycle"], "acceptance": ["Unique native sources resolve deterministically", "Non-unique sources remain ambiguous across save, undo and recompute"], "evidence": ["test:topology-replay", "check:freecad-exact-history-elementmap-gate"], "exactBlockedBy": ["Symmetric cases without unique native provenance remain intentionally ambiguous"] },
|
||||||
{ "id": "EX-TSN-04", "title": "Close topology naming across all feature edits and FCStd round-trips", "priority": "P0", "status": "pending", "dependencies": ["EX-TSN-02", "EX-TSN-03"], "deliverables": ["Cross-feature mutation matrix", "ElementMap2 history migration", "Long-chain LinkSub stability report"], "acceptance": ["Wrong bindings, unexplained relations and name drift are zero for the exhaustive corpus"], "evidence": ["check:freecad-fcstd-roundtrip", "check:freecad-exact-history-elementmap-gate"], "exactBlockedBy": ["Exhaustive cross-feature naming corpus is incomplete"] }
|
{ "id": "EX-TSN-04", "title": "Close topology naming across all feature edits and FCStd round-trips", "priority": "P0", "status": "pending", "dependencies": ["EX-TSN-02", "EX-TSN-03"], "deliverables": ["Cross-feature mutation matrix", "ElementMap2 history migration", "Long-chain LinkSub stability report"], "acceptance": ["Wrong bindings, unexplained relations and name drift are zero for the exhaustive corpus"], "evidence": ["check:freecad-fcstd-roundtrip", "check:freecad-exact-history-elementmap-gate"], "exactBlockedBy": ["Exhaustive cross-feature naming corpus is incomplete"] }
|
||||||
|
|||||||
@@ -1763,3 +1763,15 @@ PartDesign transform oracle 由 4 项扩为 10 项:补入 PolarPattern `4000`
|
|||||||
TSN 阶段门禁已接入默认执行计划。Pad 证据为 `25` 条跨 modified/generated 记录,Pocket 为 `42` 条记录,含普通两阶段和 two-sided 四阶段的 source/result/topology/relation/cleanup 校验;当前原生 provider 只捕获 `cut/fuse/pad` 三类操作,19 类目标操作仍缺 `16` 类逐阶段证据,且 `MappedNameRef/StringHasher` 私有 token 仍是明确阻塞项。
|
TSN 阶段门禁已接入默认执行计划。Pad 证据为 `25` 条跨 modified/generated 记录,Pocket 为 `42` 条记录,含普通两阶段和 two-sided 四阶段的 source/result/topology/relation/cleanup 校验;当前原生 provider 只捕获 `cut/fuse/pad` 三类操作,19 类目标操作仍缺 `16` 类逐阶段证据,且 `MappedNameRef/StringHasher` 私有 token 仍是明确阻塞项。
|
||||||
|
|
||||||
真实 oracle lane 已在固定桌面安装上完成 `27` 个命令,包含 ORA、Part/PartDesign/Sketcher、FCStd roundtrip 与 exact naming gates;WASM lane 已重跑 Chrome Pad/Pocket history harness。源代码网络抓取在本地因 GitHub 超时,验证使用显式 `FREECAD_SOURCE_OFFLINE=1` 的同一 pinned checkout;CI 默认路径仍执行真实 tag/submodule fetch,不会把离线缓存当作成功证据。
|
真实 oracle lane 已在固定桌面安装上完成 `27` 个命令,包含 ORA、Part/PartDesign/Sketcher、FCStd roundtrip 与 exact naming gates;WASM lane 已重跑 Chrome Pad/Pocket history harness。源代码网络抓取在本地因 GitHub 超时,验证使用显式 `FREECAD_SOURCE_OFFLINE=1` 的同一 pinned checkout;CI 默认路径仍执行真实 tag/submodule fetch,不会把离线缓存当作成功证据。
|
||||||
|
|
||||||
|
## 228. 2026-08-10 Builder、参数恢复、FCStd 与命名证据闭合
|
||||||
|
|
||||||
|
参数 mutation 不再由结果数量代替事务证据。新增共享 FreeCAD 运行时采集器,逐项保存参数编辑前、编辑后和恢复后的属性快照、有效 Shape、BRep 摘要、体积/面积/边界以及恢复等价性;12 个 Part 核心族、6 个 Part builder 和现有 PartDesign 成功 oracle 均接入该协议。生成矩阵现在为 `35/35` nominal、`35/35` invalid boundary、`35/35` parameter variant、`35/35` edit/recompute/recovery、`35/35` FCStd roundtrip,`incomplete=0`、`blockers=[]`。
|
||||||
|
|
||||||
|
FCStd 双向往返新增真实 `Part::Cut` 穿孔文档:`20 x 20 x 10` Box 由半径 `3`、高度 `12`、位置 `(10,10,-1)` 的 Cylinder 贯穿切除;FreeCAD 1.1.1 重算结果为有效单 Solid、7 个面、体积 `4000-90*pi`,重新保存后 Web 检查器恢复 Base/Tool/Refine、Placement 与 Shape resource。往返门由 `22` 个场景增为 `23/23`,因此 Part::Cut 的第二个往返要求和全部 35 个族均已满足。
|
||||||
|
|
||||||
|
TSN 门不再只读取 Pad/Pocket 两份报告。它现在汇总 16 份 Chrome/WASM 原生 history 报告,逐份校验 provider、operation registry、Worker/WASM、关系计数、结果 Solid、stage input/result/topology、专用 marker 和释放后 `0/0`;19 类 operation 的证据为 `19/19`,缺失为 `0`。Pocket、Revolution、Groove、Hole、MultiTransform 的 17 个显式 stage 继续逐级校验,其他专用 builder 由操作报告和 marker 绑定。`EX-TSN-01` 因此更新为 `completed`,exact 计划计数为 `2 completed / 36 in_progress / 14 pending / 0 blocked`。
|
||||||
|
|
||||||
|
命名 oracle 同时修正了旧的误分类。FreeCAD 运行时 219 个阶段中,74 个派生/操作阶段要求私有 MappedName,现为 `required=74 / complete=74`;145 个基础或支持阶段由原生 API 明确返回 `IndexedName-only`,不再被错误统计为 145 个缺失私有 token。42 个 Part/PartDesign builder 阶段均具有直接 `getElementHistory/getElementMappedName/getElementIndexedName` 证据,结果为 `42/42`、missing `0`。这只闭合锁定 oracle 的证据,不代表浏览器 OCCT 能为任意新模型执行 FreeCAD 私有命名算法:浏览器仍没有 `MappedNameRef/StringHasher` callback ABI,原生 token 仍限于 fixture/oracle,非唯一同构来源仍必须保持 ambiguous。
|
||||||
|
|
||||||
|
真实 CI oracle lane 已调整为先重跑核心参数、全部 Part/PartDesign、复合命名和 FCStd oracle,再生成参数报告并执行检查;Chrome lane在所有 `test:chrome-*` 重跑后执行 19-operation TSN 聚合门,避免读取旧报告。当前 `systemExact=false`、`EX-TSN-02=pending`、`EX-TSN-04=pending`、`EX-REL-01=pending`、exact modules `0/34`;剩余工作不得用锁定 fixture 的 token 代替浏览器实时私有命名回调。
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"check:baseline": "node scripts/check-baseline.mjs",
|
"check:baseline": "node scripts/check-baseline.mjs",
|
||||||
"check:freecad-source": "node scripts/verify-freecad-source.mjs",
|
"check:freecad-source": "node scripts/verify-freecad-source.mjs",
|
||||||
"check:bitbybit-history": "node scripts/check-bitbybit-history-surface.mjs",
|
"check:bitbybit-history": "node scripts/check-bitbybit-history-surface.mjs",
|
||||||
"check:execution-plan": "node scripts/check-freecad-execution-plan.mjs && node scripts/check-freecad-web-exact-parity-plan.mjs && node scripts/check-freecad-web-exact-promotion.mjs && node scripts/check-freecad-oracle-coverage.mjs && node scripts/check-freecad-golden-coverage.mjs && node scripts/generate-freecad-parameter-mutation-report.mjs --check && node scripts/check-freecad-tsn-stage-evidence.mjs",
|
"check:execution-plan": "node scripts/check-freecad-execution-plan.mjs && node scripts/check-freecad-web-exact-parity-plan.mjs && node scripts/check-freecad-web-exact-promotion.mjs && node scripts/check-freecad-oracle-coverage.mjs && node scripts/check-freecad-golden-coverage.mjs && node scripts/check-freecad-core-parameter-mutation-oracle.mjs && node scripts/generate-freecad-parameter-mutation-report.mjs --check && node scripts/check-freecad-tsn-stage-evidence.mjs",
|
||||||
"check:freecad-web-exact-parity-plan": "node scripts/check-freecad-web-exact-parity-plan.mjs",
|
"check:freecad-web-exact-parity-plan": "node scripts/check-freecad-web-exact-parity-plan.mjs",
|
||||||
"check:freecad-web-exact-promotion": "node scripts/check-freecad-web-exact-promotion.mjs",
|
"check:freecad-web-exact-promotion": "node scripts/check-freecad-web-exact-promotion.mjs",
|
||||||
"generate:freecad-inventory": "node scripts/generate-freecad-source-inventory.mjs",
|
"generate:freecad-inventory": "node scripts/generate-freecad-source-inventory.mjs",
|
||||||
@@ -29,6 +29,8 @@
|
|||||||
"check:freecad-golden-coverage": "node scripts/check-freecad-golden-coverage.mjs",
|
"check:freecad-golden-coverage": "node scripts/check-freecad-golden-coverage.mjs",
|
||||||
"generate:freecad-parameter-mutations": "node scripts/generate-freecad-parameter-mutation-report.mjs",
|
"generate:freecad-parameter-mutations": "node scripts/generate-freecad-parameter-mutation-report.mjs",
|
||||||
"check:freecad-parameter-mutations": "node scripts/generate-freecad-parameter-mutation-report.mjs --check",
|
"check:freecad-parameter-mutations": "node scripts/generate-freecad-parameter-mutation-report.mjs --check",
|
||||||
|
"probe:freecad-core-parameter-mutations": "node scripts/run-freecad-core-parameter-mutation-oracle.mjs",
|
||||||
|
"check:freecad-core-parameter-mutations": "node scripts/check-freecad-core-parameter-mutation-oracle.mjs",
|
||||||
"probe:freecad-partdesign-failures": "node scripts/run-freecad-partdesign-failure-oracle.mjs",
|
"probe:freecad-partdesign-failures": "node scripts/run-freecad-partdesign-failure-oracle.mjs",
|
||||||
"check:freecad-partdesign-failures": "node scripts/check-freecad-partdesign-failure-oracle.mjs",
|
"check:freecad-partdesign-failures": "node scripts/check-freecad-partdesign-failure-oracle.mjs",
|
||||||
"probe:freecad-partdesign-revolution-groove": "node scripts/run-freecad-partdesign-revolution-groove-oracle.mjs",
|
"probe:freecad-partdesign-revolution-groove": "node scripts/run-freecad-partdesign-revolution-groove-oracle.mjs",
|
||||||
|
|||||||
18
scripts/check-freecad-core-parameter-mutation-oracle.mjs
Normal file
18
scripts/check-freecad-core-parameter-mutation-oracle.mjs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { readFile } from 'node:fs/promises'
|
||||||
|
import { resolve } from 'node:path'
|
||||||
|
|
||||||
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
||||||
|
const report = JSON.parse(await readFile(resolve(root, 'config/freecad-core-parameter-mutation-oracle.json'), 'utf8'))
|
||||||
|
const expected = ['Part::Box', 'Part::Cylinder', 'Part::Sphere', 'Part::Ellipsoid', 'Part::Cone', 'Part::Torus', 'Part::Helix', 'Part::Prism', 'Part::Wedge', 'Part::Fuse', 'Part::Cut', 'Part::Common']
|
||||||
|
const fail = (message) => { throw new Error(`FreeCAD core parameter mutation oracle: ${message}`) }
|
||||||
|
if (report.schemaVersion !== 1 || report.status !== 'pass' || report.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || report.summary?.families !== expected.length || report.summary?.passed !== expected.length || report.summary?.shapeChanged !== expected.length || report.summary?.restoredExactly !== expected.length) fail('baseline or summary is invalid.')
|
||||||
|
const seen = new Set()
|
||||||
|
for (const entry of report.cases ?? []) {
|
||||||
|
if (!expected.includes(entry.familyId) || seen.has(entry.familyId)) fail(`unexpected or duplicate family ${entry.familyId}.`)
|
||||||
|
seen.add(entry.familyId)
|
||||||
|
if (entry.status !== 'pass' || entry.parameterChanged !== true || entry.shapeChanged !== true || entry.restoredExactly !== true || !entry.propertyPath) fail(`${entry.familyId} lacks a completed parameter transaction.`)
|
||||||
|
if (!entry.before?.shape?.valid || !entry.edited?.shape?.valid || !entry.restored?.shape?.valid || !entry.before.shape.brepSha256 || entry.before.shape.brepSha256 !== entry.restored.shape.brepSha256) fail(`${entry.familyId} lacks valid/restored Shape evidence.`)
|
||||||
|
if (JSON.stringify(entry.before.parameterSnapshot) === JSON.stringify(entry.edited.parameterSnapshot) || JSON.stringify(entry.before.parameterSnapshot) !== JSON.stringify(entry.restored.parameterSnapshot)) fail(`${entry.familyId} parameter snapshots are inconsistent.`)
|
||||||
|
}
|
||||||
|
if (seen.size !== expected.length) fail(`expected ${expected.length} families, found ${seen.size}.`)
|
||||||
|
console.log(JSON.stringify({ status: 'freecad-core-parameter-mutation-pass', families: seen.size, shapeChanged: report.summary.shapeChanged, restoredExactly: report.summary.restoredExactly }, null, 2))
|
||||||
@@ -24,6 +24,8 @@ let namingEvidenceBoundaryViolations = 0
|
|||||||
let nativeEvidenceStages = 0
|
let nativeEvidenceStages = 0
|
||||||
let nativeMappedNameStages = 0
|
let nativeMappedNameStages = 0
|
||||||
let nativeIndexedNameStages = 0
|
let nativeIndexedNameStages = 0
|
||||||
|
let indexedNameOnlyStages = 0
|
||||||
|
let privateTokenEvidenceRequiredStages = 0
|
||||||
let privateTokenEvidenceCompleteStages = 0
|
let privateTokenEvidenceCompleteStages = 0
|
||||||
let internalBuilderEvidenceStages = 0
|
let internalBuilderEvidenceStages = 0
|
||||||
let internalBuilderEvidenceMissingStages = 0
|
let internalBuilderEvidenceMissingStages = 0
|
||||||
@@ -38,6 +40,8 @@ for (const fixture of oracle.cases) {
|
|||||||
if (stage.namingEvidenceStatus === 'native-evidence') nativeEvidenceStages += 1
|
if (stage.namingEvidenceStatus === 'native-evidence') nativeEvidenceStages += 1
|
||||||
if (stage.nativeEvidence?.mappedNameApiEntries > 0) nativeMappedNameStages += 1
|
if (stage.nativeEvidence?.mappedNameApiEntries > 0) nativeMappedNameStages += 1
|
||||||
if (stage.nativeEvidence?.indexedNameApiEntries > 0) nativeIndexedNameStages += 1
|
if (stage.nativeEvidence?.indexedNameApiEntries > 0) nativeIndexedNameStages += 1
|
||||||
|
if (stage.nativeEvidence?.indexedNameOnly === true) indexedNameOnlyStages += 1
|
||||||
|
if (stage.nativeEvidence?.privateTokenEvidenceRequired === true) privateTokenEvidenceRequiredStages += 1
|
||||||
if (stage.nativeEvidence?.privateTokenEvidenceComplete === true) privateTokenEvidenceCompleteStages += 1
|
if (stage.nativeEvidence?.privateTokenEvidenceComplete === true) privateTokenEvidenceCompleteStages += 1
|
||||||
if (builderStageType.test(stage.typeId || '')) {
|
if (builderStageType.test(stage.typeId || '')) {
|
||||||
if (stage.nativeEvidence?.internalBuilderEvidence === true) internalBuilderEvidenceStages += 1
|
if (stage.nativeEvidence?.internalBuilderEvidence === true) internalBuilderEvidenceStages += 1
|
||||||
@@ -96,5 +100,6 @@ for (const fixture of oracle.cases) {
|
|||||||
for (const scenario of roundtrip.scenarios || []) {
|
for (const scenario of roundtrip.scenarios || []) {
|
||||||
if (scenario.status !== 'pass' || (scenario.differences || []).length !== 0) roundtripNameDrift += 1
|
if (scenario.status !== 'pass' || (scenario.differences || []).length !== 0) roundtripNameDrift += 1
|
||||||
}
|
}
|
||||||
|
if (indexedNameOnlyStages + privateTokenEvidenceRequiredStages !== nativeEvidenceStages || privateTokenEvidenceCompleteStages !== privateTokenEvidenceRequiredStages || internalBuilderEvidenceStages !== 42 || internalBuilderEvidenceMissingStages !== 0) throw new Error(`Exact native naming evidence is incomplete: indexedOnly=${indexedNameOnlyStages}, tokenRequired=${privateTokenEvidenceRequiredStages}, tokenComplete=${privateTokenEvidenceCompleteStages}, builder=${internalBuilderEvidenceStages}, builderMissing=${internalBuilderEvidenceMissingStages}.`)
|
||||||
if (roundtrip.status !== 'verified' || wrongBindings !== gate.requirements.wrongBindings || unexplainedRelations !== gate.requirements.unexplainedRelations || roundtripNameDrift !== gate.requirements.roundtripNameDrift || elementMap2ParseFailures !== gate.requirements.elementMap2ParseFailures || elementMap2SemanticFailures !== gate.requirements.elementMap2SemanticFailures || elementMap2TokenWriterFailures !== gate.requirements.elementMap2TokenWriterFailures || stringHasherParseFailures !== gate.requirements.stringHasherParseFailures || stringHasherSemanticFailures !== gate.requirements.stringHasherSemanticFailures || stringHasherEvidenceFailures !== gate.requirements.stringHasherEvidenceFailures || namingEvidenceMissing !== gate.requirements.namingEvidenceMissing || namingEvidenceBoundaryViolations !== gate.requirements.namingEvidenceBoundaryViolations) throw new Error(`Exact gate failed: wrongBindings=${wrongBindings}, unexplainedRelations=${unexplainedRelations}, roundtripNameDrift=${roundtripNameDrift}, elementMap2ParseFailures=${elementMap2ParseFailures}, elementMap2SemanticFailures=${elementMap2SemanticFailures}, elementMap2TokenWriterFailures=${elementMap2TokenWriterFailures}, stringHasherParseFailures=${stringHasherParseFailures}, stringHasherSemanticFailures=${stringHasherSemanticFailures}, stringHasherEvidenceFailures=${stringHasherEvidenceFailures}, namingEvidenceMissing=${namingEvidenceMissing}, namingEvidenceBoundaryViolations=${namingEvidenceBoundaryViolations}.`)
|
if (roundtrip.status !== 'verified' || wrongBindings !== gate.requirements.wrongBindings || unexplainedRelations !== gate.requirements.unexplainedRelations || roundtripNameDrift !== gate.requirements.roundtripNameDrift || elementMap2ParseFailures !== gate.requirements.elementMap2ParseFailures || elementMap2SemanticFailures !== gate.requirements.elementMap2SemanticFailures || elementMap2TokenWriterFailures !== gate.requirements.elementMap2TokenWriterFailures || stringHasherParseFailures !== gate.requirements.stringHasherParseFailures || stringHasherSemanticFailures !== gate.requirements.stringHasherSemanticFailures || stringHasherEvidenceFailures !== gate.requirements.stringHasherEvidenceFailures || namingEvidenceMissing !== gate.requirements.namingEvidenceMissing || namingEvidenceBoundaryViolations !== gate.requirements.namingEvidenceBoundaryViolations) throw new Error(`Exact gate failed: wrongBindings=${wrongBindings}, unexplainedRelations=${unexplainedRelations}, roundtripNameDrift=${roundtripNameDrift}, elementMap2ParseFailures=${elementMap2ParseFailures}, elementMap2SemanticFailures=${elementMap2SemanticFailures}, elementMap2TokenWriterFailures=${elementMap2TokenWriterFailures}, stringHasherParseFailures=${stringHasherParseFailures}, stringHasherSemanticFailures=${stringHasherSemanticFailures}, stringHasherEvidenceFailures=${stringHasherEvidenceFailures}, namingEvidenceMissing=${namingEvidenceMissing}, namingEvidenceBoundaryViolations=${namingEvidenceBoundaryViolations}.`)
|
||||||
console.log(JSON.stringify({ status: 'freecad-exact-history-elementmap-gate-pass', exactPromotionReady: false, cases: oracle.summary.cases, resources, stringHasherResources, nativeEvidenceStages, nativeIndexedNameStages, nativeMappedNameStages, indexedOnlyStages: nativeIndexedNameStages - nativeMappedNameStages, privateTokenEvidenceCompleteStages, internalBuilderEvidenceStages, internalBuilderEvidenceMissingStages, wrongBindings, unexplainedRelations, roundtripNameDrift, elementMap2ParseFailures, elementMap2SemanticFailures, elementMap2TokenWriterFailures, stringHasherParseFailures, stringHasherSemanticFailures, stringHasherEvidenceFailures, namingEvidenceMissing, namingEvidenceBoundaryViolations }, null, 2))
|
console.log(JSON.stringify({ status: 'freecad-exact-history-elementmap-gate-pass', exactPromotionReady: false, cases: oracle.summary.cases, resources, stringHasherResources, nativeEvidenceStages, nativeIndexedNameStages, nativeMappedNameStages, indexedOnlyStages: indexedNameOnlyStages, privateTokenEvidenceRequiredStages, privateTokenEvidenceCompleteStages, internalBuilderEvidenceStages, internalBuilderEvidenceMissingStages, wrongBindings, unexplainedRelations, roundtripNameDrift, elementMap2ParseFailures, elementMap2SemanticFailures, elementMap2TokenWriterFailures, stringHasherParseFailures, stringHasherSemanticFailures, stringHasherEvidenceFailures, namingEvidenceMissing, namingEvidenceBoundaryViolations }, null, 2))
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ const fail = (message) => { throw new Error(`FCStd round-trip verification: ${me
|
|||||||
if (report.schemaVersion !== 1 || report.baselineId !== 'freecad-1.1.1' || report.freecadCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || report.bitbybitVersion !== '1.1.1') fail('baseline is not locked to FreeCAD/Bitbybit 1.1.1.')
|
if (report.schemaVersion !== 1 || report.baselineId !== 'freecad-1.1.1' || report.freecadCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || report.bitbybitVersion !== '1.1.1') fail('baseline is not locked to FreeCAD/Bitbybit 1.1.1.')
|
||||||
if (report.unknownDifferencesFail !== true || report.status !== 'verified') fail('unknown differences are not release-blocking.')
|
if (report.unknownDifferencesFail !== true || report.status !== 'verified') fail('unknown differences are not release-blocking.')
|
||||||
if (JSON.stringify(report.directions) !== '["freecad-web-freecad","web-freecad-web"]') fail('both round-trip directions are required.')
|
if (JSON.stringify(report.directions) !== '["freecad-web-freecad","web-freecad-web"]') fail('both round-trip directions are required.')
|
||||||
if (!Array.isArray(report.scenarios) || report.scenarioCount !== 22 || report.scenarios.length !== report.scenarioCount) fail('exactly 22 native scenarios are required.')
|
if (!Array.isArray(report.scenarios) || report.scenarioCount !== 23 || report.scenarios.length !== report.scenarioCount) fail('exactly 23 native scenarios are required.')
|
||||||
|
|
||||||
const expectedIds = new Set([
|
const expectedIds = new Set([
|
||||||
'proxy-byte-preservation',
|
'proxy-byte-preservation',
|
||||||
'locked-partdesign-shape',
|
'locked-partdesign-shape',
|
||||||
'part-box', 'part-cylinder', 'part-sphere', 'part-ellipsoid', 'part-cone', 'part-torus', 'part-prism', 'part-wedge', 'part-fuse', 'part-cut', 'part-common',
|
'part-box', 'part-cylinder', 'part-sphere', 'part-ellipsoid', 'part-cone', 'part-torus', 'part-prism', 'part-wedge', 'part-fuse', 'part-cut', 'part-cut-through-hole', 'part-common',
|
||||||
'part-sphere-trim',
|
'part-sphere-trim',
|
||||||
'part-extrusion', 'part-revolution',
|
'part-extrusion', 'part-revolution',
|
||||||
'sketch-core-external-attachment', 'sketch-face-projection', 'sketch-external-modes',
|
'sketch-core-external-attachment', 'sketch-face-projection', 'sketch-external-modes',
|
||||||
@@ -41,11 +41,13 @@ const proxy = byId['proxy-byte-preservation'].evidence
|
|||||||
if (proxy.sourceArchiveBytes <= 0 || proxy.sourceArchiveBytes !== proxy.preservedArchiveBytes || proxy.sourceSha256 !== proxy.preservedSha256 || !/^[a-f0-9]{64}$/.test(proxy.sourceSha256) || proxy.byteIdentical !== true || proxy.proxyObjectCount !== 8 || proxy.blockedObjectCount !== 0 || proxy.resavedObjectCount !== 17 || proxy.resavedProxyObjectCount !== 8 || proxy.resavedShapeValid !== true || JSON.stringify(proxy.unknownTypeIds) !== '["App::Line","App::Origin","App::Plane","App::Point"]') fail('FreeCAD-origin proxy byte-preservation evidence is incomplete.')
|
if (proxy.sourceArchiveBytes <= 0 || proxy.sourceArchiveBytes !== proxy.preservedArchiveBytes || proxy.sourceSha256 !== proxy.preservedSha256 || !/^[a-f0-9]{64}$/.test(proxy.sourceSha256) || proxy.byteIdentical !== true || proxy.proxyObjectCount !== 8 || proxy.blockedObjectCount !== 0 || proxy.resavedObjectCount !== 17 || proxy.resavedProxyObjectCount !== 8 || proxy.resavedShapeValid !== true || JSON.stringify(proxy.unknownTypeIds) !== '["App::Line","App::Origin","App::Plane","App::Point"]') fail('FreeCAD-origin proxy byte-preservation evidence is incomplete.')
|
||||||
const sourceShape = byId['locked-partdesign-shape'].evidence
|
const sourceShape = byId['locked-partdesign-shape'].evidence
|
||||||
if (sourceShape.solidCount !== 1 || sourceShape.faceCount !== 23 || sourceShape.elementMapPostfixCount !== 63 || sourceShape.elementMapCount !== 2 || sourceShape.stringHasherBytes <= 0) fail('FreeCAD-origin Shape/ElementMap evidence is incomplete.')
|
if (sourceShape.solidCount !== 1 || sourceShape.faceCount !== 23 || sourceShape.elementMapPostfixCount !== 63 || sourceShape.elementMapCount !== 2 || sourceShape.stringHasherBytes <= 0) fail('FreeCAD-origin Shape/ElementMap evidence is incomplete.')
|
||||||
for (const id of ['part-box', 'part-cylinder', 'part-sphere', 'part-ellipsoid', 'part-cone', 'part-torus', 'part-prism', 'part-wedge', 'part-fuse', 'part-cut', 'part-common']) {
|
for (const id of ['part-box', 'part-cylinder', 'part-sphere', 'part-ellipsoid', 'part-cone', 'part-torus', 'part-prism', 'part-wedge', 'part-fuse', 'part-cut', 'part-cut-through-hole', 'part-common']) {
|
||||||
const evidence = byId[id].evidence
|
const evidence = byId[id].evidence
|
||||||
if (evidence.solidCount !== 1 || !Number.isFinite(evidence.volume) || evidence.volume <= 0 || evidence.propertyCount <= 0 || evidence.resavedShapeAvailable !== true) fail(`${id} did not preserve parameters and a valid Shape resource.`)
|
if (evidence.solidCount !== 1 || !Number.isFinite(evidence.volume) || evidence.volume <= 0 || evidence.propertyCount <= 0 || evidence.resavedShapeAvailable !== true) fail(`${id} did not preserve parameters and a valid Shape resource.`)
|
||||||
}
|
}
|
||||||
if (byId['part-fuse'].evidence.refine !== false || byId['part-cut'].evidence.refine !== false || byId['part-common'].evidence.refine !== true) fail('Part Boolean Refine values did not round-trip through FreeCAD.')
|
if (byId['part-fuse'].evidence.refine !== false || byId['part-cut'].evidence.refine !== false || byId['part-cut-through-hole'].evidence.refine !== false || byId['part-common'].evidence.refine !== true) fail('Part Boolean Refine values did not round-trip through FreeCAD.')
|
||||||
|
const cutThroughHole = byId['part-cut-through-hole'].evidence
|
||||||
|
if (cutThroughHole.typeId !== 'Part::Cut' || cutThroughHole.faceCount !== 7 || !Number.isFinite(cutThroughHole.volume) || Math.abs(cutThroughHole.volume - (4000 - 90 * Math.PI)) > 1e-8 || !cutThroughHole.boundingBox || JSON.stringify(cutThroughHole.boundingBox.min) !== '[0,0,0]' || JSON.stringify(cutThroughHole.boundingBox.max) !== '[20,20,10]' || cutThroughHole.properties?.Base !== 'Base' || cutThroughHole.properties?.Tool !== 'HoleTool' || cutThroughHole.properties?.Refine !== false || JSON.stringify(cutThroughHole.toolPlacement) !== '{"position":{"x":10,"y":10,"z":-1},"rotation":{"axis":{"x":0,"y":0,"z":1},"angle":0}}') fail('Part::Cut through-hole geometry, links, or placement did not round-trip through FreeCAD.')
|
||||||
const torus = byId['part-torus'].evidence
|
const torus = byId['part-torus'].evidence
|
||||||
const torusBound = 12.988706403508727
|
const torusBound = 12.988706403508727
|
||||||
if (!Number.isFinite(torus.volume) || Math.abs(torus.volume - 60 * Math.PI ** 2) > 1e-8 || torus.propertyCount !== 5 || !torus.boundingBox || torus.boundingBox.min.some((value, index) => Math.abs(value - [-torusBound, -torusBound, -2][index]) > 1e-8) || torus.boundingBox.max.some((value, index) => Math.abs(value - [torusBound, torusBound, 2][index]) > 1e-8)) fail('native Part::Torus evidence is incomplete.')
|
if (!Number.isFinite(torus.volume) || Math.abs(torus.volume - 60 * Math.PI ** 2) > 1e-8 || torus.propertyCount !== 5 || !torus.boundingBox || torus.boundingBox.min.some((value, index) => Math.abs(value - [-torusBound, -torusBound, -2][index]) > 1e-8) || torus.boundingBox.max.some((value, index) => Math.abs(value - [torusBound, torusBound, 2][index]) > 1e-8)) fail('native Part::Torus evidence is incomplete.')
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ let missingEvidenceStages = 0
|
|||||||
let nativeEvidenceValidatedStages = 0
|
let nativeEvidenceValidatedStages = 0
|
||||||
let nativeMappedNameStages = 0
|
let nativeMappedNameStages = 0
|
||||||
let nativeIndexedNameStages = 0
|
let nativeIndexedNameStages = 0
|
||||||
|
let indexedNameOnlyStages = 0
|
||||||
|
let privateTokenEvidenceRequiredStages = 0
|
||||||
let privateTokenEvidenceCompleteStages = 0
|
let privateTokenEvidenceCompleteStages = 0
|
||||||
let internalBuilderEvidenceStages = 0
|
let internalBuilderEvidenceStages = 0
|
||||||
let internalBuilderEvidenceMissingStages = 0
|
let internalBuilderEvidenceMissingStages = 0
|
||||||
@@ -122,6 +124,8 @@ for (const fixture of composite.cases) {
|
|||||||
if (stage.nativeEvidence?.stageId === stage.name && stage.nativeEvidence?.resultObjectId === stage.name && stage.nativeEvidence?.status === stage.namingEvidenceStatus) nativeEvidenceValidatedStages += 1
|
if (stage.nativeEvidence?.stageId === stage.name && stage.nativeEvidence?.resultObjectId === stage.name && stage.nativeEvidence?.status === stage.namingEvidenceStatus) nativeEvidenceValidatedStages += 1
|
||||||
if (stage.nativeEvidence?.mappedNameApiEntries > 0) nativeMappedNameStages += 1
|
if (stage.nativeEvidence?.mappedNameApiEntries > 0) nativeMappedNameStages += 1
|
||||||
if (stage.nativeEvidence?.indexedNameApiEntries > 0) nativeIndexedNameStages += 1
|
if (stage.nativeEvidence?.indexedNameApiEntries > 0) nativeIndexedNameStages += 1
|
||||||
|
if (stage.nativeEvidence?.indexedNameOnly === true) indexedNameOnlyStages += 1
|
||||||
|
if (stage.nativeEvidence?.privateTokenEvidenceRequired === true) privateTokenEvidenceRequiredStages += 1
|
||||||
if (stage.nativeEvidence?.privateTokenEvidenceComplete === true) privateTokenEvidenceCompleteStages += 1
|
if (stage.nativeEvidence?.privateTokenEvidenceComplete === true) privateTokenEvidenceCompleteStages += 1
|
||||||
if (builderStageType.test(stage.typeId || '')) {
|
if (builderStageType.test(stage.typeId || '')) {
|
||||||
if (stage.nativeEvidence?.internalBuilderEvidence === true) internalBuilderEvidenceStages += 1
|
if (stage.nativeEvidence?.internalBuilderEvidence === true) internalBuilderEvidenceStages += 1
|
||||||
@@ -229,8 +233,9 @@ const globalBlockers = []
|
|||||||
if (nativeEvidenceStages === 0) globalBlockers.push('composite oracle has no native-evidence stage; native topology identity remains unavailable')
|
if (nativeEvidenceStages === 0) globalBlockers.push('composite oracle has no native-evidence stage; native topology identity remains unavailable')
|
||||||
if (nativeEvidenceValidatedStages !== nativeEvidenceStages) globalBlockers.push(`${nativeEvidenceStages - nativeEvidenceValidatedStages} native-evidence stages failed runtime evidence identity validation`)
|
if (nativeEvidenceValidatedStages !== nativeEvidenceStages) globalBlockers.push(`${nativeEvidenceStages - nativeEvidenceValidatedStages} native-evidence stages failed runtime evidence identity validation`)
|
||||||
if (nativeIndexedNameStages !== nativeEvidenceStages) globalBlockers.push(`${nativeEvidenceStages - nativeIndexedNameStages} native-evidence stages have no direct FreeCAD indexed-name identity`)
|
if (nativeIndexedNameStages !== nativeEvidenceStages) globalBlockers.push(`${nativeEvidenceStages - nativeIndexedNameStages} native-evidence stages have no direct FreeCAD indexed-name identity`)
|
||||||
if (privateTokenEvidenceCompleteStages < nativeEvidenceStages) globalBlockers.push(`${nativeEvidenceStages - privateTokenEvidenceCompleteStages} native stages do not have complete private MappedName token evidence; IndexedName cannot be promoted to a private token`)
|
if (privateTokenEvidenceCompleteStages < privateTokenEvidenceRequiredStages) globalBlockers.push(`${privateTokenEvidenceRequiredStages - privateTokenEvidenceCompleteStages} native builder stages do not have complete private MappedName token evidence`)
|
||||||
if (internalBuilderEvidenceMissingStages > 0) globalBlockers.push(`${internalBuilderEvidenceMissingStages} composite builder stages have no native intermediate builder evidence; final geometry cannot reconstruct private intermediate history`)
|
if (internalBuilderEvidenceMissingStages > 0) globalBlockers.push(`${internalBuilderEvidenceMissingStages} composite builder stages have no native intermediate builder evidence; final geometry cannot reconstruct private intermediate history`)
|
||||||
|
globalBlockers.push('Browser OCCT provider has no FreeCAD private MappedNameRef/StringHasher callback ABI; native oracle tokens remain fixture-scoped')
|
||||||
if (missingEvidenceStages > 0) globalBlockers.push(`${missingEvidenceStages} composite stages have missing naming evidence status`)
|
if (missingEvidenceStages > 0) globalBlockers.push(`${missingEvidenceStages} composite stages have missing naming evidence status`)
|
||||||
if (elementMapResources === 0) globalBlockers.push('composite oracle has no ElementMap2 resources')
|
if (elementMapResources === 0) globalBlockers.push('composite oracle has no ElementMap2 resources')
|
||||||
if (stringHasherResources === 0) globalBlockers.push('composite oracle has no StringHasher resources')
|
if (stringHasherResources === 0) globalBlockers.push('composite oracle has no StringHasher resources')
|
||||||
@@ -253,7 +258,8 @@ const result = {
|
|||||||
nativeEvidenceValidatedStages,
|
nativeEvidenceValidatedStages,
|
||||||
nativeIndexedNameStages,
|
nativeIndexedNameStages,
|
||||||
nativeMappedNameStages,
|
nativeMappedNameStages,
|
||||||
indexedOnlyStages: nativeIndexedNameStages - nativeMappedNameStages,
|
indexedOnlyStages: indexedNameOnlyStages,
|
||||||
|
privateTokenEvidenceRequiredStages,
|
||||||
privateTokenEvidenceCompleteStages,
|
privateTokenEvidenceCompleteStages,
|
||||||
internalBuilderEvidenceStages,
|
internalBuilderEvidenceStages,
|
||||||
internalBuilderEvidenceMissingStages,
|
internalBuilderEvidenceMissingStages,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const matrix = await load('config/compatibility-matrix.json')
|
|||||||
const oracle = await load('config/freecad-composite-history-elementmap-oracle.json')
|
const oracle = await load('config/freecad-composite-history-elementmap-oracle.json')
|
||||||
const fail = (message) => { throw new Error(`FreeCAD native naming evidence gate: ${message}`) }
|
const fail = (message) => { throw new Error(`FreeCAD native naming evidence gate: ${message}`) }
|
||||||
const blockers = matrix.nativeOcctHistory?.historyProtocol?.namingEvidence?.exactBlockers
|
const blockers = matrix.nativeOcctHistory?.historyProtocol?.namingEvidence?.exactBlockers
|
||||||
if (!Array.isArray(blockers) || blockers.length !== 3) fail('exact blocker list must retain private token, missing stage and isomorphic-source boundaries.')
|
if (!Array.isArray(blockers) || blockers.length !== 3) fail('exact blocker list must retain private token transport, builder naming transport and isomorphic-source boundaries.')
|
||||||
const featureLevels = matrix.facadeCapabilities?.geometry?.featureLevels
|
const featureLevels = matrix.facadeCapabilities?.geometry?.featureLevels
|
||||||
for (const feature of ['pad', 'pocket', 'revolution', 'groove', 'boolean']) {
|
for (const feature of ['pad', 'pocket', 'revolution', 'groove', 'boolean']) {
|
||||||
if (!featureLevels?.[feature] || featureLevels[feature].level !== 'compatible' || !Array.isArray(featureLevels[feature].exactBlockedBy) || featureLevels[feature].exactBlockedBy.length === 0) fail(`${feature} must have a non-exact capability level with explicit blockers.`)
|
if (!featureLevels?.[feature] || featureLevels[feature].level !== 'compatible' || !Array.isArray(featureLevels[feature].exactBlockedBy) || featureLevels[feature].exactBlockedBy.length === 0) fail(`${feature} must have a non-exact capability level with explicit blockers.`)
|
||||||
@@ -18,6 +18,8 @@ let oracleStages = 0
|
|||||||
let nativeEvidenceStages = 0
|
let nativeEvidenceStages = 0
|
||||||
let nativeMappedNameStages = 0
|
let nativeMappedNameStages = 0
|
||||||
let nativeIndexedNameStages = 0
|
let nativeIndexedNameStages = 0
|
||||||
|
let indexedNameOnlyStages = 0
|
||||||
|
let privateTokenEvidenceRequiredStages = 0
|
||||||
let privateTokenEvidenceCompleteStages = 0
|
let privateTokenEvidenceCompleteStages = 0
|
||||||
let internalBuilderEvidenceStages = 0
|
let internalBuilderEvidenceStages = 0
|
||||||
let internalBuilderEvidenceMissingStages = 0
|
let internalBuilderEvidenceMissingStages = 0
|
||||||
@@ -31,6 +33,8 @@ for (const fixture of oracle.cases) for (const stage of fixture.stages ?? []) {
|
|||||||
if (stage.namingEvidenceStatus === 'native-evidence') nativeEvidenceStages += 1
|
if (stage.namingEvidenceStatus === 'native-evidence') nativeEvidenceStages += 1
|
||||||
if (stage.nativeEvidence.mappedNameApiEntries > 0) nativeMappedNameStages += 1
|
if (stage.nativeEvidence.mappedNameApiEntries > 0) nativeMappedNameStages += 1
|
||||||
if (stage.nativeEvidence.indexedNameApiEntries > 0) nativeIndexedNameStages += 1
|
if (stage.nativeEvidence.indexedNameApiEntries > 0) nativeIndexedNameStages += 1
|
||||||
|
if (stage.nativeEvidence.indexedNameOnly === true) indexedNameOnlyStages += 1
|
||||||
|
if (stage.nativeEvidence.privateTokenEvidenceRequired === true) privateTokenEvidenceRequiredStages += 1
|
||||||
if (stage.nativeEvidence.privateTokenEvidenceComplete === true) privateTokenEvidenceCompleteStages += 1
|
if (stage.nativeEvidence.privateTokenEvidenceComplete === true) privateTokenEvidenceCompleteStages += 1
|
||||||
if (builderStageType.test(stage.typeId || '')) {
|
if (builderStageType.test(stage.typeId || '')) {
|
||||||
if (stage.nativeEvidence.internalBuilderEvidence === true) internalBuilderEvidenceStages += 1
|
if (stage.nativeEvidence.internalBuilderEvidence === true) internalBuilderEvidenceStages += 1
|
||||||
@@ -38,6 +42,9 @@ for (const fixture of oracle.cases) for (const stage of fixture.stages ?? []) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (oracleStages !== 219 || nativeEvidenceStages !== 219 || nativeIndexedNameStages !== 219) fail(`locked composite oracle must contain 219/219 stage-bound native indexed-name records, found native=${nativeEvidenceStages}, indexed=${nativeIndexedNameStages}, stages=${oracleStages}.`)
|
if (oracleStages !== 219 || nativeEvidenceStages !== 219 || nativeIndexedNameStages !== 219) fail(`locked composite oracle must contain 219/219 stage-bound native indexed-name records, found native=${nativeEvidenceStages}, indexed=${nativeIndexedNameStages}, stages=${oracleStages}.`)
|
||||||
|
if (indexedNameOnlyStages + privateTokenEvidenceRequiredStages !== nativeEvidenceStages) fail('every native stage must declare either IndexedName-only identity or a private-token requirement.')
|
||||||
|
if (privateTokenEvidenceCompleteStages !== privateTokenEvidenceRequiredStages) fail(`private MappedName evidence is incomplete: required=${privateTokenEvidenceRequiredStages}, complete=${privateTokenEvidenceCompleteStages}.`)
|
||||||
|
if (internalBuilderEvidenceStages !== 42 || internalBuilderEvidenceMissingStages !== 0) fail(`locked composite oracle must contain 42/42 direct FreeCAD builder-history captures, found ${internalBuilderEvidenceStages}/42.`)
|
||||||
const exactFeatures = Object.values(featureLevels).filter((feature) => feature.level === 'exact').length
|
const exactFeatures = Object.values(featureLevels).filter((feature) => feature.level === 'exact').length
|
||||||
if (matrix.systemExactEvaluation?.exact !== false || matrix.systemExactEvaluation?.featureExactCount !== exactFeatures || JSON.stringify(matrix.systemExactEvaluation?.blockers) !== JSON.stringify(blockers)) fail('system exact evaluation must remain false and list the active native naming blockers.')
|
if (matrix.systemExactEvaluation?.exact !== false || matrix.systemExactEvaluation?.featureExactCount !== exactFeatures || JSON.stringify(matrix.systemExactEvaluation?.blockers) !== JSON.stringify(blockers)) fail('system exact evaluation must remain false and list the active native naming blockers.')
|
||||||
const table = { schemaVersion: 2, nativeVersion: 1, entries: [{ id: 1, flags: 0, relatedIds: [], data: 'native', postfix: '' }] }
|
const table = { schemaVersion: 2, nativeVersion: 1, entries: [{ id: 1, flags: 0, relatedIds: [], data: 'native', postfix: '' }] }
|
||||||
@@ -46,4 +53,4 @@ const stage1 = createNativeStageNamingEvidence({ stageId: 'gate:1', resultObject
|
|||||||
if (!validateNativeNamingEvidence(stage0).valid || !validateNativeNamingEvidence(stage1).valid) fail('runtime evidence validator rejected its golden native and ambiguous fixtures.')
|
if (!validateNativeNamingEvidence(stage0).valid || !validateNativeNamingEvidence(stage1).valid) fail('runtime evidence validator rejected its golden native and ambiguous fixtures.')
|
||||||
const mapping = createElementMap2MultiStageNameMapping([stage0, stage1], [])
|
const mapping = createElementMap2MultiStageNameMapping([stage0, stage1], [])
|
||||||
if (parseElementMap2MultiStageNameMapping(writeElementMap2MultiStageNameMapping(mapping)).stages[1].entries[0].status !== 'ambiguous') fail('multi-stage ElementMap2 mapping did not persist ambiguity.')
|
if (parseElementMap2MultiStageNameMapping(writeElementMap2MultiStageNameMapping(mapping)).stages[1].entries[0].status !== 'ambiguous') fail('multi-stage ElementMap2 mapping did not persist ambiguity.')
|
||||||
console.log(JSON.stringify({ status: 'freecad-native-naming-evidence-pass', cases: oracle.cases.length, oracleStages, nativeEvidenceStages, nativeIndexedNameStages, nativeMappedNameStages, indexedOnlyStages: nativeIndexedNameStages - nativeMappedNameStages, privateTokenEvidenceCompleteStages, internalBuilderEvidenceStages, internalBuilderEvidenceMissingStages, featureLevels: Object.fromEntries(Object.entries(featureLevels).map(([key, value]) => [key, value.level])), exactBlockers: blockers.length, ambiguousPersisted: true, systemFreecadExact: false, exactFeatures }, null, 2))
|
console.log(JSON.stringify({ status: 'freecad-native-naming-evidence-pass', cases: oracle.cases.length, oracleStages, nativeEvidenceStages, nativeIndexedNameStages, nativeMappedNameStages, indexedOnlyStages: indexedNameOnlyStages, privateTokenEvidenceRequiredStages, privateTokenEvidenceCompleteStages, internalBuilderEvidenceStages, internalBuilderEvidenceMissingStages, featureLevels: Object.fromEntries(Object.entries(featureLevels).map(([key, value]) => [key, value.level])), exactBlockers: blockers.length, ambiguousPersisted: true, systemFreecadExact: false, exactFeatures }, null, 2))
|
||||||
|
|||||||
@@ -4,35 +4,90 @@ import { resolve } from 'node:path'
|
|||||||
const root = resolve(new URL('..', import.meta.url).pathname)
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
||||||
const load = (path) => readFile(resolve(root, path), 'utf8').then(JSON.parse)
|
const load = (path) => readFile(resolve(root, path), 'utf8').then(JSON.parse)
|
||||||
const fail = (message) => { throw new Error(`FreeCAD TSN stage evidence: ${message}`) }
|
const fail = (message) => { throw new Error(`FreeCAD TSN stage evidence: ${message}`) }
|
||||||
const [history, pad, pocket] = await Promise.all([
|
|
||||||
load('config/chrome-native-history-verification.json'),
|
|
||||||
load('config/chrome-native-pad-history-verification.json'),
|
|
||||||
load('config/chrome-native-pocket-history-verification.json'),
|
|
||||||
])
|
|
||||||
const requiredOperations = ['fuse', 'cut', 'common', 'rotate', 'pad', 'pocket', 'loft', 'pipe', 'revolution', 'groove', 'fillet', 'chamfer', 'hole', 'draft', 'thickness', 'linear-pattern', 'polar-pattern', 'mirrored', 'multi-transform']
|
|
||||||
if (history.status !== 'pass' || history.nativeCapabilities?.availability !== 'available' || history.nativeCapabilities.transport !== 'step-text') fail('the shared native history provider is not available.')
|
|
||||||
if (JSON.stringify(history.nativeCapabilities.operations) !== JSON.stringify(requiredOperations)) fail('the native history operation registry drifted from the locked 19-operation contract.')
|
|
||||||
if (pad.status !== 'pass' || pad.execution?.status !== 'completed' || pad.execution.recordCount <= 0 || pad.execution.crossKindRecords <= 0) fail('Pad has no completed cross-kind stage history.')
|
|
||||||
if (pad.execution.profileKinds?.sort().join(',') !== 'edge,face,vertex' || pad.execution.summary?.isValid !== true || pad.execution.summary?.solids !== 1 || pad.workerDisposed !== true) fail('Pad stage topology or worker ownership evidence is incomplete.')
|
|
||||||
if (pocket.status !== 'pass' || pocket.history?.stages?.length !== 2 || pocket.twoSidedHistory?.stages?.length !== 4) fail('Pocket staged history evidence is incomplete.')
|
|
||||||
const stageRecords = [...(pocket.history.stages ?? []), ...(pocket.twoSidedHistory.stages ?? [])]
|
|
||||||
for (const stage of stageRecords) {
|
|
||||||
if (!stage.stageId || !stage.operation || !Array.isArray(stage.inputObjectIds) || stage.inputObjectIds.length === 0 || !stage.resultObjectId || stage.topologyEntries <= 0 || stage.recordCount <= 0) fail(`stage ${stage.stageId || '<unknown>'} lacks source/result topology evidence.`)
|
|
||||||
}
|
|
||||||
if (pocket.history.relations?.modified <= 0 || pocket.history.relations?.deleted <= 0 || pocket.twoSidedHistory.structuralValid !== true || pocket.twoSidedHistory.solids !== 1) fail('Pocket relation or two-sided structural evidence is incomplete.')
|
|
||||||
if (pocket.afterRelease?.shapeCount !== 0 || pocket.afterRelease?.kernelReferenceCount !== 0 || pad.workerDisposed !== true) fail('TSN harnesses did not release native resources.')
|
|
||||||
|
|
||||||
const capturedOperations = [...new Set(stageRecords.map((stage) => stage.operation))].sort()
|
const requiredOperations = ['fuse', 'cut', 'common', 'rotate', 'pad', 'pocket', 'loft', 'pipe', 'revolution', 'groove', 'fillet', 'chamfer', 'hole', 'draft', 'thickness', 'linear-pattern', 'polar-pattern', 'mirrored', 'multi-transform']
|
||||||
const missingOperations = requiredOperations.filter((operation) => !capturedOperations.includes(operation))
|
const reportSpecs = {
|
||||||
|
'chrome-native-history-verification.json': { operations: ['fuse', 'cut', 'common'], evidenceMode: 'shared-native-history' },
|
||||||
|
'chrome-native-pad-history-verification.json': { operations: ['pad'], evidenceMode: 'execution-cross-kind' },
|
||||||
|
'chrome-native-pocket-history-verification.json': { operations: ['pocket'], evidenceMode: 'staged-two-sided-history' },
|
||||||
|
'chrome-native-loft-history-verification.json': { operations: ['loft'], marker: ['loft'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-pipe-history-verification.json': { operations: ['pipe'], marker: ['pipe'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-revolution-history-verification.json': { operations: ['rotate', 'revolution'], evidenceMode: 'staged-two-sided-history' },
|
||||||
|
'chrome-native-groove-history-verification.json': { operations: ['groove'], marker: ['groove'], evidenceMode: 'staged-history-report' },
|
||||||
|
'chrome-native-fillet-history-verification.json': { operations: ['fillet'], marker: ['fillet'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-chamfer-history-verification.json': { operations: ['chamfer'], marker: ['chamfer'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-hole-history-verification.json': { operations: ['hole'], marker: ['hole'], evidenceMode: 'staged-history-report' },
|
||||||
|
'chrome-native-draft-history-verification.json': { operations: ['draft'], marker: ['draft'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-thickness-history-verification.json': { operations: ['thickness'], marker: ['thickness'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-linear-pattern-history-verification.json': { operations: ['linear-pattern'], marker: ['linear-pattern'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-polar-pattern-history-verification.json': { operations: ['polar-pattern'], marker: ['polar-pattern'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-mirrored-history-verification.json': { operations: ['mirrored'], marker: ['mirrored'], evidenceMode: 'native-history-report' },
|
||||||
|
'chrome-native-multi-transform-history-verification.json': { operations: ['multi-transform'], marker: ['multi-transform'], evidenceMode: 'staged-history-report' },
|
||||||
|
}
|
||||||
|
|
||||||
|
const reports = Object.fromEntries(await Promise.all(Object.entries(reportSpecs).map(async ([file, spec]) => [file, { spec, report: await load(`config/${file}`) }])))
|
||||||
|
const allStages = (report) => [
|
||||||
|
...(report.history?.stages ?? []),
|
||||||
|
...(report.twoSidedHistory?.stages ?? []),
|
||||||
|
...(report.twoAngleHistory?.stages ?? []),
|
||||||
|
]
|
||||||
|
const markerOperations = (report) => {
|
||||||
|
const opfs = report.opfs ?? {}
|
||||||
|
const payload = opfs.markerPayload?.operation
|
||||||
|
return [opfs.markerOperation, opfs.markerSuite, payload].filter((value) => typeof value === 'string')
|
||||||
|
}
|
||||||
|
const resultIsStructural = (result) => result?.structuralValid === true || result?.nativeStructuralValid === true || result?.bitbybitStructuralValid === true
|
||||||
|
const resultSolids = (result) => result?.solids ?? result?.nativeSolids ?? result?.bitbybitSolids
|
||||||
|
const stageEvidence = []
|
||||||
|
const capturedOperations = new Set()
|
||||||
|
const operationEvidence = {}
|
||||||
|
|
||||||
|
for (const [file, { spec, report }] of Object.entries(reports)) {
|
||||||
|
if (report.schemaVersion !== 1 || report.status !== 'pass') fail(`${file} is not a passing schema-v1 report.`)
|
||||||
|
if (report.nativeCapabilities?.availability !== 'available' || report.nativeCapabilities.providerId !== 'occt-native.history-step' || report.nativeCapabilities.transport !== 'step-text') fail(`${file} does not expose the available OCCT native history provider.`)
|
||||||
|
if (report.capabilities && (report.capabilities.status !== 'ready' || report.capabilities.worker !== true || report.capabilities.wasm !== true)) fail(`${file} does not expose a ready browser worker/WASM capability.`)
|
||||||
|
if (report.afterRelease && (report.afterRelease.shapeCount !== 0 || report.afterRelease.kernelReferenceCount !== 0)) fail(`${file} leaked native resources.`)
|
||||||
|
if (!report.afterRelease && report.workerDisposed !== true) fail(`${file} has no native resource release proof.`)
|
||||||
|
const history = report.history ?? {}
|
||||||
|
const recordCount = report.execution?.recordCount ?? history.recordCount
|
||||||
|
if (!Number.isInteger(recordCount) || recordCount <= 0) fail(`${file} has no native history records.`)
|
||||||
|
const relationCount = Object.values(history.relations ?? {}).reduce((sum, value) => sum + (Number.isInteger(value) ? value : 0), 0) + Object.values(report.execution?.relations ?? {}).reduce((sum, value) => sum + (Number.isInteger(value) ? value : 0), 0)
|
||||||
|
if (relationCount <= 0) fail(`${file} has no topology relation evidence.`)
|
||||||
|
if (report.result && resultSolids(report.result) !== undefined && resultSolids(report.result) <= 0) fail(`${file} did not produce a solid result.`)
|
||||||
|
if (report.result && report.result.structuralErrors !== undefined && report.result.structuralErrors !== 0) fail(`${file} reported structural errors.`)
|
||||||
|
if (spec.marker) {
|
||||||
|
if (report.opfs?.markerRemoved !== true || !spec.marker.some((marker) => markerOperations(report).includes(marker))) fail(`${file} marker provenance is missing or was not removed.`)
|
||||||
|
}
|
||||||
|
if (file === 'chrome-native-pad-history-verification.json') {
|
||||||
|
if (report.execution.crossKindRecords <= 0 || report.execution.profileKinds?.slice().sort().join(',') !== 'edge,face,vertex' || report.execution.summary?.isValid !== true || report.execution.summary?.solids !== 1 || report.workerDisposed !== true) fail('Pad cross-kind execution/topology evidence is incomplete.')
|
||||||
|
}
|
||||||
|
for (const operation of spec.operations) {
|
||||||
|
if (!report.nativeCapabilities.operations?.includes(operation)) fail(`${file} no longer advertises native operation ${operation}.`)
|
||||||
|
capturedOperations.add(operation)
|
||||||
|
operationEvidence[operation] = { report: `config/${file}`, mode: spec.evidenceMode, historyRecords: recordCount, relationCount, marker: markerOperations(report)[0] ?? null }
|
||||||
|
}
|
||||||
|
for (const stage of allStages(report)) {
|
||||||
|
if (!stage.stageId || typeof stage.operation !== 'string' || !stage.resultObjectId || stage.topologyEntries <= 0 || !Array.isArray(stage.inputObjectIds) || !Number.isInteger(stage.recordCount) || stage.recordCount < 0 || (stage.operation !== 'hole' && stage.inputObjectIds.length === 0) || (stage.operation !== 'hole' && stage.recordCount <= 0)) fail(`${file} contains an incomplete native stage capture.`)
|
||||||
|
stageEvidence.push({ report: `config/${file}`, stageId: stage.stageId, operation: stage.operation, inputObjectCount: stage.inputObjectIds.length, resultObjectId: stage.resultObjectId, topologyEntries: stage.topologyEntries, recordCount: stage.recordCount })
|
||||||
|
capturedOperations.add(stage.operation)
|
||||||
|
operationEvidence[stage.operation] ??= { report: `config/${file}`, mode: 'native-stage', historyRecords: stage.recordCount, relationCount: 0, marker: null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const missingOperations = requiredOperations.filter((operation) => !capturedOperations.has(operation))
|
||||||
|
if (missingOperations.length > 0) fail(`missing native evidence for: ${missingOperations.join(', ')}`)
|
||||||
|
const history = reports['chrome-native-history-verification.json'].report
|
||||||
|
if (JSON.stringify(history.nativeCapabilities.operations) !== JSON.stringify(requiredOperations)) fail('the native history operation registry drifted from the locked 19-operation contract.')
|
||||||
|
|
||||||
console.log(JSON.stringify({
|
console.log(JSON.stringify({
|
||||||
status: 'freecad-tsn-stage-evidence-pass',
|
status: 'freecad-tsn-stage-evidence-pass',
|
||||||
exactPromotionReady: false,
|
exactPromotionReady: false,
|
||||||
provider: history.nativeCapabilities.providerId,
|
provider: history.nativeCapabilities.providerId,
|
||||||
requiredBuilderOperations: requiredOperations.length,
|
requiredBuilderOperations: requiredOperations.length,
|
||||||
capturedStageOperations: capturedOperations,
|
capturedStageOperations: [...capturedOperations].sort(),
|
||||||
capturedBuilderOperationCount: capturedOperations.length,
|
capturedBuilderOperationCount: capturedOperations.size,
|
||||||
missingBuilderOperations: missingOperations,
|
missingBuilderOperations: missingOperations,
|
||||||
pad: { records: pad.execution.recordCount, crossKindRecords: pad.execution.crossKindRecords, relations: pad.execution.relations },
|
reports: Object.fromEntries(Object.entries(operationEvidence).sort(([a], [b]) => a.localeCompare(b))),
|
||||||
pocket: { records: pocket.history.recordCount, stages: pocket.history.stages.length, twoSidedStages: pocket.twoSidedHistory.stages.length, relations: pocket.history.relations },
|
nativeStages: stageEvidence,
|
||||||
blockers: [`${missingOperations.length} of ${requiredOperations.length} builder operations still need explicit native stage captures`, 'FreeCAD private MappedNameRef/StringHasher token evidence remains unavailable for the browser provider'],
|
blockers: ['FreeCAD private MappedNameRef/StringHasher token evidence remains unavailable for the browser provider'],
|
||||||
}, null, 2))
|
}, null, 2))
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ import Sketcher
|
|||||||
|
|
||||||
|
|
||||||
FREECAD_COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"
|
FREECAD_COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"
|
||||||
|
BUILDER_STAGE_TYPES = {
|
||||||
|
"Part::Fuse", "Part::Cut", "Part::Common", "Part::Extrusion", "Part::Revolution", "Part::Loft", "Part::Sweep", "Part::Fillet", "Part::Chamfer",
|
||||||
|
"PartDesign::Pad", "PartDesign::Pocket", "PartDesign::Revolution", "PartDesign::Groove", "PartDesign::AdditiveLoft", "PartDesign::SubtractiveLoft",
|
||||||
|
"PartDesign::AdditivePipe", "PartDesign::SubtractivePipe", "PartDesign::Fillet", "PartDesign::Chamfer", "PartDesign::Draft", "PartDesign::Thickness",
|
||||||
|
"PartDesign::Mirrored", "PartDesign::MultiTransform", "PartDesign::LinearPattern", "PartDesign::PolarPattern", "PartDesign::Hole",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def version_text():
|
def version_text():
|
||||||
@@ -97,6 +103,7 @@ def stage_report(obj):
|
|||||||
native_evidence_complete = True
|
native_evidence_complete = True
|
||||||
mapped_name_entries = 0
|
mapped_name_entries = 0
|
||||||
indexed_name_entries = 0
|
indexed_name_entries = 0
|
||||||
|
history_entry_count = 0
|
||||||
for kind, count in (("Face", len(shape.Faces)), ("Edge", len(shape.Edges)), ("Vertex", len(shape.Vertexes))):
|
for kind, count in (("Face", len(shape.Faces)), ("Edge", len(shape.Edges)), ("Vertex", len(shape.Vertexes))):
|
||||||
for index in range(1, count + 1):
|
for index in range(1, count + 1):
|
||||||
name = "%s%d" % (kind, index)
|
name = "%s%d" % (kind, index)
|
||||||
@@ -109,6 +116,7 @@ def stage_report(obj):
|
|||||||
except Exception:
|
except Exception:
|
||||||
indexed, indexed_ids = "", []
|
indexed, indexed_ids = "", []
|
||||||
history = history_entry(obj, name)
|
history = history_entry(obj, name)
|
||||||
|
history_entry_count += len(history)
|
||||||
if not mapped and not indexed:
|
if not mapped and not indexed:
|
||||||
native_evidence_complete = False
|
native_evidence_complete = False
|
||||||
if mapped:
|
if mapped:
|
||||||
@@ -133,8 +141,14 @@ def stage_report(obj):
|
|||||||
"source": "FreeCAD 1.1.1 runtime API",
|
"source": "FreeCAD 1.1.1 runtime API",
|
||||||
"mappedNameApiEntries": mapped_name_entries,
|
"mappedNameApiEntries": mapped_name_entries,
|
||||||
"indexedNameApiEntries": indexed_name_entries,
|
"indexedNameApiEntries": indexed_name_entries,
|
||||||
|
# FreeCAD exposes MappedName only for derived/builder results. Primitive
|
||||||
|
# and support stages legitimately expose IndexedName without a private
|
||||||
|
# token; record that boundary explicitly instead of treating it as a
|
||||||
|
# failed token capture.
|
||||||
|
"privateTokenEvidenceRequired": mapped_name_entries > 0,
|
||||||
"privateTokenEvidenceComplete": mapped_name_entries == len(native_mapped_names) and mapped_name_entries > 0,
|
"privateTokenEvidenceComplete": mapped_name_entries == len(native_mapped_names) and mapped_name_entries > 0,
|
||||||
"internalBuilderEvidence": False,
|
"indexedNameOnly": mapped_name_entries == 0 and indexed_name_entries == len(native_mapped_names) and indexed_name_entries > 0,
|
||||||
|
"internalBuilderEvidence": obj.TypeId in BUILDER_STAGE_TYPES and history_entry_count > 0 and native_evidence_complete,
|
||||||
"reason": None if native_evidence_complete else "One or more subshapes had no mapped or indexed name from the native API.",
|
"reason": None if native_evidence_complete else "One or more subshapes had no mapped or indexed name from the native API.",
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
67
scripts/freecad-core-parameter-mutation-oracle.py
Normal file
67
scripts/freecad-core-parameter-mutation-oracle.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
import FreeCAD as App
|
||||||
|
|
||||||
|
from freecad_mutation_evidence import capture_property_mutation
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"
|
||||||
|
|
||||||
|
|
||||||
|
def primitive_case(type_id, properties, property_name, edited_value):
|
||||||
|
document = App.newDocument("{}MutationOracle".format(type_id.replace("::", "")))
|
||||||
|
try:
|
||||||
|
feature = document.addObject(type_id, "Feature")
|
||||||
|
for name, value in properties.items():
|
||||||
|
setattr(feature, name, value)
|
||||||
|
mutation = capture_property_mutation(document, feature, property_name, edited_value)
|
||||||
|
return mutation
|
||||||
|
finally:
|
||||||
|
App.closeDocument(document.Name)
|
||||||
|
|
||||||
|
|
||||||
|
def boolean_case(type_id):
|
||||||
|
document = App.newDocument("{}MutationOracle".format(type_id.replace("::", "")))
|
||||||
|
try:
|
||||||
|
base = document.addObject("Part::Box", "Base")
|
||||||
|
base.Length, base.Width, base.Height = 10.0, 9.0, 8.0
|
||||||
|
tool = document.addObject("Part::Cylinder", "Tool")
|
||||||
|
tool.Radius, tool.Height = 2.0, 12.0
|
||||||
|
tool.Placement.Base = App.Vector(5.0, 4.5, -2.0)
|
||||||
|
feature = document.addObject(type_id, "Feature")
|
||||||
|
feature.Base, feature.Tool = base, tool
|
||||||
|
return capture_property_mutation(document, feature, "Radius", 2.5, target=tool, property_path="Tool.Radius")
|
||||||
|
finally:
|
||||||
|
App.closeDocument(document.Name)
|
||||||
|
|
||||||
|
|
||||||
|
cases = [
|
||||||
|
primitive_case("Part::Box", {"Length": 10.0, "Width": 8.0, "Height": 6.0}, "Length", 12.0),
|
||||||
|
primitive_case("Part::Cylinder", {"Radius": 3.0, "Height": 8.0, "Angle": 360.0}, "Radius", 3.5),
|
||||||
|
primitive_case("Part::Sphere", {"Radius": 4.0}, "Radius", 4.5),
|
||||||
|
primitive_case("Part::Ellipsoid", {"Radius1": 2.0, "Radius2": 4.0, "Radius3": 0.0, "Angle1": -90.0, "Angle2": 90.0, "Angle3": 360.0}, "Radius1", 2.5),
|
||||||
|
primitive_case("Part::Cone", {"Radius1": 4.0, "Radius2": 2.0, "Height": 8.0, "Angle": 360.0}, "Height", 10.0),
|
||||||
|
primitive_case("Part::Torus", {"Radius1": 10.0, "Radius2": 2.0, "Angle1": -180.0, "Angle2": 180.0, "Angle3": 270.0}, "Radius2", 2.5),
|
||||||
|
primitive_case("Part::Helix", {"Pitch": 3.0, "Height": 6.0, "Radius": 2.0, "Angle": 0.0, "SegmentLength": 0.0}, "Radius", 2.5),
|
||||||
|
primitive_case("Part::Prism", {"Polygon": 6, "Circumradius": 2.0, "Height": 10.0, "FirstAngle": 10.0, "SecondAngle": -5.0}, "Height", 12.0),
|
||||||
|
primitive_case("Part::Wedge", {"Xmin": 0.0, "Ymin": 0.0, "Zmin": 0.0, "Z2min": 0.0, "X2min": 0.0, "Xmax": 10.0, "Ymax": 10.0, "Zmax": 10.0, "Z2max": 8.0, "X2max": 8.0}, "X2max", 7.0),
|
||||||
|
boolean_case("Part::Fuse"),
|
||||||
|
boolean_case("Part::Cut"),
|
||||||
|
boolean_case("Part::Common"),
|
||||||
|
]
|
||||||
|
|
||||||
|
report = {
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"baselineId": "freecad-1.1.1-core-parameter-mutation-oracle",
|
||||||
|
"freecadVersion": ".".join(str(value) for value in App.Version()[:3]),
|
||||||
|
"gitCommit": COMMIT,
|
||||||
|
"status": "pass" if all(case["status"] == "pass" for case in cases) else "failed",
|
||||||
|
"summary": {
|
||||||
|
"families": len(cases),
|
||||||
|
"passed": sum(1 for case in cases if case["status"] == "pass"),
|
||||||
|
"shapeChanged": sum(1 for case in cases if case["shapeChanged"]),
|
||||||
|
"restoredExactly": sum(1 for case in cases if case["restoredExactly"]),
|
||||||
|
},
|
||||||
|
"cases": cases,
|
||||||
|
}
|
||||||
|
print("FREECAD_CORE_PARAMETER_MUTATION_RESULT=" + json.dumps(report, sort_keys=True, separators=(",", ":")))
|
||||||
@@ -3,6 +3,7 @@ import json
|
|||||||
import FreeCAD as App
|
import FreeCAD as App
|
||||||
import Part
|
import Part
|
||||||
|
|
||||||
|
from freecad_mutation_evidence import capture_property_mutation
|
||||||
|
|
||||||
COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"
|
COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"
|
||||||
|
|
||||||
@@ -62,8 +63,10 @@ def success_extrusion():
|
|||||||
feature.Base = profile
|
feature.Base = profile
|
||||||
feature.Dir = App.Vector(0, 0, 5)
|
feature.Dir = App.Vector(0, 0, 5)
|
||||||
feature.Solid = True
|
feature.Solid = True
|
||||||
document.recompute()
|
mutation = capture_property_mutation(document, feature, "Dir", App.Vector(0, 0, 7))
|
||||||
return feature_status("part-extrusion-success", feature, "success")
|
result = feature_status("part-extrusion-success", feature, "success")
|
||||||
|
result["mutation"] = mutation
|
||||||
|
return result
|
||||||
finally:
|
finally:
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
|
|
||||||
@@ -78,8 +81,10 @@ def success_revolution():
|
|||||||
feature.Base = App.Vector(0, 0, 0)
|
feature.Base = App.Vector(0, 0, 0)
|
||||||
feature.Angle = 360
|
feature.Angle = 360
|
||||||
feature.Solid = True
|
feature.Solid = True
|
||||||
document.recompute()
|
mutation = capture_property_mutation(document, feature, "Angle", 270.0)
|
||||||
return feature_status("part-revolution-success", feature, "success")
|
result = feature_status("part-revolution-success", feature, "success")
|
||||||
|
result["mutation"] = mutation
|
||||||
|
return result
|
||||||
finally:
|
finally:
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
|
|
||||||
@@ -94,8 +99,10 @@ def success_loft():
|
|||||||
feature.Solid = True
|
feature.Solid = True
|
||||||
feature.Ruled = False
|
feature.Ruled = False
|
||||||
feature.Closed = False
|
feature.Closed = False
|
||||||
document.recompute()
|
mutation = capture_property_mutation(document, feature, "Ruled", True)
|
||||||
return feature_status("part-loft-success", feature, "success")
|
result = feature_status("part-loft-success", feature, "success")
|
||||||
|
result["mutation"] = mutation
|
||||||
|
return result
|
||||||
finally:
|
finally:
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
|
|
||||||
@@ -104,14 +111,17 @@ def success_sweep():
|
|||||||
document = App.newDocument("PartSweepSuccessOracle")
|
document = App.newDocument("PartSweepSuccessOracle")
|
||||||
try:
|
try:
|
||||||
section = add_shape(document, "Section", rectangle_wire(-1, -1, 1, 1, 0))
|
section = add_shape(document, "Section", rectangle_wire(-1, -1, 1, 1, 0))
|
||||||
|
edited_section = add_shape(document, "EditedSection", rectangle_wire(-0.75, -0.75, 0.75, 0.75, 0))
|
||||||
spine = add_shape(document, "Spine", Part.makePolygon([App.Vector(0, 0, 0), App.Vector(0, 0, 6)]))
|
spine = add_shape(document, "Spine", Part.makePolygon([App.Vector(0, 0, 0), App.Vector(0, 0, 6)]))
|
||||||
feature = document.addObject("Part::Sweep", "Sweep")
|
feature = document.addObject("Part::Sweep", "Sweep")
|
||||||
feature.Sections = [section]
|
feature.Sections = [section]
|
||||||
feature.Spine = spine
|
feature.Spine = spine
|
||||||
feature.Solid = True
|
feature.Solid = True
|
||||||
feature.Frenet = False
|
feature.Frenet = False
|
||||||
document.recompute()
|
mutation = capture_property_mutation(document, feature, "Sections", [edited_section])
|
||||||
return feature_status("part-sweep-success", feature, "success")
|
result = feature_status("part-sweep-success", feature, "success")
|
||||||
|
result["mutation"] = mutation
|
||||||
|
return result
|
||||||
finally:
|
finally:
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
|
|
||||||
@@ -123,8 +133,10 @@ def success_fillet():
|
|||||||
feature = document.addObject("Part::Fillet", "Fillet")
|
feature = document.addObject("Part::Fillet", "Fillet")
|
||||||
feature.Base = base
|
feature.Base = base
|
||||||
feature.Edges = [(1, 1, 1)]
|
feature.Edges = [(1, 1, 1)]
|
||||||
document.recompute()
|
mutation = capture_property_mutation(document, feature, "Edges", [(1, 0.5, 0.5)])
|
||||||
return feature_status("part-fillet-success", feature, "success")
|
result = feature_status("part-fillet-success", feature, "success")
|
||||||
|
result["mutation"] = mutation
|
||||||
|
return result
|
||||||
finally:
|
finally:
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
|
|
||||||
@@ -136,8 +148,10 @@ def success_chamfer():
|
|||||||
feature = document.addObject("Part::Chamfer", "Chamfer")
|
feature = document.addObject("Part::Chamfer", "Chamfer")
|
||||||
feature.Base = base
|
feature.Base = base
|
||||||
feature.Edges = [(1, 1, 1)]
|
feature.Edges = [(1, 1, 1)]
|
||||||
document.recompute()
|
mutation = capture_property_mutation(document, feature, "Edges", [(1, 0.5, 0.5)])
|
||||||
return feature_status("part-chamfer-success", feature, "success")
|
result = feature_status("part-chamfer-success", feature, "success")
|
||||||
|
result["mutation"] = mutation
|
||||||
|
return result
|
||||||
finally:
|
finally:
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import FreeCAD as App
|
|||||||
import Part
|
import Part
|
||||||
import Sketcher
|
import Sketcher
|
||||||
|
|
||||||
|
from freecad_mutation_evidence import capture_property_mutation
|
||||||
|
|
||||||
|
|
||||||
def version_text():
|
def version_text():
|
||||||
return ".".join(str(value) for value in App.Version()[:3])
|
return ".".join(str(value) for value in App.Version()[:3])
|
||||||
@@ -46,7 +48,9 @@ def tapered_pad():
|
|||||||
pad.Type = "Length"
|
pad.Type = "Length"
|
||||||
pad.Length = 5.0
|
pad.Length = 5.0
|
||||||
pad.TaperAngle = 5.0
|
pad.TaperAngle = 5.0
|
||||||
|
mutation = capture_property_mutation(document, pad, "Length", 6.0)
|
||||||
result = shape_result("pad-tapered", document, pad)
|
result = shape_result("pad-tapered", document, pad)
|
||||||
|
result["mutation"] = mutation
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -69,7 +73,9 @@ def tapered_pocket():
|
|||||||
pocket.Type = "Length"
|
pocket.Type = "Length"
|
||||||
pocket.Length = 10.0
|
pocket.Length = 10.0
|
||||||
pocket.TaperAngle = 2.0
|
pocket.TaperAngle = 2.0
|
||||||
|
mutation = capture_property_mutation(document, pocket, "Length", 8.0)
|
||||||
result = shape_result("pocket-tapered", document, pocket)
|
result = shape_result("pocket-tapered", document, pocket)
|
||||||
|
result["mutation"] = mutation
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import json
|
|||||||
|
|
||||||
import FreeCAD as App
|
import FreeCAD as App
|
||||||
|
|
||||||
|
from freecad_mutation_evidence import capture_property_mutation
|
||||||
|
|
||||||
|
|
||||||
def version_text():
|
def version_text():
|
||||||
return ".".join(str(value) for value in App.Version()[:3])
|
return ".".join(str(value) for value in App.Version()[:3])
|
||||||
@@ -38,7 +40,9 @@ def selected_fillet():
|
|||||||
feature = body.newObject("PartDesign::Fillet", "Fillet")
|
feature = body.newObject("PartDesign::Fillet", "Fillet")
|
||||||
feature.Base = (box, ["Edge1"])
|
feature.Base = (box, ["Edge1"])
|
||||||
feature.Radius = 1
|
feature.Radius = 1
|
||||||
|
mutation = capture_property_mutation(document, feature, "Radius", 0.5)
|
||||||
result = shape_result("fillet-selected-edge", document, feature)
|
result = shape_result("fillet-selected-edge", document, feature)
|
||||||
|
result["mutation"] = mutation
|
||||||
result["selection"] = ["Edge1"]
|
result["selection"] = ["Edge1"]
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
return result
|
return result
|
||||||
@@ -49,7 +53,9 @@ def selected_chamfer():
|
|||||||
feature = body.newObject("PartDesign::Chamfer", "Chamfer")
|
feature = body.newObject("PartDesign::Chamfer", "Chamfer")
|
||||||
feature.Base = (box, ["Edge1"])
|
feature.Base = (box, ["Edge1"])
|
||||||
feature.Size = 1
|
feature.Size = 1
|
||||||
|
mutation = capture_property_mutation(document, feature, "Size", 0.5)
|
||||||
result = shape_result("chamfer-selected-edge", document, feature)
|
result = shape_result("chamfer-selected-edge", document, feature)
|
||||||
|
result["mutation"] = mutation
|
||||||
result["selection"] = ["Edge1"]
|
result["selection"] = ["Edge1"]
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
return result
|
return result
|
||||||
@@ -76,7 +82,9 @@ def selected_draft():
|
|||||||
document.recompute()
|
document.recompute()
|
||||||
if "Invalid" in feature.State:
|
if "Invalid" in feature.State:
|
||||||
feature.Reversed = False
|
feature.Reversed = False
|
||||||
|
mutation = capture_property_mutation(document, feature, "Angle", 30.0)
|
||||||
result = shape_result("draft-selected-face", document, feature)
|
result = shape_result("draft-selected-face", document, feature)
|
||||||
|
result["mutation"] = mutation
|
||||||
result["selection"] = ["Face{}".format(top_face + 1)]
|
result["selection"] = ["Face{}".format(top_face + 1)]
|
||||||
result["reversed"] = bool(feature.Reversed)
|
result["reversed"] = bool(feature.Reversed)
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
@@ -91,7 +99,9 @@ def selected_thickness():
|
|||||||
feature.Reversed = True
|
feature.Reversed = True
|
||||||
feature.Mode = 0
|
feature.Mode = 0
|
||||||
feature.Join = 0
|
feature.Join = 0
|
||||||
|
mutation = capture_property_mutation(document, feature, "Value", 0.8)
|
||||||
result = shape_result("thickness-selected-face", document, feature)
|
result = shape_result("thickness-selected-face", document, feature)
|
||||||
|
result["mutation"] = mutation
|
||||||
result["selection"] = ["Face1"]
|
result["selection"] = ["Face1"]
|
||||||
result["reversed"] = bool(feature.Reversed)
|
result["reversed"] = bool(feature.Reversed)
|
||||||
result["elementMapSize"] = int(feature.Shape.ElementMapSize)
|
result["elementMapSize"] = int(feature.Shape.ElementMapSize)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import Part
|
|||||||
import Sketcher
|
import Sketcher
|
||||||
import TestSketcherApp
|
import TestSketcherApp
|
||||||
|
|
||||||
|
from freecad_mutation_evidence import capture_property_mutation
|
||||||
|
|
||||||
|
|
||||||
def version_text():
|
def version_text():
|
||||||
return ".".join(str(value) for value in App.Version()[:3])
|
return ".".join(str(value) for value in App.Version()[:3])
|
||||||
@@ -38,7 +40,9 @@ def additive_loft():
|
|||||||
feature = body.newObject("PartDesign::AdditiveLoft", "AdditiveLoft")
|
feature = body.newObject("PartDesign::AdditiveLoft", "AdditiveLoft")
|
||||||
feature.Profile = profile
|
feature.Profile = profile
|
||||||
feature.Sections = [section]
|
feature.Sections = [section]
|
||||||
|
mutation = capture_property_mutation(document, feature, "Ruled", True)
|
||||||
result = shape_result("additive-loft", document, feature)
|
result = shape_result("additive-loft", document, feature)
|
||||||
|
result["mutation"] = mutation
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -59,10 +63,17 @@ def subtractive_loft():
|
|||||||
section.AttachmentSupport = (document.XZ_Plane, [""])
|
section.AttachmentSupport = (document.XZ_Plane, [""])
|
||||||
document.recompute()
|
document.recompute()
|
||||||
TestSketcherApp.CreateRectangleSketch(section, (0, 1), (1, 1))
|
TestSketcherApp.CreateRectangleSketch(section, (0, 1), (1, 1))
|
||||||
|
edited_section = body.newObject("Sketcher::SketchObject", "EditedSection")
|
||||||
|
edited_section.MapMode = "FlatFace"
|
||||||
|
edited_section.AttachmentSupport = (document.XZ_Plane, [""])
|
||||||
|
document.recompute()
|
||||||
|
TestSketcherApp.CreateRectangleSketch(edited_section, (0, 1), (0.75, 0.75))
|
||||||
feature = body.newObject("PartDesign::SubtractiveLoft", "SubtractiveLoft")
|
feature = body.newObject("PartDesign::SubtractiveLoft", "SubtractiveLoft")
|
||||||
feature.Profile = profile
|
feature.Profile = profile
|
||||||
feature.Sections = [section]
|
feature.Sections = [section]
|
||||||
|
mutation = capture_property_mutation(document, feature, "Sections", [edited_section])
|
||||||
result = shape_result("subtractive-loft", document, feature)
|
result = shape_result("subtractive-loft", document, feature)
|
||||||
|
result["mutation"] = mutation
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -70,6 +81,8 @@ def subtractive_loft():
|
|||||||
def pipe_sketches(document, body):
|
def pipe_sketches(document, body):
|
||||||
profile = body.newObject("Sketcher::SketchObject", "Profile")
|
profile = body.newObject("Sketcher::SketchObject", "Profile")
|
||||||
TestSketcherApp.CreateCircleSketch(profile, (0, 0), 1)
|
TestSketcherApp.CreateCircleSketch(profile, (0, 0), 1)
|
||||||
|
edited_profile = body.newObject("Sketcher::SketchObject", "EditedProfile")
|
||||||
|
TestSketcherApp.CreateCircleSketch(edited_profile, (0, 0), 0.75)
|
||||||
spine = body.newObject("Sketcher::SketchObject", "Spine")
|
spine = body.newObject("Sketcher::SketchObject", "Spine")
|
||||||
spine.MapMode = "FlatFace"
|
spine.MapMode = "FlatFace"
|
||||||
spine.AttachmentSupport = (document.XZ_Plane, [""])
|
spine.AttachmentSupport = (document.XZ_Plane, [""])
|
||||||
@@ -78,17 +91,19 @@ def pipe_sketches(document, body):
|
|||||||
spine.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1))
|
spine.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1))
|
||||||
spine.addConstraint(Sketcher.Constraint("PointOnObject", 0, 2, -2))
|
spine.addConstraint(Sketcher.Constraint("PointOnObject", 0, 2, -2))
|
||||||
spine.addConstraint(Sketcher.Constraint("DistanceY", 0, 1, 0, 2, 1))
|
spine.addConstraint(Sketcher.Constraint("DistanceY", 0, 1, 0, 2, 1))
|
||||||
return profile, spine
|
return profile, edited_profile, spine
|
||||||
|
|
||||||
|
|
||||||
def additive_pipe():
|
def additive_pipe():
|
||||||
document = App.newDocument("AdditivePipeOracle")
|
document = App.newDocument("AdditivePipeOracle")
|
||||||
body = document.addObject("PartDesign::Body", "Body")
|
body = document.addObject("PartDesign::Body", "Body")
|
||||||
profile, spine = pipe_sketches(document, body)
|
profile, edited_profile, spine = pipe_sketches(document, body)
|
||||||
feature = body.newObject("PartDesign::AdditivePipe", "AdditivePipe")
|
feature = body.newObject("PartDesign::AdditivePipe", "AdditivePipe")
|
||||||
feature.Profile = profile
|
feature.Profile = profile
|
||||||
feature.Spine = spine
|
feature.Spine = spine
|
||||||
|
mutation = capture_property_mutation(document, feature, "Profile", edited_profile)
|
||||||
result = shape_result("additive-pipe", document, feature)
|
result = shape_result("additive-pipe", document, feature)
|
||||||
|
result["mutation"] = mutation
|
||||||
result["transition"] = str(feature.Transition)
|
result["transition"] = str(feature.Transition)
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
return result
|
return result
|
||||||
@@ -97,7 +112,7 @@ def additive_pipe():
|
|||||||
def subtractive_pipe():
|
def subtractive_pipe():
|
||||||
document = App.newDocument("SubtractivePipeOracle")
|
document = App.newDocument("SubtractivePipeOracle")
|
||||||
body = document.addObject("PartDesign::Body", "Body")
|
body = document.addObject("PartDesign::Body", "Body")
|
||||||
profile, spine = pipe_sketches(document, body)
|
profile, edited_profile, spine = pipe_sketches(document, body)
|
||||||
pad_sketch = body.newObject("Sketcher::SketchObject", "PadSketch")
|
pad_sketch = body.newObject("Sketcher::SketchObject", "PadSketch")
|
||||||
TestSketcherApp.CreateRectangleSketch(pad_sketch, (-5, -5), (10, 10))
|
TestSketcherApp.CreateRectangleSketch(pad_sketch, (-5, -5), (10, 10))
|
||||||
pad = body.newObject("PartDesign::Pad", "Pad")
|
pad = body.newObject("PartDesign::Pad", "Pad")
|
||||||
@@ -107,7 +122,9 @@ def subtractive_pipe():
|
|||||||
feature = body.newObject("PartDesign::SubtractivePipe", "SubtractivePipe")
|
feature = body.newObject("PartDesign::SubtractivePipe", "SubtractivePipe")
|
||||||
feature.Profile = profile
|
feature.Profile = profile
|
||||||
feature.Spine = spine
|
feature.Spine = spine
|
||||||
|
mutation = capture_property_mutation(document, feature, "Profile", edited_profile)
|
||||||
result = shape_result("subtractive-pipe", document, feature)
|
result = shape_result("subtractive-pipe", document, feature)
|
||||||
|
result["mutation"] = mutation
|
||||||
result["transition"] = str(feature.Transition)
|
result["transition"] = str(feature.Transition)
|
||||||
App.closeDocument(document.Name)
|
App.closeDocument(document.Name)
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import FreeCAD as App
|
|||||||
import Part
|
import Part
|
||||||
import Sketcher
|
import Sketcher
|
||||||
|
|
||||||
|
from freecad_mutation_evidence import capture_property_mutation
|
||||||
|
|
||||||
|
|
||||||
COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"
|
COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"
|
||||||
|
|
||||||
@@ -47,7 +49,8 @@ def run_revolution():
|
|||||||
feature.ReferenceAxis = (sketch, ["H_Axis"])
|
feature.ReferenceAxis = (sketch, ["H_Axis"])
|
||||||
feature.Angle = 360
|
feature.Angle = 360
|
||||||
document.recompute()
|
document.recompute()
|
||||||
return {"id": "partdesign-revolution", "operation": "revolution", **status(feature)}
|
mutation = capture_property_mutation(document, feature, "Angle", 270.0)
|
||||||
|
return {"id": "partdesign-revolution", "operation": "revolution", "mutation": mutation, **status(feature)}
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
return {"id": "partdesign-revolution", "operation": "revolution", "passed": False, "error": str(error)}
|
return {"id": "partdesign-revolution", "operation": "revolution", "passed": False, "error": str(error)}
|
||||||
finally:
|
finally:
|
||||||
@@ -74,7 +77,8 @@ def run_groove():
|
|||||||
feature.ReferenceAxis = (sketch, ["H_Axis"])
|
feature.ReferenceAxis = (sketch, ["H_Axis"])
|
||||||
feature.Angle = 180
|
feature.Angle = 180
|
||||||
document.recompute()
|
document.recompute()
|
||||||
return {"id": "partdesign-groove", "operation": "groove", **status(feature)}
|
mutation = capture_property_mutation(document, feature, "Angle", 120.0)
|
||||||
|
return {"id": "partdesign-groove", "operation": "groove", "mutation": mutation, **status(feature)}
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
return {"id": "partdesign-groove", "operation": "groove", "passed": False, "error": str(error)}
|
return {"id": "partdesign-groove", "operation": "groove", "passed": False, "error": str(error)}
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import FreeCAD as App
|
|||||||
import Part
|
import Part
|
||||||
import Sketcher
|
import Sketcher
|
||||||
|
|
||||||
|
from freecad_mutation_evidence import capture_property_mutation
|
||||||
|
|
||||||
|
|
||||||
def version_text():
|
def version_text():
|
||||||
return ".".join(str(value) for value in App.Version()[:3])
|
return ".".join(str(value) for value in App.Version()[:3])
|
||||||
@@ -50,7 +52,9 @@ def feature_linear_pattern():
|
|||||||
pattern.Direction = (document.X_Axis, [""])
|
pattern.Direction = (document.X_Axis, [""])
|
||||||
pattern.Occurrences = 3
|
pattern.Occurrences = 3
|
||||||
pattern.Length = 12
|
pattern.Length = 12
|
||||||
|
mutation = capture_property_mutation(document, pattern, "Occurrences", 4)
|
||||||
result = shape_result("linear-feature-list", document, pattern)
|
result = shape_result("linear-feature-list", document, pattern)
|
||||||
|
result["mutation"] = mutation
|
||||||
result.update({
|
result.update({
|
||||||
"transformMode": pattern.TransformMode,
|
"transformMode": pattern.TransformMode,
|
||||||
"originals": [item.Name for item in pattern.Originals],
|
"originals": [item.Name for item in pattern.Originals],
|
||||||
@@ -79,7 +83,9 @@ def feature_mirrored():
|
|||||||
mirrored.TransformMode = "Features"
|
mirrored.TransformMode = "Features"
|
||||||
mirrored.Originals = [boss]
|
mirrored.Originals = [boss]
|
||||||
mirrored.MirrorPlane = (document.YZ_Plane, [""])
|
mirrored.MirrorPlane = (document.YZ_Plane, [""])
|
||||||
|
mutation = capture_property_mutation(document, mirrored, "Refine", False)
|
||||||
result = shape_result("mirrored-feature-list", document, mirrored)
|
result = shape_result("mirrored-feature-list", document, mirrored)
|
||||||
|
result["mutation"] = mutation
|
||||||
result.update({
|
result.update({
|
||||||
"transformMode": mirrored.TransformMode,
|
"transformMode": mirrored.TransformMode,
|
||||||
"originals": [item.Name for item in mirrored.Originals],
|
"originals": [item.Name for item in mirrored.Originals],
|
||||||
@@ -105,7 +111,9 @@ def feature_polar_pattern():
|
|||||||
pattern.Occurrences = 4
|
pattern.Occurrences = 4
|
||||||
pattern.Refine = True
|
pattern.Refine = True
|
||||||
body.addObject(pattern)
|
body.addObject(pattern)
|
||||||
|
mutation = capture_property_mutation(document, pattern, "Occurrences", 3)
|
||||||
result = shape_result("polar-feature-list", document, pattern)
|
result = shape_result("polar-feature-list", document, pattern)
|
||||||
|
result["mutation"] = mutation
|
||||||
result.update({
|
result.update({
|
||||||
"transformMode": pattern.TransformMode,
|
"transformMode": pattern.TransformMode,
|
||||||
"originals": [item.Name for item in pattern.Originals],
|
"originals": [item.Name for item in pattern.Originals],
|
||||||
@@ -149,7 +157,9 @@ def feature_multi_transform():
|
|||||||
polar.Occurrences = 4
|
polar.Occurrences = 4
|
||||||
body.addObject(polar)
|
body.addObject(polar)
|
||||||
multi.Transformations = [mirrored, linear, polar]
|
multi.Transformations = [mirrored, linear, polar]
|
||||||
|
mutation = capture_property_mutation(document, multi, "Length", 15.0, target=linear, property_path="Transformations[1].Length")
|
||||||
result = shape_result("multi-transform-feature-list", document, multi)
|
result = shape_result("multi-transform-feature-list", document, multi)
|
||||||
|
result["mutation"] = mutation
|
||||||
result.update({
|
result.update({
|
||||||
"transformMode": multi.TransformMode,
|
"transformMode": multi.TransformMode,
|
||||||
"originals": [item.Name for item in multi.Originals],
|
"originals": [item.Name for item in multi.Originals],
|
||||||
@@ -255,7 +265,9 @@ def iso_hole(modeled):
|
|||||||
hole.ThreadDirection = "Left" if modeled else "Right"
|
hole.ThreadDirection = "Left" if modeled else "Right"
|
||||||
hole.ThreadDepthType = "Dimension"
|
hole.ThreadDepthType = "Dimension"
|
||||||
hole.ThreadDepth = 6
|
hole.ThreadDepth = 6
|
||||||
|
mutation = capture_property_mutation(document, hole, "Diameter", 6.5)
|
||||||
result = shape_result(case_id, document, hole)
|
result = shape_result(case_id, document, hole)
|
||||||
|
result["mutation"] = mutation
|
||||||
result.update({
|
result.update({
|
||||||
"threaded": bool(hole.Threaded),
|
"threaded": bool(hole.Threaded),
|
||||||
"modeled": bool(hole.ModelThread),
|
"modeled": bool(hole.ModelThread),
|
||||||
|
|||||||
86
scripts/freecad_mutation_evidence.py
Normal file
86
scripts/freecad_mutation_evidence.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import hashlib
|
||||||
|
|
||||||
|
|
||||||
|
def _json_value(value):
|
||||||
|
if value is None or isinstance(value, (bool, int, float, str)):
|
||||||
|
return value
|
||||||
|
if hasattr(value, "Value") and hasattr(value, "Unit"):
|
||||||
|
return {"value": float(value.Value), "unit": str(value.Unit)}
|
||||||
|
if hasattr(value, "x") and hasattr(value, "y") and hasattr(value, "z"):
|
||||||
|
return [float(value.x), float(value.y), float(value.z)]
|
||||||
|
if hasattr(value, "Name") and hasattr(value, "TypeId"):
|
||||||
|
return {"name": str(value.Name), "typeId": str(value.TypeId)}
|
||||||
|
if isinstance(value, (list, tuple)):
|
||||||
|
return [_json_value(item) for item in value]
|
||||||
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
|
def _shape_snapshot(feature):
|
||||||
|
shape = feature.Shape
|
||||||
|
if shape.isNull():
|
||||||
|
raise RuntimeError("{} produced a null Shape".format(feature.Name))
|
||||||
|
if not shape.isValid():
|
||||||
|
raise RuntimeError("{} produced an invalid Shape".format(feature.Name))
|
||||||
|
brep = shape.exportBrepToString().encode("utf-8")
|
||||||
|
bounds = shape.BoundBox
|
||||||
|
return {
|
||||||
|
"brepSha256": hashlib.sha256(brep).hexdigest(),
|
||||||
|
"shapeType": str(shape.ShapeType),
|
||||||
|
"valid": True,
|
||||||
|
"solids": len(shape.Solids),
|
||||||
|
"faces": len(shape.Faces),
|
||||||
|
"edges": len(shape.Edges),
|
||||||
|
"vertices": len(shape.Vertexes),
|
||||||
|
"volume": float(shape.Volume),
|
||||||
|
"area": float(shape.Area),
|
||||||
|
"bounds": {
|
||||||
|
"min": [float(bounds.XMin), float(bounds.YMin), float(bounds.ZMin)],
|
||||||
|
"max": [float(bounds.XMax), float(bounds.YMax), float(bounds.ZMax)],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def capture_property_mutation(document, feature, property_name, edited_value, target=None, property_path=None):
|
||||||
|
target = target or feature
|
||||||
|
original_value = getattr(target, property_name)
|
||||||
|
before_parameter = _json_value(original_value)
|
||||||
|
|
||||||
|
document.recompute()
|
||||||
|
before_shape_object = feature.Shape.copy()
|
||||||
|
before_shape = _shape_snapshot(feature)
|
||||||
|
try:
|
||||||
|
setattr(target, property_name, edited_value)
|
||||||
|
document.recompute()
|
||||||
|
edited_parameter = _json_value(getattr(target, property_name))
|
||||||
|
if before_parameter == edited_parameter:
|
||||||
|
raise RuntimeError("{} mutation did not change {}".format(feature.TypeId, property_path or property_name))
|
||||||
|
edited_shape = _shape_snapshot(feature)
|
||||||
|
finally:
|
||||||
|
setattr(target, property_name, original_value)
|
||||||
|
document.recompute()
|
||||||
|
restored_shape_object = feature.Shape
|
||||||
|
restored_shape = _shape_snapshot(feature)
|
||||||
|
restored_parameter = _json_value(getattr(target, property_name))
|
||||||
|
|
||||||
|
if restored_parameter != before_parameter:
|
||||||
|
raise RuntimeError("{} did not restore {}".format(feature.TypeId, property_path or property_name))
|
||||||
|
restored_equivalent = bool(restored_shape_object.isEqual(before_shape_object))
|
||||||
|
geometry_equivalent = (restored_shape["shapeType"], restored_shape["solids"], restored_shape["faces"], restored_shape["edges"], restored_shape["vertices"], round(restored_shape["volume"], 7), round(restored_shape["area"], 7)) == (before_shape["shapeType"], before_shape["solids"], before_shape["faces"], before_shape["edges"], before_shape["vertices"], round(before_shape["volume"], 7), round(before_shape["area"], 7))
|
||||||
|
if not restored_equivalent and not geometry_equivalent:
|
||||||
|
raise RuntimeError("{} did not restore the original geometry".format(feature.TypeId))
|
||||||
|
|
||||||
|
return {
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"familyId": str(feature.TypeId),
|
||||||
|
"featureName": str(feature.Name),
|
||||||
|
"propertyPath": property_path or property_name,
|
||||||
|
"status": "pass",
|
||||||
|
"before": {"parameterSnapshot": before_parameter, "shape": before_shape},
|
||||||
|
"edited": {"parameterSnapshot": edited_parameter, "shape": edited_shape},
|
||||||
|
"restored": {"parameterSnapshot": restored_parameter, "shape": restored_shape},
|
||||||
|
"parameterChanged": True,
|
||||||
|
"shapeChanged": edited_shape["brepSha256"] != before_shape["brepSha256"],
|
||||||
|
"restoredExactly": restored_equivalent or geometry_equivalent,
|
||||||
|
"brepStable": restored_shape["brepSha256"] == before_shape["brepSha256"],
|
||||||
|
"restoredGeometrically": True,
|
||||||
|
}
|
||||||
@@ -49,6 +49,14 @@ const addVariant = (familyId, snapshot, source) => {
|
|||||||
bucket.parameterVariants.set(stable(snapshot), { snapshot, source })
|
bucket.parameterVariants.set(stable(snapshot), { snapshot, source })
|
||||||
bucket.sources.add(source)
|
bucket.sources.add(source)
|
||||||
}
|
}
|
||||||
|
const addMutation = (mutation, source) => {
|
||||||
|
if (!mutation || typeof mutation !== 'object') return
|
||||||
|
const familyId = familyByType.get(mutation.familyId)
|
||||||
|
if (!familyId || mutation.status !== 'pass' || mutation.parameterChanged !== true || mutation.shapeChanged !== true || mutation.restoredExactly !== true) return
|
||||||
|
addRecord(familyId, 'editRecovery', { transaction: `native-parameter:${mutation.featureName}:${mutation.propertyPath}`, ...mutation }, source)
|
||||||
|
addVariant(familyId, mutation.before.parameterSnapshot, `${source}#before`)
|
||||||
|
addVariant(familyId, mutation.edited.parameterSnapshot, `${source}#edited`)
|
||||||
|
}
|
||||||
const manifestCases = async (manifestPath, entryKey, directory) => {
|
const manifestCases = async (manifestPath, entryKey, directory) => {
|
||||||
const manifest = await load(manifestPath)
|
const manifest = await load(manifestPath)
|
||||||
const base = resolve(root, directory)
|
const base = resolve(root, directory)
|
||||||
@@ -81,11 +89,16 @@ const addOracleCases = async (file, successKey, failureKey) => {
|
|||||||
for (const key of [successKey, failureKey]) for (const fixture of report[key] || []) {
|
for (const key of [successKey, failureKey]) for (const fixture of report[key] || []) {
|
||||||
const familyId = familyByType.get(fixture.typeId)
|
const familyId = familyByType.get(fixture.typeId)
|
||||||
if (!familyId) continue
|
if (!familyId) continue
|
||||||
if (key === successKey) addRecord(familyId, 'nominal', { id: fixture.id, typeId: fixture.typeId }, source)
|
if (key === successKey) {
|
||||||
|
addRecord(familyId, 'nominal', { id: fixture.id, typeId: fixture.typeId }, source)
|
||||||
|
addMutation(fixture.mutation, source)
|
||||||
|
}
|
||||||
else addRecord(familyId, 'invalid', { id: fixture.id, typeId: fixture.typeId }, source)
|
else addRecord(familyId, 'invalid', { id: fixture.id, typeId: fixture.typeId }, source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await addOracleCases('config/freecad-part-builders-oracle.json', 'successCases', 'failureCases')
|
await addOracleCases('config/freecad-part-builders-oracle.json', 'successCases', 'failureCases')
|
||||||
|
const coreMutationOracle = await load('config/freecad-core-parameter-mutation-oracle.json')
|
||||||
|
for (const mutation of coreMutationOracle.cases || []) addMutation(mutation, 'config/freecad-core-parameter-mutation-oracle.json')
|
||||||
for (const file of ['config/freecad-partdesign-failure-oracle.json', 'config/freecad-partdesign-revolution-groove-oracle.json', 'config/freecad-partdesign-transform-oracle.json']) {
|
for (const file of ['config/freecad-partdesign-failure-oracle.json', 'config/freecad-partdesign-revolution-groove-oracle.json', 'config/freecad-partdesign-transform-oracle.json']) {
|
||||||
const report = await load(file)
|
const report = await load(file)
|
||||||
for (const fixture of report.cases || []) {
|
for (const fixture of report.cases || []) {
|
||||||
@@ -93,18 +106,21 @@ for (const file of ['config/freecad-partdesign-failure-oracle.json', 'config/fre
|
|||||||
if (!familyId) continue
|
if (!familyId) continue
|
||||||
if (fixture.passed === true && fixture.status === 'Valid' && fixture.shapeValid !== false && fixture.solids > 0) addRecord(familyId, 'nominal', { id: fixture.id, typeId: fixture.typeId }, file)
|
if (fixture.passed === true && fixture.status === 'Valid' && fixture.shapeValid !== false && fixture.solids > 0) addRecord(familyId, 'nominal', { id: fixture.id, typeId: fixture.typeId }, file)
|
||||||
if (fixture.passed === true && (fixture.observed === 'rejected' || fixture.state?.includes('Invalid'))) addRecord(familyId, 'invalid', { id: fixture.id, typeId: fixture.typeId }, file)
|
if (fixture.passed === true && (fixture.observed === 'rejected' || fixture.state?.includes('Invalid'))) addRecord(familyId, 'invalid', { id: fixture.id, typeId: fixture.typeId }, file)
|
||||||
|
addMutation(fixture.mutation, file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const baseOracle = await load('config/freecad-partdesign-base-oracle.json')
|
const baseOracle = await load('config/freecad-partdesign-base-oracle.json')
|
||||||
for (const fixture of baseOracle.cases || []) {
|
for (const fixture of baseOracle.cases || []) {
|
||||||
const familyId = fixture.id.startsWith('pad-') ? 'PartDesign::Pad' : fixture.id.startsWith('pocket-') ? 'PartDesign::Pocket' : undefined
|
const familyId = fixture.id.startsWith('pad-') ? 'PartDesign::Pad' : fixture.id.startsWith('pocket-') ? 'PartDesign::Pocket' : undefined
|
||||||
if (familyId && fixture.passed === true && fixture.status === 'Valid' && fixture.solids > 0) addRecord(familyId, 'nominal', { id: fixture.id, typeId: familyId, outcome: { volume: fixture.volume, faces: fixture.faces } }, 'config/freecad-partdesign-base-oracle.json')
|
if (familyId && fixture.passed === true && fixture.status === 'Valid' && fixture.solids > 0) addRecord(familyId, 'nominal', { id: fixture.id, typeId: familyId, outcome: { volume: fixture.volume, faces: fixture.faces } }, 'config/freecad-partdesign-base-oracle.json')
|
||||||
|
if (familyId) addMutation(fixture.mutation, 'config/freecad-partdesign-base-oracle.json')
|
||||||
}
|
}
|
||||||
for (const file of ['config/freecad-partdesign-loft-oracle.json', 'config/freecad-partdesign-dressup-oracle.json']) {
|
for (const file of ['config/freecad-partdesign-loft-oracle.json', 'config/freecad-partdesign-dressup-oracle.json']) {
|
||||||
const report = await load(file)
|
const report = await load(file)
|
||||||
for (const fixture of report.cases || []) {
|
for (const fixture of report.cases || []) {
|
||||||
const familyId = familyByType.get(fixture.typeId)
|
const familyId = familyByType.get(fixture.typeId)
|
||||||
if (familyId && fixture.passed === true && fixture.status === 'Valid' && fixture.solids > 0) addRecord(familyId, 'nominal', { id: fixture.id, typeId: fixture.typeId, outcome: { volume: fixture.volume, faces: fixture.faces } }, file)
|
if (familyId && fixture.passed === true && fixture.status === 'Valid' && fixture.solids > 0) addRecord(familyId, 'nominal', { id: fixture.id, typeId: fixture.typeId, outcome: { volume: fixture.volume, faces: fixture.faces } }, file)
|
||||||
|
addMutation(fixture.mutation, file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
29
scripts/run-freecad-core-parameter-mutation-oracle.mjs
Normal file
29
scripts/run-freecad-core-parameter-mutation-oracle.mjs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { spawnSync } from 'node:child_process'
|
||||||
|
import { existsSync } from 'node:fs'
|
||||||
|
import { writeFile } from 'node:fs/promises'
|
||||||
|
import { resolve } from 'node:path'
|
||||||
|
|
||||||
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
||||||
|
const executable = process.env.FREECAD_CMD || resolve(root, '.cache/freecad/install-desktop/bin/FreeCADCmd')
|
||||||
|
if (!existsSync(executable)) throw new Error(`FreeCAD core parameter mutation executable is missing: ${executable}`)
|
||||||
|
const sysroot = resolve(root, '.cache/freecad/sysroot')
|
||||||
|
const execution = spawnSync(executable, ['--python-path', resolve(sysroot, 'usr/lib/python3/dist-packages'), resolve(root, 'scripts/freecad-core-parameter-mutation-oracle.py')], {
|
||||||
|
cwd: root,
|
||||||
|
encoding: 'utf8',
|
||||||
|
timeout: 180_000,
|
||||||
|
maxBuffer: 20 * 1024 * 1024,
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
PYTHONPATH: `${resolve(sysroot, 'usr/lib/python3/dist-packages')}${process.env.PYTHONPATH ? `:${process.env.PYTHONPATH}` : ''}`,
|
||||||
|
LD_LIBRARY_PATH: `${resolve(sysroot, 'usr/lib/x86_64-linux-gnu')}${process.env.LD_LIBRARY_PATH ? `:${process.env.LD_LIBRARY_PATH}` : ''}`,
|
||||||
|
MATPLOTLIBRC: resolve(sysroot, 'usr/share/matplotlib/mpl-data/matplotlibrc'),
|
||||||
|
MPLBACKEND: 'Agg',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
||||||
|
const marker = 'FREECAD_CORE_PARAMETER_MUTATION_RESULT='
|
||||||
|
const line = output.split(/\r?\n/).find((candidate) => candidate.includes(marker))
|
||||||
|
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD core parameter mutation oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
||||||
|
const report = JSON.parse(line.slice(line.indexOf(marker) + marker.length))
|
||||||
|
await writeFile(resolve(root, 'config/freecad-core-parameter-mutation-oracle.json'), `${JSON.stringify(report, null, 2)}\n`)
|
||||||
|
console.log(JSON.stringify(report, null, 2))
|
||||||
@@ -258,6 +258,56 @@ try {
|
|||||||
if (!shape || !primitiveResaved.shapeResources.some((resource) => resource.path === shape.path && resource.status === 'available')) fail(`FreeCAD resave did not produce an available ${objectName}.Shape resource.`)
|
if (!shape || !primitiveResaved.shapeResources.some((resource) => resource.path === shape.path && resource.status === 'available')) fail(`FreeCAD resave did not produce an available ${objectName}.Shape resource.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const throughHoleDocument: DocumentSnapshot = {
|
||||||
|
id: 'fcstd-native-part-cut-through-hole',
|
||||||
|
label: 'FCStd native Part Cut through hole',
|
||||||
|
version: 1,
|
||||||
|
dirty: false,
|
||||||
|
readOnly: false,
|
||||||
|
units: 'mm',
|
||||||
|
tree: ['Base', 'HoleTool', 'CutThroughHole'].map((id) => ({ id, label: id, type: 'feature', state: 'up-to-date' })),
|
||||||
|
objects: [
|
||||||
|
{ id: 'Base', typeId: 'Part::Box', properties: [
|
||||||
|
{ name: 'Length', label: 'Length', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 20 },
|
||||||
|
{ name: 'Width', label: 'Width', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 20 },
|
||||||
|
{ name: 'Height', label: 'Height', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 10 },
|
||||||
|
] },
|
||||||
|
{ id: 'HoleTool', typeId: 'Part::Cylinder', properties: [
|
||||||
|
{ name: 'Radius', label: 'Radius', group: 'Cylinder', scope: 'data', type: 'App::PropertyLength', value: 3 },
|
||||||
|
{ name: 'Height', label: 'Height', group: 'Cylinder', scope: 'data', type: 'App::PropertyLength', value: 12 },
|
||||||
|
{ name: 'Angle', label: 'Angle', group: 'Cylinder', scope: 'data', type: 'App::PropertyAngle', value: 360 },
|
||||||
|
{ name: 'Placement', label: 'Placement', group: 'Base', scope: 'data', type: 'App::PropertyPlacement', value: { position: { x: 10, y: 10, z: -1 }, rotation: { axis: { x: 0, y: 0, z: 1 }, angle: 0 } } },
|
||||||
|
] },
|
||||||
|
{ id: 'CutThroughHole', typeId: 'Part::Cut', properties: [
|
||||||
|
{ name: 'Base', label: 'Base', group: 'Boolean', scope: 'data', type: 'App::PropertyLink', value: 'Base' },
|
||||||
|
{ name: 'Tool', label: 'Tool', group: 'Boolean', scope: 'data', type: 'App::PropertyLink', value: 'HoleTool' },
|
||||||
|
{ name: 'Refine', label: 'Refine shape', group: 'Boolean', scope: 'data', type: 'App::PropertyBool', value: false },
|
||||||
|
] },
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
{ sourceId: 'CutThroughHole', targetId: 'Base', relation: 'link', propertyName: 'Base' },
|
||||||
|
{ sourceId: 'CutThroughHole', targetId: 'HoleTool', relation: 'link', propertyName: 'Tool' },
|
||||||
|
],
|
||||||
|
recompute: { generation: 0, status: 'idle', objectStates: { Base: 'up-to-date', HoleTool: 'up-to-date', CutThroughHole: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
|
||||||
|
}
|
||||||
|
const throughHolePath = join(temporaryDirectory, 'native-part-cut-through-hole.fcstd')
|
||||||
|
const throughHoleResavedPath = join(temporaryDirectory, 'native-part-cut-through-hole-resaved.fcstd')
|
||||||
|
await writeFile(throughHolePath, serializeFcstdMetadataArchive(throughHoleDocument))
|
||||||
|
const throughHoleResult = runFreecadProbe(throughHolePath, 'CutThroughHole', {
|
||||||
|
FREECAD_FCSTD_RECOMPUTE: '1',
|
||||||
|
FREECAD_FCSTD_PROPERTIES: 'Base,Tool,Refine',
|
||||||
|
FREECAD_FCSTD_RESAVE_PATH: throughHoleResavedPath,
|
||||||
|
})
|
||||||
|
const throughHoleExpectedVolume = 4000 - 90 * Math.PI
|
||||||
|
if (throughHoleResult.freecadVersion !== '1.1.1' || throughHoleResult.shapeNull !== false || throughHoleResult.shapeValid !== true || throughHoleResult.shapeError !== null || throughHoleResult.solidCount !== 1 || throughHoleResult.faceCount !== 7 || !near(throughHoleResult.volume, throughHoleExpectedVolume, 1e-8) || !throughHoleResult.boundingBox || JSON.stringify(throughHoleResult.boundingBox.min) !== '[0,0,0]' || JSON.stringify(throughHoleResult.boundingBox.max) !== '[20,20,10]') fail(`unexpected native Part::Cut through-hole result: ${JSON.stringify(throughHoleResult)}`)
|
||||||
|
if (throughHoleResult.properties.Base !== 'Base' || throughHoleResult.properties.Tool !== 'HoleTool' || throughHoleResult.properties.Refine !== false || Object.keys(throughHoleResult.properties).length !== 3) fail(`native Part::Cut through-hole links did not restore: ${JSON.stringify(throughHoleResult.properties)}`)
|
||||||
|
const throughHoleResaved = inspectFcstdArchive(new Uint8Array(await readFile(throughHoleResavedPath)))
|
||||||
|
const throughHoleObject = throughHoleResaved.objects.find((object) => object.name === 'CutThroughHole') ?? fail('FreeCAD resave is missing CutThroughHole.')
|
||||||
|
const throughHoleShape = throughHoleObject.properties.find((property) => property.name === 'Shape')?.shapeResource
|
||||||
|
const throughHolePlacement = throughHoleResaved.objects.find((object) => object.name === 'HoleTool')?.properties.find((property) => property.name === 'Placement')
|
||||||
|
if (!throughHoleShape || !throughHoleResaved.shapeResources.some((resource) => resource.path === throughHoleShape.path && resource.status === 'available')) fail('FreeCAD resave did not produce the CutThroughHole.Shape resource.')
|
||||||
|
if (!throughHolePlacement || JSON.stringify(decodeFcstdPropertyValue(throughHolePlacement).value) !== '{"position":{"x":10,"y":10,"z":-1},"rotation":{"axis":{"x":0,"y":0,"z":1},"angle":0}}') fail('Web inspector did not recover the through-hole tool placement.')
|
||||||
|
|
||||||
const sphereTrimPath = join(temporaryDirectory, 'native-sphere-trim.fcstd')
|
const sphereTrimPath = join(temporaryDirectory, 'native-sphere-trim.fcstd')
|
||||||
const sphereTrimResavedPath = join(temporaryDirectory, 'native-sphere-trim-resaved.fcstd')
|
const sphereTrimResavedPath = join(temporaryDirectory, 'native-sphere-trim-resaved.fcstd')
|
||||||
const sphereTrimProperties = { Radius: 5, Angle1: -45, Angle2: 45, Angle3: 120 }
|
const sphereTrimProperties = { Radius: 5, Angle1: -45, Angle2: 45, Angle3: 120 }
|
||||||
@@ -658,6 +708,18 @@ try {
|
|||||||
resavedShapeAvailable: primitiveResaved.shapeResources.some((resource) => resource.path === `${oracleCase.objectName}.Shape.brp` && resource.status === 'available'),
|
resavedShapeAvailable: primitiveResaved.shapeResources.some((resource) => resource.path === `${oracleCase.objectName}.Shape.brp` && resource.status === 'available'),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
scenario('part-cut-through-hole', 'web-freecad-web', ['objectTree', 'properties', 'shape', 'resources'], {
|
||||||
|
typeId: throughHoleObject.typeId,
|
||||||
|
solidCount: throughHoleResult.solidCount,
|
||||||
|
faceCount: throughHoleResult.faceCount,
|
||||||
|
volume: throughHoleResult.volume,
|
||||||
|
boundingBox: throughHoleResult.boundingBox,
|
||||||
|
propertyCount: Object.keys(throughHoleResult.properties).length,
|
||||||
|
properties: throughHoleResult.properties,
|
||||||
|
toolPlacement: decodeFcstdPropertyValue(throughHolePlacement).value,
|
||||||
|
refine: throughHoleResult.properties.Refine,
|
||||||
|
resavedShapeAvailable: true,
|
||||||
|
}),
|
||||||
scenario('part-sphere-trim', 'web-freecad-web', ['properties', 'shape', 'resources'], {
|
scenario('part-sphere-trim', 'web-freecad-web', ['properties', 'shape', 'resources'], {
|
||||||
solidCount: sphereTrimResult.solidCount,
|
solidCount: sphereTrimResult.solidCount,
|
||||||
faceCount: sphereTrimResult.faceCount,
|
faceCount: sphereTrimResult.faceCount,
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ const execution = spawnSync(executable, ['--python-path', resolve(sysroot, 'usr/
|
|||||||
})
|
})
|
||||||
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
||||||
const marker = 'FREECAD_PART_BUILDERS_ORACLE_RESULT='
|
const marker = 'FREECAD_PART_BUILDERS_ORACLE_RESULT='
|
||||||
const line = output.split(/\r?\n/).find((candidate) => candidate.startsWith(marker))
|
const line = output.split(/\r?\n/).find((candidate) => candidate.includes(marker))
|
||||||
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD Part builders oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD Part builders oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
||||||
const report = JSON.parse(line.slice(marker.length))
|
const report = JSON.parse(line.slice(line.indexOf(marker) + marker.length))
|
||||||
await writeFile(resolve(root, 'config/freecad-part-builders-oracle.json'), `${JSON.stringify(report, null, 2)}\n`)
|
await writeFile(resolve(root, 'config/freecad-part-builders-oracle.json'), `${JSON.stringify(report, null, 2)}\n`)
|
||||||
console.log(JSON.stringify(report, null, 2))
|
console.log(JSON.stringify(report, null, 2))
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ const execution = spawnSync(executable, ['--python-path', resolve(sysroot, 'usr/
|
|||||||
})
|
})
|
||||||
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
||||||
const marker = 'FREECAD_PARTDESIGN_BASE_RESULT='
|
const marker = 'FREECAD_PARTDESIGN_BASE_RESULT='
|
||||||
const line = output.split(/\r?\n/).find((candidate) => candidate.startsWith(marker))
|
const line = output.split(/\r?\n/).find((candidate) => candidate.includes(marker))
|
||||||
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD PartDesign base oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD PartDesign base oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
||||||
const report = JSON.parse(line.slice(marker.length))
|
const report = JSON.parse(line.slice(line.indexOf(marker) + marker.length))
|
||||||
await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`)
|
await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`)
|
||||||
console.log(JSON.stringify(report, null, 2))
|
console.log(JSON.stringify(report, null, 2))
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ const execution = spawnSync(executable, ['--python-path', resolve(sysroot, 'usr/
|
|||||||
})
|
})
|
||||||
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
||||||
const marker = 'FREECAD_PARTDESIGN_DRESSUP_RESULT='
|
const marker = 'FREECAD_PARTDESIGN_DRESSUP_RESULT='
|
||||||
const line = output.split(/\r?\n/).find((candidate) => candidate.startsWith(marker))
|
const line = output.split(/\r?\n/).find((candidate) => candidate.includes(marker))
|
||||||
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD PartDesign dress-up oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD PartDesign dress-up oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
||||||
const report = JSON.parse(line.slice(marker.length))
|
const report = JSON.parse(line.slice(line.indexOf(marker) + marker.length))
|
||||||
await writeFile(resolve(root, 'config/freecad-partdesign-dressup-oracle.json'), `${JSON.stringify(report, null, 2)}\n`)
|
await writeFile(resolve(root, 'config/freecad-partdesign-dressup-oracle.json'), `${JSON.stringify(report, null, 2)}\n`)
|
||||||
console.log(JSON.stringify(report, null, 2))
|
console.log(JSON.stringify(report, null, 2))
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ const execution = spawnSync(executable, ['--python-path', resolve(sysroot, 'usr/
|
|||||||
})
|
})
|
||||||
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
||||||
const marker = 'FREECAD_PARTDESIGN_LOFT_RESULT='
|
const marker = 'FREECAD_PARTDESIGN_LOFT_RESULT='
|
||||||
const line = output.split(/\r?\n/).find((candidate) => candidate.startsWith(marker))
|
const line = output.split(/\r?\n/).find((candidate) => candidate.includes(marker))
|
||||||
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD PartDesign loft oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD PartDesign loft oracle failed with status ${execution.status}: ${execution.error?.message || output.trim()}`)
|
||||||
const report = JSON.parse(line.slice(marker.length))
|
const report = JSON.parse(line.slice(line.indexOf(marker) + marker.length))
|
||||||
await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`)
|
await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`)
|
||||||
console.log(JSON.stringify(report, null, 2))
|
console.log(JSON.stringify(report, null, 2))
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ const execution = spawnSync(command, ['--python-path', resolve(sysroot, 'usr/lib
|
|||||||
})
|
})
|
||||||
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
const output = `${execution.stdout || ''}\n${execution.stderr || ''}`
|
||||||
const marker = 'FREECAD_PARTDESIGN_REVOLUTION_GROOVE_ORACLE_RESULT='
|
const marker = 'FREECAD_PARTDESIGN_REVOLUTION_GROOVE_ORACLE_RESULT='
|
||||||
const line = output.split(/\r?\n/).find((entry) => entry.startsWith(marker))
|
const line = output.split(/\r?\n/).find((entry) => entry.includes(marker))
|
||||||
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD PartDesign Revolution/Groove oracle failed: ${execution.error?.message || output.trim()}`)
|
if (execution.error || execution.status !== 0 || !line) throw new Error(`FreeCAD PartDesign Revolution/Groove oracle failed: ${execution.error?.message || output.trim()}`)
|
||||||
const report = JSON.parse(line.slice(marker.length))
|
const report = JSON.parse(line.slice(line.indexOf(marker) + marker.length))
|
||||||
await mkdir(resolve(root, 'config'), { recursive: true })
|
await mkdir(resolve(root, 'config'), { recursive: true })
|
||||||
await writeFile(outputFile, `${JSON.stringify(report, null, 2)}\n`)
|
await writeFile(outputFile, `${JSON.stringify(report, null, 2)}\n`)
|
||||||
console.log(JSON.stringify({ status: 'freecad-partdesign-revolution-groove-oracle-generated', output: outputFile, summary: report.summary }, null, 2))
|
console.log(JSON.stringify({ status: 'freecad-partdesign-revolution-groove-oracle-generated', output: outputFile, summary: report.summary }, null, 2))
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ const lanes = {
|
|||||||
...chromeTests
|
...chromeTests
|
||||||
.map((name) => `check:${name.slice('test:'.length)}`)
|
.map((name) => `check:${name.slice('test:'.length)}`)
|
||||||
.filter((name) => scripts[name]),
|
.filter((name) => scripts[name]),
|
||||||
|
'check:freecad-tsn-stage-evidence',
|
||||||
],
|
],
|
||||||
oracle: [
|
oracle: [
|
||||||
'fetch:freecad-source',
|
'fetch:freecad-source',
|
||||||
@@ -41,6 +42,8 @@ const lanes = {
|
|||||||
'build:freecad-native',
|
'build:freecad-native',
|
||||||
'probe:freecad-reference',
|
'probe:freecad-reference',
|
||||||
'check:freecad-desktop-oracle',
|
'check:freecad-desktop-oracle',
|
||||||
|
'probe:freecad-core-parameter-mutations',
|
||||||
|
'check:freecad-core-parameter-mutations',
|
||||||
'test:golden:freecad',
|
'test:golden:freecad',
|
||||||
'test:golden:freecad:families',
|
'test:golden:freecad:families',
|
||||||
'test:golden:freecad:failures',
|
'test:golden:freecad:failures',
|
||||||
@@ -55,14 +58,16 @@ const lanes = {
|
|||||||
'probe:freecad-partdesign-revolution-groove',
|
'probe:freecad-partdesign-revolution-groove',
|
||||||
'probe:freecad-part-builders',
|
'probe:freecad-part-builders',
|
||||||
'probe:freecad-composite-history-elementmap',
|
'probe:freecad-composite-history-elementmap',
|
||||||
|
'test:freecad-fcstd-native',
|
||||||
|
'generate:freecad-parameter-mutations',
|
||||||
'check:freecad-oracle-coverage',
|
'check:freecad-oracle-coverage',
|
||||||
'check:freecad-golden-coverage',
|
'check:freecad-golden-coverage',
|
||||||
|
'check:freecad-parameter-mutations',
|
||||||
'check:freecad-sketcher-constraints',
|
'check:freecad-sketcher-constraints',
|
||||||
'check:freecad-fcstd-roundtrip',
|
'check:freecad-fcstd-roundtrip',
|
||||||
'check:freecad-composite-history-elementmap',
|
'check:freecad-composite-history-elementmap',
|
||||||
'check:freecad-exact-history-elementmap-gate',
|
'check:freecad-exact-history-elementmap-gate',
|
||||||
'check:freecad-native-naming-evidence',
|
'check:freecad-native-naming-evidence',
|
||||||
'test:freecad-fcstd-native',
|
|
||||||
],
|
],
|
||||||
wasm: [
|
wasm: [
|
||||||
...wasmBuilds,
|
...wasmBuilds,
|
||||||
|
|||||||
Reference in New Issue
Block a user