Adds an optional `agent:` field to story file front matter so that a
specific agent can be requested for a story. The auto-assign loop now:
1. Reads the front-matter `agent` field for each story before picking
a free agent.
2. If a preferred agent is named, uses it when free; skips the story
(without falling back) when that agent is busy.
3. Falls back to the existing `find_free_agent_for_stage` behaviour
when no preference is specified.
Ported from feature branch that predated the agents.rs module refactoring.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split the monolithic agents.rs into 6 focused modules:
- mod.rs: shared types (AgentEvent, AgentStatus, etc.) and re-exports
- pool.rs: AgentPool struct, all methods, and helper free functions
- pty.rs: PTY streaming (run_agent_pty_blocking, emit_event)
- lifecycle.rs: story movement functions (move_story_to_qa, etc.)
- gates.rs: acceptance gates (clippy, tests, coverage)
- merge.rs: squash-merge, conflict resolution, quality gates
All 121 original tests are preserved and distributed across modules.
Also adds clear_front_matter_field to story_metadata.rs to strip
stale merge_failure from front matter when stories move to done.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add "Bug Workflow: Root Cause First" guidance to all coder agent prompts
and system prompts. Adds a test ensuring all coder-stage agents include
root cause, git bisect/log, and anti-workaround instructions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the require_verified_devices config toggle. The bot now always requires
encrypted rooms and cross-signing-verified devices before executing any command.
Messages from unencrypted rooms or unverified devices are rejected.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement /btw side question slash command — lets users ask quick
questions from conversation context without disrupting the main chat.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The permission_decision_equality test was missing its closing brace,
causing it to swallow the not_found_returns_404_status test function.
This was likely caused by a bad merge conflict resolution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cherry-pick from feature branch — code was never squash-merged
despite story being accepted (bug 226).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Return { behavior: "allow", updatedInput: <input> } from prompt_permission
to match the Claude Code SDK expected format (was returning just
{ behavior: "allow" } which failed validation)
- Scaffold .claude/settings.json with sensible permission defaults (Edit,
Write, common Bash commands, mcp__story-kit__*) so fresh projects don't
trigger constant permission prompts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Call auto_assign_available_work at end of merge_agent_work so the next
story gets picked up without waiting for the PTY exit handler
- Add persistent file logging to .story_kit/logs/server.log so server
logs survive restarts
- Remove duplicate pnpm install block in run_squash_merge
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Temporary diagnostic logging to track why project_root becomes None
during merge pipeline operations. Tagged with MERGE-DEBUG for easy
grep-and-remove once the root cause is confirmed fixed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The pipeline advancement logic was ignoring report_merge_failure and
blindly trusting the server-owned completion gates_passed result. Now
report_merge_failure sets a flag on the agent entry that the pipeline
checks before advancing — stories stay in 4_merge/ when merge fails.
Squash merge of feature/story-210
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The merge of story-209 (positional path argument) added a port parameter
to open_project, but two test call sites were not updated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CLI path argument support: `story-kit-server /path/to/project` opens
the given project directly (scaffolding .story_kit/ if needed) instead of
relying on auto-detection. Resolves conflict with story-208's port parameter.
Squash merge of feature/story-209
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `prune_worktree_sync` to worktree.rs: removes a story's worktree
if it exists, delegating to `remove_worktree_sync` (best-effort,
failures logged internally)
- Update `sweep_done_to_archived` to accept `git_root` and call
`prune_worktree_sync` after promoting a story from 5_done to 6_archived
- Add Part 2 to the sweep: scan 6_archived and prune any stale worktrees
for stories already there (catches items archived before this feature)
- All worktree removal failures are logged but never block file moves
- Add 5 new tests: prune noop, prune real worktree, sweep-on-promote,
sweep-stale-archived, sweep-not-blocked-by-removal-failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The mergemaster pipeline used git merge --ff-only to apply the squash
commit from a merge-queue branch onto master. This raced with the
filesystem watcher which auto-commits pipeline file moves to master,
causing the fast-forward to fail. The mergemaster agent would then
improvise by manually moving stories to done without the code merge.
- Replace --ff-only with cherry-pick so concurrent watcher commits
don't block the merge
- Add report_merge_failure MCP tool for explicit failure handling
- Update mergemaster prompt to forbid manual file moves
- Fix cleanup_merge_workspace to handle stale directories
Squash merge of feature/story-205
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add end-to-end encryption support to the Matrix bot using the matrix-sdk
crypto features. The bot now:
- Enables E2EE on the Matrix client with cross-signing bootstrapping
- Auto-verifies its own cross-signing identity on startup
- Handles key verification requests from other users automatically
- Sends encrypted messages in E2EE-enabled rooms
- Adds MATRIX_STORE_PATH config for persistent crypto store
Squash merge of feature/story-194_story_enable_matrix_e2ee_with_cross_signing_verification_on_bot
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Story 191: Matrix bot should only respond when directly addressed.
The bot now checks if it was mentioned by name or replied to before
responding, preventing it from answering every message in a room.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add HTML formatted_body to Matrix bot messages so that markdown-style
formatting (code blocks, bold, italic, lists) renders properly in Matrix
clients. Uses the pulldown-cmark crate to convert markdown to HTML and
sets the message format to org.matrix.custom.html.
Story: 188_story_render_matrix_bot_messages_with_html_formatting
Instead of waiting for the full LLM response and sending it as a single
message, stream bot responses to Matrix as they are generated. Paragraphs
are delimited by double-newline boundaries, giving users incremental
feedback while the model is still thinking.
Story: 184_story_stream_bot_responses_to_matrix_on_double_newline_boundaries
Add Done column to pipeline board. Adds the 'done' stage to
PipelineState, exposes it via the WebSocket and REST API, and
renders a Done column in the frontend pipeline board view.
Squash merge from feature/story-166_story_add_done_column_to_pipeline_board.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>