geospec 0.0.0 → 0.1.0-beta.3

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 (100) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +244 -0
  3. package/agent/doctrine.md +55 -0
  4. package/agent/geospec-authoring/SKILL.md +495 -0
  5. package/agent/geospec-authoring/api-classes.md +13 -0
  6. package/agent/geospec-authoring/api-constants.md +16 -0
  7. package/agent/geospec-authoring/api-functions.md +57 -0
  8. package/agent/geospec-authoring/api-index.md +377 -0
  9. package/agent/geospec-authoring/api-types.md +1788 -0
  10. package/agent/geospec-authoring/public-api-classes.md +22 -0
  11. package/agent/geospec-authoring/public-api-constants.md +51 -0
  12. package/agent/geospec-authoring/public-api-functions.md +215 -0
  13. package/agent/geospec-authoring/public-api-index.md +893 -0
  14. package/agent/geospec-authoring/public-api-types-2.md +1560 -0
  15. package/agent/geospec-authoring/public-api-types-3.md +217 -0
  16. package/agent/geospec-authoring/public-api-types.md +1948 -0
  17. package/agent/resources.d.ts +19 -0
  18. package/agent/resources.js +27 -0
  19. package/agent/skills.d.cts +13 -0
  20. package/agent/skills.json +28 -0
  21. package/dist/assertion-client/client.d.mts +134 -0
  22. package/dist/assertion-client/client.mjs +2 -0
  23. package/dist/assertion-client/index.d.mts +5 -0
  24. package/dist/assertion-client/index.mjs +1 -0
  25. package/dist/config/index.d.mts +3 -0
  26. package/dist/config/index.mjs +1 -0
  27. package/dist/config/node/index.d.mts +3 -0
  28. package/dist/config/node/index.mjs +1 -0
  29. package/dist/config/node/load.d.mts +19 -0
  30. package/dist/config/node/load.mjs +1 -0
  31. package/dist/config/tau-project-artifact.d.mts +54 -0
  32. package/dist/config/tau-project-artifact.mjs +3 -0
  33. package/dist/config/types.d.mts +57 -0
  34. package/dist/config/validate.mjs +1 -0
  35. package/dist/create-geospec.d.mts +50 -0
  36. package/dist/create-geospec.mjs +1 -0
  37. package/dist/engine/client.d.mts +113 -0
  38. package/dist/engine/client.mjs +1 -0
  39. package/dist/engine/index.d.mts +3 -0
  40. package/dist/engine/index.mjs +1 -0
  41. package/dist/engine/matchers.d.mts +70 -0
  42. package/dist/engine/matchers.mjs +1 -0
  43. package/dist/engine/pmi.types.d.mts +78 -0
  44. package/dist/engine/protocol.d.mts +20 -0
  45. package/dist/engine/protocol.mjs +1 -0
  46. package/dist/geometry-unit.d.mts +12 -0
  47. package/dist/index.d.mts +6 -0
  48. package/dist/index.mjs +1 -0
  49. package/dist/mesh/index.d.mts +4 -0
  50. package/dist/mesh/index.mjs +1 -0
  51. package/dist/mesh/types.d.mts +575 -0
  52. package/dist/model/errors.d.mts +20 -0
  53. package/dist/model/errors.mjs +2 -0
  54. package/dist/model/export-intent.d.mts +79 -0
  55. package/dist/model/export-intent.mjs +1 -0
  56. package/dist/model/index.d.mts +7 -0
  57. package/dist/model/index.mjs +1 -0
  58. package/dist/model/load-model.d.mts +25 -0
  59. package/dist/model/load-model.mjs +1 -0
  60. package/dist/model/native-model-loader.d.mts +142 -0
  61. package/dist/model/native-model-loader.mjs +1 -0
  62. package/dist/model/region-scope.d.mts +23 -0
  63. package/dist/model/region-scope.mjs +1 -0
  64. package/dist/model/subject-assertions.mjs +1 -0
  65. package/dist/model/subject.d.mts +11 -0
  66. package/dist/model/subject.mjs +1 -0
  67. package/dist/model/types.d.mts +254 -0
  68. package/dist/runner/collector.d.mts +64 -0
  69. package/dist/runner/collector.mjs +2 -0
  70. package/dist/runner/discovery.d.mts +93 -0
  71. package/dist/runner/discovery.mjs +1 -0
  72. package/dist/runner/filter.d.mts +50 -0
  73. package/dist/runner/filter.mjs +1 -0
  74. package/dist/runner/index.d.mts +7 -0
  75. package/dist/runner/index.mjs +1 -0
  76. package/dist/runner/native/index.d.mts +4 -0
  77. package/dist/runner/native/index.mjs +1 -0
  78. package/dist/runner/native/native-pool-grants.d.mts +21 -0
  79. package/dist/runner/native/native-pool-grants.mjs +1 -0
  80. package/dist/runner/native/native-serial-runner.d.mts +29 -0
  81. package/dist/runner/native/native-serial-runner.mjs +1 -0
  82. package/dist/runner/pool/pool-messages.d.mts +94 -0
  83. package/dist/runner/run-geospec-module.d.mts +13 -0
  84. package/dist/runner/run-geospec-module.mjs +47 -0
  85. package/dist/runner/timeout-codes.d.mts +45 -0
  86. package/dist/runner/timeout-codes.mjs +1 -0
  87. package/dist/runner/types.d.mts +776 -0
  88. package/dist/runner/worker/index.d.mts +4 -0
  89. package/dist/runner/worker/index.mjs +1 -0
  90. package/dist/runner/worker/no-matching-tests-issue.d.mts +12 -0
  91. package/dist/runner/worker/no-matching-tests-issue.mjs +1 -0
  92. package/dist/runner/worker/runner-types.d.mts +167 -0
  93. package/dist/runner/worker/serial-runner.mjs +1 -0
  94. package/dist/selector/types.d.mts +271 -0
  95. package/dist/step/types.d.mts +134 -0
  96. package/dist/vitest/adapter.d.mts +56 -0
  97. package/dist/vitest/adapter.mjs +3 -0
  98. package/dist/vitest/index.d.mts +4 -0
  99. package/dist/vitest/index.mjs +1 -0
  100. package/package.json +114 -5
@@ -0,0 +1,575 @@
1
+ import { GeoSpecUnit } from "../geometry-unit.mjs";
2
+ import { XdeReadResult } from "../step/types.mjs";
3
+ import { JSONValue, KernelIssueCode } from "@taucad/runtime/types";
4
+ //#region src/mesh/types.d.ts
5
+ /**
6
+ * Numeric 3D vector.
7
+ *
8
+ * @public
9
+ */
10
+ type Vec3 = readonly [number, number, number];
11
+ /**
12
+ * Geometry file formats supported by the P0 mesh loader.
13
+ *
14
+ * @public
15
+ */
16
+ type MeshFileFormat = 'glb' | 'gltf' | 'mesh-buffer';
17
+ /**
18
+ * Geometry file formats understood by GeoSpec provenance.
19
+ *
20
+ * @public
21
+ */
22
+ type GeometryFileFormat = MeshFileFormat | 'step' | 'stp';
23
+ /**
24
+ * Source metadata for a loaded geometry subject.
25
+ *
26
+ * @public
27
+ */
28
+ type GeometrySource = {
29
+ kind: 'bytes' | 'array-buffer' | 'blob' | 'file' | 'path' | 'url' | 'mesh-buffer' | 'readable-stream' | 'async-iterable';
30
+ format: GeometryFileFormat;
31
+ path?: string;
32
+ name?: string;
33
+ byteLength?: number;
34
+ };
35
+ /**
36
+ * Runtime export intent recorded when GeoSpec obtains evidence from a CAD
37
+ * runtime instead of a direct geometry file.
38
+ *
39
+ * @public
40
+ */
41
+ type GeometryExportIntent = {
42
+ requested: {
43
+ format: GeometryFileFormat;
44
+ coordinateSystem?: 'y-up' | 'z-up';
45
+ unit?: {
46
+ length?: 'meter' | 'millimeter';
47
+ };
48
+ tessellation?: {
49
+ linearTolerance?: number;
50
+ angularToleranceDegrees?: number;
51
+ };
52
+ };
53
+ honored?: {
54
+ format: GeometryFileFormat;
55
+ coordinateSystem?: 'y-up' | 'z-up';
56
+ unit?: {
57
+ length?: 'meter' | 'millimeter';
58
+ };
59
+ tessellation?: {
60
+ linearTolerance?: number;
61
+ angularToleranceDegrees?: number;
62
+ };
63
+ sourceUnit?: GeoSpecUnit;
64
+ };
65
+ route?: {
66
+ kernelId?: string;
67
+ sourceFormat?: string;
68
+ targetFormat?: string;
69
+ transcoderId?: string;
70
+ fidelity?: 'mesh' | 'brep' | (string & {});
71
+ direct: boolean;
72
+ };
73
+ };
74
+ /**
75
+ * Provenance recorded by GeoSpec loaders. Tau runtime still emits geometry
76
+ * bytes/files; GeoSpec records how those bytes were consumed.
77
+ *
78
+ * @public
79
+ */
80
+ type GeometryProvenance = {
81
+ source: GeometrySource;
82
+ unit: GeoSpecUnit;
83
+ loader: 'gltf-transform' | 'in-memory' | 'opencascade-step';
84
+ contentHash?: string;
85
+ parameters?: Record<string, JSONValue>;
86
+ exportIntent?: GeometryExportIntent;
87
+ };
88
+ /**
89
+ * Capability exposed by a loaded subject.
90
+ *
91
+ * @public
92
+ */
93
+ type GeometryCapability = {
94
+ kind: 'mesh';
95
+ feature: 'triangles' | 'bounding-box' | 'connected-components' | 'watertightness' | 'surface-area' | 'volume' | 'center-of-mass' | 'distance' | 'component-overlap';
96
+ } | {
97
+ kind: 'brep';
98
+ feature: 'validity' | 'topology-counts' | 'bounding-box' | 'mass-properties' | 'planar-faces' | 'cylindrical-faces' | 'circular-holes' | 'circular-hole-patterns' | 'chamfer-features' | 'fillet-features' | 'wall-thickness';
99
+ } | {
100
+ kind: 'step';
101
+ feature: 'schema' | 'units' | 'product-structure' | 'reader-provenance';
102
+ } | {
103
+ kind: 'unsupported';
104
+ feature: string;
105
+ reason: string;
106
+ };
107
+ /**
108
+ * Diagnostic emitted by GeoSpec loaders, analyzers, and matchers.
109
+ *
110
+ * @public
111
+ */
112
+ type GeometryDiagnostic = {
113
+ code: KernelIssueCode | (string & {});
114
+ severity: 'error' | 'warning' | 'info';
115
+ message: string;
116
+ suggestion?: string;
117
+ spatial?: {
118
+ min?: Vec3;
119
+ max?: Vec3;
120
+ center?: Vec3;
121
+ };
122
+ details?: unknown;
123
+ };
124
+ /** Diagnostic form permitted inside a wire-safe subject snapshot. @public */
125
+ type GeometryEvidenceDiagnostic = Omit<GeometryDiagnostic, 'details'> & {
126
+ details?: JSONValue;
127
+ };
128
+ /**
129
+ * Mesh evidence loaded from geometry bytes or buffers.
130
+ *
131
+ * @public
132
+ */
133
+ type MeshEvidence = {
134
+ format: MeshFileFormat;
135
+ stats: GeometryStats;
136
+ };
137
+ /** Wire-safe mesh summary carried by an opaque geometry subject. @public */
138
+ type GeometrySubjectMeshEvidence = {
139
+ format: MeshFileFormat;
140
+ stats: Pick<GeometryStats, 'vertexCount' | 'meshCount' | 'triangleCount'>;
141
+ };
142
+ /**
143
+ * One triangle from mesh evidence, in geometry document coordinates.
144
+ *
145
+ * @public
146
+ */
147
+ type MeshTriangle = {
148
+ primitive: string;
149
+ triangleIndex: number;
150
+ a: [number, number, number];
151
+ b: [number, number, number];
152
+ c: [number, number, number];
153
+ center: [number, number, number];
154
+ area: number;
155
+ };
156
+ /**
157
+ * Basic exact or topology-derived BRep evidence consumed by early feature
158
+ * matchers. Loaders may provide any subset; matchers report unsupported
159
+ * diagnostics when the required evidence is absent.
160
+ *
161
+ * @public
162
+ */
163
+ type BrepEvidence = {
164
+ validity?: {
165
+ valid: boolean;
166
+ checks?: Array<{
167
+ shape: string;
168
+ status: string;
169
+ }>;
170
+ maxTolerance?: number;
171
+ freeBounds?: {
172
+ count: number;
173
+ };
174
+ smallEdges?: Array<{
175
+ length: number;
176
+ shape?: string;
177
+ location?: Vec3;
178
+ }>;
179
+ sameParameter?: boolean;
180
+ closedShells?: boolean;
181
+ closedSolids?: boolean;
182
+ solidCount?: number;
183
+ invalidSolidCount?: number;
184
+ openEdgeCount?: number;
185
+ reason?: string;
186
+ closedWires?: boolean;
187
+ };
188
+ topologyCounts?: {
189
+ vertices?: number;
190
+ edges?: number;
191
+ wires?: number;
192
+ faces?: number;
193
+ shells?: number;
194
+ solids?: number;
195
+ compounds?: number;
196
+ };
197
+ boundingBox?: {
198
+ min: Vec3;
199
+ max: Vec3;
200
+ size: Vec3;
201
+ center: Vec3;
202
+ };
203
+ massProperties?: {
204
+ surfaceArea?: number;
205
+ volume?: number;
206
+ centerOfMass?: Vec3;
207
+ mass?: number;
208
+ };
209
+ planarFaces?: Array<{
210
+ normal: Vec3;
211
+ offset: number;
212
+ area?: number;
213
+ center?: Vec3;
214
+ }>;
215
+ cylindricalFaces?: Array<{
216
+ radius: number;
217
+ axis: 'x' | 'y' | 'z';
218
+ center?: Vec3;
219
+ axisRange?: {
220
+ min: number;
221
+ max: number;
222
+ };
223
+ }>;
224
+ circularHoles?: Array<{
225
+ diameter: number;
226
+ through: boolean;
227
+ axis: 'x' | 'y' | 'z';
228
+ center?: Vec3;
229
+ axisRange?: {
230
+ min: number;
231
+ max: number;
232
+ };
233
+ }>;
234
+ circularHolePatterns?: Array<{
235
+ count: number;
236
+ holeDiameter: number;
237
+ boltCircleDiameter: number;
238
+ axis: 'x' | 'y' | 'z';
239
+ center?: Vec3;
240
+ }>;
241
+ chamferFeatures?: Array<{
242
+ distance: number;
243
+ selection?: string;
244
+ }>;
245
+ filletFeatures?: Array<{
246
+ radius: number;
247
+ selection?: string;
248
+ }>;
249
+ minimumWallThickness?: {
250
+ value: number;
251
+ location?: Vec3;
252
+ pointA?: Vec3;
253
+ pointB?: Vec3;
254
+ solidIndex?: number;
255
+ tieCount?: number;
256
+ algorithm?: string;
257
+ tolerance?: number;
258
+ supportA?: {
259
+ faceIndex?: number;
260
+ surfaceType?: string;
261
+ supportType?: string;
262
+ };
263
+ supportB?: {
264
+ faceIndex?: number;
265
+ surfaceType?: string;
266
+ supportType?: string;
267
+ };
268
+ rejections?: Record<string, number>;
269
+ };
270
+ };
271
+ /**
272
+ * STEP/XDE evidence extracted while loading a STEP subject.
273
+ *
274
+ * @public
275
+ */
276
+ type StepEvidence = {
277
+ schema?: string;
278
+ unit?: GeoSpecUnit;
279
+ productStructure?: Array<{
280
+ name: string;
281
+ path: string;
282
+ transform?: number[];
283
+ }>;
284
+ readStrategy: {
285
+ strategy: 'native-stream' | 'filesystem';
286
+ inputKind: GeometrySource['kind'];
287
+ bytesRead: number;
288
+ nativeReadStream: boolean;
289
+ copiedToEmscriptenFs: boolean;
290
+ };
291
+ capabilities: Array<{
292
+ feature: string;
293
+ supported: boolean;
294
+ reason?: string;
295
+ }>;
296
+ /** Structured AP242 XDE read result (occurrences, subshape names, datum placements). */
297
+ xde?: XdeReadResult;
298
+ };
299
+ /**
300
+ * Canonical P0 object under test for GeoSpec.
301
+ *
302
+ * This is intentionally a GeoSpec-loaded subject rather than a Tau runtime
303
+ * contract. Runtime integrations pass GLB/glTF bytes or files into loaders.
304
+ *
305
+ * @public
306
+ */
307
+ type GeometrySubject = {
308
+ kind: 'geometry-subject';
309
+ /** Opaque engine-owned identifier used by every protocol claim. */
310
+ subjectId: string;
311
+ mesh: GeometrySubjectMeshEvidence;
312
+ brep?: BrepEvidence;
313
+ step?: StepEvidence;
314
+ provenance: GeometryProvenance;
315
+ capabilities: GeometryCapability[];
316
+ diagnostics: GeometryEvidenceDiagnostic[];
317
+ };
318
+ /**
319
+ * Axis-aligned bounding box in glTF document units (meters).
320
+ * @public
321
+ */
322
+ type AabbMeters = {
323
+ min: [number, number, number];
324
+ max: [number, number, number];
325
+ };
326
+ /**
327
+ * One TRIANGLES primitive with identity for spatial-test feedback.
328
+ * @public
329
+ */
330
+ type PrimitiveRecord = {
331
+ /** The glTF node / mesh name (from kernel ShapeConfig.name when present). */
332
+ name: string;
333
+ color?: string;
334
+ vertices: number;
335
+ aabb: AabbMeters;
336
+ };
337
+ /**
338
+ * One spatial cluster from AABB overlap grouping.
339
+ * @public
340
+ */
341
+ type ClusterReport = {
342
+ label: string;
343
+ primitives: PrimitiveRecord[];
344
+ aabb: AabbMeters;
345
+ centroid: [number, number, number];
346
+ totalVertices: number;
347
+ };
348
+ /**
349
+ * Smallest clearance between two clusters along the dominant separation axis.
350
+ * @public
351
+ */
352
+ type ClusterGap = {
353
+ fromLabel: string;
354
+ toLabel: string;
355
+ axis: 'x' | 'y' | 'z';
356
+ /** Millimetres — clearance between the two named primitives' AABBs. */
357
+ gapMm: number;
358
+ fromPrimitive: string;
359
+ toPrimitive: string;
360
+ };
361
+ /**
362
+ * Structured payload when `connectedComponents` fails.
363
+ * @public
364
+ */
365
+ type ConnectedComponentsFailure = {
366
+ expected: number;
367
+ got: number;
368
+ toleranceMm: number;
369
+ clusters: ClusterReport[];
370
+ gaps: ClusterGap[];
371
+ };
372
+ /**
373
+ * Dominant primitive on an axis extremum for `boundingBox` failures.
374
+ * @public
375
+ */
376
+ type BoundingBoxAxisExtremum = {
377
+ name: string;
378
+ aabb: AabbMeters;
379
+ value: number;
380
+ };
381
+ /**
382
+ * One axis failure for `boundingBox` checks.
383
+ * @public
384
+ */
385
+ type BoundingBoxAxisFailure = {
386
+ axis: 'x' | 'y' | 'z';
387
+ field: 'size' | 'center';
388
+ expected: number;
389
+ actual: number;
390
+ tolerance: number;
391
+ minExtremum?: BoundingBoxAxisExtremum;
392
+ maxExtremum?: BoundingBoxAxisExtremum;
393
+ };
394
+ /**
395
+ * Structured payload when `boundingBox` fails.
396
+ * @public
397
+ */
398
+ type BoundingBoxFailure = {
399
+ axisFailures: BoundingBoxAxisFailure[];
400
+ };
401
+ /**
402
+ * Per-primitive watertight diagnostic (local tessellation only).
403
+ * @public
404
+ */
405
+ type WatertightPrimitiveBreakdown = {
406
+ name: string;
407
+ boundaryEdges: number;
408
+ loopCentroid: [number, number, number];
409
+ };
410
+ /**
411
+ * Class of irregular mesh edge found during watertight analysis.
412
+ * @public
413
+ */
414
+ type WatertightIrregularEdgeKind = 'open-boundary' | 'non-manifold';
415
+ /**
416
+ * Representative irregular edge, in glTF document coordinates.
417
+ * @public
418
+ */
419
+ type WatertightIrregularEdgeSample = {
420
+ start: Vec3;
421
+ end: Vec3;
422
+ center: Vec3;
423
+ incidentTriangleCount: number;
424
+ primitives: string[];
425
+ color?: string;
426
+ };
427
+ /**
428
+ * Spatial cluster of related irregular edges.
429
+ * @public
430
+ */
431
+ type WatertightIrregularEdgeCluster = {
432
+ kind: WatertightIrregularEdgeKind;
433
+ edgeCount: number;
434
+ aabb: {
435
+ min: Vec3;
436
+ max: Vec3;
437
+ center: Vec3;
438
+ };
439
+ samples: WatertightIrregularEdgeSample[];
440
+ };
441
+ /**
442
+ * Structured payload when `watertight` fails.
443
+ * @public
444
+ */
445
+ type WatertightFailure = {
446
+ /** Edges with incidence ≠ 2 (open or non-manifold). */
447
+ irregularEdges: number;
448
+ /** Edges shared by exactly one triangle (open boundary). */
449
+ openBoundaryEdges: number;
450
+ /** Edges shared by more than two triangles (over-adjacent/non-manifold). */
451
+ nonManifoldEdges: number;
452
+ irregularEdgeKindCounts: {
453
+ openBoundary: number;
454
+ nonManifold: number;
455
+ };
456
+ irregularEdgeClusters: WatertightIrregularEdgeCluster[];
457
+ irregularEdgeFraction: number;
458
+ perPrimitive: WatertightPrimitiveBreakdown[];
459
+ };
460
+ /**
461
+ * Full connected-components analysis at one tolerance.
462
+ * @public
463
+ */
464
+ type ConnectedComponentsResult = {
465
+ count: number;
466
+ clusters: ClusterReport[];
467
+ gaps: ClusterGap[];
468
+ };
469
+ /**
470
+ * Full watertight analysis (global + per-primitive breakdown).
471
+ * @public
472
+ */
473
+ type WatertightResult = {
474
+ watertight: boolean;
475
+ irregularEdges: number;
476
+ openBoundaryEdges: number;
477
+ nonManifoldEdges: number;
478
+ irregularEdgeKindCounts: {
479
+ openBoundary: number;
480
+ nonManifold: number;
481
+ };
482
+ irregularEdgeClusters: WatertightIrregularEdgeCluster[];
483
+ totalEdges: number;
484
+ irregularEdgeFraction: number;
485
+ perPrimitive: WatertightPrimitiveBreakdown[];
486
+ };
487
+ /**
488
+ * Triangle quality and scalar mesh metrics used by P0 GeoSpec matchers.
489
+ *
490
+ * Values are reported in the glTF document coordinate units.
491
+ *
492
+ * @public
493
+ */
494
+ type MeshQualityStats = {
495
+ triangleCount: number;
496
+ nonFiniteVertices: Array<{
497
+ primitive: string;
498
+ vertexIndex: number;
499
+ position: [number, number, number];
500
+ }>;
501
+ degenerateTriangles: Array<{
502
+ primitive: string;
503
+ triangleIndex: number;
504
+ area: number;
505
+ center: [number, number, number];
506
+ }>;
507
+ duplicateFaces: Array<{
508
+ primitive: string;
509
+ triangleIndex: number;
510
+ firstTriangleIndex: number;
511
+ }>;
512
+ triangles: MeshTriangle[];
513
+ surfaceArea: number;
514
+ signedVolume: number;
515
+ centerOfMass?: Vec3;
516
+ };
517
+ /**
518
+ * Scene bounding box with per-primitive contributors in the subject's unit and frame.
519
+ * @public
520
+ */
521
+ type BoundingBoxStats = {
522
+ size: [number, number, number];
523
+ center: [number, number, number];
524
+ primitives: PrimitiveRecord[];
525
+ };
526
+ /**
527
+ * Statistics about a parsed GLB geometry.
528
+ *
529
+ * `vertexCount` and `meshCount` are kept on the type for internal diagnostic
530
+ * use (and for the kernel-author Vitest harness in
531
+ * `kernel-geometry-testing.utils.ts`); they are no longer exposed via the
532
+ * agent-facing requirement schema.
533
+ *
534
+ * @public
535
+ */
536
+ type GeometryStats = {
537
+ vertexCount: number;
538
+ meshCount: number;
539
+ triangleCount: number;
540
+ meshQuality: MeshQualityStats;
541
+ watertight: boolean;
542
+ boundingBox?: BoundingBoxStats;
543
+ };
544
+ /**
545
+ * Result of evaluating a single test requirement against geometry stats.
546
+ * @public
547
+ */
548
+ type CheckResult = {
549
+ passed: true;
550
+ } | {
551
+ passed: false;
552
+ check: 'boundingBox';
553
+ reason: string;
554
+ suggestion: string;
555
+ failure: BoundingBoxFailure;
556
+ } | {
557
+ passed: false;
558
+ check: 'connectedComponents';
559
+ reason: string;
560
+ suggestion: string;
561
+ failure: ConnectedComponentsFailure;
562
+ } | {
563
+ passed: false;
564
+ check: 'watertight';
565
+ reason: string;
566
+ suggestion: string;
567
+ failure: WatertightFailure;
568
+ } | {
569
+ passed: false;
570
+ check: 'invalid';
571
+ reason: string;
572
+ suggestion: string;
573
+ };
574
+ //#endregion
575
+ export { AabbMeters, BoundingBoxAxisExtremum, BoundingBoxAxisFailure, BoundingBoxFailure, BoundingBoxStats, BrepEvidence, CheckResult, ClusterGap, ClusterReport, ConnectedComponentsFailure, ConnectedComponentsResult, GeometryCapability, GeometryDiagnostic, GeometryEvidenceDiagnostic, GeometryExportIntent, GeometryFileFormat, GeometryProvenance, GeometrySource, GeometryStats, GeometrySubject, GeometrySubjectMeshEvidence, MeshEvidence, MeshFileFormat, MeshQualityStats, MeshTriangle, PrimitiveRecord, StepEvidence, Vec3, WatertightFailure, WatertightIrregularEdgeCluster, WatertightIrregularEdgeKind, WatertightIrregularEdgeSample, WatertightPrimitiveBreakdown, WatertightResult };
@@ -0,0 +1,20 @@
1
+ import { GeometryDiagnostic } from "../mesh/types.mjs";
2
+ import { z } from "zod";
3
+ //#region src/model/errors.d.ts
4
+ /**
5
+ * Error thrown by {@link import('./load-model.js').loadModel} when geometry cannot be loaded.
6
+ *
7
+ * @public
8
+ */
9
+ declare class GeoSpecModelLoadError extends Error {
10
+ /** Structured diagnostics explaining why model loading failed. */
11
+ readonly diagnostics: readonly GeometryDiagnostic[];
12
+ /**
13
+ * Create a model-load error from structured diagnostics.
14
+ *
15
+ * @param diagnostics - Geometry diagnostics to expose to callers.
16
+ */
17
+ constructor(diagnostics: readonly GeometryDiagnostic[]);
18
+ }
19
+ //#endregion
20
+ export { GeoSpecModelLoadError };
@@ -0,0 +1,2 @@
1
+ import{isGeoSpecJsonValue as e}from"../engine/protocol.mjs";import{z as t}from"zod";const n=t.tuple([t.number(),t.number(),t.number()]),r=t.strictObject({code:t.string(),severity:t.enum([`error`,`warning`,`info`]),message:t.string(),suggestion:t.string().optional(),spatial:t.strictObject({min:n.optional(),max:n.optional(),center:n.optional()}).optional(),details:t.unknown().optional()}),i=e=>{if(typeof e==`string`)return e;try{let t=JSON.stringify(e);return typeof t==`string`?t:`[unserializable diagnostic details]`}catch{return`[unserializable diagnostic details]`}},a=t=>{let n=t.details instanceof Error?{name:t.details.name,message:t.details.message}:t.details;return structuredClone({...t,...n===void 0?{}:{details:e(n)?n:i(n)}})},o=e=>{try{return structuredClone(e)}catch{return{...e,...e.details===void 0?{}:{details:i(e.details)}}}};var s=class extends Error{diagnostics;constructor(e){let t=e.map(e=>o(e));super(t.map(e=>e.message).join(`
2
+ `)||`GeoSpec model load failed.`),this.name=`GeoSpecModelLoadError`,this.diagnostics=Object.freeze(t)}};export{s as GeoSpecModelLoadError,a as diagnosticForTransport,r as geometryDiagnosticSchema};
@@ -0,0 +1,79 @@
1
+ import { GeoSpecUnit } from "../geometry-unit.mjs";
2
+ import { GeometryDiagnostic, GeometryExportIntent } from "../mesh/types.mjs";
3
+ import { GeoSpecModelFormat, GeoSpecRuntimeClient } from "./types.mjs";
4
+ import { ExportRoute } from "@taucad/runtime/types";
5
+ //#region src/model/export-intent.d.ts
6
+ /**
7
+ *
8
+ *
9
+ * @public
10
+ */
11
+ type RuntimeBackedModelFormat = Exclude<GeoSpecModelFormat, 'mesh-buffer'>;
12
+ /** Runtime route metadata used to decide whether a runtime export can honor GeoSpec evidence requirements.
13
+ *
14
+ * @public
15
+ */
16
+ type GeoSpecExportRoute = Partial<ExportRoute> & {
17
+ kernelId?: string;
18
+ sourceFormat?: string;
19
+ targetFormat?: string;
20
+ transcoderId?: string;
21
+ fidelity?: string;
22
+ exportOptions?: {
23
+ schema?: {
24
+ properties?: Record<string, unknown>;
25
+ };
26
+ defaults?: Record<string, unknown>;
27
+ };
28
+ };
29
+ /** Runtime client shape for route-aware Tau runtimes.
30
+ *
31
+ * @public
32
+ */
33
+ type RuntimeClientWithRoutes = GeoSpecRuntimeClient & {
34
+ bestRouteFor(format: string, options?: {
35
+ readonly kernelId?: string;
36
+ }): GeoSpecExportRoute | undefined;
37
+ };
38
+ /** Resolved runtime export request and provenance for a GeoSpec model load.
39
+ *
40
+ * @public
41
+ */
42
+ type RuntimeExportIntent = {
43
+ options: Record<string, unknown>;
44
+ provenance: GeometryExportIntent;
45
+ sourceUnit: GeoSpecUnit;
46
+ };
47
+ /** Structured failure returned when a runtime cannot provide the requested GeoSpec evidence.
48
+ *
49
+ * @public
50
+ */
51
+ type RuntimeExportIntentFailure = {
52
+ success: false;
53
+ diagnostics: GeometryDiagnostic[];
54
+ };
55
+ /**
56
+ * The matchers mesh evidence answers, as the GeoSpec authoring skill lists
57
+ * them (`packages/geospec/agent/geospec-authoring/SKILL.md`): bounds, volume,
58
+ * surface area, connected components and watertightness. Every other
59
+ * exact-feature matcher needs STEP BRep evidence.
60
+ *
61
+ * @public
62
+ */
63
+ declare const geoSpecMeshEvidenceMatchers: readonly ["toHaveBoundingBox", "toHaveVolume", "toHaveSurfaceArea", "toHaveConnectedComponents", "toBeWatertight"];
64
+ /** @public */
65
+ declare const resolveRuntimeExportIntent: (options: {
66
+ runtime: GeoSpecRuntimeClient;
67
+ format: RuntimeBackedModelFormat;
68
+ meshLinearTolerance?: number;
69
+ meshAngularToleranceDegrees?: number;
70
+ /**
71
+ * The kernel that evaluates this source, when the host knows it. Routes are
72
+ * then chosen among that kernel's own, so a mesh-only kernel is told its
73
+ * BRep matchers are unsupported instead of being sent to another kernel's
74
+ * STEP route.
75
+ */
76
+ kernelId?: string;
77
+ }) => RuntimeExportIntent | RuntimeExportIntentFailure;
78
+ //#endregion
79
+ export { GeoSpecExportRoute, RuntimeBackedModelFormat, RuntimeClientWithRoutes, RuntimeExportIntent, RuntimeExportIntentFailure, geoSpecMeshEvidenceMatchers, resolveRuntimeExportIntent };
@@ -0,0 +1 @@
1
+ const e=new Set([`step`,`stp`]),t=[`toHaveBoundingBox`,`toHaveVolume`,`toHaveSurfaceArea`,`toHaveConnectedComponents`,`toBeWatertight`],n=(e,t)=>({format:e,coordinateSystem:`z-up`,unit:{length:`millimeter`},...t===void 0?{}:{tessellation:t}}),r=e=>e===void 0?{}:{tessellation:{...e.linearTolerance===void 0?{}:{linearTolerance:e.linearTolerance},...e.angularToleranceDegrees===void 0?{}:{angularTolerance:e.angularToleranceDegrees}}},i=e=>{let t=n(e.format,e.tessellation);return{options:e.exportOptions,sourceUnit:`mm`,provenance:{requested:t,honored:{format:t.format,coordinateSystem:`z-up`,unit:{length:`millimeter`},sourceUnit:`mm`,...e.tessellation===void 0?{}:{tessellation:e.tessellation}}}}},a=e=>e?{...e.kernelId===void 0?{}:{kernelId:e.kernelId},...e.sourceFormat===void 0?{}:{sourceFormat:e.sourceFormat},...e.targetFormat===void 0?{}:{targetFormat:e.targetFormat},...e.transcoderId===void 0?{}:{transcoderId:e.transcoderId},...e.fidelity===void 0?{}:{fidelity:e.fidelity},direct:d(e)}:void 0,o=`loadModel({ file, format: 'glb' }) with mesh-supported matchers (${t.join(`, `)})`,s=e=>({success:!1,diagnostics:[{code:`GEOSPEC_KERNEL_BREP_UNSUPPORTED`,severity:`error`,message:`${e.kernelId===void 0?`No kernel in this runtime`:`Kernel '${e.kernelId}'`} has no direct STEP/BRep export route, so exact BRep evidence is unavailable and BRep matchers are unsupported on ${e.kernelId===void 0?`it`:`this kernel`}.`,suggestion:`Keep the requirement and report it as unsupported on this kernel. Load mesh evidence with ${o} for the requirements a mesh can answer.`,details:{format:`step`,...e.kernelId===void 0?{}:{kernelId:e.kernelId},...e.route===void 0?{}:{route:a(e.route)},meshAlternative:{format:`glb`,matchers:[...t]}}}]}),c=e=>typeof e.bestRouteFor==`function`,l=(e,t)=>{let{capabilities:n}=e;if((n?.routes?.length??0)>0)return!0;let{routesFor:r}=e;return typeof r==`function`&&r(t).length>0},u=(e,t)=>t in(e?.exportOptions?.schema.properties??{}),d=e=>e.transcoderId===void 0,f=e=>({success:!1,diagnostics:[{code:`GEOSPEC_CANONICAL_EXPORT_UNSUPPORTED`,severity:`error`,message:`GeoSpec cannot request canonical Z-up millimeter ${e.format.toUpperCase()} evidence from this runtime route.`,suggestion:`Use a runtime route whose export schema exposes coordinateSystem and unit.length, or pass a custom runtime that returns canonical millimeter geometry bytes.`,details:{format:e.format,missing:e.missing,route:a(e.route)}}]}),p=p=>{let{runtime:m,format:h}=p,g=p.meshLinearTolerance===void 0&&p.meshAngularToleranceDegrees===void 0?void 0:{...p.meshLinearTolerance===void 0?{}:{linearTolerance:p.meshLinearTolerance},...p.meshAngularToleranceDegrees===void 0?{}:{angularToleranceDegrees:p.meshAngularToleranceDegrees}},_=c(m),{kernelId:v}=p,y=_?v===void 0?m.bestRouteFor(h):m.bestRouteFor(h,{kernelId:v}):void 0;if(e.has(h)){let e=y!==void 0&&d(y)&&y.fidelity===`brep`;if(_&&!e&&v!==void 0&&l(m,h))return s({kernelId:v,route:y});if(y&&!e)return{success:!1,diagnostics:[{code:`GEOSPEC_DIRECT_STEP_ROUTE_REQUIRED`,severity:`error`,message:`GeoSpec exact BRep evidence requires a direct STEP/BRep runtime export route.`,suggestion:`No kernel in this runtime offers a direct STEP/BRep route, so keep the requirement and report it as unsupported here. Load mesh evidence with ${o} for the requirements a mesh can answer.`,details:{route:a(y),meshAlternative:{format:`glb`,matchers:[...t]}}}]};let n={},r={format:h,sourceUnit:`mm`};return u(y,`coordinateSystem`)&&(n.coordinateSystem=`z-up`,r.coordinateSystem=`z-up`),{options:n,sourceUnit:`mm`,provenance:{requested:{format:h},honored:r,route:a(y)}}}let b=n(h,g);if(!_)return i({format:h,exportOptions:{coordinateSystem:`z-up`,unit:{length:`millimeter`},...r(g)},...g===void 0?{}:{tessellation:g}});if(!y)return l(m,h)?f({format:h,missing:[`route`]}):i({format:h,exportOptions:{coordinateSystem:`z-up`,unit:{length:`millimeter`},...r(g)},...g===void 0?{}:{tessellation:g}});let x=[`coordinateSystem`,`unit`,...g===void 0?[]:[`tessellation`]].filter(e=>!u(y,e));return x.length>0?f({format:h,route:y,missing:x}):{options:{coordinateSystem:`z-up`,unit:{length:`millimeter`},...r(g)},sourceUnit:`mm`,provenance:{requested:b,honored:{format:b.format,coordinateSystem:`z-up`,unit:{length:`millimeter`},sourceUnit:`mm`,...g===void 0?{}:{tessellation:g}},route:a(y)}}};export{t as geoSpecMeshEvidenceMatchers,p as resolveRuntimeExportIntent};
@@ -0,0 +1,7 @@
1
+ import { GeoSpecSubject } from "./subject.mjs";
2
+ import { CreateModelLoaderOptions, GeoSpecLoadRegion, GeoSpecModelFormat, GeoSpecModelLoader, GeoSpecRuntimeClient, GeoSpecRuntimeClientFactory, GeoSpecRuntimeSourceAdapter, LoadModelCodeOptions, LoadModelFileOptions, LoadModelOptions, LoadModelSourceOptions, ManagedGeoSpecModelLoader } from "./types.mjs";
3
+ import { GeoSpecExportRoute, RuntimeBackedModelFormat, RuntimeClientWithRoutes, RuntimeExportIntent, RuntimeExportIntentFailure, geoSpecMeshEvidenceMatchers, resolveRuntimeExportIntent } from "./export-intent.mjs";
4
+ import { GeoSpecModelLoadError } from "./errors.mjs";
5
+ import { createModelLoader, loadModel } from "./load-model.mjs";
6
+ import { geoSpecRegionScopedKinds, geoSpecRegionWholeModelClaimCode } from "./region-scope.mjs";
7
+ export { type CreateModelLoaderOptions, type GeoSpecExportRoute, type GeoSpecLoadRegion, type GeoSpecModelFormat, GeoSpecModelLoadError, type GeoSpecModelLoader, type GeoSpecRuntimeClient, type GeoSpecRuntimeClientFactory, type GeoSpecRuntimeSourceAdapter, type GeoSpecSubject, type LoadModelCodeOptions, type LoadModelFileOptions, type LoadModelOptions, type LoadModelSourceOptions, type ManagedGeoSpecModelLoader, type RuntimeBackedModelFormat, type RuntimeClientWithRoutes, type RuntimeExportIntent, type RuntimeExportIntentFailure, createModelLoader, geoSpecMeshEvidenceMatchers, geoSpecRegionScopedKinds, geoSpecRegionWholeModelClaimCode, loadModel, resolveRuntimeExportIntent };
@@ -0,0 +1 @@
1
+ import{GeoSpecModelLoadError as e}from"./errors.mjs";import{geoSpecRegionScopedKinds as t,geoSpecRegionWholeModelClaimCode as n}from"./region-scope.mjs";import{geoSpecMeshEvidenceMatchers as r,resolveRuntimeExportIntent as i}from"./export-intent.mjs";import{createModelLoader as a,loadModel as o}from"./load-model.mjs";export{e as GeoSpecModelLoadError,a as createModelLoader,r as geoSpecMeshEvidenceMatchers,t as geoSpecRegionScopedKinds,n as geoSpecRegionWholeModelClaimCode,o as loadModel,i as resolveRuntimeExportIntent};