summaryrefslogtreecommitdiff
path: root/makima/src/db/repository.rs
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-15 00:23:44 +0000
committersoryu <soryu@soryu.co>2026-01-15 00:23:47 +0000
commiteff0d844ca6e35bfbc2d5fdaa2d2f92177611f2e (patch)
tree90d87d6daf9dd78c31e4b816bb1d282db73821dd /makima/src/db/repository.rs
parent87044a747b47bd83249d61a45842c7f7b2eae56d (diff)
downloadsoryu-eff0d844ca6e35bfbc2d5fdaa2d2f92177611f2e.tar.gz
soryu-eff0d844ca6e35bfbc2d5fdaa2d2f92177611f2e.zip
Contract type system
Diffstat (limited to 'makima/src/db/repository.rs')
-rw-r--r--makima/src/db/repository.rs39
1 files changed, 30 insertions, 9 deletions
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs
index 3b911c2..7933f1e 100644
--- a/makima/src/db/repository.rs
+++ b/makima/src/db/repository.rs
@@ -2019,29 +2019,50 @@ pub async fn create_contract_for_owner(
owner_id: Uuid,
req: CreateContractRequest,
) -> Result<Contract, sqlx::Error> {
- // Use provided initial_phase or default to "research"
- let phase = req.initial_phase.as_deref().unwrap_or("research");
+ // Default contract type is "simple"
+ let contract_type = req.contract_type.as_deref().unwrap_or("simple");
- // Validate the phase
- let valid_phases = ["research", "specify", "plan", "execute", "review"];
+ // Validate contract type
+ let valid_types = ["simple", "specification"];
+ if !valid_types.contains(&contract_type) {
+ return Err(sqlx::Error::Protocol(format!(
+ "Invalid contract_type '{}'. Must be one of: {}",
+ contract_type,
+ valid_types.join(", ")
+ )));
+ }
+
+ // Determine valid phases based on contract type
+ let (valid_phases, default_phase): (&[&str], &str) = match contract_type {
+ "simple" => (&["plan", "execute"], "plan"),
+ "specification" => (&["research", "specify", "plan", "execute", "review"], "research"),
+ _ => (&["plan", "execute"], "plan"),
+ };
+
+ // Use provided initial_phase or default based on contract type
+ let phase = req.initial_phase.as_deref().unwrap_or(default_phase);
+
+ // Validate the phase is valid for this contract type
if !valid_phases.contains(&phase) {
return Err(sqlx::Error::Protocol(format!(
- "Invalid initial_phase '{}'. Must be one of: {}",
+ "Invalid initial_phase '{}' for contract type '{}'. Must be one of: {}",
phase,
+ contract_type,
valid_phases.join(", ")
)));
}
sqlx::query_as::<_, Contract>(
r#"
- INSERT INTO contracts (owner_id, name, description, phase)
- VALUES ($1, $2, $3, $4)
+ INSERT INTO contracts (owner_id, name, description, contract_type, phase)
+ VALUES ($1, $2, $3, $4, $5)
RETURNING *
"#,
)
.bind(owner_id)
.bind(&req.name)
.bind(&req.description)
+ .bind(contract_type)
.bind(phase)
.fetch_one(pool)
.await
@@ -2074,7 +2095,7 @@ pub async fn list_contracts_for_owner(
sqlx::query_as::<_, ContractSummary>(
r#"
SELECT
- c.id, c.name, c.description, c.phase, c.status,
+ c.id, c.name, c.description, c.contract_type, c.phase, c.status,
c.version, c.created_at,
(SELECT COUNT(*) FROM files WHERE contract_id = c.id) as file_count,
(SELECT COUNT(*) FROM tasks WHERE contract_id = c.id) as task_count,
@@ -2098,7 +2119,7 @@ pub async fn get_contract_summary_for_owner(
sqlx::query_as::<_, ContractSummary>(
r#"
SELECT
- c.id, c.name, c.description, c.phase, c.status,
+ c.id, c.name, c.description, c.contract_type, c.phase, c.status,
c.version, c.created_at,
(SELECT COUNT(*) FROM files WHERE contract_id = c.id) as file_count,
(SELECT COUNT(*) FROM tasks WHERE contract_id = c.id) as task_count,