Skip to content

Loop daemon: harden runtime-env resolution — bake resolved PATH into installed units, don't depend on nvm sourcing at runtime #107

Description

@robercano-ghbot

Incident (2026-07-10, first live daemon run)

The freshly armed pr-loop-<slug>.service polled fine but silently never merged an approved, CI-green PR (#105) and never wrote tick records: the systemd user PATH has gh but neither node nor claude, and merge-ready.sh (4 node calls), loop-census.sh (2), and write_tick_record all need node. Deadlock: unmerged PR ⇒ advance never fires ⇒ run_driver's nvm fallback (the only nvm-sourcing path) never runs. Hotfixed on main (4bf7dbb) by calling ensure_claude_on_path once in main().

Remaining hardening

  1. Bake the resolved PATH into the unit at install time: arm-loop.sh runs in a real terminal with the user's full environment — it should substitute Environment=PATH=<dirname of resolved node/claude>:... into the installed unit (new __PATH__ placeholder in the templates). Runtime nvm-sourcing then becomes the fallback, not the mechanism; installs that use fnm/volta/system node work too.
  2. Fail loudly, not silently: if node is unresolvable at daemon startup, the current warning only reaches the journal. Consider also emitting a tick record with result=env-error (or a main_dirty-style census line) so the cockpit loop-health panel (Cockpit: loop-health panel — last tick, cadence, verdict history, stall detection #85) can surface a daemon running in a degraded env.
  3. Cosmetic: the daemon-driven tick record was written with an empty cadence field (manual full-env tick recorded WATCH correctly) — trace how cadence is threaded into write_tick_record when invoked via loop-event under the daemon and fix.
  4. Tests: extend loop-daemon.test.sh with an env -i-style case asserting node-dependent steps work after startup resolution (guard the regression the hotfix fixed).

Labels: backlog (owner approves via planned).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmodule:harnessOrchestrator machinery under .claudeplannedOwner-approved for the autonomous loop (assigned ONLY by the owner)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions