From daec0f3b857864f5401b017483ad52faa1bb5ff7 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 10 Jan 2026 23:27:32 -0800 Subject: [PATCH] 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 --- .beads/issues.jsonl | 2 +- docs/adr/006-nim-worker-cli.md | 164 +++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 docs/adr/006-nim-worker-cli.md diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 5b0d14f..327ab62 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -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-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-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-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"} diff --git a/docs/adr/006-nim-worker-cli.md b/docs/adr/006-nim-worker-cli.md new file mode 100644 index 0000000..bfad7cd --- /dev/null +++ b/docs/adr/006-nim-worker-cli.md @@ -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)