Vextor

The VXL std library (card)

Declare the library once at the top of the document ("std": "vxl-std-2"); a std.* use, a std_* function call or table without the tag is VXL-F103, and any other version string is VXL-F101. Header from examples/std_plate.vxl.json:

  "schema": "vextor.vxl.v1", "id": "std_plate", "std": "vxl-std-2", "units": {"length": "mm", "angle": "deg"},

The library defines eight tables, expression functions and the fragments below. The reference cards — purpose, every check and the preconditions — are in VXL §3.5; the dimensional path and finishing stock cards are below. The exact JSON bodies are crates/vextor-vxl/std/vxl-std-2.json, pinned by a frozen digest.

Expression functions

Call std_hex_bumps(x,y,pitch,phase,radius_ratio) for the staggered compact bump lattice. Use radius_ratio 1.6/3.5 for the frozen owl and shell recipes; pitch and radius_ratio must be positive. The result is in [0,1].

std_ramp(x,lo,hi) clamps the linear ramp to [0,1] and requires lo < hi. These functions have unitless parameters/results and work in scalar, field and raster contexts.

std_smooth_band(x, lo, hi, width) has smooth ramps inside [lo,hi]: zero through lo, rising to one at lo+width, one through hi-width, then falling to zero at hi. It requires width > 0 and 2*width <= hi-lo; invalid calls refuse with a numeric-domain error.

std_iso_273 — clearance holes for metric bolts

lookup(std_iso_273, bolt, medium), where bolt is an enum param and the fit is a literal column name. Values are hole diameters in mm. The bolt component and clearance function must already be determined; a table lookup does not authorize choosing them or the fit. Record the source and adopted value in assumptions[]; an unambiguous documented default needs no question.

bolt fine medium coarse
M2 2.2 2.4 2.6
M2.5 2.7 2.9 3.1
M3 3.2 3.4 3.6
M4 4.3 4.5 4.8
M5 5.3 5.5 5.8
M6 6.4 6.6 7.0
M8 8.4 9.0 10.0
M10 10.5 11.0 12.0
M12 13.0 13.5 14.5

std_tap_drill — metric coarse tap preparation

lookup(std_tap_drill, bolt, drill) or lookup(std_tap_drill, bolt, pitch), with an enum bolt. Values are lengths in mm. The drill models the plain preparation hole; it does not verify a finished thread.

bolt drill pitch
M2 1.6 0.4
M2.5 2.05 0.45
M3 2.5 0.5
M4 3.3 0.7
M5 4.2 0.8
M6 5.0 1.0
M8 6.8 1.25
M10 8.5 1.5
M12 10.2 1.75

Signatures

Use Param (kind) Default Emits
std.mount_hole (step) d length, at point, axis dir, thick length, locate length locate 2 the primary hole step (id = the use id; <use>.wall, <use>.rim) and <part>__<use>__r; needs target
std.counterbore_hole (step) d, cb_d, cb_depth, thick, locate length; at point; axis dir locate 2 primary styled hole step and <part>__<use>__bore (through the remaining stock), <part>__<use>__cbore (blind from entry to shoulder); needs target
std.countersunk_hole (step) d, cs_d, thick, locate length; at point; axis dir; angle angle angle 90, locate 2 primary styled hole step and <part>__<use>__bore (through full thickness, with countersink at entry); needs target
std.tool_access (part) of part, d length, l length, at point, axis dir, standoff length, gap length standoff 1, gap 0.5 keep-out part <use> and <use>__c
std.datum_plane (requirement) of part, normal dir, at length, offset_tol length offset_tol 0.01 the primary planar_face requirement (id = the use id)
std.spur_gear_bored (step) module length, teeth count, face_width length, bore length, pressure_angle angle, thinning length — the primary spur_gear step (id = the use id; exports the use's bind), its centred through hole step, and the required gear_teeth (<part>__<use>__teeth) and hole (<part>__<use>__bore) requirements

Put covers on the use; it attaches to every requirement the use emits. A step fragment goes in parts[].steps[], a part fragment in parts[], a requirement fragment in requirements[]; anything else is VXL-F104.

Three uses from examples/std_plate.vxl.json:

      {"id": "s03", "use": "std.mount_hole", "target": "body", "args": {"d": "hole_d", "at": [30, 20, 4], "axis": "-z", "thick": 4}, "covers": ["n_mount"]}
    {"id": "tool", "use": "std.tool_access", "args": {"of": "plate", "d": 9, "l": 20, "at": [30, 20, 4], "axis": "-z"}, "covers": ["n_tool"]}
    {"id": "r_bottom", "use": "std.datum_plane", "args": {"of": "plate", "normal": "-z", "at": 0}, "covers": ["n_datum"]}

Convention: a hole and its tool share at and axis. Give std.mount_hole and the matching std.tool_access the same entry point and direction; the tool enters where the screw does. std.mount_hole emits a plain through hole (no counterbore/countersink/thread style and no targets); verify it with a hole requirement. Use std.counterbore_hole or std.countersunk_hole for the shipped through-hole styles. Write a hole step directly for blind, threaded or multi-target construction.

Styled-hole checks. For counterbore_hole: d > 0, cb_d > d, 0 < cb_depth < thick, thick > 0, locate > 0. Its shoulder station is entry station plus the signed drilling direction times cb_depth; the bore spans shoulder to far face. For countersunk_hole: d > 0, cs_d > d, 1 <= angle <= 179, thick > 0, locate > 0, and (cs_d - d) / 2 < thick * tan(angle / 2) so material remains below the cone. Both require a principal-axis inward entry on a planar face and enough material for the style; fragment checks do not prove the entry geometry.

Bored spur gear. std.spur_gear_bored is a step fragment: it exports the use's bind as one external spur_gear (a faceted involute prism within the stated chord bound; not an analytic involute and not an ISO 1328 / AGMA accuracy claim) plus a centred through hole. Its gear_teeth window is derived inside the fragment: axial [-1, face_width+1], radial [bore/2 + wall/2, ra + module] with wall = rf - bore/2. Checks: bore > 0 and bore < 2*(rf - module/100 - 0.01) mm. The nominal root wall must exceed the default chord allowance plus the through-hole cut’s fixed 0.01 mm fuzzy tolerance. The bundled gear_teeth row measures the complete certified tooth band from exact B-Rep trim evidence. Missing evidence keeps the required row HOLD; publication is RELEASE only after every required tooth, bore and clearance demand passes. See the spur gear pair example.

A use's own requirements check the build against the use's arguments, not against the request. A use states the feature once, and the requirements it emits prove that what was built is what the arguments say. A wrong argument (a mount hole moved in the position list, a wrong thick) therefore produces a consistent wrong feature that passes those requirements. Write the arguments from the document's params, and keep one requirement that is written from the request and does not read the use's arguments wherever a number matters (a planar_face at a shoulder, a volume_range, an envelope, a hand-written hole). In Example 11, r_mount_bore and r_mount_counterbore repeat the four positions independently from the request, including the requested bore/shoulder extents. r_volume bounds material, count and depth; it cannot verify where the holes are.

What goes wrong

Symptom Code
std.* or std_* used without the tag / with a wrong version VXL-F103 / VXL-F101
a fragment used in the wrong list VXL-F104
missing/extra target or bind VXL-F108
an enum value outside its domain VXL-E224
a well-typed argument fails a fragment check (e.g. d > 0, thick > 0, locate > 0, gap > 0, offset_tol > 0) VXL-E230, carrying the fragment's message; fix args/<name>
mount_hole's locate window or datum_plane's locator matches the wrong count write a plain hole/planar_face with the locate/near you want

offset_tol sets the face offset only; flatness stays at its default (write a plain planar_face for a different flatness). See VXL §3.4 for your own fragments.

Analytic verified stock

All are step uses with bind; required at:point has no default. Use mm for lengths. Each emits required positional feature requirements; add your own solid/envelope/mesh rows. The five-component example passes development native verification, including the bushing bore on annular ends; development verification does not establish a sealed RELEASE result.

Use Required args Proof
std.conical_stock base_diameter, top_diameter, length, at complete conical_surface, fixed +Z
std.spherical_stock diameter, at full spherical_surface
std.toroidal_stock major_radius, minor_radius, at, axis full toroidal_surface; axis principal token
std.revolved_bushing inner_diameter, outer_diameter, length, at full revolved_profile + outer_diameter + through hole; fixed +Z

Checks: unequal cone diameters, allowed zero apex/nonzero≥0.01; sphere diameter≥0.02; torus minor≥0.01 and major-minor≥0.01; bushing di≥0.02 and do-di≥0.02. Length/radii ceilings and constructor admission still apply. Failed preconditions are E230 at the use with the fragment's message. Other axes use direct cone/revolve and independent requirements. There is no generic profile-valued parameter or unverified wedge wrapper.

Verified dimensional path fragments

These three fragments have category part: write their uses in parts[], with args and optional covers, rather than in a step list with bind or target. All arguments are required and have no defaults. Lengths are in mm; at is a three-length point. axis:dir is a principal direction token. Each fragment creates part <use>, delivers its body, and emits the required measurements listed below; expanded ids follow the ordinary fragment rules in VXL §3.4.

Use Required arguments Construction Required measurements (local ids)
std.round_rod d:length, l:length, at:point, axis:dir pipe from at to at+l*axis, filled circular section solid (solid_count), section (circular swept_section), outer (outer_diameter)
std.rect_transition w:length, h:length, scale:unitless, l:length, at:point loft of centred rectangles at offsets 0 and l, final dimensions scalew and scaleh; fixed +Z placement at at solid (solid_count), sections (loft_sections, linear_vertices), start and end (planar_face at the two cap stations)
std.guided_rect_transition w:length, h:length, l:length, dx:length, dy:length, at:point Three rectangular sections at 0, l/2 and l with XY shifts (0,0), (dx/2,dy/2), (dx,dy); guided_loft, fixed frame, G0, guides lower at vertex0 and upper at vertex2 solid (solid_count), rail0 and rail1 (guide_rail), frame (section_frame, fixed G0), start and end (planar_face)
Fragment checks Accepted ranges
round_rod d=0.02–200000 mm; l=0.01–100000 mm
rect_transition w,h=0.01–100000 mm; scale>0; scalew and scaleh each 0.01–100000 mm; l=0.01–100000 mm
guided_rect_transition w,h=0.01–100000 mm; l=0.02–100000 mm so each station gap is at least 0.01 mm; abs(dx),abs(dy)≤100000 mm

The declared checks report VXL-E230 at the use when false. Constructor bounds and the final part coordinate envelope still apply after those checks. The path requirements are authored from the dimensional arguments in final part coordinates; they are not copied observations. The guided recipe states G0 facets, not general G1/G2 or continuous twist. These fragments add no closed-delivered-mesh or envelope requirement; add those separately when required.

Verified surface part fragments

These two fragments also have category part: write their uses in parts[] with args and optional covers. All arguments are required and have no defaults; lengths are in mm. Each creates part <use> delivering one closed solid and emits the required measurements listed below. The surface statements they emit are exact as built; whether the delivered STEP is admitted stays a build decision.

Use Required arguments Construction Required measurements (local ids)
std.skin_panel size_x:length, size_y:length, base_z:length, sag:length, thickness:length a 3x3 degree-2 height-field skin thickened thickness along +z solid (solid_count), wall (thickened_wall mode along, <use>.base/<use>.top), base/top (spline_surface)
std.height_field_roof size_x:length, size_y:length, base_z:length, sag:length, offset_x:length a stock box at x = offset_x, trimmed below a 6x6 symmetric height-field roof roof_net (spline_surface, trim: any), surface_probe x4 at the quarter points, expected from the control-height profile
Fragment checks Accepted ranges
skin_panel size_x, size_y=0.02–100000 mm; thickness in (0.1, 100] mm (the thicken distance range); base_z>=0 mm; control heights `base_z+thickness+
height_field_roof size_x, size_y=0.2–100000 mm; base_z>=0 mm; box height base_z+sag+2 in [0.01, 100000] mm; base_z+sag>0 mm; control heights `base_z±

The declared checks report VXL-E230 at the use when false. A use that passes them is not refused by the compiler for any value they cover: sizes, box height, thickness, base_z, sag and offset_x are checked against the admitted ranges of the statement fields they feed. These fragments add no closed-delivered-mesh or envelope requirement; add those separately when required. One use each from examples/surface_skin_and_roof.vxl.json:

    {"id": "panel", "use": "std.skin_panel", "args": {"size_x": 40, "size_y": 30, "base_z": 5, "sag": 3, "thickness": 2}}
    {"id": "roof", "use": "std.height_field_roof", "args": {"size_x": 48, "size_y": 40, "base_z": 0, "sag": 4, "offset_x": 0}}

See the surface construction card in MODELING.md and VXL §3.5 for the statements these fragments expand to.

See the path statement and measurement tables for admitted fields and selector limits, and path proof scope for the native evaluation of all four requirement kinds and the distinction between station and complete-span proof. The build runner measures the independently stated std requirements; their presence alone is not obtained evidence or a sealed RELEASE result.

Finishing stock

Two part fragments bundle a finishing statement with the independent requirements that verify it. origin is the box's minimum corner in part coordinates; all arguments are required.

Use Args Emits Proof
std.drafted_box width, depth, height length; angle angle; neutral_z length; origin point a box and a draft on the +Y wall about +Z at the neutral_z station; requirements solid_count + draft_angle the undrafted +Y wall reference (through at origin_y + depth) and the demanded angle about +Z
std.offset_stock_box width, depth, height, distance length; origin point a keep_out reference box and a stock box with face_offset on +Z by distance; requirements solid_count + feature_distance the two +Z planes separated by distance, measured along +Z

Checks: width, depth, height > 0; abs(angle) > 0 and abs(angle) <= 45; 0 < distance <= 20 mm. The draft_angle/feature_distance rows repeat the argument independently of the statement they verify (the wall reference and the two plane stations are written from the args), so a wrong argument produces a consistent wrong feature that those rows still catch. A required failure is E230 at the use. Use neutral_z no higher than height and a planar +Z predecessor; see VXL §7.14 for the statement fields and VXL §10.1 for the requirement tables.

Thread and coil fragments

Four step fragments bundle a modelled thread or coil with its required sections_v1 requirement. All arguments are required except locate (default 2 mm); at is a point, axis a principal direction token, and lengths are in mm. Put covers on the use. The internal minor is authored from the modelled pilot (major - 5*H/4 + 0.06, H = sqrt(3)/2*pitch), never from an ISO formula.

Use Required arguments Construction Required measurements (local ids)
std.threaded_hole major,pitch,minor,depth,at,axis,audit_from,audit_to hole with thread:{pitch}, depth as the blind depth; fixed right, one start thread (internal, ends:"blind", length:depth) and floor (planar_face at the blind floor); add solid/mesh rows
std.thread_stud major,pitch,minor,length,at,axis,audit_from,audit_to thread external full_profile, root length, fixed right, one start thread (ends:"full_profile", from:-3*pitch/8, flank length:length+3*pitch/4); add solid/mesh rows
std.thread_boss major,pitch,minor,length,outer,at,axis,audit_from,audit_to thread internal trimmed blank outer_diameter:outer, fixed right, one start thread (internal, ends:"through") and outer (outer_diameter); add solid/mesh rows
std.coil radius,wire,pitch,turns,at,axis helix family:"coil", circular wire section, ends:"plain", end_coils:0, fixed right, one start helix (plain, circular section); add solid/mesh rows
Fragment checks Accepted ranges
threaded_hole, thread_stud, thread_boss pitch 0.1–10 mm; major >= sqrt(3)*pitch and ≤ 100000 mm; minor above 0 and below major; length/depth contains 1–64 turns (>= pitch, <= 64*pitch); audit_from >= 0 < audit_to <= length/depth; locate in (0,100000] mm
thread_boss (extra) outer - major >= 0.02 mm and outer <= 100000 mm
coil radius 0.2–100000 mm; wire 0.1–100000 mm and < 2*radius; pitch 0.1–100 mm; turns in (0,64]; locate in (0,100000] mm

A failed precondition is VXL-E230 at the use with the fragment's message. The statement's own constructor bounds and the terminal-feature restriction (VXL-C418) still apply. The full-profile external threads from std.thread_stud have measured finite sections, uncut ends and recorded overhang, with all three stud corpus subjects published RELEASE. Native admission and independently declared requirements still decide each body and parameter choice. See the thread statement and thread/helix requirements.

Nominal hardware recipes

The six hardware tables record nominal dimensions and their ISO editions in notes. They describe purchased-part envelopes; no fit or tolerance class is implied. Size args are quoted enum expressions, e.g. "size": "'M3'" or "size": "'608'". Screws/nuts support M3/M4/M5/M6/M8/M10. Bearings support 623/624/625/626/608/6000/6001/6002/6200/6201.

Fragment Construction and independent required measurements
std.screw_seat (step, target) ISO 273 medium through bore + ISO 4762 head counterbore; two hole requirements. at is the inward entry; thick must exceed head height + clearance.
std.nut_pocket (step, target) Hex pocket along -Z from at; ISO 4032 across-flats + twice (clearance + 0.01 mm), depth = height + clearance + 0.01 mm. The construction allowance keeps the nominal gap above the required clearance after measurement uncertainty; the requirement still measures the full requested clearance. nut names a separately positioned nominal keep-out; emits clearance + pocket-floor planar_face. Clearance must be (0,2] mm.
std.screw_envelope (part) Keep-out union of nominal shank, head and tool cylinder; emits clearance from of. at is the shank/head junction; shank follows axis, head/tool go opposite. Positive lengths/gap; tool_d >= head diameter.
std.bearing_seat (part) Deliverable +Z cylinder at at, bearing-width blind seat above a shoulder, bore through shoulder; emits two hole rows + shoulder planar_face. Positive shoulder/clearance/wall; outer > seat diameter + 2*wall.

All dimensions are mm; wall controls stock sizing, not a minimum-wall measurement. There are no cosmetic threads. The screw envelope demands an entirely separated insertion/tool volume; intended head contact needs contact requirements or separate std.tool_access instead. A nonpositive geometric argument is VXL-E230; a size outside the domain is VXL-E224. The fixtures show each use. macOS native verification is a development HOLD. Its authority leaves clearance rows not_measured (development_cell_unqualified); those two rows need a Linux verification cell. Measured requirement verdicts do not qualify a release cell.

Generated std inventory

One row per shipped table, fragment or function. Parameters without = are required. Regenerate with vextor vxl reference --block std-signatures; verify this file with vextor vxl reference --check docs/skills/vextor-vxl/STD.md.

<!-- generated:reference:std-signatures -->
Entry Category Parameters / columns (types, defaults) Tables read
std_iso_273 table coarse: length, fine: length, medium: length —
std_tap_drill table drill: length, pitch: length —
std_iso_4762 table d: length, head_d: length, head_h: length, pitch: length, socket: length, socket_depth: length —
std_iso_4017 table across_flats: length, d: length, head_h: length, pitch: length —
std_iso_4032 table across_flats: length, d: length, height: length, pitch: length —
std_iso_7089 table inside: length, outside: length, thickness: length —
std_iso_8734 table diameter: length —
std_bearing_deep_groove table bore: length, outside: length, width: length —
std.mount_hole step d: length, at: point, axis: dir, thick: length, locate: length = 2 —
std.tool_access part of: part, d: length, l: length, at: point, axis: dir, standoff: length = 1, gap: length = 0.5 —
std.datum_plane requirement of: part, normal: dir, at: length, offset_tol: length = 0.01 —
std.counterbore_hole step d: length, cb_d: length, cb_depth: length, at: point, axis: dir, thick: length, locate: length = 2 —
std.countersunk_hole step d: length, cs_d: length, at: point, axis: dir, thick: length, angle: angle = 90, locate: length = 2 —
std.conical_stock step base_diameter: length, top_diameter: length, length: length, at: point —
std.spherical_stock step diameter: length, at: point —
std.toroidal_stock step major_radius: length, minor_radius: length, at: point, axis: dir —
std.revolved_bushing step inner_diameter: length, outer_diameter: length, length: length, at: point —
std.round_rod part d: length, l: length, at: point, axis: dir —
std.rect_transition part w: length, h: length, scale: unitless, l: length, at: point —
std.guided_rect_transition part w: length, h: length, l: length, dx: length, dy: length, at: point —
std.drafted_box part width: length, depth: length, height: length, angle: angle, neutral_z: length, origin: point —
std.offset_stock_box part width: length, depth: length, height: length, distance: length, origin: point —
std.spur_gear_bored step module: length, teeth: count, face_width: length, bore: length, pressure_angle: angle, thinning: length —
std.skin_panel part size_x: length, size_y: length, base_z: length, sag: length, thickness: length —
std.height_field_roof part size_x: length, size_y: length, base_z: length, sag: length, offset_x: length, grid: count = 6 —
std.split_pair step normal: dir, through: point, negative: name, positive: name —
std.imprint_rect step on_normal: dir, on_at: length, min_x: length, min_y: length, max_x: length, max_y: length, region: name —
std.threaded_hole step major: length, pitch: length, minor: length, depth: length, at: point, axis: dir, audit_from: length, audit_to: length, locate: length = 2 —
std.thread_stud step major: length, pitch: length, minor: length, length: length, at: point, axis: dir, audit_from: length, audit_to: length, locate: length = 2 —
std.thread_boss step major: length, pitch: length, minor: length, length: length, outer: length, at: point, axis: dir, audit_from: length, audit_to: length, locate: length = 2 —
std.coil step radius: length, wire: length, pitch: length, turns: unitless, at: point, axis: dir, locate: length = 2 —
std.screw_seat step size: enum, at: point, axis: dir, thick: length, clearance: length, locate: length = 2 std_iso_273, std_iso_4762
std.nut_pocket step size: enum, at: point, clearance: length, nut: part std_iso_4032
std.screw_envelope part of: part, size: enum, at: point, axis: dir, length: length, tool_d: length, tool_l: length, gap: length std_iso_4762
std.bearing_seat part size: enum, at: point, outer: length, shoulder: length, clearance: length, wall: length std_bearing_deep_groove
std.pcb_post step at: point, diameter: length, height: length, pilot: length, wall: length, draft: angle = 0, drafted: bool = "false", ribs: count = 0, rib_length: length = 2, rib_thickness: length = 1, fillet: bool = "false", root_radius: length = 0.5 —
std.rest_pad step at: point, width: length, length: length, height: length, draft: angle = 1, drafted: bool = "true", wall: length —
std.rim_lip step outline: profile, at: point, side: enum = "'inside'", inset: length, width: length, height: length, probe: point —
std.snap_arm step at: point, length: length, thickness: length, width: length, hook: dir, direction: dir, catch_depth: length, catch_length: length, embed: length —
std_hex_bumps function x: unitless, y: unitless, pitch: unitless, phase: unitless, radius_ratio: unitless —
std_ramp function x: unitless, lo: unitless, hi: unitless —
std_smooth_band function x: unitless, lo: unitless, hi: unitless, width: unitless —
<!-- /generated:reference:std-signatures -->

Enclosure recipes

All three are step fragments with target, in mm. Their requirements measure the final host; a later cut can invalidate them. Nominal dimensions do not certify a print process.

Use Construction and requirements
std.pcb_post Post at at, cylindrical for zero draft or conical for positive draft (drafted must agree). Optional 0–4 radial ribs; optional root fillet requires zero ribs. Pilot blind hole, centred top planar face (XY centroid within pilot/4 of the axis) and top-face wall disk are required.
std.rest_pad Box at at, optionally drafted on +Y about +Z at its base, then unioned into host. Required top, wall disk and (when drafted) draft angle; its undrafted wall reference is at pad mid-height, with the neutral plane at the base and a wall.near window around the pad to exclude other host walls.
std.rim_lip Pass the enclosure outline profile (object or authored profiles[] id), rim plane at_z, side 'inside'/'outside', positive inset/width/height, and required probe on the lip's top. Two offsets and their difference form the ring; +Z extrusion is unioned to host. Required top plane and local minimum_wall ≥ width within ordinary tolerance.

For inside, the ring is offset(-inset) minus offset(-(inset+width)); for outside, offset(inset+width) minus offset(inset). Existing offset failures reject collapsed regions. The outline remains in its authored XY coordinates; at sets the rim plane, without XY translation. Pick probe strictly inside the flat ring top, at z=at_z+height; its disk radius is width/8. The minimum_wall disk measures material depth normal to that top face, not a global radial-wall bound. There is no mate/gap parameter: write an explicit clearance requirement against the mating part.

Pcb checks require positive post/pilot/wall and sufficient top diameter; draft 0–15 degrees; 0–4 ribs; positive rib sizes and root_radius < height/2; fillet with ribs is E230. Rest-pad checks require positive width/length/wall, height > wall and non-closing 0–15 degree draft. See the fixtures.

Snap arm

std.snap_arm(at, length, thickness, width, hook, direction, catch_depth, catch_length, embed) is a step fragment unioned into target. direction and hook are perpendicular principal directions. A single rigid frame maps local +Z along direction, +X along hook, and +Y along direction×hook; all 24 perpendicular pairs are admitted. at is the arm root, with embed behind it; the catch ramps from length−catch_length to the flat tip at length.

Positive lengths are required, with catch_length and embed shorter than length. Parallel (or antiparallel) directions and catch_length≥length refuse E230. Independent requirements measure final-host width between the side planes and the flat tip plane. A later cut can invalidate the tip check. No mate/gap: author clearance against a mating part separately. These geometric checks do not certify snap load, fatigue, material or print behaviour. See Example 38.