11# STAGE 3 — upstream geometry.py + topology/* .py VERBATIM (pytopo=upstream)
22
3- ** State as of this checkpoint: Phase 3 (the grind), mid-flight.**
4- Branch ` feat/upstream-full-topology ` . Default pytopo stays ` lite `
5- (` PYTOPO_DEFAULT ` in UpstreamB123d.js); nothing in the default modes moved.
3+ ** State as of this checkpoint: Phase 4 gates GREEN; default deliberately
4+ left OFF (perf shortfall — see the flip decision below).**
5+ Branch ` feat/upstream-full-topology ` . ` PYTOPO_DEFAULT='lite' ` in
6+ UpstreamB123d.js; nothing in the default modes moved.
7+
8+ ## Phase 4 gates (2026-08-21, all on this tree)
9+
10+ - pytopo=upstream harness (r9): ** 210 PASS / 2 MISMATCH / 3 ERROR /
11+ 7 TIMEOUT** (` /tmp/pytopo-up-r9.{json,md} ` at run time; progression below).
12+ - pytopo=lite NEUTRALITY harness (micropython, pysrc=upstream default,
13+ no CS_PY_TOPO): ** 205 / 10 / 5 / 2 — per-script IDENTICAL to the
14+ committed upstream-Level-A baseline set** (MM: joints x2, projection x2,
15+ filter_all_edges_circle, tips/b04, objects_1d, tutorial_joints,
16+ bicycle_tire, ex08_algebra; E: objects_2d, dual_color_3mf, sm_hanger,
17+ curved_support, Buffer_Stand; T: spitfire, heat_exchanger) — despite the
18+ shared-layer changes (jsffi patch 9, enum None-members, deepcopy memo,
19+ 2-D ConvexHull, collections.abc lazy iterators).
20+ - Full playwright suite: ** 96 passed / 1 skipped** . Fast gate green incl.
21+ the native-metaclass spec (Align.__ members__ now includes NONE — the
22+ CPython surface; expectation updated).
23+ - Gotcha fixed en route: the USED_OCCT_SYMBOLS generator scans RAW TEXT
24+ (comments included) — deliberately-absent-symbol probes must use
25+ indirect lookups (` oc['Quantity_' + 'Color_1'] ` ).
26+
27+ ## Flip decision (this run): DEFAULT STAYS pytopo=lite
28+
29+ pytopo=upstream EXCEEDS the baseline on fidelity (+9 scripts incl. lite's
30+ entire COMPROMISE(edge-orientation)/(traversal-order) residual set; only
31+ 2 MISMATCH / 3 ERROR, all baseline-family). The honest shortfall is PERF:
32+ 4 scripts regress PASS/MM -> TIMEOUT (clock, algebra_performance b01+all,
33+ bicycle_tire — bicycle_tire is 4m10s solo vs the 60 s budget;
34+ b01 is 148 s vs 15 s under pytopo=lite because upstream's own
35+ Compound.__ add__ re-fuses ALL top-level shapes each step and the
36+ FFI-envelope multiplies the quadratic Python term). Profiles show
37+ MicroPython VM self-time dominating (~ 70%), not the shim dispatch.
38+ Flip when the perf work lands (see next actions).
639
740## Phase log
841
@@ -25,7 +58,15 @@ Branch `feat/upstream-full-topology`. Default pytopo stays `lite`
2558| r5 | 203 | ** 1** | 11 | 7 | insertion-ordered dedup (MicroPython dicts are UNORDERED — faces()/edges() were SCRAMBLED: the whole ex33/ex34/logo MISMATCH family), glue enum bridge + align translation |
2659| r6 | 204 | 1 | 12 | 5 | (r5's tree + ArrowHead/b12/b10-format/user-code-concat partials) |
2760| r7 | ** 209** | 3 | 5 | 5 | hasher functor rebind, deque(maxlen), ljust, ArrowHead-as-upstream-Sketch, chained concat |
28- | r8 | (running) | | | | TypeMismatch/ConstructionError exception mapping (twist_extrude, slide_latch), ** the jsffi integral-double FFI fix** (PROVENANCE patch 9: integral JS doubles >= 2^31 crossed into Python WRAPPED to int32 — 1e15 -> -1530494976, 1e100 -> 0; found via Edge(Axis) parameter ranges), MakeEdge unbounded-line glue (b10) |
61+ | r8 | 210 | 3 | 3 | 6 | TypeMismatch/ConstructionError exception mapping (twist_extrude, slide_latch), ** the jsffi integral-double FFI fix** (PROVENANCE patch 9: integral JS doubles >= 2^31 crossed into Python WRAPPED to int32 — 1e15 -> -1530494976, 1e100 -> 0; found via Edge(Axis) parameter ranges), MakeEdge unbounded-line glue (b10) |
62+ | r9 | ** 210** | ** 2** | ** 3** | 7 | None-valued enum members (Align.NONE = None IS a member — objects_sketch defaults) |
63+
64+ ** Final r9 per-script classification** : MISMATCH = objects_1d,
65+ tutorial_joints (both baseline-family). ERROR = dual_color_3mf, objects_2d,
66+ curved_support (exactly 3 of the baseline's 5 — toy_truck and ttt-ppp0110
67+ now PASS). TIMEOUT = heat_exchanger + spitfire (the baseline TIMEOUT set)
68+ + bicycle_tire/clock/algebra_performance-b01/all (PERF — the honest
69+ shortfall) + selectors_operators (one-run contention flap; PASS in r7/r8).
2970
3071** The single r5+ MISMATCH is docs/objects_1d — the baseline residual
3172(triad labels + DTA trim). Upstream topology FIXED lite's other residual
@@ -84,25 +125,39 @@ tips/b04, sm_hanger — all PASS under pytopo=upstream).**
84125
85126## Known open items (next actions, in order)
86127
87- 1 . r8 results (in flight): expect b10 + twist_extrude + slide_latch fixed
88- (jsffi fix + exception mapping) — potentially 211-212 PASS / ~ 3 ERROR.
89- 2 . Phase 4 gates NOT yet run: pytopo=lite harness re-verification
90- (205/10/5/2 per-script — CRITICAL after the jsffi number fix, which
91- touches the shared interpreter), pysrc=lite control, fast spec gate,
92- full playwright suite. THEN the flip decision (perf TIMEOUTs argue for
93- default-off this round; the per-script shortfall is 4 scripts of perf
94- + tutorial_joints magnitude + spitfire reclassification).
95- 3 . Perf: the remaining lever is the FFI envelope x upstream's Python-heavy
96- hot loops (VM self-time dominates profiles). Candidates: batch
97- ListOfShape appends, cache geom_adaptor, MicroPython native-emitter for
98- hot topology modules (interpreter-side, next rebuild).
128+ 1 . ** PERF (the flip blocker)** : bicycle_tire (250 s solo), clock (text +
129+ sequential 2-D fillets), algebra_performance b01/all (quadratic re-fuse).
130+ Profile shows MicroPython VM self-time ~ 70% (wasm-function[ 462] et al.),
131+ proxy conversion ~ 5%, GC ~ 1% — the cost is EXECUTING 19.8k lines of
132+ upstream Python per hot loop, not the dispatcher. Levers, in rough order
133+ of value: (a) MicroPython native-emitter (@micropython .native) or
134+ frozen-bytecode for topology modules — interpreter-side, next
135+ micropython-cs rebuild (also carry PROVENANCE patch 9 forward properly);
136+ (b) targeted memoization of upstream hot properties (geom_adaptor,
137+ wrapped-downcast) via loader transforms; (c) a lighter guarded-call
138+ envelope (single FFI hop) for _ BoundMethod.
139+ 2 . tutorial_joints MISMATCH magnitude (hinge_inner bbox off 160 —
140+ worse than the baseline's m6_screw-only residual): joint connect_to
141+ family, uninvestigated.
142+ 3 . spitfire is TIMEOUT here like baseline (gordon at wing scale);
143+ selectors_operators flapped TIMEOUT once under contention (PASS solo,
144+ r7/r8).
991454 . history-step SNAPSHOTS under pytopo are end-of-run only (scene is
100146 glue-assembled); fnName/line are correct. Recorded as honest partial.
101- 5 . Boot cost: libMs ~ 600 ms (vs ~ 305 pre-Stage-3); heap 16 MB holds
102- (32 MB experiment showed no win).
147+ GUI pick->line works via TopoDS producingLine tagging.
148+ 5 . Boot cost: libMs ~ 600 ms (vs ~ 305 for the pre-Stage-3 pytopo=upstream,
149+ ~ 123 ms lite); heap 16 MB holds (32 MB experiment: no win).
150+ runtime-comparison.md not yet updated with the full-stack numbers.
1031516 . FORK-ASKS Stage-3 addendum WRITTEN (Quantity_Color, BOPAlgo setters,
104152 concrete Geom surface classes, IndexedDataMap Extent, ConnectEdgesToWires
105153 out-handle, GetEulerAngles helper, ListOfShape iteration).
154+ 7 . INVENTORY line-count accounting for the eventual flip: the pytopo=lite
155+ seam that upstream topology makes obsolete is ~ 1,170 lines
156+ (topology/__ init__ 774 + geometry seam 242 + constrained_bridge 141 +
157+ sub stubs 13), replaced by topo_glue 431 (+ topo_bridge 202 shared);
158+ the 19,027 vendored upstream lines now run verbatim. Build123dLite.js
159+ itself STAYS (it is the pytopo=lite layer, the Brython default, and the
160+ glue's kernel-op library) until a post-flip round prunes it.
106161
107162## How to run things
108163
0 commit comments