From 6dbc61ec46731153941df3d55daccb9b57de0118 Mon Sep 17 00:00:00 2001 From: veronica Date: Mon, 24 Aug 2026 19:28:28 -0500 Subject: [PATCH] fix(#1408): mosaic-agent@ condition arms on either home shape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reconciler writes seat projections into the brain home when one is active (~/.mosaic/fleet/agents, mirroring start-agent-session.sh's brain-home resolution) and into MOSAIC_HOME on a legacy single-tree host. The unit's single config-home ConditionPathExists therefore skipped every seat on brain-home estates — measured on two estates independently: 27 projections vs 0 at the config path, and 5 vs 0; the gate never fired on either. Fix: two TRIGGERING conditions (`|` prefix — same-type conditions otherwise AND, which can never be true across two paths). Either shape arms the unit; start-agent-session.sh still resolves the authoritative copy itself. test-fleet-units.sh now asserts both triggering lines and REFUSES a bare (ANDing) ConditionPathExists spelling — that regression would disable autostart fleet-wide while reading as "has a condition". Sabotage-controlled: unit reverted, suite fails on the first new assertion; restored, green. Closes #1408 --- .../framework/systemd/user/mosaic-agent@.service | 12 +++++++++++- .../framework/systemd/user/test-fleet-units.sh | 11 +++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/mosaic/framework/systemd/user/mosaic-agent@.service b/packages/mosaic/framework/systemd/user/mosaic-agent@.service index 81f76b54..36db469b 100644 --- a/packages/mosaic/framework/systemd/user/mosaic-agent@.service +++ b/packages/mosaic/framework/systemd/user/mosaic-agent@.service @@ -11,7 +11,17 @@ PartOf=mosaic-tmux-holder.service # launcher would fail the unit. A skipped unit is the honest state for "enabled # but not yet configured"; systemd re-evaluates the condition on every start, so # the seat comes up on the next start once the reconciler has written env. -ConditionPathExists=%h/.config/mosaic/fleet/agents/%i.env.generated +# +# #1408: the reconciler writes projections into the BRAIN home when one is +# active (~/.mosaic/fleet/agents, mirroring start-agent-session.sh's brain-home +# resolution), and into MOSAIC_HOME on a legacy single-tree host. A single +# config-home condition therefore skipped every seat on brain-home estates — +# measured on two estates: 27 projections vs 0, and 5 vs 0, gate never fired. +# Two TRIGGERING conditions (the `|` prefix ORs same-type conditions, which +# otherwise AND): either shape arms the unit; the launcher still resolves the +# authoritative copy itself. +ConditionPathExists=|%h/.config/mosaic/fleet/agents/%i.env.generated +ConditionPathExists=|%h/.mosaic/fleet/agents/%i.env.generated [Service] Type=oneshot diff --git a/packages/mosaic/framework/systemd/user/test-fleet-units.sh b/packages/mosaic/framework/systemd/user/test-fleet-units.sh index 4edc1989..4f7ff5ab 100755 --- a/packages/mosaic/framework/systemd/user/test-fleet-units.sh +++ b/packages/mosaic/framework/systemd/user/test-fleet-units.sh @@ -32,6 +32,17 @@ if grep -qF -- '/bin/bash -lc' "$HOLDER"; then fail "holder must not start tmux through a login shell" fi grep -qF 'Requires=mosaic-tmux-holder.service' "$AGENT" || fail "agent does not require holder" +# #1408: the projection condition must arm on EITHER home shape. Both lines must +# carry the `|` triggering prefix — same-type conditions without it AND together, +# which can never be true (one file cannot exist at two paths), so a bare-spelling +# regression would disable autostart everywhere while reading as "has a condition". +grep -qF 'ConditionPathExists=|%h/.config/mosaic/fleet/agents/%i.env.generated' "$AGENT" || \ + fail "agent lacks triggering condition for the config home projection" +grep -qF 'ConditionPathExists=|%h/.mosaic/fleet/agents/%i.env.generated' "$AGENT" || \ + fail "agent lacks triggering condition for the brain home projection (#1408)" +if grep -qE '^ConditionPathExists=[^|]' "$AGENT"; then + fail "agent has a non-triggering ConditionPathExists — same-type conditions AND, re-arming #1408" +fi grep -qF 'start-agent-session.sh' "$AGENT" || fail "agent unit does not call start-agent-session.sh" if grep -qE '^Environment(File)?=' "$AGENT" "$INTERACTION"; then fail "agent units must not accept ambient or projection environment before strict parsing"