brepjs-cad 0.29.0 → 0.31.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 +70 -0
- package/dist/{brepjs-verify.cjs → brepjs-cad.cjs} +1 -1
- package/dist/{brepjs-verify.js → brepjs-cad.js} +1 -1
- package/dist/cli/main.cjs +83 -7
- package/dist/cli/main.js +83 -7
- package/dist/{diff-kQJXMzLR.cjs → diff-DhOTZnG_.cjs} +227 -22
- package/dist/{diff-DcKUadBa.js → diff-MBAc87Xi.js} +227 -22
- package/dist/mcp/server.cjs +2 -2
- package/dist/mcp/server.js +2 -2
- package/dist/sandbox/runProgram.d.ts +2 -0
- package/dist/snapshot/aiming.d.ts +57 -0
- package/dist/snapshot/registry.cjs +1 -1
- package/dist/snapshot/registry.js +1 -1
- package/dist/snapshot/shoot.cjs +46 -11
- package/dist/snapshot/shoot.d.ts +17 -1
- package/dist/snapshot/shoot.js +46 -11
- package/dist/snapshot/static.cjs +1 -1
- package/dist/snapshot/static.d.ts +1 -1
- package/dist/snapshot/static.js +1 -1
- package/dist/verify/checks.d.ts +7 -1
- package/dist/verify/manufacturability.d.ts +11 -0
- package/dist/verify/report.d.ts +59 -0
- package/dist/verify/runPart.d.ts +7 -0
- package/package.json +7 -7
- package/viewer/dist/assets/{brepjs-uHg2lsd8.js → brepjs-1Enzw6vj.js} +3 -3
- package/viewer/dist/assets/index-D00Hjy2q.js +4204 -0
- package/viewer/dist/assets/{kernelWorker-DrYQAV_l.js → kernelWorker-ynmKsxiQ.js} +1 -1
- package/viewer/dist/index.html +1 -1
- package/viewer/dist/assets/index-y1-v1YEX.js +0 -4167
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.31.0](https://github.com/andymai/brepjs/compare/brepjs-cad-v0.30.1...brepjs-cad-v0.31.0) (2026-06-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **brepjs-cad:** add airfoils.md feature recipe (swept fans/props/impellers) ([#1566](https://github.com/andymai/brepjs/issues/1566)) ([8c786db](https://github.com/andymai/brepjs/commit/8c786db69ead59edcdc9d0f8525e43324552e4db))
|
|
9
|
+
* **brepjs-cad:** aimed section cut for the design judge (Phase 3) ([#1543](https://github.com/andymai/brepjs/issues/1543)) ([40e5acd](https://github.com/andymai/brepjs/commit/40e5acd54318d768dc5a620403d17d43e358e698))
|
|
10
|
+
* **brepjs-cad:** CLI subcommands + verify hints + gridfinity examples + eval harness ([#1204](https://github.com/andymai/brepjs/issues/1204)) ([4d57198](https://github.com/andymai/brepjs/commit/4d5719874b5f5e685a4f909fd2d2363c0331770b))
|
|
11
|
+
* **brepjs-cad:** decomposed, cross-checked design-judge rubric (Phase 1.5) ([#1539](https://github.com/andymai/brepjs/issues/1539)) ([8059b6d](https://github.com/andymai/brepjs/commit/8059b6d701ae5980e6bb11f51695aa102fe2bb43))
|
|
12
|
+
* **brepjs-cad:** deterministic body/interference metrics for the design judge (Phase 1) ([#1531](https://github.com/andymai/brepjs/issues/1531)) ([d296b54](https://github.com/andymai/brepjs/commit/d296b545f2d7084b861683d61b626ace4747a371))
|
|
13
|
+
* **brepjs-cad:** kernel-anchored Set-of-Marks for the design judge ([#1545](https://github.com/andymai/brepjs/issues/1545)) ([2b6f5b4](https://github.com/andymai/brepjs/commit/2b6f5b436f2a73c96747cc71f83afc8715765cd0))
|
|
14
|
+
* **brepjs-cad:** reliable internal-bore detection for the design judge (keystone) ([#1542](https://github.com/andymai/brepjs/issues/1542)) ([0d780c3](https://github.com/andymai/brepjs/commit/0d780c3b73c2551dab2f04a6ff31bf9ec8cae2ab))
|
|
15
|
+
* **brepjs-cad:** rename from brepjs-agent + make npm-publishable (publish held) ([#1201](https://github.com/andymai/brepjs/issues/1201)) ([630bbba](https://github.com/andymai/brepjs/commit/630bbbab4885604bd4d5fb2148584a6572c8d99c))
|
|
16
|
+
* **brepjs-cad:** surface fragmentation in verify --check (the [#1](https://github.com/andymai/brepjs/issues/1) design defect) ([#1560](https://github.com/andymai/brepjs/issues/1560)) ([45a4f6e](https://github.com/andymai/brepjs/commit/45a4f6e268331b7816cd9957fbdab4c0893b2000))
|
|
17
|
+
* **brepjs-cad:** xray internal-reveal shot for the design judge (Phase 2a) ([#1540](https://github.com/andymai/brepjs/issues/1540)) ([eca5bc9](https://github.com/andymai/brepjs/commit/eca5bc9ad20fc7947132d647952245cfe466a7f4))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **brepjs-cad:** add a triangular-gusset recipe to the implement skill (bracket/enclosure eval) ([#1571](https://github.com/andymai/brepjs/issues/1571)) ([346d042](https://github.com/andymai/brepjs/commit/346d0423fefa3bd163f4075f69bf96d478543bf5))
|
|
23
|
+
* **brepjs-cad:** add the "realize the designed object" bar to the implement skill ([#1563](https://github.com/andymai/brepjs/issues/1563)) ([e150357](https://github.com/andymai/brepjs/commit/e1503570aaf271ebef1e39d48be9c70a5ffe8f03))
|
|
24
|
+
* **brepjs-cad:** close gear-teeth edge cases found by /eval-skill (ring, worm tip relief, GT2) ([#1548](https://github.com/andymai/brepjs/issues/1548)) ([4bd0494](https://github.com/andymai/brepjs/commit/4bd049401f3affcc3f38e3a31bb9520653a3e89c))
|
|
25
|
+
* **brepjs-cad:** code + hint the degenerate-edge (duplicate-vertex) verify failure ([#1550](https://github.com/andymai/brepjs/issues/1550)) ([502dffc](https://github.com/andymai/brepjs/commit/502dffc4a2ae495ae5c98b0c7966721abe0d5f48))
|
|
26
|
+
* **brepjs-cad:** correct spur-gear example flanks + add root fillet ([#1528](https://github.com/andymai/brepjs/issues/1528)) ([6971c6b](https://github.com/andymai/brepjs/commit/6971c6befa1fea36a8c2f3ee89c4aa20946020c7))
|
|
27
|
+
* **brepjs-cad:** exploded-joint legibility + disjoint-compound caveat (basics eval) ([#1565](https://github.com/andymai/brepjs/issues/1565)) ([9d06121](https://github.com/andymai/brepjs/commit/9d0612111a595e57fcfca6fd191ed9169fc2c062))
|
|
28
|
+
* **brepjs-cad:** handle brepjs/playground refs + summarize body relations in the digest ([#1547](https://github.com/andymai/brepjs/issues/1547)) ([b0acef0](https://github.com/andymai/brepjs/commit/b0acef0ad80cdd61f0d2683f1e6d0ece0cae028e))
|
|
29
|
+
* **brepjs-cad:** heal 6 implement-skill findings from the full-flywheel re-run ([#1568](https://github.com/andymai/brepjs/issues/1568)) ([f63bf3d](https://github.com/andymai/brepjs/commit/f63bf3d5a0aa638d06e11dd7e2c27e84dbf74746))
|
|
30
|
+
* **brepjs-cad:** heal implement + polish skills from clean-room eval ([#1526](https://github.com/andymai/brepjs/issues/1526)) ([0645e16](https://github.com/andymai/brepjs/commit/0645e163e1d8759c95406d0f9526d0aa3b5dd480))
|
|
31
|
+
* **brepjs-cad:** heal implement skill — deep-stack bounds extremes aren't datums ([#1529](https://github.com/andymai/brepjs/issues/1529)) ([5ed366f](https://github.com/andymai/brepjs/commit/5ed366f266b3e6e50ae4b54d5779aa05453e894a))
|
|
32
|
+
* **brepjs-cad:** heal implement skill from the eval flywheel (3 findings) ([#1552](https://github.com/andymai/brepjs/issues/1552)) ([51def82](https://github.com/andymai/brepjs/commit/51def82db4e0600e85f45e4dd828cc9caee58d15))
|
|
33
|
+
* **brepjs-cad:** heal implement skill from the full-corpus eval flywheel (4 findings) ([#1554](https://github.com/andymai/brepjs/issues/1554)) ([3cfc28e](https://github.com/andymai/brepjs/commit/3cfc28ed8b82c46330f1d75f1e98c13fd4d65a06))
|
|
34
|
+
* **brepjs-cad:** load .ts parts via native type-stripping ([#1207](https://github.com/andymai/brepjs/issues/1207)) ([198078b](https://github.com/andymai/brepjs/commit/198078becf570614c0cbf61537714fc94c2de43a))
|
|
35
|
+
* **brepjs-cad:** make blind-judge reference adaptation render multi-body parts at scale ([#1530](https://github.com/andymai/brepjs/issues/1530)) ([18d4523](https://github.com/andymai/brepjs/commit/18d4523c85e1b22496bb5c0b8fb382a1146429c6))
|
|
36
|
+
* **brepjs-cad:** polish skill — bosses on shells must fuse, or they float (eval finding) ([#1553](https://github.com/andymai/brepjs/issues/1553)) ([07cbf93](https://github.com/andymai/brepjs/commit/07cbf93e47fbf880df53bc2a1cee05bf0d17e2d5))
|
|
37
|
+
* **brepjs-cad:** run CLI via bin symlink + quality pass ([#1206](https://github.com/andymai/brepjs/issues/1206)) ([ac5b1fe](https://github.com/andymai/brepjs/commit/ac5b1feee3c5b424c37716ca06c397f7898838f1))
|
|
38
|
+
* **brepjs-cad:** teach worm-wheel and rack tooth recipes; fix gear-build contradiction ([#1544](https://github.com/andymai/brepjs/issues/1544)) ([b0da85f](https://github.com/andymai/brepjs/commit/b0da85f218d463e0f1ef0ca8760cec54b4814b02))
|
|
39
|
+
|
|
40
|
+
## [0.30.0](https://github.com/andymai/brepjs/compare/brepjs-cad-v0.29.0...brepjs-cad-v0.30.0) (2026-06-22)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### Features
|
|
44
|
+
|
|
45
|
+
* **brepjs-cad:** add airfoils.md feature recipe (swept fans/props/impellers) ([#1566](https://github.com/andymai/brepjs/issues/1566)) ([8c786db](https://github.com/andymai/brepjs/commit/8c786db69ead59edcdc9d0f8525e43324552e4db))
|
|
46
|
+
* **brepjs-cad:** aimed section cut for the design judge (Phase 3) ([#1543](https://github.com/andymai/brepjs/issues/1543)) ([40e5acd](https://github.com/andymai/brepjs/commit/40e5acd54318d768dc5a620403d17d43e358e698))
|
|
47
|
+
* **brepjs-cad:** decomposed, cross-checked design-judge rubric (Phase 1.5) ([#1539](https://github.com/andymai/brepjs/issues/1539)) ([8059b6d](https://github.com/andymai/brepjs/commit/8059b6d701ae5980e6bb11f51695aa102fe2bb43))
|
|
48
|
+
* **brepjs-cad:** deterministic body/interference metrics for the design judge (Phase 1) ([#1531](https://github.com/andymai/brepjs/issues/1531)) ([d296b54](https://github.com/andymai/brepjs/commit/d296b545f2d7084b861683d61b626ace4747a371))
|
|
49
|
+
* **brepjs-cad:** kernel-anchored Set-of-Marks for the design judge ([#1545](https://github.com/andymai/brepjs/issues/1545)) ([2b6f5b4](https://github.com/andymai/brepjs/commit/2b6f5b436f2a73c96747cc71f83afc8715765cd0))
|
|
50
|
+
* **brepjs-cad:** reliable internal-bore detection for the design judge (keystone) ([#1542](https://github.com/andymai/brepjs/issues/1542)) ([0d780c3](https://github.com/andymai/brepjs/commit/0d780c3b73c2551dab2f04a6ff31bf9ec8cae2ab))
|
|
51
|
+
* **brepjs-cad:** surface fragmentation in verify --check (the [#1](https://github.com/andymai/brepjs/issues/1) design defect) ([#1560](https://github.com/andymai/brepjs/issues/1560)) ([45a4f6e](https://github.com/andymai/brepjs/commit/45a4f6e268331b7816cd9957fbdab4c0893b2000))
|
|
52
|
+
* **brepjs-cad:** xray internal-reveal shot for the design judge (Phase 2a) ([#1540](https://github.com/andymai/brepjs/issues/1540)) ([eca5bc9](https://github.com/andymai/brepjs/commit/eca5bc9ad20fc7947132d647952245cfe466a7f4))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
### Bug Fixes
|
|
56
|
+
|
|
57
|
+
* **brepjs-cad:** add a triangular-gusset recipe to the implement skill (bracket/enclosure eval) ([#1571](https://github.com/andymai/brepjs/issues/1571)) ([346d042](https://github.com/andymai/brepjs/commit/346d0423fefa3bd163f4075f69bf96d478543bf5))
|
|
58
|
+
* **brepjs-cad:** add the "realize the designed object" bar to the implement skill ([#1563](https://github.com/andymai/brepjs/issues/1563)) ([e150357](https://github.com/andymai/brepjs/commit/e1503570aaf271ebef1e39d48be9c70a5ffe8f03))
|
|
59
|
+
* **brepjs-cad:** close gear-teeth edge cases found by /eval-skill (ring, worm tip relief, GT2) ([#1548](https://github.com/andymai/brepjs/issues/1548)) ([4bd0494](https://github.com/andymai/brepjs/commit/4bd049401f3affcc3f38e3a31bb9520653a3e89c))
|
|
60
|
+
* **brepjs-cad:** code + hint the degenerate-edge (duplicate-vertex) verify failure ([#1550](https://github.com/andymai/brepjs/issues/1550)) ([502dffc](https://github.com/andymai/brepjs/commit/502dffc4a2ae495ae5c98b0c7966721abe0d5f48))
|
|
61
|
+
* **brepjs-cad:** correct spur-gear example flanks + add root fillet ([#1528](https://github.com/andymai/brepjs/issues/1528)) ([6971c6b](https://github.com/andymai/brepjs/commit/6971c6befa1fea36a8c2f3ee89c4aa20946020c7))
|
|
62
|
+
* **brepjs-cad:** exploded-joint legibility + disjoint-compound caveat (basics eval) ([#1565](https://github.com/andymai/brepjs/issues/1565)) ([9d06121](https://github.com/andymai/brepjs/commit/9d0612111a595e57fcfca6fd191ed9169fc2c062))
|
|
63
|
+
* **brepjs-cad:** handle brepjs/playground refs + summarize body relations in the digest ([#1547](https://github.com/andymai/brepjs/issues/1547)) ([b0acef0](https://github.com/andymai/brepjs/commit/b0acef0ad80cdd61f0d2683f1e6d0ece0cae028e))
|
|
64
|
+
* **brepjs-cad:** heal 6 implement-skill findings from the full-flywheel re-run ([#1568](https://github.com/andymai/brepjs/issues/1568)) ([f63bf3d](https://github.com/andymai/brepjs/commit/f63bf3d5a0aa638d06e11dd7e2c27e84dbf74746))
|
|
65
|
+
* **brepjs-cad:** heal implement + polish skills from clean-room eval ([#1526](https://github.com/andymai/brepjs/issues/1526)) ([0645e16](https://github.com/andymai/brepjs/commit/0645e163e1d8759c95406d0f9526d0aa3b5dd480))
|
|
66
|
+
* **brepjs-cad:** heal implement skill — deep-stack bounds extremes aren't datums ([#1529](https://github.com/andymai/brepjs/issues/1529)) ([5ed366f](https://github.com/andymai/brepjs/commit/5ed366f266b3e6e50ae4b54d5779aa05453e894a))
|
|
67
|
+
* **brepjs-cad:** heal implement skill from the eval flywheel (3 findings) ([#1552](https://github.com/andymai/brepjs/issues/1552)) ([51def82](https://github.com/andymai/brepjs/commit/51def82db4e0600e85f45e4dd828cc9caee58d15))
|
|
68
|
+
* **brepjs-cad:** heal implement skill from the full-corpus eval flywheel (4 findings) ([#1554](https://github.com/andymai/brepjs/issues/1554)) ([3cfc28e](https://github.com/andymai/brepjs/commit/3cfc28ed8b82c46330f1d75f1e98c13fd4d65a06))
|
|
69
|
+
* **brepjs-cad:** make blind-judge reference adaptation render multi-body parts at scale ([#1530](https://github.com/andymai/brepjs/issues/1530)) ([18d4523](https://github.com/andymai/brepjs/commit/18d4523c85e1b22496bb5c0b8fb382a1146429c6))
|
|
70
|
+
* **brepjs-cad:** polish skill — bosses on shells must fuse, or they float (eval finding) ([#1553](https://github.com/andymai/brepjs/issues/1553)) ([07cbf93](https://github.com/andymai/brepjs/commit/07cbf93e47fbf880df53bc2a1cee05bf0d17e2d5))
|
|
71
|
+
* **brepjs-cad:** teach worm-wheel and rack tooth recipes; fix gear-build contradiction ([#1544](https://github.com/andymai/brepjs/issues/1544)) ([b0da85f](https://github.com/andymai/brepjs/commit/b0da85f218d463e0f1ef0ca8760cec54b4814b02))
|
|
72
|
+
|
|
3
73
|
## [0.29.0](https://github.com/andymai/brepjs/compare/brepjs-cad-v0.28.0...brepjs-cad-v0.29.0) (2026-06-20)
|
|
4
74
|
|
|
5
75
|
|
|
@@ -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-DhOTZnG_.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;
|
|
@@ -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-MBAc87Xi.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-DhOTZnG_.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");
|
|
@@ -215,6 +215,67 @@ function openBrowser(url, platform = process.platform) {
|
|
|
215
215
|
} catch {}
|
|
216
216
|
}
|
|
217
217
|
//#endregion
|
|
218
|
+
//#region src/snapshot/aiming.ts
|
|
219
|
+
/**
|
|
220
|
+
* Kernel-anchored marks for the judge: `B<index>` at each body's bbox centroid (only for multi-body
|
|
221
|
+
* parts — a single body needs no label) and `H1..` at each bore's axis. The same id lands on the same
|
|
222
|
+
* feature across every view (it's a 3D anchor projected per-view), giving the judge view-invariant,
|
|
223
|
+
* part-space addressing without per-body mesh color.
|
|
224
|
+
*
|
|
225
|
+
* Body labels use the body's INDEX (0-based), matching how the measured-facts digest refers to bodies
|
|
226
|
+
* ("bodies 0&1: interfering"), so the judge can cross-reference a mark with the facts. A body that
|
|
227
|
+
* can't be located (no bounds) simply gets no mark — there is no resequenced gap.
|
|
228
|
+
*/
|
|
229
|
+
function featureMarks(bodies, bores) {
|
|
230
|
+
const marks = [];
|
|
231
|
+
if (bodies.length > 1) for (const b of bodies) {
|
|
232
|
+
if (!b.bounds) continue;
|
|
233
|
+
marks.push({
|
|
234
|
+
label: `B${b.index}`,
|
|
235
|
+
pos: [
|
|
236
|
+
(b.bounds.xMin + b.bounds.xMax) / 2,
|
|
237
|
+
(b.bounds.yMin + b.bounds.yMax) / 2,
|
|
238
|
+
(b.bounds.zMin + b.bounds.zMax) / 2
|
|
239
|
+
]
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
bores.forEach((bore, i) => {
|
|
243
|
+
marks.push({
|
|
244
|
+
label: `H${i + 1}`,
|
|
245
|
+
pos: bore.axisOrigin
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
return marks;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Aim a section cut through the dominant (largest-radius) bore: cut on the basis axis MOST
|
|
252
|
+
* perpendicular to the bore axis, positioned to pass THROUGH the bore origin — so the bore opens as
|
|
253
|
+
* a clean cross-section (reads wall thickness, where the xray is cluttered). Returns null when there
|
|
254
|
+
* are no bores or no bounds. Plain structural inputs keep this decoupled from the verify report.
|
|
255
|
+
*/
|
|
256
|
+
function aimedSection(bores, bounds) {
|
|
257
|
+
if (bores.length === 0 || !bounds) return null;
|
|
258
|
+
const bore = bores.reduce((a, b) => b.radius > a.radius ? b : a);
|
|
259
|
+
const d = bore.axisDir;
|
|
260
|
+
const perp = {
|
|
261
|
+
x: Math.abs(d[0]),
|
|
262
|
+
y: Math.abs(d[1]),
|
|
263
|
+
z: Math.abs(d[2])
|
|
264
|
+
};
|
|
265
|
+
const axis = [
|
|
266
|
+
"x",
|
|
267
|
+
"y",
|
|
268
|
+
"z"
|
|
269
|
+
].reduce((a, b) => perp[b] < perp[a] ? b : a);
|
|
270
|
+
const i = axis === "x" ? 0 : axis === "y" ? 1 : 2;
|
|
271
|
+
const min = axis === "x" ? bounds.xMin : axis === "y" ? bounds.yMin : bounds.zMin;
|
|
272
|
+
const span = (axis === "x" ? bounds.xMax : axis === "y" ? bounds.yMax : bounds.zMax) - min || 1;
|
|
273
|
+
return {
|
|
274
|
+
axis,
|
|
275
|
+
frac: Math.min(1, Math.max(0, (bore.axisOrigin[i] - min) / span))
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
//#endregion
|
|
218
279
|
//#region src/cli/main.ts
|
|
219
280
|
console.log = (...args) => {
|
|
220
281
|
process.stderr.write(args.map(String).join(" ") + "\n");
|
|
@@ -230,7 +291,7 @@ async function loadSnapshotShoot() {
|
|
|
230
291
|
}
|
|
231
292
|
var program = new commander.Command();
|
|
232
293
|
program.name("brep");
|
|
233
|
-
program.command("verify", { isDefault: true }).argument("<files...>", "path(s) or glob(s) to .brep.ts modules; multiple files → a batch validity JSON array").option("--step <out>", "write the primary STEP artifact to this path").option("--glb <out>", "write a derived GLB preview to this path").option("--json <out>", "write the JSON report to this path").option("--check", "type-check the part (against brepjs types) before running; skip execution on type errors").option("--snapshot <dir>", "render iso/front/top/right PNGs to this dir (requires built viewer)").option("--serve", "after verifying, start a preview server and print a ?dir=&file= deep link (stays running)").option("--no-open", "with --serve, do not auto-open the browser (just print the viewer URL)").option("--expect-code <code>", "exit 0 only if the report emits this error code (for fixtures/eval recall)").option("--expect-invalid", "exit 0 only if the part is invalid (ok:false) — for known-bad fixtures").action(async (files, opts) => {
|
|
294
|
+
program.command("verify", { isDefault: true }).argument("<files...>", "path(s) or glob(s) to .brep.ts modules; multiple files → a batch validity JSON array").option("--step <out>", "write the primary STEP artifact to this path").option("--glb <out>", "write a derived GLB preview to this path").option("--json <out>", "write the JSON report to this path").option("--check", "type-check the part (against brepjs types) before running; skip execution on type errors").option("--snapshot <dir>", "render iso/front/top/right PNGs to this dir (requires built viewer)").option("--serve", "after verifying, start a preview server and print a ?dir=&file= deep link (stays running)").option("--no-open", "with --serve, do not auto-open the browser (just print the viewer URL)").option("--expect-code <code>", "exit 0 only if the report emits this error code (for fixtures/eval recall)").option("--expect-invalid", "exit 0 only if the part is invalid (ok:false) — for known-bad fixtures").option("--metrics", "compute deterministic manufacturability metrics (per-body breakdown + interference matrix) for the design judge — slower; off by default").action(async (files, opts) => {
|
|
234
295
|
const targets = [...new Set(files.flatMap((f) => {
|
|
235
296
|
const m = (0, node_fs.globSync)(f);
|
|
236
297
|
return m.length ? m : [f];
|
|
@@ -239,7 +300,10 @@ program.command("verify", { isDefault: true }).argument("<files...>", "path(s) o
|
|
|
239
300
|
if (opts.step || opts.serve || opts.snapshot || opts.glb || opts.expectCode || opts.expectInvalid) process.stderr.write("batch mode: --step/--glb/--serve/--snapshot/--expect-code/--expect-invalid ignored (single-file only)\n");
|
|
240
301
|
const results = [];
|
|
241
302
|
for (const f of targets) {
|
|
242
|
-
const { report, shape } = await require_diff.runPart(f, {
|
|
303
|
+
const { report, shape } = await require_diff.runPart(f, {
|
|
304
|
+
check: Boolean(opts.check),
|
|
305
|
+
metrics: Boolean(opts.metrics)
|
|
306
|
+
});
|
|
243
307
|
disposeShape(shape);
|
|
244
308
|
results.push({
|
|
245
309
|
file: f,
|
|
@@ -258,7 +322,8 @@ program.command("verify", { isDefault: true }).argument("<files...>", "path(s) o
|
|
|
258
322
|
const { report, step, glb, shape } = await require_diff.runPart((0, node_path.resolve)(file), {
|
|
259
323
|
step: wantStep,
|
|
260
324
|
glb: Boolean(opts.glb),
|
|
261
|
-
check: Boolean(opts.check)
|
|
325
|
+
check: Boolean(opts.check),
|
|
326
|
+
metrics: Boolean(opts.metrics) || Boolean(opts.snapshot)
|
|
262
327
|
});
|
|
263
328
|
let stepPath = opts.step;
|
|
264
329
|
try {
|
|
@@ -270,9 +335,13 @@ program.command("verify", { isDefault: true }).argument("<files...>", "path(s) o
|
|
|
270
335
|
if (opts.snapshot && stepPath) {
|
|
271
336
|
const shoot = await loadSnapshotShoot();
|
|
272
337
|
if (shoot) {
|
|
338
|
+
const section = aimedSection(report.manufacturability?.bores ?? [], report.measurements.bounds);
|
|
339
|
+
const marks = featureMarks(report.bodies ?? [], report.manufacturability?.bores ?? []);
|
|
273
340
|
const { pngs } = await shoot({
|
|
274
341
|
file: stepPath,
|
|
275
|
-
outDir: opts.snapshot
|
|
342
|
+
outDir: opts.snapshot,
|
|
343
|
+
...section ? { section } : {},
|
|
344
|
+
...marks.length > 0 ? { marks } : {}
|
|
276
345
|
});
|
|
277
346
|
for (const p of pngs) process.stderr.write(`snapshot: ${p}\n`);
|
|
278
347
|
}
|
|
@@ -321,7 +390,10 @@ program.command("snapshot").argument("<file>", "path to a .brep.ts module; rende
|
|
|
321
390
|
const resolved = (0, node_path.resolve)(file);
|
|
322
391
|
const base = opts.out ? (0, node_path.resolve)(opts.out) : `${resolved}-shots`;
|
|
323
392
|
const outDir = opts.label ? (0, node_path.join)(base, opts.label) : base;
|
|
324
|
-
const { report, step, shape } = await require_diff.runPart(resolved, {
|
|
393
|
+
const { report, step, shape } = await require_diff.runPart(resolved, {
|
|
394
|
+
step: true,
|
|
395
|
+
metrics: true
|
|
396
|
+
});
|
|
325
397
|
try {
|
|
326
398
|
if (!step) {
|
|
327
399
|
process.stderr.write("snapshot: part produced no STEP — nothing to render\n");
|
|
@@ -336,10 +408,14 @@ program.command("snapshot").argument("<file>", "path to a .brep.ts module; rende
|
|
|
336
408
|
process.stdout.write(require_diff.serializeReport(report) + "\n");
|
|
337
409
|
return;
|
|
338
410
|
}
|
|
411
|
+
const section = aimedSection(report.manufacturability?.bores ?? [], report.measurements.bounds);
|
|
412
|
+
const marks = featureMarks(report.bodies ?? [], report.manufacturability?.bores ?? []);
|
|
339
413
|
const { pngs } = await shoot({
|
|
340
414
|
file: stepPath,
|
|
341
415
|
outDir,
|
|
342
|
-
fresh: true
|
|
416
|
+
fresh: true,
|
|
417
|
+
...section ? { section } : {},
|
|
418
|
+
...marks.length > 0 ? { marks } : {}
|
|
343
419
|
});
|
|
344
420
|
for (const p of pngs) process.stdout.write(`${p}\n`);
|
|
345
421
|
} finally {
|
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-MBAc87Xi.js";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { existsSync, globSync, mkdirSync, realpathSync, watch, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
@@ -214,6 +214,67 @@ function openBrowser(url, platform = process.platform) {
|
|
|
214
214
|
} catch {}
|
|
215
215
|
}
|
|
216
216
|
//#endregion
|
|
217
|
+
//#region src/snapshot/aiming.ts
|
|
218
|
+
/**
|
|
219
|
+
* Kernel-anchored marks for the judge: `B<index>` at each body's bbox centroid (only for multi-body
|
|
220
|
+
* parts — a single body needs no label) and `H1..` at each bore's axis. The same id lands on the same
|
|
221
|
+
* feature across every view (it's a 3D anchor projected per-view), giving the judge view-invariant,
|
|
222
|
+
* part-space addressing without per-body mesh color.
|
|
223
|
+
*
|
|
224
|
+
* Body labels use the body's INDEX (0-based), matching how the measured-facts digest refers to bodies
|
|
225
|
+
* ("bodies 0&1: interfering"), so the judge can cross-reference a mark with the facts. A body that
|
|
226
|
+
* can't be located (no bounds) simply gets no mark — there is no resequenced gap.
|
|
227
|
+
*/
|
|
228
|
+
function featureMarks(bodies, bores) {
|
|
229
|
+
const marks = [];
|
|
230
|
+
if (bodies.length > 1) for (const b of bodies) {
|
|
231
|
+
if (!b.bounds) continue;
|
|
232
|
+
marks.push({
|
|
233
|
+
label: `B${b.index}`,
|
|
234
|
+
pos: [
|
|
235
|
+
(b.bounds.xMin + b.bounds.xMax) / 2,
|
|
236
|
+
(b.bounds.yMin + b.bounds.yMax) / 2,
|
|
237
|
+
(b.bounds.zMin + b.bounds.zMax) / 2
|
|
238
|
+
]
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
bores.forEach((bore, i) => {
|
|
242
|
+
marks.push({
|
|
243
|
+
label: `H${i + 1}`,
|
|
244
|
+
pos: bore.axisOrigin
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
return marks;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Aim a section cut through the dominant (largest-radius) bore: cut on the basis axis MOST
|
|
251
|
+
* perpendicular to the bore axis, positioned to pass THROUGH the bore origin — so the bore opens as
|
|
252
|
+
* a clean cross-section (reads wall thickness, where the xray is cluttered). Returns null when there
|
|
253
|
+
* are no bores or no bounds. Plain structural inputs keep this decoupled from the verify report.
|
|
254
|
+
*/
|
|
255
|
+
function aimedSection(bores, bounds) {
|
|
256
|
+
if (bores.length === 0 || !bounds) return null;
|
|
257
|
+
const bore = bores.reduce((a, b) => b.radius > a.radius ? b : a);
|
|
258
|
+
const d = bore.axisDir;
|
|
259
|
+
const perp = {
|
|
260
|
+
x: Math.abs(d[0]),
|
|
261
|
+
y: Math.abs(d[1]),
|
|
262
|
+
z: Math.abs(d[2])
|
|
263
|
+
};
|
|
264
|
+
const axis = [
|
|
265
|
+
"x",
|
|
266
|
+
"y",
|
|
267
|
+
"z"
|
|
268
|
+
].reduce((a, b) => perp[b] < perp[a] ? b : a);
|
|
269
|
+
const i = axis === "x" ? 0 : axis === "y" ? 1 : 2;
|
|
270
|
+
const min = axis === "x" ? bounds.xMin : axis === "y" ? bounds.yMin : bounds.zMin;
|
|
271
|
+
const span = (axis === "x" ? bounds.xMax : axis === "y" ? bounds.yMax : bounds.zMax) - min || 1;
|
|
272
|
+
return {
|
|
273
|
+
axis,
|
|
274
|
+
frac: Math.min(1, Math.max(0, (bore.axisOrigin[i] - min) / span))
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
//#endregion
|
|
217
278
|
//#region src/cli/main.ts
|
|
218
279
|
console.log = (...args) => {
|
|
219
280
|
process.stderr.write(args.map(String).join(" ") + "\n");
|
|
@@ -229,7 +290,7 @@ async function loadSnapshotShoot() {
|
|
|
229
290
|
}
|
|
230
291
|
var program = new Command();
|
|
231
292
|
program.name("brep");
|
|
232
|
-
program.command("verify", { isDefault: true }).argument("<files...>", "path(s) or glob(s) to .brep.ts modules; multiple files → a batch validity JSON array").option("--step <out>", "write the primary STEP artifact to this path").option("--glb <out>", "write a derived GLB preview to this path").option("--json <out>", "write the JSON report to this path").option("--check", "type-check the part (against brepjs types) before running; skip execution on type errors").option("--snapshot <dir>", "render iso/front/top/right PNGs to this dir (requires built viewer)").option("--serve", "after verifying, start a preview server and print a ?dir=&file= deep link (stays running)").option("--no-open", "with --serve, do not auto-open the browser (just print the viewer URL)").option("--expect-code <code>", "exit 0 only if the report emits this error code (for fixtures/eval recall)").option("--expect-invalid", "exit 0 only if the part is invalid (ok:false) — for known-bad fixtures").action(async (files, opts) => {
|
|
293
|
+
program.command("verify", { isDefault: true }).argument("<files...>", "path(s) or glob(s) to .brep.ts modules; multiple files → a batch validity JSON array").option("--step <out>", "write the primary STEP artifact to this path").option("--glb <out>", "write a derived GLB preview to this path").option("--json <out>", "write the JSON report to this path").option("--check", "type-check the part (against brepjs types) before running; skip execution on type errors").option("--snapshot <dir>", "render iso/front/top/right PNGs to this dir (requires built viewer)").option("--serve", "after verifying, start a preview server and print a ?dir=&file= deep link (stays running)").option("--no-open", "with --serve, do not auto-open the browser (just print the viewer URL)").option("--expect-code <code>", "exit 0 only if the report emits this error code (for fixtures/eval recall)").option("--expect-invalid", "exit 0 only if the part is invalid (ok:false) — for known-bad fixtures").option("--metrics", "compute deterministic manufacturability metrics (per-body breakdown + interference matrix) for the design judge — slower; off by default").action(async (files, opts) => {
|
|
233
294
|
const targets = [...new Set(files.flatMap((f) => {
|
|
234
295
|
const m = globSync(f);
|
|
235
296
|
return m.length ? m : [f];
|
|
@@ -238,7 +299,10 @@ program.command("verify", { isDefault: true }).argument("<files...>", "path(s) o
|
|
|
238
299
|
if (opts.step || opts.serve || opts.snapshot || opts.glb || opts.expectCode || opts.expectInvalid) process.stderr.write("batch mode: --step/--glb/--serve/--snapshot/--expect-code/--expect-invalid ignored (single-file only)\n");
|
|
239
300
|
const results = [];
|
|
240
301
|
for (const f of targets) {
|
|
241
|
-
const { report, shape } = await runPart(f, {
|
|
302
|
+
const { report, shape } = await runPart(f, {
|
|
303
|
+
check: Boolean(opts.check),
|
|
304
|
+
metrics: Boolean(opts.metrics)
|
|
305
|
+
});
|
|
242
306
|
disposeShape(shape);
|
|
243
307
|
results.push({
|
|
244
308
|
file: f,
|
|
@@ -257,7 +321,8 @@ program.command("verify", { isDefault: true }).argument("<files...>", "path(s) o
|
|
|
257
321
|
const { report, step, glb, shape } = await runPart(resolve(file), {
|
|
258
322
|
step: wantStep,
|
|
259
323
|
glb: Boolean(opts.glb),
|
|
260
|
-
check: Boolean(opts.check)
|
|
324
|
+
check: Boolean(opts.check),
|
|
325
|
+
metrics: Boolean(opts.metrics) || Boolean(opts.snapshot)
|
|
261
326
|
});
|
|
262
327
|
let stepPath = opts.step;
|
|
263
328
|
try {
|
|
@@ -269,9 +334,13 @@ program.command("verify", { isDefault: true }).argument("<files...>", "path(s) o
|
|
|
269
334
|
if (opts.snapshot && stepPath) {
|
|
270
335
|
const shoot = await loadSnapshotShoot();
|
|
271
336
|
if (shoot) {
|
|
337
|
+
const section = aimedSection(report.manufacturability?.bores ?? [], report.measurements.bounds);
|
|
338
|
+
const marks = featureMarks(report.bodies ?? [], report.manufacturability?.bores ?? []);
|
|
272
339
|
const { pngs } = await shoot({
|
|
273
340
|
file: stepPath,
|
|
274
|
-
outDir: opts.snapshot
|
|
341
|
+
outDir: opts.snapshot,
|
|
342
|
+
...section ? { section } : {},
|
|
343
|
+
...marks.length > 0 ? { marks } : {}
|
|
275
344
|
});
|
|
276
345
|
for (const p of pngs) process.stderr.write(`snapshot: ${p}\n`);
|
|
277
346
|
}
|
|
@@ -320,7 +389,10 @@ program.command("snapshot").argument("<file>", "path to a .brep.ts module; rende
|
|
|
320
389
|
const resolved = resolve(file);
|
|
321
390
|
const base = opts.out ? resolve(opts.out) : `${resolved}-shots`;
|
|
322
391
|
const outDir = opts.label ? join(base, opts.label) : base;
|
|
323
|
-
const { report, step, shape } = await runPart(resolved, {
|
|
392
|
+
const { report, step, shape } = await runPart(resolved, {
|
|
393
|
+
step: true,
|
|
394
|
+
metrics: true
|
|
395
|
+
});
|
|
324
396
|
try {
|
|
325
397
|
if (!step) {
|
|
326
398
|
process.stderr.write("snapshot: part produced no STEP — nothing to render\n");
|
|
@@ -335,10 +407,14 @@ program.command("snapshot").argument("<file>", "path to a .brep.ts module; rende
|
|
|
335
407
|
process.stdout.write(serializeReport(report) + "\n");
|
|
336
408
|
return;
|
|
337
409
|
}
|
|
410
|
+
const section = aimedSection(report.manufacturability?.bores ?? [], report.measurements.bounds);
|
|
411
|
+
const marks = featureMarks(report.bodies ?? [], report.manufacturability?.bores ?? []);
|
|
338
412
|
const { pngs } = await shoot({
|
|
339
413
|
file: stepPath,
|
|
340
414
|
outDir,
|
|
341
|
-
fresh: true
|
|
415
|
+
fresh: true,
|
|
416
|
+
...section ? { section } : {},
|
|
417
|
+
...marks.length > 0 ? { marks } : {}
|
|
342
418
|
});
|
|
343
419
|
for (const p of pngs) process.stdout.write(`${p}\n`);
|
|
344
420
|
} finally {
|