Files
cc-ci-orchestrator/cc-ci-plan/plan-recipe-report-skill.md
autonomic-bot c7301a9e39 feat(recipe-report): /recipe-report skill + helper + launcher (default opus); wire into upgrade-all
- 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>
2026-06-02 23:02:22 +00:00

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.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 ".
  • ① 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 configurableREPORT_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)