summaryrefslogtreecommitdiff
path: root/makima/src/server/handlers/contract_chat.rs
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-17 06:20:07 +0000
committersoryu <soryu@soryu.co>2026-01-17 16:39:24 +0000
commitbfc5d837c6212a8253accfdf95ae1a2fd692df4e (patch)
tree0cc78ff56fd28333d1e502176873d23a26d4c4a1 /makima/src/server/handlers/contract_chat.rs
parent06fb883b2b7a49c7123722463d24b0b4e57c3277 (diff)
downloadsoryu-bfc5d837c6212a8253accfdf95ae1a2fd692df4e.tar.gz
soryu-bfc5d837c6212a8253accfdf95ae1a2fd692df4e.zip
feat: Add phase_guard for contract phase transitions
Implement phase_guard logic in the advance_phase tool. When a contract has phase_guard enabled, the phase transition now: 1. Asks for user confirmation before advancing 2. Allows users to request changes to phase deliverables 3. Passes feedback to the task without advancing if changes requested Changes: - Add phase_guard field to Contract model and CreateContractRequest - Add PhaseTransitionRequest, PhaseFileInfo, PhaseTaskInfo structs - Update ChangePhaseRequest with confirmed and feedback fields - Update ContractToolRequest::AdvancePhase with confirmed/feedback - Modify advance_phase handling in contract_chat.rs with phase_guard logic - Update change_phase endpoint in contracts.rs with phase_guard support - Add database migration for phase_guard column When phase_guard=false: Phase advances immediately (current behavior) When phase_guard=true: Returns pending_confirmation status with deliverables If user provides feedback: Returns feedback to task, doesn't advance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/src/server/handlers/contract_chat.rs')
-rw-r--r--makima/src/server/handlers/contract_chat.rs86
1 files changed, 84 insertions, 2 deletions
diff --git a/makima/src/server/handlers/contract_chat.rs b/makima/src/server/handlers/contract_chat.rs
index 48dd864..29ec620 100644
--- a/makima/src/server/handlers/contract_chat.rs
+++ b/makima/src/server/handlers/contract_chat.rs
@@ -1689,7 +1689,7 @@ async fn handle_contract_request(
}
}
- ContractToolRequest::AdvancePhase { new_phase } => {
+ ContractToolRequest::AdvancePhase { new_phase, confirmed, feedback } => {
let contract = match repository::get_contract_for_owner(pool, contract_id, owner_id).await {
Ok(Some(c)) => c,
Ok(None) => {
@@ -1723,7 +1723,88 @@ async fn handle_contract_request(
};
}
- // Update phase
+ // Check if phase_guard is enabled
+ if contract.phase_guard {
+ // If user provided feedback, return it for the task to address
+ if let Some(ref user_feedback) = feedback {
+ return ContractRequestResult {
+ success: true,
+ message: format!(
+ "Phase transition to '{}' requires changes. User feedback: {}",
+ new_phase, user_feedback
+ ),
+ data: Some(json!({
+ "status": "changes_requested",
+ "currentPhase": current_phase,
+ "requestedPhase": new_phase,
+ "feedback": user_feedback,
+ "action": "Address the user feedback and try again when ready"
+ })),
+ };
+ }
+
+ // If not confirmed, return pending confirmation with phase deliverables
+ if !confirmed {
+ // Get files created in this phase
+ let phase_files = match repository::list_files_in_contract(pool, contract_id, owner_id).await {
+ Ok(files) => files
+ .into_iter()
+ .filter(|f| f.contract_phase.as_deref() == Some(current_phase))
+ .map(|f| json!({
+ "id": f.id,
+ "name": f.name,
+ "description": f.description
+ }))
+ .collect::<Vec<_>>(),
+ Err(_) => Vec::new(),
+ };
+
+ // Get tasks completed in this contract
+ let phase_tasks = match repository::list_tasks_in_contract(pool, contract_id, owner_id).await {
+ Ok(tasks) => tasks
+ .into_iter()
+ .filter(|t| t.status == "done" || t.status == "completed")
+ .map(|t| json!({
+ "id": t.id,
+ "name": t.name,
+ "status": t.status
+ }))
+ .collect::<Vec<_>>(),
+ Err(_) => Vec::new(),
+ };
+
+ // Build deliverables summary
+ let deliverables_summary = format!(
+ "Phase '{}' deliverables: {} files created, {} tasks completed.",
+ current_phase,
+ phase_files.len(),
+ phase_tasks.len()
+ );
+
+ let transition_id = uuid::Uuid::new_v4().to_string();
+
+ return ContractRequestResult {
+ success: true,
+ message: format!(
+ "Phase transition to '{}' requires user confirmation. Review the deliverables and call advance_phase again with confirmed=true to proceed, or provide feedback to request changes.",
+ new_phase
+ ),
+ data: Some(json!({
+ "status": "pending_confirmation",
+ "transitionId": transition_id,
+ "currentPhase": current_phase,
+ "nextPhase": new_phase,
+ "deliverablesSummary": deliverables_summary,
+ "phaseFiles": phase_files,
+ "phaseTasks": phase_tasks,
+ "requiresConfirmation": true,
+ "instructions": "To proceed: call advance_phase with confirmed=true. To request changes: call advance_phase with feedback='your feedback here'"
+ })),
+ };
+ }
+ }
+
+ // Update phase (either phase_guard is disabled, or user confirmed)
match repository::change_contract_phase_for_owner(pool, contract_id, owner_id, &new_phase).await {
Ok(Some(updated)) => {
// Get deliverables for the new phase
@@ -1748,6 +1829,7 @@ async fn handle_contract_request(
current_phase, new_phase, deliverables.guidance
),
data: Some(json!({
+ "status": "advanced",
"previousPhase": current_phase,
"newPhase": updated.phase,
"phaseGuidance": deliverables.guidance,