| """The two anti-gaming scripted agents (spec: build day one, wired forever). |
| |
| flag_everything: must score clearly negative on every task, or the FP penalty |
| is too weak. no_evidence: must approach zero on L2+, or a defect is leaking |
| into the ledger row. Both paginate query_ledger past the 200-row cap so real |
| L1 populations (400+) are fully covered.""" |
| from __future__ import annotations |
|
|
| from collections.abc import Sequence |
|
|
| from je_validation.envir.agent import ToolCall |
|
|
| ROW_CAP = 200 |
|
|
|
|
| def _query_pages(history): |
| return [(c, o) for c, o in history if c.tool == "query_ledger"] |
|
|
|
|
| def _collect_ids(history) -> list[str]: |
| ids: list[str] = [] |
| for _, obs in _query_pages(history): |
| if isinstance(obs, list): |
| ids += [row["entry_id"] for row in obs] |
| return ids |
|
|
|
|
| def _next_query(history) -> ToolCall | None: |
| pages = _query_pages(history) |
| if not pages: |
| return ToolCall("query_ledger", {"order_by": "entry_id"}) |
| last_obs = pages[-1][1] |
| if isinstance(last_obs, list) and len(last_obs) == ROW_CAP: |
| return ToolCall("query_ledger", |
| {"order_by": "entry_id", "offset": len(_collect_ids(history))}) |
| return None |
|
|
|
|
| def _foot(lines) -> tuple: |
| dr = cr = 0 |
| for ln in lines: |
| if "side" in ln: |
| if ln["side"] == "D": |
| dr += ln.get("amount_cents", 0) |
| else: |
| cr += ln.get("amount_cents", 0) |
| else: |
| dr = round(dr + ln.get("dr", 0), 2) |
| cr = round(cr + ln.get("cr", 0), 2) |
| return dr, cr |
|
|
|
|
| class FlagEverythingAgent: |
| def __init__(self, issue_types: Sequence[str] | None = None): |
| |
| |
| |
| self._issue_type = (issue_types or ("defect",))[0] |
|
|
| def decide(self, brief: str, history) -> ToolCall: |
| nxt = _next_query(history) |
| if nxt is not None: |
| return nxt |
| ids = _collect_ids(history) |
| n_disp = sum(1 for c, _ in history if c.tool == "disposition") |
| if n_disp < len(ids): |
| return ToolCall("disposition", { |
| "entry_id": ids[n_disp], "verdict": "flag", |
| "issue_type": self._issue_type, |
| "rationale": "flagged by baseline", "evidence_ids": []}) |
| return ToolCall("submit", {}) |
|
|
|
|
| class NoEvidenceAgent: |
| def decide(self, brief: str, history) -> ToolCall: |
| nxt = _next_query(history) |
| if nxt is not None: |
| return nxt |
| ids = _collect_ids(history) |
| gets = [(c, o) for c, o in history if c.tool == "get_entry"] |
| if len(gets) < len(ids): |
| return ToolCall("get_entry", {"entry_id": ids[len(gets)]}) |
| n_disp = sum(1 for c, _ in history if c.tool == "disposition") |
| if n_disp < len(ids): |
| eid = ids[n_disp] |
| obs = next(o for c, o in gets if c.args.get("entry_id") == eid) |
| lines = obs.get("lines", []) if isinstance(obs, dict) else [] |
| dr, cr = _foot(lines) |
| if dr != cr: |
| return ToolCall("disposition", { |
| "entry_id": eid, "verdict": "flag", "issue_type": "unbalanced", |
| "rationale": f"dr {dr} != cr {cr}", "evidence_ids": []}) |
| return ToolCall("disposition", { |
| "entry_id": eid, "verdict": "approve", "issue_type": "", |
| "rationale": "no issue visible in ledger", "evidence_ids": []}) |
| return ToolCall("submit", {}) |
|
|