Dashboard Generator — SKILL.md

SkillMonitoring & ops

Generate monitoring dashboards for Grafana and DataDog with alert integration

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the Dashboard Generator skill

What this skill tells your AI

The instructions your AI receives, as published by a5c-ai/babysitter in library/specializations/software-architecture/skills/dashboard-generator/SKILL.md and read by ahel’s review.

Role: Step 8 — Generate the Mode C HTML dashboard from analysis-result.json. Triggered by: CLAUDE.md when output_mode = "C" after Step 7 (Analyst Agent completes analysis) Reads: run-local analysis-result.json, references/html-template.md, references/color-system.md Writes: output/reports/{ticker}_C_{lang}_{YYYY-MM-DD}.html References: html-template.md, color-system.md, docs/adr/0001-mode-c-rendering-strategy.ko.md


Instructions

Step 8.1 — Load Inputs

Load in this order:

  1. Read references/html-template.md — complete HTML skeleton with all 11 sections
  2. Read references/color-system.md — Tailwind CSS classes and Chart.js color configs
  3. Read run-local analysis-result.json — analysis output from Analyst Agent
  4. Verify all required sections are present in run-local analysis-result.json

Step 8.2 — Compute Data Confidence Indicator

From run-local analysis-result.json, count the data_quality_used grade distribution:

Grade A count: {N}
Grade B count: {N}
Grade C count: {N}
Grade D count: {N}

Overall:
- All critical metrics (price, revenue, net_income) Grade A → Overall A
- ≥6 of 10 key metrics Grade A or B → Overall B
- ≥4 of 10 key metrics Grade A, B, or C → Overall C
- Otherwise → Overall D (add warning banner)

Translate to Data Confidence Indicator text:

  • Grade A: Data Confidence: A — All key metrics independently verified
  • Grade B: Data Confidence: B — {N} of 10 key metrics cross-referenced
  • Grade C: Data Confidence: C — Limited source verification. Review with caution.
  • Grade D: Data Confidence: D — ⚠️ Insufficient verified data

Step 8.3 — Section-by-Section Population

Populate each section of html-template.md with data from analysis-result.json.

JSON field → HTML placeholder mapping:

analysis-result.json fieldHTML SectionPlaceholder
tickerSection 1{TICKER}
company_nameSection 1{COMPANY_NAME}
exchangeSection 1{EXCHANGE}
price_at_analysisSection 1, 3{CURRENT_PRICE}
price_day_changeSection 1{DAY_CHANGE}
price_day_change_pctSection 1{DAY_CHANGE_PCT}
data_modeSection 1badge class
analysis_dateSection 1{ANALYSIS_DATE}
key_metrics.market_capSection 3{MARKET_CAP}
key_metrics.pe_ratioSection 3{PE_RATIO}
key_metrics.ev_ebitdaSection 3{EV_EBITDA}
key_metrics.fcf_yieldSection 3{FCF_YIELD}
key_metrics.revenue_growth_yoySection 3{REV_GROWTH}
key_metrics.operating_marginSection 3{OP_MARGIN}
scenarios.bull.*Section 2bull card values
scenarios.base.*Section 2base card values
scenarios.bear.*Section 2bear card values
rr_scoreSection 2R/R badge
verdictSection 2verdict badge
sections.variant_view_q1Section 4Q1 text
sections.variant_view_q2Section 4Q2 text
sections.variant_view_q3Section 4Q3 text
sections.precision_risksSection 4risk table rows
sections.valuation_metricsSection 5valuation table
sections.sotpSection 5SOTP section
sections.dcf_analysisSection 5DCF subsection (after SOTP)
valuation_bridge (top-level)Section 5b{VALUATION_BRIDGE_SECTION} (4 anchors + weighted fair value + reconciliation paragraph)
sections.macro_contextSection 4/6Macro Environment section
sections.peer_comparisonSection 6peer table rows
output/runs/{run_id}/peers/*.json minimum collection_timestampSection 6{PEER_COLLECTED_AT_MIN}
output/runs/{run_id}/peers/*.json maximum collection_timestampSection 6{PEER_COLLECTED_AT_MAX}
sections.analyst_coverageSection 7analyst data
historical_pricesSection 8Chart 1 data array
income_statementsSection 8, 9Charts 2/3, quarterly table
sections.qoe_summarySection 9QoE section
sections.portfolio_strategySection 10strategy text
sections.what_would_make_me_wrongSection 10WWMMW list
upcoming_catalystsSection 10catalyst table

Step 8.4 — Chart.js Data Arrays

Convert structured data to Chart.js format:

Chart 1 — 12-Month Price History:

// From historical_prices array: [{date: "2025-03-12", close: 165.20}, ...]
const priceLabels = historical_prices.map(d => d.date);
const priceData = historical_prices.map(d => d.close);
// Apply color-system.md priceChart config

Chart 2 — Quarterly Revenue + Operating Income:

// From income_statements (last 8 quarters, oldest first)
const quarters = income_statements.slice(-8).map(q => q.period_label || q.period);
const revenueData = income_statements.slice(-8).map(q => q.revenue / 1000000); // in billions
const opIncomeData = income_statements.slice(-8).map(q => q.operating_income / 1000000);
// Apply color-system.md revenueBar and operatingIncomeBar configs

Chart 3 — Margin Trends:

// From income_statements (last 8 quarters)
const grossMarginData = income_statements.slice(-8).map(q =>
  q.gross_profit && q.revenue ? (q.gross_profit / q.revenue * 100).toFixed(1) : null
);
const opMarginData = income_statements.slice(-8).map(q =>
  q.operating_income && q.revenue ? (q.operating_income / q.revenue * 100).toFixed(1) : null
);
const netMarginData = income_statements.slice(-8).map(q =>
  q.net_income && q.revenue ? (q.net_income / q.revenue * 100).toFixed(1) : null
);
// Apply color-system.md grossMarginLine, operatingMarginLine, netMarginLine configs

If historical_prices unavailable (Standard Mode without price API): Replace Chart 1 canvas with a text table:

<div class="text-gray-400 text-sm italic p-4">
  Price chart data not available in Standard Mode. Use Enhanced Mode for historical price chart.
</div>

Step 8.5 — Apply Color System

From color-system.md:

R/R Score badge:

rr_score > 3.0 → class: "bg-emerald-900 text-emerald-300 border border-emerald-700"
rr_score 1.0–3.0 → class: "bg-yellow-900 text-yellow-300 border border-yellow-700"
rr_score < 1.0 → class: "bg-red-900 text-red-300 border border-red-700"

Price change colors:

day_change_pct > 0 → text-emerald-400, ▲
day_change_pct < 0 → text-red-400, ▼
day_change_pct = 0 → text-gray-400, —

Verdict badges:

Overweight / 비중확대 → bg-emerald-900 text-emerald-300
Underweight / 비중축소 → bg-red-900 text-red-300
Neutral / 중립 → bg-gray-700 text-gray-300
Watch / 관찰 → bg-blue-900 text-blue-300

Data confidence badge colors:

Grade A → bg-emerald-900 text-emerald-300
Grade B → bg-blue-900 text-blue-300
Grade C → bg-amber-900 text-amber-300
Grade D → bg-red-900 text-red-300

DCF Valuation Rendering (if sections.dcf_analysis exists)

Place AFTER the Valuation + SOTP section.

HTML structure:

  • Subsection heading: "DCF Valuation"
  • Base case highlight: large text showing "${fair_value} ({upside_pct}%)" with color (green/red based on sign)
  • Sensitivity table: HTML with WACC rows × terminal growth columns
    • Header row: terminal growth rates
    • Each cell: "${fair_value}" with color badge
    • Green: upside > 10%, Gray: -10% to +10%, Red: downside > 10%
  • Bull/Bear line: "Bull: ${X} (+Y%) | Bear: ${X} (-Y%)"
  • Methodology note: small text below showing WACC, terminal growth, forecast years
  • If dcf_analysis is absent or null: omit entire subsection

Valuation Bridge Rendering (if top-level valuation_bridge exists)

Place AFTER the DCF / Reverse DCF subsection and BEFORE the Peer Comparison section (Section 5b). The bridge reconciles 4 valuation anchors (DCF Base, Comp Multiples, Analyst Median Target, our Base Scenario) into a weighted fair value plus a ≥50-word reconciliation_logic paragraph.

Substitute the {VALUATION_BRIDGE_SECTION} placeholder in html-template.md with the full section markup shown in the Section 5b comment block when valuation_bridge is present in analysis-result.json. When the field is absent (older snapshots, or runs without all three input anchors), replace the placeholder with an empty string — do NOT render an empty stub.

Rendering rules:

  • 4 anchor cards in a md:grid-cols-4 grid; show value, weight × 100 as integer percentage, method, and source tag.
  • Implied view colour: text-red-600 if negative, text-green-600 if positive, text-gray-600 if ~0.
  • Pass reconciliation_logic through verbatim — do NOT truncate.
  • Display decision_anchor as a small footnote so the reader knows which anchor drives the verdict (typically scenarios.base).

Macro Context Rendering (if sections.macro_context exists)

Place BETWEEN Precision Risk and Peer Comparison sections.

HTML structure:

  • Section heading: "Macro Environment" with globe icon
  • If macro_context.structured.status == "available": render only the provided series[] values, with [Macro]/grade labels.
  • If macro_context.structured.status == "unavailable": show "Macro data unavailable" plus the reason, and do not render quantitative macro cards.
  • Narrative paragraph(s)
  • Factor cards (horizontally laid out, 2-3 cards):
    • Factor name (bold)
    • Impact line (normal text)
    • Confidence badge: High (green), Medium (amber), Low (gray)
  • If risk_slot_allocated is true: note with link to Precision Risk section
  • If macro_context is absent or null: omit entire section

Auto Delta Banner Rendering (Phase B — {DELTA_BANNER} placeholder)

The dashboard skeleton in references/html-template.md reserves a {DELTA_BANNER} placeholder at the top of <main>, above the Scenario Valuation section. This is the Mode C surface for Phase B Auto Delta Mode.

Substitution rules:

  1. If the orchestrator pipeline state holds auto_delta_payload.html (stdout of delta-comparator.py compare ... --format html), substitute that string verbatim.
  2. If no payload is available (no prior snapshot, --no-delta toggle, sanitization failure, or empty stdout), substitute the empty string. Do NOT render an empty stub, a fabricated banner, or the literal placeholder. Empty-string substitution leaves the surrounding space-y-8 layout intact because the banner is a peer of other <section> blocks.
  3. Never modify the Scenario Valuation, Hero, or Variant View sections to make room for the banner — the placeholder is positioned to keep the rest of the document untouched.
  4. The banner is a self-contained <section class="delta-banner ...">. Do not wrap it in another <section> or strip its outer element.

When pipeline_state.auto_delta == false (because --no-delta was passed), treat the placeholder substitution as the empty string and skip the delta-comparator call entirely.

Step 8.6 — Missing Data Handling

For any section where data is null or Grade D:

<!-- Instead of leaving empty or omitting: -->
<div class="text-gray-500 text-sm italic">[Data unavailable]</div>

Do NOT remove the section from the HTML. Do NOT substitute fabricated data. Always show the placeholder.

Sections with all-null data: collapse the section with a note:

<div class="bg-gray-800/50 border border-gray-700 rounded-lg p-4 text-gray-500 text-sm">
  Section data not available for this analysis. Data confidence insufficient.
</div>

Step 8.7 — Write HTML File

  1. Replace all placeholders with actual values
  2. Ensure Chart.js initialization code is complete with actual data arrays
  3. Verify HTML is well-formed (all tags closed)
  4. Write to: output/reports/{ticker}_C_{lang}_{YYYY-MM-DD}.html
  5. Report path to user

Do not use scripts/render-dashboard.py for final delivery or critic patch-loop rerenders. That script is eval-only. If a Mode C patch changes analysis-result.json, repopulate the full html-template.md manually/template-guided from the patched artifact and run the rendered output validator again before delivery.

Language suffixes: EN or KR Example: output/reports/AAPL_C_EN_2026-03-12.html


Multi-Ticker Mode B HTML Generation

When called for Mode B (comparison), use mode-b-template.md instead of html-template.md.

Path: output/reports/{T1}_{T2}_{T3}_B_{lang}_{YYYY-MM-DD}.html

Load each ticker's validated-data from the run-local artifact root, or from output/data/{ticker}/latest.json refs when explicitly reusing a fresh snapshot.


Completion Check

  • html-template.md loaded
  • color-system.md loaded
  • analysis-result.json loaded and all required fields present
  • Data Confidence Indicator computed
  • All 11 sections populated (or placeholder for missing)
  • Chart.js data arrays correctly formatted (labels array, datasets array)
  • R/R Score badge uses correct color class
  • Verdict badge uses correct color class
  • Missing data uses [Data unavailable] placeholder (NOT removed)
  • HTML written to correct path
  • File path reported to user

Signals

GitHub stars
2k
Forks
112
Last commit
Sep 2026
Advanced
Item type
skill
Key
dashboard-generator
Source
github.com/a5c-ai/babysitter