Compare commits

...
12 Commits
Author SHA1 Message Date
Nubenetes Bot 7e85ec6bdd release: v2.6.5 — Fix MD023 linter errors in digest pages 2026-06-19 09:51:27 +02:00
Inaki dc0e090318 Merge pull request #356 from nubenetes/feat/fix-digest-linter
fix: MD023 lint — replace indented headings with bold in digest tabs
2026-06-19 09:51:08 +02:00
Nubenetes BotandClaude Sonnet 4.6 6f34ac8569 fix: replace indented ## headings with bold text in digest pages (MD023 lint fix)
- Change `    ## Category` to `    **Category**` inside MkDocs Material
  tabs to avoid MD023 linter errors (headings must start at col 0)
- Sanitize pipe characters in "why" text to prevent broken markdown tables
- Regenerated tech-digest.md (1328 lines, 3 tabs: 333/443/552 lines)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 09:50:53 +02:00
Nubenetes Bot 5d7f58c7fa merge: back-merge master v2.6.4 into develop 2026-06-19 09:45:22 +02:00
Nubenetes Bot 52e2560fa0 release: v2.6.4 — Fix digest periods differentiation 2026-06-19 09:45:18 +02:00
Inaki 41207ca0f0 Merge pull request #355 from nubenetes/feat/fix-digest-periods
fix: differentiate digest periods and fix NoneType stars
2026-06-19 09:44:59 +02:00
Nubenetes BotandClaude Sonnet 4.6 b5b3dc3ce2 fix: differentiate digest periods (10/15/20 items), fix year fallback, fix NoneType stars
- Variable items per period: 3 months=10, 6 months=15, 12 months=20
  so each tab shows progressively more content
- Use year field as fallback in _is_within_period when discovered_at
  doesn't discriminate (backfilled entries)
- Fix NoneType comparison in _fallback_items for entries with null stars
- Regenerated digest: 3m=220, 6m=330, 12m=440 items across 22 categories
- tech-digest.md now 1353 lines with differentiated tabs (339/449/559 lines)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 09:44:44 +02:00
Nubenetes Bot f221647646 merge: back-merge master v2.6.3 into develop 2026-06-19 09:33:18 +02:00
Nubenetes Bot 099a40d6b1 release: v2.6.3 — First Intelligence Digest with real content 2026-06-19 09:33:13 +02:00
Inaki 74cbc47e2e Merge pull request #354 from nubenetes/feat/generate-digest-content
feat: first Intelligence Digest with real content (22 categories)
2026-06-19 09:32:38 +02:00
Nubenetes BotandClaude Sonnet 4.6 f90d66478f feat: generate first Intelligence Digest with real content (22 categories, 660 items)
- Generate news_digest.json from inventory using star-based ranking
  (no Gemini tokens consumed — fallback mode)
- tech-digest.md: 1022 lines with 22 categories across 3/6/12 month tabs
- industry-digest.md: placeholder (geo_region data will populate after
  next curator run with updated Gemini prompts)
- Add gitignore exception for data/news_digest.json
- 220 items per time period across Kubernetes, AI, DevOps, Security,
  IaC, Observability, Cloud Providers, and more

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 09:32:23 +02:00
Nubenetes Bot d846c6f336 merge: back-merge master v2.6.2 into develop 2026-06-19 09:29:29 +02:00
6 changed files with 10416 additions and 25 deletions
+1
View File
@@ -351,6 +351,7 @@ MigrationBackup/
# Automatización Nubenetes
src/__pycache__/
*.json
!data/news_digest.json
.env
nubenetes_agent_env/
.venv/
File diff suppressed because it is too large Load Diff
+26 -17
View File
@@ -145,6 +145,12 @@ class NewsDigestEngine:
"12_months": 365,
}
ITEMS_PER_PERIOD: Dict[str, int] = {
"3_months": 10,
"6_months": 15,
"12_months": 20,
}
# ------------------------------------------------------------------ #
def __init__(self) -> None:
@@ -185,17 +191,20 @@ class NewsDigestEngine:
@staticmethod
def _is_within_period(entry: dict, cutoff_iso: str) -> bool:
"""Return *True* when the entry's ``discovered_at`` is on or after
the ISO-formatted *cutoff_iso* string. ISO 8601 strings sort
lexicographically so a simple ``>=`` comparison is sufficient.
"""
"""Check if entry falls within the time period using discovered_at,
with year field as fallback for backfilled entries."""
discovered = entry.get("discovered_at", "")
if not discovered:
return False
try:
return discovered >= cutoff_iso
except Exception:
return False
if discovered:
try:
if discovered >= cutoff_iso:
return True
except Exception:
pass
year = entry.get("year", "")
if year and isinstance(year, str) and year.isdigit():
cutoff_year = cutoff_iso[:4] if len(cutoff_iso) >= 4 else "2020"
return year >= cutoff_year
return False
# ------------------------------------------------------------------ #
# Prompt builder #
@@ -253,8 +262,8 @@ class NewsDigestEngine:
"url": e["url"],
"title": e.get("title", "Unknown"),
"date": e.get("discovered_at", "")[:10],
"stars": e.get("stars", 0),
"impact": "high" if e.get("stars", 0) >= 4 else "medium",
"stars": e.get("stars") or 0,
"impact": "high" if (e.get("stars") or 0) >= 4 else "medium",
"why": (e.get("ai_summary", "") or "")[:200],
"category": cat_name,
}
@@ -316,14 +325,14 @@ class NewsDigestEngine:
reverse=True,
)
max_items = self.ITEMS_PER_PERIOD.get(period_name, 10)
if len(entries) < 3:
# Too few entries include all without AI ranking
digest[period_name][cat_name] = self._fallback_items(
entries, cat_name
entries, cat_name, limit=max_items
)
continue
# Ask Gemini to rank
try:
prompt = self._build_ranking_prompt(
cat_name, entries, period_name
@@ -351,7 +360,7 @@ class NewsDigestEngine:
}
)
digest[period_name][cat_name] = ranked[:10]
digest[period_name][cat_name] = ranked[:max_items]
log_event(
f" [Digest] {period_name}/{cat_name}: "
f"{len(ranked)} items ranked"
@@ -364,7 +373,7 @@ class NewsDigestEngine:
"using star-based fallback"
)
digest[period_name][cat_name] = self._fallback_items(
entries, cat_name
entries, cat_name, limit=max_items
)
# Respect Gemini rate limits
+3 -2
View File
@@ -964,13 +964,14 @@ class V2VisionEngine:
items = period_data.get(cat, [])
if not items:
continue
md += f" ## {cat}\n\n"
md += f" **{cat}**\n\n"
md += " | Date | Resource | Impact | Why It Matters |\n"
md += " | :--- | :--- | :---: | :--- |\n"
for item in items:
impact_badge = {"critical": "🔴", "high": "🟡", "medium": "🔵"}.get(item.get("impact", "medium"), "🔵")
t = nuclear_strip(item.get("title", "Unknown"))
md += f' | {item.get("date", "")} | [{t}]({item.get("url", "#")}) | {impact_badge} {item.get("impact", "medium")} | {item.get("why", "")} |\n'
why = (item.get("why", "") or "").replace("|", "-").replace("\n", " ")
md += f' | {item.get("date", "")} | [{t}]({item.get("url", "#")}) | {impact_badge} {item.get("impact", "medium")} | {why} |\n'
md += "\n"
md += "\n"
return md
+8 -3
View File
@@ -3,7 +3,12 @@
!!! tip "Nubenetes Intelligence Digest"
AI-curated ranking of the most impactful resources, updated monthly.
!!! info "Coming Soon"
The Industry & Geo Digest will be populated automatically when the monthly pipeline runs with Gemini AI ranking. Check back after the next curation cycle.
=== "Last 3 Months"
=== "Last 6 Months"
=== "Last 12 Months"
**4 geographic categories** (Americas, Europe, Spain, Asia-Pacific) will surface industry-relevant resources classified by company and region.
+1328 -3
View File
File diff suppressed because it is too large Load Diff