story-kit: merge 164_bug_dev_process_readme_documents_wrong_pipeline_stages

This commit is contained in:
Dave
2026-02-24 18:21:32 +00:00
parent 5ff213b3c5
commit d62f679fed
2 changed files with 39 additions and 28 deletions

View File

@@ -56,7 +56,8 @@ project_root/
│ ├── 2_current/ # Work in progress
│ ├── 3_qa/ # QA review
│ ├── 4_merge/ # Ready to merge to master
── 5_archived/ # Completed work
── 5_done/ # Merged and completed (auto-swept to 6_archived after 4 hours)
│ └── 6_archived/ # Long-term archive
├── worktrees/ # Agent worktrees (managed by the server)
├── specs/ # Minimal guardrails (context + stack)
│ ├── 00_CONTEXT.md # High-level goals, domain definition, and glossary
@@ -77,7 +78,9 @@ All work items (stories, bugs, spikes) live in the same `work/` pipeline. Items
Items move through stages by moving the file between directories:
`1_upcoming` → `2_current` → `3_qa` → `4_merge` → `5_archived`
`1_upcoming` → `2_current` → `3_qa` → `4_merge` → `5_done` → `6_archived`
Items in `5_done` are auto-swept to `6_archived` after 4 hours by the server.
### Filesystem Watcher
@@ -119,10 +122,10 @@ When the user asks for a feature, follow this 4-step loop strictly:
### Step 3: Verification (Close)
* **Action:** For each Acceptance Criterion in the story, write a failing test (red), mark the criterion as tested, make the test pass (green), and refactor if needed. Keep only one failing test at a time.
* **Action:** Run compilation and make sure it succeeds without errors. Consult `specs/tech/STACK.md` and run all required linters listed there (treat warnings as errors). Run tests and make sure they all pass before proceeding. Ask questions here if needed.
* **Action:** Do not accept stories yourself. Ask the user if they accept the story. If they agree, move the story file to `work/5_archived/`.
* **Move to Archived:** After acceptance, move the story from `work/2_current/` (or `work/4_merge/`) to `work/5_archived/`.
* **Action:** Do not accept stories yourself. Ask the user if they accept the story. If they agree, move the story file to `work/5_done/`.
* **Move to Done:** After acceptance, move the story from `work/2_current/` (or `work/4_merge/`) to `work/5_done/`.
* **Action:** When the user accepts:
1. Move the story file to `work/5_archived/`
1. Move the story file to `work/5_done/`
2. Commit both changes to the feature branch
3. Perform the squash merge: `git merge --squash feature/story-name`
4. Commit to master with a comprehensive commit message
@@ -137,7 +140,7 @@ When the user asks for a feature, follow this 4-step loop strictly:
* The only files that should exist after story completion:
* Updated code in `src/`
* Updated guardrails in `specs/` (if needed)
* Archived work item in `work/5_archived/`
* Archived work item in `work/5_done/` (server auto-sweeps to `work/6_archived/` after 4 hours)
---
@@ -163,7 +166,7 @@ Not everything needs to be a full story. Simple bugs can skip the story process:
3. **Write a Failing Test:** Before fixing the bug, write a test that reproduces it (red). This proves the bug exists and prevents regression.
4. **Fix the Bug:** Make minimal code changes to make the test pass (green).
5. **User Testing:** Let the user verify the fix in the worktree before merging. Do not proceed until they confirm.
6. **Archive & Merge:** Move the bug file to `work/5_archived/`, squash merge to master, delete the worktree and branch.
6. **Archive & Merge:** Move the bug file to `work/5_done/`, squash merge to master, delete the worktree and branch.
7. **No Guardrail Update Needed:** Unless the bug reveals a missing constraint
### Bug vs Story vs Spike
@@ -192,7 +195,7 @@ Not everything needs a story or bug fix. Spikes are time-boxed investigations to
* **Recommendation:** Next step (Story, Bug, or No Action)
2. **Execute Research:** Stay within the timebox. No production code changes.
3. **Escalate if Needed:** If implementation is required, open a Story or Bug and follow that workflow.
4. **Archive:** Move the spike file to `work/5_archived/`.
4. **Archive:** Move the spike file to `work/5_done/`.
### Spike Output
* Decision and evidence, not production code
@@ -218,7 +221,7 @@ If a user hands you this document and says "Apply this process to my project":
1. **Check for MCP Tools:** Look for `.mcp.json` in the project root. If it exists, you have programmatic access to workflow tools and agent spawning capabilities.
2. **Analyze the Request:** Ask for the high-level goal ("What are we building?") and the tech preferences ("Rust or Python?").
3. **Git Check:** Check if the directory is a git repository (`git status`). If not, run `git init`.
4. **Scaffold:** Run commands to create the `work/` and `specs/` folders with the 5-stage pipeline (`work/1_upcoming/` through `work/5_archived/`).
4. **Scaffold:** Run commands to create the `work/` and `specs/` folders with the 6-stage pipeline (`work/1_upcoming/` through `work/6_archived/`).
5. **Draft Context:** Write `specs/00_CONTEXT.md` based on the user's answer.
6. **Draft Stack:** Write `specs/tech/STACK.md` based on best practices for that language.
7. **Wait:** Ask the user for "Story #1".

View File

@@ -67,12 +67,10 @@ struct WorktreeListEntry {
/// response so the agents panel is not cluttered with old completed items on
/// frontend startup.
pub fn story_is_archived(project_root: &path::Path, story_id: &str) -> bool {
project_root
.join(".story_kit")
.join("work")
.join("5_archived")
.join(format!("{story_id}.md"))
.exists()
let work = project_root.join(".story_kit").join("work");
let filename = format!("{story_id}.md");
work.join("5_done").join(&filename).exists()
|| work.join("6_archived").join(&filename).exists()
}
pub struct AgentsApi {
@@ -298,29 +296,39 @@ mod tests {
use crate::agents::AgentStatus;
use tempfile::TempDir;
fn make_archived_dir(tmp: &TempDir) -> path::PathBuf {
fn make_work_dirs(tmp: &TempDir) -> path::PathBuf {
let root = tmp.path().to_path_buf();
let archived = root
.join(".story_kit")
.join("work")
.join("5_archived");
std::fs::create_dir_all(&archived).unwrap();
for stage in &["5_done", "6_archived"] {
std::fs::create_dir_all(root.join(".story_kit").join("work").join(stage)).unwrap();
}
root
}
#[test]
fn story_is_archived_false_when_file_absent() {
let tmp = TempDir::new().unwrap();
let root = make_archived_dir(&tmp);
let root = make_work_dirs(&tmp);
assert!(!story_is_archived(&root, "79_story_foo"));
}
#[test]
fn story_is_archived_true_when_file_present() {
fn story_is_archived_true_when_file_in_5_done() {
let tmp = TempDir::new().unwrap();
let root = make_archived_dir(&tmp);
let root = make_work_dirs(&tmp);
std::fs::write(
root.join(".story_kit/work/5_archived/79_story_foo.md"),
root.join(".story_kit/work/5_done/79_story_foo.md"),
"---\nname: test\n---\n",
)
.unwrap();
assert!(story_is_archived(&root, "79_story_foo"));
}
#[test]
fn story_is_archived_true_when_file_in_6_archived() {
let tmp = TempDir::new().unwrap();
let root = make_work_dirs(&tmp);
std::fs::write(
root.join(".story_kit/work/6_archived/79_story_foo.md"),
"---\nname: test\n---\n",
)
.unwrap();
@@ -330,11 +338,11 @@ mod tests {
#[tokio::test]
async fn list_agents_excludes_archived_stories() {
let tmp = TempDir::new().unwrap();
let root = make_archived_dir(&tmp);
let root = make_work_dirs(&tmp);
// Place an archived story file
// Place an archived story file in 6_archived
std::fs::write(
root.join(".story_kit/work/5_archived/79_story_archived.md"),
root.join(".story_kit/work/6_archived/79_story_archived.md"),
"---\nname: archived story\n---\n",
)
.unwrap();