import { spawnSync } from 'node:child_process'
import { createHash } from 'node:crypto'
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
import { unzipSync } from 'fflate'
import { decodeFcstdPropertyValue, inspectFcstdArchive, rewriteFcstdMetadataArchive, serializeFcstdMetadataArchive } from '../src/facade/fcstd'
import { createSketch } from '../src/facade/sketcher'
import type { DocumentSnapshot, ShapeResourceValue } from '../src/facade/types'

const root = fileURLToPath(new URL('..', import.meta.url))
const executable = resolve(root, '.cache/freecad/install-desktop/bin/FreeCAD')
const examplePath = resolve(root, '.cache/freecad/install-desktop/share/examples/PartDesignExample.FCStd')
const probePath = resolve(root, 'scripts/freecad-fcstd-gui-probe.py')
const pythonPath = resolve(root, '.cache/freecad/sysroot/usr/lib/python3/dist-packages')
const libraryPath = resolve(root, '.cache/freecad/sysroot/usr/lib/x86_64-linux-gnu')
const matplotlibConfig = resolve(root, '.cache/freecad/sysroot/etc/matplotlibrc')
const fail = (message: string): never => { throw new Error(`FreeCAD FCStd native oracle: ${message}`) }
const near = (actual: number | null, expected: number, tolerance = 1e-8) => typeof actual === 'number' && Number.isFinite(actual) && Math.abs(actual - expected) <= tolerance
type ProbeResult = {
  freecadVersion: string
  shapeNull: boolean | null
  shapeValid: boolean | null
  solidCount: number | null
  faceCount: number | null
  volume: number | null
  boundingBox: { min: number[]; max: number[] } | null
  shapeError: string | null
  properties: Record<string, unknown>
  geometryCount: number | null
  constraintCount: number | null
  constructionGeometry: number[] | null
  constraintNames: string[] | null
  constraintTypes: string[] | null
  externalGeometryCount: number | null
  externalGeoCount: number | null
  externalTypes: number[] | null
  externalLinks: Array<{ objectName: string; subElements: string[] }> | null
  externalStates: Array<{ ref: string; id: number; geometryType: string; flags: number }> | null
  mapMode: string | null
  attachmentSupport: Array<{ objectName: string; subElements: string[] }> | null
  attachmentOffset: { position: number[]; axis: number[]; angle: number } | null
}

const runFreecadProbe = (archivePath: string, objectName: string, extraEnv: NodeJS.ProcessEnv = {}): ProbeResult => {
  const child = spawnSync('xvfb-run', ['-a', executable, '--python-path', pythonPath, probePath], {
    cwd: root,
    encoding: 'utf8',
    maxBuffer: 16 * 1024 * 1024,
    timeout: 30_000,
    env: {
      ...process.env,
      PYTHONPATH: pythonPath,
      LD_LIBRARY_PATH: libraryPath,
      MATPLOTLIBRC: matplotlibConfig,
      MPLBACKEND: 'Agg',
      FREECAD_FCSTD_PATH: archivePath,
      FREECAD_FCSTD_OBJECT: objectName,
      ...extraEnv,
    },
  })
  const output = `${child.stdout ?? ''}\n${child.stderr ?? ''}`
  if (child.status !== 0) fail(`FreeCAD exited with ${child.status}: ${output.trim()}`)
  if (/Invalid Document\.xml|Reading failed from embedded file|Property .* already exists/i.test(output)) fail(`FreeCAD reported an archive read failure: ${output.trim()}`)
  const marker = output.match(/FREECAD_FCSTD_GUI_RESULT=(\{[^\r\n]+\})/)
  if (!marker) fail(`probe result marker is missing: ${output.trim()}`)
  return JSON.parse(marker[1]) as ProbeResult
}

const temporaryDirectory = await mkdtemp(join(tmpdir(), 'bitbybit-fcstd-oracle-'))
try {
  const sourceBytes = new Uint8Array(await readFile(examplePath))
  const sourceInspection = inspectFcstdArchive(sourceBytes)
  const proxyPreservedBytes = rewriteFcstdMetadataArchive(sourceBytes, sourceInspection.proxyDocument)
  const sha256 = (bytes: Uint8Array) => createHash('sha256').update(bytes).digest('hex')
  const sourceSha256 = sha256(sourceBytes)
  const proxyPreservedSha256 = sha256(proxyPreservedBytes)
  if (sourceSha256 !== proxyPreservedSha256 || !Buffer.from(sourceBytes).equals(Buffer.from(proxyPreservedBytes))) fail('read-only proxy archive was not preserved byte-for-byte.')
  const proxyPreservedPath = join(temporaryDirectory, 'proxy-preserved.fcstd')
  const proxyResavedPath = join(temporaryDirectory, 'proxy-freecad-resaved.fcstd')
  await writeFile(proxyPreservedPath, proxyPreservedBytes)
  const proxyResult = runFreecadProbe(proxyPreservedPath, 'Body', { FREECAD_FCSTD_RESAVE_PATH: proxyResavedPath })
  if (proxyResult.freecadVersion !== '1.1.1' || proxyResult.shapeNull !== false || proxyResult.shapeValid !== true || proxyResult.faceCount !== 23) fail(`unexpected byte-preserved proxy archive result: ${JSON.stringify(proxyResult)}`)
  const proxyResavedInspection = inspectFcstdArchive(new Uint8Array(await readFile(proxyResavedPath)))
  if (sourceInspection.compatibility.proxyObjects !== 8 || sourceInspection.compatibility.blockedObjects !== 0 || proxyResavedInspection.objects.length !== sourceInspection.objects.length || proxyResavedInspection.compatibility.proxyObjects !== sourceInspection.compatibility.proxyObjects) fail('FreeCAD resave did not preserve the native proxy object inventory.')
  const sourceObject = sourceInspection.objects.find((object) => object.name === 'Body') ?? fail('PartDesignExample Body is missing.')
  const sourceShapeProperty = sourceObject.properties.find((property) => property.name === 'Shape') ?? fail('PartDesignExample Body.Shape is missing.')
  const decoded = decodeFcstdPropertyValue(sourceShapeProperty)
  if (!decoded.decoded || !decoded.value || typeof decoded.value !== 'object') fail('Body.Shape could not be decoded.')
  const shapeValue = decoded.value as ShapeResourceValue
  if (shapeValue.hasherIndex !== 0 || shapeValue.elementMapResource !== 'Body.Shape.Map.txt') fail('Body.Shape native history pointers do not match the locked oracle.')
  const sourceFiles = unzipSync(sourceBytes)
  const document: DocumentSnapshot = {
    id: 'fcstd-native-oracle',
    label: 'FCStd native oracle',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: [{ id: 'Body', label: 'Body', type: 'feature', state: 'up-to-date' }],
    objects: [{
      id: 'Body',
      typeId: 'Part::Feature',
      properties: [{ name: 'Shape', label: 'Shape', group: 'Base', scope: 'data', type: 'Part::PropertyPartShape', value: shapeValue }],
    }],
    dependencies: [],
    recompute: { generation: 0, status: 'idle', objectStates: { Body: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const requiredResources = ['StringHasher.Table.txt', 'Body.Shape.brp', 'Body.Shape.Map.txt'] as const
  for (const path of requiredResources) if (!sourceFiles[path]) fail(`locked oracle resource is missing: ${path}`)
  const opaqueEntries: Record<string, Uint8Array> = Object.fromEntries(requiredResources.map((path) => [path, new Uint8Array(sourceFiles[path])]))
  const webArchive = serializeFcstdMetadataArchive(document, { opaqueEntries })
  const webArchivePath = join(temporaryDirectory, 'web.fcstd')
  const resavedPath = join(temporaryDirectory, 'freecad-resaved.fcstd')
  await writeFile(webArchivePath, webArchive)

  const result = runFreecadProbe(webArchivePath, 'Body', { FREECAD_FCSTD_RESAVE_PATH: resavedPath })
  if (result.freecadVersion !== '1.1.1' || result.shapeNull !== false || result.shapeValid !== true || result.shapeError !== null || result.solidCount !== 1 || result.faceCount !== 23 || !near(result.volume, 583719.3669394433, 1e-6)) fail(`unexpected desktop Shape result: ${JSON.stringify(result)}`)

  const resavedInspection = inspectFcstdArchive(new Uint8Array(await readFile(resavedPath)))
  const resavedShape = resavedInspection.objects.find((object) => object.name === 'Body')?.properties.find((property) => property.name === 'Shape')?.shapeResource
  const resavedMap = resavedInspection.elementMapResources.find((resource) => resource.path === 'Body.Shape.Map.txt')
  const resavedHasher = resavedInspection.stringHasherResource
  if (resavedShape?.hasherIndex !== 0 || resavedShape.elementMap !== '1.15.70200.5' || resavedShape.elementMapResource !== 'Body.Shape.Map.txt' || resavedShape.elementMapEntries?.[0]?.key !== 'Dummy' || resavedShape.elementMapEntries[0].value !== 'Dummy') fail('FreeCAD resave did not preserve Shape history pointers.')
  if (resavedMap?.postfixCount !== 63 || resavedMap.mapCount !== 2 || resavedHasher?.status !== 'available') fail('FreeCAD resave did not preserve ElementMap2/StringHasher resources.')

  const primitiveDocument: DocumentSnapshot = {
    id: 'fcstd-native-part-box',
    label: 'FCStd native Part Box',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: ['Box', 'Cylinder', 'Sphere', 'Ellipsoid', 'Cone', 'Torus', 'Prism', 'Wedge', 'Tool', 'Fuse', 'Cut', 'Common'].map((id) => ({ id, label: id, type: 'feature', state: 'up-to-date' })),
    objects: [
      { id: 'Box', typeId: 'Part::Box', properties: [
        { name: 'Length', label: 'Length', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 2 },
        { name: 'Width', label: 'Width', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 3 },
        { name: 'Height', label: 'Height', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 4 },
        { name: 'WebMode', label: 'Web mode', group: 'Web', scope: 'data', type: 'App::PropertyEnumeration', value: 'Manufacturing', options: ['Design', 'Manufacturing', 'Inspection'] },
        { name: 'WebProgress', label: 'Web progress', group: 'Web', scope: 'data', type: 'App::PropertyPercent', value: 35 },
      ] },
      { id: 'Cylinder', typeId: 'Part::Cylinder', properties: [
        { name: 'Radius', label: 'Radius', group: 'Cylinder', scope: 'data', type: 'App::PropertyLength', value: 2 },
        { name: 'Height', label: 'Height', group: 'Cylinder', scope: 'data', type: 'App::PropertyLength', value: 5 },
        { name: 'Angle', label: 'Angle', group: 'Cylinder', scope: 'data', type: 'App::PropertyAngle', value: 180 },
      ] },
      { id: 'Sphere', typeId: 'Part::Sphere', properties: [{ name: 'Radius', label: 'Radius', group: 'Sphere', scope: 'data', type: 'App::PropertyLength', value: 3 }] },
      { id: 'Ellipsoid', typeId: 'Part::Ellipsoid', properties: [
        { name: 'Radius1', label: 'Z radius', group: 'Ellipsoid', scope: 'data', type: 'App::PropertyLength', value: 2 },
        { name: 'Radius2', label: 'X radius', group: 'Ellipsoid', scope: 'data', type: 'App::PropertyLength', value: 4 },
        { name: 'Radius3', label: 'Y radius', group: 'Ellipsoid', scope: 'data', type: 'App::PropertyLength', value: 0 },
        { name: 'Angle1', label: 'Lower angle', group: 'Ellipsoid', scope: 'data', type: 'App::PropertyAngle', value: -90 },
        { name: 'Angle2', label: 'Upper angle', group: 'Ellipsoid', scope: 'data', type: 'App::PropertyAngle', value: 90 },
        { name: 'Angle3', label: 'Azimuth angle', group: 'Ellipsoid', scope: 'data', type: 'App::PropertyAngle', value: 360 },
      ] },
      { id: 'Cone', typeId: 'Part::Cone', properties: [
        { name: 'Radius1', label: 'Radius 1', group: 'Cone', scope: 'data', type: 'App::PropertyLength', value: 4 },
        { name: 'Radius2', label: 'Radius 2', group: 'Cone', scope: 'data', type: 'App::PropertyLength', value: 2 },
        { name: 'Height', label: 'Height', group: 'Cone', scope: 'data', type: 'App::PropertyLength', value: 6 },
        { name: 'Angle', label: 'Angle', group: 'Cone', scope: 'data', type: 'App::PropertyAngle', value: 360 },
      ] },
      { id: 'Torus', typeId: 'Part::Torus', properties: [
        { name: 'Radius1', label: 'Major radius', group: 'Torus', scope: 'data', type: 'App::PropertyLength', value: 10 },
        { name: 'Radius2', label: 'Minor radius', group: 'Torus', scope: 'data', type: 'App::PropertyLength', value: 2 },
        { name: 'Angle1', label: 'Lower angle', group: 'Torus', scope: 'data', type: 'App::PropertyAngle', value: -180 },
        { name: 'Angle2', label: 'Upper angle', group: 'Torus', scope: 'data', type: 'App::PropertyAngle', value: 180 },
        { name: 'Angle3', label: 'Azimuth angle', group: 'Torus', scope: 'data', type: 'App::PropertyAngle', value: 270 },
      ] },
      { id: 'Prism', typeId: 'Part::Prism', properties: [
        { name: 'Polygon', label: 'Polygon sides', group: 'Prism', scope: 'data', type: 'App::PropertyInteger', value: 6 },
        { name: 'Circumradius', label: 'Circumradius', group: 'Prism', scope: 'data', type: 'App::PropertyLength', value: 2 },
        { name: 'Height', label: 'Height', group: 'Prism', scope: 'data', type: 'App::PropertyLength', value: 10 },
        { name: 'FirstAngle', label: 'First angle', group: 'Prism', scope: 'data', type: 'App::PropertyAngle', value: 10 },
        { name: 'SecondAngle', label: 'Second angle', group: 'Prism', scope: 'data', type: 'App::PropertyAngle', value: -5 },
      ] },
      { id: 'Wedge', typeId: 'Part::Wedge', properties: [
        { name: 'Xmin', label: 'X minimum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 0 },
        { name: 'Ymin', label: 'Y minimum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 0 },
        { name: 'Zmin', label: 'Z minimum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 0 },
        { name: 'X2min', label: 'X2 minimum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 0 },
        { name: 'Z2min', label: 'Z2 minimum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 0 },
        { name: 'Xmax', label: 'X maximum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 10 },
        { name: 'Ymax', label: 'Y maximum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 10 },
        { name: 'Zmax', label: 'Z maximum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 10 },
        { name: 'X2max', label: 'X2 maximum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 8 },
        { name: 'Z2max', label: 'Z2 maximum', group: 'Wedge', scope: 'data', type: 'App::PropertyLength', value: 8 },
      ] },
      { id: 'Tool', typeId: 'Part::Box', properties: [
        { name: 'Length', label: 'Length', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 1 },
        { name: 'Width', label: 'Width', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 1 },
        { name: 'Height', label: 'Height', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 1 },
      ] },
      ...['Fuse', 'Cut', 'Common'].map((id) => ({ id, typeId: `Part::${id}`, properties: [
        { name: 'Base', label: 'Base', group: 'Boolean', scope: 'data' as const, type: 'App::PropertyLink' as const, value: 'Box' },
        { name: 'Tool', label: 'Tool', group: 'Boolean', scope: 'data' as const, type: 'App::PropertyLink' as const, value: 'Tool' },
        { name: 'Refine', label: 'Refine shape', group: 'Boolean', scope: 'data' as const, type: 'App::PropertyBool' as const, value: id === 'Common' },
      ] })),
    ],
    dependencies: ['Fuse', 'Cut', 'Common'].flatMap((sourceId) => [
      { sourceId, targetId: 'Box', relation: 'link' as const, propertyName: 'Base' },
      { sourceId, targetId: 'Tool', relation: 'link' as const, propertyName: 'Tool' },
    ]),
    recompute: { generation: 0, status: 'idle', objectStates: Object.fromEntries(['Box', 'Cylinder', 'Sphere', 'Ellipsoid', 'Cone', 'Torus', 'Prism', 'Wedge', 'Tool', 'Fuse', 'Cut', 'Common'].map((id) => [id, 'up-to-date' as const])), dirtyObjects: [], order: [], errors: [] },
  }
  const primitiveArchivePath = join(temporaryDirectory, 'native-part-box.fcstd')
  const primitiveResavedPath = join(temporaryDirectory, 'native-part-resaved.fcstd')
  await writeFile(primitiveArchivePath, serializeFcstdMetadataArchive(primitiveDocument))
  const primitiveCases = [
    { objectName: 'Box', expectedVolume: 24, expectedFaces: 6, propertyNames: 'Length,Width,Height,WebMode,WebProgress', properties: { Length: 2, Width: 3, Height: 4, WebMode: 'Manufacturing', WebProgress: 35 } },
    { objectName: 'Cylinder', expectedVolume: 10 * Math.PI, propertyNames: 'Radius,Height,Angle', properties: { Radius: 2, Height: 5, Angle: 180 } },
    { objectName: 'Sphere', expectedVolume: 36 * Math.PI, propertyNames: 'Radius', properties: { Radius: 3 } },
    { objectName: 'Ellipsoid', expectedVolume: 133.9826640573845, expectedFaces: 1, propertyNames: 'Radius1,Radius2,Radius3,Angle1,Angle2,Angle3', properties: { Radius1: 2, Radius2: 4, Radius3: 0, Angle1: -90, Angle2: 90, Angle3: 360 } },
    { objectName: 'Cone', expectedVolume: 56 * Math.PI, propertyNames: 'Radius1,Radius2,Height,Angle', properties: { Radius1: 4, Radius2: 2, Height: 6, Angle: 360 } },
    { objectName: 'Torus', expectedVolume: 60 * Math.PI ** 2, propertyNames: 'Radius1,Radius2,Angle1,Angle2,Angle3', properties: { Radius1: 10, Radius2: 2, Angle1: -180, Angle2: 180, Angle3: 270 } },
    { objectName: 'Prism', expectedVolume: 60 * Math.sqrt(3), expectedFaces: 8, propertyNames: 'Polygon,Circumradius,Height,FirstAngle,SecondAngle', properties: { Polygon: 6, Circumradius: 2, Height: 10, FirstAngle: 10, SecondAngle: -5 } },
    { objectName: 'Wedge', expectedVolume: 2440 / 3, expectedFaces: 6, propertyNames: 'Xmin,Ymin,Zmin,Z2min,X2min,Xmax,Ymax,Zmax,Z2max,X2max', properties: { Xmin: 0, Ymin: 0, Zmin: 0, Z2min: 0, X2min: 0, Xmax: 10, Ymax: 10, Zmax: 10, Z2max: 8, X2max: 8 } },
    { objectName: 'Fuse', expectedVolume: 24, propertyNames: 'Base,Tool,Refine', properties: { Base: 'Box', Tool: 'Tool', Refine: false } },
    { objectName: 'Cut', expectedVolume: 23, propertyNames: 'Base,Tool,Refine', properties: { Base: 'Box', Tool: 'Tool', Refine: false } },
    { objectName: 'Common', expectedVolume: 1, propertyNames: 'Base,Tool,Refine', properties: { Base: 'Box', Tool: 'Tool', Refine: true } },
  ]
  const primitiveResults: Record<string, ProbeResult> = {}
  for (const oracleCase of primitiveCases) {
    const primitiveResult = runFreecadProbe(primitiveArchivePath, oracleCase.objectName, { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_PROPERTIES: oracleCase.propertyNames, ...(oracleCase.objectName === 'Common' ? { FREECAD_FCSTD_RESAVE_PATH: primitiveResavedPath } : {}) })
    primitiveResults[oracleCase.objectName] = primitiveResult
    if (primitiveResult.freecadVersion !== '1.1.1' || primitiveResult.shapeNull !== false || primitiveResult.shapeValid !== true || primitiveResult.shapeError !== null || primitiveResult.solidCount !== 1 || (oracleCase.expectedFaces !== undefined && primitiveResult.faceCount !== oracleCase.expectedFaces) || !near(primitiveResult.volume, oracleCase.expectedVolume, 1e-8)) fail(`unexpected native Part::${oracleCase.objectName} result: ${JSON.stringify(primitiveResult)}`)
    if (Object.entries(oracleCase.properties).some(([name, expected]) => primitiveResult.properties[name] !== expected) || Object.keys(primitiveResult.properties).length !== Object.keys(oracleCase.properties).length) fail(`native Part::${oracleCase.objectName} properties did not restore: ${JSON.stringify(primitiveResult.properties)}`)
  }
  const primitiveResaved = inspectFcstdArchive(new Uint8Array(await readFile(primitiveResavedPath)))
  const decodedProperty = (objectName: string, propertyName: string) => {
    const property = primitiveResaved.objects.find((object) => object.name === objectName)?.properties.find((candidate) => candidate.name === propertyName) ?? fail(`FreeCAD resave is missing ${objectName}.${propertyName}.`)
    const decodedPropertyValue = decodeFcstdPropertyValue(property)
    if (!decodedPropertyValue.decoded) fail(`FreeCAD resave could not decode ${objectName}.${propertyName}: ${decodedPropertyValue.error ?? 'unknown error'}`)
    return decodedPropertyValue.value
  }
  if (decodedProperty('Box', 'Length') !== 2 || decodedProperty('Box', 'Width') !== 3 || decodedProperty('Box', 'Height') !== 4 || decodedProperty('Box', 'WebMode') !== 'Manufacturing' || decodedProperty('Box', 'WebProgress') !== 35) fail('Web inspector did not recover the resaved Box parameters.')
  const prismRoundTripProperties = Object.fromEntries(['Polygon', 'Circumradius', 'Height', 'FirstAngle', 'SecondAngle'].map((name) => {
    const native = primitiveResaved.objects.find((object) => object.name === 'Prism')?.properties.find((property) => property.name === name)
    return [name, { typeId: native?.typeId, value: decodedProperty('Prism', name) }]
  }))
  if (prismRoundTripProperties.Polygon.value !== 6 || prismRoundTripProperties.Circumradius.value !== 2 || prismRoundTripProperties.Height.value !== 10 || prismRoundTripProperties.FirstAngle.value !== 10 || prismRoundTripProperties.SecondAngle.value !== -5) fail(`Web inspector did not recover the resaved Prism parameters: ${JSON.stringify(prismRoundTripProperties)}`)
  const wedgeValues = { Xmin: 0, Ymin: 0, Zmin: 0, Z2min: 0, X2min: 0, Xmax: 10, Ymax: 10, Zmax: 10, Z2max: 8, X2max: 8 }
  const wedgeRoundTripProperties = Object.fromEntries(Object.keys(wedgeValues).map((name) => {
    const native = primitiveResaved.objects.find((object) => object.name === 'Wedge')?.properties.find((property) => property.name === name)
    return [name, { typeId: native?.typeId, value: decodedProperty('Wedge', name) }]
  }))
  if (Object.entries(wedgeValues).some(([name, expected]) => wedgeRoundTripProperties[name].value !== expected)) fail(`Web inspector did not recover the resaved Wedge parameters: ${JSON.stringify(wedgeRoundTripProperties)}`)
  const ellipsoidValues = { Radius1: 2, Radius2: 4, Radius3: 0, Angle1: -90, Angle2: 90, Angle3: 360 }
  const ellipsoidRoundTripProperties = Object.fromEntries(Object.keys(ellipsoidValues).map((name) => {
    const native = primitiveResaved.objects.find((object) => object.name === 'Ellipsoid')?.properties.find((property) => property.name === name)
    return [name, { typeId: native?.typeId, value: decodedProperty('Ellipsoid', name) }]
  }))
  if (Object.entries(ellipsoidValues).some(([name, expected]) => ellipsoidRoundTripProperties[name].value !== expected)) fail(`Web inspector did not recover the resaved Ellipsoid parameters: ${JSON.stringify(ellipsoidRoundTripProperties)}`)
  for (const booleanName of ['Fuse', 'Cut', 'Common']) if (decodedProperty(booleanName, 'Base') !== 'Box' || decodedProperty(booleanName, 'Tool') !== 'Tool' || decodedProperty(booleanName, 'Refine') !== (booleanName === 'Common')) fail(`Web inspector did not recover the resaved ${booleanName} links and Refine value.`)
  for (const objectName of ['Box', 'Cylinder', 'Sphere', 'Ellipsoid', 'Cone', 'Torus', 'Prism', 'Wedge', 'Tool', 'Fuse', 'Cut', 'Common']) {
    const shape = primitiveResaved.objects.find((object) => object.name === objectName)?.properties.find((property) => property.name === 'Shape')?.shapeResource
    if (!shape || !primitiveResaved.shapeResources.some((resource) => resource.path === shape.path && resource.status === 'available')) fail(`FreeCAD resave did not produce an available ${objectName}.Shape resource.`)
  }

  const throughHoleDocument: DocumentSnapshot = {
    id: 'fcstd-native-part-cut-through-hole',
    label: 'FCStd native Part Cut through hole',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: ['Base', 'HoleTool', 'CutThroughHole'].map((id) => ({ id, label: id, type: 'feature', state: 'up-to-date' })),
    objects: [
      { id: 'Base', typeId: 'Part::Box', properties: [
        { name: 'Length', label: 'Length', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 20 },
        { name: 'Width', label: 'Width', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 20 },
        { name: 'Height', label: 'Height', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 10 },
      ] },
      { id: 'HoleTool', typeId: 'Part::Cylinder', properties: [
        { name: 'Radius', label: 'Radius', group: 'Cylinder', scope: 'data', type: 'App::PropertyLength', value: 3 },
        { name: 'Height', label: 'Height', group: 'Cylinder', scope: 'data', type: 'App::PropertyLength', value: 12 },
        { name: 'Angle', label: 'Angle', group: 'Cylinder', scope: 'data', type: 'App::PropertyAngle', value: 360 },
        { name: 'Placement', label: 'Placement', group: 'Base', scope: 'data', type: 'App::PropertyPlacement', value: { position: { x: 10, y: 10, z: -1 }, rotation: { axis: { x: 0, y: 0, z: 1 }, angle: 0 } } },
      ] },
      { id: 'CutThroughHole', typeId: 'Part::Cut', properties: [
        { name: 'Base', label: 'Base', group: 'Boolean', scope: 'data', type: 'App::PropertyLink', value: 'Base' },
        { name: 'Tool', label: 'Tool', group: 'Boolean', scope: 'data', type: 'App::PropertyLink', value: 'HoleTool' },
        { name: 'Refine', label: 'Refine shape', group: 'Boolean', scope: 'data', type: 'App::PropertyBool', value: false },
      ] },
    ],
    dependencies: [
      { sourceId: 'CutThroughHole', targetId: 'Base', relation: 'link', propertyName: 'Base' },
      { sourceId: 'CutThroughHole', targetId: 'HoleTool', relation: 'link', propertyName: 'Tool' },
    ],
    recompute: { generation: 0, status: 'idle', objectStates: { Base: 'up-to-date', HoleTool: 'up-to-date', CutThroughHole: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const throughHolePath = join(temporaryDirectory, 'native-part-cut-through-hole.fcstd')
  const throughHoleResavedPath = join(temporaryDirectory, 'native-part-cut-through-hole-resaved.fcstd')
  await writeFile(throughHolePath, serializeFcstdMetadataArchive(throughHoleDocument))
  const throughHoleResult = runFreecadProbe(throughHolePath, 'CutThroughHole', {
    FREECAD_FCSTD_RECOMPUTE: '1',
    FREECAD_FCSTD_PROPERTIES: 'Base,Tool,Refine',
    FREECAD_FCSTD_RESAVE_PATH: throughHoleResavedPath,
  })
  const throughHoleExpectedVolume = 4000 - 90 * Math.PI
  if (throughHoleResult.freecadVersion !== '1.1.1' || throughHoleResult.shapeNull !== false || throughHoleResult.shapeValid !== true || throughHoleResult.shapeError !== null || throughHoleResult.solidCount !== 1 || throughHoleResult.faceCount !== 7 || !near(throughHoleResult.volume, throughHoleExpectedVolume, 1e-8) || !throughHoleResult.boundingBox || JSON.stringify(throughHoleResult.boundingBox.min) !== '[0,0,0]' || JSON.stringify(throughHoleResult.boundingBox.max) !== '[20,20,10]') fail(`unexpected native Part::Cut through-hole result: ${JSON.stringify(throughHoleResult)}`)
  if (throughHoleResult.properties.Base !== 'Base' || throughHoleResult.properties.Tool !== 'HoleTool' || throughHoleResult.properties.Refine !== false || Object.keys(throughHoleResult.properties).length !== 3) fail(`native Part::Cut through-hole links did not restore: ${JSON.stringify(throughHoleResult.properties)}`)
  const throughHoleResaved = inspectFcstdArchive(new Uint8Array(await readFile(throughHoleResavedPath)))
  const throughHoleObject = throughHoleResaved.objects.find((object) => object.name === 'CutThroughHole') ?? fail('FreeCAD resave is missing CutThroughHole.')
  const throughHoleShape = throughHoleObject.properties.find((property) => property.name === 'Shape')?.shapeResource
  const throughHolePlacement = throughHoleResaved.objects.find((object) => object.name === 'HoleTool')?.properties.find((property) => property.name === 'Placement')
  if (!throughHoleShape || !throughHoleResaved.shapeResources.some((resource) => resource.path === throughHoleShape.path && resource.status === 'available')) fail('FreeCAD resave did not produce the CutThroughHole.Shape resource.')
  if (!throughHolePlacement || JSON.stringify(decodeFcstdPropertyValue(throughHolePlacement).value) !== '{"position":{"x":10,"y":10,"z":-1},"rotation":{"axis":{"x":0,"y":0,"z":1},"angle":0}}') fail('Web inspector did not recover the through-hole tool placement.')

  const sphereTrimPath = join(temporaryDirectory, 'native-sphere-trim.fcstd')
  const sphereTrimResavedPath = join(temporaryDirectory, 'native-sphere-trim-resaved.fcstd')
  const sphereTrimProperties = { Radius: 5, Angle1: -45, Angle2: 45, Angle3: 120 }
  const sphereTrimDocument: DocumentSnapshot = {
    id: 'fcstd-native-sphere-trim', label: 'FCStd native Sphere trim', version: 1, dirty: false, readOnly: false, units: 'mm',
    tree: [{ id: 'SphereTrim', label: 'SphereTrim', type: 'feature', state: 'up-to-date' }],
    objects: [{ id: 'SphereTrim', typeId: 'Part::Sphere', properties: [
      { name: 'Radius', label: 'Radius', group: 'Sphere', scope: 'data', type: 'App::PropertyLength', value: sphereTrimProperties.Radius },
      { name: 'Angle1', label: 'Lower angle', group: 'Sphere', scope: 'data', type: 'App::PropertyAngle', value: sphereTrimProperties.Angle1 },
      { name: 'Angle2', label: 'Upper angle', group: 'Sphere', scope: 'data', type: 'App::PropertyAngle', value: sphereTrimProperties.Angle2 },
      { name: 'Angle3', label: 'Azimuth angle', group: 'Sphere', scope: 'data', type: 'App::PropertyAngle', value: sphereTrimProperties.Angle3 },
    ] }],
    dependencies: [],
    recompute: { generation: 0, status: 'idle', objectStates: { SphereTrim: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  await writeFile(sphereTrimPath, serializeFcstdMetadataArchive(sphereTrimDocument))
  const sphereTrimResult = runFreecadProbe(sphereTrimPath, 'SphereTrim', {
    FREECAD_FCSTD_RECOMPUTE: '1',
    FREECAD_FCSTD_PROPERTIES: 'Radius,Angle1,Angle2,Angle3',
    FREECAD_FCSTD_RESAVE_PATH: sphereTrimResavedPath,
  })
  const sphereTrimZ = 5 * Math.sin(Math.PI / 4)
  const sphereTrimVolume = (Math.PI * (25 * (sphereTrimZ * 2) - (sphereTrimZ ** 3 - (-sphereTrimZ) ** 3) / 3)) / 3
  const sphereTrimBounds = { min: [-2.5, 0, -sphereTrimZ], max: [5, 5, sphereTrimZ] }
  if (sphereTrimResult.freecadVersion !== '1.1.1' || sphereTrimResult.shapeNull !== false || sphereTrimResult.shapeValid !== true || sphereTrimResult.solidCount !== 1 || !near(sphereTrimResult.volume, sphereTrimVolume, 1e-8) || !sphereTrimResult.boundingBox || sphereTrimResult.boundingBox.min.some((value, index) => !near(value, sphereTrimBounds.min[index], 1e-8)) || sphereTrimResult.boundingBox.max.some((value, index) => !near(value, sphereTrimBounds.max[index], 1e-8))) fail(`unexpected native Part::Sphere trim result: ${JSON.stringify(sphereTrimResult)}`)
  if (Object.entries(sphereTrimProperties).some(([name, expected]) => sphereTrimResult.properties[name] !== expected)) fail(`native Part::Sphere trim properties did not restore: ${JSON.stringify(sphereTrimResult.properties)}`)
  const sphereTrimResaved = inspectFcstdArchive(new Uint8Array(await readFile(sphereTrimResavedPath)))
  const sphereTrimObject = sphereTrimResaved.objects.find((object) => object.name === 'SphereTrim') ?? fail('FreeCAD resave is missing SphereTrim.')
  for (const [name, expected] of Object.entries(sphereTrimProperties)) {
    const property = sphereTrimObject.properties.find((candidate) => candidate.name === name) ?? fail(`FreeCAD resave is missing SphereTrim.${name}.`)
    const decodedValue = decodeFcstdPropertyValue(property)
    if (!decodedValue.decoded || decodedValue.value !== expected) fail(`Web inspector did not recover SphereTrim.${name}.`)
  }

  const featureProfile = createSketch('FeatureProfile', [
    { id: 'profile-bottom', type: 'line', start: { x: 2, y: 0 }, end: { x: 4, y: 0 } },
    { id: 'profile-right', type: 'line', start: { x: 4, y: 0 }, end: { x: 4, y: 3 } },
    { id: 'profile-top', type: 'line', start: { x: 4, y: 3 }, end: { x: 2, y: 3 } },
    { id: 'profile-left', type: 'line', start: { x: 2, y: 3 }, end: { x: 2, y: 0 } },
  ])
  const partFeatureDocument: DocumentSnapshot = {
    id: 'fcstd-native-part-features', label: 'FCStd native Part features', version: 1, dirty: false, readOnly: false, units: 'mm',
    tree: [
      { id: 'FeatureProfile', label: 'FeatureProfile', type: 'sketch', state: 'up-to-date' },
      { id: 'Extrusion', label: 'Extrusion', type: 'feature', state: 'up-to-date' },
      { id: 'Revolution', label: 'Revolution', type: 'feature', state: 'up-to-date' },
    ],
    objects: [
      { id: 'FeatureProfile', typeId: 'Sketcher::SketchObject', properties: [], sketch: featureProfile },
      { id: 'Extrusion', typeId: 'Part::Extrusion', properties: [
        { name: 'Base', label: 'Base', group: 'Extrude', scope: 'data', type: 'App::PropertyLink', value: 'FeatureProfile' },
        { name: 'Dir', label: 'Direction', group: 'Extrude', scope: 'data', type: 'App::PropertyVector', value: { x: 0, y: 0, z: 1 } },
        { name: 'DirMode', label: 'Direction mode', group: 'Extrude', scope: 'data', type: 'App::PropertyEnumeration', value: 'Custom', options: ['Custom', 'Edge', 'Normal'] },
        { name: 'LengthFwd', label: 'Forward length', group: 'Extrude', scope: 'data', type: 'App::PropertyDistance', value: 5 },
        { name: 'LengthRev', label: 'Reverse length', group: 'Extrude', scope: 'data', type: 'App::PropertyDistance', value: 0 },
        { name: 'Solid', label: 'Solid', group: 'Extrude', scope: 'data', type: 'App::PropertyBool', value: true },
        { name: 'Reversed', label: 'Reversed', group: 'Extrude', scope: 'data', type: 'App::PropertyBool', value: false },
        { name: 'Symmetric', label: 'Symmetric', group: 'Extrude', scope: 'data', type: 'App::PropertyBool', value: false },
        { name: 'TaperAngle', label: 'Taper angle', group: 'Extrude', scope: 'data', type: 'App::PropertyAngle', value: 0 },
        { name: 'TaperAngleRev', label: 'Reverse taper angle', group: 'Extrude', scope: 'data', type: 'App::PropertyAngle', value: 0 },
      ] },
      { id: 'Revolution', typeId: 'Part::Revolution', properties: [
        { name: 'Source', label: 'Source', group: 'Revolve', scope: 'data', type: 'App::PropertyLink', value: 'FeatureProfile' },
        { name: 'Base', label: 'Axis base', group: 'Revolve', scope: 'data', type: 'App::PropertyVector', value: { x: 0, y: 0, z: 0 } },
        { name: 'Axis', label: 'Axis', group: 'Revolve', scope: 'data', type: 'App::PropertyVector', value: { x: 0, y: 1, z: 0 } },
        { name: 'Angle', label: 'Angle', group: 'Revolve', scope: 'data', type: 'App::PropertyAngle', value: 360 },
        { name: 'Symmetric', label: 'Symmetric', group: 'Revolve', scope: 'data', type: 'App::PropertyBool', value: false },
        { name: 'Solid', label: 'Solid', group: 'Revolve', scope: 'data', type: 'App::PropertyBool', value: true },
      ] },
    ],
    dependencies: [
      { sourceId: 'Extrusion', targetId: 'FeatureProfile', relation: 'link', propertyName: 'Base' },
      { sourceId: 'Revolution', targetId: 'FeatureProfile', relation: 'link', propertyName: 'Source' },
    ],
    recompute: { generation: 0, status: 'idle', objectStates: { FeatureProfile: 'up-to-date', Extrusion: 'up-to-date', Revolution: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const partFeaturePath = join(temporaryDirectory, 'native-part-features.fcstd')
  const partFeatureResavedPath = join(temporaryDirectory, 'native-part-features-resaved.fcstd')
  await writeFile(partFeaturePath, serializeFcstdMetadataArchive(partFeatureDocument))
  const extrusionResult = runFreecadProbe(partFeaturePath, 'Extrusion', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_PROPERTIES: 'Base,DirMode,LengthFwd,LengthRev,Solid,Reversed,Symmetric,TaperAngle,TaperAngleRev' })
  if (extrusionResult.freecadVersion !== '1.1.1' || extrusionResult.shapeNull !== false || extrusionResult.shapeValid !== true || extrusionResult.shapeError !== null || extrusionResult.solidCount !== 1 || !near(extrusionResult.volume, 30, 1e-8)) fail(`unexpected native Part::Extrusion result: ${JSON.stringify(extrusionResult)}`)
  if (JSON.stringify(extrusionResult.properties) !== '{"Base":"FeatureProfile","DirMode":"Custom","LengthFwd":5,"LengthRev":0,"Reversed":false,"Solid":true,"Symmetric":false,"TaperAngle":0,"TaperAngleRev":0}') fail(`native Part::Extrusion properties did not restore: ${JSON.stringify(extrusionResult.properties)}`)
  const revolutionResult = runFreecadProbe(partFeaturePath, 'Revolution', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_PROPERTIES: 'Source,Angle,Symmetric,Solid' })
  if (revolutionResult.freecadVersion !== '1.1.1' || revolutionResult.shapeNull !== false || revolutionResult.shapeValid !== true || revolutionResult.shapeError !== null || revolutionResult.solidCount !== 1 || !near(revolutionResult.volume, 36 * Math.PI, 1e-8)) fail(`unexpected native Part::Revolution result: ${JSON.stringify(revolutionResult)}`)
  if (JSON.stringify(revolutionResult.properties) !== '{"Angle":360,"Solid":true,"Source":"FeatureProfile","Symmetric":false}') fail(`native Part::Revolution properties did not restore: ${JSON.stringify(revolutionResult.properties)}`)
  const revolutionResavedResult = runFreecadProbe(partFeaturePath, 'Revolution', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_PROPERTIES: 'Source,Angle,Symmetric,Solid', FREECAD_FCSTD_RESAVE_PATH: partFeatureResavedPath })
  if (revolutionResavedResult.shapeValid !== true) fail('FreeCAD did not resave the verified native Part::Revolution document.')
  const partFeatureResaved = inspectFcstdArchive(new Uint8Array(await readFile(partFeatureResavedPath)))
  const resavedFeatureValue = (objectName: string, propertyName: string) => {
    const property = partFeatureResaved.objects.find((object) => object.name === objectName)?.properties.find((candidate) => candidate.name === propertyName) ?? fail(`FreeCAD resave is missing ${objectName}.${propertyName}.`)
    const decodedValue = decodeFcstdPropertyValue(property)
    if (!decodedValue.decoded) fail(`Web inspector could not decode ${objectName}.${propertyName}.`)
    return decodedValue.value
  }
  if (partFeatureResaved.objects.find((object) => object.name === 'Extrusion')?.typeId !== 'Part::Extrusion' || resavedFeatureValue('Extrusion', 'Base') !== 'FeatureProfile' || resavedFeatureValue('Extrusion', 'LengthFwd') !== 5 || resavedFeatureValue('Extrusion', 'Solid') !== true) fail('Web inspector did not recover the resaved native Part::Extrusion schema.')
  if (partFeatureResaved.objects.find((object) => object.name === 'Revolution')?.typeId !== 'Part::Revolution' || resavedFeatureValue('Revolution', 'Source') !== 'FeatureProfile' || resavedFeatureValue('Revolution', 'Angle') !== 360 || resavedFeatureValue('Revolution', 'Solid') !== true) fail('Web inspector did not recover the resaved native Part::Revolution schema.')
  for (const objectName of ['Extrusion', 'Revolution']) {
    const shape = partFeatureResaved.objects.find((object) => object.name === objectName)?.properties.find((property) => property.name === 'Shape')?.shapeResource
    if (!shape || !partFeatureResaved.shapeResources.some((resource) => resource.path === shape.path && resource.status === 'available')) fail(`FreeCAD resave did not produce an available ${objectName}.Shape resource.`)
  }

  const sketch = createSketch('Sketch', [
    { id: 'bottom', type: 'line', start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
    { id: 'right', type: 'line', start: { x: 20, y: 0 }, end: { x: 20, y: 10 } },
    { id: 'top', type: 'line', start: { x: 20, y: 10 }, end: { x: 0, y: 10 } },
    { id: 'left', type: 'line', start: { x: 0, y: 10 }, end: { x: 0, y: 0 } },
    { id: 'construction-axis', type: 'line', start: { x: 10, y: 0 }, end: { x: 10, y: 10 }, construction: true },
    { id: 'reference-circle', type: 'circle', center: { x: 30, y: 5 }, radius: 2 },
    { id: 'datum-point', type: 'point', position: { x: 35, y: 5 } },
    { id: 'profile-arc', type: 'arc', center: { x: 40, y: 5 }, radius: 2, startAngle: 0, endAngle: Math.PI },
    { id: 'profile-ellipse', type: 'ellipse', center: { x: 47, y: 5 }, majorRadius: 3, minorRadius: 1.5, rotation: 0.25 },
    { id: 'profile-spline', type: 'bspline', degree: 2, controlPoints: [{ x: 52, y: 3 }, { x: 54, y: 7 }, { x: 56, y: 3 }], weights: [1, 1, 1], knots: [0, 0, 0, 1, 1, 1], periodic: false },
  ], [
    { id: 'bottom-horizontal', type: 'horizontal', geometryId: 'bottom' },
    { id: 'right-vertical', type: 'vertical', geometryId: 'right' },
    { id: 'top-horizontal', type: 'horizontal', geometryId: 'top' },
    { id: 'left-vertical', type: 'vertical', geometryId: 'left' },
    { id: 'join-bottom-right', type: 'coincident', first: { geometryId: 'bottom', point: 'end' }, second: { geometryId: 'right', point: 'start' } },
    { id: 'join-right-top', type: 'coincident', first: { geometryId: 'right', point: 'end' }, second: { geometryId: 'top', point: 'start' } },
    { id: 'join-top-left', type: 'coincident', first: { geometryId: 'top', point: 'end' }, second: { geometryId: 'left', point: 'start' } },
    { id: 'join-left-bottom', type: 'coincident', first: { geometryId: 'left', point: 'end' }, second: { geometryId: 'bottom', point: 'start' } },
    { id: 'axis-vertical', type: 'vertical', geometryId: 'construction-axis' },
    { id: 'circle-reference-radius', type: 'radius', geometryId: 'reference-circle', value: 2, driving: false },
    { id: 'external-point-on-edge', type: 'pointOnObject', point: { geometryId: 'datum-point', point: 'position' }, geometryId: 'external-box-edge-projection' },
  ])
  const externalSource = { schemaVersion: 1 as const, objectId: 'ExternalBox', kind: 'edge' as const, persistentId: 'Edge1', topologyVersion: 3, generation: 2, status: 'stable' as const, signature: 'native-box-edge-1' }
  const supportSource = { schemaVersion: 1 as const, objectId: 'ExternalBox', kind: 'face' as const, persistentId: 'Face1', topologyVersion: 3, generation: 2, status: 'stable' as const, signature: 'native-box-face-1' }
  sketch.externalGeometry = [{
    id: 'external-box-edge',
    source: externalSource,
    projection: { id: 'external-box-edge-projection', type: 'line', start: { x: 0, y: 0 }, end: { x: 20, y: 0 }, construction: true },
    construction: true,
  }]
  const sketchDocument: DocumentSnapshot = {
    id: 'fcstd-native-sketch',
    label: 'FCStd native Sketch',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: [{ id: 'ExternalBox', label: 'ExternalBox', type: 'feature', state: 'up-to-date' }, { id: 'Sketch', label: 'Sketch', type: 'sketch', state: 'up-to-date' }],
    objects: [
      { id: 'ExternalBox', typeId: 'Part::Box', properties: [
        { name: 'Length', label: 'Length', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 20 },
        { name: 'Width', label: 'Width', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 10 },
        { name: 'Height', label: 'Height', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 1 },
      ] },
      { id: 'Sketch', typeId: 'Sketcher::SketchObject', properties: [
        { name: 'Support', label: 'Support', group: 'Attachment', scope: 'data', type: 'App::PropertyLink', value: { objectId: 'ExternalBox', subElement: supportSource } },
        { name: 'MapMode', label: 'Map mode', group: 'Attachment', scope: 'data', type: 'App::PropertyEnumeration', value: 'FlatFace', options: ['Deactivated', 'ObjectXY', 'ObjectXZ', 'ObjectYZ', 'FlatFace', 'NormalToEdge'] },
        { name: 'AttachmentOffset', label: 'Attachment offset', group: 'Attachment', scope: 'data', type: 'App::PropertyPlacement', value: { position: { x: 0, y: 0, z: 0.25 }, rotation: { axis: { x: 0, y: 0, z: 1 }, angle: 0 } } },
      ], sketch },
    ],
    dependencies: [{ sourceId: 'Sketch', targetId: 'ExternalBox', relation: 'topo-ref', propertyName: 'ExternalGeometry:external-box-edge', reference: 'Edge1' }],
    recompute: { generation: 0, status: 'idle', objectStates: { ExternalBox: 'up-to-date', Sketch: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const sketchArchivePath = join(temporaryDirectory, 'native-sketch.fcstd')
  const sketchResavedPath = join(temporaryDirectory, 'native-sketch-resaved.fcstd')
  await writeFile(sketchArchivePath, serializeFcstdMetadataArchive(sketchDocument))
  const sketchResult = runFreecadProbe(sketchArchivePath, 'Sketch', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_PROPERTIES: 'WebGeometryIds,WebExternalIds,WebExternalProjectionIds', FREECAD_FCSTD_RESAVE_PATH: sketchResavedPath })
  const expectedConstraintNames = sketch.constraints.map((constraint) => constraint.id)
  if (sketchResult.freecadVersion !== '1.1.1' || sketchResult.geometryCount !== 10 || sketchResult.constraintCount !== 11 || sketchResult.externalGeometryCount !== 1 || sketchResult.externalGeoCount !== 3 || JSON.stringify(sketchResult.externalTypes) !== '[0]' || JSON.stringify(sketchResult.externalLinks) !== '[{"objectName":"ExternalBox","subElements":["Edge1"]}]' || sketchResult.mapMode !== 'FlatFace' || JSON.stringify(sketchResult.attachmentSupport) !== '[{"objectName":"ExternalBox","subElements":["Face1"]}]' || JSON.stringify(sketchResult.attachmentOffset?.position) !== '[0,0,0.25]' || !near(sketchResult.attachmentOffset?.angle ?? null, 0) || JSON.stringify(sketchResult.constructionGeometry) !== '[4]' || JSON.stringify(sketchResult.constraintNames) !== JSON.stringify(expectedConstraintNames) || JSON.stringify(sketchResult.properties.WebGeometryIds) !== JSON.stringify(sketch.geometry.map((geometry) => geometry.id)) || JSON.stringify(sketchResult.properties.WebExternalIds) !== '["external-box-edge"]' || JSON.stringify(sketchResult.properties.WebExternalProjectionIds) !== '["external-box-edge-projection"]') fail(`unexpected native Sketch result: ${JSON.stringify(sketchResult)}`)
  const resavedSketchInspection = inspectFcstdArchive(new Uint8Array(await readFile(sketchResavedPath)))
  const resavedSketchObject = resavedSketchInspection.objects.find((object) => object.name === 'Sketch') ?? fail('Web inspector did not find the resaved native Sketch object.')
  const resavedSketch = resavedSketchObject.sketch ?? fail('Web inspector did not reconstruct the resaved native Sketch.')
  if (JSON.stringify(resavedSketch.geometry.map((geometry) => geometry.id)) !== JSON.stringify(sketch.geometry.map((geometry) => geometry.id)) || JSON.stringify(resavedSketch.constraints.map((constraint) => constraint.id)) !== JSON.stringify(expectedConstraintNames) || resavedSketch.geometry[4]?.construction !== true || resavedSketch.externalGeometry[0]?.id !== 'external-box-edge' || resavedSketch.externalGeometry[0]?.projection.id !== 'external-box-edge-projection' || JSON.stringify(resavedSketch.externalGeometry[0]?.source) !== JSON.stringify(externalSource)) fail('Web inspector did not preserve native Sketch IDs, external TopoRef, or construction state.')
  const resavedMapMode = resavedSketchObject.properties.find((property) => property.name === 'MapMode') ?? fail('FreeCAD resave did not preserve Sketch.MapMode.')
  const resavedAttachmentSupport = resavedSketchObject.properties.find((property) => property.name === 'AttachmentSupport') ?? fail('FreeCAD resave did not preserve Sketch.AttachmentSupport.')
  if (decodeFcstdPropertyValue(resavedMapMode).value !== 'FlatFace' || JSON.stringify(decodeFcstdPropertyValue(resavedAttachmentSupport).value) !== '{"schemaVersion":1,"entries":[{"objectId":"ExternalBox","subElement":"Face1"}]}') fail('Web inspector did not decode the native Sketch attachment fields.')
  const proxySketch = resavedSketchInspection.proxyDocument.objects.find((object) => object.id === 'Sketch') ?? fail('Web proxy document did not preserve the resaved Sketch.')
  if (JSON.stringify(proxySketch.properties.find((property) => property.name === 'Support')?.value) !== JSON.stringify({ objectId: 'ExternalBox', subElement: supportSource }) || proxySketch.properties.find((property) => property.name === 'MapMode')?.value !== 'FlatFace') fail('Web proxy document did not recover the exact Support TopoRef or MapMode.')

  const faceSketch = createSketch('FaceSketch', [{ id: 'datum', type: 'point', position: { x: 0, y: 5 } }])
  const faceSource = { schemaVersion: 1 as const, objectId: 'FaceBox', kind: 'face' as const, persistentId: 'Face6', topologyVersion: 5, generation: 4, status: 'stable' as const, signature: 'native-box-face-6' }
  faceSketch.externalGeometry = [
    { id: 'face-left', source: faceSource, projection: { id: 'face-left-projection', type: 'line', start: { x: 0, y: 0 }, end: { x: 0, y: 10 }, construction: true }, construction: true },
    { id: 'face-top', source: faceSource, projection: { id: 'face-top-projection', type: 'line', start: { x: 0, y: 10 }, end: { x: 20, y: 10 }, construction: true }, construction: true },
    { id: 'face-right', source: faceSource, projection: { id: 'face-right-projection', type: 'line', start: { x: 20, y: 0 }, end: { x: 20, y: 10 }, construction: true }, construction: true },
    { id: 'face-bottom', source: faceSource, projection: { id: 'face-bottom-projection', type: 'line', start: { x: 0, y: 0 }, end: { x: 20, y: 0 }, construction: true }, construction: true },
  ]
  faceSketch.constraints = [{ id: 'datum-on-face-left', type: 'pointOnObject', point: { geometryId: 'datum', point: 'position' }, geometryId: 'face-left-projection' }]
  const faceDocument: DocumentSnapshot = {
    id: 'fcstd-native-face-projection',
    label: 'FCStd native Face projection',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: [{ id: 'FaceBox', label: 'FaceBox', type: 'feature', state: 'up-to-date' }, { id: 'FaceSketch', label: 'FaceSketch', type: 'sketch', state: 'up-to-date' }],
    objects: [
      { id: 'FaceBox', typeId: 'Part::Box', properties: [
        { name: 'Length', label: 'Length', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 20 },
        { name: 'Width', label: 'Width', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 10 },
        { name: 'Height', label: 'Height', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 1 },
      ] },
      { id: 'FaceSketch', typeId: 'Sketcher::SketchObject', properties: [], sketch: faceSketch },
    ],
    dependencies: [{ sourceId: 'FaceSketch', targetId: 'FaceBox', relation: 'topo-ref', propertyName: 'ExternalGeometry:face-left', reference: 'Face6' }],
    recompute: { generation: 0, status: 'idle', objectStates: { FaceBox: 'up-to-date', FaceSketch: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const faceArchivePath = join(temporaryDirectory, 'native-face-projection.fcstd')
  const faceResavedPath = join(temporaryDirectory, 'native-face-projection-resaved.fcstd')
  await writeFile(faceArchivePath, serializeFcstdMetadataArchive(faceDocument))
  const faceResult = runFreecadProbe(faceArchivePath, 'FaceSketch', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_RESAVE_PATH: faceResavedPath })
  if (faceResult.freecadVersion !== '1.1.1' || faceResult.geometryCount !== 1 || faceResult.constraintCount !== 1 || faceResult.externalGeometryCount !== 1 || faceResult.externalGeoCount !== 6 || JSON.stringify(faceResult.externalTypes) !== '[0]' || JSON.stringify(faceResult.externalLinks) !== '[{"objectName":"FaceBox","subElements":["Face6"]}]' || JSON.stringify(faceResult.constraintNames) !== '["datum-on-face-left"]' || JSON.stringify(faceResult.constraintTypes) !== '["PointOnObject"]') fail(`unexpected native Face projection result: ${JSON.stringify(faceResult)}`)
  const resavedFace = inspectFcstdArchive(new Uint8Array(await readFile(faceResavedPath))).objects.find((object) => object.name === 'FaceSketch')?.sketch ?? fail('Web inspector did not reconstruct the resaved native Face projection Sketch.')
  if (JSON.stringify(resavedFace.externalGeometry.map((external) => external.id)) !== JSON.stringify(faceSketch.externalGeometry.map((external) => external.id)) || JSON.stringify(resavedFace.externalGeometry.map((external) => external.projection.id)) !== JSON.stringify(faceSketch.externalGeometry.map((external) => external.projection.id)) || resavedFace.externalGeometry.some((external) => JSON.stringify(external.source) !== JSON.stringify(faceSource)) || JSON.stringify(resavedFace.constraints) !== JSON.stringify([{ ...faceSketch.constraints[0], driving: true }])) fail(`Web inspector did not preserve the native Face projection group: ${JSON.stringify(resavedFace)}`)

  const modeSketch = createSketch('ModeSketch')
  const intersectionSource = { schemaVersion: 1 as const, objectId: 'ModeBox', kind: 'face' as const, persistentId: 'Face1', topologyVersion: 6, generation: 4, status: 'stable' as const, signature: 'native-box-face-1-intersection' }
  const bothSource = { schemaVersion: 1 as const, objectId: 'ModeBox', kind: 'face' as const, persistentId: 'Face6', topologyVersion: 6, generation: 4, status: 'stable' as const, signature: 'native-box-face-6-both' }
  const syncSource = { schemaVersion: 1 as const, objectId: 'ModeBox', kind: 'edge' as const, persistentId: 'Edge1', topologyVersion: 6, generation: 4, status: 'stable' as const, signature: 'native-box-edge-1-sync' }
  modeSketch.externalGeometry = [
    { id: 'intersection-face', source: intersectionSource, projection: { id: 'intersection-face-line', type: 'line', start: { x: 0, y: 0 }, end: { x: 0, y: 10 }, construction: true }, construction: true, mode: 'intersection', defining: true },
    { id: 'both-left', source: bothSource, projection: { id: 'both-left-line', type: 'line', start: { x: 0, y: 0 }, end: { x: 0, y: 10 }, construction: true }, construction: true, mode: 'both', defining: true },
    { id: 'both-top', source: bothSource, projection: { id: 'both-top-line', type: 'line', start: { x: 0, y: 10 }, end: { x: 20, y: 10 }, construction: true }, construction: true, mode: 'both', defining: true },
    { id: 'both-right', source: bothSource, projection: { id: 'both-right-line', type: 'line', start: { x: 20, y: 0 }, end: { x: 20, y: 10 }, construction: true }, construction: true, mode: 'both', defining: true },
    { id: 'both-bottom', source: bothSource, projection: { id: 'both-bottom-line', type: 'line', start: { x: 0, y: 0 }, end: { x: 20, y: 0 }, construction: true }, construction: true, mode: 'both', defining: true },
    { id: 'frozen-edge', source: syncSource, projection: { id: 'frozen-edge-line', type: 'line', start: { x: 0, y: 0 }, end: { x: 20, y: 0 }, construction: true }, construction: true, frozen: true },
  ]
  const modeDocument: DocumentSnapshot = {
    id: 'fcstd-native-external-modes',
    label: 'FCStd native external modes',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: [{ id: 'ModeBox', label: 'ModeBox', type: 'feature', state: 'up-to-date' }, { id: 'ModeSketch', label: 'ModeSketch', type: 'sketch', state: 'up-to-date' }],
    objects: [
      { id: 'ModeBox', typeId: 'Part::Box', properties: [
        { name: 'Length', label: 'Length', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 20 },
        { name: 'Width', label: 'Width', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 10 },
        { name: 'Height', label: 'Height', group: 'Box', scope: 'data', type: 'App::PropertyLength', value: 1 },
      ] },
      { id: 'ModeSketch', typeId: 'Sketcher::SketchObject', properties: [], sketch: modeSketch },
    ],
    dependencies: [
      { sourceId: 'ModeSketch', targetId: 'ModeBox', relation: 'topo-ref', propertyName: 'ExternalGeometry:intersection-face', reference: 'Face1' },
      { sourceId: 'ModeSketch', targetId: 'ModeBox', relation: 'topo-ref', propertyName: 'ExternalGeometry:both-left', reference: 'Face6' },
      { sourceId: 'ModeSketch', targetId: 'ModeBox', relation: 'topo-ref', propertyName: 'ExternalGeometry:frozen-edge', reference: 'Edge1' },
    ],
    recompute: { generation: 0, status: 'idle', objectStates: { ModeBox: 'up-to-date', ModeSketch: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const modeArchivePath = join(temporaryDirectory, 'native-external-modes.fcstd')
  const modeResavedPath = join(temporaryDirectory, 'native-external-modes-resaved.fcstd')
  await writeFile(modeArchivePath, serializeFcstdMetadataArchive(modeDocument))
  const modeResult = runFreecadProbe(modeArchivePath, 'ModeSketch', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_RESAVE_PATH: modeResavedPath })
  if (modeResult.freecadVersion !== '1.1.1' || modeResult.geometryCount !== 0 || modeResult.constraintCount !== 0 || modeResult.externalGeometryCount !== 1 || modeResult.externalGeoCount !== 8 || JSON.stringify(modeResult.externalTypes) !== '[1,2,0]' || JSON.stringify(modeResult.externalLinks) !== '[{"objectName":"ModeBox","subElements":["Face1","Face6","Edge1"]}]' || JSON.stringify(modeResult.externalStates?.map((state) => state.flags)) !== '[1,1,1,1,1,2]') fail(`unexpected native external mode result: ${JSON.stringify(modeResult)}`)
  const resavedModes = inspectFcstdArchive(new Uint8Array(await readFile(modeResavedPath))).objects.find((object) => object.name === 'ModeSketch')?.sketch ?? fail('Web inspector did not reconstruct the resaved native external mode Sketch.')
  if (JSON.stringify(resavedModes.externalGeometry.map((external) => external.id)) !== JSON.stringify(modeSketch.externalGeometry.map((external) => external.id)) || JSON.stringify(resavedModes.externalGeometry.map((external) => external.projection.id)) !== JSON.stringify(modeSketch.externalGeometry.map((external) => external.projection.id)) || JSON.stringify(resavedModes.externalGeometry.map((external) => external.mode ?? 'projection')) !== '["intersection","both","both","both","both","projection"]' || resavedModes.externalGeometry.slice(0, 5).some((external) => external.defining !== true) || resavedModes.externalGeometry[5].frozen !== true) fail(`Web inspector did not preserve native external modes and flags: ${JSON.stringify(resavedModes)}`)

  const snellSketch = createSketch('SnellSketch', [
    { id: 'incident-ray', type: 'line', start: { x: 0, y: 0 }, end: { x: 5, y: 5 } },
    { id: 'refracted-ray', type: 'line', start: { x: 5, y: 5 }, end: { x: 10, y: 2 } },
    { id: 'boundary', type: 'line', start: { x: 0, y: 5 }, end: { x: 10, y: 5 }, construction: true },
  ], [{ id: 'refraction', type: 'snellsLaw', first: { geometryId: 'incident-ray', point: 'end' }, second: { geometryId: 'refracted-ray', point: 'start' }, boundaryGeometryId: 'boundary', value: 1.2 }])
  const snellDocument: DocumentSnapshot = {
    id: 'fcstd-native-snells-law',
    label: 'FCStd native SnellsLaw',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: [{ id: 'SnellSketch', label: 'SnellSketch', type: 'sketch', state: 'up-to-date' }],
    objects: [{ id: 'SnellSketch', typeId: 'Sketcher::SketchObject', properties: [], sketch: snellSketch }],
    dependencies: [],
    recompute: { generation: 0, status: 'idle', objectStates: { SnellSketch: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const snellArchivePath = join(temporaryDirectory, 'native-snells-law.fcstd')
  const snellResavedPath = join(temporaryDirectory, 'native-snells-law-resaved.fcstd')
  await writeFile(snellArchivePath, serializeFcstdMetadataArchive(snellDocument))
  const snellResult = runFreecadProbe(snellArchivePath, 'SnellSketch', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_RESAVE_PATH: snellResavedPath })
  if (snellResult.freecadVersion !== '1.1.1' || snellResult.geometryCount !== 3 || snellResult.constraintCount !== 1 || JSON.stringify(snellResult.constructionGeometry) !== '[2]' || JSON.stringify(snellResult.constraintNames) !== '["refraction"]' || JSON.stringify(snellResult.constraintTypes) !== '["SnellsLaw"]') fail(`unexpected native SnellsLaw result: ${JSON.stringify(snellResult)}`)
  const resavedSnell = inspectFcstdArchive(new Uint8Array(await readFile(snellResavedPath))).objects.find((object) => object.name === 'SnellSketch')?.sketch ?? fail('Web inspector did not reconstruct the resaved native SnellsLaw Sketch.')
  if (JSON.stringify(resavedSnell.geometry.map((geometry) => geometry.id)) !== JSON.stringify(snellSketch.geometry.map((geometry) => geometry.id)) || JSON.stringify(resavedSnell.constraints) !== JSON.stringify([{ ...snellSketch.constraints[0], driving: true }])) fail('Web inspector did not preserve the native SnellsLaw references or value.')

  const weightSketch = createSketch('WeightSketch', [{
    id: 'weighted-spline',
    type: 'bspline',
    degree: 2,
    controlPoints: [{ x: 0, y: 0 }, { x: 3, y: 4 }, { x: 6, y: 0 }],
    weights: [1, 0.75, 1],
    knots: [0, 0, 0, 1, 1, 1],
    periodic: false,
  }], [{ id: 'middle-weight', type: 'weight', geometryId: 'weighted-spline', controlPointIndex: 1, value: 0.75 }])
  const weightDocument: DocumentSnapshot = {
    id: 'fcstd-native-weight',
    label: 'FCStd native Weight',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: [{ id: 'WeightSketch', label: 'WeightSketch', type: 'sketch', state: 'up-to-date' }],
    objects: [{ id: 'WeightSketch', typeId: 'Sketcher::SketchObject', properties: [], sketch: weightSketch }],
    dependencies: [],
    recompute: { generation: 0, status: 'idle', objectStates: { WeightSketch: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const weightArchivePath = join(temporaryDirectory, 'native-weight.fcstd')
  const weightResavedPath = join(temporaryDirectory, 'native-weight-resaved.fcstd')
  await writeFile(weightArchivePath, serializeFcstdMetadataArchive(weightDocument))
  const weightResult = runFreecadProbe(weightArchivePath, 'WeightSketch', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_RESAVE_PATH: weightResavedPath })
  if (weightResult.freecadVersion !== '1.1.1' || weightResult.geometryCount !== 2 || weightResult.constraintCount !== 2 || JSON.stringify(weightResult.constructionGeometry) !== '[1]' || JSON.stringify(weightResult.constraintNames) !== '["__WebSyntheticAlignment0","middle-weight"]' || JSON.stringify(weightResult.constraintTypes) !== '["InternalAlignment","Weight"]') fail(`unexpected native B-spline Weight result: ${JSON.stringify(weightResult)}`)
  const resavedWeight = inspectFcstdArchive(new Uint8Array(await readFile(weightResavedPath))).objects.find((object) => object.name === 'WeightSketch')?.sketch ?? fail('Web inspector did not reconstruct the resaved native B-spline Weight Sketch.')
  if (JSON.stringify(resavedWeight.geometry.map((geometry) => geometry.id)) !== '["weighted-spline"]' || JSON.stringify(resavedWeight.constraints) !== JSON.stringify([{ ...weightSketch.constraints[0], driving: true }])) fail(`Web inspector did not preserve the native B-spline Weight constraint: ${JSON.stringify(resavedWeight)}`)

  const internalSketch = createSketch('InternalSketch', [
    { id: 'ellipse', type: 'ellipse', center: { x: 5, y: 4 }, majorRadius: 3, minorRadius: 2, rotation: 0.25 },
    { id: 'spline', type: 'bspline', degree: 2, controlPoints: [{ x: 0, y: 0 }, { x: 2, y: 3 }, { x: 4, y: 2 }, { x: 6, y: 0 }], weights: [1, 0.8, 1.2, 1], knots: [0, 0, 0, 0.5, 1, 1, 1], periodic: false },
  ], [
    { id: 'ellipse-major', type: 'internalAlignment', geometryId: 'ellipse', internalGeometryIndex: 0, alignmentType: 'ellipse-major' },
    { id: 'ellipse-minor', type: 'internalAlignment', geometryId: 'ellipse', internalGeometryIndex: 0, alignmentType: 'ellipse-minor' },
    { id: 'ellipse-focus-1', type: 'internalAlignment', geometryId: 'ellipse', internalGeometryIndex: 0, alignmentType: 'ellipse-focus' },
    { id: 'ellipse-focus-2', type: 'internalAlignment', geometryId: 'ellipse', internalGeometryIndex: 1, alignmentType: 'ellipse-focus' },
    { id: 'spline-middle-knot', type: 'internalAlignment', geometryId: 'spline', internalGeometryIndex: 1, alignmentType: 'bspline-knot' },
  ])
  const internalDocument: DocumentSnapshot = {
    id: 'fcstd-native-internal-alignment',
    label: 'FCStd native InternalAlignment',
    version: 1,
    dirty: false,
    readOnly: false,
    units: 'mm',
    tree: [{ id: 'InternalSketch', label: 'InternalSketch', type: 'sketch', state: 'up-to-date' }],
    objects: [{ id: 'InternalSketch', typeId: 'Sketcher::SketchObject', properties: [], sketch: internalSketch }],
    dependencies: [],
    recompute: { generation: 0, status: 'idle', objectStates: { InternalSketch: 'up-to-date' }, dirtyObjects: [], order: [], errors: [] },
  }
  const internalArchivePath = join(temporaryDirectory, 'native-internal-alignment.fcstd')
  const internalResavedPath = join(temporaryDirectory, 'native-internal-alignment-resaved.fcstd')
  await writeFile(internalArchivePath, serializeFcstdMetadataArchive(internalDocument))
  const internalResult = runFreecadProbe(internalArchivePath, 'InternalSketch', { FREECAD_FCSTD_RECOMPUTE: '1', FREECAD_FCSTD_RESAVE_PATH: internalResavedPath })
  if (internalResult.freecadVersion !== '1.1.1' || internalResult.geometryCount !== 7 || internalResult.constraintCount !== 5 || JSON.stringify(internalResult.constructionGeometry) !== '[2,3,4,5,6]' || JSON.stringify(internalResult.constraintNames) !== JSON.stringify(internalSketch.constraints.map((constraint) => constraint.id)) || JSON.stringify(internalResult.constraintTypes) !== '["InternalAlignment","InternalAlignment","InternalAlignment","InternalAlignment","InternalAlignment"]') fail(`unexpected native InternalAlignment result: ${JSON.stringify(internalResult)}`)
  const resavedInternal = inspectFcstdArchive(new Uint8Array(await readFile(internalResavedPath))).objects.find((object) => object.name === 'InternalSketch')?.sketch ?? fail('Web inspector did not reconstruct the resaved native InternalAlignment Sketch.')
  if (JSON.stringify(resavedInternal.geometry.map((geometry) => geometry.id)) !== '["ellipse","spline"]' || JSON.stringify(resavedInternal.constraints) !== JSON.stringify(internalSketch.constraints.map((constraint) => ({ ...constraint, driving: true })))) fail(`Web inspector did not preserve native ellipse/B-spline InternalAlignment: ${JSON.stringify(resavedInternal)}`)

  const summary = {
    status: 'freecad-fcstd-native-oracle-pass',
    freecadVersion: result.freecadVersion,
    shape: { solidCount: result.solidCount, faceCount: result.faceCount, volume: result.volume },
    primitives: Object.fromEntries(Object.entries(primitiveResults).map(([objectName, primitiveResult]) => [objectName, { properties: primitiveResult.properties, solidCount: primitiveResult.solidCount, faceCount: primitiveResult.faceCount, volume: primitiveResult.volume }])),
    primitiveRoundTrip: { objectCount: primitiveResaved.objects.length, shapeResourceCount: primitiveResaved.shapeResources.length, stringHasher: primitiveResaved.stringHasherResource?.status ?? 'absent' },
    sketch: { geometryCount: sketchResult.geometryCount, constraintCount: sketchResult.constraintCount, constructionGeometry: sketchResult.constructionGeometry, constraintTypes: sketchResult.constraintTypes, externalGeometryCount: sketchResult.externalGeometryCount, externalGeoCount: sketchResult.externalGeoCount, externalLinks: sketchResult.externalLinks, mapMode: sketchResult.mapMode, attachmentSupport: sketchResult.attachmentSupport, attachmentOffset: sketchResult.attachmentOffset },
    sketchRoundTrip: { geometryIds: resavedSketch.geometry.map((geometry) => geometry.id), constraintIds: resavedSketch.constraints.map((constraint) => constraint.id), externalIds: resavedSketch.externalGeometry.map((external) => external.id), externalSources: resavedSketch.externalGeometry.map((external) => external.source), support: proxySketch.properties.find((property) => property.name === 'Support')?.value, mapMode: proxySketch.properties.find((property) => property.name === 'MapMode')?.value },
    faceProjection: { geometryCount: faceResult.geometryCount, constraintCount: faceResult.constraintCount, externalGeometryCount: faceResult.externalGeometryCount, externalGeoCount: faceResult.externalGeoCount, externalLinks: faceResult.externalLinks, roundTripIds: resavedFace.externalGeometry.map((external) => external.id) },
    externalModes: { externalGeometryCount: modeResult.externalGeometryCount, externalGeoCount: modeResult.externalGeoCount, externalTypes: modeResult.externalTypes, externalStates: modeResult.externalStates, roundTripModes: resavedModes.externalGeometry.map((external) => external.mode ?? 'projection') },
    snellsLaw: { geometryCount: snellResult.geometryCount, constraintCount: snellResult.constraintCount, constraintTypes: snellResult.constraintTypes, roundTrip: resavedSnell.constraints },
    weight: { geometryCount: weightResult.geometryCount, constraintCount: weightResult.constraintCount, constructionGeometry: weightResult.constructionGeometry, constraintTypes: weightResult.constraintTypes, roundTrip: resavedWeight.constraints },
    internalAlignment: { geometryCount: internalResult.geometryCount, constraintCount: internalResult.constraintCount, constructionGeometry: internalResult.constructionGeometry, constraintTypes: internalResult.constraintTypes, roundTrip: resavedInternal.constraints },
    elementMap: { postfixCount: resavedMap.postfixCount, mapCount: resavedMap.mapCount },
    stringHasherBytes: resavedHasher.byteLength,
  }
  const webStages = ['web-model', 'web-write', 'freecad-open', 'freecad-recompute', 'freecad-resave', 'web-inspect']
  const sourceStages = ['freecad-source', 'web-inspect', 'web-write', 'freecad-open', 'freecad-resave', 'web-inspect-resaved']
  const proxyStages = ['freecad-source', 'web-inspect', 'web-byte-preserving-write', 'byte-compare', 'freecad-open', 'freecad-resave', 'web-inspect-resaved']
  const scenario = (id: string, direction: 'freecad-web-freecad' | 'web-freecad-web', domains: string[], evidence: Record<string, unknown>, stages?: string[]) => ({
    id,
    direction,
    stages: stages ?? (direction === 'freecad-web-freecad' ? sourceStages : webStages),
    domains,
    freecadVersion: '1.1.1',
    status: 'pass',
    differences: [],
    evidence,
  })
  const roundTripScenarios = [
    scenario('proxy-byte-preservation', 'freecad-web-freecad', ['objectTree', 'properties', 'gui', 'resources', 'proxy'], {
      sourceArchiveBytes: sourceBytes.byteLength,
      preservedArchiveBytes: proxyPreservedBytes.byteLength,
      sourceSha256,
      preservedSha256: proxyPreservedSha256,
      byteIdentical: true,
      proxyObjectCount: sourceInspection.compatibility.proxyObjects,
      blockedObjectCount: sourceInspection.compatibility.blockedObjects,
      unknownTypeIds: sourceInspection.compatibility.unknownTypeIds,
      resavedObjectCount: proxyResavedInspection.objects.length,
      resavedProxyObjectCount: proxyResavedInspection.compatibility.proxyObjects,
      resavedShapeValid: proxyResult.shapeValid,
    }, proxyStages),
    scenario('locked-partdesign-shape', 'freecad-web-freecad', ['shape', 'topology', 'resources'], {
      solidCount: result.solidCount,
      faceCount: result.faceCount,
      volume: result.volume,
      elementMapPostfixCount: resavedMap.postfixCount,
      elementMapCount: resavedMap.mapCount,
      stringHasherBytes: resavedHasher.byteLength,
    }),
    ...primitiveCases.map((oracleCase) => {
      const primitiveResult = primitiveResults[oracleCase.objectName]
      return scenario(`part-${oracleCase.objectName.toLowerCase()}`, 'web-freecad-web', ['objectTree', 'properties', 'shape', 'resources'], {
        typeId: `Part::${oracleCase.objectName}`,
        solidCount: primitiveResult.solidCount,
        faceCount: primitiveResult.faceCount,
        volume: primitiveResult.volume,
        boundingBox: primitiveResult.boundingBox,
        propertyCount: Object.keys(primitiveResult.properties).length,
        ...(oracleCase.objectName === 'Prism' || oracleCase.objectName === 'Wedge' || oracleCase.objectName === 'Ellipsoid' ? { properties: primitiveResult.properties } : {}),
        refine: primitiveResult.properties.Refine,
        resavedShapeAvailable: primitiveResaved.shapeResources.some((resource) => resource.path === `${oracleCase.objectName}.Shape.brp` && resource.status === 'available'),
      })
    }),
    scenario('part-cut-through-hole', 'web-freecad-web', ['objectTree', 'properties', 'shape', 'resources'], {
      typeId: throughHoleObject.typeId,
      solidCount: throughHoleResult.solidCount,
      faceCount: throughHoleResult.faceCount,
      volume: throughHoleResult.volume,
      boundingBox: throughHoleResult.boundingBox,
      propertyCount: Object.keys(throughHoleResult.properties).length,
      properties: throughHoleResult.properties,
      toolPlacement: decodeFcstdPropertyValue(throughHolePlacement).value,
      refine: throughHoleResult.properties.Refine,
      resavedShapeAvailable: true,
    }),
    scenario('part-sphere-trim', 'web-freecad-web', ['properties', 'shape', 'resources'], {
      solidCount: sphereTrimResult.solidCount,
      faceCount: sphereTrimResult.faceCount,
      volume: sphereTrimResult.volume,
      boundingBox: sphereTrimResult.boundingBox,
      properties: sphereTrimResult.properties,
      resavedShapeAvailable: sphereTrimResaved.shapeResources.some((resource) => resource.path === 'SphereTrim.Shape.brp' && resource.status === 'available'),
    }),
    scenario('part-extrusion', 'web-freecad-web', ['objectTree', 'properties', 'sketch', 'shape', 'resources'], {
      typeId: partFeatureResaved.objects.find((object) => object.name === 'Extrusion')?.typeId,
      solidCount: extrusionResult.solidCount,
      faceCount: extrusionResult.faceCount,
      volume: extrusionResult.volume,
      properties: extrusionResult.properties,
      resavedShapeAvailable: partFeatureResaved.shapeResources.some((resource) => resource.path === 'Extrusion.Shape.brp' && resource.status === 'available'),
    }),
    scenario('part-revolution', 'web-freecad-web', ['objectTree', 'properties', 'sketch', 'shape', 'resources'], {
      typeId: partFeatureResaved.objects.find((object) => object.name === 'Revolution')?.typeId,
      solidCount: revolutionResult.solidCount,
      faceCount: revolutionResult.faceCount,
      volume: revolutionResult.volume,
      properties: revolutionResult.properties,
      resavedShapeAvailable: partFeatureResaved.shapeResources.some((resource) => resource.path === 'Revolution.Shape.brp' && resource.status === 'available'),
    }),
    scenario('sketch-core-external-attachment', 'web-freecad-web', ['objectTree', 'properties', 'sketch', 'topology'], {
      geometryCount: sketchResult.geometryCount,
      constraintCount: sketchResult.constraintCount,
      externalTypes: sketchResult.externalTypes,
      mapMode: sketchResult.mapMode,
      roundTripGeometryIds: resavedSketch.geometry.length,
      roundTripConstraintIds: resavedSketch.constraints.length,
    }),
    scenario('sketch-face-projection', 'web-freecad-web', ['sketch', 'topology'], {
      externalTypes: faceResult.externalTypes,
      externalGeoCount: faceResult.externalGeoCount,
      roundTripIds: resavedFace.externalGeometry.length,
    }),
    scenario('sketch-external-modes', 'web-freecad-web', ['sketch', 'topology', 'properties'], {
      externalTypes: modeResult.externalTypes,
      externalGeoCount: modeResult.externalGeoCount,
      nativeFlags: modeResult.externalStates?.map((state) => state.flags),
      roundTripModes: resavedModes.externalGeometry.map((external) => external.mode ?? 'projection'),
    }),
    scenario('sketch-snells-law', 'web-freecad-web', ['sketch', 'properties'], {
      geometryCount: snellResult.geometryCount,
      constraintTypes: snellResult.constraintTypes,
      roundTripConstraints: resavedSnell.constraints.length,
    }),
    scenario('sketch-bspline-weight', 'web-freecad-web', ['sketch', 'properties'], {
      geometryCount: weightResult.geometryCount,
      constraintTypes: weightResult.constraintTypes,
      roundTripConstraints: resavedWeight.constraints.length,
    }),
    scenario('sketch-internal-alignment', 'web-freecad-web', ['sketch', 'properties'], {
      geometryCount: internalResult.geometryCount,
      constraintTypes: internalResult.constraintTypes,
      roundTripConstraints: resavedInternal.constraints.length,
    }),
  ]
  const roundTripReport = {
    schemaVersion: 1,
    baselineId: 'freecad-1.1.1',
    freecadCommit: '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d',
    bitbybitVersion: '1.1.1',
    unknownDifferencesFail: true,
    directions: ['freecad-web-freecad', 'web-freecad-web'],
    scenarioCount: roundTripScenarios.length,
    scenarios: roundTripScenarios,
    status: 'verified',
  }
  const reportPath = resolve(root, 'config/freecad-fcstd-roundtrip-verification.json')
  await writeFile(reportPath, `${JSON.stringify(roundTripReport, null, 2)}\n`)
  console.log(JSON.stringify({ ...summary, roundTripReport: { path: 'config/freecad-fcstd-roundtrip-verification.json', scenarioCount: roundTripScenarios.length, directions: roundTripReport.directions } }, null, 2))
} finally {
  if (process.env.FREECAD_FCSTD_KEEP_TEMP === '1') console.error(`FREECAD_FCSTD_TEMP=${temporaryDirectory}`)
  else await rm(temporaryDirectory, { recursive: true, force: true })
}
