Repair legacy direct source links (#214)
Replace 14 aggregator-only historical source sets with direct verified publisher links and gate source-link integrity before deployment.
Full diff
@@ -52,6 +52,7 @@ jobs:\n python tests/test_briefing.py\n python tests/test_images.py\n python tests/test_manufacturer_sources.py\n+ python tests/test_source_links.py\n \n update:\n if: github.event_name != 'pull_request'\n@@ -84,6 +85,7 @@ jobs:\n run: |\n python tests/test_companion.py\n python tests/test_flightwatch.py\n+ python tests/test_source_links.py\n \n - name: Test headline priority and subject scope\n run: python tests/test_headline_rotation.py\n@@ -25,20 +25,8 @@\n },\n "sources": [\n {\n- "name": "長榮航空 EVA Air — 長榮航空12月1日起開航桃園-印度德里直飛航線 拓展南亞市場、串聯北美航網 即日起開放訂位購票",\n- "url": "https://news.google.com/rss/articles/CBMiswFBVV95cUxPalprU0pYdjRfeE0zQXh3Yl9rUmREdXlKdnhZUm9lQTdpNHM3a2YxZm5ES2syNUpnUVBxZ1lwMG9INTI5WnpGUm12SVlsYTY5akJBYm00MUQwdTgweWVfQ1ltXzlyTzRwZUhHVkRwM3ZxT190NW4xeEVzWS1ONVFnZDAtNXoxR2tKN04yaDZDNFFWQmE3SFp1dW9zNXMtR1FuN2J0OUpJSFFsZjVDNDNweElxQQ?oc=5"\n- },\n- {\n- "name": "ETtoday財經雲 — 搶攻AI半導體供應鏈市場 長榮航空12月1日起開航印度德里",\n- "url": "https://news.google.com/rss/articles/CBMiUkFVX3lxTE95V0dHM05nNzVxNGNtczhDYWpHVUFELUxpWEhEdjZTS2xTNmhtSDdPdU1zeFEwdnFtdHVEOE5ZNHR2MUxHcG1vQlBBR3hsY2pNV2fSAVBBVV95cUxQRjcydWVHTFl6RlRzRTV6cWFRX0RERnhLWlp3cDB4NkM3ZmxzVDc0akZmeFc4bkxlTGRjMUxiLVJMRF9NV1ZVbERTMU5BVWVjXw?oc=5"\n- },\n- {\n- "name": "UDN — 台灣唯一直飛!鴻海、聯發科搶設點 長榮航空12月1日開航桃園-印度",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTFBEWWlQaXg1YTU4Z0lhbkpnaGFkMXN4UXZkT29HX1VfOTd6NHlOVEVLaXlfNnZKTlF6SElCc2NJU21FcGdQdkFMZlc4akdLb1ZE0gFWQVVfeXFMUGlHNXliRzljWGNNVEhMemJiTmNib3ZqYkZEVThNX3NOOFhDek5TTGVRSlhzMlNKM3BBS042cW1GdjNkdUp2SXdndHNHZmpwNnRWVmdiVGc?oc=5"\n- },\n- {\n- "name": "ETtoday新聞雲 — 長榮航空12/1開航桃園-印度德里 即日起開放購票",\n- "url": "https://news.google.com/rss/articles/CBMiXkFVX3lxTFBrb2F5RTRyVkM1NUZFMGloVlhzTG1DbjJ0d01zbTdVZXpnS0tULVJQYmJ5bGh2VXhER0ZVcDZnM0dBXzI4NGNDV0lUc1hSYk1aaHdsVDduTHkzX3U0Y0HSAUtBVV95cUxQSDRyRGFtZU9oNU5uTHByQUxOZ29XSEt2WnhZQ2tSWEFqYTFkb09aZm5DTGU2SDlTeTBlbHotc1VKV1NGTnVRY1dzRlk?oc=5"\n+ "name": "長榮航空 EVA Air — EVA Air To Launch Nonstop Taipei-Delhi Service on December 1",\n+ "url": "https://www.evaair.com/en-jp/about-eva-air/news/news-releases/2026-08-05-direct-flights-from-taipei-to-delhi.html"\n }\n ],\n "articleFormat": "brief",\n@@ -26,8 +26,8 @@\n },\n "sources": [\n {\n- "name": "Reuters — Japan orders evacuations as Typhoon Dolphin approaches, can…",\n- "url": "https://news.google.com/rss/articles/CBMixwFBVV95cUxQWFZfc3lhZFI0Tl91RGozVldWUjlvVVV5NUY2UHhXdmVjSXhXaHRoMFQyZDhQcWhGbVZmdVJNb2ttTVlVZEhmQkkyTGl2ZlZkVzJXQjdfdUVVNlpfSVIxS0tDb09wUlhYZXRGdm1mUUVLSV96ajdxenk1R2h2YjVSaWY0OUJ2N2xyWTU5MzRlMTFLdTJIYnVBczlHaVBJc0JHOG55MC0ycUJrbTFQSFdqV2J6VWVtMDhEWVNraXZSNE5xenBWU3lv?oc=5"\n+ "name": "The Japan Times / Reuters — Japan orders evacuations and cancels 500 flights as Typhoon Dolphin approaches",\n+ "url": "https://www.japantimes.co.jp/news/2026/08/07/japan/typhoon-dolphin-approaches-japan/"\n }\n ],\n "articleFormat": "brief",\n@@ -132,12 +132,8 @@\n },\n "sources": [\n {\n- "name": "Reuters — Etna eruption extends closure of Sicily's Catania airport u…",\n- "url": "https://news.google.com/rss/articles/CBMiwwFBVV95cUxNUTJ0cXZfa3BPZGVZWnVrd3Y5aDNRRlNIREJzeWdUUFpCYVhMTnVVUDBVRE55dnNCSzA3U1g5RFV3SzU5MVg1NktGX3NNSkdRYnJ2VjlnYzQ0SFg4QWk1SlA2aG95dUlPZTF2YWMteFdqWnZqX1c0eWpYbVktemNfMVBfODVfYVpyV2V1am1LdV9FVEc1b2JFUlFqNkdJYkdONTRUQ1JLYmN5dTMzLTZwMjFRVWRmMmpvWmlOVnVNOVQxYnc?oc=5"\n- },\n- {\n- "name": "reuters.com — Etna ash keeps Catania airport shut until Friday, disruptin…",\n- "url": "https://news.google.com/rss/articles/CBMiygFBVV95cUxPRkE3MDh4N2VXRXdHdEljQ3FHVmE0UU9LODRoM283YVhwWGZCLXZBNGo1eEhaVG5jTG52V24zTFVJMTFxbDRKclZRYlRhQmtVUDMzZ1dzdy0tcm8yeWR6T3k2eURIWjhaWXl0c3B1TkItdmhoUFFBLWVZVVdRbDRON0RFcnRha09qVG52SFFZTElhbDFoV0ZrR0s4MVhLcDBFd1hlakFpSWMzaXVURmRzVHlBR0stSDdYVlBFMnYyaDJXSk50OWdveUdR?oc=5"\n+ "name": "Internazionale / Reuters — Etna eruption extends closure of Sicily's Catania airport until Saturday",\n+ "url": "https://www.internazionale.it/ultime-notizie-reuters/2026/08/14/etna-eruption-extends-closure-of-sicily-s-catania-airport-until-saturday"\n }\n ],\n "articleFormat": "brief",\n@@ -28,128 +28,16 @@\n },\n "sources": [\n {\n- "name": "The Aviation Herald — Incident: Malta Air B38M at Faro and Seville on Aug 24th 20…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTFBIbjNlRTY4VXFEVk5lbjJOMXE2UlAxVTA0V25LeldvdE5lZU1KWjF0c0lTWXl5ejdraWF5dk9uT3BJamozVmtlWGZfYkRJOWdxT29FbEwyWE4?oc=5"\n+ "name": "Airportia / The Aviation Herald — Malta Air B38M at Faro and Seville on Aug 24th 2026",\n+ "url": "https://www.airportia.com/news/malta-air-b38m-at-faro-and-seville-on-aug-24th-2026-flaps-failure/"\n },\n {\n- "name": "The Aviation Herald — Incident: United B764 near London on Aug 24th 2026, packs i…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE4xU0MxTVpkN0kzZDd2S2tBYmt5WFFEbkkwSGxiSXljRi16TklpVWwxWWUyMnRLVXg2Q3ZmTVhJb1A2NDFJSjIwWV9fZlkydWNTUmtpOHpuS2Y?oc=5"\n+ "name": "Airportia / The Aviation Herald — United B764 near London on Aug 24th 2026",\n+ "url": "https://www.airportia.com/news/united-b764-near-london-on-aug-24th-2026-packs-issue/"\n },\n {\n- "name": "The Aviation Herald — Incident: Lingus A21N at Dublin on Aug 23rd 2026, fumes on…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTFAwdEd6aTdOQk9FMEVodDA0U0lRYzNuRmRjS2ZwTWpUMnRTdVlFUFZETWRmTnNMVHNTdlZpMkhpZzI4S3VzNUw0ZGRZaU9DM2F2Mzl5NWhRa3Q?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Delta A333 near St. John's on Aug 23rd 2026, engi…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE5vdEs3QjFZdno5cFpSVEtaSEtwS09OdUZCWmp0RWR2WTR1OWNZTjF6VDNlSlNhS2xVeDg3VUpXRFZvWVNReklFUTJndHZtd0VaSkNRTVBueHk?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Lingus A21N at Dublin on Aug 23rd 2026, fumes on…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE1fZElzakNQRUFJYk1NcHJsbEl1VWJBWDk4MlV4UGQyT1RoQzU2bkVDWEs5Z1QtZ19NMmtTSlNKZnB5RHpleUVIMFk4NVVhWmVQ?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Thai B773 at Frankfurt on Aug 21st 2026, could no…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTFA2cHZLd0ZSZ0JKYmZFVFI1WlBUX00tTnJKTTBCb2Q0ZDlqQ3B5YURZS2lucWFmR3JtRlBLR0VsWEpQbHllcVBzazdaV0ZNZ040?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Delta B764 at New York on Aug 21st 2026, engine c…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE92NTVjN0VpSndYaTBYcFhyWmEzRFhzNTdpYWNsc3hpVFJLd1ltdlNfWTdFTlJrNGNtOF9FWlp5MW1saUt3LWdWbU9mNkFZMF84?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Delta B764 at New York on Aug 21st 2026, engine c…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE1ZSVRxUHV4UVVIOC1aS1dMbEM1NUNFRUI2T1ZBSDE1V1ZFdWhva0toRXN0MlJCZVMxeWlmTmNiZjRNUW9NdDFWOERjWmxhZzlGQUpFMXVPdlY?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: United B763 at Geneva on Aug 20th 2026, engine sh…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE1GeEg5akhWOVhiSkEzOVlRUFpMZ2g3WmdPVEo0aFB4U3dqTmlmbjBPSnVNcndkUmFfWHdLaDdVVFk0MzBrTWVqM2FCTnczUk9nZFVuUHU3dFE?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: China West A319 at Lhasa on Aug 20th 2026, reject…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE1manZ6RU9tbU1tUjZkVVVVRW41cTdNQzhza0RCQjU2Y0J6OURFUlp0aVhSTnZvWXZJTy1uMkpqd29ZWFd0M0NRTHhwRnNxanNscUUtT1RKRHU?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Malaysia A333 at Tokyo on Aug 20th 2026, rejected…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE5VMV9BSENicVkxY0lQUDI0Z2phNkdrczVTRFVfVFZkMEJqa19LZUtLRVBTWG5KZkhHLWNuMUc1OUtBbXFoVGFLM3NmU01zTlZPaV9YdGdXUHA?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: United B763 at Geneva on Aug 20th 2026, engine sh…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE1CNHktU2cwcEpSY2NXRkQwN2Y4SlFnbVNTT21FRXoxVnlBWmFMVndnLWMxVWxnM3hPWkM0bm55ZFRWcHk0M0ZfZlRfaC1XZkRo?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: China West A319 at Lhasa on Aug 20th 2026, reject…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTFBwc3RIalRETm42aDRkdkR6T2Z5OEphLWVzWXZONTQxTTFJNF9IdVRPcHY5VEJDU05BenB0OHVSbnZkSzIzcl95TFpteEw2Mk9Z?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Delta B739 at Atlanta on Aug 20th 2026, engine fa…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE5KZmVHMWozanptY3VnejhEaVNHa0h6bFl1WjNvZnRwamFrYmZDODNwcGRMSGQ2cXJCdzN4NWRpSVZtYWhXdW1DcE82NVBIUHJv?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: France B773 at New York on Aug 19th 2026, bird st…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTFBvY1ROV1diU1hHdUJhdTNZWmpOcWc1SVFNaWd3WVVYN2FYa25zaDZEcHhlNVZIa3BMeEd5TnpfbHdLbGdnOGFhUzlDckwyVjVa?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Smartwings Poland B738 near Valencia on Aug 18th…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE5JdkhtZFYzSXZXUGRuN202SEMxaEVRc0E2MDdVM2d4bWVkY2lfVGNwcDcxYVFQdHJoYlJ6Y21Jc2hRSDZzWWFpSGdIaERqSS1n?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: British Airways A35K near London on Aug 18th 2026…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTFBJUG0zZUxSc0tzVjNaSHBsUTBmd1UxTktHQndJN3JiWW1lNGVyMnd4VmR1VUZJN3EwOWJrZW1EcnJRNFdFVkFvallLYkIxbzhq?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Lufthansa A388 at Munich on Aug 17th 2026, touche…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE44X1BkWjQ2QzVHRXgxdFh1ZkVLQ2ZuRVZBMmp6aVFyckowbWo1NUcwOG9OSE0wTWtrV25lek1jcFVORVhjU2ZZWkJ4V3pSWTJnMEkwNXFuQTc?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: PSA CRJ7 at Washington on Aug 17th 2026, smoke in…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE5PVGQ4U0ZBelBzdXQwMFpKY3E5Mng0Z0l4YnpHT0ZyT184TmhuRUhDcV9jWWlIc1I3WDVvdUhYblhSMGpJNmpxUzk3R1ZzS0Yt?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Lufthansa A388 at Munich on Aug 17th 2026, touche…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTFBwVFM0WUJHRUNyUzJIOEQ4bkRXNjFOeEtXeGxoMFNYc3A5ajdiN1Nhb3V2eTk1d3IxWFYxdHZBUVlOMEpabGxFSXVQZmM4eG45?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: PSA CRJ7 at Washington on Aug 17th 2026, smoke in…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTFBUT3ZwRXZzUm5HeUpTZk53OUdVUlVWdXNUZG5UV09EcmxNWE1IT1M3RXpXTHVHdnBzYVlLNXVTTGhha0Z6SUYyOGZZei0zeUpqbG1DWGIwSm4?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Alaska B39M near Chicago on Aug 16th 2026, engine…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE55YmlvUjBabVV2aGlkR3dpSW1ZdDhsTXVzYjYwMmNHWXVDZVBTOG5aU2R3ODROeGJkLWhnTHdzcjNXdlp3WXdEeElKTUFlal82bk1MTXBtWVA?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Lingus A320 at Cork on Aug 16th 2026, gear proble…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTFB2ZkVybDFXMGVUZTRVR0RFeDMwS3JaVnl5S3VMY3VrQkw4c3FaWmdvSHZBZ1VaMTRGNTZvSU93UTdTaEoxTEg2dWpjNHA0ZVdi?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Hainan A333 near Krasnoyarsk on Aug 15th 2026, me…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE14cjRhazVCcXhqM042QlZpSGdEQVhqbDRvX2V0YXllelZzSmxrckhSNVFFQTBtQnExR05veUlpV3dBNThCZUFyVWhFVUhLSHE4?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Ryanair B38M near Alicante on Aug 15th 2026, indi…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE9FemhqbHFHM3YwMHhERDJEQUh2MUxmd3otVkV3azZzNzViQkxSZGNaZXN1Nzhjdm1rZVE3dEpmLUxoa0JJX0dJNFRQLW1OemFTazNYRFFpQXg?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: UPS B763 at Denver on Aug 15th 2026, all instrume…",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE5najQ3d2ZLSnVqNEFuZFB6cy1UaFdfUlFlRUROSjNDaWdSZE1ZLWhxbXBwOGtPZHMwM0ctY3NUZ3lLVEZnRXRZZm8yVnl2LTky?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Lingus A320 at Cork on Aug 16th 2026, gear proble…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE5VT2EwQnNYdTJELTltWWszVjJHSC1mQ2VuLVpEVEdDYmFfUHJuUWVMcTY0UGlxNWc2MVhQRFBXTlliTmxfNTZRNEVGUXdkcE0xd0NXMXczR0Q?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: UPS B763 at Denver on Aug 15th 2026, all instrume…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE0waU5TMFJSdjBlNWZfeklteFBjS2ZvLUZ6TW8zb01VSHF5YW80T3BtbFpiSnExSnAydzAyUEkwMU1NVGZOdnRjMHZEb1pUTkk4bEROWTRGRlM?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Delta A321 at Atlanta on Aug 13th 2026, smell of…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTFBVWlVpU1MzMzFaSUhPR2dMdFNGcUFSbC1LbExBbkRRWVg5Tjd1MWIxNnFTYXNIU21fNnBGNEZ2bnlIRmpWSG1YVUY2MkdYQUlRMlU0cVhHTk8?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: Swiss A333 near Boston on Aug 14th 2026, hydrauli…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE9NNm1GMHc2c3dmaTZ1N2lFWFRWWEk0TGpvQk5BaWJBaVZFTkMzSm96UjNlRl9PN3RJa3ZCcmtBdGRDVWpXOVhyY252aVFTd2cyYS00TkZIbEU?oc=5"\n- },\n- {\n- "name": "The Aviation Herald — Incident: KLM A21N at Amsterdam on Aug 14th 2026, dog around",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE1Xbk02QVhxdVJ5RmJxZG90VWlobWtlWEZUNGNmaF9RbWptZWtZd2xSaVotR3dPUjdBMXg2bkFUVkQwWV9OVm8zUGEtMDM0YW9VaU1tZnZfLXg?oc=5"\n+ "name": "Airportia / The Aviation Herald — Lingus A21N at Dublin on Aug 23rd 2026",\n+ "url": "https://www.airportia.com/news/lingus-a21n-at-dublin-on-aug-23rd-2026-fumes-on-board/"\n }\n ],\n "articleFormat": "roundup",\n@@ -894,8 +782,8 @@\n },\n "sources": [\n {\n- "name": "The Aviation Herald — Incident: American B738 and American B738 at Phoenix on Aug…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTFA1dXNVS0xYWG1sTU9Md0hweGZsTDI5aHBiVk9vNEEyd3dmUFNUa0JHbDBJZ3N0OTAxelVuUTBxVF9Od3FLN3FBODVuRHphTkJHdUd1MmdOb00?oc=5"\n+ "name": "Airportia / The Aviation Herald — American B738 and American B738 at Phoenix on Aug 13th 2026",\n+ "url": "https://www.airportia.com/news/american-b738-and-american-b738-at-phoenix-on-aug-13th-2026-two-aircraft-same-callsign-one-on-departure-one-on-arrival/"\n }\n ],\n "articleFormat": "brief",\n@@ -1875,7 +1763,7 @@\n "id": "a-20260816-2304-reliance-industries-and-rolls-royce-anno",\n "publishedUtc": "2026-08-16T23:04Z",\n "cat": "mil",\n- "primarySource": "Rolls-Royce 官方新聞室",\n+ "primarySource": "Rolls-Royce",\n "image": null,\n "zh": {\n "title": "Reliance Industries 與勞斯萊斯宣布合作開發印度 AMCA 戰機引擎",\n@@ -1899,8 +1787,8 @@\n },\n "sources": [\n {\n- "name": "Rolls-Royce 官方新聞室 — Reliance Industries and Rolls-Royce announce strategic inte…",\n- "url": "https://news.google.com/rss/articles/CBMiswJBVV95cUxNZnFhdUh3d1hhbmFEUXl4OTdBU1dDV0ZnYkRDQVZONmxFa2Z2UDlzdFcwVEEwYlRHanhZTm5YV095VGJKWmZXS1Rfb0pWTEpUM19vTmxBcE1yZko5WEUxaVpmTnA4LUE4cjFvbUJhaDVEMk14ZkRUTmtMb3FJZGVPcjVMOHAyNkNyREE2TERBQUttcGJtMFBPclUzeklIT1cycE1Yd3VmWWd5UEY4VktVemlfVEFha3g5WDIyMDhrX25JQmEwTjVha1ZKWUV2NW1xaXJnSjN5V1JLeDd3ZWVJakczNWk1bUFpc2FPUGlwWnBqMTJWSmdXdDBBeDdxYnhhb2h4aHF2enpkLTRqS2ExeWJRNTFFWGc2d0lpZC1xV1NheGpTT2Mwd1NPZ1UwRkY5RlNr?oc=5"\n+ "name": "Rolls-Royce — Reliance Industries and Rolls-Royce announce strategic intent to partner on India's AMCA combat engine",\n+ "url": "https://www.rolls-royce.com/media/press-releases/2026/14-08-2026-reliance-industries-and-rolls-royce-announce-strategic-intent-to-partner-and-develop-indias-indigenous-combat-engine-for-the-amca-programme.aspx"\n }\n ],\n "articleFormat": "brief",\n@@ -2532,8 +2420,8 @@\n },\n "sources": [\n {\n- "name": "The Aviation Herald — Incident: United B739 at Chicago on Aug 13th 2026, rejected…",\n- "url": "https://news.google.com/rss/articles/CBMiWEFVX3lxTE5wM0N6Mk1Bc1JTNWlXRzk2YXFtRzNxc0NGX2JoMkNHMHZ6MDVqT0t0VHIteVhrRzU4LWc3X2tweXVUaThVQndLeWRqNnBIcVFpa1ZiR3VMeHA?oc=5"\n+ "name": "Airportia / The Aviation Herald — United B739 at Chicago on Aug 13th 2026",\n+ "url": "https://www.airportia.com/news/united-b739-at-chicago-on-aug-13th-2026-rejected-takeoff-due-to-tyre-damage/"\n }\n ],\n "articleFormat": "brief",\n@@ -261,16 +261,8 @@\n },\n "sources": [\n {\n- "name": "Reuters — Amazon plans drone delivery expansion to about 500 US local…",\n- "url": "https://news.google.com/rss/articles/CBMipgFBVV95cUxNcHdhMC1IZUpFSl94Sm9Iand5bW93SFBoZjdUcmd4YnBlY3dsaERKQURqNDRWOHZoSnltcE9jZjUyelJpT2RjR1dXREVmWFluLWgyR01LdTF5aVNsbER2NERJOVlGWDFNNi1sek05OURVTWhsdU1lVC1YbUN0a2l0UW5vZzhBbXhZaGVHbVdnREVzZXA4LTZnZUVvUzRjZGFrOFA1QUV3?oc=5"\n- },\n- {\n- "name": "WSJ — Amazon to Expand Drone Delivery Service to Nearly 500 Local…",\n- "url": "https://news.google.com/rss/articles/CBMigAFBVV95cUxQWFU4cDVTOEY2djFVZlU2UkNySldoSjFMSzNDT3VJZXRKN1I2THY5UElyOHlGQ2ZNaExuQkYzREFxX0s5Rk9Uakl6NFJtMGRib19Hdnk5cklZWUFiQzlneEtacW5ueXR2RVlBM09wQ2wzeFoxb3RTclVLVFpfaEVfSw?oc=5"\n- },\n- {\n- "name": "CNBC — Amazon to expand drone service to nearly 500 cities after t…",\n- "url": "https://news.google.com/rss/articles/CBMiqwFBVV95cUxPZ3BxOFZnTzBJVWI5ZGxBWXUwWWdmTG9EYmlDcTBLbXpHb1NyT3lzNDVCWmtyOFRMSUVHbjk5VllueGM0OE5nc0JwRllRTWFBeTUxVlg5MDRhY1NjQmdZWEF6MnFkYWlWZjV1Xy0xWFdxVWt4RlRjS2RRR0Z3OThpNlMxR3p2M3JFQmZld2RFam9DeXhEZm1hcEM2d1haUzQ4dHBjbmgzX3Z0NEXSAbABQVVfeXFMTV9jM3FXZ1NsU0NkVVlISXpLanlUczBVQ2ZDeE4zTDFZUDJBUzRlRlVIalh5MG9aMktBWU1tZWtCR0lYOGVqMDhkdXRvbzgyZno0NC1UdDY1X1BxdHBXbVBqUGg0aFpKamItNmQ5QXFXVmZnSzZwbVQzR3Y2OC1KdmdNeVB5WTg4T1g0ZkdGRktWb0E2aTlCNzVrMV83cTNGQ1R6dXpMUk1HTFZXM3Y0dEY?oc=5"\n+ "name": "Investing.com / Reuters — Amazon plans drone delivery expansion to about 500 US locales",\n+ "url": "https://www.investing.com/news/economy-news/amazon-plans-drone-delivery-expansion-to-about-500-us-locales-4868017"\n }\n ],\n "articleFormat": "brief",\n@@ -4,7 +4,7 @@\n "id": "a-20260820-0826-taiwan-railway-to-add-158-trains-for-hol",\n "publishedUtc": "2026-08-20T08:26Z",\n "cat": "ops",\n- "primarySource": "臺灣交通要聞",\n+ "primarySource": "臺鐵公司",\n "image": null,\n "zh": {\n "title": "台鐵因應中秋暨教師節連假加開158列次 8月25日開放訂票",\n@@ -26,16 +26,8 @@\n },\n "sources": [\n {\n- "name": "臺灣交通要聞 — 中秋暨教師節連假 台鐵加開158列次、8/25起開放訂票",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE5FNHExbnJ2d2pCQnIxSmZ4ZWw4aHBnMEhCcG5xZjJhbmllM3pCX0dGeUFvd1lsN1hhRngzTUg2XzV4YUl4SUJWS0Q0bzNlNTZP?oc=5"\n- },\n- {\n- "name": "自由時報 — 台鐵中秋、教師節連假加開158列次8/25零時開放訂票- 生活",\n- "url": "https://news.google.com/rss/articles/CBMiZEFVX3lxTE9OdFNwek9kRUpTMjljV21RaEZualVKWDhsMVdFeU40UVhpb0RxM2FJT1h6eWJzeExDaVZxMWxrWmlwQzh5V21WV1ZjMjFlOFV2MGNRZ3dSZWJleno3TkdoNHdXR04?oc=5"\n- },\n- {\n- "name": "ETtoday新聞雲 — 台鐵中秋教師連假「加開158班次」 8/25開放訂票",\n- "url": "https://news.google.com/rss/articles/CBMiXkFVX3lxTFB1UjhCM3ZHd2R5U0JscWFwNEtYV0xqUndwZmdfS3M3SUZ6YzRTQjd4Q2MtSWlIUlZMYjBITlRid2pEcVBLRm1HdldlZWN4VDZPRi15dGJVX090RDB3T1HSAUtBVV95cUxOalU4ZXhMRnRRLVRmWVBQaTdPQnN2OGFuYmdSUW9WNVVnS2VOUGVuakNTWnV2WklrWDAxRm9EZUVUUjZHNF9oWVlYZzA?oc=5"\n+ "name": "國營臺灣鐵路股份有限公司 — 臺鐵公司115年中秋暨教師節連續假期加開158列次",\n+ "url": "https://www.railway.gov.tw/tra-tip-web/tip/tip009/tip911/newsDtl?newsNo=8ae4cac296da854e0196e35211d71e1e&page=8"\n }\n ],\n "articleFormat": "brief",\n@@ -4,7 +4,7 @@\n "id": "a-20260823-2312-tra-suspends-south-link-and-taitung-line",\n "publishedUtc": "2026-08-23T23:12Z",\n "cat": "ops",\n- "primarySource": "臺灣交通要聞",\n+ "primarySource": "臺鐵公司",\n "image": null,\n "zh": {\n "title": "受暴雨影響 台鐵南迴線與台東線週一上午對號列車停駛",\n@@ -26,16 +26,8 @@\n },\n "sources": [\n {\n- "name": "臺灣交通要聞 — 暴雨狂炸南部、東部週一上午台鐵南迴線、台東線對號列車停駛- 生活",\n- "url": "https://news.google.com/rss/articles/CBMiZEFVX3lxTFBoelA3TWFkelRTUmotRDlOYWUzZ09VZGtRdklObUhYOWdSX21xYjhkYmtYZC0wV3VTRDJOb0dUUTJVZFhwSVF3cU9rZ0dpOWJwNzU1UnMwdDgxc2Jfek9Tb2lvM0k?oc=5"\n- },\n- {\n- "name": "臺灣交通要聞 — 暴雨狂炸南部、東部週一上午台鐵南迴線、台東線對號列車停駛- 嘉義縣",\n- "url": "https://news.google.com/rss/articles/CBMidEFVX3lxTE81TFZzWG5sTk1fOEs4UDFZcGpESTJIdVlwNnI3bnNBa1pvX3o4N1h4ZFBCa0RaWmZRNGt6U1Vlc2xvTDRLWDVmeGhzdzlIY3hGdVJ4OG9ka3dIZVNuZzRVMHFDdjBReGZJNmNYekRGWlNpc3Vn?oc=5"\n- },\n- {\n- "name": "自由時報 — 暴雨狂炸南部、東部週一上午台鐵南迴線、台東線對號列車停駛- 屏東縣",\n- "url": "https://news.google.com/rss/articles/CBMib0FVX3lxTE1KZWxRMmp3VEExVnJiMEcwYW01bnBKcEh3MDh1YVhUNUZ0aDAzeUJDUjRBX2NjLW5iQ0d2VWJ5Wk9aajBPQWVQUnowUkV1VWpqQzQ4aWEzOWpzdnc4OHk1UDFDR2hQYTFsNEhmOVVraw?oc=5"\n+ "name": "國營臺灣鐵路股份有限公司 — 8月24日12時前南迴線及臺東線部分對號列車停駛",\n+ "url": "https://tip.railway.gov.tw/tra-tip-web/tip/tip009/tip911/newsDtl?newsNo=8ae4cac2a025b48401a02f435fa50e3c"\n }\n ],\n "articleFormat": "brief",\n@@ -239,7 +239,7 @@\n "id": "a-20260824-0751-tra-suspends-south-link-and-eastern-line",\n "publishedUtc": "2026-08-24T07:51Z",\n "cat": "ops",\n- "primarySource": "臺灣交通要聞",\n+ "primarySource": "臺鐵公司",\n "image": null,\n "zh": {\n "title": "台鐵因應豪大雨南迴及東部幹線對號車24日18時前停駛",\n@@ -260,28 +260,8 @@\n },\n "sources": [\n {\n- "name": "臺灣交通要聞 — 台鐵東部幹線對號列車停駛區間車視降雨狀況行駛| 生活",\n- "url": "https://news.google.com/rss/articles/CBMiX0FVX3lxTFAwMmxmNGZJU0tMZDh2cFRadDlxRU53Z1IzZlppcGdWUmxyV0IxV3hoQ1BjUnBReEJaeXJjMWlGUWdidjZPRUdXNFBidmlSa3hfUWVqaFhhWVBBQ3ZLZFZz?oc=5"\n- },\n- {\n- "name": "臺灣交通要聞 — 台鐵南迴線、東部幹線對號列車停駛區間車機動行駛- 生活",\n- "url": "https://news.google.com/rss/articles/CBMiZEFVX3lxTE1WWnR2ODdsMV91eDhHYVJUUWhSYUVoVXBPVHVMTUVLdFZsUFhubFUwSldGRTdFWjM2RzNGRFlHenBZZTZjWi1LTlF1WGhhMUtlMGVtM0dwSGlETjU4Nm1DaktHcmY?oc=5"\n- },\n- {\n- "name": "臺灣交通要聞 — 臺鐵公司因應豪大雨於今24日18時前 南迴線及東部幹線對號列車停駛 區間車機動行駛",\n- "url": "https://news.google.com/rss/articles/CBMiSkFVX3lxTE1yb1lYNXhQVlFfZUwxNnNENHcwaldBZWk1WDUxSjBQdkJMRkFINEJFLWNPTkNIWDFhM1NHWU9sRFFFMGRZZ0ltVnpn?oc=5"\n- },\n- {\n- "name": "臺灣交通要聞 — 台鐵18時前南迴線、東部幹線對號列車停駛 區間車機動行駛",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTFBMY0NGcC03M3N4V2VydG80TEoySi1ycHlpTmp3R241WUJOaXNVRVlJS19LQkVZa2U5aVk0ZEtzb0RiOFNrZEQ4aVp1MURac0Uz0gFWQVVfeXFMT0JXdV9FT2JYX0lkdTRGSnJHaWRualJQN1lLT20weDY3RE0yZGg0SlJJRkVMZlNlSGEyRlI5V0hfTFdXZmVEa3doRklrMGJVbVU1d1diYkE?oc=5"\n- },\n- {\n- "name": "臺灣交通要聞 — 台鐵晚上6點前南迴、東幹線對號車停駛 區間車機動行駛",\n- "url": "https://news.google.com/rss/articles/CBMiTEFVX3lxTFA1aXB4cHA1Y3pFcjFJR0IwYks0Y0E4aGF6NldhXzJmcVZPQ1pqMkdKdGNiZ2xVOXYtZTNHNjBIQlM4YUVzaldlMWpPS1PSAVJBVV95cUxOeU9PNWZnSXlWUVRqRUxOSlRaX0tDb29fRXdLZFhCcGpVblNHajBsaC1JUmtob2dwTUdoT1JZVDZvQVVUOUhWWjFSMzZoZXFtS3RR?oc=5"\n- },\n- {\n- "name": "經濟日報 — 台鐵18時前南迴線、東部幹線對號列車停駛 區間車機動行駛",\n- "url": "https://news.google.com/rss/articles/CBMigwFBVV95cUxPNWlFdzVESElZWVZ3V3ZQX2NKWUpFSERhNC16TG8xWUFqU2xfbVAxcHZIaXVPZjlCaWdXVlFwNU1qQ0pjVG0xVDJtdHliTVZ1YzFYWC1TQkhPcFhGZk9HeUk0cmFmWnlOWHpFcWR4UTZELUMzZGVvVVk3Xzd1VFhlU2ozTdIBYkFVX3lxTE0ydmk0UXQ4dTM5Wmw5SWo3WVBQdjhwbGVuU2JXOXRVUWk1NkhTNHFXZ3FzYi11RlN2X2l0SWk3eURMS0RGYnVCSjdpZ2xvSUFtRXFuckFoUl81b2VzWjJ5ZFNR?oc=5"\n+ "name": "國營臺灣鐵路股份有限公司 — 8月24日18時前南迴線及東部幹線對號列車停駛",\n+ "url": "https://tip.railway.gov.tw/tra-tip-web/tip/tip009/tip911/newsDtl?newsNo=8ae4cac2a025b48401a03115630938ed&page=0"\n }\n ],\n "articleFormat": "brief",\n@@ -4,7 +4,7 @@\n "id": "a-20260826-0043-taiwan-railways-clears-south-link-line-s",\n "publishedUtc": "2026-08-26T00:43Z",\n "cat": "ops",\n- "primarySource": "臺灣交通要聞",\n+ "primarySource": "臺鐵公司",\n "image": null,\n "zh": {\n "title": "台鐵南迴線枋山至枋野段搶通 8月26日首班車恢復正常營運",\n@@ -26,12 +26,8 @@\n },\n "sources": [\n {\n- "name": "臺灣交通要聞 — 台鐵南迴線枋山至枋野間搶通 26日首班車起恢復正常",\n- "url": "https://news.google.com/rss/articles/CBMiYkFVX3lxTE5zbVN3MG5kNTNuenl0UUdWbWJQNGVVTFlXNUdUN2FOX2pGaGdaaVNaVWZWMENId1hJVHN5MUJDOXhEQ1VGcGt5UHNGMVF4NFlNODByVXNJamIta3VpV2hfMk5n0gFiQVVfeXFMTnNtU3cwbmQ1M256eXRRR1ZtYlA0ZVVMWVc1R1Q3YU5fakZoZ1ppU1pVZlYwQ0h3WElUc3kxQkM5eERDVUZwa3lQc0YxUXg0WU04MHJVc0lqYi1rdWlXaF8yTmc?oc=5"\n- },\n- {\n- "name": "經濟日報 — 台鐵南迴線枋山至枋野間搶通 26日首班車起恢復正常",\n- "url": "https://news.google.com/rss/articles/CBMigAFBVV95cUxNNmFLYWRJMG5oTUZQUV9BTjNYQmRBY0hyWHRmZWhLcGlMLUFDZURLSENRY2RFTXVoU0pURDZvRmVzaGIxVEN2a2U4eEZBTkV6NnJRTGduSmFZdmVPQUloTFdiMVBuSVlIeFNsVS1kR1oyNDBtMzlWeVVnMk0zSy0wc9IBX0FVX3lxTE5sMkZyc0d5WFFsUkFaMEg5VHo5X01RbTJKczlSRWdVX1BqQVBXN1l1MWx3ak93QkZWWEVtamw3VmU1VUV1XzNlWFRyc1BndjlacUphX3p2eV85LUVSWVpJ?oc=5"\n+ "name": "國營臺灣鐵路股份有限公司 — 8月26日南迴線列車恢復正常行駛",\n+ "url": "https://www.railway.gov.tw/tra-tip-web/tip/tip009/tip911/newsDtl?newsNo=8ae4cac2a03527ac01a0394e0062489c&page=0"\n }\n ],\n "articleFormat": "brief",\n@@ -4,7 +4,7 @@\n "id": "a-20260826-0219-heavy-rain-worsens-mudslides-as-tra-susp",\n "publishedUtc": "2026-08-26T02:19Z",\n "cat": "ops",\n- "primarySource": "臺灣交通要聞",\n+ "primarySource": "臺鐵公司",\n "image": null,\n "zh": {\n "title": "豪雨引發枋山枋野土石流加劇 台鐵南迴線8月25日深夜前全線停駛",\n@@ -26,12 +26,8 @@\n },\n "sources": [\n {\n- "name": "臺灣交通要聞 — 豪雨狂炸…枋山枋野土石流加劇 台鐵南迴線今晚24時前全停駛",\n- "url": "https://news.google.com/rss/articles/CBMiVkFVX3lxTE5GNFhMbmZ3eFplNS13cU5heUpiY3UtV1BKMEF4SHJwQjBKbmlyc18yZ0wyXzh4aEktZHBvS0JacmVPQUVRZ2dZbVlSdTVFeHZoWjFSX1BR0gFWQVVfeXFMTkY0WExuZnd4WmU1LXdxTmF5SmJjdS1XUEowQXhIcnBCMEpuaXJzXzJnTDJfOHhoSS1kcG9LQlpyZU9BRVFnZ1ltWVJ1NUV4dmhaMVJfUFE?oc=5"\n- },\n- {\n- "name": "UDN — 豪雨狂炸…枋山枋野土石流加劇 台鐵南迴線今晚24時前全停駛",\n- "url": "https://news.google.com/rss/articles/CBMiUEFVX3lxTE1OUjV2Y3V5d09ycDFxVW0wRXVITHVYNVhxZ21YWXNDekZhRTJDUXl1RDhieTFiZ2pUcjZGZ0pLcnJzNXRkbjBxdmtSWDkzOUwz0gFWQVVfeXFMTkY0WExuZnd4WmU1LXdxTmF5SmJjdS1XUEowQXhIcnBCMEpuaXJzXzJnTDJfOHhoSS1kcG9LQlpyZU9BRVFnZ1ltWVJ1NUV4dmhaMVJfUFE?oc=5"\n+ "name": "國營臺灣鐵路股份有限公司 — 枋山至枋野土石流加劇,8月25日24時前南迴線停駛",\n+ "url": "https://www.railway.gov.tw/tra-tip-web/tip/tip009/tip911/newsDtl?newsNo=8ae4cac2a03527ac01a037f96bc04657&page=0"\n }\n ],\n "articleFormat": "brief",\n@@ -231,7 +231,7 @@\n "id": "a-20260826-1232-vessel-lan-bai-1-runs-aground-off-xiaoli",\n "publishedUtc": "2026-08-26T12:32Z",\n "cat": "safety",\n- "primarySource": "臺灣交通要聞",\n+ "primarySource": "中央社 CNA",\n "image": null,\n "zh": {\n "title": "小琉球藍白1號因港口積淤擱淺 船上146人順利獲救",\n@@ -253,12 +253,8 @@\n },\n "sources": [\n {\n- "name": "臺灣交通要聞 — 淤泥積港口!小琉球「藍白1號」擱淺 146人困海中央虛驚獲救- 生活",\n- "url": "https://news.google.com/rss/articles/CBMiakFVX3lxTE9uNDZpZ3pLY3BlN19iYkRSaGgxTkwzekxDVEV0TkFSdU5vRGExRnNZZDlJbFo0enZzcjZyVDFfNE5mZHJPY0FlYlJKMmZpSVBuRG1jRXZHajFLeGgzdjkyb19ZMHB2c1ZpR1E?oc=5"\n- },\n- {\n- "name": "自由時報 — 淤泥積港口!小琉球「藍白1號」擱淺 146人困海中央虛驚獲救- 生活",\n- "url": "https://news.google.com/rss/articles/CBMiZEFVX3lxTE5ma1lVTGxoYndKb3k1Y28yNWJIRldqWVFLU1dSRFNkT2xYTnZsYWNtemxXVkhjSkI2eUNBVlhuVXQ5OXFnOVlOWDJIaFczeTRzZlFCWE5ZUHo2dzBsRDF6MUZwaWU?oc=5"\n+ "name": "中央社 CNA — 藍白航運客船擱淺 146人平安脫困",\n+ "url": "https://www.cna.com.tw/news/asoc/202608260275.aspx"\n }\n ],\n "articleFormat": "brief",\n@@ -1,6 +1,7 @@\n """Regression checks for direct public source links."""\n from __future__ import annotations\n \n+import json\n import sys\n from pathlib import Path\n \n@@ -56,6 +57,29 @@ def main() -> int:\n assert all(not common.is_google_news_url(source["url"])\n for source in public_sources)\n \n+ # Every non-archived historical article must retain at least one direct\n+ # publisher/source URL. Google News may be discovery input, but it is not\n+ # a public attribution target and build.py intentionally filters it out.\n+ google_only = []\n+ for path in sorted(build.ARTICLES_DIR.glob("*.json")):\n+ payload = json.loads(path.read_text(encoding="utf-8"))\n+ for article in payload.get("articles", []):\n+ if not isinstance(article, dict) or article.get("archived") is True:\n+ continue\n+ urls = [\n+ str(source.get("url") or "")\n+ for source in article.get("sources", [])\n+ if isinstance(source, dict) and source.get("url")\n+ ]\n+ direct_urls = [\n+ url for url in urls\n+ if url.startswith(("http://", "https://"))\n+ and not common.is_google_news_url(url)\n+ ]\n+ if not direct_urls:\n+ google_only.append((path.name, article.get("id")))\n+ assert not google_only, f"published articles without direct sources: {google_only}"\n+\n print("PASS test_source_links")\n return 0\n