/render-html: Markdown → single-file HTML for human reading
Markdown is for writers. HTML is for readers. ARIS workflow nodes write Markdown (canonical, audit-trail-friendly, machine-parseable).
/render-htmlturns selected artifacts into a polished single-file HTML view for the human who actually has to read them. The Markdown stays the source of truth.
When to use this skill
Use /render-html for ARIS artifacts that have a real human reader:
| Artifact | Why HTML helps | Template |
|---|---|---|
idea-stage/IDEA_REPORT.md | Ranked ideas + pilot signal + scores feel like a decision dashboard, not a flat list | academic |
review-stage/AUTO_REVIEW.md (+ REVIEW_STATE.json) | Round-by-round score progression + weakness status; pass --state to embed the JSON | academic |
paper/KILL_ARGUMENT.md (+ KILL_ARGUMENT.json) | Per-point attack/defense with <details> Q&A cards + red/yellow/green callouts | academic |
research-wiki/SUMMARY.md (or research-wiki/index.md) | Cross-entity cockpit: papers / ideas / experiments / claims at a glance | dashboard |
PAPER_PLAN.md (optional) | Claims-evidence matrix renders better as a polished table than raw MD | academic |
RESUBMIT_REPORT.{md,json} (optional) | 7-state failure-mode ledger | academic or dashboard |
Do NOT use for:
- LaTeX paper output — the final reader-facing artifact is PDF, not HTML.
SKILL.mdfiles — those are internal LLM-facing protocol..aris/traces/*review traces — forensic debug, not human display.- Every Markdown file in your project — only artifacts that benefit from sticky TOC, callouts, math, or score progressions.
Core invariants
- MD / JSON is canonical, HTML is generated view. Edit the source, then re-render. Do not hand-edit the HTML.
- Cross-model review at the artifact boundary (ARIS invariant). Academic-template HTML — used for the artifacts humans actually read (IDEA_REPORT, AUTO_REVIEW, KILL_ARGUMENT, PAPER_PLAN) — is reviewed by a fresh cross-family Codex thread before being claimed as a finished view. Dashboard-template HTML (cockpit / debug views) skips review by default but accepts
--reviewto force it. See § HTML Review Gate below. - Drift detection. Every rendered HTML embeds the source path, SHA256, and generation timestamp in
<meta>tags AND in the visible page header. If the HTML and source diverge, the meta tells you which version of the source produced it. - Single-file output. No build system, no separate CSS, no
node_modules. Just one.html. - CDN-friendly default,
--offlinefallback. MathJax 3 and highlight.js load fromcdn.jsdelivr.netby default. Pass--offlineto skip both — math will appear as raw$x$, code blocks won't get syntax highlighting, but everything stays readable. - Pure stdlib helper.
render_html.pyuses onlyre,html,hashlib,json,datetime,pathlib,argparse,sys. No pip install required. - Defense-in-depth XSS sanitization. The helper strips
<script>/<style>/<iframe>/<object>/<embed>/<form>/<input>/<button>/<link>/<meta>/<base>tags, allon*event-handler attributes (onclick,onload, …), and rewritesjavascript:/vbscript:/data:href/src/action schemes to#blocked-unsafe-url:. ARIS workflow artifacts should not contain these in the first place, but the sanitizer is the safety net in case an LLM hallucinates one. Markdown text content is HTML-escaped separately and never reaches the sanitizer.
Tool Location
Arch C self-contained: the canonical implementation lives at skills/render-html/scripts/render_html.py (this SKILL's own scripts/ subdirectory), together with its templates at skills/render-html/scripts/templates/{academic,dashboard}.html. The helper is new — no legacy tools/ shim exists.
Resolve $RENDER_HTML with the Codex hybrid chain (managed project install, in-repo checkout, ARIS repo fallback, then copied global Codex skill install). This is Policy A — skill-local gate:
RENDER_HTML=""
cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)" || exit 1
if [ -z "${ARIS_REPO:-}" ] && [ -f .aris/installed-skills-codex.txt ]; then
ARIS_REPO=$(awk -F'\t' '$1=="repo_root"{print $2; exit}' .aris/installed-skills-codex.txt 2>/dev/null) || true
fi
[ -f ".agents/skills/render-html/scripts/render_html.py" ] && RENDER_HTML=".agents/skills/render-html/scripts/render_html.py"
[ -z "$RENDER_HTML" ] && [ -f "skills/render-html/scripts/render_html.py" ] && RENDER_HTML="skills/render-html/scripts/render_html.py"
[ -z "$RENDER_HTML" ] && [ -n "${ARIS_REPO:-}" ] && [ -f "$ARIS_REPO/skills/render-html/scripts/render_html.py" ] && RENDER_HTML="$ARIS_REPO/skills/render-html/scripts/render_html.py"
[ -z "$RENDER_HTML" ] && [ -f ~/.codex/skills/render-html/scripts/render_html.py ] && RENDER_HTML="$HOME/.codex/skills/render-html/scripts/render_html.py"
[ -z "$RENDER_HTML" ] && {
echo "ERROR: render_html.py not resolved at .agents/skills/render-html/scripts/, skills/render-html/scripts/, \$ARIS_REPO/skills/render-html/scripts/, or ~/.codex/skills/render-html/scripts/." >&2
echo " /render-html cannot produce HTML output. Fix: rerun install_aris_codex.sh, export ARIS_REPO, or copy the render-html skill into ~/.codex/skills/." >&2
exit 1
}
Invocation
# Default: academic template, output to <input>.html alongside source
python3 "$RENDER_HTML" idea-stage/IDEA_REPORT.md
# Dashboard template for cockpit-style views
python3 "$RENDER_HTML" research-wiki/SUMMARY.md --template dashboard
# Custom output path + title + eyebrow
python3 "$RENDER_HTML" review-stage/AUTO_REVIEW.md \
--out review-stage/AUTO_REVIEW.html \
--title "Auto Review — overnight run" \
--eyebrow "Workflow 2"
# Embed sidecar state JSON (rendered as a folded <details> JSON block at end)
python3 "$RENDER_HTML" review-stage/AUTO_REVIEW.md \
--state review-stage/REVIEW_STATE.json
# Embed sidecar JSON (e.g., for KILL_ARGUMENT.md + KILL_ARGUMENT.json)
python3 "$RENDER_HTML" paper/KILL_ARGUMENT.md \
--json paper/KILL_ARGUMENT.json \
--title "Kill Argument — adversarial review"
# Offline (no CDN; math + code render as plain text)
python3 "$RENDER_HTML" idea-stage/IDEA_REPORT.md --offline
# JSON-only input (wrapped in a <pre><code class="language-json"> block)
python3 "$RENDER_HTML" review-stage/REVIEW_STATE.json --template dashboard
# Language attr (default zh-CN; set for English-primary artifacts)
python3 "$RENDER_HTML" docs/SKILLS_CATALOG.md --lang en
# Skip review (academic template otherwise reviews by default)
python3 "$RENDER_HTML" idea-stage/IDEA_REPORT.md
# … then the skill skips the spawn_agent review step if --no-review
# was on the command line. Pass --review to a dashboard render to force it.
The --review / --no-review flags are parsed by the SKILL orchestrator
(Claude Code), not by render_html.py. The helper itself stays pure
stdlib and never calls MCP. See § HTML Review Gate below for the
exact resolution and prompt.
Workflow
Step 1: Identify the artifact
From $ARGUMENTS, determine what to render. Common patterns:
- "render IDEA_REPORT" →
idea-stage/IDEA_REPORT.md, academic template - "make AUTO_REVIEW readable" →
review-stage/AUTO_REVIEW.md+--state review-stage/REVIEW_STATE.json - "show the kill argument as HTML" →
paper/KILL_ARGUMENT.md+--json paper/KILL_ARGUMENT.json - "research-wiki dashboard" → look for
research-wiki/SUMMARY.mdor generate from raw entity counts (Phase 2 work; for Phase 1 just renderSUMMARY.mdif present, else fall back to listing top-level wiki structure)
Step 2: Pick template
academic(default): linear long-form. Sticky TOC sidebar + serif body + callouts + tables + math + Q&A<details>. Use for IDEA_REPORT, AUTO_REVIEW, KILL_ARGUMENT, PAPER_PLAN.dashboard: grid layout, smaller font, denser metrics cards, no TOC sidebar. Use for resea