Skip to content

Releases

0.5.0

Choose a tag to compare

@pzfreo pzfreo released this 12 Nov 11:07
18eefdc

Upgrading from 0.4.9:

  • Rust API. Recognition records, evidence and fingerprint documents, reports,
    refusal/error types and options are #[non_exhaustive]: add fallback match arms,
    destructure with .., and build values with Default::default() or the provided
    constructors (Rust API evolution).
  • Fingerprints are quiddity-rust/fingerprint/4. correspond refuses stored /3
    fingerprints; re-fingerprint each part from its own geometry with this release.
  • Assembly manifests are quiddity-manifest/2, one instance per assembly occurrence.
    /1 manifests are refused; rescan the source.
  • Recognition schema stays quiddity-rust/recognition/6. New families and fields are
    additive.
  • Thanks to @xu9299 for shared recognition/evidence analysis (#227), recess evidence
    without solid ownership (#234), Windows snapshot provenance paths (#237) and faster
    face integration (#246).

Breaking (Rust API)

  • Recognition records,
    evidence and fingerprint documents, reports, refusal/error types and defaultable
    recognition options are now #[non_exhaustive]. Match extensible enums with a
    fallback arm and destructure extensible structs with ... Construct options with
    Default::default() then assign public fields; use the provided constructors for
    caller-authored values. See Rust API evolution for the full list
    and the closed value types deliberately kept exhaustive.
  • Presentation text placements, callout geometry, polyline roles, evidence statuses
    and face-accounting groups are also non-exhaustive; use TextPlacement::new or
    presentation::Callout::default() for construction and handle unknown variants.
  • Breaking public Rust API changes require a minor bump before 1.0. This includes
    field/variant additions on exhaustive types and removing or feature-gating APIs.
    CI checks both published crates against their latest stable crates.io release;
    a non-empty Unreleased Breaking (Rust API) section sanctions a pending minor bump.
  • Breaking (fingerprint format): fingerprints are quiddity-rust/fingerprint/4
    (FINGERPRINT_VERSION). Values changed several times within /3 (#71, #84/#85, #92,
    #100, #118, #134, #189) without a way to tell which vintage a stored fingerprint has, so
    correspond now refuses /3 with an error asking for the part to be re-fingerprinted.
    Consumers that store fingerprints must re-fingerprint each part from its own geometry
    with this quiddity; there is no migration. The /4 values are this release's values;
    the structure and fields are unchanged. Recognition schema stays /6. For #254.

Changed

  • Face integration reuses complete cached moments, skips kink searches that cannot
    affect refinement, and stops once an accepted leaf makes the existing refusal
    inevitable. Integration nodes, error criteria and returned results are unchanged.
    From #246 (@xu9299).
  • Breaking (manifest format): assembly manifests are quiddity-manifest/2, with one
    instances entry per assembly occurrence. A product's solids and surface models are all
    placed by that one entry; /1 listed one entry per body, so a multi-solid part was placed
    over itself several times. /1 manifests are refused with "rescan the source". From #190.
  • Section-recess candidates whose faces have no solid owner (open shells, or faces dropped
    in a degraded run) no longer fail evidence for the whole file. recognition/6 gains a
    section_recess_source_refusals family naming those sources; a returned projection error
    now gives a partial result (complete: false) instead of an evidence error. Eligibility
    checks the defining and consulted faces, so a candidate consulting a face on another solid
    is refused (evidence). SectionRecessProjection gains
    source_refusals and is #[non_exhaustive]. From #234 (@xu9299).

Documentation

  • haecceity states its scope: it reads, queries and writes B-reps and does not model them
    (README "Scope", crate docs and the crates.io description). From #203.

Fixed

  • Refuse incompatible complex targets in schema reference slots throughout shape
    topology and geometry, and loops with neither edges nor a vertex. Empty programmatic faces no longer panic in loop placement.
    Nine regression inputs and 256 time-bounded token mutations exercise this path;
    the mutation harness also rejects caught family panics.

  • Python native entry points catch internal Rust panics as quiddity.QuiddityError
    (a RuntimeError, caught by except Exception) with the panic message. Normal
    input errors retain their existing ValueError / PmiError types.

  • PMI edition upgrades report R4 repairs for unset required label/text attributes,
    writing empty strings without inventing identifiers or other values. Ordinary AP242
    writes preserve those defects; Add refuses source-record repairs with their kinds and ids.
    Rust API: UpgradeRepairKind gains R4UnsetRequiredString and becomes
    #[non_exhaustive]; matches need a fallback arm (see Breaking above). CLI and Python: a write
    report's instances.replaced counts distinct records, so a record with two repairs
    counts once.

  • Mass quadrature judges tangent rank independently of the UV parameter scales. The narrow
    spline sheet captured/.../2fe0e2383b80a0b8 now has its true area (10 mm², was 0.011),
    and the recovery length and tolerances derived from it follow.

  • A solid whose face normals are mixed (some inward, some outward) and whose volume is
    negative has its inward faces repaired, but only when every face's material side is
    proved, the wires stay coherent, the mass becomes positive and every repaired face is
    re-proved outward. input_repairs reports solid 0: mixed face senses repaired (N faces).
    The check is cheap and looks at the first eight faces, so it is face-order dependent: a
    shell whose first decisive face is outward is not repaired
    (recognition trust). In the fixtures, MFCAD++ (test split)
    and MFInstSeg it fires only on truck_master_shaft_hole:

    • its volume is now +46140.66 mm³, where it was −47426.50;
    • its Ø30×40 outer cylinder is a BossRecord Ø30 h40 instead of a flat-bottomed
      HoleRecord 40 deep;
    • its fingerprint normals, convex/concave adjacency and frame refusal
      (no-analytic-direction, was no-material) follow.
  • Two known differences from OCCT are recorded. Both are checked by independent integrals
    that agree with ours, and neither changes a comparison band:

    • truck_master_shaft_hole is 1.12e-4 above OCCT, which builds approximate cap pcurves.
      The part's bore intersection curves lie up to 0.12 mm off their surfaces, so its
      volume is only defined to about 2e-4 (the design intent is 46139.11 mm³).
    • varying_pitch_sweep differs by 4.2% in volume because OCCT integrates its open pcurve
      wires without closing the gaps. OCCT's own mesh agrees with ours, and tools/gvp.py
      counts it as KNOWN-REFERENCE while ours stays within the band of that mesh.
  • The snapshot tool uses / in manifest-relative paths so Windows input digests
    and nested snapshots can be checked against the same provenance manifest. From #237
    (@xu9299).

  • Mass integrals wrap closed spline tangents with their points and use consistent
    containment and integration domains for seamless torus bands. This restores the
    missing cylindrical areas in NIST STC-10 and the toroidal area in FTC-11, and
    corrects four adjoining STC-10 faces. Volume centroids and face moments now
    require valid mass integrals instead of accepting rejected face contributions.
    Mass validity shares the moments' quadrature and the existing per-face cache,
    avoiding a separate mass pass on faces first queried for their moments.

  • Closed rectangular pockets with analytic floor rounds retain their full depth and
    vertical corner radius (#228), extending the blind-recess floor-claim work (#205,
    #207). Optional floor_radius reports a proved uniform floor radius;
    floor_fillets attaches each treated face, supporting wall and local radius to
    the pocket, including mixed sharp/rounded floors. Open slots stay slots.
    FTC-08 has the same defect: pockets 8→9, slots 4→3 and fillets 95→91.
    Its surviving slot ranks 1–3 become 0–2; fillet ranks 66–73 become 64–71
    and 76–94 become 72–90. Existing pocket ranks and the other 99 corpus
    parts are unchanged. Face-specific inventory loss entries retain the historical
    slot/fillet baselines and tighten all three FTC-08 pocket floors to nine.
    The six existing section projections remain unchanged; one explicit refusal
    records the newly recognised pocket's unsupported toroidal floor geometry.
    Ball-end corners with equal wall/floor radii use spherical patches; their floor
    faces are owned once by the pocket. Floor-treated pockets supersede duplicate
    prismatic readings, and raw slot fallbacks survive until a pocket is accepted.
    Unsupported nonanalytic revolution floor transitions issue PocketRefusal
    rather than a truncated-depth pocket. FTC-08 raw slot candidates return to four;
    its physical slot loss allowance is retired while accepted ranks stay unchanged.
    Across revisions, adding a floor fillet to an existing pocket matches as an
    orphaned feature plus a new feature, as a None→Some corner radius already does.
    Shared per-solid floor analysis, early mouth checks and reuse of legacy cavity
    completion avoid repeated graph walks on parts without floor-blended pockets.

  • Internal bevel leg ties use intrinsic support area; symmetric ties remain unordered in
    fingerprints. Feature-policy angular tolerances retain slightly noisy STEP supports,
    with the slope angle measured on the actual supports rather than an ideal right angle.

Added

  • assembly_layout example generates contiguous, interleaved and seeded shuffled
    assemblies, and streams scale fixtures with fresh...
Read more

0.4.9

Choose a tag to compare

@pzfreo pzfreo released this 07 Nov 07:49
17a883a

Upgrading from 0.4.8: recognition schema /6, fingerprints /3, quiddity-rust/evidence/1 (one additive key), the haecceity.pmi/1 schema and the PMI reader string /19 are unchanged. Rust API: EvidenceDocument is not #[non_exhaustive] and gains edge_sources, so code that builds it with a struct literal must add the field (#202). quiddity::cli and the quiddity binary now need the default cli feature: a build with default-features = false (for example, to leave out presentation) must add features = ["cli"] to keep them, or leave it out to keep clap out (#201). The command line is now parsed by clap (#199); see Changed for the usage cases that now exit differently. Recognition output changes where a circular blind step cut by a second feature is now recognised in place of a cylindrical_profiles record (#215).

Added

  • quiddity completions SHELL (#199) prints a shell completion script (bash, zsh, fish,
    powershell or elvish) to stdout; the README gives the install one-liners. quiddity --version prints the version.
  • Evidence (#202): quiddity-rust/evidence/1 gains edge_sources, parallel to
    face_sources: per edge, the STEP EDGE_CURVE {entity, instance} it was read from, or
    null. The key is additive, so the schema version stays /1 (as for failures); existing
    keys and values are unchanged. Rust API: EvidenceDocument (not #[non_exhaustive])
    gains edge_sources, so struct literals need it; new alias EvidenceEdgeSource.
  • Python (#202): pmi.read(step, findings=True) returns (document, findings), keeping the
    reader's findings on the selected part (or no part) from a successful read; without the
    argument the result is the same dict as before. quiddity.parts(step) returns exactly
    quiddity parts' JSON. quiddity.step_entities(step) lists the file's DATA instances in
    file order: #N, entity type (each leaf of a complex instance) and referenced instances.
    Rust API: new file_api::parts and file_api::step_entities; quiddity parts now goes
    through file_api::parts, with unchanged output.
  • correspondence::congruent(a, b) proves two parts geometrically identical: it returns a
    proper rigid motion taking a onto b with the face pairs, or None. It tries an exact
    B-rep match, the centroid translation, then align, and accepts a motion only when every
    face matches and samples of the trimmed faces agree both ways within 1e-5 mm. Names are never
    read, and mirror images do not match. congruent_with(a, af, b, bf) takes fingerprints
    already made, for comparing one part against many. It moves draftwright's pack check into
    quiddity for Specify to share (#209, for specify-core#150). haecceity gains Part::same_brep,
    the exact B-rep comparison.

Changed

  • The quiddity command line (the binary and the Python console script) is parsed by clap
    instead of by hand. For everything that worked before, commands, flags, defaults, exit
    codes, output and refusals are unchanged, as are the messages for values checked by quiddity
    (--part, --mode, --presentation). Help and usage errors are clap's (Usage: quiddity …, on stderr with exit 2 as before). Newly refused or changed: pmi json usage errors (a
    missing argument or -o, an unknown command, an unknown, repeated or valueless option) exit
    2 instead of 1, with clap's message (a bad --part value is still refused with exit 1);
    evidence --framed with no file exits 2 (was 1, --framed read as the file); a trailing
    flag with no value is reported by clap; -h/--help after a command (parts, evidence,
    fingerprints, capabilities, …) shows its help and exits 0 (was an error: 1 where read as
    a file, 2 for capabilities); -V prints the version (was read as a file, exit 1); a file
    to recognise named completions must be given as ./completions. Newly accepted: a positional after
    the flags (evidence --framed part.step, pmi read --part 1 part.step), -- FILE, and --option=VALUE
    (--output=out.step). The command line is the root crate's default cli feature, so a
    library build can leave clap out (default-features = false) (#199, #201).

Fixed

  • Circular blind steps remain recognised when a secondary cut adds a convex planar
    neighbour along an intact cylindrical wall. Geometric corner supports and a complete
    wall boundary proof prevent admitting interrupted walls (#208, #215).

0.4.8

Choose a tag to compare

@pzfreo pzfreo released this 06 Nov 07:41
449ab51

Upgrading from 0.4.7: recognition schema /6, fingerprints /3 and the haecceity.pmi/1 schema are unchanged. The PMI reader string moves from haecceity-pmi-read/17 to /19.

  • PMI presentation follows CAx-IF PMI Recommended Practice 4.1 (#193):
    • Source leaders are tessellated inside their callouts, with no bare polyline curve occurrences.
    • Placeholders carry a direct axis placement, the standard PMI type names and links to their semantic PMI.
    • Curve sets use the Table 18 names (note, label, …).
    • Alignment moves from placeholder names to AP242 identification metadata. Older files remain readable.
    • PMI writes add the recommended-practice reference to FILE_DESCRIPTION, replacing an older PMI reference and keeping everything else.
  • A default Notes saved view (#198): general notes in one plane get an AP242 saved view named Notes, facing their annotation plane and framing the part and notes upright.
    • It is checked with NIST's STEP File Analyzer 5.41 (no errors; one expected advisory) and against NIST CTC-02's entity layout.
    • Add keeps foreign views and defaults, and reuses its own Notes view. Replace and remove clean it up. Edition-1 Add skips it; Replace upgrades edition 1 to 4 only when the view can be written.
    • In assemblies, only the first eligible part gets a view. Notes on several planes, or in several text orientations, produce a factual finding instead.
    • PmiRead.saved_views (Rust) lists saved views. Default views no longer produce a face-less shape-aspect finding.
  • Unique draughting-model names (#198): new models get unique names to satisfy UR1, such as PMI callouts (2) or datum feature symbols (2), including on assemblies without notes.
  • Materials (#198): a material with no separate name repeats its ID as its description, so no semantic text is empty. Its absence still round-trips.
  • Selected placed bodies (#194, for #111; thanks to @xu9299): StepFile::placed(&self, keep: &[usize]) reads chosen body instances in file coordinates, with their original STEP identities for PMI attachment. For example, it can read a plate and one of two coincident pins.
  • Rust API: PmiRead (not #[non_exhaustive]) gains saved_views: Vec<SavedView>, so struct literals and exhaustive patterns need it. New: pmi::SavedView and StepFile::placed. WriteReport (non-exhaustive) gains saved_view_findings.
  • CLI and Python: write reports gain saved_view_findings as an optional key.
  • Contributions: contributions are now taken under Apache-2.0 with a DCO sign-off (git commit -s), replacing the CLA (#192, #197). A Windows path-separator fix applies to the p21 broken-fixture test (#196).

Written STEP changes for every PMI write (RP 4.1 presentation and the FILE_DESCRIPTION reference), for files with general notes (a Notes view; Replace may upgrade edition 1 to 4), for assemblies (draughting-model names) and for materials without a separate name.

0.4.7

Choose a tag to compare

@pzfreo pzfreo released this 04 Nov 07:59
dcba9d3

Upgrading from 0.4.6: recognition schema /6, fingerprints /3 and the haecceity.pmi/1 schema are unchanged. The PMI reader string moves from haecceity-pmi-read/15 to /17.

  • Sealed interior voids are not holes (#189): a closed internal cavity (a void shell of the solid) is reported only as interior_voids, no longer also as holes and hole_patterns. Every sealed shell, spheres included, now gets an exact closed_shell record from its shell volume, so existing void records' volume and sample fields, and their fingerprints, change. Existing interior_voids ids keep their order. Holes that open to the outside are unchanged.
  • PMI round trip on the NIST CTC/FTC models (#188): all ten available CTC/FTC AP242 files round-trip with empty differences, and the NIST strict test runs in CI.
    • Dimensions with no stated value are written through unchanged, with no refusal from write or validate (Python no longer raises PmiError for them), no invented value and no nonconformance finding.
    • A projected zone whose end has no geometry is kept and written; the reader reports it as a fact finding (it was nonconformance).
    • Anonymous attribute units are matched by content, so PMI carried into a new file (quiddity brep --pmi) binds the same unit; that path also writes the standard mass units it needs.
    • Replace keeps datum support shared with PMI it can't read, and rebinds it only to equal replacement datums (WriteReport.retained_shared).
    • Upgrade repair R3: when the written PMI needs a newer AP242 edition, INTEGER representation items written as exactly integral REALs are written as INTEGERs, each reported.
  • Rust API: FindingKind gains Fact and UpgradeRepairKind gains R3IntegerLiteral; neither enum is #[non_exhaustive], so exhaustive matches need an arm. pmi::write::WriteReport (non-exhaustive) gains retained_shared: Vec<u64>. New: Finding::preserved_fact and Part::shell_mass (signed volume and area of a closed shell).
  • CLI and Python: write reports gain retained_shared as an optional key; PMI JSON findings can now have kind: "fact".

0.4.6

Choose a tag to compare

@pzfreo pzfreo released this 03 Nov 09:05
1ebf8cb

Upgrading from 0.4.5: recognition schema /6, fingerprints /3, the haecceity.pmi/1 schema and the PMI reader string haecceity-pmi-read/15 are unchanged.

  • Add mode keeps the file's own bytes (#185): every Add write now keeps pre-existing carriers, usages, controls and presentation at their original ids. This reverses 0.4.5's Add-mode normalisation, which broke datum_feature.WR2 when adding a datum to NIST CTC-01. Any Add write that would change an original entity fails atomically with WriteError::AddPreservation, which names the entities. That covers R1/R2 upgrade repairs and AP214 keyword rewrites; use Replace for those. Skipped normalisations are reported in WriteReport.preserved_normalizations as legacy-text-rechunking, kept-usage-factoring, functional-sar-isolation or legacy-endpoint-retirement.
  • Source callout positions (#183): PMI writing accepts an optional haecceity.presentation/1 companion: Rust/JSON write_with_presentation, Python presentation=, and CLI --source-presentation on quiddity pmi write (exactly one selected part) and quiddity pmi json import. The CLI flag exists only in json-import builds. /1 adds the optional Graphic.leader; readers that validate against the 0.4.5 schema (additionalProperties: false) reject documents that use it. Without a companion, #183 changes nothing.
  • Notes layout (#184): unplaced feature notes become their own leadered callouts, and the general-notes block moves clear of drawn ink. Written presentation changes for files with feature notes or a crowded notes position; four writer goldens changed (pmi_gaps, pmi_gaps_gram, spool_fits_intent, assembly_plate_pin_intent).
  • Reports: WriteReport adds presentation_warnings (placed text edge-on or overlapping, and feature notes whose glyphs can't be drawn) and preserved_normalizations. The CLI pmi write report and the Python report gain both as optional keys; pmi json import adds presentation_warnings. Python writer_findings gains both categories.
  • Rust API: WriteError gains AddPreservation and is not #[non_exhaustive], so exhaustive matches need an arm. json::presentation::Graphic gains the pub field leader and is not #[non_exhaustive], so struct literals must supply it.

Added

  • Notes blocks use actual projected strokes and row text cells, selecting the first clear downward offset instead of avoiding whole callout boxes. Feature-note extent matches frame placement.

  • Generate individual leadered callouts for unplaced feature notes; keep the general-notes block clear of generated, source-placed, and kept file ink.

  • Source callouts honour /1 text alignment, attach leaders to the box edge towards
    the tip, and refuse conflicting placements on a shared datum symbol. JSON CLI
    import accepts --source-presentation with xcaf requirement ids.

  • Source placement requires the json-import and presentation features.
    The CLI source flag is hidden without json-import; builds without presentation
    drawing refuse source input clearly. Minimal builds retain their previous features.

  • PMI writing accepts optional source callout planes, text positions and leader
    tips through Rust/JSON write_with_presentation, Python presentation=, and
    CLI --source-presentation FILE. Placed notes have their own note-linked
    callouts. Invalid placements fail atomically; edge-on text and overlaps warn
    without moving supplied positions. Saved views remain a later phase.

  • haecceity.presentation/1 adds optional Graphic.leader (a model-space point
    in millimetres). Old companions still read. WriteReport adds
    presentation_warnings; #183 changes no writer golden.

Fixed

  • Add upgrade refusals name the required repairs and entity ids, explain that
    Replace retains a part with no PMI, and warn that it re-authors existing PMI.
    Retained legacy aliases no longer generate classification certificates or gain
    checker exemptions; before/after checks retain their original findings. Reuse
    across representations sharing a context is limited to Add preservation.
    The CLI and Python reports carry preserved_normalizations records ({id, normalization}).
  • Add preserves original entity bytes: every Add write keeps pre-existing
    carriers, usages, controls and presentation at their original ids. Add no longer
    retires legacy endpoint wrappers, isolates functional SARs or rechunks retained
    legacy text, superseding 0.4.5's normalization behavior. Skipped normalizations
    appear in WriteReport.preserved_normalizations; schema upgrades requiring entity
    repairs now fail atomically in Add (use Replace for those repairs).
  • Adding a datum on a kept face or pattern emits a separate .T. datum_feature,
    fixing NIST CTC-01's .F. perpendicularity carrier (datum_feature.WR2). Only
    faces with kept usages get independent GISUs in new representations; uncovered
    faces use ordinary carriers. Pattern datums retain their member scope. Non-datum
    additions also get independent usages when safe reuse is impossible. Each narrow
    CAx-IF §5.1 exception names the actual aspect and preserved carrier in
    WriteReport.geometry_carrier_exemptions; unrelated source aspects are not exempt.
    Kept carriers are never promoted in any mode; datum leaves created in the same
    write remain reusable. No EXPRESS validation rule is exempted.

0.4.5

Choose a tag to compare

@pzfreo pzfreo released this 02 Nov 17:26
845a891

Upgrading from 0.4.4: recognition schema /6, fingerprints /3 and the haecceity.pmi/1 schema are unchanged. The PMI reader string advances to haecceity-pmi-read/15. Semantic PMI reads as before, with two exceptions: the datum findings below, and aspects that 0.4.5 writes named haecceity.feature/1. Old files are unaffected by the second.

  • Writer (#181): written STEP links PMI to geometry the way CAx-IF PMI v4.1 §5.1 and §6.5 recommend. Each face has one shape aspect, which every dimension and tolerance on it reuses, and datum features are referenced directly. Semantic values are unchanged, and OpenCascade reads every checked-in written golden as before. A narrow exemption covers two shared-carrier shapes that OpenCascade 7.9.3 and NIST SFA 5.41 misread in the strict form. They are reported in WriteReport.geometry_carrier_exemptions, which the CLI and Python report also show as an optional geometry_carrier_exemptions key. The thumbwheel golden also keeps one allow-listed presentation-only carrier.
  • Reader (#180): a datum whose feature reaches no face is now an Unresolved finding. A Solid Edge re-export of NIST CTC-01 that loses datum B's feature is pinned as a fixture.
  • Recognition (#178, #179): through holes with partly obstructed exits, and helical coil springs. The schema fields are additive, but existing records change on affected parts: spring wire faces lose their hole, boss and fillet records, and partly covered exits become through.
  • Rust API: Features gains the public field helical_springs and is not #[non_exhaustive], so struct literals must supply it (..Default::default() still works). PHYSICAL_FAMILIES now has 43 entries. New public types: HelicalSpring, SpringTolerances, ExitObstruction, GeometryCarrierExemption.

Fixed

  • Datum features that resolve to no faces are reported as Unresolved findings: datum <L> feature resolves to no faces when the feature is kept but reaches no face, and datum <L> is not read: what establishes it does not resolve when nothing establishes the datum (previously a Nonconformance, "datum is established by neither a feature nor a target"; such a datum was not read before either). The Solid Edge 2026 re-export of NIST CTC-01 and the control it was made from are fixtures (tests/fixtures/ap242/reexport/). The re-export reports exactly datum B unresolved. Writer round trips are checked so that no datum becomes unresolved.
  • PMI dimensions and tolerances reuse the face's existing shape aspect and GISU,
    including datum features (CAx-IF PMI v4.1 §5.1 / §6.5.1–2). Location endpoints no
    longer use faceless SHAPE_ASPECT('DIMENSION') wrappers. Multi-face features
    retain composites of shared per-face carriers so OCCT reads one GISU per face
    without violating IIRU UR2. Adding a datum to a kept ordinary feature specializes
    that carrier to datum_feature, reported in rewritten, preserving its id and usages.
    Consumer note: written STEP entity linking changes; semantic PMI values and
    haecceity.pmi/1 are unchanged. Reader binding advances to haecceity-pmi-read/15:
    explicitly authored standalone members use SHAPE_ASPECT.name='haecceity.feature/1'
    so they remain features when shared as composition members. Old files read as before.
    Specialized areas, runouts, groups and zones keep their meaning; plain requirements
    share neutral geometry carriers instead. Complex neutral composites can gain a datum
    in place. Legacy endpoint wrappers are retired on Add; independent same-content
    features retain separate removal provenance. A second datum label on an already
    established feature is refused under datum_feature.WR1.
    Adding a datum to a kept pattern specializes the same group aspect to a datum
    feature. Without presentation, adding a datum and its own size keeps the §6.5.3
    combined dimension over the kept geometry carrier, preserving existing feature controls.
    For ambiguous shared controlled-pair and datum-target-support SARs that both
    OCCT 7.9.3 XCAF and NIST SFA 5.41 read as composition, retain private forwarding
    aspects under a narrow §5.1 exemption.
    WriteReport.geometry_carrier_exemptions and the optional CLI/Python report field
    list each actual exempt addition by structural condition and endpoint/carrier id.
    Datum-feature endpoints stay direct; semantic face/GISU uniqueness remains mandatory.
    The thumbwheel Add golden retains one explicitly allow-listed presentation-only
    carrier so XCAF preserves the internal-thread callout, while coalescing its other
    producer duplicates. The raw Specify input is unchanged.
    Specify ownership stamps (specify-core:written:v1) are deleted with removed records;
    haecceity does not reattach them. Specify's own Replace re-stamps newly emitted roots
    after the haecceity write (specify-core-rust/src/writer.rs:784, src/provenance.rs:91).

Added

  • Recognise complete round-wire helical coil springs from swept NURBS tubes and connected cylinder/torus approximations. The optional helical_springs / HelicalSpring record supplies a file-space axis, hand, wire/mean/outer/inner diameters, physical free length, measured total coils, pitch, end type and exact claimed faces. Active coils remain null with an explicit basis when inactive ends are unproved; rate is never inferred. Spring claims suppress individual wire hole/boss/fillet callouts. Draftwright consumers can dimension free length and outer diameter on a simplified spring view and populate a data table from the record. Recognition schema 6 and fingerprint format 3 are unchanged for this additive family; Python recognition JSON exposes the same record.

  • Partially obstructed hole exits: bores spanning their local wall now report
    bottom: "through" when a planar partial cap leaves part of the exit open.
    Optional exit_obstructions on hole records (also in pattern members) names
    each mouth, its covering face indices and approximate covered-area fraction.
    Full caps retain blind classifications; undecidable geometry remains unknown.
    Consumers should re-recognise affected parts, draw THRU and warn about the
    obstruction. Recognition schema /6 and fingerprints /3 are unchanged: the
    diagnostic field is additive, omitted when empty, and excluded from fingerprints.
    Rust HoleRecord literals must supply exit_obstructions (normally Vec::new()).

0.4.4

Choose a tag to compare

@pzfreo pzfreo released this 01 Nov 19:30
53cf360

Upgrading from 0.4.3: recognition schema /6, fingerprints /3, the haecceity.pmi/1 schema and the PMI reader string haecceity-pmi-read/14 are unchanged, so semantic PMI reads as in 0.4.3. STEP writing changes only for parts with threads. Presentation JSON gains the optional fields below, including for files without threads.

  • Thread callouts (#175): written presentation now includes internal and external thread callouts (stated pitch, class and depth, or THRU) in a stack local to the feature, with any controls on that thread. Thread-free writes are unchanged.
  • Presentation JSON: haecceity.presentation/1 gains two optional fields so a host can redraw text in its own font. polyline_roles is per graphic. cell_box is per text placement: it appears on read file text when the file states a planar extent and a known alignment, and on generated text. Older documents still read. Readers that validate against the 0.4.3 schema (additionalProperties: false), or haecceity 0.4.3's JSON import, will reject the new fields. The Python package's schema copy is updated.
  • API note: the Rust structs json::presentation::Graphic (polyline_roles), json::presentation::TextPlacement (cell_box) and presentation::Callout (frame_strokes, text_symbols, cell_boxes) gain public fields and are not #[non_exhaustive]. Code that builds them as struct literals must add the new fields; code that only reads them is unaffected. New public items: the function presentation::thread and the enum json::presentation::PolylineRole (not #[non_exhaustive]).

Added

  • Generate internal/external thread callouts with stated pitch, class and depth (or THRU), in feature-local stacks. Presentation JSON adds optional polyline roles and text cell boxes for host-font rendering; older documents remain readable. Five feature-on STEP goldens gain thread graphics: thread_replaced, assembly_plate_pin_intent, editor_assembly_pin_alone, string_post_tapped_intent, and thumbwheel_thread_knurl_intent; their XCAF captures are refreshed. Thread-free writes and feature-off goldens are unchanged.

0.4.3

Choose a tag to compare

@pzfreo pzfreo released this 01 Nov 10:51
56a4cbc

Upgrading from 0.4.2: recognition schema /6, fingerprints /3 and the haecceity.pmi/1 schema are unchanged; only files whose datum features have several constituents read differently.

  • Datum constituents (#173): a face aspect composing a datum feature maps to the whole datum only when it is the datum's whole face set. Constituents of a multi-face datum (e.g. three separately sized lands) keep their own features and dimensions; the datum still holds all faces. Single-constituent datums (NIST STC10's seven folds, the Solid Edge CTC-01 re-export) read as in 0.4.2. Specify can drop its temporary LM10UU writer adjustment.
  • Bounded STEP strings (#172): strings the writer generates are at most 8192 encoded bytes, so OpenCascade can read written files (NIST STC-10 failed before). Long descriptive values, including haecceity's JSON item-id map, are written as ordered lists of text chunks; legacy single strings still read. Readers of haecceity's ordering property or descriptive text outside haecceity must join the chunks in list order. Strings carried unchanged from the input are written as they are, with a non-fatal long_strings warning. Generated names, identifiers and fallback product/header names longer than the bound are now explicit errors (never truncated), and a generated note graphic whose wording exceeds it is named General notes (the full text stays in the chunked descriptive items). API note: both Rust WriteReports (#[non_exhaustive]) gain long_strings: Vec<LongStringWarning> (record, encoded_bytes, byte_offset); the new public const pmi::write::MAX_STRING_LITERAL_BYTES is 8192; report JSON carries long_strings only when there are warnings.
  • Presentation (#171): generated size callouts sit above their feature control frames in one annotation plane, and saved-view packing reserves label ink, so callouts no longer overlap. Written PMI graphics change accordingly.
  • PMI reader string: changes from haecceity-pmi-read/13 to haecceity-pmi-read/14.

Fixed

  • A plain face aspect composing a datum feature aliases the datum only when its face
    set equals the whole datum feature's. Constituents of a multi-land datum retain
    separate features and size dimensions; the datum still collects all faces once.
    Single-constituent datum features, all-around groups and per-member datum groups
    retain their existing semantics. Consumers: legacy PMI reader binding advances
    to haecceity-pmi-read/14; re-read bound PMI documents. Specify can remove its
    workaround for the three independent Ø19 sizes on LM10UU's datum A lands.
  • STEP PMI writes bound generated encoded string literals to 8192 bytes, preventing
    OpenCascade's scanner overflow on NIST STC-10. Long descriptive values,
    including JSON item-id maps, UDA payloads and notes, use ordered compound/list
    representation items of text chunks; legacy single-string values still read.
    Consumer note: readers of haecceity's ordering property or descriptive text
    must concatenate marked chunks in list order. Semantic JSON is unchanged.
    Generated indivisible oversized names/identifiers are now explicit errors.
    Retained source/header/presentation text is preserved with non-fatal
    long_strings warnings naming the record and encoded length; both PMI and
    B-rep write reports expose the warnings (CLI and Python reports include them).
    Source product labels are preserved by B-rep writes; newly generated fallback
    product/header names remain bounded. Add also rechunks producer-owned legacy
    descriptive metadata at its original ids, preserving links and decoded values.
    API note: both Rust write reports gain long_strings (LongStringWarning), and
    pmi::write::MAX_STRING_LITERAL_BYTES is public; optional report JSON
    adds that field only when warnings exist. Existing semantic JSON is unchanged.
  • Keep generated size callouts above their feature control frames in one annotation
    plane, and reserve plain label ink in saved-view packing to prevent overlapping
    callouts without loosening feature-distance or spindle ladder drift limits.

0.4.2

Choose a tag to compare

@pzfreo pzfreo released this 01 Nov 04:10
d7112fd

Upgrading from 0.4.1: recognition schema /6 and fingerprints /3 are unchanged.

  • Recognition (#157, #159, #160): turned steps on stock with proved spanner flats are kept, interrupted coaxial torus fillets are grouped, and chamfer/angled-step corners are omitted unless proven. At your next pin, affected parts' fillet records renumber their run-local ids where interrupted arcs merge (64 groups in the corpus), some corner values become null where they could not be proven, and turned parts with flats gain their turned steps.
  • PMI reading (#168): strictly reversed dimension limits and signed deviations are read swapped, with a non-fatal finding, instead of refusing the dimension. Plain face aspects composing a datum feature resolve to that datum feature. On NIST STC10 seven duplicate features fold into their datum features (173 → 166), with references re-indexed.
  • PMI identifiers and zones (#170): duplicate or empty source identifiers no longer abort the JSON read (NIST STC06 and STC09 now export); repeated ids fall back to content-derived JSON ids, with a non-fatal finding. Each haecceity.pmi/1 item gains an optional identifier carrying the file's characteristic number, duplicates included. Update closed-object schemas for this additive field (the Python schema mirror includes it). Rust struct literals of json::Semantic and JSON-enabled PartIdentifiers need the new identifiers / json_identifiers fields. An exporter's runout zone with no angle on a non-runout tolerance recovers its stated zone form, with a finding.
  • PMI reader string: changes from haecceity-pmi-read/11 to haecceity-pmi-read/13 (the /12 step in #168 was never released).

Fixed

  • PMI JSON reads no longer abort on duplicate or empty source identifiers. Unique wire
    ids fall back to content identities, and non-fatal findings retain the affected STEP
    instances and identifier values. Optional per-item identifier fields carry source
    characteristic numbers, including duplicates, independently of reference id fields.
    Consumers: update closed-object schemas for this additive haecceity.pmi/1 field;
    resolve references by id. The Python schema mirror includes the addition.
    Rust json::Semantic gains identifiers; JSON-enabled PartIdentifiers gains
    json_identifiers for round-trip source metadata, so struct literals need those fields.

  • Recover an explicitly stated diameter/plain zone on a non-runout tolerance when an
    exporter supplies a runout-zone definition without its required orientation. Report
    the nonconformance; refuse when the missing orientation determines the zone's meaning.
    Legacy PMI read binding /13 identifies the additional source-identifier findings.

  • For #157, #159, #160, retain turned steps on stock with proved spanner flats,
    group interrupted coaxial torus fillets with exact defining faces, and omit
    chamfer/angled-step corners unless their wedge is consistent at published
    precision and has no material interior, retaining correct boundary-touching corners. Recognition /6 and fingerprints /3 are unchanged.
    At your next pin: affected parts' fillet records renumber their run-local ids where
    interrupted arcs merge (64 groups in the corpus), and some corner values become null
    where they could not be proven. Turned parts with flats gain their turned steps.

  • PMI import repairs strictly reversed dimension limits and signed deviations with
    a non-fatal nonconformance finding identifying the source instances. Equal bounds
    and reversals whose nominal lies outside the corrected absolute limits remain refused.

  • Plain face aspects composing an indivisible datum feature retain the owning feature
    identity when referenced by tolerances, properties or presentation; their faces are
    collected once. All-around groups and per-member datum groups keep their semantics.
    Legacy PMI reader binding /12 identifies the corrected output.

0.4.1

Choose a tag to compare

@pzfreo pzfreo released this 31 Oct 22:27
a2195ee

Upgrading from 0.4.0: recognition schema /6 and fingerprints /3 are unchanged, and successful recognition output is byte-identical.

  • Panic isolation (#161): a panicking family no longer aborts the run. Incomplete documents add optional failures and complete: false.
  • Presentation: text placements carry optional stroked; generated general notes are one numbered GENERAL NOTES block beside the part; regenerated ladders and datum flags sit by their features again; generated presentations gain one view per annotation plane. Feature-on (written PMI) graphics change accordingly.
  • Callout reading (#166): PmiRead.callouts lists decoded graphical PMI annotations and their semantic links.
  • API note: haecceity::pmi::PmiRead gains the public field callouts; code that builds PmiRead with a struct literal must add it. Code that receives it from pmi::read is unaffected.
  • AP214: files with FreeCAD's PRODUCT_TYPE now take PMI (pzfreo/specify-core#89), with each keyword rewrite reported in edition_rewrites.

Added

  • Haecceity PmiRead.callouts lists decoded graphical PMI annotations and every
    DMIA semantic link, including unresolved definitions, independently of the existing
    presentation accounting count. Links use part-qualified model ids and follow JSON
    transport ordering; note callout reading remains compatible.

Fixed

  • Generated part notes share one numbered GENERAL NOTES block in JSON and STEP,
    retaining each requirement's semantic link and the bounds-relative placement.
  • Regenerated PMI uses measured, compact dimension ladders and reserves datum
    flags before labels. Saved-view packing keeps labels near their features and
    text placements use the actual stroke transform, including clipped short spans.
    Written linear ladders share the compact ink spacing and retain seven-view clearance.
  • For pzfreo/specify-core#89, write PMI into legacy AP214 files containing
    PRODUCT_TYPE, changing only that keyword to PRODUCT_RELATED_PRODUCT_CATEGORY
    and reporting each edition rewrite with its instance id and entity names.
  • For #161, isolate panicking recognition families and block their dependents while
    preserving independent results. Incomplete recognition/6 and evidence/1 documents
    add optional failures and complete: false; successful output is unchanged.
  • Haecceity presentation v1 adds optional per-text stroked metadata, avoiding
    duplicate generated labels, and orthographic views for generated annotation planes.
    Generated general notes now form a bounds-relative column two capital heights
    beside the part; written STEP notes use the same placement rule.