Skip to content

Commit 357e25f

Browse files
committed
add constraints plan
1 parent e93dbad commit 357e25f

1 file changed

Lines changed: 145 additions & 0 deletions

File tree

docs/void/plan-constraints-v2.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Void Constraints V2 Plan (Planegcs-First, Fallback as Safety Net)
2+
3+
## Goal
4+
5+
Move sketch solving to a clean planegcs-first architecture, remove dual-solver behavioral drift, and improve drag/tangent stability.
6+
7+
## Current Findings
8+
9+
1. Constraint solving is currently dual-mode by default:
10+
- `enforceWithPlanegcs()` runs, then a fallback settle pass is still applied.
11+
- This can reintroduce different motion/priority behavior after planegcs already converged.
12+
13+
2. Drag interactions frequently force fallback:
14+
- During drag, `useFallback: tangentDriven || !pointDrag` is used in pointer drag paths.
15+
- This bypasses planegcs exactly where stable incremental behavior matters most.
16+
17+
3. Tangent constraints are not mapped into planegcs in the current mapper:
18+
- `toPlanegcsConstraint()` covers many constraints but not sketch `tangent`.
19+
- Tangency currently depends on fallback heuristics (`constraints_tangent.js`).
20+
21+
4. The planegcs wrapper already supports temporary constraints:
22+
- Constraint objects with `temporary: true` are supported by the wrapper path.
23+
- This enables proper drag-driving constraints with lower priority solving semantics.
24+
25+
5. `angle_via_point` is available in the solver bindings:
26+
- Suitable for robust endpoint tangency encoding (angle = 0 at shared endpoint).
27+
- This aligns with FreeCAD guidance for improved stability vs direct tangent formulations in corner cases.
28+
29+
## Root Cause Summary
30+
31+
1. Two solvers are actively shaping geometry during interaction.
32+
2. Drag logic has explicit fallback preference in key paths.
33+
3. Tangency is solved outside planegcs, creating inconsistent convergence and corner-case instability.
34+
35+
## Target Architecture
36+
37+
1. Planegcs is the primary and default solver for all live interaction and final settle.
38+
2. Fallback solver is retained only as failure recovery.
39+
3. Drag uses temporary constraints in planegcs:
40+
- Temporary point-to-point/point-to-line style guidance constraints to cursor/ghost references.
41+
- No permanent topology mutation from drag constraints.
42+
4. Tangency uses planegcs-native representation:
43+
- Shared-endpoint tangent: `angle_via_point` with angle = 0.
44+
- Non-shared cases: use direct tangent primitives where stable (`tangent_la`, `tangent_aa`, etc.), with endpoint-angle fallback where needed.
45+
46+
## Phased Execution
47+
48+
## Phase 1: Instrumentation and Guardrails
49+
50+
1. Add solver telemetry per enforce call:
51+
- planegcs used, fallback used, solve status, elapsed time.
52+
2. Add debug toggle to display active temporary constraints during drag.
53+
3. Add deterministic logs for tangent constraint path selection.
54+
55+
Exit Criteria:
56+
1. We can observe when and why fallback is invoked.
57+
58+
## Phase 2: Temporary Drag Constraints
59+
60+
1. Add drag-time temporary constraints (`temporary: true`) in planegcs solve graph.
61+
2. Remove drag-path forced fallback defaults.
62+
3. Keep fallback only if planegcs solve fails or returns non-converged status.
63+
64+
Exit Criteria:
65+
1. Drag no longer “snaps back” from dual-pass disagreement.
66+
2. Solver path during normal drag is planegcs-only.
67+
68+
## Phase 3: Tangent Migration
69+
70+
1. Implement tangent mapping in `toPlanegcsConstraint()`:
71+
- line-arc, arc-arc, line-circle as available.
72+
2. For shared-endpoint tangent pairs, map to `angle_via_point` (angle=0).
73+
3. Keep old tangent fallback path behind a temporary feature flag for rollback.
74+
75+
Exit Criteria:
76+
1. Tangent drag corner cases no longer require tangent-specific fallback aggressiveness.
77+
2. Shared-endpoint tangent cases are stable under repeated edits/drag.
78+
79+
## Phase 4: Remove Default Dual Settle
80+
81+
1. Remove unconditional fallback settle after successful planegcs solve.
82+
2. Fallback runs only on explicit planegcs failure paths.
83+
3. Keep compatibility switch (`constraints_v2_force_fallback`) for emergency rollback.
84+
85+
Exit Criteria:
86+
1. Single primary solver behavior in normal operation.
87+
2. Fewer constraint jitter/regressions from solver disagreement.
88+
89+
## Phase 5: Cleanup
90+
91+
1. Simplify pointer drag enforcement call sites.
92+
2. Remove tangent-specific fallback tuning knobs that become obsolete.
93+
3. Document canonical constraint mapping table and temporary-constraint rules.
94+
95+
Exit Criteria:
96+
1. Constraint code paths are materially simpler and easier to reason about.
97+
98+
## Proposed Code Touchpoints
99+
100+
1. `src/void/sketch/constraints.js`
101+
- Add temporary constraint plumbing and tangent mapping in `toPlanegcsConstraint()`.
102+
- Remove unconditional fallback settle on success.
103+
104+
2. `src/void/sketch/pointer.js`
105+
- Replace drag-time fallback preference with planegcs temporary constraints.
106+
107+
3. `src/void/sketch/constraints_actions.js`
108+
- Ensure apply/edit flows use planegcs-first, fallback-on-failure behavior.
109+
110+
4. `src/void/sketch/constraints_tangent.js`
111+
- Transition from primary solver role to compatibility fallback only.
112+
113+
5. `src/void/solver/sketch/gcs_wrapper.js`
114+
- Confirm temporary constraint lifecycle handling and cleanup.
115+
116+
## Risks and Mitigations
117+
118+
1. Risk: Regression in legacy sketches tuned around fallback behavior.
119+
- Mitigation: feature flag + staged rollout + telemetry.
120+
121+
2. Risk: Performance regressions during drag with added temporary constraints.
122+
- Mitigation: limit temporary constraint count to active dragged subset; cap iterations.
123+
124+
3. Risk: Incorrect tangent mapping for mixed entity types.
125+
- Mitigation: explicit mapping matrix tests per constraint subtype.
126+
127+
## Validation Plan
128+
129+
1. Unit tests:
130+
- Tangent mapping (shared endpoint and non-shared).
131+
- Temporary constraint injection/removal lifecycle.
132+
- Planegcs success path without fallback pass.
133+
134+
2. Interaction tests:
135+
- Drag with dimensions, coincident, perpendicular, and tangent combos.
136+
- Repeated drag/release cycles without geometric drift.
137+
- Circular/grid/polygon pattern interactions under drag.
138+
139+
3. Regression scenarios:
140+
- Known tangent corner cases.
141+
- Previously flaky dual-solver “snap back” sketches.
142+
143+
## Recommendation
144+
145+
Start with Phase 2 (temporary drag constraints + fallback-on-failure only for drag) before full tangent migration. This yields immediate UX improvement and reduces dual-solver interference while keeping rollback safety.

0 commit comments

Comments
 (0)