|
8 | 8 | from maf_starter.orchestration import RunStagePauseKind, SpecialistRole, StageName, StageStatus |
9 | 9 | from maf_starter.routing_types import RouteLane |
10 | 10 |
|
| 11 | +SDLC_PHASE_ID = Literal[ |
| 12 | + "understand", |
| 13 | + "research", |
| 14 | + "analyze", |
| 15 | + "plan", |
| 16 | + "risk-assessment", |
| 17 | + "implement", |
| 18 | + "verify", |
| 19 | + "review", |
| 20 | + "improve", |
| 21 | + "document", |
| 22 | + "update-memory", |
| 23 | + "finished", |
| 24 | +] |
| 25 | +ExecutionBatch = Literal["discovery", "design", "change", "assurance", "closure"] |
| 26 | +PhaseStatus = Literal[ |
| 27 | + "pending", |
| 28 | + "ready", |
| 29 | + "running", |
| 30 | + "passed", |
| 31 | + "failed", |
| 32 | + "invalidated", |
| 33 | + "rolled-back", |
| 34 | + "waiting", |
| 35 | + "terminal", |
| 36 | +] |
| 37 | + |
11 | 38 | ProviderName = Literal[ |
12 | 39 | "ollama", |
13 | 40 | "openai", |
@@ -138,6 +165,84 @@ class StageOutputModel(BaseModel): |
138 | 165 | raw_output: str | None = None |
139 | 166 |
|
140 | 167 |
|
| 168 | +class SdlcPhaseModel(BaseModel): |
| 169 | + id: SDLC_PHASE_ID |
| 170 | + name: str |
| 171 | + batch: ExecutionBatch |
| 172 | + dependencies: list[SDLC_PHASE_ID] = Field(default_factory=list) |
| 173 | + verifier: str |
| 174 | + required_artifacts: list[str] = Field(default_factory=list) |
| 175 | + success_criteria: list[str] = Field(default_factory=list) |
| 176 | + rollback_to: SDLC_PHASE_ID | None = None |
| 177 | + max_attempts: int | None = None |
| 178 | + |
| 179 | + |
| 180 | +class SdlcProfileModel(BaseModel): |
| 181 | + kind: Literal["SdlcProfile"] = "SdlcProfile" |
| 182 | + profile_id: str |
| 183 | + profile_version: Literal["v1.1"] = "v1.1" |
| 184 | + goal_budget: int |
| 185 | + phases: list[SdlcPhaseModel] = Field(default_factory=list) |
| 186 | + goal_attempts: int | None = None |
| 187 | + iterations: int | None = None |
| 188 | + runtime_minutes: int | None = None |
| 189 | + model_calls: int | None = None |
| 190 | + no_progress_limit: int | None = None |
| 191 | + repository_overrides: dict[str, Any] = Field(default_factory=dict) |
| 192 | + |
| 193 | + |
| 194 | +class PhaseExecutionRequestModel(BaseModel): |
| 195 | + kind: Literal["PhaseExecutionRequest"] = "PhaseExecutionRequest" |
| 196 | + profile_version: Literal["v1.1"] = "v1.1" |
| 197 | + phase: SDLC_PHASE_ID |
| 198 | + batch: ExecutionBatch |
| 199 | + goal: str |
| 200 | + constraints: list[str] = Field(default_factory=list) |
| 201 | + validated_inputs: list[str] = Field(default_factory=list) |
| 202 | + prior_evidence: list[dict[str, Any]] = Field(default_factory=list) |
| 203 | + required_output_schema: str | None = None |
| 204 | + required_artifacts: list[str] = Field(default_factory=list) |
| 205 | + success_criteria: list[str] = Field(default_factory=list) |
| 206 | + verifier: str = "" |
| 207 | + failure_behavior: str | None = None |
| 208 | + rollback_behavior: str | None = None |
| 209 | + memory_candidate_fields: list[str] = Field(default_factory=list) |
| 210 | + human_escalation_conditions: list[str] = Field(default_factory=list) |
| 211 | + |
| 212 | + |
| 213 | +class PhaseExecutionResultModel(BaseModel): |
| 214 | + kind: Literal["PhaseExecutionResult"] = "PhaseExecutionResult" |
| 215 | + phase: SDLC_PHASE_ID |
| 216 | + batch: ExecutionBatch | None = None |
| 217 | + status: PhaseStatus |
| 218 | + prompt_digest: str |
| 219 | + artifacts: list[dict[str, Any]] = Field(default_factory=list) |
| 220 | + output: dict[str, Any] = Field(default_factory=dict) |
| 221 | + prompt_metadata: dict[str, Any] = Field(default_factory=dict) |
| 222 | + sanitized_prompt: str | None = None |
| 223 | + verifier: str = "" |
| 224 | + checkpoint: str | None = None |
| 225 | + |
| 226 | + |
| 227 | +class PhaseVerificationResultModel(BaseModel): |
| 228 | + kind: Literal["PhaseVerificationResult"] = "PhaseVerificationResult" |
| 229 | + phase: SDLC_PHASE_ID |
| 230 | + verifier: str |
| 231 | + outcome: Literal["passed", "failed", "inconclusive"] |
| 232 | + invalidated_phase_ids: list[SDLC_PHASE_ID] = Field(default_factory=list) |
| 233 | + evidence: list[dict[str, Any]] = Field(default_factory=list) |
| 234 | + reason: str | None = None |
| 235 | + |
| 236 | + |
| 237 | +class MemoryCandidateRecordModel(BaseModel): |
| 238 | + kind: Literal["MemoryCandidateRecord"] = "MemoryCandidateRecord" |
| 239 | + phase: SDLC_PHASE_ID |
| 240 | + version: str |
| 241 | + summary: str |
| 242 | + evidence: list[str] = Field(default_factory=list) |
| 243 | + created_at: datetime |
| 244 | + |
| 245 | + |
141 | 246 | class StageTimelineEntry(BaseModel): |
142 | 247 | stage: StageName |
143 | 248 | status: StageStatus |
@@ -240,6 +345,15 @@ class SessionSummary(BaseModel): |
240 | 345 | workspace_stale_detail: str | None = None |
241 | 346 | workspace_last_checked_at: datetime | None = None |
242 | 347 | workspace_drift_fields: list[str] = Field(default_factory=list) |
| 348 | + sdlc_profile: SdlcProfileModel | None = None |
| 349 | + current_sdlc_phase: SDLC_PHASE_ID | None = None |
| 350 | + current_sdlc_batch: ExecutionBatch | None = None |
| 351 | + current_sdlc_verifier: str | None = None |
| 352 | + current_sdlc_budget: dict[str, Any] = Field(default_factory=dict) |
| 353 | + rollback_origin: SDLC_PHASE_ID | None = None |
| 354 | + rollback_reason: str | None = None |
| 355 | + phase_execution: dict[str, PhaseExecutionResultModel] = Field(default_factory=dict) |
| 356 | + phase_verifications: dict[str, PhaseVerificationResultModel] = Field(default_factory=dict) |
243 | 357 | attempt_count: int = 0 |
244 | 358 | latest_attempt_id: str | None = None |
245 | 359 | artifact_manifest: dict[str, Any] = Field(default_factory=dict) |
|
0 commit comments