geospec 0.0.0 → 0.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +244 -0
  3. package/agent/doctrine.md +47 -0
  4. package/agent/geospec-authoring/SKILL.md +496 -0
  5. package/agent/geospec-authoring/api-classes.md +13 -0
  6. package/agent/geospec-authoring/api-constants.md +6 -0
  7. package/agent/geospec-authoring/api-functions.md +49 -0
  8. package/agent/geospec-authoring/api-index.md +362 -0
  9. package/agent/geospec-authoring/api-types.md +1700 -0
  10. package/agent/geospec-authoring/public-api-classes.md +22 -0
  11. package/agent/geospec-authoring/public-api-constants.md +19 -0
  12. package/agent/geospec-authoring/public-api-functions.md +196 -0
  13. package/agent/geospec-authoring/public-api-index.md +856 -0
  14. package/agent/geospec-authoring/public-api-types-2.md +1513 -0
  15. package/agent/geospec-authoring/public-api-types.md +2048 -0
  16. package/agent/resources.d.ts +19 -0
  17. package/agent/resources.js +26 -0
  18. package/agent/skills.d.cts +13 -0
  19. package/agent/skills.json +27 -0
  20. package/dist/assertion-client/client.d.mts +124 -0
  21. package/dist/assertion-client/client.mjs +2 -0
  22. package/dist/assertion-client/index.d.mts +5 -0
  23. package/dist/assertion-client/index.mjs +1 -0
  24. package/dist/config/index.d.mts +3 -0
  25. package/dist/config/index.mjs +1 -0
  26. package/dist/config/node/index.d.mts +3 -0
  27. package/dist/config/node/index.mjs +1 -0
  28. package/dist/config/node/load.d.mts +19 -0
  29. package/dist/config/node/load.mjs +1 -0
  30. package/dist/config/tau-project-artifact.d.mts +54 -0
  31. package/dist/config/tau-project-artifact.mjs +3 -0
  32. package/dist/config/types.d.mts +57 -0
  33. package/dist/config/validate.mjs +1 -0
  34. package/dist/create-geospec.d.mts +49 -0
  35. package/dist/create-geospec.mjs +1 -0
  36. package/dist/engine/client.d.mts +93 -0
  37. package/dist/engine/client.mjs +1 -0
  38. package/dist/engine/index.d.mts +3 -0
  39. package/dist/engine/index.mjs +1 -0
  40. package/dist/engine/matchers.d.mts +70 -0
  41. package/dist/engine/matchers.mjs +1 -0
  42. package/dist/engine/pmi.types.d.mts +78 -0
  43. package/dist/engine/protocol.d.mts +20 -0
  44. package/dist/engine/protocol.mjs +1 -0
  45. package/dist/geometry-unit.d.mts +12 -0
  46. package/dist/index.d.mts +6 -0
  47. package/dist/index.mjs +1 -0
  48. package/dist/mesh/index.d.mts +4 -0
  49. package/dist/mesh/index.mjs +1 -0
  50. package/dist/mesh/types.d.mts +575 -0
  51. package/dist/model/errors.d.mts +20 -0
  52. package/dist/model/errors.mjs +2 -0
  53. package/dist/model/export-intent.d.mts +63 -0
  54. package/dist/model/export-intent.mjs +1 -0
  55. package/dist/model/index.d.mts +6 -0
  56. package/dist/model/index.mjs +1 -0
  57. package/dist/model/load-model.d.mts +25 -0
  58. package/dist/model/load-model.mjs +1 -0
  59. package/dist/model/native-model-loader.d.mts +119 -0
  60. package/dist/model/native-model-loader.mjs +1 -0
  61. package/dist/model/subject-assertions.mjs +1 -0
  62. package/dist/model/subject.d.mts +11 -0
  63. package/dist/model/subject.mjs +1 -0
  64. package/dist/model/types.d.mts +207 -0
  65. package/dist/runner/collector.d.mts +62 -0
  66. package/dist/runner/collector.mjs +2 -0
  67. package/dist/runner/discovery.d.mts +93 -0
  68. package/dist/runner/discovery.mjs +1 -0
  69. package/dist/runner/filter.d.mts +50 -0
  70. package/dist/runner/filter.mjs +1 -0
  71. package/dist/runner/index.d.mts +6 -0
  72. package/dist/runner/index.mjs +1 -0
  73. package/dist/runner/native/index.d.mts +4 -0
  74. package/dist/runner/native/index.mjs +1 -0
  75. package/dist/runner/native/native-pool-grants.d.mts +21 -0
  76. package/dist/runner/native/native-pool-grants.mjs +1 -0
  77. package/dist/runner/native/native-serial-runner.d.mts +29 -0
  78. package/dist/runner/native/native-serial-runner.mjs +1 -0
  79. package/dist/runner/pool/pool-messages.d.mts +94 -0
  80. package/dist/runner/run-geospec-module.d.mts +13 -0
  81. package/dist/runner/run-geospec-module.mjs +47 -0
  82. package/dist/runner/types.d.mts +743 -0
  83. package/dist/runner/worker/index.d.mts +4 -0
  84. package/dist/runner/worker/index.mjs +1 -0
  85. package/dist/runner/worker/no-matching-tests-issue.d.mts +12 -0
  86. package/dist/runner/worker/no-matching-tests-issue.mjs +1 -0
  87. package/dist/runner/worker/runner-types.d.mts +146 -0
  88. package/dist/runner/worker/serial-runner.mjs +1 -0
  89. package/dist/selector/types.d.mts +271 -0
  90. package/dist/step/types.d.mts +134 -0
  91. package/dist/vitest/adapter.d.mts +56 -0
  92. package/dist/vitest/adapter.mjs +3 -0
  93. package/dist/vitest/index.d.mts +4 -0
  94. package/dist/vitest/index.mjs +1 -0
  95. package/package.json +114 -5
@@ -0,0 +1,2048 @@
1
+ # geospec — Types
2
+
3
+ 91 top-level symbols. Signatures are verbatim typescript.
4
+
5
+ // A model admitted by one live GeoSpec host scope
6
+ GeoSpecSubject: {
7
+ readonly [subjectBrand]: true;
8
+ }
9
+
10
+ readonly [subjectBrand]: true
11
+
12
+ // Geometry units accepted at GeoSpec evidence-loading boundaries
13
+ // Remarks: Loaded subjects normalize coordinates into canonical millimetres; this type describes source and provenance units, not a project-wide configuration.
14
+ GeoSpecUnit: 'mm' | 'cm' | 'm' | 'in' | 'ft' | (string & {})
15
+
16
+ // Geometry assertion collected from a GeoSpec test module
17
+ GeoSpecAssertion: {
18
+ /** Assertion kind. */
19
+ kind: 'boundingBox' | 'connectedComponents' | 'watertight' | 'componentInterference' | 'assemblyOccurrences' | 'spatialRelationships' | 'meshIntegrity' | 'noDiagnostics' | 'surfaceArea' | 'volume' | 'mass' | 'centerOfMass' | 'validBrep' | 'topologyCounts' | 'stepUnits' | 'productStructure' | 'planarFace' | 'cylindricalFace' | 'circularHole' | 'circularHolePattern' | 'chamferFeature' | 'filletFeature' | 'minimumWallThickness' | 'voidContinuity' | 'toSatisfyRationalPlate' | 'toSatisfyParallelPlaneDistance';
20
+ /** User-authored value passed to expectGeo(). */
21
+ subject: unknown;
22
+ /** Expected geometry condition. */
23
+ expected: unknown;
24
+ /** True when the assertion evaluated successfully. */
25
+ passed?: boolean;
26
+ /** Structured diagnostics from matcher evaluation. */
27
+ diagnostics?: GeometryDiagnostic[];
28
+ /** Exact compiled assertion report, including core-owned bytes and polarity. */
29
+ report?: GeoSpecCanonicalClaimReport;
30
+ /** The host load which admitted this assertion's subject; independent of equal geometry hashes. */
31
+ loadId?: string;
32
+ /** Wall-clock cost of matcher evaluation in milliseconds (R1: budgeted matchers only). */
33
+ durationMs?: number;
34
+ }
35
+
36
+ // Assertion kind
37
+ kind: 'boundingBox' | 'connectedComponents' | 'watertight' | 'componentInterference' | 'assemblyOccurrences' | 'spatialRelationships' | 'meshIntegrity' | 'noDiagnostics' | 'surfaceArea' | 'volume' | 'mass' | 'centerOfMass' | 'validBrep' | 'topologyCounts' | 'stepUnits' | 'productStructure' | 'planarFace' | 'cylindricalFace' | 'circularHole' | 'circularHolePattern' | 'chamferFeature' | 'filletFeature' | 'minimumWallThickness' | 'voidContinuity' | 'toSatisfyRationalPlate' | 'toSatisfyParallelPlaneDistance'
38
+
39
+ // User-authored value passed to expectGeo()
40
+ subject: unknown
41
+
42
+ // Expected geometry condition
43
+ expected: unknown
44
+
45
+ // True when the assertion evaluated successfully
46
+ passed?: boolean
47
+
48
+ // Structured diagnostics from matcher evaluation
49
+ diagnostics?: GeometryDiagnostic[]
50
+
51
+ // Exact compiled assertion report, including core-owned bytes and polarity
52
+ report?: GeoSpecCanonicalClaimReport
53
+
54
+ // The host load which admitted this assertion's subject
55
+ loadId?: string
56
+
57
+ // Wall-clock cost of matcher evaluation in milliseconds (R1
58
+ durationMs?: number
59
+
60
+ // Assembly occurrence rule accepted by `expectGeo(...).toHaveAssemblyOccurrences(...)`
61
+ GeoSpecAssemblyOccurrenceExpectation: {
62
+ name: GeoSpecComponentSelector;
63
+ count?: GeoSpecNumericExpectation;
64
+ bounds?: {
65
+ within?: GeoSpecComponentSelector;
66
+ min?: Vec3 | GeoSpecAxisExpectation;
67
+ max?: Vec3 | GeoSpecAxisExpectation;
68
+ center?: GeoSpecPointExpectation;
69
+ tolerance?: number;
70
+ };
71
+ }
72
+
73
+ name: GeoSpecComponentSelector
74
+
75
+ count?: GeoSpecNumericExpectation
76
+
77
+ bounds?: {
78
+ within?: GeoSpecComponentSelector;
79
+ min?: Vec3 | GeoSpecAxisExpectation;
80
+ max?: Vec3 | GeoSpecAxisExpectation;
81
+ center?: GeoSpecPointExpectation;
82
+ tolerance?: number;
83
+ }
84
+
85
+ // Assembly occurrence expectation accepted by `expectGeo(...).toHaveAssemblyOccurrences(...)`
86
+ GeoSpecAssemblyOccurrencesExpectation: {
87
+ occurrences: GeoSpecAssemblyOccurrenceExpectation[];
88
+ uniqueNames?: boolean;
89
+ }
90
+
91
+ occurrences: GeoSpecAssemblyOccurrenceExpectation[]
92
+
93
+ uniqueNames?: boolean
94
+
95
+ // Axis-keyed numeric expectation used by high-level geometry matchers
96
+ GeoSpecAxisExpectation: {
97
+ x?: number;
98
+ y?: number;
99
+ z?: number;
100
+ }
101
+
102
+ x?: number
103
+
104
+ y?: number
105
+
106
+ z?: number
107
+
108
+ // Bounding-box expectation accepted by `expectGeo(...).toHaveBoundingBox(...)`
109
+ GeoSpecBoundingBoxExpectation: {
110
+ min?: Vec3 | Partial<Record<keyof GeoSpecAxisExpectation, GeoSpecNumericExpectation>>;
111
+ max?: Vec3 | Partial<Record<keyof GeoSpecAxisExpectation, GeoSpecNumericExpectation>>;
112
+ size?: Vec3 | Partial<Record<keyof GeoSpecAxisExpectation, GeoSpecNumericExpectation>>;
113
+ center?: Vec3 | Partial<Record<keyof GeoSpecAxisExpectation, GeoSpecNumericExpectation>>;
114
+ tolerance?: number;
115
+ }
116
+
117
+ min?: Vec3 | Partial<Record<keyof GeoSpecAxisExpectation, GeoSpecNumericExpectation>>
118
+
119
+ max?: Vec3 | Partial<Record<keyof GeoSpecAxisExpectation, GeoSpecNumericExpectation>>
120
+
121
+ size?: Vec3 | Partial<Record<keyof GeoSpecAxisExpectation, GeoSpecNumericExpectation>>
122
+
123
+ center?: Vec3 | Partial<Record<keyof GeoSpecAxisExpectation, GeoSpecNumericExpectation>>
124
+
125
+ tolerance?: number
126
+
127
+ // Center-of-mass expectation accepted by `expectGeo(...).toHaveCenterOfMass(...)`
128
+ GeoSpecCenterOfMassExpectation: {
129
+ point: GeoSpecPointExpectation;
130
+ tolerance?: number;
131
+ }
132
+
133
+ point: GeoSpecPointExpectation
134
+
135
+ tolerance?: number
136
+
137
+ // Chamfer-feature expectation accepted by `expectGeo(...).toHaveChamferFeature(...)`
138
+ GeoSpecChamferFeatureExpectation: {
139
+ distance: number;
140
+ selection?: string;
141
+ tolerance?: number;
142
+ }
143
+
144
+ distance: number
145
+
146
+ selection?: string
147
+
148
+ tolerance?: number
149
+
150
+ // Circular-hole expectation accepted by `expectGeo(...).toHaveCircularHole(...)`
151
+ GeoSpecCircularHoleExpectation: {
152
+ diameter: number;
153
+ through?: boolean;
154
+ axis?: 'x' | 'y' | 'z';
155
+ center?: GeoSpecPointExpectation;
156
+ tolerance?: number;
157
+ }
158
+
159
+ diameter: number
160
+
161
+ through?: boolean
162
+
163
+ axis?: 'x' | 'y' | 'z'
164
+
165
+ center?: GeoSpecPointExpectation
166
+
167
+ tolerance?: number
168
+
169
+ // Cylindrical-face expectation accepted by `expectGeo(...).toHaveCylindricalFace(...)`
170
+ GeoSpecCylindricalFaceExpectation: {
171
+ radius: number;
172
+ axis: 'x' | 'y' | 'z';
173
+ tolerance?: number;
174
+ }
175
+
176
+ radius: number
177
+
178
+ axis: 'x' | 'y' | 'z'
179
+
180
+ tolerance?: number
181
+
182
+ // Intentional component interference allowance accepted by `expectGeo(...).toHaveNoComponentInterference(...)`
183
+ GeoSpecComponentInterferenceAllowance: {
184
+ kind?: 'intentionalInterference';
185
+ left: GeoSpecComponentSelector;
186
+ right: GeoSpecComponentSelector;
187
+ maxVolume?: number;
188
+ reason: string;
189
+ }
190
+
191
+ kind?: 'intentionalInterference'
192
+
193
+ left: GeoSpecComponentSelector
194
+
195
+ right: GeoSpecComponentSelector
196
+
197
+ maxVolume?: number
198
+
199
+ reason: string
200
+
201
+ // Component-interference expectation accepted by `expectGeo(...).toHaveNoComponentInterference(...)`
202
+ // Remarks: GeoSpec checks for positive solid intersection volume between assembly components. Tangent contact and correctly meshed gears are allowed. `pairs` narrows the check to specific component-label pairs while preserving exact positive-volume evidence for every selected pair. `allowances` documents explicitly intentional positive-volume interference such as gasket compression, press fits, or simplified thread engagement.
203
+ GeoSpecComponentInterferenceExpectation: {
204
+ tolerance?: number;
205
+ pairs?: GeoSpecComponentInterferencePairExpectation[];
206
+ allowances?: GeoSpecComponentInterferenceAllowance[];
207
+ }
208
+
209
+ tolerance?: number
210
+
211
+ pairs?: GeoSpecComponentInterferencePairExpectation[]
212
+
213
+ allowances?: GeoSpecComponentInterferenceAllowance[]
214
+
215
+ // A pair-specific component-interference check accepted by `expectGeo(...).toHaveNoComponentInterference(...)`
216
+ GeoSpecComponentInterferencePairExpectation: {
217
+ left: GeoSpecComponentSelector;
218
+ right: GeoSpecComponentSelector;
219
+ }
220
+
221
+ left: GeoSpecComponentSelector
222
+
223
+ right: GeoSpecComponentSelector
224
+
225
+ // Connected-components expectation accepted by `expectGeo(...).toHaveConnectedComponents(...)`
226
+ GeoSpecConnectedComponentsExpectation: {
227
+ count: number;
228
+ tolerance?: number;
229
+ toleranceMm?: number;
230
+ }
231
+
232
+ count: number
233
+
234
+ tolerance?: number
235
+
236
+ toleranceMm?: number
237
+
238
+ // Geometry selector used by inspection and spatial relationship matchers
239
+ GeoSpecGeometrySelector: GeoSpecComponentSelector | {
240
+ kind: 'occurrence';
241
+ /** Product or instance name to match (also matches the PRODUCT name shared by instanced parts). */
242
+ name?: GeoSpecComponentSelector;
243
+ /** Exact occurrence path — the per-instance identity when instances share one product. */
244
+ path?: GeoSpecComponentSelector;
245
+ } | {
246
+ kind: 'axis';
247
+ name?: GeoSpecComponentSelector;
248
+ axis?: 'x' | 'y' | 'z';
249
+ center?: Vec3;
250
+ direction?: Vec3;
251
+ radius?: number;
252
+ tolerance?: number;
253
+ } | {
254
+ kind: 'plane';
255
+ name?: GeoSpecComponentSelector;
256
+ normal?: Vec3;
257
+ offset?: number;
258
+ tolerance?: number;
259
+ }
260
+ /**
261
+ * SB3 V1 selector catalog kinds (body/face/datum/interface/group plus the
262
+ * string shorthand), resolved by the native engine. SB4 routes
263
+ * relationship endpoints through that engine: the legacy explicit
264
+ * axis/plane members above resolve as `stability: 'explicit'` fixtures
265
+ * (rejected by the production evidence policy), while named legacy forms
266
+ * become engine queries. The catalog's occurrence/axis/plane query forms
267
+ * stay out of this union because their `kind` discriminants collide with
268
+ * the legacy explicit members.
269
+ */
270
+ | Exclude<GeometrySelector, string | {
271
+ kind: 'occurrence' | 'axis' | 'plane';
272
+ }>
273
+
274
+ // Assertion chain returned by `expectGeo(subject)`
275
+ GeoSpecMatcher: {
276
+ /** Core-owned negation; missing or refused evidence still fails. */
277
+ readonly not: Omit<GeoSpecMatcher, 'not'>;
278
+ /** Assert the fixed rational plate contract. */
279
+ toSatisfyRationalPlate(): GeoSpecAssertion;
280
+ /** Assert the fixed parallel-plane distance contract. */
281
+ toSatisfyParallelPlaneDistance(): GeoSpecAssertion;
282
+ /**
283
+ * Assert axis-aligned bounds, size, or center for a loaded geometry subject.
284
+ */
285
+ toHaveBoundingBox(first: Vec3 | GeoSpecBoundingBoxExpectation, second?: Vec3): GeoSpecAssertion;
286
+ /**
287
+ * Assert how many spatially disjoint chunks the mesh contains.
288
+ */
289
+ toHaveConnectedComponents(expected: GeoSpecConnectedComponentsExpectation): GeoSpecAssertion;
290
+ /**
291
+ * Assert closed mesh edge incidence; this does not prove vertex-manifold
292
+ * validity, embeddedness, a Boolean fuse, or material connectivity.
293
+ */
294
+ toBeWatertight(): GeoSpecAssertion;
295
+ /**
296
+ * Assert that separate assembly components do not occupy the same solid volume.
297
+ */
298
+ toHaveNoComponentInterference(expected?: GeoSpecComponentInterferenceExpectation): GeoSpecAssertion;
299
+ /**
300
+ * Assert that named assembly occurrences exist with expected counts and bounds.
301
+ */
302
+ toHaveAssemblyOccurrences(expected: GeoSpecAssemblyOccurrencesExpectation): GeoSpecAssertion;
303
+ /**
304
+ * Assert that selected entities satisfy declared spatial relationships.
305
+ */
306
+ toHaveSpatialRelationships(expected: GeoSpecSpatialRelationshipsExpectation): GeoSpecAssertion;
307
+ /**
308
+ * Assert rendered mesh evidence is internally trustworthy for downstream checks.
309
+ */
310
+ toHaveMeshIntegrity(expected: GeoSpecMeshIntegrityExpectation): GeoSpecAssertion;
311
+ /**
312
+ * Assert that the subject carries no diagnostics at the rejected severities.
313
+ */
314
+ toHaveNoDiagnostics(expected?: GeoSpecNoDiagnosticsExpectation): GeoSpecAssertion;
315
+ /**
316
+ * Assert total surface area, preferring exact BRep mass properties when available.
317
+ */
318
+ toHaveSurfaceArea(expected: GeoSpecSurfaceAreaExpectation): GeoSpecAssertion;
319
+ /**
320
+ * Assert enclosed volume, preferring exact BRep mass properties when available.
321
+ */
322
+ toHaveVolume(expected: GeoSpecVolumeExpectation): GeoSpecAssertion;
323
+ /**
324
+ * Assert mass derived from exact mass properties or volume times density.
325
+ */
326
+ toHaveMass(expected: GeoSpecMassExpectation): GeoSpecAssertion;
327
+ /**
328
+ * Assert the center of mass or mesh-derived centroid for a closed subject.
329
+ */
330
+ toHaveCenterOfMass(expected: GeoSpecCenterOfMassExpectation): GeoSpecAssertion;
331
+ /**
332
+ * Assert that exact BRep evidence reports a valid shape.
333
+ */
334
+ toBeValidBrep(expected?: GeoSpecValidBrepExpectation): GeoSpecAssertion;
335
+ /**
336
+ * Assert exact BRep topology counts.
337
+ */
338
+ toHaveTopologyCounts(expected: GeoSpecTopologyCountsExpectation): GeoSpecAssertion;
339
+ /**
340
+ * Assert the STEP unit evidence.
341
+ */
342
+ toHaveStepUnits(expected: GeoSpecStepUnitsExpectation): GeoSpecAssertion;
343
+ /**
344
+ * Assert STEP product-structure evidence.
345
+ */
346
+ toHaveProductStructure(expected: GeoSpecProductStructureExpectation): GeoSpecAssertion;
347
+ /**
348
+ * Assert that BRep evidence contains a planar face matching the requested constraints.
349
+ */
350
+ toHavePlanarFace(expected: GeoSpecPlanarFaceExpectation): GeoSpecAssertion;
351
+ /**
352
+ * Assert that BRep evidence contains a cylindrical face with the requested radius and axis.
353
+ */
354
+ toHaveCylindricalFace(expected: GeoSpecCylindricalFaceExpectation): GeoSpecAssertion;
355
+ /**
356
+ * Assert that BRep evidence contains a circular hole matching diameter, center, and axis.
357
+ */
358
+ toHaveCircularHole(expected: GeoSpecCircularHoleExpectation): GeoSpecAssertion;
359
+ /**
360
+ * Assert that BRep evidence contains a repeated circular-hole pattern.
361
+ */
362
+ toHaveCircularHolePattern(expected: GeoSpecCircularHolePatternExpectation): GeoSpecAssertion;
363
+ /**
364
+ * Assert that BRep evidence contains a chamfer feature with the requested distance.
365
+ */
366
+ toHaveChamferFeature(expected: GeoSpecChamferFeatureExpectation): GeoSpecAssertion;
367
+ /**
368
+ * Assert that BRep evidence contains a fillet feature with the requested radius.
369
+ */
370
+ toHaveFilletFeature(expected: GeoSpecFilletFeatureExpectation): GeoSpecAssertion;
371
+ /**
372
+ * Assert that BRep evidence reports a minimum wall thickness satisfying the expectation.
373
+ */
374
+ toHaveMinimumWallThickness(expected: GeoSpecMinimumWallThicknessExpectation): GeoSpecAssertion;
375
+ /**
376
+ * Assert that the declared waypoints share one connected void, stay isolated
377
+ * from the declared spaces, and hold the minimum cross-section.
378
+ */
379
+ toHaveVoidContinuity(expected: GeoSpecVoidContinuityExpectation): GeoSpecAssertion;
380
+ }
381
+
382
+ // Core-owned negation
383
+ readonly not: Omit<GeoSpecMatcher, 'not'>
384
+
385
+ // Assert the fixed rational plate contract
386
+ // GeoSpecMatcher.toSatisfyRationalPlate (method)
387
+ toSatisfyRationalPlate(): GeoSpecAssertion;
388
+
389
+ // Assert the fixed parallel-plane distance contract
390
+ // GeoSpecMatcher.toSatisfyParallelPlaneDistance (method)
391
+ toSatisfyParallelPlaneDistance(): GeoSpecAssertion;
392
+
393
+ // Assert axis-aligned bounds, size, or center for a loaded geometry subject
394
+ // GeoSpecMatcher.toHaveBoundingBox (method)
395
+ toHaveBoundingBox(first: Vec3 | GeoSpecBoundingBoxExpectation, second?: Vec3): GeoSpecAssertion;
396
+
397
+ // Assert how many spatially disjoint chunks the mesh contains
398
+ // GeoSpecMatcher.toHaveConnectedComponents (method)
399
+ toHaveConnectedComponents(expected: GeoSpecConnectedComponentsExpectation): GeoSpecAssertion;
400
+
401
+ // Assert closed mesh edge incidence
402
+ // GeoSpecMatcher.toBeWatertight (method)
403
+ toBeWatertight(): GeoSpecAssertion;
404
+
405
+ // Assert that separate assembly components do not occupy the same solid volume
406
+ // GeoSpecMatcher.toHaveNoComponentInterference (method)
407
+ toHaveNoComponentInterference(expected?: GeoSpecComponentInterferenceExpectation): GeoSpecAssertion;
408
+
409
+ // Assert that named assembly occurrences exist with expected counts and bounds
410
+ // GeoSpecMatcher.toHaveAssemblyOccurrences (method)
411
+ toHaveAssemblyOccurrences(expected: GeoSpecAssemblyOccurrencesExpectation): GeoSpecAssertion;
412
+
413
+ // Assert that selected entities satisfy declared spatial relationships
414
+ // GeoSpecMatcher.toHaveSpatialRelationships (method)
415
+ toHaveSpatialRelationships(expected: GeoSpecSpatialRelationshipsExpectation): GeoSpecAssertion;
416
+
417
+ // Assert rendered mesh evidence is internally trustworthy for downstream checks
418
+ // GeoSpecMatcher.toHaveMeshIntegrity (method)
419
+ toHaveMeshIntegrity(expected: GeoSpecMeshIntegrityExpectation): GeoSpecAssertion;
420
+
421
+ // Assert that the subject carries no diagnostics at the rejected severities
422
+ // GeoSpecMatcher.toHaveNoDiagnostics (method)
423
+ toHaveNoDiagnostics(expected?: GeoSpecNoDiagnosticsExpectation): GeoSpecAssertion;
424
+
425
+ // Assert total surface area, preferring exact BRep mass properties when available
426
+ // GeoSpecMatcher.toHaveSurfaceArea (method)
427
+ toHaveSurfaceArea(expected: GeoSpecSurfaceAreaExpectation): GeoSpecAssertion;
428
+
429
+ // Assert enclosed volume, preferring exact BRep mass properties when available
430
+ // GeoSpecMatcher.toHaveVolume (method)
431
+ toHaveVolume(expected: GeoSpecVolumeExpectation): GeoSpecAssertion;
432
+
433
+ // Assert mass derived from exact mass properties or volume times density
434
+ // GeoSpecMatcher.toHaveMass (method)
435
+ toHaveMass(expected: GeoSpecMassExpectation): GeoSpecAssertion;
436
+
437
+ // Assert the center of mass or mesh-derived centroid for a closed subject
438
+ // GeoSpecMatcher.toHaveCenterOfMass (method)
439
+ toHaveCenterOfMass(expected: GeoSpecCenterOfMassExpectation): GeoSpecAssertion;
440
+
441
+ // Assert that exact BRep evidence reports a valid shape
442
+ // GeoSpecMatcher.toBeValidBrep (method)
443
+ toBeValidBrep(expected?: GeoSpecValidBrepExpectation): GeoSpecAssertion;
444
+
445
+ // Assert exact BRep topology counts
446
+ // GeoSpecMatcher.toHaveTopologyCounts (method)
447
+ toHaveTopologyCounts(expected: GeoSpecTopologyCountsExpectation): GeoSpecAssertion;
448
+
449
+ // Assert the STEP unit evidence
450
+ // GeoSpecMatcher.toHaveStepUnits (method)
451
+ toHaveStepUnits(expected: GeoSpecStepUnitsExpectation): GeoSpecAssertion;
452
+
453
+ // Assert STEP product-structure evidence
454
+ // GeoSpecMatcher.toHaveProductStructure (method)
455
+ toHaveProductStructure(expected: GeoSpecProductStructureExpectation): GeoSpecAssertion;
456
+
457
+ // Assert that BRep evidence contains a planar face matching the requested constraints
458
+ // GeoSpecMatcher.toHavePlanarFace (method)
459
+ toHavePlanarFace(expected: GeoSpecPlanarFaceExpectation): GeoSpecAssertion;
460
+
461
+ // Assert that BRep evidence contains a cylindrical face with the requested radius and axis
462
+ // GeoSpecMatcher.toHaveCylindricalFace (method)
463
+ toHaveCylindricalFace(expected: GeoSpecCylindricalFaceExpectation): GeoSpecAssertion;
464
+
465
+ // Assert that BRep evidence contains a circular hole matching diameter, center, and axis
466
+ // GeoSpecMatcher.toHaveCircularHole (method)
467
+ toHaveCircularHole(expected: GeoSpecCircularHoleExpectation): GeoSpecAssertion;
468
+
469
+ // Assert that BRep evidence contains a repeated circular-hole pattern
470
+ // GeoSpecMatcher.toHaveCircularHolePattern (method)
471
+ toHaveCircularHolePattern(expected: GeoSpecCircularHolePatternExpectation): GeoSpecAssertion;
472
+
473
+ // Assert that BRep evidence contains a chamfer feature with the requested distance
474
+ // GeoSpecMatcher.toHaveChamferFeature (method)
475
+ toHaveChamferFeature(expected: GeoSpecChamferFeatureExpectation): GeoSpecAssertion;
476
+
477
+ // Assert that BRep evidence contains a fillet feature with the requested radius
478
+ // GeoSpecMatcher.toHaveFilletFeature (method)
479
+ toHaveFilletFeature(expected: GeoSpecFilletFeatureExpectation): GeoSpecAssertion;
480
+
481
+ // Assert that BRep evidence reports a minimum wall thickness satisfying the expectation
482
+ // GeoSpecMatcher.toHaveMinimumWallThickness (method)
483
+ toHaveMinimumWallThickness(expected: GeoSpecMinimumWallThicknessExpectation): GeoSpecAssertion;
484
+
485
+ // Assert that the declared waypoints share one connected void, stay isolated from the declared spaces, and hold the minimum cross-section
486
+ // GeoSpecMatcher.toHaveVoidContinuity (method)
487
+ toHaveVoidContinuity(expected: GeoSpecVoidContinuityExpectation): GeoSpecAssertion;
488
+
489
+ // Mass expectation accepted by `expectGeo(...).toHaveMass(...)`
490
+ GeoSpecMassExpectation: {
491
+ value: number | GeoSpecNumericExpectation;
492
+ density?: number;
493
+ tolerance?: number;
494
+ }
495
+
496
+ value: number | GeoSpecNumericExpectation
497
+
498
+ density?: number
499
+
500
+ tolerance?: number
501
+
502
+ // Mesh integrity expectation accepted by `expectGeo(...).toHaveMeshIntegrity(...)`
503
+ GeoSpecMeshIntegrityExpectation: {
504
+ finitePositions?: boolean;
505
+ degenerateTriangles?: {
506
+ count?: number;
507
+ maxCount?: number;
508
+ areaTolerance?: number;
509
+ };
510
+ duplicateFaces?: {
511
+ count?: number;
512
+ maxCount?: number;
513
+ };
514
+ watertight?: boolean;
515
+ triangleCount?: GeoSpecNumericExpectation;
516
+ }
517
+
518
+ finitePositions?: boolean
519
+
520
+ degenerateTriangles?: {
521
+ count?: number;
522
+ maxCount?: number;
523
+ areaTolerance?: number;
524
+ }
525
+
526
+ duplicateFaces?: {
527
+ count?: number;
528
+ maxCount?: number;
529
+ }
530
+
531
+ watertight?: boolean
532
+
533
+ triangleCount?: GeoSpecNumericExpectation
534
+
535
+ // Diagnostic severities rejected by `expectGeo(...).toHaveNoDiagnostics(...)`
536
+ // Remarks: Defaults to `error` and `warning` when omitted.
537
+ GeoSpecNoDiagnosticsExpectation: {
538
+ severities?: Array<GeometryDiagnostic['severity']>;
539
+ }
540
+
541
+ severities?: Array<GeometryDiagnostic['severity']>
542
+
543
+ // Minimum-wall-thickness expectation accepted by `expectGeo(...).toHaveMinimumWallThickness(...)`
544
+ GeoSpecMinimumWallThicknessExpectation: {
545
+ value: GeoSpecNumericExpectation;
546
+ tolerance?: number;
547
+ }
548
+
549
+ value: GeoSpecNumericExpectation
550
+
551
+ tolerance?: number
552
+
553
+ // Circular-hole-pattern expectation accepted by `expectGeo(...).toHaveCircularHolePattern(...)`
554
+ GeoSpecCircularHolePatternExpectation: {
555
+ count: number;
556
+ holeDiameter: number;
557
+ boltCircleDiameter?: number;
558
+ axis?: 'x' | 'y' | 'z';
559
+ center?: GeoSpecPointExpectation;
560
+ tolerance?: number;
561
+ }
562
+
563
+ count: number
564
+
565
+ holeDiameter: number
566
+
567
+ boltCircleDiameter?: number
568
+
569
+ axis?: 'x' | 'y' | 'z'
570
+
571
+ center?: GeoSpecPointExpectation
572
+
573
+ tolerance?: number
574
+
575
+ // Fillet-feature expectation accepted by `expectGeo(...).toHaveFilletFeature(...)`
576
+ GeoSpecFilletFeatureExpectation: {
577
+ radius: number;
578
+ selection?: string;
579
+ tolerance?: number;
580
+ }
581
+
582
+ radius: number
583
+
584
+ selection?: string
585
+
586
+ tolerance?: number
587
+
588
+ // Shared scalar expectation used by geometry measurements
589
+ GeoSpecNumericExpectation: number | {
590
+ value?: number;
591
+ greaterThan?: number;
592
+ greaterThanOrEqual?: number;
593
+ lessThan?: number;
594
+ lessThanOrEqual?: number;
595
+ }
596
+
597
+ // Planar-face expectation accepted by `expectGeo(...).toHavePlanarFace(...)`
598
+ GeoSpecPlanarFaceExpectation: {
599
+ normal: GeoSpecPointExpectation;
600
+ offset: number;
601
+ area?: GeoSpecNumericExpectation;
602
+ tolerance?: number;
603
+ }
604
+
605
+ normal: GeoSpecPointExpectation
606
+
607
+ offset: number
608
+
609
+ area?: GeoSpecNumericExpectation
610
+
611
+ tolerance?: number
612
+
613
+ // Point expectation accepted by center and feature matchers
614
+ GeoSpecPointExpectation: Vec3 | GeoSpecAxisExpectation
615
+
616
+ // Product-structure expectation accepted by `expectGeo(...).toHaveProductStructure(...)`
617
+ GeoSpecProductStructureExpectation: {
618
+ names?: string[];
619
+ count?: GeoSpecNumericExpectation;
620
+ }
621
+
622
+ names?: string[]
623
+
624
+ count?: GeoSpecNumericExpectation
625
+
626
+ // One spatial relationship accepted by `expectGeo(...).toHaveSpatialRelationships(...)`
627
+ // Remarks: Verdicts are decided by exact BRep evidence only (D3): extrema for `contact`/`clearance`, analytic fact comparison for `coaxial`/`concentric`/`coplanar`/`parallel`/`perpendicular`/`angle`, exact solid classification for `containment`/`insertion`, and exact boolean common volume for `interference` (positive volume outside the `minVolume`/`maxVolume` allowance band fails).
628
+ GeoSpecSpatialRelationshipExpectation: {
629
+ id?: string;
630
+ kind: 'contact' | 'clearance' | 'coaxial' | 'concentric' | 'coplanar' | 'parallel' | 'perpendicular' | 'angle' | 'containment' | 'insertion' | 'interference';
631
+ subject: GeoSpecGeometrySelector;
632
+ target: GeoSpecGeometrySelector;
633
+ tolerance?: number;
634
+ angularToleranceDegrees?: number;
635
+ /** Expected angle in degrees for `kind: 'angle'` (orientation-insensitive). */
636
+ angleDegrees?: number;
637
+ /** Declared insertion axis (subject-frame direction) for `kind: 'insertion'`. */
638
+ axis?: Vec3;
639
+ min?: number;
640
+ max?: number;
641
+ minVolume?: number;
642
+ maxVolume?: number;
643
+ reason?: string;
644
+ }
645
+
646
+ id?: string
647
+
648
+ kind: 'contact' | 'clearance' | 'coaxial' | 'concentric' | 'coplanar' | 'parallel' | 'perpendicular' | 'angle' | 'containment' | 'insertion' | 'interference'
649
+
650
+ subject: GeoSpecGeometrySelector
651
+
652
+ target: GeoSpecGeometrySelector
653
+
654
+ tolerance?: number
655
+
656
+ angularToleranceDegrees?: number
657
+
658
+ // Expected angle in degrees for `kind
659
+ angleDegrees?: number
660
+
661
+ // Declared insertion axis (subject-frame direction) for `kind
662
+ axis?: Vec3
663
+
664
+ min?: number
665
+
666
+ max?: number
667
+
668
+ minVolume?: number
669
+
670
+ maxVolume?: number
671
+
672
+ reason?: string
673
+
674
+ // Spatial relationship expectation accepted by `expectGeo(...).toHaveSpatialRelationships(...)`
675
+ GeoSpecSpatialRelationshipsExpectation: {
676
+ relationships: GeoSpecSpatialRelationshipExpectation[];
677
+ }
678
+
679
+ relationships: GeoSpecSpatialRelationshipExpectation[]
680
+
681
+ // STEP unit expectation accepted by `expectGeo(...).toHaveStepUnits(...)`
682
+ GeoSpecStepUnitsExpectation: {
683
+ unit: string;
684
+ }
685
+
686
+ unit: string
687
+
688
+ // Surface-area expectation accepted by `expectGeo(...).toHaveSurfaceArea(...)`
689
+ GeoSpecSurfaceAreaExpectation: {
690
+ value: number | GeoSpecNumericExpectation;
691
+ tolerance?: number;
692
+ }
693
+
694
+ value: number | GeoSpecNumericExpectation
695
+
696
+ tolerance?: number
697
+
698
+ // Topology-count expectation accepted by `expectGeo(...).toHaveTopologyCounts(...)`
699
+ GeoSpecTopologyCountsExpectation: {
700
+ vertices?: GeoSpecNumericExpectation;
701
+ edges?: GeoSpecNumericExpectation;
702
+ wires?: GeoSpecNumericExpectation;
703
+ faces?: GeoSpecNumericExpectation;
704
+ shells?: GeoSpecNumericExpectation;
705
+ solids?: GeoSpecNumericExpectation;
706
+ compounds?: GeoSpecNumericExpectation;
707
+ tolerance?: number;
708
+ }
709
+
710
+ vertices?: GeoSpecNumericExpectation
711
+
712
+ edges?: GeoSpecNumericExpectation
713
+
714
+ wires?: GeoSpecNumericExpectation
715
+
716
+ faces?: GeoSpecNumericExpectation
717
+
718
+ shells?: GeoSpecNumericExpectation
719
+
720
+ solids?: GeoSpecNumericExpectation
721
+
722
+ compounds?: GeoSpecNumericExpectation
723
+
724
+ tolerance?: number
725
+
726
+ // Exact BRep validity expectation accepted by `expectGeo(...).toBeValidBrep(...)`
727
+ GeoSpecValidBrepExpectation: {
728
+ maxTolerance?: number;
729
+ freeBounds?: {
730
+ count?: GeoSpecNumericExpectation;
731
+ };
732
+ minEdgeLength?: number;
733
+ sameParameter?: boolean;
734
+ closedShells?: boolean;
735
+ closedWires?: boolean;
736
+ }
737
+
738
+ maxTolerance?: number
739
+
740
+ freeBounds?: {
741
+ count?: GeoSpecNumericExpectation;
742
+ }
743
+
744
+ minEdgeLength?: number
745
+
746
+ sameParameter?: boolean
747
+
748
+ closedShells?: boolean
749
+
750
+ closedWires?: boolean
751
+
752
+ // Void-continuity expectation accepted by `expectGeo(...).toHaveVoidContinuity(...)`
753
+ // Remarks: A whole-assembly negative-space claim: the ordered `path` waypoints must all lie in ONE connected open-void component (void = outside every `material` solid), that component must not reach any `isolatedFrom` point, and its tightest sampled cross-section must meet `minCrossSection`. Connectivity and isolation are proven from Boolean shell topology, generalized winding-number body identity, and deterministic cross-sections.
754
+ GeoSpecVoidContinuityExpectation: {
755
+ /** Ordered waypoints (>= 1) known to lie in the void being proven. */
756
+ path: GeoSpecVoidWaypoint[];
757
+ /**
758
+ * Occurrence names whose solids bound the void. Defaults to every occurrence
759
+ * in the subject (the whole-assembly negative space).
760
+ */
761
+ material?: string[];
762
+ /** Minimum required bottleneck cross-section (mm²), sampled. */
763
+ minCrossSection?: number;
764
+ /** Points that must NOT be reachable from the path void (isolation claim). */
765
+ isolatedFrom?: Vec3[];
766
+ /**
767
+ * Region bounded for the proof (subject frame). Defaults to the union
768
+ * of the `material` occurrence bounds, which encloses every interior void.
769
+ */
770
+ bounds?: {
771
+ min: Vec3;
772
+ max: Vec3;
773
+ };
774
+ }
775
+
776
+ // Ordered waypoints (>= 1) known to lie in the void being proven
777
+ path: GeoSpecVoidWaypoint[]
778
+
779
+ // Occurrence names whose solids bound the void
780
+ material?: string[]
781
+
782
+ // Minimum required bottleneck cross-section (mm²), sampled
783
+ minCrossSection?: number
784
+
785
+ // Points that must NOT be reachable from the path void (isolation claim)
786
+ isolatedFrom?: Vec3[]
787
+
788
+ // Region bounded for the proof (subject frame)
789
+ bounds?: {
790
+ min: Vec3;
791
+ max: Vec3;
792
+ }
793
+
794
+ // One void-continuity waypoint
795
+ GeoSpecVoidWaypoint: Vec3 | {
796
+ occurrence: string;
797
+ }
798
+
799
+ // Volume expectation accepted by `expectGeo(...).toHaveVolume(...)`
800
+ GeoSpecVolumeExpectation: {
801
+ value: number | GeoSpecNumericExpectation;
802
+ tolerance?: number;
803
+ }
804
+
805
+ value: number | GeoSpecNumericExpectation
806
+
807
+ tolerance?: number
808
+
809
+ // Basic exact or topology-derived BRep evidence consumed by early feature matchers
810
+ BrepEvidence: {
811
+ validity?: {
812
+ valid: boolean;
813
+ checks?: Array<{
814
+ shape: string;
815
+ status: string;
816
+ }>;
817
+ maxTolerance?: number;
818
+ freeBounds?: {
819
+ count: number;
820
+ };
821
+ smallEdges?: Array<{
822
+ length: number;
823
+ shape?: string;
824
+ location?: Vec3;
825
+ }>;
826
+ sameParameter?: boolean;
827
+ closedShells?: boolean;
828
+ closedSolids?: boolean;
829
+ solidCount?: number;
830
+ invalidSolidCount?: number;
831
+ openEdgeCount?: number;
832
+ reason?: string;
833
+ closedWires?: boolean;
834
+ };
835
+ topologyCounts?: {
836
+ vertices?: number;
837
+ edges?: number;
838
+ wires?: number;
839
+ faces?: number;
840
+ shells?: number;
841
+ solids?: number;
842
+ compounds?: number;
843
+ };
844
+ boundingBox?: {
845
+ min: Vec3;
846
+ max: Vec3;
847
+ size: Vec3;
848
+ center: Vec3;
849
+ };
850
+ massProperties?: {
851
+ surfaceArea?: number;
852
+ volume?: number;
853
+ centerOfMass?: Vec3;
854
+ mass?: number;
855
+ };
856
+ planarFaces?: Array<{
857
+ normal: Vec3;
858
+ offset: number;
859
+ area?: number;
860
+ center?: Vec3;
861
+ }>;
862
+ cylindricalFaces?: Array<{
863
+ radius: number;
864
+ axis: 'x' | 'y' | 'z';
865
+ center?: Vec3;
866
+ axisRange?: {
867
+ min: number;
868
+ max: number;
869
+ };
870
+ }>;
871
+ circularHoles?: Array<{
872
+ diameter: number;
873
+ through: boolean;
874
+ axis: 'x' | 'y' | 'z';
875
+ center?: Vec3;
876
+ axisRange?: {
877
+ min: number;
878
+ max: number;
879
+ };
880
+ }>;
881
+ circularHolePatterns?: Array<{
882
+ count: number;
883
+ holeDiameter: number;
884
+ boltCircleDiameter: number;
885
+ axis: 'x' | 'y' | 'z';
886
+ center?: Vec3;
887
+ }>;
888
+ chamferFeatures?: Array<{
889
+ distance: number;
890
+ selection?: string;
891
+ }>;
892
+ filletFeatures?: Array<{
893
+ radius: number;
894
+ selection?: string;
895
+ }>;
896
+ minimumWallThickness?: {
897
+ value: number;
898
+ location?: Vec3;
899
+ pointA?: Vec3;
900
+ pointB?: Vec3;
901
+ solidIndex?: number;
902
+ tieCount?: number;
903
+ algorithm?: string;
904
+ tolerance?: number;
905
+ supportA?: {
906
+ faceIndex?: number;
907
+ surfaceType?: string;
908
+ supportType?: string;
909
+ };
910
+ supportB?: {
911
+ faceIndex?: number;
912
+ surfaceType?: string;
913
+ supportType?: string;
914
+ };
915
+ rejections?: Record<string, number>;
916
+ };
917
+ }
918
+
919
+ validity?: {
920
+ valid: boolean;
921
+ checks?: Array<{
922
+ shape: string;
923
+ status: string;
924
+ }>;
925
+ maxTolerance?: number;
926
+ freeBounds?: {
927
+ count: number;
928
+ };
929
+ smallEdges?: Array<{
930
+ length: number;
931
+ shape?: string;
932
+ location?: Vec3;
933
+ }>;
934
+ sameParameter?: boolean;
935
+ closedShells?: boolean;
936
+ closedSolids?: boolean;
937
+ solidCount?: number;
938
+ invalidSolidCount?: number;
939
+ openEdgeCount?: number;
940
+ reason?: string;
941
+ closedWires?: boolean;
942
+ }
943
+
944
+ topologyCounts?: {
945
+ vertices?: number;
946
+ edges?: number;
947
+ wires?: number;
948
+ faces?: number;
949
+ shells?: number;
950
+ solids?: number;
951
+ compounds?: number;
952
+ }
953
+
954
+ boundingBox?: {
955
+ min: Vec3;
956
+ max: Vec3;
957
+ size: Vec3;
958
+ center: Vec3;
959
+ }
960
+
961
+ massProperties?: {
962
+ surfaceArea?: number;
963
+ volume?: number;
964
+ centerOfMass?: Vec3;
965
+ mass?: number;
966
+ }
967
+
968
+ planarFaces?: Array<{
969
+ normal: Vec3;
970
+ offset: number;
971
+ area?: number;
972
+ center?: Vec3;
973
+ }>
974
+
975
+ cylindricalFaces?: Array<{
976
+ radius: number;
977
+ axis: 'x' | 'y' | 'z';
978
+ center?: Vec3;
979
+ axisRange?: {
980
+ min: number;
981
+ max: number;
982
+ };
983
+ }>
984
+
985
+ circularHoles?: Array<{
986
+ diameter: number;
987
+ through: boolean;
988
+ axis: 'x' | 'y' | 'z';
989
+ center?: Vec3;
990
+ axisRange?: {
991
+ min: number;
992
+ max: number;
993
+ };
994
+ }>
995
+
996
+ circularHolePatterns?: Array<{
997
+ count: number;
998
+ holeDiameter: number;
999
+ boltCircleDiameter: number;
1000
+ axis: 'x' | 'y' | 'z';
1001
+ center?: Vec3;
1002
+ }>
1003
+
1004
+ chamferFeatures?: Array<{
1005
+ distance: number;
1006
+ selection?: string;
1007
+ }>
1008
+
1009
+ filletFeatures?: Array<{
1010
+ radius: number;
1011
+ selection?: string;
1012
+ }>
1013
+
1014
+ minimumWallThickness?: {
1015
+ value: number;
1016
+ location?: Vec3;
1017
+ pointA?: Vec3;
1018
+ pointB?: Vec3;
1019
+ solidIndex?: number;
1020
+ tieCount?: number;
1021
+ algorithm?: string;
1022
+ tolerance?: number;
1023
+ supportA?: {
1024
+ faceIndex?: number;
1025
+ surfaceType?: string;
1026
+ supportType?: string;
1027
+ };
1028
+ supportB?: {
1029
+ faceIndex?: number;
1030
+ surfaceType?: string;
1031
+ supportType?: string;
1032
+ };
1033
+ rejections?: Record<string, number>;
1034
+ }
1035
+
1036
+ // Geometry file formats understood by GeoSpec provenance
1037
+ GeometryFileFormat: MeshFileFormat | 'step' | 'stp'
1038
+
1039
+ // Capability exposed by a loaded subject
1040
+ GeometryCapability: {
1041
+ kind: 'mesh';
1042
+ feature: 'triangles' | 'bounding-box' | 'connected-components' | 'watertightness' | 'surface-area' | 'volume' | 'center-of-mass' | 'distance' | 'component-overlap';
1043
+ } | {
1044
+ kind: 'brep';
1045
+ feature: 'validity' | 'topology-counts' | 'bounding-box' | 'mass-properties' | 'planar-faces' | 'cylindrical-faces' | 'circular-holes' | 'circular-hole-patterns' | 'chamfer-features' | 'fillet-features' | 'wall-thickness';
1046
+ } | {
1047
+ kind: 'step';
1048
+ feature: 'schema' | 'units' | 'product-structure' | 'reader-provenance';
1049
+ } | {
1050
+ kind: 'unsupported';
1051
+ feature: string;
1052
+ reason: string;
1053
+ }
1054
+
1055
+ kind: 'mesh'
1056
+
1057
+ feature: 'triangles' | 'bounding-box' | 'connected-components' | 'watertightness' | 'surface-area' | 'volume' | 'center-of-mass' | 'distance' | 'component-overlap'
1058
+
1059
+ // Diagnostic emitted by GeoSpec loaders, analyzers, and matchers
1060
+ GeometryDiagnostic: {
1061
+ code: KernelIssueCode | (string & {});
1062
+ severity: 'error' | 'warning' | 'info';
1063
+ message: string;
1064
+ suggestion?: string;
1065
+ spatial?: {
1066
+ min?: Vec3;
1067
+ max?: Vec3;
1068
+ center?: Vec3;
1069
+ };
1070
+ details?: unknown;
1071
+ }
1072
+
1073
+ code: KernelIssueCode | (string & {})
1074
+
1075
+ severity: 'error' | 'warning' | 'info'
1076
+
1077
+ message: string
1078
+
1079
+ suggestion?: string
1080
+
1081
+ spatial?: {
1082
+ min?: Vec3;
1083
+ max?: Vec3;
1084
+ center?: Vec3;
1085
+ }
1086
+
1087
+ details?: unknown
1088
+
1089
+ // Provenance recorded by GeoSpec loaders
1090
+ GeometryProvenance: {
1091
+ source: GeometrySource;
1092
+ unit: GeoSpecUnit;
1093
+ loader: 'gltf-transform' | 'in-memory' | 'opencascade-step';
1094
+ contentHash?: string;
1095
+ parameters?: Record<string, JSONValue>;
1096
+ exportIntent?: GeometryExportIntent;
1097
+ }
1098
+
1099
+ source: GeometrySource
1100
+
1101
+ unit: GeoSpecUnit
1102
+
1103
+ loader: 'gltf-transform' | 'in-memory' | 'opencascade-step'
1104
+
1105
+ contentHash?: string
1106
+
1107
+ parameters?: Record<string, JSONValue>
1108
+
1109
+ exportIntent?: GeometryExportIntent
1110
+
1111
+ // Source metadata for a loaded geometry subject
1112
+ GeometrySource: {
1113
+ kind: 'bytes' | 'array-buffer' | 'blob' | 'file' | 'path' | 'url' | 'mesh-buffer' | 'readable-stream' | 'async-iterable';
1114
+ format: GeometryFileFormat;
1115
+ path?: string;
1116
+ name?: string;
1117
+ byteLength?: number;
1118
+ }
1119
+
1120
+ kind: 'bytes' | 'array-buffer' | 'blob' | 'file' | 'path' | 'url' | 'mesh-buffer' | 'readable-stream' | 'async-iterable'
1121
+
1122
+ format: GeometryFileFormat
1123
+
1124
+ path?: string
1125
+
1126
+ name?: string
1127
+
1128
+ byteLength?: number
1129
+
1130
+ // Canonical P0 object under test for GeoSpec
1131
+ // Remarks: This is intentionally a GeoSpec-loaded subject rather than a Tau runtime contract. Runtime integrations pass GLB/glTF bytes or files into loaders.
1132
+ GeometrySubject: {
1133
+ kind: 'geometry-subject';
1134
+ /** Opaque engine-owned identifier used by every protocol claim. */
1135
+ subjectId: string;
1136
+ mesh: GeometrySubjectMeshEvidence;
1137
+ brep?: BrepEvidence;
1138
+ step?: StepEvidence;
1139
+ provenance: GeometryProvenance;
1140
+ capabilities: GeometryCapability[];
1141
+ diagnostics: GeometryEvidenceDiagnostic[];
1142
+ }
1143
+
1144
+ kind: 'geometry-subject'
1145
+
1146
+ // Opaque engine-owned identifier used by every protocol claim
1147
+ subjectId: string
1148
+
1149
+ mesh: GeometrySubjectMeshEvidence
1150
+
1151
+ brep?: BrepEvidence
1152
+
1153
+ step?: StepEvidence
1154
+
1155
+ provenance: GeometryProvenance
1156
+
1157
+ capabilities: GeometryCapability[]
1158
+
1159
+ diagnostics: GeometryEvidenceDiagnostic[]
1160
+
1161
+ // Wire-safe mesh summary carried by an opaque geometry subject
1162
+ GeometrySubjectMeshEvidence: {
1163
+ format: MeshFileFormat;
1164
+ stats: Pick<GeometryStats, 'vertexCount' | 'meshCount' | 'triangleCount'>;
1165
+ }
1166
+
1167
+ format: MeshFileFormat
1168
+
1169
+ stats: Pick<GeometryStats, 'vertexCount' | 'meshCount' | 'triangleCount'>
1170
+
1171
+ // Mesh evidence loaded from geometry bytes or buffers
1172
+ MeshEvidence: {
1173
+ format: MeshFileFormat;
1174
+ stats: GeometryStats;
1175
+ }
1176
+
1177
+ format: MeshFileFormat
1178
+
1179
+ stats: GeometryStats
1180
+
1181
+ // Geometry file formats supported by the P0 mesh loader
1182
+ MeshFileFormat: 'glb' | 'gltf' | 'mesh-buffer'
1183
+
1184
+ // Triangle quality and scalar mesh metrics used by P0 GeoSpec matchers
1185
+ // Remarks: Values are reported in the glTF document coordinate units.
1186
+ MeshQualityStats: {
1187
+ triangleCount: number;
1188
+ nonFiniteVertices: Array<{
1189
+ primitive: string;
1190
+ vertexIndex: number;
1191
+ position: [number, number, number];
1192
+ }>;
1193
+ degenerateTriangles: Array<{
1194
+ primitive: string;
1195
+ triangleIndex: number;
1196
+ area: number;
1197
+ center: [number, number, number];
1198
+ }>;
1199
+ duplicateFaces: Array<{
1200
+ primitive: string;
1201
+ triangleIndex: number;
1202
+ firstTriangleIndex: number;
1203
+ }>;
1204
+ triangles: MeshTriangle[];
1205
+ surfaceArea: number;
1206
+ signedVolume: number;
1207
+ centerOfMass?: Vec3;
1208
+ }
1209
+
1210
+ triangleCount: number
1211
+
1212
+ nonFiniteVertices: Array<{
1213
+ primitive: string;
1214
+ vertexIndex: number;
1215
+ position: [number, number, number];
1216
+ }>
1217
+
1218
+ degenerateTriangles: Array<{
1219
+ primitive: string;
1220
+ triangleIndex: number;
1221
+ area: number;
1222
+ center: [number, number, number];
1223
+ }>
1224
+
1225
+ duplicateFaces: Array<{
1226
+ primitive: string;
1227
+ triangleIndex: number;
1228
+ firstTriangleIndex: number;
1229
+ }>
1230
+
1231
+ triangles: MeshTriangle[]
1232
+
1233
+ surfaceArea: number
1234
+
1235
+ signedVolume: number
1236
+
1237
+ centerOfMass?: Vec3
1238
+
1239
+ // One triangle from mesh evidence, in geometry document coordinates
1240
+ MeshTriangle: {
1241
+ primitive: string;
1242
+ triangleIndex: number;
1243
+ a: [number, number, number];
1244
+ b: [number, number, number];
1245
+ c: [number, number, number];
1246
+ center: [number, number, number];
1247
+ area: number;
1248
+ }
1249
+
1250
+ primitive: string
1251
+
1252
+ triangleIndex: number
1253
+
1254
+ a: [number, number, number]
1255
+
1256
+ b: [number, number, number]
1257
+
1258
+ c: [number, number, number]
1259
+
1260
+ center: [number, number, number]
1261
+
1262
+ area: number
1263
+
1264
+ // STEP/XDE evidence extracted while loading a STEP subject
1265
+ StepEvidence: {
1266
+ schema?: string;
1267
+ unit?: GeoSpecUnit;
1268
+ productStructure?: Array<{
1269
+ name: string;
1270
+ path: string;
1271
+ transform?: number[];
1272
+ }>;
1273
+ readStrategy: {
1274
+ strategy: 'native-stream' | 'filesystem';
1275
+ inputKind: GeometrySource['kind'];
1276
+ bytesRead: number;
1277
+ nativeReadStream: boolean;
1278
+ copiedToEmscriptenFs: boolean;
1279
+ };
1280
+ capabilities: Array<{
1281
+ feature: string;
1282
+ supported: boolean;
1283
+ reason?: string;
1284
+ }>;
1285
+ /** Structured AP242 XDE read result (occurrences, subshape names, datum placements). */
1286
+ xde?: XdeReadResult;
1287
+ }
1288
+
1289
+ schema?: string
1290
+
1291
+ unit?: GeoSpecUnit
1292
+
1293
+ productStructure?: Array<{
1294
+ name: string;
1295
+ path: string;
1296
+ transform?: number[];
1297
+ }>
1298
+
1299
+ readStrategy: {
1300
+ strategy: 'native-stream' | 'filesystem';
1301
+ inputKind: GeometrySource['kind'];
1302
+ bytesRead: number;
1303
+ nativeReadStream: boolean;
1304
+ copiedToEmscriptenFs: boolean;
1305
+ }
1306
+
1307
+ capabilities: Array<{
1308
+ feature: string;
1309
+ supported: boolean;
1310
+ reason?: string;
1311
+ }>
1312
+
1313
+ // Structured AP242 XDE read result (occurrences, subshape names, datum placements)
1314
+ xde?: XdeReadResult
1315
+
1316
+ // Numeric 3D vector
1317
+ Vec3: readonly [number, number, number]
1318
+
1319
+ // Numeric 3D vector
1320
+ GeoSpecVec3: readonly [number, number, number]
1321
+
1322
+ // One matcher's contract entry
1323
+ GeoSpecMatcherDescriptor: {
1324
+ readonly kind: GeoSpecAssertion['kind'];
1325
+ readonly expected: GeoSpecMatcherExpectedShape;
1326
+ readonly mode: GeoSpecMatcherMode;
1327
+ }
1328
+
1329
+ readonly kind: GeoSpecAssertion['kind']
1330
+
1331
+ readonly expected: GeoSpecMatcherExpectedShape
1332
+
1333
+ readonly mode: GeoSpecMatcherMode
1334
+
1335
+ // How the substrate derives an assertion's recorded `expected` value from the arguments the spec author passed
1336
+ // Remarks: - `first` — the first argument verbatim. - `first-or-empty` — the first argument, defaulting to `{}`. - `bounds` — `(min, max)` pairs collapse to `{ min, max }`; a lone object argument passes through. - `true` — nullary matchers record the literal `true`.
1337
+ GeoSpecMatcherExpectedShape: 'first' | 'first-or-empty' | 'bounds' | 'true'
1338
+
1339
+ // Whether a matcher settles synchronously (throwing its `GeoSpecAssertionError` inside the `it()` body) or asynchronously (settled before the test completes)
1340
+ GeoSpecMatcherMode: 'sync' | 'async'
1341
+
1342
+ // Every matcher name exposed by `expectGeo(...)`
1343
+ GeoSpecMatcherName: Exclude<keyof GeoSpecMatcher, 'not'>
1344
+
1345
+ // In-memory triangle mesh source
1346
+ MeshBufferSource: {
1347
+ format: 'mesh-buffer';
1348
+ positions: Float32Array<ArrayBuffer> | number[];
1349
+ indices?: Uint32Array<ArrayBuffer> | Uint16Array<ArrayBuffer> | number[];
1350
+ name?: string;
1351
+ }
1352
+
1353
+ format: 'mesh-buffer'
1354
+
1355
+ positions: Float32Array<ArrayBuffer> | number[]
1356
+
1357
+ indices?: Uint32Array<ArrayBuffer> | Uint16Array<ArrayBuffer> | number[]
1358
+
1359
+ name?: string
1360
+
1361
+ // Mesh source forms accepted by {@link import ('./load-model.js').loadModel}
1362
+ MeshSource: Uint8Array<ArrayBuffer> | ArrayBuffer | Blob | File | URL | string | MeshBufferSource
1363
+
1364
+ // Axis-aligned bounding box in glTF document units (meters)
1365
+ AabbMeters: {
1366
+ min: [number, number, number];
1367
+ max: [number, number, number];
1368
+ }
1369
+
1370
+ min: [number, number, number]
1371
+
1372
+ max: [number, number, number]
1373
+
1374
+ // Dominant primitive on an axis extremum for `boundingBox` failures
1375
+ BoundingBoxAxisExtremum: {
1376
+ name: string;
1377
+ aabb: AabbMeters;
1378
+ value: number;
1379
+ }
1380
+
1381
+ name: string
1382
+
1383
+ aabb: AabbMeters
1384
+
1385
+ value: number
1386
+
1387
+ // One axis failure for `boundingBox` checks
1388
+ BoundingBoxAxisFailure: {
1389
+ axis: 'x' | 'y' | 'z';
1390
+ field: 'size' | 'center';
1391
+ expected: number;
1392
+ actual: number;
1393
+ tolerance: number;
1394
+ minExtremum?: BoundingBoxAxisExtremum;
1395
+ maxExtremum?: BoundingBoxAxisExtremum;
1396
+ }
1397
+
1398
+ axis: 'x' | 'y' | 'z'
1399
+
1400
+ field: 'size' | 'center'
1401
+
1402
+ expected: number
1403
+
1404
+ actual: number
1405
+
1406
+ tolerance: number
1407
+
1408
+ minExtremum?: BoundingBoxAxisExtremum
1409
+
1410
+ maxExtremum?: BoundingBoxAxisExtremum
1411
+
1412
+ // Structured payload when `boundingBox` fails
1413
+ BoundingBoxFailure: {
1414
+ axisFailures: BoundingBoxAxisFailure[];
1415
+ }
1416
+
1417
+ axisFailures: BoundingBoxAxisFailure[]
1418
+
1419
+ // Scene bounding box with per-primitive contributors in the subject's unit and frame
1420
+ BoundingBoxStats: {
1421
+ size: [number, number, number];
1422
+ center: [number, number, number];
1423
+ primitives: PrimitiveRecord[];
1424
+ }
1425
+
1426
+ size: [number, number, number]
1427
+
1428
+ center: [number, number, number]
1429
+
1430
+ primitives: PrimitiveRecord[]
1431
+
1432
+ // Result of evaluating a single test requirement against geometry stats
1433
+ CheckResult: {
1434
+ passed: true;
1435
+ } | {
1436
+ passed: false;
1437
+ check: 'boundingBox';
1438
+ reason: string;
1439
+ suggestion: string;
1440
+ failure: BoundingBoxFailure;
1441
+ } | {
1442
+ passed: false;
1443
+ check: 'connectedComponents';
1444
+ reason: string;
1445
+ suggestion: string;
1446
+ failure: ConnectedComponentsFailure;
1447
+ } | {
1448
+ passed: false;
1449
+ check: 'watertight';
1450
+ reason: string;
1451
+ suggestion: string;
1452
+ failure: WatertightFailure;
1453
+ } | {
1454
+ passed: false;
1455
+ check: 'invalid';
1456
+ reason: string;
1457
+ suggestion: string;
1458
+ }
1459
+
1460
+ passed: true
1461
+
1462
+ // Smallest clearance between two clusters along the dominant separation axis
1463
+ ClusterGap: {
1464
+ fromLabel: string;
1465
+ toLabel: string;
1466
+ axis: 'x' | 'y' | 'z';
1467
+ /** Millimetres — clearance between the two named primitives' AABBs. */
1468
+ gapMm: number;
1469
+ fromPrimitive: string;
1470
+ toPrimitive: string;
1471
+ }
1472
+
1473
+ fromLabel: string
1474
+
1475
+ toLabel: string
1476
+
1477
+ axis: 'x' | 'y' | 'z'
1478
+
1479
+ // Millimetres — clearance between the two named primitives' AABBs
1480
+ gapMm: number
1481
+
1482
+ fromPrimitive: string
1483
+
1484
+ toPrimitive: string
1485
+
1486
+ // One spatial cluster from AABB overlap grouping
1487
+ ClusterReport: {
1488
+ label: string;
1489
+ primitives: PrimitiveRecord[];
1490
+ aabb: AabbMeters;
1491
+ centroid: [number, number, number];
1492
+ totalVertices: number;
1493
+ }
1494
+
1495
+ label: string
1496
+
1497
+ primitives: PrimitiveRecord[]
1498
+
1499
+ aabb: AabbMeters
1500
+
1501
+ centroid: [number, number, number]
1502
+
1503
+ totalVertices: number
1504
+
1505
+ // Structured payload when `connectedComponents` fails
1506
+ ConnectedComponentsFailure: {
1507
+ expected: number;
1508
+ got: number;
1509
+ toleranceMm: number;
1510
+ clusters: ClusterReport[];
1511
+ gaps: ClusterGap[];
1512
+ }
1513
+
1514
+ expected: number
1515
+
1516
+ got: number
1517
+
1518
+ toleranceMm: number
1519
+
1520
+ clusters: ClusterReport[]
1521
+
1522
+ gaps: ClusterGap[]
1523
+
1524
+ // Full connected-components analysis at one tolerance
1525
+ ConnectedComponentsResult: {
1526
+ count: number;
1527
+ clusters: ClusterReport[];
1528
+ gaps: ClusterGap[];
1529
+ }
1530
+
1531
+ count: number
1532
+
1533
+ clusters: ClusterReport[]
1534
+
1535
+ gaps: ClusterGap[]
1536
+
1537
+ // Diagnostic form permitted inside a wire-safe subject snapshot
1538
+ GeometryEvidenceDiagnostic: Omit<GeometryDiagnostic, 'details'> & {
1539
+ details?: JSONValue;
1540
+ }
1541
+
1542
+ code: KernelIssueCode | (string & {})
1543
+
1544
+ severity: 'error' | 'warning' | 'info'
1545
+
1546
+ message: string
1547
+
1548
+ suggestion?: string
1549
+
1550
+ spatial?: {
1551
+ min?: Vec3;
1552
+ max?: Vec3;
1553
+ center?: Vec3;
1554
+ }
1555
+
1556
+ details?: JSONValue
1557
+
1558
+ // Statistics about a parsed GLB geometry
1559
+ // Remarks: `vertexCount` and `meshCount` are kept on the type for internal diagnostic use (and for the kernel-author Vitest harness in `kernel-geometry-testing.utils.ts`); they are no longer exposed via the agent-facing requirement schema.
1560
+ GeometryStats: {
1561
+ vertexCount: number;
1562
+ meshCount: number;
1563
+ triangleCount: number;
1564
+ meshQuality: MeshQualityStats;
1565
+ watertight: boolean;
1566
+ boundingBox?: BoundingBoxStats;
1567
+ }
1568
+
1569
+ vertexCount: number
1570
+
1571
+ meshCount: number
1572
+
1573
+ triangleCount: number
1574
+
1575
+ meshQuality: MeshQualityStats
1576
+
1577
+ watertight: boolean
1578
+
1579
+ boundingBox?: BoundingBoxStats
1580
+
1581
+ // One TRIANGLES primitive with identity for spatial-test feedback
1582
+ PrimitiveRecord: {
1583
+ /** The glTF node / mesh name (from kernel ShapeConfig.name when present). */
1584
+ name: string;
1585
+ color?: string;
1586
+ vertices: number;
1587
+ aabb: AabbMeters;
1588
+ }
1589
+
1590
+ // The glTF node / mesh name (from kernel ShapeConfig.name when present)
1591
+ name: string
1592
+
1593
+ color?: string
1594
+
1595
+ vertices: number
1596
+
1597
+ aabb: AabbMeters
1598
+
1599
+ // Structured payload when `watertight` fails
1600
+ WatertightFailure: {
1601
+ /** Edges with incidence ≠ 2 (open or non-manifold). */
1602
+ irregularEdges: number;
1603
+ /** Edges shared by exactly one triangle (open boundary). */
1604
+ openBoundaryEdges: number;
1605
+ /** Edges shared by more than two triangles (over-adjacent/non-manifold). */
1606
+ nonManifoldEdges: number;
1607
+ irregularEdgeKindCounts: {
1608
+ openBoundary: number;
1609
+ nonManifold: number;
1610
+ };
1611
+ irregularEdgeClusters: WatertightIrregularEdgeCluster[];
1612
+ irregularEdgeFraction: number;
1613
+ perPrimitive: WatertightPrimitiveBreakdown[];
1614
+ }
1615
+
1616
+ // Edges with incidence ≠ 2 (open or non-manifold)
1617
+ irregularEdges: number
1618
+
1619
+ // Edges shared by exactly one triangle (open boundary)
1620
+ openBoundaryEdges: number
1621
+
1622
+ // Edges shared by more than two triangles (over-adjacent/non-manifold)
1623
+ nonManifoldEdges: number
1624
+
1625
+ irregularEdgeKindCounts: {
1626
+ openBoundary: number;
1627
+ nonManifold: number;
1628
+ }
1629
+
1630
+ irregularEdgeClusters: WatertightIrregularEdgeCluster[]
1631
+
1632
+ irregularEdgeFraction: number
1633
+
1634
+ perPrimitive: WatertightPrimitiveBreakdown[]
1635
+
1636
+ // Spatial cluster of related irregular edges
1637
+ WatertightIrregularEdgeCluster: {
1638
+ kind: WatertightIrregularEdgeKind;
1639
+ edgeCount: number;
1640
+ aabb: {
1641
+ min: Vec3;
1642
+ max: Vec3;
1643
+ center: Vec3;
1644
+ };
1645
+ samples: WatertightIrregularEdgeSample[];
1646
+ }
1647
+
1648
+ kind: WatertightIrregularEdgeKind
1649
+
1650
+ edgeCount: number
1651
+
1652
+ aabb: {
1653
+ min: Vec3;
1654
+ max: Vec3;
1655
+ center: Vec3;
1656
+ }
1657
+
1658
+ samples: WatertightIrregularEdgeSample[]
1659
+
1660
+ // Class of irregular mesh edge found during watertight analysis
1661
+ WatertightIrregularEdgeKind: 'open-boundary' | 'non-manifold'
1662
+
1663
+ // Representative irregular edge, in glTF document coordinates
1664
+ WatertightIrregularEdgeSample: {
1665
+ start: Vec3;
1666
+ end: Vec3;
1667
+ center: Vec3;
1668
+ incidentTriangleCount: number;
1669
+ primitives: string[];
1670
+ color?: string;
1671
+ }
1672
+
1673
+ start: Vec3
1674
+
1675
+ end: Vec3
1676
+
1677
+ center: Vec3
1678
+
1679
+ incidentTriangleCount: number
1680
+
1681
+ primitives: string[]
1682
+
1683
+ color?: string
1684
+
1685
+ // Per-primitive watertight diagnostic (local tessellation only)
1686
+ WatertightPrimitiveBreakdown: {
1687
+ name: string;
1688
+ boundaryEdges: number;
1689
+ loopCentroid: [number, number, number];
1690
+ }
1691
+
1692
+ name: string
1693
+
1694
+ boundaryEdges: number
1695
+
1696
+ loopCentroid: [number, number, number]
1697
+
1698
+ // Full watertight analysis (global + per-primitive breakdown)
1699
+ WatertightResult: {
1700
+ watertight: boolean;
1701
+ irregularEdges: number;
1702
+ openBoundaryEdges: number;
1703
+ nonManifoldEdges: number;
1704
+ irregularEdgeKindCounts: {
1705
+ openBoundary: number;
1706
+ nonManifold: number;
1707
+ };
1708
+ irregularEdgeClusters: WatertightIrregularEdgeCluster[];
1709
+ totalEdges: number;
1710
+ irregularEdgeFraction: number;
1711
+ perPrimitive: WatertightPrimitiveBreakdown[];
1712
+ }
1713
+
1714
+ watertight: boolean
1715
+
1716
+ irregularEdges: number
1717
+
1718
+ openBoundaryEdges: number
1719
+
1720
+ nonManifoldEdges: number
1721
+
1722
+ irregularEdgeKindCounts: {
1723
+ openBoundary: number;
1724
+ nonManifold: number;
1725
+ }
1726
+
1727
+ irregularEdgeClusters: WatertightIrregularEdgeCluster[]
1728
+
1729
+ totalEdges: number
1730
+
1731
+ irregularEdgeFraction: number
1732
+
1733
+ perPrimitive: WatertightPrimitiveBreakdown[]
1734
+
1735
+ // Runtime route metadata used to decide whether a runtime export can honor GeoSpec evidence requirements
1736
+ GeoSpecExportRoute: Partial<ExportRoute> & {
1737
+ kernelId?: string;
1738
+ sourceFormat?: string;
1739
+ targetFormat?: string;
1740
+ transcoderId?: string;
1741
+ fidelity?: string;
1742
+ exportOptions?: {
1743
+ schema?: {
1744
+ properties?: Record<string, unknown>;
1745
+ };
1746
+ defaults?: Record<string, unknown>;
1747
+ };
1748
+ }
1749
+
1750
+ RuntimeBackedModelFormat: Exclude<GeoSpecModelFormat, 'mesh-buffer'>
1751
+
1752
+ // Runtime client shape for route-aware Tau runtimes
1753
+ RuntimeClientWithRoutes: GeoSpecRuntimeClient & {
1754
+ bestRouteFor(format: string, options?: {
1755
+ readonly kernelId?: string;
1756
+ }): GeoSpecExportRoute | undefined;
1757
+ }
1758
+
1759
+ open: (input: Pick<Parameters<RuntimeClient['open']>[0], 'source' | 'parameters' | 'stage' | 'watch' | 'signal'>) => Pick<ReturnType<RuntimeClient['open']>, 'export' | 'close'>
1760
+
1761
+ // RuntimeClientWithRoutes.on (method)
1762
+ on?(event: 'telemetry', handler: (batch: {
1763
+ readonly entries: ReadonlyArray<{
1764
+ name: string;
1765
+ duration: number;
1766
+ startTime: number;
1767
+ workerTimeOrigin: number;
1768
+ }>;
1769
+ }) => void): () => void;
1770
+
1771
+ // RuntimeClientWithRoutes.bestRouteFor (method)
1772
+ bestRouteFor(format: string, options?: {
1773
+ readonly kernelId?: string;
1774
+ }): GeoSpecExportRoute | undefined;
1775
+
1776
+ // Resolved runtime export request and provenance for a GeoSpec model load
1777
+ RuntimeExportIntent: {
1778
+ options: Record<string, unknown>;
1779
+ provenance: GeometryExportIntent;
1780
+ sourceUnit: GeoSpecUnit;
1781
+ }
1782
+
1783
+ options: Record<string, unknown>
1784
+
1785
+ provenance: GeometryExportIntent
1786
+
1787
+ sourceUnit: GeoSpecUnit
1788
+
1789
+ // Structured failure returned when a runtime cannot provide the requested GeoSpec evidence
1790
+ RuntimeExportIntentFailure: {
1791
+ success: false;
1792
+ diagnostics: GeometryDiagnostic[];
1793
+ }
1794
+
1795
+ success: false
1796
+
1797
+ diagnostics: GeometryDiagnostic[]
1798
+
1799
+ // Defaults accepted by {@link import ('./load-model.js').createModelLoader}
1800
+ CreateModelLoaderOptions: {
1801
+ /** Initialized compiled engine supplied by the host, never selected by an authored spec. */
1802
+ engine: GeoSpecNativeModelEngine;
1803
+ /** Rooted host reader for direct filesystem or URL sources. */
1804
+ readSource?: GeoSpecNativeSourceReader;
1805
+ /** Geometry format to export when an individual call does not specify one. */
1806
+ format?: GeoSpecModelFormat;
1807
+ /** Runtime client or lazy runtime factory. */
1808
+ runtime?: GeoSpecRuntimeClient | GeoSpecRuntimeClientFactory;
1809
+ /** Source-specific runtime adapters, e.g. host-provided GPL-isolated kernels. */
1810
+ sourceAdapters?: readonly GeoSpecRuntimeSourceAdapter[];
1811
+ /** Project root used by runtime integrations. */
1812
+ projectPath?: string;
1813
+ /** STEP reader strategy used for STEP sources or exports. */
1814
+ stepStreaming?: StepStreamingMode;
1815
+ /** Whether STEP loading should also produce mesh evidence. Defaults to true. */
1816
+ mesh?: boolean;
1817
+ /** Linear tolerance used while meshing exact BRep evidence. */
1818
+ meshLinearTolerance?: number;
1819
+ /** Angular tolerance in degrees used while meshing exact BRep evidence. */
1820
+ meshAngularToleranceDegrees?: number;
1821
+ }
1822
+
1823
+ // Initialized compiled engine supplied by the host, never selected by an authored spec
1824
+ engine: GeoSpecNativeModelEngine
1825
+
1826
+ // Rooted host reader for direct filesystem or URL sources
1827
+ readSource?: GeoSpecNativeSourceReader
1828
+
1829
+ // Geometry format to export when an individual call does not specify one
1830
+ format?: GeoSpecModelFormat
1831
+
1832
+ // Runtime client or lazy runtime factory
1833
+ runtime?: GeoSpecRuntimeClient | GeoSpecRuntimeClientFactory
1834
+
1835
+ // Source-specific runtime adapters, e.g
1836
+ sourceAdapters?: readonly GeoSpecRuntimeSourceAdapter[]
1837
+
1838
+ // Project root used by runtime integrations
1839
+ projectPath?: string
1840
+
1841
+ // STEP reader strategy used for STEP sources or exports
1842
+ stepStreaming?: StepStreamingMode
1843
+
1844
+ // Whether STEP loading should also produce mesh evidence
1845
+ mesh?: boolean
1846
+
1847
+ // Linear tolerance used while meshing exact BRep evidence
1848
+ meshLinearTolerance?: number
1849
+
1850
+ // Angular tolerance in degrees used while meshing exact BRep evidence
1851
+ meshAngularToleranceDegrees?: number
1852
+
1853
+ // Geometry formats accepted by {@link import ('./load-model.js').loadModel}
1854
+ GeoSpecModelFormat: MeshFileFormat | 'step' | 'stp'
1855
+
1856
+ // Function shape used by GeoSpec runners to provide model loading inside VM executed test files
1857
+ GeoSpecModelLoader: <Code extends Record<string, string> = Record<string, string>>(options: LoadModelOptions<Code>) => Promise<GeoSpecSubject>
1858
+
1859
+ // A configured loader whose shared runtime can be released with its owner
1860
+ ManagedGeoSpecModelLoader: GeoSpecModelLoader & {
1861
+ dispose(): Promise<void>;
1862
+ }
1863
+
1864
+ // ManagedGeoSpecModelLoader.dispose (method)
1865
+ dispose(): Promise<void>;
1866
+
1867
+ // Runtime client surface consumed by `geospec/model`
1868
+ // Remarks: GeoSpec accepts concrete Tau runtime clients from multiple call sites but only needs connection lifecycle and request-scoped documents. Keep this shape small so typed runtime clients do not have to widen their full generic method surface to GeoSpec's testing DSL. A client with `shutdown` is awaited through it when GeoSpec releases an owned runtime, so its host resources are closed before the caller (for example a worker thread) exits.
1869
+ GeoSpecRuntimeClient: Pick<RuntimeClient, 'connect' | 'terminate'> & Partial<Pick<RuntimeClient, 'shutdown'>> & {
1870
+ open: (input: Pick<Parameters<RuntimeClient['open']>[0], 'source' | 'parameters' | 'stage' | 'watch' | 'signal'>) => Pick<ReturnType<RuntimeClient['open']>, 'export' | 'close'>;
1871
+ on?(event: 'telemetry', handler: (batch: {
1872
+ readonly entries: ReadonlyArray<{
1873
+ name: string;
1874
+ duration: number;
1875
+ startTime: number;
1876
+ workerTimeOrigin: number;
1877
+ }>;
1878
+ }) => void): () => void;
1879
+ }
1880
+
1881
+ open: (input: Pick<Parameters<RuntimeClient['open']>[0], 'source' | 'parameters' | 'stage' | 'watch' | 'signal'>) => Pick<ReturnType<RuntimeClient['open']>, 'export' | 'close'>
1882
+
1883
+ // GeoSpecRuntimeClient.on (method)
1884
+ on?(event: 'telemetry', handler: (batch: {
1885
+ readonly entries: ReadonlyArray<{
1886
+ name: string;
1887
+ duration: number;
1888
+ startTime: number;
1889
+ workerTimeOrigin: number;
1890
+ }>;
1891
+ }) => void): () => void;
1892
+
1893
+ // Lazy runtime factory consumed by `geospec/model`
1894
+ GeoSpecRuntimeClientFactory: () => Promise<GeoSpecRuntimeClient>
1895
+
1896
+ // Explicit source adapter for formats whose runtime setup is not part of the generic Tau runtime preset
1897
+ GeoSpecRuntimeSourceAdapter: {
1898
+ id: string;
1899
+ extensions: readonly string[];
1900
+ createRuntime(options: {
1901
+ projectPath?: string;
1902
+ file?: string;
1903
+ }): Promise<GeoSpecRuntimeClient>;
1904
+ }
1905
+
1906
+ id: string
1907
+
1908
+ extensions: readonly string[]
1909
+
1910
+ // GeoSpecRuntimeSourceAdapter.createRuntime (method)
1911
+ createRuntime(options: {
1912
+ projectPath?: string;
1913
+ file?: string;
1914
+ }): Promise<GeoSpecRuntimeClient>;
1915
+
1916
+ // Inline code-CAD model load options
1917
+ LoadModelCodeOptions: {
1918
+ /** Source files keyed by project-relative path. */
1919
+ code: Code;
1920
+ /** Entry path to render from {@link code}. */
1921
+ file: keyof Code & string;
1922
+ /** Geometry format to export. Defaults to `glb`. */
1923
+ format?: GeoSpecModelFormat;
1924
+ /** Explicit parameters passed to the runtime. */
1925
+ parameters?: Record<string, unknown>;
1926
+ /** Runtime client or lazy runtime factory. */
1927
+ runtime?: GeoSpecRuntimeClient | GeoSpecRuntimeClientFactory;
1928
+ /** Source-specific runtime adapters, e.g. host-provided GPL-isolated kernels. */
1929
+ sourceAdapters?: readonly GeoSpecRuntimeSourceAdapter[];
1930
+ /** Project root used by runtime integrations. */
1931
+ projectPath?: string;
1932
+ /** STEP reader strategy used for STEP exports. */
1933
+ stepStreaming?: StepStreamingMode;
1934
+ /** Whether STEP loading should also produce mesh evidence. Defaults to true. */
1935
+ mesh?: boolean;
1936
+ /** Linear tolerance used while meshing exact BRep evidence. */
1937
+ meshLinearTolerance?: number;
1938
+ /** Angular tolerance in degrees used while meshing exact BRep evidence. */
1939
+ meshAngularToleranceDegrees?: number;
1940
+ }
1941
+
1942
+ // Source files keyed by project-relative path
1943
+ code: Code
1944
+
1945
+ // Entry path to render from {@link code }
1946
+ file: keyof Code & string
1947
+
1948
+ // Geometry format to export
1949
+ format?: GeoSpecModelFormat
1950
+
1951
+ // Explicit parameters passed to the runtime
1952
+ parameters?: Record<string, unknown>
1953
+
1954
+ // Runtime client or lazy runtime factory
1955
+ runtime?: GeoSpecRuntimeClient | GeoSpecRuntimeClientFactory
1956
+
1957
+ // Source-specific runtime adapters, e.g
1958
+ sourceAdapters?: readonly GeoSpecRuntimeSourceAdapter[]
1959
+
1960
+ // Project root used by runtime integrations
1961
+ projectPath?: string
1962
+
1963
+ // STEP reader strategy used for STEP exports
1964
+ stepStreaming?: StepStreamingMode
1965
+
1966
+ // Whether STEP loading should also produce mesh evidence
1967
+ mesh?: boolean
1968
+
1969
+ // Linear tolerance used while meshing exact BRep evidence
1970
+ meshLinearTolerance?: number
1971
+
1972
+ // Angular tolerance in degrees used while meshing exact BRep evidence
1973
+ meshAngularToleranceDegrees?: number
1974
+
1975
+ // Filesystem-backed model load options
1976
+ LoadModelFileOptions: {
1977
+ /** Project-relative model file to render. */
1978
+ file: string;
1979
+ /** Project root used by runtime integrations. */
1980
+ projectPath?: string;
1981
+ /** Geometry format to export. Defaults to `glb`. */
1982
+ format?: GeoSpecModelFormat;
1983
+ /** Explicit parameters passed to the runtime. */
1984
+ parameters?: Record<string, unknown>;
1985
+ /** Runtime client or lazy runtime factory. */
1986
+ runtime?: GeoSpecRuntimeClient | GeoSpecRuntimeClientFactory;
1987
+ /** Source-specific runtime adapters, e.g. host-provided GPL-isolated kernels. */
1988
+ sourceAdapters?: readonly GeoSpecRuntimeSourceAdapter[];
1989
+ /** STEP reader strategy used for STEP exports. */
1990
+ stepStreaming?: StepStreamingMode;
1991
+ /** Whether STEP loading should also produce mesh evidence. Defaults to true. */
1992
+ mesh?: boolean;
1993
+ /** Linear tolerance used while meshing exact BRep evidence. */
1994
+ meshLinearTolerance?: number;
1995
+ /** Angular tolerance in degrees used while meshing exact BRep evidence. */
1996
+ meshAngularToleranceDegrees?: number;
1997
+ }
1998
+
1999
+ // Project-relative model file to render
2000
+ file: string
2001
+
2002
+ // Project root used by runtime integrations
2003
+ projectPath?: string
2004
+
2005
+ // Geometry format to export
2006
+ format?: GeoSpecModelFormat
2007
+
2008
+ // Explicit parameters passed to the runtime
2009
+ parameters?: Record<string, unknown>
2010
+
2011
+ // Runtime client or lazy runtime factory
2012
+ runtime?: GeoSpecRuntimeClient | GeoSpecRuntimeClientFactory
2013
+
2014
+ // Source-specific runtime adapters, e.g
2015
+ sourceAdapters?: readonly GeoSpecRuntimeSourceAdapter[]
2016
+
2017
+ // STEP reader strategy used for STEP exports
2018
+ stepStreaming?: StepStreamingMode
2019
+
2020
+ // Whether STEP loading should also produce mesh evidence
2021
+ mesh?: boolean
2022
+
2023
+ // Linear tolerance used while meshing exact BRep evidence
2024
+ meshLinearTolerance?: number
2025
+
2026
+ // Angular tolerance in degrees used while meshing exact BRep evidence
2027
+ meshAngularToleranceDegrees?: number
2028
+
2029
+ // Options accepted by {@link import ('./load-model.js').loadModel}
2030
+ LoadModelOptions: LoadModelSourceOptions | LoadModelCodeOptions<Code> | LoadModelFileOptions
2031
+
2032
+ // Geometry format to export
2033
+ format?: GeoSpecModelFormat
2034
+
2035
+ // Explicit parameters passed to the runtime
2036
+ parameters?: Record<string, unknown>
2037
+
2038
+ // STEP reader strategy used for STEP exports
2039
+ stepStreaming?: StepStreamingMode
2040
+
2041
+ // Whether STEP loading should also produce mesh evidence
2042
+ mesh?: boolean
2043
+
2044
+ // Linear tolerance used while meshing exact BRep evidence
2045
+ meshLinearTolerance?: number
2046
+
2047
+ // Angular tolerance in degrees used while meshing exact BRep evidence
2048
+ meshAngularToleranceDegrees?: number