feat(changelog): stronger release evidence and generated cover images - #77
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
/blade link BL-R7Y7TQ |
|
Got it — |
|
/blade review this pr |
|
Blade cannot work for you yet, an operator has to approve you first. |
|
/blade review this pr |
|
I've kicked off a reviewer for PR #77 ( One flag: the spawn came back with a warning that the reviewer role lacks |
There was a problem hiding this comment.
Reviewed the diff plus the full contents of the key files (not just the PR description): scripts/changelog/source.ts, scripts/generate-changelog-draft.ts, scripts/changelog/config.ts, scripts/changelog/cover.ts + imagegen/*, scripts/changelog/README.md, tests/changelog-v2.test.ts, scripts/changelog/state.json, and both changed workflow files. I don't have clone access in this environment, so I read/traced the code rather than executing bun test myself — the test file (tests/changelog-v2.test.ts) is substantial (~35 cases) and does exercise the claims below with mocked fetch, so 44 passing across the suite is plausible.
Claims checked against the code, not just the description:
- Submodule range expansion (
expandReleasedBrowserCommits+resolveSubmoduleRange/parseSubmodulePatchinsource.ts): correctly parses the gitlink patch for base/head SHAs, falls back to the contents API at parent/commit refs when no patch is available, and validates both are full 40-char SHAs that differ. Abehindcompare status (pure rollback) is skipped with a warning;divergedcorrectly throws instead of silently dropping evidence, per the documented recovery flow inscripts/changelog/README.md. Verified with tests covering ahead/behind/diverged. - Cutoff authority / quiet weeks:
resolveWindowanchorssincetostate.untilunless an explicit override is given (and rejects an override later than the stored cutoff), replacing the old git-log-derived/DEFAULT_LOOKBACK_DAYSbootstrap approach entirely.main()only callsupdateChangelogStateafter a draft is actually written — on "no commits", "no eligible groups", or "model returned nothing", it returns early without touching state, so the next run'ssincestill starts at the last published cutoff and the window grows cumulatively. This matches the "honest quiet weeks" claim. - Historical preview side-effect freedom: in
--previewmode,main()never callsupdateChangelogMeta/updateChangelogLlms/updateChangelogState/appendGithubOutput, never writes undercontent/docs/changelog/, and never generates a cover image — all preview writes go to a freshmkdtempworkspace (source-facts.json,excluded-groups.json,run.json, the draft +review.md). Nothing in the script shells out to git or touches GitHub write endpoints, so "can't push a branch or open a PR" is actually just "the script never tries to," which holds up. Also confirmed preview mode skips requesting an OpenAI key entirely when there are no eligible groups (a real quiet-week replay needs noOPENAI_API_KEY), matching the README. - Model/config:
DEFAULT_OPENAI_MODEL = 'gpt-5.6-sol',DEFAULT_OPENAI_REASONING_EFFORT = 'low', both overridable via env vars validated against an explicit allow-list (throws on invalid effort). Workflow wiresCHANGELOG_OPENAI_MODEL/CHANGELOG_OPENAI_REASONING_EFFORTthrough from repo vars. - Reviewer request:
changelog-draft.ymlnow passesreviewers: nibzard / fukoudatopeter-evans/create-pull-request, gated the same way as the rest of the PR-creation step.
Minor, non-blocking observations:
fetchRepositoryCommits(used for thedirect-mode repos: cookbook/leaderboard/cli/docs) still caps at 10 pages / 1000 commits and silently stops instead of erroring if a window has more activity than that — pre-existing behavior from before this PR, but the new cumulative "quiet week" window design makes long silent stretches (and therefore larger windows) more likely than before. Might be worth an explicit bound check like the one already used for the 3,000-file commit cap, so a truncated result fails loudly instead of quietly.- The
internal_only/routine_maintenanceclassifiers insource.ts(classifyGroup) rely on hardcoded keyword lists (jetstream,nats,puppet-master,fleet controller,nomad,gcp teardown, etc.) and path prefixes. That's consistent with the PR's own framing ("small repo-specific eligibility rules"), but it's inherently brittle to wording drift in future commit messages — worth a comment in the code calling out that this list needs periodic upkeep. - The cover-image pipeline (
scripts/changelog/cover.ts+scripts/changelog/imagegen/*, several new files/deps:sharp,pngjs,playwright) is a substantial, largely independent feature bundled into a PR titled "improve changelog source evidence." It's disclosed in the PR body and looks solid/tested, but reviewers should know this PR is doing much more than the title implies — worth calling out explicitly if it wasn't already discussed. - Hardcoding
nibzard/fukoudaas reviewers in the workflow YAML is a simple, reasonable choice, but has no fallback if either username becomes invalid (org departure, etc.);peter-evans/create-pull-requestwill likely just log an error on that field rather than fail the whole run, so low risk, but flagging for awareness.
None of the above block the change; I didn't find gaps between the narrative and the implementation, and the test coverage for the tricky parts (submodule range recovery, window/cutoff math, preview isolation, quiet-week classification) is genuinely there, not just claimed.
|
@nibzard Independent review is in (posted as a COMMENT review on the PR). Verdict: looks good — every headline claim checked against the actual code (not just the description):
No security, injection, or correctness issues found. Note: it couldn't run Four non-blocking items worth a look:
Not approved/merged — that's yours to do. |
|
Spawned a reviewer for #77 (not self-reviewed since it's the same author's PR). Reviewer read the full diff and source, confirmed all PR claims hold up, found no security/correctness issues, posted a COMMENT review, and flagged 4 minor non-blocking items. Relayed the verdict to @nibzard on the PR thread. |
- Tolerate a rolled-back or rewritten submodule pointer by skipping that host commit's expansion with a warning instead of failing the run; the application release comparison still fails loudly. - Bound the application release head with the explicit until timestamp so a manual window cannot include commits promoted after its cutoff. - Write excluded-groups.json to the preview workspace so exclusion decisions can be audited locally without exposing them publicly. - Document the audit path, failure recovery, and manual changelog publishing in the generator README.
Time of day was baked into the house style, so every cover rendered at blue hour whatever the motif asked for, and 'quiet infrastructure beauty' added towers and cranes to scenes that had none. The grade now comes from one of six time-of-day presets, picked at random per card and recorded in the sidecar JSON. The night preset is written brighter than a real night because the card lays a 20-40% black scrim over the background. Also spawn the CLI end-to-end tests synchronously. Asynchronous spawns deadlocked for 30s about half the time once the Chromium integration tests had launched browsers in the same runner process.
75288d4 to
b123bb5
Compare
|
/blade how would you improve or fix "The eligibility classifier's hardcoded internal-infra keyword list is brittle to wording drift." |
|
Looked at the actual classifier in if (/\b(jetstream|nats|puppet[- ]?master|fleet controller|nomad|gcp teardown)\b/.test(headlineText)) {
return 'internal_only';
}It's a one-off regex of internal tool/service proper nouns buried inline, next to a separate
This is advice, not a change I've made — say the word if you want it implemented and I'll delegate to a dev against the |
|
niko (console): yes hardcoding keywords is shit, can we do this structural signal over keyword text matching. simple is beautiful |
|
Kicked off a dev to implement this on PR #77's branch ( Heads up: the spawn came back with a warning that this session lacks the |
|
niko (console): A child you delegated (thread 5c0c7daa-6ee6-41ba-9c3c-6bb3fef91183) finished — status: failed; summary: Cannot proceed: this session lacks the |
|
As flagged before spawning: the dev confirmed it has no This needs an operator to add the |
|
niko (console): A child you delegated (thread 5c0c7daa-6ee6-41ba-9c3c-6bb3fef91183) ended its turn without calling close, so it has gone idle and will not continue on its own. Its box and its whole transcript are still intact. Its last message was: I already reported this above — to summarize for the record: this task can't proceed from my side because the Decide what follows. If that message shows the task is complete, close this thread — your close summary is the final message delivered to whoever is watching, so carry the concrete results and any PR or issue links into it. If work remains, resume it: |
|
No further action from that child will change the outcome — it hit the same wall twice, confirmed it's an operator-side grant issue, not something a retry or workaround fixes. Status stands: PR #77 is untouched, no code changed. This is blocked until an operator enables the |
The motif comes from a model reading untrusted commit text and lands in both an image prompt and the public PR body. It is now collapsed to a single line, so an embedded newline cannot break out of the PR body's bullet list, and capped at 400 characters.
What changed
Source evidence
steel-browsersubmodule range instead of treating the pointer update as the story.gpt-5.6-solwith low reasoning effort.nibzardandfukoudaon generated changelog PRs.Cover images
changelog-imagegentool intoscripts/changelog/imagegen/with its assets and all 71 of its tests, ported tobun test.coverMotifscene description alongside the changelog body.public/images/changelog/<n>.pngand point the draft frontmatter at it: agpt-image-2background, an ordered dither, the fixed Figma card layout, quantized to PNG-8.--time-of-dayor a free-form--color-grade, and recorded in the sidecar JSON.Why
The source repositories contain uneven commit messages, direct commits, sparse PR descriptions, and release promotion through a submodule. This change improves the evidence supplied to the changelog generator without requiring engineers to change how they work.
Cover images were made by hand for every previous changelog. Since the drafting model already holds the full picture of the week, it can propose the cover scene in the same call, at no extra model round trip.
Reviewing this PR
scripts/changelog/imagegen/**is vendored code. Every file has been diffed against the original tool with formatting normalized, and the only differences are one asset path (../assets/to./assets/), Biome reformatting, and the new time-of-day presets. Reviewer attention is better spent onscripts/changelog/cover.ts, thegenerate-changelog-draft.tschanges,scripts/changelog/prompt.md, and the two workflow files.Live comparison
The replay found nine released logical change groups and retained four. Every filtered group and the application
mainversusreleasegap was spot-checked; no additional shipped customer news was missed. The only plausible fifth item was the false-504/JetStream fix deliberately removed from #35.Impact
Starting with changelog #36, drafts should be based on stronger release evidence, omit routine/internal noise, and remain short when a week genuinely has little customer-facing news. Historical previews cannot update state, write a changelog, push a branch, or open a PR.
Each weekly run now also spends one
gpt-image-2image generation. Committed covers are 1420x800 PNG-8, roughly 200KB, against roughly 800KB for the hand-made covers they replace. CI and the changelog workflow install Playwright's Chromium, which adds about 30 seconds to each run.Validation
bun run check,bun run typecheck,bun run validate-links,bun run buildbun test— 137 passing, including the 71 ported imagegen testschangelog-036.mdxpointing at a 1420x800 PNG-8 cover, withmeta.json,llms.txt, andstate.jsonall updated correctly, and touched exactly the four paths the workflow commits.One dependency stays unverified until this runs in Actions: whether the
OPENAI_API_KEYsecret hasgpt-image-2access. If it does not, the cover step degrades to the placeholder and says so in the PR body, so the changelog still ships. Aworkflow_dispatchwithopen_pr: falsesettles it.