feat: mail-triage via llm-connect (no host Claude)

Add LLMConnectClient and mail-triage: CSV metadata → OpenRouter-backed
llm-connect JSON plan → deterministic mail-log apply + commit. Server path
for Binky mail intake on Railiance (BINKY-WP-0006).
This commit is contained in:
tegwick 2026-07-22 00:05:23 +02:00
parent 66ccd4fa01
commit 7520a53831
7 changed files with 730 additions and 4 deletions

View file

@ -200,6 +200,26 @@ def main(argv: list[str] | None = None) -> int:
scan.add_argument("--out", default="mailmeta/reports")
scan.add_argument("--no-hub", action="store_true", help="Skip hub reporting")
triage = sub.add_parser(
"mail-triage",
help="Triage newest mail CSV via llm-connect (JSON + deterministic apply; no Claude)",
)
triage.add_argument("--target-repo", required=True)
triage.add_argument("--reports-dir", default="mailmeta/reports")
triage.add_argument("--mail-log", default="mailmeta/mail-log.md")
triage.add_argument(
"--max-rows",
type=int,
default=None,
help="Max CSV rows to send to the model (default env MAIL_TRIAGE_MAX_ROWS or 40)",
)
triage.add_argument("--no-hub", action="store_true", help="Skip hub reporting")
triage.add_argument(
"--no-commit",
action="store_true",
help="Apply log updates but do not git commit",
)
validate = sub.add_parser(
"validate",
help="Validate instance manifest (.kaizen/schedule.yml + harness fields)",
@ -305,6 +325,33 @@ def main(argv: list[str] | None = None) -> int:
ok = smoke_result.run.ok and (smoke_result.pushed or args.no_push)
return 0 if ok else 1
if args.command == "mail-triage":
from agent_harness.mail_triage import run_mail_triage
triage_result = run_mail_triage(
target_repo=Path(args.target_repo).expanduser(),
reports_dir=args.reports_dir,
mail_log_rel=args.mail_log,
max_rows=args.max_rows,
report_to_hub=not args.no_hub,
commit=not args.no_commit,
)
print(
json.dumps(
{
"ok": triage_result.ok,
"report": triage_result.report,
"entries_applied": triage_result.entries_applied,
"committed": triage_result.committed,
"head_after": triage_result.head_after,
"reason": triage_result.reason,
"model_meta": triage_result.model_meta,
},
indent=2,
)
)
return 0 if triage_result.ok else 1
if args.command == "mail-scan":
from agent_harness.mailscan import run_mail_scan