feat(WARDEN-WP-0021): T3-T5 — visibility, approve loop, runbook (scheduled worker complete)
T4 (review→send loop): conservative tick persists structured drafts to state_dir/worker-drafts.json; `warden worker drafts` lists them, `warden worker approve <id> [--body …]` sends the reviewed draft as the reply + marks read + drops it. Escalated plans persist no draft. Live-verified end-to-end. T3 (visibility): `warden worker status` (pending drafts, triage count, last digest, timer state); best-effort notify-send nudge in the tick when drafts are pending. T5: wiki/playbooks/scheduled-worker.md (enable/disable, the approve loop, failure modes, conservative-only posture) + SCOPE note. WARDEN-WP-0021 finished: the conservative worker now runs on a systemd --user timer (enabled, every 15 min), triages new inbox messages into drafts you approve with one command, degrades gracefully, and stops with one command. 249 tests, lint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9dc1db0162
commit
a10bbd2162
7 changed files with 253 additions and 6 deletions
|
|
@ -1212,3 +1212,42 @@ def worker_run(
|
|||
else:
|
||||
console.print("[green]Conservative triage[/green] — drafting; nothing sent to other agents.")
|
||||
console.print(run_conservative(plans, hub, topic_id=topic_id))
|
||||
|
||||
|
||||
@worker_app.command("drafts")
|
||||
def worker_drafts() -> None:
|
||||
"""List the worker's pending drafted replies (from the conservative tier)."""
|
||||
from warden.worker import list_drafts
|
||||
console.print(list_drafts())
|
||||
|
||||
|
||||
@worker_app.command("approve")
|
||||
def worker_approve(
|
||||
message_id: Annotated[str, typer.Argument(help="Message id to send the drafted reply for")],
|
||||
body: Annotated[
|
||||
Optional[str], typer.Option("--body", help="Override the drafted reply text before sending")
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Send a reviewed draft as the reply and mark the message read."""
|
||||
from warden.worker import HubClient, approve_draft
|
||||
try:
|
||||
console.print(approve_draft(message_id, HubClient(), body_override=body))
|
||||
except Exception as e: # noqa: BLE001 — surface transport errors cleanly
|
||||
err.print(f"[red]Approve failed:[/red] {e}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
@worker_app.command("status")
|
||||
def worker_status_cmd() -> None:
|
||||
"""Show worker state: pending drafts, triage count, last digest, timer status."""
|
||||
import subprocess
|
||||
from warden.worker import worker_status
|
||||
console.print(worker_status())
|
||||
try:
|
||||
st = subprocess.run(
|
||||
["systemctl", "--user", "is-active", "ops-warden-worker.timer"],
|
||||
capture_output=True, text=True, timeout=5,
|
||||
).stdout.strip()
|
||||
console.print(f"timer : {st or 'unknown'}")
|
||||
except Exception: # noqa: BLE001 — systemd may be absent (cron/other host)
|
||||
console.print("timer : (systemd not available)")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue