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

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:
iven
2026-04-06 00:49:16 +08:00
parent f9e1ce1d6e
commit 26a833d1c8
25 changed files with 408 additions and 143 deletions

View File

@@ -179,6 +179,9 @@ pub struct ClassroomMetadata {
pub source_document: Option<String>,
pub model: Option<String>,
pub version: String,
/// P2-10: Whether content was generated from placeholder fallback (not LLM)
#[serde(default)]
pub is_placeholder: bool,
pub custom: serde_json::Map<String, serde_json::Value>,
}
@@ -325,6 +328,7 @@ impl GenerationPipeline {
let outline = if let Some(driver) = &self.driver {
self.generate_outline_with_llm(driver.as_ref(), &prompt, request).await?
} else {
tracing::warn!("[P2-10] No LLM driver available, using placeholder outline");
self.generate_outline_placeholder(request)
};
@@ -397,14 +401,15 @@ impl GenerationPipeline {
// Stage 0: Agent profiles
let agents = self.generate_agent_profiles(&request).await;
// Stage 1: Outline
// Stage 1: Outline — track if placeholder was used (P2-10)
let is_placeholder = self.driver.is_none();
let outline = self.generate_outline(&request).await?;
// Stage 2: Scenes
let scenes = self.generate_scenes(&outline).await?;
// Build classroom
self.build_classroom(request, outline, scenes, agents)
self.build_classroom(request, outline, scenes, agents, is_placeholder)
}
// --- LLM integration methods ---
@@ -787,6 +792,7 @@ Use Chinese if the topic is in Chinese. Include metaphors that relate to everyda
_outline: Vec<OutlineItem>,
scenes: Vec<GeneratedScene>,
agents: Vec<AgentProfile>,
is_placeholder: bool,
) -> Result<Classroom> {
let total_duration: u32 = scenes.iter()
.map(|s| s.content.duration_seconds)
@@ -814,6 +820,7 @@ Use Chinese if the topic is in Chinese. Include metaphors that relate to everyda
source_document: request.document.map(|_| "user_document".to_string()),
model: None,
version: "2.0.0".to_string(),
is_placeholder, // P2-10: mark placeholder content
custom: serde_json::Map::new(),
},
})

View File

@@ -201,7 +201,17 @@ impl Kernel {
let context = HandContext::default();
let start = std::time::Instant::now();
let hand_result = self.hands.execute(hand_id, &context, input).await;
// P2-02: Apply timeout to execute_hand_with_source (same as execute_hand)
let timeout_secs = self.hands.get_config(hand_id)
.await
.map(|c| if c.timeout_secs > 0 { c.timeout_secs } else { context.timeout_secs })
.unwrap_or(context.timeout_secs);
let hand_result = tokio::time::timeout(
std::time::Duration::from_secs(timeout_secs),
self.hands.execute(hand_id, &context, input),
).await;
let duration = start.elapsed();
// Check if cancelled during execution
@@ -217,6 +227,23 @@ impl Kernel {
self.running_hand_runs.remove(&run_id);
let completed_at = chrono::Utc::now().to_rfc3339();
// Handle timeout result
let hand_result = match hand_result {
Ok(result) => result,
Err(_) => {
// Timeout elapsed
cancel_flag.store(true, std::sync::atomic::Ordering::Relaxed);
run.status = HandRunStatus::Failed;
run.error = Some(format!("Hand execution timed out after {}s", timeout_secs));
run.duration_ms = Some(duration.as_millis() as u64);
run.completed_at = Some(completed_at);
self.memory.update_hand_run(&run).await?;
return Err(zclaw_types::ZclawError::Internal(
format!("Hand '{}' timed out after {}s", hand_id, timeout_secs)
));
}
};
match &hand_result {
Ok(res) => {
run.status = HandRunStatus::Completed;