Commit Graph
4 Commits
Author SHA1 Message Date
4grayandClaude Fable 5 1417632f73 fix(release): act on the second Codex pass
Four P2 findings, each with a regression test:

- The authored-body check could never fail. The tag workflow appends
  GitHub's generated notes to the authored text (FULL_BODY in
  build-and-make.yaml), so `release.body` is never empty and testing it for
  emptiness proved nothing. It now compares the body against the local
  CHANGELOG.md public section — the actual authored source — and reports an
  internal-only release as such instead of warning about it.
- A release with no highlights failed the documented card step, which
  necessarily included every internal-only release since validation forbids
  highlights there. Now the hero card is still rendered when public notes
  exist, an internal-only release writes nothing, and both exit 0.
- Card output is keyed by the exact version rather than the minor slug
  (0.24.0 and 0.24.1 share a blog post but not a card set), and a run first
  removes the cards a previous run wrote there, so a renamed or dropped
  highlight cannot leave a stale image waiting to be published. Only files
  matching what this tool writes are removed.
- Telegram could still truncate breaking changes into the counter when a
  release had no highlights, since the fitting loop trims the tail. Dropping
  a breaking entry now fails with an actionable error.

Docs: docs/architecture/release-pipeline.md, .changes/README.md, CLAUDE.md
and AGENTS.md updated for the new output path and the no-highlight and
internal-only behavior.

180 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 09:51:29 +02:00
4grayandClaude Fable 5 9bd1fa54b0 fix(release): correct highlight parsing, card layout and gate reliability
Seven defects found by an adversarial pass over the new tooling, each with
a regression test:

- `highlight:` was silently truncated at the first ` #`. The comment strip
  was written when every field was a slug, enum or number; it now applies
  only to those closed-vocabulary keys. `highlight: Sources #N chip` kept
  parsing as "Sources" and shipped that to all four surfaces.
- Quote stripping removed a leading or trailing quote independently, so
  `highlight: "Up Next" rail` lost its opening quote. Both ends must now
  carry the same quote character.
- A whitespace-only quoted value passed validation and then crashed the
  card generator mid-run, after PNGs were already written. Values are
  trimmed after unquoting, so it fails validation instead; the hero card
  also no longer indexes wrapText's empty result blindly.
- Feature cards painted the opaque screenshot frame over the last body
  line whenever the headline wrapped to two lines. The body's line budget
  is now derived from the space actually left above the frame.
- Un-highlighted breaking changes were folded into "…plus N more fixes and
  improvements" on Telegram and never shown. They are always spelled out.
- Both CLI guards compared a non-realpath'd argv[1] against a realpath'd
  import.meta.url, so reaching either script through a symlinked path (on
  macOS, anything under /tmp or /var) made it a silent exit-0 no-op — which
  for the publication gate reads exactly like a pass.
- spawnSync reports a missing gh binary and a signalled child as
  `status: null`, both of which were blamed on the build.

The highlight cap drops from 80 to 60 characters: 60 is the hero card's
single-line budget, so a valid highlight now always renders in full rather
than being silently ellipsized.

Docs: new docs/architecture/release-pipeline.md carries the full contract —
surfaces, the ordering constraint around --consume, highlight semantics,
card layout rules, and the 27-asset draft verification table. release-cut
now references it instead of restating the asset list (474/500 words), and
CLAUDE.md, AGENTS.md and .changes/README.md point at it; the README's
release sequence no longer omits the announcement and card steps.

172 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 09:17:18 +02:00
4grayandClaude Fable 5 4b30e0613a fix(release): address review findings on the release tooling
CodeQL: the pacman rule built a regex from the interpolated version and
escaped only dots. It now compares plain strings, so the exported
requiredAssetRules() carries no escaping trap; only the literal compression
suffix stays a regex.

verify-draft-release:
- Never exits 0 once the release is published. The asset report still
  prints (auditing after the fact is useful), but a pre-publication gate
  must not report success for a boundary already crossed.
- Polls for the tag run before concluding it does not exist: `gh run list`
  reports what is indexed right now, and a run pushed seconds ago routinely
  is not. Adds injectable progress/sleep io, so runVerification is async.
- The live sleep timer is deliberately not unref'd — a pending promise does
  not hold the event loop open, and an empty loop exits 0, which would turn
  a mid-poll exit into a silent false success.
- `--repo` is shape-checked so a typo fails with the usage line.

Announcements: an internal-only release now returns null instead of
throwing a misleading "even a single entry exceeds the limit" error. The
CLI explains it on stderr, leaves stdout empty and exits 0 — the shape
extract-changelog-section.mjs --public already uses for the same case.

Highlight cards: card filenames derive from the note filename, never the
screenshot slug. Two highlights may legitimately share one manifest shot,
which previously made the second card overwrite the first.

Tests: the CLI harness moved to spawnSync — execFileSync discards stderr on
success, hiding exactly the messages these paths emit. Adds regressions for
each finding above (165 passing).

Docs: CLAUDE.md and AGENTS.md release sections (mirrored, verified
identical) now document the highlight field, the announcement/card
commands, and the draft verifier; .changes/README.md records the
internal-only announcement behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 08:57:00 +02:00
4grayandClaude Fable 5 dcd28c1334 feat(release): announcement formats, highlight cards, and draft verification
Extends the release tooling around the .changes notes pipeline:

- New optional `highlight:` frontmatter field marks a release's headline
  changes (max 80 chars, rejected on `type: internal`).
- `--format telegram` renders a paste-ready plain-text post guaranteed to
  fit the 4096-character limit (highlights lead, the rest collapses into a
  counter); `--format reddit` renders markdown with a suggested title line,
  a Highlights section, and a collapsed change list. Both are stdout dry
  runs and must run before `--consume`.
- The blog scaffold uses the highlight as a ready section heading instead
  of a TODO, and highlight notes without screenshots get their own section.
- `release:verify:draft` waits for the v* tag build via `gh run watch`,
  then checks draft status, the authored body, and the complete 27-asset
  set (verified against a real full matrix build). Read-only; publishing
  stays manual.
- `release:cards:generate` renders branded 1200x630 highlight cards (with
  a framed mock-server screenshot strip when the note names one, purely
  typographic otherwise) plus a release hero card into dist/, matching the
  website palette. Copying into the website tree stays a manual act.

Docs: .changes/README.md, release-notes and release-cut skills (both
copies byte-identical). No release note: release tooling only, no runtime
behavior change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 00:28:44 +02:00