Merge pull request 'fix(teams): say "game server", not "shard", on the never-synced Teams panel' (#221) from fix/teams-panel-neutral-wording into main
All checks were successful
sync-project-tree / sync (push) Successful in 19s
Build container images / build (push) Successful in 1m55s
Build container images / deploy (push) Successful in 41s
SonarQube / analysis (push) Successful in 10m49s

Reviewed-on: #221
Reviewed-by: Colby Whitlock <whitlocktech@gmail.com>
This commit is contained in:
2026-10-22 19:59:38 +00:00
6 changed files with 9 additions and 9 deletions

View File

@@ -41,7 +41,7 @@ export function relativeTime(when, now = Date.now()) {
* Distinct from `teamAdmin.freshnessOf`, which is worded for an operator * Distinct from `teamAdmin.freshnessOf`, which is worded for an operator
* debugging a sync. A visitor needs one sentence about whether what they are * debugging a sync. A visitor needs one sentence about whether what they are
* looking at is current, and specifically must never be shown an unconfirmed * looking at is current, and specifically must never be shown an unconfirmed
* empty projection as though it were a confirmed empty shard. * empty projection as though it were a confirmed empty one.
*/ */
export function freshnessNote(sync = {}, now = Date.now()) { export function freshnessNote(sync = {}, now = Date.now()) {
// Nothing supplies Teams here, so there is nothing to be stale ABOUT. A // Nothing supplies Teams here, so there is nothing to be stale ABOUT. A
@@ -57,7 +57,7 @@ export function freshnessNote(sync = {}, now = Date.now()) {
* Group feed items into days, newest first, preserving order within a day (§4.3). * Group feed items into days, newest first, preserving order within a day (§4.3).
* *
* Keyed by local calendar date rather than by a UTC slice: "yesterday" is a * Keyed by local calendar date rather than by a UTC slice: "yesterday" is a
* property of where the reader is sitting, and a shard's evening raid landing at * property of where the reader is sitting, and a game server's evening raid landing at
* 00:30 UTC belongs on the day the players experienced it. * 00:30 UTC belongs on the day the players experienced it.
*/ */
export function groupByDay(items = [], locale = undefined) { export function groupByDay(items = [], locale = undefined) {

View File

@@ -3,7 +3,7 @@
// //
// Plain JS with tests, following lib/moduleAdmin.js. The reason it is worth // Plain JS with tests, following lib/moduleAdmin.js. The reason it is worth
// splitting here specifically: this screen's job is to tell an operator the // splitting here specifically: this screen's job is to tell an operator the
// difference between "the shard has no Teams" and "core has not been able to ask // difference between "the game server has no Teams" and "core has not been able to ask
// for two hours", and those two produce almost the same page. Getting that // for two hours", and those two produce almost the same page. Getting that
// wording right is logic, not markup. // wording right is logic, not markup.
@@ -31,7 +31,7 @@ export function freshnessOf(sync = {}) {
return { return {
tone: TONE.bad, tone: TONE.bad,
label: 'Never synced', label: 'Never synced',
detail: 'Core has never had an answer it could trust. What is shown below is not a confirmed empty shard.', detail: 'Core has never had an answer it could trust. What is shown below does not confirm that the game server has no Teams.',
} }
} }
if (sync.stale) { if (sync.stale) {

View File

@@ -14,7 +14,7 @@ import TeamVoice from './TeamVoice.jsx'
// Three panels, in the order an operator needs them: // Three panels, in the order an operator needs them:
// //
// 1. **Sync state**, verbatim, including the last error. The screen's first job // 1. **Sync state**, verbatim, including the last error. The screen's first job
// is to make "the shard has no Teams" and "core has not been able to ask for // is to make "the game server has no Teams" and "core has not been able to ask for
// two hours" impossible to confuse — they render almost identically // two hours" impossible to confuse — they render almost identically
// otherwise, and one is fine while the other is an outage. // otherwise, and one is fine while the other is an outage.
// 2. **The review queue** — Teams auto-hidden because their name matched the // 2. **The review queue** — Teams auto-hidden because their name matched the

View File

@@ -19,7 +19,7 @@ test('a deployment with no provider is not stale, it is uninvolved', () => {
assert.equal(freshnessNote({ configured: false }, NOW), null) assert.equal(freshnessNote({ configured: false }, NOW), null)
}) })
test('never synced is a warning, and never reads as a confirmed empty shard', () => { test('never synced is a warning, and never reads as a confirmed empty roster', () => {
const note = freshnessNote({ configured: true, lastSyncAt: null }, NOW) const note = freshnessNote({ configured: true, lastSyncAt: null }, NOW)
assert.equal(note.tone, 'warn') assert.equal(note.tone, 'warn')
assert.match(note.text, /Not yet confirmed/) assert.match(note.text, /Not yet confirmed/)

View File

@@ -21,13 +21,13 @@ test('no provider is idle, not a fault', () => {
assert.match(f.label, /No Team provider/) assert.match(f.label, /No Team provider/)
}) })
test('never synced is reported as never synced, not as an empty shard', () => { test('never synced is reported as never synced, not as a game server with no Teams', () => {
// The failure this prevents: an empty projection core has never confirmed, // The failure this prevents: an empty projection core has never confirmed,
// rendered as though the game genuinely has no Teams. // rendered as though the game genuinely has no Teams.
const f = freshnessOf({ configured: true, lastSyncAt: null }) const f = freshnessOf({ configured: true, lastSyncAt: null })
assert.equal(f.tone, TONE.bad) assert.equal(f.tone, TONE.bad)
assert.equal(f.label, 'Never synced') assert.equal(f.label, 'Never synced')
assert.match(f.detail, /not a confirmed empty shard/) assert.match(f.detail, /does not confirm that the game server has no Teams/)
}) })
test('stale says how old it is', () => { test('stale says how old it is', () => {

View File

@@ -135,7 +135,7 @@ async function syncStatus() {
configured: true, configured: true,
lastSyncAt, lastSyncAt,
// Never synced at all is stale: a page must not present an empty projection // Never synced at all is stale: a page must not present an empty projection
// as a confirmed empty shard. // as a confirmed empty one.
stale: ageS > intervalS * STALE_INTERVALS, stale: ageS > intervalS * STALE_INTERVALS,
consecutiveFailures: state ? state.consecutive_failures : 0, consecutiveFailures: state ? state.consecutive_failures : 0,
} }