huskies: merge 1031
This commit is contained in:
@@ -15,6 +15,7 @@ use crate::http::workflow::{
|
||||
use crate::io::story_metadata::parse_unchecked_todos;
|
||||
use crate::service::story::parse_test_cases;
|
||||
use crate::slog_warn;
|
||||
use crate::validation::{AddCriterionRequest, EditCriterionRequest};
|
||||
#[allow(unused_imports)]
|
||||
use crate::workflow::{
|
||||
TestCaseResult, TestStatus, WorkflowState, evaluate_acceptance_with_coverage,
|
||||
@@ -268,13 +269,10 @@ pub(crate) fn tool_edit_criterion(args: &Value, ctx: &AppContext) -> Result<Stri
|
||||
.get("criterion_index")
|
||||
.and_then(|v| v.as_u64())
|
||||
.ok_or("Missing required argument: criterion_index")? as usize;
|
||||
let new_text = args
|
||||
.get("new_text")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or("Missing required argument: new_text")?;
|
||||
let req = EditCriterionRequest::from_json(args)?;
|
||||
|
||||
let root = ctx.state.get_project_root()?;
|
||||
edit_criterion_in_file(&root, story_id, criterion_index, new_text)?;
|
||||
edit_criterion_in_file(&root, story_id, criterion_index, req.new_text.as_ref())?;
|
||||
|
||||
Ok(format!(
|
||||
"Criterion {criterion_index} updated for story '{story_id}'."
|
||||
@@ -286,16 +284,14 @@ pub(crate) fn tool_add_criterion(args: &Value, ctx: &AppContext) -> Result<Strin
|
||||
.get("story_id")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or("Missing required argument: story_id")?;
|
||||
let criterion = args
|
||||
.get("criterion")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or("Missing required argument: criterion")?;
|
||||
let req = AddCriterionRequest::from_json(args)?;
|
||||
|
||||
let root = ctx.state.get_project_root()?;
|
||||
add_criterion_to_file(&root, story_id, criterion)?;
|
||||
add_criterion_to_file(&root, story_id, req.criterion.as_ref())?;
|
||||
|
||||
Ok(format!(
|
||||
"Added criterion to story '{story_id}': - [ ] {criterion}"
|
||||
"Added criterion to story '{story_id}': - [ ] {}",
|
||||
req.criterion.as_ref()
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use crate::http::context::AppContext;
|
||||
use crate::http::workflow::update_story_in_file;
|
||||
use crate::slog_warn;
|
||||
use crate::validation::UpdateStoryRequest;
|
||||
use serde_json::Value;
|
||||
|
||||
pub(crate) fn tool_update_story(args: &Value, ctx: &AppContext) -> Result<String, String> {
|
||||
@@ -10,23 +11,20 @@ pub(crate) fn tool_update_story(args: &Value, ctx: &AppContext) -> Result<String
|
||||
.get("story_id")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or("Missing required argument: story_id")?;
|
||||
let user_story = args.get("user_story").and_then(|v| v.as_str());
|
||||
let description = args.get("description").and_then(|v| v.as_str());
|
||||
|
||||
let req = UpdateStoryRequest::from_json(args)?;
|
||||
|
||||
// Explicit top-level args map onto typed CRDT registers directly (story 929:
|
||||
// no YAML front-matter writes). The `front_matter` object is the legacy
|
||||
// escape hatch; every known key is recognised and routed below, and any
|
||||
// unknown key is rejected loudly rather than silently flushed to disk.
|
||||
if let Some(name) = args.get("name").and_then(|v| v.as_str()) {
|
||||
if name.trim().is_empty() {
|
||||
return Err("name must not be empty".to_string());
|
||||
}
|
||||
if !crate::crdt_state::set_name(story_id, Some(name)) {
|
||||
return Err(format!(
|
||||
"Story '{story_id}' not found in CRDT — name was not updated. \
|
||||
The story may not exist or may not yet be registered."
|
||||
));
|
||||
}
|
||||
if let Some(ref name) = req.name
|
||||
&& !crate::crdt_state::set_name(story_id, Some(name.as_ref()))
|
||||
{
|
||||
return Err(format!(
|
||||
"Story '{story_id}' not found in CRDT — name was not updated. \
|
||||
The story may not exist or may not yet be registered."
|
||||
));
|
||||
}
|
||||
if let Some(agent) = args.get("agent").and_then(|v| v.as_str()) {
|
||||
crate::crdt_state::set_agent(story_id, agent.parse::<crate::config::AgentName>().ok());
|
||||
@@ -46,11 +44,10 @@ pub(crate) fn tool_update_story(args: &Value, ctx: &AppContext) -> Result<String
|
||||
);
|
||||
}
|
||||
"name" => {
|
||||
let s = value.as_str().filter(|s| !s.trim().is_empty());
|
||||
if s.is_none() {
|
||||
return Err("name must not be empty".to_string());
|
||||
}
|
||||
if !crate::crdt_state::set_name(story_id, s) {
|
||||
let raw = value.as_str().unwrap_or("");
|
||||
let validated = crate::validation::StoryName::parse(raw)
|
||||
.map_err(|errs| crate::validation::format_errors_as_json(&errs))?;
|
||||
if !crate::crdt_state::set_name(story_id, Some(validated.as_ref())) {
|
||||
return Err(format!(
|
||||
"Story '{story_id}' not found in CRDT — name was not updated."
|
||||
));
|
||||
@@ -188,8 +185,13 @@ pub(crate) fn tool_update_story(args: &Value, ctx: &AppContext) -> Result<String
|
||||
let root = ctx.state.get_project_root()?;
|
||||
|
||||
// Only call update_story_in_file when there is body content to update.
|
||||
if user_story.is_some() || description.is_some() {
|
||||
update_story_in_file(&root, story_id, user_story, description)?;
|
||||
if req.user_story.is_some() || req.description.is_some() {
|
||||
update_story_in_file(
|
||||
&root,
|
||||
story_id,
|
||||
req.user_story.as_ref().map(|d| d.as_str()),
|
||||
req.description.as_ref().map(|d| d.as_str()),
|
||||
)?;
|
||||
}
|
||||
|
||||
// Bug 503: warn if any depends_on in the (now updated) story points at an archived story.
|
||||
|
||||
Reference in New Issue
Block a user