feat: improve V2 architecture with detailed logging and dynamic navigation

This commit is contained in:
Nubenetes Bot
2026-05-15 01:06:14 +02:00
parent c32192b3d8
commit e48d56a1d5
3 changed files with 69 additions and 3 deletions

View File

@@ -39,7 +39,7 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYTHONPATH: .
run: |
python src/v2_optimizer.py
python -u src/v2_optimizer.py
- name: Create Pull Request for V2 Elite Update
uses: peter-evans/create-pull-request@v6

View File

@@ -15,6 +15,7 @@ This file contains the accumulated instructions and long-term vision for the aut
9. **URL Expansion**: All shortened links (t.co, bit.ly, buff.ly, etc.) MUST be expanded to their original long version before being evaluated or injected. This ensures inventory homogeneity and improves global deduplication precision.
10. **Official Language (English Only)**: All injected content (titles, descriptions, headers), execution logs, and automated communications (PRs) MUST be exclusively in ENGLISH. Nubenetes is a global resource and linguistic consistency is critical.
11. **Workflow-Config Synchronization**: The GitHub Actions curation workflow form (`agentic_cron.yml`) MUST remain perfectly synchronized with the curation sources configuration file (`data/curation_sources.yaml`). Any addition, removal, or renaming of topics/categories in the configuration file requires a corresponding update to the workflow's input fields (checkboxes) to ensure users can toggle those sources manually. This maintains consistency between data-driven sources and the UI trigger.
12. **V2 Elite Maintenance**: The Nubenetes V2 (Agentic Elite) edition is a derived view of the V1 archive. It is managed via the `src/v2_optimizer.py` script and stored in the `v2-docs/` directory. AI agents MUST NOT modify `v2-docs/` directly via standard curation workflows; they must only use the `agentic_v2_builder.yml` workflow to perform the periodic "Elite Selection" process. Standard curation and cleaning workflows must always target the `docs/` directory as the primary source of truth.
## 🛠️ Structural Evolution & Navigation
@@ -31,6 +32,7 @@ This file contains the accumulated instructions and long-term vision for the aut
* **Semantic Polish**: When a section becomes excessively flat, the AI should propose and implement a reorganization into logical sub-sections purely to improve readability and classification, without restricting the volume of content.
* **Navigation Integrity**: Every structural change must be reflected in:
* `mkdocs.yml` (Navigation menu).
* `v2-mkdocs.yml` (V2 Navigation menu).
* `docs/index.md` (Main Table of Contents).
* The internal TOC of the modified page.
* **Orphan Curation**: Periodically audit the `docs/` folder to find unlinked files and integrate them into the navigation based on their topic.
@@ -51,3 +53,4 @@ The bot must rotate between profiles to avoid detection:
* **May 2026**: Generation of PRs with visual analytics (Mermaid) and Health Matrix.
* **May 2026**: Implementation of Backup-based Curation (JSON/MD) to avoid X.com blocks.
* **May 2026**: Implementation of multi-source curation and category-based filtering in GitHub Workflow.
* **May 2026**: Introduction of **Nubenetes V2 (Agentic Elite)** architecture. Implemented persistent `v2-docs/` storage, the `v2_optimizer.py` engine for 2026 standard filtering, and a dual-deployment pipeline to host both V1 (Exhaustive) and V2 (Elite) versions in parallel.

View File

@@ -84,18 +84,81 @@ class V2Optimizer:
async def run_full_optimization(self):
log_event("STARTING V2 AGENTIC OPTIMIZATION (THE ARCHITECT'S CUT)", section_break=True)
files = [f for f in os.listdir(V1_DIR) if f.endswith(".md") and f != "index.md"]
if not os.path.exists(V1_DIR):
log_event(f"[!] CRITICAL: Source directory {V1_DIR} not found.")
return
files = [f for f in os.listdir(V1_DIR) if f.endswith(".md") and f != "index.md"]
log_event(f"[*] Found {len(files)} files to process in {V1_DIR}")
if not files:
log_event("[!] No markdown files found to optimize.")
return
# Ensure output directory exists
os.makedirs(V2_DIR, exist_ok=True)
log_event(f"[*] Output directory verified: {V2_DIR}")
# Batch processing to avoid rate limits
for i in range(0, len(files), 5):
total_files = len(files)
for i in range(0, total_files, 5):
batch = files[i:i+5]
log_event(f">>> Processing batch {i//5 + 1} ({len(batch)} files)...")
await asyncio.gather(*[self.optimize_file(f) for f in batch])
await asyncio.sleep(2)
# Generate Landing Page
log_event("[*] Generating V2 landing page...")
await self._generate_v2_index()
# Sync Navigation
log_event("[*] Syncing V2 navigation from original mkdocs.yml...")
await self._sync_navigation()
log_event("V2 OPTIMIZATION FINISHED SUCCESSFULLY.", section_break=True)
async def _sync_navigation(self):
"""
Reads mkdocs.yml and generates a filtered nav for v2-mkdocs.yml
"""
try:
with open("mkdocs.yml", "r") as f:
v1_config = yaml.safe_load(f)
with open("v2-mkdocs.yml", "r") as f:
v2_config = yaml.safe_load(f)
v1_nav = v1_config.get("nav", [])
def filter_nav(nav_item):
if isinstance(nav_item, str):
return nav_item if os.path.exists(os.path.join(V2_DIR, nav_item)) else None
if isinstance(nav_item, dict):
new_item = {}
for key, value in nav_item.items():
if isinstance(value, list):
filtered_list = [filter_nav(i) for i in value]
filtered_list = [i for i in filtered_list if i is not None]
if filtered_list: new_item[key] = filtered_list
else:
if os.path.exists(os.path.join(V2_DIR, value)):
new_item[key] = value
return new_item if new_item else None
return None
v2_nav = [filter_nav(item) for item in v1_nav]
v2_nav = [item for item in v2_nav if item is not None]
v2_config["nav"] = v2_nav
with open("v2-mkdocs.yml", "w") as f:
yaml.dump(v2_config, f, sort_keys=False)
log_event(" [OK] v2-mkdocs.yml navigation updated.")
except Exception as e:
log_event(f" [!] Error syncing navigation: {e}")
async def _generate_v2_index(self):
v2_index = (
"# Welcome to Nubenetes V2\n\n"