review: usability audit v0.10.0 — all 11 findings resolved #34

Merged
user2595 merged 10 commits from review/usability-audit-2026-05-31 into main 2026-05-31 08:32:23 +00:00
Owner

Summary

Documentation and usability review of v0.10.0 — all 11 findings resolved.
Audit document: doc/reviewer/usability-audit-2026-05-31.md

Findings (11/11 )

ID Severity What
U1 🔴 Critical New example_flatten.cpp: real conformal flattening with Θ_v=2π (cathead: 5 Newton iters, u_v range≈2.96)
U2 🔴 Critical New example_cgal_api.cpp: first runnable CGAL public API example
U3 🟡 Medium contracts.md: check/enforce_gauss_bonnet HyperIdeal restriction + newton_hyper_ideal preconditions corrected
U4 🟡 Medium README: v0.9.0 → v0.10.0, 277 tests
U5 🟡 Medium Discrete_conformal_map.h: stale \file block rewritten, lists all 5 entry functions
U6 🟡 Medium README + 2 examples: gauge-vertex overload replaces old manual loop
U7 🟠 Minor getting-started.md: LOW_MEMORY_BUILD Mode 4 section added
U8 🟠 Minor README: LOW_MEMORY_BUILD compile-time entry added
U9 🟠 Minor layout.hpp: Layout2D.uv/.halfedge_uv index semantics + no-compaction precondition documented
U10 🟠 Minor getting-started.md: CLI parameter reference table (7 flags)
U11 🟠 Roadmap phases.md: Phase 9h — CLI extensions (--tol/--max-iter + Phase-9a models), effort estimates + implementation sketches

New files

  • code/examples/example_flatten.cpp — primary use case, real conformal map
  • code/examples/example_cgal_api.cpp — CGAL public API demo

Test plan

  • /test-cgal on the Pi
  • /quality-gates

🤖 Generated with Claude Code

## Summary Documentation and usability review of v0.10.0 — all 11 findings resolved. Audit document: `doc/reviewer/usability-audit-2026-05-31.md` ### Findings (11/11 ✅) | ID | Severity | What | |----|----------|------| | U1 | 🔴 Critical | New `example_flatten.cpp`: real conformal flattening with Θ_v=2π (cathead: 5 Newton iters, u_v range≈2.96) | | U2 | 🔴 Critical | New `example_cgal_api.cpp`: first runnable CGAL public API example | | U3 | 🟡 Medium | `contracts.md`: check/enforce_gauss_bonnet HyperIdeal restriction + newton_hyper_ideal preconditions corrected | | U4 | 🟡 Medium | README: v0.9.0 → v0.10.0, 277 tests | | U5 | 🟡 Medium | `Discrete_conformal_map.h`: stale `\file` block rewritten, lists all 5 entry functions | | U6 | 🟡 Medium | README + 2 examples: gauge-vertex overload replaces old manual loop | | U7 | 🟠 Minor | `getting-started.md`: LOW_MEMORY_BUILD Mode 4 section added | | U8 | 🟠 Minor | README: LOW_MEMORY_BUILD compile-time entry added | | U9 | 🟠 Minor | `layout.hpp`: Layout2D.uv/.halfedge_uv index semantics + no-compaction precondition documented | | U10 | 🟠 Minor | `getting-started.md`: CLI parameter reference table (7 flags) | | U11 | 🟠 Roadmap | `phases.md`: Phase 9h — CLI extensions (--tol/--max-iter + Phase-9a models), effort estimates + implementation sketches | ### New files - `code/examples/example_flatten.cpp` — primary use case, real conformal map - `code/examples/example_cgal_api.cpp` — CGAL public API demo ## Test plan - [ ] `/test-cgal` on the Pi - [ ] `/quality-gates` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
user2595 added 7 commits 2026-05-30 23:52:56 +00:00
External documentation and usability review of v0.10.0.
9 findings covering documentation correctness, API usability,
and new-user experience.

Critical:
  U1 — All examples show trivial identity map (natural theta),
       not real conformal flattening — new users see no-op output
  U2 — CGAL public API has zero runnable examples

Medium:
  U3 — contracts.md incorrect: check_gauss_bonnet row missing
       HyperIdeal restriction (deleted overload after Finding-B)
  U4 — README still shows v0.9.0 (current: v0.10.0, 277 tests)
  U5 — Discrete_conformal_map.h header comment describes Phase-8a
       state; all 5 entry functions already implemented
  U6 — New gauge-vertex overload (Finding-D) not reflected in
       README or examples — old verbose loop still shown

Minor:
  U7 — CONFORMALLAB_LOW_MEMORY_BUILD absent from getting-started.md
  U8 — CONFORMALLAB_LOW_MEMORY_BUILD absent from README table
  U9 — Layout2D.uv index semantics undocumented (v.idx() contract)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Finding-U1 and Finding-U2 from doc/reviewer/usability-audit-2026-05-31.md.

The existing examples (example_euclidean, example_layout, example_hyper_ideal)
all used the "natural theta" pattern which makes x*=0 trivially the
equilibrium — u_v ≈ 0 everywhere, no deformation. A new user following
these examples saw solver output but not conformal geometry.

New: example_flatten.cpp
  - PRIMARY USE CASE: conformally flatten a mesh to the plane
  - Sets Θ_v = 2π for all interior vertices (flat target)
  - Pins boundary vertices (no Gauss-Bonnet check for open meshes)
  - Demonstrates non-trivial u_v (cathead.obj: range ≈ 2.96, 5 Newton iters)
  - Documents the difference from "natural theta" explicitly

New: example_cgal_api.cpp
  - Demonstrates CGAL::discrete_conformal_map_euclidean (Discrete_conformal_map.h)
  - First runnable CGAL public API example; contrast with internal API
  - Documents the "natural theta" default behaviour and explains why u_v=0
  - Explains when to use CGAL API vs internal API

Both examples registered in code/examples/CMakeLists.txt and compile
cleanly with -DWITH_CGAL=ON.

Updated:
  - example_euclidean.cpp: prominent "TESTING CONVENTION" warning
  - example_layout.cpp: same warning on set_natural_theta helper
  - doc/getting-started.md: example_flatten is now the recommended
    "start here" example; note on natural-theta behaviour added

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
U10: CLI has no parameter reference in README or getting-started.md.
     Documents all 7 current flags with defaults in the audit file so
     a future session can add the table to getting-started.md.

U11: Three useful CLI gaps documented as a roadmap item:
     - --tol / --max-iter: Newton solver tuning, currently hardcoded
     - -g cp_euclidean / -g inversive_distance: Phase-9a models not
       reachable from CLI despite being fully implemented in the library
     Each item has an effort estimate (~30 min / ~2 h) and concrete
     acceptance criteria so a future session can pick it up cold.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Finding-U3 from doc/reviewer/usability-audit-2026-05-31.md.

Three concrete errors corrected:

1. check_gauss_bonnet() row (was: implies all map types work)
   → now: 'EuclideanMaps/SphericalMaps only' — HyperIdealMaps overload
     is = delete (compile error since external-audit Finding-B fix)

2. enforce_gauss_bonnet() row (same issue)
   → same restriction note added

3. newton_hyper_ideal() preconditions (was: 'lambda0 initialised')
   → WRONG: HyperIdeal computes lengths from b_v, a_e via zeta functions
     internally; lambda0 plays no role.  Correct precondition:
     'no lambda0 needed · no GB pre-check'
   → Added explanation: strictly convex energy (Springborn 2020 Thm 1.3)
     → Newton converges for any targets without a pre-check

Gauss-Bonnet prose section also updated:
  - Examples now show EuclideanMaps/SphericalMaps explicitly
  - HyperIdeal compile-error note added with the correct hyperbolic
    identity Σ(2π-Θ_v) - Area = 2π·χ and why no pre-check is needed
  - Open-mesh note added (GB identity does not hold for boundary meshes)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
U4 (README.md:17) — status line: v0.9.0 → v0.10.0, test count 0 → 277

U5 (Discrete_conformal_map.h:6-16) — \file Doxygen block rewritten:
  was: 'provides a single function … Spherical/hyperbolic scheduled for Phase 8b.2'
  now: lists all three discrete_conformal_map_* functions already present,
       plus pointers to the circle-packing companion headers

U7 (getting-started.md) — new 'Mode 4 — Low-memory build' section added
  after Mode 3; shows CONFORMALLAB_LOW_MEMORY_BUILD=ON with -j1 and explains
  the -O0 / no PCH / batch-1 tradeoffs for Raspberry Pi / ≤ 4 GB runners

U8 (README.md compile-time modes) — LOW_MEMORY_BUILD entry added to the
  compile-time workflow code block with a one-line explanation and the
  mandatory -j1 note

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Finding-U6 from doc/reviewer/usability-audit-2026-05-31.md.

The Finding-D fix (external-audit-2026-05-30) added a clean one-call
gauge-vertex overload:
  assign_euclidean_vertex_dof_indices(mesh, maps, gauge_vertex)

But all user-facing code still showed the old verbose manual loop:
  auto vit = mesh.vertices().begin();
  maps.v_idx[*vit++] = -1;
  int idx = 0;
  for (; vit != mesh.vertices().end(); ++vit) maps.v_idx[*vit] = idx++;

Replaced in three places:
  README.md 'Minimal usage' code block
  example_euclidean.cpp Step 3
  example_layout.cpp  pin_first() helper

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs: Layout2D index semantics, CLI table, CLI roadmap (U9+U10+U11)
Some checks failed
C++ Tests / test-fast (push) Has been cancelled
C++ Tests / test-cgal (push) Has been cancelled
C++ Tests / quality-gates (push) Has been cancelled
API Docs / doc-build (push) Has been cancelled
Markdown link check / check (push) Has been cancelled
C++ Tests / test-fast (pull_request) Successful in 2m10s
C++ Tests / quality-gates (pull_request) Has been skipped
C++ Tests / test-cgal (pull_request) Has been skipped
37b538aae4
U9 (layout.hpp + example_layout.cpp)
  Layout2D.uv and .halfedge_uv now have explicit Doxygen docs stating:
    - indexing: v.idx() / h.idx() (raw integer index)
    - length: mesh.number_of_vertices() / number_of_halfedges()
    - precondition: no vertex removal / collect_garbage() after loading
    - access pattern example in the doc comment
  example_layout.cpp: access site comment + static_cast<size_t>(v.idx())

U10 (getting-started.md)
  New 'CLI parameter reference' table (7 rows) added directly below the
  CLI usage examples; cross-references --help as the canonical source

U11 (doc/roadmap/phases.md)
  New Phase 9h 'CLI usability extensions' section inserted before Phase 10:
    9h.1  --tol / --max-iter solver-tuning params  (~30 min, no deps)
    9h.2  -g cp_euclidean / -g inversive_distance  (~2-4 h, needs 9a )
  Each sub-task has effort estimate, implementation sketch, and
  acceptance criteria so a future session can pick it up cold.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
user2595 added 1 commit 2026-05-30 23:53:06 +00:00
ci: trigger full pipeline /ci-all
Some checks failed
C++ Tests / test-fast (pull_request) Failing after 12m31s
C++ Tests / quality-gates (pull_request) Has been skipped
C++ Tests / test-fast (push) Successful in 1m51s
C++ Tests / quality-gates (push) Failing after 2m13s
API Docs / doc-build (push) Successful in 53s
Markdown link check / check (push) Successful in 45s
C++ Tests / test-cgal (pull_request) Has been skipped
C++ Tests / test-cgal (push) Failing after 21m0s
a7b966c850
user2595 added 1 commit 2026-05-31 05:56:51 +00:00
ci: remove /ci-all — Pi cannot sustain parallel Docker containers
Some checks failed
C++ Tests / test-fast (push) Successful in 1m55s
C++ Tests / test-cgal (push) Has been cancelled
C++ Tests / quality-gates (push) Has started running
API Docs / doc-build (push) Has been cancelled
Markdown link check / check (push) Has been cancelled
C++ Tests / test-fast (pull_request) Successful in 2m16s
C++ Tests / quality-gates (pull_request) Has been skipped
C++ Tests / test-cgal (pull_request) Has been skipped
d4ea5fdd2e
The Pi runner (3-4 GB RAM, swap heavily loaded) OOMs when /ci-all
triggers test-cgal + quality-gates + doc-build + links simultaneously:
four Docker containers start at once after test-fast completes, each
consuming 150-400 MB, exhausting available RAM.

Fix: /ci-all removed from all three workflow files.  Each keyword
now triggers exactly one job — no parallel container competition.

Safe workflow: one keyword per commit.
  Typical sequence:
    git commit -m 'fix: ... /test-cgal'   → CGAL tests (~5 min)
    git commit -m 'chore: /quality-gates' → style checks (~30 s)

CLAUDE.md: CI table updated with Pi-runner warning note.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
user2595 added 1 commit 2026-05-31 05:59:39 +00:00
ci: add memory limits to all containers — Pi protection
Some checks failed
C++ Tests / test-fast (pull_request) Failing after 2m7s
C++ Tests / quality-gates (pull_request) Has been skipped
C++ Tests / test-fast (push) Failing after 2m10s
C++ Tests / quality-gates (push) Has been skipped
API Docs / doc-build (push) Has been skipped
Markdown link check / check (push) Has been skipped
C++ Tests / test-cgal (pull_request) Has been skipped
C++ Tests / test-cgal (push) Has been skipped
d5a4d0e8ff
Every container now has an explicit --memory limit so the OOM killer
has clean boundaries to work with instead of letting any single job
consume all available RAM:

  test-fast:      800m  (build Eigen+GTest, run 26 tests)
  test-cgal:     2000m  (LOW_MEMORY_BUILD, was already set)
  quality-gates:  600m  (apt install + 4 script checks)
  doc-build:      800m  (Doxygen HTML generation)
  markdown-links: 400m  (pure Python, very lightweight)

memory-swap = 1.5× memory in each case (150% total) so the OOM
killer fires cleanly without exhausting the SD card.

⚠  This is workflow-side protection only.  The runner-side fix
   (capacity: 1 in act-runner config) prevents parallel containers
   entirely and is the more reliable protection — see CLAUDE.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
user2595 merged commit dc978cf5d3 into main 2026-05-31 08:32:23 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: conformallab/ConformalLabpp#34
No description provided.