Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions .claude/skills/intentumdiff-release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,120 @@ impossible.
3. Tag from `main`; the tag triggers publication
4. Open the next RC branch immediately, so in-flight work has a base

## Definition of ready to release

**Nothing is published until every box below is ticked.** Not "mostly", not "the important
ones" — all of them. This list exists because 0.0.1 was published with green CI and had to
be pulled from three registries within a day.

If a box cannot be ticked, the release does not happen. The correct response to schedule
pressure is a later release, never a lower bar.

### Artefact

- [ ] `smoke_published_wheel.py` passes against a **locally built** artefact
- [ ] Every check inside it passes — install, import, console script, `python -m`, a real
diff, **clean stderr**, **all URLs resolve**
- [ ] The extension VSIX installs into a **clean VS Code profile** and works there
- [ ] Extension host log is clean — no errors, no warnings about missing files
- [ ] Tested on every platform the artefact claims to support

### Docs

- [ ] Documentation site is **live**, not planned
- [ ] **Every** example in **every** README has been extracted and run verbatim, and its
real output matches what the doc claims
- [ ] **Every** link in user-facing docs resolves — READMEs, error messages, `--help`,
the Marketplace listing
- [ ] No reference to a page, domain or command that does not exist
- [ ] Demo media shows the CURRENT build, not an older UI

### Correctness

- [ ] Full test suite green in every affected repo, run in **that** repo
- [ ] The headline claim demonstrably works on a real repository — not a fixture
- [ ] Known limitations are written down and honest. A missing capability documented is
fine; one implied to work is not
- [ ] No regression against the previous release on a real-world diff

### Release hygiene

- [ ] Version is a **prerelease** unless the artefact has been used in anger
- [ ] Tag matches the manifest exactly
- [ ] CHANGELOG says what changed, in the user's terms
- [ ] Prior broken versions yanked or unpublished
- [ ] A rollback plan exists — and note that for PyPI and the marketplaces, "rollback"
means yank plus a new version, never delete

### The rule behind the list

**Green CI is not evidence a product works.** It is evidence the code compiles and the
tests we thought to write pass. Every 0.0.1 defect passed CI and was obvious thirty seconds
after installing the package.

Before publishing, someone must install the artefact and use it the way the README says to.
Every time. No exceptions, however small the change looks.

## MANDATORY: smoke-test the artefact before any publish

**CI proves the code builds. It does not prove the artefact works.** These are different
claims, and only the second one matters to a user.

IntentumDiff **0.0.1 shipped broken and had to be pulled from PyPI and both extension
marketplaces**, despite every check being green. Four defects, all invisible to CI and all
obvious within thirty seconds of installing the published package:

| Defect | Why CI could not see it |
|---|---|
| ~69 "Failed to catalog parser plugin" errors on every run | the distribution name was missing from the package's own first-party trust list; in a source checkout the distribution resolves differently and the check passes |
| `python -m intentumdiff` failed | no `__main__.py`; nothing in CI invoked it |
| Error message linked to an unregistered domain | no test followed a documented URL |
| README's headline example raised `NameError` | it was a fragment; nothing ever ran it |

None of these is exotic. All four were found by installing the wheel and typing what the
README says to type.

### The gate

Before tagging **any** release:

```bash
python scripts/smoke_published_wheel.py --wheel dist/<built>.whl # pre-publish
python scripts/smoke_published_wheel.py # post-publish
```

It installs into a clean venv and checks what a user does in their first five minutes:
install, import, console script, `python -m`, a real diff, **clean stderr**, and that
**every URL in the output resolves**.

Two of those deserve emphasis, because exit codes hide both:

- **Clean stderr.** 0.0.1 returned correct results *and* printed 69 errors. Exit code 0.
- **Live URLs.** A link in an error message is a promise; a dead one is worse than none.

### Beyond the script

The script is the floor, not the ceiling. Also required before a release:

- **Run every example in every README verbatim.** Extract the code block, execute it,
compare against the documented output. A fragment that cannot run is a broken example.
- **Follow every link in user-facing docs.** Dead links are how docs rot silently.
- **Exercise the extension in a vanilla VS Code**, not a dev host — a clean profile, no
workspace settings, no other extensions.
- **Confirm the claimed feature actually works.** Not "the code path is covered" — install
it and watch it do the thing.

## Ship beta first

The first release of anything user-facing is a **prerelease**: `0.0.2b1`, `0.0.2-beta.1`.

A version without a beta marker is a claim of stability. Make that claim after the artefact
has been installed and used, never before — the cost of retracting it is far higher than
the cost of a `b1` suffix. PyPI cannot delete a version and a Marketplace listing cannot be
overwritten, so "we can fix it in the next one" is not a recovery plan.

Promote to a stable version only once the beta has been smoke-tested and actually used.

## Version rules

- The tag **must** match the version in the manifest — `pyproject.toml`, `package.json`,
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ jobs:
with:
persist-credentials: false

- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: dist-*
path: downloaded-dist/
Expand Down Expand Up @@ -295,7 +295,7 @@ jobs:
with:
persist-credentials: false

- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: dist-*
path: downloaded-dist/
Expand Down
Loading