feat: increase agent iteration limits and add stdin cleanup to maestro interactive loop
This commit is contained in:
+1
-1
@@ -683,7 +683,7 @@ DEFAULT_HTTP_TIMEOUT = 120
|
||||
CONTEXT_COMPACT_THRESHOLD_CHARS = 500_000
|
||||
CONTEXT_KEEP_TAIL_MESSAGES = 14
|
||||
MAX_ITERATIONS = 1000
|
||||
DELEGATE_MAX_ITERATIONS = 60
|
||||
DELEGATE_MAX_ITERATIONS = 180
|
||||
OUTPUT_CAP_BYTES = 256 * 1024
|
||||
TOOL_ARG_PREVIEW = 220
|
||||
IMAGE_MAX_BYTES = 20 * 1024 * 1024
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ from .agent import (
|
||||
_with_datetime,
|
||||
)
|
||||
|
||||
DEFAULT_MAX_ITER = 60
|
||||
DEFAULT_MAX_ITER = 180
|
||||
WRITE_BUDGET = 20
|
||||
|
||||
_RUN_LOCK = asyncio.Lock()
|
||||
|
||||
+30
-4
@@ -6,6 +6,7 @@ import argparse
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
import sys
|
||||
from typing import Any, Optional
|
||||
|
||||
@@ -24,7 +25,7 @@ from .agent import (
|
||||
from .fleet import REGISTRY, ordered_agents
|
||||
from .orchestrator import run_fleet
|
||||
|
||||
MAESTRO_AGENT_MAX_ITER = 60
|
||||
MAESTRO_AGENT_MAX_ITER = 180
|
||||
MAX_RETURNED_FINDINGS = 12
|
||||
|
||||
_LAST_RESULTS: dict[str, dict[str, Any]] = {}
|
||||
@@ -272,17 +273,42 @@ async def _turn(messages: list[dict[str, Any]], renderer: MarkdownRenderer) -> N
|
||||
)
|
||||
|
||||
|
||||
_OWN_OUTPUT_PREFIX = re.compile(r"^\d{1,2}:\d{2}:\d{2}\s+\+\d{1,2}:\d{2}:\d{2}")
|
||||
|
||||
|
||||
def _has_terminal_control(raw: str) -> bool:
|
||||
return any(ch == "\x1b" or (ord(ch) < 32 and ch != "\t") for ch in raw)
|
||||
|
||||
|
||||
def _drain_stdin() -> None:
|
||||
try:
|
||||
if not sys.stdin.isatty():
|
||||
return
|
||||
import termios
|
||||
|
||||
termios.tcflush(sys.stdin.fileno(), termios.TCIFLUSH)
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
|
||||
|
||||
def _prompt_line() -> str:
|
||||
_drain_stdin()
|
||||
return input("\n> ")
|
||||
|
||||
|
||||
async def interactive(renderer: MarkdownRenderer) -> None:
|
||||
renderer.print("# Maestro\nThe conductor. Ask about any quality dimension, or say `exit` to quit.")
|
||||
messages: list[dict[str, Any]] = [{"role": "system", "content": _with_datetime(MAESTRO_PROMPT)}]
|
||||
loop = asyncio.get_event_loop()
|
||||
while True:
|
||||
try:
|
||||
line = await loop.run_in_executor(None, lambda: input("\n> "))
|
||||
raw = await loop.run_in_executor(None, _prompt_line)
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
break
|
||||
line = line.strip()
|
||||
if not line:
|
||||
if _has_terminal_control(raw):
|
||||
continue
|
||||
line = raw.strip()
|
||||
if not line or _OWN_OUTPUT_PREFIX.match(line):
|
||||
continue
|
||||
if line.lower() in ("exit", "quit"):
|
||||
break
|
||||
|
||||
@@ -22,7 +22,7 @@ def _parser() -> argparse.ArgumentParser:
|
||||
mode.add_argument("--check", dest="mode", action="store_const", const="check")
|
||||
parser.set_defaults(mode="fix")
|
||||
parser.add_argument("--only", default=None, help="Comma-separated subset of agent names")
|
||||
parser.add_argument("--max-iter", type=int, default=40)
|
||||
parser.add_argument("--max-iter", type=int, default=120)
|
||||
parser.add_argument("--no-color", action="store_true")
|
||||
parser.add_argument("-v", "--verbose", action="store_true")
|
||||
return parser
|
||||
|
||||
+30
-4
@@ -13,8 +13,32 @@ class StyleAgent(MaintenanceAgent):
|
||||
return (
|
||||
"Enforce the explicit CLAUDE.md and AGENTS.md coding rules across all source.\n\n"
|
||||
"DETECT (mostly deterministic, grep and AST):\n"
|
||||
"- Forbidden naming prefixes and suffixes: _new, _old, _current, _prev, _next (outside iteration), _temp, _tmp, "
|
||||
"_v1/_v2/_v3, better_, best_, simple_, my_, the_, _data, _info, and the rest of the forbidden list.\n"
|
||||
"- Forbidden naming prefixes and suffixes, CONTEXT-AWARE: the banned tokens are _new, _old, _current, _prev, "
|
||||
"_next (outside iteration), _temp, _tmp, _v1/_v2/_v3, better_, best_, simple_, my_, the_, _data, _info, and the "
|
||||
"rest of the forbidden list. This rule targets LAZY, RENAMEABLE VARIABLE AND HELPER names you own - it is NOT a "
|
||||
"blind substring sweep, and most surface hits on _data/_info/_item/_val are FALSE POSITIVES. Run this exact "
|
||||
"decision algorithm for EVERY candidate before recording it, and skip it the moment any test below fails:\n"
|
||||
" STEP 1 - IS IT A CONTRACT IDENTIFIER? Resolve what the name actually is. If it is a string that other code, "
|
||||
"templates, the database, the API, or docs reference by that exact spelling, it is a CONTRACT and renaming it is "
|
||||
"a breaking change (Doctrine C and D), NOT a style fix. Contract identifiers include: a Jinja template global or "
|
||||
"filter (templates.env.globals[...] / env.filters[...], called as {{ name(...) }} in .html), a Devii action or "
|
||||
"tool name=, a route path or endpoint, a DB table or column, a Pydantic or dataclass FIELD, a JSON response key, "
|
||||
"an audit event key, a site_settings/config/env key, a CSS class, or a JS export. For ANY contract identifier: do "
|
||||
"NOT flag it as a forbidden-name violation and NEVER rename it; at most record ONE info finding noting the "
|
||||
"convention. (Examples that are contracts, hence NOT violations: the template global badge_info; the Devii action "
|
||||
"admin_services_data.)\n"
|
||||
" STEP 2 - SUBSTANCE TEST (only for a genuinely local/private, freely-renameable name). Ask: is the trailing "
|
||||
"(or leading) token a VAGUE PLACEHOLDER that adds zero information, so the name means exactly the same thing "
|
||||
"without it? Real violations: users_new -> users_active, connection_old, my_config -> config, result_val -> "
|
||||
"result, payload_obj -> payload, user_data -> user. It is a FALSE POSITIVE (do NOT flag) when: the token is the "
|
||||
"actual domain noun or a real concept here (an audit event, a metrics sample, a request's data body of a "
|
||||
"data endpoint, badge info as a real thing); OR the token is part of a larger real word or compound (data inside "
|
||||
"metadata, info inside a normal word, next/prev as loop iterators); OR dropping it would collide with another "
|
||||
"name in scope or lose genuine meaning; OR it matches a well-known external library/framework name.\n"
|
||||
" STEP 3 - CONFIDENCE GATE. Record a forbidden-name WARNING only if, after steps 1-2, you are CERTAIN it is a "
|
||||
"renameable local name whose token is pure placeholder AND you can state the safe replacement and have checked "
|
||||
"its references (Doctrine C). Otherwise drop it or record a single info finding. A wrong rename is a regression; "
|
||||
"when in doubt, do not flag.\n"
|
||||
"- No comments or docstrings in source files, EXCEPT the mandatory header and the docstrings that @tool functions "
|
||||
"require for their schema (the proven agent engine convention).\n"
|
||||
"- Em-dash, CONTEXT-AWARE (think before you touch it): the rule bans em-dashes (U+2014, and U+2013) "
|
||||
@@ -42,12 +66,14 @@ class StyleAgent(MaintenanceAgent):
|
||||
"string), leaving every data em-dash untouched, "
|
||||
"add the type annotation, convert os.path to pathlib, convert the dict to a dataclass, remove the version pin, add "
|
||||
"the header, or name the constant. Only touch code you are already editing for a finding; do not restyle untouched "
|
||||
"code. A rename that would change a public API symbol is reported, not auto-applied."
|
||||
"code. A rename is auto-applied ONLY for a confirmed local/private name that passed the forbidden-name decision "
|
||||
"algorithm, and ONLY after you grep every reference and update them in the same run (Doctrine C); a rename that "
|
||||
"would touch a contract identifier or any public API symbol is reported, never auto-applied."
|
||||
)
|
||||
|
||||
def scope_units(self) -> list[tuple[str, str]]:
|
||||
return [
|
||||
("forbidden-names", "devplacepy/**/*.py forbidden naming prefixes/suffixes"),
|
||||
("forbidden-names", "devplacepy/**/*.py forbidden naming prefixes/suffixes on renameable local names only - run the decision algorithm: contract identifiers (template globals, Devii action names, DB columns, schema fields, routes, CSS/JS/config keys) and meaningful domain tokens are false positives, not violations"),
|
||||
("headers", "retoor header on created/edited files only; one info finding for pre-existing files that lack it, never a mass sweep"),
|
||||
("em-dash", "prose em-dashes (comments, docstrings, user-facing strings, markdown) become hyphens; em-dashes that are DATA (replace/maketrans/regex targets, sanitizers, fixtures) are left untouched"),
|
||||
("typing", "Python function signatures and variables fully typed"),
|
||||
|
||||
Reference in New Issue
Block a user