Compare commits

...

466 Commits

Author SHA1 Message Date
Timmy eb2b9f435a Bump version to 0.9.0 2026-04-03 17:07:30 +01:00
Timmy cd02fc1bd4 Ignoring old storkit files 2026-04-03 17:06:58 +01:00
Timmy 359cbc3c91 Ignoring timers 2026-04-03 17:05:35 +01:00
Timmy 00fa7bf50a Done rename merge 2026-04-03 17:04:02 +01:00
Timmy ba8de6847e Renamed storkit to huskies in mcp 2026-04-03 17:03:44 +01:00
Timmy 98e9f06564 Moving stories along 2026-04-03 17:03:31 +01:00
Timmy 2f5a7a271f Added some convenience scripts for Docker 2026-04-03 17:03:07 +01:00
Timmy 2d8ccb3eb6 huskies: rename project from storkit to huskies
Rename all references from storkit to huskies across the codebase:
- .storkit/ directory → .huskies/
- Binary name, Cargo package name, Docker image references
- Server code, frontend code, config files, scripts
- Fix script/test to build frontend before cargo clippy/test
  so merge worktrees have frontend/dist available for RustEmbed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 16:12:52 +01:00
dave a7035b6ba7 storkit: create 467_story_mcp_tool_to_return_current_time_in_project_timezone 2026-04-03 14:29:05 +00:00
dave 8ead452b73 storkit: accept 461_bug_strip_bot_mention_fails_on_element_markdown_mention_pill_format 2026-04-03 13:53:45 +00:00
dave 4036acbe59 storkit: accept 460_bug_strip_bot_mention_fails_on_element_markdown_mention_pill_format 2026-04-03 13:51:44 +00:00
dave c5dc938bdf storkit: create 455_story_rename_project_from_storkit_to_huskies 2026-04-03 13:31:12 +00:00
dave a091bec6d4 storkit: done 466_story_configurable_timezone_in_project_toml_for_timer_scheduling 2026-04-03 13:16:20 +00:00
dave e9954d244b storkit: merge 466_story_configurable_timezone_in_project_toml_for_timer_scheduling 2026-04-03 13:16:16 +00:00
dave e1cea8f958 storkit: create 466_story_configurable_timezone_in_project_toml_for_timer_scheduling 2026-04-03 13:01:46 +00:00
dave adee92c5e9 storkit: create 466_story_configurable_timezone_in_project_toml_for_timer_scheduling 2026-04-03 13:01:05 +00:00
dave daeac81e84 storkit: done 463_story_configurable_rate_limit_notification_suppression 2026-04-03 12:59:57 +00:00
dave 8059df8330 storkit: merge 463_story_configurable_rate_limit_notification_suppression 2026-04-03 12:59:54 +00:00
dave f199bf3979 storkit: delete 466_bug_timer_uses_container_utc_timezone_instead_of_host_local_timezone 2026-04-03 12:59:22 +00:00
dave d32bef5020 storkit: create 466_bug_timer_uses_container_utc_timezone_instead_of_host_local_timezone 2026-04-03 12:59:05 +00:00
dave 9f523b448d storkit: done 465_bug_timer_tick_loop_never_fires_due_entries 2026-04-03 12:48:34 +00:00
dave fade022b55 storkit: merge 465_bug_timer_tick_loop_never_fires_due_entries 2026-04-03 12:48:30 +00:00
dave 289092d88f storkit: create 465_bug_timer_tick_loop_never_fires_due_entries 2026-04-03 12:37:33 +00:00
dave 45f97167fd storkit: create 465_bug_timer_tick_loop_never_fires_due_entries 2026-04-03 12:31:55 +00:00
dave dae6486ada storkit: done 464_bug_timer_rejects_backlog_stories_should_move_to_current_on_fire 2026-04-03 12:08:43 +00:00
dave 1bf32c6537 storkit: merge 464_bug_timer_rejects_backlog_stories_should_move_to_current_on_fire 2026-04-03 12:08:39 +00:00
dave 199c8eb448 storkit: done 462_bug_stage_transition_notifications_can_arrive_out_of_order_and_show_wrong_story_name 2026-04-03 12:05:01 +00:00
dave 641384e794 storkit: merge 462_bug_stage_transition_notifications_can_arrive_out_of_order_and_show_wrong_story_name 2026-04-03 12:04:58 +00:00
dave 48a193484e storkit: done 461_bug_strip_bot_mention_fails_on_element_markdown_mention_pill_format 2026-04-03 12:01:46 +00:00
dave 9b05f94c4c storkit: create 464_bug_timer_rejects_backlog_stories_should_move_to_current_on_fire 2026-04-03 11:53:50 +00:00
dave 759c00556e fix: timer supports backlog stories — moves to current before starting
The timer tick loop now calls move_story_to_current() before
start_agent(), so stories scheduled from the backlog are moved into the
pipeline automatically when the timer fires. The timer bot command also
accepts backlog stories (previously required current).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:50:30 +00:00
dave 4808279873 storkit: create 463_story_configurable_rate_limit_notification_suppression 2026-04-03 11:38:07 +00:00
dave c7d6d568d3 storkit: create 462_bug_stage_transition_notifications_can_arrive_out_of_order_and_show_wrong_story_name 2026-04-03 11:31:29 +00:00
Timmy 0995c55a82 Bump version to 0.8.8 2026-04-03 11:07:39 +01:00
dave 41197c667a storkit: done 460_bug_strip_bot_mention_fails_on_element_markdown_mention_pill_format 2026-04-03 10:00:54 +00:00
dave 7da73aa435 storkit: merge 460_bug_strip_bot_mention_fails_on_element_markdown_mention_pill_format 2026-04-03 10:00:50 +00:00
dave 3d83cc61b6 storkit: create 461_bug_strip_bot_mention_fails_on_element_markdown_mention_pill_format 2026-04-03 09:53:38 +00:00
dave 334d52bd2b storkit: create 460_bug_strip_bot_mention_fails_on_element_markdown_mention_pill_format 2026-04-03 09:51:18 +00:00
dave 8ff1de73d4 storkit: accept 458_story_matrix_bot_ignores_messages_addressed_to_other_bots_in_ambient_mode 2026-04-02 21:06:38 +00:00
dave d37fdf8e10 fix: strip emoji between bot mention and command text
strip_mention_separator now skips all non-ASCII-alphanumeric chars
(emoji, colons, spaces) and returns a slice starting at the first
command character. Fixes mention pills with emoji display names
(e.g. "timmy ️ status") not matching bot commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:06:52 +00:00
dave 7ff88641c0 storkit: done 459_bug_matrix_history_json_and_timers_json_missing_from_scaffold_storkit_gitignore 2026-04-02 17:18:31 +00:00
dave b8ac5622d6 storkit: merge 459_bug_matrix_history_json_and_timers_json_missing_from_scaffold_storkit_gitignore 2026-04-02 17:18:28 +00:00
dave 4df3f8594c storkit: accept 457_bug_store_json_created_at_project_root_instead_of_inside_storkit 2026-04-02 17:15:50 +00:00
dave 56e71293d6 chore: remove debug log from verification handler 2026-04-02 17:10:09 +00:00
dave 2df214cad1 storkit: create 459_bug_matrix_history_json_and_timers_json_missing_from_scaffold_storkit_gitignore 2026-04-02 17:02:54 +00:00
dave f43b84a7ef storkit: done 458_story_matrix_bot_ignores_messages_addressed_to_other_bots_in_ambient_mode 2026-04-02 15:51:25 +00:00
dave ce4a0cb7f9 storkit: merge 458_story_matrix_bot_ignores_messages_addressed_to_other_bots_in_ambient_mode 2026-04-02 15:51:22 +00:00
dave 52e9fe2a87 storkit: accept 456_bug_matrix_bot_ignores_in_room_verification_requests_from_element 2026-04-02 15:41:28 +00:00
dave a22d67c36c storkit: create 458_story_matrix_bot_ignores_messages_addressed_to_other_bots_in_ambient_mode 2026-04-02 15:37:30 +00:00
dave 0cb98c2a3e storkit: accept 454_story_deduplicate_work_item_display_in_web_ui_story_panel 2026-04-02 15:17:41 +00:00
dave e6439238d2 storkit: done 457_bug_store_json_created_at_project_root_instead_of_inside_storkit 2026-04-02 13:27:49 +00:00
dave 967a306ea8 storkit: merge 457_bug_store_json_created_at_project_root_instead_of_inside_storkit 2026-04-02 13:27:46 +00:00
dave 46d09d4d45 storkit: create 457_bug_store_json_created_at_project_root_instead_of_inside_storkit 2026-04-02 13:15:04 +00:00
Timmy 13e3bd00f1 Bump version to 0.8.7 2026-04-02 14:09:25 +01:00
dave cd6d98b99f debug: log all room messages in verification handler to diagnose in-room verification 2026-04-02 13:08:02 +00:00
Timmy 358f177584 Bump version to 0.8.6 2026-04-02 13:39:49 +01:00
dave b60bb57aa4 storkit: done 456_bug_matrix_bot_ignores_in_room_verification_requests_from_element 2026-04-02 11:54:01 +00:00
dave 7003fca873 storkit: merge 456_bug_matrix_bot_ignores_in_room_verification_requests_from_element 2026-04-02 11:53:58 +00:00
dave b5d825356e storkit: create 456_bug_matrix_bot_ignores_in_room_verification_requests_from_element 2026-04-02 11:40:40 +00:00
dave 896eb4fc52 storkit: done 454_story_deduplicate_work_item_display_in_web_ui_story_panel 2026-04-02 11:00:55 +00:00
dave f8d7438eec storkit: merge 454_story_deduplicate_work_item_display_in_web_ui_story_panel 2026-04-02 11:00:52 +00:00
dave f7f4e8f95b storkit: create 455_story_rename_project_from_storkit_to_huskies 2026-04-02 10:58:03 +00:00
dave af76910f36 storkit: create 454_story_deduplicate_work_item_display_in_web_ui_story_panel 2026-04-02 10:43:24 +00:00
dave f06111f045 storkit: done 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-04-02 10:31:08 +00:00
dave c6020b7f43 storkit: merge 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-04-02 10:31:05 +00:00
dave 488b798275 storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-04-02 10:17:28 +00:00
dave 0df19967ca storkit: accept 453_bug_agent_pty_crashes_with_fatal_runtime_error_on_restart_after_gate_failure 2026-04-02 10:17:22 +00:00
dave 6e04015676 storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-04-02 10:17:22 +00:00
dave acaf9477a1 storkit: done 453_bug_agent_pty_crashes_with_fatal_runtime_error_on_restart_after_gate_failure 2026-04-02 10:15:55 +00:00
dave 46a89d481a storkit: accept 451_bug_chat_test_tsx_help_test_expects_removed_overlay_behavior 2026-04-02 10:11:49 +00:00
dave c51428414e storkit: done 451_bug_chat_test_tsx_help_test_expects_removed_overlay_behavior 2026-04-02 10:11:49 +00:00
Timmy 50405800c6 Bump version to 0.8.5 2026-04-02 11:08:18 +01:00
dave 4aca056bc9 storkit: accept 450_bug_web_ui_silently_swallows_chat_errors_including_oauth_login_link 2026-03-31 18:53:14 +00:00
dave 5e725340b4 storkit: accept 449_bug_oauth_callback_url_ignores_port_cli_flag 2026-03-31 18:52:13 +00:00
dave 3fa2064e3e storkit: done 450_bug_web_ui_silently_swallows_chat_errors_including_oauth_login_link 2026-03-31 14:59:41 +00:00
dave 16f9722851 storkit: merge 450_bug_web_ui_silently_swallows_chat_errors_including_oauth_login_link 2026-03-31 14:59:38 +00:00
dave 5f0680c6c1 storkit: done 449_bug_oauth_callback_url_ignores_port_cli_flag 2026-03-31 14:55:49 +00:00
dave 57e0197d75 storkit: merge 449_bug_oauth_callback_url_ignores_port_cli_flag 2026-03-31 14:55:46 +00:00
dave dc4bac3a85 fix: update /help test to expect botCommand dispatch, fix PTY fd leak in claude_code.rs (#451, #452)
The /help test expected the help overlay to appear, but /help now goes
through botCommand like other slash commands. Updated the test to match.

Also added reader thread join and child.wait() calls to
claude_code.rs to prevent PTY master fd leaks from web UI chat sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:48:47 +00:00
dave f16545ec36 fix: join PTY reader thread before returning to prevent stale fd leak (#453)
The reader thread spawned in run_agent_pty_blocking was never joined,
leaving a cloned PTY master fd open after the agent exited. When the
pipeline restarted the agent on the same worktree, the stale fd from
the previous session interfered with the new PTY allocation, causing
Claude Code's bundled ripgrep to crash with:
  fatal runtime error: assertion failed: output.write(&bytes).is_ok()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:41:00 +00:00
dave d132ed8e64 storkit: accept 448_story_send_oauth_login_link_via_chat_when_credentials_are_missing 2026-03-31 14:22:34 +00:00
dave 2a633d604a storkit: create 453_bug_agent_pty_crashes_with_fatal_runtime_error_on_restart_after_gate_failure 2026-03-31 14:16:32 +00:00
dave 6a44c0b8ee storkit: accept 447_bug_element_tab_completion_display_name_breaks_bot_command_matching 2026-03-31 14:14:51 +00:00
dave 3f97e34f21 storkit: create 453_bug_agent_pty_crashes_with_fatal_runtime_error_on_restart_after_gate_failure 2026-03-31 14:13:22 +00:00
dave 49a8a23d75 storkit: accept 446_story_oauth_login_button_in_web_ui 2026-03-31 14:08:30 +00:00
dave 1358a32476 storkit: create 453_bug_agent_pty_crashes_with_fatal_runtime_error_on_restart_after_gate_failure 2026-03-31 14:04:40 +00:00
Dave 9b79160c95 storkit: create 453_bug_agent_pty_crashes_with_fatal_runtime_error_on_restart_after_gate_failure 2026-03-31 12:25:40 +00:00
Timmy 0cbe99677f Using init: true in docker 2026-03-31 12:36:22 +01:00
dave 46b1609528 storkit: create 453_bug_agent_pty_crashes_with_fatal_runtime_error_on_restart_after_gate_failure 2026-03-31 11:31:05 +00:00
dave 2b0b08ceda storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-03-31 11:30:44 +00:00
dave 19cc684433 storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-03-31 11:30:28 +00:00
dave fecb157291 storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-03-31 11:25:59 +00:00
dave ac84e7240e storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-03-31 11:21:51 +00:00
dave d5d82bdb00 storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-03-31 11:21:45 +00:00
dave f10edd6718 storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-03-31 11:17:47 +00:00
dave 3f6cd55833 storkit: create 452_bug_claude_code_pty_crashes_with_fatal_runtime_error_on_agent_restart 2026-03-31 11:13:05 +00:00
dave a9e8bc4d87 storkit: create 451_bug_chat_test_tsx_help_test_expects_removed_overlay_behavior 2026-03-31 11:12:55 +00:00
dave 063e0fa76e storkit: create 450_bug_web_ui_silently_swallows_chat_errors_including_oauth_login_link 2026-03-31 10:55:02 +00:00
dave 9e7bd33822 storkit: create 449_bug_oauth_callback_url_ignores_port_cli_flag 2026-03-31 10:49:23 +00:00
Timmy 7427865e46 Adding more slash commands 2026-03-31 11:33:41 +01:00
Timmy ff5f9c76fd Bump version to 0.8.4 2026-03-31 11:32:10 +01:00
dave 641bbfbe2e storkit: done 448_story_send_oauth_login_link_via_chat_when_credentials_are_missing 2026-03-31 10:28:06 +00:00
dave 5516ec4595 storkit: merge 448_story_send_oauth_login_link_via_chat_when_credentials_are_missing 2026-03-31 10:28:02 +00:00
Timmy 762467efd4 Allowing stat in claude permissions 2026-03-31 11:22:15 +01:00
Timmy 3f54bda360 Updating sha2 2026-03-31 11:21:50 +01:00
dave 4d1e388a48 storkit: done 447_bug_element_tab_completion_display_name_breaks_bot_command_matching 2026-03-31 10:18:24 +00:00
dave 10be86587a storkit: merge 447_bug_element_tab_completion_display_name_breaks_bot_command_matching 2026-03-31 10:18:21 +00:00
dave 6a10591413 storkit: done 446_story_oauth_login_button_in_web_ui 2026-03-31 10:08:43 +00:00
dave 321c88e05e storkit: merge 446_story_oauth_login_button_in_web_ui 2026-03-31 10:08:40 +00:00
dave 23562dfa61 storkit: create 448_story_send_oauth_login_link_via_chat_when_credentials_are_missing 2026-03-31 10:04:26 +00:00
dave cb6ebf1d69 storkit: create 447_bug_element_tab_completion_display_name_breaks_bot_command_matching 2026-03-31 09:58:58 +00:00
Timmy a006985faf Bump version to 0.8.3 2026-03-30 18:17:09 +01:00
dave 3fce9ec082 feat: add Linux arm64 build to release script
Builds aarch64-unknown-linux-musl via cross alongside the existing
x86_64 Linux and macOS arm64 targets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:15:16 +00:00
dave 03026c70cc storkit: create 446_story_oauth_login_button_in_web_ui 2026-03-30 16:27:30 +00:00
Timmy b75679175b Bump version to 0.8.2 2026-03-30 11:57:05 +01:00
dave 440081016d storkit: accept 433_story_setup_wizard_interviews_user_on_bare_projects_with_no_existing_code 2026-03-29 04:29:58 +00:00
dave e8f3629c76 storkit: accept 438_story_slash_command_autocomplete_in_web_ui_text_input 2026-03-29 02:08:37 +00:00
dave c5cdc0f594 storkit: done 433_story_setup_wizard_interviews_user_on_bare_projects_with_no_existing_code 2026-03-29 00:46:08 +00:00
dave fec417cb16 storkit: merge 433_story_setup_wizard_interviews_user_on_bare_projects_with_no_existing_code 2026-03-29 00:46:05 +00:00
dave a70a06a5fb storkit: create 433_story_setup_wizard_interviews_user_on_bare_projects_with_no_existing_code 2026-03-29 00:29:17 +00:00
dave 0a617e1c18 storkit: accept 445_bug_rate_limited_mergemaster_exits_advance_stories_to_done_without_merging 2026-03-29 00:05:27 +00:00
dave 4527f71857 storkit: accept 444_refactor_extract_shared_test_helpers_test_ctx_write_story_file_make_api 2026-03-28 23:46:26 +00:00
dave 6e0d12d145 storkit: accept 440_refactor_consolidate_is_permission_approval_into_chat_util 2026-03-28 23:44:25 +00:00
dave d471d29c72 storkit: accept 434_story_wizard_auto_checks_completion_on_first_conversation 2026-03-28 23:34:10 +00:00
dave 0b652eec21 storkit: done 434_story_wizard_auto_checks_completion_on_first_conversation 2026-03-28 23:33:07 +00:00
dave b32fdf7d65 storkit: merge 434_story_wizard_auto_checks_completion_on_first_conversation 2026-03-28 23:33:05 +00:00
dave 2da0e1eb55 storkit: accept 442_refactor_deduplicate_stage_display_name_into_shared_module 2026-03-28 22:58:18 +00:00
dave 269124a1fd storkit: accept 443_refactor_extract_shared_find_story_name_from_commands 2026-03-28 22:40:14 +00:00
dave 5992f9bd19 storkit: merge 438_story_slash_command_autocomplete_in_web_ui_text_input 2026-03-28 22:27:40 +00:00
dave a53967453e storkit: done 438_story_slash_command_autocomplete_in_web_ui_text_input 2026-03-28 22:26:16 +00:00
dave ab4b218ac7 storkit: accept 441_refactor_deduplicate_get_project_root_wrappers_in_io_modules 2026-03-28 20:35:05 +00:00
dave d5b936c88d storkit: accept 439_refactor_unify_story_stuck_states_into_a_single_status_field 2026-03-28 20:28:04 +00:00
dave 07cc0e3f29 storkit: accept 437_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_input 2026-03-28 20:22:04 +00:00
dave db4a84c70f storkit: done 445_bug_rate_limited_mergemaster_exits_advance_stories_to_done_without_merging 2026-03-28 20:08:18 +00:00
dave 3048d26e66 storkit: merge 445_bug_rate_limited_mergemaster_exits_advance_stories_to_done_without_merging 2026-03-28 20:08:15 +00:00
dave 8e45b2a08d storkit: done 444_refactor_extract_shared_test_helpers_test_ctx_write_story_file_make_api 2026-03-28 19:51:20 +00:00
dave ddc4a57cd2 storkit: merge 444_refactor_extract_shared_test_helpers_test_ctx_write_story_file_make_api 2026-03-28 19:51:17 +00:00
dave d216f3c267 storkit: done 440_refactor_consolidate_is_permission_approval_into_chat_util 2026-03-28 19:47:36 +00:00
dave 8cd881c8f1 storkit: merge 440_refactor_consolidate_is_permission_approval_into_chat_util 2026-03-28 19:47:33 +00:00
dave 2867e1d15f storkit: accept 431_story_qa_agent_reviews_code_changes_against_acceptance_criteria 2026-03-28 19:30:48 +00:00
dave c2c9d3f9cb storkit: create 445_bug_rate_limited_mergemaster_exits_advance_stories_to_done_without_merging 2026-03-28 19:19:17 +00:00
dave f734b4a3c6 storkit: done 443_refactor_extract_shared_find_story_name_from_commands 2026-03-28 19:09:13 +00:00
dave 890693efda storkit: done 442_refactor_deduplicate_stage_display_name_into_shared_module 2026-03-28 18:57:31 +00:00
dave 5403b29261 storkit: done 439_refactor_unify_story_stuck_states_into_a_single_status_field 2026-03-28 18:36:45 +00:00
dave 8ee59f5dc1 storkit: merge 439_refactor_unify_story_stuck_states_into_a_single_status_field 2026-03-28 18:36:42 +00:00
dave 5dcc35a1b3 fix: gate runner delegates to script/test instead of hardcoding cargo clippy
The acceptance gate was hardcoded to run cargo clippy, which fails on
non-Rust projects (Go, Node, etc.). Now the gate only runs script/test
which is project-specific. Clippy is added to storkit's own script/test
so Rust linting is preserved for this project.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:15:29 +00:00
dave af70b68cd1 storkit: accept 432_story_complete_setup_wizard_with_mcp_tools_and_agent_driven_file_generation 2026-03-28 18:12:43 +00:00
dave e356f9b2dd storkit: accept 423_story_auto_schedule_timer_on_rate_limit_to_resume_after_reset 2026-03-28 17:42:42 +00:00
dave 96793de11b storkit: merge 441_refactor_deduplicate_get_project_root_wrappers_in_io_modules 2026-03-28 16:48:49 +00:00
dave bfe70f5599 storkit: done 439_refactor_unify_story_stuck_states_into_a_single_status_field 2026-03-28 16:48:42 +00:00
dave 98aedaddf0 storkit: done 442_refactor_deduplicate_stage_display_name_into_shared_module 2026-03-28 16:47:58 +00:00
dave 496ce864d7 storkit: done 441_refactor_deduplicate_get_project_root_wrappers_in_io_modules 2026-03-28 16:46:18 +00:00
dave 243738551c fix: wizard README instructions explicitly require LLM to generate and write files
The LLM was having the conversation with the user but never following
through with wizard_generate calls. The instructions now spell out
the full workflow: get hint, write content, stage it, show user, confirm.
Also adds "keep moving" instruction so the LLM auto-advances to the
next step after confirmation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:37:25 +00:00
dave 20f2d97f06 storkit: create 444_refactor_extract_shared_test_helpers_test_ctx_write_story_file_make_api 2026-03-28 16:34:45 +00:00
dave b6edc1bff7 storkit: create 443_refactor_extract_shared_find_story_name_from_commands 2026-03-28 16:34:41 +00:00
dave c45613a3ad storkit: create 442_refactor_deduplicate_stage_display_name_into_shared_module 2026-03-28 16:34:39 +00:00
dave 7efed33851 storkit: create 441_refactor_deduplicate_get_project_root_wrappers_in_io_modules 2026-03-28 16:34:36 +00:00
dave b00a477070 storkit: create 440_refactor_consolidate_is_permission_approval_into_chat_util 2026-03-28 16:34:35 +00:00
dave 52f2e89659 storkit: done 437_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_input 2026-03-28 16:33:29 +00:00
dave 08db28d9d6 storkit: merge 437_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_input 2026-03-28 16:33:26 +00:00
dave 77ff0ce093 storkit: create 439_refactor_unify_story_stuck_states_into_a_single_status_field 2026-03-28 16:27:51 +00:00
dave 0ab1b1232b storkit: create 439_refactor_unify_story_stuck_states_into_a_single_status_field 2026-03-28 16:27:36 +00:00
dave 209e01bc06 storkit: create 438_story_slash_command_autocomplete_in_web_ui_text_input 2026-03-28 16:24:44 +00:00
dave 2650b1a42e storkit: create 437_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_input 2026-03-28 16:21:19 +00:00
Timmy 3595df4d9d Bump version to 0.8.1 2026-03-28 15:37:08 +00:00
dave 5d84100c41 storkit: create 436_refactor_unify_story_stuck_states_into_a_single_status_field 2026-03-28 15:35:14 +00:00
dave dd436ad186 storkit: create 435_story_unblock_command_handles_all_stuck_states_not_just_blocked_flag 2026-03-28 15:33:39 +00:00
dave b811b9188f storkit: done 431_story_qa_agent_reviews_code_changes_against_acceptance_criteria 2026-03-28 15:33:19 +00:00
dave 9935311c35 storkit: merge 431_story_qa_agent_reviews_code_changes_against_acceptance_criteria 2026-03-28 15:33:16 +00:00
dave be0036922a fix: unblock command also clears merge_failure field
Previously unblock only checked for blocked=true. Stories stuck in
merge with a merge_failure field were not considered "blocked" and
unblock refused to act. Now it clears both blocked and merge_failure,
and reports which fields were cleared.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:33:01 +00:00
dave 361f9dff0d fix(426): also narrow pre-cherry-pick code change check to .storkit/work/
There were two places checking for code changes: the post-cherry-pick
verification (already fixed) and a pre-cherry-pick check in the
merge-queue worktree. The pre-cherry-pick check was still filtering
all of .storkit/ which rejected stories that only change project.toml.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:27:19 +00:00
dave fc160b5c5f feat: wizard detects bare projects and prompts user interview for context/stack
wizard_generate now checks if the project has no source code. On bare
projects, the generation hints tell the LLM to ask the user what they
want to build and what tech stack they plan to use, rather than trying
to read a nonexistent codebase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:17:42 +00:00
dave 9092b8a2c9 fix: wizard hints address the LLM not the user, README adds bare project guidance
The format_wizard_state hints now tell the LLM what to do ("show it
to the user and ask if they're happy") rather than exposing tool names
to the user ("Run wizard_generate").

README wizard instructions now distinguish between existing-code projects
(read codebase, generate files) and bare projects (interview the user
about what they want to build).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:15:14 +00:00
dave dfe3d96313 docs: move wizard instructions to .storkit/README.md for LLM-agnostic access
The wizard check was only in CLAUDE.md which is Claude-specific.
Move the primary instruction to .storkit/README.md (step 1 of First
Steps) so any LLM reading the dev process docs will discover the wizard.
CLAUDE.md keeps a shorter pointer to the README.

Also fix stale .story_kit/ paths to .storkit/ in the README.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:12:54 +00:00
dave bcefa6a25d storkit: create 434_story_wizard_auto_checks_completion_on_first_conversation 2026-03-28 15:06:53 +00:00
dave 50bfeddcb5 fix: scaffold CLAUDE.md uses active wizard instruction
Change from passive "call wizard_status to check progress" to active
"On your first conversation, call wizard_status" with IMPORTANT prefix.
Without the direct instruction, Claude ignores the wizard tools.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:06:21 +00:00
dave 8e6b8ef338 storkit: create 433_story_setup_wizard_interviews_user_on_bare_projects_with_no_existing_code 2026-03-28 15:00:04 +00:00
dave d363eb63e2 fix: scaffold CLAUDE.md now mentions wizard and MCP tools
Without this, Claude Code in a freshly scaffolded project has no idea
storkit's wizard or MCP tools exist and gives generic setup advice.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:37:44 +00:00
dave 422cec370d docs: rewrite quickstart as a step-by-step with wizard flow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:34:45 +00:00
dave 973b7d6f72 storkit: done 432_story_complete_setup_wizard_with_mcp_tools_and_agent_driven_file_generation 2026-03-28 14:24:02 +00:00
dave 49b78f3642 storkit: merge 432_story_complete_setup_wizard_with_mcp_tools_and_agent_driven_file_generation 2026-03-28 14:23:59 +00:00
dave 93576e3f83 fix(426): narrow merge verification exclude to .storkit/work/ only
The post-cherry-pick diff check was excluding all of .storkit/, which
rejected stories whose deliverable is .storkit/project.toml changes
(e.g. 431 updating QA agent prompts). Narrow the exclusion to
.storkit/work/ which is where pipeline file moves live.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:21:57 +00:00
dave dd7f71dd87 docs: add Claude Code quickstart, web UI, and chat transport sections to README
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:03:23 +00:00
dave 9a8492c72f storkit: create 432_story_complete_setup_wizard_with_mcp_tools_and_agent_driven_file_generation 2026-03-28 14:00:20 +00:00
dave ac9bdde164 storkit: create 431_story_qa_agent_reviews_code_changes_against_acceptance_criteria 2026-03-28 13:58:38 +00:00
dave 0b2ec64c74 storkit: done 430_bug_status_command_traffic_light_dots_not_coloured_in_matrix 2026-03-28 13:57:41 +00:00
dave fe0a032e8e storkit: merge 430_bug_status_command_traffic_light_dots_not_coloured_in_matrix 2026-03-28 13:57:38 +00:00
dave eff8f6a6a6 feat(399): add --port CLI flag with project.toml persistence
Manual merge of story 399 feature branch, adapted for the current CLI
parser (which includes the init subcommand from 429).

- storkit --port 3000 sets the listening port
- storkit --port=3000 also works
- Port resolution: CLI flag > STORKIT_PORT env > default 3001
- Supports combining with init: storkit init --port 3000 /path
- Replaces CliDirective enum with CliArgs struct that handles both
  --port and init in a single pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 13:47:02 +00:00
Timmy e45eab82f2 Bump version to 0.8.0 2026-03-28 13:32:07 +00:00
dave 310ad365e6 storkit: done 429_story_interactive_project_setup_wizard_for_new_storkit_projects 2026-03-28 13:29:08 +00:00
dave 0b50c66caa storkit: merge 429_story_interactive_project_setup_wizard_for_new_storkit_projects 2026-03-28 13:29:05 +00:00
dave 9feed0f882 storkit: create 430_bug_status_command_traffic_light_dots_not_coloured_in_matrix 2026-03-28 13:27:45 +00:00
dave bb3301c5af fix: release script handles already-bumped version gracefully
Skip the version bump commit if nothing changed, so re-running
script/release for the same version doesn't fail on empty commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 13:18:11 +00:00
dave a2123274a5 fix: release script exits silently when grep finds no matches
The changelog grep commands return exit code 1 when no commits match,
which set -euo pipefail treats as fatal. Add || true guards so the
script continues to the tag/push/release steps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 13:11:35 +00:00
dave 3cbbc5387a storkit: create 429_story_interactive_project_setup_wizard_for_new_storkit_projects 2026-03-28 13:06:19 +00:00
dave 4e828fbdd1 storkit: create 429_story_interactive_project_setup_wizard_for_new_storkit_projects 2026-03-28 13:03:11 +00:00
Timmy 6d88595e0d Adding GPL for the moment. 2026-03-28 13:02:12 +00:00
Timmy aa90646edf Bump version to 0.7.1 2026-03-28 12:51:39 +00:00
dave 7235ab7c7c storkit: done 427_story_server_side_text_normalization_for_chat_message_line_breaks 2026-03-28 12:44:52 +00:00
dave a0326dae78 storkit: done 426_bug_mergemaster_pipeline_marks_story_done_without_verifying_code_landed_on_master 2026-03-28 12:37:43 +00:00
dave 953fce2ca6 fix(426): verify cherry-pick landed on master before marking story done
After the cherry-pick step in run_squash_merge, verify:
1. project_root is on the base branch (not a merge-queue branch)
2. HEAD commit has actual code changes (not an empty/story-only diff)

If either check fails, return success=false so the story stays in merge
stage for retry instead of being phantom-advanced to done.

Also rename move_story_to_archived → move_story_to_done.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 12:37:03 +00:00
dave 5035b84de5 storkit: create 426_bug_mergemaster_pipeline_marks_story_done_without_verifying_code_landed_on_master 2026-03-28 12:29:48 +00:00
Timmy c2f477dde6 Bump version to 0.7.0 2026-03-28 12:20:00 +00:00
dave b098c8ff9f storkit: merge 428_refactor_split_pool_pipeline_rs_into_submodules 2026-03-28 11:50:15 +00:00
dave 7fea543f60 storkit: done 428_refactor_split_pool_pipeline_rs_into_submodules 2026-03-28 11:50:02 +00:00
dave f8bb23a6d4 fix(424): correct WatcherEvent::HardBlock to RateLimitHardBlock in pool/mod.rs
Story 424's merge used the wrong variant name HardBlock instead of
RateLimitHardBlock, breaking master compilation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 11:47:26 +00:00
dave 0016841770 storkit: create 426_bug_mergemaster_pipeline_marks_story_done_without_verifying_code_landed_on_master 2026-03-28 11:35:03 +00:00
dave 3639d64da6 fix(424): add throttled field to all StoryAgent ctors and handle HardBlock in ws.rs
The initial commit added the `throttled` field to `StoryAgent` but missed
several construction sites in lifecycle.rs, test_helpers.rs, and scan.rs.
Also adds the `HardBlock` match arm in the WebSocket event conversion and
minor CSS/import ordering fixes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 11:33:43 +00:00
dave ebdcf18134 feat(424): rate-limit traffic-light dots and hard-block alerts
- Add HardBlock variant to WatcherEvent (story_id, agent_name, reset_time)
- In pty.rs, distinguish allowed_warning (throttle) from hard blocks;
  emit RateLimitWarning for throttles, HardBlock for actual 429s
- Add `throttled: bool` field to StoryAgent / AgentInfo
- Pool spawns a background listener that sets throttled=true on
  RateLimitWarning or HardBlock events and fires AgentStateChanged
- Status command shows traffic-light dots: ○ idle, ● running, ◑ throttled, ✗ blocked
- Read blocked flag from story front matter for the ✗ dot
- Notifications: RateLimitWarning silenced (too noisy); HardBlock sends
  urgent chat notification with optional reset time
- Tests added for traffic_light_dot, read_story_blocked, status output,
  and all notification paths
2026-03-28 11:33:01 +00:00
dave d83f2ae4c1 storkit: done 424_story_rate_limit_traffic_light_status_and_hard_block_alerts 2026-03-28 11:27:19 +00:00
dave f6c0d35f11 storkit: create 427_story_server_side_text_normalization_for_chat_message_line_breaks 2026-03-28 11:21:11 +00:00
dave facbf51f05 storkit: create 426_bug_mergemaster_pipeline_marks_story_done_without_verifying_code_landed_on_master 2026-03-28 11:18:36 +00:00
dave 847ebc292f storkit: create 424_story_rate_limit_traffic_light_status_and_hard_block_alerts 2026-03-28 11:11:32 +00:00
Timmy 065ca2bd8f Bump version to 0.6.1 2026-03-28 11:07:06 +00:00
dave 34988855bc storkit: create 428_refactor_split_pool_pipeline_rs_into_submodules 2026-03-28 11:00:26 +00:00
dave 7fc788baea docs: rewrite README for 0.6.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:56:36 +00:00
dave 40575924b5 chore: bump version to 0.6.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:50:59 +00:00
dave 4f56fa6cbe storkit: done 427_story_server_side_text_normalization_for_chat_message_line_breaks 2026-03-28 10:41:46 +00:00
dave 52513b55ff storkit: merge 427_story_server_side_text_normalization_for_chat_message_line_breaks 2026-03-28 10:41:43 +00:00
dave 1ae2fa9b9b storkit: create 427_story_server_side_text_normalization_for_chat_message_line_breaks 2026-03-28 10:28:23 +00:00
dave 6077f74dbd storkit: accept 09_story_remove_scroll_bars 2026-03-28 10:12:53 +00:00
dave 8ab2e19e98 fix(423): handle RateLimitHardBlock in ws.rs match
The new WatcherEvent::RateLimitHardBlock variant added in the feature
commit was not covered in the ws.rs From<WatcherEvent> match, causing
a compile error. Add the missing arm returning None (same as
RateLimitWarning — handled by chat notifications only, not WebSocket).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 10:11:44 +00:00
dave b44f3a33e3 feat(423): auto-schedule timer on rate limit to resume after reset
- pty.rs: detect rate_limit_event hard blocks, parse reset_at, emit
  WatcherEvent::RateLimitHardBlock with story_id, agent_name, reset_at
- watcher.rs: add RateLimitHardBlock variant to WatcherEvent enum
- timer.rs: add TimerStore::upsert (add-or-update-to-later) and
  spawn_rate_limit_auto_scheduler (listens for RateLimitHardBlock,
  upserts timer for the blocked story)
- notifications.rs: handle RateLimitHardBlock events with a debounced
  chat notification including the scheduled resume time;
  add format_rate_limit_hard_block_notification helper
- matrix/mod.rs: subscribe second watcher_rx for auto-scheduler,
  pass it to run_bot
- matrix/bot/run.rs: wire spawn_rate_limit_auto_scheduler into bot startup

Tests cover: AC1 (hard block detection in pty), AC2 (auto-scheduler
adds timer), AC3 (upsert deduplication), AC5 (chat notification sent),
AC6 (worktree preserved — timer fires start_agent on existing worktree)
2026-03-28 10:11:08 +00:00
dave 57407aed51 storkit: create 426_bug_mergemaster_pipeline_marks_story_done_without_verifying_code_landed_on_master 2026-03-28 10:09:41 +00:00
dave a29677b3c7 storkit: create 426_bug_mergemaster_pipeline_marks_story_done_without_verifying_code_landed_on_master 2026-03-28 10:06:17 +00:00
dave 95df450fca storkit: create 426_bug_mergemaster_pipeline_marks_story_done_without_verifying_code_landed_on_master 2026-03-28 10:05:58 +00:00
dave 6c6bc35785 feat: add unblock command and MCP tool to reset blocked stories
- Add `unblock` bot command (chat + web UI slash command) that clears the
  `blocked` flag and resets `retry_count` to 0 in story front matter
- Works across all pipeline stages (1_backlog through 6_archived)
- Returns confirmation with story name and ID, or clear error if story
  is not found or not blocked
- Expose `unblock_story` MCP tool for programmatic use by agents
- Make `chat::commands::unblock` module pub(crate) so story_tools can
  call `unblock_by_number`
- Add 8 unit tests covering registration, validation, core logic, and
  edge cases (not-found, not-blocked, any stage, story ID in response)
- Update MCP tools list test: 49 → 50 tools
2026-03-28 10:05:51 +00:00
dave 7652bbba9c storkit: done 423_story_auto_schedule_timer_on_rate_limit_to_resume_after_reset 2026-03-28 09:50:07 +00:00
dave efd89a26ac config: increase max_retries from 2 to 3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 09:41:25 +00:00
dave 71d4746009 storkit: done 425_story_chat_notification_when_a_story_blocks_with_reason 2026-03-28 09:38:50 +00:00
dave 98b5475160 storkit: merge 425_story_chat_notification_when_a_story_blocks_with_reason 2026-03-28 09:38:47 +00:00
dave 740f1b5e6e storkit: create 425_story_chat_notification_when_a_story_blocks_with_reason 2026-03-28 09:25:19 +00:00
dave c0bab1e671 storkit: create 425_story_chat_notification_when_a_story_blocks_with_reason 2026-03-28 09:23:45 +00:00
dave 306810e4d5 storkit: done 419_bug_matrix_bot_crashes_on_transient_network_error_instead_of_retrying 2026-03-28 09:11:29 +00:00
dave 1193b7ac9a storkit: merge 419_bug_matrix_bot_crashes_on_transient_network_error_instead_of_retrying 2026-03-28 09:11:26 +00:00
dave 05db012aaf storkit: done 422_story_unblock_command_to_reset_blocked_stories 2026-03-28 09:08:02 +00:00
dave bc3c852509 storkit: create 424_story_rate_limit_traffic_light_status_and_hard_block_alerts 2026-03-28 09:07:16 +00:00
dave 04051282da storkit: create 424_story_rate_limit_traffic_light_status_and_hard_block_alerts 2026-03-28 09:06:26 +00:00
dave 081b33a8a6 storkit: done 421_story_timer_command_for_deferred_agent_start 2026-03-28 09:02:23 +00:00
dave cf5424f9a6 storkit: merge 421_story_timer_command_for_deferred_agent_start 2026-03-28 09:02:20 +00:00
dave 1ec9aaab8a storkit: done 420_story_loc_for_a_specified_file_bot_command_and_web_ui_slash_command 2026-03-28 08:59:03 +00:00
dave d6f82393f5 storkit: merge 420_story_loc_for_a_specified_file_bot_command_and_web_ui_slash_command 2026-03-28 08:58:57 +00:00
dave f4ce0e017b storkit: create 423_story_auto_schedule_timer_on_rate_limit_to_resume_after_reset 2026-03-28 08:49:23 +00:00
dave c0ea5f0cb8 storkit: done 418_refactor_split_pool_auto_assign_rs_into_submodules 2026-03-28 08:48:05 +00:00
dave d375c4b1d3 storkit: merge 418_refactor_split_pool_auto_assign_rs_into_submodules 2026-03-28 08:48:02 +00:00
dave 4ea4be1462 storkit: create 422_story_unblock_command_to_reset_blocked_stories 2026-03-28 08:44:31 +00:00
dave bc1c1cd2c9 storkit: create 421_story_timer_command_for_deferred_agent_start 2026-03-28 08:35:41 +00:00
dave c1e4c40f31 storkit: create 421_story_timer_command_for_deferred_agent_start 2026-03-28 08:35:02 +00:00
dave 203e8f22be storkit: done 417_refactor_split_matrix_bot_rs_into_focused_modules 2026-03-28 08:30:04 +00:00
dave 665c036a56 storkit: merge 417_refactor_split_matrix_bot_rs_into_focused_modules 2026-03-28 08:30:01 +00:00
dave 73304f08ac storkit: create 420_story_loc_for_a_specified_file_bot_command_and_web_ui_slash_command 2026-03-28 08:17:32 +00:00
dave fe9fc69f96 storkit: create 420_story_loc_for_a_specified_file_bot_command_and_web_ui_slash_command 2026-03-28 08:17:05 +00:00
dave 3b0542cd41 storkit: create 419_bug_matrix_bot_crashes_on_transient_network_error_instead_of_retrying 2026-03-28 08:10:38 +00:00
dave 102919e0b3 storkit: accept 415_refactor_split_agents_pool_mod_rs_into_submodules 2026-03-27 19:53:40 +00:00
dave d63aa0a3c2 storkit: accept 416_refactor_split_io_fs_rs_into_submodules 2026-03-27 19:49:39 +00:00
dave 7f7db57933 storkit: accept 414_story_loc_command_filters_out_known_huge_files 2026-03-27 19:14:37 +00:00
dave 043791194f storkit: accept 413_refactor_split_slack_rs_into_focused_modules 2026-03-27 18:59:36 +00:00
dave 710f839c65 storkit: accept 409_refactor_split_whatsapp_rs_into_focused_modules 2026-03-27 18:38:35 +00:00
dave b0e21abb6e storkit: accept 410_story_loc_bot_command_top_files_by_line_count 2026-03-27 18:32:34 +00:00
dave 6b71c07f5b storkit: create 418_refactor_split_pool_auto_assign_rs_into_submodules 2026-03-27 16:53:50 +00:00
dave 9cff3c753d storkit: create 417_refactor_split_matrix_bot_rs_into_focused_modules 2026-03-27 16:52:05 +00:00
dave 6acd7f5249 storkit: done 416_refactor_split_io_fs_rs_into_submodules 2026-03-27 16:08:12 +00:00
dave 26f5b25f22 storkit: merge 416_refactor_split_io_fs_rs_into_submodules 2026-03-27 16:08:10 +00:00
dave 8bc0bd592e storkit: done 415_refactor_split_agents_pool_mod_rs_into_submodules 2026-03-27 15:56:03 +00:00
dave 7c25aca39b storkit: merge 415_refactor_split_agents_pool_mod_rs_into_submodules 2026-03-27 15:56:00 +00:00
dave 5173bf4aef storkit: create 416_refactor_split_io_fs_rs_into_submodules 2026-03-27 15:48:47 +00:00
dave 7f7f49d757 storkit: done 414_story_loc_command_filters_out_known_huge_files 2026-03-27 15:37:54 +00:00
dave e88b9bbc63 storkit: merge 414_story_loc_command_filters_out_known_huge_files 2026-03-27 15:37:51 +00:00
dave db22ab2229 storkit: create 415_refactor_split_agents_pool_mod_rs_into_submodules 2026-03-27 15:30:33 +00:00
dave c30ad79398 storkit: done 413_refactor_split_slack_rs_into_focused_modules 2026-03-27 15:29:26 +00:00
dave 16853328fa storkit: merge 413_refactor_split_slack_rs_into_focused_modules 2026-03-27 15:29:23 +00:00
dave 8ac8cdba88 storkit: create 414_story_loc_command_filters_out_known_huge_files 2026-03-27 15:14:08 +00:00
dave c046edebda storkit: accept 404_bug_whatsapp_and_slack_missing_assign_command_handler 2026-03-27 15:09:57 +00:00
dave eef9669c95 storkit: done 404_bug_whatsapp_and_slack_missing_assign_command_handler 2026-03-27 15:09:53 +00:00
dave a9cdd3a354 storkit: merge 404_bug_whatsapp_and_slack_missing_assign_command_handler 2026-03-27 15:09:50 +00:00
dave b4eeb499e9 storkit: create 413_refactor_split_slack_rs_into_focused_modules 2026-03-27 14:59:06 +00:00
dave fca46c3806 storkit: done 403_bug_whatsapp_and_slack_missing_rmtree_command_handler 2026-03-27 14:57:09 +00:00
dave 2510fe44bc storkit: done 409_refactor_split_whatsapp_rs_into_focused_modules 2026-03-27 14:40:18 +00:00
dave e152cf3cb8 storkit: create 412_story_recheck_bot_command_to_re_run_gates_without_restarting_agent 2026-03-27 14:37:05 +00:00
dave 7d3b256fff storkit: done 410_story_loc_bot_command_top_files_by_line_count 2026-03-27 14:36:11 +00:00
dave f6d632139e storkit: merge 410_story_loc_bot_command_top_files_by_line_count 2026-03-27 14:36:07 +00:00
dave 204a99c2e7 storkit: create 412_story_recheck_bot_command_to_re_run_gates_without_restarting_agent 2026-03-27 14:35:06 +00:00
Timmy f28a03e42e Added git variables to entry point 2026-03-27 14:26:49 +00:00
Timmy 26f4edadcc Ditching story kit port file 2026-03-27 14:11:55 +00:00
Timmy fd58631e65 Removed misleading comment on docker compose file 2026-03-27 14:11:35 +00:00
dave f70399a28f storkit: accept 407_spike_fly_io_machines_for_multi_tenant_storkit_saas 2026-03-27 13:41:29 +00:00
Timmy 02d08faaa2 Fixing build/test errors in master/ 2026-03-27 12:31:08 +00:00
dave 2dc77479ad storkit: done 407_spike_fly_io_machines_for_multi_tenant_storkit_saas 2026-03-27 11:20:32 +00:00
dave c5761ae968 storkit: create 410_story_loc_bot_command_top_files_by_line_count 2026-03-27 11:05:00 +00:00
dave 67754781ca storkit: create 409_refactor_split_whatsapp_rs_into_focused_modules 2026-03-27 10:58:13 +00:00
dave 3436507a21 storkit: create 410_story_loc_bot_command_top_files_by_line_count 2026-03-27 10:57:47 +00:00
dave 93bc08574b storkit: create 407_spike_fly_io_machines_for_multi_tenant_storkit_saas 2026-03-27 10:57:41 +00:00
Timmy 3571511349 restore: reset past source tree deletion, apply pending work 2026-03-27 10:49:39 +00:00
dave 04214ca155 storkit: create 408_spike_fly_io_machines_api_integration_for_multi_tenant_storkit_saas 2026-03-26 21:12:06 +00:00
dave 4d48df152c storkit: create 407_spike_fly_io_machines_for_multi_tenant_storkit_saas 2026-03-26 21:11:46 +00:00
dave e0a70a4c1c storkit: create 408_spike_fly_io_machines_api_integration_for_multi_tenant_storkit_saas 2026-03-26 21:11:31 +00:00
dave bae50fbc5b storkit: create 407_spike_fly_io_machines_for_multi_tenant_storkit_saas 2026-03-26 21:07:56 +00:00
dave 8998dac593 storkit: create 407_spike_fly_io_machines_for_multi_tenant_storkit_saas 2026-03-26 21:01:42 +00:00
dave e6b300e70e storkit: create 407_spike_fly_io_machines_for_multi_tenant_storkit_saas 2026-03-26 21:01:21 +00:00
dave b22e2b9274 storkit: done 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 20:51:54 +00:00
dave 24b1aa6e7f storkit: merge 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 20:51:52 +00:00
dave 85e37e03a8 storkit: done 399_story_cli_port_flag_with_project_toml_persistence 2026-03-26 20:46:59 +00:00
dave f22a2666b8 storkit: accept 396_story_whatsapp_bot_startup_announcement_after_restart 2026-03-26 20:23:33 +00:00
dave 507889627a storkit: done 396_story_whatsapp_bot_startup_announcement_after_restart 2026-03-26 20:22:29 +00:00
dave c4cee72938 storkit: merge 396_story_whatsapp_bot_startup_announcement_after_restart 2026-03-26 20:22:26 +00:00
dave 33cb363651 storkit: done 400_bug_whatsapp_and_slack_missing_reset_command_handler 2026-03-26 20:18:00 +00:00
dave cd3ded278d storkit: merge 400_bug_whatsapp_and_slack_missing_reset_command_handler 2026-03-26 20:17:57 +00:00
dave b5bf75aa5a storkit: delete 398_bug_whatsapp_and_slack_missing_async_command_handlers_for_start_rebuild_reset_rmtree_assign 2026-03-26 20:09:30 +00:00
dave f6b5b1b01a storkit: create 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 20:07:54 +00:00
dave 26d34245f9 storkit: create 400_bug_whatsapp_and_slack_missing_reset_command_handler 2026-03-26 20:06:13 +00:00
dave de54265c35 storkit: create 404_bug_whatsapp_and_slack_missing_assign_command_handler 2026-03-26 20:05:40 +00:00
dave a52d1e098f storkit: create 403_bug_whatsapp_and_slack_missing_rmtree_command_handler 2026-03-26 20:05:33 +00:00
dave 015fa48c32 storkit: create 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 20:05:27 +00:00
dave abc30c93d1 storkit: create 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 20:04:41 +00:00
dave cf2faa9bff storkit: create 402_bug_whatsapp_and_slack_missing_rebuild_command_handler 2026-03-26 20:04:02 +00:00
dave 92aa1ebccf storkit: done 402_bug_whatsapp_and_slack_missing_rebuild_command_handler 2026-03-26 20:02:47 +00:00
Timmy 877f69c897 feat: browser-based OAuth login flow (story 406)
Add three HTTP endpoints for OAuth login without terminal access:
- GET /oauth/authorize — generates PKCE params, redirects to
  claude.com/cai/oauth/authorize with code=true and full scopes
- GET /callback — exchanges auth code for tokens via JSON POST to
  platform.claude.com/v1/oauth/token, writes ~/.claude/.credentials.json
- GET /oauth/status — returns current credential state as JSON

Uses SHA-256 (sha2 crate) for PKCE code challenge. The authorize URL
targets claude.com/cai/ (not platform.claude.com) which is required
for Max/Pro subscriptions to grant user:inference scope.

Users visit http://localhost:3001/oauth/authorize in their browser
to authenticate. Matrix/WhatsApp can send this link when auth fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 19:58:18 +00:00
Timmy 710b604b7c feat: auto-refresh expired OAuth token for Claude Code PTY (story 405)
Detect authentication_failed errors from the Claude Code PTY stream
and automatically refresh the OAuth access token using the stored
refresh token in ~/.claude/.credentials.json.

- New module server/src/llm/oauth.rs: reads credentials, calls
  platform.claude.com/v1/oauth/token with JSON body, writes back
- PTY provider detects "error":"authentication_failed" via AtomicBool
- chat_stream retries once after successful refresh
- Clear error message if refresh also fails

On success the retry is transparent. On failure the user sees:
"OAuth session expired. Please run claude login to re-authenticate."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 19:58:04 +00:00
Timmy ab4ce2db92 chore: archive bug 397, create story 399, fix platform-specific npm deps
- Archive completed bug 397
- Create story 399 (CLI port flag)
- Remove @biomejs/cli-darwin-arm64 and @rollup/rollup-darwin-arm64
  from package.json (breaks Docker builds on Linux)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 19:57:50 +00:00
Timmy 61f6fd60a8 storkit: merge 402_bug_whatsapp_and_slack_missing_rebuild_command_handler 2026-03-26 11:20:55 +00:00
Timmy e66149e07c storkit: done 397_bug_selection_screen_directory_picker_unreadable_in_dark_mode 2026-03-26 11:16:24 +00:00
Timmy 108a697483 storkit: merge 397_bug_selection_screen_directory_picker_unreadable_in_dark_mode 2026-03-26 11:16:21 +00:00
Timmy 1a7f419ecf storkit: create 404_bug_whatsapp_and_slack_missing_assign_command_handler 2026-03-26 11:12:18 +00:00
Timmy 96b1ce373b storkit: create 403_bug_whatsapp_and_slack_missing_rmtree_command_handler 2026-03-26 11:12:16 +00:00
Timmy 58e41f7e0b storkit: create 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 11:12:13 +00:00
Timmy c9a2fa58eb storkit: create 400_bug_whatsapp_and_slack_missing_reset_command_handler 2026-03-26 11:12:11 +00:00
Timmy 64c0f190cf storkit: create 404_bug_whatsapp_and_slack_missing_assign_command_handler 2026-03-26 11:09:49 +00:00
Timmy fc443ed987 storkit: create 403_bug_whatsapp_and_slack_missing_rmtree_command_handler 2026-03-26 11:09:48 +00:00
Timmy 7939a19816 storkit: create 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 11:09:46 +00:00
Timmy 46b5087157 storkit: create 400_bug_whatsapp_and_slack_missing_reset_command_handler 2026-03-26 11:09:45 +00:00
Timmy a8d6524b56 storkit: create 404_bug_whatsapp_and_slack_missing_assign_command_handler 2026-03-26 11:09:28 +00:00
Timmy 61d63db84c storkit: create 403_bug_whatsapp_and_slack_missing_rmtree_command_handler 2026-03-26 11:09:27 +00:00
Timmy aa4ec8c779 storkit: create 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 11:09:25 +00:00
Timmy 3777042ad3 storkit: create 400_bug_whatsapp_and_slack_missing_reset_command_handler 2026-03-26 11:09:24 +00:00
Timmy feb340beba storkit: create 404_bug_whatsapp_and_slack_missing_assign_command_handler 2026-03-26 11:07:33 +00:00
Timmy 23369c514d storkit: create 403_bug_whatsapp_and_slack_missing_rmtree_command_handler 2026-03-26 11:07:31 +00:00
Timmy 832da16b6f storkit: create 402_bug_whatsapp_and_slack_missing_rebuild_command_handler 2026-03-26 11:07:29 +00:00
Timmy 131964cbc3 storkit: create 401_bug_whatsapp_and_slack_missing_start_command_handler 2026-03-26 11:07:27 +00:00
Timmy 81db0504ed storkit: create 400_bug_whatsapp_and_slack_missing_reset_command_handler 2026-03-26 11:07:25 +00:00
Timmy 584a44a516 storkit: create 399_story_cli_port_flag_with_project_toml_persistence 2026-03-26 11:05:12 +00:00
Timmy c7c4a57533 storkit: create 399_story_cli_port_flag_with_project_toml_persistence 2026-03-26 11:03:43 +00:00
Timmy 0a67c28f8c storkit: create 398_bug_whatsapp_and_slack_missing_async_command_handlers_for_start_rebuild_reset_rmtree_assign 2026-03-26 11:00:01 +00:00
Timmy 6476492caa storkit: create 397_bug_selection_screen_directory_picker_unreadable_in_dark_mode 2026-03-26 10:52:06 +00:00
dave faf8734ea8 storkit: accept 393_story_pipeline_stage_notifications_for_whatsapp_and_slack_transports 2026-03-25 19:35:57 +00:00
dave 862f0704be storkit: accept 394_story_whatsapp_and_slack_permission_prompt_forwarding 2026-03-25 19:31:56 +00:00
dave d3df1586c6 storkit: accept 395_refactor_fix_npm_deprecated_module_warnings 2026-03-25 19:27:55 +00:00
dave 8a1996e0e4 storkit: accept 390_bug_whatsapp_missing_async_command_handlers_for_start_rebuild_reset_rmtree_assign 2026-03-25 19:21:55 +00:00
dave 61f5a0c3be storkit: accept 392_refactor_extract_shared_transport_utilities_from_matrix_module_into_chat_submodule 2026-03-25 17:59:45 +00:00
dave d7bc785de1 storkit: accept 391_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_characters 2026-03-25 17:54:45 +00:00
dave eaac665a9f storkit: accept 389_story_whatsapp_phone_number_allowlist_authorization 2026-03-25 17:39:44 +00:00
dave d702aa59c4 storkit: accept 387_story_configurable_base_branch_name_in_project_toml 2026-03-25 17:30:43 +00:00
dave 9df9a1454a storkit: create 396_story_whatsapp_bot_startup_announcement_after_restart 2026-03-25 15:52:39 +00:00
dave 47163d235c storkit: done 390_bug_whatsapp_missing_async_command_handlers_for_start_rebuild_reset_rmtree_assign 2026-03-25 15:44:38 +00:00
dave a7342fc9d3 storkit: done 393_story_pipeline_stage_notifications_for_whatsapp_and_slack_transports 2026-03-25 15:37:57 +00:00
dave 5dd8feb75c storkit: merge 393_story_pipeline_stage_notifications_for_whatsapp_and_slack_transports 2026-03-25 15:37:54 +00:00
dave f5024b2648 storkit: done 394_story_whatsapp_and_slack_permission_prompt_forwarding 2026-03-25 15:34:54 +00:00
dave 6521c83eec storkit: merge 394_story_whatsapp_and_slack_permission_prompt_forwarding 2026-03-25 15:34:50 +00:00
dave 65e3643655 storkit: done 395_refactor_fix_npm_deprecated_module_warnings 2026-03-25 15:31:30 +00:00
dave fc95b57a78 storkit: merge 395_refactor_fix_npm_deprecated_module_warnings 2026-03-25 15:31:20 +00:00
dave 7c1a970b13 storkit: create 390_bug_whatsapp_missing_async_command_handlers_for_start_rebuild_reset_rmtree_assign 2026-03-25 15:21:39 +00:00
dave 64e2df20b7 storkit: create 390_bug_whatsapp_missing_async_command_handlers_for_start_rebuild_reset_rmtree_assign 2026-03-25 15:21:32 +00:00
dave 90e3612fd3 storkit: create 395_refactor_fix_npm_deprecated_module_warnings 2026-03-25 15:17:02 +00:00
dave 962bfe37c6 storkit: create 394_story_whatsapp_and_slack_permission_prompt_forwarding 2026-03-25 15:02:00 +00:00
dave f05c6a42b0 storkit: done 392_refactor_extract_shared_transport_utilities_from_matrix_module_into_chat_submodule 2026-03-25 14:46:06 +00:00
dave 077288e7b7 storkit: merge 392_refactor_extract_shared_transport_utilities_from_matrix_module_into_chat_submodule 2026-03-25 14:46:02 +00:00
dave 580ab1ce68 storkit: create 393_story_pipeline_stage_notifications_for_whatsapp_and_slack_transports 2026-03-25 14:35:32 +00:00
Timmy 71a6c72614 Adding in a holding page for a website 2026-03-25 14:27:06 +00:00
dave fae7b3be20 storkit: create 388_story_whatsapp_webhook_hmac_signature_verification 2026-03-25 14:08:00 +00:00
dave 775b9ac7e3 storkit: create 388_story_whatsapp_webhook_hmac_signature_verification 2026-03-25 14:07:37 +00:00
dave 5a87d55dd4 storkit: done 391_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_characters 2026-03-25 14:05:03 +00:00
dave 0457fbfecc storkit: merge 391_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_characters 2026-03-25 14:04:59 +00:00
dave 13b16138b5 storkit: create 392_refactor_extract_shared_transport_utilities_from_matrix_module_into_chat_submodule 2026-03-25 13:59:02 +00:00
dave 8249896449 storkit: create 392_refactor_extract_shared_transport_utilities_from_matrix_module_into_chat_submodule 2026-03-25 13:58:06 +00:00
dave dbd932bf46 storkit: create 392_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_characters 2026-03-25 13:55:49 +00:00
dave eef49678ce storkit: create 391_bug_strip_prefix_ci_panics_on_multi_byte_utf_8_characters 2026-03-25 13:54:13 +00:00
dave 58ee82c988 storkit: done 390_bug_whatsapp_missing_async_command_handlers_for_start_rebuild_reset_rmtree_assign 2026-03-25 13:47:24 +00:00
dave 49ac23044a storkit: done 389_story_whatsapp_phone_number_allowlist_authorization 2026-03-25 13:42:35 +00:00
dave 84a775be77 storkit: merge 389_story_whatsapp_phone_number_allowlist_authorization 2026-03-25 13:42:31 +00:00
dave 60c0c95f38 storkit: done 387_story_configurable_base_branch_name_in_project_toml 2026-03-25 13:33:45 +00:00
dave a1a30bcc42 storkit: merge 387_story_configurable_base_branch_name_in_project_toml 2026-03-25 13:33:38 +00:00
dave 96ebd7ecb8 storkit: create 390_bug_whatsapp_missing_async_command_handlers_for_start_rebuild_reset_rmtree_assign 2026-03-25 13:22:16 +00:00
dave 25c8b1ec25 storkit: accept 386_story_unreleased_command_shows_list_of_stories_since_last_release 2026-03-25 02:13:11 +00:00
dave bcb7cfabee storkit: accept 385_story_slack_markdown_to_mrkdwn_formatting_conversion 2026-03-25 02:02:10 +00:00
dave d4dad1d556 storkit: accept 384_story_whatsapp_markdown_to_whatsapp_formatting_conversion 2026-03-25 01:34:08 +00:00
dave 195c7c51c4 storkit: create 389_story_whatsapp_phone_number_allowlist_authorization 2026-03-24 22:25:59 +00:00
dave 968d973cff storkit: create 388_story_whatsapp_webhook_hmac_signature_verification 2026-03-24 22:25:55 +00:00
dave 4394ab3fed storkit: done 386_story_unreleased_command_shows_list_of_stories_since_last_release 2026-03-24 22:23:05 +00:00
dave 11bbfca3da storkit: merge 386_story_unreleased_command_shows_list_of_stories_since_last_release 2026-03-24 22:23:01 +00:00
dave a9aa88b655 storkit: create 387_story_configurable_base_branch_name_in_project_toml 2026-03-24 22:20:49 +00:00
dave b62974dd88 storkit: create 387_story_configurable_base_branch_name_in_project_toml 2026-03-24 22:17:46 +00:00
dave ac52a8bb4e storkit: done 385_story_slack_markdown_to_mrkdwn_formatting_conversion 2026-03-24 22:12:39 +00:00
dave 18755aac96 storkit: merge 385_story_slack_markdown_to_mrkdwn_formatting_conversion 2026-03-24 22:12:31 +00:00
dave 5d37421f70 storkit: create 386_story_unreleased_command_shows_list_of_stories_since_last_release 2026-03-24 22:12:16 +00:00
dave 224d269971 storkit: create 385_story_slack_markdown_to_mrkdwn_formatting_conversion 2026-03-24 22:01:58 +00:00
dave 6146a173f1 storkit: done 384_story_whatsapp_markdown_to_whatsapp_formatting_conversion 2026-03-24 21:54:19 +00:00
dave 821345d266 storkit: accept 383_refactor_reorganize_chat_system_into_chat_module_with_transport_submodules 2026-03-24 21:41:42 +00:00
dave 0fa63e2de3 storkit: accept 382_story_whatsapp_transport_supports_twilio_api_as_alternative_to_meta_cloud_api 2026-03-24 21:33:45 +00:00
dave d8cbec8268 storkit: create 384_story_whatsapp_markdown_to_whatsapp_formatting_conversion 2026-03-24 21:33:44 +00:00
Timmy 618a2779ff Bump version to 0.6.0 2026-03-24 21:27:38 +00:00
Timmy 721d12bcfe Fixing code warnings 2026-03-24 21:26:48 +00:00
Timmy df6d2db327 Upgrading toml and pulldown-cmark 2026-03-24 21:25:15 +00:00
Timmy 49285c1865 Binding promiscuously in Docker to make things happen 2026-03-24 21:24:57 +00:00
Timmy 0c15be43b8 Ignoring whatsapp history 2026-03-24 21:24:38 +00:00
Timmy 9408bd2cdf Bump version to 0.6.0 2026-03-24 21:06:15 +00:00
Timmy a24e4c5c85 Making Matrix config fields optional to meet Twilio login needs 2026-03-24 21:05:35 +00:00
Timmy c0133fe733 Ignoring backed up bot creds 2026-03-24 20:56:59 +00:00
dave 752c3904bf storkit: accept 380_story_assign_command_restarts_coder_when_story_is_already_in_progress 2026-03-24 19:02:42 +00:00
dave bac53ac09a storkit: accept 381_story_bot_command_to_delete_a_worktree 2026-03-24 18:49:41 +00:00
dave b2ef2eca5f storkit: accept 368_story_web_ui_oauth_flow_for_claude_authentication 2026-03-24 18:48:40 +00:00
dave fb05f71e76 storkit: accept 379_bug_start_agent_ignores_story_front_matter_agent_assignment 2026-03-24 18:44:36 +00:00
dave 438be196c9 feat: scaffold creates per-transport bot.toml example files
New projects now get bot.toml.matrix.example, bot.toml.whatsapp-meta.example,
bot.toml.whatsapp-twilio.example, and bot.toml.slack.example in .storkit/
during scaffolding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:13:32 +00:00
dave f1b4894d6e docs: split bot.toml.example into per-transport example files
Replace the monolithic bot.toml.example with separate files for each
transport: matrix, whatsapp-meta, whatsapp-twilio, and slack. Add a
chat bot configuration section to the README explaining that only one
transport can be active at a time and how to set up each one.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:10:37 +00:00
dave bd281fd749 storkit: done 383_refactor_reorganize_chat_system_into_chat_module_with_transport_submodules 2026-03-24 17:57:24 +00:00
dave 79edc28334 storkit: merge 383_refactor_reorganize_chat_system_into_chat_module_with_transport_submodules 2026-03-24 17:57:21 +00:00
dave 92c53704f0 storkit: create 383_refactor_reorganize_chat_system_into_chat_module_with_transport_submodules 2026-03-24 17:40:36 +00:00
dave 7223fa2f10 storkit: done 382_story_whatsapp_transport_supports_twilio_api_as_alternative_to_meta_cloud_api 2026-03-24 17:36:35 +00:00
dave dedf951b17 storkit: merge 382_story_whatsapp_transport_supports_twilio_api_as_alternative_to_meta_cloud_api 2026-03-24 17:36:32 +00:00
dave aad583defd storkit: create 382_story_whatsapp_transport_supports_twilio_api_as_alternative_to_meta_cloud_api 2026-03-24 16:41:13 +00:00
dave 88b02cf746 storkit: done 380_story_assign_command_restarts_coder_when_story_is_already_in_progress 2026-03-24 15:05:55 +00:00
dave 1a9833d820 storkit: merge 380_story_assign_command_restarts_coder_when_story_is_already_in_progress 2026-03-24 15:05:52 +00:00
dave a904cda629 storkit: done 381_story_bot_command_to_delete_a_worktree 2026-03-24 15:02:54 +00:00
dave c755c03f0e storkit: merge 381_story_bot_command_to_delete_a_worktree 2026-03-24 15:02:50 +00:00
dave a8630f3e1b storkit: done 379_bug_start_agent_ignores_story_front_matter_agent_assignment 2026-03-24 14:59:32 +00:00
dave 9fb1bd5711 storkit: merge 379_bug_start_agent_ignores_story_front_matter_agent_assignment 2026-03-24 14:59:28 +00:00
dave 0b3ce0f33e storkit: done 368_story_web_ui_oauth_flow_for_claude_authentication 2026-03-24 14:54:30 +00:00
dave f4b7573f0a storkit: create 381_story_bot_command_to_delete_a_worktree 2026-03-24 14:49:24 +00:00
dave bb801ba826 storkit: create 380_story_assign_command_restarts_coder_when_story_is_already_in_progress 2026-03-24 14:49:21 +00:00
dave 53634d638d storkit: create 379_bug_start_agent_ignores_story_front_matter_agent_assignment 2026-03-24 14:44:30 +00:00
dave b50e7cff00 storkit: create 368_story_web_ui_oauth_flow_for_claude_authentication 2026-03-24 14:40:50 +00:00
dave 68973b0bb8 storkit: create 368_story_web_ui_oauth_flow_for_claude_authentication 2026-03-24 13:36:24 +00:00
dave 34bbf5a122 storkit: accept 376_story_rename_mcp_whatsup_tool_to_status_for_consistency 2026-03-24 13:35:35 +00:00
dave ed3c5f9c95 storkit: accept 376_story_rename_mcp_whatsup_tool_to_status_for_consistency 2026-03-24 11:10:25 +00:00
dave 59d1a2c069 storkit: done 376_story_rename_mcp_whatsup_tool_to_status_for_consistency 2026-03-24 11:09:21 +00:00
dave 52e73bfbea storkit: merge 376_story_rename_mcp_whatsup_tool_to_status_for_consistency 2026-03-24 11:09:17 +00:00
Timmy 4e590401a5 Bump version to 0.5.1 2026-03-24 10:55:06 +00:00
dave 6b6815325d storkit: accept 378_story_status_command_shows_work_item_type_story_bug_spike_refactor_next_to_each_item 2026-03-23 22:33:10 +00:00
dave f874783b09 storkit: accept 377_bug_update_story_mcp_tool_writes_front_matter_values_as_yaml_strings_instead_of_native_types 2026-03-23 22:26:09 +00:00
dave 292f9cdfe2 storkit: accept 375_bug_default_project_toml_contains_rust_specific_setup_commands_for_non_rust_projects 2026-03-23 22:24:09 +00:00
dave 1cce46d3fa chore: bump version to 0.5.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 18:49:54 +00:00
dave e85c06df19 storkit: done 377_bug_update_story_mcp_tool_writes_front_matter_values_as_yaml_strings_instead_of_native_types 2026-03-23 18:45:40 +00:00
dave 8b85ca743e storkit: merge 377_bug_update_story_mcp_tool_writes_front_matter_values_as_yaml_strings_instead_of_native_types 2026-03-23 18:45:37 +00:00
dave 1a7b6c7342 storkit: done 378_story_status_command_shows_work_item_type_story_bug_spike_refactor_next_to_each_item 2026-03-23 18:42:53 +00:00
dave 4a94158ef2 storkit: merge 378_story_status_command_shows_work_item_type_story_bug_spike_refactor_next_to_each_item 2026-03-23 18:42:49 +00:00
dave f10ea1ecf2 storkit: done 374_story_web_ui_implements_all_bot_commands_as_slash_commands 2026-03-23 18:35:56 +00:00
dave 1a3b69301a storkit: merge 374_story_web_ui_implements_all_bot_commands_as_slash_commands 2026-03-23 18:35:52 +00:00
dave 6d3eab92fd storkit: create 378_story_status_command_shows_work_item_type_story_bug_spike_refactor_next_to_each_item 2026-03-23 18:32:14 +00:00
dave f6920a87ad storkit: merge 375_bug_default_project_toml_contains_rust_specific_setup_commands_for_non_rust_projects 2026-03-23 18:32:05 +00:00
dave 5f9d903987 storkit: done 375_bug_default_project_toml_contains_rust_specific_setup_commands_for_non_rust_projects 2026-03-23 18:30:18 +00:00
dave ea916d27f4 storkit: create 377_bug_update_story_mcp_tool_writes_front_matter_values_as_yaml_strings_instead_of_native_types 2026-03-23 18:25:53 +00:00
dave 970b9bcd9d storkit: accept 373_bug_scaffold_gitignore_missing_transient_pipeline_stage_directories 2026-03-23 18:12:45 +00:00
dave a5ee6890f5 storkit: create 376_story_rename_mcp_whatsup_tool_to_status_for_consistency 2026-03-23 17:58:23 +00:00
dave 41dc3292bb storkit: accept 371_bug_no_arg_storkit_in_empty_directory_skips_scaffold 2026-03-23 17:56:56 +00:00
dave 3766f8b464 storkit: accept 370_bug_scaffold_does_not_create_mcp_json_in_project_root 2026-03-23 16:57:28 +00:00
dave 0c85ecc85c storkit: accept 369_bug_cli_treats_help_and_version_as_project_paths 2026-03-23 16:43:27 +00:00
dave 2c29a4d2b8 storkit: create 375_bug_default_project_toml_contains_rust_specific_setup_commands_for_non_rust_projects 2026-03-23 14:29:25 +00:00
dave 454d694d24 storkit: done 372_story_scaffold_auto_detects_tech_stack_and_configures_script_test 2026-03-23 14:25:58 +00:00
dave 96bedd70dc storkit: merge 372_story_scaffold_auto_detects_tech_stack_and_configures_script_test 2026-03-23 14:25:54 +00:00
dave fffdd5c5ea storkit: create 374_story_web_ui_implements_all_bot_commands_as_slash_commands 2026-03-23 14:22:11 +00:00
dave 4805598932 storkit: done 373_bug_scaffold_gitignore_missing_transient_pipeline_stage_directories 2026-03-23 14:15:36 +00:00
dave 3d55e2fcc6 Add transient pipeline stages to scaffold .gitignore
work/2_current/, work/3_qa/, work/4_merge/ are not committed to git
(only 1_backlog, 5_done, 6_archived are). New projects were missing
these entries in .storkit/.gitignore.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 14:13:15 +00:00
dave 96b31d1a48 storkit: create 372_story_scaffold_auto_detects_tech_stack_and_configures_script_test 2026-03-23 14:12:37 +00:00
dave 11168fa426 storkit: create 373_bug_scaffold_gitignore_missing_transient_pipeline_stage_directories 2026-03-23 14:12:03 +00:00
dave c2c2d65889 storkit: done 371_bug_no_arg_storkit_in_empty_directory_skips_scaffold 2026-03-23 14:08:46 +00:00
dave 5c8c4b7ff3 storkit: merge 371_bug_no_arg_storkit_in_empty_directory_skips_scaffold 2026-03-23 14:08:43 +00:00
dave fbab93f493 storkit: create 372_story_scaffold_auto_detects_tech_stack_and_configures_script_test 2026-03-23 14:08:16 +00:00
dave 78ff6d104e storkit: create 371_bug_no_arg_storkit_in_empty_directory_skips_scaffold 2026-03-23 13:56:02 +00:00
661 changed files with 37721 additions and 24488 deletions
+9 -6
View File
@@ -1,10 +1,12 @@
{ {
"enabledMcpjsonServers": ["storkit"], "enabledMcpjsonServers": [
"huskies"
],
"permissions": { "permissions": {
"allow": [ "allow": [
"Bash(./server/target/debug/storkit:*)", "Bash(./server/target/debug/huskies:*)",
"Bash(./target/debug/storkit:*)", "Bash(./target/debug/huskies:*)",
"Bash(STORKIT_PORT=*)", "Bash(HUSKIES_PORT=*)",
"Bash(cargo build:*)", "Bash(cargo build:*)",
"Bash(cargo check:*)", "Bash(cargo check:*)",
"Bash(cargo clippy:*)", "Bash(cargo clippy:*)",
@@ -54,7 +56,7 @@
"WebFetch(domain:portkey.ai)", "WebFetch(domain:portkey.ai)",
"WebFetch(domain:www.shuttle.dev)", "WebFetch(domain:www.shuttle.dev)",
"WebSearch", "WebSearch",
"mcp__storkit__*", "mcp__huskies__*",
"Edit", "Edit",
"Write", "Write",
"Bash(find *)", "Bash(find *)",
@@ -67,7 +69,8 @@
"Bash(tail *)", "Bash(tail *)",
"Bash(wc *)", "Bash(wc *)",
"Bash(npx vite:*)", "Bash(npx vite:*)",
"Bash(npm run dev:*)" "Bash(npm run dev:*)",
"Bash(stat *)"
] ]
} }
} }
+3 -3
View File
@@ -2,9 +2,9 @@
**/target/ **/target/
**/node_modules/ **/node_modules/
frontend/dist/ frontend/dist/
.storkit/worktrees/ .huskies/worktrees/
.storkit/logs/ .huskies/logs/
.storkit/work/6_archived/ .huskies/work/6_archived/
.git/ .git/
*.swp *.swp
*.swo *.swo
+7 -2
View File
@@ -5,9 +5,10 @@
# Local environment (secrets) # Local environment (secrets)
.env .env
# App specific (root-level; storkit subdirectory patterns live in .storkit/.gitignore) # App specific (root-level; huskies subdirectory patterns live in .huskies/.gitignore)
store.json store.json
.storkit_port .huskies_port
.huskies/bot.toml.bak
# Rust stuff # Rust stuff
target target
@@ -44,3 +45,7 @@ server/target
*.sln *.sln
*.sw? *.sw?
/test-results/.last-run.json /test-results/.last-run.json
# Ignore old story files until we feel like deleting them
.storkit
.storkit_port
@@ -20,3 +20,9 @@ coverage/
# Token usage log (generated at runtime, contains cost data) # Token usage log (generated at runtime, contains cost data)
token_usage.jsonl token_usage.jsonl
# Chat service logs
whatsapp_history.json
# Timers
timers.json
+34 -6
View File
@@ -9,16 +9,22 @@
When you start a new session with this project: When you start a new session with this project:
1. **Check for MCP Tools:** Read `.mcp.json` to discover the MCP server endpoint. Then list available tools by calling: 1. **Check Setup Wizard:** Call `wizard_status` to check if project setup is complete. If the wizard is not complete, guide the user through the remaining steps. Important rules for the wizard flow:
- **Be conversational.** Don't show tool names, step numbers, or raw wizard output to the user.
- **On projects with existing code:** Read the codebase and generate each file, then show the user what you wrote and ask if it looks right.
- **On bare projects with no code:** Ask the user what they want to build, what language/framework they plan to use, and generate files from their answers.
- **You must actually generate the files.** The workflow for each step is: (1) call `wizard_generate` with no args to get a hint, (2) write the file content yourself based on the conversation, (3) call `wizard_generate` again with the `content` argument containing the full file body, (4) show the user what you wrote, (5) call `wizard_confirm` (they approve), `wizard_retry` (they want changes), or `wizard_skip` (they want to skip). Do not stop after discussing — follow through and write the files.
- **Keep moving.** After each step is confirmed, immediately proceed to the next wizard step without waiting for the user to ask.
2. **Check for MCP Tools:** Read `.mcp.json` to discover the MCP server endpoint. Then list available tools by calling:
```bash ```bash
curl -s "$(jq -r '.mcpServers["storkit"].url' .mcp.json)" \ curl -s "$(jq -r '.mcpServers["huskies"].url' .mcp.json)" \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
``` ```
This returns the full tool catalog (create stories, spawn agents, record tests, manage worktrees, etc.). Familiarize yourself with the available tools before proceeding. These tools allow you to directly manipulate the workflow and spawn subsidiary agents without manual file manipulation. This returns the full tool catalog (create stories, spawn agents, record tests, manage worktrees, etc.). Familiarize yourself with the available tools before proceeding. These tools allow you to directly manipulate the workflow and spawn subsidiary agents without manual file manipulation.
2. **Read Context:** Check `.story_kit/specs/00_CONTEXT.md` for high-level project goals. 3. **Read Context:** Check `.huskies/specs/00_CONTEXT.md` for high-level project goals.
3. **Read Stack:** Check `.story_kit/specs/tech/STACK.md` for technical constraints and patterns. 4. **Read Stack:** Check `.huskies/specs/tech/STACK.md` for technical constraints and patterns.
4. **Check Work Items:** Look at `.story_kit/work/1_backlog/` and `.story_kit/work/2_current/` to see what work is pending. 5. **Check Work Items:** Look at `.huskies/work/1_backlog/` and `.huskies/work/2_current/` to see what work is pending.
--- ---
@@ -228,7 +234,29 @@ If a user hands you this document and says "Apply this process to my project":
--- ---
## 6. Code Quality ## 6. Chat Bot Configuration
Story Kit includes a chat bot that can be connected to one messaging platform at a time. The bot handles commands, LLM conversations, and pipeline notifications.
**Only one transport can be active at a time.** To configure the bot, copy the appropriate example file to `.huskies/bot.toml`:
| Transport | Example file | Webhook endpoint |
|-----------|-------------|-----------------|
| Matrix | `bot.toml.matrix.example` | *(uses Matrix sync, no webhook)* |
| WhatsApp (Meta Cloud API) | `bot.toml.whatsapp-meta.example` | `/webhook/whatsapp` |
| WhatsApp (Twilio) | `bot.toml.whatsapp-twilio.example` | `/webhook/whatsapp` |
| Slack | `bot.toml.slack.example` | `/webhook/slack` |
```bash
cp .huskies/bot.toml.matrix.example .huskies/bot.toml
# Edit bot.toml with your credentials
```
The `bot.toml` file is gitignored (it contains secrets). The example files are checked in for reference.
---
## 7. Code Quality
**MANDATORY:** Before completing Step 3 (Verification) of any story, you MUST run all applicable linters, formatters, and test suites and fix ALL errors and warnings. Zero tolerance for warnings or errors. **MANDATORY:** Before completing Step 3 (Verification) of any story, you MUST run all applicable linters, formatters, and test suites and fix ALL errors and warnings. Zero tolerance for warnings or errors.
+26
View File
@@ -0,0 +1,26 @@
# Matrix Transport
# Copy this file to bot.toml and fill in your values.
# Only one transport can be active at a time.
enabled = true
transport = "matrix"
homeserver = "https://matrix.example.com"
username = "@botname:example.com"
password = "your-bot-password"
# List one or more rooms to listen in.
room_ids = ["!roomid:example.com"]
# Users allowed to interact with the bot (fail-closed: empty = nobody).
allowed_users = ["@youruser:example.com"]
# Bot display name in chat.
# display_name = "Assistant"
# Maximum conversation turns to remember per room (default: 20).
# history_size = 20
# Rooms where the bot responds to all messages (not just addressed ones).
# This list is updated automatically when users toggle ambient mode at runtime.
# ambient_rooms = ["!roomid:example.com"]
+23
View File
@@ -0,0 +1,23 @@
# Slack Transport
# Copy this file to bot.toml and fill in your values.
# Only one transport can be active at a time.
#
# Setup:
# 1. Create a Slack App at api.slack.com/apps
# 2. Add OAuth scopes: chat:write, chat:update
# 3. Subscribe to bot events: message.channels, message.groups, message.im
# 4. Install the app to your workspace
# 5. Set your webhook URL in Event Subscriptions: https://your-server/webhook/slack
enabled = true
transport = "slack"
slack_bot_token = "xoxb-..."
slack_signing_secret = "your-signing-secret"
slack_channel_ids = ["C01ABCDEF"]
# Bot display name (used in formatted messages).
# display_name = "Assistant"
# Maximum conversation turns to remember per channel (default: 20).
# history_size = 20
+33
View File
@@ -0,0 +1,33 @@
# WhatsApp Transport (Meta Cloud API)
# Copy this file to bot.toml and fill in your values.
# Only one transport can be active at a time.
#
# Setup:
# 1. Create a Meta Business App at developers.facebook.com
# 2. Add the WhatsApp product
# 3. Copy your Phone Number ID and generate a permanent access token
# 4. Register your webhook URL: https://your-server/webhook/whatsapp
# 5. Set the verify token below to match what you configure in Meta's dashboard
enabled = true
transport = "whatsapp"
whatsapp_provider = "meta"
whatsapp_phone_number_id = "123456789012345"
whatsapp_access_token = "EAAx..."
whatsapp_verify_token = "my-secret-verify-token"
# Optional: name of the approved Meta message template used for notifications
# sent outside the 24-hour messaging window (default: "pipeline_notification").
# whatsapp_notification_template = "pipeline_notification"
# Bot display name (used in formatted messages).
# display_name = "Assistant"
# Maximum conversation turns to remember per user (default: 20).
# history_size = 20
# Optional: restrict which phone numbers can interact with the bot.
# When set, only listed numbers are processed; all others are silently ignored.
# When absent or empty, all numbers are allowed (open by default).
# whatsapp_allowed_phones = ["+15551234567", "+15559876543"]
+29
View File
@@ -0,0 +1,29 @@
# WhatsApp Transport (Twilio)
# Copy this file to bot.toml and fill in your values.
# Only one transport can be active at a time.
#
# Setup:
# 1. Sign up at twilio.com
# 2. Activate the WhatsApp sandbox (Messaging > Try it out > Send a WhatsApp message)
# 3. Send the sandbox join code from your WhatsApp to the sandbox number
# 4. Copy your Account SID, Auth Token, and sandbox number below
# 5. Set your webhook URL in the Twilio console: https://your-server/webhook/whatsapp
enabled = true
transport = "whatsapp"
whatsapp_provider = "twilio"
twilio_account_sid = "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
twilio_auth_token = "your_auth_token"
twilio_whatsapp_number = "+14155238886"
# Bot display name (used in formatted messages).
# display_name = "Assistant"
# Maximum conversation turns to remember per user (default: 20).
# history_size = 20
# Optional: restrict which phone numbers can interact with the bot.
# When set, only listed numbers are processed; all others are silently ignored.
# When absent or empty, all numbers are allowed (open by default).
# whatsapp_allowed_phones = ["+15551234567", "+15559876543"]
+123 -52
View File
@@ -11,12 +11,17 @@ max_coders = 3
# Maximum retries per story per pipeline stage before marking as blocked. # Maximum retries per story per pipeline stage before marking as blocked.
# Set to 0 to disable retry limits. # Set to 0 to disable retry limits.
max_retries = 2 max_retries = 3
# Base branch name for this project. Worktree creation, merges, and agent prompts
# use this value for {{base_branch}}. When not set, falls back to auto-detection
# (reads current HEAD branch).
base_branch = "master"
[[component]] [[component]]
name = "frontend" name = "frontend"
path = "frontend" path = "frontend"
setup = ["npm install", "npm run build"] setup = ["npm ci", "npm run build"]
teardown = [] teardown = []
[[component]] [[component]]
@@ -58,40 +63,62 @@ system_prompt = "You are a full-stack engineer working autonomously in a git wor
[[agent]] [[agent]]
name = "qa-2" name = "qa-2"
stage = "qa" stage = "qa"
role = "Reviews coder work in worktrees: runs quality gates, generates testing plans, and reports findings." role = "Reviews coder work in worktrees: runs quality gates, verifies acceptance criteria, and reports findings."
model = "sonnet" model = "sonnet"
max_turns = 40 max_turns = 40
max_budget_usd = 4.00 max_budget_usd = 4.00
prompt = """You are the QA agent for story {{story_id}}. Your job is to review the coder's work in the worktree and produce a structured QA report. prompt = """You are the QA agent for story {{story_id}}. Your job is to verify the coder's work satisfies the story's acceptance criteria and produce a structured QA report.
Read CLAUDE.md first, then .story_kit/README.md to understand the dev process. Read CLAUDE.md first, then .story_kit/README.md to understand the dev process.
## Your Workflow ## Your Workflow
### 1. Code Quality Scan ### 0. Read the Story
- Run `git diff master...HEAD --stat` to see what files changed - Read the story file at `.huskies/work/3_qa/{{story_id}}.md`
- Run `git diff master...HEAD` to review the actual changes for obvious coding mistakes (unused imports, dead code, unhandled errors, hardcoded values) - Extract every acceptance criterion (the `- [ ]` checkbox lines)
- Run `cargo clippy --all-targets --all-features` and note any warnings - Keep this list in mind for Step 3
### 1. Deterministic Gates (Prerequisites)
Run these first if any fail, reject immediately without proceeding to AC review:
- Run `cargo clippy --all-targets --all-features` must show 0 errors, 0 warnings
- Run `cargo test` and verify all tests pass
- If a `frontend/` directory exists: - If a `frontend/` directory exists:
- Run `npm run build` and note any TypeScript errors - Run `npm run build` and note any TypeScript errors
- Run `npx @biomejs/biome check src/` and note any linting issues - Run `npx @biomejs/biome check src/` and note any linting issues
- Run `npm test` and verify all frontend tests pass
### 2. Test Verification ### 2. Code Change Review
- Run `cargo test` and verify all tests pass - Run `git diff master...HEAD --stat` to see what files changed
- If `frontend/` exists: run `npm test` and verify all frontend tests pass - Run `git diff master...HEAD` to review the actual changes
- Review test quality: look for tests that are trivial or don't assert meaningful behavior - Flag any incomplete implementations:
- `todo!()`, `unimplemented!()`, `panic!()` used as stubs
- Placeholder strings like "TODO", "FIXME", "not implemented"
- Empty match arms or arms that just return `Default::default()`
- Hardcoded values where real logic is expected
- Note any obvious coding mistakes (unused imports, dead code, unhandled errors)
### 3. Manual Testing Support ### 3. Acceptance Criteria Review
For each AC extracted in Step 0:
- Review the diff and test files to determine if the code addresses this AC
- PASS: describe specifically how the code addresses it (which file/function/test)
- FAIL: explain exactly what is missing or incorrect
An AC fails if:
- No code change or test relates to it
- The implementation is stubbed out (todo!/unimplemented!)
- A test exists but doesn't actually assert the behaviour described
### 4. Manual Testing Support (only if all gates PASS and all ACs PASS)
- Build the server: run `cargo build` and note success/failure - Build the server: run `cargo build` and note success/failure
- If build succeeds: find a free port (try 3010-3020) and attempt to start the server - If build succeeds: find a free port (try 3010-3020) and attempt to start the server
- Generate a testing plan including: - Generate a testing plan including:
- URL to visit in the browser - URL to visit in the browser
- Things to check in the UI - Things to check in the UI
- curl commands to exercise relevant API endpoints - curl commands to exercise relevant API endpoints
- Kill the test server when done: `pkill -f 'target.*storkit' || true` (NEVER use `pkill -f storkit` it kills the vite dev server) - Kill the test server when done: `pkill -f 'target.*huskies' || true` (NEVER use `pkill -f huskies` it kills the vite dev server)
### 4. Produce Structured Report ### 5. Produce Structured Report and Verdict
Print your QA report to stdout before your process exits. The server will automatically run acceptance gates. Use this format: Print your QA report to stdout. Then call `approve_qa` or `reject_qa` via the MCP tool based on the overall result. Use this format:
``` ```
## QA Report for {{story_id}} ## QA Report for {{story_id}}
@@ -100,27 +127,38 @@ Print your QA report to stdout before your process exits. The server will automa
- clippy: PASS/FAIL (details) - clippy: PASS/FAIL (details)
- TypeScript build: PASS/FAIL/SKIP (details) - TypeScript build: PASS/FAIL/SKIP (details)
- Biome lint: PASS/FAIL/SKIP (details) - Biome lint: PASS/FAIL/SKIP (details)
- Code review findings: (list any issues found, or "None")
### Test Verification
- cargo test: PASS/FAIL (N tests) - cargo test: PASS/FAIL (N tests)
- npm test: PASS/FAIL/SKIP (N tests) - npm test: PASS/FAIL/SKIP (N tests)
- Test quality issues: (list any trivial/weak tests, or "None") - Incomplete implementations: (list any todo!/unimplemented!/stubs found, or "None")
- Other code review findings: (list any issues found, or "None")
### Acceptance Criteria Review
- AC: <criterion text>
Result: PASS/FAIL
Evidence: <how the code addresses it, or what is missing>
(repeat for each AC)
### Manual Testing Plan ### Manual Testing Plan
- Server URL: http://localhost:PORT (or "Build failed") - Server URL: http://localhost:PORT (or "Skipped — gate/AC failure" or "Build failed")
- Pages to visit: (list) - Pages to visit: (list, or "N/A")
- Things to check: (list) - Things to check: (list, or "N/A")
- curl commands: (list) - curl commands: (list, or "N/A")
### Overall: PASS/FAIL ### Overall: PASS/FAIL
Reason: (summary of why it passed or the primary reason it failed)
``` ```
After printing the report:
- If Overall is PASS: call `approve_qa(story_id='{{story_id}}')` via MCP
- If Overall is FAIL: call `reject_qa(story_id='{{story_id}}', notes='<concise reason>')` via MCP so the coder knows exactly what to fix
## Rules ## Rules
- Do NOT modify any code read-only review only - Do NOT modify any code read-only review only
- If the server fails to start, still provide the testing plan with curl commands - Gates must pass before AC review a gate failure is an automatic reject
- The server automatically runs acceptance gates when your process exits""" - If any AC is not met, the overall result is FAIL
system_prompt = "You are a QA agent. Your job is read-only: review code quality, run tests, try to start the server, and produce a structured QA report. Do not modify code. The server automatically runs acceptance gates when your process exits." - Always call approve_qa or reject_qa never leave the story without a verdict"""
system_prompt = "You are a QA agent. Your job is read-only: run quality gates, verify each acceptance criterion against the diff, and produce a structured QA report. Always call approve_qa or reject_qa via MCP to record your verdict. Do not modify code."
[[agent]] [[agent]]
name = "coder-opus" name = "coder-opus"
@@ -135,40 +173,62 @@ system_prompt = "You are a senior full-stack engineer working autonomously in a
[[agent]] [[agent]]
name = "qa" name = "qa"
stage = "qa" stage = "qa"
role = "Reviews coder work in worktrees: runs quality gates, generates testing plans, and reports findings." role = "Reviews coder work in worktrees: runs quality gates, verifies acceptance criteria, and reports findings."
model = "sonnet" model = "sonnet"
max_turns = 40 max_turns = 40
max_budget_usd = 4.00 max_budget_usd = 4.00
prompt = """You are the QA agent for story {{story_id}}. Your job is to review the coder's work in the worktree and produce a structured QA report. prompt = """You are the QA agent for story {{story_id}}. Your job is to verify the coder's work satisfies the story's acceptance criteria and produce a structured QA report.
Read CLAUDE.md first, then .story_kit/README.md to understand the dev process. Read CLAUDE.md first, then .story_kit/README.md to understand the dev process.
## Your Workflow ## Your Workflow
### 1. Code Quality Scan ### 0. Read the Story
- Run `git diff master...HEAD --stat` to see what files changed - Read the story file at `.huskies/work/3_qa/{{story_id}}.md`
- Run `git diff master...HEAD` to review the actual changes for obvious coding mistakes (unused imports, dead code, unhandled errors, hardcoded values) - Extract every acceptance criterion (the `- [ ]` checkbox lines)
- Run `cargo clippy --all-targets --all-features` and note any warnings - Keep this list in mind for Step 3
### 1. Deterministic Gates (Prerequisites)
Run these first if any fail, reject immediately without proceeding to AC review:
- Run `cargo clippy --all-targets --all-features` must show 0 errors, 0 warnings
- Run `cargo test` and verify all tests pass
- If a `frontend/` directory exists: - If a `frontend/` directory exists:
- Run `npm run build` and note any TypeScript errors - Run `npm run build` and note any TypeScript errors
- Run `npx @biomejs/biome check src/` and note any linting issues - Run `npx @biomejs/biome check src/` and note any linting issues
- Run `npm test` and verify all frontend tests pass
### 2. Test Verification ### 2. Code Change Review
- Run `cargo test` and verify all tests pass - Run `git diff master...HEAD --stat` to see what files changed
- If `frontend/` exists: run `npm test` and verify all frontend tests pass - Run `git diff master...HEAD` to review the actual changes
- Review test quality: look for tests that are trivial or don't assert meaningful behavior - Flag any incomplete implementations:
- `todo!()`, `unimplemented!()`, `panic!()` used as stubs
- Placeholder strings like "TODO", "FIXME", "not implemented"
- Empty match arms or arms that just return `Default::default()`
- Hardcoded values where real logic is expected
- Note any obvious coding mistakes (unused imports, dead code, unhandled errors)
### 3. Manual Testing Support ### 3. Acceptance Criteria Review
For each AC extracted in Step 0:
- Review the diff and test files to determine if the code addresses this AC
- PASS: describe specifically how the code addresses it (which file/function/test)
- FAIL: explain exactly what is missing or incorrect
An AC fails if:
- No code change or test relates to it
- The implementation is stubbed out (todo!/unimplemented!)
- A test exists but doesn't actually assert the behaviour described
### 4. Manual Testing Support (only if all gates PASS and all ACs PASS)
- Build the server: run `cargo build` and note success/failure - Build the server: run `cargo build` and note success/failure
- If build succeeds: find a free port (try 3010-3020) and attempt to start the server - If build succeeds: find a free port (try 3010-3020) and attempt to start the server
- Generate a testing plan including: - Generate a testing plan including:
- URL to visit in the browser - URL to visit in the browser
- Things to check in the UI - Things to check in the UI
- curl commands to exercise relevant API endpoints - curl commands to exercise relevant API endpoints
- Kill the test server when done: `pkill -f 'target.*storkit' || true` (NEVER use `pkill -f storkit` it kills the vite dev server) - Kill the test server when done: `pkill -f 'target.*huskies' || true` (NEVER use `pkill -f huskies` it kills the vite dev server)
### 4. Produce Structured Report ### 5. Produce Structured Report and Verdict
Print your QA report to stdout before your process exits. The server will automatically run acceptance gates. Use this format: Print your QA report to stdout. Then call `approve_qa` or `reject_qa` via the MCP tool based on the overall result. Use this format:
``` ```
## QA Report for {{story_id}} ## QA Report for {{story_id}}
@@ -177,27 +237,38 @@ Print your QA report to stdout before your process exits. The server will automa
- clippy: PASS/FAIL (details) - clippy: PASS/FAIL (details)
- TypeScript build: PASS/FAIL/SKIP (details) - TypeScript build: PASS/FAIL/SKIP (details)
- Biome lint: PASS/FAIL/SKIP (details) - Biome lint: PASS/FAIL/SKIP (details)
- Code review findings: (list any issues found, or "None")
### Test Verification
- cargo test: PASS/FAIL (N tests) - cargo test: PASS/FAIL (N tests)
- npm test: PASS/FAIL/SKIP (N tests) - npm test: PASS/FAIL/SKIP (N tests)
- Test quality issues: (list any trivial/weak tests, or "None") - Incomplete implementations: (list any todo!/unimplemented!/stubs found, or "None")
- Other code review findings: (list any issues found, or "None")
### Acceptance Criteria Review
- AC: <criterion text>
Result: PASS/FAIL
Evidence: <how the code addresses it, or what is missing>
(repeat for each AC)
### Manual Testing Plan ### Manual Testing Plan
- Server URL: http://localhost:PORT (or "Build failed") - Server URL: http://localhost:PORT (or "Skipped — gate/AC failure" or "Build failed")
- Pages to visit: (list) - Pages to visit: (list, or "N/A")
- Things to check: (list) - Things to check: (list, or "N/A")
- curl commands: (list) - curl commands: (list, or "N/A")
### Overall: PASS/FAIL ### Overall: PASS/FAIL
Reason: (summary of why it passed or the primary reason it failed)
``` ```
After printing the report:
- If Overall is PASS: call `approve_qa(story_id='{{story_id}}')` via MCP
- If Overall is FAIL: call `reject_qa(story_id='{{story_id}}', notes='<concise reason>')` via MCP so the coder knows exactly what to fix
## Rules ## Rules
- Do NOT modify any code read-only review only - Do NOT modify any code read-only review only
- If the server fails to start, still provide the testing plan with curl commands - Gates must pass before AC review a gate failure is an automatic reject
- The server automatically runs acceptance gates when your process exits""" - If any AC is not met, the overall result is FAIL
system_prompt = "You are a QA agent. Your job is read-only: review code quality, run tests, try to start the server, and produce a structured QA report. Do not modify code. The server automatically runs acceptance gates when your process exits." - Always call approve_qa or reject_qa never leave the story without a verdict"""
system_prompt = "You are a QA agent. Your job is read-only: run quality gates, verify each acceptance criterion against the diff, and produce a structured QA report. Always call approve_qa or reject_qa via MCP to record your verdict. Do not modify code."
[[agent]] [[agent]]
name = "mergemaster" name = "mergemaster"
+43
View File
@@ -0,0 +1,43 @@
# Example project.toml — copy to .huskies/project.toml and customise.
# This file is checked in; project.toml itself is gitignored (it may contain
# instance-specific settings).
# Project-wide default QA mode: "server", "agent", or "human".
# Per-story `qa` front matter overrides this setting.
default_qa = "server"
# Default model for coder agents. Only agents with this model are auto-assigned.
# Opus coders are reserved for explicit per-story `agent:` front matter requests.
default_coder_model = "sonnet"
# Maximum concurrent coder agents. Stories wait in 2_current/ when all slots are full.
max_coders = 3
# Maximum retries per story per pipeline stage before marking as blocked.
# Set to 0 to disable retry limits.
max_retries = 2
# Base branch name for this project. Worktree creation, merges, and agent prompts
# use this value for {{base_branch}}. When not set, falls back to auto-detection
# (reads current HEAD branch).
base_branch = "main"
[[component]]
name = "server"
path = "."
setup = ["cargo build"]
teardown = []
[[agent]]
name = "coder-1"
role = "Full-stack engineer"
stage = "coder"
model = "sonnet"
max_turns = 50
max_budget_usd = 5.00
prompt = """
You are working in a git worktree on story {{story_id}}.
Read CLAUDE.md first, then .huskies/README.md to understand the dev process.
Run: cd "{{worktree_path}}" && git difftool {{base_branch}}...HEAD
Commit all your work before your process exits.
"""
@@ -6,7 +6,7 @@ Slack integration is configured via `bot.toml` in the project's `.story_kit/` di
```toml ```toml
transport = "slack" transport = "slack"
display_name = "Storkit" display_name = "Huskies"
slack_bot_token = "xoxb-..." slack_bot_token = "xoxb-..."
slack_signing_secret = "..." slack_signing_secret = "..."
slack_channel_ids = ["C01ABCDEF"] slack_channel_ids = ["C01ABCDEF"]
@@ -29,11 +29,11 @@ Slash commands provide quick access to pipeline commands without mentioning the
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `/storkit-status` | Show pipeline status and agent availability | | `/huskies-status` | Show pipeline status and agent availability |
| `/storkit-cost` | Show token spend: 24h total, top stories, and breakdown | | `/huskies-cost` | Show token spend: 24h total, top stories, and breakdown |
| `/storkit-show` | Display the full text of a work item (e.g. `/storkit-show 42`) | | `/huskies-show` | Display the full text of a work item (e.g. `/huskies-show 42`) |
| `/storkit-git` | Show git status: branch, changes, ahead/behind | | `/huskies-git` | Show git status: branch, changes, ahead/behind |
| `/storkit-htop` | Show system and agent process dashboard | | `/huskies-htop` | Show system and agent process dashboard |
All slash command responses are **ephemeral** — only the user who invoked the command sees the response. All slash command responses are **ephemeral** — only the user who invoked the command sees the response.
@@ -118,8 +118,8 @@ To support both Remote and Local models, the system implements a `ModelProvider`
Multiple instances can run simultaneously in different worktrees. To avoid port conflicts: Multiple instances can run simultaneously in different worktrees. To avoid port conflicts:
- **Backend:** Set `STORKIT_PORT` to a unique port (default is 3001). Example: `STORKIT_PORT=3002 cargo run` - **Backend:** Set `HUSKIES_PORT` to a unique port (default is 3001). Example: `HUSKIES_PORT=3002 cargo run`
- **Frontend:** Run `npm run dev` from `frontend/`. It auto-selects the next unused port. It reads `STORKIT_PORT` to know which backend to talk to, so export it before running: `export STORKIT_PORT=3002 && cd frontend && npm run dev` - **Frontend:** Run `npm run dev` from `frontend/`. It auto-selects the next unused port. It reads `HUSKIES_PORT` to know which backend to talk to, so export it before running: `export HUSKIES_PORT=3002 && cd frontend && npm run dev`
When running in a worktree, use a port that won't conflict with the main instance (3001). Ports 3002+ are good choices. When running in a worktree, use a port that won't conflict with the main instance (3001). Ports 3002+ are good choices.
@@ -0,0 +1,24 @@
---
name: "WhatsApp webhook HMAC signature verification"
retry_count: 3
blocked: true
---
# Story 388: WhatsApp webhook HMAC signature verification
## User Story
As a bot operator, I want incoming WhatsApp webhook requests to be cryptographically verified, so that forged requests from unauthorized sources are rejected.
## Acceptance Criteria
- [ ] Meta webhooks: validate X-Hub-Signature-256 HMAC-SHA256 header using the app secret before processing
- [ ] Twilio webhooks: validate request signature using the auth token before processing
- [ ] Requests with missing or invalid signatures are rejected with 403 Forbidden
- [ ] Verification is fail-closed: if signature checking is configured, unsigned requests are rejected
- [ ] Existing bot.toml config is extended with any needed secrets (e.g. Meta app_secret for HMAC verification)
- [ ] MUST use audited crypto crates (hmac, sha2, sha1, base64) — no hand-rolled cryptographic primitives
## Out of Scope
- TBD
@@ -0,0 +1,40 @@
---
name: "Fly.io Machines API integration for multi-tenant huskies SaaS"
---
# Spike 408: Fly.io Machines API integration for multi-tenant huskies SaaS
## Question
Can we build a working Rust integration that creates and manages per-tenant Fly.io Machines, attaches volumes, injects Claude credentials, and proxies JWT-authenticated HTTP/WebSocket traffic to the right machine?
## Hypothesis
A thin Rust service using `reqwest` for the Machines API and `axum` for the reverse proxy is sufficient. No heavyweight orchestration framework needed.
## Prerequisites
- Fly.io account with API token (set `FLY_API_TOKEN` env var)
- Spike 407 findings reviewed
## Timebox
4 hours
## Investigation Plan
- [ ] Create a minimal Rust crate in `spikes/fly_machines/` — do not touch production code
- [ ] Implement machine lifecycle: create, start, stop, destroy via Fly Machines REST API using `reqwest`
- [ ] Test attaching a persistent volume to a machine and verify it persists across stop/start
- [ ] Test secret injection — pass a dummy `credentials.json` as a Fly secret and verify it's readable inside the machine
- [ ] Sketch the auth proxy: JWT validation → machine lookup → reverse proxy to machine's private IP; verify WebSocket proxying works
- [ ] Measure actual cold start time for a minimal huskies container image
- [ ] Document any API quirks, rate limits, or sharp edges discovered during testing
## Findings
- TBD
## Recommendation
- TBD
@@ -0,0 +1,22 @@
---
name: "Multi-account OAuth token rotation on rate limit"
---
# Story 411: Multi-account OAuth token rotation on rate limit
## User Story
As a huskies user with multiple Claude Max subscriptions, I want the system to automatically rotate to a different account when one gets rate limited, so that agents and chat don't stall out waiting for limits to reset.
## Acceptance Criteria
- [ ] OAuth login flow stores credentials per-account (keyed by email), not overwriting previous accounts
- [ ] GET /oauth/status returns all stored accounts and their status (active, rate-limited, expired)
- [ ] When the active account hits a rate limit, huskies automatically swaps to the next available account's refresh token, refreshes, and retries
- [ ] The bot sends a notification in Matrix/WhatsApp when it swaps accounts
- [ ] If all accounts are rate limited, the bot surfaces a clear message with the time until the earliest reset
- [ ] A new /oauth/authorize login adds to the account pool rather than replacing the current credentials
## Out of Scope
- TBD
@@ -0,0 +1,24 @@
---
name: "Recheck bot command to re-run gates without restarting agent"
---
# Story 412: Recheck bot command to re-run gates without restarting agent
## User Story
As a user, I want to send `recheck <number>` to the bot so that it re-runs acceptance gates on an existing worktree without spawning a new agent, so I can unblock stories that failed due to environment issues without wasting agent turns.
## Acceptance Criteria
- [ ] recheck command is registered in chat/commands/mod.rs and appears in help output
- [ ] `recheck <number>` runs run_acceptance_gates on the story's existing worktree
- [ ] If gates pass, the story advances through the pipeline (same as if a coder completed successfully)
- [ ] If gates fail, the error output is returned to the user (not silently retried)
- [ ] If no worktree exists for the story, returns a clear error
- [ ] Does not spawn a new agent or increment retry_count
- [ ] Works from all transports (Matrix, WhatsApp, Slack)
- [ ] Works from web UI slash commands
## Out of Scope
- TBD
@@ -0,0 +1,21 @@
---
name: "Unblock command handles all stuck states not just blocked flag"
---
# Story 435: Unblock command handles all stuck states not just blocked flag
## User Story
As a project owner, I want the unblock command to clear any stuck state on a story — not just the blocked flag — so that I have a single command to unstick stories regardless of why they're stuck.
## Acceptance Criteria
- [ ] Unblock clears merge_failure field in addition to blocked flag
- [ ] Unblock clears review_hold field
- [ ] Unblock reports which fields were cleared in the confirmation message
- [ ] Unblock works on stories in any pipeline stage (backlog, current, qa, merge, done)
- [ ] If no stuck state is found (no blocked, merge_failure, or review_hold), returns a clear message saying so
## Out of Scope
- TBD
@@ -0,0 +1,26 @@
---
name: "Unify story stuck states into a single status field"
---
# Refactor 436: Unify story stuck states into a single status field
## Current State
- TBD
## Desired State
Replace the separate blocked, merge_failure, and review_hold front matter fields with a single status field (e.g. status: blocked, status: merge_failure, status: review_hold). Simplifies the unblock command, auto-assign checks, and pipeline advance logic.
## Acceptance Criteria
- [ ] Replace blocked: true, merge_failure: string, and review_hold: true with a single status: field in story front matter
- [ ] Auto-assign checks a single field instead of three separate ones
- [ ] Pipeline advance and lifecycle code reads/writes the unified status field
- [ ] Unblock command clears the status field regardless of which stuck state it was
- [ ] retry_count remains a separate field (it's a counter, not a state)
- [ ] Migration: existing stories with old fields are handled gracefully on read
## Out of Scope
- TBD
@@ -0,0 +1,31 @@
---
name: "Rename project from \"huskies\" to \"huskies\""
---
# Story 455: Rename project from "huskies" to "huskies"
## User Story
As a project maintainer, I want to rename the project from \"huskies\" to \"huskies\" so that the product has its new identity throughout the codebase, tooling, and documentation. The new domain is huskies.dev — update all references to huskies.dev accordingly (website, contact email hello@huskies.dev, etc).
## Acceptance Criteria
- [ ] Rust crate name in server/Cargo.toml changed from 'huskies' to 'huskies'
- [ ] Binary name changed to 'huskies' (Dockerfile CMD, release script binary names)
- [ ] Environment variables renamed: STORKIT_PORT → HUSKIES_PORT, STORKIT_HOST → HUSKIES_HOST
- [ ] Docker service name, container_name, image name, and volume names updated in docker-compose.yml
- [ ] Docker user/group renamed from 'huskies' to 'huskies' in Dockerfile (groupadd, useradd, home dir /home/huskies/.claude)
- [ ] MCP server registration renamed from 'huskies' to 'huskies' in scaffold-generated .mcp.json and in server/src/http/mcp/mod.rs serverInfo name
- [ ] All 35+ MCP tool permission patterns updated from mcp__huskies__* to mcp__huskies__* across code and permission configs
- [ ] The .huskies/ project directory marker renamed to .huskies/ throughout all Rust source (paths.rs, config.rs, scaffold.rs, watcher.rs, prompts.rs, and all agent/pipeline code)
- [ ] Release script updated: Gitea repo path dave/huskies → dave/huskies, changelog regex updated to match ^(huskies|huskies|story-kit): for backwards-compatible history parsing, binary artifact names updated
- [ ] Git commit prefix convention updated from 'huskies:' to 'huskies:' in huskies README and agent prompts
- [ ] Website updated: page title, headings, and contact email (hello@huskies.dev) if domain changes
- [ ] README.md updated: all CLI examples use 'huskies' binary name, all .huskies/ references become .huskies/
- [ ] A migration path exists for existing installs: either huskies auto-detects and migrates .huskies/ → .huskies/, or a migration script (script/migrate) is provided
- [ ] All Claude Code .mcp.json files in existing worktrees are regenerated via scaffold or migration
- [ ] Gitea repository renamed from dave/huskies to dave/huskies (external action required, noted in story)
## Out of Scope
- TBD
@@ -0,0 +1,41 @@
---
name: "Stage transition notifications can arrive out of order and show wrong story name"
agent: coder-opus
---
# Bug 462: Stage transition notifications can arrive out of order and show wrong story name
## Description
When a story moves through stages quickly (e.g. QA → Merge → Done), the stage transition notifications can arrive out of order in Matrix chat. The Done notification appears before the Merge notification.
Two issues:
1. **Out-of-order delivery**: When two notifications are sent close together, the Matrix homeserver can deliver them in the wrong order. The notification handler processes events sequentially and awaits each send, but the homeserver does not guarantee ordering for near-simultaneous messages.
2. **Missing story name on stale notifications**: The second notification shows the raw item_id instead of the story name because `read_story_name` looks in the stage directory from the event (e.g. `4_merge/`), but the file has already moved to the next stage (e.g. `5_done/`).
3. **`inferred_from_stage` guesses the source stage** instead of tracking the actual from-stage. This means skipped stages would show incorrect transitions.
## How to Reproduce
1. Have a story in QA that passes quickly
2. Story moves QA → Merge → Done in rapid succession
3. Observe notifications in Matrix
## Actual Result
Notifications arrive in wrong order (Done before Merge). The later notification shows the raw item_id instead of the story name:
🎉 #32 upgrade TypeScript... — Merge → Done
#32 32_story_upgrade_typescript_and_tsconfig... — QA → Merge
## Expected Result
Notifications arrive in chronological order. All notifications show the story name. Ideally, rapid transitions are coalesced into a single notification for the final stage.
## Acceptance Criteria
- [ ] read_story_name falls back to searching all stages when the expected stage directory has no match
- [ ] Consider deduplicating rapid transitions within a short window (e.g. only notify for the final stage)
- [ ] Track actual from-stage in WatcherEvent instead of guessing via inferred_from_stage
@@ -0,0 +1,21 @@
---
name: "Configurable rate limit notification suppression"
---
# Story 463: Configurable rate limit notification suppression
## User Story
As a ..., I want ..., so that ...
## Acceptance Criteria
- [ ] New boolean config field in project.toml (e.g. rate_limit_notifications) defaults to true
- [ ] When false, RateLimitWarning chat notifications are suppressed
- [ ] RateLimitHardBlock and StoryBlocked notifications are always sent regardless of the setting
- [ ] Stage transition notifications are unaffected
- [ ] Config is hot-reloaded when project.toml changes
## Out of Scope
- TBD
@@ -0,0 +1,33 @@
---
name: "Timer rejects backlog stories — should move to current on fire"
---
# Bug 464: Timer rejects backlog stories — should move to current on fire
## Description
The `timer` bot command requires stories to be in `work/2_current/` before scheduling. When a user tries to schedule a backlog story (e.g. `timer 463 12:45`), it returns:
"Story **463_story_...** is not in `work/2_current/`. Move it to current before scheduling a timer."
The timer should accept backlog stories. When the timer fires, it should move the story from backlog to current and let auto-assign start an agent.
## How to Reproduce
1. Have a story in backlog (e.g. 463)
2. Run `timer 463 12:45`
3. Observe rejection message
## Actual Result
Timer command rejects stories not in `work/2_current/`.
## Expected Result
Timer command accepts backlog stories. When the timer fires, it moves the story to current and auto-assign picks it up.
## Acceptance Criteria
- [ ] Timer bot command accepts stories in backlog or current
- [ ] Timer tick loop calls move_story_to_current before start_agent for backlog stories
- [ ] Unit tests cover scheduling and firing for backlog stories
@@ -0,0 +1,36 @@
---
name: "Timer tick loop never fires due entries"
agent: coder-opus
---
# Bug 465: Timer tick loop never fires due entries
## Description
The timer tick loop (`spawn_timer_tick_loop`) is spawned by the Matrix bot runner, the Matrix bot is confirmed running (processing messages), but timers never fire. Past-due entries remain in `.huskies/timers.json` indefinitely — `take_due` never consumes them.
The tick loop uses `tokio::spawn` which swallows panics silently. If `move_story_to_current` or `start_agent` panics on the first tick (when all past-due entries fire at once), the entire task dies with no log output. The PTY debug spam may also push any `[timer]` log entries out of the ring buffer.
The bot command successfully adds entries to the in-memory store and persists them to disk, but the tick loop never processes them.
## How to Reproduce
1. Set a timer via bot command: `timer 463 HH:MM` (a time in the near future)
2. Wait past the scheduled time
3. Check `.huskies/timers.json` — entries are still present
4. Check server logs for `[timer]` — no entries found
## Actual Result
Timer entries remain in timers.json indefinitely. No `[timer] Timer fired` log entries appear. The story is never moved to current and no agent is started.
## Expected Result
Within 30 seconds of the scheduled time, the tick loop should call `take_due`, remove the entry from disk, move the story to current (if in backlog), and start an agent.
## Acceptance Criteria
- [ ] Add panic-catching (catch_unwind or tokio CancellationToken) to the tick loop so failures are logged
- [ ] Add a startup log line confirming the tick loop is running and how many pending timers were loaded
- [ ] Verify take_due runs on each 30-second tick by adding periodic debug logging
- [ ] Integration test: create a past-due timer entry, run the tick loop, assert the entry is consumed
@@ -0,0 +1,21 @@
---
name: "Configurable timezone in project.toml for timer scheduling"
---
# Story 466: Configurable timezone in project.toml for timer scheduling
## User Story
As a user running huskies in a container where TZ defaults to UTC, I want to configure my project's timezone in project.toml so that timer HH:MM inputs are interpreted in my actual timezone.
## Acceptance Criteria
- [ ] Add a `timezone` field to project.toml (e.g. `timezone = "Europe/London"`)
- [ ] next_occurrence_of_hhmm uses the configured timezone instead of chrono::Local
- [ ] Falls back to chrono::Local if no timezone is configured
- [ ] Timer confirmation message displays the time in the configured timezone
- [ ] timer list command shows times in the configured timezone
## Out of Scope
- TBD
@@ -10,7 +10,7 @@ The `prompt_permission` MCP tool returns plain text ("Permission granted for '..
## How to Reproduce ## How to Reproduce
1. Start the storkit server and open the web UI 1. Start the huskies server and open the web UI
2. Chat with the claude-code-pty model 2. Chat with the claude-code-pty model
3. Ask it to do something that requires a tool NOT in `.claude/settings.json` allow list (e.g. `wc -l /etc/hosts`, or WebFetch to a non-allowed domain) 3. Ask it to do something that requires a tool NOT in `.claude/settings.json` allow list (e.g. `wc -l /etc/hosts`, or WebFetch to a non-allowed domain)
4. The permission dialog appears — click Approve 4. The permission dialog appears — click Approve
@@ -6,7 +6,7 @@ name: "Retry limit for mergemaster and pipeline restarts"
## User Story ## User Story
As a developer using storkit, I want pipeline auto-restarts to have a configurable retry limit so that failing agents don't loop infinitely consuming CPU and API credits. As a developer using huskies, I want pipeline auto-restarts to have a configurable retry limit so that failing agents don't loop infinitely consuming CPU and API credits.
## Acceptance Criteria ## Acceptance Criteria
@@ -23,7 +23,7 @@ The watcher should periodically check `5_done/` and move items older than 4 hour
- All MCP tools and pipeline logic that reference `5_archived` need updating to use `5_done` - All MCP tools and pipeline logic that reference `5_archived` need updating to use `5_done`
- Frontend pipeline display if it shows archived/done items - Frontend pipeline display if it shows archived/done items
- `.story_kit/README.md`: update pipeline stage documentation - `.story_kit/README.md`: update pipeline stage documentation
- Story 116's init scaffolding: `storkit init` must create `5_done/` and `6_archived/` directories - Story 116's init scaffolding: `huskies init` must create `5_done/` and `6_archived/` directories
- Any templates or scaffold code that creates the `.story_kit/work/` directory structure - Any templates or scaffold code that creates the `.story_kit/work/` directory structure
## Acceptance Criteria ## Acceptance Criteria
@@ -35,7 +35,7 @@ The watcher should periodically check `5_done/` and move items older than 4 hour
- [ ] Existing items in old `5_archived/` are migrated to `6_archived/` - [ ] Existing items in old `5_archived/` are migrated to `6_archived/`
- [ ] Frontend pipeline display updated if applicable - [ ] Frontend pipeline display updated if applicable
- [ ] `.story_kit/README.md` updated to reflect the new pipeline stages - [ ] `.story_kit/README.md` updated to reflect the new pipeline stages
- [ ] `storkit init` scaffolding creates `5_done/` and `6_archived/` (coordinate with story 116) - [ ] `huskies init` scaffolding creates `5_done/` and `6_archived/` (coordinate with story 116)
## Out of Scope ## Out of Scope

Some files were not shown because too many files have changed in this diff Show More