GapDetector
This commit is contained in:
@@ -22,3 +22,10 @@ LanguageLiteral = Literal[
|
||||
Language.CPP,
|
||||
Language.C,
|
||||
]
|
||||
|
||||
|
||||
def _normalize_language(raw: dict) -> dict:
|
||||
lang = raw.get("language")
|
||||
if isinstance(lang, dict) and isinstance(lang.get("name"), str):
|
||||
lang["name"] = lang["name"].strip().lower()
|
||||
return raw
|
||||
|
||||
@@ -2,34 +2,19 @@ from typing import Literal
|
||||
|
||||
from pydantic import Field, model_validator
|
||||
|
||||
from contracts.CodeLanguages import Language
|
||||
from contracts.base import _StrictModel
|
||||
|
||||
|
||||
class LanguageSnapshot(_StrictModel):
|
||||
"""
|
||||
The language the plan commits to, plus the toolchain it will use.
|
||||
Chosen by Plan from the target files; consumed by Act and Verify.
|
||||
"""
|
||||
name: str = Field(
|
||||
min_length=1,
|
||||
description="Language name, e.g. 'python', 'typescript', 'go'.",
|
||||
)
|
||||
name: Language = Field(description="Primary language the plan commits to.")
|
||||
version: str | None = Field(
|
||||
description="Language version if known, else null.",
|
||||
)
|
||||
test_runner: str = Field(
|
||||
min_length=1,
|
||||
description="How tests are run, e.g. 'pytest', 'vitest', 'go test'.",
|
||||
)
|
||||
formatter: str | None = Field(
|
||||
description="Formatter command, or null if none.",
|
||||
)
|
||||
linter: str | None = Field(
|
||||
description="Linter command, or null if none.",
|
||||
)
|
||||
detected_from: list[str] = Field(
|
||||
description="Marker files used to detect, e.g. ['pyproject.toml'].",
|
||||
description="Language version if known (e.g. '3.12'), else null.",
|
||||
)
|
||||
test_runner: str = Field(min_length=1)
|
||||
formatter: str | None = Field(description="Formatter command, or null.")
|
||||
linter: str | None = Field(description="Linter command, or null.")
|
||||
detected_from: list[str] = Field(min_length=1)
|
||||
|
||||
|
||||
class PlanStep(_StrictModel):
|
||||
@@ -86,4 +71,15 @@ class PlanOutput(_StrictModel):
|
||||
if f.startswith("/") or ".." in f.split("/"):
|
||||
raise ValueError(f"unsafe path: {f!r}")
|
||||
|
||||
return self
|
||||
return self
|
||||
|
||||
def wrap_ref_siblings(node):
|
||||
if isinstance(node, dict):
|
||||
if "$ref" in node and len(node) > 1:
|
||||
ref = node["$ref"]
|
||||
siblings = {k: wrap_ref_siblings(v) for k, v in node.items() if k != "$ref"}
|
||||
return {"anyOf": [{"$ref": ref}], **siblings}
|
||||
return {k: wrap_ref_siblings(v) for k, v in node.items()}
|
||||
if isinstance(node, list):
|
||||
return [wrap_ref_siblings(x) for x in node]
|
||||
return node
|
||||
|
||||
Reference in New Issue
Block a user