diff --git a/GEMINI.md b/GEMINI.md index 5d73008f..c8ab194f 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -126,4 +126,5 @@ The bot must rotate between profiles to avoid detection: - **Automatic Detection**: The `agentic_v2_builder.yml` workflow now triggers automatically whenever `docs/` changes or after a curation run. - **Cost Efficiency**: Only NEW links from V1 are sent to Gemini. Existing links use cached AI evaluations but are locally "upgraded" with real-time GitHub metadata (stars/dates) and dynamic maturity tagging. - **Maturity Taxonomy**: Replaced generic labels with a professional 5-tier system (`[DE FACTO STANDARD]`, `[ENTERPRISE-STABLE]`, `[EMERGING]`, `[LEGACY]`, `[GUIDE]`) explained in the V2 Index. + - **Mandatory Descriptions**: Every resource in V2 MUST have a description. If the V1 source is missing one, the Optimizer uses Gemini to generate a professional 1-2 sentence summary and caches it. - **Manual Control**: The workflow supports a `force_reevaluate` flag for full architectural refreshes. diff --git a/README.md b/README.md index 20b12fc8..ebfcdedf 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,7 @@ To maintain the high-density quality of V2 without redundant AI costs, the `V2Vi 2. **Dynamic "Upgrading"**: Even for cached links, the engine performs real-time local updates: - **GitHub Metadata**: Fetches live star counts and last-commit dates via the GitHub API to ensure chronological accuracy. - **Maturity Tagging**: Applies a sophisticated 5-tier taxonomy (De Facto Standard, Enterprise Stable, Emerging, Legacy, Guide) based on live data. + - **Mandatory AI Descriptions**: Ensures 100% description coverage. If a link in V1 lacks a description, the engine automatically generates a professional summary using Gemini. 3. **Flat Routing**: Both versions use `use_directory_urls: false` to ensure relative asset paths (`images/`) remain stable across all sub-pages. ### Comparison Matrix diff --git a/src/v2_optimizer.py b/src/v2_optimizer.py index a003a32e..3fc59152 100644 --- a/src/v2_optimizer.py +++ b/src/v2_optimizer.py @@ -36,10 +36,14 @@ class V2VisionEngine: "PHASE 1: TECHNICAL PRESERVATION (HIGH INCLUSIVITY)\n" "- KEEP >90% of technical resources.\n" "PHASE 2: SOPHISTICATED SYNTHESIS & DATING\n" - "- Extract precise PUBLICATION YEAR: Look for dates in the URL (e.g., /2023/05/ post dates), Twitter/X post dates, or text context. Return 'N/A' if truly unknown, do NOT guess '2024'.\n" + "- Extract precise PUBLICATION YEAR: Look for dates in the URL, Twitter/X post dates, or text context. Return 'N/A' if truly unknown.\n" "- Assign QUALITY level (1-3 stars).\n" - "- Assign a MATURITY TAG based on content type/status: '[ENTERPRISE-STABLE]', '[EMERGING / INNOVATION]', '[ARCHITECTURE-GUIDE]', '[TOOLING]', '[CASE-STUDY]', or '[CHEATSHEET]'.\n" - " * Note: We will override tags for GitHub repos using real API data (Stars/Commits), so focus on classifying blogs and articles correctly.\n" + "- Assign a MATURITY TAG based on content type/status.\n" + "PHASE 3: MANDATORY DESCRIPTIONS (V1 PRIORITY)\n" + "- If 'Current Desc' is already provided and descriptive, DO NOT CHANGE IT.\n" + "- If 'Current Desc' is empty, too short, or non-descriptive, generate a professional 1-2 sentence summary.\n" + "- To generate the summary: Analyze the URL and title. If you recognize the technical resource, describe its core value proposition for a Cloud Architect in 2026.\n" + "- Style: Technical, neutral, and informative. Language: English only.\n" ) self.cache = self._load_cache() @@ -219,9 +223,14 @@ class V2VisionEngine: item = l.copy() if not force_eval and url in self.cache and "stars" in self.cache[url]: item.update(self.cache[url]) - else: + # If cache has a generated description and item is missing one, use it + if "ai_summary" in self.cache[url] and not item["description"]: + item["description"] = self.cache[url]["ai_summary"] + + # Re-evaluate if description is still missing even after cache check + if not item.get("description"): to_evaluate.append(item) - continue # process later via API + continue # Re-apply GitHub metadata and mature tagging for cached items if "github.com" in url: @@ -239,12 +248,12 @@ class V2VisionEngine: for i in range(0, len(to_evaluate), BATCH_SIZE): batch = to_evaluate[i:i+BATCH_SIZE] batch_num = i//BATCH_SIZE + 1 - log_event(f" [>] Processing Batch {batch_num} with AI...") + log_event(f" [>] Processing Batch {batch_num} with AI (Mandatory Descriptions)...") prompt = ( f"{self.library_criteria}\n" - "Respond ONLY with a JSON object: {\"results\": [{\"idx\": int, \"year\": \"YYYY\", \"stars\": int, \"is_video\": bool, \"tag\": \"[TAG]\"}, ...]}\n\n" - "LINKS:\n" + "\n".join([f"{idx}. {l['title']} ({l['url']})" for idx, l in enumerate(batch)]) + "Respond ONLY with a JSON object: {\"results\": [{\"idx\": int, \"year\": \"YYYY\", \"stars\": int, \"is_video\": bool, \"tag\": \"[TAG]\", \"summary\": \"1-2 sentences description\"}, ...]}\n\n" + "LINKS:\n" + "\n".join([f"{idx}. {l['title']} ({l['url']}) - Current Desc: {l['description'][:50]}" for idx, l in enumerate(batch)]) ) try: @@ -260,9 +269,12 @@ class V2VisionEngine: "year": str(res.get("year", "N/A")), "stars": min(max(int(res.get("stars", 1)), 1), 3), "is_video": res.get("is_video", False), - "tag": res.get("tag", "[ENTERPRISE-STABLE]") + "tag": res.get("tag", "[ENTERPRISE-STABLE]"), + "ai_summary": res.get("summary", "") } item.update(eval_data) + if not item["description"] and item["ai_summary"]: + item["description"] = item["ai_summary"] # GitHub overrides if "github.com" in item["url"]: