ruslanmv
Deploy: metrics + docs (Batch 12)
22b729d
Raw
History Blame Contribute Delete
7.02 kB
"""Pydantic schemas for the /v1 Continuous Build workflow API (Batch C2).
Wire vocabularies are hyphenated and stored verbatim (``approved``/``needs-repair``/``rejected``
/``not-run``). The UI copy ("Passed" / "Needs repair" / "Rejected") is derived in the response
via ``ui_label`` so the engine's status is never re-spelled on the way through.
"""
from __future__ import annotations
from datetime import datetime
from enum import StrEnum
from pydantic import Field
from app.schemas.common import CoderId, StrictModel
# --- status vocabulary ---------------------------------------------------------------------
class BatchChangeType(StrEnum):
SMALL_UPDATE = "small-update"
ADD_FEATURE = "add-feature"
FIX_ISSUE = "fix-issue"
_UI_LABELS = {
"approved": "Passed",
"needs-repair": "Needs repair",
"rejected": "Rejected",
"not-run": "Not run",
"running": "Running",
}
def ui_label(status: str) -> str:
return _UI_LABELS.get(status, status)
# --- projects ------------------------------------------------------------------------------
class ProjectCreate(StrictModel):
title: str = Field(min_length=1)
slug: str = Field(min_length=1, max_length=120)
description: str = ""
class ProjectResponse(StrictModel):
id: str
owner_id: str
title: str
slug: str
description: str
status: str
privacy: str
created_at: datetime
# --- versions ------------------------------------------------------------------------------
class VersionCreate(StrictModel):
project_id: str
version_label: str = Field(default="v1.0.0", max_length=32)
title: str = Field(min_length=1)
requirements_md: str = ""
parent_version_id: str | None = None
class VersionResponse(StrictModel):
id: str
project_id: str
parent_version_id: str | None
version_label: str
title: str
requirements_md: str
status: str
created_at: datetime
# --- batches -------------------------------------------------------------------------------
class BatchCreate(StrictModel):
version_id: str
title: str = ""
goal_md: str = Field(min_length=1)
change_type: BatchChangeType = BatchChangeType.ADD_FEATURE
class BatchResponse(StrictModel):
id: str
version_id: str
ordinal: int
title: str
goal_md: str
change_type: str
status: str
parent_commit_id: str | None
created_at: datetime
class PromptPackRequest(StrictModel):
coder: CoderId = CoderId.GENERIC_AI_CODER
class PromptPackResponse(StrictModel):
batch_id: str
prompt_version_id: str
coder: str
prompt_text: str
constraints: dict
batch_status: str
# --- executions / validation ---------------------------------------------------------------
class ChangedFile(StrictModel):
path: str = Field(min_length=1)
change_type: str = "modified" # added|modified|deleted
class DependencyChange(StrictModel):
name: str
version: str | None = None
action: str = "add" # add|remove|update
class ExecutionRequest(StrictModel):
coder: CoderId = CoderId.GENERIC_AI_CODER
changed_files: list[ChangedFile] = Field(default_factory=list)
dependency_changes: list[DependencyChange] = Field(default_factory=list)
patch: str | None = None
summary: str = ""
class ValidationFindingResponse(StrictModel):
id: str
severity: str
status: str
check_name: str
file_path: str | None
message: str
remediation: str | None
class ValidationRunResponse(StrictModel):
id: str
commit_id: str
status: str
ui_label: str
score: int | None
runner: str
findings: list[ValidationFindingResponse] = Field(default_factory=list)
class CommitResponse(StrictModel):
id: str
version_id: str
batch_id: str
commit_no: int
summary: str
tree_hash: str
validation_status: str
ui_label: str
parent_commit_id: str | None
created_at: datetime
class ExecutionResponse(StrictModel):
"""Result of submitting a batch's changes: the commit + its validation outcome."""
commit: CommitResponse
validation_run: ValidationRunResponse
outcome: str # committed|needs-repair|rejected
next_action: str
class CommitDiffResponse(StrictModel):
base_commit_id: str | None
head_commit_id: str
patch: str
class ArtifactResponse(StrictModel):
id: str
artifact_type: str
storage_key: str
sha256: str
size_bytes: int
# --- async runs + events (Batch C3) --------------------------------------------------------
class RunEnqueueResponse(StrictModel):
run_id: str
status: str
ui_label: str
events_url: str
ws_url: str
class RunResponse(StrictModel):
id: str
batch_id: str | None
commit_id: str | None
status: str
ui_label: str
score: int | None
runner: str
class RunEventResponse(StrictModel):
seq: int
run_id: str
event_type: str
payload: dict
created_at: datetime | None = None
# --- repair batches ------------------------------------------------------------------------
class RepairBatchRequest(StrictModel):
validation_run_id: str
coder: CoderId = CoderId.GENERIC_AI_CODER
# --- timeline ------------------------------------------------------------------------------
class TimelineEntry(StrictModel):
kind: str # batch|commit
id: str
ordinal: int | None = None
commit_no: int | None = None
title: str = ""
status: str = ""
ui_label: str | None = None
created_at: datetime
class TimelineResponse(StrictModel):
version_id: str
version_label: str
entries: list[TimelineEntry]
# --- sync (Track L2: mb sync ↔ /v1) --------------------------------------------------------
# The local .mb/ store and the server tables share shapes and an id space (content-addressed
# ids fit String(36)), so sync is upsert-by-id.
class SyncProject(StrictModel):
id: str
slug: str
title: str = ""
description: str = ""
class SyncVersion(StrictModel):
id: str
project_id: str
version_label: str = "v1.0.0"
title: str = ""
requirements_md: str = ""
class SyncBatch(StrictModel):
id: str
version_id: str
ordinal: int = Field(ge=1)
title: str = ""
goal_md: str = ""
change_type: str = "add-feature"
status: str = "draft"
parent_commit_id: str | None = None
class SyncCommit(StrictModel):
id: str
batch_id: str
version_id: str
commit_no: int = Field(ge=1)
summary: str = ""
tree_hash: str
validation_status: str = "not-run"
parent_commit_id: str | None = None
manifest: dict = Field(default_factory=dict)
class SyncRequest(StrictModel):
project: SyncProject
version: SyncVersion
batches: list[SyncBatch] = Field(default_factory=list)
commits: list[SyncCommit] = Field(default_factory=list)
class SyncResponse(StrictModel):
project_id: str
version_id: str
applied: dict
timeline: TimelineResponse