prechips 0.1.2__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {prechips-0.1.2 → prechips-0.2.0}/PKG-INFO +77 -13
- {prechips-0.1.2 → prechips-0.2.0}/README.md +76 -12
- {prechips-0.1.2 → prechips-0.2.0}/pyproject.toml +3 -1
- {prechips-0.1.2 → prechips-0.2.0}/pyproject.toml.orig +3 -1
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/__init__.py +1 -1
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/cli.py +19 -6
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/findings.py +5 -2
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/inputs.py +175 -20
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/joint_features.py +68 -28
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/kernel/__init__.py +321 -16
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/kernel/freecad_job.py +1158 -58
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/kernel/render_diagram.py +32 -1
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/kernel/render_inputs.py +8 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/measurements.py +78 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/model.py +545 -37
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/process_features.py +106 -15
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/__init__.py +10 -2
- prechips-0.2.0/src/prechips/rules/_bench.py +73 -0
- prechips-0.2.0/src/prechips/rules/_cutting_force.py +226 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/accessibility.py +5 -0
- prechips-0.2.0/src/prechips/rules/blank_credit.py +384 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/centre_support.py +3 -3
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/consistency.py +31 -14
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/coordinates.py +94 -21
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/coverage.py +134 -7
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/finish_route.py +2 -2
- prechips-0.2.0/src/prechips/rules/guided_sweep.py +1287 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/headroom.py +28 -9
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/hold_fields.py +2 -2
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/inspection.py +228 -36
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/joints.py +8 -4
- prechips-0.2.0/src/prechips/rules/keep_piece.py +92 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/level_entry.py +4 -1
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/manual_arc.py +174 -8
- prechips-0.2.0/src/prechips/rules/parting_face.py +44 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/prepared_blank.py +11 -8
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/resolution.py +120 -17
- prechips-0.2.0/src/prechips/rules/saw_cut.py +166 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/speeds_feeds.py +39 -2
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/thin_wall_under_clamp.py +4 -2
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/tip_endpoints.py +3 -2
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/tool_resolves.py +40 -16
- prechips-0.2.0/src/prechips/rules/tooling_hole.py +331 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/travel.py +25 -4
- prechips-0.2.0/src/prechips/rules/zero_recipe/__init__.py +1 -0
- prechips-0.2.0/src/prechips/rules/zero_recipe/faces.py +305 -0
- prechips-0.2.0/src/prechips/rules/zero_recipe/native.py +1237 -0
- prechips-0.2.0/src/prechips/rules/zero_recipe/rule.py +517 -0
- prechips-0.2.0/src/prechips/rules/zero_recipe/tool_setting.py +719 -0
- prechips-0.2.0/src/prechips/rules/zero_recipe/touch.py +341 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/sheet.py +471 -161
- prechips-0.2.0/src/prechips/sheet_sweep.py +327 -0
- prechips-0.1.2/src/prechips/rules/_bench.py +0 -52
- prechips-0.1.2/src/prechips/rules/saw_cut.py +0 -111
- prechips-0.1.2/src/prechips/rules/zero_recipe.py +0 -2956
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/clamp_labels.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/kernel/boolean_pool.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/kernel/chain_boundary.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/kernel/render_png.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/kernel/step_faces.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/report.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/_envelope.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/_profile.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/construction.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/datum_consistency.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/engagement.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/envelope.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/finish_coverage.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/fixture_interference.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/geometry_common.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/indexing.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/internal_corner_radius.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/op_chain.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/op_order.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/purchased_tooling.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/reach.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/sizing.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/stickout.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/stock_diameter.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/turned_profile.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/turning_deflection.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/rules/vise.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/telemetry.py +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/tokens.css +0 -0
- {prechips-0.1.2 → prechips-0.2.0}/src/prechips/trig.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: prechips
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Checks before chips: deterministic validation of machining process plans against part geometry and a shop inventory.
|
|
5
5
|
Author: Pedro Paulo Vezza Campos
|
|
6
6
|
Author-email: Pedro Paulo Vezza Campos <pedro@vezza.com.br>
|
|
@@ -65,8 +65,9 @@ shows ample real land: at least 2.4596 mm (about 2.46 mm), versus the 0.5 mm
|
|
|
65
65
|
policy. Missing circular-topology proof, not physical land, keeps S8/S9's
|
|
66
66
|
post-plunge retouches unknown pending [#208](https://github.com/pedropaulovc/prechips/issues/208).
|
|
67
67
|
Release 0.1.1 includes #198, #192 and #199 with that documented interim exit 4.
|
|
68
|
-
Release 0.1.2 adds #235, #236 and surface-profile zones and keeps that exit 4
|
|
69
|
-
|
|
68
|
+
Release 0.1.2 adds #235, #236 and surface-profile zones and keeps that exit 4.
|
|
69
|
+
Release 0.2.0 breaks input schemas without compatibility shims and still keeps
|
|
70
|
+
that exit 4: exit-0 restoration by #208 is deferred to a later release;
|
|
70
71
|
the authored plan and its requirements are unchanged.
|
|
71
72
|
|
|
72
73
|
See the example guide's [print and native acceptance limits](examples/README.md#print-and-native-acceptance-limits).
|
|
@@ -83,6 +84,10 @@ uv run ruff check .
|
|
|
83
84
|
uv run ruff format --check .
|
|
84
85
|
```
|
|
85
86
|
|
|
87
|
+
While iterating, `uv run scripts/affected_tests.py --base main` runs only the
|
|
88
|
+
tests a change can affect (`--dry-run` prints the selection); CI always runs the
|
|
89
|
+
full suite.
|
|
90
|
+
|
|
86
91
|
Install [FreeCAD 1.x](https://github.com/FreeCAD/FreeCAD/releases) for real
|
|
87
92
|
geometry checks. Discovery uses `FREECAD_CMD` first, the installed Windows
|
|
88
93
|
FreeCAD 1.1 path next, then `FreeCADCmd`/`freecadcmd` on `PATH`. For example,
|
|
@@ -100,9 +105,9 @@ two pytest workers and load-scope scheduling, caps extra native workers at one,
|
|
|
100
105
|
records durations (complete in JUnit) and uploads the pytest log and JUnit
|
|
101
106
|
results even on failure. Successful geometry results persist across runs in a
|
|
102
107
|
cache namespaced by runner OS/architecture, pinned AppImage SHA-256, cache epoch
|
|
103
|
-
and engine source digest. Each immutable save key also includes the
|
|
104
|
-
attempt;
|
|
105
|
-
publish
|
|
108
|
+
and engine source digest (only the sources `freecadcmd` executes). Each immutable save key also includes the shard index,
|
|
109
|
+
run ID and attempt; a shard restores its own latest entry, else the shared
|
|
110
|
+
namespace prefix. Only successful test shards publish their per-run cache.
|
|
106
111
|
The product reports unknown geometry (`?`, exit 4) without FreeCAD;
|
|
107
112
|
skips do not change that behavior.
|
|
108
113
|
CI also sets `PRECHIPS_REQUIRE_PRINT_BROWSER=1`: a missing or unlaunchable
|
|
@@ -267,16 +272,31 @@ only when it is read across a face: a drawn band whose feature names the face
|
|
|
267
272
|
extent in `tilt_across` ([features](docs/features.md#angle-bands-read-across-a-face)),
|
|
268
273
|
or a BASIC angle a surface profile bounds by `tilt_across`. Inspection judges it as
|
|
269
274
|
the linear zone it reads across that length, on gauge resolution alone; any other
|
|
270
|
-
angle band is `?` (no angular gauge capability).
|
|
275
|
+
angle band is `?` (no angular gauge capability). A gauge or DRO resolution must be a
|
|
276
|
+
positive length or `"unknown"`: 0 or less is refused at load, never read as perfect
|
|
277
|
+
resolution ([inventory](docs/inventory.md)).
|
|
271
278
|
|
|
272
279
|
Native [saw cut-off](docs/plan.md#saw-cut-off) supports `saw_cut` / `cut_off` on
|
|
273
280
|
mill, bench and bandsaw setups: an explicit blade-centre plane plus inventory
|
|
274
281
|
kerf removes only the discarded stock side. The traveler shows cited blade sfm
|
|
275
282
|
and descent feed, not spindle RPM; cylinder-based accessibility explicitly does
|
|
276
|
-
not apply.
|
|
283
|
+
not apply. A [hand saw on the bench](docs/plan.md#hand-saw-on-the-bench-straight-or-to-a-scribed-line)
|
|
284
|
+
(`kind = "hand_saw"` on a bench/manual machine) keeps the manual-bench waiver and
|
|
285
|
+
has no blade speed; it cuts straight on a `cut_plane` or `follows` an earlier
|
|
286
|
+
scribe op's line, removing only its declared `stock_removal_bounds` and leaving
|
|
287
|
+
at least `allowance_mm` outside the line for the file (unknown extent is `?`). A
|
|
288
|
+
bandsaw in vertical mode (`saw_modes`) follows a scribed curve the same way, hand-fed;
|
|
289
|
+
along a scribed arc the predicted removal follows the curve, offset by the allowance. Dividing-head headroom uses centre height and the posed axis offset,
|
|
277
290
|
and child hole operations inherit a missing travel centre from their named
|
|
278
291
|
parent/hole while explicit unknown locations remain debt.
|
|
279
292
|
|
|
293
|
+
A cut that frees the part from its frame leaves a held split: every pressed piece
|
|
294
|
+
stays in the stock. The op that ends it (usually `release`) takes
|
|
295
|
+
`keep = "<feature>"`, and only the piece carrying that finished feature goes on to
|
|
296
|
+
later setups. Each discarded piece is logged by the
|
|
297
|
+
[`keep_piece`](docs/rules-geometry.md#keep-piece) finding. A keep that cannot pick
|
|
298
|
+
exactly one piece is `?`.
|
|
299
|
+
|
|
280
300
|
On the lathe, a parting/grooving blade's Z touch names the blade corner it sets
|
|
281
301
|
(the touched face's normal decides it; a scribe touch states it), and every blade
|
|
282
302
|
op row prints Z as that corner's reading. Each toolpost tool's first touch-off in
|
|
@@ -409,7 +429,17 @@ phase: [#213](https://github.com/pedropaulovc/prechips/issues/213)); a
|
|
|
409
429
|
arc's bore (or a template) and checks R with a radius gauge whose range covers
|
|
410
430
|
it. `chords` (sagitta proven inside the band, ends on the DRO grid) and a
|
|
411
431
|
`rotary_table` recipe (inventory table, centre pin, offset and dial readings)
|
|
412
|
-
finish arcs on the mill
|
|
432
|
+
finish arcs on the mill, and a `guided_sweep` (#255), in a setup of its own, finishes an arc whose centre
|
|
433
|
+
is too far off the part for a table: the cutter is touched to a measured master
|
|
434
|
+
and locked while a swing arm on a pivot, or a sled whose rail bears on two
|
|
435
|
+
rollers, sweeps the work under it; the master's radius limits widened by the
|
|
436
|
+
measured pivot play, or the rail's form error and roller runout through the
|
|
437
|
+
rollers' geometry, must hold the band, and an unmeasured guide is debt, never a
|
|
438
|
+
perfect rail. The setup picture draws an arc sled's table-side rollers
|
|
439
|
+
render-only from the sled's measured `roller_dia`, `roller_height` and
|
|
440
|
+
`bed_height` and its `rail_side` (a missing fact is a `NOT SHOWN` note with its
|
|
441
|
+
`measure:` instruction), and notes where a swing arm's pivot post stands, off
|
|
442
|
+
the picture. No traveler prints MDI, G-code or a continuous circle;
|
|
413
443
|
the former `arc_table` method and machine `contouring` are gone.
|
|
414
444
|
Drawing dimensions retain their declared precision; when no precision is
|
|
415
445
|
declared, known values still print their own digits rather than `?`. Operative
|
|
@@ -600,7 +630,15 @@ distinct from requirement-associated records: one full-width white freeform
|
|
|
600
630
|
readings/observations area below each real requirement, at least 20 mm clear
|
|
601
631
|
interior depth excluding labels, padding and borders. Known owners, limits,
|
|
602
632
|
gauges, units and method references stay associated; feature/location can be
|
|
603
|
-
identified when needed without inferred reading counts or statistics.
|
|
633
|
+
identified when needed without inferred reading counts or statistics. A
|
|
634
|
+
multi-feature `inspect` op prints as one station card; its `checks`,
|
|
635
|
+
`go_no_go` and `inspection_methods` may be scoped per listed feature
|
|
636
|
+
([plan](docs/plan.md#operation)), and each feature's row then names its own
|
|
637
|
+
gauge, GO / NO-GO pair and method.
|
|
638
|
+
A radius band `[0, r]` ("R r MAX", sharp allowed) is read as a limit check: a
|
|
639
|
+
radius or profile gauge passes only with a leaf at exactly r and no declared leaf
|
|
640
|
+
tolerance. A safe smaller leaf the traveler does not name is
|
|
641
|
+
[`?`](docs/rules-inspection.md).
|
|
604
642
|
Specifically named procedure blanks remain separate, with a 35 × 10 mm clear
|
|
605
643
|
interior floor. Pre-clamping M acquisition occurs only for explicit
|
|
606
644
|
`measure_before_hold = true` with an authored `measure`; pen room stays in its
|
|
@@ -632,6 +670,13 @@ When all component envelopes are known, their union must contain the finished
|
|
|
632
670
|
STEP; otherwise all component references carry geometry debt.
|
|
633
671
|
A nonempty root `as_is_faces` declaration needs the full joined supply exterior
|
|
634
672
|
and every component envelope known, so it can withhold otherwise-known branches.
|
|
673
|
+
A blank bought already laser-, waterjet- or plasma-cut is a
|
|
674
|
+
[profiled blank](docs/plan.md#profiled-blank): `form = "profiled_blank"` with a
|
|
675
|
+
`blank` table naming its cited, digest-bound STEP (in part-model coordinates)
|
|
676
|
+
and the vendor's ± cut tolerance, on the root stock or a component. The kernel
|
|
677
|
+
uses that solid as the supply; [`blank_credit`](docs/rules-geometry.md#blank_credit)
|
|
678
|
+
credits an as-is face only when it lies on the blank and its drawing bands hold
|
|
679
|
+
the tolerance, so out-of-band faces still need ops.
|
|
635
680
|
Empty or omitted declarations add no cross-component dependency. Removal
|
|
636
681
|
fragmentation is checked per input solid; deleting one piece cannot mask
|
|
637
682
|
splitting another.
|
|
@@ -652,12 +697,22 @@ over the face's full area. Declared fit bands must cover the
|
|
|
652
697
|
worst-case mating diameters, prepared geometry must reach the join along the
|
|
653
698
|
selected stock lineage, and the kernel refuses interference outside the
|
|
654
699
|
permitted fit or missing component-owned finished material at the join.
|
|
655
|
-
|
|
700
|
+
A joint's `forms` names exported features whose faces the join itself leaves, such as
|
|
701
|
+
a root fillet `R0.2 MAX` that a press leaves sharp. The kernel admits that sharp
|
|
702
|
+
corner against the feature's band, judged with the socket's declared mouth
|
|
703
|
+
`edge_break` (a broken mouth leaves a groove, which is refused), and `coverage` credits its faces only after a
|
|
704
|
+
post-join check reads the band. Without that check the credit is `?`.
|
|
705
|
+
A cylindrical joint's `method` is the assembly action (`silver_braze` or `slip`
|
|
706
|
+
for clearance, `press` for interference); a retaining compound on the interface
|
|
707
|
+
is a `compound = { product, cure_time_min, surface_prep }` block, required on a
|
|
708
|
+
slip fit and optional on a press fit.
|
|
709
|
+
Unknown joint dimensions or compound process facts withhold the union
|
|
656
710
|
and its render, rather than assuming a fit or cure. Each assembly step joins
|
|
657
711
|
exactly two disjoint inputs: an existing assembly may receive one new component.
|
|
658
712
|
Finite both-open cylindrical sockets accept turned sleeves; clearance joining
|
|
659
|
-
fills the mating annulus, not a sleeve's intentional bore.
|
|
660
|
-
travelers state surface prep, cure time and do not disturb until cured
|
|
713
|
+
fills the mating annulus, not a sleeve's intentional bore. Compound-joint
|
|
714
|
+
travelers state surface prep, cure time and do not disturb until cured; a press
|
|
715
|
+
fit with a compound is pressed in with the compound on the interface.
|
|
661
716
|
Plan-owned `process_features` describe stock preparation a later setup relies
|
|
662
717
|
on — a faced `end_face` or a combined drill and countersink `centre_hole` — and
|
|
663
718
|
are never drawing dimensions or coverage. The kernel cuts them, so the picture
|
|
@@ -672,6 +727,11 @@ unresolved. A tailstock drill chuck or a rest is not a centre. The centre depth
|
|
|
672
727
|
is the Machinery's Handbook Table 6 drill length plus the countersink to the mouth,
|
|
673
728
|
printed as a tailstock-quill depth, and only for the selected centre drill's
|
|
674
729
|
own accepted D, C, angle, body and point with the mouth on the touched end.
|
|
730
|
+
A `tooling_hole` is a locating hole drilled (and reamed) in the work's own waste:
|
|
731
|
+
its ops are judged as plain hole ops, the kernel cuts it, a later setup's fixture
|
|
732
|
+
or clamp pin whose `locates` names it gets a band fit check, and a setup that
|
|
733
|
+
still names it after a waste cut took it is an error (`tooling_hole`, always
|
|
734
|
+
required where a setup works or locates on one).
|
|
675
735
|
A mill route squares a sawn rectangular bar the same way: each blank face is
|
|
676
736
|
an `end_face` that a face op cuts flat, or a side-milling profile cuts on an end
|
|
677
737
|
overhanging the vise. The kernel removes each as a planar slab, so later pictures
|
|
@@ -681,6 +741,10 @@ declaration within the declared tolerance and requires an inventory gauge and
|
|
|
681
741
|
written method for its size, flatness, squareness and parallelism checks, which
|
|
682
742
|
the sheet prints as CHECK THE BLANK. A hold's `jaw_bar` puts a round bar against
|
|
683
743
|
the moving jaw while a reference face seats on the fixed jaw.
|
|
744
|
+
A lathe `part_off` also prepares an `end_face`: a piece parted off over length
|
|
745
|
+
keeps its later stock known until a later setup faces it to length.
|
|
746
|
+
`parting_face` checks that the end face is the disc at the op's `to_z`, with its
|
|
747
|
+
axis pointing into the kept piece toward the exposed end.
|
|
684
748
|
See [the plan format](docs/plan.md) for the authored fields.
|
|
685
749
|
|
|
686
750
|
Cutter self-contact exclusion is only a thin shell of the sampled face;
|
|
@@ -45,8 +45,9 @@ shows ample real land: at least 2.4596 mm (about 2.46 mm), versus the 0.5 mm
|
|
|
45
45
|
policy. Missing circular-topology proof, not physical land, keeps S8/S9's
|
|
46
46
|
post-plunge retouches unknown pending [#208](https://github.com/pedropaulovc/prechips/issues/208).
|
|
47
47
|
Release 0.1.1 includes #198, #192 and #199 with that documented interim exit 4.
|
|
48
|
-
Release 0.1.2 adds #235, #236 and surface-profile zones and keeps that exit 4
|
|
49
|
-
|
|
48
|
+
Release 0.1.2 adds #235, #236 and surface-profile zones and keeps that exit 4.
|
|
49
|
+
Release 0.2.0 breaks input schemas without compatibility shims and still keeps
|
|
50
|
+
that exit 4: exit-0 restoration by #208 is deferred to a later release;
|
|
50
51
|
the authored plan and its requirements are unchanged.
|
|
51
52
|
|
|
52
53
|
See the example guide's [print and native acceptance limits](examples/README.md#print-and-native-acceptance-limits).
|
|
@@ -63,6 +64,10 @@ uv run ruff check .
|
|
|
63
64
|
uv run ruff format --check .
|
|
64
65
|
```
|
|
65
66
|
|
|
67
|
+
While iterating, `uv run scripts/affected_tests.py --base main` runs only the
|
|
68
|
+
tests a change can affect (`--dry-run` prints the selection); CI always runs the
|
|
69
|
+
full suite.
|
|
70
|
+
|
|
66
71
|
Install [FreeCAD 1.x](https://github.com/FreeCAD/FreeCAD/releases) for real
|
|
67
72
|
geometry checks. Discovery uses `FREECAD_CMD` first, the installed Windows
|
|
68
73
|
FreeCAD 1.1 path next, then `FreeCADCmd`/`freecadcmd` on `PATH`. For example,
|
|
@@ -80,9 +85,9 @@ two pytest workers and load-scope scheduling, caps extra native workers at one,
|
|
|
80
85
|
records durations (complete in JUnit) and uploads the pytest log and JUnit
|
|
81
86
|
results even on failure. Successful geometry results persist across runs in a
|
|
82
87
|
cache namespaced by runner OS/architecture, pinned AppImage SHA-256, cache epoch
|
|
83
|
-
and engine source digest. Each immutable save key also includes the
|
|
84
|
-
attempt;
|
|
85
|
-
publish
|
|
88
|
+
and engine source digest (only the sources `freecadcmd` executes). Each immutable save key also includes the shard index,
|
|
89
|
+
run ID and attempt; a shard restores its own latest entry, else the shared
|
|
90
|
+
namespace prefix. Only successful test shards publish their per-run cache.
|
|
86
91
|
The product reports unknown geometry (`?`, exit 4) without FreeCAD;
|
|
87
92
|
skips do not change that behavior.
|
|
88
93
|
CI also sets `PRECHIPS_REQUIRE_PRINT_BROWSER=1`: a missing or unlaunchable
|
|
@@ -247,16 +252,31 @@ only when it is read across a face: a drawn band whose feature names the face
|
|
|
247
252
|
extent in `tilt_across` ([features](docs/features.md#angle-bands-read-across-a-face)),
|
|
248
253
|
or a BASIC angle a surface profile bounds by `tilt_across`. Inspection judges it as
|
|
249
254
|
the linear zone it reads across that length, on gauge resolution alone; any other
|
|
250
|
-
angle band is `?` (no angular gauge capability).
|
|
255
|
+
angle band is `?` (no angular gauge capability). A gauge or DRO resolution must be a
|
|
256
|
+
positive length or `"unknown"`: 0 or less is refused at load, never read as perfect
|
|
257
|
+
resolution ([inventory](docs/inventory.md)).
|
|
251
258
|
|
|
252
259
|
Native [saw cut-off](docs/plan.md#saw-cut-off) supports `saw_cut` / `cut_off` on
|
|
253
260
|
mill, bench and bandsaw setups: an explicit blade-centre plane plus inventory
|
|
254
261
|
kerf removes only the discarded stock side. The traveler shows cited blade sfm
|
|
255
262
|
and descent feed, not spindle RPM; cylinder-based accessibility explicitly does
|
|
256
|
-
not apply.
|
|
263
|
+
not apply. A [hand saw on the bench](docs/plan.md#hand-saw-on-the-bench-straight-or-to-a-scribed-line)
|
|
264
|
+
(`kind = "hand_saw"` on a bench/manual machine) keeps the manual-bench waiver and
|
|
265
|
+
has no blade speed; it cuts straight on a `cut_plane` or `follows` an earlier
|
|
266
|
+
scribe op's line, removing only its declared `stock_removal_bounds` and leaving
|
|
267
|
+
at least `allowance_mm` outside the line for the file (unknown extent is `?`). A
|
|
268
|
+
bandsaw in vertical mode (`saw_modes`) follows a scribed curve the same way, hand-fed;
|
|
269
|
+
along a scribed arc the predicted removal follows the curve, offset by the allowance. Dividing-head headroom uses centre height and the posed axis offset,
|
|
257
270
|
and child hole operations inherit a missing travel centre from their named
|
|
258
271
|
parent/hole while explicit unknown locations remain debt.
|
|
259
272
|
|
|
273
|
+
A cut that frees the part from its frame leaves a held split: every pressed piece
|
|
274
|
+
stays in the stock. The op that ends it (usually `release`) takes
|
|
275
|
+
`keep = "<feature>"`, and only the piece carrying that finished feature goes on to
|
|
276
|
+
later setups. Each discarded piece is logged by the
|
|
277
|
+
[`keep_piece`](docs/rules-geometry.md#keep-piece) finding. A keep that cannot pick
|
|
278
|
+
exactly one piece is `?`.
|
|
279
|
+
|
|
260
280
|
On the lathe, a parting/grooving blade's Z touch names the blade corner it sets
|
|
261
281
|
(the touched face's normal decides it; a scribe touch states it), and every blade
|
|
262
282
|
op row prints Z as that corner's reading. Each toolpost tool's first touch-off in
|
|
@@ -389,7 +409,17 @@ phase: [#213](https://github.com/pedropaulovc/prechips/issues/213)); a
|
|
|
389
409
|
arc's bore (or a template) and checks R with a radius gauge whose range covers
|
|
390
410
|
it. `chords` (sagitta proven inside the band, ends on the DRO grid) and a
|
|
391
411
|
`rotary_table` recipe (inventory table, centre pin, offset and dial readings)
|
|
392
|
-
finish arcs on the mill
|
|
412
|
+
finish arcs on the mill, and a `guided_sweep` (#255), in a setup of its own, finishes an arc whose centre
|
|
413
|
+
is too far off the part for a table: the cutter is touched to a measured master
|
|
414
|
+
and locked while a swing arm on a pivot, or a sled whose rail bears on two
|
|
415
|
+
rollers, sweeps the work under it; the master's radius limits widened by the
|
|
416
|
+
measured pivot play, or the rail's form error and roller runout through the
|
|
417
|
+
rollers' geometry, must hold the band, and an unmeasured guide is debt, never a
|
|
418
|
+
perfect rail. The setup picture draws an arc sled's table-side rollers
|
|
419
|
+
render-only from the sled's measured `roller_dia`, `roller_height` and
|
|
420
|
+
`bed_height` and its `rail_side` (a missing fact is a `NOT SHOWN` note with its
|
|
421
|
+
`measure:` instruction), and notes where a swing arm's pivot post stands, off
|
|
422
|
+
the picture. No traveler prints MDI, G-code or a continuous circle;
|
|
393
423
|
the former `arc_table` method and machine `contouring` are gone.
|
|
394
424
|
Drawing dimensions retain their declared precision; when no precision is
|
|
395
425
|
declared, known values still print their own digits rather than `?`. Operative
|
|
@@ -580,7 +610,15 @@ distinct from requirement-associated records: one full-width white freeform
|
|
|
580
610
|
readings/observations area below each real requirement, at least 20 mm clear
|
|
581
611
|
interior depth excluding labels, padding and borders. Known owners, limits,
|
|
582
612
|
gauges, units and method references stay associated; feature/location can be
|
|
583
|
-
identified when needed without inferred reading counts or statistics.
|
|
613
|
+
identified when needed without inferred reading counts or statistics. A
|
|
614
|
+
multi-feature `inspect` op prints as one station card; its `checks`,
|
|
615
|
+
`go_no_go` and `inspection_methods` may be scoped per listed feature
|
|
616
|
+
([plan](docs/plan.md#operation)), and each feature's row then names its own
|
|
617
|
+
gauge, GO / NO-GO pair and method.
|
|
618
|
+
A radius band `[0, r]` ("R r MAX", sharp allowed) is read as a limit check: a
|
|
619
|
+
radius or profile gauge passes only with a leaf at exactly r and no declared leaf
|
|
620
|
+
tolerance. A safe smaller leaf the traveler does not name is
|
|
621
|
+
[`?`](docs/rules-inspection.md).
|
|
584
622
|
Specifically named procedure blanks remain separate, with a 35 × 10 mm clear
|
|
585
623
|
interior floor. Pre-clamping M acquisition occurs only for explicit
|
|
586
624
|
`measure_before_hold = true` with an authored `measure`; pen room stays in its
|
|
@@ -612,6 +650,13 @@ When all component envelopes are known, their union must contain the finished
|
|
|
612
650
|
STEP; otherwise all component references carry geometry debt.
|
|
613
651
|
A nonempty root `as_is_faces` declaration needs the full joined supply exterior
|
|
614
652
|
and every component envelope known, so it can withhold otherwise-known branches.
|
|
653
|
+
A blank bought already laser-, waterjet- or plasma-cut is a
|
|
654
|
+
[profiled blank](docs/plan.md#profiled-blank): `form = "profiled_blank"` with a
|
|
655
|
+
`blank` table naming its cited, digest-bound STEP (in part-model coordinates)
|
|
656
|
+
and the vendor's ± cut tolerance, on the root stock or a component. The kernel
|
|
657
|
+
uses that solid as the supply; [`blank_credit`](docs/rules-geometry.md#blank_credit)
|
|
658
|
+
credits an as-is face only when it lies on the blank and its drawing bands hold
|
|
659
|
+
the tolerance, so out-of-band faces still need ops.
|
|
615
660
|
Empty or omitted declarations add no cross-component dependency. Removal
|
|
616
661
|
fragmentation is checked per input solid; deleting one piece cannot mask
|
|
617
662
|
splitting another.
|
|
@@ -632,12 +677,22 @@ over the face's full area. Declared fit bands must cover the
|
|
|
632
677
|
worst-case mating diameters, prepared geometry must reach the join along the
|
|
633
678
|
selected stock lineage, and the kernel refuses interference outside the
|
|
634
679
|
permitted fit or missing component-owned finished material at the join.
|
|
635
|
-
|
|
680
|
+
A joint's `forms` names exported features whose faces the join itself leaves, such as
|
|
681
|
+
a root fillet `R0.2 MAX` that a press leaves sharp. The kernel admits that sharp
|
|
682
|
+
corner against the feature's band, judged with the socket's declared mouth
|
|
683
|
+
`edge_break` (a broken mouth leaves a groove, which is refused), and `coverage` credits its faces only after a
|
|
684
|
+
post-join check reads the band. Without that check the credit is `?`.
|
|
685
|
+
A cylindrical joint's `method` is the assembly action (`silver_braze` or `slip`
|
|
686
|
+
for clearance, `press` for interference); a retaining compound on the interface
|
|
687
|
+
is a `compound = { product, cure_time_min, surface_prep }` block, required on a
|
|
688
|
+
slip fit and optional on a press fit.
|
|
689
|
+
Unknown joint dimensions or compound process facts withhold the union
|
|
636
690
|
and its render, rather than assuming a fit or cure. Each assembly step joins
|
|
637
691
|
exactly two disjoint inputs: an existing assembly may receive one new component.
|
|
638
692
|
Finite both-open cylindrical sockets accept turned sleeves; clearance joining
|
|
639
|
-
fills the mating annulus, not a sleeve's intentional bore.
|
|
640
|
-
travelers state surface prep, cure time and do not disturb until cured
|
|
693
|
+
fills the mating annulus, not a sleeve's intentional bore. Compound-joint
|
|
694
|
+
travelers state surface prep, cure time and do not disturb until cured; a press
|
|
695
|
+
fit with a compound is pressed in with the compound on the interface.
|
|
641
696
|
Plan-owned `process_features` describe stock preparation a later setup relies
|
|
642
697
|
on — a faced `end_face` or a combined drill and countersink `centre_hole` — and
|
|
643
698
|
are never drawing dimensions or coverage. The kernel cuts them, so the picture
|
|
@@ -652,6 +707,11 @@ unresolved. A tailstock drill chuck or a rest is not a centre. The centre depth
|
|
|
652
707
|
is the Machinery's Handbook Table 6 drill length plus the countersink to the mouth,
|
|
653
708
|
printed as a tailstock-quill depth, and only for the selected centre drill's
|
|
654
709
|
own accepted D, C, angle, body and point with the mouth on the touched end.
|
|
710
|
+
A `tooling_hole` is a locating hole drilled (and reamed) in the work's own waste:
|
|
711
|
+
its ops are judged as plain hole ops, the kernel cuts it, a later setup's fixture
|
|
712
|
+
or clamp pin whose `locates` names it gets a band fit check, and a setup that
|
|
713
|
+
still names it after a waste cut took it is an error (`tooling_hole`, always
|
|
714
|
+
required where a setup works or locates on one).
|
|
655
715
|
A mill route squares a sawn rectangular bar the same way: each blank face is
|
|
656
716
|
an `end_face` that a face op cuts flat, or a side-milling profile cuts on an end
|
|
657
717
|
overhanging the vise. The kernel removes each as a planar slab, so later pictures
|
|
@@ -661,6 +721,10 @@ declaration within the declared tolerance and requires an inventory gauge and
|
|
|
661
721
|
written method for its size, flatness, squareness and parallelism checks, which
|
|
662
722
|
the sheet prints as CHECK THE BLANK. A hold's `jaw_bar` puts a round bar against
|
|
663
723
|
the moving jaw while a reference face seats on the fixed jaw.
|
|
724
|
+
A lathe `part_off` also prepares an `end_face`: a piece parted off over length
|
|
725
|
+
keeps its later stock known until a later setup faces it to length.
|
|
726
|
+
`parting_face` checks that the end face is the disc at the op's `to_z`, with its
|
|
727
|
+
axis pointing into the kept piece toward the exposed end.
|
|
664
728
|
See [the plan format](docs/plan.md) for the authored fields.
|
|
665
729
|
|
|
666
730
|
Cutter self-contact exclusion is only a thin shell of the sampled face;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "prechips"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "Checks before chips: deterministic validation of machining process plans against part geometry and a shop inventory."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -34,6 +34,8 @@ dev = [
|
|
|
34
34
|
"pillow>=12.3.0",
|
|
35
35
|
"pypdfium2>=5.14.0",
|
|
36
36
|
"pytest>=8.3",
|
|
37
|
+
"pytest-split>=0.11.0",
|
|
38
|
+
"pytest-testmon>=2.2.0",
|
|
37
39
|
"pytest-xdist>=3.8.0",
|
|
38
40
|
"ruff>=0.8",
|
|
39
41
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "prechips"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "Checks before chips: deterministic validation of machining process plans against part geometry and a shop inventory."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -31,6 +31,8 @@ dev = [
|
|
|
31
31
|
"pillow>=12.3.0",
|
|
32
32
|
"pypdfium2>=5.14.0",
|
|
33
33
|
"pytest>=8.3",
|
|
34
|
+
"pytest-split>=0.11.0",
|
|
35
|
+
"pytest-testmon>=2.2.0",
|
|
34
36
|
"pytest-xdist>=3.8.0",
|
|
35
37
|
"ruff>=0.8",
|
|
36
38
|
]
|
|
@@ -11,11 +11,13 @@ import re
|
|
|
11
11
|
import sys
|
|
12
12
|
import tomllib
|
|
13
13
|
import uuid
|
|
14
|
+
from copy import deepcopy
|
|
14
15
|
from pathlib import Path
|
|
15
16
|
|
|
16
17
|
from prechips import __version__, telemetry
|
|
17
18
|
from prechips.findings import Finding, exit_code
|
|
18
19
|
from prechips.inputs import BadInput, Bundle, load_bundle, load_inventory
|
|
20
|
+
from prechips.model import profiled
|
|
19
21
|
from prechips.report import (
|
|
20
22
|
build_report,
|
|
21
23
|
canonical_bytes,
|
|
@@ -140,12 +142,15 @@ def _write_outputs(
|
|
|
140
142
|
temporary.unlink(missing_ok=True)
|
|
141
143
|
|
|
142
144
|
|
|
143
|
-
def _evaluate(bundle: Bundle, tracing: telemetry.Telemetry):
|
|
145
|
+
def _evaluate(bundle: Bundle, job: dict, tracing: telemetry.Telemetry):
|
|
146
|
+
"""Every rule's findings on ``bundle``. Each geometry rule reads the bundle's kernel
|
|
147
|
+
job (prepared_job): ``job``, built once by the caller, is lent to each rule as a copy."""
|
|
144
148
|
from prechips.rules import RULES, required_coverage
|
|
149
|
+
from prechips.rules.geometry_common import lend_job
|
|
145
150
|
|
|
146
151
|
findings = []
|
|
147
152
|
for rule in RULES:
|
|
148
|
-
with tracing.span(f"rule.{rule.name}.evaluate"):
|
|
153
|
+
with tracing.span(f"rule.{rule.name}.evaluate"), lend_job(bundle, job):
|
|
149
154
|
rows = rule.evaluate(bundle)
|
|
150
155
|
for finding in rows:
|
|
151
156
|
with tracing.span(
|
|
@@ -516,6 +521,8 @@ def _stock_piece_volume(piece: dict, subject: str) -> dict:
|
|
|
516
521
|
if round_form
|
|
517
522
|
else "section_mm, length_mm"
|
|
518
523
|
if rectangular_form
|
|
524
|
+
else "blank STEP (a profiled blank's volume is not compared)"
|
|
525
|
+
if profiled(piece)
|
|
519
526
|
else "form, length_mm (shape unresolved)"
|
|
520
527
|
)
|
|
521
528
|
return {
|
|
@@ -694,10 +701,16 @@ def _run(args, tracing: telemetry.Telemetry) -> int:
|
|
|
694
701
|
destinations = _output_paths(out, names, all_inputs)
|
|
695
702
|
except OSError as exc:
|
|
696
703
|
raise BadInput(f"Cannot check output path: {exc}") from exc
|
|
697
|
-
from prechips.kernel import run_geometries
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
704
|
+
from prechips.kernel import build_job, run_geometries
|
|
705
|
+
|
|
706
|
+
# One kernel job per bundle serves both the kernel request and every rule: the bundle
|
|
707
|
+
# does not change in between, and the job does not read the kernel's result.
|
|
708
|
+
jobs = []
|
|
709
|
+
for bundle in bundles:
|
|
710
|
+
with tracing.span("kernel.build_job"):
|
|
711
|
+
jobs.append(build_job(bundle))
|
|
712
|
+
run_geometries(bundles, [deepcopy(job) for job in jobs])
|
|
713
|
+
findings = [_evaluate(bundle, job, tracing) for bundle, job in zip(bundles, jobs, strict=True)]
|
|
701
714
|
try:
|
|
702
715
|
assets = [render_assets(bundle) for bundle in bundles]
|
|
703
716
|
reports = [
|
|
@@ -47,16 +47,19 @@ class Finding:
|
|
|
47
47
|
# hand-finished arc needs, a centre the work rides on must be one the stock already
|
|
48
48
|
# has, and prepared_blank gates the size of the blank a declared preparation hands the
|
|
49
49
|
# first machining setup; bought tooling no receipt check can accept leaves the setup
|
|
50
|
-
# nothing proven to hold or guide the work with
|
|
51
|
-
#
|
|
50
|
+
# nothing proven to hold or guide the work with; a keep that cannot pick the piece that
|
|
51
|
+
# leaves a held split leaves every later setup's stock unknown: no policy omission can
|
|
52
|
+
# waive them. A not_applicable row never blocks.
|
|
52
53
|
ALWAYS_REQUIRED = frozenset(
|
|
53
54
|
{
|
|
54
55
|
"joint_fit",
|
|
55
56
|
"joint_assembly",
|
|
56
57
|
"manual_arc",
|
|
57
58
|
"centre_support",
|
|
59
|
+
"tooling_hole",
|
|
58
60
|
"prepared_blank",
|
|
59
61
|
"purchased_tooling",
|
|
62
|
+
"keep_piece",
|
|
60
63
|
}
|
|
61
64
|
)
|
|
62
65
|
|