feat: classify fillet ordered pair row
This commit is contained in:
@@ -24,12 +24,12 @@
|
|||||||
],
|
],
|
||||||
"followUpProgress": "config/freecad-follow-up-task-progress.json"
|
"followUpProgress": "config/freecad-follow-up-task-progress.json"
|
||||||
},
|
},
|
||||||
"nextTask": "TSN-PAIR-groove-multi-transform",
|
"nextTask": "TSN-PAIR-chamfer-cut",
|
||||||
"summary": {
|
"summary": {
|
||||||
"tasks": 1756,
|
"tasks": 1756,
|
||||||
"completed": 317,
|
"completed": 337,
|
||||||
"inProgress": 1,
|
"inProgress": 1,
|
||||||
"pending": 1438
|
"pending": 1418
|
||||||
},
|
},
|
||||||
"milestones": [
|
"milestones": [
|
||||||
{
|
{
|
||||||
@@ -4206,181 +4206,235 @@
|
|||||||
{
|
{
|
||||||
"id": "TSN-PAIR-groove-multi-transform",
|
"id": "TSN-PAIR-groove-multi-transform",
|
||||||
"title": "Classify ordered operation pair groove->multi-transform",
|
"title": "Classify ordered operation pair groove->multi-transform",
|
||||||
"status": "in_progress",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "groove->multi-transform",
|
"pair": "groove->multi-transform",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-fuse",
|
"id": "TSN-PAIR-fillet-fuse",
|
||||||
"title": "Classify ordered operation pair fillet->fuse",
|
"title": "Classify ordered operation pair fillet->fuse",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->fuse",
|
"pair": "fillet->fuse",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-cut",
|
"id": "TSN-PAIR-fillet-cut",
|
||||||
"title": "Classify ordered operation pair fillet->cut",
|
"title": "Classify ordered operation pair fillet->cut",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->cut",
|
"pair": "fillet->cut",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-common",
|
"id": "TSN-PAIR-fillet-common",
|
||||||
"title": "Classify ordered operation pair fillet->common",
|
"title": "Classify ordered operation pair fillet->common",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->common",
|
"pair": "fillet->common",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-rotate",
|
"id": "TSN-PAIR-fillet-rotate",
|
||||||
"title": "Classify ordered operation pair fillet->rotate",
|
"title": "Classify ordered operation pair fillet->rotate",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->rotate",
|
"pair": "fillet->rotate",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-pad",
|
"id": "TSN-PAIR-fillet-pad",
|
||||||
"title": "Classify ordered operation pair fillet->pad",
|
"title": "Classify ordered operation pair fillet->pad",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->pad",
|
"pair": "fillet->pad",
|
||||||
|
"classification": "rejected",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builder-and-freecad-profile-reject-with-clean-resave"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-pocket",
|
"id": "TSN-PAIR-fillet-pocket",
|
||||||
"title": "Classify ordered operation pair fillet->pocket",
|
"title": "Classify ordered operation pair fillet->pocket",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->pocket",
|
"pair": "fillet->pocket",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-loft",
|
"id": "TSN-PAIR-fillet-loft",
|
||||||
"title": "Classify ordered operation pair fillet->loft",
|
"title": "Classify ordered operation pair fillet->loft",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->loft",
|
"pair": "fillet->loft",
|
||||||
|
"classification": "rejected",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"freecad-input-precondition-reject-with-kernel-diagnostic-and-clean-resave"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-pipe",
|
"id": "TSN-PAIR-fillet-pipe",
|
||||||
"title": "Classify ordered operation pair fillet->pipe",
|
"title": "Classify ordered operation pair fillet->pipe",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->pipe",
|
"pair": "fillet->pipe",
|
||||||
|
"classification": "rejected",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"freecad-input-precondition-reject-with-kernel-diagnostic-and-clean-resave"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-revolution",
|
"id": "TSN-PAIR-fillet-revolution",
|
||||||
"title": "Classify ordered operation pair fillet->revolution",
|
"title": "Classify ordered operation pair fillet->revolution",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->revolution",
|
"pair": "fillet->revolution",
|
||||||
|
"classification": "rejected",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builder-and-freecad-profile-reject-with-clean-resave"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-groove",
|
"id": "TSN-PAIR-fillet-groove",
|
||||||
"title": "Classify ordered operation pair fillet->groove",
|
"title": "Classify ordered operation pair fillet->groove",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->groove",
|
"pair": "fillet->groove",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-fillet",
|
"id": "TSN-PAIR-fillet-fillet",
|
||||||
"title": "Classify ordered operation pair fillet->fillet",
|
"title": "Classify ordered operation pair fillet->fillet",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->fillet",
|
"pair": "fillet->fillet",
|
||||||
|
"classification": "rejected",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builder-and-freecad-profile-reject-with-clean-resave"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-chamfer",
|
"id": "TSN-PAIR-fillet-chamfer",
|
||||||
"title": "Classify ordered operation pair fillet->chamfer",
|
"title": "Classify ordered operation pair fillet->chamfer",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->chamfer",
|
"pair": "fillet->chamfer",
|
||||||
|
"classification": "rejected",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builder-and-freecad-profile-reject-with-clean-resave"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-hole",
|
"id": "TSN-PAIR-fillet-hole",
|
||||||
"title": "Classify ordered operation pair fillet->hole",
|
"title": "Classify ordered operation pair fillet->hole",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->hole",
|
"pair": "fillet->hole",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-draft",
|
"id": "TSN-PAIR-fillet-draft",
|
||||||
"title": "Classify ordered operation pair fillet->draft",
|
"title": "Classify ordered operation pair fillet->draft",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->draft",
|
"pair": "fillet->draft",
|
||||||
|
"classification": "rejected",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builder-and-freecad-profile-reject-with-clean-resave"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-thickness",
|
"id": "TSN-PAIR-fillet-thickness",
|
||||||
"title": "Classify ordered operation pair fillet->thickness",
|
"title": "Classify ordered operation pair fillet->thickness",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->thickness",
|
"pair": "fillet->thickness",
|
||||||
|
"classification": "rejected",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-and-freecad-profile-no-op-with-clean-resave"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-linear-pattern",
|
"id": "TSN-PAIR-fillet-linear-pattern",
|
||||||
"title": "Classify ordered operation pair fillet->linear-pattern",
|
"title": "Classify ordered operation pair fillet->linear-pattern",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->linear-pattern",
|
"pair": "fillet->linear-pattern",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-polar-pattern",
|
"id": "TSN-PAIR-fillet-polar-pattern",
|
||||||
"title": "Classify ordered operation pair fillet->polar-pattern",
|
"title": "Classify ordered operation pair fillet->polar-pattern",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->polar-pattern",
|
"pair": "fillet->polar-pattern",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -4394,27 +4448,33 @@
|
|||||||
{
|
{
|
||||||
"id": "TSN-PAIR-fillet-multi-transform",
|
"id": "TSN-PAIR-fillet-multi-transform",
|
||||||
"title": "Classify ordered operation pair fillet->multi-transform",
|
"title": "Classify ordered operation pair fillet->multi-transform",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "fillet->multi-transform",
|
"pair": "fillet->multi-transform",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-chamfer-fuse",
|
"id": "TSN-PAIR-chamfer-fuse",
|
||||||
"title": "Classify ordered operation pair chamfer->fuse",
|
"title": "Classify ordered operation pair chamfer->fuse",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"dependencies": [
|
"dependencies": [],
|
||||||
"TSN-PROD-DRIFT-001"
|
|
||||||
],
|
|
||||||
"pair": "chamfer->fuse",
|
"pair": "chamfer->fuse",
|
||||||
|
"classification": "accepted",
|
||||||
|
"evidence": [
|
||||||
|
"config/freecad-ordered-operation-pair-classification.json",
|
||||||
|
"native-builders-mutation-naming-and-fcstd-resave-pass"
|
||||||
|
],
|
||||||
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
"exit": "native acceptance or rejection is recorded; accepted pairs include builder, mutation, naming, and resave evidence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "TSN-PAIR-chamfer-cut",
|
"id": "TSN-PAIR-chamfer-cut",
|
||||||
"title": "Classify ordered operation pair chamfer->cut",
|
"title": "Classify ordered operation pair chamfer->cut",
|
||||||
"status": "pending",
|
"status": "in_progress",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"TSN-PROD-DRIFT-001"
|
"TSN-PROD-DRIFT-001"
|
||||||
],
|
],
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -390,7 +390,7 @@
|
|||||||
{
|
{
|
||||||
"path": "sw.js",
|
"path": "sw.js",
|
||||||
"bytes": 1390,
|
"bytes": 1390,
|
||||||
"sha256": "dfe8893e68cda6991ca64b5f5eaa19097c5b6d8f4bdc13f2423328950671a5be"
|
"sha256": "8b0477955514535bb11cef3733135b67422cc8c085b4331c3b9cb1a1adc9d852"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "vendor/camotics/camotics-sweep.wasm",
|
"path": "vendor/camotics/camotics-sweep.wasm",
|
||||||
@@ -412,7 +412,7 @@
|
|||||||
"status": "signed",
|
"status": "signed",
|
||||||
"algorithm": "Ed25519",
|
"algorithm": "Ed25519",
|
||||||
"keyId": "bitbybit-local-release-2026",
|
"keyId": "bitbybit-local-release-2026",
|
||||||
"payloadSha256": "e6d83894b72503eed170bec685d761d868784e28fbc5a221d78c0b270a472b37",
|
"payloadSha256": "ad5f25aeb7e1382b3172d9919357a9831ac198841e54304a6789665cd21cda31",
|
||||||
"signature": "FZ+gouN7G/kpiInw2zMQ5FBLXPJzurcdHv3lk4NThmtPGe6NXoe8KkIngxO8vbRba0E2e1jwoSgbv2HfvY5xAw=="
|
"signature": "c8xaS8E7BOThrQKOK9WlCLpMazuqlBZ6eMKbCTt+tzeC0b4TyEEaiVvjelUtFDjo5PK0fVYPeYISrS2895LTDA=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
生成日期:2026-08-15。基线:FreeCAD 1.1.1 / `0108fd4b4850cc46e625b60e53cea7a7bbe69f8d`。
|
生成日期:2026-08-15。基线:FreeCAD 1.1.1 / `0108fd4b4850cc46e625b60e53cea7a7bbe69f8d`。
|
||||||
|
|
||||||
- 唯一活动任务:`TSN-PAIR-groove-multi-transform`
|
- 唯一活动任务:`TSN-PAIR-chamfer-cut`
|
||||||
- 微任务:1756 total / 317 completed / 1 in_progress / 1438 pending
|
- 微任务:1756 total / 337 completed / 1 in_progress / 1418 pending
|
||||||
- 有序操作对:191/361 classified / 170 unknown
|
- 有序操作对:211/361 classified / 150 unknown
|
||||||
- Property:27/85 native types / 58 opaque types
|
- Property:27/85 native types / 58 opaque types
|
||||||
- exact 任务:5/52 completed
|
- exact 任务:5/52 completed
|
||||||
- 模块能力:0 exact / 26 compatible / 5 proxy / 3 development
|
- 模块能力:0 exact / 26 compatible / 5 proxy / 3 development
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
| `ORA-GUI-BASELINE` | 106 | 106 | 0 | 0 | `-` |
|
| `ORA-GUI-BASELINE` | 106 | 106 | 0 | 0 | `-` |
|
||||||
| `ORA-GUI-WORKFLOWS` | 7 | 7 | 0 | 0 | `-` |
|
| `ORA-GUI-WORKFLOWS` | 7 | 7 | 0 | 0 | `-` |
|
||||||
| `TSN-RECOVERY-DRIFT` | 13 | 13 | 0 | 0 | `-` |
|
| `TSN-RECOVERY-DRIFT` | 13 | 13 | 0 | 0 | `-` |
|
||||||
| `TSN-ORDERED-PAIRS` | 361 | 191 | 1 | 169 | `TSN-PAIR-groove-multi-transform` |
|
| `TSN-ORDERED-PAIRS` | 361 | 211 | 1 | 149 | `TSN-PAIR-chamfer-cut` |
|
||||||
| `PROPERTY-CODECS` | 522 | 0 | 0 | 522 | `-` |
|
| `PROPERTY-CODECS` | 522 | 0 | 0 | 522 | `-` |
|
||||||
| `DOCUMENT-SEMANTICS` | 90 | 0 | 0 | 90 | `-` |
|
| `DOCUMENT-SEMANTICS` | 90 | 0 | 0 | 90 | `-` |
|
||||||
| `CORE-MODELING` | 171 | 0 | 0 | 171 | `-` |
|
| `CORE-MODELING` | 171 | 0 | 0 | 171 | `-` |
|
||||||
|
|||||||
@@ -205,6 +205,26 @@ const expectedPairs = [
|
|||||||
{ pair: 'groove->linear-pattern', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut', firstInputCount: 2, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse', secondInputCount: 1, mutationParameter: 'translationX', mutationTrajectory: [8, 9, 8] },
|
{ pair: 'groove->linear-pattern', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut', firstInputCount: 2, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse', secondInputCount: 1, mutationParameter: 'translationX', mutationTrajectory: [8, 9, 8] },
|
||||||
{ pair: 'groove->polar-pattern', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut', firstInputCount: 2, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse', secondInputCount: 1, mutationParameter: 'angle', mutationTrajectory: [90, 120, 90] },
|
{ pair: 'groove->polar-pattern', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut', firstInputCount: 2, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse', secondInputCount: 1, mutationParameter: 'angle', mutationTrajectory: [90, 120, 90] },
|
||||||
{ pair: 'groove->mirrored', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut', firstInputCount: 2, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse', secondInputCount: 1, mutationParameter: 'planeOriginX', mutationTrajectory: [5, 6, 5] },
|
{ pair: 'groove->mirrored', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut', firstInputCount: 2, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse', secondInputCount: 1, mutationParameter: 'planeOriginX', mutationTrajectory: [5, 6, 5] },
|
||||||
|
{ pair: 'groove->multi-transform', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut', firstInputCount: 2, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse(ordered)', secondInputCount: 1, mutationParameter: 'multiTranslationX', mutationTrajectory: [8, 9, 8] },
|
||||||
|
{ pair: 'fillet->fuse', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepAlgoAPI_Fuse', secondInputCount: 2, mutationParameter: 'toolOffsetX', mutationTrajectory: [8, 7, 8] },
|
||||||
|
{ pair: 'fillet->cut', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepAlgoAPI_Cut', secondInputCount: 2, mutationParameter: 'toolSize', mutationTrajectory: [4, 3, 4] },
|
||||||
|
{ pair: 'fillet->common', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepAlgoAPI_Common', secondInputCount: 2, mutationParameter: 'toolOffsetX', mutationTrajectory: [7, 6, 7] },
|
||||||
|
{ pair: 'fillet->rotate', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepBuilderAPI_Transform', secondInputCount: 1, mutationParameter: 'angle', mutationTrajectory: [15, 22.5, 15] },
|
||||||
|
{ pair: 'fillet->pad', decision: 'rejected', reasonCode: 'native-builder-and-freecad-profile-reject-with-clean-resave', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, rejectionAuthority: 'occt-builder', secondBuilder: 'BRepPrimAPI_MakePrism', secondInputCount: 1, mutationParameter: 'length', mutationTrajectory: [5, 7.5, 5], nativeTypeId: 'PartDesign::Pad', freeCadDiagnostic: 'FeatureExtrusion: Length: Could not extrude the sketch!' },
|
||||||
|
{ pair: 'fillet->pocket', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepPrimAPI_MakePrism+BRepAlgoAPI_Cut', secondInputCount: 2, mutationParameter: 'length', mutationTrajectory: [5, 4, 5] },
|
||||||
|
{ pair: 'fillet->loft', decision: 'rejected', reasonCode: 'freecad-input-precondition-reject-with-kernel-diagnostic-and-clean-resave', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, rejectionAuthority: 'freecad-document', kernelOutcome: 'accepted', secondBuilder: 'BRepOffsetAPI_ThruSections', secondInputCount: 2, mutationParameter: 'ruled', mutationTrajectory: [false, true, false], nativeTypeId: 'Part::Loft', freeCadDiagnostic: 'Profile shape is not a single vertex, edge, wire nor face.' },
|
||||||
|
{ pair: 'fillet->pipe', decision: 'rejected', reasonCode: 'freecad-input-precondition-reject-with-kernel-diagnostic-and-clean-resave', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, rejectionAuthority: 'freecad-document', kernelOutcome: 'invalid-result', secondBuilder: 'BRepOffsetAPI_MakePipe', secondInputCount: 2, mutationParameter: 'spineLength', mutationTrajectory: [15, 12, 15], nativeTypeId: 'Part::Sweep', freeCadDiagnostic: 'A fatal error occurred when making the sweep' },
|
||||||
|
{ pair: 'fillet->revolution', decision: 'rejected', reasonCode: 'native-builder-and-freecad-profile-reject-with-clean-resave', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, rejectionAuthority: 'occt-builder', secondBuilder: 'BRepPrimAPI_MakeRevol', secondInputCount: 1, mutationParameter: 'angle', mutationTrajectory: [360, 270, 360], nativeTypeId: 'Part::Revolution', freeCadDiagnostic: 'Solids are not Processed' },
|
||||||
|
{ pair: 'fillet->groove', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut', secondInputCount: 2, mutationParameter: 'angle', mutationTrajectory: [360, 180, 360] },
|
||||||
|
{ pair: 'fillet->fillet', decision: 'rejected', reasonCode: 'native-builder-and-freecad-profile-reject-with-clean-resave', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, rejectionAuthority: 'occt-builder', secondBuilder: 'BRepFilletAPI_MakeFillet', secondInputCount: 1, mutationParameter: 'radius', mutationTrajectory: [0.4, 0.6, 0.4], nativeTypeId: 'Part::Fillet', freeCadDiagnostic: 'There are no suitable edges for chamfer or fillet' },
|
||||||
|
{ pair: 'fillet->chamfer', decision: 'rejected', reasonCode: 'native-builder-and-freecad-profile-reject-with-clean-resave', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, rejectionAuthority: 'occt-builder', secondBuilder: 'BRepFilletAPI_MakeChamfer', secondInputCount: 1, mutationParameter: 'distance', mutationTrajectory: [0.4, 0.6, 0.4], nativeTypeId: 'Part::Chamfer', freeCadDiagnostic: 'There are no suitable edges for chamfer or fillet' },
|
||||||
|
{ pair: 'fillet->hole', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepPrimAPI_MakeCylinder+BRepAlgoAPI_Cut', secondInputCount: 1, mutationParameter: 'radius', mutationTrajectory: [1, 1.5, 1] },
|
||||||
|
{ pair: 'fillet->draft', decision: 'rejected', reasonCode: 'native-builder-and-freecad-profile-reject-with-clean-resave', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, rejectionAuthority: 'occt-builder', secondBuilder: 'BRepOffsetAPI_DraftAngle', secondInputCount: 1, mutationParameter: 'angle', mutationTrajectory: [5, 8, 5], nativeTypeId: 'PartDesign::Draft', freeCadDiagnostic: '', inputShapeTransfer: 'partdesign-feature-summary-exact-with-explicit-brep-drift' },
|
||||||
|
{ pair: 'fillet->thickness', decision: 'rejected', reasonCode: 'native-and-freecad-profile-no-op-with-clean-resave', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, rejectionAuthority: 'occt-no-op', kernelOutcome: 'no-op', secondBuilder: 'BRepOffsetAPI_MakeThickSolid', secondInputCount: 1, mutationParameter: 'offset', mutationTrajectory: [-0.4, -0.6, -0.4], nativeTypeId: 'Part::Thickness', freeCadDiagnostic: 'Valid', freecadProfileNoOp: true },
|
||||||
|
{ pair: 'fillet->linear-pattern', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse', secondInputCount: 1, mutationParameter: 'translationX', mutationTrajectory: [8, 9, 8] },
|
||||||
|
{ pair: 'fillet->polar-pattern', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse', secondInputCount: 1, mutationParameter: 'angle', mutationTrajectory: [30, 45, 30] },
|
||||||
|
{ pair: 'fillet->multi-transform', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeFillet', firstInputCount: 1, secondBuilder: 'BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse(ordered)', secondInputCount: 1, mutationParameter: 'multiTranslationX', mutationTrajectory: [8, 9, 8] },
|
||||||
|
{ pair: 'chamfer->fuse', decision: 'accepted', reasonCode: 'native-builders-mutation-naming-and-fcstd-resave-pass', firstBuilder: 'BRepFilletAPI_MakeChamfer', firstInputCount: 1, secondBuilder: 'BRepAlgoAPI_Fuse', secondInputCount: 2, mutationParameter: 'toolOffsetX', mutationTrajectory: [8, 7, 8] },
|
||||||
]
|
]
|
||||||
if (report.nativeProbe?.artifacts?.length !== 3 || report.classifications?.length !== expectedPairs.length) fail('native artifacts or classification prefix is incomplete.')
|
if (report.nativeProbe?.artifacts?.length !== 3 || report.classifications?.length !== expectedPairs.length) fail('native artifacts or classification prefix is incomplete.')
|
||||||
for (const [index, entry] of report.classifications.entries()) {
|
for (const [index, entry] of report.classifications.entries()) {
|
||||||
@@ -226,20 +246,31 @@ for (const [index, entry] of report.classifications.entries()) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (rejection.kernelRestoredExactly !== true || rejection.kernelAttempts?.length !== 3) fail(`${expected.pair} OCCT diagnostic trajectory is incomplete.`)
|
if (rejection.kernelRestoredExactly !== true || rejection.kernelAttempts?.length !== 3) fail(`${expected.pair} OCCT diagnostic trajectory is incomplete.`)
|
||||||
for (const [attemptIndex, attempt] of rejection.kernelAttempts.entries()) if (attempt.operation !== secondOperation || attempt.builder !== expected.secondBuilder || attempt.inputCount !== expected.secondInputCount || attempt.parameter !== expected.mutationParameter || attempt.parameterValue !== expected.mutationTrajectory[attemptIndex] || attempt.runtime !== 'occt-native' || attempt.outcome !== expected.kernelOutcome || attempt.resultProduced !== true || attempt.shapeProduced !== true || attempt.validShapeProduced !== (expected.kernelOutcome === 'accepted') || attempt.historyProduced !== true || attempt.historyProvider !== 'occt-native' || attempt.summary?.isValid !== (expected.kernelOutcome === 'accepted') || attempt.historyRecords < 1 || !attempt.historySha256 || attempt.authority !== (expected.kernelOutcome === 'accepted' ? 'kernel-superset-only' : 'kernel-invalid-result')) fail(`${expected.pair} OCCT compatibility attempt ${attemptIndex} is invalid.`)
|
for (const [attemptIndex, attempt] of rejection.kernelAttempts.entries()) {
|
||||||
|
const validKernelShape = expected.kernelOutcome !== 'invalid-result'
|
||||||
|
const expectedAuthority = expected.kernelOutcome === 'no-op' ? 'kernel-no-op' : expected.kernelOutcome === 'accepted' ? 'kernel-superset-only' : 'kernel-invalid-result'
|
||||||
|
if (attempt.operation !== secondOperation || attempt.builder !== expected.secondBuilder || attempt.inputCount !== expected.secondInputCount || attempt.parameter !== expected.mutationParameter || attempt.parameterValue !== expected.mutationTrajectory[attemptIndex] || attempt.runtime !== 'occt-native' || attempt.outcome !== expected.kernelOutcome || attempt.resultProduced !== true || attempt.shapeProduced !== true || attempt.validShapeProduced !== validKernelShape || attempt.historyProduced !== true || attempt.historyProvider !== 'occt-native' || attempt.summary?.isValid !== validKernelShape || attempt.historyRecords < 1 || !attempt.historySha256 || attempt.authority !== expectedAuthority || (expected.kernelOutcome === 'no-op' && JSON.stringify(attempt.summary) !== JSON.stringify(entry.first.summary))) fail(`${expected.pair} OCCT compatibility attempt ${attemptIndex} is invalid.`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const persistence = rejection.persistence
|
const persistence = rejection.persistence
|
||||||
const diagnostic = persistence?.diagnostic
|
const diagnostic = persistence?.diagnostic
|
||||||
const freecadProfileAccepted = expected.freecadProfileAccepted === true
|
const freecadProfileAccepted = expected.freecadProfileAccepted === true
|
||||||
const persistenceChecksPass = Object.values(persistence?.checks ?? {}).every(Boolean) || (freecadProfileAccepted && persistence?.checks?.nativeFeatureRejected === false && Object.entries(persistence?.checks ?? {}).filter(([key]) => key !== 'nativeFeatureRejected').every(([, value]) => value === true)) || (!freecadProfileAccepted && persistence?.checks?.nativeFeatureRejected === true && Object.entries(persistence?.checks ?? {}).filter(([key]) => key !== 'freecadProfileAccepted').every(([, value]) => value === true))
|
const freecadProfileNoOp = expected.freecadProfileNoOp === true
|
||||||
|
const persistenceChecksPass = Object.values(persistence?.checks ?? {}).every(Boolean) || (freecadProfileAccepted && persistence?.checks?.nativeFeatureRejected === false && Object.entries(persistence?.checks ?? {}).filter(([key]) => key !== 'nativeFeatureRejected').every(([, value]) => value === true)) || (freecadProfileNoOp && persistence?.checks?.freecadProfileNoOp === true && persistence?.checks?.freecadProfileAccepted === false && persistence?.checks?.nativeFeatureRejected === false && Object.entries(persistence?.checks ?? {}).filter(([key]) => !['nativeFeatureRejected', 'freecadProfileAccepted'].includes(key)).every(([, value]) => value === true)) || (!freecadProfileAccepted && !freecadProfileNoOp && persistence?.checks?.nativeFeatureRejected === true && Object.entries(persistence?.checks ?? {}).filter(([key]) => key !== 'freecadProfileAccepted').every(([, value]) => value === true))
|
||||||
if (persistence?.status !== 'pass' || persistence.decision !== 'rejected' || persistence.pair !== entry.pair || persistence.operation !== secondOperation || persistence.nativeTypeId !== expected.nativeTypeId || persistence.freecadVersion !== '1.1.1' || !persistenceChecksPass) fail(`${expected.pair} FCStd rejection evidence is incomplete.`)
|
if (persistence?.status !== 'pass' || persistence.decision !== 'rejected' || persistence.pair !== entry.pair || persistence.operation !== secondOperation || persistence.nativeTypeId !== expected.nativeTypeId || persistence.freecadVersion !== '1.1.1' || !persistenceChecksPass) fail(`${expected.pair} FCStd rejection evidence is incomplete.`)
|
||||||
if (diagnostic?.nativeTypeId !== expected.nativeTypeId || diagnostic.parameter?.name !== expected.mutationParameter || diagnostic.parameter.value !== expected.mutationTrajectory[0] || diagnostic.inputShape?.solids !== 1 || diagnostic.recomputeResult !== true || !diagnostic.objects?.some(({ name, typeId }) => name === 'PairResult' && typeId === expected.nativeTypeId)) fail(`${expected.pair} did not capture a real FreeCAD profile evaluation.`)
|
if (diagnostic?.nativeTypeId !== expected.nativeTypeId || diagnostic.parameter?.name !== expected.mutationParameter || diagnostic.parameter.value !== expected.mutationTrajectory[0] || diagnostic.inputShape?.solids !== 1 || diagnostic.recomputeResult !== true || !diagnostic.objects?.some(({ name, typeId }) => name === 'PairResult' && typeId === expected.nativeTypeId)) fail(`${expected.pair} did not capture a real FreeCAD profile evaluation.`)
|
||||||
if (freecadProfileAccepted) {
|
if (freecadProfileNoOp) {
|
||||||
|
if (diagnostic.shapeNull !== false || diagnostic.shapeValid !== true || diagnostic.statusString !== 'Valid' || !diagnostic.state?.includes('Up-to-date') || JSON.stringify(diagnostic.resultShape) !== JSON.stringify(diagnostic.inputShape)) fail(`${expected.pair} FreeCAD no-op evidence is incomplete.`)
|
||||||
|
} else if (freecadProfileAccepted) {
|
||||||
if (persistence.checks.nativeFeatureRejected !== false || persistence.checks.freecadProfileAccepted !== true || diagnostic.shapeNull !== false || diagnostic.shapeValid !== true || diagnostic.statusString !== 'Valid' || !diagnostic.state?.includes('Up-to-date')) fail(`${expected.pair} FreeCAD profile acceptance evidence is incomplete.`)
|
if (persistence.checks.nativeFeatureRejected !== false || persistence.checks.freecadProfileAccepted !== true || diagnostic.shapeNull !== false || diagnostic.shapeValid !== true || diagnostic.statusString !== 'Valid' || !diagnostic.state?.includes('Up-to-date')) fail(`${expected.pair} FreeCAD profile acceptance evidence is incomplete.`)
|
||||||
} else if (diagnostic.shapeNull !== true || diagnostic.shapeValid !== false || !diagnostic.state?.includes('Invalid') || diagnostic.statusString === 'Valid') {
|
} else if (diagnostic.shapeNull !== true || diagnostic.shapeValid !== false || !diagnostic.state?.includes('Invalid') || diagnostic.statusString === 'Valid') {
|
||||||
fail(`${expected.pair} did not capture a real rejected FreeCAD recompute.`)
|
fail(`${expected.pair} did not capture a real rejected FreeCAD recompute.`)
|
||||||
}
|
}
|
||||||
if (expected.freeCadDiagnostic && diagnostic.statusString !== expected.freeCadDiagnostic) fail(`${expected.pair} FreeCAD profile diagnostic changed.`)
|
if (Object.hasOwn(expected, 'freeCadDiagnostic') && diagnostic.statusString !== expected.freeCadDiagnostic) fail(`${expected.pair} FreeCAD profile diagnostic changed.`)
|
||||||
|
if (expected.inputShapeTransfer === 'partdesign-feature-summary-exact-with-explicit-brep-drift') {
|
||||||
|
const input = diagnostic.input
|
||||||
|
if (input?.name !== 'DraftBase' || input.typeId !== 'PartDesign::Feature' || JSON.stringify(input.subelements) !== JSON.stringify(['Face1']) || input.sourceName !== persistence.source?.name || input.shapeSummaryTransferredExactly !== true || typeof input.sourceBrepSha256 !== 'string' || typeof input.draftBaseBrepSha256 !== 'string' || input.sourceBrepSha256 === input.draftBaseBrepSha256) fail(`${expected.pair} PartDesign input Shape transfer evidence is incomplete.`)
|
||||||
|
}
|
||||||
if (persistence.source?.shape?.solids !== 1 || !persistence.source.shape.brepSha256 || JSON.stringify(persistence.rollback?.before) !== JSON.stringify(persistence.rollback?.after)) fail(`${expected.pair} abort did not restore the source object set and Shape.`)
|
if (persistence.source?.shape?.solids !== 1 || !persistence.source.shape.brepSha256 || JSON.stringify(persistence.rollback?.before) !== JSON.stringify(persistence.rollback?.after)) fail(`${expected.pair} abort did not restore the source object set and Shape.`)
|
||||||
const phases = persistence.phases
|
const phases = persistence.phases
|
||||||
if (JSON.stringify(phases?.initial) !== JSON.stringify(phases?.reopened) || JSON.stringify(phases?.initial) !== JSON.stringify(phases?.resaved) || phases.initial.objects?.length !== persistence.rollback.before.objects.length || phases.initial.objects?.some(({ typeId }) => typeId === 'PartDesign::Body' || typeId === 'PartDesign::Pad' || typeId === 'Part::Loft' || typeId === 'Part::Revolution')) fail(`${expected.pair} polluted the clean FCStd save/reopen/resave chain.`)
|
if (JSON.stringify(phases?.initial) !== JSON.stringify(phases?.reopened) || JSON.stringify(phases?.initial) !== JSON.stringify(phases?.resaved) || phases.initial.objects?.length !== persistence.rollback.before.objects.length || phases.initial.objects?.some(({ typeId }) => typeId === 'PartDesign::Body' || typeId === 'PartDesign::Pad' || typeId === 'Part::Loft' || typeId === 'Part::Revolution')) fail(`${expected.pair} polluted the clean FCStd save/reopen/resave chain.`)
|
||||||
@@ -255,6 +286,6 @@ for (const [index, entry] of report.classifications.entries()) {
|
|||||||
const phases = entry.persistence.phases
|
const phases = entry.persistence.phases
|
||||||
if (JSON.stringify(phases?.initial) !== JSON.stringify(phases?.reopened) || JSON.stringify(phases?.initial) !== JSON.stringify(phases?.resaved) || phases.initial.namingEvidenceSha256 !== entry.second.namingEvidenceSha256) fail(`${expected.pair} FCStd phases changed Shape or naming evidence.`)
|
if (JSON.stringify(phases?.initial) !== JSON.stringify(phases?.reopened) || JSON.stringify(phases?.initial) !== JSON.stringify(phases?.resaved) || phases.initial.namingEvidenceSha256 !== entry.second.namingEvidenceSha256) fail(`${expected.pair} FCStd phases changed Shape or naming evidence.`)
|
||||||
}
|
}
|
||||||
const expectedSummary = { registeredOperations: 19, orderedPairs: 361, classifiedPairs: 187, accepted: 143, rejected: 44, unknown: 174 }
|
const expectedSummary = { registeredOperations: 19, orderedPairs: 361, classifiedPairs: 207, accepted: 155, rejected: 52, unknown: 154 }
|
||||||
if (JSON.stringify(report.summary) !== JSON.stringify(expectedSummary)) fail('summary is inconsistent.')
|
if (JSON.stringify(report.summary) !== JSON.stringify(expectedSummary)) fail('summary is inconsistent.')
|
||||||
console.log(JSON.stringify({ status: 'freecad-ordered-operation-pair-classification-pass', completedTasks: report.classifications.map(({ taskId }) => taskId), pairs: report.classifications.map(({ pair, classification }) => ({ pair, classification })), nativeBuilderRuns: report.classifications.length * 4, fcstdPhases: report.classifications.length * 3, remainingPairs: report.summary.unknown }, null, 2))
|
console.log(JSON.stringify({ status: 'freecad-ordered-operation-pair-classification-pass', completedTasks: report.classifications.map(({ taskId }) => taskId), pairs: report.classifications.map(({ pair, classification }) => ({ pair, classification })), nativeBuilderRuns: report.classifications.length * 4, fcstdPhases: report.classifications.length * 3, remainingPairs: report.summary.unknown }, null, 2))
|
||||||
|
|||||||
@@ -246,6 +246,29 @@ def collect_rejected():
|
|||||||
feature.Edges = [(index, 0.4, 0.4) for index in range(1, len(source.Shape.Edges) + 1)]
|
feature.Edges = [(index, 0.4, 0.4) for index in range(1, len(source.Shape.Edges) + 1)]
|
||||||
diagnostic["parameter"] = {"name": "distance", "value": 0.4}
|
diagnostic["parameter"] = {"name": "distance", "value": 0.4}
|
||||||
diagnostic["input"] = link_snapshot(feature.Base)
|
diagnostic["input"] = link_snapshot(feature.Base)
|
||||||
|
elif operation == "draft":
|
||||||
|
body = document.addObject("PartDesign::Body", "Body")
|
||||||
|
draft_base = body.newObject("PartDesign::Feature", "DraftBase")
|
||||||
|
draft_base.Shape = source.Shape.copy()
|
||||||
|
datum_plane = body.newObject("PartDesign::Plane", "DatumPlane")
|
||||||
|
datum_plane.AttachmentSupport = [(document.XY_Plane, "")]
|
||||||
|
datum_plane.MapMode = "FlatFace"
|
||||||
|
datum_line = body.newObject("PartDesign::Line", "DatumLine")
|
||||||
|
datum_line.AttachmentSupport = [(document.Z_Axis, "")]
|
||||||
|
datum_line.MapMode = "TwoPointLine"
|
||||||
|
feature = body.newObject("PartDesign::Draft", "PairResult")
|
||||||
|
feature.Base = (draft_base, ["Face1"])
|
||||||
|
feature.NeutralPlane = (datum_plane, [""])
|
||||||
|
feature.PullDirection = (datum_line, [""])
|
||||||
|
feature.Angle = 5.0
|
||||||
|
feature.Reversed = False
|
||||||
|
diagnostic["parameter"] = {"name": "angle", "value": round(float(feature.Angle), 7)}
|
||||||
|
diagnostic["input"] = link_snapshot(feature.Base)
|
||||||
|
diagnostic["input"]["sourceName"] = source.Name
|
||||||
|
draft_base_shape = shape_snapshot_from_shape(draft_base.Shape, include_brep=True)
|
||||||
|
diagnostic["input"]["shapeSummaryTransferredExactly"] = {key: value for key, value in draft_base_shape.items() if key != "brepSha256"} == {key: value for key, value in baseline_source_shape.items() if key != "brepSha256"}
|
||||||
|
diagnostic["input"]["sourceBrepSha256"] = baseline_source_shape["brepSha256"]
|
||||||
|
diagnostic["input"]["draftBaseBrepSha256"] = draft_base_shape["brepSha256"]
|
||||||
elif operation == "thickness":
|
elif operation == "thickness":
|
||||||
feature = document.addObject("Part::Thickness", "PairResult")
|
feature = document.addObject("Part::Thickness", "PairResult")
|
||||||
feature.Faces = (source, ["Face2"])
|
feature.Faces = (source, ["Face2"])
|
||||||
@@ -268,6 +291,8 @@ def collect_rejected():
|
|||||||
diagnostic["state"] = [str(value) for value in feature.State]
|
diagnostic["state"] = [str(value) for value in feature.State]
|
||||||
diagnostic["shapeNull"] = bool(feature.Shape.isNull())
|
diagnostic["shapeNull"] = bool(feature.Shape.isNull())
|
||||||
diagnostic["shapeValid"] = False if feature.Shape.isNull() else bool(feature.Shape.isValid())
|
diagnostic["shapeValid"] = False if feature.Shape.isNull() else bool(feature.Shape.isValid())
|
||||||
|
if not feature.Shape.isNull():
|
||||||
|
diagnostic["resultShape"] = shape_snapshot_from_shape(feature.Shape)
|
||||||
finally:
|
finally:
|
||||||
document.abortTransaction()
|
document.abortTransaction()
|
||||||
document.recompute()
|
document.recompute()
|
||||||
@@ -297,12 +322,13 @@ def collect_rejected():
|
|||||||
or "Error" in diagnostic["state"]
|
or "Error" in diagnostic["state"]
|
||||||
or "Invalid" in diagnostic["state"]
|
or "Invalid" in diagnostic["state"]
|
||||||
)
|
)
|
||||||
freecad_profile_accepted = operation in ("fillet", "chamfer", "thickness") and not feature_rejected and not diagnostic["shapeNull"] and diagnostic["shapeValid"] and diagnostic["statusString"] == "Valid"
|
freecad_profile_no_op = operation == "thickness" and not feature_rejected and not diagnostic["shapeNull"] and diagnostic["shapeValid"] and diagnostic["statusString"] == "Valid" and diagnostic.get("resultShape") == diagnostic.get("inputShape")
|
||||||
expected_type_id = {"pad": "PartDesign::Pad", "loft": "Part::Loft", "pipe": "Part::Sweep", "revolution": "Part::Revolution", "fuse": "Part::Fuse", "fillet": "Part::Fillet", "chamfer": "Part::Chamfer", "thickness": "Part::Thickness"}[operation]
|
freecad_profile_accepted = operation in ("fillet", "chamfer", "thickness") and not freecad_profile_no_op and not feature_rejected and not diagnostic["shapeNull"] and diagnostic["shapeValid"] and diagnostic["statusString"] == "Valid"
|
||||||
input_names = [diagnostic.get("input", {}).get("name")] if operation in ("pad", "revolution", "fillet", "chamfer", "thickness") else ([diagnostic.get("input", {}).get(key, {}).get("name") for key in ("base", "tool")] if operation == "fuse" else [item["name"] for item in diagnostic.get("input", {}).get("sections", [])])
|
expected_type_id = {"pad": "PartDesign::Pad", "loft": "Part::Loft", "pipe": "Part::Sweep", "revolution": "Part::Revolution", "fuse": "Part::Fuse", "fillet": "Part::Fillet", "chamfer": "Part::Chamfer", "draft": "PartDesign::Draft", "thickness": "Part::Thickness"}[operation]
|
||||||
|
input_names = [diagnostic.get("input", {}).get("sourceName", diagnostic.get("input", {}).get("name"))] if operation in ("pad", "revolution", "fillet", "chamfer", "draft", "thickness") else ([diagnostic.get("input", {}).get(key, {}).get("name") for key in ("base", "tool")] if operation == "fuse" else [item["name"] for item in diagnostic.get("input", {}).get("sections", [])])
|
||||||
checks = {
|
checks = {
|
||||||
"nativeFeatureConstructed": diagnostic.get("nativeTypeId") == expected_type_id,
|
"nativeFeatureConstructed": diagnostic.get("nativeTypeId") == expected_type_id,
|
||||||
"fuseSolidUsedAsInput": source_name in input_names and diagnostic.get("inputShape", {}).get("solids") == 1,
|
"fuseSolidUsedAsInput": source_name in input_names and diagnostic.get("inputShape", {}).get("solids") == 1 and (operation != "draft" or diagnostic.get("input", {}).get("shapeSummaryTransferredExactly") is True),
|
||||||
"recomputeStatusCaptured": diagnostic["recomputeResult"] is not None or diagnostic["exceptionType"] is not None,
|
"recomputeStatusCaptured": diagnostic["recomputeResult"] is not None or diagnostic["exceptionType"] is not None,
|
||||||
"nativeFeatureRejected": feature_rejected,
|
"nativeFeatureRejected": feature_rejected,
|
||||||
"freecadProfileAccepted": freecad_profile_accepted,
|
"freecadProfileAccepted": freecad_profile_accepted,
|
||||||
@@ -311,6 +337,8 @@ def collect_rejected():
|
|||||||
"documentUnpolluted": baseline == initial,
|
"documentUnpolluted": baseline == initial,
|
||||||
"documentStable": initial == reopened_snapshot and initial == resaved_snapshot,
|
"documentStable": initial == reopened_snapshot and initial == resaved_snapshot,
|
||||||
}
|
}
|
||||||
|
if freecad_profile_no_op:
|
||||||
|
checks["freecadProfileNoOp"] = True
|
||||||
return {
|
return {
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"baselineId": "freecad-1.1.1-ordered-operation-pair-resave",
|
"baselineId": "freecad-1.1.1-ordered-operation-pair-resave",
|
||||||
@@ -332,7 +360,7 @@ def collect_rejected():
|
|||||||
},
|
},
|
||||||
"phases": {"initial": initial, "reopened": reopened_snapshot, "resaved": resaved_snapshot},
|
"phases": {"initial": initial, "reopened": reopened_snapshot, "resaved": resaved_snapshot},
|
||||||
"checks": checks,
|
"checks": checks,
|
||||||
"status": "pass" if all(checks.values()) or (operation in ("fillet", "chamfer", "thickness") and freecad_profile_accepted and all(value for key, value in checks.items() if key != "nativeFeatureRejected")) or (not freecad_profile_accepted and feature_rejected and all(value for key, value in checks.items() if key != "freecadProfileAccepted")) else "failed",
|
"status": "pass" if all(checks.values()) or (operation in ("fillet", "chamfer", "thickness") and freecad_profile_accepted and all(value for key, value in checks.items() if key != "nativeFeatureRejected")) or (freecad_profile_no_op and all(value for key, value in checks.items() if key not in ("nativeFeatureRejected", "freecadProfileAccepted"))) or (not freecad_profile_accepted and feature_rejected and all(value for key, value in checks.items() if key != "freecadProfileAccepted")) else "failed",
|
||||||
}
|
}
|
||||||
finally:
|
finally:
|
||||||
for name in list(App.listDocuments().keys()):
|
for name in list(App.listDocuments().keys()):
|
||||||
|
|||||||
@@ -119,6 +119,13 @@ const pairSpecOverrides = {
|
|||||||
'groove->thickness': { ...operationSpecs.thickness, decision: 'rejected', rejectionAuthority: 'occt-builder' },
|
'groove->thickness': { ...operationSpecs.thickness, decision: 'rejected', rejectionAuthority: 'occt-builder' },
|
||||||
'groove->polar-pattern': { ...operationSpecs['polar-pattern'], nominal: { ...operationSpecs['polar-pattern'].nominal, angle: 90 }, edited: { angle: 120 }, beforeValue: 90, editedValue: 120 },
|
'groove->polar-pattern': { ...operationSpecs['polar-pattern'], nominal: { ...operationSpecs['polar-pattern'].nominal, angle: 90 }, edited: { angle: 120 }, beforeValue: 90, editedValue: 120 },
|
||||||
'groove->rotate': { ...operationSpecs.rotate },
|
'groove->rotate': { ...operationSpecs.rotate },
|
||||||
|
'fillet->fuse': { ...operationSpecs.fuse, nominal: { toolSize: 5, toolOffset: 8 }, edited: { toolSize: 5, toolOffset: 7 }, beforeValue: 8, editedValue: 7 },
|
||||||
|
'fillet->common': { ...operationSpecs.common, nominal: { toolSize: 5, toolOffset: 7 }, edited: { toolSize: 5, toolOffset: 6 }, beforeValue: 7, editedValue: 6 },
|
||||||
|
'fillet->fillet': { ...operationSpecs.fillet, decision: 'rejected', rejectionAuthority: 'occt-builder' },
|
||||||
|
'fillet->chamfer': { ...operationSpecs.chamfer, decision: 'rejected', rejectionAuthority: 'occt-builder' },
|
||||||
|
'fillet->draft': { ...operationSpecs.draft, decision: 'rejected', rejectionAuthority: 'occt-builder' },
|
||||||
|
'fillet->thickness': { ...operationSpecs.thickness, decision: 'rejected', rejectionAuthority: 'occt-no-op', kernelOutcome: 'no-op' },
|
||||||
|
'chamfer->fuse': { ...operationSpecs.fuse, nominal: { toolSize: 5, toolOffset: 8 }, edited: { toolSize: 5, toolOffset: 7 }, beforeValue: 8, editedValue: 7 },
|
||||||
}
|
}
|
||||||
|
|
||||||
const createOperation = (module, { operation, objectStep, toolSize, toolOffset, angle, length, profileWidth = 2, profileHeight = 3, profileX = 0.5, profileY = 2, profileZ = 0, ruled, spineLength, radius, distance, depth, position, direction, faceIndex, axisOrigin, neutralPlaneDirection, reversed, offset, intersectionJoin, translationX, planeOriginX, multiTranslationX, multiMirrorPlaneX = 5, stage }) => {
|
const createOperation = (module, { operation, objectStep, toolSize, toolOffset, angle, length, profileWidth = 2, profileHeight = 3, profileX = 0.5, profileY = 2, profileZ = 0, ruled, spineLength, radius, distance, depth, position, direction, faceIndex, axisOrigin, neutralPlaneDirection, reversed, offset, intersectionJoin, translationX, planeOriginX, multiTranslationX, multiMirrorPlaneX = 5, stage }) => {
|
||||||
@@ -236,7 +243,8 @@ const captureKernelCompatibilityStage = (module, definition, parameterValue, exp
|
|||||||
try {
|
try {
|
||||||
const outcome = response.summary?.isValid === true ? 'accepted' : 'invalid-result'
|
const outcome = response.summary?.isValid === true ? 'accepted' : 'invalid-result'
|
||||||
const noHistorySuperset = expectedOutcome === 'accepted-no-history' && outcome === 'accepted'
|
const noHistorySuperset = expectedOutcome === 'accepted-no-history' && outcome === 'accepted'
|
||||||
if (response.provider !== 'occt-native' || (!noHistorySuperset && outcome !== expectedOutcome) || !response.resultStep?.startsWith('ISO-10303-21;') || (response.records?.length < 1 && !noHistorySuperset)) fail(`${definition.stage.stageId} OCCT compatibility probe returned an unexpected result: ${JSON.stringify({ provider: response.provider, outcome, expectedOutcome, summary: response.summary, resultStep: Boolean(response.resultStep), records: response.records?.length, result: Boolean(response.result) })}`)
|
const noOp = expectedOutcome === 'no-op' && outcome === 'accepted' && JSON.stringify(canonicalSummary(response.summary)) === JSON.stringify(definition.inputSummary)
|
||||||
|
if (response.provider !== 'occt-native' || (!noHistorySuperset && !noOp && outcome !== expectedOutcome) || !response.resultStep?.startsWith('ISO-10303-21;') || (response.records?.length < 1 && !noHistorySuperset)) fail(`${definition.stage.stageId} OCCT compatibility probe returned an unexpected result: ${JSON.stringify({ provider: response.provider, outcome, expectedOutcome, summary: response.summary, inputSummary: definition.inputSummary, resultStep: Boolean(response.resultStep), records: response.records?.length, result: Boolean(response.result) })}`)
|
||||||
return {
|
return {
|
||||||
operation: definition.operation,
|
operation: definition.operation,
|
||||||
builder: operationSpecs[definition.operation].builder,
|
builder: operationSpecs[definition.operation].builder,
|
||||||
@@ -244,7 +252,7 @@ const captureKernelCompatibilityStage = (module, definition, parameterValue, exp
|
|||||||
parameter: operationSpecs[definition.operation].parameter,
|
parameter: operationSpecs[definition.operation].parameter,
|
||||||
parameterValue,
|
parameterValue,
|
||||||
runtime: 'occt-native',
|
runtime: 'occt-native',
|
||||||
outcome: noHistorySuperset ? expectedOutcome : outcome,
|
outcome: noHistorySuperset || noOp ? expectedOutcome : outcome,
|
||||||
resultProduced: true,
|
resultProduced: true,
|
||||||
shapeProduced: true,
|
shapeProduced: true,
|
||||||
validShapeProduced: response.summary.isValid === true,
|
validShapeProduced: response.summary.isValid === true,
|
||||||
@@ -253,7 +261,7 @@ const captureKernelCompatibilityStage = (module, definition, parameterValue, exp
|
|||||||
summary: canonicalSummary(response.summary),
|
summary: canonicalSummary(response.summary),
|
||||||
historyRecords: response.records.length,
|
historyRecords: response.records.length,
|
||||||
historySha256: sha256(JSON.stringify(response.records)),
|
historySha256: sha256(JSON.stringify(response.records)),
|
||||||
authority: noHistorySuperset ? 'kernel-superset-no-history' : outcome === 'accepted' ? 'kernel-superset-only' : 'kernel-invalid-result',
|
authority: noOp ? 'kernel-no-op' : noHistorySuperset ? 'kernel-superset-no-history' : outcome === 'accepted' ? 'kernel-superset-only' : 'kernel-invalid-result',
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
response.result?.delete?.()
|
response.result?.delete?.()
|
||||||
@@ -340,7 +348,8 @@ const persistPair = async (pair, step, namingEvidence, decision) => {
|
|||||||
const payload = markerIndex >= 0 ? output.slice(markerIndex + marker.length).match(/\{.*\}/s)?.[0] : undefined
|
const payload = markerIndex >= 0 ? output.slice(markerIndex + marker.length).match(/\{.*\}/s)?.[0] : undefined
|
||||||
if (execution.error || execution.status !== 0 || !payload) fail(`FreeCAD FCStd replay exited with ${execution.status}: ${execution.error?.message || output.trim()}`)
|
if (execution.error || execution.status !== 0 || !payload) fail(`FreeCAD FCStd replay exited with ${execution.status}: ${execution.error?.message || output.trim()}`)
|
||||||
const persistence = JSON.parse(payload)
|
const persistence = JSON.parse(payload)
|
||||||
const checksPass = Object.values(persistence.checks).every(Boolean) || (decision === 'rejected' && persistence.checks.freecadProfileAccepted === true && persistence.checks.nativeFeatureRejected === false && Object.entries(persistence.checks).filter(([key]) => key !== 'nativeFeatureRejected').every(([, value]) => value === true)) || (decision === 'rejected' && persistence.checks.freecadProfileAccepted === false && persistence.checks.nativeFeatureRejected === true && Object.entries(persistence.checks).filter(([key]) => key !== 'freecadProfileAccepted').every(([, value]) => value === true))
|
if (!persistence?.checks || typeof persistence.checks !== 'object') fail(`FreeCAD FCStd replay returned incomplete evidence: ${JSON.stringify(persistence)}`)
|
||||||
|
const checksPass = Object.values(persistence.checks).every(Boolean) || (decision === 'rejected' && persistence.checks.freecadProfileAccepted === true && persistence.checks.nativeFeatureRejected === false && Object.entries(persistence.checks).filter(([key]) => key !== 'nativeFeatureRejected').every(([, value]) => value === true)) || (decision === 'rejected' && persistence.checks.freecadProfileNoOp === true && persistence.checks.freecadProfileAccepted === false && persistence.checks.nativeFeatureRejected === false && Object.entries(persistence.checks).filter(([key]) => !['nativeFeatureRejected', 'freecadProfileAccepted'].includes(key)).every(([, value]) => value === true)) || (decision === 'rejected' && persistence.checks.freecadProfileAccepted === false && persistence.checks.nativeFeatureRejected === true && Object.entries(persistence.checks).filter(([key]) => key !== 'freecadProfileAccepted').every(([, value]) => value === true))
|
||||||
if (persistence.status !== 'pass' || persistence.decision !== decision || persistence.freecadVersion !== '1.1.1' || persistence.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || !checksPass) fail(`FreeCAD FCStd replay failed: ${JSON.stringify(persistence)}`)
|
if (persistence.status !== 'pass' || persistence.decision !== decision || persistence.freecadVersion !== '1.1.1' || persistence.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || !checksPass) fail(`FreeCAD FCStd replay failed: ${JSON.stringify(persistence)}`)
|
||||||
return persistence
|
return persistence
|
||||||
} finally {
|
} finally {
|
||||||
@@ -384,25 +393,30 @@ const classifyPair = async (fromOperation, toOperation, pairIndex) => {
|
|||||||
const secondDefinition = {
|
const secondDefinition = {
|
||||||
operation: toOperation,
|
operation: toOperation,
|
||||||
objectStep: first.response.resultStep,
|
objectStep: first.response.resultStep,
|
||||||
|
inputSummary: first.report.summary,
|
||||||
...spec.nominal,
|
...spec.nominal,
|
||||||
stage: { stageId: `pair:${pairId}:second`, ordinal: 1, objectId: `pair:${pairId}:first`, objectTag: 1101 + pairIndex * 100, resultObjectId: `pair:${pairId}:second`, resultObjectTag: 1201 + pairIndex * 100, namingEvidence: first.namingEvidence },
|
stage: { stageId: `pair:${pairId}:second`, ordinal: 1, objectId: `pair:${pairId}:first`, objectTag: 1101 + pairIndex * 100, resultObjectId: `pair:${pairId}:second`, resultObjectTag: 1201 + pairIndex * 100, namingEvidence: first.namingEvidence },
|
||||||
}
|
}
|
||||||
if (spec.decision === 'rejected') {
|
if (spec.decision === 'rejected') {
|
||||||
try {
|
try {
|
||||||
const trajectory = [spec.beforeValue, spec.editedValue, spec.beforeValue]
|
const trajectory = [spec.beforeValue, spec.editedValue, spec.beforeValue]
|
||||||
if (spec.rejectionAuthority === 'freecad-document') {
|
if (['freecad-document', 'occt-no-op'].includes(spec.rejectionAuthority)) {
|
||||||
const kernelAttempts = trajectory.map((value) => captureKernelCompatibilityStage(module, { ...secondDefinition, [spec.parameter]: value }, value, spec.kernelOutcome))
|
const kernelAttempts = trajectory.map((value) => captureKernelCompatibilityStage(module, { ...secondDefinition, [spec.parameter]: value }, value, spec.kernelOutcome))
|
||||||
const kernelRestoredExactly = JSON.stringify(kernelAttempts[0]) === JSON.stringify(kernelAttempts[2])
|
const kernelRestoredExactly = JSON.stringify(kernelAttempts[0]) === JSON.stringify(kernelAttempts[2])
|
||||||
if (!kernelRestoredExactly) fail(`${pair} OCCT diagnostic probe did not restore exactly.`)
|
if (!kernelRestoredExactly) fail(`${pair} OCCT diagnostic probe did not restore exactly.`)
|
||||||
const persistence = await persistPair(pair, first.response.resultStep, first.namingEvidence, 'rejected')
|
const persistence = await persistPair(pair, first.response.resultStep, first.namingEvidence, 'rejected')
|
||||||
|
const freecadProfileAccepted = persistence.checks.freecadProfileAccepted === true
|
||||||
|
const freecadProfileNoOp = persistence.checks.freecadProfileNoOp === true
|
||||||
return {
|
return {
|
||||||
taskId: `TSN-PAIR-${pairId}`,
|
taskId: `TSN-PAIR-${pairId}`,
|
||||||
pair,
|
pair,
|
||||||
classification: 'rejected',
|
classification: 'rejected',
|
||||||
reasonCode: 'freecad-input-precondition-reject-with-kernel-diagnostic-and-clean-resave',
|
reasonCode: spec.rejectionAuthority === 'occt-no-op'
|
||||||
|
? freecadProfileAccepted ? 'native-builder-no-op-with-freecad-profile-acceptance-and-clean-resave' : freecadProfileNoOp ? 'native-and-freecad-profile-no-op-with-clean-resave' : 'native-builder-no-op-and-freecad-profile-reject-with-clean-resave'
|
||||||
|
: 'freecad-input-precondition-reject-with-kernel-diagnostic-and-clean-resave',
|
||||||
nativeDecision: 'rejected',
|
nativeDecision: 'rejected',
|
||||||
first: first.report,
|
first: first.report,
|
||||||
rejection: { scope: 'second-operation-only', authority: 'freecad-document', parameter: spec.parameter, trajectory, kernelAttempts, kernelRestoredExactly, persistence },
|
rejection: { scope: 'second-operation-only', authority: spec.rejectionAuthority, parameter: spec.parameter, trajectory, kernelAttempts, kernelRestoredExactly, persistence },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const attempts = trajectory.map((value) => captureRejectedStage(module, { ...secondDefinition, [spec.parameter]: value }))
|
const attempts = trajectory.map((value) => captureRejectedStage(module, { ...secondDefinition, [spec.parameter]: value }))
|
||||||
@@ -453,6 +467,7 @@ const classifyPair = async (fromOperation, toOperation, pairIndex) => {
|
|||||||
|
|
||||||
const operations = ['fuse', 'cut', 'common', 'rotate', 'pad', 'pocket', 'loft', 'pipe', 'revolution', 'groove', 'fillet', 'chamfer', 'hole', 'draft', 'thickness', 'linear-pattern', 'polar-pattern', 'mirrored', 'multi-transform']
|
const operations = ['fuse', 'cut', 'common', 'rotate', 'pad', 'pocket', 'loft', 'pipe', 'revolution', 'groove', 'fillet', 'chamfer', 'hole', 'draft', 'thickness', 'linear-pattern', 'polar-pattern', 'mirrored', 'multi-transform']
|
||||||
const orderedPairPrefix = [...operations.map((toOperation) => ['fuse', toOperation]), ['cut', 'fuse'], ['cut', 'cut'], ['cut', 'common'], ['cut', 'pad'], ['cut', 'pocket'], ['cut', 'loft'], ['cut', 'pipe'], ['cut', 'revolution'], ['cut', 'groove'], ['cut', 'fillet'], ['cut', 'chamfer'], ['cut', 'hole'], ['cut', 'draft'], ['cut', 'thickness'], ['cut', 'linear-pattern'], ['cut', 'polar-pattern'], ['cut', 'mirrored'], ['cut', 'multi-transform'], ['common', 'fuse'], ['common', 'cut'], ['common', 'common'], ['common', 'rotate'], ['common', 'pad'], ['common', 'pocket'], ['common', 'loft'], ['common', 'pipe'], ['common', 'revolution'], ['common', 'groove'], ['common', 'fillet'], ['common', 'chamfer'], ['common', 'hole'], ['common', 'draft'], ['common', 'thickness'], ['common', 'linear-pattern'], ['common', 'polar-pattern'], ['common', 'mirrored'], ['common', 'multi-transform'], ['rotate', 'fuse'], ['rotate', 'cut'], ['rotate', 'common'], ['rotate', 'rotate'], ['rotate', 'pad'], ['rotate', 'pocket'], ['rotate', 'loft'], ['rotate', 'pipe'], ['rotate', 'revolution'], ['rotate', 'groove'], ['rotate', 'chamfer'], ['rotate', 'hole'], ['rotate', 'draft'], ['rotate', 'thickness'], ['rotate', 'linear-pattern'], ['rotate', 'polar-pattern'], ['rotate', 'mirrored'], ['rotate', 'multi-transform'], ['pad', 'fuse'], ['pad', 'cut'], ['pad', 'common'], ['pad', 'rotate'], ['pad', 'pad'], ['pad', 'pocket'], ['pad', 'loft'], ['pad', 'pipe'], ['pad', 'revolution'], ['pad', 'groove'], ['pad', 'fillet'], ['pad', 'chamfer'], ['pad', 'hole'], ['pad', 'draft'], ['pad', 'thickness'], ['pad', 'linear-pattern'], ['pad', 'polar-pattern'], ['pad', 'mirrored'], ['pad', 'multi-transform'], ['pocket', 'fuse'], ['pocket', 'cut'], ['pocket', 'common'], ['pocket', 'rotate'], ['pocket', 'pad'], ['pocket', 'pocket'], ['pocket', 'loft'], ['pocket', 'pipe'], ['pocket', 'revolution'], ['pocket', 'groove'], ['pocket', 'fillet'], ['pocket', 'chamfer'], ['pocket', 'hole'], ['pocket', 'draft'], ['pocket', 'thickness'], ['pocket', 'linear-pattern'], ['pocket', 'polar-pattern'], ['pocket', 'mirrored'], ['pocket', 'multi-transform'], ['loft', 'fuse'], ['loft', 'cut'], ['loft', 'common'], ['loft', 'rotate'], ['loft', 'pad'], ['loft', 'pocket'], ['loft', 'loft'], ['loft', 'pipe'], ['loft', 'revolution'], ['loft', 'groove'], ['loft', 'fillet'], ['loft', 'chamfer'], ['loft', 'hole'], ['loft', 'draft'], ['loft', 'thickness'], ['loft', 'linear-pattern'], ['loft', 'polar-pattern'], ['loft', 'mirrored'], ['loft', 'multi-transform'], ['pipe', 'fuse'], ['pipe', 'cut'], ['pipe', 'common'], ['pipe', 'rotate'], ['pipe', 'pad'], ['pipe', 'pocket'], ['pipe', 'loft'], ['pipe', 'pipe'], ['pipe', 'revolution'], ['pipe', 'groove'], ['pipe', 'fillet'], ['pipe', 'chamfer'], ['pipe', 'hole'], ['pipe', 'draft'], ['pipe', 'thickness'], ['pipe', 'linear-pattern'], ['pipe', 'polar-pattern'], ['pipe', 'mirrored'], ['pipe', 'multi-transform'], ['revolution', 'fuse'], ['revolution', 'cut'], ['revolution', 'common'], ['revolution', 'rotate'], ['revolution', 'pad'], ['revolution', 'pocket'], ['revolution', 'loft'], ['revolution', 'pipe'], ['revolution', 'revolution'], ['revolution', 'groove'], ['revolution', 'fillet'], ['revolution', 'chamfer'], ['revolution', 'hole'], ['revolution', 'draft'], ['revolution', 'thickness'], ['revolution', 'linear-pattern'], ['revolution', 'polar-pattern'], ['revolution', 'mirrored'], ['revolution', 'multi-transform'], ['groove', 'fuse'], ['groove', 'cut'], ['groove', 'common'], ['groove', 'rotate'], ['groove', 'pad'], ['groove', 'pocket'], ['groove', 'loft'], ['groove', 'pipe'], ['groove', 'revolution'], ['groove', 'groove'], ['groove', 'fillet'], ['groove', 'chamfer'], ['groove', 'hole'], ['groove', 'draft'], ['groove', 'thickness'], ['groove', 'linear-pattern'], ['groove', 'polar-pattern'], ['groove', 'mirrored']]
|
const orderedPairPrefix = [...operations.map((toOperation) => ['fuse', toOperation]), ['cut', 'fuse'], ['cut', 'cut'], ['cut', 'common'], ['cut', 'pad'], ['cut', 'pocket'], ['cut', 'loft'], ['cut', 'pipe'], ['cut', 'revolution'], ['cut', 'groove'], ['cut', 'fillet'], ['cut', 'chamfer'], ['cut', 'hole'], ['cut', 'draft'], ['cut', 'thickness'], ['cut', 'linear-pattern'], ['cut', 'polar-pattern'], ['cut', 'mirrored'], ['cut', 'multi-transform'], ['common', 'fuse'], ['common', 'cut'], ['common', 'common'], ['common', 'rotate'], ['common', 'pad'], ['common', 'pocket'], ['common', 'loft'], ['common', 'pipe'], ['common', 'revolution'], ['common', 'groove'], ['common', 'fillet'], ['common', 'chamfer'], ['common', 'hole'], ['common', 'draft'], ['common', 'thickness'], ['common', 'linear-pattern'], ['common', 'polar-pattern'], ['common', 'mirrored'], ['common', 'multi-transform'], ['rotate', 'fuse'], ['rotate', 'cut'], ['rotate', 'common'], ['rotate', 'rotate'], ['rotate', 'pad'], ['rotate', 'pocket'], ['rotate', 'loft'], ['rotate', 'pipe'], ['rotate', 'revolution'], ['rotate', 'groove'], ['rotate', 'chamfer'], ['rotate', 'hole'], ['rotate', 'draft'], ['rotate', 'thickness'], ['rotate', 'linear-pattern'], ['rotate', 'polar-pattern'], ['rotate', 'mirrored'], ['rotate', 'multi-transform'], ['pad', 'fuse'], ['pad', 'cut'], ['pad', 'common'], ['pad', 'rotate'], ['pad', 'pad'], ['pad', 'pocket'], ['pad', 'loft'], ['pad', 'pipe'], ['pad', 'revolution'], ['pad', 'groove'], ['pad', 'fillet'], ['pad', 'chamfer'], ['pad', 'hole'], ['pad', 'draft'], ['pad', 'thickness'], ['pad', 'linear-pattern'], ['pad', 'polar-pattern'], ['pad', 'mirrored'], ['pad', 'multi-transform'], ['pocket', 'fuse'], ['pocket', 'cut'], ['pocket', 'common'], ['pocket', 'rotate'], ['pocket', 'pad'], ['pocket', 'pocket'], ['pocket', 'loft'], ['pocket', 'pipe'], ['pocket', 'revolution'], ['pocket', 'groove'], ['pocket', 'fillet'], ['pocket', 'chamfer'], ['pocket', 'hole'], ['pocket', 'draft'], ['pocket', 'thickness'], ['pocket', 'linear-pattern'], ['pocket', 'polar-pattern'], ['pocket', 'mirrored'], ['pocket', 'multi-transform'], ['loft', 'fuse'], ['loft', 'cut'], ['loft', 'common'], ['loft', 'rotate'], ['loft', 'pad'], ['loft', 'pocket'], ['loft', 'loft'], ['loft', 'pipe'], ['loft', 'revolution'], ['loft', 'groove'], ['loft', 'fillet'], ['loft', 'chamfer'], ['loft', 'hole'], ['loft', 'draft'], ['loft', 'thickness'], ['loft', 'linear-pattern'], ['loft', 'polar-pattern'], ['loft', 'mirrored'], ['loft', 'multi-transform'], ['pipe', 'fuse'], ['pipe', 'cut'], ['pipe', 'common'], ['pipe', 'rotate'], ['pipe', 'pad'], ['pipe', 'pocket'], ['pipe', 'loft'], ['pipe', 'pipe'], ['pipe', 'revolution'], ['pipe', 'groove'], ['pipe', 'fillet'], ['pipe', 'chamfer'], ['pipe', 'hole'], ['pipe', 'draft'], ['pipe', 'thickness'], ['pipe', 'linear-pattern'], ['pipe', 'polar-pattern'], ['pipe', 'mirrored'], ['pipe', 'multi-transform'], ['revolution', 'fuse'], ['revolution', 'cut'], ['revolution', 'common'], ['revolution', 'rotate'], ['revolution', 'pad'], ['revolution', 'pocket'], ['revolution', 'loft'], ['revolution', 'pipe'], ['revolution', 'revolution'], ['revolution', 'groove'], ['revolution', 'fillet'], ['revolution', 'chamfer'], ['revolution', 'hole'], ['revolution', 'draft'], ['revolution', 'thickness'], ['revolution', 'linear-pattern'], ['revolution', 'polar-pattern'], ['revolution', 'mirrored'], ['revolution', 'multi-transform'], ['groove', 'fuse'], ['groove', 'cut'], ['groove', 'common'], ['groove', 'rotate'], ['groove', 'pad'], ['groove', 'pocket'], ['groove', 'loft'], ['groove', 'pipe'], ['groove', 'revolution'], ['groove', 'groove'], ['groove', 'fillet'], ['groove', 'chamfer'], ['groove', 'hole'], ['groove', 'draft'], ['groove', 'thickness'], ['groove', 'linear-pattern'], ['groove', 'polar-pattern'], ['groove', 'mirrored']]
|
||||||
|
orderedPairPrefix.push(['groove', 'multi-transform'], ['fillet', 'fuse'], ['fillet', 'cut'], ['fillet', 'common'], ['fillet', 'rotate'], ['fillet', 'pad'], ['fillet', 'pocket'], ['fillet', 'loft'], ['fillet', 'pipe'], ['fillet', 'revolution'], ['fillet', 'groove'], ['fillet', 'fillet'], ['fillet', 'chamfer'], ['fillet', 'hole'], ['fillet', 'draft'], ['fillet', 'thickness'], ['fillet', 'linear-pattern'], ['fillet', 'polar-pattern'], ['fillet', 'multi-transform'], ['chamfer', 'fuse'])
|
||||||
const classifications = []
|
const classifications = []
|
||||||
const selectedPairs = process.env.FREECAD_ONLY_PAIR ? orderedPairPrefix.filter(([fromOperation, toOperation]) => `${fromOperation}->${toOperation}` === process.env.FREECAD_ONLY_PAIR) : orderedPairPrefix
|
const selectedPairs = process.env.FREECAD_ONLY_PAIR ? orderedPairPrefix.filter(([fromOperation, toOperation]) => `${fromOperation}->${toOperation}` === process.env.FREECAD_ONLY_PAIR) : orderedPairPrefix
|
||||||
if (process.env.FREECAD_ONLY_PAIR && selectedPairs.length !== 1) fail(`focused pair ${process.env.FREECAD_ONLY_PAIR} is not in the classified prefix.`)
|
if (process.env.FREECAD_ONLY_PAIR && selectedPairs.length !== 1) fail(`focused pair ${process.env.FREECAD_ONLY_PAIR} is not in the classified prefix.`)
|
||||||
|
|||||||
182
后续工作.txt
182
后续工作.txt
@@ -1919,4 +1919,186 @@ git diff --check
|
|||||||
- `5 -> 6 -> 5` 镜像平面轨迹使体积在 `1000 -> 1190.575222 -> 1000` 间变化,编辑态增至 22 Face,并精确恢复名义摘要、history 与语义 naming。
|
- `5 -> 6 -> 5` 镜像平面轨迹使体积在 `1000 -> 1190.575222 -> 1000` 间变化,编辑态增至 22 Face,并精确恢复名义摘要、history 与语义 naming。
|
||||||
- 上游 Groove naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定镜像平面、互补融合、变异、恢复和持久化证据。
|
- 上游 Groove naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定镜像平面、互补融合、变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-groove-multi-transform`
|
||||||
|
|
||||||
|
`groove->multi-transform` 已完成原生接受分类,并闭合 Groove 起始行的全部 19 个有序操作对:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut` 双输入 builder,生成有效 1 Solid、体积 `995.287611`、10 Face 和 18 条原生 history。
|
||||||
|
- 下游使用 ordered `BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse` builder,依次执行 X 平移和关于 `x=5` 的镜像并融合;名义结果为有效 1 Solid、24 Face、体积 `2600`,包含 525 条原生 history。
|
||||||
|
- `8 -> 9 -> 8` 首步 X 平移轨迹使体积在 `2600 -> 2797.6768884 -> 2600` 间变化,编辑态增至 40 Face,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Groove naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定 ordered builder、变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-fuse`
|
||||||
|
|
||||||
|
`fillet->fuse` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepAlgoAPI_Fuse` 双输入 builder,并以相交工具形成有效 1 Solid;名义结果为 33 Face、体积 `1071.3666774`,包含 79 条原生 history。
|
||||||
|
- `8 -> 7 -> 8` 工具 X 偏移轨迹使体积在 `1071.3666774 -> 1046.4010137 -> 1071.3666774` 间变化,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定相交融合、变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-cut`
|
||||||
|
|
||||||
|
`fillet->cut` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepAlgoAPI_Cut` 双输入 builder,对 Fillet 结果执行减料;名义结果为有效 1 Solid、31 Face、体积 `932.1027009`,包含 42 条原生 history。
|
||||||
|
- `4 -> 3 -> 4` 工具尺寸轨迹使体积在 `932.1027009 -> 969.0683646 -> 932.1027009` 间变化,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定减料变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-common`
|
||||||
|
|
||||||
|
`fillet->common` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepAlgoAPI_Common` 双输入 builder,以相交工具求 Fillet 结果的布尔交集;名义结果为有效 1 Solid、10 Face、体积 `74.5643421`,包含 360 条原生 history。
|
||||||
|
- `7 -> 6 -> 7` 工具 X 偏移轨迹使体积在 `74.5643421 -> 99.5300058 -> 74.5643421` 间变化,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定有体积交集、变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-rotate`
|
||||||
|
|
||||||
|
`fillet->rotate` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepBuilderAPI_Transform` 单输入 builder 绕 Z 轴旋转 Fillet 结果;名义结果保持有效 1 Solid、26 Face 和体积 `995.9653557`,包含 338 条原生 history。
|
||||||
|
- `15 -> 22.5 -> 15` 角度轨迹改变包围盒(名义 `[-2.4982926, 0.0898978, -1e-7, 9.5693604, 12.1575509, 10.0000001]`,编辑态 `[-3.7042092, 0.1226251, -1e-7, 9.1161702, 12.9430046, 10.0000001]`),并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定刚体变换、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-pad`
|
||||||
|
|
||||||
|
`fillet->pad` 已完成原生拒绝分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- OCCT `BRepPrimAPI_MakePrism` 对 Fillet Solid 在 `5 -> 7.5 -> 5` 长度轨迹中稳定于 builder 阶段拒绝,三次均不产生结果 Shape 或 history。
|
||||||
|
- FreeCAD `PartDesign::Pad` 使用同一 Fillet Solid 作为 Profile,返回 `FeatureExtrusion: Length: Could not extrude the sketch!`,结果 Shape 为空且状态含 `Invalid`;未伪造下游 naming 或接受变异证据。
|
||||||
|
- transaction abort 后对象集、源 Shape 和 BREP 哈希精确恢复;干净 FCStd save/reopen/resave 三阶段一致,focused gate 已锁定拒绝阶段、诊断、回滚和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-pocket`
|
||||||
|
|
||||||
|
`fillet->pocket` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepPrimAPI_MakePrism+BRepAlgoAPI_Cut` 双输入 builder,对 Fillet 结果执行减料拉伸;名义结果为有效 1 Solid、28 Face、体积 `966.2980048`,包含 100 条原生 history。
|
||||||
|
- `5 -> 4 -> 5` 深度轨迹使体积在 `966.2980048 -> 972.2636685 -> 966.2980048` 间变化,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定减料拉伸、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-loft`
|
||||||
|
|
||||||
|
`fillet->loft` 已完成原生拒绝分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- OCCT `BRepOffsetAPI_ThruSections` 在 `false -> true -> false` ruled 轨迹中生成有效 1 Solid 和 24 条 history,但该结果仅作为 `kernel-superset-only` 诊断,不提升 FreeCAD 能力。
|
||||||
|
- FreeCAD `Part::Loft` 对 Fillet Solid section 返回 `Profile shape is not a single vertex, edge, wire nor face.`,结果 Shape 为空且状态含 `Invalid`;未伪造下游 naming 或接受变异证据。
|
||||||
|
- transaction abort 后对象集、源 Shape 和 BREP 哈希精确恢复;干净 FCStd save/reopen/resave 三阶段一致,focused gate 已锁定 FreeCAD 决策权、kernel 诊断、回滚和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-pipe`
|
||||||
|
|
||||||
|
`fillet->pipe` 已完成原生拒绝分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- OCCT `BRepOffsetAPI_MakePipe` 在 `15 -> 12 -> 15` spine 长度轨迹中均产生无效零体积 Shape 和 28 条 history,仅记为 `kernel-invalid-result`,不伪造接受 Shape。
|
||||||
|
- FreeCAD `Part::Sweep` 对 Fillet Solid section 返回 `A fatal error occurred when making the sweep`,结果 Shape 为空且状态含 `Invalid`。
|
||||||
|
- transaction abort 后对象集、源 Shape 和 BREP 哈希精确恢复;干净 FCStd save/reopen/resave 三阶段一致,focused gate 已锁定 FreeCAD 决策权、kernel 无效诊断、回滚和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-revolution`
|
||||||
|
|
||||||
|
`fillet->revolution` 已完成原生拒绝分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- OCCT `BRepPrimAPI_MakeRevol` 对 Fillet Solid 在 `360 -> 270 -> 360` 角度轨迹中稳定于 builder 阶段拒绝,三次均不产生结果 Shape 或 history。
|
||||||
|
- FreeCAD `Part::Revolution` 使用同一 Fillet Solid 作为 Source,返回 `Solids are not Processed`,结果 Shape 为空且状态含 `Invalid`;未伪造下游 naming 或接受变异证据。
|
||||||
|
- transaction abort 后对象集、源 Shape 和 BREP 哈希精确恢复;干净 FCStd save/reopen/resave 三阶段一致,focused gate 已锁定拒绝阶段、精确诊断、回滚和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-groove`
|
||||||
|
|
||||||
|
`fillet->groove` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepPrimAPI_MakeRevol+BRepAlgoAPI_Cut` 双输入 builder 对 Fillet 结果执行旋转减料;名义结果为有效 1 Solid、30 Face、体积 `991.2529668`,包含 18 条原生 history。
|
||||||
|
- `360 -> 180 -> 360` 角度轨迹使拓扑从 30 Face 变为 27 Face 后恢复,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定旋转减料、变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-fillet`
|
||||||
|
|
||||||
|
`fillet->fillet` 已完成原生拒绝分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 第二个 OCCT `BRepFilletAPI_MakeFillet` 对已圆角 Solid 在 `0.4 -> 0.6 -> 0.4` 半径轨迹中稳定于 builder 阶段拒绝,三次均不产生结果 Shape 或 history。
|
||||||
|
- FreeCAD `Part::Fillet` 使用同一 Fillet Solid 作为 Base,返回 `There are no suitable edges for chamfer or fillet`,结果 Shape 为空且状态含 `Invalid`;未伪造下游 naming 或接受变异证据。
|
||||||
|
- transaction abort 后对象集、源 Shape 和 BREP 哈希精确恢复;干净 FCStd save/reopen/resave 三阶段一致,focused gate 已锁定拒绝阶段、精确诊断、回滚和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-chamfer`
|
||||||
|
|
||||||
|
`fillet->chamfer` 已完成原生拒绝分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- OCCT `BRepFilletAPI_MakeChamfer` 对 Fillet Solid 在 `0.4 -> 0.6 -> 0.4` 距离轨迹中稳定于 builder 阶段拒绝,三次均不产生结果 Shape 或 history。
|
||||||
|
- FreeCAD `Part::Chamfer` 使用同一 Fillet Solid 作为 Base,返回 `There are no suitable edges for chamfer or fillet`,结果 Shape 为空且状态含 `Invalid`;未伪造下游 naming 或接受变异证据。
|
||||||
|
- transaction abort 后对象集、源 Shape 和 BREP 哈希精确恢复;干净 FCStd save/reopen/resave 三阶段一致,focused gate 已锁定拒绝阶段、精确诊断、回滚和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-hole`
|
||||||
|
|
||||||
|
`fillet->hole` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepPrimAPI_MakeCylinder+BRepAlgoAPI_Cut` builder 对 Fillet 结果执行中心贯穿孔;名义结果为有效 1 Solid、27 Face、体积 `964.5494292`,包含 23 条原生 history。
|
||||||
|
- `1 -> 1.5 -> 1` 半径轨迹使体积在 `964.5494292 -> 925.279521 -> 964.5494292` 间变化,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 下游获得无歧义 `native-evidence` naming,上游 Fillet 证据已传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-draft`
|
||||||
|
|
||||||
|
`fillet->draft` 已完成原生拒绝分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 只读原生适用性扫描枚举 Fillet 结果的全部 26 个 Face,在锁定的 +Z 拉伸方向与 XY 中性面下均无有效 Draft Shape;没有用选面 fallback 伪造接受。
|
||||||
|
- OCCT `BRepOffsetAPI_DraftAngle` 在 `5 -> 8 -> 5` 角度轨迹中稳定于 builder 阶段拒绝,三次均不产生结果 Shape 或 history。
|
||||||
|
- FreeCAD `PartDesign::Draft` 通过事务内 Body、DatumPlane、DatumLine 和 `PartDesign::Feature` Base 评估同一 Fillet 几何;Base 的有效性、拓扑数、体积、面积和边界摘要精确一致,同时显式记录 FreeCAD 元素映射导致的 BREP 重序列化哈希差异。
|
||||||
|
- FreeCAD 结果合同为空状态字符串、空 Shape 和 `Touched/Invalid`;transaction abort 后 Body 及所有临时对象消失,顶层源 Shape 的 BREP 哈希精确恢复,干净 FCStd save/reopen/resave 三阶段一致。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-thickness`
|
||||||
|
|
||||||
|
`fillet->thickness` 已完成原生 no-op 拒绝分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 只读原生扫描确认:全部 26 个 Face 在 `-0.4/-0.6` offset 下均返回与输入同摘要的 Shape;6 个主面的 `0.4/0.6` 正向 offset 只产生无效 Shape 或 builder 拒绝,没有可用的真实变异轨迹。
|
||||||
|
- OCCT `BRepOffsetAPI_MakeThickSolid` 在 `-0.4 -> -0.6 -> -0.4` 轨迹中每次均返回有效 Shape 和 1 条 history,但有效性、Solid/Face/Edge/Vertex、体积、面积、边界与 history 哈希全部不变,因此被显式分类为 `kernel-no-op`,不冒充接受。
|
||||||
|
- FreeCAD `Part::Thickness` 对同一 Fillet Solid 和 `Face2` 返回 `Valid/Up-to-date` 且 Shape 非空,但结果 Shape 摘要与输入逐字段相同,因此同样记为 `freecadProfileNoOp`。
|
||||||
|
- transaction abort 后对象集、源 Shape 和 BREP 哈希精确恢复;干净 FCStd save/reopen/resave 三阶段一致,focused gate 已锁定双 no-op、回滚和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-linear-pattern`
|
||||||
|
|
||||||
|
`fillet->linear-pattern` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse` builder 沿 X 方向复制并融合 Fillet 结果;名义结果为有效 1 Solid、42 Face、体积 `1794.8665943`,包含 266 条原生 history。
|
||||||
|
- `8 -> 9 -> 8` 平移轨迹使体积在 `1794.8665943 -> 1894.7292492 -> 1794.8665943` 间变化,X 上界从 18 变为 19 后恢复,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定交叠融合、变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-polar-pattern`
|
||||||
|
|
||||||
|
`fillet->polar-pattern` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse` builder 绕 Z 轴旋转复制并融合 Fillet 结果;30 度名义结果为有效 1 Solid、46 Face、体积 `1417.6209625`,包含 234 条原生 history。
|
||||||
|
- `30 -> 45 -> 30` 角度轨迹使体积在 `1417.6209625 -> 1580.485276 -> 1417.6209625` 间变化,面积和边界也同步变化,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定旋转融合、变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-fillet-multi-transform`
|
||||||
|
|
||||||
|
`fillet->multi-transform` 已完成原生接受分类,并闭合 Fillet 起始行中尚需分类的全部有序操作对:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeFillet` 单输入 builder,对 10x10x10 Box 的全部边执行圆角,生成有效 1 Solid、26 Face、体积 `995.9653557` 和 150 条原生 history。
|
||||||
|
- 下游使用 ordered `BRepBuilderAPI_Transform+BRepAlgoAPI_Fuse` builder,依次执行 X 平移、关于 `x=5` 的镜像并融合;名义结果为有效 1 Solid、58 Face、体积 `2593.7678329`,包含 1103 条原生 history。
|
||||||
|
- `8 -> 9 -> 8` 首步 X 平移轨迹使体积在 `2593.7678329 -> 2793.4931426 -> 2593.7678329` 间变化,边界从 `[-8, 18]` 扩展为 `[-9, 19]` 后恢复,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Fillet naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定 ordered builder、变异、恢复和持久化证据。
|
||||||
|
|
||||||
|
### `TSN-PAIR-chamfer-fuse`
|
||||||
|
|
||||||
|
`chamfer->fuse` 已完成原生接受分类:
|
||||||
|
|
||||||
|
- 上游使用真实 `BRepFilletAPI_MakeChamfer` 单输入 builder,对 10x10x10 Box 的全部边执行倒角,生成有效 1 Solid、26 Face、体积 `990.7413333` 和 150 条原生 history。
|
||||||
|
- 下游使用真实 `BRepAlgoAPI_Fuse` 双输入 builder,以相交工具融合 Chamfer 结果;名义结果为有效 1 Solid、33 Face、体积 `1066.6586667`,包含 78 条原生 history。
|
||||||
|
- `8 -> 7 -> 8` 工具 X 偏移轨迹使体积在 `1066.6586667 -> 1041.7386667 -> 1066.6586667` 间变化,X 上界从 13 变为 12 后恢复,并精确恢复名义摘要、history 与语义 naming。
|
||||||
|
- 上游 Chamfer naming 证据向下游传播;FreeCAD FCStd save/reopen/resave 三阶段 Shape 与 naming evidence 稳定,focused gate 已锁定相交融合、变异、恢复和持久化证据。
|
||||||
|
|
||||||
后续任务必须从机器队列的最新 `nextTask` 继续,不在本文手工维护任务名称。
|
后续任务必须从机器队列的最新 `nextTask` 继续,不在本文手工维护任务名称。
|
||||||
|
|||||||
Reference in New Issue
Block a user