Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 78 additions & 5 deletions answers/coops-tide-hilo.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@
"words": [
"tides",
"tide",
"high tide",
"low tide",
"next high tide",
"next low tide",
"tide times",
"tide chart",
"when is high tide"
"tide table",
"tide schedule"
],
"primary": true,
"kind": "list",
Expand Down Expand Up @@ -41,6 +38,82 @@
"step": "hour"
}
},
{
"name": "next_high",
"label": "Next high tide",
"words": [
"next high tide",
"high tide",
"when is high tide"
],
"primary": false,
"kind": "list",
"path": "predictions",
"row": [
{
"path": "t",
"label": "Time",
"type": "time"
},
{
"path": "type",
"label": "High/Low",
"type": "text"
},
{
"path": "v",
"label": "Height",
"type": "number",
"unit": "ft"
}
],
"filter": {
"path": "type",
"equals": "H"
},
"axis": {
"cell": "t",
"step": "hour"
}
},
{
"name": "next_low",
"label": "Next low tide",
"words": [
"next low tide",
"low tide",
"when is low tide"
],
"primary": false,
"kind": "list",
"path": "predictions",
"row": [
{
"path": "t",
"label": "Time",
"type": "time"
},
{
"path": "type",
"label": "High/Low",
"type": "text"
},
{
"path": "v",
"label": "Height",
"type": "number",
"unit": "ft"
}
],
"filter": {
"path": "type",
"equals": "L"
},
"axis": {
"cell": "t",
"step": "hour"
}
},
{
"name": "first_tide_time",
"label": "First tide today",
Expand Down
10 changes: 8 additions & 2 deletions answers/open-meteo-forecast.json
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@
"label": "Rain chance",
"type": "number",
"unit_path": "hourly_units.precipitation_probability"
},
{
"path": "hourly.snowfall",
"label": "Snowfall",
"type": "number",
"unit_path": "hourly_units.snowfall"
}
],
"limit": 24,
Expand Down Expand Up @@ -337,6 +343,6 @@
}
}
],
"sample_url": "https://api.open-meteo.com/v1/forecast?latitude=32.7765&longitude=-79.9311&current=temperature_2m,apparent_temperature,relative_humidity_2m,weather_code,wind_speed_10m&hourly=temperature_2m,precipitation_probability,weather_code&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_probability_max,snowfall_sum,sunrise,sunset&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto",
"checked": "2026-10-06"
"sample_url": "https://api.open-meteo.com/v1/forecast?latitude=32.7765&longitude=-79.9311&current=temperature_2m,apparent_temperature,relative_humidity_2m,weather_code,wind_speed_10m&hourly=temperature_2m,precipitation_probability,weather_code,snowfall&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_probability_max,snowfall_sum,sunrise,sunset&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto",
"checked": "2026-10-08"
}
6 changes: 3 additions & 3 deletions answers/swpc-kp-forecast.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"filter": {"path": "observed", "equals": "predicted"},
"row": [
{"path": "time_tag", "label": "Window starts", "type": "time", "utc": true},
{"path": "kp", "label": "Kp", "type": "number"}
{"path": "kp", "label": "Kp", "type": "number", "unit": "Kp"}
],
"axis": {"cell": "time_tag", "step": "hour"}
},
Expand All @@ -24,7 +24,7 @@
"filter": {"path": "observed", "equals": "estimated"},
"row": [
{"path": "time_tag", "label": "Window starts", "type": "time", "utc": true},
{"path": "kp", "label": "Kp", "type": "number"}
{"path": "kp", "label": "Kp", "type": "number", "unit": "Kp"}
],
"may_be_empty": true,
"axis": {"cell": "time_tag", "step": "hour"}
Expand All @@ -38,7 +38,7 @@
"filter": {"path": "observed", "equals": "observed"},
"row": [
{"path": "time_tag", "label": "Window starts", "type": "time", "utc": true},
{"path": "kp", "label": "Kp", "type": "number"}
{"path": "kp", "label": "Kp", "type": "number", "unit": "Kp"}
],
"newest_first": true,
"axis": {"cell": "time_tag", "step": "hour"}
Expand Down
2 changes: 1 addition & 1 deletion sources/curated/core.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
{"access": {"auth": "none", "contact_ua": false, "docs_url": "https://help.nytimes.com/hc/en-us/articles/115014893428-Terms-of-Service", "headers": {}, "kind": "rss", "params": [], "url_template": "https://rss.nytimes.com/services/xml/rss/nyt/World.xml"}, "categories": ["news/topic_news"], "coverage": {"entity": "The New York Times", "geo": "US"}, "description": "NYT World RSS feed.", "examples": ["world news"], "freshness": {"cadence": "minutes"}, "id": "nyt-world", "kinds": ["latest_items"], "name": "NYT World", "notes": "", "origin": {"at": "2026-09-28T04:10:32Z", "by": "bootstrap/core_seed"}, "provider": {"authority": "primary", "id": "nyt", "name": "The New York Times", "url": "https://www.nytimes.com"}, "terms": {"note": "public RSS for personal, non-commercial use", "status": "terms_allow", "terms_url": "https://help.nytimes.com/hc/en-us/articles/115014893428-Terms-of-Service"}, "tier": "curated", "validation": {"bytes": 128033, "checked_at": "2026-09-28T04:10:40Z", "http": 200, "note": "xml 57 items", "robots": "allow", "status": "ok"}, "votes": {"no": 0, "yes": 0}}
{"access": {"auth": "none", "contact_ua": false, "docs_url": "https://world.openfoodfacts.org/terms-of-use", "headers": {}, "kind": "http_json", "params": [{"example": "3017620422003", "fill": {"from": "text"}, "kind": "product", "name": "barcode", "required": true}], "url_template": "https://world.openfoodfacts.org/api/v2/product/{barcode}.json"}, "categories": ["health/nutrition"], "coverage": {"entity": "", "geo": "global"}, "description": "Ingredients, nutrition and scores for a barcode.", "examples": ["nutrition for this barcode"], "freshness": {"cadence": "static"}, "id": "off-product", "kinds": ["lookup"], "name": "Open Food Facts product", "notes": "", "origin": {"at": "2026-09-28T04:10:32Z", "by": "bootstrap/core_seed"}, "provider": {"authority": "community", "id": "openfoodfacts", "name": "Open Food Facts", "url": "https://world.openfoodfacts.org"}, "terms": {"note": "ODbL", "status": "open_license", "terms_url": "https://world.openfoodfacts.org/terms-of-use"}, "tier": "curated", "validation": {"bytes": 152819, "checked_at": "2026-09-28T04:10:40Z", "http": 200, "note": "json", "robots": "disallow", "status": "ok"}, "votes": {"no": 0, "yes": 0}}
{"access": {"auth": "none", "contact_ua": false, "docs_url": "https://open-meteo.com/en/terms", "headers": {}, "kind": "http_json", "params": [{"example": "32.7765", "fill": {"field": "lat", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lat", "required": true}, {"example": "-79.9311", "fill": {"field": "lon", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lon", "required": true}], "url_template": "https://air-quality-api.open-meteo.com/v1/air-quality?latitude={lat}&longitude={lon}&current=us_aqi,pm2_5,pm10,ozone&hourly=us_aqi&timezone=auto"}, "categories": ["weather/air_quality"], "coverage": {"entity": "", "geo": "global"}, "description": "US AQI, PM2.5, PM10 and ozone now and by hour for a latitude/longitude (model data).", "examples": ["air quality in Phoenix", "is the air safe today", "smoke levels"], "freshness": {"cadence": "hourly"}, "id": "open-meteo-air-quality", "kinds": ["current_value", "forecast"], "name": "Open-Meteo air quality", "notes": "", "origin": {"at": "2026-09-28T04:10:32Z", "by": "bootstrap/core_seed"}, "provider": {"authority": "primary", "id": "open-meteo", "name": "Open-Meteo", "url": "https://open-meteo.com"}, "terms": {"note": "CC BY 4.0; free for non-commercial use; attribution required", "status": "open_license", "terms_url": "https://open-meteo.com/en/terms"}, "tier": "curated", "validation": {"bytes": 3138, "checked_at": "2026-09-28T04:10:40Z", "http": 200, "note": "json", "robots": "disallow", "status": "ok"}, "votes": {"no": 0, "yes": 0}}
{"access": {"auth": "none", "contact_ua": false, "docs_url": "https://open-meteo.com/en/terms", "headers": {}, "kind": "http_json", "params": [{"example": "32.7765", "fill": {"field": "lat", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lat", "required": true}, {"example": "-79.9311", "fill": {"field": "lon", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lon", "required": true}], "url_template": "https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&current=temperature_2m,apparent_temperature,relative_humidity_2m,weather_code,wind_speed_10m&hourly=temperature_2m,precipitation_probability,weather_code&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_probability_max,snowfall_sum,sunrise,sunset&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto"}, "categories": ["weather/forecast", "weather/current"], "coverage": {"entity": "", "geo": "global"}, "description": "Current conditions plus hourly and daily forecast for any latitude/longitude, US units: temperature, highs and lows, rain chance, snow and conditions such as thunderstorms, hail, fog or freezing rain, from this morning and this afternoon through tonight and the week ahead.", "examples": ["weather in Austin", "what's the temperature", "rain chance this weekend", "will it storm tonight", "frost tonight"], "freshness": {"cadence": "hourly"}, "id": "open-meteo-forecast", "kinds": ["forecast", "current_value", "trend"], "name": "Open-Meteo forecast", "notes": "", "origin": {"at": "2026-09-28T04:10:32Z", "by": "bootstrap/core_seed"}, "provider": {"authority": "primary", "id": "open-meteo", "name": "Open-Meteo", "url": "https://open-meteo.com"}, "terms": {"note": "CC BY 4.0; free for non-commercial use; attribution required", "status": "open_license", "terms_url": "https://open-meteo.com/en/terms"}, "tier": "curated", "validation": {"bytes": 5989, "checked_at": "2026-09-29T03:40:12Z", "http": 200, "note": "json", "robots": "allow", "status": "ok"}, "votes": {"no": 0, "yes": 0}}
{"access": {"auth": "none", "contact_ua": false, "docs_url": "https://open-meteo.com/en/terms", "headers": {}, "kind": "http_json", "params": [{"example": "32.7765", "fill": {"field": "lat", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lat", "required": true}, {"example": "-79.9311", "fill": {"field": "lon", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lon", "required": true}], "url_template": "https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&current=temperature_2m,apparent_temperature,relative_humidity_2m,weather_code,wind_speed_10m&hourly=temperature_2m,precipitation_probability,weather_code,snowfall&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_probability_max,snowfall_sum,sunrise,sunset&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto"}, "categories": ["weather/forecast", "weather/current"], "coverage": {"entity": "", "geo": "global"}, "description": "Current conditions plus hourly and daily forecast for any latitude/longitude, US units: temperature, highs and lows, rain chance, snow and conditions such as thunderstorms, hail, fog or freezing rain, from this morning and this afternoon through tonight and the week ahead.", "examples": ["weather in Austin", "what's the temperature", "rain chance this weekend", "will it storm tonight", "frost tonight"], "freshness": {"cadence": "hourly"}, "id": "open-meteo-forecast", "kinds": ["forecast", "current_value", "trend"], "name": "Open-Meteo forecast", "notes": "", "origin": {"at": "2026-09-28T04:10:32Z", "by": "bootstrap/core_seed"}, "provider": {"authority": "primary", "id": "open-meteo", "name": "Open-Meteo", "url": "https://open-meteo.com"}, "terms": {"note": "CC BY 4.0; free for non-commercial use; attribution required", "status": "open_license", "terms_url": "https://open-meteo.com/en/terms"}, "tier": "curated", "validation": {"bytes": 5989, "checked_at": "2026-09-29T03:40:12Z", "http": 200, "note": "json", "robots": "allow", "status": "ok"}, "votes": {"no": 0, "yes": 0}}
{"access": {"auth": "none", "contact_ua": false, "docs_url": "https://open-meteo.com/en/terms", "headers": {}, "kind": "http_json", "params": [{"example": "32.7765", "fill": {"field": "lat", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lat", "required": true}, {"example": "-79.9311", "fill": {"field": "lon", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lon", "required": true}, {"example": "2026-09-01", "fill": {"format": "%Y-%m-%d", "from": "clock", "offset_days": -30}, "kind": "date", "name": "start", "required": true}, {"example": "2026-09-20", "fill": {"format": "%Y-%m-%d", "from": "clock", "offset_days": 0}, "kind": "date", "name": "end", "required": true}], "url_template": "https://archive-api.open-meteo.com/v1/archive?latitude={lat}&longitude={lon}&start_date={start}&end_date={end}&daily=temperature_2m_max,temperature_2m_min,precipitation_sum&temperature_unit=fahrenheit&precipitation_unit=inch&timezone=auto"}, "categories": ["weather/climate_records"], "coverage": {"entity": "", "geo": "global"}, "description": "Daily historical highs, lows and precipitation for any date range and location.", "examples": ["how hot was last month", "rainfall this month compared to normal"], "freshness": {"cadence": "daily"}, "id": "open-meteo-history", "kinds": ["trend", "lookup"], "name": "Open-Meteo historical weather", "notes": "", "origin": {"at": "2026-09-28T04:10:32Z", "by": "bootstrap/core_seed"}, "provider": {"authority": "primary", "id": "open-meteo", "name": "Open-Meteo", "url": "https://open-meteo.com"}, "terms": {"note": "CC BY 4.0; free for non-commercial use; attribution required", "status": "open_license", "terms_url": "https://open-meteo.com/en/terms"}, "tier": "curated", "validation": {"bytes": 971, "checked_at": "2026-09-28T04:10:40Z", "http": 200, "note": "json", "robots": "disallow", "status": "ok"}, "votes": {"no": 0, "yes": 0}}
{"access": {"auth": "none", "contact_ua": false, "docs_url": "https://open-meteo.com/en/terms", "headers": {}, "kind": "http_json", "params": [{"example": "32.7765", "fill": {"field": "lat", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lat", "required": true}, {"example": "-79.80", "fill": {"field": "lon", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lon", "required": true}], "url_template": "https://marine-api.open-meteo.com/v1/marine?latitude={lat}&longitude={lon}&current=wave_height,wave_direction,wave_period,swell_wave_height,swell_wave_direction,swell_wave_period,sea_surface_temperature&hourly=wave_height&length_unit=imperial&temperature_unit=fahrenheit&timezone=auto"}, "categories": ["water/surf_waves", "water/water_temperature"], "coverage": {"entity": "", "geo": "global", "water": "ocean_coastal"}, "description": "Wave height, direction and period, swell, and sea-surface temperature for a coastal latitude/longitude (ocean and coast only: no data on inland lakes).", "examples": ["surf report Folly Beach", "wave height tomorrow", "swell direction Huntington Beach"], "freshness": {"cadence": "hourly"}, "id": "open-meteo-marine", "kinds": ["current_value", "forecast"], "name": "Open-Meteo marine", "notes": "", "origin": {"at": "2026-09-28T04:10:32Z", "by": "bootstrap/core_seed"}, "provider": {"authority": "primary", "id": "open-meteo", "name": "Open-Meteo", "url": "https://open-meteo.com"}, "terms": {"note": "CC BY 4.0; free for non-commercial use; attribution required", "status": "open_license", "terms_url": "https://open-meteo.com/en/terms"}, "tier": "curated", "validation": {"bytes": 4727, "checked_at": "2026-09-29T03:58:27Z", "http": 200, "note": "json", "robots": "disallow", "status": "ok"}, "votes": {"no": 0, "yes": 0}}
{"access": {"auth": "none", "contact_ua": false, "docs_url": "https://open-meteo.com/en/docs", "headers": {}, "kind": "http_json", "params": [{"example": "32.7765", "fill": {"field": "lat", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lat", "required": true}, {"example": "-79.9311", "fill": {"field": "lon", "from": "resolver", "resolver": "place"}, "kind": "place", "name": "lon", "required": true}], "url_template": "https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&daily=sunrise,sunset&timezone=auto&forecast_days=7"}, "categories": ["sky/sun_moon"], "coverage": {"entity": "", "geo": "global"}, "description": "Sunrise and sunset times for a latitude/longitude in the place's own local time, today and the next six days.", "examples": ["what time is sunset", "sunrise tomorrow", "when is sunset in Denver", "sunrise times this week"], "freshness": {"cadence": "daily"}, "id": "open-meteo-sun", "kinds": ["next_event", "current_value"], "name": "Open-Meteo sunrise & sunset", "notes": "", "origin": {"at": "2026-09-29T04:00:00Z", "by": "data-fixes-0929"}, "provider": {"authority": "primary", "id": "open-meteo", "name": "Open-Meteo", "url": "https://open-meteo.com"}, "terms": {"note": "CC BY 4.0; free for non-commercial use; attribution required", "status": "open_license", "terms_url": "https://open-meteo.com/en/terms"}, "tier": "curated", "validation": {"bytes": 663, "checked_at": "2026-09-29T03:40:12Z", "http": 200, "note": "json", "robots": "disallow", "status": "ok"}, "votes": {"no": 0, "yes": 0}}
Expand Down
8 changes: 4 additions & 4 deletions sourcetool/answers.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,8 @@ def answer_problems(answers, params=()) -> list[str]:
errs.append(f"{w}: measure must be one of {'/'.join(MEASURES)}")
elif kind == "list":
rows = a.get("row")
if not isinstance(rows, list) or not 1 <= len(rows) <= 4:
errs.append(f"{w}: row must hold 1-4 fields")
if not isinstance(rows, list) or not 1 <= len(rows) <= 5:
errs.append(f"{w}: row must hold 1-5 fields")
else:
for j, f in enumerate(rows):
errs += _field_problems(f"{w} row[{j}]", f, ROW_KEYS, ROW_TYPES)
Expand All @@ -245,8 +245,8 @@ def answer_problems(answers, params=()) -> list[str]:
errs += _filter_problems(w, a["filter"])
else:
cols = a.get("columns")
if not isinstance(cols, list) or not 2 <= len(cols) <= 4:
errs.append(f"{w}: columns must hold 2-4 fields")
if not isinstance(cols, list) or not 2 <= len(cols) <= 5:
errs.append(f"{w}: columns must hold 2-5 fields")
else:
for j, f in enumerate(cols):
errs += _field_problems(f"{w} columns[{j}]", f, COLUMN_KEYS, ROW_TYPES)
Expand Down
1 change: 0 additions & 1 deletion tests/fixtures/keyword_lint_baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,6 @@
"water/surf_waves: no curated source filed here speaks to 'swell forecast'",
"water/surf_waves: no curated source filed here speaks to 'waist high'",
"water/surf_waves: no curated source filed here speaks to 'wave forecast'",
"water/tides: no curated source filed here speaks to 'tide table'",
"water/water_levels: no curated source filed here speaks to 'coastal flooding'",
"water/water_levels: no curated source filed here speaks to 'flood at high tide'",
"water/water_levels: no curated source filed here speaks to 'high tide flooding'",
Expand Down
Loading
Loading