Make the build's systemd probe test what the build actually runs

Table of Contents

This page is a capture in the inbox bucket of the product backlog — a pre-sprint idea, not yet pulled into a sprint as a story.

1. What

compass build runs the configure step plainly and wraps only the cmake --build step in a memory-capped scope:

if not args.dry_run and slot_name is not None and compass_claude._has_user_systemd():
    build_cmd = [
        "systemd-run", "--user", "--scope", "-q", "--collect", ...
    ] + build_cmd

The probe asks a different question than the wrap needs answered:

def _has_user_systemd() -> bool:
    if shutil.which("systemd-run") is None:
        return False
    try:
        systemctl_bus.run(["show-environment"], ..., check=True)
        return True
    except (subprocess.CalledProcessError, OSError):
        return False

systemctl show-environment can succeed where systemd-run --scope cannot, because the scope needs a connection systemctl never opens. When that happens the probe says yes, the wrap is added, and the build dies before compiling anything:

Failed to connect to user scope bus via local transport: No such file or directory
❌ Command failed with exit code 1: systemd-run --user --scope -q --collect ...

The probe should exercise what the wrap depends on — for example a trivial systemd-run --user --scope true — or the wrap should go through the ORES_USE_BUSCTL transport that the rest of compass now adopts, so one setting governs every systemd call.

Two further traps for whoever picks this up:

  • compass build --dry-run cannot show the problem. A dry run does not take the build lock, so slot_name is None and the wrap is skipped; the dry run prints a plain cmake command and looks healthy.
  • Unsetting DBUS_SESSION_BUS_ADDRESS and pointing XDG_RUNTIME_DIR at an empty directory does make the probe fail and the build proceed, which is how the analytics verification finished on 2026-09-26. That is a workaround for one sandbox, not a fix.

2. Why

Found on 2026-09-26 while re-verifying the ores.analytics clean pass after rebasing onto a main that carries the .env transport adoption. Builds that had succeeded earlier in the same sandbox began failing immediately, with no source change involved: main moved the systemd calls onto systemctl_bus, the probe started passing where it used to fail, and the scope wrap became reachable.

The cost is that the sandbox cannot build at all, so no local verification is possible there without the workaround — and the failure names a transport problem rather than the probe, which sends a reader looking at systemd instead of at compass.

3. References

  • projects/ores.compass/src/compass.py — the scope wrap in the build command builder.
  • projects/ores.compass/src/compass_claude.py — _has_user_systemd().
  • projects/ores.compass/src/systemctl_bus.py — use_busctl() and configure_from_env(); the docstring warns that a .env value nothing hands over does nothing.
  • doc/knowledge/architecture/env_format_version_log.org — version 24 introduced ORES_USE_BUSCTL.

4. See also

Emacs 29.3 (Org mode 9.6.15)