From 2626c7838771336f90943e215552b40a320c19d6 Mon Sep 17 00:00:00 2001 From: Nils Briggen Date: Tue, 15 Sep 2026 20:00:54 +0200 Subject: [PATCH] docs: record smooth loft and performance evidence --- FUSION_LOG.md | 64 ++++++------------- NAMING.md | 16 +++-- docs/PERFORMANCE_2026-09-14.md | 56 ++++++++-------- ...09-14_daily-reliability-spline-modeling.md | 50 +++++++++++++-- .../2026-09-15-usability-organic-modeling.md | 33 +++++----- 5 files changed, 117 insertions(+), 102 deletions(-) diff --git a/FUSION_LOG.md b/FUSION_LOG.md index 14c9ff8..a6a7d0f 100644 --- a/FUSION_LOG.md +++ b/FUSION_LOG.md @@ -684,55 +684,27 @@ real shell). What is still absent is changing the SEQUENCE — adding a fit poin spline, or removing one — which needs the same "remove a sketch entity" primitive entry 6's own residue now names. -### 10. Loft is ruled only, with no tangency and no guides. — **PARTIAL, INVESTIGATED 2026-08-29, NOT A FLAG TO FLIP** +### 10. Smooth section lofts ship; tangency and guides remain absent. — **PARTIALLY RESOLVED 2026-09-15** -**Evidence.** `FeaturePayload::Loft` documents the choice explicitly and honestly: *"The -sections are **ruled** — straight between neighbours — and that is a naming decision before it -is a geometry one … Locality is what the key exists for, so ruled is what ships."* +`FeaturePayload::Loft` now persists `LoftMode::{Ruled, Smooth}`. Smooth mode +uses OCCT's exact global B-spline interpolation through every section; it is not +a per-span smoothing flag and does not polygonize spline sections. The real +shell exposes the mode for creation and editing, including ordered section +navigation, preview/cancel/apply, explicit body targets, persistence, and +STEP/STL export. The five-section ergonomic-handle workflow is the driven +acceptance path. -**Absent:** smooth/G1 continuity between sections, tangency to an adjacent face, guide rails, -a centreline, and per-section takeoff weights. +The earlier naming objection was valid and is now paid explicitly rather than +ignored. Ruled spans retain local `Bridged` keys. Smooth lateral faces use +`SmoothColumn` with the complete OCCT-reported section-edge set, naming-store +v6, and fail-closed completeness/ambiguity checks. Any section-list change may +re-mint every smooth column; that is the documented non-local identity contract. -**The trade is recorded, and this session independently re-confirmed it against the real OCCT -header rather than trusting the comment alone.** `BRepOffsetAPI_ThruSections`'s `ruled` flag -is a WHOLE-SHAPE constructor parameter, not a per-span setting — `SetContinuity`, `SetParType` -and the rest of its smoothing controls are all parameters of ONE global B-spline-surface fit -through every section at once. There is no OCCT mechanism to smooth "just between these two -adjacent sections": a smoothed loft is one continuous surface, so there is no local pair of -sections left to key `Bridged`'s identity by. This is structural, not a missing flag — -implementing it as `Loft { smooth: bool, .. }` on the existing key would be building on a -locality claim that does not hold. - -**What a correct future design needs, if pursued:** either (a) a genuinely new, explicitly -NON-local `ProvenanceKey` variant naming the whole section set per column — editing *any* -section would re-mint *every* column's identity, a real and different trade-off nothing else -in this naming model has, needing its own `NAMING.md` amendment and explicit sign-off before -implementation, not an autonomous call during a feature pass; or (b) tangency to an adjacent -FACE at just the loft's start/end — a different geometric question from whole-interior -smoothing, not yet investigated, that may or may not have the same locality problem and is -worth checking on its own rather than folded into "smooth loft." Guide rails (a second picked -curve constraining the loft's shape) are separate again and unexamined either way. - -**The practical answer, decided 2026-08-30: a synthetic near-boundary section, not the -non-local key.** Asked to choose between building option (a) above and deferring, the call was -to defer — the full `ProvenanceKey` variant is real and buildable, but its cost is open-ended -and ongoing (any edit to a smoothed loft's section list, anywhere, re-mints every downstream -reference to any of its faces, for as long as the feature exists), and nothing today asks for -true G1 continuity hard enough to justify paying that price speculatively (CLAUDE.md: "do not -write speculative abstraction for phases that do not exist yet"). A zero-risk alternative -already ships everything this codebase's own loft supports: insert an extra section curve close -to the real end, shaped to approximate the desired tangent direction, and loft through it — -ordinary ruled lofting, ordinary `Bridged` keys, no kernel change, no naming change, no version -bump, available today with the existing `AddLoft`/`SetLoftSections` commands **at the document -layer only** (corrected 2026-09-02: `SetLoftSections` is on `NOT_YET`, so no gesture in the -running app repoints a loft's sections, and the workaround cannot be performed there). It approximates -G1 continuity rather than proving it exactly, which is the honest trade for paying nothing. -**The full design is not lost, only shelved:** the non-local `ProvenanceKey::SmoothColumn` (or -equivalent) — its shape, its dormancy behaviour, its invasiveness, its save-format impact — was -worked out in the same research pass that produced this recommendation, and is ready to build -later, with a known price tag rather than a guessed one, if real use ever demonstrates the -synthetic-section workaround is not good enough. No implementation this pass; this entry stays -open only as a record of the decision, not as unfinished work. +Still absent are G1/G2 attachment to neighboring faces, guide rails, centerline +lofts, periodic lofts, and per-section takeoff weights. A smooth section loft +therefore promises interpolation through its sections only. Those remaining +features require separate geometry, naming, and interaction designs and are not +implied by the smooth control. ### 11. Sweep pins its path to the world XZ plane and offers no orientation control. — **NARROWED TO ONE ITEM** diff --git a/NAMING.md b/NAMING.md index 99519e1..abb03fd 100644 --- a/NAMING.md +++ b/NAMING.md @@ -511,12 +511,16 @@ Amendment from the loft (2026-08-10): the next person to add an N-input operation should read first:** `sources` cannot be read off ordinal position, for any operation, without a measurement saying it can. -- **Ruled, not smoothed, and that is a naming decision.** A smoothed loft - makes one face per column spanning *all* sections, so its `sources` would - be the whole section set and adding a section anywhere would re-mint every - side face. Ruled gives each face exactly two sources, which is the - locality the key exists for. If smoothing ever ships as a flag, flipping - it is a deliberate one-time id churn behind the format version. +- **Ruled and smooth have distinct provenance.** A ruled span keeps + `Bridged { sources: {lower, upper}, sibling }`. A smooth loft makes one + lateral face per complete column spanning every section, so it uses + `SmoothColumn { sources, sibling }` (tag byte 11) with the full + OCCT-reported section-edge set. The evaluator refuses a column unless + every section contributes exactly one edge and every reported face maps + unambiguously. Adding/removing/reordering a section therefore deliberately + re-mints smooth lateral ids; switching ruled/smooth is likewise deliberate + identity churn. Naming-store v6 makes that new spelling explicit rather + than widening persisted `Bridged` keys. - **`sibling` ships at 0 and is unexercised**, deliberately. The façade refuses any span claiming more than one face, so a source pair names at most one face per operation. The field is in the key anyway because adding diff --git a/docs/PERFORMANCE_2026-09-14.md b/docs/PERFORMANCE_2026-09-14.md index 097cd67..b62c88e 100644 --- a/docs/PERFORMANCE_2026-09-14.md +++ b/docs/PERFORMANCE_2026-09-14.md @@ -36,51 +36,55 @@ is rejected before aggregation. The default is five samples. `--samples` accepts 1 through 20; the focused contract uses one to keep developer feedback short. -`preview_ms` is specifically disposable command-plus-compile time on an -isolated document/store copy. It does not include egui input dispatch, worker -queueing, GPU upload, or rendering, and therefore is not an end-to-end UI -latency claim. +`preview_ms` is specifically disposable command, compile, and CPU tessellation +time on an isolated document/store copy. Schema v2 breaks that number into +`preview_edit_ms`, `preview_compile_ms`, and `preview_tessellate_ms`. It does +not include egui input dispatch, worker queueing, GPU upload, or frame +presentation, and therefore is not an end-to-end UI latency claim. ## Release result Command: ```bash -VERNIER_GIT_REVISION='069660ca9f605795b29cf51ec1b2d191976c44ab+task11.11d123938648359b0a78d4b2233866d0fdc921e50183312dff33eac049ee88e0' \ - cargo build --locked --release -p vernier-cli -target/release/vernier-cli --bench-workflows --json > target/performance/workflows.json +target/release/vernier-cli --bench-workflows --json --samples 5 \ + > target/bench-workflows-5-samples.json ``` -The embedded `build_revision` combines the immutable base `HEAD` with SHA-256 -over the per-file SHA-256 rows of the seven Task 11 Rust source/test paths. A -normal build without `VERNIER_GIT_REVISION` reports the explicit fallback -`unknown`; this release artifact was checked to contain the exact value above, -not the fallback. +This locally built measurement binary reports the explicit fallback revision +`unknown`; it was built after the performance implementation commit `ffc1fdb` +and before script-only commit `218e42a`. The final release build and gate remain +the source-revision authority, not this descriptive timing file. Machine/build metadata reported by the artifact: release profile, VernierCAD 0.0.1, CachyOS, Linux 7.2.3-1-cachyos, x86_64, 28 logical CPUs. -| Workflow | Cold median / max | Preview median / max | Apply median / max | Tail median / max | Peak RSS | Features / faces / triangles | +| Workflow | Cold median / max | Preview median / max | Compile / tessellate median | Apply median / max | Tail median / max | Peak RSS | |---|---:|---:|---:|---:|---:|---:| -| L2 enclosure | 19.861 / 25.149 ms | 19.477 / 25.765 ms | 19.361 / 29.635 ms | 14.787 / 26.003 ms | 38,543,360 B | 7 / 15 / 460 | -| L3 rod holder | 192.719 / 198.463 ms | 221.036 / 230.842 ms | 219.498 / 229.333 ms | 192.881 / 198.792 ms | 57,208,832 B | 8 / 15 / 224 | -| L4 multi-body | 122.239 / 135.137 ms | 121.285 / 131.888 ms | 121.146 / 126.476 ms | 98.299 / 100.643 ms | 38,543,360 B | 40 / 80 / 280 | +| L2 enclosure | 19.814 / 19.891 ms | 22.264 / 28.670 ms | 19.573 / 2.693 ms | 19.473 / 27.767 ms | 14.867 / 15.762 ms | 38,383,616 B | +| L3 rod holder | 192.896 / 200.786 ms | 233.091 / 237.528 ms | 223.734 / 1.885 ms | 219.813 / 221.889 ms | 189.909 / 192.890 ms | 57,180,160 B | +| L4 multi-body | 122.239 / 131.595 ms | 128.830 / 143.993 ms | 121.271 / 7.455 ms | 123.606 / 124.435 ms | 98.074 / 101.065 ms | 39,227,392 B | -Raw artifact: `target/performance/workflows.json` (SHA-256 -`bd3d38340a9e0b67317add851bdd8117461ca0fe28290519906620fc6756c9d8`). +The rows retain 7/15/460, 8/15/224, and 40/80/280 +features/faces/triangles respectively. Raw artifact: +`target/bench-workflows-5-samples.json` (SHA-256 +`73ef32318935d334f3ccf205ac4710ddd2c32176f7f39293179393fa7f85030f`). ## Reading the result -L2 medians are around 15–20 ms for the measured modeling operations. L4's +L2 medians are around 15–22 ms for the measured modeling operations. L4's 40-feature multi-body history is around 98 ms for a steady tail revert and -121–122 ms for cold compile/apply. L3 is the clear interaction bottleneck: its +121–129 ms for compile/preview. L3 is the clear interaction bottleneck: its upstream spline edit rebuilds the exact sweep, spline-section loft, named-edge fillet, and direct edit chain. Preview/apply medians are about 220 ms, while the tail revert is about 193 ms. -No optimization is included in this change. The L3 cost is distributed across -the full downstream exact-geometry and naming rebuild, not isolated here to a -single small implementation path whose behavior could be changed safely. The -next performance investigation should profile that compile before selecting an -optimization; this measurement deliberately stops at identifying the -bottleneck. +The first safe profiling cycle found no qualifying 25% change. Compilation is +96% of L3 preview time; CPU tessellation is below 1%, and authoring the command +is negligible. That compile intentionally rebuilds every downstream exact OCCT +operation and its naming history after an early path-sketch edit. Persisting or +sharing live OCCT shape handles across the disposable worker checkpoint would +change ownership and isolation contracts, while skipping history work would +weaken stable-reference guarantees. Neither is a low-risk optimization. The +instrumentation stays in place so a later kernel-level profile can target a +specific evaluator without guessing; no geometry or naming shortcut was taken. diff --git a/docs/PLAN_2026-09-14_daily-reliability-spline-modeling.md b/docs/PLAN_2026-09-14_daily-reliability-spline-modeling.md index 8e4f707..5bbe530 100644 --- a/docs/PLAN_2026-09-14_daily-reliability-spline-modeling.md +++ b/docs/PLAN_2026-09-14_daily-reliability-spline-modeling.md @@ -178,12 +178,48 @@ The managed targets recorded for this baseline are: - `previous`: `/home/nilsb/.local/share/vernier/releases/c111f856929f6c6370cb4ff5cd094bdb39f699f2` -## Next sequence — ergonomic handle and smooth lofts +## Phase 6 — ergonomic handle acceptance — focused-verified -The next acceptance part is an ergonomic handle with a mounting base. It first -drives practical editing with the existing exact ruled loft, then becomes the -acceptance part for exact smooth section interpolation. The implementation plan +The real shell now builds a mounting base, drills two through holes, authors +five closed cubic-spline sections, previews/cancels and then applies an explicit +Join loft, fillets the base, changes the upstream hole diameter, and exercises +undo/redo. A separate worker reopens the native document and naming sidecar and +independently exports matching STEP/STL geometry. A one-cubic-millimetre false +oracle fails at its exact geometry step. + +## Phase 7 — measured interaction bottleneck — complete, no speculative change + +The workflow report is schema v2 and separates command authoring, exact +compile/naming, and CPU tessellation. Five fresh-process samples identify L3 at +233.091 ms median preview: 223.734 ms compile and 1.885 ms tessellation. The +first safe cycle found no qualifying 25% optimization. Sharing live OCCT handles +across disposable worker checkpoints or omitting history evaluation would cross +shape-ownership or stable-reference contracts, so neither shortcut was taken. +The measurement and evidence boundary are recorded in +`docs/PERFORMANCE_2026-09-14.md`. + +## Phase 8 — exact smooth loft geometry and naming — focused-verified + +`LoftMode::Smooth` uses exact `BRepOffsetAPI_ThruSections` interpolation, not a +polygonal substitute. Its lateral provenance is derived from complete OCCT +history columns; missing, duplicated, or partial history refuses the operation. +Smooth and ruled provenance are deliberately distinct, with naming-store v6. + +## Phase 9 — persisted smooth-loft interaction — focused-verified + +Document format 42 persists `LoftMode::{Ruled, Smooth}` and migrates format 41 +to `Ruled`. The real loft builder/editor exposes both modes, keeps ordered +section navigation and removal reachable, and preserves preview/apply/cancel, +explicit target-body behavior, undo/redo, save/reopen, and export semantics. +The Phase 6 handle is the driven smooth-loft acceptance part. + +## Phase 10 — release certification — pending final gate + +The only remaining sequence is one full integrated gate at the final source +revision, followed by a final-SHA AppImage build/smoke, staged installed-worker +smoke, and the atomic managed-launcher switch. The existing installed release +remains untouched until all of those pass, and then becomes `previous` for +rollback. + +Per-phase verification was deliberately focused. The implementation checklist is `docs/superpowers/plans/2026-09-15-usability-organic-modeling.md`. - -Per-phase verification is deliberately focused: affected tests plus the relevant -driven workflow. One full gate is reserved for the release candidate. diff --git a/docs/superpowers/plans/2026-09-15-usability-organic-modeling.md b/docs/superpowers/plans/2026-09-15-usability-organic-modeling.md index a7d6529..7c4f6ec 100644 --- a/docs/superpowers/plans/2026-09-15-usability-organic-modeling.md +++ b/docs/superpowers/plans/2026-09-15-usability-organic-modeling.md @@ -20,35 +20,34 @@ ### Task 1: Installed baseline and handle acceptance -- [ ] Record `0.0.4-alpha` at `b0232f41` as the installed baseline and retain `c111f856` as rollback. -- [ ] Add a five-section cubic-spline handle workflow with mounting base, holes, fillets, upstream editing, persistence, and STEP/STL oracles. -- [ ] Fix only interaction blockers reproduced by that workflow, with a failing regression test before each fix. +- [x] Record `0.0.4-alpha` at `b0232f41` as the installed baseline and retain `c111f856` as rollback. +- [x] Add a five-section cubic-spline handle workflow with mounting base, holes, fillets, upstream editing, persistence, and STEP/STL oracles. +- [x] Fix only interaction blockers reproduced by that workflow, with a failing regression test before each fix. ### Task 2: Interaction performance -- [ ] Add phase timing for queueing, compile/naming, tessellation, GPU upload, and visible preview acknowledgement. -- [ ] Profile the handle and L3 workflows with five samples. -- [ ] Optimize the largest safe contributor and retain exact geometry/naming signatures. -- [ ] Accept a 25% median improvement or record that the first safe profiling cycle found no qualifying change. +- [x] Add phase timing for authoring, compile/naming, and CPU tessellation, with the queue/GPU/frame boundary stated explicitly. +- [x] Profile the representative L2-L4 workflows with five fresh-process samples. +- [x] Preserve exact geometry/naming signatures while measuring the largest contributor. +- [x] Record that the first safe profiling cycle found no qualifying 25% change: exact compile/naming is 96% of L3 preview and the obvious shortcuts cross shape-ownership or reference-stability boundaries. ### Task 3: Smooth-loft geometry and provenance -- [ ] Add a failing kernel test for a smooth five-section cubic-spline solid and its OCCT history. -- [ ] Extend the bridge and evaluator with an explicit loft mode and bounded OCCT failure handling. -- [ ] Define smooth lateral-face provenance from the complete section column and refuse incomplete or ambiguous history. -- [ ] Add reorientation, upstream-edit, invalid-solid, and broken-reference tests. +- [x] Add a failing kernel test for a smooth five-section cubic-spline solid and its OCCT history. +- [x] Extend the bridge and evaluator with an explicit loft mode and bounded OCCT failure handling. +- [x] Define smooth lateral-face provenance from the complete section column and refuse incomplete or ambiguous history. +- [x] Add reorientation, upstream-edit, invalid-solid, and broken-reference tests. ### Task 4: Persisted GUI smooth lofts -- [ ] Add `LoftMode::{Ruled, Smooth}` to the document and migrate format 41 lofts to `Ruled`. -- [ ] Add `SetLoftMode`, undo/redo coverage, and compile dispatch. -- [ ] Add a ruled/smooth control to the existing loft builder and editor, including preview/apply/cancel. -- [ ] Drive the smooth handle through edit, save/reopen, STEP/STL export, and a designed negative control. +- [x] Add `LoftMode::{Ruled, Smooth}` to the document and migrate format 41 lofts to `Ruled`. +- [x] Add `SetLoftMode`, undo/redo coverage, and compile dispatch. +- [x] Add a ruled/smooth control to the existing loft builder and editor, including preview/apply/cancel. +- [x] Drive the smooth handle through edit, save/reopen, STEP/STL export, and a designed negative control. ### Task 5: Release -- [ ] Run the focused handle and smooth-loft workflows. +- [x] Run the focused handle and smooth-loft workflows. - [ ] Run one full integrated gate on the final candidate. - [ ] Build and smoke the AppImage with its bundled worker. - [ ] Switch the managed launcher atomically and retain the previous release for rollback. -