464 Commits

Author SHA1 Message Date
Inaki Fernandez
2edac4413a fix(health-checker): prevent TypeErrors when stars is null in database 2026-07-12 19:30:33 +02:00
Inaki Fernandez
6a6663027a fix(health-checker): prevent TypeError when health_score is null in database 2026-07-12 17:38:38 +02:00
Inaki Fernandez
2d5400ab48 fix(ai-models): mandate Pro models for grounding requests to avoid empty responses 2026-07-12 16:02:46 +02:00
Inaki Fernandez
6088772df8 fix(health-checker): prevent TypeError when last_checked is None 2026-07-12 13:44:26 +02:00
Inaki Fernandez
4bdd1202a1 fix: resolve ImportError by defining TOTAL_SHARDS in inventory_manager.py 2026-07-11 16:50:06 +02:00
Inaki Fernandez
138bc28e87 feat: link admonition headers to their respective primary sources in V2 2026-07-11 16:25:26 +02:00
Inaki Fernandez
b0e8fc222b feat: complete Pipeline Graph View integration in V2 and document Red Hat/CloudBees best practices 2026-07-11 16:16:10 +02:00
Inaki Fernandez
37cdf8a00b feat: inject CloudBees and Red Hat OpenShift Jenkins Pipeline best practices and warnings under V2 Pipeline Architecture section 2026-07-11 16:16:08 +02:00
Inaki Fernandez
25e90508b1 feat: inject Pipeline as Code core principles under V2 Pipeline Architecture section 2026-07-11 16:08:14 +02:00
Inaki Fernandez
7df7ced665 feat: deprecate Blue Ocean and replace with Pipeline Graph View in V1 and V2 2026-07-11 16:02:52 +02:00
Inaki Fernandez
f779ae2d57 feat: add official OpenShift Jenkins image and Helm deployment guide to V2 2026-07-11 15:45:09 +02:00
Inaki Fernandez
9b6c252422 feat: inject high-value V1 references across Jenkins V2 sections 2026-07-11 15:36:12 +02:00
Inaki Fernandez
772c935067 feat: enrich V2 jenkins page with high-density configuration tutorial and key V1 references 2026-07-11 15:23:16 +02:00
Inaki Fernandez
6711720d34 feat: inject high-value DSL solutions and slide/video embeds into V2 jenkins.md 2026-07-11 15:14:37 +02:00
Inaki Fernandez
487a21d195 chore: resolve empty slides, update Red Hat blog paths, rescue Rookout links, and fix spacing formatting 2026-07-11 14:39:32 +02:00
Inaki Fernandez
baf117fa61 fix(v2): add Awesome Lists to the Portal Guide quick-nav popover
The top horizontal bar is a custom quick-nav (docs/overrides/main.html), not
Material's tab bar (navigation.tabs is disabled). Its "Portal Guide" popover was
hardcoded with Topic Map/Methodology/Tags/About and did not include Awesome
Lists — so the earlier MkDocs nav change wasn't visible there.

- Add " Awesome Lists" to the Portal Guide popover (after Topic Map).
- Make the sidebar nav durable too: add the top-level " Awesome Lists" entry
  and the Portal Guide "Awesome Lists" child to _sync_enterprise_navigation, and
  exclude other-awesome-lists.md from its dimension via _FIXED_PAGES, so a full
  pipeline run no longer wipes these entries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 18:43:07 +02:00
Inaki Fernandez
6c36a493c7 feat(v2): add Awesome Lists hero card on index + Portal Guide nav entry
- New "Awesome Lists" hero-badge card on the V2 index, right after "Get
  Started", linking to /other-awesome-lists/.
- Custom gold-star + list-motif cover (docs/images/awesome-lists-cover.svg),
  matching the Awesome Lists page hero theme.
- New .hero-badge-card--gold modifier.
- Also list "Awesome Lists" under the Portal Guide top-bar menu (after Topic
  Map) for discoverability, in addition to the flagship " Awesome Lists" tab.
- Card added to the index template (survives regeneration) and to the current
  rendered v2-docs/index.md for immediate deploy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 18:25:19 +02:00
Inaki Fernandez
07e64cbda0 feat(v2): promote Awesome Lists to a flagship page with hero + category grid
The V2 "Awesome Lists" page (other-awesome-lists.md, derived from V1's
/v1/other-awesome-lists/) already existed but was buried under the
"Architectural Foundations" submenu. Promote it to a top-level, high-impact
destination:

- New src/awesome_page.py builds a hero banner + a category card grid derived
  from the page's own rendered H2 sections (stays in sync with AI re-clustering).
- v2_optimizer injects the header for other-awesome-lists.md during rendering,
  so it survives pipeline regeneration.
- Move it to a prominent top-level nav entry " Awesome Lists" (removed from the
  Architectural Foundations submenu).
- Add hero/grid/card styles to the V2 stylesheet.
- Apply the header to the current rendered page for immediate deploy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 18:00:53 +02:00
Inaki Fernandez
521918d553 fix(v2): persist About standardization quotes in render template
The agentic V2 pipeline re-renders v2-docs/about.md from the
v2_optimizer.py template, which had overwritten the manually-added
Kelsey Hightower / Red Hat / Automation Anxiety sections on the last
release. Move those sections into the template so they survive
regeneration, and re-apply them to the rendered about.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 17:31:35 +02:00
Nubenetes Bot
b35d0c55d7 feat(v2): denser Trending lanes with pure-CSS "Show more" disclosure
The Trending section felt sparse (6 + 4 cards). Make it much denser while
keeping the page manageable:

- Lane 1 "Trending Now": select up to 16 category-diverse fresh items.
- Lane 2 "Rising this Quarter": select up to 12 sustained-momentum items.
- Each lane shows the first N cards (9 / 6) and tucks the rest behind a
  pure-CSS, no-JS "Show N more" / "Show less" disclosure (checkbox-hack +
  general-sibling combinator), scoped per lane via a .trending-lane wrapper.
- New .trending-card--extra (hidden by default, fade-in on reveal) and
  .trending-showmore pill styles, with slate-theme variants.

The two lanes remain de-duplicated by URL (verified: 16 + 12 cards, zero
overlap) and lane 2 keeps its sustained signal (bpftrace, OpenTelemetry,
Gateway API, Vault, Argo CD, Ray, ...). Verified the toggle in a real
browser via Playwright: 9->16 cards on click, label flips correctly.

Generator + CSS change; the docs/ CSS edit auto-triggers the 04.1 publisher
to regenerate v2-docs on develop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:32:05 +02:00
Nubenetes Bot
9a0d2ce7d1 feat(v2): make "Rising this Quarter" a genuine sustained-momentum signal
The second Trending lane previously reused lane 1's scoring formula (just a
softer half-life over a wider window), so it surfaced the same fresh/high-impact
items as lane 1 — effectively lane 1's leftovers under a "Sustained Momentum"
label. Verified: both lanes showed items aged 2-6 days.

Changes:
- _select_lane now takes a score_fn so each lane drives off a different signal.
- _fresh_score (lane 1): unchanged 21d-half-life freshness bias.
- _sustained_score (lane 2): rewards proven staying power (presence in the
  12-month digest window) and de-prioritises <7d items (lane 1's job). Lane 2
  now surfaces matured pillars — Prometheus, Flux, bpftrace, Backstage — with
  zero overlap with lane 1.
- Suppress the 🆕 NEW pill in lane 2 (a "sustained" card flagged NEW is
  contradictory; freshness is lane 1's signal).
- Anchor "now" to digest _meta.last_updated instead of wall-clock, so identical
  digest input renders identical cards (no age/ordering churn on re-renders).
- Harden _select_lane against None/non-dict window entries (latent crash).

Generator-only change; CI publisher (04.1) regenerates v2-docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:14:43 +02:00
Nubenetes Bot
c2e5772323 feat(v2): add "Rising this Quarter" second lane to Trending
Extract lane selection/rendering into reusable helpers (_select_lane,
_render_cards) and add a second momentum lane below "Trending Now":

- "📈 Rising this Quarter — Sustained Momentum": 6-month digest window
  with a soft 60d half-life (vs 21d for lane 1), so it favours resources
  with sustained relevance rather than just the freshest items.
- De-duplicated against lane 1 by URL, so the two lanes surface different
  resources (verified: FinOps / NVIDIA device-plugin / Ruff / vLLM with
  real star counts, no overlap with the Trending lane).
- New .trending-section__title--secondary style (divider + lighter weight).

Generator-only change; CI publisher (04.1) regenerates v2-docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:55:25 +02:00
Nubenetes Bot
a9fe5dded5 feat(v2): momentum-weighted, category-diverse Trending Now
Rework the V2 'Trending Now' section so it reflects real momentum instead
of pinning evergreen/foundational tools:

- Hybrid ranking: impact_weight x recency_decay (21d half-life) so fresh
  items surface and the section rotates between releases (date was shown
  but never used to rank before).
- Diversity quota: at most one card per digest category, then backfill —
  replaces the old impact-only sort that filled all slots with the 2-3
  highest-volume categories.
- Real momentum signal: join each item with the inventory by URL and show
  the live GitHub star count (e.g. 38.2k★); fall back to the 1-5 Gemini
  score only when no gh_stars. Adds a 🆕 NEW pill for items <= 7 days old.
- Clean titles: strip github.com/owner/ paths and 'domain.tld:' prefixes
  (no more 'github.com: Istio' or raw repo slugs).
- Fix star-render bug ('🌟'*stars or 0 printed a literal 0 when stars=0).

Generator-only change; CI publisher (04.1) regenerates v2-docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:51:54 +02:00
Nubenetes Bot
154e6940c4 feat(v2): add Resource Density Heatmap to Topic Map page
Render a true colour-matrix heatmap on the Topic Map page (distinct from
the size-based Label cloud on index/Tags). One tile per category, grouped
by strategic dimension, with tile warmth (.th-1..6) encoding how many
AI-curated resources it holds. Log scale since counts span ~1..160.

The existing directory grid is preserved below a new "Full Category
Directory" heading. Generator-only change; the publisher regenerates
topic-map.md. CSS adds .topic-heatmap / .topic-heatcell with light + slate
palettes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:20:02 +02:00
Nubenetes Bot
12254d7495 revert: disable top nav tabs; group orientation pages under "Portal Guide"
The top tab bar forced Material to scope the left sidebar to the active
tab, which regressed the always-populated vertical nav. Revert
navigation.tabs (+ .sticky) so the left column behaves as before.

Apply the intended grouping in the (restored) left nav instead:
- New "Portal Guide" collapsible group: Topic Map, Methodology,
  Technical Tags, About.
- about.md is pulled out of its Architectural Foundations dimension
  (skipped in the generator's dimension loop) so it is not duplicated.
- Agentic Video Hub stays a prominent top-level group with its video
  subpages (no longer hidden in a tab-overflow "...more" menu).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 19:57:38 +02:00
Nubenetes Bot
5801b8f311 feat: add Label Heatmap to the V2 index, after the YouTube mosaic
Extract the tag aggregation and heatmap rendering into shared helpers
(_aggregate_tags / _render_tag_heatmap) so the index and the Technical
Tags page derive identical, slug-stable tag metadata. The index now ends
with the full Label Heatmap right after the mosaic, with each label
deep-linking across to its /tags/#slug section (verified: 75 anchors,
0 dangling). The Tags-page heatmap is unchanged (same-page anchors).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 19:34:18 +02:00
Nubenetes Bot
886f823c7f feat: group Topic Map nav + promote Videos + drop redundant video TOC
Navigation (v2_optimizer._sync_enterprise_navigation + v2-mkdocs.yml):
- "Topic Map" becomes a collapsible hub holding the three orientation
  pages — Topic Map (section index), Methodology, Technical Tags — since
  they are all about how the portal is structured.
- "Agentic Video Hub" is promoted above Intelligence Digest as a
  prominent top-level dropdown, keeping its category subpages.

Video subpages (v2_video_portal):
- Drop the in-page "## Table of Contents" block; it duplicated Material's
  native right-column "On this page" TOC (toc.follow), matching how the
  topic pages already omit it. The technology ordering list is retained
  internally to drive section render order.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 19:13:55 +02:00
Nubenetes Bot
eb9d58e13f feat: add Confluence-style label heatmap to Technical Tags page
Render a weighted "popular labels" cloud at the top of tags.md: every
label is listed alphabetically and sized/coloured by how many resources
carry it (log scale, 6 levels) so the most-used tags read biggest and
warmest. Each label anchors to its section below for jump-to-filter.

- v2_optimizer: emit .v2-tag-heatmap block in _generate_global_tag_index
- v2_elite.css: .v2-heat-1..6 size + warmth ramp (light + slate)
- bump CSS cache-buster to v2.9.39

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 19:07:12 +02:00
Nubenetes Bot
ce82aa07ec feat(v2/gen): add Kubernetes provider hub (sub-page index)
Audit of fragmentation found only two prefix clusters: aws (fixed in v2.9.34)
and kubernetes. Unlike AWS, kubernetes is well-classified — a rich parent (157
links) with substantial, distinct children (tools 144, networking 64, security
52, monitoring 24, storage 14, autoscaling 13, ...), not 1-3 link stubs. So
NOTHING is merged for kubernetes; this only adds a 'Deep-Dive Topic Pages' hub
to kubernetes.md indexing its 14 substantial sub-pages (Tools · Networking ·
Security · Monitoring · Storage · Autoscaling · Operators · Alternatives ·
Big Data · Tutorials · Backup & Migrations · Client Libraries · Local Dev ·
On-Premise) — purely additive navigation, no merging, no pruning.

Other small pages (pulumi, kustomize, registries, angular, ...) are legitimate
distinct topics, not fragments of a parent, so they are intentionally left
alone. Verified with --render-only; generator-only, CI republishes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 16:46:58 +02:00
Nubenetes Bot
c271c69b1f feat(v2/gen): de-fragment AWS pages — consolidate stubs + provider hub
The AWS landing page rendered with only ~3 links because AWS content was split
across ~20 granular pages (Azure/GCP use a single rich page each), and many AWS
sub-pages had just 1-5 links. Two generator changes fix this:

A. Provider hub: aws.md now renders a 'Deep-Dive Topic Pages' index linking to
   the substantial AWS sub-pages that remain (Serverless · Storage · Networking
   · Security · IaC · Backup · New Features), via a new self.subpage_hubs map.
   So the landing is a navigable index instead of a stub.

B. Stub consolidation: the near-empty / junk-drawer AWS sub-pages (<=7 links,
   plus 'miscellaneous') merge into aws.md via the existing merge_map mechanism
   (aws-miscellaneous, aws-databases, aws-devops, aws-containers, aws-monitoring,
   aws-architecture, aws-tools-scripts, aws-messaging, aws-data, aws-training,
   aws-pricing). Those slugs are also removed from self.dimensions so the full
   pipeline prunes the orphaned pages and auto-syncs the nav.

Verified locally with --render-only: aws.md goes from 3 to 44 links plus the
7-child hub block; V1 (docs/) is untouched by design — it stays the exhaustive
archive and is still read as the merge source. No regenerated v2-docs or
inventory committed (CI republishes per the generator→republish pattern).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 16:41:50 +02:00
Nubenetes Bot
40275974c0 feat(v2): collapsible nested left nav + 3 home section headings
Two fixes following the tabs removal:

1) Nav was a FLAT list of 18 section labels with no expand/indent, because
   navigation.sections rendered them as non-collapsible group labels and
   navigation.prune stripped inactive children. Disabled both → the left
   sidebar is now a proper COLLAPSIBLE, nested, indented tree (14 toggles,
   chevrons, collapsed by default). No size penalty (88213 vs 88516 bytes).

2) Home had a single H2, so its right-hand 'On this page' TOC was empty. Added
   '## Explore the Ecosystem' (badge cards) and '## Trending Now' (digest) to
   join the existing '## The Cloud Native Universe We Track' — the home's right
   TOC now lists three real sections.

Net effect: both side columns are now useful on every page, incl. the home —
left = full collapsible directory, right = per-page section map.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 14:33:27 +02:00
Nubenetes Bot
c377b4e4d9 feat(v2/seo): richer per-page descriptions from top resources + creation dates
- Enrich each page's meta description with its top-ranked resource names
  (long-tail keywords) instead of a pure template — e.g. 'Top Kubernetes
  resources for 2026, AI-ranked: Helm, kube-prometheus and more — curated Cloud
  Native tools, guides and references.' URL/path-like and emoji-laden titles are
  filtered out; pages whose top links are all URL-like fall back to the clean
  template. Capped at ~160 chars on a word boundary.
- Enable git-revision creation dates (enable_creation_date: true) so every page
  footer shows both 'Created' and 'Last update' — an age/freshness signal.

Verified locally: descriptions are clean, tool-named, 126-151 chars; the footer
renders both dates. Pages pick up the new front-matter on the next Publisher run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 13:39:44 +02:00
Nubenetes Bot
6fb3808850 feat(v2/seo): unique per-page meta descriptions + robots.txt
Every V2 page previously fell back to the identical global site_description
(duplicate meta descriptions = SEO penalty across ~140 pages). The generator now
emits a unique description: front-matter per page — derived from the page title
and its strategic dimension — which Material renders as <meta name=description>
and og:description. Topic Map and Methodology get tailored descriptions too.

Also add v2-docs/robots.txt (deployed at the site root) allowing full crawl and
referencing both the V2 (root) and V1 (/v1/) sitemaps.

Verified locally: each built page now carries a distinct meta description, and
robots.txt lands in the build output. The ~140 generated pages pick up their
front-matter on the next V2 Publisher run.

Note: the 12 redirect-stub pages (chef->ansible, react->javascript, ...) were
left as-is — they already 0s meta-refresh redirect with canonical pointing at
the target, which is better SEO than noindex (and the redirects plugin would
overwrite any front-matter anyway).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 13:21:57 +02:00
Nubenetes Bot
8e065c5406 feat(v2/tags): grouped, compact Technical Tags Index TOC + unique anchors
The Technical Tags Index TOC was a flat 80-entry numbered list that buried the
8 meaningful maturity tags under a long tail of one-resource 'X Content'
language tags, with colliding anchors (C / C# / C++ all -> #c-content) and a
'1 resources' grammar bug.

- Group the TOC: 'Maturity and Quality' as a clean numbered list; 'Technical
  Domains' and 'Language and Format' as compact, count-sorted inline pill rows.
- Precompute unique, explicit heading anchors ({#slug}) shared by the TOC and
  the section headers (c-sharp-content, c-plus-plus-content, dedup counter),
  fixing the collisions.
- Correct singular/plural ('1 resource').
- Filter non-language language values (En, Not Applicable, Multi-Language,
  Polyglot, ...) so they no longer create meaningless tag buckets.

Validated: 0 markdownlint errors on the regenerated tags.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 13:05:48 +02:00
Nubenetes Bot
01c514b07b fix(rss): derive feed lastBuildDate from item content dates, not _meta
Follow-up to v2.9.19: deriving lastBuildDate from _meta.last_updated only moved
the drift one level — that analysis timestamp is itself bumped on every publish
even when the ranked content is unchanged, so feed.xml kept differing between
develop and master. Use the freshest item's content date instead (the items only
change when the ranking actually changes). Verified: deterministic across reruns,
and the develop and master digests both yield 2026-06-18, so feed.xml is now
byte-identical across branches — the drift is fully eliminated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 12:46:52 +02:00
Nubenetes Bot
09d7a68ef8 fix(rss): derive feed lastBuildDate from content, not wall-clock now()
rss_generator set <lastBuildDate> to datetime.utcnow(), so every republish
rewrote it even when the digest was unchanged — leaving a 1-line develop<->master
drift in v2-docs/feed.xml (the residual after the PR Guardian drift fix). Derive
it from the digest's _meta.last_updated (the actual analysis date), falling back
to the most recent item date, so the feed is a pure function of its input:
regenerating unchanged content now yields byte-identical output. Verified
deterministic across repeated runs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 12:37:11 +02:00
Nubenetes Bot
15ffc91ec2 fix(ci): PR Guardian must not auto-format the generated v2-docs/ tree
The Guardian's auto_format_file ("&"->"and" in headings, URL trailing-slash
normalization) ran on every changed .md including the generated v2-docs/, then
committed the result back to the PR branch. Because PRs land on develop while
release branches merge to master via plain git merge (no Guardian run), develop
ended up with the normalized form and master with the generator's raw form —
a perpetual cosmetic develop<->master drift that spawned recurring no-op
'Release: Agentic V2 Portal Update' PRs (e.g. #399).

v2_optimizer.py is the single source of truth for v2-docs/ formatting, so the
Guardian now skips that tree in the auto-format loop and drops it from the
auto-commit 'git add'. Hand-authored docs/ and README/inventory are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 12:14:49 +02:00
Nubenetes Bot
ae0af172dc fix(v2): Topic Map dimensions must be h2 not h3 (MD001 lint failure)
The Topic Map page H1 is 'Topic Map', so dimension headings jumped h1->h3
and tripped markdownlint MD001/heading-increment, failing 07.2 Markdown
Linter on develop and master after v2.9.16. Emit dimensions as h2 in the
generator, the committed page, and update the CSS selector
(.topic-map-dim h2). Verified 0 errors with the CI markdownlint config.
Bumped v2_elite.css?v=2.9.17.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 12:03:02 +02:00
Nubenetes Bot
c41028e023 feat(v2): restructure home — Topic Map + Methodology pages, mosaic & a11y polish
Declutter the V2 landing page into a curated entry point and move the
full category directory and reference legends to dedicated pages.

Home (index):
- Move "Trending Now / Digest" above the signature YouTube mosaic (fix
  inverted altitude: fresh, dynamic content first).
- Replace the ~130-link "Strategic Dimensions" dump with a "Topic Map"
  badge card + a slim reference footer (Topic Map · Methodology · Videos).
- Frame the mosaic with a "The Cloud Native Universe We Track" heading.

New generated pages:
- topic-map.md — full category directory by dimension in a responsive
  multi-column CSS grid, with per-category resource counts.
- methodology.md — Maturity Taxonomy + Technical Impact legend tables
  (moved out of the home).

Mosaic (kept as brand signature, reinforced):
- Surface the per-group category labels that were hidden in title=.
- loading="lazy" on the ~150 channel logos (LCP/perf win).

about.md videos:
- youtube-nocookie.com + loading="lazy" + responsive aspect-ratio wrapper.

Config & cleanup:
- Disable navigation.expand (169-entry nav stayed fully open); the Topic
  Map page now serves as the full directory.
- Branded 404 page with clear ways back (Home / Topic Map / V1 Archive).
- Hoist repeated inline styles (hero badge row) into CSS classes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:52:21 +02:00
Nubenetes Bot
2e281e98ea feat(v2): category-first digest layout for a navigable right-hand TOC
The Tech & Cloud and Industry & Geo digest pages rendered period-first (three
time-window tabs, each nesting every category as bold text), so they had zero
real headings and an empty "On this page" TOC. Inverted _generate_digest_pages()
to category-first: each category is a real ## heading with the 3 time-windows as
content tabs inside it. The right TOC now lists all 22 tech categories / 4 geo
regions once each, headings sit at column 0 (no MD023 workaround), tabs preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 19:50:23 +02:00
Nubenetes Bot
19b7b44e20 feat(v2): restore in-page search/tag filter & drop redundant Markdown TOC
Fix: the per-page resource search box with maturity tag-pills stopped
appearing after navigation.instant was enabled (DOMContentLoaded fires only
on first SPA load). Reworked v2_filter.js to init via Material's document$
observable with a DOMContentLoaded fallback, guard double-injection, bind the
clickable-tag delegation once, and add a no-results state. Cache-bust ?v=2.9.12.

Change: removed the duplicated Markdown "## Table of Contents" from all 156 V2
content pages and from v2_optimizer.py — it forced hundreds of links of scroll
on large pages. Replaced by Material's native sticky "On this page" TOC
(removed toc.integrate, added toc.follow). tags.md keeps its TOC (it is an index).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 18:49:15 +02:00
Nubenetes Bot
48e8f71b6d fix: populate Industry & Geo Intelligence Digest (España→Spain rename)
_get_entry_geo() called entry.get("url","") before the url key was
injected into the dict, so TLD inference always received an empty
string and all 304 geo-eligible entries were silently dropped.

Fix: add url= parameter to _get_entry_geo and pass the dict key from
generate_digest. Also renames España→Spain in DIGEST_CATEGORIES,
GEO_CATEGORIES, TLD map, and v2_optimizer geo_cats list.

news_digest.json now includes Americas/Europe/Spain/Asia-Pacific data
(star-based fallback; Gemini will re-rank on next Monday CI run).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 16:24:18 +02:00
Nubenetes Bot
b470c4acdb fix: escape pipe chars in digest table link titles
Titles containing ' | ' (e.g. "Neo, Now in the Terminal | Pulumi Blog")
broke the Markdown table renderer because the unescaped pipe was parsed
as a column separator.

Root cause: v2_optimizer.py escaped pipes in the 'why' column but not
in the link title — one-line fix adds `.replace("|", r"\|")` to `t`.

Also corrects the 4 already-rendered broken entries in tech-digest.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 16:04:21 +02:00
Nubenetes Bot
1fe0509433 fix: deterministic inventory dump — last_checked as INTEGER
last_checked stored epoch seconds as REAL; SQLite's version-specific
REAL->text float printing rewrote ~every row on dump, so a locally
regenerated inventory.sql diverged from CI's. Normalize last_checked to
int on the entry before both the SQL record and the YAML dump, and make
the column INTEGER. All readers do coarse day-level staleness checks, so
sub-second precision is unused.

Verified: load->save idempotent for inventory.sql AND inventory.yaml, and
local (SQLite 3.40.1) output byte-identical to CI-equivalent python:3.11
(SQLite 3.46.1). The deterministic data regenerates on the next pipeline
save; committing only the code avoids conflicting with pipeline data churn.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:37:51 +02:00
Nubenetes Bot
e95cd9dc56 fix: stop YouTube mosaic from rendering the entire inventory (index outage)
load_inventory_channels() selected entries via 'youtube_mosaic' in entry
(key presence). save_inventory() always writes a youtube_mosaic column
that the SQL round-trip materializes as an empty dict {} on EVERY entry,
so the filter matched all 18,647 inventory entries and emitted ~18.6k
inline <img> links on a single line. That produced a 4MB v2-docs/index.md
(and 2.9MB docs/index.md), hanging both V1 and V2 index pages in the
browser. A prior revert masked it; the next SQL-backed sync re-broke it.

Fix: only treat an entry as a mosaic channel when youtube_mosaic is a
non-empty dict with a logo image (136 curated channels). Regenerated both
index files via reorganize_mosaic — docs/index.md is now byte-identical
to the last known-good state (52KB); v2-docs/index.md back to 41KB.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:24:00 +02:00
Nubenetes Bot
9d13a6a21a fix: store gh_pushed as None instead of 'N/A' at enrichment source
The date field gh_pushed was written as the literal string 'N/A' when
GitHub data was unavailable (fast_enrich, gemini_utils). That non-date
string then reached datetime.fromisoformat() downstream. Now writes None
(which all readers already handle); gh_license keeps its 'N/A' string
sentinel since it is a displayed value, not a date.

Also hardens the twin fromisoformat() call in agentic_curator's MVQ
penalty check (guards N/A/None and wraps parsing) so a bad value can't
crash a curation batch.

Adds scripts/normalize_gh_pushed.py to clean the 281 existing inventory
entries (run in CI to avoid SQLite float-serialization churn — see
script docstring).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:10:06 +02:00
Nubenetes Bot
4212b1f5ae fix: harden Platinum audit against null/N-A inventory fields
The V2 safety audit emitted hundreds of WARN lines and then aborted
entirely with 'NoneType object has no attribute lower':

- validate_mvq_compliance: gh_pushed of 'N/A' (and historic None/empty)
  was passed to datetime.fromisoformat() -> 'Invalid isoformat string';
  and gh_stars/stars stored as null hit 'None * int'. Now skips entries
  with no usable push date and coalesces None before the star math.
- validate_linguistic_tagging: a null 'language' field caused
  None.lower(), which aborted the whole report. Now coalesces to English.
- generate_audit_report: each mandate now runs in isolation so a single
  bad entry can no longer kill the entire audit; failures are logged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:03:33 +02:00
Nubenetes Bot
e773676a70 feat: incremental digest engine — reuse Gemini results when inventory unchanged
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>
2026-06-19 14:09:11 +02:00
Nubenetes Bot
1dd0dab308 fix: 3 critical publisher/deploy safety issues
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>
2026-06-19 13:29:10 +02:00
Nubenetes Bot
f4208bca4d fix: comprehensive None-stars guard across all v2_optimizer comparisons
_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>
2026-06-19 12:45:20 +02:00