File size: 2,577 Bytes
fc88b2a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | """
server/handoff_validator.py
Validates structured handoff notes written by the agent at the end of Session 1.
Enforces a 6-section required format. Rejects (not penalises) invalid notes so
the agent can retry within its retry budget.
"""
from dataclasses import dataclass
@dataclass
class ValidationResult:
valid: bool
reason: str = ""
class HandoffValidator:
"""
Validates that the agent's handoff note:
1. Contains all 6 required section headers.
2. Does not embed large code blocks (prevents code-dump gaming).
3. Does not exceed the token budget (prevents padding gaming).
"""
REQUIRED_SECTIONS = [
"TASK:",
"COMPLETED:",
"REMAINING:",
"KEY FUNCTIONS:",
"EDGE CASES:",
"NEXT STEPS:",
]
MAX_CODE_BLOCK_LINES = 5 # prevents "just paste the code" shortcut
MAX_TOKENS = 400 # hard ceiling — forces compression
def validate(self, content: str) -> ValidationResult:
if not content or not content.strip():
return ValidationResult(valid=False, reason="Handoff note is empty.")
for section in self.REQUIRED_SECTIONS:
if section not in content:
return ValidationResult(
valid=False,
reason=f"Missing required section: '{section}'. "
f"All required: {self.REQUIRED_SECTIONS}",
)
code_lines = self._count_code_block_lines(content)
if code_lines > self.MAX_CODE_BLOCK_LINES:
return ValidationResult(
valid=False,
reason=(
f"Code block too long ({code_lines} lines, max {self.MAX_CODE_BLOCK_LINES}). "
"Use function signatures only, not full implementations."
),
)
token_count = len(content.split())
if token_count > self.MAX_TOKENS:
return ValidationResult(
valid=False,
reason=(
f"Handoff too long ({token_count} tokens, max {self.MAX_TOKENS}). "
"Be more concise."
),
)
return ValidationResult(valid=True)
def _count_code_block_lines(self, content: str) -> int:
in_block = False
count = 0
for line in content.split("\n"):
stripped = line.strip()
if stripped.startswith("```"):
in_block = not in_block
elif in_block:
count += 1
return count
|