Revert "fix(installer): re-link runtime assets after the CLI stage"
ci/woodpecker/pr/ci Pipeline was canceled

This reverts 47e90767. I was wrong: the fix is correct about the cause and
makes the outcome worse.

The acceptance run passed everything I set out to check — greenfield canary
1125, --next --yes, no TTY, rc=0, node v22.23.2 + CLI 0.0.50-next.2413 from a
fresh login shell, and both enforcement hooks wired in ~/.claude/settings.json
where before they were stripped. Then `mosaic doctor` on that same host:

  [ERROR] Lease-enforcement hooks (mutator-gate.py, receipt-observer-client.py)
  are wired in ~/.claude/settings.json, but broker not healthy
  (checkBrokerSupervisorHealth() reports unhealthy). Every gated tool call will
  fail closed and BRICK this agent (see #869).

So the change takes a greenfield host from 'enforcement quietly off, agent
works' to 'enforcement wired, broker absent, agent bricks on the first gated
tool call'. The pre-existing behaviour reaches the safe state for the wrong
reason; this reaches the unsafe state for the right one. Safe-for-the-wrong-
reason still wins.

The real defect is underneath both, and it is not an ordering bug:

  mosaic __link-claude-settings ...   -> rc=0  (leaseEnforcementActivatable:
                                                 activatable, wire the hooks)
  mosaic doctor                       -> ERROR (checkBrokerSupervisorHealth:
                                                 unhealthy, hooks will brick)

Two capability checks, same host, opposite verdicts. And after a complete
install there is no broker supervisor to be healthy: no systemd --user unit
matching lease/broker, nothing under ~/.mosaic but the bootstrapped node, and
no lease or broker script in ~/.config/mosaic/tools/_scripts/. Lease
enforcement cannot be activated on a greenfield host at all, so
leaseEnforcementActivatable() returning true is the thing that is wrong.

Filing that separately. PR #1229 goes back to exactly the four commits scooby
reviewed.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-15 21:42:20 -05:00
co-authored by Claude Opus 5
parent 47e90767b7
commit fb5bb98a32
-33
View File
@@ -953,39 +953,6 @@ if [[ "$FLAG_CLI" == "true" ]]; then
fi
fi
# ═══════════════════════════════════════════════════════════════════════════════
# Post-install repair: link runtime assets again, now that the CLI exists
# ═══════════════════════════════════════════════════════════════════════════════
#
# The framework's own install.sh ends by running `mosaic-link-runtime-assets`,
# and that script asks the `mosaic` CLI whether lease enforcement can be
# activated on this host before deciding whether to wire the #828 enforcement
# hooks into settings.json. On a first install there is no CLI to ask — Part 1
# runs before Part 2 — so it takes its fail-safe branch, prints a four-line
# ERROR, and writes settings.json with the hooks stripped out.
#
# The result is that a greenfield host always ends up with enforcement
# disabled, decided by the order the two halves install in rather than by
# anything about the host. Measured on canary 1125, greenfield, both the
# `--ref` and `--next` lanes.
#
# Running it once more here lets the guard reach its real verdict. The script
# is idempotent — unchanged files are skipped — so on an upgrade, where the CLI
# was already present and the first pass already succeeded, this is a no-op.
# No `--allow-inactive-enforcement`: Part 1 does not pass it either, and this
# pass must not be more permissive than the one it is correcting.
if [[ "$FLAG_CHECK" == "false" && "$FLAG_FRAMEWORK" == "true" && "$FLAG_CLI" == "true" ]]; then
RELINK_SCRIPT="$MOSAIC_HOME/tools/_scripts/mosaic-link-runtime-assets"
if [[ -x "$RELINK_SCRIPT" && -x "$PREFIX/bin/mosaic" ]]; then
step "Runtime assets (re-check with CLI present)"
if PATH="$PREFIX/bin:$PATH" "$RELINK_SCRIPT" >/dev/null; then
ok "Runtime assets linked"
else
warn "Runtime asset linking is still degraded — see message above."
fi
fi
fi
# ═══════════════════════════════════════════════════════════════════════════════
# Summary
# ═══════════════════════════════════════════════════════════════════════════════