brepjs-verify 0.3.0 → 0.4.0
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.
- package/CHANGELOG.md +7 -0
- package/README.md +9 -0
- package/dist/brepjs-verify.cjs +1 -1
- package/dist/brepjs-verify.js +1 -1
- package/dist/cli/main.cjs +1 -1
- package/dist/cli/main.js +1 -1
- package/dist/{diff-mxAOOl_m.cjs → diff-BNmCp_8I.cjs} +78 -1
- package/dist/{diff-Covv1XuJ.js → diff-D5U3Ie2F.js} +78 -1
- package/dist/verify/expected.d.ts +15 -0
- package/package.json +4 -2
- package/reference/llms-full.txt +2052 -0
- package/reference/llms.txt +1810 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.0](https://github.com/andymai/brepjs/compare/brepjs-verify-v0.3.0...brepjs-verify-v0.4.0) (2026-06-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **brepjs-verify:** eval-driven skill, hint, and reference improvements ([#1219](https://github.com/andymai/brepjs/issues/1219)) ([1a9b80f](https://github.com/andymai/brepjs/commit/1a9b80f3d3dbb44d7a8ae2f601ff305b70534efe))
|
|
9
|
+
|
|
3
10
|
## [0.3.0](https://github.com/andymai/brepjs/compare/brepjs-verify-v0.2.1...brepjs-verify-v0.3.0) (2026-06-04)
|
|
4
11
|
|
|
5
12
|
|
package/README.md
CHANGED
|
@@ -21,6 +21,15 @@ The CLI the skill invokes. Install it in **your** project, where `brepjs` + the
|
|
|
21
21
|
npm i -D brepjs-verify brepjs occt-wasm
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## API reference
|
|
25
|
+
|
|
26
|
+
The package bundles brepjs's full API reference for offline/agent use — the complete export surface with signatures and examples:
|
|
27
|
+
|
|
28
|
+
- `reference/llms-full.txt` — every export, full signatures (the deep reference)
|
|
29
|
+
- `reference/llms.txt` — the same content as a quicker index
|
|
30
|
+
|
|
31
|
+
Point your agent at `node_modules/brepjs-verify/reference/llms-full.txt` for anything the skill's curated references don't cover.
|
|
32
|
+
|
|
24
33
|
## The `.brep.ts` contract
|
|
25
34
|
|
|
26
35
|
A model is a module whose default export is a zero-arg function returning a shape (or a `Result<shape>`):
|
package/dist/brepjs-verify.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_diff = require("./diff-
|
|
2
|
+
const require_diff = require("./diff-BNmCp_8I.cjs");
|
|
3
3
|
exports.DEFAULT_TOLERANCE_PCT = require_diff.DEFAULT_TOLERANCE_PCT;
|
|
4
4
|
exports.TYPECHECK_CODE = require_diff.TYPECHECK_CODE;
|
|
5
5
|
exports.emptyReport = require_diff.emptyReport;
|
package/dist/brepjs-verify.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as typecheckPart, c as isExpectedDims, d as emptyReport, i as TYPECHECK_CODE, l as pctDelta, m as serializeReport, n as runMeasure, o as DEFAULT_TOLERANCE_PCT, r as runPart, s as evaluateExpected, t as runDiff, u as runChecks } from "./diff-
|
|
1
|
+
import { a as typecheckPart, c as isExpectedDims, d as emptyReport, i as TYPECHECK_CODE, l as pctDelta, m as serializeReport, n as runMeasure, o as DEFAULT_TOLERANCE_PCT, r as runPart, s as evaluateExpected, t as runDiff, u as runChecks } from "./diff-D5U3Ie2F.js";
|
|
2
2
|
export { DEFAULT_TOLERANCE_PCT, TYPECHECK_CODE, emptyReport, evaluateExpected, isExpectedDims, pctDelta, runChecks, runDiff, runMeasure, runPart, serializeReport, typecheckPart };
|
package/dist/cli/main.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const require_diff = require("../diff-
|
|
3
|
+
const require_diff = require("../diff-BNmCp_8I.cjs");
|
|
4
4
|
let node_url = require("node:url");
|
|
5
5
|
let node_fs = require("node:fs");
|
|
6
6
|
let node_path = require("node:path");
|
package/dist/cli/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { f as pushError, h as loadBrep, m as serializeReport, n as runMeasure, p as reportOk, r as runPart, t as runDiff } from "../diff-
|
|
2
|
+
import { f as pushError, h as loadBrep, m as serializeReport, n as runMeasure, p as reportOk, r as runPart, t as runDiff } from "../diff-D5U3Ie2F.js";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { existsSync, mkdirSync, realpathSync, watch, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
@@ -164,6 +164,14 @@ var HINT_TABLE = {
|
|
|
164
164
|
fix: "The boolean subtraction failed — often a tool that does not actually intersect the base, or tolerance issues.",
|
|
165
165
|
nextStep: "Confirm the tool overlaps the base, optionally heal the inputs, then re-cut."
|
|
166
166
|
},
|
|
167
|
+
FILLET_FAILED: {
|
|
168
|
+
fix: "The fillet could not be built — usually the radius is too large for an edge it touched (it cannot exceed the adjacent face/wall), or you filleted EVERY edge (the no-edge-list form) including ones too thin to round.",
|
|
169
|
+
nextStep: "Select only the edges you mean to round — e.g. edgeFinder().inDirection(\"Z\").findAll(solid) — and/or reduce the radius below the thinnest adjacent wall, then re-verify."
|
|
170
|
+
},
|
|
171
|
+
CHAMFER_FAILED: {
|
|
172
|
+
fix: "The chamfer could not be built — usually the distance is too large for an edge it touched, or you chamfered EVERY edge (the no-edge-list form) including ones too thin.",
|
|
173
|
+
nextStep: "Select only the target edges with an edge finder and/or reduce the distance below the shortest adjacent edge, then re-verify."
|
|
174
|
+
},
|
|
167
175
|
BOOLEAN_HAS_ERRORS: {
|
|
168
176
|
fix: "The boolean ran but the kernel reported errors (often coincident faces or near-tangent contact).",
|
|
169
177
|
nextStep: "Perturb one operand slightly so contact is a clean overlap, or heal the inputs, then retry."
|
|
@@ -199,6 +207,10 @@ var HINT_TABLE = {
|
|
|
199
207
|
TYPECHECK: {
|
|
200
208
|
fix: "Fix the TypeScript type error before running the part — the API call or value does not match brepjs’s types.",
|
|
201
209
|
nextStep: "Correct the flagged type (e.g. argument/return type or import), then re-verify."
|
|
210
|
+
},
|
|
211
|
+
EXPECTED_UNKNOWN_KEY: {
|
|
212
|
+
fix: "Your `expected` block has keys the CLI does not assert (so the intended check never ran). Bounds must be `{ xMin, xMax, yMin, yMax, zMin, zMax }` — not `{ min, max }` or `{ x, y, z }`.",
|
|
213
|
+
nextStep: "Rewrite `expected` using only volume, area, tolerancePct, and bounds.{xMin..zMax}, then re-verify."
|
|
202
214
|
}
|
|
203
215
|
};
|
|
204
216
|
/** Synthetic code attached to validity-check failures (validSolid returns a plain string error). */
|
|
@@ -302,8 +314,38 @@ function pctDelta(actual, expected) {
|
|
|
302
314
|
return Math.abs(actual - expected) / Math.abs(expected) * 100;
|
|
303
315
|
}
|
|
304
316
|
function withinTolerance(actual, expected, tolerancePct) {
|
|
317
|
+
if (Math.abs(actual - expected) <= 1e-6) return true;
|
|
305
318
|
return pctDelta(actual, expected) <= tolerancePct;
|
|
306
319
|
}
|
|
320
|
+
var TOP_LEVEL_KEYS = new Set([
|
|
321
|
+
"volume",
|
|
322
|
+
"area",
|
|
323
|
+
"bounds",
|
|
324
|
+
"tolerancePct"
|
|
325
|
+
]);
|
|
326
|
+
var BOUND_KEYS = new Set([
|
|
327
|
+
"xMin",
|
|
328
|
+
"xMax",
|
|
329
|
+
"yMin",
|
|
330
|
+
"yMax",
|
|
331
|
+
"zMin",
|
|
332
|
+
"zMax"
|
|
333
|
+
]);
|
|
334
|
+
/**
|
|
335
|
+
* Keys in an `expected` block that the CLI does not understand and would silently ignore — a
|
|
336
|
+
* `{ min: [...], max: [...] }` or `{ x: [...] }` bounds shape, or a misspelled top-level field.
|
|
337
|
+
* Surfaced as an error (not dropped) so a wrong `expected` shape fails loud instead of passing
|
|
338
|
+
* vacuously with the intended assertion never run.
|
|
339
|
+
*/
|
|
340
|
+
function unknownExpectedKeys(expected) {
|
|
341
|
+
const bad = [];
|
|
342
|
+
for (const k of Object.keys(expected)) if (!TOP_LEVEL_KEYS.has(k)) bad.push(k);
|
|
343
|
+
const bounds = expected.bounds;
|
|
344
|
+
if (bounds && typeof bounds === "object") {
|
|
345
|
+
for (const k of Object.keys(bounds)) if (!BOUND_KEYS.has(k)) bad.push(`bounds.${k}`);
|
|
346
|
+
}
|
|
347
|
+
return bad;
|
|
348
|
+
}
|
|
307
349
|
function isExpectedDims(v) {
|
|
308
350
|
if (typeof v !== "object" || v === null) return false;
|
|
309
351
|
const r = v;
|
|
@@ -427,6 +469,25 @@ var COMPILER_OPTIONS = {
|
|
|
427
469
|
skipLibCheck: true,
|
|
428
470
|
allowImportingTsExtensions: true
|
|
429
471
|
};
|
|
472
|
+
/**
|
|
473
|
+
* Locate the `@types/node` declarations so a part may import Node built-ins (`node:fs` to load a
|
|
474
|
+
* font, `node:fs/promises` to read a STEP file, etc.) without `--check` failing on the import.
|
|
475
|
+
* Returns the `@types` directory to use as a `typeRoots` entry. Probes the tool's own install
|
|
476
|
+
* first (where `@types/node` ships as a dependency), then the part's directory.
|
|
477
|
+
*/
|
|
478
|
+
function nodeTypesRoot(partPath, toolDir) {
|
|
479
|
+
const froms = [
|
|
480
|
+
{}.url,
|
|
481
|
+
toolDir ? (0, node_url.pathToFileURL)((0, node_path.resolve)(toolDir, "package.json")).href : void 0,
|
|
482
|
+
(0, node_url.pathToFileURL)(partPath).href
|
|
483
|
+
];
|
|
484
|
+
for (const from of froms) {
|
|
485
|
+
if (!from) continue;
|
|
486
|
+
try {
|
|
487
|
+
return (0, node_path.dirname)((0, node_path.dirname)((0, node_module.createRequire)(from).resolve("@types/node/package.json")));
|
|
488
|
+
} catch {}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
430
491
|
function diagnosticToErrorInfo(d) {
|
|
431
492
|
const text = typescript.default.flattenDiagnosticMessageText(d.messageText, "\n");
|
|
432
493
|
let where = "";
|
|
@@ -451,6 +512,11 @@ function typecheckPart(partPath, toolDir) {
|
|
|
451
512
|
const dts = resolveBrepjsTypes(partPath, toolDir);
|
|
452
513
|
const options = { ...COMPILER_OPTIONS };
|
|
453
514
|
if (dts) options.paths = { brepjs: [dts] };
|
|
515
|
+
const typesRoot = nodeTypesRoot(partPath, toolDir);
|
|
516
|
+
if (typesRoot) {
|
|
517
|
+
options.typeRoots = [typesRoot];
|
|
518
|
+
options.types = ["node"];
|
|
519
|
+
}
|
|
454
520
|
const program = typescript.default.createProgram([partPath], options);
|
|
455
521
|
const errors = [
|
|
456
522
|
...program.getSemanticDiagnostics(),
|
|
@@ -487,7 +553,13 @@ function toErrorInfo(prefix, e) {
|
|
|
487
553
|
code: e.code,
|
|
488
554
|
suggestion: e.suggestion
|
|
489
555
|
};
|
|
490
|
-
if (e instanceof Error)
|
|
556
|
+
if (e instanceof Error) {
|
|
557
|
+
const code = e.message.match(/\[[A-Z][A-Z0-9_]*\]\s+([A-Z][A-Z0-9_]+):/)?.[1];
|
|
558
|
+
return code ? {
|
|
559
|
+
message: `${prefix}: ${e.message}`,
|
|
560
|
+
code
|
|
561
|
+
} : { message: `${prefix}: ${e.message}` };
|
|
562
|
+
}
|
|
491
563
|
return { message: `${prefix}: ${String(e)}` };
|
|
492
564
|
}
|
|
493
565
|
function finalize(result) {
|
|
@@ -567,6 +639,11 @@ async function runPart(modulePath, opts = {}) {
|
|
|
567
639
|
if (isExpectedDims(mod.expected)) {
|
|
568
640
|
const expected = mod.expected;
|
|
569
641
|
result.assertions = evaluateExpected(expected, result.measurements);
|
|
642
|
+
const unknown = unknownExpectedKeys(expected);
|
|
643
|
+
if (unknown.length > 0) pushError(result, {
|
|
644
|
+
message: `expected has unrecognized keys (ignored): ${unknown.join(", ")}. Valid keys: volume, area, tolerancePct, bounds.{xMin,xMax,yMin,yMax,zMin,zMax}.`,
|
|
645
|
+
code: "EXPECTED_UNKNOWN_KEY"
|
|
646
|
+
});
|
|
570
647
|
}
|
|
571
648
|
let glb;
|
|
572
649
|
let step;
|
|
@@ -162,6 +162,14 @@ var HINT_TABLE = {
|
|
|
162
162
|
fix: "The boolean subtraction failed — often a tool that does not actually intersect the base, or tolerance issues.",
|
|
163
163
|
nextStep: "Confirm the tool overlaps the base, optionally heal the inputs, then re-cut."
|
|
164
164
|
},
|
|
165
|
+
FILLET_FAILED: {
|
|
166
|
+
fix: "The fillet could not be built — usually the radius is too large for an edge it touched (it cannot exceed the adjacent face/wall), or you filleted EVERY edge (the no-edge-list form) including ones too thin to round.",
|
|
167
|
+
nextStep: "Select only the edges you mean to round — e.g. edgeFinder().inDirection(\"Z\").findAll(solid) — and/or reduce the radius below the thinnest adjacent wall, then re-verify."
|
|
168
|
+
},
|
|
169
|
+
CHAMFER_FAILED: {
|
|
170
|
+
fix: "The chamfer could not be built — usually the distance is too large for an edge it touched, or you chamfered EVERY edge (the no-edge-list form) including ones too thin.",
|
|
171
|
+
nextStep: "Select only the target edges with an edge finder and/or reduce the distance below the shortest adjacent edge, then re-verify."
|
|
172
|
+
},
|
|
165
173
|
BOOLEAN_HAS_ERRORS: {
|
|
166
174
|
fix: "The boolean ran but the kernel reported errors (often coincident faces or near-tangent contact).",
|
|
167
175
|
nextStep: "Perturb one operand slightly so contact is a clean overlap, or heal the inputs, then retry."
|
|
@@ -197,6 +205,10 @@ var HINT_TABLE = {
|
|
|
197
205
|
TYPECHECK: {
|
|
198
206
|
fix: "Fix the TypeScript type error before running the part — the API call or value does not match brepjs’s types.",
|
|
199
207
|
nextStep: "Correct the flagged type (e.g. argument/return type or import), then re-verify."
|
|
208
|
+
},
|
|
209
|
+
EXPECTED_UNKNOWN_KEY: {
|
|
210
|
+
fix: "Your `expected` block has keys the CLI does not assert (so the intended check never ran). Bounds must be `{ xMin, xMax, yMin, yMax, zMin, zMax }` — not `{ min, max }` or `{ x, y, z }`.",
|
|
211
|
+
nextStep: "Rewrite `expected` using only volume, area, tolerancePct, and bounds.{xMin..zMax}, then re-verify."
|
|
200
212
|
}
|
|
201
213
|
};
|
|
202
214
|
/** Synthetic code attached to validity-check failures (validSolid returns a plain string error). */
|
|
@@ -300,8 +312,38 @@ function pctDelta(actual, expected) {
|
|
|
300
312
|
return Math.abs(actual - expected) / Math.abs(expected) * 100;
|
|
301
313
|
}
|
|
302
314
|
function withinTolerance(actual, expected, tolerancePct) {
|
|
315
|
+
if (Math.abs(actual - expected) <= 1e-6) return true;
|
|
303
316
|
return pctDelta(actual, expected) <= tolerancePct;
|
|
304
317
|
}
|
|
318
|
+
var TOP_LEVEL_KEYS = new Set([
|
|
319
|
+
"volume",
|
|
320
|
+
"area",
|
|
321
|
+
"bounds",
|
|
322
|
+
"tolerancePct"
|
|
323
|
+
]);
|
|
324
|
+
var BOUND_KEYS = new Set([
|
|
325
|
+
"xMin",
|
|
326
|
+
"xMax",
|
|
327
|
+
"yMin",
|
|
328
|
+
"yMax",
|
|
329
|
+
"zMin",
|
|
330
|
+
"zMax"
|
|
331
|
+
]);
|
|
332
|
+
/**
|
|
333
|
+
* Keys in an `expected` block that the CLI does not understand and would silently ignore — a
|
|
334
|
+
* `{ min: [...], max: [...] }` or `{ x: [...] }` bounds shape, or a misspelled top-level field.
|
|
335
|
+
* Surfaced as an error (not dropped) so a wrong `expected` shape fails loud instead of passing
|
|
336
|
+
* vacuously with the intended assertion never run.
|
|
337
|
+
*/
|
|
338
|
+
function unknownExpectedKeys(expected) {
|
|
339
|
+
const bad = [];
|
|
340
|
+
for (const k of Object.keys(expected)) if (!TOP_LEVEL_KEYS.has(k)) bad.push(k);
|
|
341
|
+
const bounds = expected.bounds;
|
|
342
|
+
if (bounds && typeof bounds === "object") {
|
|
343
|
+
for (const k of Object.keys(bounds)) if (!BOUND_KEYS.has(k)) bad.push(`bounds.${k}`);
|
|
344
|
+
}
|
|
345
|
+
return bad;
|
|
346
|
+
}
|
|
305
347
|
function isExpectedDims(v) {
|
|
306
348
|
if (typeof v !== "object" || v === null) return false;
|
|
307
349
|
const r = v;
|
|
@@ -425,6 +467,25 @@ var COMPILER_OPTIONS = {
|
|
|
425
467
|
skipLibCheck: true,
|
|
426
468
|
allowImportingTsExtensions: true
|
|
427
469
|
};
|
|
470
|
+
/**
|
|
471
|
+
* Locate the `@types/node` declarations so a part may import Node built-ins (`node:fs` to load a
|
|
472
|
+
* font, `node:fs/promises` to read a STEP file, etc.) without `--check` failing on the import.
|
|
473
|
+
* Returns the `@types` directory to use as a `typeRoots` entry. Probes the tool's own install
|
|
474
|
+
* first (where `@types/node` ships as a dependency), then the part's directory.
|
|
475
|
+
*/
|
|
476
|
+
function nodeTypesRoot(partPath, toolDir) {
|
|
477
|
+
const froms = [
|
|
478
|
+
import.meta.url,
|
|
479
|
+
toolDir ? pathToFileURL(resolve(toolDir, "package.json")).href : void 0,
|
|
480
|
+
pathToFileURL(partPath).href
|
|
481
|
+
];
|
|
482
|
+
for (const from of froms) {
|
|
483
|
+
if (!from) continue;
|
|
484
|
+
try {
|
|
485
|
+
return dirname(dirname(createRequire(from).resolve("@types/node/package.json")));
|
|
486
|
+
} catch {}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
428
489
|
function diagnosticToErrorInfo(d) {
|
|
429
490
|
const text = ts.flattenDiagnosticMessageText(d.messageText, "\n");
|
|
430
491
|
let where = "";
|
|
@@ -449,6 +510,11 @@ function typecheckPart(partPath, toolDir) {
|
|
|
449
510
|
const dts = resolveBrepjsTypes(partPath, toolDir);
|
|
450
511
|
const options = { ...COMPILER_OPTIONS };
|
|
451
512
|
if (dts) options.paths = { brepjs: [dts] };
|
|
513
|
+
const typesRoot = nodeTypesRoot(partPath, toolDir);
|
|
514
|
+
if (typesRoot) {
|
|
515
|
+
options.typeRoots = [typesRoot];
|
|
516
|
+
options.types = ["node"];
|
|
517
|
+
}
|
|
452
518
|
const program = ts.createProgram([partPath], options);
|
|
453
519
|
const errors = [
|
|
454
520
|
...program.getSemanticDiagnostics(),
|
|
@@ -485,7 +551,13 @@ function toErrorInfo(prefix, e) {
|
|
|
485
551
|
code: e.code,
|
|
486
552
|
suggestion: e.suggestion
|
|
487
553
|
};
|
|
488
|
-
if (e instanceof Error)
|
|
554
|
+
if (e instanceof Error) {
|
|
555
|
+
const code = e.message.match(/\[[A-Z][A-Z0-9_]*\]\s+([A-Z][A-Z0-9_]+):/)?.[1];
|
|
556
|
+
return code ? {
|
|
557
|
+
message: `${prefix}: ${e.message}`,
|
|
558
|
+
code
|
|
559
|
+
} : { message: `${prefix}: ${e.message}` };
|
|
560
|
+
}
|
|
489
561
|
return { message: `${prefix}: ${String(e)}` };
|
|
490
562
|
}
|
|
491
563
|
function finalize(result) {
|
|
@@ -565,6 +637,11 @@ async function runPart(modulePath, opts = {}) {
|
|
|
565
637
|
if (isExpectedDims(mod.expected)) {
|
|
566
638
|
const expected = mod.expected;
|
|
567
639
|
result.assertions = evaluateExpected(expected, result.measurements);
|
|
640
|
+
const unknown = unknownExpectedKeys(expected);
|
|
641
|
+
if (unknown.length > 0) pushError(result, {
|
|
642
|
+
message: `expected has unrecognized keys (ignored): ${unknown.join(", ")}. Valid keys: volume, area, tolerancePct, bounds.{xMin,xMax,yMin,yMax,zMin,zMax}.`,
|
|
643
|
+
code: "EXPECTED_UNKNOWN_KEY"
|
|
644
|
+
});
|
|
568
645
|
}
|
|
569
646
|
let glb;
|
|
570
647
|
let step;
|
|
@@ -16,8 +16,23 @@ export interface ExpectedDims {
|
|
|
16
16
|
tolerancePct?: number;
|
|
17
17
|
}
|
|
18
18
|
export declare const DEFAULT_TOLERANCE_PCT = 0.5;
|
|
19
|
+
/**
|
|
20
|
+
* Absolute slack (mm / mm² / mm³) below which a deviation always passes, independent of
|
|
21
|
+
* percent tolerance. Kernel coordinates carry sub-nanometer float noise (e.g. a loft base
|
|
22
|
+
* lands at z = -1e-7, not 0), so a percent comparison against an expected `0` — where any
|
|
23
|
+
* nonzero deviation is infinite percent — would make a zero-valued bound or measurement
|
|
24
|
+
* impossible to assert. 1e-6 is far above that noise and far below any real feature size.
|
|
25
|
+
*/
|
|
26
|
+
export declare const ABS_EPSILON = 0.000001;
|
|
19
27
|
/** Percent deviation of `actual` from `expected`; 0 expected matches only 0 actual. */
|
|
20
28
|
export declare function pctDelta(actual: number, expected: number): number;
|
|
29
|
+
/**
|
|
30
|
+
* Keys in an `expected` block that the CLI does not understand and would silently ignore — a
|
|
31
|
+
* `{ min: [...], max: [...] }` or `{ x: [...] }` bounds shape, or a misspelled top-level field.
|
|
32
|
+
* Surfaced as an error (not dropped) so a wrong `expected` shape fails loud instead of passing
|
|
33
|
+
* vacuously with the intended assertion never run.
|
|
34
|
+
*/
|
|
35
|
+
export declare function unknownExpectedKeys(expected: object): string[];
|
|
21
36
|
export declare function isExpectedDims(v: unknown): v is ExpectedDims;
|
|
22
37
|
/**
|
|
23
38
|
* Compare measured dimensions against a part's `expected` export. Each declared field becomes one
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brepjs-verify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Agent skill + verify/preview tooling for authoring parametric brepjs CAD code",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -34,12 +34,13 @@
|
|
|
34
34
|
"files": [
|
|
35
35
|
"dist",
|
|
36
36
|
"viewer/dist",
|
|
37
|
+
"reference",
|
|
37
38
|
"CHANGELOG.md",
|
|
38
39
|
"LICENSE",
|
|
39
40
|
"README.md"
|
|
40
41
|
],
|
|
41
42
|
"scripts": {
|
|
42
|
-
"build": "vite build && vite build --config viewer/vite.config.ts",
|
|
43
|
+
"build": "node scripts/copyReference.mjs && vite build && vite build --config viewer/vite.config.ts",
|
|
43
44
|
"typecheck": "tsc --noEmit && tsc -p viewer/tsconfig.json --noEmit && tsc -p bench/tsconfig.json",
|
|
44
45
|
"lint": "eslint src tests viewer bench",
|
|
45
46
|
"test": "vitest run",
|
|
@@ -50,6 +51,7 @@
|
|
|
50
51
|
"prepack": "npm run build"
|
|
51
52
|
},
|
|
52
53
|
"dependencies": {
|
|
54
|
+
"@types/node": "^25.9.1",
|
|
53
55
|
"brepjs": "^18.0.0",
|
|
54
56
|
"commander": "^13.0.0",
|
|
55
57
|
"occt-wasm": "^3.0.0",
|