mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
fix(tools): say when get_wind answers from a stale forecast run
When the model upstream fails, the wind proxy keeps serving its last run, however old, with manifest.stale set. The wind layer shows that, but get_wind ignored it and gave the old run's wind as current. get_wind now returns stale and adds "(forecast may be stale)" to its summary, the way get_weather and the space tools flag stale data. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
713285b554
commit
fb88dd6e1b
3 files changed
+35
-2
No files matched your search
@@ -5827,7 +5827,7 @@ closed. Performance and live agency reliability require recorded validation.
|
|||||||
|
|
||||||
## Wind forecast models
|
## Wind forecast models
|
||||||
|
|
||||||
Wind supports selectable GFS/IFS models with persisted model choice. Each fetch chooses the available cycle and forecast step nearest the current time; rows show both issue and valid UTC timestamps. Grid identities include model, cycle, forecast step and any requested scalar field. The six model/field cache slots each retain the last two issued grids for manifest/grid rollover, coalesce concurrent requests, retain last-good data on failures and retry no faster than once per minute. Model changes clear the old field immediately, cancel old acquisition and ignore superseded results.
|
Wind supports selectable GFS/IFS models with persisted model choice. Each fetch chooses the available cycle and forecast step nearest the current time; rows show both issue and valid UTC timestamps. Grid identities include model, cycle, forecast step and any requested scalar field. The six model/field cache slots each retain the last two issued grids for manifest/grid rollover, coalesce concurrent requests, retain last-good data on failures and retry no faster than once per minute. Model changes clear the old field immediately, cancel old acquisition and ignore superseded results. Last-good data is marked stale; the wind row shows it, and `get_wind` returns `stale` and adds "(forecast may be stale)" to its summary.
|
||||||
|
|
||||||
### Local Weather review candidate
|
### Local Weather review candidate
|
||||||
|
|
||||||
|
|||||||
@@ -204,10 +204,14 @@ export const getWind = defineTool({
|
|||||||
const speed = windSpeed(vector.u, vector.v);
|
const speed = windSpeed(vector.u, vector.v);
|
||||||
const from = windFrom(vector.u, vector.v);
|
const from = windFrom(vector.u, vector.v);
|
||||||
const kph = speed * 3.6;
|
const kph = speed * 3.6;
|
||||||
|
// When the model upstream fails, the proxy keeps serving the last run it
|
||||||
|
// has, however old, marked stale.
|
||||||
|
const stale = snapshot.stale === true;
|
||||||
return {
|
return {
|
||||||
summary:
|
summary:
|
||||||
`Wind at ${point.label}: ${kph.toFixed(0)} km/h` +
|
`Wind at ${point.label}: ${kph.toFixed(0)} km/h` +
|
||||||
(from === 'Calm' ? ', calm.' : ` from the ${from}.`),
|
(from === 'Calm' ? ', calm' : ` from the ${from}`) +
|
||||||
|
(stale ? ' (forecast may be stale).' : '.'),
|
||||||
data: {
|
data: {
|
||||||
view: suggestView(services, {
|
view: suggestView(services, {
|
||||||
point,
|
point,
|
||||||
@@ -224,6 +228,7 @@ export const getWind = defineTool({
|
|||||||
level: snapshot.level ?? '10 m above ground',
|
level: snapshot.level ?? '10 m above ground',
|
||||||
model,
|
model,
|
||||||
cycle: snapshot.cycle ?? null,
|
cycle: snapshot.cycle ?? null,
|
||||||
|
stale,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -148,6 +148,34 @@ test('wind is sampled from the model grid at the location', async () => {
|
|||||||
const calm = await catalog.call('get_wind', { location: { lat: 0, lon: 0 } });
|
const calm = await catalog.call('get_wind', { location: { lat: 0, lon: 0 } });
|
||||||
assert.equal(calm.summary, 'Wind at 0.0000, 0.0000: 0 km/h, calm.');
|
assert.equal(calm.summary, 'Wind at 0.0000, 0.0000: 0 km/h, calm.');
|
||||||
assert.equal(calm.data.calm, true);
|
assert.equal(calm.data.calm, true);
|
||||||
|
assert.equal(calm.data.stale, false);
|
||||||
|
// The proxy's last run, served while the model upstream fails.
|
||||||
|
const cached = composeCatalog({
|
||||||
|
tools: coreTools,
|
||||||
|
services: {
|
||||||
|
wind: {
|
||||||
|
getSnapshot: async (options) => ({
|
||||||
|
...(await wind.getSnapshot(options)),
|
||||||
|
stale: true,
|
||||||
|
reason: 'Wind upstream unavailable',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const stale = await cached.call('get_wind', { location: { lat: 0, lon: 0 } });
|
||||||
|
assert.equal(
|
||||||
|
stale.summary,
|
||||||
|
'Wind at 0.0000, 0.0000: 0 km/h, calm (forecast may be stale).',
|
||||||
|
);
|
||||||
|
assert.equal(stale.data.stale, true);
|
||||||
|
u.fill(10);
|
||||||
|
const staleWest = await cached.call('get_wind', {
|
||||||
|
location: { lat: 30.27, lon: -97.74 },
|
||||||
|
});
|
||||||
|
assert.equal(
|
||||||
|
staleWest.summary,
|
||||||
|
'Wind at 30.2700, -97.7400: 36 km/h from the W (forecast may be stale).',
|
||||||
|
);
|
||||||
const down = composeCatalog({
|
const down = composeCatalog({
|
||||||
tools: coreTools,
|
tools: coreTools,
|
||||||
services: { wind: { getSnapshot: async () => ({ unavailable: true }) } },
|
services: { wind: { getSnapshot: async () => ({ unavailable: true }) } },
|
||||||
|
|||||||
Reference in new issue
Block a user