Backlog/lib/zargs/todo/implementation_plan.md

19 KiB

zargs Implementation Plan

Project Structure

lib/zargs/
├── src/
│   ├── main.zig              # Public API exports
│   ├── ArgumentRegistry.zig  # Core registry implementation
│   ├── ArgumentType.zig      # Type system and conversions
│   ├── parsing.zig           # Argv parsing logic
│   ├── help.zig              # Help text generation
│   └── metadata.zig          # Metadata extraction from structs
├── tests/
│   ├── basic_test.zig        # Basic functionality
│   ├── collision_test.zig    # Type collision detection
│   ├── parsing_test.zig      # Argument parsing
│   └── help_test.zig         # Help generation
├── examples/
│   ├── simple.zig            # Minimal example
│   ├── game_engine.zig       # Multi-module game engine example
│   └── persistence.zig       # Help text persistence example
├── research/                 # Design documents (existing)
├── todo/                     # Implementation tracking (current)
└── build.zig                # Build configuration

Phase 1: Core Type System (Week 1)

1.1 ArgumentType Implementation

File: src/ArgumentType.zig

Tasks:

  • Define ArgumentType enum with all supported types
    • bool, u8, u16, u32, u64
    • i8, i16, i32, i64
    • string ([]const u8)
    • string_list ([]const []const u8)
    • enum_type (for Zig enums)
  • Implement fromZigType(comptime T: type) function
    • Handle bool
    • Handle integers with proper signedness/width detection
    • Handle string slices
    • Handle string list slices
    • Handle enums
    • Handle ?T (optional) by unwrapping
    • Provide clear compile errors for unsupported types
  • Implement matches(self, other) for type compatibility
  • Add unit tests for type detection

Acceptance Criteria:

  • All Zig primitive types correctly map to ArgumentType
  • Optional types unwrap correctly
  • Clear compile errors for unsupported types (structs, unions, etc.)
  • Type compatibility checker works correctly

Estimated Time: 1-2 days


1.2 ParsedValue Union

File: src/ArgumentType.zig (same file)

Tasks:

  • Define ParsedValue tagged union
  • Implement conversion functions:
    • fromString(arg_type: ArgumentType, s: []const u8, allocator: Allocator) !ParsedValue
    • toTypedValue(comptime T: type, parsed: ParsedValue) T
  • Handle list parsing (comma-separated values)
  • Handle enum parsing (string to enum value)
  • Add unit tests for value conversions

Acceptance Criteria:

  • String to typed value conversion works for all types
  • Lists properly split on commas
  • Enums parse from string names
  • Error handling for invalid values

Estimated Time: 1 day


Phase 2: Metadata System (Week 1)

2.1 Metadata Structures

File: src/metadata.zig

Tasks:

  • Define ArgumentMetadata struct
    • name, type, default_value_str
    • short, long, help, value_name
    • is_list flag
    • source_location
    • modules list (ArrayList)
  • Define ModuleInfo struct
    • name
    • arguments list (ArrayList)
  • Define FieldMetadata struct (for comptime extraction)

Acceptance Criteria:

  • Structures compile and are well-documented
  • Memory management strategy clear

Estimated Time: 0.5 days


2.2 Metadata Extraction

File: src/metadata.zig

Tasks:

  • Implement extractFieldMetadata(comptime T: type, comptime field_name: []const u8)
    • Get meta decl if exists
    • Extract short/long/help/value_name from meta
    • Generate defaults if meta missing
    • Convert field name to kebab-case for long form
  • Implement extractDocComment(comptime T: type, comptime field_name: []const u8) []const u8
    • Use doc comments as help text (if available in future Zig)
    • Fallback to empty string for now
  • Implement formatDefaultValue(comptime T: type, value: T, allocator: Allocator) ![]const u8
    • Format bool as "true"/"false"
    • Format integers as strings
    • Format strings as-is
    • Format enums as tag names
    • Format lists as comma-separated

Acceptance Criteria:

  • Can extract metadata from any valid struct
  • Default values formatted correctly
  • Missing meta declarations handled gracefully

Estimated Time: 1-2 days


Phase 3: Core Registry (Week 2)

3.1 ArgumentRegistry Basic Structure

File: src/ArgumentRegistry.zig

Tasks:

  • Define ArgumentRegistry struct with fields:
    • allocator, arena
    • arguments (StringHashMap)
    • modules (StringHashMap)
    • parsed_values (StringHashMap)
    • parsed_structs (StringHashMap)
    • argv cache
    • help_requested flag
  • Implement init(allocator: Allocator) ArgumentRegistry
  • Implement deinit(self: *ArgumentRegistry) void
    • Clean up all ArrayLists in modules
    • Clean up all ArrayLists in arguments
    • Deinit hashmaps
    • Deinit arena

Acceptance Criteria:

  • Registry initializes correctly
  • No memory leaks (test with MemoryLeakDetector)
  • All resources cleaned up properly

Estimated Time: 1 day


3.2 Help Request Detection

File: src/ArgumentRegistry.zig

Tasks:

  • Implement isHelpRequested(self: *ArgumentRegistry) bool
    • Cache argv on first call
    • Scan for "--help" or "-h"
    • Set help_requested flag
    • Return cached result on subsequent calls

Acceptance Criteria:

  • Help detection works before any parsing
  • Argv cached for later use
  • No performance issues with repeated calls

Estimated Time: 0.5 days


3.3 Metadata Registration

File: src/ArgumentRegistry.zig

Tasks:

  • Implement registerMetadata(self: *ArgumentRegistry, comptime T: type, opts: ParseOptions) !void
    • Get or create module entry
    • Iterate over struct fields (comptime)
    • Extract metadata for each field
    • Check for existing arguments (collision detection)
    • Error on incompatible type collisions with source locations
    • Warn on compatible type collisions
    • Add argument to module's list
    • Store ArgumentMetadata in registry

Acceptance Criteria:

  • Metadata correctly extracted from structs
  • Compatible collisions allowed with warnings
  • Incompatible collisions rejected with clear error messages
  • Source locations captured and displayed in errors

Estimated Time: 2 days


3.4 Struct Already Parsed Check

File: src/ArgumentRegistry.zig

Tasks:

  • Implement struct tracking in parsed_structs hashmap
  • Use @typeName(T) as key
  • Skip re-registration if already seen

Acceptance Criteria:

  • Calling parse() twice with same struct is efficient
  • No duplicate metadata registration

Estimated Time: 0.5 days


Phase 4: Argument Parsing (Week 2-3)

4.1 Argv Parsing Infrastructure

File: src/parsing.zig

Tasks:

  • Implement parseArgv(self: *ArgumentRegistry) !void
    • Get argv via std.process.argsAlloc() if not cached
    • Skip program name
    • Iterate over arguments
    • Dispatch to appropriate parser
  • Implement parseArg(self: *ArgumentRegistry, arg: []const u8) !void
    • Handle --long-name=value format
    • Handle --long-name value format (next arg)
    • Handle --flag (boolean) format
    • Look up argument metadata
    • Parse value according to type
    • Store in parsed_values
  • Implement parseShortArg(self: *ArgumentRegistry, short: u8) !void
    • Look up by short character
    • Handle value if required
    • Handle flag if boolean

Acceptance Criteria:

  • All argument formats parsed correctly
  • Unknown arguments produce clear errors
  • Values parsed according to type
  • Boolean flags don't require values

Estimated Time: 2 days


4.2 Value Parsing

File: src/parsing.zig

Tasks:

  • Implement integer parsing with error handling
  • Implement boolean parsing ("true"/"false", "1"/"0")
  • Implement string parsing (already a string)
  • Implement list parsing (split on comma)
  • Implement enum parsing (string to enum tag)
  • Handle parsing errors with useful messages

Acceptance Criteria:

  • All types parse correctly from strings
  • Clear errors for invalid values
  • Edge cases handled (empty strings, invalid numbers, etc.)

Estimated Time: 1 day


4.3 Struct Reconstruction

File: src/ArgumentRegistry.zig

Tasks:

  • Implement reconstructStruct(self: *ArgumentRegistry, comptime T: type) T
    • Create uninitialized struct
    • Iterate over fields (comptime)
    • Look up parsed value by long name
    • Convert ParsedValue to field type
    • Fall back to default if not parsed
    • Return completed struct

Acceptance Criteria:

  • Structs correctly populated with parsed values
  • Defaults used when arguments not provided
  • Type conversions work correctly
  • All fields properly initialized

Estimated Time: 1 day


4.4 Main parse() Function

File: src/ArgumentRegistry.zig

Tasks:

  • Implement parse(self: *ArgumentRegistry, comptime T: type, opts: ParseOptions) !T
    • Check if already parsed (use parsed_structs)
    • If not, register metadata
    • Parse argv (only new arguments)
    • Reconstruct and return struct
    • Mark struct as parsed

Acceptance Criteria:

  • Complete parse flow works end-to-end
  • Lazy parsing only processes new arguments
  • Subsequent calls return cached results efficiently

Estimated Time: 1 day


Phase 5: Help Generation (Week 3)

5.1 Help Text Formatting

File: src/help.zig

Tasks:

  • Implement getUsageAlloc(self: *ArgumentRegistry, allocator: Allocator) ![]const u8
    • Write header ("Usage: [OPTIONS]")
    • Write global options (--help)
    • Group arguments by module
    • Format each argument:
      • -s, --long-name <VALUE>
      • Help text
      • Default value
    • Return allocated string

Acceptance Criteria:

  • Help text is well-formatted and readable
  • Arguments grouped by module
  • Defaults shown for all arguments
  • Short and long forms displayed correctly

Estimated Time: 1 day


5.2 Help Text Alignment

File: src/help.zig

Tasks:

  • Calculate maximum width of argument specifications
  • Align help text in columns
  • Handle line wrapping for long help text
  • Ensure consistent spacing

Acceptance Criteria:

  • Help text looks professional
  • Columns aligned nicely
  • Readable on standard terminal widths

Estimated Time: 0.5 days


Phase 6: Public API (Week 3)

6.1 Main Module Exports

File: src/main.zig

Tasks:

  • Export ArgumentRegistry
  • Export ArgumentType
  • Export ParsedValue
  • Export helper types (ParseOptions, etc.)
  • Add top-level documentation
  • Define version constant

Acceptance Criteria:

  • All public types accessible
  • API is clean and well-documented
  • Version information available

Estimated Time: 0.5 days


6.2 Global Registry Helper

File: src/main.zig

Tasks:

  • Consider providing helper to initialize global registry
  • Document pattern for global usage
  • Provide example code

Acceptance Criteria:

  • Clear guidance on using global singleton
  • Thread safety considerations documented

Estimated Time: 0.5 days


Phase 7: Testing (Week 4)

7.1 Unit Tests

Files: tests/*.zig

Tasks:

  • Test type detection and conversion
  • Test metadata extraction
  • Test argument parsing (all formats)
  • Test collision detection (compatible and incompatible)
  • Test help generation
  • Test struct reconstruction
  • Test list parsing
  • Test enum parsing
  • Test error conditions

Acceptance Criteria:

  • 100% code coverage of core logic
  • All edge cases tested
  • Clear test names and documentation

Estimated Time: 2 days


7.2 Integration Tests

Files: tests/*.zig

Tasks:

  • Test full parse cycle with multiple structs
  • Test module registration order independence
  • Test argv caching behavior
  • Test help request before parsing
  • Test help text persistence workflow

Acceptance Criteria:

  • End-to-end workflows tested
  • Multiple modules interacting correctly
  • Real-world scenarios covered

Estimated Time: 1 day


7.3 Memory Leak Testing

Files: tests/*.zig

Tasks:

  • Wrap all tests with memory leak detection
  • Test cleanup paths (deinit)
  • Test error paths (proper cleanup on errors)
  • Verify arena allocator usage

Acceptance Criteria:

  • Zero memory leaks in all tests
  • All allocations properly freed

Estimated Time: 0.5 days


Phase 8: Examples and Documentation (Week 4)

8.1 Simple Example

File: examples/simple.zig

Tasks:

  • Single struct with basic types
  • Parse and print values
  • Show help usage
  • Document every step

Acceptance Criteria:

  • Works as minimal starting point
  • Clear and easy to understand

Estimated Time: 0.5 days


8.2 Game Engine Example

File: examples/game_engine.zig

Tasks:

  • Multiple modules (Engine, Physics, Audio, Renderer)
  • Each module has its own Args struct
  • Show scattered parsing pattern
  • Generate help text
  • Demonstrate compatible collisions

Acceptance Criteria:

  • Realistic game engine scenario
  • Shows plugin architecture usage
  • Help text properly grouped

Estimated Time: 1 day


8.3 Persistence Example

File: examples/persistence.zig

Tasks:

  • Generate help text after parsing
  • Write to file
  • Show embedding with @embedFile
  • Fast --help response

Acceptance Criteria:

  • Demonstrates novel persistence feature
  • Shows workflow for production usage

Estimated Time: 0.5 days


8.4 README and API Documentation

Files: README.md, doc comments

Tasks:

  • Write comprehensive README
    • What is zargs?
    • Why use it?
    • Quick start guide
    • Design philosophy
    • Comparison to alternatives
  • Document all public APIs with doc comments
  • Add usage examples to doc comments
  • Document design decisions

Acceptance Criteria:

  • README is compelling and informative
  • All public APIs documented
  • Examples included in docs

Estimated Time: 1 day


Phase 9: Build System (Week 4)

9.1 Build.zig Setup

File: build.zig

Tasks:

  • Define library module
  • Add test step
  • Add example build steps
  • Add install step
  • Configure for Zig 0.14

Acceptance Criteria:

  • zig build compiles library
  • zig build test runs all tests
  • zig build run-simple runs simple example
  • Works with Zig 0.14

Estimated Time: 0.5 days


9.2 Integration with Backlog Engine

File: Integration into main project

Tasks:

  • Import as lib/zargs module
  • Make available to engine modules
  • Test with actual engine code
  • Document engine-specific patterns

Acceptance Criteria:

  • Engine can use zargs
  • Works with existing build system

Estimated Time: 0.5 days


Phase 10: Polish and Release (Week 5)

10.1 Error Messages

Tasks:

  • Review all error messages
  • Ensure helpful and actionable
  • Include context (argument name, module, source location)
  • Format consistently

Acceptance Criteria:

  • User-friendly error messages
  • Easy to debug issues

Estimated Time: 0.5 days


10.2 Performance Testing

Tasks:

  • Benchmark parsing overhead
  • Benchmark help generation
  • Profile memory usage
  • Optimize hot paths if needed

Acceptance Criteria:

  • Parsing overhead negligible
  • Help generation fast
  • Memory usage reasonable

Estimated Time: 1 day


10.3 Edge Cases

Tasks:

  • Test with empty argv
  • Test with no arguments defined
  • Test with only --help
  • Test with very long argument lists
  • Test with unicode in arguments
  • Test with special characters

Acceptance Criteria:

  • No crashes on edge cases
  • Reasonable behavior

Estimated Time: 0.5 days


10.4 Final Review

Tasks:

  • Code review entire implementation
  • Check for TODOs
  • Verify all tests pass
  • Run formatter
  • Check for memory leaks
  • Update documentation

Acceptance Criteria:

  • Code is production-ready
  • No known issues

Estimated Time: 1 day


Timeline Summary

Phase Duration Milestone
1. Core Type System 2-3 days Type detection working
2. Metadata System 1.5-2.5 days Metadata extraction working
3. Core Registry 4 days Registry structure complete
4. Argument Parsing 5 days End-to-end parsing working
5. Help Generation 1.5 days Help text generation working
6. Public API 1 day API finalized
7. Testing 3.5 days Full test coverage
8. Examples & Docs 3 days Documentation complete
9. Build System 1 day Build integration complete
10. Polish & Release 3 days Production ready

Total Estimated Time: ~25 days (5 weeks)

Success Criteria

  • All unit tests pass
  • All integration tests pass
  • Zero memory leaks
  • All examples run correctly
  • Documentation complete and clear
  • Can parse arguments from multiple modules
  • Compatible collisions work
  • Incompatible collisions error appropriately
  • Help text generation works
  • Help text persistence workflow demonstrated
  • Integration with Backlog engine successful

Risks and Mitigations

Risk Impact Mitigation
Comptime complexity too high High Start simple, iterate; use runtime where needed
Memory management issues High Test early with leak detection; use arena allocator
Type system edge cases Medium Comprehensive type testing; clear error messages
Help text formatting tricky Low Reference existing tools; iterate on format
Integration issues Medium Test integration early in Phase 9

Open Questions

  1. Should we support positional arguments in v2? (deferred to v1 feedback)
  2. Should we support config file loading? (separate feature, later)
  3. Should we support environment variable fallback? (separate feature, later)
  4. What about shell completion generation? (v2 feature)
  5. How to handle argument value validation? (v2 feature - validators)

Dependencies

  • Zig 0.14
  • No external dependencies (pure std lib)

Testing Strategy

  1. Unit tests - Test individual components in isolation
  2. Integration tests - Test component interactions
  3. Example tests - Ensure examples compile and run
  4. Memory tests - Verify no leaks with GeneralPurposeAllocator
  5. Manual testing - Test with Backlog engine integration

Notes

  • Keep implementation simple and focused on core use case
  • Prioritize game engine / plugin architecture scenario
  • Document design decisions and tradeoffs
  • Write tests alongside implementation (TDD where appropriate)
  • Get feedback early from engine integration