Skip to content

Releases: SunboX/circuitjson-toolkit

CircuitJSON Toolkit 1.4.2

Choose a tag to compare

@SunboX SunboX released this 23 Jul 21:32

CircuitJSON Toolkit 1.4.2 removes repeated immutable-graph work from
toolkit-owned document rebuilds and cooperative structured-clone adoption.

Changes:

  • Reuse already branded, frozen extension roots when rebuilding validated
    documents.
  • Validate each acquired clone container and freeze it atomically rather than
    redefining every property.
  • Preserve defensive handling for arbitrary caller data and cancellation
    checkpoints for cooperative work.
  • Add packaged release notes and ownership/atomicity regression coverage.

Verification:

  • Complete multi-phase test suite: 12 + 520 + 18 + 1 + 11 + 5 + 10 tests,
    zero failures.
  • npm run check:format
  • npm run check:features (1,207 mappings)
  • npm publish --dry-run (circuitjson-toolkit-1.4.2.tgz, 194 entries,
    424,001 bytes packed)

circuitjson-toolkit 1.4.1

Choose a tag to compare

@SunboX SunboX released this 22 Jul 16:31

circuitjson-toolkit 1.4.1

This patch release adds a shared self-adjusting-computation runtime for
persistent toolkit and application state. It implements dynamic dependency
tracing and ordered change propagation without coupling the common package to
DOM, Three.js, or source-format parser state.

Self-adjusting computation

  • SelfAdjustingComputation is available from the package root and is shared
    by identity through the Gerber, Altium, KiCad, and PCB Scene3D packages.
  • Named synchronous computations record the data and control-flow paths they
    observe. Explicit changed roots start propagation from reverse reader lists.
  • Potentially affected computations compare their previous observations and
    reuse successful results when values, presence, key structure, and selected
    atomic identities remain unchanged.
  • Re-execution replaces the previous trace and its abandoned reader edges.
    forget() and clear() reclaim trace storage explicitly.
  • Tracked snapshots reject mutation and asynchronous trace escape. Callers can
    choose an atomic boundary for immutable documents and native objects.

Verification

The unit suite covers nested and structural reads, control-flow replacement,
stale reader removal, atomic document identity, failed and asynchronous
computations, write rejection, explicit trace reclamation, and equality with a
fresh runtime after each propagated change.

circuitjson-toolkit 1.4.0

Choose a tag to compare

@SunboX SunboX released this 15 Jul 00:01

circuitjson-toolkit 1.4.0

This minor release removes redundant ownership work when a source toolkit or
browser worker has already established an exact graph provenance boundary. It
also lets browser hosts return control between validation and extension
sealing without changing the canonical result contract.

Owned document construction

  • DocumentResult.createValidatedOwned(fields, runtime?) creates the same
    validated ecad-toolkit.document.v1 envelope as createValidated().
  • A source-toolkit convergence builder may transfer a newly constructed,
    standard-built-in graph into the envelope. Ordinary model and extension
    nodes retain their identities and are deeply frozen in place instead of
    being copied into a second full graph.
  • The method is intentionally destructive. It is only safe when the toolkit
    exclusively owns the complete mutable graph and will not mutate it after the
    call. Arbitrary caller values, raw untrusted input, cross-realm objects,
    proxies, and altered prototypes must continue through createValidated().
  • Binary properties retain their defensive boundary and validation. Ownership
    limits, validation proofs, and immutable-envelope guarantees are unchanged.

Cooperative structured-clone preparation

  • CircuitJsonDocumentContext.prepareStructuredCloneAsync(input, options?)
    accepts the same structured-clone input and indexes option as the
    synchronous method, plus the required ownership: 'exclusive' declaration
    and an optional yield scheduler.
  • This is a destructive transfer. Callers must relinquish every alias and
    shared-memory writer until settlement. Mutation before a node is acquired is
    outside the contract and cannot be detected reliably; rejection can leave a
    partially locked graph.
  • The method validates and deeply freezes the model, then yields between
    bounded slices of dense-array traversal, Map/Set normalization, immutable
    text accounting, binary copying and installation, and property locking
    before sealing the canonical envelope.
  • Acquired containers are shape-locked and their descriptors are checked while
    sealing. Individual plain extension records are capped at 16,384 properties
    so one record cannot create an unbounded cooperative inspection step.
  • Existing immutable contexts are reused without a transfer declaration.
    Transferred ordinary records retain identity; dense arrays are normalized
    into clean arrays while preserving aliases and cycles, preventing unsupported
    hidden properties from leaking mutable state.
  • An injected yield function is awaited at each scheduling boundary. Without
    one, the toolkit prefers scheduler.yield() and otherwise uses a zero-delay
    host task.
  • The promise resolves to the same immutable CircuitJsonDocumentContext
    shape with the same indexes, caches, limits, and validation authority.

Compatibility

  • No parser option, package subpath, class, parameter, or return field is
    removed or renamed.
  • DocumentResult remains ecad-toolkit.document.v1; its model, source,
    extensions, assets, diagnostics, and statistics fields are unchanged.
  • createValidatedOwned() and prepareStructuredCloneAsync() are additive.
    The defensive and synchronous APIs retain their previous behavior.

Verification and performance

Synthetic regression coverage verifies ordinary-record identity retention,
alias/cycle-preserving clean arrays, deep freeze, chunked text and binary
processing, dense-array and Map/Set scheduling,
cooperative yield ordering, progressive shape/property locking, the exclusive
ownership contract, and context reuse across document batches. The full
adversarial suite continues to cover hostile accessors, altered and cross-realm
built-ins, defensive binary ownership, worker parity, synchronous mutation
isolation, and bounded extension graphs.

On the same browser and machine, the exact large native-PCB deep link that
previously produced 3.29-second and 2.17-second renderer-main tasks retained
the same 25,729-element PCB SVG and view box after this release. A final fresh
open peaked at 17.7 milliseconds on the renderer main thread. A forced reload
peaked at 404.4 milliseconds, consisting of 196.8 milliseconds of browser
structured-clone deserialization plus 205.3 milliseconds of browser garbage
collection; no application JavaScript task approached the previous stalls.
The largest scheduled parser-worker task in that reload was 5.9 milliseconds.
A separate 150,000-record exclusive-adoption probe yielded 880 times and
completed in 487.35 milliseconds, with a 1.22-millisecond p95 slice and a
6.94-millisecond maximum outlier. A 32 MiB immutable-text probe completed in
8.13 milliseconds across 513 yields; a 32 MiB binary probe completed in 3.40
milliseconds across 514 yields. These figures describe fixed local workloads
and are not runtime guarantees; deterministic shape, validation, and ownership
tests remain the release gates.

circuitjson-toolkit 1.3.0

Choose a tag to compare

@SunboX SunboX released this 14 Jul 20:48

circuitjson-toolkit 1.3.0

Faster canonical extension ownership

This minor release adds an explicit fast ownership path for large native
extension graphs received through the platform structured-clone algorithm.
Ordinary records, arrays, and standard local data containers are classified
without deliberately invoking incompatible intrinsic getters, while genuine
buffers and views still use captured platform slots as the final authority.

The new CircuitJsonDocumentContext.prepareStructuredClone(document, options?)
method has the same options and return shape as prepare(). It is intended for
the exact result of a completed platform structured clone, or for a graph
created entirely by the toolkit after that boundary. Hosts must continue to use
prepare() for arbitrary caller-owned, cross-realm, proxy-backed, or
prototype-modified input. The optimization is source-format-neutral and
requires no example-specific handling.

Measured on the deterministic standard-built-in metadata workload used during
development, capturing 50,000 populated records fell from about 3.7 seconds to
about 0.16 seconds. Browser timing for the combined library and ECAD Forge
release is documented by the application release because network transfer,
application interaction preparation, and SVG mounting are outside this
library's ownership boundary.

Compatibility and API changes

  • No public class, package subpath, parameter, or return field is removed or
    renamed.
  • CircuitJsonDocumentContext.prepareStructuredClone(document, options?) is a
    new opt-in method for the explicit structured-clone provenance contract.
  • Parser, project, renderer, worker, and extension result shapes are unchanged.
  • The existing prepare() path remains exact and prototype-independent.
    Cross-realm and altered-prototype ArrayBuffer, SharedArrayBuffer, typed
    array, and DataView values, resizable buffers, byte ceilings, and
    defensive-copy behavior are retained.
  • Proven standard plain-data graphs no longer generate caught exceptions merely
    to prove that each ordinary node is not binary data.

The new regression coverage pauses on every thrown exception in an isolated
runtime, proving that a representative proven-standard metadata graph completes
with zero binary-probe exceptions. Exact-path regressions cover altered and
cross-realm binary objects plus proxy prototype traps. Existing adversarial and
full-suite contracts continue to cover hostile accessors, worker parity,
mutation isolation, and bounded extension ownership.

circuitjson-toolkit 1.2.1

Choose a tag to compare

@SunboX SunboX released this 14 Jul 18:24

circuitjson-toolkit 1.2.1

Large canonical worker results

This patch release keeps valid high-fidelity documents and multi-document
projects inside explicit, format-neutral worker limits:

  • Selected native extensions may contain up to 4,000,000 structured items and
    128 MiB of string or binary content.
  • A canonical standalone document may contain up to 5,000,000 result values
    within the existing 250 MB byte ceiling.
  • An exact canonical project may contain up to 8,000,000 aggregate values and
    256 MiB, while every document retains its own 5,000,000-value and 250 MB
    limits.
  • Non-document project metadata retains the generic 2,000,000-value and 250 MB
    limits.

Elevated budgets require the complete canonical document or project envelope;
a schema string alone does not change generic result limits. Reused object
graphs are charged independently to document and project-metadata scopes in a
property-order-independent way. Repeated alias-accounting work is also capped
by the project aggregate budget, keeping transport time bounded.

No public class, method, package subpath, parameter, or result field is removed
or renamed. Oversized results continue to fail visibly rather than being
truncated.

circuitjson-toolkit 1.2.0

Choose a tag to compare

@SunboX SunboX released this 14 Jul 15:26

circuitjson-toolkit 1.2.0

Canonical PCB fidelity

This minor release expands the shared CircuitJSON contract used by the Gerber,
Altium, KiCad, and 3D viewer packages. Existing canonical fields remain
authoritative, while source formats can retain exact rendering information in
validated, source-neutral extension fields.

API additions

  • pcb_note_text, pcb_fabrication_note_text, and pcb_silkscreen_text may
    retain independent font_width and font_height, stroke_width, the exact
    nine-position source_anchor_alignment, is_hidden, source_layer,
    source_type, and source_text_kind.
  • Board-note ccw_rotation and fabrication-note is_mirrored are validated
    when present, so downstream renderers can consume the original orientation
    without source-format adapters.
  • CircuitJsonPcbHolePrimitiveModel.build() now returns cornerRadius and
    computes board-space bounds for rotated rectangles and pills instead of
    treating their local width and height as axis-aligned.

Behavior and performance

  • Structured metadata snapshots and worker request graphs accept valid nesting
    up to 256 levels, matching the deeper native data graphs emitted by ECAD
    parsers while retaining the existing item and byte limits.
  • The new fields pass through the existing immutable document ownership and
    validation boundaries; no viewer or host-app workaround is required.

No existing public class, method, package subpath, parameter, or document
envelope is removed in this release. Consumers that exhaustively validate PCB
text or primitive return objects should accept the additive fields above.

v1.1.2

Choose a tag to compare

@SunboX SunboX released this 12 Jul 17:20

circuitjson-toolkit 1.1.2

Deterministic schematic paint

This patch removes browser-dependent SVG fill behavior from the canonical
schematic renderer.

  • Open arcs, polylines, and unfilled shapes now emit fill="none" explicitly,
    so they cannot become black-filled in a browser or host stylesheet.
  • Filled schematic primitives retain a valid authored fill_color or
    fillColor. When is_filled: true has no authored paint, rendering uses
    var(--schematic-fill-color, #f1d8bd).
  • Generic schematic_component and schematic_symbol bodies now emit the
    shared schematic fill and default-ink theme variables explicitly.
  • Filled paths render as polygons; open paths remain polylines. This preserves
    geometry while making fill intent unambiguous.
  • Unsafe authored paints remain rejected by the existing SVG paint sanitizer.

Public exports, method names, parameters, CircuitJSON document envelopes, and
renderer return shapes are unchanged from 1.1.1.

circuitjson-toolkit 1.1.1

Choose a tag to compare

@SunboX SunboX released this 11 Jul 21:04

circuitjson-toolkit 1.1.1

Synchronous queued-request ownership

This patch makes the common worker client own every accepted parser and
project request when it enters the queue behind active work.

  • Default transferInput: false requests clone their exact binary graph into
    a private queue snapshot immediately. Later caller mutation cannot change a
    queued parser input, project entry, or attached asset.
  • transferInput: true detaches exact transferable caller buffers immediately
    after queue admission. Partial views, resizable buffers, and shared buffers
    keep their isolated-copy behavior without detaching unrelated caller bytes.
  • Shared backing-buffer aliases remain shared in the owned request, and queued
    snapshots transfer to the worker without another binary copy when posted.
  • Disposed, pre-cancelled, over-limit, and initial worker-construction failures
    reject before ownership. Automatic direct fallback therefore retains valid
    binary input.
  • Parser and project queues use the same bounded, accessor-safe traversal and
    retain existing cancellation, error, and response behavior.

Public names, parameters, package subpaths, document envelopes, and project
envelopes are unchanged from 1.1.0. Gerber, Altium, KiCad, viewers, and ECAD
Forge receive the corrected behavior through the shared ParserWorkerClient.

circuitjson-toolkit 1.1.0

Choose a tag to compare

@SunboX SunboX released this 11 Jul 17:44

circuitjson-toolkit 1.1.0

Breaking API convergence

This minor release intentionally changes public names, parameters, return
shapes, and package layout so CircuitJSON, Gerber, Altium, and KiCad toolkits
can expose the same API.

The root is an exact 17-class contract: the 14 canonical classes plus temporary
CircuitJsonDocument, CircuitJsonIndexer, and CircuitJsonUnits viewer
compatibility exports. Exactly 37 previous CircuitJSON-specific classes remain
available from circuitjson-toolkit/extensions; they were not removed and are
classified as shared or derived for all four toolkits.

Key changes:

  • Parser.parse({ fileName, data }, options) replaces filename/text-specific
    parser calls and returns ecad-toolkit.document.v1.
  • ProjectLoader returns ecad-toolkit.project.v1 with canonical document
    envelopes. It now captures one bounded stable entry snapshot, enforces
    maxEntries before inspecting entries, and gives direct and worker paths the
    same known-field behavior.
  • Parser failures use ToolkitError; tryParse and tryLoad return exact
    success/failure discriminants.
  • retainSource is now the explicit 'none' | 'reference' contract.
    Reference mode preserves exact caller identity only on direct parser calls,
    exposes it non-enumerably, and never serializes or freezes the caller input.
  • PCB, schematic, BOM, interaction, query, manufacturing, simulation, and 3D
    services consume either a document result, a CircuitJSON model, or a reused
    CircuitJsonDocumentContext.
  • Canonical schematic graphics now include asset-backed schematic_image
    rows and hierarchical schematic_sheet_symbol rows. Images keep payloads
    in ToolkitAsset records, and child sheet symbols no longer masquerade as
    selectable pages or hide unowned root graphics.
  • PcbScene3dBuilder and PcbScene3dPreparator return data-only,
    millimeter-based, right-handed Z-up scenes. The package does not depend on
    Three.js and never fetches assets implicitly.
  • ecad-toolkit.worker.v1 provides equivalent parse/project results, ordered
    progress, cancellation, strict clone-safe errors, opt-in input transfer, and
    worker-owned output transfer.
  • ParserWorkerClient.parseAttempt() and loadProjectAttempt() give source
    toolkits request-scoped automatic-worker fallback: only local construction
    failure sets unavailable: true; parser, protocol, and runtime failures stay
    visible.
  • Canonical subpaths now include /parser, /project, /renderers,
    /interaction, /query, /manufacturing, /simulation, /scene3d,
    /capabilities, /extensions, and /testing.
  • Shared validation proofs, indexes, render preparation, queries, and scene
    preparation are request-scoped and reused to avoid repeated parsing,
    validation, cloning, and spatial work.
  • Validated source extensions are captured once as immutable owned data under
    a separate 128 MiB payload and 2,000,000-item ceiling. Realistic large native
    graphs now survive direct and worker results; over-limit graphs fail visibly
    and the worker keeps its 250 MB whole-result ceiling. Binary extension values
    stay byte-backed behind defensive-copy access rather than expanding into
    plain number arrays.
  • CircuitJsonDocumentContext can now only be created through prepare();
    direct construction fails before reading input so viewers and applications
    can consume the same validation-bound context without adapter workarounds.
  • CircuitJsonDocument.normalizeModel(model, { owned }) is the shared
    copy-on-write compatibility boundary for legacy table geometry, PCB artwork
    paths, pad diagnostics, courtyards, layer aliases, and stroke dash fields.
    Toolkits normalize owned projections before one validation pass; viewers no
    longer need application-side repair code.
  • The complete serialized-input validator is compiled from the pinned
    development dependency circuit-json@0.0.446. It preserves upstream
    refinement, pipeline, and SI-unit transform rejection behavior while keeping
    the published browser runtime dependency-free.
  • Compiler provenance now also verifies and records the exact lock integrity
    and distribution entry SHA-256 for format-si-unit@0.0.7 and zod@3.25.76.
  • Full compatibility parsing canonicalizes legacy Gerber/KiCad outer-layer
    aliases (1/32, F.*/B.*, and descriptor layer.name), fills via layer
    defaults, converts legacy trace vias, and retains silkscreen circle/oval and
    courtyard geometry for viewers without app-side adapters.
  • CircuitJsonPcbHolePrimitiveModel now measures polygon pad_outline in the
    pad's rotation-local coordinate system and retains pill drill width, height,
    diameter, and independent board-space rotation. Legal outer_width,
    outer_height, rect_ccw_rotation, and hole_ccw_rotation variants are
    preserved. Downstream viewers no longer need format-specific plated-slot
    sizing logic.
  • Legal square pcb_hole rows normalize to equal-width rectangular apertures
    rather than circular fallbacks.
  • extensions: 'none' now has the exact common return shape {} for native
    documents and projects instead of a source-namespaced placeholder.
  • ZipArchiveInspector now validates exact local/central filenames, CRC32, and
    size metadata and exposes verifyExtractedBytes() so stored and deflated
    corruption is rejected after bounded inflation. Compression ratios use
    compressed and uncompressed member payload totals, so ZIP comments or other
    container padding cannot bypass expansion limits.
  • /testing now exports ToolkitLoopbackWorker alongside the contract fixtures
    and runner so all toolkits share one real structured-clone worker regression
    boundary.
  • Direct async parser/project paths now snapshot exact binary windows and
    selected assets before progress callbacks. Worker-received inputs reuse their
    structured-clone ownership boundary, and direct companion assets are prepared
    once, closing callback mutation races without redundant receiver/result copies.
  • npm run sync:schema -- --check is a read-only drift gate that recompiles the
    live pinned union and checks exact contract, provenance, snapshot, and
    generated-module equality.
  • Validation now freezes each proven model once, the legacy parser hands its
    already-built index to the next consumer, multi-side legacy rendering shares
    one primitive preparation, and compact identifier indexes avoid cloning
    duplicate element graphs.
  • ToolkitAsset.measure(), prepare(), and prepareAll() provide one
    descriptor-safe asset boundary. Metadata mode copies no payload; full mode
    copies once; project limits include attached assets in direct and worker
    execution. Missing media types are inferred consistently for common ECAD
    model and image suffixes, including model/vrml for WRL/VRML and
    model/step for STEP/STP, while explicit values remain authoritative.
  • Canonical schematic rendering preserves explicit multi-value dash patterns,
    accepts only safe SVG line-cap values, and honors show_label: false in both
    component markup and bounds. Source toolkits can retain native styles and
    hidden designators without renderer or application workarounds.
  • The release benchmark runner enforces the frozen 1.0.17 workloads: both
    primary cases must be at least 20% faster, non-primary regressions are
    bounded, and the duplicate index graph must be at least 25% smaller. Timing
    uses three independent processes. Every process imports toolkit modules from
    the freshly extracted npm tarball candidate and records an execution marker
    that reconciles its package version and source digest with candidate
    provenance.
  • The retained Node 20 / Apple M3 Max result passes every timing and clone
    gate, including at least 20% faster for both primary workloads and 85.32%
    fewer duplicate-index clone bytes. See
    benchmarks/results-v1.1.0.json for samples and checksums.
  • Gerber, Altium, and KiCad packages now consume CircuitJSON Toolkit as their
    shared runtime; their license terms do not replace this package's AGPL or
    separately granted commercial terms.

Before:

import { CircuitJsonParser } from 'circuitjson-toolkit'

const model = CircuitJsonParser.parseText(text, {
    fileName: 'board.json'
})

After:

import { Parser } from 'circuitjson-toolkit'

const document = Parser.parse({
    fileName: 'board.json',
    data: text
})

console.log(document.model)

See migration.md and its generated
appendix pages for the exhaustive 1.0.17 feature mapping,
and capabilities.md for host-side capability gating.

v1.0.17

Choose a tag to compare

@SunboX SunboX released this 28 Jun 22:56

Changes

  • Added repository fix-quality guidance in AGENTS.md so future fixes must address general behavior instead of sample-specific workarounds.
  • Bumped circuitjson-toolkit from 1.0.16 to 1.0.17 in package.json and package-lock.json for publication.

Branch reconciliation

  • Fetched all remotes and tags with pruning before release.
  • No local or remote branch refs were unmerged into main, so no branch merges were needed.

Validation

  • npm test: passed 74 tests.
  • npm run check:format: passed.
  • npm publish --dry-run --cache /private/tmp/circuitjson-toolkit-npm-cache: produced circuitjson-toolkit-1.0.17.tgz with 64 files, 113.4 kB package size, and 640.0 kB unpacked size.

Git

  • Release commit: 8c9d7de.
  • Annotated tag: v1.0.17.
  • main and tag pushed to origin before publishing.