feat: classify fillet ordered pair row
This commit is contained in:
@@ -119,6 +119,13 @@ const pairSpecOverrides = {
|
||||
'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->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 }) => {
|
||||
@@ -236,7 +243,8 @@ const captureKernelCompatibilityStage = (module, definition, parameterValue, exp
|
||||
try {
|
||||
const outcome = response.summary?.isValid === true ? 'accepted' : 'invalid-result'
|
||||
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 {
|
||||
operation: definition.operation,
|
||||
builder: operationSpecs[definition.operation].builder,
|
||||
@@ -244,7 +252,7 @@ const captureKernelCompatibilityStage = (module, definition, parameterValue, exp
|
||||
parameter: operationSpecs[definition.operation].parameter,
|
||||
parameterValue,
|
||||
runtime: 'occt-native',
|
||||
outcome: noHistorySuperset ? expectedOutcome : outcome,
|
||||
outcome: noHistorySuperset || noOp ? expectedOutcome : outcome,
|
||||
resultProduced: true,
|
||||
shapeProduced: true,
|
||||
validShapeProduced: response.summary.isValid === true,
|
||||
@@ -253,7 +261,7 @@ const captureKernelCompatibilityStage = (module, definition, parameterValue, exp
|
||||
summary: canonicalSummary(response.summary),
|
||||
historyRecords: response.records.length,
|
||||
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 {
|
||||
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
|
||||
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 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)}`)
|
||||
return persistence
|
||||
} finally {
|
||||
@@ -384,25 +393,30 @@ const classifyPair = async (fromOperation, toOperation, pairIndex) => {
|
||||
const secondDefinition = {
|
||||
operation: toOperation,
|
||||
objectStep: first.response.resultStep,
|
||||
inputSummary: first.report.summary,
|
||||
...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 },
|
||||
}
|
||||
if (spec.decision === 'rejected') {
|
||||
try {
|
||||
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 kernelRestoredExactly = JSON.stringify(kernelAttempts[0]) === JSON.stringify(kernelAttempts[2])
|
||||
if (!kernelRestoredExactly) fail(`${pair} OCCT diagnostic probe did not restore exactly.`)
|
||||
const persistence = await persistPair(pair, first.response.resultStep, first.namingEvidence, 'rejected')
|
||||
const freecadProfileAccepted = persistence.checks.freecadProfileAccepted === true
|
||||
const freecadProfileNoOp = persistence.checks.freecadProfileNoOp === true
|
||||
return {
|
||||
taskId: `TSN-PAIR-${pairId}`,
|
||||
pair,
|
||||
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',
|
||||
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 }))
|
||||
@@ -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 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 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.`)
|
||||
|
||||
Reference in New Issue
Block a user