Checking
Independent intent
Requirements describe the user’s needs independently of the model and its selectors.
vxl check admits syntax and types; only a build obtains geometric evidence.
If exact-solid admission fails, inspect summary structural_gate and warnings; solid_count
is not_measured with structural_gate_failed even when the raw count matches its nominal.
Requirements
Requirement cookbook
Each exact feature requirement locates one feature. For delivered mesh kinds use the mesh card.
A planar_face / std.datum_plane is a plane: several
coplanar faces (feet, a mirrored or patterned part, a face split by a groove) are measured as one.
normal is outward from the material; on a pocket or groove face it points into the void (groove
floor: +z). A build row opposite_normal_at_station means: reverse normal. There is no
expect field (VXL-R601). Use near or requirement at_each to disambiguate. Defaults
materialize at check time.
Feature → statement → the requirement that catches it being wrong. "Catches" means a build
with that mistake does not RELEASE. Every exact part also takes solid_count and
closed_delivered_mesh; mesh topology uses component_count instead of solid_count.
| Statement / feature | Requirement that catches it | Cannot be measured |
|---|---|---|
box |
envelope (bounds), planar_face, volume_range; sharp_boundary for an unmodified straight crease |
— |
cylinder |
outer_diameter (outward wall, axis and one maximal full-turn band), envelope, planar_face, volume_range |
roundness, unsupported trims |
extrude |
envelope, a tilted planar_face (normal+through+near), volume_range |
curved sides |
union |
solid_count (bodies that did not join), envelope/volume_range, fillet_radius/planar_face at the joint |
— |
cut |
slot for a through/blind stadium profile, hole for a cylindrical tool; planar_face+near for a pocket floor or shoulder; minimum_wall; envelope/volume_range |
unsupported floor/profile forms |
intersect |
envelope, volume_range, planar_face |
— |
pattern |
envelope/volume_range (count and spacing as extent/material); one at_each requirement per instance that matters |
which instance is where; a requirement never counts |
mirror |
envelope/volume_range; the feature's own requirement at its mirrored position |
— |
hole, through |
hole with through:[a,b] (diameter, axis, position, both ends) |
— |
hole, blind |
hole with blind:{mouth:<len>,floor:<len>} |
a blind hole whose floor corner is chamfered |
hole + counterbore |
two hole on one axis: bore through:[far face, shoulder], counterbore blind:{mouth:entry,floor:shoulder}; planar_face at the shoulder |
the counterbore diameter except through that second hole; a chamfered inner corner |
hole + countersink |
one hole over the whole thickness (or blind) with countersink:{diameter,angle,at}; opposite-end mouths sharp expectation composes |
omission of mouths makes no style-absence claim; unknown blend chains stay not measured |
hole + thread |
a required thread with measurement:"sections_v1", an explicit locator, ends:"blind" or "through" and an audit range; a blind hole also takes a planar_face floor |
finite planes only; no whole-surface certificate; full-profile external ends and overhang are measured |
thread (external/internal) |
required thread with measurement:"sections_v1"; author major/minor/pitch/length/winding/ends yourself |
the internal flank form; the whole surface between the finite planes |
helix / coil / spring |
required helix with measurement:"sections_v1"; plain ends only |
physical spring load, stiffness, fatigue; the family spelling |
multi-target hole |
one hole/through per wall the drill crosses |
a range over two walls (a cardinality mismatch) |
fillet |
fillet_radius for local size; finishing_run for the complete stated interval |
curved faces, hole rims, both ends mitered → volume_range only |
chamfer |
chamfer_size for local size; finishing_run for complete convex perpendicular run; a mouth chamfer is the hole's countersink |
concave (VXL-R670) or non-perpendicular edges; a counterbore inner corner or blind floor corner makes the hole not_measured; a chamfer on a curved edge or a countersink has no measurable kind (VXL-V811) |
place |
envelope with bounds; the feature's requirement where the move puts it |
size cannot see a move; a body symmetric under the rotation |
shell |
minimum_wall (disk on an outer face), planar_face at outer ± thickness, volume_range, hole through:[outer, outer±wall] per wall; for a sealed exact cavity, enclosed_cavity_count with required: true and expect: N |
cavity shape or void volume; opening the wrong face with the right count |
split + partition |
partition on its checkpoints (count, side, exact cut areas, no overlap; full_v1 adds coverage and volume); each piece's own requirements |
an unstated cut law; a B-spline face portion by name (G401) |
imprint + imprint_region |
imprint_region (locate, extent, area, boundary); planar_face still measures the support as one plane |
the imprint's material (it changes none); the old support face name where one face is needed (G408) |
| two parts | clearance (min, or contacts for a designed contact) |
a flat B-spline contact (reported absent) |
Measurement card: outer_diameter needs diameter, principal axis, axis_at and
span:{from,to} equal to one maximal full-turn band of the observed outward cylinder wall
(within boundary tolerance), not an arbitrary sub-interval of a band. A band is a connected
station interval where the validated chart cells cover the whole turn exactly once; it ends at
a full circular ring or at a retained boundary station where coverage becomes partial. A plain
complete wall has one band equal to its full axial extent. With several bands, the authored span
selects the matching band; if none matches, the row is a measured Fail and reports every observed
band. A later Boolean may therefore leave a measurable intact band even when it notches another
part of the same wall. The candidate's existing wall_incomplete classification is retained;
nonempty bands make only the matching OD span measurable. Unsupported non-line trims remain
wall_trim_unsupported. The completeness rule for hole is unchanged. For a grip at z=20 with
length 56 ending at the guard's bottom face z=76, write the whole maximal band:
{"id":"r_grip_od","kind":"outer_diameter","subject":"dagger","diameter":24,
"axis":"z","axis_at":[0,0,0],"span":{"from":20,"to":76}}
sharp_boundary and
finishing_run need independent between:{first:{planar:{normal,at|through}},second:{planar:{normal,at|through}}}
and run:{axis,from,to} with increasing endpoints; no names or nested near.
A finishing run adds exactly one finish:{fillet:{radius,tol?}} or
finish:{chamfer:{distance,tol?}}. Every relevant segment must qualify, and interior gaps fail;
local size rows do not prove full coverage. A blind slot uses blind:{mouth,floor} instead of
through; its complete planar stadium floor and empty observed prism are measured. Slot/OD
boundary defaults to position; slot boundary is positive, below width/2 and half blind depth
(R689). Equal blind mouth/floor stations first report R611 at blind; change one station to
the intended open end or floor, since no positive tolerance can create depth. Position may be
zero with explicit positive boundary. A complete connected split bore
is one measured group with every sorted member face; disconnected walls remain separate and
unsupported trims cannot pass. Write mouths:[{at:<declared open station>,style:"sharp"}] for
an explicit sharp opening; omit it only when no absence-of-modification claim is intended.
Complete Sharp chains pass, proved modifications fail, and Unknown/incomplete chains stay not
measured. See the tested mouth and split recipes.
Sharp-mouth/split-bore corpus: 18 fixtures, six RELEASE and twelve designated-row HOLD in the recorded native measurements.
A sharp-run gap with proved detail.modified_intervals requires removing the chamfer, fillet
or break-producing cut in parts[].steps to restore the raw crease over run.from..run.to.
A finishing-run gap instead requires finishing the missing segment with the authored finish.
Correct between or run only if they misstate the intended geometry. For ambiguous cylinder
groups, narrow positive locate around axis_at only when axes differ; coaxial groups instead
need the intended diameter and span or through/blind extent to distinguish them, or
removal of unintended competing geometry. For per-probe resource limits, simplify topology in
parts[].steps on subject; removing redundant requirements alone cannot repair that scan.
Full rules: VXL §7 (statements) and §10.1 (requirement kinds).
Locate a requirement by geometry written from the document's params (normal with at/through),
not by a construction face name: a requirement that names the faces its own step's selector used
follows the same wrong build (VXL-W980).
| Kind | Template | Cannot prove |
|---|---|---|
solid_count |
{"kind":"solid_count","subject":"bracket"} |
anything about shape |
envelope |
{"bounds":{"min":[0,0,0],"max":[30,40,40]},"tol":0.05} |
interior features |
gear_teeth |
{"subject":"wheel","axis":{"at":[0,0,0],"dir":[0,0,1]},"window":{"axial":[-1,9],"radial":[10,30]},"module":2,"teeth":24,"pressure_angle":20,"face_width":8,"measurement":"prism_section_v1"} |
complete raw-trim prism evidence is required; explicitly demand tol.base / tol.angle for separately bracketed base diameter / pressure angle; helical/bevel/worm/internal teeth, racks, root fillets, tip relief; an ISO 1328 / AGMA grade |
hole |
{"diameter":4.5,"axis":"z","axis_at":[15,14,0],"through":[0,4],"tol":{"diameter":0.05,"position":0.05}}; blind "blind":{"mouth": 12, "floor": 7.6}; countersink "countersink":{"diameter":6.8,"angle":90,"at":40} |
thread geometry needs a separate thread requirement, including for full-profile external threads; which cylinder when two coaxial ones are equally close |
slot |
{"from":[8,10,0],"to":[22,10,0],"width":6,"through":[0,5], "axis": "z"} |
a non-obround slot |
planar_face |
{"normal":"-z","at":0,"near":{"x":[0,30],"y":[0,40]},"flatness":0.01,"tol":{"offset":0.05}}; tilted: normal:[0,0.866,-0.5] + through |
sharp boundaries, face angles |
fillet_radius |
{"radius":1,"between":[{"planar":{"normal":"+z","at":"plate"}},{"planar":{"normal":"+y","at":"arm"}}]} |
supports not two planar faces 10–170° apart; a face with no cross-section end; a nested near inside between (VXL-R671) or two named supports whose bounds do not meet (VXL-R672) |
chamfer_size |
{"distance":0.5,"between":[{"planar":{"normal":"+z","at":"height"}},{"planar":{"normal":"+x","at":"width"}}],"tol":0.05} |
non-perpendicular supports; a concave edge. It checks three things: both setbacks equal distance, both faces of between are where you say, and the chamfer is 45 degrees. Write between as the two faces the chamfer step's edge lies between, with their real stations; if the stock dimension is a parameter, write the station with the same parameter (e.g. {"normal": "+z", "at": "height"}), not a number |
thread |
{"form":"internal","major_diameter":4,"minor_diameter":3.3022277717,"pitch":0.7,"length":6,"ends":"blind","audit":[1,5],"tol":{"diameter":0.05,"profile":0.05}} with an explicit axis/at locator or a feature datum; add measurement:"sections_v1" |
the internal flank form; the whole surface between the finite planes |
helix |
{"radius":7,"pitch":3.2,"turns":3.25,"section":{"circle":{"diameter":1.4}},"ends":"plain","end_coils":0} with measurement:"sections_v1" and a locator |
physical load/stiffness/fatigue; the family spelling |
volume_range |
{"min":"0.999 * a * a * a","max":"1.001 * a * a * a"} (nominal as a formula; never min=max) |
where material is |
closed_delivered_mesh |
{"artifact":"stl"}; on a cavity-bearing exact subject also require {"kind":"enclosed_cavity_count","subject":"part","expect":N} |
Core 3MF (not decoded); cavity count by itself |
component_count |
{"subject":"part","expect":2}; this is the literal surface-component topology count, so one outer plus one inner shell is 2 |
material occupancy, closure, containment or orientation |
enclosed_cavity_count |
{"subject":"part","expect":1,"required":true}; exact and mesh delivered subjects |
void shape, void volume, drainage or accessibility |
clearance |
{"operands":["bracket","tool_base"],"min":0.5} (min > 0); designed contact "contacts":[{"planar":{"normal":"+z","at":12}}] |
a flat B-spline contact (reported absent) |
minimum_wall |
{"min":3,"tol":0.02,"disk":{"on":{"planar":{"normal":"+x","at":3}},"center":[3,12,12],"radius":1.5,"margin":0.5}} |
the thinnest point of a whole feature; exact nominal thickness |
unmeasured |
{"describe":"all exposed faces are surface grind Ra 1.6"} |
declared_unmeasured; detail.describe and the explanation retain the authored text and name kind/required choices; use a supported measurable claim or required:false for an intentionally optional disclosure (the latter does not measure the claim) |
minimum_wall.min is a lower threshold; the decision depth is min - tol with
0 <= tol < min. disk.margin must be positive and is additional clearance from the disk
perimeter to every boundary of its selected face, not a thickness tolerance.
hole.blind names its open end and floor as {"mouth":<len>,"floor":<len>}. A slot
names 3D end-centre points with from and to, a width, an axis, and exactly one
through:[from,to] or blind:{mouth,floor}. Endpoint components along axis are ignored.
The retired positional hole extent is an error (VXL-R674).
Reserved gap kind (reported unsupported, HOLD when required): global_wall. opening has a
closed mesh-only payload (mesh card); it is refused on an exact subject.
Kinds that used to be reserved are now measurable: thread, helix, gear_teeth, gear_mesh,
slot, counterbore, blind_hole, fillet_radius_general, contact_clearance,
chamfer_size, feature_distance and text. The spellings counterbored_hole,
countersunk_hole, fillet, contact and chamfer are refused as removed aliases (for
countersunk_hole write kind: "hole" with a countersink style; countersink.at is allowed
only on a through hole). thread, helix and material_region are measurable kinds, not reserved.
For material_region, author a cylinder {origin,axis,radius,length} or a right-handed box
{origin,x,y,z,size}, expected state:"material" or "void", and positive boundary_clearance.
Complete planar/cylindrical boundary exclusion and an actual interior classifier are required;
unsupported carriers, incomplete proof and exhausted fixed proof budgets keep required rows at
HOLD. A wrong interior state after complete exclusion or a certified boundary witness FAILs.
Any other kind is VXL-R602.
Keep-out recipes
A keep-out is a part with role:"keep_out". It is verified, never delivered; acceptance is
forbidden. Author it in the same frame as the request, then write a clearance requirement against
the deliverable.
| Recipe | Shape | Rule |
|---|---|---|
| Tool access | cylinder at the screw axis, axis into the part | start the tool off the entry face; clearance.min > 0 |
| Fastener head | cylinder or box around the head axis | cover the head diameter plus a small ring |
| Fit gauge | the mating profile as an extrude | stand it off the seat; a designed contact is clearance with contacts, never min: 0 |
| Cable path | a box/cylinder sleeve | keep clearance.min off every nearby face |
Stand-off rule. Touching counts as a collision. Start every keep-out more than clearance.min
away from the seat face, or, when the two are meant to touch there, declare that plane in the
clearance's contacts and keep min positive. VXL-W930 fires for any clearance whose operands
meet on an undeclared plane, or whose declared contact the predicted boxes do not meet (static,
predicted boxes only; silence is not measured proof).
Evidence grades
Exact
Exact evidence proves only the measured claim on its named subject. A static check is not a measurement.
ConservativeBound
Under mesh_conservative_v1, Exact PASS or a safe-side ConservativeBound may pass.
Keep each measurement’s admission and locator limits from the mesh card.
Estimate and diagnostic-only
An Estimate never satisfies a required check. Compact replies, entity filters and diagnostic previews never decide RELEASE. Required Unknown, incomplete admission and exhausted budgets hold.
HOLD and repair
Read report/summary.json and report/revision-packet.json; fix one typed problem and rebuild
within the gated loop budgets. Unresolved problems mean HOLD.
Use vextor vxl explain FILE --target ID for source expression dependencies; repair
X101 using its bounded candidates (compact replies show the first candidates), and use Q501
did_you_mean only as spelling help.
Traps
Each line is a trap with the code it raises. vextor vxl explain CODE prints the full rule.
| Trap | Code |
|---|---|
A thread hole needs a numeric depth, is cut after every other feature of its binding (shell, fillet, chamfer, Boolean), and verifies only through a required thread requirement with measurement:"sections_v1" |
VXL-C415, VXL-C418, VXL-W977 |
| A thread pitch must be ≤ half the diameter and 1–64 turns; a thread costs about 1,300 triangles per turn | VXL-C416, VXL-W973 |
A counterbore or countersink must fit the material behind its entry face (the wall of a shelled part), else VXL-C440 at the style or VXL-X109 at build; a blind hole deeper than the wall is a port and has no floor |
VXL-C440, VXL-X109, VXL-Q513 |
A through range is per wall: one drill through two walls takes one requirement per wall [outer, outer±wall]; a range over both is a mismatch |
build not_measured: locator_cardinality_mismatch |
volume_range needs a real range (never min = max): a correct 10 mm cube measures 999.9999999999998 mm³ |
build HOLD |
| A requirement that names the faces its own step's selector used is not independent | VXL-W980 |
Without countersink or an explicit mouths sharp expectation, no absence-of-cone claim is made; a complete sharp expectation fails on a proved cone/shoulder |
VXL-R683 rejects a same-end countersink/sharp conflict |
| Unsupported floor/inner-corner forms cannot pass a hole proof; a mouth chamfer is an observed cone, while unsupported fillet/blend chains remain Unknown/not measured | — |
A chamfer with no chamfer_size requirement is warned; a counterbore mouth chamfer is re-read as a countersink of the counterbore |
VXL-W920 |
| A chamfer on a curved edge (a rounded-corner arc, a boss rim, a hole floor or shoulder, a countersink) has no measurable kind | VXL-V811 |
| A delivered thread or helix without a required typed feature requirement is warned; full-profile external threads are measured with uncut ends and recorded overhang | VXL-W977 |
clearance contacts are 1–4 distinct principal-axis planes with min > 0 and positive area; a tilted normal is refused |
VXL-R669, VXL-R665, VXL-R620 |
chamfer_size is convex and perpendicular only |
VXL-R670, VXL-R664 |
A second shell on the same body, or on a body composed with it, is refused |
VXL-C436 |
Faces opened by a shell change only its target: a name another live binding still carries is refused, and proven removals are reserved |
VXL-N122, VXL-Q513 |
A shell's open takes 1–8 distinct face selectors (no edge, no hole rim); thickness is (0, 20] mm |
VXL-Q511, VXL-Q512, VXL-Q514, VXL-C411 |
| The kernel cannot build every shell: the build fails and installs nothing | VXL-X106 |
| A second hole on the axis of a first is not buildable (so a styled hole with a countersunk mouth is not expressible) | VXL-X104, VXL-C410 |
| One style per hole; its diameter must exceed the hole and its depth fit the extent | VXL-C412, VXL-C413, VXL-C417 |
| A fillet or chamfer at the countersink neck (cone meets bore) is refused | VXL-C419 |
fillet_radius supports must be two flat faces 10–170° apart |
VXL-R661 |
A countersink expectation's at is the mouth station; at on a blind hole, or a tolerance alone, is refused |
VXL-R666, VXL-R667, VXL-R668 |
A slot needs distinct from/to end centres, positive width, and exactly one nonempty through or directed blind |
VXL-R662, VXL-R663, VXL-R611, VXL-S011 |
One entity per requirement: no expect field, no invented kind |
VXL-R601, VXL-R602 |
A place or shell that cannot move or remove a contained name safely (another live binding shares it) |
VXL-N122 |
| A hole enters square to its face; a tilted, sideways or outward axis is refused, never snapped | VXL-C441 (first hole of a box or cylinder), VXL-X111 (build) |
fillet_radius is not_measured: unsupported_representation with explanation "end arc sweep differs from the expected sweep by … rad": the rounded face does not run the full angle between the two faces in between — another feature cut it, or between names a face the fillet does not end on. Check between (and near); a residual of a whole fraction of a turn (0.785 = 45°) means a different pair of faces |
— |
| Hole/OD boundary must be positive; slot boundary must be positive, below half width and half blind depth; default errors point at originating position | VXL-R611 (hole/OD), VXL-R689 (slot) |
between: a nested near inside a planar query (VXL-R671); two named supports whose construction bounds do not meet (VXL-R672) |
VXL-R671, VXL-R672 |
| An outward cylinder (boss/standoff) is retained as an exclusion from inward hole matches; use OD for one whole maximal full-turn band | outer_diameter |
A blind hole deeper than its wall is a port: it builds and has no floor |
VXL-Q513, VXL-X101 |
A multi-target hole needs targets 2–8 distinct bindings, each with a planar entry face at at |
VXL-C432–VXL-C435 |
toward not perpendicular to the plane; a quaternion rotation |
VXL-G310/VXL-G311, VXL-G320 |
A Boolean target = tool; at and center together; a disjoint tool; a cut that splits the part |
VXL-C401, VXL-W970/VXL-W971, solid_count |
A fragment, use or std problem; a name containing __; a reference to a repeated use |
VXL-F1xx, VXL-N104, VXL-N101 |
A selector without expect; the wrong edge count at build |
VXL-Q502, VXL-X101 |
A split needs both sides of its cutter; a missing side, a repeated side, or bind together with count is refused |
VXL-C512 |
A split or imprint on a body carrying a modelled thread, coil or gear is refused in this version |
VXL-C516 |
A partition needs scope, 2–8 pieces and a real split step; a section statement is refused (write section_contour) |
VXL-R742, VXL-R740, VXL-C519 |
After an imprint the old support face is two faces; select <region> or <region>.outside, and never fillet/chamfer the flat imprinted boundary |
VXL-G408 |
A keep-out flush with its seat; an occurrence that touches nothing; a need with no covers or unmodeled |
VXL-W930, VXL-W940, VXL-W950 |
Final-file checks
Output contract
- Exactly one authored source file:
<name>.vxl.json,schema: "vextor.vxl.v1", units mm and degrees. Native delivery files (such as STEP, STL or 3MF) are separate outputs produced by a build. - Prefer composition: define a reusable shape in
defs[]anduseit, useat_eachfor statements andeachfor array entries, and use the sealedstdlibrary (declare"std": "vxl-std-2") for screw holes, tool access and datums. Auseexpands in place at check/build time; the expanded form is what runs, and no private__id is ever writable. - Write the compact form: omit
title,notesand every field that equals its default; use typed functions for repeated formulas,variants[]for named finite override sets, and define adefs[]fragment when the same group of statements would otherwise appear three or more times. - A missing fact is blocking when different answers give geometrically different parts or it is an
interface dimension of something the user owns. Ask via
questions[];checknever blocks on it. - If you reuse a standard dimension, declare the source in
assumptions[]; a length param whose id starts withhead_,nut_,washer_,screw_,bolt_,thread_orinsert_and is not sourced isVXL-W960— take it from astd_table, record it, or rename it. - Run
vxl checkuntil clean before uploading. Never present a document you have not checked.
Executable facts
The stdlib test instructions cover check versus measure, a missed hole, selector cardinality, Estimate/HOLD and compact HOLD. The 20-document manifest uses existing handwritten examples; check success makes no new build verdict claim.
Delivery decision
Every required need must have acceptable measured evidence. Read the actual label and cell; macOS arm64 development builds remain HOLD. Deliver HOLD files with that label and unresolved questions visible; only an obtained RELEASE may be called RELEASE.
Conventions card
Paste-ready prompt card: CONVENTIONS.md. std library: STD.md; the reference states each rule once.
Examples
- req_chamfer_size
- req_fillet_general
- req_sharp_boundary