Maintenance | Electric Cherry
{#snippet actions()} {#if data}{/if} {/snippet} {#if error}{/if} {#if notice}

{notice}

{/if} {#if data?.policies.paused}
All maintenance is paused. Checks and verification continue. New actions, scheduled runs, and queued maintenance are held. Submitted operations finish recovery. Campaigns, betas, and manual Provisioning actions continue.
{/if} saveContext()} ariaLabel="Maintenance views" idPrefix="maintenance-tabs" panelId="maintenance-panel" />
{#if data} {#if view === 'policies'}

Policies apply to the current fleet and respect intentionally stopped servers. Disabling a recovery or automatic update policy holds its queued actions. Already submitted operations continue verification.

{#each policies as policy}

{policy.title}

{data.policies[policy.id] ? 'Enabled' : 'Disabled'}

{policy.description}

{/each}

Scheduled restarts

Restart the running fleet daily, even without a new release. Intentionally stopped servers are excluded. Busy servers wait until empty and may restart later.

{ event.preventDefault(); void act({ action: 'schedule', enabled: scheduleEnabled, time: scheduleTime, timeZone: $timeZone }); }}>

Saving follows daylight saving changes in your selected timezone. Skipped times run at the next valid minute; repeated times run once. Missed days become one run on resume.

{#if data.runtime.schedule.enabled && data.runtime.schedule.timeZone !== $timeZone}

Saved for {data.runtime.schedule.time} in {data.runtime.schedule.timeZone}. Save to use {$timeZone}.

{/if} {#if data.runtime.schedule.nextAt}

Next run: {$timeFormat.dateTime(data.runtime.schedule.nextAt)}{data.policies.paused ? ' · Held while maintenance is paused' : ''}

{/if}

Disabling the schedule stops future runs. Existing requests remain in Activity, where unsubmitted restarts can be cancelled.

{:else} {#if view === 'overview'}
{attention} need attention{waiting} active{outdated.length} outdated{unknown.length} versions unverified
{#if data.runtime.schedule.nextAt}

Next scheduled restart: {$timeFormat.dateTime(data.runtime.schedule.nextAt)} · Manage schedule

{/if} {#if data.recovery.lastScanAt}

Health and drift checked {$timeFormat.dateTime(data.recovery.lastScanAt)}

{/if} {#if data.recovery.scanError}{/if} {/if}
{#if view === 'activity'}{/if}
{#if view === 'overview' && ['all', 'updates'].includes(kind)}

Plutonium updates

Published revision: {data.runtime.release.revision ? `r${data.runtime.release.revision}` : 'Unknown'} · Production manifest · Changelog

{#if data.runtime.release.checkedAt}

Checked {$timeFormat.dateTime(data.runtime.release.checkedAt)}

{/if} {#if data.runtime.release.error}{/if}

Plutainer applies the available release at startup when auto-update is enabled. Maintenance verifies the running revision after recovery. Unknown versions require a successful check before automatic updates.

{#each versions as version (version.server)} {@const pending = activeJobs.find(j => j.server === version.server)} {:else}{/each}
ServerRunning revisionStatusAction
{version.revision ? `r${version.revision}` : 'Unknown'}{#if version.checked_at}{$timeFormat.dateTime(version.checked_at)}{/if}{#if version.error}{version.error}{/if} {version.update_status === 'outdated' ? 'Update available' : version.update_status === 'current' ? 'Up to date' : version.update_status === 'ahead' ? 'Ahead of published release' : version.update_status === 'stopped' ? 'Intentionally stopped' : 'Unverified'} {#if pending}Restart pending{:else if version.update_status === 'outdated'}{/if}
No matching fleet servers.
{/if}

{view === 'overview' ? 'Active work & attention' : 'Maintenance activity'}

{#each matching.slice(0, limit) as item (item.key)}

{item.title} ·

{item.label}
{#if item.detail}

{item.detail}

{/if}

{$timeFormat.dateTime(item.at)}{item.job?.target_revision ? ` · Expected r${item.job.target_revision} or newer` : ''}

{:else}{/each}
saveContext(false)} label="activities" />
{/if} {:else if !error}

Loading maintenance…

{/if}