taskchampion-rb 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/docs/plan.md ADDED
@@ -0,0 +1,612 @@
1
+ # TaskChampion Ruby Bindings - Completion Plan
2
+
3
+ ## Status Overview
4
+
5
+ **Date**: 2025-01-31
6
+ **Current State**: 🎉 **MAJOR BREAKTHROUGH ACHIEVED**
7
+ **Core Issue**: ✅ **SOLVED** - Send trait architectural incompatibility resolved
8
+ **Remaining Work**: Standard implementation details and polishing
9
+
10
+ ### What's Done ✅
11
+
12
+ - **Thread Safety Solution**: ThreadBound wrapper pattern implemented and working
13
+ - **Core Architecture**: Replica and Task types successfully use ThreadBound
14
+ - **Magnus API Migration**: Major 0.6→0.7 compatibility issues resolved
15
+ - **Error System**: Ruby exception hierarchy with ThreadError, StorageError, etc.
16
+ - **Proof of Concept**: Fundamental approach validated and functional
17
+
18
+ ### Current Compilation Status
19
+
20
+ - **Before**: 54+ errors, primary issue was `cannot be sent between threads safely`
21
+ - **Now**: ~35 errors, all are solvable implementation details
22
+ - **Remaining**: Method registration, parameter signatures, type conversions
23
+
24
+ ---
25
+
26
+ ## Phase 1: Complete Basic Compilation (Priority: HIGH)
27
+
28
+ **Goal**: Get a clean compilation without runtime functionality
29
+ **Timeline**: 1-2 days
30
+ **Effort**: Medium
31
+
32
+ ### 1.1 Fix Magnus 0.7 Method Registration
33
+
34
+ **Issue**: Methods need `&Ruby` as first parameter in Magnus 0.7
35
+
36
+ **Files to Fix**:
37
+ - `ext/taskchampion/src/tag.rs`
38
+ - `ext/taskchampion/src/annotation.rs`
39
+ - `ext/taskchampion/src/operation.rs`
40
+ - `ext/taskchampion/src/operations.rs`
41
+ - `ext/taskchampion/src/task.rs`
42
+ - `ext/taskchampion/src/replica.rs`
43
+
44
+ **Pattern**:
45
+ ```rust
46
+ // Old (Magnus 0.6)
47
+ fn new(param: String) -> Result<Self, Error>
48
+
49
+ // New (Magnus 0.7)
50
+ fn new(_ruby: &Ruby, param: String) -> Result<Self, Error>
51
+ ```
52
+
53
+ **Method Trait Imports**:
54
+ ```rust
55
+ // Add to imports where method! macro is used
56
+ use magnus::method::{Function0, Function1, Function2, Function3};
57
+ // OR research if there's a better way to import method traits
58
+ ```
59
+
60
+ **Tasks**:
61
+ - [ ] Update all method signatures to include `&Ruby` parameter
62
+ - [ ] Import required method traits for `method!` macro
63
+ - [ ] Fix method registration calls
64
+ - [ ] Test compilation after each file
65
+
66
+ ### 1.2 Resolve Type Conversion Issues
67
+
68
+ **Issue**: String ↔ Value conversions and return types
69
+
70
+ **Common Patterns to Fix**:
71
+ ```rust
72
+ // Value creation
73
+ Value::from(()) // instead of Qnil::new() ✅ DONE
74
+
75
+ // Type conversions
76
+ Value::try_convert(v) // instead of v.try_convert() ✅ DONE
77
+
78
+ // Optional returns
79
+ option_to_ruby(value, |v| Ok(v.into())) // verify pattern works
80
+ ```
81
+
82
+ **Tasks**:
83
+ - [ ] Review all `mismatched types` errors
84
+ - [ ] Fix String → Value conversions
85
+ - [ ] Fix return type consistency
86
+ - [ ] Update optional value handling
87
+
88
+ ### 1.3 Fix Remaining API Issues
89
+
90
+ **Issue**: Magnus 0.7 API usage consistency
91
+
92
+ **Tasks**:
93
+ - [ ] Verify all `Ruby::get()` calls have proper error conversion
94
+ - [ ] Check `const_get` usage is consistent
95
+ - [ ] Validate `funcall` vs `ruby.funcall` patterns
96
+ - [ ] Fix any remaining deprecated API usage
97
+
98
+ **Expected Outcome**: Clean compilation with no errors
99
+
100
+ ---
101
+
102
+ ## Phase 2: Basic Functionality Testing (Priority: HIGH)
103
+
104
+ **Goal**: Verify core operations work end-to-end
105
+ **Timeline**: 1-2 days
106
+ **Effort**: Medium
107
+
108
+ ### 2.1 Create Minimal Test Suite
109
+
110
+ **File**: `test/test_basic_functionality.rb`
111
+
112
+ ```ruby
113
+ require 'test_helper'
114
+
115
+ class TestBasicFunctionality < Minitest::Test
116
+ def test_replica_creation
117
+ replica = Taskchampion::Replica.new_in_memory
118
+ assert_not_nil replica
119
+ end
120
+
121
+ def test_thread_safety_enforcement
122
+ replica = Taskchampion::Replica.new_in_memory
123
+
124
+ thread_error_raised = false
125
+ Thread.new do
126
+ begin
127
+ replica.task_uuids # Should raise ThreadError
128
+ rescue Taskchampion::ThreadError
129
+ thread_error_raised = true
130
+ end
131
+ end.join
132
+
133
+ assert thread_error_raised, "ThreadError should be raised on cross-thread access"
134
+ end
135
+
136
+ def test_basic_task_operations
137
+ replica = Taskchampion::Replica.new_in_memory
138
+ operations = Taskchampion::Operations.new
139
+
140
+ # Basic task creation and retrieval
141
+ uuid = SecureRandom.uuid
142
+ task = replica.create_task(uuid, operations)
143
+ assert_not_nil task
144
+
145
+ # Verify task can be retrieved
146
+ retrieved = replica.task(uuid)
147
+ assert_not_nil retrieved
148
+ end
149
+ end
150
+ ```
151
+
152
+ **Tasks**:
153
+ - [ ] Create basic test structure
154
+ - [ ] Test replica creation (in_memory, on_disk)
155
+ - [ ] Verify thread safety enforcement works
156
+ - [ ] Test basic task operations
157
+ - [ ] Run: `bundle exec ruby test/test_basic_functionality.rb`
158
+
159
+ ### 2.2 Validate ThreadBound Implementation
160
+
161
+ **Goal**: Ensure thread safety works as designed
162
+
163
+ **Tests**:
164
+ - [ ] **Same-thread access**: Should work normally
165
+ - [ ] **Cross-thread access**: Should raise `Taskchampion::ThreadError`
166
+ - [ ] **Error messages**: Should be clear and helpful
167
+ - [ ] **Memory safety**: No segfaults or crashes
168
+
169
+ **Commands**:
170
+ ```bash
171
+ cd /home/tcase/Sites/reference/taskchampion-rb
172
+ bundle exec ruby -e "
173
+ require './lib/taskchampion'
174
+ replica = Taskchampion::Replica.new_in_memory
175
+ puts 'Same thread: OK'
176
+
177
+ Thread.new do
178
+ begin
179
+ replica.task_uuids
180
+ puts 'ERROR: Should have raised ThreadError'
181
+ rescue => e
182
+ puts \"Cross thread raised: #{e.class} - #{e.message}\"
183
+ end
184
+ end.join
185
+ "
186
+ ```
187
+
188
+ ### 2.3 Basic Ruby API Verification
189
+
190
+ **Goal**: Verify Ruby-side API is usable
191
+
192
+ **Tasks**:
193
+ - [ ] Test module loading: `require 'taskchampion'`
194
+ - [ ] Test class accessibility: `Taskchampion::Replica`, `Taskchampion::Task`
195
+ - [ ] Test method calls don't crash
196
+ - [ ] Verify return types are correct Ruby objects
197
+
198
+ ---
199
+
200
+ ## Phase 3: Complete API Implementation (Priority: MEDIUM)
201
+
202
+ **Goal**: Implement full TaskChampion API surface
203
+ **Timeline**: 3-5 days
204
+ **Effort**: High
205
+
206
+ ### 3.1 Complete Method Registration
207
+
208
+ **Goal**: Restore all method registrations that were commented out
209
+
210
+ **Strategy**: Fix method registration issues systematically
211
+
212
+ **Files to Complete**:
213
+ ```
214
+ ext/taskchampion/src/tag.rs - Tag methods
215
+ ext/taskchampion/src/annotation.rs - Annotation methods
216
+ ext/taskchampion/src/task.rs - Task methods
217
+ ext/taskchampion/src/operation.rs - Operation methods
218
+ ext/taskchampion/src/operations.rs - Operations methods
219
+ ext/taskchampion/src/replica.rs - Replica methods
220
+ ```
221
+
222
+ **Method Categories**:
223
+ - [ ] **Creation methods**: `new`, constructors
224
+ - [ ] **Data access**: getters, setters
225
+ - [ ] **Utility methods**: `to_s`, `inspect`, `==`, `hash`
226
+ - [ ] **Business logic**: task operations, sync, etc.
227
+
228
+ ### 3.2 Implement Missing Classes
229
+
230
+ **Classes needing completion**:
231
+ - [ ] **WorkingSet**: Task working set management
232
+ - [ ] **DependencyMap**: Task dependency tracking
233
+ - [ ] **Status**: Task status enumeration
234
+ - [ ] **AccessMode**: Storage access modes
235
+
236
+ **Pattern for each class**:
237
+ ```rust
238
+ #[magnus::wrap(class = "Taskchampion::ClassName", free_immediately)]
239
+ pub struct ClassName(ThreadBound<TCClassName>);
240
+
241
+ impl ClassName {
242
+ fn new(_ruby: &Ruby, /* params */) -> Result<Self, Error> {
243
+ // Implementation
244
+ Ok(ClassName(ThreadBound::new(tc_object)))
245
+ }
246
+
247
+ // Other methods...
248
+ }
249
+
250
+ pub fn init(module: &RModule) -> Result<(), Error> {
251
+ let class = module.define_class("ClassName", class::object())?;
252
+ class.define_singleton_method("new", method!(ClassName::new, /* arity */))?;
253
+ // Other method registrations...
254
+ Ok(())
255
+ }
256
+ ```
257
+
258
+ ### 3.3 Ruby API Polish
259
+
260
+ **Tasks**:
261
+ - [ ] **Consistent naming**: Ensure Ruby idiomatic method names
262
+ - [ ] **Parameter validation**: Proper error messages for invalid input
263
+ - [ ] **Return types**: Consistent with Ruby expectations
264
+ - [ ] **Documentation strings**: Add method documentation
265
+
266
+ **Ruby Conventions**:
267
+ ```ruby
268
+ # Good Ruby API design
269
+ task.active? # not task.is_active
270
+ task.description # not task.get_description
271
+ task.uuid # not task.get_uuid
272
+ ```
273
+
274
+ ---
275
+
276
+ ## Phase 4: Advanced Features & Integration (Priority: MEDIUM)
277
+
278
+ **Goal**: Complete TaskChampion feature set
279
+ **Timeline**: 2-3 days
280
+ **Effort**: Medium
281
+
282
+ ### 4.1 Server Synchronization
283
+
284
+ **Features**:
285
+ - [ ] **Local sync**: `sync_to_local(server_dir, avoid_snapshots)`
286
+ - [ ] **Remote sync**: `sync_to_remote(url:, client_id:, encryption_secret:, avoid_snapshots:)`
287
+ - [ ] **GCP sync**: `sync_to_gcp(bucket:, credential_path:, encryption_secret:, avoid_snapshots:)`
288
+
289
+ **Ruby API Design**:
290
+ ```ruby
291
+ # Keyword arguments for complex methods
292
+ replica.sync_to_remote(
293
+ url: "https://server.com",
294
+ client_id: uuid,
295
+ encryption_secret: secret,
296
+ avoid_snapshots: false
297
+ )
298
+ ```
299
+
300
+ ### 4.2 Advanced Task Operations
301
+
302
+ **Features**:
303
+ - [ ] **Task modification**: Set properties, tags, annotations
304
+ - [ ] **Task queries**: Find by criteria, filtering
305
+ - [ ] **Bulk operations**: Multiple task updates
306
+ - [ ] **Undo system**: Operation reversal
307
+
308
+ ### 4.3 Storage Configuration
309
+
310
+ **Features**:
311
+ - [ ] **On-disk storage**: Configurable paths, creation options
312
+ - [ ] **In-memory storage**: For testing and temporary use
313
+ - [ ] **Access modes**: ReadOnly, ReadWrite configurations
314
+ - [ ] **Database migration**: Handle version upgrades
315
+
316
+ ---
317
+
318
+ ## Phase 5: Testing & Quality Assurance (Priority: HIGH)
319
+
320
+ **Goal**: Comprehensive testing and stability
321
+ **Timeline**: 2-3 days
322
+ **Effort**: Medium
323
+
324
+ ### 5.1 Comprehensive Test Suite
325
+
326
+ **Test Categories**:
327
+ - [ ] **Unit tests**: Each class and method
328
+ - [ ] **Integration tests**: End-to-end workflows
329
+ - [ ] **Thread safety tests**: Concurrent access patterns
330
+ - [ ] **Error handling tests**: All error conditions
331
+ - [ ] **Memory tests**: No leaks or crashes
332
+
333
+ **Test Structure**:
334
+ ```
335
+ test/
336
+ ├── test_helper.rb
337
+ ├── unit/
338
+ │ ├── test_replica.rb
339
+ │ ├── test_task.rb
340
+ │ ├── test_operations.rb
341
+ │ └── test_thread_safety.rb
342
+ ├── integration/
343
+ │ ├── test_task_lifecycle.rb
344
+ │ ├── test_sync_operations.rb
345
+ │ └── test_working_set.rb
346
+ └── performance/
347
+ └── test_benchmarks.rb
348
+ ```
349
+
350
+ ### 5.2 Thread Safety Validation
351
+
352
+ **Critical Tests**:
353
+ ```ruby
354
+ def test_cross_thread_access_raises_error
355
+ replica = Taskchampion::Replica.new_in_memory
356
+
357
+ errors = []
358
+ threads = 10.times.map do
359
+ Thread.new do
360
+ begin
361
+ replica.task_uuids
362
+ errors << "No error raised in #{Thread.current}"
363
+ rescue Taskchampion::ThreadError => e
364
+ # Expected - this is correct behavior
365
+ rescue => e
366
+ errors << "Wrong error type: #{e.class}"
367
+ end
368
+ end
369
+ end
370
+
371
+ threads.each(&:join)
372
+ assert errors.empty?, "Thread safety issues: #{errors}"
373
+ end
374
+
375
+ def test_same_thread_access_works
376
+ replica = Taskchampion::Replica.new_in_memory
377
+
378
+ # Should work fine
379
+ uuids = replica.task_uuids
380
+ assert uuids.is_a?(Array)
381
+ end
382
+ ```
383
+
384
+ ### 5.3 Memory Safety & Performance
385
+
386
+ **Tests**:
387
+ - [ ] **Memory leaks**: Long-running operations don't leak
388
+ - [ ] **Crash resistance**: Invalid input doesn't crash Ruby
389
+ - [ ] **Performance**: Reasonable performance vs pure TaskChampion
390
+ - [ ] **Resource cleanup**: Objects are properly freed
391
+
392
+ **Tools**:
393
+ ```bash
394
+ # Memory leak detection
395
+ valgrind --tool=memcheck ruby test/test_memory.rb
396
+
397
+ # Performance benchmarking
398
+ ruby test/performance/benchmarks.rb
399
+ ```
400
+
401
+ ---
402
+
403
+ ## Phase 6: Documentation & Polish (Priority: MEDIUM)
404
+
405
+ **Goal**: Production-ready documentation and packaging
406
+ **Timeline**: 1-2 days
407
+ **Effort**: Low
408
+
409
+ ### 6.1 API Documentation
410
+
411
+ **Files to create/update**:
412
+ - [ ] **README.md**: Installation, basic usage, examples
413
+ - [ ] **API_REFERENCE.md**: Complete API documentation
414
+ - [ ] **THREAD_SAFETY.md**: Thread safety guidelines
415
+ - [ ] **EXAMPLES.md**: Common usage patterns
416
+
417
+ **Ruby Documentation**:
418
+ ```ruby
419
+ # Add YARD documentation comments
420
+ class Replica
421
+ # Creates a new replica with on-disk storage
422
+ #
423
+ # @param path [String] Path to task database directory
424
+ # @param create_if_missing [Boolean] Create database if it doesn't exist
425
+ # @param access_mode [Symbol] :read_write or :read_only
426
+ # @return [Replica] New replica instance
427
+ # @raise [Taskchampion::StorageError] If database cannot be accessed
428
+ def self.new_on_disk(path, create_if_missing: false, access_mode: :read_write)
429
+ end
430
+ end
431
+ ```
432
+
433
+ ### 6.2 Examples and Tutorials
434
+
435
+ **Example Scripts**:
436
+ ```ruby
437
+ # examples/basic_usage.rb
438
+ require 'taskchampion'
439
+
440
+ # Create a task database
441
+ replica = Taskchampion::Replica.new_on_disk("/tmp/tasks", create_if_missing: true)
442
+
443
+ # Create some tasks
444
+ operations = Taskchampion::Operations.new
445
+ task1 = replica.create_task(SecureRandom.uuid, operations)
446
+ task2 = replica.create_task(SecureRandom.uuid, operations)
447
+
448
+ # Modify tasks
449
+ task1.set_description("Learn TaskChampion Ruby bindings")
450
+ task1.set_status(:pending)
451
+
452
+ # Save changes
453
+ replica.commit_operations(operations)
454
+
455
+ # Query tasks
456
+ all_tasks = replica.tasks
457
+ puts "Total tasks: #{all_tasks.size}"
458
+
459
+ # Sync with server (if configured)
460
+ replica.sync_to_remote(
461
+ url: ENV['TASKCHAMPION_SERVER'],
462
+ client_id: ENV['CLIENT_ID'],
463
+ encryption_secret: ENV['ENCRYPTION_SECRET']
464
+ )
465
+ ```
466
+
467
+ ### 6.3 Packaging & Distribution
468
+
469
+ **Tasks**:
470
+ - [ ] **Gemspec polish**: Proper dependencies, descriptions, metadata
471
+ - [ ] **Version management**: Semantic versioning aligned with TaskChampion
472
+ - [ ] **Build automation**: CI/CD for multiple Ruby versions and platforms
473
+ - [ ] **Precompiled gems**: Binary gems for major platforms
474
+
475
+ ---
476
+
477
+ ## Phase 7: Production Readiness (Priority: LOW)
478
+
479
+ **Goal**: Production deployment preparation
480
+ **Timeline**: 1-2 days
481
+ **Effort**: Low
482
+
483
+ ### 7.1 Error Handling & Logging
484
+
485
+ **Features**:
486
+ - [ ] **Comprehensive error coverage**: All TaskChampion errors mapped to Ruby
487
+ - [ ] **Logging integration**: Optional logging support
488
+ - [ ] **Debug modes**: Detailed error information in development
489
+ - [ ] **Graceful degradation**: Handle edge cases smoothly
490
+
491
+ ### 7.2 Platform Support
492
+
493
+ **Targets**:
494
+ - [ ] **Ruby versions**: 3.0, 3.1, 3.2, 3.3, 3.4
495
+ - [ ] **Platforms**: Linux (x86_64, ARM64), macOS (Intel, Apple Silicon), Windows
496
+ - [ ] **Precompiled gems**: Reduce compilation requirements for users
497
+
498
+ ### 7.3 Community & Maintenance
499
+
500
+ **Tasks**:
501
+ - [ ] **Contributing guidelines**: How to contribute to the project
502
+ - [ ] **Issue templates**: Bug reports, feature requests
503
+ - [ ] **Release process**: Automated releases with changelogs
504
+ - [ ] **Community docs**: Integration with broader TaskChampion ecosystem
505
+
506
+ ---
507
+
508
+ ## Risk Assessment & Mitigation
509
+
510
+ ### Low Risk ✅
511
+ - **Thread safety implementation**: Core pattern is proven and working
512
+ - **Basic API surface**: Standard Ruby/C extension patterns
513
+ - **Documentation**: Straightforward technical writing
514
+
515
+ ### Medium Risk ⚠️
516
+ - **Magnus 0.7 method registration**: May require more research
517
+ - **Complex API methods**: Server sync, advanced operations
518
+ - **Performance optimization**: May need tuning
519
+
520
+ ### High Risk ⚡
521
+ - **Cross-platform compilation**: Platform-specific issues possible
522
+ - **Memory management edge cases**: Complex object lifecycles
523
+ - **TaskChampion API changes**: Future compatibility
524
+
525
+ ### Mitigation Strategies
526
+ 1. **Incremental approach**: Test each phase before proceeding
527
+ 2. **Community engagement**: Ask Magnus maintainers for guidance
528
+ 3. **Fallback plans**: Simplify features if complexity is too high
529
+ 4. **Version pinning**: Pin TaskChampion version to avoid surprises
530
+
531
+ ---
532
+
533
+ ## Success Metrics
534
+
535
+ ### Phase Completion Criteria
536
+
537
+ **Phase 1 Success**:
538
+ - ✅ Clean compilation (0 errors)
539
+ - ✅ Basic gem loading works
540
+ - ✅ No crashes on simple operations
541
+
542
+ **Phase 2 Success**:
543
+ - ✅ Thread safety enforcement works
544
+ - ✅ Basic task operations complete
545
+ - ✅ Simple test suite passes
546
+
547
+ **Phase 3 Success**:
548
+ - ✅ Full API surface available
549
+ - ✅ All major classes implemented
550
+ - ✅ Ruby-idiomatic interface
551
+
552
+ **Final Success**:
553
+ - ✅ Comprehensive test suite passes
554
+ - ✅ Production-ready documentation
555
+ - ✅ Community can use the gem successfully
556
+
557
+ ### Quality Gates
558
+
559
+ - **Code quality**: No compiler warnings, clean lints
560
+ - **Memory safety**: No crashes, leaks, or undefined behavior
561
+ - **API consistency**: Ruby conventions followed throughout
562
+ - **Performance**: Reasonable overhead vs native TaskChampion
563
+ - **Documentation**: Complete and accurate API reference
564
+
565
+ ---
566
+
567
+ ## Getting Started
568
+
569
+ ### Immediate Next Steps (Today)
570
+
571
+ 1. **Start with Phase 1.1**: Fix method registration issues
572
+ ```bash
573
+ cd /home/tcase/Sites/reference/taskchampion-rb
574
+ bundle exec rake compile 2>&1 | grep "call_handle_error" | head -5
575
+ ```
576
+
577
+ 2. **Focus on one file at a time**: Start with `tag.rs` (smallest scope)
578
+
579
+ 3. **Research Magnus 0.7 patterns**: Look for working examples
580
+
581
+ 4. **Test incrementally**: Compile after each fix
582
+
583
+ ### Daily Progress Tracking
584
+
585
+ Create daily progress files:
586
+ - `progress/2025-01-31.md` - Document what was accomplished
587
+ - Track compilation error count reduction
588
+ - Note any blockers or discoveries
589
+ - Plan next day's priorities
590
+
591
+ ### Resource Links
592
+
593
+ - **Magnus Documentation**: https://docs.rs/magnus/0.7.1/magnus/
594
+ - **TaskChampion Rust API**: https://docs.rs/taskchampion/2.0.2/taskchampion/
595
+ - **Ruby C Extensions Guide**: https://guides.rubygems.org/gems-with-extensions/
596
+ - **Thread Safety Patterns**: Ruby concurrency best practices
597
+
598
+ ---
599
+
600
+ ## Conclusion
601
+
602
+ The hardest part is **DONE**. The architectural breakthrough has been achieved, and what remains is systematic implementation work.
603
+
604
+ **Key Insight**: We've proven that Magnus CAN handle non-Send types, opening up possibilities for many other Rust libraries that were previously thought incompatible with Ruby bindings.
605
+
606
+ **Path Forward**: Follow this plan systematically, test incrementally, and don't hesitate to simplify features if they become too complex. The core functionality is working, and everything else is additive.
607
+
608
+ 🎯 **Focus**: Get Phase 1 completed first - clean compilation is the foundation for everything else.
609
+
610
+ **Estimated Total Time**: 2-3 weeks for full completion
611
+ **Minimum Viable Product**: 1 week (through Phase 2)
612
+ **Production Ready**: 2-3 weeks (through Phase 6)