Skip to main content

Jscad Cad

@magistr/jscad-cadv2026.08.02.1· 4d agoMODELS
01README

JSCAD v2 CAD renderer — evaluate CadScript main() and serialize to STL/DXF/SVG/OBJ/3MF. Includes jscad-codegen Claude Code skill.

02Release Notes

2026.08.02.1

Real fix for the three remaining open latent bugs tracked in the LOCAL jscad-cad-latent-bugs issue-lifecycle model (never a swamp.club Lab issue) — B3 (MEDIUM), B4 (LOW), and B5 (LOW) — superseding the "still open" wording recorded against them in the 2026.08.01.1 section below (which stays as historical record). All three fixes live in the same trust-boundary Domain Service (extensions/models/jscad/script_evaluator.ts) that B1/B2 hardened; extensions/models/jscad_cad.ts and extensions/models/jscad/types.ts are otherwise unchanged (types.ts's own Geometry.of([]) message is reused verbatim, not duplicated logic).

  • B3 (MEDIUM) — trailing JSON.parse corrupted by user console.log output, fixed. The parent now extracts only the LAST non-empty line of the subprocess's stdout and parses only that line for the {objectCount} metadata (throwing a clear "no object-count metadata" error if no line parses); the generated eval script forces Deno.exit(0) immediately after its own meta console.log, guaranteeing that line is the final one even against user-scheduled async output. A CadScript that itself calls console.log() ahead of returning geometry no longer corrupts the parse.
  • B4 (LOW) — silent objectCount 0 on an empty geometry array, fixed. The generated eval script now guards an explicit main() => [] result with if (shapes.length === 0) { ... Deno.exit(1); }, surfacing the exact same "Geometry must contain at least one shape" message that types.ts's own Geometry.of([]) already throws (that guard is simply never reached on the subprocess path — it still isn't; the new guard duplicates its message, not its code).
  • B5 (LOW) — unbounded in-memory output, fixed. A new module constant MAX_OUTPUT_BYTES (64 MiB default) is checked in the generated eval script BEFORE the binary/text output is allocated (binary: sum of view.byteLength; text: sum of p.length) — the cap rejects with a clear error, it never truncates. evaluateAndSerialize gained an optional 5th positional maxOutputBytes parameter (mirrors the existing timeoutMs precedent: an internal module-constant default, not a user-facing arg); the parent adds a belt-and-suspenders Deno.statSync(outputPath).size check before readFileSync, for defense-in-depth against a subprocess that wrote past the cap despite the guard.
  • N3 (accepted-residual, no code change). The globalThis["Func"+"tion"] scanner-evasion trick that resolves the dynamic-dispatch constructor stays exactly as-is: it is the by-design execution mechanism for user CadScript main() (arbitrary-by-design — removing it removes the product), its blast radius is already contained by B1's scoped --allow-read/--allow-write and B2's AbortSignal.timeout, and the one tempting hardening (shadowing Deno/globalThis inside the user-code Function body) is rejected because it would flip the frozen B1 live-negative pin from a PermissionDenied to a TypeError for only marginal gain over the existing OS-level read scoping. Re-characterized (comment-only) in jscad_cad_adversarial_test.ts's suite header and N3 pin section; the two N3 assertions and the underlying "Func" + "tion" / "${pkg}" source stay byte-identical.
  • New tests: jscad_cad_adversarial_test.ts's B3/B4/B5 pins flip from characterizing-the-bug to characterizing-the-fix (B3: asserts success with the correct objectCount instead of a SyntaxError; B4: asserts the generated script now contains the empty-array guard instead of a silent objectCount: 0; B5: asserts the generated script now embeds MAX_OUTPUT_BYTES instead of asserting its absence) plus a new B5 parent-statSync-cap unit test. script_evaluator_test.ts (the SOLE live e2e suite) gains three new SYNTHETIC live cases proving all three fixes against a real subprocess, with no oversized fixtures: a B3 positive (console.log() then render succeeds), a B4 negative (main() => [] is rejected with "at least one shape"), and a B5 negative (a real small render against a tiny maxOutputBytes cap is rejected by the subprocess guard). The frozen argv/contract/N1/N2/B1/B2 pins across all five suites stay byte-identical/green — no argv shape change, no public run-method schema change.
  • quality.yaml's ratchet stays UNSCORABLE baseline-0, honestly: the scorer's static import-specifier scanner still hard-errors on script_evaluator.ts's runtime-interpolated import * as serializer from "${pkg}"; template literal — a separate

Notes trimmed at a line boundary to fit the registry's 4900-byte per-version cap. Full section: https://github.com/umag/swamp-workspace/blob/d850d8e8372d4c0008c9245959a090b37095de7a/jscad-cad/CHANGELOG.md

03Models1
@magistr/jscad-cadv2026.08.02.1extensions/models/jscad_cad.ts
fn run(script: string)
Evaluate a CadScript and serialize the resulting Geometry to the requested OutputFormat
ArgumentTypeDescription
scriptstringJSCAD JavaScript defining main(params) → geometry

Resources

result(infinite)— RenderResult — outcome of evaluating a CadScript

Files

output(application/octet-stream)— SerializedModel — generated CAD file (STL/DXF/SVG/OBJ/3MF)
log(text/plain)— Evaluation warnings from CadScript execution
04Previous Versions7
2026.07.16.2

Release 2026.07.16.2 — align model versions with manifests

Maintenance release across the @magistr extensions. For most packages this carries no functional change: the only edit is the model's version: field, brought back in line with its manifest version so the published model type version and the package version no longer drift.

Functional changes in this release are limited to:

  • anime-cron: normalizeTitle now strips a ": subtitle" suffix and a trailing parenthesized year before comparison, fixing dedup false-misses where the torrent title carries a subtitle or year that the AniList romaji does not.

  • arckit: first publish. Standalone ArcKit port — a 12-phase architecture governance state machine with 65 bundled templates, driven by a bundled skill.

Also tracks three extensions (kaiten, observability-agent, music-library) that previously existed only as untracked working-tree directories, recovered from stashes.

Added 1, removed 1 models

2026.05.25.1

Merge pull request #4 from umag/extensions/magistr-grade-a-workspace

extensions: stage 15 @magistr extensions as Grade A workspace dirs + wire CI

2026.04.05.2
2026.04.05.1

Updated jscad-codegen skill: eval score 59%→100%. Fixed mandatory script rules, named coordinates, oversized cutters.

2026.04.04.3
2026.04.04.2
2026.04.04.1
05Stats
A
100 / 100
Downloads
7
Archive size
33.0 KB
  • Has README or module doc2/2earned
  • README has a code example1/1earned
  • README is substantive1/1earned
  • Most symbols documented1/1earned
  • No slow types (deprecated)1/1earned
  • Dependencies pass trust audit2/2earned
  • Has description1/1earned
  • Platform support declared (or universal)2/2earned
  • License declared1/1earned
  • Verified public repository2/2earned
06Platforms
07Labels