# Implementation Plan v2 - Refined ## Critical Changes from v1 1. **Add string handling strategy early (Phase 1.3)** 2. **Define error types upfront (Phase 1.4)** 3. **Emphasize test-driven development throughout** 4. **Clarify memory ownership at every step** 5. **Add missing helpers (kebab-case conversion, etc.)** --- ## Phase 1: Foundation (Week 1: Days 1-3) ### 1.1 ArgumentType Enum **File:** `src/ArgumentType.zig` **Duration:** 1 day - [ ] Define `ArgumentType` enum - [ ] Implement `fromZigType(comptime T: type) ArgumentType` - [ ] Implement `matches(self, other) bool` - [ ] **TESTS:** Type detection for all supported types **Key Decision:** Support `?T` by unwrapping to underlying type --- ### 1.2 ParsedValue Union **File:** `src/ArgumentType.zig` **Duration:** 1 day - [ ] Define `ParsedValue` tagged union - [ ] Implement `fromString(type, string, allocator) !ParsedValue` - [ ] Implement `toTypedValue(comptime T: type, parsed) T` - [ ] **TESTS:** Conversions for all types, error cases **Key Decision:** Allocate strings into caller-provided arena --- ### 1.3 String Handling Strategy **File:** `src/utils.zig` **Duration:** 0.5 days - [ ] Implement `toKebabCase(comptime name: []const u8) []const u8` - Convert camelCase/snake_case to kebab-case - Comptime function, returns comptime string - [ ] Document string ownership model: - Arena owns all parsed strings - Comptime strings (field names, literals) not duplicated - Runtime strings (argv) duplicated into arena - [ ] **TESTS:** kebab-case conversion edge cases **Key Decision:** Use arena allocator for all dynamic strings --- ### 1.4 Error Type Definitions **File:** `src/errors.zig` **Duration:** 0.5 days - [ ] Define comprehensive error set: ```zig pub const Error = error{ IncompatibleArgumentType, UnknownArgument, InvalidValue, InvalidIntegerValue, InvalidBooleanValue, InvalidEnumValue, MissingArgumentValue, OutOfMemory, }; ``` - [ ] Document when each error occurs - [ ] Consider error payloads for context **Key Decision:** Separate error type allows clear API contracts --- ## Phase 2: Metadata Extraction (Week 1: Days 4-5) ### 2.1 Metadata Structures **File:** `src/metadata.zig` **Duration:** 0.5 days - [ ] Define `ArgumentMetadata` struct - [ ] Define `ModuleInfo` struct - [ ] Define `FieldMeta` (what goes in `pub const meta = .{...}`) - [ ] Document structure ownership --- ### 2.2 Comptime Metadata Extraction **File:** `src/metadata.zig` **Duration:** 1.5 days - [ ] `extractFieldMetadata(comptime T: type, comptime field: Field) FieldMeta` - Get `T.meta.field_name` if exists - Generate defaults for missing fields - Convert field name to kebab-case - Extract default value - [ ] `extractDocComment(comptime T: type, comptime field_name: []const u8) []const u8` - Return empty for now (future: parse doc comments) - [ ] `formatDefaultValue(comptime T: type, value: T, allocator) ![]const u8` - Format bool, int, string, enum, list - [ ] **TESTS:** Metadata extraction with various struct configurations **Key Decision:** All metadata extraction is comptime --- ## Phase 3: Core Registry (Week 2: Days 6-9) ### 3.1 Registry Structure **File:** `src/ArgumentRegistry.zig` **Duration:** 1 day - [ ] Define struct with all fields - [ ] Implement `init(allocator) ArgumentRegistry` - [ ] Implement `deinit()` - [ ] **TESTS:** Init/deinit, memory leak detection **Key Decision:** Use StringHashMap for O(1) lookups --- ### 3.2 argv Caching **File:** `src/ArgumentRegistry.zig` **Duration:** 0.5 days - [ ] Cache argv on first access - [ ] Implement `isHelpRequested() bool` - [ ] **TESTS:** Help detection, caching behavior **Key Decision:** Registry owns argv memory --- ### 3.3 Metadata Registration with Collision Detection **File:** `src/ArgumentRegistry.zig` **Duration:** 2 days - [ ] `registerMetadata(comptime T: type, opts: ParseOptions) !void` - Create/get module entry - For each field: - Extract metadata - Check for existing argument - If exists and types match: warn, add module - If exists and types differ: error with locations - If new: store metadata - [ ] Implement collision detection logic - [ ] Format error messages with source locations - [ ] **TESTS:** Compatible collisions, incompatible collisions, error messages **Key Decision:** Source locations captured via `@src()`, stored as-is (compile-time strings) --- ### 3.4 Struct Tracking **File:** `src/ArgumentRegistry.zig` **Duration:** 0.5 days - [ ] Track parsed structs by type name - [ ] Skip re-registration if already parsed - [ ] **TESTS:** Multiple parse calls with same struct --- ## Phase 4: Argument Parsing (Week 2-3: Days 10-14) ### 4.1 Argv Parsing Infrastructure **File:** `src/parsing.zig` **Duration:** 1.5 days - [ ] `parseArgv() !void` - Iterate cached argv - Dispatch to appropriate parser - [ ] `parseArg(arg: []const u8) !void` - Handle `--long=value` - Handle `--long value` - Handle `--flag` (bool) - [ ] `parseShortArg(short: u8) !void` - Look up by short name - Handle value/flag - [ ] **TESTS:** All argument formats, unknown arguments **Key Decision:** Duplicate parsed strings into arena --- ### 4.2 Value Parsing with List Support **File:** `src/parsing.zig` **Duration:** 1.5 days - [ ] Parse integers with range checking - [ ] Parse booleans (true/false, 1/0, yes/no) - [ ] Parse strings (already strings, but duplicate) - [ ] Parse lists: - Split on comma - Also support repeated args: `--list=a --list=b` - Accumulate into single list - [ ] Parse enums (stringToEnum) - [ ] **TESTS:** All types, edge cases, error conditions **Key Decision:** Support both comma-separated and repeated arguments for lists --- ### 4.3 Struct Reconstruction with Type Safety **File:** `src/ArgumentRegistry.zig` **Duration:** 1 day - [ ] `reconstructStruct(comptime T: type) T` - For each field: - Get parsed value by long name - Convert to field type with comptime assertions - Fall back to default if not provided - Handle `?T` (optional) types - [ ] Runtime type checking for safety - [ ] **TESTS:** Struct reconstruction, optional fields, defaults **Key Decision:** Comptime type checks prevent runtime type errors --- ### 4.4 Main parse() Integration **File:** `src/ArgumentRegistry.zig` **Duration:** 1 day - [ ] `parse(comptime T: type, opts: ParseOptions) !T` - Check parsed_structs - If new: registerMetadata, parseArgv - reconstructStruct and return - Mark as parsed - [ ] **TESTS:** Full end-to-end parsing, multiple structs **Key Decision:** Single function handles everything --- ## Phase 5: Help Generation (Week 3: Days 15-16) ### 5.1 Help Text Generation **File:** `src/help.zig` **Duration:** 1 day - [ ] `getUsageAlloc(allocator) ![]const u8` - Write header - Write global options (--help) - For each module: - Write module name - For each argument: - Format `-s, --long Help text [default: X]` - Calculate alignment for readability - [ ] **TESTS:** Help text format, alignment, grouping **Key Decision:** Generate fresh each time (acceptable performance) --- ## Phase 6: Public API (Week 3-4: Day 17) ### 6.1 Module Exports and Documentation **File:** `src/main.zig` **Duration:** 1 day - [ ] Export all public types - [ ] Add top-level module documentation - [ ] Define version constant - [ ] Document global registry pattern - [ ] **TESTS:** Ensure exports are accessible --- ## Phase 7: Comprehensive Testing (Week 4: Days 18-21) ### 7.1 Unit Test Coverage **Duration:** 2 days - [ ] Achieve 100% coverage of: - Type detection and conversion - Metadata extraction - Collision detection - Parsing logic - Struct reconstruction - Help generation - [ ] Test error paths - [ ] Test edge cases --- ### 7.2 Integration Tests **Duration:** 1 day - [ ] Multi-module scenarios - [ ] Parse order independence - [ ] Help text workflow - [ ] Persistence workflow --- ### 7.3 Memory and Safety Tests **Duration:** 1 day - [ ] Memory leak detection on all tests - [ ] Test cleanup on error paths - [ ] Arena allocator correctness - [ ] Stress tests (many arguments, large values) --- ## Phase 8: Examples and Documentation (Week 5: Days 22-24) ### 8.1 Examples **Duration:** 2 days - [ ] `examples/simple.zig` - Basic usage - [ ] `examples/game_engine.zig` - Multi-module - [ ] `examples/persistence.zig` - Help text persistence - [ ] Ensure all examples compile and run --- ### 8.2 Documentation **Duration:** 1 day - [ ] Write comprehensive README - [ ] Document all public APIs - [ ] Add usage examples to doc comments - [ ] Document design decisions and tradeoffs --- ## Phase 9: Build and Integration (Week 5: Day 25) ### 9.1 Build System **Duration:** 0.5 days - [ ] Configure build.zig - [ ] Test, example, and install steps - [ ] Verify Zig 0.14 compatibility --- ### 9.2 Engine Integration **Duration:** 0.5 days - [ ] Import into Backlog engine - [ ] Test with actual engine modules - [ ] Document engine-specific usage --- ## Phase 10: Polish (Week 5: Day 25) ### 10.1 Final Review **Duration:** 0.5 days - [ ] Review all error messages - [ ] Run formatter - [ ] Check for TODOs - [ ] Verify no memory leaks - [ ] Performance check --- ## Daily Checklist Template For each day of implementation: - [ ] Write tests FIRST for new functionality - [ ] Implement feature - [ ] Ensure tests pass - [ ] Check for memory leaks - [ ] Update documentation - [ ] Commit with clear message --- ## Test-Driven Development Workflow 1. **Write failing test** - Define expected behavior 2. **Implement minimum** - Make test pass 3. **Refactor** - Improve code quality 4. **Repeat** - Next feature --- ## Memory Ownership Rules ### Simple Rules: 1. **Registry owns:** argv, all parsed strings (via arena) 2. **Caller owns:** allocator passed to registry 3. **Comptime owns:** field names, type names, meta strings 4. **Return values:** Structs contain pointers into registry arena - Valid until registry.deinit() - Document this lifetime requirement ### Rule of Thumb: - If it comes from argv → duplicate into arena - If it's comptime → use as-is - If it's dynamically formatted → allocate from arena --- ## Success Metrics - [ ] All tests pass (100% coverage target) - [ ] Zero memory leaks detected - [ ] All examples compile and run - [ ] Documentation complete and clear - [ ] Integration with Backlog engine successful - [ ] Collision detection works correctly - [ ] Help generation produces readable output - [ ] Can demonstrate persistence workflow --- ## Open Questions Resolved 1. **Positional arguments?** No, deferred to v2 2. **Config files?** No, separate feature 3. **Environment variables?** No, separate feature 4. **Shell completion?** No, v2 feature 5. **Validators?** No, v2 feature All features deferred to maintain focus on core use case. --- ## Confidence Level: 95% **Why higher:** - Addressed string handling explicitly - Clarified memory ownership model - Emphasized TDD approach - Defined error types upfront - Covered missing utility functions **Remaining concerns:** - Comptime complexity (will discover during Phase 2) - Edge cases in parsing (will catch with comprehensive tests) **Mitigation:** - Build incrementally - Test each component in isolation - Integration test early (Phase 7) --- ## Go/No-Go Decision Points ### After Phase 1 (Day 3): **Check:** Type system working correctly? - If yes: proceed - If no: revisit type design ### After Phase 2 (Day 5): **Check:** Metadata extraction compiling and working? - If yes: proceed - If no: simplify metadata approach ### After Phase 4 (Day 14): **Check:** Full parse cycle working end-to-end? - If yes: proceed to polish - If no: debug integration issues ### After Phase 7 (Day 21): **Check:** All tests passing, no leaks? - If yes: ready for production - If no: fix issues before release --- ## Implementation Notes - Keep each file under 500 lines - Prefer clarity over cleverness - Document all comptime behavior - Write tests for every public function - Use meaningful error messages - Follow Zig style guide **Ready to implement!** 🚀