release-prep · diff
git:20260822.94279fe to git:20260901.484ab7d
44 added, 222 removed. Audit A to A.
---
name: release-prep
- description: Pre-release docs sync — diff HEAD against the last v* tag on the publish remote, list feature additions, update README language/tool inventory, draft the CHANGELOG release entry, propose the version bump. Runs before /release. Prevents shipping with stale docs.
- disable-model-invocation: false
+ description: Audit and prepare public release metadata before the separately authorized release workflow
+ disable-model-invocation: true
---
- # Release Prep Workflow
-
- Prepare docs for a PyPI release. Complements `/release` — this is the **docs sync** step; `/release` is the **cut + publish** step.
-
- ## When to Use
-
- - Before running `/release`.
- - After a batch of features has landed on `main` and you need to know "what's new since last publish?"
- - User says: "prepare for release", "what's new since last publish", "update docs before release".
-
- ## Golden Rule
-
- **Use the `publish` remote, not local tags.** Local tags can include inherited upstream tags that were never published. PyPI watches the `publish` remote.
-
- ## Steps
-
- ### Step 1: Resolve last published version
-
- ```bash
- # Last v* tag on the publish remote (PyPI source of truth)
- LAST_TAG=$(git ls-remote --tags publish 2>/dev/null \
- | grep -E 'refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$' \
- | awk '{print $2}' | sed 's|refs/tags/||' \
- | sort -V | tail -1)
- echo "Last published: $LAST_TAG"
- ```
-
- If `publish` is not a git remote, fall back to asking the user which remote holds releases — do **not** use the latest local tag blindly.
-
- Compare against `pyproject.toml` — if they differ, flag and investigate before continuing.
-
- ### Step 2: List commits since last publish
-
- ```bash
- git log "$LAST_TAG..HEAD" --oneline
- git log "$LAST_TAG..HEAD" --oneline | wc -l
- ```
-
- Group by conventional-commit scope. Ignore noise: `chore: archive completed tasks`, `chore: autopilot housekeeping`, `fix(*): auto-fix verify errors`.
-
- Categorize user-facing changes:
-
- | Category | Signal |
- |----------|--------|
- | New feature | `feat(*)` with description (e.g. `feat(MINE-DART): Dart language support`) |
- | New MCP tool | `feat(MCP-*)` or diff touches `mempalace_code/mcp_server.py` tool registry |
- | Bug fix | `fix(*)` not tagged `auto-fix verify` |
- | Docs | `docs(*)` |
- | Breaking | Any commit whose body says "BREAKING" or touches storage format / public API |
- | Dependency change | Diff touches `pyproject.toml` or `uv.lock` |
-
- ### Step 3: Detect feature surface changes
-
- Cross-check the commit log against the code to catch anything the commit messages missed.
-
- **New languages in the miner** — diff language dispatch tables:
+ # Release Prep
- ```bash
- git diff "$LAST_TAG..HEAD" -- mempalace_code/miner.py mempalace_code/mining/ \
- | grep -E '^\+.*(LANG_|_chunks|parse_|tool_|language.*=.*")'
- ```
+ Use for release notes, public-document synchronization, and a proposed version
+ bump before `/release`.
- **MCP surface changes** — verify the current public contract and inspect changed tool families:
+ ## Canonical owners
- ```bash
- python scripts/docs_drift_guard.py --json
- git diff --name-status "$LAST_TAG..HEAD" -- \
- mempalace_code/mcp/registry.py mempalace_code/mcp/tools/
- ```
+ Read `AGENTS.md`, `docs/RELEASING.md`, `CHANGELOG.md`, and `pyproject.toml` in
+ full. Use the `publish` remote as release history; local tags may include
+ unpublished upstream history.
- **Python version bumps** — scan `pyproject.toml` history for `requires-python` changes.
+ ## Guards
- **Dependency bounds or lockfile changes** — list direct packages and run advisory
- checks before drafting public notes:
+ - Run `autopilot doctor --json`; require `safe_to_edit=true` for every proposed
+ local path.
+ - Never invoke Codex, Claude, Gemini, another model/provider, or an authenticated
+ client during release preparation.
+ - Never read, copy, inspect, require, or transmit credentials, API keys, OAuth
+ tokens, keychains, auth files, paid-account state, or ambient credentials.
+ - Inspection authorizes no edits. Require fresh authority for the exact docs,
+ changelog, and version paths before writing.
+ - Commit, push, tag, publication, and candidate cleanup each require separate
+ explicit authority. This skill performs none of them.
+ - Never use `--force`, rewrite a public ref, or infer release identity from a
+ local tag.
- ```bash
- git diff "$LAST_TAG..HEAD" -- pyproject.toml uv.lock
- python - <<'PY'
- import tomllib
- data = tomllib.load(open("pyproject.toml", "rb"))
- print("runtime:", data["project"]["dependencies"])
- print("optional:", data["project"].get("optional-dependencies", {}))
- print("dev:", data.get("dependency-groups", {}).get("dev", []))
- PY
- ```
+ ## Inspect
- Do not raise an optional dependency ceiling into a known affected advisory
- range. Record held upgrades in `docs/BACKLOG.yaml` and `docs/plans/`.
+ Resolve the last plain `vX.Y.Z` tag with
+ `python scripts/release_public_read.py --version-tags`. Compare that tag through
+ `HEAD` and inspect the current public behavior owners. Report:
- ### Step 4: Check docs for staleness
+ - user-visible additions, changes, fixes, and compatibility notes;
+ - public docs or examples that disagree with executable behavior;
+ - package, optional-extra, CLI, MCP, or Python-support changes;
+ - the smallest semantic-version bump justified by that diff.
- For each item in Step 3, verify it appears in the right docs file.
+ Do not turn internal plans, local paths, machines, agent identities, incident
+ details, or private release evidence into public notes.
- | Change | Doc that must update |
- |--------|----------------------|
- | New language | `README.md` — "What gets indexed" bullet + Language-Aware Code Mining table |
- | New MCP tool | `README.md` — MCP tool inventory tables (Read / Write / Graph / Diary groups) |
- | New MCP tool | `docs/LLM_USAGE_RULES.md` — Routing table + any relevant rule section |
- | Python minimum bump | `README.md` Requirements section + `pyproject.toml` `requires-python` |
- | Dependency bound/security change | `CHANGELOG.md`, `CLAUDE.md`, and any relevant plan/backlog item |
- | Breaking change | `CHANGELOG.md` under `### Breaking` |
- | Any feature | `CHANGELOG.md` under the release header for this version |
+ ## Apply when authorized
- Report each stale location as a to-fix item. Do not assume commit messages already covered it.
+ Update only the confirmed version owner, one consolidated release entry in
+ `CHANGELOG.md`, and public docs proven stale by the diff. Do not create a second
+ release procedure or tracked validation log.
- Run the deterministic contract check after documentation edits:
+ ## Validate
```bash
python scripts/docs_drift_guard.py
- ```
-
- It verifies the package version, Python minimum, MCP tool/profile counts, LLM
- profile blocks, changelog release heading, README badge, and the canonical
- GitHub About source text in `docs/RELEASING.md`.
-
- ### Step 5: Propose version bump
-
- | What changed | Bump |
- |--------------|------|
- | Any breaking change (API / CLI / storage format / MCP tool signatures) | Major (X.0.0) |
- | New languages, new MCP tools, new CLI commands, behavior changes that are backwards-compatible | Minor (0.X.0) |
- | Only bug fixes, docs, CI, internal refactors | Patch (0.0.X) |
-
- State the reasoning. Ask the user to confirm.
-
- ### Step 6: Draft the CHANGELOG release entry
-
- Open `CHANGELOG.md`. If scattered per-task entries already exist at the top (pattern: `## YYYY-MM-DD · TASK-SLUG`), **consolidate** them under a single release header:
-
- ```markdown
- ## vX.Y.Z — YYYY-MM-DD
-
- ### Added
- - **N new languages in the code miner:**
- - **<Lang>** — <symbol types>; <notable features> (<TASK-SLUG>)
- - …
- - **N new MCP tools:**
- - `mempalace_<name>` — <one-line purpose> (<TASK-SLUG>)
- - …
-
- ### Changed
- - **<human-friendly summary>** — <what shifted>, <why it matters> (<TASK-SLUG>)
-
- ### Fixed
- - <if applicable>
-
- ### Breaking
- - <if applicable — otherwise omit the section>
- ```
-
- Do **not** leave the per-task entries above the release header; consolidate them into bullets beneath it. One release header per version.
-
- ### Step 7: Update README and LLM_USAGE_RULES
-
- Apply the to-fix items from Step 4. Touch `README.md` and `docs/LLM_USAGE_RULES.md` directly. Do not ask the user to paste snippets — just make the edits.
-
- ### Step 8: Bump `pyproject.toml`
-
- ```bash
- # Replace "<NEW>" with the confirmed version
- grep -E "^version\s*=" pyproject.toml
- ```
-
- Edit the file; do not use `sed -i` unless portable (`sed -i '' 's/…/…/'` on macOS, plain `sed -i` on Linux). Prefer the Edit tool.
-
- ### Step 9: Commit
-
- ```bash
- git add pyproject.toml CHANGELOG.md README.md docs/LLM_USAGE_RULES.md
- git commit -m "chore: prepare release vX.Y.Z"
- ```
-
- Do **not** tag or push. That is `/release`'s job — and note that `/release` never
- pushes this branch or local `main` anywhere. It rebuilds this reviewed tree as a
- candidate commit on top of `publish/main`, publishes that as its own candidate
- branch (`release/vX.Y.Z`, or `release/vX.Y.Z-rc2` on a rebuild), and only
- fast-forwards the already-green candidate onto public `main`.
-
- ### Step 10: Run the live pre-tag check
-
- Immediately before `/release` creates the tag, run the canonical command:
-
- ```bash
+ python scripts/public_safety_scan.py --tracked --staged
+ python scripts/quality_scorecard.py --check
python scripts/release_preflight.py --tag vX.Y.Z --require-clean --check-live-upstream
```
- The default preflight remains static and network-free. This explicit opt-in
- command adds the read-only live upstream comparison before the immutable tag is
- created.
-
- ### Step 11: Hand off
-
- Report:
-
- ```
- ## Release-prep for vX.Y.Z
-
- Last published: vA.B.C (publish remote)
- Commits since: <N>
-
- Features added:
- - <language list>
- - <MCP tool list>
- - <other>
-
- Docs updated:
- - README.md: <what>
- - CHANGELOG.md: v<version> release header
- - docs/LLM_USAGE_RULES.md: <if touched>
- - pyproject.toml: <old> → <new>
-
- Next: run /release. It builds a candidate on publish/main, pushes it as its own
- candidate branch (release/vX.Y.Z, or release/vX.Y.Z-rc2 on a rebuild), waits for
- that exact SHA to go green, fast-forwards it onto public main, then tags.
- Deleting the candidate branch afterwards needs its own explicit approval.
- ```
-
- ## Gotchas
-
- - **`git describe --tags --abbrev=0` is wrong for this use case.** It returns the most recent local tag regardless of origin. Upstream tags pulled into the fork (e.g. v3.0.0 from an inherited upstream) will poison the result. Always use `git ls-remote --tags publish`.
- - **`pyproject.toml` version and the `publish`-remote latest tag should match** after the last release. If `pyproject.toml` is ahead, the previous release was cut but the tag never pushed — investigate before bumping again.
- - **Do not push to `origin` on release.** Per project feedback: releases go to `publish` only. `/release` handles this; this skill does not push.
- - **Local `main` and public `main` are different histories.** Public `main` carries one squashed commit per release, so it can never be reached by pushing a development branch. Never `--force` and never rewrite public history to "fix" that: `/release` promotes a `release/v*` candidate branch built on `publish/main` instead, and a failed candidate is rebuilt under a new immutable name (`release/vX.Y.Z-rc2`) rather than force-updated.
- - **Dependency changes need an audit trail.** Before release notes claim a package upgrade is safe, verify current and target versions against OSV or an equivalent advisory source and test a clean hosted-CI-equivalent resolver. Public notes may include advisory IDs and version ranges; private resolver paths and local incident details stay out.
- - **Skip the per-task changelog headers.** Some autopilot flows write `## YYYY-MM-DD · TASK-SLUG` entries at the top of CHANGELOG as work lands. Before release, consolidate them into a single release header with grouped bullets. Do not leave both forms.
+ The live preflight is read-only. A failure stops the handoff; it does not
+ authorize a gate, ruleset, remote, or workflow repair.
## Output
- ```
- ## Release-prep summary
-
- Last published: <vX.Y.Z>
- Proposed version: <vA.B.C> (<major|minor|patch>)
- Commits: <N> since <vX.Y.Z>
- Features: <count> new languages, <count> new MCP tools
- Docs updated: <list>
- Version file: bumped
- Committed: <yes|no>
-
- Hand off to: /release
- ```
+ Report the last published tag, proposed version and reason, exact modified
+ paths, validation results, and one next action. Hand off to `/release` only when
+ the prepared tree is coherent. Report the commit command instead of running it.