#!/usr/bin/env python3 """HTML layout helpers for the Skill Atlas report.""" import html from typing import Any SCRIPT_INTERFACE = "internal-module" SCRIPT_INTERFACE_REASON = "Imported by build_skill_atlas.py to render the static Skill Atlas HTML report." def render_html(payload: dict[str, Any]) -> str: summary = payload["summary"] rows = [] for skill in payload["catalog"]["skills"][:80]: rows.append( "" f"{html.escape(skill['name'])}" f"{html.escape(skill['path'])}" f"{html.escape(skill.get('owner') or 'missing')}" f"{html.escape(skill.get('maturity') or 'unknown')}" f"{html.escape(skill.get('review_cadence') or 'missing')}" f"{html.escape(skill.get('atlas_scope') or 'release')}" "" ) blockers = ( payload["actionable_route_collisions"][:20] + payload["actionable_owner_review_gaps"][:20] + payload["actionable_stale_skills"][:20] + payload["actionable_drift_signals"][:20] ) blocker_items = "".join( f"
  • {html.escape(item.get('name', item.get('skill_a', 'issue')))} {html.escape(item.get('reason', item.get('status', ', '.join(item.get('missing', item.get('signal_types', []))))))}
  • " for item in blockers ) opportunity_items = "".join( ( "
  • " f"{html.escape(item.get('skill') or item.get('source_type', 'opportunity'))} " f"{html.escape(item.get('note') or item.get('recommendation') or item.get('signal', 'no-route opportunity'))}" f"
    {html.escape(item.get('source', ''))}" "
  • " ) for item in payload["no_route_opportunities"][:20] ) return f""" Skill Atlas

    Skill Atlas

    Portfolio-level review for route overlap, stale ownership, shared resources, telemetry drift, and no-route opportunities.

    Skills{summary['skill_count']}
    Actionable{summary['actionable_skill_count']}
    Route Collisions{summary['actionable_route_collision_count']}
    Owner Gaps{summary['actionable_owner_gap_count']}
    Stale Skills{summary['actionable_stale_count']}
    Drift Signals{summary['actionable_drift_signal_count']}
    No-Route Opportunities{summary['no_route_opportunity_count']}

    Actionable Issues

    No-Route Opportunities

    Missed-trigger telemetry and explicit failure cases become candidate routing work without storing raw prompts or outputs.

    Full Portfolio Counts

    All scanned skills remain visible: {summary['route_collision_count']} total route collisions, {summary['owner_gap_count']} total owner gaps, {summary['stale_count']} total stale signals, and {summary['drift_signal_count']} telemetry drift signals.

    Catalog

    {''.join(rows)}
    NamePathOwnerMaturityReviewScope
    """