Commit Graph

120 Commits

Author SHA1 Message Date
Levi Neely 2d908c6dcd Assist: add Comment tag to leave comments on beads
- Add Comment tag to bead view window tagline
- New /AnviLLM/Tasks/{bead-id}/comment window with Put handler
- Fix comments display: JSON field is 'text' not 'body'
2026-03-16 11:23:46 +01:00
Levi Neely 47a97e5cea supervisor: replace Go package with anvillm-supervisor shell script
Remove the internal/supervisor Go package and cron-driven orphan check
script. Replace with a single anvillm-supervisor script invoked by cron
that handles both orphan bead recovery (--orphans, every 5m) and idle
worker nudging (--nudge, every 1m). Nudges use send_message.sh as user,
consistent with existing mail processing. anvilsrv no longer runs any
supervisor goroutine.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 14:47:56 +01:00
Levi Neely 8e88660f65 supervisor: nudge idle worker-role bots to run their polling loop
Replace dead assignWork() stub with nudgeIdleWorkers(), which sends a
prompt to any session whose role has worker: true in its front-matter
and has been idle for more than 15 seconds. A 15-second ticker drives
the checks. Bots that should be polling for beads will self-correct
after a brief idle period.

Add Worker bool to RoleMeta, parsed from "worker: true" front-matter,
and IsWorker() helper on RolesFS. Remove unused beads/mailbox/eventbus
deps from the supervisor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 14:25:21 +01:00
Levi Neely 6ea87e1810 Assist: remap bead prefixes, add open/defer; orphan: skip user-claimed
Tasks window Put handler prefix changes:
  ~ → c  (claim)
  ^ → u  (unclaim)
  o      (open/promote deferred)
  d      (defer)
  x, f, -, + unchanged

Orphan check now skips beads claimed by "user" — human-held beads
are not orphans.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:21:25 +01:00
Levi Neely b52f0b5e85 beads: simplify claim — open only, orphan recovery via unclaim
Claim now rejects anything not in status=open. Dead-assignee takeover
is handled by unclaiming the bead (which fires BeadReady), letting any
waiting bot claim it normally. Removes isAlive/SetSessionLiveness.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:51:22 +01:00
Levi Neely d0acd32f8f beads: atomic conditional claim with orphan takeover
claim now runs in a transaction: reads current status/assignee, allows
claim only if status=open or (status=in_progress and assignee is dead).
Returns ErrAlreadyClaimed if the current assignee is alive.

BeadsFS.SetSessionLiveness wires a func(agentID string) bool from the
session manager so the claim handler can check liveness without importing
the session package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:48:14 +01:00
Levi Neely 68cc9445a9 supervisor: replace polling with event-driven work assignment
- Add EventBeadReady to eventbus, published by BeadsFS on open/reopen/unclaim
- Wire eventbus into BeadsFS via SetEventBus (called after server init)
- Supervisor now reacts to EventStateChange{idle} and EventBeadReady
  instead of a 5s ticker; 60s fallback ticker retained for safety

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 15:52:18 +01:00
Levi Neely d76ccf4979 mcptools: convert all positional args to named flags
Every argument in every mcptools script is now a named flag (--mount,
--id, --agent-id, --session-id, --cwd, --child, --repo, --ticket, etc.).
No positional arguments remain. SKILL.md files updated to match.

Also updates cmd/Assist/main.go to pass --cwd flag to mount_beads.sh.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 13:41:25 +01:00
Levi Neely 021b1b8221 mount_beads: drop friendly name, UUID is the mount name
Simplify: the optional friendly name parameter is removed. UUID first
segment is always the mount name; mtab provides the path mapping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 00:24:20 +01:00
Levi Neely 6cd4c450b1 Assist: read mount_beads.sh via 9p client instead of shelling out
Use readFile() to fetch the script over the existing 9p connection,
then pipe it to bash -s. Removes dependency on the 9p CLI binary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 00:09:16 +01:00
Levi Neely bede87b619 Assist: delegate mountProject to mount_beads.sh mcptool
Replace direct beads/ctl write with mount_beads.sh subprocess call.
UUID-based mount names are now generated by the script; the returned
name is captured and used as windowMount. Optional friendly name is
passed through for display only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 00:07:15 +01:00
Levi Neely 2a1d620a31 rename 9P endpoint from 'agent' to 'anvillm'
- Update socket path, MountService calls, path prefixes
- Update mcptools, scripts, docs, diagrams, services
- Fix idleSince initialization at session creation
2026-03-12 12:13:40 +01:00
Levi Neely 46da046fb3 tmux: remove FIFO plumbing, fix per-window metadata
- Remove dead streaming code: reader(), waitForReady(), StartupHandler, pipe-pane
- Switch recovery metadata from session-scoped set-environment to window-scoped set-option -w @key
- Sessions now start in idle state immediately (no startup wait)
2026-03-12 11:47:37 +01:00
Levi Neely 39b49e83ce beads: reduce context overflow, simplify filters, atomic blockers
- list_beads.sh/list_ready_beads.sh: filter to id,priority,title,status
- Add read_bead_comments.sh tool and Comments view in Assist
- Simplify Assist filters to All/Ready (was 6 status filters)
- Server-side filtering: list excludes closed at DB, ready uses GetReadyWork
- Default limit 100, DB-level filtering
- Atomic blockers= support in new command
2026-03-11 09:45:20 +01:00
Levi Neely 3896b3db43 Assist: add Comments view for beads; add read_bead_comments.sh tool 2026-03-11 09:07:05 +01:00
Levi Neely 824ab88fe3 anvilmcp: handle args passed as JSON-encoded string; fix team-templates install path
- Parse args as JSON string fallback when LLM passes args incorrectly
- Update SKILLS_PROMPT and agent docs to use unquoted args syntax
- Install team-templates under $INSTALL_PATH/Teams instead of hardcoded $HOME/bin/Teams

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 17:40:35 +01:00
Levi Neely 919335a271 conductor: adaptive delegation based on available staff
- roles/conductor.md: discover roster before planning; adapt workflow
  to available roles (dev-only, dev+review, dev+review+test, etc.);
  drive iterative cycles; parallelize across multiple same-role bots;
  report skipped phases instead of blocking on missing roles

- team-templates/debug: new workflow with conductor+developer+tester;
  blocks until all roles are idle before returning

- list format: replace model field with role (field 5) in agent/list;
  update Assist, anvillm, anvilwebgw, list_sessions.sh accordingly

- Assist /AnviLLM/: replace Model column with Role in session list
2026-03-07 17:24:40 +01:00
Levi Neely 3e74c264e9 anvilmcp: add pipe mode for tool composition
Adds a third execution mode: pipe accepts an ordered array of stages
{tool?, args?, code?} and chains them as a Unix pipeline. Tool stages
are read from 9P (trusted); inline code stages are validated individually
before the pipeline is assembled, so the combined string always runs as
trusted regardless of mix. readTool moved from main.go to execute.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 18:47:42 +01:00
Levi Neely b913fcc644 Fix elevated bash execution 2026-03-06 17:02:57 +01:00
Levi Neely 7f8cf66533 anvilmcp: add timeout guidance to schema 2026-03-06 15:12:10 +01:00
Levi Neely bda779380e anvilmcp: use single quotes for bash arg escaping
Prevents shell variable expansion in tool args. $VAR now stays
literal instead of expanding to empty string.
2026-03-06 15:03:26 +01:00
Levi Neely fc6cca01a8 Remove Go language support from execute_code (go run lacks stdin)
Keep code extensible for future language support.
2026-03-06 14:15:51 +01:00
Levi Neely b3bb801b23 execute_code: add tool/args params, read from 9P, trust tools
- Add 'tool' param to read tool code from 9P namespace
- Add 'args' as array (passed as positional params via set --)
- Tools from 9P skip dangerous pattern validation (trusted)
- Add Go language support
- Update all skills to use tool/args syntax
2026-03-06 14:07:16 +01:00
Levi Neely b21c56b960 anvilmcp: use layered sandbox config from sandbox package
Reuse the same layered config approach as anvilsrv:
- global.yaml provides base permissions (including /usr, /lib, /bin)
- sandbox/<name>.yaml adds sandbox-specific permissions
- Merge uses most-permissive-wins strategy

This fixes the fallback to default sandbox, which now has proper
system paths from global.yaml.
2026-03-06 10:18:31 +01:00
Levi Neely 2046bc2513 anvilmcp: fallback to default sandbox on permission errors
When sandbox is not explicitly specified, retry with 'default' sandbox
if the initial execution fails with permission denied or missing file errors.
This allows third-party skills designed for execute_bash to work without
modification while preserving isolation when sandbox is explicitly set.
2026-03-06 10:03:01 +01:00
Levi Neely 0d847f96f3 execute_code: configurable sandbox, fix dangerous patterns
- Add sandbox parameter to execute_code (default: anvilmcp)
- Load sandbox config from ~/.config/anvillm/sandbox/<name>.yaml
- Fallback to ./cfg/sandbox/<name>.yaml for development
- Add cwd config option: 'temp' for isolated workspace, '{CWD}' for caller's dir
- Create cfg/sandbox/anvilmcp.yaml with restricted defaults
- Update cfg/sandbox/default.yaml with cwd: '{CWD}'

Dangerous pattern fixes (bash, not JS/Python):
- Remove curl/wget block (network controlled by landrun)
- Remove chmod 777, eval(), exec() (wrong syntax)
- Allow /etc/passwd (world-readable, needed for user lookups)
- Fix /dev/ write check to only block /dev/sd* (not /dev/null)
- Fix eval pattern for actual bash usage

Update skills with explicit sandbox specifications:
- anvilmcp sandbox for normal operations
- default sandbox for spawn_agent.sh (needs full permissions)
2026-03-06 09:53:41 +01:00
Levi Neely d0c596dcaa Add mail_history.sh script for parsing agent message history 2026-03-05 17:08:55 +01:00
Levi Neely 6475b9f216 Add maildir messaging support for agent communication 2026-03-05 14:33:47 +01:00
Levi Neely c0d09125ca Add backend-specific handlers for clear, compact, resume commands
- Add ClearHandler, CompactHandler, ResumeHandler callbacks to tmux.Config
- kiro-cli: clear/resume need 250ms delay + confirmation key
- claude: clear/compact are simple /command[ENTER], resume not implemented
- Add Resume tag and handler to Assist prompt window
- Update server.go to use new Session methods
2026-03-05 09:41:05 +01:00
Levi Neely e3a63dedd8 tmux backend and p9 server improvements 2026-03-05 09:32:07 +01:00
Levi Neely 33026360b3 Assist: reset view to top after refreshing window content
Add w.Addr("0")/dot=addr/show after content writes in refreshList,
refreshMailboxWindow, refreshDaemonWindow, and refreshViewBeadWindow
so windows no longer scroll to the bottom on open or refresh.

Closes anv-hww

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 18:42:07 +01:00
Levi Neely ba5fd04025 fix: make beads mount work with lazy initialization
- Changed NewServer to accept *BeadsFS instead of bd.Storage
- BeadsFS is always created but with no initial mounts
- Each mount opens its own store on-demand
- Added nil check in supervisor to handle missing beads gracefully
2026-03-01 00:47:13 +01:00
Levi Neely 33dbc312b0 fix: remove eager beads store initialization at startup
The beads store was being opened unconditionally at startup, causing
crashes when the database was corrupted or incompatible. Now it's only
opened on-demand when actually needed.
2026-03-01 00:41:39 +01:00
Levi Neely afe13afba2 Fix 9p tool access in execute_code sandbox
- Add DISPLAY, WAYLAND_DISPLAY, USER to landrun env passthrough
- Mount /etc/passwd read-only for getuser() to work
- Update mcptools scripts to check /etc/shadow instead of /etc/passwd for sandbox detection
2026-02-28 20:49:42 +01:00
Levi Neely 95efd907fb Add frontend support for mountable beads and remove global mount state
- Add mount management UI to all frontends (anvillm TUI, Assist, anvilwebgw, anvillm.el)
- Mount commands default to directory basename if name not specified
- Server validates directory exists before mounting
- Umount accepts either mount name or cwd path
- Fix server bug: all beads operations now use mount-specific store
- Remove currentMount global - all operations require explicit mount parameter
- Each Tasks window tracks its own windowMount independently
- Bead detail windows receive mount from parent window
- When no mounts exist, show instructions to mount a project
- When unmounting current mount, switch to first available or show empty state
- Mount validation: Select command checks mount exists before switching
- Database path: ~/.beads/<cwd-hyphenated> to prevent cross-contamination
2026-02-28 13:35:46 +01:00
Levi Neely 1e3623920e Add mountable beads projects with per-project databases
- Mount projects: echo "mount /path/to/project name" | 9p write agent/beads/ctl
- Unmount: echo "umount name" | 9p write agent/beads/ctl
- All beads endpoints work in mounts (list, ready, pending, blocked, etc.)
- Add agent/beads/mtab for mount discovery (mount→cwd mappings)
- Store databases at ~/.beads/<cwd-hyphenated> to prevent cross-contamination
- Supervisor auto-assigns claimable beads to idle bots with matching cwd
- Fix supervisor duplicate messages (track assigned beads, filter by assignee)
- Update beads skill with mtab discovery pattern
- Fix race conditions and add proper locking for mount access
2026-02-28 11:35:19 +01:00
Levi Neely cbace3407c Update changes 2026-02-27 12:12:08 +01:00
Levi Neely 0b612aa0cc Add logging.Init() to all cmd programs
- anvilwebgw: init logging in startCmd
- anvilweb: init logging in main
- anvillm: init logging in main
- Assist: init logging in main

Each program now creates its own timestamped log file
2026-02-27 11:51:50 +01:00
Levi Neely 2111f19e9f Add zap logging to ~/.config/anvillm/logs with panic recovery
- Created internal/logging package with zap logger
- Added panic recovery to anvilsrv main loop, monitor goroutine, and mail processing
- Replaced log.Printf/Fatal with zap in debug, p9, tmux packages
- Fixed beads race condition: clear assignee before closing issue
- All errors and crashes now logged to ~/.config/anvillm/logs
2026-02-27 11:46:49 +01:00
Levi Neely f252aa9452 Add sandbox enforcement to mcptools scripts 2026-02-27 00:25:01 +01:00
Levi Neely 17ec56fbdd Update messaging skill and execute command 2026-02-27 00:06:13 +01:00
Levi Neely e1df81fda6 Compress skills and add network tools
- Compressed skills to <500 tokens each (except rc-shell at 591)
  - beads: 535→59 lines (89% reduction)
  - rc-shell: 270→98 lines (64% reduction)
  - acme-api: 228→85 lines (63% reduction)
  - write-skills: 141→71 lines (50% reduction)
  - github-cli: 133→76 lines (43% reduction)
  - agent-kb: 111→70 lines (37% reduction)
  - jira-to-beads: 129→49 lines (62% reduction)
  - github-to-beads: 109→49 lines (55% reduction)

- Added mcptools for network operations
  - jira-to-beads: fetch Jira hierarchy, create beads
  - github-to-beads: fetch GitHub issues, parse task lists, create beads

- Updated execute_code landrun permissions
  - Added --unrestricted-network for API calls
  - Added user bin dirs: ~/bin, ~/.local/bin, ~/opt, ~/go/bin, $PLAN9/bin

- Documented beads delete behavior (no cascade)

Total token savings: ~2,400 tokens across all skills
2026-02-26 20:02:24 +01:00
Levi Neely 8b87e3514a Move tool scripts from cmd/anvilmcp to mcptools/ 2026-02-26 14:36:50 +01:00
Levi Neely 5f8c41b576
Implement MCP code execution pattern (#20)
* Implement MCP code execution pattern

- Add execute_code tool for bash execution in landrun sandbox
- Remove redundant MCP tools (read_inbox, send_message, etc.)
- Implement dynamic tool discovery from ~/.config/anvillm/mcptools/
- Add workspace isolation (~/.cache/anvillm/exec)
- Add security: output limits, concurrency limits, validation, path traversal protection
- Update bot templates (Conductor, Taskmaster) with bash examples
- Update anvillm-communication skill to use execute_code pattern
- Create comprehensive documentation (user guide, migration guide, security guide)
- Add test suite for validation and limitedWriter
- Fix landrun flags: --rox for executables, --env for AGENT_ID passthrough
- Network blocked by default (no --connect-tcp or --unrestricted-network)

Token reduction: 80-99% via progressive tool discovery and subprocess data processing

* Fix code review issues in MCP code execution pattern

- Security: Change security.jsonl permissions from 0644 to 0600
- Bug: Fix limitedWriter to return correct byte count for io.Copy
- Bug: Fix tool schema inconsistency (execute_code requires only 'code')
- Performance: Move whitespace regex to package-level var
- Security: Improve validateCode with regex patterns and normalization
- Cleanup: Remove dead code from main.go and tools.go
- Cleanup: Rewrite shell scripts to use jq for safe JSON construction
- Docs: Fix duplicate sections and JavaScript syntax in bash examples

* Improve code validation security patterns

- Fix rm -rf bypass: allow optional whitespace before /
- Expand rm -rf to block sensitive paths (/home, /var, /usr, etc.)
- Block all network protocols in curl/wget (not just http/https)
- Add test for regex pattern compilation
- Add test cases for tabs, sensitive paths, ftp/file protocols

* Harden shell scripts and improve rate limiting

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Levi Neely <lneely@pascom.net>
2026-02-26 14:02:54 +01:00
Levi Neely 2418f12012 Fix review findings from code review
- Include model in session list output (eliminates N+1 reads)
- Add jq error handling in Supervisor dispatch_ready_beads
- Use process substitution in Supervisor to avoid subshell variable scope
- Fix claude backend Execute to return error (commands go through PTY)
- Make createSubtask return childID (eliminates duplicate O(n) scan)

Fixes: bd-1z2, bd-73r, bd-cid, bd-viu, bd-vdi
2026-02-26 12:05:28 +01:00
Levi Neely 5bcaa38ad7 cost / usage optimization, phase 1 2026-02-25 19:17:50 +01:00
Levi Neely 50ae907741 anvilwebgw: read message timestamp from JSON instead of filename 2026-02-25 15:03:36 +01:00
Levi Neely 74eec073d3 anvilwebgw: fix session list field mapping (alias/backend swap) 2026-02-25 14:57:27 +01:00
Levi Neely 572ac91d86 Set CLAUDE_CONFIG_DIR at startup and propagate to tmux/shell/sandbox
- anvilsrv sets CLAUDE_CONFIG_DIR to ~/.config/anvillm/claude on start
  if not already set in the environment
- Claude backend includes CLAUDE_CONFIG_DIR in its Environment map so
  it is set in the tmux session and exported to the shell
- tmux backend now exports all b.cfg.Environment vars to the shell
  (via sendKeys) in addition to setting them in the tmux environment,
  both on CreateSession and Restart
- cfg/backends/claude.yaml adds CLAUDE_CONFIG_DIR to the sandbox env
  whitelist so landrun passes it through to the Claude process

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 11:49:02 +01:00
Levi Neely 065e4a3295
Add bulk-archive via inline Put notation to inbox and archive windows (#12)
* Add inline Put actions for sessions and tasks windows

Introduce a Put command to both the sessions list and tasks windows,
allowing inline edits via prefixed annotations in the body:

Sessions (cmd/Assist/main.go):
  - `- <id>`              Kill session
  - `~ <id>`              Stop session (graceful)
  - `@ <id> <alias>`      Set alias on session
  - `+ <backend> <path> [alias]`  Start new session

Tasks (cmd/Assist/main.go + internal/p9/beads.go):
  - `- [idx]`   Delete bead
  - `~ [idx]`   Claim bead as user
  - `^ [idx]`   Unclaim bead (clear assignee, reset to open)
  - `x [idx]`   Complete bead
  - `f [idx]`   Fail bead
  - `+ <title>` Create new bead with title pre-filled

Also adds `unclaim` ctl command to BeadsFS and helper functions:
claimBeadAsUser, unclaimBead, completeBead, failBead,
openNewBeadWindowWithTitle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add [Failed] [PendingReview] [PendingApproval] filters to tasks window

Extends the tasks window filter bar with three new status filters:

- [Failed]          closed beads whose close_reason != "completed"
- [PendingReview]   beads with status "pending_review"
- [PendingApproval] beads with status "pending_approval"

Implementation details:
- Add CloseReason field (json:"close_reason") to Bead struct so
  fail-vs-complete distinction is available after JSON decode.
- listBeadsWithFilter: add "failed" special case (closed beads with
  non-"completed" close_reason); "pending_review" and
  "pending_approval" fall through the existing status equality path.
- handleTasksWindow: wire Failed/PendingReview/PendingApproval cases
  to set statusFilter and refresh the list.
- refreshTasksWindowWithBeads: update filter bar header line.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add bulk-archive via inline Put notation to inbox and archive windows

In the inbox window, lines prefixed with "- <shortID>" are parsed on Put
and each matching message is archived (moved to completed). In the archive
window the same notation permanently deletes the message from the archive.

Adds: parseMailEdits, mailEdit type, deleteArchivedMessage in Assist;
DeleteFromCompleted in mailbox.Manager; "delete <msg-id>" command on
user/ctl in the p9 server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:58:37 +01:00