docs: ADR-006 Nim language choice for worker CLI

Documents rationale for using Nim with ORC for the worker coordination
CLI: fast startup, single binary, Python-like syntax, excellent SQLite
support via tiny_sqlite, CLI generation via cligen.

Closes skills-q40

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
dan 2026-01-10 23:27:32 -08:00
parent b9866b7930
commit daec0f3b85
2 changed files with 165 additions and 1 deletions

View file

@ -177,7 +177,7 @@
{"id":"skills-pdg","title":"Enable AT-SPI for UI tree access","description":"## Findings\n\nAT-SPI (Assistive Technology Service Provider Interface) provides semantic UI tree access - buttons, labels, text fields, their states and coordinates.\n\n### Current state\n- AT-SPI is **disabled** on this NixOS system\n- Environment has `NO_AT_BRIDGE=1` and `GTK_A11Y=none`\n- No apps are exposing accessibility info\n\n### To enable\n```nix\nservices.gnome.at-spi2-core.enable = true;\n```\n\nThen rebuild and re-login (apps must start fresh to register with bus).\n\n### App support\n- **GTK apps**: Should work automatically\n- **Qt apps**: Need `QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1` env var\n- **Electron**: Varies by app, often poor support\n\n### Trade-offs\n- Adds runtime overhead to all GTK/Qt apps\n- May want as boot-time option rather than always-on\n- Only useful for automation/accessibility use cases\n\n### Tools once enabled\n- `python3-pyatspi` / `dogtail` for querying UI tree\n- `accerciser` for visual inspection of accessibility tree\n\n### Next steps\n**Blocked by dotfiles-0l3** - NixOS config change filed in dotfiles repo.\n\nAfter dotfiles change deployed:\n1. Test with common apps (Firefox, terminals, etc.)\n2. Build skill to query UI elements\n\n## Related\nParent epic: skills-kg7 (Desktop automation for Wayland/niri)","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:59:55.799402507-08:00","updated_at":"2025-12-29T15:05:00.794702992-05:00"} {"id":"skills-pdg","title":"Enable AT-SPI for UI tree access","description":"## Findings\n\nAT-SPI (Assistive Technology Service Provider Interface) provides semantic UI tree access - buttons, labels, text fields, their states and coordinates.\n\n### Current state\n- AT-SPI is **disabled** on this NixOS system\n- Environment has `NO_AT_BRIDGE=1` and `GTK_A11Y=none`\n- No apps are exposing accessibility info\n\n### To enable\n```nix\nservices.gnome.at-spi2-core.enable = true;\n```\n\nThen rebuild and re-login (apps must start fresh to register with bus).\n\n### App support\n- **GTK apps**: Should work automatically\n- **Qt apps**: Need `QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1` env var\n- **Electron**: Varies by app, often poor support\n\n### Trade-offs\n- Adds runtime overhead to all GTK/Qt apps\n- May want as boot-time option rather than always-on\n- Only useful for automation/accessibility use cases\n\n### Tools once enabled\n- `python3-pyatspi` / `dogtail` for querying UI tree\n- `accerciser` for visual inspection of accessibility tree\n\n### Next steps\n**Blocked by dotfiles-0l3** - NixOS config change filed in dotfiles repo.\n\nAfter dotfiles change deployed:\n1. Test with common apps (Firefox, terminals, etc.)\n2. Build skill to query UI elements\n\n## Related\nParent epic: skills-kg7 (Desktop automation for Wayland/niri)","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:59:55.799402507-08:00","updated_at":"2025-12-29T15:05:00.794702992-05:00"}
{"id":"skills-prt","title":"worklog: remove inline section list, reference template","description":"SKILL.md lists 11 sections that duplicate worklog-template.org. Will drift. Replace with directive to parse sections from template dynamically. Found by bloat lens review.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T02:03:16.811093872-05:00","updated_at":"2025-12-27T10:05:51.513685966-05:00","closed_at":"2025-12-27T10:05:51.513685966-05:00","close_reason":"Closed"} {"id":"skills-prt","title":"worklog: remove inline section list, reference template","description":"SKILL.md lists 11 sections that duplicate worklog-template.org. Will drift. Replace with directive to parse sections from template dynamically. Found by bloat lens review.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T02:03:16.811093872-05:00","updated_at":"2025-12-27T10:05:51.513685966-05:00","closed_at":"2025-12-27T10:05:51.513685966-05:00","close_reason":"Closed"}
{"id":"skills-pu4","title":"Clean up stale beads.left.jsonl merge artifact","description":"bd doctor flagged multiple JSONL files. beads.left.jsonl is empty merge artifact that should be removed: git rm .beads/beads.left.jsonl","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-30T11:58:33.292221449-08:00","updated_at":"2025-11-30T12:37:49.916795223-08:00","closed_at":"2025-11-30T12:37:49.916795223-08:00"} {"id":"skills-pu4","title":"Clean up stale beads.left.jsonl merge artifact","description":"bd doctor flagged multiple JSONL files. beads.left.jsonl is empty merge artifact that should be removed: git rm .beads/beads.left.jsonl","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-30T11:58:33.292221449-08:00","updated_at":"2025-11-30T12:37:49.916795223-08:00","closed_at":"2025-11-30T12:37:49.916795223-08:00"}
{"id":"skills-q40","title":"ADR: Nim language for worker CLI","description":"Language decision: Nim (ORC, cligen, tiny_sqlite) for the worker coordination CLI.\n\nRationale:\n- Single static binary deployment\n- Fast startup (~1ms) for CLI commands\n- Python-like syntax, easy to iterate\n- Excellent SQLite support via tiny_sqlite\n- cligen auto-generates CLI from proc signatures\n- ORC memory management handles cycles\n- Threads + channels for heartbeat without shared state\n\nDependencies:\n- tiny_sqlite: SQLite wrapper with RAII\n- cligen: CLI framework\n- jsony: Fast JSON (optional)\n- SQLite amalgamation for static linking\n\nBuild: nim c -d:release --mm:orc --threads:on src/worker.nim\n\nSee: docs/design/mvp-scope.md, message-passing-layer.md, worker-cli-primitives.md","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-10T18:04:05.004285163-08:00","created_by":"dan","updated_at":"2026-01-10T18:04:05.004285163-08:00"} {"id":"skills-q40","title":"ADR: Nim language for worker CLI","description":"Language decision: Nim (ORC, cligen, tiny_sqlite) for the worker coordination CLI.\n\nRationale:\n- Single static binary deployment\n- Fast startup (~1ms) for CLI commands\n- Python-like syntax, easy to iterate\n- Excellent SQLite support via tiny_sqlite\n- cligen auto-generates CLI from proc signatures\n- ORC memory management handles cycles\n- Threads + channels for heartbeat without shared state\n\nDependencies:\n- tiny_sqlite: SQLite wrapper with RAII\n- cligen: CLI framework\n- jsony: Fast JSON (optional)\n- SQLite amalgamation for static linking\n\nBuild: nim c -d:release --mm:orc --threads:on src/worker.nim\n\nSee: docs/design/mvp-scope.md, message-passing-layer.md, worker-cli-primitives.md","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-10T18:04:05.004285163-08:00","created_by":"dan","updated_at":"2026-01-10T23:27:32.570914258-08:00","closed_at":"2026-01-10T23:27:32.570914258-08:00","close_reason":"ADR-006 documents Nim language decision for worker CLI"}
{"id":"skills-qeh","title":"Add README.md for web-research skill","description":"web-research skill has SKILL.md and scripts but no README.md. AGENTS.md says README.md is for humans, contains installation instructions, usage examples, prerequisites.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-30T11:58:14.475647113-08:00","updated_at":"2025-12-28T22:37:48.339288261-05:00","closed_at":"2025-12-28T22:37:48.339288261-05:00","close_reason":"Added README.md with prerequisites, usage examples, and cross-references","dependencies":[{"issue_id":"skills-qeh","depends_on_id":"skills-vb5","type":"blocks","created_at":"2025-11-30T12:01:30.278784381-08:00","created_by":"daemon","metadata":"{}"}]} {"id":"skills-qeh","title":"Add README.md for web-research skill","description":"web-research skill has SKILL.md and scripts but no README.md. AGENTS.md says README.md is for humans, contains installation instructions, usage examples, prerequisites.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-30T11:58:14.475647113-08:00","updated_at":"2025-12-28T22:37:48.339288261-05:00","closed_at":"2025-12-28T22:37:48.339288261-05:00","close_reason":"Added README.md with prerequisites, usage examples, and cross-references","dependencies":[{"issue_id":"skills-qeh","depends_on_id":"skills-vb5","type":"blocks","created_at":"2025-11-30T12:01:30.278784381-08:00","created_by":"daemon","metadata":"{}"}]}
{"id":"skills-qekj","title":"Start heartbeat before state transition in start command","description":"[ERROR] MED worker.nim:202-206 - Heartbeat started after state transition. If heartbeat fails, worker is WORKING but not heartbeating. Start heartbeat before transition, or handle failure by reverting state.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-10T20:12:10.656162605-08:00","created_by":"dan","updated_at":"2026-01-10T20:55:02.327535804-08:00","closed_at":"2026-01-10T20:55:02.327535804-08:00","close_reason":"P2 bugs fixed"} {"id":"skills-qekj","title":"Start heartbeat before state transition in start command","description":"[ERROR] MED worker.nim:202-206 - Heartbeat started after state transition. If heartbeat fails, worker is WORKING but not heartbeating. Start heartbeat before transition, or handle failure by reverting state.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-10T20:12:10.656162605-08:00","created_by":"dan","updated_at":"2026-01-10T20:55:02.327535804-08:00","closed_at":"2026-01-10T20:55:02.327535804-08:00","close_reason":"P2 bugs fixed"}
{"id":"skills-qiq0","title":"Extract DefaultRemote and IntegrationBranch constants","description":"[EVOLVE] LOW git.nim - 'origin' remote and 'integration' branch hardcoded throughout (lines 40,66,67,93,96,97,109,133). Extract to constants in types.nim.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-10T19:52:14.580188398-08:00","created_by":"dan","updated_at":"2026-01-10T20:32:28.36719341-08:00","closed_at":"2026-01-10T20:32:28.36719341-08:00","close_reason":"Created utils.nim with common helpers"} {"id":"skills-qiq0","title":"Extract DefaultRemote and IntegrationBranch constants","description":"[EVOLVE] LOW git.nim - 'origin' remote and 'integration' branch hardcoded throughout (lines 40,66,67,93,96,97,109,133). Extract to constants in types.nim.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-10T19:52:14.580188398-08:00","created_by":"dan","updated_at":"2026-01-10T20:32:28.36719341-08:00","closed_at":"2026-01-10T20:32:28.36719341-08:00","close_reason":"Created utils.nim with common helpers"}

View file

@ -0,0 +1,164 @@
# ADR-006: Nim for Worker Coordination CLI
## Status
Accepted
## Context
The multi-agent orchestration system needs a CLI tool (`worker`) for:
- Spawning worker workspaces with git worktrees
- State machine transitions (ASSIGNED → WORKING → IN_REVIEW → APPROVED → COMPLETED)
- Heartbeat monitoring for stuck agent detection
- SQLite-based message bus for coordination
- Review-gate integration for quality enforcement
Requirements:
- Fast startup (<10ms) for CLI commands run frequently
- Single static binary for deployment simplicity
- SQLite with WAL mode for concurrent access
- Background thread for heartbeat without shared state complexity
- Easy iteration during development
## Decision
Use **Nim** with ORC memory management for the worker CLI.
### Core Dependencies
| Package | Purpose |
|---------|---------|
| `tiny_sqlite` | SQLite wrapper with RAII, statement caching |
| `cligen` | Auto-generates CLI from proc signatures |
| `std/json` | JSON parsing for context files |
### Why Nim
**Performance:**
- ~1ms startup time (vs ~50ms Python, ~20ms Go)
- Compiles to native binary via C backend
- No runtime initialization overhead
**Developer Experience:**
- Python-like syntax, low learning curve
- REPL available for prototyping (`nim secret`)
- Compile-time checks catch errors early
- Excellent error messages
**Memory Management:**
- ORC (Ownership + Reference Counting) handles cycles automatically
- No manual memory management needed
- Deterministic cleanup via destructors
- Thread-safe without shared state via channels
**SQLite Integration:**
- `tiny_sqlite` provides clean RAII semantics
- Statement caching for performance
- Proper NULL handling via Option types
- WAL mode works correctly with multiple connections
**CLI Generation:**
- `cligen` generates CLI from proc signatures
- Help text from doc comments
- Type-safe argument parsing
- Subcommands via `dispatchMulti`
Example:
```nim
proc spawn(taskId: string, description = "", fromBranch = "origin/integration") =
## Create a new worker workspace
...
when isMainModule:
dispatchMulti(
[spawn, help = {"taskId": "Task identifier"}]
)
```
### Alternatives Considered
**Python:**
- Slow startup (~50ms) unacceptable for frequent CLI calls
- Packaging complexity (venv, dependencies)
- Would work for prototype but not production
**Go:**
- Faster startup than Python (~20ms) but still slower than Nim
- More verbose syntax
- Good SQLite support via mattn/go-sqlite3
- Reasonable choice but Nim is more pleasant to write
**Rust:**
- Excellent performance and safety
- Steep learning curve slows iteration
- Borrow checker friction for exploratory code
- Good for later rewrite if needed
**Bash:**
- Used for review-gate (simpler requirements)
- Inadequate for state machine and SQLite operations
- Error handling is painful
### Build Configuration
```nim
# config.nims
switch("mm", "orc") # Memory management
switch("threads", "on") # Background heartbeat thread
switch("d", "release") # Optimizations
switch("opt", "size") # Smaller binary
switch("passL", "-lsqlite3") # Link SQLite
```
Build command:
```bash
nim c -d:release src/worker.nim
```
### Architecture
```
src/
├── worker.nim # CLI dispatch, command implementations
└── worker/
├── types.nim # Shared types, constants, error types
├── db.nim # SQLite operations, message bus
├── state.nim # State machine transitions
├── git.nim # Worktree operations
├── context.nim # Worker context file handling
├── heartbeat.nim # Background heartbeat thread
├── review.nim # Review-gate integration
└── utils.nim # Common helpers
```
## Consequences
### Positive
- Sub-millisecond startup enables responsive CLI
- Single binary simplifies deployment
- ORC eliminates memory management burden
- `cligen` reduces CLI boilerplate to near-zero
- Python-like syntax enables fast iteration
- Type safety catches bugs at compile time
### Negative
- Smaller ecosystem than Python/Go/Rust
- Fewer developers familiar with Nim
- Some library quality variance
- Compiler occasionally has edge case bugs
### Mitigations
- Pin Nim version (2.2.x) for stability
- Use well-maintained libraries (tiny_sqlite, cligen)
- Keep modules small and focused for maintainability
- Document patterns for future contributors
## References
- [Nim Manual](https://nim-lang.org/docs/manual.html)
- [tiny_sqlite](https://github.com/GULPF/tiny_sqlite)
- [cligen](https://github.com/c-blake/cligen)
- [ORC Memory Management](https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc-in-nim.html)