@dangahagan/weather-mcp 1.35.10 → 1.35.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://badge.fury.io/js/@dangahagan%2Fweather-mcp.svg)](https://www.npmjs.com/package/@dangahagan/weather-mcp)
4
4
  [![MCP Registry](https://img.shields.io/badge/MCP-Registry-blue)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.dgahagan/weather-mcp)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
- [![Tests](https://img.shields.io/badge/tests-4%2C890%20passing-brightgreen)](./docs/testing/TEST_SUITE_README.md)
6
+ [![Tests](https://img.shields.io/badge/tests-4%2C968%20passing-brightgreen)](./docs/testing/TEST_SUITE_README.md)
7
7
  [![Node](https://img.shields.io/badge/node-%3E%3D18-339933?logo=node.js&logoColor=white)](https://nodejs.org)
8
8
 
9
9
  **Give your AI assistant real weather data — 17 tools, zero API keys, zero signup, zero cost.**
@@ -58,7 +58,7 @@ Choose this one if you want:
58
58
 
59
59
  - **Genuinely free** — every data source is a free public API. No trial that expires, no credit card, no rate-limited "free tier" bait.
60
60
  - **No API keys** — install to first forecast in under a minute. Nothing to configure, nothing to leak into a repo. ([Four optional keys](#optional-api-keys) add extras if you want them; the default configuration needs none.)
61
- - **Fully open source** — MIT licensed, readable TypeScript, 4,890 tests. Audit it, fork it, fix it.
61
+ - **Fully open source** — MIT licensed, readable TypeScript, 4,968 tests. Audit it, fork it, fix it.
62
62
  - **Privacy-respecting** — your queries go directly from your machine to public weather APIs. No middleman server, and no telemetry unless you opt in.
63
63
  - **Breadth** — 17 tools covering weather, safety hazards (lightning, floods, wildfires), marine conditions, air quality, and historical data back to 1940. Most weather MCPs stop at forecasts.
64
64
 
@@ -394,7 +394,7 @@ Being honest about what free public data can and can't do:
394
394
  ```bash
395
395
  npm run build # Compile TypeScript
396
396
  npm run dev # Run in development mode
397
- npm test # Run all 4,890 tests
397
+ npm test # Run all 4,968 tests
398
398
  npm run test:coverage # Coverage report
399
399
  npm run audit # Dependency vulnerability scan
400
400
  ```
@@ -1 +1 @@
1
- {"version":3,"file":"lightningHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/lightningHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EAM1B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAuD,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAe1G;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,OAAO,EACb,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAyB7D;AAuKD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA6G9G;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,yBAAyB,EACnC,MAAM,GAAE,WAAwB,GAC/B,MAAM,CAiLR"}
1
+ {"version":3,"file":"lightningHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/lightningHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EAM1B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAuD,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAe1G;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,OAAO,EACb,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAyB7D;AAuKD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAkH9G;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,yBAAyB,EACnC,MAAM,GAAE,WAAwB,GAC/B,MAAM,CA2LR"}
@@ -205,7 +205,10 @@ export async function getLightningActivity(params) {
205
205
  // monitoring began after the start of the requested window (fresh server, or
206
206
  // first query for this area), a "no strikes" result is inconclusive — say so
207
207
  // instead of implying verified safety.
208
- const coverageStart = blitzortungService.getCoverageStart(latitude, longitude, radius);
208
+ // Which bound decided the start: a reconnect inside the window shortens coverage for a reason
209
+ // that is neither a cold start nor an outage, and the render names it.
210
+ const coverageBound = {};
211
+ const coverageStart = blitzortungService.getCoverageStart(latitude, longitude, radius, coverageBound);
209
212
  const coverageMinutes = coverageStart
210
213
  ? Math.max(0, Math.min(timeWindow, (now.getTime() - coverageStart.getTime()) / (1000 * 60)))
211
214
  : 0;
@@ -222,7 +225,9 @@ export async function getLightningActivity(params) {
222
225
  // complete-looking window - and every caveat below is gated on `!isComplete`, so the outage
223
226
  // text would be skipped entirely. `coverageMinutes` stays honest about earlier monitoring.
224
227
  isComplete: coverageMinutes >= timeWindow && !feedUnavailable,
225
- feedUnavailable
228
+ feedUnavailable,
229
+ // Added only when true, so every existing state keeps its exact object shape.
230
+ ...(coverageBound.boundedBy === 'connection' ? { reconnectBounded: true } : {})
226
231
  };
227
232
  if (!coverage.isComplete && safety.level === 'safe') {
228
233
  // Only the *message* is gated on whether there is a nearest-strike distance at all: with one
@@ -299,6 +304,9 @@ export function formatLightningActivityResponse(response, detail = 'standard') {
299
304
  // than an outage. The internal safety level stays `safe` - this is a render-time substitution,
300
305
  // not a fifth level - and only `safe` is overridden, so a buffered EXTREME keeps its own heading.
301
306
  const feedDown = response.coverage.feedUnavailable === true;
307
+ // Strict `=== true` for the same reason: a fixture without the field reads as a cold start.
308
+ const reconnectedAt = response.coverage.monitoringSince;
309
+ const reconnected = response.coverage.reconnectBounded === true && reconnectedAt !== null;
302
310
  const statusSuffix = limitedData && response.safety.level === 'safe' ? ' (LIMITED DATA)' : '';
303
311
  if (feedDown && response.safety.level === 'safe') {
304
312
  lines.push('## ⚪ Safety Status: UNKNOWN (LIVE FEED UNAVAILABLE)');
@@ -347,11 +355,18 @@ export function formatLightningActivityResponse(response, detail = 'standard') {
347
355
  `Re-check in a few minutes or consult official weather services before making safety decisions.`);
348
356
  lines.push('');
349
357
  // Explain WHY coverage is limited so a fresh/near-zero reading is not mistaken for
350
- // verified calm — this is expected on a first query, not an error.
351
- lines.push('*Why: lightning is monitored via a live feed that only begins buffering strikes once ' +
352
- 'an area is first queried, so a location’s first lookup starts near zero coverage and ' +
353
- 'builds over the following minutes. Saved locations are pre-warmed at startup. Historical ' +
354
- 'strikes cannot be backfilled.*');
358
+ // verified calm — this is expected on a first query, not an error. A window shortened by a
359
+ // feed reconnect is neither a cold start nor an outage: telling someone "first lookup" about
360
+ // an area watched for hours would be a false explanation, so that case names the reconnect.
361
+ lines.push(reconnected
362
+ ? '*Why: the connection to the live Blitzortung.org lightning feed dropped and was ' +
363
+ `re-established at ${reconnectedAt.toISOString()}. Strikes during the gap ` +
364
+ 'were not received and cannot be backfilled, so coverage of this area restarts at the reconnect ' +
365
+ 'and builds over the following minutes.*'
366
+ : '*Why: lightning is monitored via a live feed that only begins buffering strikes once ' +
367
+ 'an area is first queried, so a location’s first lookup starts near zero coverage and ' +
368
+ 'builds over the following minutes. Saved locations are pre-warmed at startup. Historical ' +
369
+ 'strikes cannot be backfilled.*');
355
370
  }
356
371
  lines.push('');
357
372
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lightningHandler.js","sourceRoot":"","sources":["../../src/handlers/lightningHandler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lightningHandler.js","sourceRoot":"","sources":["../../src/handlers/lightningHandler.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,9 @@
2
2
  * Handler for get_wildfire_info tool.
3
3
  *
4
4
  * Routed by country (see docs/plans/global-wildfire-plan.md D1/D2):
5
- * US → NIFC/WFIGS named incidents (the original path, byte-identical
6
- * output), elsewhere → NASA FIRMS satellite fire detections (VIIRS, near
5
+ * US → NIFC/WFIGS named incidents, each measured to its mapped perimeter
6
+ * (the reported point of origin only when no usable perimeter is
7
+ * published), elsewhere → NASA FIRMS satellite fire detections (VIIRS, near
7
8
  * real-time, global). An explicit `source` forces the branch; there is
8
9
  * deliberately no cross-fallback — managed incidents (names, acreage,
9
10
  * containment) and satellite heat detections are different claims, and
@@ -1 +1 @@
1
- {"version":3,"file":"wildfireHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/wildfireHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAyB,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AA4B5D,KAAK,aAAa,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAqF3F,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,CAAC,EAAE,YAAY,EAC3B,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,OAAO,CAAC,aAAa,CAAC,CAyGxB"}
1
+ {"version":3,"file":"wildfireHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/wildfireHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAyB,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AA6B5D,KAAK,aAAa,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AA+J3F,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,CAAC,EAAE,YAAY,EAC3B,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,OAAO,CAAC,aAAa,CAAC,CAyGxB"}
@@ -2,8 +2,9 @@
2
2
  * Handler for get_wildfire_info tool.
3
3
  *
4
4
  * Routed by country (see docs/plans/global-wildfire-plan.md D1/D2):
5
- * US → NIFC/WFIGS named incidents (the original path, byte-identical
6
- * output), elsewhere → NASA FIRMS satellite fire detections (VIIRS, near
5
+ * US → NIFC/WFIGS named incidents, each measured to its mapped perimeter
6
+ * (the reported point of origin only when no usable perimeter is
7
+ * published), elsewhere → NASA FIRMS satellite fire detections (VIIRS, near
7
8
  * real-time, global). An explicit `source` forces the branch; there is
8
9
  * deliberately no cross-fallback — managed incidents (names, acreage,
9
10
  * containment) and satellite heat detections are different claims, and
@@ -21,6 +22,7 @@ import { resolveCountryCode, resolveLocationAsync, prependLocationLine } from '.
21
22
  import { validateDetail } from '../utils/validation.js';
22
23
  import { guessTimezoneFromCoords, formatObservationAge } from '../utils/timezone.js';
23
24
  import { calculateDistance, kmToMiles } from '../utils/distance.js';
25
+ import { distanceToPerimeterKm } from '../utils/firePerimeter.js';
24
26
  import { displayValue } from '../utils/displayBanding.js';
25
27
  import { isInUS } from '../utils/geography.js';
26
28
  import { logger } from '../utils/logger.js';
@@ -101,6 +103,81 @@ function formatDistanceFigure(km) {
101
103
  const shownKm = displayValue(km, 1);
102
104
  return `${shownKm.toFixed(1)} km (${kmToMiles(shownKm).toFixed(2)} mi)`;
103
105
  }
106
+ /**
107
+ * Parse NIFC's reported point of origin, or `null` when either coordinate is
108
+ * unusable.
109
+ *
110
+ * Usable means finite, in coordinate range, and **non-zero**. No incident in
111
+ * NIFC's covered set (US, PR, VI, GU) can sit on the equator or the prime
112
+ * meridian, so a `0` is a second "not recorded" encoding beside `null`
113
+ * (GOTCHAS G56), not a coordinate. Treating it as one would measure the fire
114
+ * thousands of km away and drop it at the radius filter; treating it as absent
115
+ * keeps the fire listed as unlocated, the cautious direction.
116
+ */
117
+ function parseOrigin(rawLat, rawLon) {
118
+ if (typeof rawLat !== 'number' || typeof rawLon !== 'number')
119
+ return null;
120
+ if (!Number.isFinite(rawLat) || !Number.isFinite(rawLon))
121
+ return null;
122
+ if (rawLat === 0 || rawLon === 0)
123
+ return null;
124
+ if (rawLat < -90 || rawLat > 90 || rawLon < -180 || rawLon > 180)
125
+ return null;
126
+ return { latitude: rawLat, longitude: rawLon };
127
+ }
128
+ /**
129
+ * The first acreage field that is a finite number greater than zero, or `null`
130
+ * meaning "NIFC published no size". Zero is absent here, unlike containment: a
131
+ * mapped perimeter of zero area is not a reading, it is a second "not
132
+ * recorded" encoding (GOTCHAS G56). The old `|| 0` printed `0 acres`.
133
+ */
134
+ function parseAcres(candidates) {
135
+ for (const raw of candidates) {
136
+ if (typeof raw === 'number' && Number.isFinite(raw) && raw > 0)
137
+ return raw;
138
+ }
139
+ return null;
140
+ }
141
+ /**
142
+ * NIFC's discovery timestamp (epoch ms) as a `Date`, or `null` meaning "NIFC
143
+ * published no discovery date". Epoch `0` is absent, not 1 January 1970: no
144
+ * current incident was discovered then. A finite value outside the `Date`
145
+ * range (e.g. `Number.MAX_VALUE`) is absent too. The old fallback was
146
+ * `new Date()`, which printed today's date and `Days Active: 0`.
147
+ */
148
+ function parseDiscoveryDate(raw) {
149
+ if (typeof raw !== 'number' || !Number.isFinite(raw) || raw <= 0)
150
+ return null;
151
+ const date = new Date(raw);
152
+ return Number.isNaN(date.getTime()) ? null : date;
153
+ }
154
+ /** The line beneath `**Distance:**` naming what the distance was measured to. */
155
+ function formatDistanceBasisLine(fire) {
156
+ switch (fire.distanceBasis) {
157
+ case 'perimeter':
158
+ return fire.distance === 0
159
+ ? `**Measured to:** the mapped fire perimeter — this location is inside it\n`
160
+ : `**Measured to:** nearest edge of the mapped fire perimeter\n`;
161
+ case 'origin':
162
+ return `**Measured to:** reported point of origin (NIFC published no usable perimeter)\n`;
163
+ case 'unlocated':
164
+ return `**Measured to:** not available — NIFC published neither a perimeter nor a point of origin\n`;
165
+ }
166
+ }
167
+ /**
168
+ * The Safety Assessment line for wildfires with no published location. They
169
+ * select no tier, because a tier is a claim about a distance, so the section
170
+ * must say they exist and that it is not an all-clear.
171
+ */
172
+ function formatUnlocatedWildfireLine(names) {
173
+ const n = names.length;
174
+ const shown = names.slice(0, 5).join(', ');
175
+ const more = n > 5 ? ` and ${n - 5} more` : '';
176
+ const one = n === 1;
177
+ return `⚠️ ${n} wildfire${one ? '' : 's'} in this search area ${one ? 'has' : 'have'} no published location (${shown}${more}). ` +
178
+ `${one ? 'Its' : 'Their'} distance is unknown and is not reflected in any tier above. ` +
179
+ `Do not read this section as an all-clear.\n`;
180
+ }
104
181
  export async function handleGetWildfireInfo(args, nifcService, locationStore, geocodingService, firmsService, nominatimService) {
105
182
  // Resolve location from coordinates, a saved location name, or a geocoded city name
106
183
  const resolved = await resolveLocationAsync(args, locationStore, geocodingService);
@@ -189,11 +266,12 @@ export async function handleGetWildfireInfo(args, nifcService, locationStore, ge
189
266
  return result;
190
267
  }
191
268
  /**
192
- * The original US path: NIFC/WFIGS named incidents with acreage,
193
- * containment, and the containment-aware safety assessment. Byte-identical
194
- * to the pre-global behavior (locked by tests/unit/wildfire-handler.test.ts
195
- * passing unedited). `failed` is true only when the catch replaced the fire
196
- * list with the error block.
269
+ * The US path: NIFC/WFIGS named incidents with acreage, containment, and the
270
+ * containment-aware safety assessment. Each fire is measured to its mapped
271
+ * perimeter (zero inside it), else to its reported point of origin, else it is
272
+ * listed as unlocated with no distance; the line beneath `**Distance:**` names
273
+ * which. `failed` is true only when the catch replaced the fire list with the
274
+ * error block.
197
275
  */
198
276
  async function formatNIFCWildfire(nifcService, latitude, longitude, radius, detail,
199
277
  /**
@@ -221,7 +299,82 @@ outsideCoverage = false) {
221
299
  // Query NIFC for fire perimeters
222
300
  const response = await nifcService.queryFirePerimeters(west, south, east, north);
223
301
  const features = response.features || [];
224
- if (features.length === 0 && outsideCoverage) {
302
+ // Measure and filter first, then branch on the filtered list (D3): a
303
+ // response whose every feature lies beyond the radius is the no-fires
304
+ // case (or the coverage disclosure), never a "Found 0 active fire" count.
305
+ const firesWithDistance = [];
306
+ for (const feature of features) {
307
+ const attrs = feature.attributes;
308
+ // Basis order: mapped perimeter → reported point of origin → unlocated.
309
+ // A fire is an area; the origin is a coordinate entered once and is
310
+ // sometimes far from the fire, so it is only the fallback. `null` is
311
+ // a refusal to measure, never a number (GOTCHAS G68).
312
+ const origin = parseOrigin(attrs.attr_InitialLatitude, attrs.attr_InitialLongitude);
313
+ const perimeterKm = distanceToPerimeterKm(latitude, longitude, feature.geometry?.rings);
314
+ let fireDistance;
315
+ let distanceBasis;
316
+ if (perimeterKm !== null) {
317
+ fireDistance = perimeterKm;
318
+ distanceBasis = 'perimeter';
319
+ }
320
+ else if (origin !== null) {
321
+ fireDistance = calculateDistance(latitude, longitude, origin.latitude, origin.longitude);
322
+ distanceBasis = 'origin';
323
+ }
324
+ else {
325
+ fireDistance = null;
326
+ distanceBasis = 'unlocated';
327
+ }
328
+ // Keep a located fire within the radius, and every unlocated fire:
329
+ // an unknown distance is not evidence that the fire is far away.
330
+ if (fireDistance === null || fireDistance <= radius) {
331
+ if (fireDistance === null) {
332
+ logger.warn('NIFC published no usable location for an incident', {
333
+ incident: attrs.poly_IncidentName
334
+ });
335
+ }
336
+ // Parsed before the literal so the warn can be guarded on the result.
337
+ // Warn only when the value is present but unusable — a plain
338
+ // null/undefined is the normal wire shape for a quarter of live rows,
339
+ // and warning on it would emit ~50 lines per request on a healthy
340
+ // feed. This is a data-quality event, not a security one, so no
341
+ // securityEvent flag (unlike the FIRMS row cap below).
342
+ const containment = parseContainment(attrs.attr_PercentContained);
343
+ if (attrs.attr_PercentContained != null && containment === null) {
344
+ logger.warn('NIFC published an unusable containment value', {
345
+ incident: attrs.poly_IncidentName,
346
+ value: attrs.attr_PercentContained
347
+ });
348
+ }
349
+ const fireInfo = {
350
+ name: attrs.poly_IncidentName || 'Unknown Fire',
351
+ distance: fireDistance,
352
+ distanceBasis,
353
+ acres: parseAcres([attrs.poly_GISAcres, attrs.attr_FinalAcres, attrs.attr_CalculatedAcres]),
354
+ containment,
355
+ discoveryDate: parseDiscoveryDate(attrs.attr_FireDiscoveryDateTime),
356
+ latitude: origin?.latitude,
357
+ longitude: origin?.longitude,
358
+ state: attrs.attr_POOState,
359
+ county: attrs.attr_POOCounty,
360
+ city: attrs.attr_POOCity,
361
+ type: attrs.attr_IncidentTypeCategory === 'WF' ? 'Wildfire' :
362
+ attrs.attr_IncidentTypeCategory === 'RX' ? 'Prescribed Fire' : 'Unknown',
363
+ status: attrs.poly_FeatureStatus || 'Active'
364
+ };
365
+ firesWithDistance.push({ fire: fireInfo, distance: fireDistance });
366
+ }
367
+ }
368
+ // Sort by distance (nearest first), unlocated fires last. The sort is
369
+ // stable, so unlocated fires keep the upstream order among themselves.
370
+ firesWithDistance.sort((a, b) => {
371
+ if (a.distance === null)
372
+ return b.distance === null ? 0 : 1;
373
+ if (b.distance === null)
374
+ return -1;
375
+ return a.distance - b.distance;
376
+ });
377
+ if (firesWithDistance.length === 0 && outsideCoverage) {
225
378
  // Forced `source: "nifc"` outside NIFC coverage. An empty result here
226
379
  // means "this authority does not track fires at this location", which
227
380
  // is emphatically not an all-clear — so no ✅ and no "currently clear"
@@ -234,7 +387,7 @@ outsideCoverage = false) {
234
387
  output += `Use \`source: "firms"\` (or omit \`source\`) for NASA FIRMS satellite fire `;
235
388
  output += `detections, which are global.\n`;
236
389
  }
237
- else if (features.length === 0) {
390
+ else if (firesWithDistance.length === 0) {
238
391
  output += `✅ **No active wildfires found within ${radius} km**\n\n`;
239
392
  if (response.exceededTransferLimit) {
240
393
  output += `*Results may be incomplete — the fire data service truncated the response.*\n\n`;
@@ -243,57 +396,6 @@ outsideCoverage = false) {
243
396
  output += `**Note:** This data includes active wildfires and prescribed burns tracked by the National Interagency Fire Center. Small fires or very recent ignitions may not yet be included.\n`;
244
397
  }
245
398
  else {
246
- // Process and filter fires by actual distance
247
- const firesWithDistance = [];
248
- for (const feature of features) {
249
- const attrs = feature.attributes;
250
- // Calculate distance from center point to fire origin
251
- let fireDistance = radius; // default if no coordinates
252
- if (attrs.attr_InitialLatitude && attrs.attr_InitialLongitude) {
253
- fireDistance = calculateDistance(latitude, longitude, attrs.attr_InitialLatitude, attrs.attr_InitialLongitude);
254
- }
255
- else if (feature.geometry?.rings?.[0]?.[0]) {
256
- // Use first point of fire perimeter if no origin coordinates
257
- const [fireLon, fireLat] = feature.geometry.rings[0][0];
258
- fireDistance = calculateDistance(latitude, longitude, fireLat, fireLon);
259
- }
260
- // Only include fires within radius
261
- if (fireDistance <= radius) {
262
- // Parsed before the literal so the warn can be guarded on the result.
263
- // Warn only when the value is present but unusable — a plain
264
- // null/undefined is the normal wire shape for a quarter of live rows,
265
- // and warning on it would emit ~50 lines per request on a healthy
266
- // feed. This is a data-quality event, not a security one, so no
267
- // securityEvent flag (unlike the FIRMS row cap below).
268
- const containment = parseContainment(attrs.attr_PercentContained);
269
- if (attrs.attr_PercentContained != null && containment === null) {
270
- logger.warn('NIFC published an unusable containment value', {
271
- incident: attrs.poly_IncidentName,
272
- value: attrs.attr_PercentContained
273
- });
274
- }
275
- const fireInfo = {
276
- name: attrs.poly_IncidentName || 'Unknown Fire',
277
- distance: fireDistance,
278
- acres: attrs.poly_GISAcres || attrs.attr_FinalAcres || attrs.attr_CalculatedAcres || 0,
279
- containment,
280
- discoveryDate: attrs.attr_FireDiscoveryDateTime
281
- ? new Date(attrs.attr_FireDiscoveryDateTime)
282
- : new Date(),
283
- latitude: attrs.attr_InitialLatitude,
284
- longitude: attrs.attr_InitialLongitude,
285
- state: attrs.attr_POOState,
286
- county: attrs.attr_POOCounty,
287
- city: attrs.attr_POOCity,
288
- type: attrs.attr_IncidentTypeCategory === 'WF' ? 'Wildfire' :
289
- attrs.attr_IncidentTypeCategory === 'RX' ? 'Prescribed Fire' : 'Unknown',
290
- status: attrs.poly_FeatureStatus || 'Active'
291
- };
292
- firesWithDistance.push({ fire: fireInfo, distance: fireDistance });
293
- }
294
- }
295
- // Sort by distance (nearest first)
296
- firesWithDistance.sort((a, b) => a.distance - b.distance);
297
399
  const fireCount = firesWithDistance.length;
298
400
  const wildfireCount = firesWithDistance.filter(f => f.fire.type === 'Wildfire').length;
299
401
  const prescribedCount = firesWithDistance.filter(f => f.fire.type === 'Prescribed Fire').length;
@@ -313,8 +415,8 @@ outsideCoverage = false) {
313
415
  // remainder note stays accurate at every level, including full.
314
416
  const maxFiresToShow = detail === 'full' ? 25 : 5;
315
417
  const firesToShow = firesWithDistance.slice(0, maxFiresToShow);
316
- for (const { fire, distance } of firesToShow) {
317
- output += formatFireDetails(fire, distance, timezone);
418
+ for (const { fire } of firesToShow) {
419
+ output += formatFireDetails(fire, timezone);
318
420
  }
319
421
  if (firesWithDistance.length > maxFiresToShow) {
320
422
  const remaining = firesWithDistance.length - maxFiresToShow;
@@ -343,7 +445,12 @@ outsideCoverage = false) {
343
445
  // old `|| 0` made it: an unknown containment is not evidence of
344
446
  // containment. displayValue does not accept null, so the case is
345
447
  // spelled out rather than coerced.
346
- const nearestWildfire = wildfires.find(f => f.fire.containment === null || displayValue(f.fire.containment, 0) < 100);
448
+ const isDisplayedUncontained = (f) => f.fire.containment === null || displayValue(f.fire.containment, 0) < 100;
449
+ // Only a located fire can select a tier: a tier is a claim about a
450
+ // distance, and an unlocated fire has none (GOTCHAS G68).
451
+ const nearestWildfire = wildfires.find((f) => f.distance !== null && isDisplayedUncontained(f));
452
+ const unlocatedWildfires = wildfires.filter(f => f.distance === null);
453
+ const unlocatedUncontained = unlocatedWildfires.some(isDisplayedUncontained);
347
454
  if (wildfires.length > 0) {
348
455
  output += `\n## Safety Assessment\n\n`;
349
456
  if (nearestWildfire) {
@@ -360,8 +467,11 @@ outsideCoverage = false) {
360
467
  // them, do not assume symmetry. And because the sentence printed
361
468
  // beneath says "within 5 km", which includes 5.0.
362
469
  const dist = displayValue(nearestWildfire.distance, 1);
470
+ // Located fires sort first, so whenever a located nearestWildfire
471
+ // exists, wildfires[0] is located too; the null check narrows the
472
+ // type and is never the deciding term.
363
473
  const nearestOverall = wildfires[0];
364
- if (nearestOverall !== nearestWildfire) {
474
+ if (nearestOverall !== nearestWildfire && nearestOverall.distance !== null) {
365
475
  output += `ℹ️ Nearest fire (${nearestOverall.fire.name}, ${nearestOverall.distance.toFixed(1)} km) is 100% contained and excluded from the danger assessment.\n\n`;
366
476
  }
367
477
  if (dist <= 5) {
@@ -387,7 +497,7 @@ outsideCoverage = false) {
387
497
  output += `- Air quality may be affected by smoke\n`;
388
498
  }
389
499
  }
390
- else {
500
+ else if (!unlocatedUncontained) {
391
501
  // Wildfires are present but every one is 100% contained. Still
392
502
  // surface the section — omitting it would hide that fires exist
393
503
  // nearby — pinned at the lowest (AWARENESS) tier.
@@ -396,6 +506,14 @@ outsideCoverage = false) {
396
506
  output += `- Stay informed about fire progression\n`;
397
507
  output += `- Air quality may be affected by smoke\n`;
398
508
  }
509
+ // Otherwise an unlocated wildfire is not displayed-contained: no
510
+ // tier and no all-contained line. The line below names it.
511
+ if (unlocatedWildfires.length > 0) {
512
+ const blockAbove = nearestWildfire !== undefined || !unlocatedUncontained;
513
+ if (blockAbove)
514
+ output += `\n`;
515
+ output += formatUnlocatedWildfireLine(unlocatedWildfires.map(f => f.fire.name));
516
+ }
399
517
  output += `\n`;
400
518
  }
401
519
  }
@@ -658,13 +776,16 @@ function formatClusterDetails(cluster, ordinal) {
658
776
  /**
659
777
  * Format detailed information for a single wildfire
660
778
  */
661
- function formatFireDetails(fire, distance, timezone) {
779
+ function formatFireDetails(fire, timezone) {
662
780
  let output = `## ${fire.name}\n\n`;
663
781
  // Fire type emoji
664
782
  const typeEmoji = fire.type === 'Wildfire' ? '🔥' :
665
783
  fire.type === 'Prescribed Fire' ? '🟦' : '⚪';
666
784
  output += `**Type:** ${typeEmoji} ${fire.type}\n`;
667
- output += `**Distance:** ${formatDistanceFigure(distance)}\n`;
785
+ output += fire.distance === null
786
+ ? `**Distance:** not reported\n`
787
+ : `**Distance:** ${formatDistanceFigure(fire.distance)}\n`;
788
+ output += formatDistanceBasisLine(fire);
668
789
  if (fire.state) {
669
790
  let location = fire.state;
670
791
  if (fire.county)
@@ -673,22 +794,34 @@ function formatFireDetails(fire, distance, timezone) {
673
794
  location += ` near ${fire.city}`;
674
795
  output += `**Location:** ${location}\n`;
675
796
  }
676
- if (fire.latitude && fire.longitude) {
677
- output += `**Coordinates:** ${fire.latitude.toFixed(4)}, ${fire.longitude.toFixed(4)}\n`;
797
+ // Set only when parseOrigin found both coordinates usable. Labelled as the
798
+ // reported origin because, once distance is measured to the perimeter, an
799
+ // unlabelled coordinate far from the printed distance reads as a contradiction.
800
+ if (fire.latitude !== undefined && fire.longitude !== undefined) {
801
+ output += `**Point of Origin (reported):** ${fire.latitude.toFixed(4)}, ${fire.longitude.toFixed(4)}\n`;
678
802
  }
679
803
  output += `\n`;
680
804
  // Fire statistics
681
805
  output += `### Status\n`;
682
- output += `**Size:** ${fire.acres.toFixed(0)} acres (${(fire.acres * 0.404686).toFixed(0)} hectares)\n`;
806
+ output += fire.acres === null
807
+ ? `**Size:** not reported\n`
808
+ : `**Size:** ${fire.acres.toFixed(0)} acres (${(fire.acres * 0.404686).toFixed(0)} hectares)\n`;
683
809
  // The bar is the completed tenths of the printed figure: a full bar means
684
810
  // the printed figure is `100%`, an empty bar means it is below `10%`, and
685
811
  // each cell is a completed ten percent. A fire NIFC published no usable
686
812
  // containment for reads `not reported`, with no bar at all.
687
813
  output += formatContainmentLine(fire.containment);
688
- const now = new Date();
689
- const daysActive = Math.floor((now.getTime() - fire.discoveryDate.getTime()) / (1000 * 60 * 60 * 24));
690
- output += `**Discovery Date:** ${fire.discoveryDate.toLocaleDateString('en-US', { timeZone: timezone })}\n`;
691
- output += `**Days Active:** ${daysActive}\n`;
814
+ // A day count derived from a date nobody published has no honest value, so
815
+ // Days Active is omitted, not zeroed, when the date is absent.
816
+ if (fire.discoveryDate === null) {
817
+ output += `**Discovery Date:** not reported\n`;
818
+ }
819
+ else {
820
+ const now = new Date();
821
+ const daysActive = Math.floor((now.getTime() - fire.discoveryDate.getTime()) / (1000 * 60 * 60 * 24));
822
+ output += `**Discovery Date:** ${fire.discoveryDate.toLocaleDateString('en-US', { timeZone: timezone })}\n`;
823
+ output += `**Days Active:** ${daysActive}\n`;
824
+ }
692
825
  output += `\n---\n\n`;
693
826
  return output;
694
827
  }