- 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>
88 lines
6.3 KiB
Markdown
88 lines
6.3 KiB
Markdown
# 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.net` already 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. covers
|
|
`report.ci.*` — **no cert step** (confirm at deploy).
|
|
- **Data:** `/upgrade-all` already 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 Python `http.server`), content-hash tag, deployed by a
|
|
`deploy-reports.service` reconcile 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`)`, entrypoint `web-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 existing `ccci-dashboard`
|
|
service and serve `/var/lib/cc-ci-reports` from `dashboard.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` (mirroring `launch-upgrader.py`) starts a `cc-ci-report` session on
|
|
**`REPORT_MODEL` (default `opus`)** / `REPORT_BACKEND` (default `claude`) — independent of the
|
|
upgrader's `sonnet`. **Initial config: upgrader = sonnet, report = opus.** It's launched right after the
|
|
weekly `/upgrade-all` completes (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>.md` summary; 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 to `cc-ci:/var/lib/cc-ci-reports` over 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 <date the report was run>".
|
|
- **① 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 ✓` or `RED · 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.zone` mirror — viewers need access to follow them; the
|
|
report's prose must stand on its own.
|
|
|
|
## E. Definition of Done
|
|
1. `reports.nix` deployed; `https://report.ci.commoninternet.net/` serves the index over TLS.
|
|
2. `/recipe-report` skill generates `week-<date>.html` (3 sections + full table) and regenerates `index.html`.
|
|
3. Wired to run automatically after the weekly `/upgrade-all`; produces a report end-to-end on the next run.
|
|
4. Page is public-safe (no secrets); renders cleanly on desktop + mobile.
|
|
5. NOT merged anything; the report only *reports* (read-only on PRs/CI).
|
|
|
|
## F. Decisions
|
|
- **Report model is separately configurable** — `REPORT_MODEL` (default **`opus`**), independent of the
|
|
upgrader (`sonnet`). The report runs as its own `cc-ci-report` agent (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:alpine` new stack (recommended) vs extend the dashboard. *(open)*
|
|
- Retention: keep all weekly reports indefinitely (tiny static HTML) — assumed yes. *(open)*
|