251eeb21ff
Continuing the round-3 deep-pass cleanup. Three more run-blockers + one robustness fix. RB5 — MERGING handler never invoked from master loop: ``run_merging_tick`` was exported by the master package but no caller fired it. Workflows that transition to MERGING (via reviewer approval) would sit there indefinitely with no Forgejo merge call. Fix: - ``master/loop.py`` accepts a ``merging_args=(owner, repo, merge_callback)`` kwarg. When set, the tick fires every iteration (cheap if no workflows in MERGING). - ``MasterTickReport`` gains ``merging: MergingHandlerReport | None``. - ``master/__main__.py`` wires it from the Forgejo callback bundle. RB6 — periodic discovery never fires: ``run_discovery`` was only called at startup via ``run_startup_backfill`` + the ``--discovery-only-once`` smoke flag. PRs created after master startup would not be discovered until the master restarted. Fix: - ``master/loop.py`` accepts ``discovery_args=(owner, repo, list_prs, list_issues)`` or the 5-tuple with kwargs. Periodic tick on its own cadence (``CONTROLLER_DISCOVERY_INTERVAL_S``, default 30s). - ``MasterTickReport`` gains ``discovery: DiscoveryReport | None``. - ``master/__main__.py`` wires it + threads ``require_opt_in_label`` through. RB-robust — worker calls create_all defensively: Master is normally responsible for schema creation (workers run After= it via systemd ordering). But if the worker is started in isolation (test / local dev / unit ordering broken), it'd crash on the first query against missing tables. Fix: - ``worker/__main__.py`` calls ``create_all(engine)`` after ``build_engine``. ``create_all`` is idempotent (CREATE TABLE IF NOT EXISTS); safe to call from both master + worker. - ``cleveragents-controller-worker@.service`` adds ``After=cleveragents-controller-master.service`` + ``Wants=cleveragents-controller-master.service`` so systemd enforces the start ordering in production. Total: 703 controller tests pass (no test changes; all new wiring is exercised by master_main_loop tests via the new kwargs). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
61 lines
2.1 KiB
Desktop File
61 lines
2.1 KiB
Desktop File
[Unit]
|
|
Description=cleveragents controller — worker instance %i
|
|
Documentation=file:///etc/cleveragents/RUNBOOK.md
|
|
# Master initializes the DB schema via create_all on startup; workers
|
|
# should not race that.
|
|
After=network-online.target postgresql.service opencode.service cleveragents-controller-master.service
|
|
Wants=network-online.target cleveragents-controller-master.service
|
|
# Template unit. Enable per-instance via:
|
|
# systemctl enable --now cleveragents-controller-worker@implementer-1
|
|
# systemctl enable --now cleveragents-controller-worker@reviewer-1
|
|
# %i becomes the worker's role-pool identifier. The same env file
|
|
# (with CLEVERAGENTS_WORKER_ROLES_%i override) configures which roles
|
|
# this instance dequeues.
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=cleveragents
|
|
Group=cleveragents
|
|
WorkingDirectory=/opt/cleveragents-core
|
|
EnvironmentFile=/etc/cleveragents/worker.env
|
|
# Per-instance override file (optional): /etc/cleveragents/worker.%i.env
|
|
# overrides anything in worker.env for this specific instance.
|
|
EnvironmentFile=-/etc/cleveragents/worker.%i.env
|
|
|
|
# CLEVERAGENTS_WORKER_ROLES is read from env (default = all 5 roles).
|
|
# Per-instance env files override it to specialize pools — e.g. for
|
|
# instance "implementer-1" set CLEVERAGENTS_WORKER_ROLES=implementer
|
|
# in /etc/cleveragents/worker.implementer-1.env.
|
|
ExecStart=/opt/cleveragents-core/.venv/bin/python -m tools.controller.worker \
|
|
--opencode-url=${CONTROLLER_OPENCODE_URL} \
|
|
--log-level=${CONTROLLER_LOG_LEVEL}
|
|
|
|
KillSignal=SIGTERM
|
|
TimeoutStopSec=60s
|
|
# Longer than master because in-flight attempts get a graceful
|
|
# heartbeat-driven stop (worker waits for current attempt to finish
|
|
# OR for its TTL to pass).
|
|
Restart=always
|
|
RestartSec=10s
|
|
RestartPreventExitStatus=2
|
|
|
|
LimitNOFILE=8192
|
|
|
|
# Hardening
|
|
NoNewPrivileges=true
|
|
PrivateTmp=true
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
ReadWritePaths=/var/lib/cleveragents /var/log/cleveragents /tmp
|
|
# Workers spawn per-attempt MCP subprocesses; need /tmp writable.
|
|
ProtectKernelTunables=true
|
|
ProtectKernelModules=true
|
|
ProtectControlGroups=true
|
|
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
SyslogIdentifier=cleveragents-worker-%i
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|