Spaces:
Running
Running
File size: 11,057 Bytes
2bf281f 7c80447 2bf281f 8778e44 7c80447 8778e44 2bf281f 8778e44 2bf281f 8778e44 e9b9bfd 2bf281f 8778e44 2bf281f 8778e44 2bf281f 8778e44 37f9abc ea15e09 6c314e0 37f9abc 8778e44 76e192b fccd7f6 76e192b 0450a06 fccd7f6 0450a06 fccd7f6 0450a06 fccd7f6 0450a06 fccd7f6 0450a06 76e192b 0450a06 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 ea15e09 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b fccd7f6 76e192b 96e57e5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | from enum import Enum, StrEnum
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field
from multi_agent_sdlc.tools.tester.validation import NonBlankStr
class RiskLevel(str, Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
class Task(BaseModel):
id: str = Field(description="Short unique id, e.g. 'T1', 'T2'")
title: str = Field(description="Title of the task")
owner: Literal["coder", "tester"] = Field(
description=(
"Owner of the task. "
"Use 'coder' for production code, application configuration, "
"runtime behaviour, and implementation documentation. "
"Use 'tester' for unit tests, integration tests, fixtures, mocks, "
"test data, coverage configuration, and test documentation. "
"A task must have exactly one owner. Do not assign test creation "
"or test-file changes to the coder."
)
)
description: str = Field(
description="What needs to be built/changed, specific enough for Coder to act without re-asking"
)
acceptance_criteria: list[str] = Field(
description="Concrete, testable conditions — this is what Tester checks against"
)
depends_on: list[str] = Field(
default_factory=list, description="Task ids that must complete first"
)
target_files: list[str] = Field(
description=(
"File paths relative to the application's project directory. "
"Do not include `sandbox/` or the project id. "
"Examples: `src/calculator/core.py`, `tests/test_core.py`."
)
)
risk: RiskLevel = Field(description="Risk level of the task")
class DevelopmentPlan(BaseModel):
project_id: str = Field(
description=(
"Unique lowercase kebab-case identifier used as the project "
"directory under `sandbox`, for example `terminal-calculator`."
)
)
goal: str = Field(description="Restated user objective")
tasks: list[Task]
execution_order: list[str] = Field(
description="Task ids in dependency-resolved order — Planner computes this so downstream nodes don't need a topo-sort"
)
assumptions: list[str] = Field(
default_factory=list, description="Things the Planner assumed due to ambiguity"
)
out_of_scope: list[str] = Field(
default_factory=list,
description="Explicitly excluded to prevent unclear goals during Coder execution",
)
class CoderSummary(BaseModel):
implementation_summary: str = Field(
description=(
"Brief factual summary of the production implementation completed "
"by the Coder. Do not include unverified test or quality claims."
)
)
completed_task_ids: list[str] = Field(
default_factory=list,
description=(
"Identifiers of Coder-owned plan tasks that were implemented. "
"Include only tasks supported by completed file operations."
),
)
modified_files: list[str] = Field(
default_factory=list,
description=(
"Project-relative paths of production files created or modified "
"by the Coder. Do not include test files."
),
)
runtime_dependencies: list[str] = Field(
default_factory=list,
description=(
"Production runtime dependencies added to the project. "
"Do not include testing, linting, coverage, or type-checking tools."
),
)
entry_points: list[str] = Field(
default_factory=list,
description=(
"Command-line entry-point names configured under " "`[project.scripts]`."
),
)
executed_operations: list[str] = Field(
default_factory=list,
description=(
"Operations actually executed by Coder tools and their observed "
"outcomes, such as successful `uv sync` or application launch."
),
)
unresolved_issues: list[str] = Field(
default_factory=list,
description=(
"Known implementation problems, blockers, uncertainties, or "
"failed operations that remain unresolved."
),
)
tester_notes: list[str] = Field(
default_factory=list,
description=(
"Concise handoff notes identifying behaviour or acceptance "
"criteria the Tester should verify. Do not claim they already pass."
),
)
class VerificationType(StrEnum):
SYNC = "sync"
ENTRY_POINT = "entry_point"
PYTEST = "pytest"
RUFF_CHECK = "ruff_check"
RUFF_FORMAT_CHECK = "ruff_format_check"
MYPY = "mypy"
COMPLETE_PROJECT_VERIFICATION = "complete_project_verification"
class VerificationResult(BaseModel):
model_config = ConfigDict(extra="forbid")
verification_type: VerificationType
command: list[str] = Field(min_length=1)
status: Literal["passed", "failed", "blocked", "not_executed"]
exit_code: int | None
summary: str = Field(min_length=1)
related_task_ids: list[str]
class AcceptanceCriterionResult(BaseModel):
model_config = ConfigDict(extra="forbid")
task_id: str = Field(min_length=1)
criterion: str = Field(min_length=1)
status: Literal["passed", "failed", "blocked", "not_executed"]
evidence: str = Field(min_length=1)
class TesterRepair(BaseModel):
model_config = ConfigDict(extra="forbid")
description: str = Field(min_length=1)
files_modified: list[str] = Field(min_length=1)
verification_result: str = Field(min_length=1)
class ImplementationFailure(BaseModel):
model_config = ConfigDict(extra="forbid")
description: str = Field(min_length=1)
related_task_ids: list[str] = Field(min_length=1)
evidence: str = Field(min_length=1)
class UnresolvedIssue(BaseModel):
model_config = ConfigDict(extra="forbid")
owner: Literal["coder", "tester", "environment", "unknown"]
description: str = Field(min_length=1)
related_task_ids: list[str]
evidence: str = Field(min_length=1)
class CoderRepairRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
related_task_ids: list[str] = Field(min_length=1)
affected_files: list[str] = Field(min_length=1)
failed_criteria: list[str] = Field(min_length=1)
observed_behavior: str = Field(min_length=1)
expected_behavior: str = Field(min_length=1)
evidence: str = Field(min_length=1)
class TesterSummary(BaseModel):
"""Final structured handoff from the Tester to the Reviewer or Coder."""
model_config = ConfigDict(extra="forbid")
addressed_task_ids: list[NonBlankStr] = Field(
description=(
"Tester-owned task identifiers actively worked on during this cycle, "
"including test implementation, Tester-owned repairs, verification, "
"or investigation. Include blocked Tester-owned tasks that were "
"attempted. Do not include Coder-owned tasks merely because their "
"implementation was verified."
)
)
passed_task_ids: list[NonBlankStr] = Field(
description=(
"Tester-owned task identifiers whose applicable acceptance criteria "
"all passed with supporting evidence. Do not include Coder-owned tasks "
"or Tester-owned tasks that are failed, blocked, incomplete, or "
"unresolved."
)
)
related_task_ids: list[NonBlankStr] = Field(
description=(
"Approved task identifiers owned by other agents whose outputs were "
"evaluated, exercised, or affected during this Tester cycle. Do not "
"include Tester-owned tasks listed in addressed_task_ids."
)
)
files_created_or_modified: list[str] = Field(
description=(
"Project-relative Tester-owned files actually created or modified."
)
)
development_dependencies_added: list[str] = Field(
description=(
"Development dependencies newly added by the Tester during this cycle. "
"Do not include dependencies that were already present or merely used. "
"Include version constraints exactly as written in project configuration."
)
)
verification_results: list[VerificationResult] = Field(
description=(
"Verification operations actually executed. This field must contain "
"sufficient successful evidence when `overall_status` is `passed`."
)
)
acceptance_criteria_results: list[AcceptanceCriterionResult] = Field(
description=(
"Results for all applicable approved acceptance criteria when "
"`overall_status` is `passed`."
)
)
tester_repairs: list[TesterRepair] = Field(
description=(
"Repairs made only to Tester-owned files or verification configuration."
)
)
implementation_failures: list[ImplementationFailure] = Field(
description=(
"Failures attributed to Coder-owned production code or configuration."
)
)
unresolved_issues: list[UnresolvedIssue] = Field(
description=(
"Issues that remain unresolved, could not be safely classified, or "
"prevented required verification from completing. Do not duplicate "
"confirmed Coder-owned defects already recorded in "
"`implementation_failures` and `coder_repair_requests`. This field "
"should normally be non-empty only when `overall_status` is `blocked`."
)
)
overall_status: Literal["passed", "failed", "blocked"] = Field(
description=(
"Final Tester outcome. Use `passed` only when the latest complete "
"project verification passed and every applicable acceptance criterion "
"passed. Use `failed` when verification produced evidence of at least "
"one Coder-owned production defect requiring repair. Use `blocked` only "
"when required verification could not be completed or a failure could "
"not be safely classified because of an external, environmental, tool, "
"dependency, or access limitation."
)
)
coder_repair_requests: list[CoderRepairRequest] = Field(
description=("Focused production defects requiring repair by the Coder.")
)
class VerificationCycle(BaseModel):
cycle_number: int
tester_summary: TesterSummary
class CoderMode(StrEnum):
IMPLEMENTATION = "implementation"
REPAIR = "repair"
class ImplementationCycle(BaseModel):
cycle_number: int
# mode: CoderMode
coder_summary: CoderSummary
class CoderStatus(StrEnum):
IMPLEMENTING = "implementing"
REPAIRING = "repairing"
COMPLETED = "completed"
BLOCKED = "blocked"
FAILED = "failed"
class TesterStatus(StrEnum):
TESTING = "testing"
PASSED = "passed"
REPAIR_REQUIRED = "repair_required"
BLOCKED = "blocked"
|