M2.8: switch over to the new loop
nisse-dev now runs only the conversational loop. The gated state machine it was built alongside is gone: - Removed control.py, planner.py, executor.py, approvals.py, gates.py (command_form moves to loop/reader.py), publish.py and poller.py, the old assembly in agent.py (its shared helpers move to loop/build.py), the store's state-machine view (get_state, transition), their tests, the old end-to-end and live planning/milestone/gate tests, and specs/orchestrator.qnt with its scenarios. - Roles are driver, helper, expert and classifier; driver is required. loop:, roles.planner, roles.executor and tuning.executor are refused with what to use instead; tuning.driver takes the turn cap and failure limit. - The benchmark and the capability matrix measure the driver: the loop's own system prompt and tools, the task's plan as the agreed restatement. Task plans end with finish_milestone, so earlier runs show as (old); stored runs' executor tuning reads as the driver's. - A delegation on the loop records what its helper's alias resolved to (L9), as the old path's did. - The dump shows a work item's revision and what it waits for. - Behaviour the old tests covered and the loop shares stays covered: driver runs that fail on a model call, stop mid-turn, reset the failure count; go-aheads ignoring case and punctuation; a request too big to fit is never sent; the assembly tests, now on build_loop_agent. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
This commit is contained in:
1 parent
09232dcbdd
commit
6ae2375194
89 files changed
+951
-8592
No files matched your search
@@ -22,7 +22,14 @@ from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from e2e_support import dependent_task, e2e_roles, fresh_repo, operator_gitea, task
|
||||
from e2e_support import (
|
||||
build_host,
|
||||
dependent_task,
|
||||
e2e_roles,
|
||||
fresh_repo,
|
||||
operator_gitea,
|
||||
task,
|
||||
)
|
||||
|
||||
from nisse_dev.config import AgentConfig, LoopTuning
|
||||
from nisse_dev.execution import SSHHost
|
||||
@@ -54,8 +61,6 @@ def running(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> Iterator[tuple[RunningLoop, InMemoryTransport, str]]:
|
||||
from test_end_to_end import build_host
|
||||
|
||||
run = uuid.uuid4().hex[:8]
|
||||
stack = contextlib.ExitStack()
|
||||
# Kept outside pytest's temp directories, which pytest prunes, so a
|
||||
@@ -66,15 +71,18 @@ def running(
|
||||
operator = operator_gitea(live_config.gitea_url)
|
||||
account = GiteaClient(live_config.gitea_url, live_config.gitea_token).whoami()
|
||||
fresh = stack.enter_context(fresh_repo(operator, run, keep / "keys", agent=account))
|
||||
[project] = live_config.projects
|
||||
project = replace(
|
||||
project,
|
||||
repo=fresh.name,
|
||||
base_branch="main",
|
||||
push_key=fresh.push_key,
|
||||
workspace=Path(f"/tmp/nisse-e2e-{run}/sandbox"),
|
||||
build_host=build_host(ssh_host),
|
||||
)
|
||||
config = replace(
|
||||
live_config.with_project(
|
||||
repo=fresh.name,
|
||||
base_branch="main",
|
||||
push_key=fresh.push_key,
|
||||
workspace=Path(f"/tmp/nisse-e2e-{run}/sandbox"),
|
||||
build_host=build_host(ssh_host),
|
||||
),
|
||||
loop="new",
|
||||
live_config,
|
||||
projects=(project,),
|
||||
roles=e2e_roles(),
|
||||
state_db=keep / "state.db",
|
||||
# Short, so a bug's grace period runs out within the test.
|
||||
@@ -97,10 +105,10 @@ def running(
|
||||
if agent is not None:
|
||||
agent.stop()
|
||||
host = SSHHost(
|
||||
config.build_host.address,
|
||||
key=config.build_host.key,
|
||||
user=config.build_host.user,
|
||||
port=config.build_host.port,
|
||||
project.build_host.address,
|
||||
key=project.build_host.key,
|
||||
user=project.build_host.user,
|
||||
port=project.build_host.port,
|
||||
state_dir=tmp_path / "ssh",
|
||||
)
|
||||
host.execute(f"rm -rf /tmp/nisse-e2e-{run}")
|
||||
@@ -197,7 +205,7 @@ class Operator:
|
||||
|
||||
def merge_and_close(self, issue: int) -> None:
|
||||
"""Approve and merge the item's PR, and see the agent close the item."""
|
||||
gitea, repo = self.agent.gitea, self.agent.config.gitea_repo
|
||||
gitea, repo = self.agent.gitea, self.agent.config.projects[0].repo
|
||||
as_operator = operator_gitea(self.agent.config.gitea_url)
|
||||
pr = loop_of(self.item(issue)).pr
|
||||
with contextlib.suppress(GiteaError): # approval may not be required
|
||||
@@ -222,7 +230,7 @@ class Operator:
|
||||
|
||||
def tidy(self, issues: list[int], prs: list[int]) -> None:
|
||||
"""Leave the sandbox tidy: whatever is still open gets closed."""
|
||||
gitea, repo = self.agent.gitea, self.agent.config.gitea_repo
|
||||
gitea, repo = self.agent.gitea, self.agent.config.projects[0].repo
|
||||
as_operator = operator_gitea(self.agent.config.gitea_url)
|
||||
for issue in issues:
|
||||
item = self.item(issue)
|
||||
@@ -245,7 +253,7 @@ def test_the_slice_end_to_end(
|
||||
) -> None:
|
||||
agent, transport, run = running
|
||||
operator = Operator(agent, transport)
|
||||
gitea, repo = agent.gitea, agent.config.gitea_repo
|
||||
gitea, repo = agent.gitea, agent.config.projects[0].repo
|
||||
as_operator = operator_gitea(agent.config.gitea_url)
|
||||
issue = None
|
||||
pr = 0
|
||||
@@ -297,7 +305,7 @@ def test_an_issue_blocked_on_another_waits_for_it(
|
||||
closes; then B starts from a workspace that has A's work."""
|
||||
agent, transport, run = running
|
||||
operator = Operator(agent, transport)
|
||||
gitea, repo = agent.gitea, agent.config.gitea_repo
|
||||
gitea, repo = agent.gitea, agent.config.projects[0].repo
|
||||
as_operator = operator_gitea(agent.config.gitea_url)
|
||||
owner, name = repo.split("/")
|
||||
issues: list[int] = []
|
||||
@@ -360,7 +368,7 @@ def test_a_bug_goes_ahead_after_its_grace_period(
|
||||
the grace period runs out, with no go from the operator."""
|
||||
agent, transport, run = running
|
||||
operator = Operator(agent, transport)
|
||||
repo, base = agent.config.gitea_repo, agent.config.base_branch
|
||||
repo, base = agent.config.projects[0].repo, agent.config.projects[0].base_branch
|
||||
as_operator = operator_gitea(agent.config.gitea_url)
|
||||
issues: list[int] = []
|
||||
prs: list[int] = []
|
||||
@@ -412,7 +420,7 @@ def test_a_plain_yes_is_a_go_ahead(
|
||||
and the agent says so before acting."""
|
||||
agent, transport, run = running
|
||||
operator = Operator(agent, transport)
|
||||
repo = agent.config.gitea_repo
|
||||
repo = agent.config.projects[0].repo
|
||||
as_operator = operator_gitea(agent.config.gitea_url)
|
||||
issues: list[int] = []
|
||||
prs: list[int] = []
|
||||
@@ -454,7 +462,7 @@ def test_a_two_milestone_feature(
|
||||
it; the item closes after both merge."""
|
||||
agent, transport, run = running
|
||||
operator = Operator(agent, transport)
|
||||
gitea, repo = agent.gitea, agent.config.gitea_repo
|
||||
gitea, repo = agent.gitea, agent.config.projects[0].repo
|
||||
as_operator = operator_gitea(agent.config.gitea_url)
|
||||
issues: list[int] = []
|
||||
prs: list[int] = []
|
||||
@@ -510,7 +518,7 @@ def test_a_conversation_becomes_filed_work(
|
||||
is proposed, agreed, filed as a record issue, and started as agreed."""
|
||||
agent, transport, run = running
|
||||
operator = Operator(agent, transport)
|
||||
gitea, repo = agent.gitea, agent.config.gitea_repo
|
||||
gitea, repo = agent.gitea, agent.config.projects[0].repo
|
||||
issues: list[int] = []
|
||||
prs: list[int] = []
|
||||
|
||||
@@ -602,7 +610,7 @@ def test_a_conversation_becomes_a_new_project(
|
||||
with fresh_repo(
|
||||
as_operator, f"{run}-new", keep / "keys", agent=agent.account, seed=False
|
||||
) as repo:
|
||||
host = agent.config.build_host
|
||||
host = agent.config.projects[0].build_host
|
||||
filled = (
|
||||
entry.group(1)
|
||||
.replace(f"<owner>/{name}", repo.name)
|
||||
@@ -646,7 +654,7 @@ def test_a_question_leaves_the_restatement_up(
|
||||
nothing: the same revision stays up, and a go binds to it."""
|
||||
agent, transport, run = running
|
||||
operator = Operator(agent, transport)
|
||||
repo = agent.config.gitea_repo
|
||||
repo = agent.config.projects[0].repo
|
||||
as_operator = operator_gitea(agent.config.gitea_url)
|
||||
issues: list[int] = []
|
||||
try:
|
||||
|
||||
Reference in new issue
Block a user