Skip to content

docs(blog): lay PR blog drafts out for readers, result first - #1286

Merged
gHashTag merged 1 commit into
mainfrom
docs/blog-template-reader-first
Oct 3, 2026
Merged

gHashTag merged 1 commit into
mainfrom
docs/blog-template-reader-first

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 3, 2026

Copy link
Copy Markdown
Owner

Summary

PR blog drafts used to open with a provenance disclaimer and a list of file paths. They now open with the result, the way readers actually read a technical post. The blog-post skill also gains a short, sourced writing guide.

Before: disclaimer → "Work report" → file list → "Context and reasoning" → [status] Command: … Result: … Evidence: … bullets → limits.

After: result → one-line check count (Open PR. Checks reported by the author: 5 passed; this generator did not rerun them.) → The problem → How it works → See it run (optional) → What changed → How we checked (a table) → Try it yourself (optional) → What this does not show → How this post was made.

Changes

  • scripts/pr_blog_report.py
    • make_post() follows the new order. Checks are a table block (Check / Status / Result / Evidence), and failed and not_run checks are shown next to passed ones. The provenance notice is now the last section.
    • blog.cast is optional and must match term/<id>/session.cast. It adds a "See it run" section and a "Terminal recording" receipt.
    • blog.reproduce is optional: 1–8 commands, rendered as a code block. The generator never runs them.
    • Any other blog key is still refused.
    • make_markdown() renders tables with every cell escaped. Reproduce commands become escaped list items, not a fence, so a command cannot close a fence.
  • scripts/test_pr_blog_report.py: tests for the section order, the table (statuses, pipe escaping, check counts), the optional keys, and refusal of bad cast paths, empty or oversized reproduce lists and unknown keys.
  • .claude/skills/blog-post/SKILL.md: a new "How a post reads" section with 12 rules and their sources.
  • docs/PR_BLOG_AUTOMATION.md: documents the optional keys and how the draft is laid out (outline[0] is the problem), and points to the skill instead of copying the guide.

Sources for the writing rules

{
  "version": 1,
  "head_sha": "620d9340522958c6ce652c047c3dc3ca81abe852",
  "summary": "Generated PR blog drafts now lead with the result and a one-line count of reported checks, show checks as a table that keeps failures visible, and move the provenance notice to the end; the blog-post skill gains a sourced writing guide.",
  "changes": [
    "scripts/pr_blog_report.py: make_post() reorders the draft as result, problem, how it works, changes, a checks table, limits and provenance last",
    "scripts/pr_blog_report.py: optional blog.cast (term/<id>/session.cast) and blog.reproduce (1-8 commands, shown, never run); other blog keys still refused",
    "scripts/pr_blog_report.py: make_markdown() renders tables with escaped cells and reproduce commands as escaped list items, never a fence",
    "scripts/test_pr_blog_report.py: tests for section order, check table, check counts, optional keys and refusals",
    ".claude/skills/blog-post/SKILL.md: new section How a post reads, twelve rules with their sources",
    "docs/PR_BLOG_AUTOMATION.md: optional keys and draft layout documented, pointing at the skill instead of copying it"
  ],
  "tests": [
    {
      "command": "python3 -m unittest discover -s scripts -p 'test_pr_blog*.py'",
      "status": "passed",
      "result": "58 tests ran and all passed, including the four new template tests",
      "evidence": "local run on this head, 2026-10-03"
    },
    {
      "command": "python3 scripts/pr_blog_report.py validate on the current gHashTag/trinity#1273 event",
      "status": "passed",
      "result": "a real report renders in the new order with a five-row checks table and the provenance section last",
      "evidence": "draft.md and post.json written to a local temp directory and read through, 2026-10-03"
    },
    {
      "command": "website build rendering a post.json table block",
      "status": "not_run",
      "result": "not needed for this change: the table and code blocks already exist in the site schema and Blog.tsx renders them; left to CI",
      "evidence": "apps/website/src/data/blog/types.ts defines table and code blocks; Blog.tsx has their render cases"
    }
  ],
  "limitations": [
    "Existing work reports were written for the old layout, so outline items that state limits can land under How it works until authors follow the new order.",
    "blog.cast becomes a link and a receipt, not an embedded player: the terminal block is not on main until gHashTag/trinity#1273 merges.",
    "The writing rules guide the author agent and human writers; nothing checks automatically that a finished article follows them."
  ],
  "tags": ["Blog", "Writing", "Automation"],
  "blog": {
    "title": "Our PR blog drafts now open with the result",
    "summary": "The generator that turns a PR's work report into a blog draft now puts the result first and failures in plain view, following published guidance on how engineers read technical posts.",
    "outline": [
      "Every merged PR in this repository gets a blog draft generated from its work report, and those drafts opened with a disclaimer and a list of file paths, so the first thing a reader saw was neither the result nor the reason to care.",
      "The generator now follows what style guides and experienced engineering bloggers agree on: put the result and its number first, one idea per paragraph, the problem before the solution, and evidence the reader can check themselves.",
      "Checks became a table with a status column, so a failed or skipped check sits next to the passed ones instead of hiding in a bracketed bullet, and the line under the result counts them before anyone scrolls.",
      "Two optional fields let an author attach a published terminal recording and the exact commands to reproduce the result, and the guide that explains each section lives in one place, the blog-post skill, with its sources."
    ]
  }
}

🤖 Generated with Claude Code

The generated draft opened with a provenance disclaimer and a list of file
paths. It now leads with the result and a one-line count of reported checks.
The problem and the solution come next, then the changes and a "How we
checked" table that keeps failed and not-run checks visible. The draft ends
with what the post does not show and how it was made.

The work report accepts two optional blog keys. blog.cast names a recording
published on the site (term/<id>/session.cast). blog.reproduce lists 1-8
commands for readers to run, which the generator shows and never runs. Any
other key is still refused.

The blog-post skill gains "How a post reads", a short writing guide distilled
from published guidance on engineering blogs. PR_BLOG_AUTOMATION.md points to
it instead of copying it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the status:in-progress 🔵 Agent working label Oct 3, 2026
@gHashTag
gHashTag merged commit de5a474 into main Oct 3, 2026
27 of 33 checks passed
@github-actions github-actions Bot added status:completed Done and removed status:in-progress 🔵 Agent working labels Oct 3, 2026
github-actions Bot added a commit that referenced this pull request Oct 3, 2026
docs(blog): lay PR blog drafts out for readers, result first (#1286)

The generated draft opened with a provenance disclaimer and a list of file
paths. It now leads with the result and a one-line count of reported checks.
The problem and the solution come next, then the changes and a "How we
checked" table that keeps failed and not-run checks visible. The draft ends
with what the post does not show and how it was made.

The work report accepts two optional blog keys. blog.cast names a recording
published on the site (term/<id>/session.cast). blog.reproduce lists 1-8
commands for readers to run, which the generator shows and never runs. Any
other key is still refused.

The blog-post skill gains "How a post reads", a short writing guide distilled
from published guidance on engineering blogs. PR_BLOG_AUTOMATION.md points to
it instead of copying it.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant