Remove test_plan gate from the codebase

The test_plan field was a gate from the old interactive web UI workflow
where a human would approve a test plan before the LLM could write code.
With autonomous coder agents, this gate is dead weight — coders sometimes
obey the README's "wait for approval" instruction and produce no code.

Removes: TestPlanStatus enum, ensure_test_plan_approved checks in fs/shell,
set_test_plan MCP tool + handler, test_plan from story/bug front matter
creation, test_plan validation in validate_story_dirs, and all related tests.
Updates README to remove Step 2 (Test Planning) and renumber steps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dave
2026-02-23 19:12:05 +00:00
parent cc2511b792
commit 31037f5bf5
7 changed files with 23 additions and 363 deletions

View File

@@ -1,7 +1,5 @@
use crate::io::story_metadata::{TestPlanStatus, parse_front_matter};
use crate::state::SessionState;
use serde::Serialize;
use std::fs;
use std::path::PathBuf;
use std::process::Command;
@@ -10,30 +8,6 @@ fn get_project_root(state: &SessionState) -> Result<PathBuf, String> {
state.get_project_root()
}
async fn ensure_test_plan_approved(root: PathBuf) -> Result<(), String> {
let approved = tokio::task::spawn_blocking(move || {
let story_path = root
.join(".story_kit")
.join("stories")
.join("current")
.join("26_establish_tdd_workflow_and_gates.md");
let contents = fs::read_to_string(&story_path)
.map_err(|e| format!("Failed to read story file for test plan approval: {e}"))?;
let metadata = parse_front_matter(&contents)
.map_err(|e| format!("Failed to parse story front matter: {e:?}"))?;
Ok::<bool, String>(matches!(metadata.test_plan, Some(TestPlanStatus::Approved)))
})
.await
.map_err(|e| format!("Task failed: {e}"))??;
if approved {
Ok(())
} else {
Err("Test plan is not approved for the current story.".to_string())
}
}
#[derive(Serialize, Debug, poem_openapi::Object)]
pub struct CommandOutput {
pub stdout: String,
@@ -80,7 +54,6 @@ pub async fn exec_shell(
state: &SessionState,
) -> Result<CommandOutput, String> {
let root = get_project_root(state)?;
ensure_test_plan_approved(root.clone()).await?;
exec_shell_impl(command, args, root).await
}
@@ -89,24 +62,6 @@ mod tests {
use super::*;
use tempfile::tempdir;
#[tokio::test]
async fn exec_shell_requires_approved_test_plan() {
let dir = tempdir().expect("tempdir");
let state = SessionState::default();
{
let mut root = state.project_root.lock().expect("lock project root");
*root = Some(dir.path().to_path_buf());
}
let result = exec_shell("ls".to_string(), Vec::new(), &state).await;
assert!(
result.is_err(),
"expected shell execution to be blocked when test plan is not approved"
);
}
#[tokio::test]
async fn exec_shell_impl_rejects_disallowed_command() {
let dir = tempdir().unwrap();