Each (category × period) cell in news_digest.json now carries a hash of its
entry pool (sorted URLs). Before calling Gemini, the engine checks:
1. Hash matches stored hash (same inventory entries)
2. Last analyzed within MAX_STALENESS_DAYS=30
Both conditions true → reuse existing ranked list, 0 Gemini API calls.
Only cells where the inventory actually changed (new/removed entries) trigger
a fresh Gemini ranking.
Expected savings: re-runs with code-only changes → 0 API calls (down from 66).
New ingestion batch → only affected categories call Gemini (5-10 of 26 typical).
Stale refresh (>30d) → full refresh at most once per month.
Also:
- Remove day-level GitHub Actions cache for digest (redundant: news_digest.json
is committed to the repo and is the persistent store for _meta)
- Always run news_digest.py in both 04.1 and 09 workflows (it's cheap when 0
Gemini calls are needed)
- Trending badge now reads _meta.last_updated (actual analysis date) instead of
file mtime (which changes on every render/commit)
- Remove invalid extra_head key from v2-mkdocs.yml (left over from rollback)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. Skip page deletion and nav sync in --render-only mode
The CI publisher always uses --render-only but the pruning phase was
deleting pages not regenerated in a given pass (e.g. low-hit pages),
breaking nav references and corrupting the MkDocs build.
2. Protect dimension pages from deletion in full mode
Even in a full (non-render-only) run, pages defined in self.dimensions
are never deleted. Truly orphaned pages (not in dimensions AND not
generated) are the only ones pruned.
3. _sync_enterprise_navigation returns True/False
Deletion is gated on nav sync success. If nav sync fails, deletion
is skipped to prevent inconsistency (deleted files + stale nav).
Also fixes the fragile re.sub(r'nav:.*') regex by using string
indexing instead, preventing accidental truncation of extra_css etc.
4. Deploy workflow V2 sanity check
If V2 build produces fewer than 50 HTML pages or no index.html,
deploy falls back to V1-only instead of overwriting V1 with a
broken V2 build.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The publisher deleted ~30 v2-docs pages still referenced in v2-mkdocs.yml nav,
producing a broken MkDocs build. Rolling back to last known good state (v2.8.4).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove extra_head (not a valid MkDocs config key, was breaking V2 build)
- Fix digital-money.md redirect: finops.md was deleted by publisher,
redirect now points to kubernetes.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_render_single_link (line 872) crashed with TypeError: '>=' not supported
between NoneType and int. Replaced ALL remaining .get('stars', 0) patterns
with .get('stars') or 0 throughout v2_optimizer.py to prevent further
crashes from null stars values in inventory.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Publisher and weekly digest workflows now restore news_digest.json from
GitHub Actions cache using key news-digest-YYYY-MM-DD. If cache hits
(same-day re-run after publisher failure), the Gemini digest step is
skipped entirely — saving ~20min and Gemini API credits.
Cache is saved immediately after successful generation and expires
automatically after 7 days (GitHub Actions cache policy).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three sites in v2_optimizer where `-x.get("stars", default)` crashes
with TypeError when stars field is present but null in inventory.
Fixed with `-(x.get("stars") or default)` pattern consistently.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
item.get("resource_type", "Reference") returns None when the field
exists with a null value in the inventory. Use `or "Reference"` instead.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. geo_region inference: _infer_geo_from_url() infers Americas/Europe/España/Asia-Pacific
from URL TLD (.es .de .fr .uk .jp .cn etc.) as fallback when geo_region field is empty.
Industry digest now shows real content instead of empty categories.
2. Last-updated badge: trending section header now shows "Updated Jun 19, 2026" pill
derived from news_digest.json mtime — gives readers confidence in freshness.
3. Search boost: tech-digest and industry-digest pages now have search.boost: 2
frontmatter so they rank higher in MkDocs Material site search.
4. RSS feed (src/rss_generator.py): generates v2-docs/feed.xml with top-20 curated
picks from 3-month digest. Runs after news_digest in publisher. Autodiscovery
<link rel="alternate"> added to v2-mkdocs.yml extra_head.
5. Weekly cron (09.weekly_digest.yml): runs every Monday 06:00 UTC, generates digest
with Gemini, renders digest pages, commits, then triggers publisher.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>