NAMES · Prepare the four package-name claims¶
Running 2026-10-29 · branch autopilot/pypi-name-claim · Thomas: \"Pour PyPI, prépare-moi déjà ce qu'il faudrait faire dans un fichier ou sur le CI\" · nothing published, no token made, no workflow run · round 1 on 0ca035f: code, security and doc changes, all applied · round 2 on 2433dc2: code approve, security approve, doc approve 12/14, the remaining changes applied · round 3 on 46888e0: security approve, three minors applied · open for Thomas: inbox #71 (agent deny rules), the placeholder version, the registry provider string, where the logger's catalogue page lives

What changed¶
.github/workflows/pypi-publish.yml, new: started by hand, one project per run (spectio,spectio-open,snakemake-logger-plugin-spectio), three jobs:build: only uv (checked againstUV_SHA256) and the pinneduv_buildbackend run:uv build, the sha256 sums recorded as a job output, thendist/uploaded;smoke: on a downloaded copy:twine check --strict, the wheel's file list againstwheel-contents.txt, the wheel installed in a fresh venv andtools/release/pypi-placeholders/smoke.pyrun;publish: needs both, only frommain, in environmentpypi-<project>, the only job withid-token: write; checks the downloaded files against the build job's sums and count, then uploads them withpypa/gh-action-pypi-publishv1.14.3 andskip-existing.
tools/release/pypi-placeholders/, new: three working0.0.0packages (uv_build==0.11.32, MIT,RepositoryURL, no classifiers).spectioandspectio-openinstall a command with--version.snakemake-logger-plugin-spectiois a Snakemake logger that appends one JSON line per log event to--logger-spectio-file(defaultspectio-events.jsonl). It opens the file withO_NOFOLLOW|O_NONBLOCK, then refuses it unlessfstatshows a regular file of the current user with one link, and sets it to 0600.dev/versions.env:TWINE_VERSION=7.0.0..github/CODEOWNERS:/tools/release/is code-owned.- Guide, new: Claim the package names: the registry claim,
mainprotection and the GitHub environments, the pending publishers, the run, the manual fallback, open points. - Spec: dev-env §12 Publishing: FC-314 to FC-317.
- Records: the name-claim verification, the review record, a decision-log entry, a status line on inbox #66 and a new inbox #71.
Why¶
Thomas, 2026-10-29: "Comment faire pour réserver ces 4 noms de paquets? … Pour PyPI, prépare-moi déjà ce qu'il faudrait faire dans un fichier ou sur le CI. Puis je préparerai ceci moi-même sur le site." The fact-check found that a PyPI pending publisher holds nothing until it is used, so the preparation is a workflow Thomas runs right after adding each publisher, plus packages that do something real (PEP 541).
How to test it¶
From the repository root, for one project (smoke.py needs the wheel installed):
uv build --out-dir /tmp/d tools/release/pypi-placeholders/snakemake-logger-plugin-spectio
uv venv /tmp/v && uv pip install --python /tmp/v/bin/python /tmp/d/*.whl
/tmp/v/bin/python tools/release/pypi-placeholders/smoke.py snakemake-logger-plugin-spectio
Evidence¶
- Jobs replayed locally (every
run:block of the three jobs, in order): all steps exit 0 for the three projects, withtwine checkPASSED on each wheel and sdist andsmoke: <project> ok;publish's check passes on the build job's sums;bogusstops at::error::Unknown project: bogus. An extra line inwheel-contents.txtfails the smoke job'sdiff. A byte appended to the wheel after the sums failspublish'ssha256sum --check(FAILED,1 computed checksum did NOT match); an extra wheel added todist/fails its count. - Smoke, logger (
smoke.py): one event written as valid JSON; refused: a symlinked path (target untouched), a FIFO (ENXIO, no hang), a second hard link, a file of another user; tightened: an existing 0666 file of ours ends at 0600; no settings object: the defaultspectio-events.jsonlin the working directory. The other-user case patchesos.getuidto return another uid, since the test runs without root. - The checks are live: each of four mutants of the installed module fails
smoke.py, with the assertion that names it. The mutants drop the uid check, drop the link-count check, replacefchmodwithpass, or dropO_NONBLOCK(the FIFO open then blocks until the 5 s guard fires: "opening a FIFO log file blocked"). - Settings can be None? Through the CLI, no: snakemake 9.27.1 builds one settings object per
--logger(snakemake/cli.py:2085-2088), andget_settingsreturns an instance filled from the dataclass defaults when no flag is given (snakemake-interface-common 1.23.0plugin_registry/plugin.py:223-231). The interface types the argumentOptional[LogHandlerSettingsBase](snakemake-interface-logger-plugins 2.1.0base.py:19), so an API caller may pass None; the handler then usesLogHandlerSettings(). - Real Snakemake runs (snakemake 9.27.1, a one-rule Snakefile):
--logger spectio --logger-spectio-file events.jsonlexits 0 and writes 14 valid JSON lines (workflow_started,run_info,job_started,job_info,job_finished,progress,resources_info), mode600;--logger spectiowith no flag writes 14 lines tospectio-events.jsonl;- with
events.jsonla symlink to a missing file, the run stops withOSError: [Errno 40] Too many levels of symbolic links, and the target is not created. - an existing 0666
loose.jsonlexits 0 and ends at mode600; a second hard link to the log file stops the run withPermissionError: refusing …: not a regular file of ours with one link; - a FIFO at
fifo.jsonlstops the run in under a second withOSError: [Errno 6] No such device or address.
- setup-uv checksum:
UV_SHA256indev/versions.envequals theuv-x86_64-unknown-linux-gnu.tar.gz.sha256the uv 0.11.32 release publishes; setup-uv v6.8.0 declareschecksum(action.yml:21-23) and its built-in list stops at 0.8.20. - Linters: actionlint (the repo's pinned binary, with shellcheck): clean. zizmor 1.31.1
--offline --min-severity low: no findings. The online audits need a token and run in CI. - Docs:
python3 tools/docs/check.py --base origin/autopilot/integrationandmkdocs build --strict: see the PR's Checks.
Review (record):
- Round 1, on
0ca035f:code-reviewerchanges (0/1/4),security-reviewerchanges (0/1/5),doc-reviewerchanges 10/14; all applied. - Round 2, on
2433dc2: all three approve (doc 12/14); the minors applied, CR-008 accepted. - Round 3, on
46888e0:security-reviewerapprove (0/0/3): SEC-4b, SEC-7b, SEC-8, all applied. - No
code-simplifierpass: the simplify findings CR-005 to CR-007 were applied by hand.
CODE step=NAMES review=approve b/M/m=0/0/4 security=approve b/M/m=0/0/3 rounds=3 simplify=CR-005,CR-006,CR-007 by hand tests=pass
Figures and media¶
name-claim(light and dark), drawn bytools/diagrams/name_claim.py. It shows the two ways a name is held: the registry claim, and the PyPI pending publisher followed by the build, smoke and publish jobs. Both PNGs were looked at after each render.- No screenshots or casts: nothing in this step has a screen.
Findings and open questions¶
- FC-314 to FC-317 (verification): applied to dev-env §12.
- CR-001 to CR-009, SEC-1 to SEC-8 (with SEC-1b, SEC-4b, SEC-7b) and the doc reviews (review record): applied, except SEC-1's permission part, now inbox #71.
- Open for Thomas: inbox #71; the placeholder version (
0.0.0proposed); the registry provider string; where the logger's catalogue page lives (verification, open point 9).