diff --git a/scripts/check_growth_live.py b/scripts/check_growth_live.py
index 71a9d29..2e29903 100644
--- a/scripts/check_growth_live.py
+++ b/scripts/check_growth_live.py
@@ -13,6 +13,14 @@
CATALOG_MIN_ITEMS = 92
FEATURED_SLUGS = ("debate-me", "tappitsu-battle", "future-me", "twotaku")
GROWTH_RELEASE_ID = "growth-20261106-wave2"
+GROWTH_LASTMOD_BASELINE = "2026-11-07"
+GROWTH_UPDATED_PATHS = (
+ "/", "/apps",
+ "/support/taletime/", "/support/debate-me/",
+ "/support/dog-breeds-encyclopedia/", "/support/face-reaction-battle/",
+ "/guides/quick-games/", "/guides/daily-habits/",
+ "/guides/decision-helpers/", "/guides/ai-tools/",
+)
PATHS = ("/", "/apps", "/robots.txt", "/sitemap.xml") + tuple(
f"/support/{slug}/" for slug in SLUGS
)
@@ -154,6 +162,18 @@ def check(path, key, valid):
loc = "https://appdevelopsk.com" + path
check("/sitemap.xml", f"listed_{path}", f"{loc}" in sitemap)
+ # Recent content changes must be discoverable through a current sitemap.
+ # Dates later than the baseline are valid when the page changes again.
+ for path in GROWTH_UPDATED_PATHS:
+ canonical = "https://appdevelopsk.com" + path
+ match = re.search(
+ r"" + re.escape(canonical) +
+ r"\s*(\d{4}-\d{2}-\d{2})",
+ sitemap,
+ )
+ check("/sitemap.xml", f"fresh_lastmod_{path}",
+ bool(match and match.group(1) >= GROWTH_LASTMOD_BASELINE))
+
return {"passed": all(item["passed"] for item in findings),
"passedChecks": sum(item["passed"] for item in findings),
"totalChecks": len(findings), "checks": findings,
diff --git a/scripts/test_growth_live.py b/scripts/test_growth_live.py
index 89205a7..365ed4a 100644
--- a/scripts/test_growth_live.py
+++ b/scripts/test_growth_live.py
@@ -2,7 +2,7 @@
import json
import unittest
-from check_growth_live import FEATURED_SLUGS, GROWTH_RELEASE_ID, PATHS, SLUGS, inspect
+from check_growth_live import FEATURED_SLUGS, GROWTH_RELEASE_ID, GROWTH_UPDATED_PATHS, PATHS, SLUGS, inspect
def valid_pages():
@@ -59,9 +59,17 @@ def valid_pages():
f'' +
" ".join(f'' for x in other))
pages["/robots.txt"] = "User-agent: *\\nAllow: /icons/\\n"
- pages["/sitemap.xml"] = "".join(
- f"https://appdevelopsk.com{p}"
- for p in ("/", "/apps") + tuple(f"/support/{s}/" for s in SLUGS))
+ pages["/sitemap.xml"] = (
+ "".join(
+ f"https://appdevelopsk.com{p}2026-11-07"
+ for p in GROWTH_UPDATED_PATHS
+ ) +
+ "".join(
+ f"https://appdevelopsk.com/support/{slug}/"
+ for slug in SLUGS
+ if f"/support/{slug}/" not in GROWTH_UPDATED_PATHS
+ )
+ )
for path in ("/", "/apps") + tuple(f"/support/{slug}/" for slug in SLUGS):
pages[path] = (f'' + pages[path])
@@ -74,6 +82,22 @@ def test_valid_source_fixture_passes(self):
self.assertTrue(report["passed"])
self.assertEqual(report["passedChecks"], report["totalChecks"])
+ def test_recent_sitemap_timestamp_regression_fails(self):
+ data = valid_pages()
+ data["/sitemap.xml"] = data["/sitemap.xml"].replace(
+ "https://appdevelopsk.com/apps2026-11-07",
+ "https://appdevelopsk.com/apps2026-11-06",
+ )
+ self.assertFalse(inspect(data)["passed"])
+
+ def test_missing_recent_sitemap_page_fails(self):
+ data = valid_pages()
+ data["/sitemap.xml"] = data["/sitemap.xml"].replace(
+ "https://appdevelopsk.com/guides/ai-tools/2026-11-07",
+ "",
+ )
+ self.assertFalse(inspect(data)["passed"])
+
def test_missing_related_link_fails(self):
data = valid_pages()
data["/support/future-me/"] = data["/support/future-me/"].replace(
diff --git a/scripts/test_sitemap_growth_freshness.py b/scripts/test_sitemap_growth_freshness.py
new file mode 100644
index 0000000..52a3e52
--- /dev/null
+++ b/scripts/test_sitemap_growth_freshness.py
@@ -0,0 +1,61 @@
+"""Validate catalog and recently revised support/guide sitemap dates.
+
+Run with: python3 -m unittest discover -s scripts -p 'test_sitemap_growth_freshness.py' -v
+"""
+from datetime import date
+from pathlib import Path
+import unittest
+import xml.etree.ElementTree as ET
+
+ROOT = Path(__file__).resolve().parent.parent
+NS = "{http://www.sitemaps.org/schemas/sitemap/0.9}"
+BASE = "https://appdevelopsk.com"
+CHANGED_2026_11_07 = (
+ "/", "/apps",
+ "/support/taletime/", "/support/debate-me/",
+ "/support/dog-breeds-encyclopedia/", "/support/face-reaction-battle/",
+ "/guides/quick-games/", "/guides/daily-habits/",
+ "/guides/decision-helpers/", "/guides/ai-tools/",
+)
+
+
+def entries():
+ root = ET.parse(ROOT / "sitemap.xml").getroot()
+ if root.tag != NS + "urlset":
+ raise ValueError("unexpected sitemap XML root")
+ records = []
+ for item in root.findall(NS + "url"):
+ url = item.findtext(NS + "loc")
+ lastmod = item.findtext(NS + "lastmod")
+ records.append((url, lastmod))
+ return records
+
+
+class GrowthSitemapFreshnessTests(unittest.TestCase):
+ def test_sitemap_canonical_urls_are_unique(self):
+ records = entries()
+ urls = [url for url, _ in records]
+ self.assertEqual(len(urls), len(set(urls)))
+ self.assertGreaterEqual(len(urls), 319)
+ self.assertTrue(all(url.startswith(BASE + "/") for url in urls))
+ self.assertNotIn(BASE + "/apps.html", urls)
+
+ def test_changed_pages_have_accurate_nov_7_date(self):
+ pages = dict(entries())
+ for path in CHANGED_2026_11_07:
+ with self.subTest(path=path):
+ self.assertEqual(pages.get(BASE + path), "2026-11-07")
+
+ def test_sitemap_dates_are_valid_and_not_future(self):
+ for url, stamp in entries():
+ with self.subTest(url=url):
+ parsed = date.fromisoformat(stamp)
+ self.assertLessEqual(parsed, date.today())
+
+ def test_filtered_catalog_urls_are_not_indexed_separately(self):
+ urls = [url for url, _ in entries()]
+ self.assertFalse(any("?goal=" in url for url in urls))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sitemap.xml b/sitemap.xml
index 0fa0e69..f284b1b 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -1,11 +1,11 @@
- https://appdevelopsk.com/2026-11-05weekly1.0
+ https://appdevelopsk.com/2026-11-07weekly1.0
https://appdevelopsk.com/about2026-08-18yearly0.4
https://appdevelopsk.com/contact2026-08-18yearly0.4
https://appdevelopsk.com/privacy2026-08-18yearly0.4
https://appdevelopsk.com/terms2026-08-18yearly0.4
- https://appdevelopsk.com/apps2026-11-06weekly0.9
+ https://appdevelopsk.com/apps2026-11-07weekly0.9
https://appdevelopsk.com/support/2026-08-18weekly0.6
https://appdevelopsk.com/privacy-policy/2026-08-18weekly0.3
https://appdevelopsk.com/support/30sec-challenge/2026-08-18monthly0.8
@@ -27,16 +27,16 @@
https://appdevelopsk.com/support/daily-duel/2026-08-18monthly0.8
https://appdevelopsk.com/support/date-pilot/2026-08-18monthly0.8
https://appdevelopsk.com/support/date-roulette/2026-08-18monthly0.8
- https://appdevelopsk.com/support/debate-me/2026-11-05monthly0.8
+ https://appdevelopsk.com/support/debate-me/2026-11-07monthly0.8
https://appdevelopsk.com/support/debrief/2026-08-18monthly0.8
https://appdevelopsk.com/support/dinner-home-roulette/2026-08-18monthly0.8
https://appdevelopsk.com/support/dinosaur-encyclopedia/2026-08-18monthly0.8
- https://appdevelopsk.com/support/dog-breeds-encyclopedia/2026-08-18monthly0.8
+ https://appdevelopsk.com/support/dog-breeds-encyclopedia/2026-11-07monthly0.8
https://appdevelopsk.com/support/dream-log/2026-08-18monthly0.8
https://appdevelopsk.com/support/drift/2026-08-18monthly0.8
https://appdevelopsk.com/support/earsense/2026-08-18monthly0.8
https://appdevelopsk.com/support/eye-break/2026-08-18monthly0.8
- https://appdevelopsk.com/support/face-reaction-battle/2026-10-27monthly0.8
+ https://appdevelopsk.com/support/face-reaction-battle/2026-11-07monthly0.8
https://appdevelopsk.com/support/face-symmetry/2026-08-18monthly0.8
https://appdevelopsk.com/support/face-vibe/2026-11-04monthly0.8
https://appdevelopsk.com/support/fileforce/2026-08-18monthly0.8
@@ -112,7 +112,7 @@
https://appdevelopsk.com/support/study-roulette/2026-08-18monthly0.8
https://appdevelopsk.com/support/sub-tracker/2026-08-18monthly0.8
https://appdevelopsk.com/support/take-sides/2026-08-18monthly0.8
- https://appdevelopsk.com/support/taletime/2026-08-18monthly0.8
+ https://appdevelopsk.com/support/taletime/2026-11-07monthly0.8
https://appdevelopsk.com/support/tappitsu-battle/2026-11-05monthly0.8
https://appdevelopsk.com/support/tier-rank-me/2026-08-18monthly0.8
https://appdevelopsk.com/support/tracepedia/2026-08-18monthly0.8
@@ -315,8 +315,8 @@
https://appdevelopsk.com/terms/smile-score/2026-08-18yearly0.3
https://appdevelopsk.com/terms/idea-market/2026-11-04yearly0.3
https://appdevelopsk.com/csae-standards/2026-08-18yearly0.3
- https://appdevelopsk.com/guides/quick-games/2026-10-30monthly0.7
- https://appdevelopsk.com/guides/daily-habits/2026-10-27monthly0.7
- https://appdevelopsk.com/guides/decision-helpers/2026-10-27monthly0.7
- https://appdevelopsk.com/guides/ai-tools/2026-10-27monthly0.7
+ https://appdevelopsk.com/guides/quick-games/2026-11-07monthly0.7
+ https://appdevelopsk.com/guides/daily-habits/2026-11-07monthly0.7
+ https://appdevelopsk.com/guides/decision-helpers/2026-11-07monthly0.7
+ https://appdevelopsk.com/guides/ai-tools/2026-11-07monthly0.7