Add `mosaic fleet regen`, a projection-only recovery command that rebuilds
each `fleet/agents/<name>.env.generated` from the `roster.yaml` SSOT after an
upgrade or partial write leaves the generated projections stale or missing.
- Dry-run by default; `--write` applies; `--json` for machine output. Reuses the
merged reconciler's projection plumbing (projectRosterV2AgentGeneratedEnv +
the generated-env boundary) rather than reimplementing fleet logic.
- Structurally NEVER issues a lifecycle/restart call — regen recovers config
only; a recordingRunner gate proves no runner invocation ever occurs.
- Serializes against agent CRUD and reconcile via BOTH fleet locks
(roster.yaml.mutation.lock + roster.yaml.reconcile.lock), acquired
mutation-then-reconcile and released in reverse; both are non-blocking `wx`
locks that throw on contention, so no deadlock is possible.
- Hardens the shared managed-lock helper: ownership-proving tokened lock reused
for both locks with per-lock fault labels; init-failure cleanup no longer
strands a just-created lock (dev/ino guard, with a persisted-token fallback
when the post-create stat itself fails); acquire-unwind surfaces a lock
cleanup fault instead of dropping it.
- Resolves personas the SAME way reconcile does by forwarding configured
rolesDir/overrideDir, so a custom-persona-root deployment cannot have
reconcile accept a roster that regen rejects.
- Report/output is secrev-safe: paths and counts only, never projected values.
- Docs: upgrade-safety-and-recovery runbook + fleet-local-canary note.
Tests are TDD red-first with co-located specs (regen spec: 26 tests covering
dry-run/write dispositions, the never-restarts gate, all lock regressions, and
persona-root wiring).
A residual check-then-unlink TOCTOU in the lock release remains (byte-identical
to the merged reconcile lock; unreachable within the `wx` writer protocol); its
true fix is an fd-held advisory lock adopted by all fleet writers, tracked as a
separate follow-up.
Part of #791
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>