Improve operational UX, recovery flows, and action safety
Implement the approved UX review across Fleet, Betas, Library, deployments, and Settings. Add reviewed promotion and reconciliation plans, atomic queued-removal cancellation, recoverable beta drafts and launch inputs, accessible controls, and mobile improvements. Validated with 473 tests, a clean typecheck, production build, and isolated desktop/mobile browser walkthroughs. Include the review and implementation coverage notes.
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import type { BetaRequirement, BetaTestView } from './beta-plan.js';
|
||||
import { needsGameTelemetry } from './beta-plan-summary.js';
|
||||
|
||||
export function betaWaitingCondition(requirement: BetaRequirement, observation?: BetaTestView['servers'][number]['observation']): string {
|
||||
if (requirement.kind === 'manual') return 'Waiting for a tester to record their name and observation.';
|
||||
if (requirement.kind === 'recovery') return 'The other checks must pass before the next restart when empty; each cycle needs fresh evidence.';
|
||||
if (requirement.kind === 'healthy-minutes') return observation?.healthy === true
|
||||
? 'Collecting consecutive fresh healthy observations; an outage or monitoring gap resets this duration.'
|
||||
: 'Waiting for fresh container and RCON health observations. Unhealthy or stale observations reset this duration.';
|
||||
if (requirement.kind === 'failure-budget') return 'An observed health outage exceeded the budget. Investigate before starting a fresh attempt.';
|
||||
if (needsGameTelemetry(requirement)) {
|
||||
if (!observation?.lastGameplayAt) return 'No gameplay report received for this attempt. Check the game reporter and Telemetry API requests.';
|
||||
if (observation.gameEnded) return 'Waiting for the next game and its qualifying reports.';
|
||||
if (requirement.kind === 'population') return `Waiting for a game report containing at least ${requirement.target} players.`;
|
||||
const players = `at least ${requirement.minPlayers} player${requirement.minPlayers === 1 ? '' : 's'}`;
|
||||
if ((observation.players ?? 0) < requirement.minPlayers) return `The latest report has ${observation.players ?? 0} players; this check needs ${players}.`;
|
||||
if (requirement.kind === 'matches') return requirement.minMinutes && !observation.matchStarted
|
||||
? 'This match has no game-start report, so its duration cannot qualify. Waiting for a new game start and game end.'
|
||||
: `Waiting for game end${requirement.minRound ? ` after reaching round ${requirement.minRound}` : ''} with ${players}${requirement.minMinutes ? ` and at least ${requirement.minMinutes} minutes since game start` : ''}.`;
|
||||
if (requirement.kind === 'round') return `Waiting for a round change or game end reporting round ${requirement.target} or higher with ${players}.`;
|
||||
return `Time is credited when the next report arrives, with ${players} at both ends of the interval. It does not advance continuously between reports.`;
|
||||
}
|
||||
return 'Waiting for qualifying evidence.';
|
||||
}
|
||||
|
||||
export function betaEvidenceSummary(event: BetaTestView['evidence'][number]): string {
|
||||
let payload: Record<string, unknown>;
|
||||
try { payload = JSON.parse(event.payload); } catch { return event.kind.replaceAll('-', ' ').replaceAll('_', ' '); }
|
||||
if (!payload || typeof payload !== 'object') return event.kind;
|
||||
if (['game_start', 'round_change', 'game_end'].includes(event.kind)) {
|
||||
const label = event.kind === 'game_start' ? 'Game started' : event.kind === 'game_end' ? 'Game ended' : 'Round changed';
|
||||
return `${label}${typeof payload.round === 'number' ? ` at round ${payload.round}` : ''}${Array.isArray(payload.players) ? ` with ${payload.players.length} players` : ''}${typeof payload.map === 'string' ? ` on ${payload.map}` : ''}.`;
|
||||
}
|
||||
if (event.kind === 'manual-sign-off') return `${payload.requirement ?? 'Checklist'}: ${payload.note ?? 'Signed off'}`;
|
||||
if (event.kind === 'health' || event.kind === 'status-sample') return `${payload.healthy ? 'Healthy observation' : 'Unhealthy observation'}${payload.reason ? `: ${payload.reason}` : '.'}`;
|
||||
return event.kind.replaceAll('-', ' ').replaceAll('_', ' ');
|
||||
}
|
||||
Reference in New Issue
Block a user