Files
cleveragents-core/tools/controller/deploy/systemd/cleveragents-controller-worker@.service
T
drew 251eeb21ff fix(controller): more pipeline run-blockers — merging tick, periodic discovery, worker create_all, systemd ordering
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>
2026-05-18 16:47:10 -04:00

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