Dashboard Generator — SKILL.md
SkillMonitoring & opsGenerate monitoring dashboards for Grafana and DataDog with alert integration
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
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:
- Read
references/html-template.md— complete HTML skeleton with all 11 sections - Read
references/color-system.md— Tailwind CSS classes and Chart.js color configs - Read run-local
analysis-result.json— analysis output from Analyst Agent - 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 field | HTML Section | Placeholder |
|---|---|---|
ticker | Section 1 | {TICKER} |
company_name | Section 1 | {COMPANY_NAME} |
exchange | Section 1 | {EXCHANGE} |
price_at_analysis | Section 1, 3 | {CURRENT_PRICE} |
price_day_change | Section 1 | {DAY_CHANGE} |
price_day_change_pct | Section 1 | {DAY_CHANGE_PCT} |
data_mode | Section 1 | badge class |
analysis_date | Section 1 | {ANALYSIS_DATE} |
key_metrics.market_cap | Section 3 | {MARKET_CAP} |
key_metrics.pe_ratio | Section 3 | {PE_RATIO} |
key_metrics.ev_ebitda | Section 3 | {EV_EBITDA} |
key_metrics.fcf_yield | Section 3 | {FCF_YIELD} |
key_metrics.revenue_growth_yoy | Section 3 | {REV_GROWTH} |
key_metrics.operating_margin | Section 3 | {OP_MARGIN} |
scenarios.bull.* | Section 2 | bull card values |
scenarios.base.* | Section 2 | base card values |
scenarios.bear.* | Section 2 | bear card values |
rr_score | Section 2 | R/R badge |
verdict | Section 2 | verdict badge |
sections.variant_view_q1 | Section 4 | Q1 text |
sections.variant_view_q2 | Section 4 | Q2 text |
sections.variant_view_q3 | Section 4 | Q3 text |
sections.precision_risks | Section 4 | risk table rows |
sections.valuation_metrics | Section 5 | valuation table |
sections.sotp | Section 5 | SOTP section |
sections.dcf_analysis | Section 5 | DCF subsection (after SOTP) |
valuation_bridge (top-level) | Section 5b | {VALUATION_BRIDGE_SECTION} (4 anchors + weighted fair value + reconciliation paragraph) |
sections.macro_context | Section 4/6 | Macro Environment section |
sections.peer_comparison | Section 6 | peer table rows |
output/runs/{run_id}/peers/*.json minimum collection_timestamp | Section 6 | {PEER_COLLECTED_AT_MIN} |
output/runs/{run_id}/peers/*.json maximum collection_timestamp | Section 6 | {PEER_COLLECTED_AT_MAX} |
sections.analyst_coverage | Section 7 | analyst data |
historical_prices | Section 8 | Chart 1 data array |
income_statements | Section 8, 9 | Charts 2/3, quarterly table |
sections.qoe_summary | Section 9 | QoE section |
sections.portfolio_strategy | Section 10 | strategy text |
sections.what_would_make_me_wrong | Section 10 | WWMMW list |
upcoming_catalysts | Section 10 | catalyst 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-4grid; show value, weight × 100 as integer percentage, method, and source tag. - Implied view colour:
text-red-600if negative,text-green-600if positive,text-gray-600if ~0. - Pass
reconciliation_logicthrough verbatim — do NOT truncate. - Display
decision_anchoras a small footnote so the reader knows which anchor drives the verdict (typicallyscenarios.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 providedseries[]values, with[Macro]/grade labels. - If
macro_context.structured.status == "unavailable": show "Macro data unavailable" plus thereason, 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:
- If the orchestrator pipeline state holds
auto_delta_payload.html(stdout ofdelta-comparator.py compare ... --format html), substitute that string verbatim. - If no payload is available (no prior snapshot,
--no-deltatoggle, 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 surroundingspace-y-8layout intact because the banner is a peer of other<section>blocks. - 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.
- 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
- Replace all placeholders with actual values
- Ensure Chart.js initialization code is complete with actual data arrays
- Verify HTML is well-formed (all tags closed)
- Write to:
output/reports/{ticker}_C_{lang}_{YYYY-MM-DD}.html - 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.mdloaded -
color-system.mdloaded -
analysis-result.jsonloaded 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
More in Monitoring & ops
Skill · anthropics
More in Monitoring & opsagent-eval
Skill · affaan-m
More in Monitoring & opsdashboard-builder
Skill · affaan-m
More in Monitoring & opsbabysit
Skill · thedotmack
More in Monitoring & opseng-runbook
Skill · nexu-io
More in Monitoring & opsweekly-update
Skill · nexu-io
More in Monitoring & ops