95 lines
3.7 KiB
Python
95 lines
3.7 KiB
Python
# SPDX-FileCopyrightText: 2026 Art Sea LLC
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
"""Shared workflow story objects for Alpha postflight and Beta retry judgement calls."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, TYPE_CHECKING
|
|
|
|
from band_aider.context.class_meta import ClassMeta
|
|
from band_aider.context.failing_test import FailingTest
|
|
from band_aider.judgement.test_runner_strategy import TestRunResult
|
|
from band_aider.judgement.code_editor import EditorRecord
|
|
|
|
if TYPE_CHECKING:
|
|
from band_aider.context.provenance import FutureGuidance
|
|
from band_aider.context.working_backlog import ChangeType, TestingBacklog
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AcceptedSourceStory:
|
|
"""AcceptedSourceStory records the accepted source change and its test-planning evidence."""
|
|
|
|
current_source: ClassMeta
|
|
source_effect: str
|
|
source_diff: str
|
|
upstream_classes: list[ClassMeta]
|
|
downstream_classes: list[ClassMeta]
|
|
original_cot: str
|
|
editor_records: list[EditorRecord] = field(default_factory=list)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class DirectTestCandidate:
|
|
"""DirectTestCandidate retains only the state needed after direct execution."""
|
|
|
|
focused_test: ClassMeta
|
|
targeted_result: TestRunResult
|
|
semantic_vote_tally: int = 0
|
|
failing: FailingTest | None = None
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TargetedFailureStory:
|
|
"""TargetedFailureStory records one routed targeted failure and its shared evidence."""
|
|
|
|
testing_item: TestingBacklog | None
|
|
raw_output: str
|
|
work_needed: str
|
|
candidate_sources: list[ClassMeta]
|
|
failing: FailingTest
|
|
failure_phase: str
|
|
accepted_alpha_summary: str = ""
|
|
structural_evidence: dict[str, Any] | None = None
|
|
semantic_evidence: dict[str, Any] | None = None
|
|
previous_beta_guidance: str = ""
|
|
beta_edit_diff: str = ""
|
|
beta_editor_summary: str = ""
|
|
focused_test: ClassMeta | None = None
|
|
summary: str = ""
|
|
upstream_classes: list[ClassMeta] = field(default_factory=list)
|
|
downstream_classes: list[ClassMeta] = field(default_factory=list)
|
|
original_cot: str = ""
|
|
change_type: ChangeType | None = None
|
|
failure_context_sources: list[ClassMeta] = field(default_factory=list)
|
|
future_guidance: tuple[FutureGuidance, ...] = ()
|
|
editor_records: list[EditorRecord] = field(default_factory=list)
|
|
|
|
def __post_init__(self) -> None:
|
|
"""Normalize either Beta backlog provenance or direct Alpha evidence into one story."""
|
|
|
|
testing_item = self.testing_item
|
|
# Snapshot established Beta backlog metadata into the owner-neutral routing story.
|
|
if testing_item is not None:
|
|
object.__setattr__(self, "focused_test", testing_item.focused_spotlight)
|
|
object.__setattr__(self, "summary", testing_item.summary)
|
|
object.__setattr__(self, "upstream_classes", list(testing_item.upstream_classes))
|
|
object.__setattr__(self, "downstream_classes", list(testing_item.downstream_classes))
|
|
object.__setattr__(self, "original_cot", testing_item.original_cot)
|
|
object.__setattr__(self, "change_type", testing_item.change_type)
|
|
object.__setattr__(self, "future_guidance", testing_item.future_guidance)
|
|
object.__setattr__(self, "editor_records", list(testing_item.editor_records))
|
|
object.__setattr__(
|
|
self,
|
|
"failure_context_sources",
|
|
list(testing_item.failure_context_sources),
|
|
)
|
|
|
|
# Reject stories that cannot identify both the failed test and its planned change kind.
|
|
if self.focused_test is None or self.change_type is None:
|
|
raise ValueError(
|
|
"TargetedFailureStory requires focused_test and change_type evidence."
|
|
)
|