feat(fleet): preventive health + local fallback (guard/tunnel/fallback drift) - #329
Merged
Conversation
Closes #328 Makes fleet drift visible and one-click fixable after the 2026-08-07 silent-fork (#324): pure fleet_health module (darwin-only) drives guard/settings/tunnel checks used by amicode.healthcheck and an activation-time fleet warning with [Fix fleet] -> tools/fleet/install.sh. Vends the fleet as tools/fleet/{guard,plist,install.sh} + packaged packages/extension/tools/fleet/* (VSIX !tools/**), CI fleet-gate fails on template or packaged drift, and healthcheck + install --check stay green on both hosts. Test: pnpm --filter amicode test (923 pass, +13 fleet), pnpm typecheck, build, vsce package includes tools/fleet, assert_fleet_guard.sh + install.sh --check green.
Per CONTEXT.md Local fallback / Rejoin (ADR 0005). On fleet client when canonical unreachable (mini offline — tailscale Online:false — tunnel 255), guard previously exit 1 with no escape hatch. Adds machine-scoped fallback marker ~/.amico/ops/fleet/fallback.json and: - guard honors fallback: if marker exists, allow local spawn (fall through to frozen/VSIX/dev) instead of exit 1, with hint to Enter Local Fallback - fleet_fallback.ts pure module (isFallbackActive/enter/exit, fallbackPath, status label) + fleet_fallback.test.ts (4) - fleet_health: +Fleet fallback row, skips guard/settings/tunnel drift while fallback active so healthcheck stays green on intentional drift; aggregate now 4 checks - extension: amicode.fleet.fallback.enter/exit + amicode.fleet.rejoin (archive shard to ~/.amico/fleet-recovery/<date>, exit, restore guard+4096), fallback status bar (warning bg, click to Rejoin), healthcheck+activation fallback-aware - package.json 3 commands, .vscodeignore already !tools/** - vsce packages extension/tools/fleet/*, assert_fleet_guard checks fallback marker Normal ssh remains Match host amico-mini LAN-first (verified tailscale erlich ok, amico-mini timeout is canonical offline, not ssh tweak). Test: typecheck ok, 928 tests, build, vsce includes extension/tools/fleet 4 files, guard with fallback now execs opencode on client.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #328, closes #332
Summary
Fleet hardening (#324) fixed the silent-fork as ops (
guard+15/2tunnel) but left no product signal —mainbehind, stale guard,30/3plist all silent. When the canonical is actually offline (tailscale Online:false2026-08-11,erlichstillOnline:true→ normalsshhealthy, fleetssh amico-minitimeout) the panel was just dead with no hatch. Ships the preventive health + local fallback perCONTEXT.md/ADR 0005.Preventive health (#328):
fleet_health.ts(Aarons-Mac-mini/4096, injectable reads) —guard/settings/tunneldarwin-only checks +Fleet fallbackrow (now 4 checks total).extension.tsamicode.healthcheckfleet rows + activation warning[Fix fleet]→amicode.fleet.repair(bash <extensionPath>/tools/fleet/install.sh).tools/fleet/{guard,plist,install.sh}↔packages/extension/tools/fleet/*(!tools/**,vsceincludes 4 files,cmpCI gate),assert_fleet_guard.sh+ci.ymlfleet-gate.Local fallback (#332):
~/.amico/ops/fleet/fallback.json({active,since,previousBinary,previousPort}) — machine-scoped, never synced.if [ -f "$FALLBACK" ]; then :; elif [ "$(scutil …)" != … ]; then exit 1—touch fallback.json && guard --helpnowexecsopencodeon client (verified), hint added:Run 'Amicode: Fleet — Enter Local Fallback'.fleet_fallback.ts(enter/exit/isActive/read/status) +fleet_fallback.test.ts(4).extension.tsfallback status bar$(warning) Fleet: LOCAL FALLBACK(warning bg, click → Rejoin) +amicode.fleet.fallback.enter(modal, saves prevopencodeBinary/opencodePort, clears to vendored+0ephemeral, restarts),…exit(restoresguard+4096),…rejoin(probes127.0.0.1:4096/4096, archives~/.local/share/opencode/opencode.db→~/.amico/fleet-recovery/<date>/, then exits fallback + healthcheck).fleet_healthskipsguard/settings/tunnelwhile fallback active (intentional drift not red),tools/fleet/README.mdLocal fallback docs,Match host amico-miniLAN-first unchanged (erlichproves normalsshhealthy).Parent: #283.
Testing
pnpm --filter amicode typecheck— cleanpnpm --filter amicode test— 928 passed (910 → +13fleet_health+4fleet_fallback+1 fallback aggregate)pnpm --filter amicode run build—dist/extension.js 853kbvsce package— includesextension/tools/fleet/*4 files (amico-opencode-fleet-guard2147B fallback-aware)bash packages/extension/scripts/assert_fleet_guard.sh—all fleet gates passed(fallback marker check)touch fallback.json→guard --helpshowsopencodenotrefusing;rm→refusing+ hint;Match host amico-miniping Aarons-Mac-mini.local→.localon LAN else100.125.66.86;erlichsshOnline:truevsaarons-mac-miniOnline:falseproves ssh tweak intactFollow-on
Full server-side Rejoin fixture-locked merge (#290) lands with identity/Fleet-token (#284) — this is local-only shard archive per
preserve, never delete.Checklist
Fleet fallback: ACTIVEwhile offline,healthcheckgreen on fallbacklsof -iTCP:4096ssh LISTENwhen canonical up, localopencodeLISTEN on ephemeral when fallbacktools/fleet/*↔packages/extension/tools/fleet/*cmpclean via CI