Improve coding agent reliability
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-08-21 23:46:16 +02:00
parent ed7b88ade4
commit 2df37b671b
11 changed files with 31 additions and 8 deletions

View File

@@ -17,7 +17,7 @@ AUTOMATION_MODE=dry-run
ALLOW_DIRECT_MAIN=false
AGENT_COMMAND=aider
AGENT_MODEL=mistral/mistral-medium-latest
AGENT_MODEL=mistral/devstral-latest
MISTRAL_API_KEY=
POLL_SECONDS=60

View File

@@ -88,7 +88,7 @@ die empfohlene Betriebsart.
Default:
```dotenv
AGENT_MODEL=mistral/mistral-medium-latest
AGENT_MODEL=mistral/devstral-latest
```
Das Chat-Modell und Coding-Modell sind bewusst getrennt. Fuer Coding-Agenten sollte ein

View File

@@ -18,7 +18,7 @@ services:
GITEA_USERNAME: ${GITEA_USERNAME:-automation-bot}
GITEA_TOKEN: ${GITEA_TOKEN:-}
AGENT_COMMAND: ${AGENT_COMMAND:-aider}
AGENT_MODEL: ${AGENT_MODEL:-mistral/mistral-medium-latest}
AGENT_MODEL: ${AGENT_MODEL:-mistral/devstral-latest}
MISTRAL_API_KEY: ${MISTRAL_API_KEY:-}
POLL_SECONDS: ${POLL_SECONDS:-60}
STALE_CLAIM_MINUTES: ${STALE_CLAIM_MINUTES:-90}

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
import os
import pwd
import shutil
import subprocess
from pathlib import Path
@@ -18,6 +19,13 @@ class AiderAgent:
task_file.chmod(0o600)
command = self.command(task_file)
coder = pwd.getpwnam("coder")
git_config = Path(coder.pw_dir) / ".gitconfig"
git_config.write_text(
"[user]\n\tname = LAI Automation Coder\n\temail = coder@localhost\n"
f"[safe]\n\tdirectory = {workspace.resolve()}\n"
)
git_config.chmod(0o600)
os.chown(git_config, coder.pw_uid, coder.pw_gid)
os.chown(task_file, coder.pw_uid, coder.pw_gid)
for path in workspace.rglob("*"):
if ".git" not in path.parts:
@@ -49,6 +57,9 @@ class AiderAgent:
timeout=900,
)
finally:
shutil.rmtree(workspace / ".aider.tags.cache.v4", ignore_errors=True)
for artifact in (".aider.chat.history.md", ".aider.input.history"):
(workspace / artifact).unlink(missing_ok=True)
os.chown(workspace, 0, coder.pw_gid, follow_symlinks=False)
workspace.chmod(0o775)
if result.returncode != 0:
@@ -72,4 +83,8 @@ class AiderAgent:
"--input-history-file",
"/dev/null",
"--no-analytics",
"--edit-format",
"diff",
"--timeout",
"60",
]

View File

@@ -64,7 +64,7 @@ class Settings:
gitea_token=os.getenv("GITEA_TOKEN", ""),
gitea_username=os.getenv("GITEA_USERNAME", "automation-bot"),
agent_command=os.getenv("AGENT_COMMAND", "aider"),
agent_model=os.getenv("AGENT_MODEL", "mistral/mistral-medium-latest"),
agent_model=os.getenv("AGENT_MODEL", "mistral/devstral-latest"),
test_commands=_commands(
os.getenv(
"TEST_COMMANDS",

View File

@@ -15,6 +15,7 @@ _ALWAYS_DENIED = (
"docker-compose",
".gitea/",
".github/",
".aider",
)
_DIRECT_MAIN_DENIED = (

View File

@@ -36,6 +36,7 @@ def build_task(report: FailureReport) -> str:
Rules:
- First add a regression test that reproduces the reported behavior.
- The regression test must execute the relevant production behavior; never mock or stub the behavior being tested.
- Make the smallest production change that fixes the root cause.
- Preserve read-only SQL validation and tenant isolation.
- Never read or modify .env files, credentials, deployment secrets, or production data.

View File

@@ -108,7 +108,8 @@ class AutomationWorker:
"stderr": result.stderr[-6000:],
})
if result.returncode != 0:
raise RuntimeError(f"Test command failed: {command}\n{result.stderr[-2000:]}")
output = (result.stdout + "\n" + result.stderr)[-4000:]
raise RuntimeError(f"Test command failed: {command}\n{output}")
return results
@staticmethod

View File

@@ -12,3 +12,4 @@ def test_aider_command_cannot_mutate_git_configuration_or_send_analytics() -> No
assert "--no-analytics" in command
assert "--no-auto-commits" in command
assert command.count("/dev/null") == 2
assert command[-4:] == ["--edit-format", "diff", "--timeout", "60"]

View File

@@ -15,9 +15,12 @@ def test_policy_accepts_small_application_change() -> None:
def test_policy_rejects_secrets_and_vendor_paths() -> None:
result = evaluate_changes(ChangeSummary((".env", "vendor/foo.php"), 2, 0), settings())
result = evaluate_changes(
ChangeSummary((".env", "vendor/foo.php", ".aider.tags.cache.v4/cache.db"), 3, 0),
settings(),
)
assert not result.allowed
assert len(result.errors) == 2
assert len(result.errors) == 3
def test_direct_main_blocks_validator_and_migrations() -> None:

View File

@@ -30,6 +30,7 @@ def test_task_contains_constraints_and_redacted_report() -> None:
assert "secret-value" not in task
assert "admin@example.com" not in task
assert "Do not commit or push" in task
assert "never mock or stub the behavior being tested" in task
def test_redact_removes_extended_credentials() -> None: