Loop guard (3 identical pushes), end_reason and activation error records per run; thinking off for the stage 1 baseline

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014aUaQeLnwbb1zTpN7kHeat
This commit is contained in:
Kral
2026-10-04 07:07:44 +02:00
parent 040b9900fd
commit 0401186a6c
6 changed files with 79 additions and 8 deletions

View File

@@ -1,4 +1,5 @@
"""Tool proxy between agent and MCP: whitelist, budget, prefix filter, trajectory log."""
import hashlib
import json
import re
import time
@@ -30,6 +31,23 @@ VARIANTS = {
"packageName": "package", "includeType": "include", "className": "class_name"},
},
}
def activation_messages(text, is_error=False):
"""Error messages (severity E) of a write result; the whole text if the call itself failed."""
try:
obj = json.loads(text)
except (TypeError, ValueError):
return [str(text)[:300]] if is_error else []
if not isinstance(obj, dict):
return []
msgs = (obj.get("activation") or {}).get("messages") or obj.get("messages") or []
out = [str(m.get("message", ""))[:300] for m in msgs if isinstance(m, dict) and m.get("severity") == "E"]
if not out and is_error:
out = [str(obj.get("message") or text)[:300]]
return out
RUN_PREFIX = re.compile(r"^Z\d[0-9A-Z]{5,6}_", re.I)
@@ -49,6 +67,10 @@ class ToolProxy:
self.activations = 0
self.fail_streak = 0
self.max_fail_streak = 0
self.activation_failures = 0 # write calls that failed
self.activation_errors = [] # unique error messages of failed writes
self.same_push_streak = 0 # identical sap_push_source (object + source hash) in a row
self._last_push = None
self.log = open(log_path, "a")
self.adt = None
self.fallbacks = [] # writes that needed the ADT activation fallback
@@ -125,6 +147,11 @@ class ToolProxy:
else:
if tool in WRITE_TOOLS and (tool == "sap_activate" or args.get("activate", True)):
self.activations += 1
if tool == "sap_push_source":
key = (name, str(args.get("includeType", "")),
hashlib.md5(str(args.get("source", "")).encode()).hexdigest())
self.same_push_streak = self.same_push_streak + 1 if key == self._last_push else 1
self._last_push = key
err, text = self.mcp.call(tool, args)
if tool == "sap_push_source":
if str(args.get("objectType", "")).upper() in ("PROG", "FUNC") and not args.get("includeType"):
@@ -139,6 +166,11 @@ class ToolProxy:
failed = err or '"success":false' in text.replace(" ", "")
self.fail_streak = self.fail_streak + 1 if failed else 0
self.max_fail_streak = max(self.max_fail_streak, self.fail_streak)
if failed:
self.activation_failures += 1
for m in activation_messages(text, err):
if m not in self.activation_errors and len(self.activation_errors) < 30:
self.activation_errors.append(m)
entry["is_error"], entry["result"] = result[0], result[1][:20000]
self.log.write(json.dumps(entry) + "\n")
self.log.flush()