Extends lintDescription() with 8 new rules: Acme address format correction
(file:N-N → file:N,N), imperative verb start, vague language detection, how
signal, no first-person voice, forbidden vague phrases, inline code (backticks),
and cross-reference on long descriptions (>150 chars). Updates containsLineRef()
to also recognise #N char-position addresses; adds containsAcmeRegexAddr(),
containsHyphenRange(), and containsBdRef() helpers. Adds 32 tests covering every
rule in beads_lint_test.go.
Updates bot-templates/Conductor (6-question cold-completion gate, File Addressing
section), bot-templates/Taskmaster (File Addressing section with grammar
reference), and skills/beads/SKILL.md (Description Quality section with full lint
rule table and Acme addressing guide).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add description lint check to beads new command (bd-3bu.3):
warns to stderr on missing file path, function/line ref, short
description, or missing acceptance criterion; --no-lint and
IDEA:-prefixed titles bypass lint
- Add post-completion write-back convention to beads SKILL.md
(bd-3bu.2): quality ratings good/missing-location/missing-pattern/
too-vague, plus anti-pattern for closing without a quality comment
- Update Taskmaster prompt with five-field schema, KB query
requirement, and type-specific templates bug/feature/refactor/idea
(bd-3bu.1, bd-3bu.4)
- Add P1/P2 cold-completion gate to Conductor prompt (bd-3bu.5):
five-question checklist before assigning high-priority beads to bots
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
* 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>
* Fix child relationship handling
* Fix: Remove automatic dependency creation in createSubtask()
Parent-child relationships are hierarchical via ID structure only.
The server was incorrectly creating blocking dependencies between
parent and child beads, causing children to block parents.
---------
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Replaces the TTL-based event queue (internal/events) with a proper
in-memory pub-sub bus (internal/eventbus) backed by simonfxr/pubsub.
The agent/events 9P endpoint is now a streaming subscriber: clients
block on reads and receive one JSON-encoded event per read until they
disconnect. Each open(2) creates a per-connection subscription; clunk
and connection teardown cancel it automatically.
- internal/eventbus/bus.go: new package wrapping simonfxr/pubsub;
provides Publish(agent, type, data) and Subscribe() -> (chan, cancel)
- internal/events/events.go: deleted
- internal/session/manager.go: SetEventQueue -> SetEventBus; all
publish sites updated to use eventbus constants
- internal/p9/server.go: fid gains eventCh/eventUnsub fields; Topen
subscribes, Tread blocks on channel, Tclunk/serve-defer cancel
- cmd/anvilsrv/main.go: wired to SetEventBus
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Drop PROMPT, QUESTION, ANSWER, STATUS_UPDATE, and ERROR_REPORT
constants and their handling in ValidateMessageType.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LOG_ERROR and LOG_INFO are no longer supported. Remove the constants,
drop them from ValidateMessageType, update ERROR_REPORT deprecation
notice to point to PROMPT_RESPONSE, and remove LOG_ERROR from the
skill docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the inbox processing loop that auto-completed PROMPT_RESPONSE
messages, so they now stay in the user's inbox like all other types.
Update message.go grouping and SKILL.md docs accordingly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace hardcoded PROMPT_RESPONSE/subject/to values with dynamic
placeholders so bots derive the correct response type, recipient,
and subject from message context. Also restructure prompt assembly
order so the task instruction appears before the send_message
instruction (context → prompt → outInstruction).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Document all existing API endpoints and properties
- Add agent/beads/stale endpoint for stale work detection
- Add agent/beads/children/{id} for hierarchical queries
- Add agent/beads/query endpoint for filtered queries with JSON
- Update documentation with comprehensive examples
Closes bd-5sk, bd-eg2.5.1.5
- Pass sessionID from p9 server to BeadsFS.Write
- Use sessionID as actor in executeCtl instead of hardcoded 'system'
- Assignee now automatically set to claiming session ID
- Falls back to 'system' if no sessionID available
- Tasks window with sorted list, blocker count column, index for navigation
- View window with frontmatter (title, status, blockers), Put saves changes
- New window with blockers field for setting deps on create
- Hierarchical subtask IDs (bd-s2r.1) via parent-id parameter
- Blocks tag for quick dependency add via selection
- Remove tag for deleting beads via chord
- beads/ctl commands: new, update, delete, dep, undep
- beads/{id}/json includes blockers array
- Fixed parseQuotedArgs to preserve empty quoted strings
- Fixed escape sequence handling in descriptions
Backend changes:
- Add CreatedAt() to Session interface
- Implement CreatedAt() in tmux.Session (field already existed)
- Sort Manager.List() by creation time descending
Benefits:
- Deterministic ordering (no more random map iteration)
- Newest sessions appear first (most useful)
- All clients benefit immediately
- head -1 now reliably gets most recent session
README:
- Update example to use head -1 for newest session
- Document that list is sorted newest first
- Emit initial state change event (stopped -> starting) when session is created
- Rename 'exited' state to 'killed' for clarity
- Remove duplicate killed event emission (Close() already emits via transitionToLocked)
- Set OnStateChange callback in NewManager to emit state change events
- All state changes now properly emit events via callbacks
- Wire all state changes in tmux session to use transitionToLocked (triggers OnStateChange)
- Close() exited state
- Refresh() stopped states (intentional stop, restart spam prevention, auto-restart failure, PID=0)
- Add event callbacks to mailbox manager for send/receive events
- Callbacks fire when message removed from outbox (send) and delivered to inbox (receive)
- Consistent with state change callback pattern
- Fix /events 9p read handler to respect offset/count
- Prevents infinite read loop by properly signaling EOF
- Uses readFile() pattern like /list for consistency
- Updated anvillm-communication skill to use MCP tools
- Changed session.go to instruct agents to use send_message
- Updated manager.go to tell agents to use read_inbox
- Updated Claude hook to mention read_inbox tool
- Cleaner, more consistent interface across all documentation
- Simplified Claude hooks to use AGENT_ID instead of PID lookup
- Updated 9p-read-inbox to use AGENT_ID env var
- Removed temporary file creation in tmux.go
- Much cleaner and more reliable approach
- Fix PROMPT_RESPONSE messages not auto-completing
- Remove deprecated message types (LogInfo, LogError, StatusUpdate)
- Remove entire chat log system (replaced by audit log)
- Migrate user prompts to mailbox system in main.go
- Remove {id}/in and {id}/out 9P endpoints
- Only mail processor uses sess.Send() directly
- Fix file index constants after removing in/out files
- Remove unused SendCtl function
- Remove Sandbox button from main window tag
- Remove Sandbox case handler and related functions
- Remove sandbox package import
- Delete internal/ui/sandbox.go
The Sandbox window is no longer needed as sandbox configuration
has been split into layered configuration (global, backends, roles, tools).
- Created internal/audit package for centralized logging
- Replaced per-session log files with single agent/audit file
- Updated all UIs (TUI, web, Emacs) to use centralized audit log
- Modified mailbox manager to log all message deliveries with aliases
- Updated Alog script to stream centralized audit log
- Removed session-specific log streaming in favor of global audit log
Front-ends were constructing anvillm-{backend} but backend now uses
anvillm-{namespace}. Updated Assist and emacs to read tmux target from
the tmux file instead of constructing it from backend name.
Also removed broken direct prompt functionality from emacs (P and M-P
keybindings that used /in file directly).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Created install-claude-hooks.sh to merge hooks into existing settings.json
- Updated mkfile to use merge script instead of overwriting settings.json
- Made agent name configurable via CLAUDE_AGENT_NAME env var
- Added Claude agent configuration and hook scripts
- Removed unused NewClaudeWithContinue/NewClaudeWithResume functions
- Remove reserved flag and all reservation logic (unnecessary for kiro-cli)
- Fix session ID file creation: detect kiro-cli runs directly in pane
- Add retry loop for FindBackendPID with kiro-cli detection
- Update hooks to use PPID's parent (kiro-cli PID) instead of 15569
- Remove 5-second delay from running->idle transition
- Clean up workflow scripts: remove explicit skill references and communication protocol sections
- Update researcher roles to use knowledge base, web, and codebase
- Created STATE_MACHINE_VERIFICATION.md documenting all states and transitions
- Added error→idle transition for manual recovery from error state
- Added error→starting transition for restart from error state
- Verified all 21 transition call sites across codebase
Agents were getting stuck in 'running' state after sending messages
to user. Previously only peer messages triggered idle transition.
Now all outbox messages (user and peer) trigger transition to idle,
allowing agents to receive new messages and preventing stuck states.
Verified by comprehensive state machine simulation covering all
transitions, edge cases, concurrency, and session lifecycle.
- Drain all outbox messages in batch instead of one per tick
- Process inbound messages synchronously to ensure delivery before completion
- Keep failed messages in inbox for retry instead of re-delivering
- Simplify control flow with early continue pattern
- Fix Attach button to launch foot terminal with tmux attach
- Add tmux file to 9P server to expose session:window target
- Replace action buttons with cleaner layout: main actions visible,
secondary actions in dropdown menu
- Add browser notifications for session state changes
- Preserve open dropdown menu across table refresh
- Remove disabled state from Prompt button (mailbox queues prompts)
When an agent sends a message to another agent (not user),
automatically set sender state to idle. This ensures agents
can receive responses without needing explicit STATUS_UPDATE.
Message to user now triggers idle state automatically.
Removed separate idle signal instruction from prompts.
Single action (send to user) replaces two-step process.
- Add agent/user/ directory with inbox/outbox/completed
- User is first-class participant (not a session)
- Bot->user: bot writes to outbox with to="user"
- User->bot: user writes to user/outbox with to="{session-id}"
- User inbox messages written to sender's log file
- Add mailbox manager with inbox/outbox/completed structure
- Expose mailboxes via 9P filesystem (agent/{id}/inbox, outbox, completed)
- Mail processor runs every 5s to deliver messages from outbox to inbox
- Messages delivered when recipient is idle, formatted and sent via in file
- Retry logic: 3 attempts max, then discard with notification to sender
- Race condition fixes: messages moved to completed before sending
- Auto-generate message ID and timestamp if missing from bot's JSON
- Update peer-bot skill to use mailbox system with JSON format
- Update all workflows (DevReview, DevReviewQA, Planning) with:
- Explicit shell command examples for sending messages
- plan9 task for all agents
- Mailbox instructions without markdown code blocks
- Fix idle signaling: bots must write summary to out BEFORE signaling idle
- All messages archived in completed/ with proper metadata
- Add global.yaml base config (renamed from sandbox.yaml)
- Add backend-specific configs (claude.yaml, kiro-cli.yaml)
- Add role configs (developer, reviewer, tester, architect, etc.)
- Add task configs (git, docker, go, rust, python, nodejs, etc.)
- Implement config merging: global + backend + role + tasks
- Update workflows to use roles and tasks
- Create tester role with read-only source, execute-only bins
- Fix reviewer role to use rox for bin directories
- Auto-create RW directories that don't exist
- Make backend configs required (fail if missing)
- Update mkfile to install cfg files to ~/.config/anvillm
- Remove Role-Based Sessions from IDEAS.md (now implemented)
- Add chat log support with new 'log' file (read) and 'out' file (write)
- Fix deadlock: create appendToChatLogLocked for callers holding mutex
- Improve prompts to request comprehensive summaries with actual response text
- Enforce 2MB chat log size limit with smart truncation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The Stop() method was destroying the tmux window because it killed the
bash shell (pane PID) instead of just the backend process. This commit
fixes the issue by:
1. Added FindBackendPID() to find the actual backend process (child of bash)
2. Modified session creation to store the backend PID, not the shell PID
3. Updated stopInternal() to kill only the backend process:
- Send Ctrl+C (handles SIGINT)
- Send second Ctrl+C if still alive (some CLIs need 2x)
- Use SIGTERM/SIGKILL on backend PID if unresponsive
- Never kill the bash shell, preserving the tmux window
4. Fixed Restart() to properly clean up and recreate FIFO
Tested successfully:
- Stop kills backend but preserves window ✓
- Session state transitions to "stopped" ✓
- Restart reuses same window and works ✓
- Can send prompts after restart ✓
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add Stop and Restart commands for session management, allowing graceful
termination and restart of backend processes. Add peer-bot skill for
agent-to-agent communication via 9P filesystem.
Critical fixes:
- Fix double-unlock deadlock in Stop() that would cause immediate panic
- Fix resource leak in Restart() where transitioning flag wasn't cleared on error paths
- Fix race conditions in reader() goroutine from multiple lock/unlock cycles
- Fix busy loop in reader() after EOF by using proper wait loop instead of polling FIFO
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- IsBusy now checks /proc/PID/stat for process state (R/D = busy)
when no child processes exist, fixing false idle detection
- Add Refresh() to Session interface to re-detect state on demand
Detect idle state by checking if kiro-cli-chat has tool children
rather than relying purely on output quiescence. Fixes premature
idle detection during long-running processes like remote builds.
- Add context field to sessions (prepended to every prompt)
- Add summary field (first 100 chars of last response)
- Expose context/summary via 9p filesystem
- Add Alias and Context commands to acme UI
- Improve notify script to show cwd basename and summary
- Simplify Kill command to use session ID instead of PID
- Update list format to include alias column
- Add IDEAS.md notes on bot-to-bot communication