Repository navigation
Rework the weekly digest into one scannable message wired to the SLA sweep - #21952
Conversation
…sweep The digest was a model-written recital: 32 "ready to merge" PRs as a wall of bare numbers, a per-author in-flight tally, the same three oldest issues every week, and a 24h CI line that read HEALTHY while master deploys were failing. Now it's collect -> rank -> render: - digest.py runs sla-sweep.py --dry-run (the sweep's own no-mutation mode) and ships its verdicts, so "over review SLA by team" and "abandoned, closes in N days" render whether or not REVIEW_V3_SLA is on. It also collects week-over-week throughput, failed scheduled/master runs, and the lane switches (passed from repo vars, since GITHUB_TOKEN can't read them). - render.py renders everything deterministically, one PR per mention, blog/ marketing collapsed to one line. - rank.py is the only model call: it orders the top five "Needs a human" items. Any failure falls back to a fixed priority order. sla-sweep.py gains projected_close_days() and a closes_in_days field on author-time actions, so the digest's "closes in N days" comes from the evaluator, not a copy of its policy. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Gcx8uerksNXPswPTofF6ke
Sentinel — merge gate status (preview)Warning
|
| Gate | What it needs | |
|---|---|---|
| ✅ | G1 review-ran | Nothing to do: review current at dde18633b. |
| ✅ | G2 findings-answered | Nothing to do: every finding answered. |
| 🔴 | G3 right-approver | Needs approval from a member of any review team (pulumi/docs-blog-review, pulumi/docs-guild, pulumi/docs-marketing-review, pulumi/docs-tools) or a repository administrator — no qualifying human approval at this head (bot approvals never count). |
| ➖ | G4 infra-evidence | Doesn't apply to this PR: no changed path affects the deploy. |
| ➖ | G5 oversized-ack | Doesn't apply to this PR: not oversized. |
Break glass: a member of a routing team (.github/review-routing.yml teams:) can apply review:waived, which is logged.
Evaluated at head dde18633b.
|
Your site preview for commit dde1863 is ready! 🎉 http://www-testing-pulumi-docs-origin-pr-21952-dde18633.s3-website.us-west-2.amazonaws.com |
…ting by role Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Gcx8uerksNXPswPTofF6ke
…rs, trim review loop Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Gcx8uerksNXPswPTofF6ke
Reviewer's guide v5 — not for the authorTip Check the PR author: nothing here is yours. Your to-do list is the "Author action guide" comment. Approval needed from: @pulumi/docs-tools — any member's approval satisfies the merge gate. Note What this PR changes:
The blocking risk is a digest that silently misreports or fails to post, such as a broken workflow step or a mis-ranked SLA breach. The infra review, claim verification, and style lint all ran. Review confidence:
|
Author action guide v5 — nothing blocks mergeNote Nothing here needs an answer from you. A human reviewer still approves the merge. This PR reworks the weekly digest workflow into a single ranked Slack message fed by the SLA sweep; the review checked the workflow, scripts, prompts, and their tests. Full evidence: verification trail, investigation log, review history. Review v5 · updated 2026-09-28T23:11:12Z · head commit dde1863 Please don't edit or delete this comment; it's the review's record. |
|
Status: the review came back with zero findings ( Correction: an earlier version of this comment said Sentinel G1 was stale-red. That was my mistake. I'd read the 19:28Z check run, which ran before the review posted. The 19:35Z run is correct, so there's nothing to fix. Generated by Claude Code |
|
Independent adversarial review of head Checked and fine
Please fix before approval
Output polish (the sample meets the brief overall: one message, about 2.1k characters, phone-scannable):
Generated by Claude Code |
…ledger states
- merge-now / keep-or-kill candidates only when the sweep's verdicts arrived;
without them every approval-bound PR looked verdict-free.
- An abandoned PR with no close projection reads "closes at the next sweep",
never "closes in Noned".
- Flag a missing review ledger (the dry run then evaluates from empty state).
- rank.py catches everything; the workflow step also falls back to {}.
- An unknown sweep state never renders as "off"; say "sweep is off" once.
- Owners stay paired with their team; blog count excludes PRs listed
elsewhere; equal 7-day throughput windows; no "vs last week" without
deltas; no fallback footer when there's nothing to rank.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Gcx8uerksNXPswPTofF6ke
|
All fixed in
Polish:
Generated by Claude Code |
|
@claude #update-review
Each one has a new test in Generated by Claude Code |
|
Dispositions for the adversarial review of Heads-up for C&C: two sessions worked this review in parallel. The original author session wasn't stopped, and it pushed
Every new test fails on the code it guards against and passes at The PR body now has a dry-run render from live data at Generated by Claude Code |
|
@claude pushed 6b62478 addressing the adversarial review #update-review
Generated by Claude Code |
|
@claude #update-review
Generated by Claude Code |
|
I verified head Optional nits. Fix these if you're pushing anyway; none of them block.
Generated by Claude Code |
…links - Drop the dedicated blog/marketing line. Blog and marketing PRs are listed like any other: overdue ones under "Over review SLA" by team, and in the top-five pool. - "Ready to merge" is now the merge gate's own verdict. digest.py reads each non-draft PR's Sentinel check (preview "would be: success", or an enforcing "success"). Humans are listed as links, bots as a count. This replaces the old no-required-reviewer "merge-now" kind. - "Awaiting review": one GitHub search link per routed team (from review-routing.yml) for no-blockers PRs with that team's review still requested. Each count comes from the same query the link opens. - A Sentinel-green PR is listed once, as ready, even when the SLA sweep still calls it overdue. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Gcx8uerksNXPswPTofF6ke
|
@claude #update-review
A PR the Sentinel marks ready is listed once, as ready, even if the SLA sweep still has it overdue. Generated by Claude Code |
- Every capped list (SLA team rows, ready to merge, keep-or-close, untriaged issues, merged over findings, broken workflows) now sends its full version to a thread reply, and the cut reads "+N more in thread". Nothing cut, no reply. - "Needs a human" says "top 5 of N"; the thread continues it from 6 in the fixed priority order, each item with its reason. - post-to-slack.py --thread posts the reply under the first message (thread_ts from chat.postMessage, channel ID from the same response); a failed reply warns without failing the job. The dry run prints both. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Gcx8uerksNXPswPTofF6ke
|
@claude #update-review
Generated by Claude Code |
Proposed changes
Reworks the Monday #docs-ops digest so Cam can read it in under a minute and know what needs a human this week. It's now one Slack message at about 2.3k characters. Today's post was two messages totaling about 5.1k.
Pipeline: collect → rank → render → post
scripts/weekly-digest/digest.py(collect, deterministic):scripts/review-v3/sla-sweep.py --dry-run. That's the sweep's own no-mutation contract: no comments, labels, closes, Slack messages, or state writes. The digest ships the resulting verdicts, so "Over review SLA, by team" and "Abandoned" render whether or not the scheduled sweep is on.REVIEW_V3_SLAis untouched.streakthat separates broken from flaky;DIGEST_VARS), passed from repo variables becauseGITHUB_TOKENcan't read them. Each switch uses the same on/off semantics as its owning workflow (== '1'vs!= '0').scripts/weekly-digest/render.py(render, deterministic):digest.pyreads each non-draft PR's Sentinel check (preview "would be: success", or an enforcing "success"). Human PRs are listed as links; bot PRs are a count.review-routing.yml) forreview:no-blockersPRs with that team's review still requested. Each count comes from the same query the link opens. GitHub drops a team's request once any member reviews, so this means "requested, not yet reviewed".scripts/weekly-digest/rank.py+rank-prompt.md(the only model call): orders the top five "Needs a human" candidates and adds a 12-word "why" for each. Output is validated: unknown refs and duplicates are dropped. Any failure (no key, API error,max_tokens, bad JSON) falls back to a fixed priority order and says so in the message, so an API hiccup no longer costs the team the week's digest. Replacessynthesis-prompt.md..github/workflows/weekly-digest.yml:actions: readfor run history;DIGEST_VARS;dry_runstill previews without posting.sla-sweep.py, one minimal and tested change (called out per the lane rules): new pureprojected_close_days(config, idle_days, warn_age_days), pluscloses_in_days/undecided_countfields on author-time actions in the run record. That keeps "closes in N days" in the evaluator instead of copying its warn/close policy into the digest. Mutation paths and behavior are unchanged. Two new tests are intest_sla_sweep.py.Tests:
scripts/weekly-digest/test_digest.pyhas 31 tests: switch semantics, verdict shaping, run streaks and sorting, dedup, blog routing by role, batch compression, red-CI naming, ranking validation and fallback, mrkdwn escaping, the one-message size, and a regression test for each C&C review item. The suite is wired intoscripts/test-review-pipeline.sh, and thereview-pipeline-tests.ymlpath filter now includesscripts/weekly-digest/**.make test-review-pipelinepasses locally.After: rendered from today's real pulumi/docs data (Sep 28, head
6b62478)Collected live with
digest.pyat6b62478, dry run only (nothing posted to Slack). Caveats for this sample:ghand blocks GraphQL andsearch/*, so a scratch read-onlyghshim answered over repo-scoped REST, refusing any non-GET call. Throughput counts came from the repo's issues listing filtered locally instead of the search API. The shim isn't committed; CI uses realgh.rank-prompt.mdthrough a Sonnet subagent.REVIEW_V3_SLAunset,BLOG_REVIEW_COUNT=0). The "unknown" switches are this sandbox's gap; CI passes all seven.With the sweep on, the Abandoned rows read "closes in Nd" (or "closes at the next sweep"), and a
*SLA sweep, last 7d*: N escalations · N warned · N closed · N waivedline summarizes what the sweep actually did.A Sentinel-green PR is listed once, as ready, even when the SLA sweep still calls it overdue: the gate accepts an approval from any review team, while the sweep waits on the routed team.
Before: today's actual post (excerpt, about 5.1k characters across 2 messages)
Those 32 "ready to merge" PRs were really waiting on approval, and 22 of them were past SLA. The sweep's verdicts now group them by team with days waiting and an owner.
Quality loop
Three subagent reviewers read the rendered output each round, with different lenses: a busy maintainer skimming on a phone, a skeptic hunting filler and redundancy, and an on-call reader asking "what would I miss?"
What the rounds changed:
Follow-up: C&C adversarial review
All five fixes and the polish landed in
0251e0fd, each with a regression test.6b62478closes two gaps it left: with SLA verdicts unavailable, the footer no longer says "N in progress within SLA", andrank.py's never-fatal path now has its own test. The dispositions are in the PR thread.Related issues (optional)
None filed. Noticed along the way: Audit Logs - Update Events has failed every scheduled run this week (#21924).
https://claude.ai/code/session_01Gcx8uerksNXPswPTofF6ke
https://claude.ai/code/session_017Ea8K7TekJVG8KiLSXYf4d
🤖 Generated with Claude Code
Generated by Claude Code