- recipe-report.py: survey (run + per-recipe PRs + CI verdicts) / render (spec->HTML) / publish (copy to cc-ci:/var/lib/cc-ci-reports + regen index). - skill .claude/skills/recipe-report: review the weekly run, classify needs-attention vs routine, publish one public HTML page per week + index at report.ci.commoninternet.net. Read-only. - launch-report.py: one-shot cc-ci-report agent, REPORT_MODEL default opus (separate from the sonnet upgrader), REPORT_BACKEND default claude. - upgrade-all SKILL: closing step launches the report agent. Serving (nix/modules/reports.nix) already deployed + live. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.3 KiB
Plan — /recipe-report skill + report.ci.commoninternet.net
Status: IMPLEMENTED 2026-06-02 — serving live at https://report.ci.commoninternet.net; skill
recipe-report + helper cc-ci-plan/recipe-report.py + launcher cc-ci-plan/launch-report.py
(REPORT_MODEL default opus); upgrade-all launches the report as its closing step. Created: 2026-06-02.
Goal: after the weekly /upgrade-all, generate a public HTML "Recipe Report" that reviews how
the upgrade went and the state of every recipe + open PR — served at report.ci.commoninternet.net,
one page per week, with a home-page index of all reports.
Why it's cheap to build
The serving model already exists (dashboard): a Nix-built image → Swarm service → traefik
Host(...) + wildcard TLS, bind-mounting a host dir read-only. We mirror it for reports.
- DNS:
report.ci.commoninternet.netalready resolves (wildcard*.ci.commoninternet.net→ the host) — no operator DNS step. - TLS: the same wildcard cert (
/var/lib/ci-certs/live/) that serves ci./drone./backups. coversreport.ci.*— no cert step (confirm at deploy). - Data:
/upgrade-allalready writes/srv/cc-ci/.cc-ci-logs/upgrades/upgrade-all-<date>.md; open PRs + CI verdicts come from the Gitea/Drone APIs (creds in.testenv).
A. Serving infra — new nix/modules/reports.nix (cc-ci product repo)
A tiny static-file server mirroring dashboard.nix:
- Image:
nginx:alpine(or reuse the dashboard's Pythonhttp.server), content-hash tag, deployed by adeploy-reports.servicereconcile oneshot (same pattern as dashboard/bridge). - Bind-mount
/var/lib/cc-ci-reports(read-only) as the web root. - traefik labels:
Host(report.ci.commoninternet.net), entrypointweb-secure,tls=true. - Web root layout:
index.html+week-<YYYY-MM-DD>.html(one per report). Public, unauthenticated. - (Lighter alternative: add a second traefik router
Host(report.ci…)→ the existingccci-dashboardservice and serve/var/lib/cc-ci-reportsfromdashboard.py. Recommend the separate server for clean decoupling.)
B. The skill — .claude/skills/recipe-report/ (orchestrator repo)
A SKILL.md (LLM-driven review + HTML generation) + a helper script for the deterministic survey/scaffold.
- Runs as its OWN agent session — model independent of the upgrader. The report must use a model
configured separately from the upgrader, so it canNOT be a step inside the sonnet upgrader session.
A new
launch-report.py(mirroringlaunch-upgrader.py) starts acc-ci-reportsession onREPORT_MODEL(defaultopus) /REPORT_BACKEND(defaultclaude) — independent of the upgrader'ssonnet. Initial config: upgrader = sonnet, report = opus. It's launched right after the weekly/upgrade-allcompletes (the weekly job launches the report agent as its final step / a follow-on). It reads the dated summary + PR/CI state from disk + the APIs, so it needs none of the upgrader's in-context state. - Inputs: the dated
upgrade-all-<date>.mdsummary; open PRs per recipe (Gitea API); each recipe's current vs latest version + CI verdict (Drone); the previous week's report (to note "new since last week"). Runs from the orchestrator; writes the HTML tocc-ci:/var/lib/cc-ci-reportsover ssh. - Review/judgment (the skill's job): summarize the run (green / stale-test / failed / skipped counts,
notable regressions), then classify every item into:
- Needs attention — PRs ready to merge (GREEN), and errors/failures to investigate.
- Routine — minor bumps, stale-test (needs
--with-tests), up-to-date / skipped-by-design.
C. HTML output (per-week page + index)
Each week-<date>.html:
- Title: "The Recipe Report" · Subtitle: "Week of ".
- ① Needs attention (top, prominent): important PRs to merge + errors to look into — short prose per item with the PR/build link.
- ② Routine (below): the less-important items (minor upgrades, stale-test, skipped) — compact.
- ③ Comprehensive table (bottom): every recipe →
current → target· upgrade status · CI verdict · open PR (link) · notes. - CI results: LINK only, no embedded images. For each run, show its level/result as a number / short
info string (e.g.
level 8 ✓orRED · restore) and hyperlink to the Drone build + dashboard summary — do not embed the summary-card images. - Footer: generated timestamp, link to the live dashboard (ci.commoninternet.net), link back to the index.
index.html (home): "The Recipe Report" + a reverse-chronological list of all weekly reports (date +
one-line headline), each linking to its page. The skill regenerates the index each run.
Styling: self-contained, inline CSS, clean + mobile-friendly, no JS (fully static).
D. Public-safety (unauthenticated page)
- Include only public-safe data: recipe names, version bumps, PR titles + links, CI verdicts, concise error summaries. No secrets, tokens, internal IPs, or raw logs (summarize — never dump logs that could contain generated app secrets; the build already redacts, but the report must not re-introduce).
- PR links point to the private
git.autonomic.zonemirror — viewers need access to follow them; the report's prose must stand on its own.
E. Definition of Done
reports.nixdeployed;https://report.ci.commoninternet.net/serves the index over TLS./recipe-reportskill generatesweek-<date>.html(3 sections + full table) and regeneratesindex.html.- Wired to run automatically after the weekly
/upgrade-all; produces a report end-to-end on the next run. - Page is public-safe (no secrets); renders cleanly on desktop + mobile.
- NOT merged anything; the report only reports (read-only on PRs/CI).
F. Decisions
- Report model is separately configurable —
REPORT_MODEL(defaultopus), independent of the upgrader (sonnet). The report runs as its owncc-ci-reportagent (per §B). ✓ (operator-set) - CI results: link only, with the level/result shown as a number/info string — no embedded images. ✓ (operator-set)
- Static server:
nginx:alpinenew stack (recommended) vs extend the dashboard. (open) - Retention: keep all weekly reports indefinitely (tiny static HTML) — assumed yes. (open)