# Automate release Phase 2 in CI

Moves release **Phase 2** (tag → publish Release → back-merge main→develop) out of the releasing skill and into CI, so a release finishes automatically when the release PR merges — with no standing…

| | |
| --- | --- |
| Status | CLAUDE CODE-WRITTEN · OPEN |
| Source | github:todofixthis/phx-claude-siat#18 |
| Original | https://github.com/todofixthis/phx-claude-siat/pull/18 |
| Workspace | Showcase |
| Tags | github, code, docs, python, config |

## What it does

**The change is spread across 13 files in 2 areas, with no single file dominating.**

Claude Code opened this, so there is no author to ask. 13 files changed across 2 areas of todofixthis/phx-claude-siat, 797 added and 85 removed.

Moves release **Phase 2** (tag → publish Release → back-merge main→develop) out of the releasing skill and into CI, so a release finishes automatically when the release PR merges — with no standing…

**Diagram: Where the change landed. Node size is not to scale; the line counts are exact.**

- phx-claude-siat (13 files, 882 lines) [accent]
- Build & CI (7 files, 446 lines) [bad]
- Docs (6 files, 436 lines) [neutral]
- test_release_notes.py (+142 −0) [neutral]
- phx-claude-siat -> Build & CI
- phx-claude-siat -> Docs
- Build & CI -> test_release_notes.py : heaviest

- **Written by an agent.** Claude Code authored this change. The usual review shortcut, asking the person who wrote it, is not available, so everything a reviewer needs has to come from the diff itself.
- **Heaviest file.** docs/adr/007-keep-repo-scripts-stdlib-only.md, +145 −0, which is 16% of the change.
- **No test changed.** 0 source files changed with no accompanying test edit.
- **Configuration touched.** test_release_notes.py, release.yml, release_notes.py. Config changes are small in the diff and large in effect.
- **Spread.** 13 files, 882 changed lines in total.

## How it works

**The largest single edit is in 007-keep-repo-scripts-stdlib-only.md.**

Quoted verbatim from the diff. This is the biggest hunk by changed lines, which is where a reviewer's attention usually belongs first.

```markdown
@@ -0,0 +1,145 @@
+---
+status: Accepted
+date: 2026-07-28
+tags: [adr, ci, dependencies, duplication, frontmatter, git-hooks, pep723, pre-commit, python, scripts, stdlib, tooling, uv]
+summary: Keep everything under scripts/ stdlib-only with no Python project at the repo root, and reach for a root project rather than per-script PEP 723 metadata if that ever changes; revisit on a second compromise over a grammar this repo does not define, or when the adapted frontmatter parser gains a third copy or its copies drift on shared input.
+---
+
+# 007: Keep repo scripts stdlib-only
+
+## Context
+
+`scripts/` has grown to five files — ADR index generation, manifest validation, release
+notes, a shared version pattern, and one test module — run by CI, the pre-commit hook,
+and the [`releasing`][] skill, each as `python3 scripts/<area>/<name>.py` from the repo
+root. None declares a dependency, and the repo root carries no `pyproject.toml`.
+
+[ADR 006][] already reasons from that constraint (choosing `tomllib` because it is
+standard library, and rejecting alternatives needing "a dependency the repo lacks"), and
+[ADR 005][] already accepts one of its costs: the flat-frontmatter parser adapted between
+[`generate_index.py`][] and [`validate_manifests.py`][]. Neither states the constraint
+itself, so each new script re-decides it, and the first to answer "add a dependency"
```

_docs/adr/007-keep-repo-scripts-stdlib-only.md, +145 −0. The largest hunk in the largest file._

## File map

**Every file this change touches, heaviest first.**

Role is inferred from the path and risk from the path and the line count. Neither was read from the code.

| File | Role | Change | Risk |
| --- | --- | --- | --- |
| `docs/adr/007-keep-repo-scripts-stdlib-only.md` | documentation | added, +145 −0 | none |
| `scripts/ci/test_release_notes.py` | test coverage | added, +142 −0 | low |
| `.github/workflows/release.yml` | application code | added, +137 −0 | high |
| `.agents/skills/releasing/SKILL.md` | documentation | modified, +65 −68 | none |
| `docs/adr/008-release-only-x-y-z-versions.md` | documentation | added, +106 −0 | none |
| `scripts/ci/release_notes.py` | application code | added, +102 −0 | medium |
| `docs/release-automation.md` | documentation | added, +34 −0 | none |
| `scripts/ci/validate_manifests.py` | application code | modified, +14 −14 | low |
| `scripts/ci/versions.py` | application code | added, +18 −0 | low |
| `AGENTS.md` | documentation | modified, +16 −0 | none |
| `.github/workflows/pr.yml` | application code | modified, +13 −1 | high |
| `scripts/adr/generate_index.py` | application code | modified, +3 −2 | low |
| `docs/adr/INDEX.md` | documentation | modified, +2 −0 | none |

## Receipts

**Where each number above comes from.**

All of it is arithmetic over the file list and the check results, so it can be recomputed from the source.

- **Claim.** Manufactured significance: 1 occurrence.
  - Evidence: …unchanged, and I'd have been wrong to let it stand as the explanation for the lint gap. (The *esca…
  - Where: description and comments
- **Claim.** Em dash density: 91 occurrences.
  - Evidence: …hes automatically when the release PR merges — with no standing human/agent bypass on `deve…
  - Where: description and comments
- **Claim.** Claude Code wrote this change.
  - Evidence: Generated with [Claude Code]
  - Where: pull request description
- **Claim.** 13 files changed, +797 −85.
  - Evidence: docs/adr/007-keep-repo-scripts-stdlib-only.md (+145 −0); scripts/ci/test_release_notes.py (+142 −0); .github/workflows/release.yml (+137 −0)
  - Where: https://github.com/todofixthis/phx-claude-siat/pull/18
- **Claim.** 007-keep-repo-scripts-stdlib-only.md carries 16% of the changed lines.
  - Evidence: 145 of 882 changed lines
  - Where: docs/adr/007-keep-repo-scripts-stdlib-only.md
- **Claim.** It arrived as 14 commits.
  - Evidence: Add release-automation spec and design-doc note 🧭
  - Where: commit 884ba04
- **Claim.** CI reports 0 failing of 5.
  - Evidence: gate
  - Where: CI check: gate
- **Claim.** The change drew 57 comments.
  - Evidence: Will this work with the repo protections? Given the workflow is idempotent, I wonder if the remediation here is for the agent to determine w…
  - Where: comment by todofixthis

## Where to attack

**What the shape of this diff suggests looking at first.**

These come from structure alone: which areas were touched, what was not touched alongside them, and what CI says. None of them is a judgement about the code.

- **Configuration changed** (high)
  - scripts/ci/test_release_notes.py, .github/workflows/release.yml, scripts/ci/release_notes.py changed. A config edit is usually a handful of lines and decides behaviour for an entire environment, so diff size is a poor guide to its blast radius.
  - Mitigation: Check what reads each of these values, and in which environments they differ.

## Merge order

**A reading order for the review, not a deployment plan.**

Ordered by how expensive each part is to get wrong, which is a structural property rather than an informed one.

1. **Review the configuration changes.** test_release_notes.py, release.yml, release_notes.py. Smallest diff, widest effect.
2. **Then 007-keep-repo-scripts-stdlib-only.md.** The largest single file in the change, +145 −0.
3. **Decide whether a test is needed.** Nothing in this change adds or edits one.

## What this brief could not check

- No language model read this change. Every statement here is computed from file paths, line counts, and CI status, so it describes the shape of the diff and not what the diff means.
