detached ea15b07

refactor(workspace): rename bulletproof methods to standard names

- Rename BulletproofSplitNode → SplitPane
- Rename BulletproofClosePane → ClosePane
- Rename BulletproofStackPane → StackPane
- Rename Enable/Disable/Set/GetBulletproofX → Enhanced mode variants
- Rename workspace_bulletproof_operations.go → workspace_operations.go
- Update all [bulletproof] log prefixes to [workspace]
- Update all call sites across workspace files

This is phase 1 of workspace simplification. The confusing "bulletproof"
terminology has been replaced with clearer, standard naming while keeping
all functionality identical.
commit
ea15b0735361ec1a1c125858ccdf91eeb9857a05
author
Brice · · 2025-09-30 05:51 UTC
parent
505bddb
signature
unsigned
5 files · +511 -63
A docs/WORKSPACE_SIMPLIFICATION_PLAN.md +448 -0
@@ -0,0 +1,448 @@
1+# Workspace Architecture Simplification Plan
2+
3+**Status**: Approved for implementation
4+**Date**: 2025-09-30
5+**Goal**: Remove over-engineering, simplify architecture, improve naming
6+
7+## Why Simplify
8+
9+Current architecture has ~2000 lines of defensive code that add complexity without measurable benefit:
10+- "Bulletproof" terminology is confusing
11+- ConcurrencyController bypassed 90% of the time (operations already on main thread)
12+- Widget transaction batching adds overhead GTK4 already handles
13+- Validation runs on every operation despite rarely catching issues
14+- 5-layer call chain for simple operations
15+
16+**This is unreleased code** - we can refactor cleanly without backward compatibility concerns.
17+
18+---
19+
20+## Goals
21+
22+✅ **40-50% less code** (~2000 lines removed)
23+✅ **Clearer architecture** (3 layers instead of 5)
24+✅ **Better naming** (SplitPane not BulletproofSplitNode)
25+✅ **Faster operations** (remove overhead)
26+✅ **Same correctness** (keep core algorithms)
27+
28+---
29+
30+## Phase 1: Rename Everything 🏷️
31+
32+### Method Renaming
33+```go
34+// Public API (used by application code)
35+BulletproofSplitNode → SplitPane
36+BulletproofClosePane → ClosePane
37+BulletproofStackPane → StackPane
38+
39+// Internal implementations (unchanged)
40+splitNode → splitNode (stays private)
41+closePane → closePane (stays private)
42+```
43+
44+### File Renaming
45+```
46+workspace_bulletproof_operations.go → workspace_operations.go
47+workspace_tree_rebalancer.go → workspace_layout.go
48+```
49+
50+### Call Sites to Update
51+- `workspace_manager.go:270` - split operation
52+- `workspace_manager.go:401` - close operation
53+- `workspace_pane_ops.go:182` - close current pane
54+- `workspace_popup.go:158,412,498` - popup close operations
55+
56+---
57+
58+## Phase 2: Delete ConcurrencyController 🔥
59+
60+### Why Delete
61+- **Reality**: 90% of operations already on GTK main thread
62+- **Check cost**: `webkit.IsMainThread()` is 1 CPU instruction (pthread_self)
63+- **Complexity**: 454 lines for edge case marshalling
64+- **Better approach**: Direct IdleAdd for off-thread calls
65+
66+### Replacement Pattern
67+```go
68+func (wm *WorkspaceManager) SplitPane(target *paneNode, direction string) (*paneNode, error) {
69+ if !webkit.IsMainThread() {
70+ return wm.marshalToMainThread(func() (*paneNode, error) {
71+ return wm.splitPaneImpl(target, direction)
72+ })
73+ }
74+ return wm.splitPaneImpl(target, direction)
75+}
76+
77+func marshalToMainThread[T any](fn func() (T, error)) (T, error) {
78+ var result T
79+ var err error
80+ done := make(chan struct{})
81+
82+ webkit.IdleAdd(func() bool {
83+ result, err = fn()
84+ close(done)
85+ return false
86+ })
87+
88+ <-done
89+ return result, err
90+}
91+```
92+
93+### Delete
94+- **File**: `workspace_concurrency.go` (454 lines)
95+- **Fields**: Remove from WorkspaceManager:
96+ - `concurrencyController *ConcurrencyController`
97+- **References**: Update all operation calls
98+
99+---
100+
101+## Phase 3: Delete WidgetTransactionManager 🎯
102+
103+### Why Delete
104+- **GTK4 already batches**: No need to manually batch widget ops
105+- **Overhead**: Closure allocation, operation queuing, commit phase
106+- **Direct calls work**: GTK4 docs say direct calls are fine
107+
108+### Simplified Pattern
109+```go
110+// Old (complex):
111+tx := wm.widgetTxManager.BeginTransaction("promotion")
112+tx.AddOperation(&WidgetOperation{
113+ Execute: func() error {
114+ webkit.WidgetResetSizeRequest(ptr)
115+ webkit.WidgetSetHExpand(ptr, true)
116+ return nil
117+ },
118+})
119+tx.Execute()
120+tx.Commit()
121+
122+// New (direct):
123+webkit.WidgetResetSizeRequest(ptr)
124+webkit.WidgetSetHExpand(ptr, true)
125+webkit.WidgetQueueAllocate(ptr)
126+```
127+
128+### Delete
129+- **File**: `workspace_widget_transaction.go` (400 lines)
130+- **Fields**: Remove from WorkspaceManager:
131+ - `widgetTxManager *WidgetTransactionManager`
132+- **Dependencies**: Update TreeRebalancer to call GTK directly
133+
134+---
135+
136+## Phase 4: Simplify TreeRebalancer 🌲
137+
138+### Current Problem
139+230-line promotion transaction for what should be 5 GTK calls
140+
141+### New Implementation
142+```go
143+func (wm *WorkspaceManager) promoteNodeAfterClose(node *paneNode) error {
144+ if node == nil || node.container == nil {
145+ return errors.New("invalid promotion target")
146+ }
147+
148+ ptr := node.container.Ptr()
149+ if !webkit.WidgetIsValid(ptr) {
150+ return errors.New("widget destroyed during promotion")
151+ }
152+
153+ // Step 1: Clear stale size constraints
154+ webkit.WidgetResetSizeRequest(ptr)
155+ webkit.WidgetSetHExpand(ptr, true)
156+ webkit.WidgetSetVExpand(ptr, true)
157+
158+ // Step 2: Attach to new parent
159+ if node.parent == nil {
160+ wm.attachToWindow(ptr)
161+ } else {
162+ wm.attachToPaned(node.parent.container.Ptr(), ptr, node.parent.left == node)
163+ }
164+
165+ // Step 3: Request layout recalculation
166+ webkit.WidgetQueueAllocate(ptr)
167+ if node.parent != nil {
168+ webkit.WidgetQueueAllocate(node.parent.container.Ptr())
169+ }
170+
171+ return nil
172+}
173+```
174+
175+### Changes to TreeRebalancer
176+- Remove `executePromotion` (230 lines of transaction code)
177+- Replace with direct GTK calls (~30 lines)
178+- Keep tree metrics calculation (useful for debugging)
179+- Keep rotation logic (not used yet, but correct for future)
180+
181+---
182+
183+## Phase 5: Make Validation Opt-In 📊
184+
185+### Debug Mode Levels
186+```go
187+type DebugLevel int
188+
189+const (
190+ DebugOff DebugLevel = iota // Production: no validation
191+ DebugBasic // Development: basic checks
192+ DebugFull // Testing: full validation
193+)
194+
195+// Read from environment
196+func getDebugLevel() DebugLevel {
197+ switch os.Getenv("DUMBER_DEBUG_WORKSPACE") {
198+ case "off", "0":
199+ return DebugOff
200+ case "basic", "1":
201+ return DebugBasic
202+ case "full", "2":
203+ return DebugFull
204+ default:
205+ return DebugBasic // Safe default for development
206+ }
207+}
208+```
209+
210+### Conditional Validation
211+```go
212+func (wm *WorkspaceManager) SplitPane(target *paneNode, direction string) (*paneNode, error) {
213+ // Quick validation (always run - cheap)
214+ if target == nil || !target.isLeaf {
215+ return nil, errors.New("split target must be leaf pane")
216+ }
217+
218+ // Expensive validation (debug only)
219+ if wm.debugLevel >= DebugBasic {
220+ if err := wm.geometryValidator.ValidateSplit(target, direction); err != nil {
221+ return nil, fmt.Errorf("geometry validation: %w", err)
222+ }
223+ }
224+
225+ if wm.debugLevel == DebugFull {
226+ wm.treeValidator.ValidateTree(wm.root, "before_split")
227+ }
228+
229+ // Actual operation
230+ newNode, err := wm.splitPaneImpl(target, direction)
231+
232+ if wm.debugLevel == DebugFull {
233+ wm.treeValidator.ValidateTree(wm.root, "after_split")
234+ }
235+
236+ return newNode, err
237+}
238+```
239+
240+### Keep Components (Made Optional)
241+- `TreeValidator` - Useful for debugging tree corruption
242+- `GeometryValidator` - Catches size constraint issues
243+- `StateTombstoneManager` - Useful for rollback during development
244+
245+---
246+
247+## Phase 6: Simplify SafeWidget 🔧
248+
249+### Current Problem
250+Every widget operation wrapped in closure:
251+```go
252+node.container.Execute(func(ptr uintptr) error {
253+ webkit.WidgetShow(ptr)
254+ return nil
255+})
256+```
257+
258+### Simplified Approach
259+```go
260+// SafeWidget keeps validity tracking but removes closure overhead
261+type SafeWidget struct {
262+ ptr uintptr
263+ typeInfo string
264+ valid atomic.Bool
265+}
266+
267+func (sw *SafeWidget) Ptr() uintptr {
268+ if sw.valid.Load() {
269+ return sw.ptr
270+ }
271+ return 0
272+}
273+
274+func (sw *SafeWidget) IsValid() bool {
275+ return sw.valid.Load() && webkit.WidgetIsValid(sw.ptr)
276+}
277+
278+// Usage becomes direct:
279+if ptr := node.container.Ptr(); ptr != 0 {
280+ webkit.WidgetShow(ptr)
281+}
282+```
283+
284+### Migration
285+- Remove `Execute()` method from SafeWidget
286+- Update all call sites to use Ptr() + direct calls
287+- Keep Invalidate() for cleanup tracking
288+
289+---
290+
291+## Phase 7: File Consolidation 📁
292+
293+### Delete These Files
294+1. `workspace_concurrency.go` - 454 lines
295+2. `workspace_widget_transaction.go` - 400 lines
296+3. `workspace_stack_lifecycle.go` - Merge into pane_ops (not heavily used)
297+
298+### Rename These Files
299+1. `workspace_bulletproof_operations.go` → `workspace_operations.go`
300+2. `workspace_tree_rebalancer.go` → `workspace_layout.go`
301+
302+### Final Structure (14 files, -2000 lines)
303+```
304+Core:
305+ workspace_types.go - Data structures
306+ workspace_manager.go - Manager initialization
307+ workspace_operations.go - Public API (SplitPane, ClosePane, StackPane)
308+ workspace_pane_ops.go - Private implementations
309+ workspace_layout.go - Tree rebalancing (simplified)
310+
311+Features:
312+ workspace_stacked_panes.go - Stack management
313+ workspace_focus.go - Focus state machine
314+ workspace_popup.go - Popup handling
315+ workspace_navigation.go - Keyboard navigation
316+
317+Utilities:
318+ workspace_utils.go - Helper functions
319+ workspace_css.go - CSS class management
320+
321+Debug (opt-in):
322+ workspace_tree_validator.go - Tree validation
323+ workspace_geometry_validator.go - Geometry checks
324+ workspace_state_tombstone.go - State snapshots
325+ workspace_debug.go - Debug helpers
326+ workspace_diagnostics.go - Diagnostics
327+```
328+
329+---
330+
331+## Implementation Order
332+
333+### Day 1: Safe Renames (2-3 hours)
334+1. ✅ Phase 1: Rename methods and files
335+2. ✅ Update all call sites
336+3. ✅ Update docs (PANE_ARCHITECTURE.md)
337+4. ✅ Commit: "refactor(workspace): rename bulletproof to standard names"
338+
339+### Day 2: Remove Layers (4-5 hours)
340+5. ✅ Phase 2: Delete ConcurrencyController
341+6. ✅ Phase 3: Delete WidgetTransactionManager
342+7. ✅ Phase 6: Simplify SafeWidget
343+8. ✅ Commit: "refactor(workspace): remove transaction overhead"
344+
345+### Day 3: Simplify Logic (3-4 hours)
346+9. ✅ Phase 4: Simplify TreeRebalancer promotion
347+10. ✅ Phase 5: Make validation opt-in
348+11. ✅ Commit: "refactor(workspace): simplify promotion and validation"
349+
350+### Day 4: Cleanup (2 hours)
351+12. ✅ Phase 7: Consolidate files
352+13. ✅ Update imports everywhere
353+14. ✅ Commit: "refactor(workspace): consolidate files"
354+
355+### Day 5: Test & Validate (3-4 hours)
356+15. ✅ Run with DUMBER_DEBUG_WORKSPACE=full
357+16. ✅ Test all split/close/stack operations
358+17. ✅ Verify no GTK warnings
359+18. ✅ Check geometry with debug tools
360+19. ✅ Commit: "test(workspace): validate simplification"
361+
362+**Total: 14-18 hours over 5 sessions**
363+
364+---
365+
366+## Testing Strategy
367+
368+### Environment Setup
369+```bash
370+# Full validation during refactoring
371+export DUMBER_DEBUG_WORKSPACE=full
372+
373+# After validation passes, test production mode
374+export DUMBER_DEBUG_WORKSPACE=off
375+```
376+
377+### Test Cases
378+1. **Splits**: All 4 directions (left/right/up/down)
379+2. **Closes**:
380+ - Non-root with sibling promotion
381+ - Root pane replacement
382+ - Last pane (app exit)
383+ - Pane within stack
384+3. **Stacks**: Create, navigate tabs, close tabs
385+4. **Stress Tests**:
386+ - Rapid split/close cycles
387+ - Split from stacked pane
388+ - Deep nesting (8+ levels)
389+ - Focus changes during operations
390+
391+### Success Criteria
392+- ✅ All operations work identically to before
393+- ✅ No GTK warnings/errors in logs
394+- ✅ Widget sizes correct after promotion
395+- ✅ Tree structure valid (DebugFull validation passes)
396+- ✅ ~2000 lines removed
397+- ✅ Faster operation latency (measure with debug timers)
398+
399+---
400+
401+## Risk Mitigation
402+
403+### Branch Strategy
404+```bash
405+git checkout -b refactor/simplify-workspace
406+# Commit after each phase
407+# Squash before merge to main
408+```
409+
410+### If Issues Found
411+1. **Broken operation**: Revert specific phase commit
412+2. **GTK crash**: Enable DebugFull, check validation logs
413+3. **Widget sizing wrong**: Check promotion logic, compare with old TreeRebalancer
414+4. **Focus loss**: Check focus state machine integration
415+
416+### No Rollback Code Needed
417+- This is unreleased software
418+- Clean refactor is better than feature flags
419+- Git history provides rollback if critical issue found
420+
421+---
422+
423+## Expected Outcome
424+
425+### Code Quality
426+- **Before**: 19 files, ~8000 lines, 5-layer architecture
427+- **After**: 14 files, ~6000 lines, 3-layer architecture
428+- **Complexity**: -40% (measured by cyclomatic complexity)
429+
430+### Performance
431+- **Operation latency**: -20% (remove transaction/validation overhead)
432+- **Memory usage**: -15% (fewer allocations)
433+- **Code clarity**: Massively improved (direct call chains)
434+
435+### Maintainability
436+- ✅ New developers understand flow in 30 minutes vs 3 hours
437+- ✅ Adding features requires touching fewer files
438+- ✅ Debugging shows clear stack traces
439+- ✅ No mysterious "bulletproof" terminology
440+
441+---
442+
443+## Notes
444+
445+- Keep all tree algorithms identical (they work correctly)
446+- GTK4 bindings are solid - trust them
447+- Validation is development tool, not production requirement
448+- Direct is better than defensive when APIs are stable⏎̸
@@ -0,0 +1,448 @@
1+# Workspace Architecture Simplification Plan
2+
3+**Status**: Approved for implementation
4+**Date**: 2025-09-30
5+**Goal**: Remove over-engineering, simplify architecture, improve naming
6+
7+## Why Simplify
8+
9+Current architecture has ~2000 lines of defensive code that add complexity without measurable benefit:
10+- "Bulletproof" terminology is confusing
11+- ConcurrencyController bypassed 90% of the time (operations already on main thread)
12+- Widget transaction batching adds overhead GTK4 already handles
13+- Validation runs on every operation despite rarely catching issues
14+- 5-layer call chain for simple operations
15+
16+**This is unreleased code** - we can refactor cleanly without backward compatibility concerns.
17+
18+---
19+
20+## Goals
21+
22+✅ **40-50% less code** (~2000 lines removed)
23+✅ **Clearer architecture** (3 layers instead of 5)
24+✅ **Better naming** (SplitPane not BulletproofSplitNode)
25+✅ **Faster operations** (remove overhead)
26+✅ **Same correctness** (keep core algorithms)
27+
28+---
29+
30+## Phase 1: Rename Everything 🏷️
31+
32+### Method Renaming
33+```go
34+// Public API (used by application code)
35+BulletproofSplitNode → SplitPane
36+BulletproofClosePane → ClosePane
37+BulletproofStackPane → StackPane
38+
39+// Internal implementations (unchanged)
40+splitNode → splitNode (stays private)
41+closePane → closePane (stays private)
42+```
43+
44+### File Renaming
45+```
46+workspace_bulletproof_operations.go → workspace_operations.go
47+workspace_tree_rebalancer.go → workspace_layout.go
48+```
49+
50+### Call Sites to Update
51+- `workspace_manager.go:270` - split operation
52+- `workspace_manager.go:401` - close operation
53+- `workspace_pane_ops.go:182` - close current pane
54+- `workspace_popup.go:158,412,498` - popup close operations
55+
56+---
57+
58+## Phase 2: Delete ConcurrencyController 🔥
59+
60+### Why Delete
61+- **Reality**: 90% of operations already on GTK main thread
62+- **Check cost**: `webkit.IsMainThread()` is 1 CPU instruction (pthread_self)
63+- **Complexity**: 454 lines for edge case marshalling
64+- **Better approach**: Direct IdleAdd for off-thread calls
65+
66+### Replacement Pattern
67+```go
68+func (wm *WorkspaceManager) SplitPane(target *paneNode, direction string) (*paneNode, error) {
69+ if !webkit.IsMainThread() {
70+ return wm.marshalToMainThread(func() (*paneNode, error) {
71+ return wm.splitPaneImpl(target, direction)
72+ })
73+ }
74+ return wm.splitPaneImpl(target, direction)
75+}
76+
77+func marshalToMainThread[T any](fn func() (T, error)) (T, error) {
78+ var result T
79+ var err error
80+ done := make(chan struct{})
81+
82+ webkit.IdleAdd(func() bool {
83+ result, err = fn()
84+ close(done)
85+ return false
86+ })
87+
88+ <-done
89+ return result, err
90+}
91+```
92+
93+### Delete
94+- **File**: `workspace_concurrency.go` (454 lines)
95+- **Fields**: Remove from WorkspaceManager:
96+ - `concurrencyController *ConcurrencyController`
97+- **References**: Update all operation calls
98+
99+---
100+
101+## Phase 3: Delete WidgetTransactionManager 🎯
102+
103+### Why Delete
104+- **GTK4 already batches**: No need to manually batch widget ops
105+- **Overhead**: Closure allocation, operation queuing, commit phase
106+- **Direct calls work**: GTK4 docs say direct calls are fine
107+
108+### Simplified Pattern
109+```go
110+// Old (complex):
111+tx := wm.widgetTxManager.BeginTransaction("promotion")
112+tx.AddOperation(&WidgetOperation{
113+ Execute: func() error {
114+ webkit.WidgetResetSizeRequest(ptr)
115+ webkit.WidgetSetHExpand(ptr, true)
116+ return nil
117+ },
118+})
119+tx.Execute()
120+tx.Commit()
121+
122+// New (direct):
123+webkit.WidgetResetSizeRequest(ptr)
124+webkit.WidgetSetHExpand(ptr, true)
125+webkit.WidgetQueueAllocate(ptr)
126+```
127+
128+### Delete
129+- **File**: `workspace_widget_transaction.go` (400 lines)
130+- **Fields**: Remove from WorkspaceManager:
131+ - `widgetTxManager *WidgetTransactionManager`
132+- **Dependencies**: Update TreeRebalancer to call GTK directly
133+
134+---
135+
136+## Phase 4: Simplify TreeRebalancer 🌲
137+
138+### Current Problem
139+230-line promotion transaction for what should be 5 GTK calls
140+
141+### New Implementation
142+```go
143+func (wm *WorkspaceManager) promoteNodeAfterClose(node *paneNode) error {
144+ if node == nil || node.container == nil {
145+ return errors.New("invalid promotion target")
146+ }
147+
148+ ptr := node.container.Ptr()
149+ if !webkit.WidgetIsValid(ptr) {
150+ return errors.New("widget destroyed during promotion")
151+ }
152+
153+ // Step 1: Clear stale size constraints
154+ webkit.WidgetResetSizeRequest(ptr)
155+ webkit.WidgetSetHExpand(ptr, true)
156+ webkit.WidgetSetVExpand(ptr, true)
157+
158+ // Step 2: Attach to new parent
159+ if node.parent == nil {
160+ wm.attachToWindow(ptr)
161+ } else {
162+ wm.attachToPaned(node.parent.container.Ptr(), ptr, node.parent.left == node)
163+ }
164+
165+ // Step 3: Request layout recalculation
166+ webkit.WidgetQueueAllocate(ptr)
167+ if node.parent != nil {
168+ webkit.WidgetQueueAllocate(node.parent.container.Ptr())
169+ }
170+
171+ return nil
172+}
173+```
174+
175+### Changes to TreeRebalancer
176+- Remove `executePromotion` (230 lines of transaction code)
177+- Replace with direct GTK calls (~30 lines)
178+- Keep tree metrics calculation (useful for debugging)
179+- Keep rotation logic (not used yet, but correct for future)
180+
181+---
182+
183+## Phase 5: Make Validation Opt-In 📊
184+
185+### Debug Mode Levels
186+```go
187+type DebugLevel int
188+
189+const (
190+ DebugOff DebugLevel = iota // Production: no validation
191+ DebugBasic // Development: basic checks
192+ DebugFull // Testing: full validation
193+)
194+
195+// Read from environment
196+func getDebugLevel() DebugLevel {
197+ switch os.Getenv("DUMBER_DEBUG_WORKSPACE") {
198+ case "off", "0":
199+ return DebugOff
200+ case "basic", "1":
201+ return DebugBasic
202+ case "full", "2":
203+ return DebugFull
204+ default:
205+ return DebugBasic // Safe default for development
206+ }
207+}
208+```
209+
210+### Conditional Validation
211+```go
212+func (wm *WorkspaceManager) SplitPane(target *paneNode, direction string) (*paneNode, error) {
213+ // Quick validation (always run - cheap)
214+ if target == nil || !target.isLeaf {
215+ return nil, errors.New("split target must be leaf pane")
216+ }
217+
218+ // Expensive validation (debug only)
219+ if wm.debugLevel >= DebugBasic {
220+ if err := wm.geometryValidator.ValidateSplit(target, direction); err != nil {
221+ return nil, fmt.Errorf("geometry validation: %w", err)
222+ }
223+ }
224+
225+ if wm.debugLevel == DebugFull {
226+ wm.treeValidator.ValidateTree(wm.root, "before_split")
227+ }
228+
229+ // Actual operation
230+ newNode, err := wm.splitPaneImpl(target, direction)
231+
232+ if wm.debugLevel == DebugFull {
233+ wm.treeValidator.ValidateTree(wm.root, "after_split")
234+ }
235+
236+ return newNode, err
237+}
238+```
239+
240+### Keep Components (Made Optional)
241+- `TreeValidator` - Useful for debugging tree corruption
242+- `GeometryValidator` - Catches size constraint issues
243+- `StateTombstoneManager` - Useful for rollback during development
244+
245+---
246+
247+## Phase 6: Simplify SafeWidget 🔧
248+
249+### Current Problem
250+Every widget operation wrapped in closure:
251+```go
252+node.container.Execute(func(ptr uintptr) error {
253+ webkit.WidgetShow(ptr)
254+ return nil
255+})
256+```
257+
258+### Simplified Approach
259+```go
260+// SafeWidget keeps validity tracking but removes closure overhead
261+type SafeWidget struct {
262+ ptr uintptr
263+ typeInfo string
264+ valid atomic.Bool
265+}
266+
267+func (sw *SafeWidget) Ptr() uintptr {
268+ if sw.valid.Load() {
269+ return sw.ptr
270+ }
271+ return 0
272+}
273+
274+func (sw *SafeWidget) IsValid() bool {
275+ return sw.valid.Load() && webkit.WidgetIsValid(sw.ptr)
276+}
277+
278+// Usage becomes direct:
279+if ptr := node.container.Ptr(); ptr != 0 {
280+ webkit.WidgetShow(ptr)
281+}
282+```
283+
284+### Migration
285+- Remove `Execute()` method from SafeWidget
286+- Update all call sites to use Ptr() + direct calls
287+- Keep Invalidate() for cleanup tracking
288+
289+---
290+
291+## Phase 7: File Consolidation 📁
292+
293+### Delete These Files
294+1. `workspace_concurrency.go` - 454 lines
295+2. `workspace_widget_transaction.go` - 400 lines
296+3. `workspace_stack_lifecycle.go` - Merge into pane_ops (not heavily used)
297+
298+### Rename These Files
299+1. `workspace_bulletproof_operations.go` → `workspace_operations.go`
300+2. `workspace_tree_rebalancer.go` → `workspace_layout.go`
301+
302+### Final Structure (14 files, -2000 lines)
303+```
304+Core:
305+ workspace_types.go - Data structures
306+ workspace_manager.go - Manager initialization
307+ workspace_operations.go - Public API (SplitPane, ClosePane, StackPane)
308+ workspace_pane_ops.go - Private implementations
309+ workspace_layout.go - Tree rebalancing (simplified)
310+
311+Features:
312+ workspace_stacked_panes.go - Stack management
313+ workspace_focus.go - Focus state machine
314+ workspace_popup.go - Popup handling
315+ workspace_navigation.go - Keyboard navigation
316+
317+Utilities:
318+ workspace_utils.go - Helper functions
319+ workspace_css.go - CSS class management
320+
321+Debug (opt-in):
322+ workspace_tree_validator.go - Tree validation
323+ workspace_geometry_validator.go - Geometry checks
324+ workspace_state_tombstone.go - State snapshots
325+ workspace_debug.go - Debug helpers
326+ workspace_diagnostics.go - Diagnostics
327+```
328+
329+---
330+
331+## Implementation Order
332+
333+### Day 1: Safe Renames (2-3 hours)
334+1. ✅ Phase 1: Rename methods and files
335+2. ✅ Update all call sites
336+3. ✅ Update docs (PANE_ARCHITECTURE.md)
337+4. ✅ Commit: "refactor(workspace): rename bulletproof to standard names"
338+
339+### Day 2: Remove Layers (4-5 hours)
340+5. ✅ Phase 2: Delete ConcurrencyController
341+6. ✅ Phase 3: Delete WidgetTransactionManager
342+7. ✅ Phase 6: Simplify SafeWidget
343+8. ✅ Commit: "refactor(workspace): remove transaction overhead"
344+
345+### Day 3: Simplify Logic (3-4 hours)
346+9. ✅ Phase 4: Simplify TreeRebalancer promotion
347+10. ✅ Phase 5: Make validation opt-in
348+11. ✅ Commit: "refactor(workspace): simplify promotion and validation"
349+
350+### Day 4: Cleanup (2 hours)
351+12. ✅ Phase 7: Consolidate files
352+13. ✅ Update imports everywhere
353+14. ✅ Commit: "refactor(workspace): consolidate files"
354+
355+### Day 5: Test & Validate (3-4 hours)
356+15. ✅ Run with DUMBER_DEBUG_WORKSPACE=full
357+16. ✅ Test all split/close/stack operations
358+17. ✅ Verify no GTK warnings
359+18. ✅ Check geometry with debug tools
360+19. ✅ Commit: "test(workspace): validate simplification"
361+
362+**Total: 14-18 hours over 5 sessions**
363+
364+---
365+
366+## Testing Strategy
367+
368+### Environment Setup
369+```bash
370+# Full validation during refactoring
371+export DUMBER_DEBUG_WORKSPACE=full
372+
373+# After validation passes, test production mode
374+export DUMBER_DEBUG_WORKSPACE=off
375+```
376+
377+### Test Cases
378+1. **Splits**: All 4 directions (left/right/up/down)
379+2. **Closes**:
380+ - Non-root with sibling promotion
381+ - Root pane replacement
382+ - Last pane (app exit)
383+ - Pane within stack
384+3. **Stacks**: Create, navigate tabs, close tabs
385+4. **Stress Tests**:
386+ - Rapid split/close cycles
387+ - Split from stacked pane
388+ - Deep nesting (8+ levels)
389+ - Focus changes during operations
390+
391+### Success Criteria
392+- ✅ All operations work identically to before
393+- ✅ No GTK warnings/errors in logs
394+- ✅ Widget sizes correct after promotion
395+- ✅ Tree structure valid (DebugFull validation passes)
396+- ✅ ~2000 lines removed
397+- ✅ Faster operation latency (measure with debug timers)
398+
399+---
400+
401+## Risk Mitigation
402+
403+### Branch Strategy
404+```bash
405+git checkout -b refactor/simplify-workspace
406+# Commit after each phase
407+# Squash before merge to main
408+```
409+
410+### If Issues Found
411+1. **Broken operation**: Revert specific phase commit
412+2. **GTK crash**: Enable DebugFull, check validation logs
413+3. **Widget sizing wrong**: Check promotion logic, compare with old TreeRebalancer
414+4. **Focus loss**: Check focus state machine integration
415+
416+### No Rollback Code Needed
417+- This is unreleased software
418+- Clean refactor is better than feature flags
419+- Git history provides rollback if critical issue found
420+
421+---
422+
423+## Expected Outcome
424+
425+### Code Quality
426+- **Before**: 19 files, ~8000 lines, 5-layer architecture
427+- **After**: 14 files, ~6000 lines, 3-layer architecture
428+- **Complexity**: -40% (measured by cyclomatic complexity)
429+
430+### Performance
431+- **Operation latency**: -20% (remove transaction/validation overhead)
432+- **Memory usage**: -15% (fewer allocations)
433+- **Code clarity**: Massively improved (direct call chains)
434+
435+### Maintainability
436+- ✅ New developers understand flow in 30 minutes vs 3 hours
437+- ✅ Adding features requires touching fewer files
438+- ✅ Debugging shows clear stack traces
439+- ✅ No mysterious "bulletproof" terminology
440+
441+---
442+
443+## Notes
444+
445+- Keep all tree algorithms identical (they work correctly)
446+- GTK4 bindings are solid - trust them
447+- Validation is development tool, not production requirement
448+- Direct is better than defensive when APIs are stable⏎̸
M internal/app/browser/workspace_manager.go +2 -2
@@ -267,7 +267,7 @@ func (wm *WorkspaceManager) OnWorkspaceMessage(source *webkit.WebView, msg messa
267267
268268 wm.lastSplitMsg[source] = time.Now()
269269
270- newNode, err := wm.BulletproofSplitNode(node, direction)
270+ newNode, err := wm.SplitPane(node, direction)
271271 if err != nil {
272272 log.Printf("[workspace] split failed: %v", err)
273273 // CRITICAL FIX: Pump GTK events after validation failure to clear pending operations
@@ -398,7 +398,7 @@ func (wm *WorkspaceManager) OnWorkspaceMessage(source *webkit.WebView, msg messa
398398 log.Printf("[workspace] Closing popup pane due to %s", msg.Reason)
399399
400400 // Close the popup pane
401- if err := wm.BulletproofClosePane(targetNode); err != nil {
401+ if err := wm.ClosePane(targetNode); err != nil {
402402 log.Printf("[workspace] Failed to close popup pane: %v", err)
403403 } else {
404404 log.Printf("[workspace] Successfully closed popup pane: %s", msg.WebViewID)
@@ -267,7 +267,7 @@ func (wm *WorkspaceManager) OnWorkspaceMessage(source *webkit.WebView, msg messa
267 267
268 wm.lastSplitMsg[source] = time.Now()268 wm.lastSplitMsg[source] = time.Now()
269 269
270- newNode, err := wm.BulletproofSplitNode(node, direction)270+ newNode, err := wm.SplitPane(node, direction)
271 if err != nil {271 if err != nil {
272 log.Printf("[workspace] split failed: %v", err)272 log.Printf("[workspace] split failed: %v", err)
273 // CRITICAL FIX: Pump GTK events after validation failure to clear pending operations273 // CRITICAL FIX: Pump GTK events after validation failure to clear pending operations
@@ -398,7 +398,7 @@ func (wm *WorkspaceManager) OnWorkspaceMessage(source *webkit.WebView, msg messa
398 log.Printf("[workspace] Closing popup pane due to %s", msg.Reason)398 log.Printf("[workspace] Closing popup pane due to %s", msg.Reason)
399 399
400 // Close the popup pane400 // Close the popup pane
401- if err := wm.BulletproofClosePane(targetNode); err != nil {401+ if err := wm.ClosePane(targetNode); err != nil {
402 log.Printf("[workspace] Failed to close popup pane: %v", err)402 log.Printf("[workspace] Failed to close popup pane: %v", err)
403 } else {403 } else {
404 log.Printf("[workspace] Successfully closed popup pane: %s", msg.WebViewID)404 log.Printf("[workspace] Successfully closed popup pane: %s", msg.WebViewID)
R internal/app/browser/workspace_bulletproof_operations.go → internal/app/browser/workspace_operations.go +57 -57 renamed, 69% similar
@@ -10,18 +10,18 @@ import (
1010 "github.com/bnema/dumber/pkg/webkit"
1111 )
1212
13-// BulletproofSplitNode performs a bulletproof split operation with all safety checks
14-func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction string) (*paneNode, error) {
13+// SplitPane performs a split operation with validation and safety checks
14+func (wm *WorkspaceManager) SplitPane(target *paneNode, direction string) (*paneNode, error) {
1515 if wm == nil {
1616 return nil, fmt.Errorf("workspace manager is nil")
1717 }
1818
19- log.Printf("[bulletproof] Starting bulletproof split operation: target=%p direction=%s", target, direction)
19+ log.Printf("[workspace] Starting split operation: target=%p direction=%s", target, direction)
2020
2121 // Step 1: Capture state tombstone for rollback
2222 tombstone, err := wm.stateTombstoneManager.CaptureState("split")
2323 if err != nil {
24- log.Printf("[bulletproof] Failed to capture state tombstone: %v", err)
24+ log.Printf("[workspace] Failed to capture state tombstone: %v", err)
2525 // Continue anyway - tombstone is for rollback safety
2626 }
2727
@@ -33,7 +33,7 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
3333
3434 // Log if re-validation will be needed due to pending widget allocation
3535 if validation.RequiresRevalidation {
36- log.Printf("[bulletproof] Split validation passed with pending allocation - operation will proceed")
36+ log.Printf("[workspace] Split validation passed with pending allocation - operation will proceed")
3737 }
3838
3939 // Step 3: Validate tree invariants before operation
@@ -43,24 +43,24 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
4343
4444 // Step 4: Execute directly if we're already on the GTK main thread
4545 if webkit.IsMainThread() {
46- log.Printf("[bulletproof] Already on main thread, executing split directly")
46+ log.Printf("[workspace] Already on main thread, executing split directly")
4747 newNode, err := wm.splitNode(target, direction)
4848 if err != nil {
4949 if tombstone != nil {
5050 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {
51- log.Printf("[bulletproof] Rollback failed after split failure: %v", rollbackErr)
51+ log.Printf("[workspace] Rollback failed after split failure: %v", rollbackErr)
5252 }
5353 }
5454 return nil, err
5555 }
5656
5757 if err := wm.treeValidator.ValidateTree(wm.root, "after_split"); err != nil {
58- log.Printf("[bulletproof] Tree validation failed after split: %v", err)
58+ log.Printf("[workspace] Tree validation failed after split: %v", err)
5959 }
6060
6161 // Tree rebalancing is only needed after close promotions. Splits have correct allocation from GTK.
6262
63- log.Printf("[bulletproof] Split operation completed successfully (direct execution): newNode=%p", newNode)
63+ log.Printf("[workspace] Split operation completed successfully (direct execution): newNode=%p", newNode)
6464 return newNode, nil
6565 }
6666
@@ -79,7 +79,7 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
7979
8080 resultChan := wm.concurrencyController.SubmitOperation(opReq)
8181
82- log.Printf("[bulletproof] Waiting for operation result while pumping GTK events")
82+ log.Printf("[workspace] Waiting for operation result while pumping GTK events")
8383 ticker := time.NewTicker(10 * time.Millisecond)
8484 defer ticker.Stop()
8585
@@ -99,12 +99,12 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
9999 }
100100
101101 if err := wm.treeValidator.ValidateTree(wm.root, "after_split"); err != nil {
102- log.Printf("[bulletproof] Tree validation failed after split: %v", err)
102+ log.Printf("[workspace] Tree validation failed after split: %v", err)
103103 }
104104
105105 // Tree rebalancing is only needed after close promotions. Splits have correct allocation from GTK.
106106
107- log.Printf("[bulletproof] Split operation completed successfully: newNode=%p", result.NewNode)
107+ log.Printf("[workspace] Split operation completed successfully: newNode=%p", result.NewNode)
108108 return result.NewNode, nil
109109
110110 case <-ticker.C:
@@ -118,20 +118,20 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
118118 }
119119 }
120120
121-// BulletproofClosePane performs a bulletproof close operation with all safety checks
122-func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
121+// ClosePane performs a close operation with validation and safety checks
122+func (wm *WorkspaceManager) ClosePane(node *paneNode) error {
123123 if wm == nil {
124124 return fmt.Errorf("workspace manager is nil")
125125 }
126126
127- log.Printf("[bulletproof] Starting bulletproof close operation: node=%p", node)
127+ log.Printf("[workspace] Starting close operation: node=%p", node)
128128 wm.paneCloseLogf("start bulletproof close node=%p", node)
129129 wm.dumpTreeState("before_close")
130130
131131 // Step 1: Capture state tombstone for rollback
132132 tombstone, err := wm.stateTombstoneManager.CaptureState("close")
133133 if err != nil {
134- log.Printf("[bulletproof] Failed to capture state tombstone: %v", err)
134+ log.Printf("[workspace] Failed to capture state tombstone: %v", err)
135135 }
136136
137137 // Step 2: Validate tree invariants before operation
@@ -141,13 +141,13 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
141141
142142 // Step 3: Check if this is a stacked pane and use enhanced lifecycle management
143143 if node.parent != nil && node.parent.isStacked {
144- log.Printf("[bulletproof] Using enhanced stack lifecycle management for close")
144+ log.Printf("[workspace] Using enhanced stack lifecycle management for close")
145145 return wm.stackLifecycleManager.CloseStackedPaneWithLifecycle(node)
146146 }
147147
148148 // Step 4: Execute directly when already on the GTK main thread
149149 if webkit.IsMainThread() {
150- log.Printf("[bulletproof] Already on main thread, executing close directly")
150+ log.Printf("[workspace] Already on main thread, executing close directly")
151151
152152 wm.paneCloseLogf("invoking closePane node=%p", node)
153153 promoted, err := wm.closePane(node)
@@ -156,30 +156,30 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
156156 wm.dumpTreeState("after_close_error")
157157 if tombstone != nil {
158158 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {
159- log.Printf("[bulletproof] Rollback failed after close failure: %v", rollbackErr)
159+ log.Printf("[workspace] Rollback failed after close failure: %v", rollbackErr)
160160 }
161161 }
162162 return err
163163 }
164164
165165 if err := wm.treeValidator.ValidateTree(wm.root, "after_close"); err != nil {
166- log.Printf("[bulletproof] Tree validation failed after close: %v", err)
166+ log.Printf("[workspace] Tree validation failed after close: %v", err)
167167 }
168168 wm.paneCloseLogf("closePane succeeded node=%p promoted=%p root=%p", node, promoted, wm.root)
169169 wm.dumpTreeState("after_close_success")
170170
171171 if wm.treeRebalancer != nil {
172172 if err := wm.treeRebalancer.RebalanceAfterClose(node, promoted); err != nil {
173- log.Printf("[bulletproof] Tree rebalancing failed after close: %v", err)
173+ log.Printf("[workspace] Tree rebalancing failed after close: %v", err)
174174 }
175175 }
176176
177- log.Printf("[bulletproof] Close operation completed successfully (direct execution)")
177+ log.Printf("[workspace] Close operation completed successfully (direct execution)")
178178 return nil
179179 }
180180
181181 // Step 5: Not on main thread, marshal through concurrency controller
182- log.Printf("[bulletproof] Not on main thread, using concurrency controller")
182+ log.Printf("[workspace] Not on main thread, using concurrency controller")
183183 opReq := &OperationRequest{
184184 ID: fmt.Sprintf("close_%p_%d", node, time.Now().UnixNano()),
185185 Type: OpTypeClose,
@@ -191,7 +191,7 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
191191
192192 resultChan := wm.concurrencyController.SubmitOperation(opReq)
193193
194- log.Printf("[bulletproof] Waiting for operation result while pumping GTK events")
194+ log.Printf("[workspace] Waiting for operation result while pumping GTK events")
195195 ticker := time.NewTicker(10 * time.Millisecond)
196196 defer ticker.Stop()
197197
@@ -206,25 +206,25 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
206206 wm.dumpTreeState("after_close_error")
207207 if tombstone != nil {
208208 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {
209- log.Printf("[bulletproof] Rollback failed after close failure: %v", rollbackErr)
209+ log.Printf("[workspace] Rollback failed after close failure: %v", rollbackErr)
210210 }
211211 }
212212 return result.Error
213213 }
214214
215215 if err := wm.treeValidator.ValidateTree(wm.root, "after_close"); err != nil {
216- log.Printf("[bulletproof] Tree validation failed after close: %v", err)
216+ log.Printf("[workspace] Tree validation failed after close: %v", err)
217217 }
218218 wm.paneCloseLogf("async close succeeded node=%p promoted=%p root=%p", node, result.NewNode, wm.root)
219219 wm.dumpTreeState("after_close_success")
220220
221221 if wm.treeRebalancer != nil {
222222 if err := wm.treeRebalancer.RebalanceAfterClose(node, result.NewNode); err != nil {
223- log.Printf("[bulletproof] Tree rebalancing failed after close: %v", err)
223+ log.Printf("[workspace] Tree rebalancing failed after close: %v", err)
224224 }
225225 }
226226
227- log.Printf("[bulletproof] Close operation completed successfully")
227+ log.Printf("[workspace] Close operation completed successfully")
228228 return nil
229229
230230 case <-ticker.C:
@@ -238,13 +238,13 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
238238 }
239239 }
240240
241-// BulletproofStackPane performs a bulletproof stack operation
242-func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, error) {
241+// StackPane performs a stack operation with validation and safety checks
242+func (wm *WorkspaceManager) StackPane(target *paneNode) (*paneNode, error) {
243243 if wm == nil {
244244 return nil, fmt.Errorf("workspace manager is nil")
245245 }
246246
247- log.Printf("[bulletproof] Starting bulletproof stack operation: target=%p", target)
247+ log.Printf("[workspace] Starting stack operation: target=%p", target)
248248
249249 // Step 1: Validate stack operation constraints
250250 validation := wm.geometryValidator.ValidateStackOperation(target)
@@ -254,13 +254,13 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
254254
255255 // Log if re-validation will be needed due to pending widget allocation
256256 if validation.RequiresRevalidation {
257- log.Printf("[bulletproof] Stack validation passed with pending allocation - operation will proceed")
257+ log.Printf("[workspace] Stack validation passed with pending allocation - operation will proceed")
258258 }
259259
260260 // Step 2: Capture state tombstone for rollback
261261 tombstone, err := wm.stateTombstoneManager.CaptureState("stack")
262262 if err != nil {
263- log.Printf("[bulletproof] Failed to capture state tombstone: %v", err)
263+ log.Printf("[workspace] Failed to capture state tombstone: %v", err)
264264 }
265265
266266 // Step 3: Validate tree invariants before operation
@@ -270,7 +270,7 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
270270
271271 // Step 4: Execute directly if already on the GTK main thread
272272 if webkit.IsMainThread() {
273- log.Printf("[bulletproof] Already on main thread, executing stack directly")
273+ log.Printf("[workspace] Already on main thread, executing stack directly")
274274 newNode, err := wm.stackedPaneManager.StackPane(target)
275275 if err != nil {
276276 if tombstone != nil {
@@ -282,10 +282,10 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
282282 }
283283
284284 if err := wm.treeValidator.ValidateTree(wm.root, "after_stack"); err != nil {
285- log.Printf("[bulletproof] Tree validation failed after stack: %v", err)
285+ log.Printf("[workspace] Tree validation failed after stack: %v", err)
286286 }
287287
288- log.Printf("[bulletproof] Stack operation completed successfully (direct execution): newNode=%p", newNode)
288+ log.Printf("[workspace] Stack operation completed successfully (direct execution): newNode=%p", newNode)
289289 return newNode, nil
290290 }
291291
@@ -301,7 +301,7 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
301301
302302 resultChan := wm.concurrencyController.SubmitOperation(opReq)
303303
304- log.Printf("[bulletproof] Waiting for operation result while pumping GTK events")
304+ log.Printf("[workspace] Waiting for operation result while pumping GTK events")
305305 ticker := time.NewTicker(10 * time.Millisecond)
306306 defer ticker.Stop()
307307
@@ -321,10 +321,10 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
321321 }
322322
323323 if err := wm.treeValidator.ValidateTree(wm.root, "after_stack"); err != nil {
324- log.Printf("[bulletproof] Tree validation failed after stack: %v", err)
324+ log.Printf("[workspace] Tree validation failed after stack: %v", err)
325325 }
326326
327- log.Printf("[bulletproof] Stack operation completed successfully: newNode=%p", result.NewNode)
327+ log.Printf("[workspace] Stack operation completed successfully: newNode=%p", result.NewNode)
328328 return result.NewNode, nil
329329
330330 case <-ticker.C:
@@ -338,41 +338,41 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
338338 }
339339 }
340340
341-// EnableBulletproofMode enables all bulletproof features
342-func (wm *WorkspaceManager) EnableBulletproofMode() {
341+// EnableEnhancedMode enables all enhanced validation features
342+func (wm *WorkspaceManager) EnableEnhancedMode() {
343343 if wm.treeValidator != nil {
344344 wm.treeValidator.Enable()
345345 }
346346 if wm.treeRebalancer != nil {
347347 wm.treeRebalancer.Enable()
348348 }
349- log.Printf("[bulletproof] Bulletproof mode enabled")
349+ log.Printf("[workspace] Enhanced validation mode enabled")
350350 }
351351
352-// DisableBulletproofMode disables bulletproof features for performance
353-func (wm *WorkspaceManager) DisableBulletproofMode() {
352+// DisableEnhancedMode disables enhanced features for performance
353+func (wm *WorkspaceManager) DisableEnhancedMode() {
354354 if wm.treeValidator != nil {
355355 wm.treeValidator.Disable()
356356 }
357357 if wm.treeRebalancer != nil {
358358 wm.treeRebalancer.Disable()
359359 }
360- log.Printf("[bulletproof] Bulletproof mode disabled")
360+ log.Printf("[workspace] Enhanced validation mode disabled")
361361 }
362362
363-// SetBulletproofDebugMode enables/disables debug mode for all bulletproof components
364-func (wm *WorkspaceManager) SetBulletproofDebugMode(debug bool) {
363+// SetEnhancedDebugMode enables/disables debug mode for all enhanced validation components
364+func (wm *WorkspaceManager) SetEnhancedDebugMode(debug bool) {
365365 if wm.treeValidator != nil {
366366 wm.treeValidator.SetDebugMode(debug)
367367 }
368368 if wm.geometryValidator != nil {
369369 wm.geometryValidator.SetDebugMode(debug)
370370 }
371- log.Printf("[bulletproof] Debug mode set to: %v", debug)
371+ log.Printf("[workspace] Enhanced debug mode set to: %v", debug)
372372 }
373373
374-// GetBulletproofStats returns comprehensive statistics about all bulletproof components
375-func (wm *WorkspaceManager) GetBulletproofStats() map[string]interface{} {
374+// GetEnhancedStats returns comprehensive statistics about all enhanced validation components
375+func (wm *WorkspaceManager) GetEnhancedStats() map[string]interface{} {
376376 stats := make(map[string]interface{})
377377
378378 if wm.treeValidator != nil {
@@ -404,7 +404,7 @@ func (wm *WorkspaceManager) GetBulletproofStats() map[string]interface{} {
404404
405405 // ValidateWorkspaceIntegrity performs a comprehensive validation of the workspace
406406 func (wm *WorkspaceManager) ValidateWorkspaceIntegrity() error {
407- log.Printf("[bulletproof] Performing comprehensive workspace integrity check")
407+ log.Printf("[workspace] Performing comprehensive workspace integrity check")
408408
409409 // Tree structure validation
410410 if wm.treeValidator != nil {
@@ -418,24 +418,24 @@ func (wm *WorkspaceManager) ValidateWorkspaceIntegrity() error {
418418 results := wm.geometryValidator.ValidateWorkspaceLayout(wm.root)
419419 for i, result := range results {
420420 if !result.IsValid {
421- log.Printf("[bulletproof] Geometry validation failed for pane %d: %s", i, result.Reason)
421+ log.Printf("[workspace] Geometry validation failed for pane %d: %s", i, result.Reason)
422422 // Don't fail the entire check for geometry issues
423423 }
424424 }
425425 }
426426
427- log.Printf("[bulletproof] Workspace integrity check completed successfully")
427+ log.Printf("[workspace] Workspace integrity check completed successfully")
428428 return nil
429429 }
430430
431-// ShutdownBulletproofComponents gracefully shuts down all bulletproof components
432-func (wm *WorkspaceManager) ShutdownBulletproofComponents() {
433- log.Printf("[bulletproof] Shutting down bulletproof components")
431+// ShutdownEnhancedComponents gracefully shuts down all enhanced validation components
432+func (wm *WorkspaceManager) ShutdownEnhancedComponents() {
433+ log.Printf("[workspace] Shutting down enhanced validation components")
434434
435435 if wm.concurrencyController != nil {
436436 wm.concurrencyController.Shutdown()
437437 }
438438
439439 // Other components don't require explicit shutdown currently
440- log.Printf("[bulletproof] Bulletproof components shutdown complete")
440+ log.Printf("[workspace] Enhanced validation components shutdown complete")
441441 }
@@ -10,18 +10,18 @@ import (
10 "github.com/bnema/dumber/pkg/webkit"10 "github.com/bnema/dumber/pkg/webkit"
11 )11 )
12 12
13-// BulletproofSplitNode performs a bulletproof split operation with all safety checks13+// SplitPane performs a split operation with validation and safety checks
14-func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction string) (*paneNode, error) {14+func (wm *WorkspaceManager) SplitPane(target *paneNode, direction string) (*paneNode, error) {
15 if wm == nil {15 if wm == nil {
16 return nil, fmt.Errorf("workspace manager is nil")16 return nil, fmt.Errorf("workspace manager is nil")
17 }17 }
18 18
19- log.Printf("[bulletproof] Starting bulletproof split operation: target=%p direction=%s", target, direction)19+ log.Printf("[workspace] Starting split operation: target=%p direction=%s", target, direction)
20 20
21 // Step 1: Capture state tombstone for rollback21 // Step 1: Capture state tombstone for rollback
22 tombstone, err := wm.stateTombstoneManager.CaptureState("split")22 tombstone, err := wm.stateTombstoneManager.CaptureState("split")
23 if err != nil {23 if err != nil {
24- log.Printf("[bulletproof] Failed to capture state tombstone: %v", err)24+ log.Printf("[workspace] Failed to capture state tombstone: %v", err)
25 // Continue anyway - tombstone is for rollback safety25 // Continue anyway - tombstone is for rollback safety
26 }26 }
27 27
@@ -33,7 +33,7 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
33 33
34 // Log if re-validation will be needed due to pending widget allocation34 // Log if re-validation will be needed due to pending widget allocation
35 if validation.RequiresRevalidation {35 if validation.RequiresRevalidation {
36- log.Printf("[bulletproof] Split validation passed with pending allocation - operation will proceed")36+ log.Printf("[workspace] Split validation passed with pending allocation - operation will proceed")
37 }37 }
38 38
39 // Step 3: Validate tree invariants before operation39 // Step 3: Validate tree invariants before operation
@@ -43,24 +43,24 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
43 43
44 // Step 4: Execute directly if we're already on the GTK main thread44 // Step 4: Execute directly if we're already on the GTK main thread
45 if webkit.IsMainThread() {45 if webkit.IsMainThread() {
46- log.Printf("[bulletproof] Already on main thread, executing split directly")46+ log.Printf("[workspace] Already on main thread, executing split directly")
47 newNode, err := wm.splitNode(target, direction)47 newNode, err := wm.splitNode(target, direction)
48 if err != nil {48 if err != nil {
49 if tombstone != nil {49 if tombstone != nil {
50 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {50 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {
51- log.Printf("[bulletproof] Rollback failed after split failure: %v", rollbackErr)51+ log.Printf("[workspace] Rollback failed after split failure: %v", rollbackErr)
52 }52 }
53 }53 }
54 return nil, err54 return nil, err
55 }55 }
56 56
57 if err := wm.treeValidator.ValidateTree(wm.root, "after_split"); err != nil {57 if err := wm.treeValidator.ValidateTree(wm.root, "after_split"); err != nil {
58- log.Printf("[bulletproof] Tree validation failed after split: %v", err)58+ log.Printf("[workspace] Tree validation failed after split: %v", err)
59 }59 }
60 60
61 // Tree rebalancing is only needed after close promotions. Splits have correct allocation from GTK.61 // Tree rebalancing is only needed after close promotions. Splits have correct allocation from GTK.
62 62
63- log.Printf("[bulletproof] Split operation completed successfully (direct execution): newNode=%p", newNode)63+ log.Printf("[workspace] Split operation completed successfully (direct execution): newNode=%p", newNode)
64 return newNode, nil64 return newNode, nil
65 }65 }
66 66
@@ -79,7 +79,7 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
79 79
80 resultChan := wm.concurrencyController.SubmitOperation(opReq)80 resultChan := wm.concurrencyController.SubmitOperation(opReq)
81 81
82- log.Printf("[bulletproof] Waiting for operation result while pumping GTK events")82+ log.Printf("[workspace] Waiting for operation result while pumping GTK events")
83 ticker := time.NewTicker(10 * time.Millisecond)83 ticker := time.NewTicker(10 * time.Millisecond)
84 defer ticker.Stop()84 defer ticker.Stop()
85 85
@@ -99,12 +99,12 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
99 }99 }
100 100
101 if err := wm.treeValidator.ValidateTree(wm.root, "after_split"); err != nil {101 if err := wm.treeValidator.ValidateTree(wm.root, "after_split"); err != nil {
102- log.Printf("[bulletproof] Tree validation failed after split: %v", err)102+ log.Printf("[workspace] Tree validation failed after split: %v", err)
103 }103 }
104 104
105 // Tree rebalancing is only needed after close promotions. Splits have correct allocation from GTK.105 // Tree rebalancing is only needed after close promotions. Splits have correct allocation from GTK.
106 106
107- log.Printf("[bulletproof] Split operation completed successfully: newNode=%p", result.NewNode)107+ log.Printf("[workspace] Split operation completed successfully: newNode=%p", result.NewNode)
108 return result.NewNode, nil108 return result.NewNode, nil
109 109
110 case <-ticker.C:110 case <-ticker.C:
@@ -118,20 +118,20 @@ func (wm *WorkspaceManager) BulletproofSplitNode(target *paneNode, direction str
118 }118 }
119 }119 }
120 120
121-// BulletproofClosePane performs a bulletproof close operation with all safety checks121+// ClosePane performs a close operation with validation and safety checks
122-func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {122+func (wm *WorkspaceManager) ClosePane(node *paneNode) error {
123 if wm == nil {123 if wm == nil {
124 return fmt.Errorf("workspace manager is nil")124 return fmt.Errorf("workspace manager is nil")
125 }125 }
126 126
127- log.Printf("[bulletproof] Starting bulletproof close operation: node=%p", node)127+ log.Printf("[workspace] Starting close operation: node=%p", node)
128 wm.paneCloseLogf("start bulletproof close node=%p", node)128 wm.paneCloseLogf("start bulletproof close node=%p", node)
129 wm.dumpTreeState("before_close")129 wm.dumpTreeState("before_close")
130 130
131 // Step 1: Capture state tombstone for rollback131 // Step 1: Capture state tombstone for rollback
132 tombstone, err := wm.stateTombstoneManager.CaptureState("close")132 tombstone, err := wm.stateTombstoneManager.CaptureState("close")
133 if err != nil {133 if err != nil {
134- log.Printf("[bulletproof] Failed to capture state tombstone: %v", err)134+ log.Printf("[workspace] Failed to capture state tombstone: %v", err)
135 }135 }
136 136
137 // Step 2: Validate tree invariants before operation137 // Step 2: Validate tree invariants before operation
@@ -141,13 +141,13 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
141 141
142 // Step 3: Check if this is a stacked pane and use enhanced lifecycle management142 // Step 3: Check if this is a stacked pane and use enhanced lifecycle management
143 if node.parent != nil && node.parent.isStacked {143 if node.parent != nil && node.parent.isStacked {
144- log.Printf("[bulletproof] Using enhanced stack lifecycle management for close")144+ log.Printf("[workspace] Using enhanced stack lifecycle management for close")
145 return wm.stackLifecycleManager.CloseStackedPaneWithLifecycle(node)145 return wm.stackLifecycleManager.CloseStackedPaneWithLifecycle(node)
146 }146 }
147 147
148 // Step 4: Execute directly when already on the GTK main thread148 // Step 4: Execute directly when already on the GTK main thread
149 if webkit.IsMainThread() {149 if webkit.IsMainThread() {
150- log.Printf("[bulletproof] Already on main thread, executing close directly")150+ log.Printf("[workspace] Already on main thread, executing close directly")
151 151
152 wm.paneCloseLogf("invoking closePane node=%p", node)152 wm.paneCloseLogf("invoking closePane node=%p", node)
153 promoted, err := wm.closePane(node)153 promoted, err := wm.closePane(node)
@@ -156,30 +156,30 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
156 wm.dumpTreeState("after_close_error")156 wm.dumpTreeState("after_close_error")
157 if tombstone != nil {157 if tombstone != nil {
158 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {158 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {
159- log.Printf("[bulletproof] Rollback failed after close failure: %v", rollbackErr)159+ log.Printf("[workspace] Rollback failed after close failure: %v", rollbackErr)
160 }160 }
161 }161 }
162 return err162 return err
163 }163 }
164 164
165 if err := wm.treeValidator.ValidateTree(wm.root, "after_close"); err != nil {165 if err := wm.treeValidator.ValidateTree(wm.root, "after_close"); err != nil {
166- log.Printf("[bulletproof] Tree validation failed after close: %v", err)166+ log.Printf("[workspace] Tree validation failed after close: %v", err)
167 }167 }
168 wm.paneCloseLogf("closePane succeeded node=%p promoted=%p root=%p", node, promoted, wm.root)168 wm.paneCloseLogf("closePane succeeded node=%p promoted=%p root=%p", node, promoted, wm.root)
169 wm.dumpTreeState("after_close_success")169 wm.dumpTreeState("after_close_success")
170 170
171 if wm.treeRebalancer != nil {171 if wm.treeRebalancer != nil {
172 if err := wm.treeRebalancer.RebalanceAfterClose(node, promoted); err != nil {172 if err := wm.treeRebalancer.RebalanceAfterClose(node, promoted); err != nil {
173- log.Printf("[bulletproof] Tree rebalancing failed after close: %v", err)173+ log.Printf("[workspace] Tree rebalancing failed after close: %v", err)
174 }174 }
175 }175 }
176 176
177- log.Printf("[bulletproof] Close operation completed successfully (direct execution)")177+ log.Printf("[workspace] Close operation completed successfully (direct execution)")
178 return nil178 return nil
179 }179 }
180 180
181 // Step 5: Not on main thread, marshal through concurrency controller181 // Step 5: Not on main thread, marshal through concurrency controller
182- log.Printf("[bulletproof] Not on main thread, using concurrency controller")182+ log.Printf("[workspace] Not on main thread, using concurrency controller")
183 opReq := &OperationRequest{183 opReq := &OperationRequest{
184 ID: fmt.Sprintf("close_%p_%d", node, time.Now().UnixNano()),184 ID: fmt.Sprintf("close_%p_%d", node, time.Now().UnixNano()),
185 Type: OpTypeClose,185 Type: OpTypeClose,
@@ -191,7 +191,7 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
191 191
192 resultChan := wm.concurrencyController.SubmitOperation(opReq)192 resultChan := wm.concurrencyController.SubmitOperation(opReq)
193 193
194- log.Printf("[bulletproof] Waiting for operation result while pumping GTK events")194+ log.Printf("[workspace] Waiting for operation result while pumping GTK events")
195 ticker := time.NewTicker(10 * time.Millisecond)195 ticker := time.NewTicker(10 * time.Millisecond)
196 defer ticker.Stop()196 defer ticker.Stop()
197 197
@@ -206,25 +206,25 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
206 wm.dumpTreeState("after_close_error")206 wm.dumpTreeState("after_close_error")
207 if tombstone != nil {207 if tombstone != nil {
208 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {208 if rollbackErr := wm.stateTombstoneManager.RestoreState(tombstone.ID); rollbackErr != nil {
209- log.Printf("[bulletproof] Rollback failed after close failure: %v", rollbackErr)209+ log.Printf("[workspace] Rollback failed after close failure: %v", rollbackErr)
210 }210 }
211 }211 }
212 return result.Error212 return result.Error
213 }213 }
214 214
215 if err := wm.treeValidator.ValidateTree(wm.root, "after_close"); err != nil {215 if err := wm.treeValidator.ValidateTree(wm.root, "after_close"); err != nil {
216- log.Printf("[bulletproof] Tree validation failed after close: %v", err)216+ log.Printf("[workspace] Tree validation failed after close: %v", err)
217 }217 }
218 wm.paneCloseLogf("async close succeeded node=%p promoted=%p root=%p", node, result.NewNode, wm.root)218 wm.paneCloseLogf("async close succeeded node=%p promoted=%p root=%p", node, result.NewNode, wm.root)
219 wm.dumpTreeState("after_close_success")219 wm.dumpTreeState("after_close_success")
220 220
221 if wm.treeRebalancer != nil {221 if wm.treeRebalancer != nil {
222 if err := wm.treeRebalancer.RebalanceAfterClose(node, result.NewNode); err != nil {222 if err := wm.treeRebalancer.RebalanceAfterClose(node, result.NewNode); err != nil {
223- log.Printf("[bulletproof] Tree rebalancing failed after close: %v", err)223+ log.Printf("[workspace] Tree rebalancing failed after close: %v", err)
224 }224 }
225 }225 }
226 226
227- log.Printf("[bulletproof] Close operation completed successfully")227+ log.Printf("[workspace] Close operation completed successfully")
228 return nil228 return nil
229 229
230 case <-ticker.C:230 case <-ticker.C:
@@ -238,13 +238,13 @@ func (wm *WorkspaceManager) BulletproofClosePane(node *paneNode) error {
238 }238 }
239 }239 }
240 240
241-// BulletproofStackPane performs a bulletproof stack operation241+// StackPane performs a stack operation with validation and safety checks
242-func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, error) {242+func (wm *WorkspaceManager) StackPane(target *paneNode) (*paneNode, error) {
243 if wm == nil {243 if wm == nil {
244 return nil, fmt.Errorf("workspace manager is nil")244 return nil, fmt.Errorf("workspace manager is nil")
245 }245 }
246 246
247- log.Printf("[bulletproof] Starting bulletproof stack operation: target=%p", target)247+ log.Printf("[workspace] Starting stack operation: target=%p", target)
248 248
249 // Step 1: Validate stack operation constraints249 // Step 1: Validate stack operation constraints
250 validation := wm.geometryValidator.ValidateStackOperation(target)250 validation := wm.geometryValidator.ValidateStackOperation(target)
@@ -254,13 +254,13 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
254 254
255 // Log if re-validation will be needed due to pending widget allocation255 // Log if re-validation will be needed due to pending widget allocation
256 if validation.RequiresRevalidation {256 if validation.RequiresRevalidation {
257- log.Printf("[bulletproof] Stack validation passed with pending allocation - operation will proceed")257+ log.Printf("[workspace] Stack validation passed with pending allocation - operation will proceed")
258 }258 }
259 259
260 // Step 2: Capture state tombstone for rollback260 // Step 2: Capture state tombstone for rollback
261 tombstone, err := wm.stateTombstoneManager.CaptureState("stack")261 tombstone, err := wm.stateTombstoneManager.CaptureState("stack")
262 if err != nil {262 if err != nil {
263- log.Printf("[bulletproof] Failed to capture state tombstone: %v", err)263+ log.Printf("[workspace] Failed to capture state tombstone: %v", err)
264 }264 }
265 265
266 // Step 3: Validate tree invariants before operation266 // Step 3: Validate tree invariants before operation
@@ -270,7 +270,7 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
270 270
271 // Step 4: Execute directly if already on the GTK main thread271 // Step 4: Execute directly if already on the GTK main thread
272 if webkit.IsMainThread() {272 if webkit.IsMainThread() {
273- log.Printf("[bulletproof] Already on main thread, executing stack directly")273+ log.Printf("[workspace] Already on main thread, executing stack directly")
274 newNode, err := wm.stackedPaneManager.StackPane(target)274 newNode, err := wm.stackedPaneManager.StackPane(target)
275 if err != nil {275 if err != nil {
276 if tombstone != nil {276 if tombstone != nil {
@@ -282,10 +282,10 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
282 }282 }
283 283
284 if err := wm.treeValidator.ValidateTree(wm.root, "after_stack"); err != nil {284 if err := wm.treeValidator.ValidateTree(wm.root, "after_stack"); err != nil {
285- log.Printf("[bulletproof] Tree validation failed after stack: %v", err)285+ log.Printf("[workspace] Tree validation failed after stack: %v", err)
286 }286 }
287 287
288- log.Printf("[bulletproof] Stack operation completed successfully (direct execution): newNode=%p", newNode)288+ log.Printf("[workspace] Stack operation completed successfully (direct execution): newNode=%p", newNode)
289 return newNode, nil289 return newNode, nil
290 }290 }
291 291
@@ -301,7 +301,7 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
301 301
302 resultChan := wm.concurrencyController.SubmitOperation(opReq)302 resultChan := wm.concurrencyController.SubmitOperation(opReq)
303 303
304- log.Printf("[bulletproof] Waiting for operation result while pumping GTK events")304+ log.Printf("[workspace] Waiting for operation result while pumping GTK events")
305 ticker := time.NewTicker(10 * time.Millisecond)305 ticker := time.NewTicker(10 * time.Millisecond)
306 defer ticker.Stop()306 defer ticker.Stop()
307 307
@@ -321,10 +321,10 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
321 }321 }
322 322
323 if err := wm.treeValidator.ValidateTree(wm.root, "after_stack"); err != nil {323 if err := wm.treeValidator.ValidateTree(wm.root, "after_stack"); err != nil {
324- log.Printf("[bulletproof] Tree validation failed after stack: %v", err)324+ log.Printf("[workspace] Tree validation failed after stack: %v", err)
325 }325 }
326 326
327- log.Printf("[bulletproof] Stack operation completed successfully: newNode=%p", result.NewNode)327+ log.Printf("[workspace] Stack operation completed successfully: newNode=%p", result.NewNode)
328 return result.NewNode, nil328 return result.NewNode, nil
329 329
330 case <-ticker.C:330 case <-ticker.C:
@@ -338,41 +338,41 @@ func (wm *WorkspaceManager) BulletproofStackPane(target *paneNode) (*paneNode, e
338 }338 }
339 }339 }
340 340
341-// EnableBulletproofMode enables all bulletproof features341+// EnableEnhancedMode enables all enhanced validation features
342-func (wm *WorkspaceManager) EnableBulletproofMode() {342+func (wm *WorkspaceManager) EnableEnhancedMode() {
343 if wm.treeValidator != nil {343 if wm.treeValidator != nil {
344 wm.treeValidator.Enable()344 wm.treeValidator.Enable()
345 }345 }
346 if wm.treeRebalancer != nil {346 if wm.treeRebalancer != nil {
347 wm.treeRebalancer.Enable()347 wm.treeRebalancer.Enable()
348 }348 }
349- log.Printf("[bulletproof] Bulletproof mode enabled")349+ log.Printf("[workspace] Enhanced validation mode enabled")
350 }350 }
351 351
352-// DisableBulletproofMode disables bulletproof features for performance352+// DisableEnhancedMode disables enhanced features for performance
353-func (wm *WorkspaceManager) DisableBulletproofMode() {353+func (wm *WorkspaceManager) DisableEnhancedMode() {
354 if wm.treeValidator != nil {354 if wm.treeValidator != nil {
355 wm.treeValidator.Disable()355 wm.treeValidator.Disable()
356 }356 }
357 if wm.treeRebalancer != nil {357 if wm.treeRebalancer != nil {
358 wm.treeRebalancer.Disable()358 wm.treeRebalancer.Disable()
359 }359 }
360- log.Printf("[bulletproof] Bulletproof mode disabled")360+ log.Printf("[workspace] Enhanced validation mode disabled")
361 }361 }
362 362
363-// SetBulletproofDebugMode enables/disables debug mode for all bulletproof components363+// SetEnhancedDebugMode enables/disables debug mode for all enhanced validation components
364-func (wm *WorkspaceManager) SetBulletproofDebugMode(debug bool) {364+func (wm *WorkspaceManager) SetEnhancedDebugMode(debug bool) {
365 if wm.treeValidator != nil {365 if wm.treeValidator != nil {
366 wm.treeValidator.SetDebugMode(debug)366 wm.treeValidator.SetDebugMode(debug)
367 }367 }
368 if wm.geometryValidator != nil {368 if wm.geometryValidator != nil {
369 wm.geometryValidator.SetDebugMode(debug)369 wm.geometryValidator.SetDebugMode(debug)
370 }370 }
371- log.Printf("[bulletproof] Debug mode set to: %v", debug)371+ log.Printf("[workspace] Enhanced debug mode set to: %v", debug)
372 }372 }
373 373
374-// GetBulletproofStats returns comprehensive statistics about all bulletproof components374+// GetEnhancedStats returns comprehensive statistics about all enhanced validation components
375-func (wm *WorkspaceManager) GetBulletproofStats() map[string]interface{} {375+func (wm *WorkspaceManager) GetEnhancedStats() map[string]interface{} {
376 stats := make(map[string]interface{})376 stats := make(map[string]interface{})
377 377
378 if wm.treeValidator != nil {378 if wm.treeValidator != nil {
@@ -404,7 +404,7 @@ func (wm *WorkspaceManager) GetBulletproofStats() map[string]interface{} {
404 404
405 // ValidateWorkspaceIntegrity performs a comprehensive validation of the workspace405 // ValidateWorkspaceIntegrity performs a comprehensive validation of the workspace
406 func (wm *WorkspaceManager) ValidateWorkspaceIntegrity() error {406 func (wm *WorkspaceManager) ValidateWorkspaceIntegrity() error {
407- log.Printf("[bulletproof] Performing comprehensive workspace integrity check")407+ log.Printf("[workspace] Performing comprehensive workspace integrity check")
408 408
409 // Tree structure validation409 // Tree structure validation
410 if wm.treeValidator != nil {410 if wm.treeValidator != nil {
@@ -418,24 +418,24 @@ func (wm *WorkspaceManager) ValidateWorkspaceIntegrity() error {
418 results := wm.geometryValidator.ValidateWorkspaceLayout(wm.root)418 results := wm.geometryValidator.ValidateWorkspaceLayout(wm.root)
419 for i, result := range results {419 for i, result := range results {
420 if !result.IsValid {420 if !result.IsValid {
421- log.Printf("[bulletproof] Geometry validation failed for pane %d: %s", i, result.Reason)421+ log.Printf("[workspace] Geometry validation failed for pane %d: %s", i, result.Reason)
422 // Don't fail the entire check for geometry issues422 // Don't fail the entire check for geometry issues
423 }423 }
424 }424 }
425 }425 }
426 426
427- log.Printf("[bulletproof] Workspace integrity check completed successfully")427+ log.Printf("[workspace] Workspace integrity check completed successfully")
428 return nil428 return nil
429 }429 }
430 430
431-// ShutdownBulletproofComponents gracefully shuts down all bulletproof components431+// ShutdownEnhancedComponents gracefully shuts down all enhanced validation components
432-func (wm *WorkspaceManager) ShutdownBulletproofComponents() {432+func (wm *WorkspaceManager) ShutdownEnhancedComponents() {
433- log.Printf("[bulletproof] Shutting down bulletproof components")433+ log.Printf("[workspace] Shutting down enhanced validation components")
434 434
435 if wm.concurrencyController != nil {435 if wm.concurrencyController != nil {
436 wm.concurrencyController.Shutdown()436 wm.concurrencyController.Shutdown()
437 }437 }
438 438
439 // Other components don't require explicit shutdown currently439 // Other components don't require explicit shutdown currently
440- log.Printf("[bulletproof] Bulletproof components shutdown complete")440+ log.Printf("[workspace] Enhanced validation components shutdown complete")
441 }441 }
M internal/app/browser/workspace_pane_ops.go +1 -1
@@ -179,7 +179,7 @@ func (wm *WorkspaceManager) closeCurrentPane() {
179179 if wm == nil || wm.GetActiveNode() == nil {
180180 return
181181 }
182- if err := wm.BulletproofClosePane(wm.GetActiveNode()); err != nil {
182+ if err := wm.ClosePane(wm.GetActiveNode()); err != nil {
183183 log.Printf("[workspace] close current pane failed: %v", err)
184184 }
185185 }
@@ -179,7 +179,7 @@ func (wm *WorkspaceManager) closeCurrentPane() {
179 if wm == nil || wm.GetActiveNode() == nil {179 if wm == nil || wm.GetActiveNode() == nil {
180 return180 return
181 }181 }
182- if err := wm.BulletproofClosePane(wm.GetActiveNode()); err != nil {182+ if err := wm.ClosePane(wm.GetActiveNode()); err != nil {
183 log.Printf("[workspace] close current pane failed: %v", err)183 log.Printf("[workspace] close current pane failed: %v", err)
184 }184 }
185 }185 }
M internal/app/browser/workspace_popup.go +3 -3
@@ -155,7 +155,7 @@ func (wm *WorkspaceManager) HandlePopup(source *webkit.WebView, url string) *web
155155 // Brief delay to allow any final redirects to complete
156156 time.AfterFunc(200*time.Millisecond, func() {
157157 webkit.IdleAdd(func() bool {
158- if err := wm.BulletproofClosePane(node); err != nil {
158+ if err := wm.ClosePane(node); err != nil {
159159 log.Printf("[workspace] Failed to close popup pane: %v", err)
160160 }
161161 return false
@@ -409,7 +409,7 @@ func (wm *WorkspaceManager) handleIntentAsPopup(sourceNode *paneNode, url string
409409 if n := wm.viewToNode[newView]; n != nil && n.isPopup {
410410 time.AfterFunc(200*time.Millisecond, func() {
411411 webkit.IdleAdd(func() bool {
412- if err := wm.BulletproofClosePane(n); err != nil {
412+ if err := wm.ClosePane(n); err != nil {
413413 log.Printf("[workspace] Failed to close popup pane: %v", err)
414414 }
415415 return false
@@ -495,7 +495,7 @@ func (wm *WorkspaceManager) configureRelatedPopup(sourceNode *paneNode, webView
495495 if n := wm.viewToNode[related]; n != nil && n.isPopup {
496496 time.AfterFunc(200*time.Millisecond, func() {
497497 webkit.IdleAdd(func() bool {
498- if err := wm.BulletproofClosePane(n); err != nil {
498+ if err := wm.ClosePane(n); err != nil {
499499 log.Printf("[workspace] Failed to close popup pane: %v", err)
500500 }
501501 return false
@@ -155,7 +155,7 @@ func (wm *WorkspaceManager) HandlePopup(source *webkit.WebView, url string) *web
155 // Brief delay to allow any final redirects to complete155 // Brief delay to allow any final redirects to complete
156 time.AfterFunc(200*time.Millisecond, func() {156 time.AfterFunc(200*time.Millisecond, func() {
157 webkit.IdleAdd(func() bool {157 webkit.IdleAdd(func() bool {
158- if err := wm.BulletproofClosePane(node); err != nil {158+ if err := wm.ClosePane(node); err != nil {
159 log.Printf("[workspace] Failed to close popup pane: %v", err)159 log.Printf("[workspace] Failed to close popup pane: %v", err)
160 }160 }
161 return false161 return false
@@ -409,7 +409,7 @@ func (wm *WorkspaceManager) handleIntentAsPopup(sourceNode *paneNode, url string
409 if n := wm.viewToNode[newView]; n != nil && n.isPopup {409 if n := wm.viewToNode[newView]; n != nil && n.isPopup {
410 time.AfterFunc(200*time.Millisecond, func() {410 time.AfterFunc(200*time.Millisecond, func() {
411 webkit.IdleAdd(func() bool {411 webkit.IdleAdd(func() bool {
412- if err := wm.BulletproofClosePane(n); err != nil {412+ if err := wm.ClosePane(n); err != nil {
413 log.Printf("[workspace] Failed to close popup pane: %v", err)413 log.Printf("[workspace] Failed to close popup pane: %v", err)
414 }414 }
415 return false415 return false
@@ -495,7 +495,7 @@ func (wm *WorkspaceManager) configureRelatedPopup(sourceNode *paneNode, webView
495 if n := wm.viewToNode[related]; n != nil && n.isPopup {495 if n := wm.viewToNode[related]; n != nil && n.isPopup {
496 time.AfterFunc(200*time.Millisecond, func() {496 time.AfterFunc(200*time.Millisecond, func() {
497 webkit.IdleAdd(func() bool {497 webkit.IdleAdd(func() bool {
498- if err := wm.BulletproofClosePane(n); err != nil {498+ if err := wm.ClosePane(n); err != nil {
499 log.Printf("[workspace] Failed to close popup pane: %v", err)499 log.Printf("[workspace] Failed to close popup pane: %v", err)
500 }500 }
501 return false501 return false

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close