band-aider-pub/band_aider/loop/supreme_loop.py
2026-10-17 11:57:37 -07:00

745 lines
34 KiB
Python

# SPDX-FileCopyrightText: 2026 Art Sea LLC
#
# SPDX-License-Identifier: AGPL-3.0-only
from __future__ import annotations
import json
from dataclasses import dataclass
from pathlib import Path
from typing import Callable
from band_aider.ai_client import llm_logging
from band_aider.ai_client.json_completion import load_json_completion
from band_aider.ai_client.openai_compatible_client import OpenAICompatibleClient
from band_aider.context.band_aider_facts import get_band_aider_facts
from band_aider.context.bootstrap_context import BootstrapContext
from band_aider.context.class_meta import ClassMeta
from band_aider.context.context_factory import context_factory
from band_aider.context.cot_task_generator import CotTaskRecord
from band_aider.context.global_context import GlobalContext, Intent, SovereignState
from band_aider.context.provenance import Provenance
from band_aider.context.resume_state import resume_settings
from band_aider.context.stabilization_context import StabilizationContext
from band_aider.context.traversed_frontier_history import TraversedFrontierHistory
from band_aider.judgement.code_parser import CodeParser
from band_aider.judgement.code_editor import CodeEditor
from band_aider.judgement.cross_cutting_concern_check import CrossCuttingConcernCheckFactory
from band_aider.judgement.current_cot_completed_check import CurrentCotCompletedCheckFactory
from band_aider.judgement.file_salience_check import FileSalienceCheckFactory
from band_aider.judgement.repository_idiom_check import RepositoryIdiomCheckFactory
from band_aider.judgement.tighten_design_work_check import TightenDesignWorkCheckFactory
from band_aider.judgement.intent_check import IntentCheckFactory
from band_aider.judgement.prompt_formatter import PromptFormatterBuilder, format_prompt
from band_aider.strategies import LanguageStrategySet
from band_aider.judgement.noop_gate import NoopGate
from band_aider.loop.bootstrap_loop import BootstrapLoop
from band_aider.loop.loop_gate import LoopGate
from band_aider.loop.mechanical_loop_gate import MechanicalLoopGate
from band_aider.loop.proto_loop import ProtoLoop
from band_aider.loop.stabilization_loop import StabilizationLoop
from band_aider.reporting.change_report_writer import ChangeReportWriter
from band_aider.ui.status import publish_cot_status, publish_loop_status
StabilizationGateFactory = Callable[[StabilizationContext], LoopGate]
@dataclass(init=False)
class SupremeLoop(ProtoLoop[LoopGate, GlobalContext]):
"""SupremeLoop wraps recursive, COT, and relevant-file loops around the base retry loop."""
file_salience_check_factory: FileSalienceCheckFactory | None = None
current_cot_completed_check_factory: CurrentCotCompletedCheckFactory | None = None
stabilization_gate_factory: StabilizationGateFactory | None = None
aider_worker: CodeEditor | None = None
cross_cutting_concern_check_factory: CrossCuttingConcernCheckFactory | None = None
repository_idiom_check_factory: RepositoryIdiomCheckFactory | None = None
tighten_design_work_check_factory: TightenDesignWorkCheckFactory | None = None
provenance: Provenance | None = None
def __init__(
self,
goal: str,
parser: CodeParser,
client: OpenAICompatibleClient,
repo_root: Path,
src_root: Path,
test_root: Path,
actor: str,
intent_check_factory: IntentCheckFactory,
prompt_formatter_builder: PromptFormatterBuilder,
original_prompt: str | None = None,
file_salience_check_factory: FileSalienceCheckFactory | None = None,
current_cot_completed_check_factory: CurrentCotCompletedCheckFactory | None = None,
stabilization_gate_factory: StabilizationGateFactory | None = None,
aider_worker: CodeEditor | None = None,
cross_cutting_concern_check_factory: CrossCuttingConcernCheckFactory | None = None,
repository_idiom_check_factory: RepositoryIdiomCheckFactory | None = None,
tighten_design_work_check_factory: TightenDesignWorkCheckFactory | None = None,
search_anchors: tuple[str, ...] = (),
parser_factory=None,
logger=None,
repo_exec=None,
language: str | None = None,
search_policy_scope: str = "broad",
search_policy_reason: str = "",
hydrate: bool | None = None,
context: GlobalContext | None = None,
provenance: Provenance | None = None,
) -> None:
"""Create SupremeLoop with a GlobalContext, no-op base gate, and optional edit worker."""
context_was_provided = context is not None
should_hydrate = False
if context is None:
context_kwargs = {
"goal": goal,
"parser": parser,
"client": client,
"repo_root": repo_root,
"src_root": src_root,
"test_root": test_root,
"actor": actor,
"prompt_formatter_builder": prompt_formatter_builder,
"intent_check_factory": intent_check_factory,
"original_prompt": original_prompt,
"search_anchors": tuple(search_anchors),
"parser_factory": parser_factory,
"search_policy_scope": search_policy_scope,
"search_policy_reason": search_policy_reason,
"repo_exec": repo_exec,
}
should_hydrate = resume_settings().hydrate if hydrate is None else hydrate
if should_hydrate:
context = context_factory.thaw(GlobalContext, **context_kwargs)
if context is None:
# A rejected checkpoint is not a hydrated run. Re-enter the
# ordinary fresh-context path so discovery and intent are built.
should_hydrate = False
context = context_factory.create(GlobalContext, **context_kwargs)
context.search_anchors = (
tuple(getattr(context, "search_anchors", ()))
if should_hydrate and not search_anchors
else tuple(search_anchors)
)
gate = NoopGate(context)
super().__init__(gate=gate, context=context, logger=logger)
context.logger = self.logger
if not context_was_provided and not should_hydrate:
context.sync()
self.logger.info(
"[probe] SupremeLoop context.sync complete relevant=%s "
"intent=%s",
len(getattr(context, "relevant_files", ())),
context.intent,
)
context.file_manager.capture_frozen_once()
# A direct Supreme caller owns its graph only when Sovereign did not supply one.
if provenance is None:
self.provenance = Provenance.open(
repo_root=context.file_manager.repo_root,
repo_exec=context.file_manager.repo_exec,
resume=resume_settings().hydrate,
)
else:
self.provenance = provenance
self.file_salience_check_factory = (
file_salience_check_factory or FileSalienceCheckFactory(
repo_root=context.file_manager.repo_root,
client=client,
prompt_formatter_builder=prompt_formatter_builder,
repo_exec=context.file_manager.repo_exec,
)
)
self.current_cot_completed_check_factory = (
current_cot_completed_check_factory
or CurrentCotCompletedCheckFactory(client, prompt_formatter_builder)
)
self.stabilization_gate_factory = stabilization_gate_factory
self.aider_worker = aider_worker
self.cross_cutting_concern_check_factory = (
cross_cutting_concern_check_factory
or CrossCuttingConcernCheckFactory(client, prompt_formatter_builder)
)
self.repository_idiom_check_factory = (
repository_idiom_check_factory
or RepositoryIdiomCheckFactory(client, prompt_formatter_builder)
)
self.tighten_design_work_check_factory = (
tighten_design_work_check_factory
or TightenDesignWorkCheckFactory(client, prompt_formatter_builder)
)
def _create_bootstrap_context(self) -> BootstrapContext:
"""Create a fresh bootstrap context from current pass relevance."""
visible_locations = [
candidate.location
for candidate in self.context.relevant_files
if self.context.file_manager.current_src(candidate.location) is not None
]
return context_factory.create(
BootstrapContext,
goal=self.context.goal,
classes=list(self.context.relevant_files),
upstream_file_manager=self.context.file_manager,
visible_locations=visible_locations,
search_anchors=self.context.search_anchors,
)
def _create_bootstrap_loop(self, *, thaw: bool = False) -> BootstrapLoop:
"""Create or thaw the bootstrap loop for reusable-construct mapping."""
# A resumed bootstrap must retain its checkpointed mapping progress.
if thaw:
bootstrap_context = context_factory.thaw(
BootstrapContext,
upstream_file_manager=self.context.file_manager,
)
else:
bootstrap_context = self._create_bootstrap_context()
bootstrap_context.search_anchors = self.context.search_anchors
return BootstrapLoop(
context=bootstrap_context,
language_strategy_set=LanguageStrategySet.get(self.context.file_manager),
aider_worker=self.aider_worker,
cross_cutting_concern_check_factory=self.cross_cutting_concern_check_factory,
repository_idiom_check_factory=self.repository_idiom_check_factory,
tighten_design_work_check_factory=self.tighten_design_work_check_factory,
logger=self.logger.getChild("bootstrap"),
)
def _run_bootstrap_if_needed(self, *, thaw: bool = False) -> str:
"""Run or resume bootstrap mapping and return a blocked summary when it stops."""
if self.context.bootstrap_completed:
return ""
self.context.bootstrap_started = True
self.context.bootstrap_completed = False
publish_loop_status(
previous_loop="SupremeLoop",
current_loop="BootstrapLoop",
next_loop="SupremeLoop",
current_item="Mapping: finding cross-cutting concerns",
)
loop = self._create_bootstrap_loop(thaw=thaw)
self._run(loop)
self.context.record_bootstrap_involved_locations(
list(
getattr(
loop.context,
"involved_locations",
list(loop.context.created_locations),
)
)
)
self.context.bootstrap_started = False
if loop.context.stage == "blocked":
self.context.bootstrap_completed = True
return f"Bootstrap mapping stopped: {loop.context.blocked_summary}"
self.context.bootstrap_completed = True
return ""
def _prepare_cot_after_bootstrap(self) -> bool:
"""Refresh in-memory relevance and break down ordinary COT tasks."""
story_cursor = self.context.story_cursor
self.context.refresh_relevant_files_from_current_metadata()
current_locations = {
candidate.location
for candidate in self.context.relevant_files
}
# Bootstrap discoveries remain part of this pass when their source still exists.
for location in story_cursor.bootstrap_involved_locations:
if location in current_locations:
continue
current = self.context.file_manager.current_src(location)
if current is None:
continue
self.context.relevant_files.append(current)
current_locations.add(location)
if not self.context.relevant_files:
return False
self.context.generate_cot_tasks()
return bool(story_cursor.cot_task_records)
def _bootstrap_surrogate_roots_for(self, root: ClassMeta) -> list[ClassMeta]:
"""Return bootstrap-involved sibling roots for the first stabilization story."""
story_cursor = self.context.story_cursor
task_cursor = story_cursor.task_cursor
bootstrap_locations = set(story_cursor.bootstrap_involved_locations)
# Surrogates only complete the first bootstrap-rooted stabilization story.
if (
task_cursor.current_cot_index != 0
or story_cursor.claimed_locations_this_recursive_pass
or root.location not in bootstrap_locations
):
return []
surrogates: list[ClassMeta] = []
for location in sorted(bootstrap_locations - {root.location}):
current = self.context.file_manager.current_src(location)
if current is None:
continue
surrogates.append(current)
return surrogates
def _create_stabilization_context(self, root: ClassMeta) -> StabilizationContext:
"""Create a fresh stabilization context around the selected root file."""
story_cursor = self.context.story_cursor
task_cursor = story_cursor.task_cursor
surrogate_roots = self._bootstrap_surrogate_roots_for(root)
context = context_factory.create(
StabilizationContext,
goal=(self.context.current_cot_task_record.task if self.context.current_cot_task_record else self.context.goal),
classes=self.context.classes,
upstream_file_manager=self.context.file_manager,
root_change=root,
surrogate_roots=surrogate_roots,
cot_index=task_cursor.current_cot_index,
total_cot=len(story_cursor.cot_task_records) or 1,
inherited_remediation_backlog=(
self.context.inherited_deferred_remediation_for_current_cot()
),
prior_traversed_frontiers=task_cursor.prior_traversed_frontiers,
)
return context
def _thaw_stabilization_context(self, root: ClassMeta) -> StabilizationContext:
"""Thaw the active stabilization context around the selected root file."""
story_cursor = self.context.story_cursor
task_cursor = story_cursor.task_cursor
context = context_factory.thaw(
StabilizationContext,
goal=(self.context.current_cot_task_record.task if self.context.current_cot_task_record else self.context.goal),
classes=self.context.classes,
upstream_file_manager=self.context.file_manager,
root_change=root,
cot_index=task_cursor.current_cot_index,
total_cot=len(story_cursor.cot_task_records) or 1,
)
# Resume cannot continue without the checkpoint that owns current COT state.
if context is None:
raise RuntimeError("Active StabilizationContext checkpoint was not available.")
return context
def _create_stabilization_gate(self, context: StabilizationContext) -> LoopGate:
"""Create the gate used by the stabilization loop for one selected root."""
if self.stabilization_gate_factory is not None:
return self.stabilization_gate_factory(context)
return MechanicalLoopGate(
context=context,
may_enter=lambda: (
context.upstream_file_manager is not None
and bool(context.frontier[0])
),
should_continue=lambda: True,
)
def _create_stabilization_loop(self, root: ClassMeta) -> StabilizationLoop:
"""Create a fresh stabilization loop for the selected root file."""
context = self._create_stabilization_context(root)
gate = self._create_stabilization_gate(context)
previous_root_location = (
self.context.previous_cot_root_location_for_current_cot()
)
previous_cot_root_readonly_file = (
self.context.file_manager.source_path(previous_root_location)
if previous_root_location is not None
else None
)
return StabilizationLoop(
gate=gate,
context=context,
language_strategy_set=LanguageStrategySet.get(self.context.file_manager),
aider_worker=self.aider_worker,
previous_cot_root_readonly_file=previous_cot_root_readonly_file,
previous_cot_records=self.context.previous_cot_records_for_current_cot(),
future_cot_records=self.context.future_cot_records_for_current_cot(),
provenance=self.provenance,
logger=self.logger.getChild("stabilization"),
)
def _thaw_stabilization_loop(self, root: ClassMeta) -> StabilizationLoop:
"""Thaw the active stabilization loop for the selected root file."""
context = self._thaw_stabilization_context(root)
gate = self._create_stabilization_gate(context)
previous_root_location = (
self.context.previous_cot_root_location_for_current_cot()
)
previous_cot_root_readonly_file = (
self.context.file_manager.source_path(previous_root_location)
if previous_root_location is not None
else None
)
return StabilizationLoop(
gate=gate,
context=context,
language_strategy_set=LanguageStrategySet.get(self.context.file_manager),
aider_worker=self.aider_worker,
previous_cot_root_readonly_file=previous_cot_root_readonly_file,
previous_cot_records=self.context.previous_cot_records_for_current_cot(),
future_cot_records=self.context.future_cot_records_for_current_cot(),
provenance=self.provenance,
logger=self.logger.getChild("stabilization"),
)
def _post_run(self) -> str:
"""Return the summary produced for one selected stabilization root."""
story_cursor = self.context.story_cursor
task_cursor = story_cursor.task_cursor
root = task_cursor.active_root
# A child summary is meaningful only while a root owns the active story.
if root is None:
return "No stabilization root was selected."
child_summaries = "\n".join(
story_cursor.marginal_result[
task_cursor.marginal_result_start:
]
)
# Preserve the distinction between an empty child result and completed work.
if not child_summaries.strip():
return f"Stabilization for {root.location} produced no child summary."
return f"Stabilization for {root.location} completed with summary:\n{child_summaries}"
def _prepare_work(self) -> ProtoLoop | None:
"""Return the stabilization loop for the active root selected by the backlog loop."""
task_cursor = self.context.story_cursor.task_cursor
active_root = task_cursor.active_root
# The protocol has no child work until the backlog selects a concrete root.
if active_root is None:
return None
loop = self._create_stabilization_loop(active_root)
return loop
def _active_stabilization_checkpoint_matches(self) -> bool:
"""Return whether the latest stabilization checkpoint matches the active root."""
task_cursor = self.context.story_cursor.task_cursor
root = task_cursor.active_root
# No selected root means there is no child checkpoint to resume.
if root is None:
return False
payload = context_factory.latest_payload_for(StabilizationContext)
# Only an existing payload can prove that the selected root is resumable.
if payload is None:
return False
checkpoint_root = payload.get("root_change")
return (
isinstance(checkpoint_root, ClassMeta)
and checkpoint_root.location == root.location
and payload.get("cot_index")
== task_cursor.current_cot_index
)
def _cot_record_completed(self, record: CotTaskRecord) -> bool:
"""Evaluate one completed COT root after stabilization has finished."""
if self.current_cot_completed_check_factory is None:
return True
current_root = self.context.file_manager.current_src(record.root.location)
root = current_root or record.root
check = self.current_cot_completed_check_factory.create(
self.context.original_prompt
)
return check(record.task, [root])
def _capture_traversed_frontier_history(
self,
stabilization_context: StabilizationContext,
) -> None:
"""Persist this accepted COT's local traversal as the next lineage head."""
task_cursor = self.context.story_cursor.task_cursor
previous = task_cursor.prior_traversed_frontiers
# A crash after this persist but before root completion must not duplicate a node.
if (
previous is not None
and previous.cot_index == stabilization_context.cot_index
and previous.root_location == stabilization_context.root_change.location
):
return
task_cursor.prior_traversed_frontiers = TraversedFrontierHistory(
cot_index=stabilization_context.cot_index,
root_location=stabilization_context.root_change.location,
frontiers=stabilization_context.traversed_frontier_snapshot(),
previous=previous,
)
self.context.persist()
def _stabilize_root(self, root: ClassMeta, *, thaw: bool = False) -> bool:
"""Run one root and advance only after local acceptance and durable handoff."""
task_cursor = self.context.story_cursor.task_cursor
self.context.mark_root_visited(root)
self.context.stabilization_started = True
publish_loop_status(
previous_loop=type(self).__name__,
current_loop="StabilizationLoop",
current_item=root.location,
)
# Resume must reuse the durable child context; a fresh COT creates one.
if thaw:
loop = self._thaw_stabilization_loop(root)
else:
loop = self._create_stabilization_loop(root)
# An accepted checkpoint needs only its parent-owned handoff retried on resume.
if not loop.context.accepted:
self._run(loop)
# Retain the active root and its child checkpoint when current-owned work remains unresolved.
if not loop.context.accepted:
self.logger.warning(
"COT %s for %s remains incomplete within current ownership: %s",
task_cursor.current_cot_index,
root.location,
loop.context.blocked_summary or "local work remains",
)
return False
handoff = loop.context.remaining_deferred_remediation
# Persist child-owned remediation before this root can leave the active COT.
if handoff.inherited_items or handoff.deferred_items:
if not self.context.handoff_deferred_remediation_to_next_cot(handoff):
self.logger.warning(
"COT %s for %s is locally accepted but deferred remediation remains untransferred.",
task_cursor.current_cot_index,
root.location,
)
return False
self.logger.info(
"Current COT closed with %s deferred source-remediation item(s) transferred.",
len(handoff.inherited_items) + len(handoff.deferred_items),
)
self._capture_traversed_frontier_history(loop.context)
story_roots = list(loop.context.t0)
summary = self._post_run()
self.context.mark_root_stabilized(root, summary, story_roots=story_roots)
return True
def _summarize_recursive_run(self, completed: bool) -> str:
"""Return the final supreme-loop summary from all recursive-pass summaries."""
story_cursor = self.context.story_cursor
net_effects = {
**self.context.file_manager.src_net_effects(),
**self.context.file_manager.test_net_effects(),
}
expected = {
"summary": "SUCCESS or FAILED followed by one concise sentence",
}
prompt = (
"Summarize this SupremeLoop run.\n"
"Start with SUCCESS if the original request appears satisfied, otherwise FAILED.\n"
"Use the loop summaries, current CDC evidence, and net effects as evidence.\n\n"
"Return strict JSON only with this shape:\n"
f"{json.dumps(expected, indent=2)}\n\n"
f"Original request:\n{self.context.original_prompt}\n\n"
f"Completed by relevance fixed point:\n{completed}\n\n"
f"Net effects:\n{json.dumps(net_effects, indent=2)}\n\n"
"Loop summaries:\n"
f"{json.dumps(story_cursor.run_summaries, indent=2)}"
)
data = load_json_completion(
self.context.client,
format_prompt(
self.context.prompt_formatter_builder,
"SUPREME SUMMARY",
prompt,
),
prompt_formatter_builder=self.context.prompt_formatter_builder,
references=[expected],
)
return str(data.get("summary") or ("SUCCESS" if completed else "FAILED"))
def _report_cot_tasks(self) -> list[str]:
"""Return the COT task list that should be persisted in the final report."""
story_cursor = self.context.story_cursor
tasks = [record.task for record in story_cursor.cot_task_records if record.task.strip()]
if tasks:
return tasks
history = story_cursor.stabilization_summaries_by_cot
if isinstance(history, dict):
return [str(task) for task in history if str(task).strip()]
return []
def _write_change_report(self, result: str) -> Path:
"""Persist the final markdown change report for the completed run."""
writer = ChangeReportWriter(repo_root=self.context.repo_root)
counts = (
writer.changed_file_counts(self.context.file_manager)
if hasattr(writer, "changed_file_counts")
else {}
)
path = writer.write(
original_job=self.context.original_prompt,
cot_tasks=self._report_cot_tasks(),
file_manager=self.context.file_manager,
final_summary=result,
)
facts = get_band_aider_facts()
facts.record_report(
report_path=path,
files_modified=int(counts.get("changed", 0) or 0),
files_added=int(counts.get("created", 0) or 0),
)
self._persist_facts_if_configured()
return path
def _persist_facts_if_configured(self) -> None:
"""Persist facts when the CLI has configured resume settings."""
try:
settings = resume_settings()
except RuntimeError:
return
checkpoint_dir = settings.checkpoint_dir
facts = get_band_aider_facts()
facts.persist(checkpoint_dir)
def run(self, logger_name: str | None = None) -> str:
"""Run recursive request passes, COT tasks, and relevant files around the base retry loop."""
if not self._logger_stack: self._logger_stack.append(llm_logging.logger_for_loop(self))
if logger_name: self._logger_stack.append(self.logger.getChild(llm_logging.safe_log_segment(logger_name)))
llm_logging.set_current_logger(self.logger)
try:
story_cursor = self.context.story_cursor
task_cursor = story_cursor.task_cursor
resume_stabilization = self.context.stabilization_started
# A retained active root resumes only when its child checkpoint still matches.
if resume_stabilization:
if (
task_cursor.active_root is not None
and not self._active_stabilization_checkpoint_matches()):
self.context.stabilization_started = False
# continue
start_index = task_cursor.current_cot_index
elif (
getattr(self.context, "bootstrap_started", False)
and not getattr(self.context, "bootstrap_completed", False)
):
bootstrap_blocked = self._run_bootstrap_if_needed(thaw=True)
# Bootstrap blockage is evidence; Stabilization remains the repair owner.
if bootstrap_blocked:
self.logger.warning(
"Bootstrap mapping stopped; attempting serious repair in stabilization: %s",
bootstrap_blocked,
)
story_cursor.run_summaries.append(bootstrap_blocked)
self.context.persist()
if not self._prepare_cot_after_bootstrap():
completed = not bool(self.context.relevant_files)
result = self._summarize_recursive_run(completed=completed)
self._finish_story(result)
return result
start_index = 0
elif (
getattr(self.context, "bootstrap_completed", False)
and not story_cursor.cot_task_records
):
if not self._prepare_cot_after_bootstrap():
completed = not bool(self.context.relevant_files)
result = self._summarize_recursive_run(completed=completed)
self._finish_story(result)
return result
start_index = 0
elif story_cursor.cot_task_records:
start_index = task_cursor.current_cot_index
else:
if not self.context.begin_recursive_pass():
completed = not bool(self.context.relevant_files)
result = self._summarize_recursive_run(completed=completed)
self._finish_story(result)
return result
if self.context.intent and self.context.intent & Intent.FEATURE:
bootstrap_blocked = self._run_bootstrap_if_needed()
# Bootstrap blockage is evidence; Stabilization remains the repair owner.
if bootstrap_blocked:
self.logger.warning(
"Bootstrap mapping stopped; attempting serious repair in stabilization: %s",
bootstrap_blocked,
)
story_cursor.run_summaries.append(bootstrap_blocked)
self.context.persist()
if not self._prepare_cot_after_bootstrap():
completed = not bool(self.context.relevant_files)
result = self._summarize_recursive_run(completed=completed)
self._finish_story(result)
return result
start_index = 0
# Each planned COT owns one sequential root stabilization attempt.
for index in range(start_index, len(story_cursor.cot_task_records)):
cot_started = get_band_aider_facts().begin_cot()
self.context.set_current_cot_task(index);
publish_cot_status(self.context)
self._logger_stack.append(self.logger.getChild(
llm_logging.safe_log_segment(f"{index}_{self.context.current_cot_task_record.task if self.context.current_cot_task_record else 'cot'}")));
llm_logging.set_current_logger(self.logger)
try:
if (
resume_stabilization
and task_cursor.active_root is not None
and task_cursor.active_stabilization_key == f"{self.context.current_cot_key()}:{task_cursor.active_root.location}"
and task_cursor.active_root.location not in self.context.stabilized_locations_for_current_cot()):
stabilized = self._stabilize_root(
task_cursor.active_root,
thaw=True,
)
if stabilized is False:
return self._post_run()
resume_stabilization = False
continue
elif (
resume_stabilization
and task_cursor.active_root is None
):
resume_stabilization = False
continue
resume_stabilization = False
record = self.context.current_cot_task_record
if record is None:
raise RuntimeError(
"COT task record is missing for the active COT index"
)
if self._stabilize_root(record.root) is False:
return self._post_run()
finally:
facts = get_band_aider_facts()
facts.finish_cot(cot_started)
self._persist_facts_if_configured()
self._logger_stack.pop()
llm_logging.set_current_logger(self.logger)
self.context.stabilization_started = False
completed = all(map(self._cot_record_completed, story_cursor.cot_task_records))
result = self._summarize_recursive_run(completed=completed)
self._finish_story(result)
return result
finally:
if logger_name: self._logger_stack.pop()
llm_logging.set_current_logger(self.logger if self._logger_stack else None)
def _finish_story(self, result: str) -> None:
"""Persist story completion boundary independently of CDC success."""
completion_state = SovereignState.BETWEEN_STORIES
self.context.supreme_result = result
self.context.supreme_completion_state = completion_state
persist = getattr(self.context, "persist", None)
# Some focused contexts intentionally omit checkpoint persistence.
if callable(persist):
persist()