fix(hud): AI summary in the UI language, canonical feed state, partial aggregation

The HUD sends its locale with the summary context; the proxy names that
language in the instructions and the input, English when missing or
unsupported. The model returns {summary, feedState}; the HUD shows the
summary only when feedState matches its own state for a view that is not
nominal, and appends its own translated state tag.

partial joins the shared feed-state table between fallback and nominal,
so one partial layer no longer reads off and partial plus nominal no
longer reads nominal.
This commit is contained in:
German Khokhlov committed 2026-10-30 12:37:43 +04:00
1 parent 423ca3ca5f
commit 563df3bad9
7 files changed
+386 -56

No files matched your search

+33 -1
View File
@@ -90,7 +90,15 @@ test('layerFeedState matches the chip classifier for every honesty class', () =>
test('chip labels and severity cover every feed-state the envelope can emit', () => {
assert.deepEqual(
[...LAYER_FEED_STATES],
['nominal', 'loading', 'degraded', 'stale', 'fallback', 'unavailable'],
[
'nominal',
'loading',
'degraded',
'stale',
'partial',
'fallback',
'unavailable',
],
);
assert.deepEqual([...SNAPSHOT_FEED_STATES], [...LAYER_FEED_STATES, 'off']);
for (const state of LAYER_FEED_STATES) {
@@ -107,6 +115,30 @@ test('chip labels and severity cover every feed-state the envelope can emit', ()
assert.equal(worstFeedState([]), null);
});
test('partial is a feed-state of its own: above nominal, below every fault', () => {
const layer = (id, stats) => ({ id, name: id, enabled: true, stats });
const partial = layer('flights', {
partial: true,
count: 4,
lastUpdate: NOW,
});
const nominal = layer('vessels', { count: 9, lastUpdate: NOW });
const stale = layer('cctv', { stale: true, count: 2, lastUpdate: NOW });
const overall = (layers) =>
feedProvenanceEnvelope(layers, { now: NOW }).overall;
assert.equal(overall([partial]), 'partial');
assert.equal(overall([partial, nominal]), 'partial');
assert.equal(overall([nominal, partial]), 'partial');
assert.equal(overall([partial, stale]), 'stale');
assert.equal(overall([stale, partial]), 'stale');
assert.equal(LAYER_FEED_STATE_LABELS.partial, 'PARTIAL');
assert.equal(
FEED_STATE_SEVERITY.fallback < FEED_STATE_SEVERITY.partial &&
FEED_STATE_SEVERITY.partial < FEED_STATE_SEVERITY.nominal,
true,
);
});
test('a disabled layer is off even when leftover stats would read stale', () => {
const snap = layerSnapshot(
{