import { createMockFacade } from './facade/mockFacade' import { createDraftDocument } from './facade/draft' import { createPlot } from './facade/plot' import { createProductionDocument } from './facade/productionDocument' import { createSpreadsheet } from './facade/spreadsheet' import { createTechDrawPage } from './facade/techDraw' import type { TopoRefValue } from './facade/types' type ProductionReport = { schemaVersion: 1 status: 'pass' | 'failed' browserId: 'chrome' crossOriginIsolated: boolean closure?: { complete: boolean; artifacts: number; missingKinds: number; missingDependencies: number; cycles: number; documentVersion: number; reopenedComplete: boolean; artifactVersions: number[] } workflow?: { created: { spreadsheetCells: number; draftObjects: number; techdrawViews: number; plotSeries: number } edited: { spreadsheetValue: number; draftStartX: number; techdrawDimension: number; plotValue: number } exports: { spreadsheetCsvBytes: number; draftJsonBytes: number; techdrawSvgBytes: number; techdrawPdfBytes: number; techdrawPdfValid: boolean; plotSvgBytes: number; plotCsvBytes: number } } persistence?: { mode: string; byteLength: number; hash: string; roundTrip: boolean; released: boolean } opfs?: { markerSuite: string; artifacts: number; markerRemoved: boolean } afterRelease?: { shapeCount: number; kernelReferenceCount: number } error?: string } const sha256 = async (bytes: Uint8Array) => [...new Uint8Array(await crypto.subtle.digest('SHA-256', Uint8Array.from(bytes).buffer))].map((value) => value.toString(16).padStart(2, '0')).join('') const ref = (id: string, version: number): TopoRefValue => ({ schemaVersion: 1, objectId: 'draft-line', kind: 'vertex', persistentId: id, topologyVersion: version, generation: version, status: 'stable', signature: id }) const run = async (): Promise => { const facade = createMockFacade() const report: ProductionReport = { schemaVersion: 1, status: 'failed', browserId: 'chrome', crossOriginIsolated: globalThis.crossOriginIsolated === true } try { if (!report.crossOriginIsolated || !navigator.storage?.getDirectory) throw new Error('Chrome production document evidence requires isolated OPFS.') await facade.project.list() const document = createProductionDocument('doc', 'Production workflow') const sheet = createSpreadsheet('sheet', 'Parameters') sheet.setCell('A1', 2, { alias: 'Input' }) sheet.setCell('A2', '=Input * 2', { alias: 'Output' }) const initialSheet = sheet.evaluate() document.add({ id: 'sheet', kind: 'Spreadsheet', dependencies: [], payload: { snapshot: sheet.snapshot(), evaluation: initialSheet } }) const draft = createDraftDocument('draft', 'Profile') draft.createLine('profile', { x: 0, y: 0 }, { x: 4, y: 0 }) document.add({ id: 'draft', kind: 'Draft', dependencies: [], payload: { snapshot: draft.snapshot() } }) const page = createTechDrawPage('page', 'Profile drawing') page.addSource({ id: 'draft-line', revision: 1, points: [{ id: 'start', ref: ref('Vertex1', 1), point: { x: 0, y: 0, z: 0 } }, { id: 'end', ref: ref('Vertex2', 1), point: { x: 4, y: 0, z: 0 } }], edges: [{ id: 'edge', start: 'start', end: 'end' }] }) page.addView({ id: 'front', sourceId: 'draft-line', direction: { x: 0, y: 0, z: 1 }, position: { x: 80, y: 80 }, scale: 8 }) page.addDimension({ id: 'length', sourceId: 'draft-line', first: ref('Vertex1', 1), second: ref('Vertex2', 1), label: 'Profile length' }) page.addAnnotation({ id: 'note', text: 'Production profile', position: { x: 20, y: 20 } }) page.addGeometricTolerance({ id: 'straightness', sourceId: 'draft-line', reference: ref('Vertex1', 1), characteristic: 'flatness', value: 0.05 }) document.add({ id: 'page', kind: 'TechDraw', dependencies: ['draft'], payload: { snapshot: page.snapshot() } }) const plot = createPlot('plot', 'Parameter history') plot.setAxes({ x: { label: 'Revision', scale: 'linear', minimum: 2, maximum: 3 }, y: { label: 'Output', scale: 'linear', minimum: 0, maximum: 8 } }) plot.setSeries({ id: 'output', label: 'Output', points: [{ x: 2, y: 4 }, { x: 3, y: 4 }], style: { color: '#007f86', lineWidth: 2 } }) plot.bindSeries('output', { sourceId: 'sheet', xRange: 'A1:A2', yRange: 'A1:A2' }) document.add({ id: 'plot', kind: 'Plot', dependencies: ['sheet'], payload: { snapshot: plot.snapshot() } }) sheet.setCell('A1', 3, { alias: 'Input' }) const editedSheet = sheet.evaluate() const spreadsheetValue = editedSheet.cells.A2.value?.value ?? Number.NaN const movedLine = draft.move('profile', { x: 1, y: 2 }) page.updateSource({ id: 'draft-line', revision: 2, points: [{ id: 'start', ref: ref('Vertex1', 2), point: { x: 1, y: 2, z: 0 } }, { id: 'end', ref: ref('Vertex2', 2), point: { x: spreadsheetValue, y: 2, z: 0 } }], edges: [{ id: 'edge', start: 'start', end: 'end' }] }) plot.updateBoundSeries('output', [{ x: 2, y: 4 }, { x: 3, y: spreadsheetValue }]) const spreadsheetCsv = sheet.exportCsv() const draftJson = JSON.stringify(draft.snapshot()) const techdrawSvg = page.exportSvg() const techdrawPdf = page.exportPdf() const plotSvg = plot.exportSvg() const plotCsv = plot.exportCsv() const techdrawPdfText = new TextDecoder().decode(techdrawPdf) document.update('sheet', { payload: { snapshot: sheet.snapshot(), evaluation: editedSheet, exportBytes: new TextEncoder().encode(spreadsheetCsv).byteLength } }) document.update('draft', { payload: { snapshot: draft.snapshot(), exportBytes: new TextEncoder().encode(draftJson).byteLength } }) document.update('page', { payload: { snapshot: page.snapshot(), svgBytes: new TextEncoder().encode(techdrawSvg).byteLength, pdfBytes: techdrawPdf.byteLength } }) document.update('plot', { payload: { snapshot: plot.snapshot(), svgBytes: new TextEncoder().encode(plotSvg).byteLength, csvBytes: new TextEncoder().encode(plotCsv).byteLength } }) const closure = document.closure() const serialized = document.save() const reopened = createProductionDocument('reopened', 'Reopened production workflow') const reopenedSnapshot = reopened.load(serialized) const reopenedClosure = reopened.closure() const payload = new TextEncoder().encode(serialized) const stored = await facade.project.resource.put(payload, 'application/vnd.bitbybit.production-document+json') const loaded = await facade.project.resource.get(stored.hash) const roundTrip = loaded !== null && await sha256(loaded) === await sha256(payload) await facade.project.resource.release(stored.hash) const released = await facade.project.resource.get(stored.hash) === null const directory = await navigator.storage.getDirectory() const markerName = 'production-document-chrome-marker.json' const marker = await directory.getFileHandle(markerName, { create: true }) const writable = await marker.createWritable() await writable.write(JSON.stringify({ suite: 'DOC-CLOSURE', artifacts: closure.artifacts })) await writable.close() const markerPayload = JSON.parse(await (await marker.getFile()).text()) as { suite: string; artifacts: number } await directory.removeEntry(markerName) let markerRemoved = false try { await directory.getFileHandle(markerName) } catch (error) { markerRemoved = error instanceof DOMException && error.name === 'NotFoundError' } const pageSnapshot = page.snapshot() const plotSnapshot = plot.snapshot() report.closure = { complete: closure.complete, artifacts: closure.artifacts, missingKinds: closure.missingKinds.length, missingDependencies: closure.missingDependencies.length, cycles: closure.cycles.length, documentVersion: document.snapshot().version, reopenedComplete: reopenedClosure.complete && reopenedSnapshot.artifacts.length === 4, artifactVersions: document.snapshot().artifacts.map((artifact) => artifact.version).sort() } report.workflow = { created: { spreadsheetCells: 2, draftObjects: 1, techdrawViews: 1, plotSeries: 1 }, edited: { spreadsheetValue, draftStartX: movedLine.kind === 'line' ? movedLine.start.x : Number.NaN, techdrawDimension: pageSnapshot.dimensions[0]?.value ?? Number.NaN, plotValue: plotSnapshot.series[0]?.points.at(-1)?.y ?? Number.NaN }, exports: { spreadsheetCsvBytes: new TextEncoder().encode(spreadsheetCsv).byteLength, draftJsonBytes: new TextEncoder().encode(draftJson).byteLength, techdrawSvgBytes: new TextEncoder().encode(techdrawSvg).byteLength, techdrawPdfBytes: techdrawPdf.byteLength, techdrawPdfValid: techdrawPdfText.startsWith('%PDF-1.4') && techdrawPdfText.endsWith('%%EOF\n'), plotSvgBytes: new TextEncoder().encode(plotSvg).byteLength, plotCsvBytes: new TextEncoder().encode(plotCsv).byteLength }, } report.persistence = { mode: facade.project.capabilities().mode, byteLength: stored.byteLength, hash: stored.hash, roundTrip, released } report.opfs = { markerSuite: markerPayload.suite, artifacts: markerPayload.artifacts, markerRemoved } report.status = report.closure.complete && report.closure.artifacts === 4 && report.closure.missingKinds === 0 && report.closure.missingDependencies === 0 && report.closure.cycles === 0 && report.closure.documentVersion === 8 && report.closure.reopenedComplete && report.closure.artifactVersions.every((version) => version === 2) && report.workflow.created.spreadsheetCells === 2 && report.workflow.created.draftObjects === 1 && report.workflow.created.techdrawViews === 1 && report.workflow.created.plotSeries === 1 && report.workflow.edited.spreadsheetValue === 6 && report.workflow.edited.draftStartX === 1 && report.workflow.edited.techdrawDimension === 5 && report.workflow.edited.plotValue === 6 && Object.entries(report.workflow.exports).every(([name, value]) => name === 'techdrawPdfValid' ? value === true : typeof value === 'number' && value > 0) && report.persistence.mode === 'sqlite-opfs' && report.persistence.roundTrip && report.persistence.released && report.opfs.markerSuite === 'DOC-CLOSURE' && report.opfs.artifacts === 4 && report.opfs.markerRemoved ? 'pass' : 'failed' } catch (error) { report.error = error instanceof Error ? error.stack || error.message : String(error) } finally { facade.geometry.dispose() await new Promise((resolve) => setTimeout(resolve, 0)) const capabilities = facade.geometry.capabilities() report.afterRelease = { shapeCount: capabilities.shapeCount, kernelReferenceCount: capabilities.kernelReferenceCount } if (capabilities.shapeCount !== 0 || capabilities.kernelReferenceCount !== 0) { report.status = 'failed'; report.error = `${report.error ? `${report.error} ` : ''}Shape ownership gate failed.` } } return report } run().then((report) => { ;(window as Window & { __bitbybitProductionReport?: ProductionReport }).__bitbybitProductionReport = report document.documentElement.dataset.status = report.status document.querySelector('#result')!.textContent = JSON.stringify(report, null, 2) }).catch((error) => { document.documentElement.dataset.status = 'failed' document.querySelector('#result')!.textContent = error instanceof Error ? error.stack || error.message : String(error) }) export {}