story-kit: merge 164_bug_dev_process_readme_documents_wrong_pipeline_stages
This commit is contained in:
@@ -56,7 +56,8 @@ project_root/
|
|||||||
│ ├── 2_current/ # Work in progress
|
│ ├── 2_current/ # Work in progress
|
||||||
│ ├── 3_qa/ # QA review
|
│ ├── 3_qa/ # QA review
|
||||||
│ ├── 4_merge/ # Ready to merge to master
|
│ ├── 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)
|
├── worktrees/ # Agent worktrees (managed by the server)
|
||||||
├── specs/ # Minimal guardrails (context + stack)
|
├── specs/ # Minimal guardrails (context + stack)
|
||||||
│ ├── 00_CONTEXT.md # High-level goals, domain definition, and glossary
|
│ ├── 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:
|
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
|
### Filesystem Watcher
|
||||||
|
|
||||||
@@ -119,10 +122,10 @@ When the user asks for a feature, follow this 4-step loop strictly:
|
|||||||
### Step 3: Verification (Close)
|
### 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:** 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:** 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/`.
|
* **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 Archived:** After acceptance, move the story from `work/2_current/` (or `work/4_merge/`) to `work/5_archived/`.
|
* **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:
|
* **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
|
2. Commit both changes to the feature branch
|
||||||
3. Perform the squash merge: `git merge --squash feature/story-name`
|
3. Perform the squash merge: `git merge --squash feature/story-name`
|
||||||
4. Commit to master with a comprehensive commit message
|
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:
|
* The only files that should exist after story completion:
|
||||||
* Updated code in `src/`
|
* Updated code in `src/`
|
||||||
* Updated guardrails in `specs/` (if needed)
|
* 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.
|
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).
|
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.
|
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
|
7. **No Guardrail Update Needed:** Unless the bug reveals a missing constraint
|
||||||
|
|
||||||
### Bug vs Story vs Spike
|
### 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)
|
* **Recommendation:** Next step (Story, Bug, or No Action)
|
||||||
2. **Execute Research:** Stay within the timebox. No production code changes.
|
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.
|
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
|
### Spike Output
|
||||||
* Decision and evidence, not production code
|
* 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.
|
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?").
|
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`.
|
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.
|
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.
|
6. **Draft Stack:** Write `specs/tech/STACK.md` based on best practices for that language.
|
||||||
7. **Wait:** Ask the user for "Story #1".
|
7. **Wait:** Ask the user for "Story #1".
|
||||||
|
|||||||
@@ -67,12 +67,10 @@ struct WorktreeListEntry {
|
|||||||
/// response so the agents panel is not cluttered with old completed items on
|
/// response so the agents panel is not cluttered with old completed items on
|
||||||
/// frontend startup.
|
/// frontend startup.
|
||||||
pub fn story_is_archived(project_root: &path::Path, story_id: &str) -> bool {
|
pub fn story_is_archived(project_root: &path::Path, story_id: &str) -> bool {
|
||||||
project_root
|
let work = project_root.join(".story_kit").join("work");
|
||||||
.join(".story_kit")
|
let filename = format!("{story_id}.md");
|
||||||
.join("work")
|
work.join("5_done").join(&filename).exists()
|
||||||
.join("5_archived")
|
|| work.join("6_archived").join(&filename).exists()
|
||||||
.join(format!("{story_id}.md"))
|
|
||||||
.exists()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AgentsApi {
|
pub struct AgentsApi {
|
||||||
@@ -298,29 +296,39 @@ mod tests {
|
|||||||
use crate::agents::AgentStatus;
|
use crate::agents::AgentStatus;
|
||||||
use tempfile::TempDir;
|
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 root = tmp.path().to_path_buf();
|
||||||
let archived = root
|
for stage in &["5_done", "6_archived"] {
|
||||||
.join(".story_kit")
|
std::fs::create_dir_all(root.join(".story_kit").join("work").join(stage)).unwrap();
|
||||||
.join("work")
|
}
|
||||||
.join("5_archived");
|
|
||||||
std::fs::create_dir_all(&archived).unwrap();
|
|
||||||
root
|
root
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn story_is_archived_false_when_file_absent() {
|
fn story_is_archived_false_when_file_absent() {
|
||||||
let tmp = TempDir::new().unwrap();
|
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"));
|
assert!(!story_is_archived(&root, "79_story_foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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 tmp = TempDir::new().unwrap();
|
||||||
let root = make_archived_dir(&tmp);
|
let root = make_work_dirs(&tmp);
|
||||||
std::fs::write(
|
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",
|
"---\nname: test\n---\n",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -330,11 +338,11 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn list_agents_excludes_archived_stories() {
|
async fn list_agents_excludes_archived_stories() {
|
||||||
let tmp = TempDir::new().unwrap();
|
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(
|
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",
|
"---\nname: archived story\n---\n",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user