fix: resolve 17 P2 defects and 5 P3 defects from pre-launch audit
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Batch fix covering multiple modules:
- P2-01: HandRegistry Semaphore-based max_concurrent enforcement
- P2-03: Populate toolCount/metricCount from Hand trait methods
- P2-06: heartbeat_update_config minimum interval validation
- P2-07: ReflectionResult used_fallback marker for rule-based fallback
- P2-08/09: identity_propose_change parameter naming consistency
- P2-10: ClassroomMetadata is_placeholder flag for LLM failure
- P2-11: classroomStore userDidCloseDuringGeneration intent tracking
- P2-12: workflowStore pipeline_create sends actionType
- P2-13/14: PipelineInfo step_count + PipelineStepInfo for proper step mapping
- P2-15: Pipe transform support in context.resolve (8 transforms)
- P2-16: Mustache {{...}} → \${...} auto-normalization
- P2-17: SaaSLogin password placeholder 6→8
- P2-19: serialize_skill_md + update_skill preserve tools field
- P2-22: ToolOutputGuard sensitive patterns from warn→block
- P2-23: Mutex::unwrap() → unwrap_or_else in relay/service.rs
- P3-01/03/07/08/09: Various P3 fixes
- DEFECT_LIST.md: comprehensive status sync (43/51 fixed, 8 remaining)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -40,10 +40,18 @@ pub struct UpdatePipelineRequest {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct WorkflowStepInput {
|
||||
/// Action type discriminator (P2-12: enables non-Hand action types)
|
||||
pub action_type: Option<String>,
|
||||
pub hand_name: String,
|
||||
pub name: Option<String>,
|
||||
pub params: Option<HashMap<String, Value>>,
|
||||
pub condition: Option<String>,
|
||||
/// LLM generation template (for action_type = "llm_generate")
|
||||
pub template: Option<String>,
|
||||
/// Parallel collection path (for action_type = "parallel")
|
||||
pub each: Option<String>,
|
||||
/// Condition branches (for action_type = "condition")
|
||||
pub branches: Option<HashMap<String, Value>>,
|
||||
}
|
||||
|
||||
/// Create a new pipeline as a YAML file
|
||||
@@ -74,18 +82,57 @@ pub async fn pipeline_create(
|
||||
return Err(format!("Pipeline file already exists: {}", file_path.display()));
|
||||
}
|
||||
|
||||
// Build Pipeline struct
|
||||
// P2-12: Build PipelineSteps with proper action type from WorkflowStepInput
|
||||
let steps: Vec<PipelineStep> = request.steps.into_iter().enumerate().map(|(i, s)| {
|
||||
let step_id = s.name.clone().unwrap_or_else(|| format!("step-{}", i + 1));
|
||||
PipelineStep {
|
||||
id: step_id,
|
||||
action: Action::Hand {
|
||||
let params_map: HashMap<String, String> = s.params
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.to_string()))
|
||||
.collect();
|
||||
|
||||
let action = match s.action_type.as_deref().unwrap_or("hand") {
|
||||
"llm_generate" => Action::LlmGenerate {
|
||||
template: s.template.unwrap_or_default(),
|
||||
input: params_map,
|
||||
model: None,
|
||||
temperature: None,
|
||||
max_tokens: None,
|
||||
json_mode: false,
|
||||
},
|
||||
"parallel" => Action::Parallel {
|
||||
each: s.each.unwrap_or_else(|| "item".to_string()),
|
||||
step: Box::new(PipelineStep {
|
||||
id: format!("{}-body", step_id),
|
||||
action: Action::Hand {
|
||||
hand_id: s.hand_name.clone(),
|
||||
hand_action: "execute".to_string(),
|
||||
params: params_map,
|
||||
},
|
||||
description: None,
|
||||
when: None,
|
||||
retry: None,
|
||||
timeout_secs: None,
|
||||
}),
|
||||
max_workers: None,
|
||||
},
|
||||
"condition" => Action::Condition {
|
||||
condition: s.condition.unwrap_or_default(),
|
||||
branches: vec![],
|
||||
default: None,
|
||||
},
|
||||
_ => Action::Hand {
|
||||
hand_id: s.hand_name.clone(),
|
||||
hand_action: "execute".to_string(),
|
||||
params: s.params.unwrap_or_default().into_iter().map(|(k, v)| (k, v.to_string())).collect(),
|
||||
params: params_map,
|
||||
},
|
||||
};
|
||||
|
||||
PipelineStep {
|
||||
id: step_id,
|
||||
action,
|
||||
description: s.name,
|
||||
when: s.condition,
|
||||
when: None,
|
||||
retry: None,
|
||||
timeout_secs: None,
|
||||
}
|
||||
@@ -156,18 +203,58 @@ pub async fn pipeline_update(
|
||||
..existing.metadata.clone()
|
||||
};
|
||||
|
||||
// P2-12: Build PipelineSteps with proper action type (mirrors pipeline_create logic)
|
||||
let updated_steps = match request.steps {
|
||||
Some(steps) => steps.into_iter().enumerate().map(|(i, s)| {
|
||||
let step_id = s.name.clone().unwrap_or_else(|| format!("step-{}", i + 1));
|
||||
PipelineStep {
|
||||
id: step_id,
|
||||
action: Action::Hand {
|
||||
let params_map: HashMap<String, String> = s.params
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.to_string()))
|
||||
.collect();
|
||||
|
||||
let action = match s.action_type.as_deref().unwrap_or("hand") {
|
||||
"llm_generate" => Action::LlmGenerate {
|
||||
template: s.template.unwrap_or_default(),
|
||||
input: params_map,
|
||||
model: None,
|
||||
temperature: None,
|
||||
max_tokens: None,
|
||||
json_mode: false,
|
||||
},
|
||||
"parallel" => Action::Parallel {
|
||||
each: s.each.unwrap_or_else(|| "item".to_string()),
|
||||
step: Box::new(PipelineStep {
|
||||
id: format!("{}-body", step_id),
|
||||
action: Action::Hand {
|
||||
hand_id: s.hand_name.clone(),
|
||||
hand_action: "execute".to_string(),
|
||||
params: params_map,
|
||||
},
|
||||
description: None,
|
||||
when: None,
|
||||
retry: None,
|
||||
timeout_secs: None,
|
||||
}),
|
||||
max_workers: None,
|
||||
},
|
||||
"condition" => Action::Condition {
|
||||
condition: s.condition.unwrap_or_default(),
|
||||
branches: vec![],
|
||||
default: None,
|
||||
},
|
||||
_ => Action::Hand {
|
||||
hand_id: s.hand_name.clone(),
|
||||
hand_action: "execute".to_string(),
|
||||
params: s.params.unwrap_or_default().into_iter().map(|(k, v)| (k, v.to_string())).collect(),
|
||||
params: params_map,
|
||||
},
|
||||
};
|
||||
|
||||
PipelineStep {
|
||||
id: step_id,
|
||||
action,
|
||||
description: s.name,
|
||||
when: s.condition,
|
||||
when: None,
|
||||
retry: None,
|
||||
timeout_secs: None,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user