story-kit: accept 49_story_deterministic_bug_lifecycle_management
This commit is contained in:
@@ -10,7 +10,7 @@ The `prompt_permission` MCP tool returns plain text ("Permission granted for '..
|
|||||||
|
|
||||||
## How to Reproduce
|
## How to Reproduce
|
||||||
|
|
||||||
1. Start the story-kit server and open the web UI
|
1. Start the storkit 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 story-kit, 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 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.
|
||||||
|
|
||||||
## 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: `story-kit init` must create `5_done/` and `6_archived/` directories
|
- Story 116's init scaffolding: `storkit 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
|
||||||
- [ ] `story-kit init` scaffolding creates `5_done/` and `6_archived/` (coordinate with story 116)
|
- [ ] `storkit init` scaffolding creates `5_done/` and `6_archived/` (coordinate with story 116)
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|
||||||
|
|||||||
@@ -17,21 +17,21 @@ const TEMPLATE_MARKER_CONTEXT: &str = "Agentic AI Code Assistant";
|
|||||||
const TEMPLATE_MARKER_STACK: &str = "Agentic Code Assistant";
|
const TEMPLATE_MARKER_STACK: &str = "Agentic Code Assistant";
|
||||||
```
|
```
|
||||||
|
|
||||||
These markers are phrases that appear in the scaffold templates (`server/src/io/fs.rs` lines 233 and 269). The detection logic (`is_template_or_missing` at line 59) checks if the file *contains* the marker string. But these phrases are generic enough that real project content can contain them too — especially when the project being managed IS an agentic code assistant (i.e. story-kit managing itself).
|
These markers are phrases that appear in the scaffold templates (`server/src/io/fs.rs` lines 233 and 269). The detection logic (`is_template_or_missing` at line 59) checks if the file *contains* the marker string. But these phrases are generic enough that real project content can contain them too — especially when the project being managed IS an agentic code assistant (i.e. storkit managing itself).
|
||||||
|
|
||||||
## The Fix
|
## The Fix
|
||||||
|
|
||||||
Replace the content-based marker detection with a dedicated sentinel comment that only exists in untouched scaffold templates. The sentinel should be something that would never appear in real content, like an HTML comment:
|
Replace the content-based marker detection with a dedicated sentinel comment that only exists in untouched scaffold templates. The sentinel should be something that would never appear in real content, like an HTML comment:
|
||||||
|
|
||||||
```
|
```
|
||||||
<!-- story-kit:scaffold-template -->
|
<!-- storkit:scaffold-template -->
|
||||||
```
|
```
|
||||||
|
|
||||||
Changes needed:
|
Changes needed:
|
||||||
|
|
||||||
1. **`server/src/io/onboarding.rs`**: Replace `TEMPLATE_MARKER_CONTEXT` and `TEMPLATE_MARKER_STACK` with a single `TEMPLATE_SENTINEL` constant set to `"<!-- story-kit:scaffold-template -->"`. Update `check_onboarding_status` to use it for both context and stack checks.
|
1. **`server/src/io/onboarding.rs`**: Replace `TEMPLATE_MARKER_CONTEXT` and `TEMPLATE_MARKER_STACK` with a single `TEMPLATE_SENTINEL` constant set to `"<!-- storkit:scaffold-template -->"`. Update `check_onboarding_status` to use it for both context and stack checks.
|
||||||
|
|
||||||
2. **`server/src/io/fs.rs`**: Add `<!-- story-kit:scaffold-template -->` as the first line of both `STORY_KIT_CONTEXT` and `STORY_KIT_STACK` template constants (lines 233 and 269).
|
2. **`server/src/io/fs.rs`**: Add `<!-- storkit:scaffold-template -->` as the first line of both `STORY_KIT_CONTEXT` and `STORY_KIT_STACK` template constants (lines 233 and 269).
|
||||||
|
|
||||||
3. **`server/src/io/onboarding.rs` tests**: Update the test `needs_onboarding_true_when_specs_contain_scaffold_markers` to use the sentinel instead of the old marker phrases. Also add a test confirming that content containing "Agentic AI Code Assistant" WITHOUT the sentinel does NOT trigger onboarding.
|
3. **`server/src/io/onboarding.rs` tests**: Update the test `needs_onboarding_true_when_specs_contain_scaffold_markers` to use the sentinel instead of the old marker phrases. Also add a test confirming that content containing "Agentic AI Code Assistant" WITHOUT the sentinel does NOT trigger onboarding.
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ Changes needed:
|
|||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] Scaffold templates contain the sentinel `<!-- story-kit:scaffold-template -->` as first line
|
- [ ] Scaffold templates contain the sentinel `<!-- storkit:scaffold-template -->` as first line
|
||||||
- [ ] `needs_onboarding()` returns false for projects whose specs contain "Agentic AI Code Assistant" but NOT the sentinel
|
- [ ] `needs_onboarding()` returns false for projects whose specs contain "Agentic AI Code Assistant" but NOT the sentinel
|
||||||
- [ ] `needs_onboarding()` returns true for untouched scaffold content (which contains the sentinel)
|
- [ ] `needs_onboarding()` returns true for untouched scaffold content (which contains the sentinel)
|
||||||
- [ ] Existing tests updated and passing
|
- [ ] Existing tests updated and passing
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ As a project owner, I want agent role descriptions to explicitly require test-fi
|
|||||||
|
|
||||||
## Test Results
|
## Test Results
|
||||||
|
|
||||||
<!-- story-kit-test-results: {"unit":[{"name":"Coder roles mention test-first and record_tests","status":"pass","details":"coder-1, coder-2, and coder-opus role fields and prompts updated to require test-first development and call record_tests MCP tool"},{"name":"QA roles verify record_tests was called","status":"pass","details":"qa and qa-2 role fields, prompts, and system_prompts updated to explicitly verify record_tests was called and flag missing results as FAIL"},{"name":"Mergemaster role checks ensure_acceptance before merging","status":"pass","details":"mergemaster role field, prompt workflow step 1, and system_prompt updated to call ensure_acceptance before triggering merge_agent_work"}],"integration":[]} -->
|
<!-- storkit-test-results: {"unit":[{"name":"Coder roles mention test-first and record_tests","status":"pass","details":"coder-1, coder-2, and coder-opus role fields and prompts updated to require test-first development and call record_tests MCP tool"},{"name":"QA roles verify record_tests was called","status":"pass","details":"qa and qa-2 role fields, prompts, and system_prompts updated to explicitly verify record_tests was called and flag missing results as FAIL"},{"name":"Mergemaster role checks ensure_acceptance before merging","status":"pass","details":"mergemaster role field, prompt workflow step 1, and system_prompt updated to call ensure_acceptance before triggering merge_agent_work"}],"integration":[]} -->
|
||||||
|
|
||||||
### Unit Tests (3 passed, 0 failed)
|
### Unit Tests (3 passed, 0 failed)
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ As a project owner, I want test results written to the story markdown file when
|
|||||||
|
|
||||||
## Test Results
|
## Test Results
|
||||||
|
|
||||||
<!-- story-kit-test-results: {"unit":[{"name":"test_write_persists","status":"pass","details":null}],"integration":[{"name":"test_roundtrip","status":"pass","details":null}]} -->
|
<!-- storkit-test-results: {"unit":[{"name":"test_write_persists","status":"pass","details":null}],"integration":[{"name":"test_roundtrip","status":"pass","details":null}]} -->
|
||||||
|
|
||||||
### Unit Tests (1 passed, 0 failed)
|
### Unit Tests (1 passed, 0 failed)
|
||||||
|
|
||||||
@@ -31,4 +31,3 @@ As a project owner, I want test results written to the story markdown file when
|
|||||||
### Integration Tests (1 passed, 0 failed)
|
### Integration Tests (1 passed, 0 failed)
|
||||||
|
|
||||||
- ✅ test_roundtrip
|
- ✅ test_roundtrip
|
||||||
|
|
||||||
|
|||||||
@@ -26,4 +26,4 @@ An MCP tool (e.g. add_criterion or edit_story) that can add/remove/update accept
|
|||||||
|
|
||||||
- [ ] An MCP tool exists to add acceptance criteria to a story file
|
- [ ] An MCP tool exists to add acceptance criteria to a story file
|
||||||
- [ ] An MCP tool exists to update the story description or user story text
|
- [ ] An MCP tool exists to update the story description or user story text
|
||||||
- [ ] These tools auto-commit changes to the story file like other story-kit MCP tools do
|
- [ ] These tools auto-commit changes to the story file like other storkit MCP tools do
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ As a Matrix room participant, I want the bot to only respond when I address it w
|
|||||||
- [ ] Bot ignores messages that don't mention @timmy or the bot's Matrix user ID
|
- [ ] Bot ignores messages that don't mention @timmy or the bot's Matrix user ID
|
||||||
- [ ] Bot responds normally when mentioned with @timmy at the start or anywhere in the message
|
- [ ] Bot responds normally when mentioned with @timmy at the start or anywhere in the message
|
||||||
- [ ] Bot still processes replies to its own messages (threaded replies)
|
- [ ] Bot still processes replies to its own messages (threaded replies)
|
||||||
- [ ] Existing command handling (story-kit MCP tools, etc.) still works when the bot is addressed
|
- [ ] Existing command handling (storkit MCP tools, etc.) still works when the bot is addressed
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ The new merge-queue worktree approach (introduced ~24 hours ago) has a race cond
|
|||||||
|
|
||||||
1. `run_squash_merge()` creates a `merge-queue/{story_id}` branch at master's current HEAD
|
1. `run_squash_merge()` creates a `merge-queue/{story_id}` branch at master's current HEAD
|
||||||
2. It creates a temporary worktree, runs `git merge --squash`, commits, and runs quality gates — all in the merge-queue worktree
|
2. It creates a temporary worktree, runs `git merge --squash`, commits, and runs quality gates — all in the merge-queue worktree
|
||||||
3. Meanwhile, the **filesystem watcher auto-commits pipeline file moves** to master (e.g. "story-kit: queue X for merge", "story-kit: done Y")
|
3. Meanwhile, the **filesystem watcher auto-commits pipeline file moves** to master (e.g. "storkit: queue X for merge", "storkit: done Y")
|
||||||
4. By the time step 7 tries `git merge --ff-only merge-queue/{story_id}` on master, master has diverged and the fast-forward fails
|
4. By the time step 7 tries `git merge --ff-only merge-queue/{story_id}` on master, master has diverged and the fast-forward fails
|
||||||
5. `run_squash_merge()` returns `success: false` (correctly) but `gates_passed: true` (misleading)
|
5. `run_squash_merge()` returns `success: false` (correctly) but `gates_passed: true` (misleading)
|
||||||
6. The `merge_agent_work` caller correctly reports failure — but the mergemaster is a Claude Code agent, not the Rust pipeline. The agent sees the failure, gives up on the squash merge, and instead manually moves the story file to done without the code
|
6. The `merge_agent_work` caller correctly reports failure — but the mergemaster is a Claude Code agent, not the Rust pipeline. The agent sees the failure, gives up on the squash merge, and instead manually moves the story file to done without the code
|
||||||
@@ -39,7 +39,7 @@ The stale `.story_kit/merge_workspace` directory from failed merges blocks subse
|
|||||||
|
|
||||||
## Actual Result
|
## Actual Result
|
||||||
|
|
||||||
Stories are moved to 5_done with pipeline commit messages like "story-kit: done ..." but the feature branch code is never squash-merged onto master. Feature branches retain unmerged commits.
|
Stories are moved to 5_done with pipeline commit messages like "storkit: done ..." but the feature branch code is never squash-merged onto master. Feature branches retain unmerged commits.
|
||||||
|
|
||||||
## Expected Result
|
## Expected Result
|
||||||
|
|
||||||
|
|||||||
@@ -6,24 +6,24 @@ name: "Project scaffold does not write .mcp.json to project root"
|
|||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
When a new project is opened/scaffolded, `.mcp.json` is not written to the project root. The `write_mcp_json()` function (worktree.rs:6) is only called during worktree creation, not during `scaffold_story_kit()` (io/fs.rs:464) or `open_project()` (io/fs.rs:503). This means claude-pty spawned with `--permission-prompt-tool mcp__story-kit__prompt_permission` immediately fails because the MCP tool isn't available.
|
When a new project is opened/scaffolded, `.mcp.json` is not written to the project root. The `write_mcp_json()` function (worktree.rs:6) is only called during worktree creation, not during `scaffold_story_kit()` (io/fs.rs:464) or `open_project()` (io/fs.rs:503). This means claude-pty spawned with `--permission-prompt-tool mcp__storkit__prompt_permission` immediately fails because the MCP tool isn't available.
|
||||||
|
|
||||||
Additionally, there is no way for the user to trigger scaffolding from the CLI — `find_story_kit_root()` in main.rs falls through without scaffolding if `.story_kit/` doesn't exist yet, so the only path is via the UI file chooser.
|
Additionally, there is no way for the user to trigger scaffolding from the CLI — `find_story_kit_root()` in main.rs falls through without scaffolding if `.story_kit/` doesn't exist yet, so the only path is via the UI file chooser.
|
||||||
|
|
||||||
## How to Reproduce
|
## How to Reproduce
|
||||||
|
|
||||||
1. Create an empty directory or navigate to a project without `.story_kit/`
|
1. Create an empty directory or navigate to a project without `.story_kit/`
|
||||||
2. Run `story-kit`
|
2. Run `storkit`
|
||||||
3. Open the project via the UI file chooser
|
3. Open the project via the UI file chooser
|
||||||
4. Try to chat using the claude-code provider
|
4. Try to chat using the claude-code provider
|
||||||
|
|
||||||
## Actual Result
|
## Actual Result
|
||||||
|
|
||||||
Claude Code exits immediately with: `Error: MCP tool mcp__story-kit__prompt_permission (passed via --permission-prompt-tool) not found. Available MCP tools: none`
|
Claude Code exits immediately with: `Error: MCP tool mcp__storkit__prompt_permission (passed via --permission-prompt-tool) not found. Available MCP tools: none`
|
||||||
|
|
||||||
## Expected Result
|
## Expected Result
|
||||||
|
|
||||||
`.mcp.json` is written to the project root during scaffolding/open, so claude-code can connect to the story-kit MCP server.
|
`.mcp.json` is written to the project root during scaffolding/open, so claude-code can connect to the storkit MCP server.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ name: "Accept optional positional path argument on startup"
|
|||||||
|
|
||||||
## User Story
|
## User Story
|
||||||
|
|
||||||
As a user, I want to run `story-kit .` or `story-kit /path/to/project` to start the server with that directory as the project, so that I don't have to use the UI file chooser.
|
As a user, I want to run `storkit .` or `storkit /path/to/project` to start the server with that directory as the project, so that I don't have to use the UI file chooser.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] Running `story-kit` with no args behaves as today (auto-detect from cwd)
|
- [ ] Running `storkit` with no args behaves as today (auto-detect from cwd)
|
||||||
- [ ] Running `story-kit .` opens the current directory as the project
|
- [ ] Running `storkit .` opens the current directory as the project
|
||||||
- [ ] Running `story-kit /some/path` opens that path as the project
|
- [ ] Running `storkit /some/path` opens that path as the project
|
||||||
- [ ] If the path has no .story_kit/, it is scaffolded automatically
|
- [ ] If the path has no .story_kit/, it is scaffolded automatically
|
||||||
- [ ] Invalid paths produce a clear error message
|
- [ ] Invalid paths produce a clear error message
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ name: "Skip selection screen when CLI path argument provided"
|
|||||||
|
|
||||||
## User Story
|
## User Story
|
||||||
|
|
||||||
As a user, I want the frontend to go straight to the project workspace when I start the server with an explicit path argument (e.g. `story-kit .`), so that I don't have to click through the selection screen for a project the server already opened.
|
As a user, I want the frontend to go straight to the project workspace when I start the server with an explicit path argument (e.g. `storkit .`), so that I don't have to click through the selection screen for a project the server already opened.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ As a developer setting up a new project with Story Kit, I want the scaffold to g
|
|||||||
- [ ] CLAUDE.md includes a directive to read .story_kit/README.md for the dev process
|
- [ ] CLAUDE.md includes a directive to read .story_kit/README.md for the dev process
|
||||||
- [ ] Scaffold does not overwrite an existing CLAUDE.md (consistent with other scaffold files)
|
- [ ] Scaffold does not overwrite an existing CLAUDE.md (consistent with other scaffold files)
|
||||||
- [ ] Onboarding status does not check CLAUDE.md (it is not a required onboarding step)
|
- [ ] Onboarding status does not check CLAUDE.md (it is not a required onboarding step)
|
||||||
- [ ] CLAUDE.md content matches the story-kit-app's own CLAUDE.md (command chaining rule + read .story_kit/README.md directive), prefixed with the scaffold sentinel
|
- [ ] CLAUDE.md content matches the storkit-app's own CLAUDE.md (command chaining rule + read .story_kit/README.md directive), prefixed with the scaffold sentinel
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ As a user interacting with agents via the web UI, I want an "Always Allow" optio
|
|||||||
- [ ] After Always Allow, Claude Code's built-in permission system handles future checks without calling the prompt tool
|
- [ ] After Always Allow, Claude Code's built-in permission system handles future checks without calling the prompt tool
|
||||||
- [ ] Edit and Write rules use the tool name (e.g. Edit, Write)
|
- [ ] Edit and Write rules use the tool name (e.g. Edit, Write)
|
||||||
- [ ] Bash rules use the command prefix pattern (e.g. Bash(git *))
|
- [ ] Bash rules use the command prefix pattern (e.g. Bash(git *))
|
||||||
- [ ] MCP tool rules use the tool name pattern (e.g. mcp__story-kit__create_story)
|
- [ ] MCP tool rules use the tool name pattern (e.g. mcp__storkit__create_story)
|
||||||
- [ ] Existing rules in settings.json are not duplicated
|
- [ ] Existing rules in settings.json are not duplicated
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
name: "Show agent logs for a story in expanded work item"
|
name: "Show agent logs for a story in expanded work item"
|
||||||
merge_failure: "Merge workspace `.story_kit/merge_workspace` is still occupied by story 236's merge branch (merge-queue/236_story_show_test_results_for_a_story_in_expanded_work_item). The merge pipeline cannot create a new worktree while the existing one is present. To unblock: either wait for story 236's merge to complete, or manually clean up with `git worktree remove .story_kit/merge_workspace` and `git branch -D merge-queue/236_story_show_test_results_for_a_story_in_expanded_work_item`, then re-trigger the merge for story 235."
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Story 235: Show agent logs for a story in expanded work item
|
# Story 235: Show agent logs for a story in expanded work item
|
||||||
@@ -21,7 +20,7 @@ As a user, I want to see agent logs for a story inside its expanded view, so tha
|
|||||||
|
|
||||||
## Test Results
|
## Test Results
|
||||||
|
|
||||||
<!-- story-kit-test-results: {"unit":[{"name":"shows placeholder when no agent is assigned to the story","status":"pass","details":null},{"name":"shows agent name and running status when agent is running","status":"pass","details":null},{"name":"shows log output when agent emits output events","status":"pass","details":null},{"name":"appends multiple output events to the log","status":"pass","details":null},{"name":"updates status to completed after done event","status":"pass","details":null},{"name":"shows failed status after error event","status":"pass","details":null},{"name":"shows completed agent status without subscribing to stream","status":"pass","details":null},{"name":"shows failed agent status for a failed agent without subscribing to stream","status":"pass","details":null},{"name":"shows agent logs section (not placeholder) when agent is assigned","status":"pass","details":null}],"integration":[]} -->
|
<!-- storkit-test-results: {"unit":[{"name":"shows placeholder when no agent is assigned to the story","status":"pass","details":null},{"name":"shows agent name and running status when agent is running","status":"pass","details":null},{"name":"shows log output when agent emits output events","status":"pass","details":null},{"name":"appends multiple output events to the log","status":"pass","details":null},{"name":"updates status to completed after done event","status":"pass","details":null},{"name":"shows failed status after error event","status":"pass","details":null},{"name":"shows completed agent status without subscribing to stream","status":"pass","details":null},{"name":"shows failed agent status for a failed agent without subscribing to stream","status":"pass","details":null},{"name":"shows agent logs section (not placeholder) when agent is assigned","status":"pass","details":null}],"integration":[]} -->
|
||||||
|
|
||||||
### Unit Tests (9 passed, 0 failed)
|
### Unit Tests (9 passed, 0 failed)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
name: "Show test results for a story in expanded work item"
|
name: "Show test results for a story in expanded work item"
|
||||||
merge_failure: "merge_agent_work tool returned empty output on 2 attempts. The tool was called successfully (confirmed via MERGE-DEBUG logs) but produced no result - no success/failure status, no gate output. Possible causes: (1) dirty working tree on master (unstaged changes to .claude/settings.json and .mcp.json), (2) internal tool error being swallowed silently. The feature branch has 2 commits ready to merge (ae62aab, 8d5b81e). Story is still in 4_merge/. Human investigation needed."
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Story 236: Show test results for a story in expanded work item
|
# Story 236: Show test results for a story in expanded work item
|
||||||
@@ -21,7 +20,7 @@ As a user, I want to see test results for a story inside its expanded view, so t
|
|||||||
|
|
||||||
## Test Results
|
## Test Results
|
||||||
|
|
||||||
<!-- story-kit-test-results: {"unit":[{"name":"my_unit_test","status":"pass","details":null}],"integration":[{"name":"my_int_test","status":"fail","details":"assertion failed"}]} -->
|
<!-- storkit-test-results: {"unit":[{"name":"my_unit_test","status":"pass","details":null}],"integration":[{"name":"my_int_test","status":"fail","details":"assertion failed"}]} -->
|
||||||
|
|
||||||
### Unit Tests (1 passed, 0 failed)
|
### Unit Tests (1 passed, 0 failed)
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ As a Matrix user messaging the bot, I want the bot to correctly recognize my cro
|
|||||||
|
|
||||||
## Test Results
|
## Test Results
|
||||||
|
|
||||||
<!-- story-kit-test-results: {"unit":[{"name":"sender_with_cross_signing_identity_is_accepted","status":"pass","details":"Verifies get_user_identity Some(_) → accepted"},{"name":"sender_without_cross_signing_identity_is_rejected","status":"pass","details":"Verifies get_user_identity None → rejected"}],"integration":[]} -->
|
<!-- storkit-test-results: {"unit":[{"name":"sender_with_cross_signing_identity_is_accepted","status":"pass","details":"Verifies get_user_identity Some(_) → accepted"},{"name":"sender_without_cross_signing_identity_is_rejected","status":"pass","details":"Verifies get_user_identity None → rejected"}],"integration":[]} -->
|
||||||
|
|
||||||
### Unit Tests (2 passed, 0 failed)
|
### Unit Tests (2 passed, 0 failed)
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
---
|
---
|
||||||
name: "Move story-kit ignores into .story_kit/.gitignore"
|
name: "Move storkit ignores into .story_kit/.gitignore"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Story 259: Move story-kit ignores into .story_kit/.gitignore
|
# Story 259: Move storkit ignores into .story_kit/.gitignore
|
||||||
|
|
||||||
## User Story
|
## User Story
|
||||||
|
|
||||||
As a developer using story-kit, I want story-kit-specific gitignore patterns to live inside .story_kit/.gitignore, so that the host project's root .gitignore stays clean and story-kit concerns are self-contained.
|
As a developer using storkit, I want storkit-specific gitignore patterns to live inside .story_kit/.gitignore, so that the host project's root .gitignore stays clean and storkit concerns are self-contained.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] A .gitignore file exists at .story_kit/.gitignore containing all story-kit-specific ignore patterns
|
- [ ] A .gitignore file exists at .story_kit/.gitignore containing all storkit-specific ignore patterns
|
||||||
- [ ] The root .gitignore no longer contains story-kit-specific ignore patterns
|
- [ ] The root .gitignore no longer contains storkit-specific ignore patterns
|
||||||
- [ ] The deterministic project scaffold process creates .story_kit/.gitignore when initialising a new project
|
- [ ] The deterministic project scaffold process creates .story_kit/.gitignore when initialising a new project
|
||||||
- [ ] Existing repos continue to work correctly after the change (no previously-ignored files become tracked)
|
- [ ] Existing repos continue to work correctly after the change (no previously-ignored files become tracked)
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
---
|
---
|
||||||
name: "Rename binary and all references from story-kit to storkit"
|
name: "Rename binary and all references from storkit to storkit"
|
||||||
agent: coder-opus
|
agent: coder-opus
|
||||||
---
|
---
|
||||||
|
|
||||||
# Story 315: Rename binary and all references from story-kit to storkit
|
# Story 315: Rename binary and all references from storkit to storkit
|
||||||
|
|
||||||
## User Story
|
## User Story
|
||||||
|
|
||||||
As a project owner, I want the binary, crate name, package name, and all code/config references renamed from story-kit/story_kit to storkit, so that the branding is consistent throughout the project.
|
As a project owner, I want the binary, crate name, package name, and all code/config references renamed from storkit/story_kit to storkit, so that the branding is consistent throughout the project.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] Binary name changed from story-kit to storkit in Cargo.toml
|
- [ ] Binary name changed from storkit to storkit in Cargo.toml
|
||||||
- [ ] Crate/package name changed from story-kit/story_kit to storkit throughout Cargo.toml files
|
- [ ] Crate/package name changed from storkit/story_kit to storkit throughout Cargo.toml files
|
||||||
- [ ] All code references to story_kit (module names, paths, env vars like CARGO_MANIFEST_DIR) updated
|
- [ ] All code references to story_kit (module names, paths, env vars like CARGO_MANIFEST_DIR) updated
|
||||||
- [ ] Config directory .story_kit renamed to .storkit
|
- [ ] Config directory .story_kit renamed to .storkit
|
||||||
- [ ] All server code references to .story_kit paths updated
|
- [ ] All server code references to .story_kit paths updated
|
||||||
- [ ] Git commit messages prefix changed from 'story-kit:' to 'storkit:'
|
- [ ] Git commit messages prefix changed from 'storkit:' to 'storkit:'
|
||||||
- [ ] Frontend references updated (if any)
|
- [ ] Frontend references updated (if any)
|
||||||
- [ ] script/* files updated to reference the new binary name
|
- [ ] script/* files updated to reference the new binary name
|
||||||
- [ ] Release script updated for new binary name
|
- [ ] Release script updated for new binary name
|
||||||
- [ ] MCP server name updated from story-kit to storkit
|
- [ ] MCP server name updated from storkit to storkit
|
||||||
- [ ] CLAUDE.md and README references updated
|
- [ ] CLAUDE.md and README references updated
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ As a developer running autonomous agents, I want all story file mutations to hap
|
|||||||
- [ ] `start_agent` auto-commits the move from upcoming/ to current/ on master
|
- [ ] `start_agent` auto-commits the move from upcoming/ to current/ on master
|
||||||
- [ ] New MCP tool `check_criterion(story_id, criterion_index)` checks off an acceptance criterion and auto-commits to master
|
- [ ] New MCP tool `check_criterion(story_id, criterion_index)` checks off an acceptance criterion and auto-commits to master
|
||||||
- [ ] New MCP tool `set_test_plan(story_id, status)` updates the test_plan front matter field and auto-commits to master
|
- [ ] New MCP tool `set_test_plan(story_id, status)` updates the test_plan front matter field and auto-commits to master
|
||||||
- [ ] All auto-commits use deterministic commit messages (e.g. "story-kit: accept story 42")
|
- [ ] All auto-commits use deterministic commit messages (e.g. "storkit: accept story 42")
|
||||||
- [ ] Agents never need to edit story markdown files directly — all mutations go through server tools
|
- [ ] Agents never need to edit story markdown files directly — all mutations go through server tools
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ As a developer running autonomous agents, I want all bug file mutations to happe
|
|||||||
- [ ] New MCP tool `list_bugs()` returns all open bugs (files in `.story_kit/bugs/` excluding `archive/`)
|
- [ ] New MCP tool `list_bugs()` returns all open bugs (files in `.story_kit/bugs/` excluding `archive/`)
|
||||||
- [ ] New MCP tool `close_bug(bug_id)` moves a bug from `.story_kit/bugs/` to `.story_kit/bugs/archive/` and auto-commits to master
|
- [ ] New MCP tool `close_bug(bug_id)` moves a bug from `.story_kit/bugs/` to `.story_kit/bugs/archive/` and auto-commits to master
|
||||||
- [ ] `start_agent` supports bug IDs (e.g. `bug-5-description`) — no move needed since bugs don't have upcoming/current
|
- [ ] `start_agent` supports bug IDs (e.g. `bug-5-description`) — no move needed since bugs don't have upcoming/current
|
||||||
- [ ] All auto-commits use deterministic commit messages (e.g. "story-kit: create bug bug-6-fix-foo", "story-kit: close bug bug-5")
|
- [ ] All auto-commits use deterministic commit messages (e.g. "storkit: create bug bug-6-fix-foo", "storkit: close bug bug-5")
|
||||||
- [ ] Agents never need to edit bug markdown files directly — all mutations go through server tools
|
- [ ] Agents never need to edit bug markdown files directly — all mutations go through server tools
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ The server is a file mover that commits. Every mutation handler does the same th
|
|||||||
|
|
||||||
1. **`notify` crate** — does it reliably detect renames/moves across subdirectories on macOS and Linux? What events fire for `fs::rename`?
|
1. **`notify` crate** — does it reliably detect renames/moves across subdirectories on macOS and Linux? What events fire for `fs::rename`?
|
||||||
2. **Debouncing** — git operations touch multiple files. What's the right debounce window? Can we batch changes into a single commit?
|
2. **Debouncing** — git operations touch multiple files. What's the right debounce window? Can we batch changes into a single commit?
|
||||||
3. **Deterministic commit messages** — can the watcher infer intent from the move? e.g., file appears in `2_current/` → "story-kit: start {story_id}", file appears in `5_archived/` → "story-kit: accept {story_id}"
|
3. **Deterministic commit messages** — can the watcher infer intent from the move? e.g., file appears in `2_current/` → "storkit: start {story_id}", file appears in `5_archived/` → "storkit: accept {story_id}"
|
||||||
4. **Race conditions** — what if the watcher fires while a git commit is in progress? Need a mutex or queue?
|
4. **Race conditions** — what if the watcher fires while a git commit is in progress? Need a mutex or queue?
|
||||||
5. **What stays in mutation handlers** — do the MCP tools still need validation (e.g., "can't move to 2_current if not in 1_upcoming")? Or is the filesystem the only source of truth?
|
5. **What stays in mutation handlers** — do the MCP tools still need validation (e.g., "can't move to 2_current if not in 1_upcoming")? Or is the filesystem the only source of truth?
|
||||||
6. **Worktree interaction** — worktrees share `.git/`, so commits from the watcher in the main repo don't conflict with worktree work
|
6. **Worktree interaction** — worktrees share `.git/`, so commits from the watcher in the main repo don't conflict with worktree work
|
||||||
@@ -50,7 +50,7 @@ The server is a file mover that commits. Every mutation handler does the same th
|
|||||||
|
|
||||||
- **WebSocket integration** (`server/src/http/ws.rs`): Each WebSocket client subscribes to a `broadcast::Sender<WatcherEvent>`. When the watcher flushes a batch, it broadcasts a `WatcherEvent`; the WS handler converts it to `WorkItemChanged` and pushes it to the client. Frontend gets live updates with no polling.
|
- **WebSocket integration** (`server/src/http/ws.rs`): Each WebSocket client subscribes to a `broadcast::Sender<WatcherEvent>`. When the watcher flushes a batch, it broadcasts a `WatcherEvent`; the WS handler converts it to `WorkItemChanged` and pushes it to the client. Frontend gets live updates with no polling.
|
||||||
|
|
||||||
- **`create_story` simplified** (`server/src/http/mcp.rs`): The MCP tool now writes the file and returns — `commit = false`. The watcher picks up the new file in `1_upcoming/` within 300 ms and auto-commits `"story-kit: create {story_id}"`.
|
- **`create_story` simplified** (`server/src/http/mcp.rs`): The MCP tool now writes the file and returns — `commit = false`. The watcher picks up the new file in `1_upcoming/` within 300 ms and auto-commits `"storkit: create {story_id}"`.
|
||||||
|
|
||||||
### Questions Answered
|
### Questions Answered
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ The server is a file mover that commits. Every mutation handler does the same th
|
|||||||
|
|
||||||
2. **Debouncing**: 300 ms works well in practice. `fs::rename` is atomic and fires a single event. File writes (e.g. editing a story) may fire multiple events; 300 ms collapses them into one commit. Longer windows (500 ms+) could be used if git is slow.
|
2. **Debouncing**: 300 ms works well in practice. `fs::rename` is atomic and fires a single event. File writes (e.g. editing a story) may fire multiple events; 300 ms collapses them into one commit. Longer windows (500 ms+) could be used if git is slow.
|
||||||
|
|
||||||
3. **Deterministic commit messages**: Yes — directory name → action mapping is clean. Stage `1_upcoming` → `"story-kit: create {item_id}"`, `2_current` → `"story-kit: start {item_id}"`, `3_qa` → `"story-kit: queue {item_id} for QA"`, `4_merge` → `"story-kit: queue {item_id} for merge"`, `5_archived` → `"story-kit: accept {item_id}"`.
|
3. **Deterministic commit messages**: Yes — directory name → action mapping is clean. Stage `1_upcoming` → `"storkit: create {item_id}"`, `2_current` → `"storkit: start {item_id}"`, `3_qa` → `"storkit: queue {item_id} for QA"`, `4_merge` → `"storkit: queue {item_id} for merge"`, `5_archived` → `"storkit: accept {item_id}"`.
|
||||||
|
|
||||||
4. **Race conditions**: The watcher uses synchronous `git` subprocess calls inside the debounce flush. Since we're on a dedicated thread with no parallelism, there's no concurrent commit risk within the watcher. If a mutation handler commits first, `git commit` exits with "nothing to commit" and the watcher skips gracefully while still broadcasting the event.
|
4. **Race conditions**: The watcher uses synchronous `git` subprocess calls inside the debounce flush. Since we're on a dedicated thread with no parallelism, there's no concurrent commit risk within the watcher. If a mutation handler commits first, `git commit` exits with "nothing to commit" and the watcher skips gracefully while still broadcasting the event.
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ As a Story Kit user, I want every project initialised by Story Kit to have a scr
|
|||||||
- [ ] The Rust server can invoke script/test as the canonical way to run all tests for any project
|
- [ ] The Rust server can invoke script/test as the canonical way to run all tests for any project
|
||||||
- [ ] Agents use script/test instead of guessing test commands — they only need to check output if exit code is non-zero, saving LLM tokens
|
- [ ] Agents use script/test instead of guessing test commands — they only need to check output if exit code is non-zero, saving LLM tokens
|
||||||
- [ ] script/test exits 0 on success, non-zero on failure — agents treat it as a single pass/fail gate without parsing output on success
|
- [ ] script/test exits 0 on success, non-zero on failure — agents treat it as a single pass/fail gate without parsing output on success
|
||||||
- [ ] For this project (story-kit-app), script/test runs cargo test, pnpm test, and pnpm test:e2e
|
- [ ] For this project (storkit-app), script/test runs cargo test, pnpm test, and pnpm test:e2e
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ name: "Server-owned agent completion: remove report_completion dependency"
|
|||||||
|
|
||||||
## User Story
|
## User Story
|
||||||
|
|
||||||
As a developer using story-kit, I want the server to automatically run acceptance
|
As a developer using storkit, I want the server to automatically run acceptance
|
||||||
gates and advance the pipeline when an agent process exits, so that the pipeline
|
gates and advance the pipeline when an agent process exits, so that the pipeline
|
||||||
does not stall when an agent forgets or fails to call `report_completion`.
|
does not stall when an agent forgets or fails to call `report_completion`.
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ GET /api/health returns 404 not found. The server should have a health check end
|
|||||||
|
|
||||||
## How to Reproduce
|
## How to Reproduce
|
||||||
|
|
||||||
1. Start the story-kit server
|
1. Start the storkit server
|
||||||
2. curl http://localhost:3001/api/health
|
2. curl http://localhost:3001/api/health
|
||||||
3. Observe 404 not found response
|
3. Observe 404 not found response
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ The correct mechanism for non-interactive permission handling is the `--permissi
|
|||||||
|
|
||||||
## How to Reproduce
|
## How to Reproduce
|
||||||
|
|
||||||
1. Start the story-kit server
|
1. Start the storkit server
|
||||||
2. Open the web UI and select claude-code-pty as the model
|
2. Open the web UI and select claude-code-pty as the model
|
||||||
3. Send a message that triggers a tool requiring permission (e.g. "search the web for something")
|
3. Send a message that triggers a tool requiring permission (e.g. "search the web for something")
|
||||||
4. Observe that no permission dialog appears — the tool either auto-approves or the denial appears as text in the tool drawer
|
4. Observe that no permission dialog appears — the tool either auto-approves or the denial appears as text in the tool drawer
|
||||||
@@ -54,7 +54,7 @@ A full-screen permission dialog appears showing the tool name and input, with Ap
|
|||||||
- On receiving `WsRequest::PermissionResponse` from the client, send the decision back through the oneshot sender
|
- On receiving `WsRequest::PermissionResponse` from the client, send the decision back through the oneshot sender
|
||||||
|
|
||||||
### 5. Update Claude Code spawning (`server/src/llm/providers/claude_code.rs`)
|
### 5. Update Claude Code spawning (`server/src/llm/providers/claude_code.rs`)
|
||||||
- Add `--permission-prompt-tool mcp__story-kit__prompt_permission` to the CLI args
|
- Add `--permission-prompt-tool mcp__storkit__prompt_permission` to the CLI args
|
||||||
- Remove `PermissionReqMsg` struct and `permission_tx` parameter (no longer needed — permissions flow through MCP, not PTY)
|
- Remove `PermissionReqMsg` struct and `permission_tx` parameter (no longer needed — permissions flow through MCP, not PTY)
|
||||||
- Clean up the triple-duplicate `permission_request` match arms (dead code from story 80 merge)
|
- Clean up the triple-duplicate `permission_request` match arms (dead code from story 80 merge)
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ Determine how to stop the filesystem watcher from auto-committing every pipeline
|
|||||||
## Context
|
## Context
|
||||||
|
|
||||||
The watcher in `server/src/io/watcher.rs` currently auto-commits every file change in `.story_kit/work/`. A single story run generates 5+ commits just from pipeline moves:
|
The watcher in `server/src/io/watcher.rs` currently auto-commits every file change in `.story_kit/work/`. A single story run generates 5+ commits just from pipeline moves:
|
||||||
- `story-kit: create 42_story_foo`
|
- `storkit: create 42_story_foo`
|
||||||
- `story-kit: start 42_story_foo`
|
- `storkit: start 42_story_foo`
|
||||||
- `story-kit: queue 42_story_foo for QA`
|
- `storkit: queue 42_story_foo for QA`
|
||||||
- `story-kit: queue 42_story_foo for merge`
|
- `storkit: queue 42_story_foo for merge`
|
||||||
- `story-kit: accept 42_story_foo`
|
- `storkit: accept 42_story_foo`
|
||||||
|
|
||||||
Since story runs complete relatively quickly, the intermediate state (current/qa/merge) is transient and doesn't need to be committed. Only creation and archival are meaningful checkpoints.
|
Since story runs complete relatively quickly, the intermediate state (current/qa/merge) is transient and doesn't need to be committed. Only creation and archival are meaningful checkpoints.
|
||||||
|
|
||||||
@@ -105,8 +105,8 @@ Prototype implemented: added `COMMIT_WORTHY_STAGES` constant and `should_commit_
|
|||||||
- All 872 tests pass, clippy clean
|
- All 872 tests pass, clippy clean
|
||||||
|
|
||||||
A full story run will now produce only 2 pipeline commits instead of 5+:
|
A full story run will now produce only 2 pipeline commits instead of 5+:
|
||||||
- `story-kit: create 42_story_foo` (creation in `1_upcoming`)
|
- `storkit: create 42_story_foo` (creation in `1_upcoming`)
|
||||||
- `story-kit: accept 42_story_foo` (archival in `6_archived`)
|
- `storkit: accept 42_story_foo` (archival in `6_archived`)
|
||||||
|
|
||||||
The intermediate moves (`start`, `queue for QA`, `queue for merge`, `done`) are still broadcast to WebSocket clients for real-time frontend updates, but no longer clutter git history.
|
The intermediate moves (`start`, `queue for QA`, `queue for merge`, `done`) are still broadcast to WebSocket clients for real-time frontend updates, but no longer clutter git history.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user