mirror of
https://github.com/0xWheatyz/handler.git
synced 2026-08-30 07:26:25 +00:00
feat!: headless is the only runner - delete the tmux run path (phase 4)
Agent runs are now always worker-owned 'claude -p' subprocesses; tmux survives only for the interactive /login flow. - deleted: worker.capture_agent_output/_pane_tail + the capture loop arm (the empty-/log bug's home), spawn's tmux launch/_claude_command, the tmux resume/kill branches (the silent-send-keys bug's home), tmux.session_name/list_sessions, the CLI attach subcommand, the 'runner' setting - spawn: task is now a hard requirement (headless has no idle REPL) - enforced in spawn (SpawnError) and the API (400); onboarding seeding dropped (-p skips the trust dialog) - resume: single headless path; pre-headless agent rows (no session_id) degrade to the context-re-injection fresh run - settings_gen: permissions allowlist is always emitted - credsync: change-triggered uploads key on .claude/.credentials.json only (claude touches ~/.claude.json every run - keying on it would ping-pong uploads between workers); logins still publish explicitly - cli list: liveness from agent_runs in the DB, not tmux - tests: spawn/kill/resume re-pointed at the fake_launch seam (conftest); integration test now drives API -> worker -> real fake claude subprocess -> events endpoint; README documents the headless model + multi-worker deployment invariants Suite 295 green; frontend unchanged since phase 3.
This commit is contained in:
+31
-6
@@ -1,7 +1,8 @@
|
||||
"""Shared fixtures. Everything runs on a fresh SQLite file per test, materialized via
|
||||
a *real* ``alembic upgrade head`` — so the migration path itself is under test, not
|
||||
just ``create_all``. No live claude/tmux/mise is ever touched: the three seams
|
||||
(``control.tmux``, ``hooks.verify``, ``control.spawn.resume``) are faked.
|
||||
just ``create_all``. No live claude/tmux/mise is ever touched: the seams
|
||||
(``control.headless.launch`` for runs, ``control.tmux`` for the login flow,
|
||||
``hooks.verify``, ``control.spawn.resume``) are faked.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -111,20 +112,44 @@ def fake_tmux(monkeypatch):
|
||||
def send_enter(name):
|
||||
calls["send_enter"].append({"name": name})
|
||||
|
||||
def list_sessions():
|
||||
return list(live)
|
||||
|
||||
monkeypatch.setattr(tmux, "new_session", new_session)
|
||||
monkeypatch.setattr(tmux, "has_session", has_session)
|
||||
monkeypatch.setattr(tmux, "kill_session", kill_session)
|
||||
monkeypatch.setattr(tmux, "send_keys", send_keys)
|
||||
monkeypatch.setattr(tmux, "send_text", send_text)
|
||||
monkeypatch.setattr(tmux, "send_enter", send_enter)
|
||||
monkeypatch.setattr(tmux, "list_sessions", list_sessions)
|
||||
|
||||
return {"calls": calls, "live": live}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_launch(monkeypatch):
|
||||
"""Record ``headless.launch`` calls instead of spawning a claude subprocess.
|
||||
|
||||
Mirrors the real launch's DB side effects (run row + agent session/worker) so kill/
|
||||
resume logic downstream of a fake spawn behaves like production, minus the process.
|
||||
"""
|
||||
from handler.control import headless
|
||||
from handler.db import repository as repo
|
||||
from handler.db.engine import connection
|
||||
|
||||
calls: list[dict] = []
|
||||
|
||||
def launch(agent, *, kind, prompt, settings_path, env, worker_id, on_exit=None):
|
||||
session_id = agent.get("session_id") if kind == "resume" else f"fake-sid-{len(calls) + 1}"
|
||||
with connection() as conn:
|
||||
run = repo.create_run(conn, agent["id"], session_id, worker_id, kind)
|
||||
repo.set_agent_session(conn, agent["id"], session_id, worker_id)
|
||||
calls.append(
|
||||
{"agent": agent, "kind": kind, "prompt": prompt, "settings_path": settings_path,
|
||||
"env": env, "worker_id": worker_id, "run": run}
|
||||
)
|
||||
return run
|
||||
|
||||
monkeypatch.setattr(headless, "launch", launch)
|
||||
return calls
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_gitops(monkeypatch):
|
||||
"""Fake the git seam: record config/add/commit, return a controllable branch/sha."""
|
||||
|
||||
Reference in New Issue
Block a user