chore(release): 1.0.0b1 — the v1 target, staged as a beta
All seven v1 capabilities are landed (ROADMAP's v1 target is met), so this is the first release of the 1.x train. Staged as a beta rather than cut final on the operator's call: per the canonical policy `-beta.N` means feature-complete, external testing, no new features, focus is on bugs — which is exactly this state, with a cross-frontier bug-hunt panel outstanding on U7's diff. The repo learned this sequencing the hard way once: v0.2.0 was tagged and announced while a contract panel was in flight, the panel found three defects in the code just released, and v0.2.1 shipped within the hour. A beta is the designed answer to that, not a workaround for it. ALSO FIXES A SECOND COPY OF THE VERSION, found while cutting this one. `booth.__version__` was the literal `0.1.0` and had been wrong through six releases. It is now read from pyproject.toml — deliberately NOT from importlib.metadata, which describes a different artifact: this repo has no build step and no install step (booth.service runs uvicorn with WorkingDirectory set to the tree), and the venv was carrying a vestigial booth-0.3.0.dist-info with no package directory behind it. Installed metadata therefore reported 0.3.0 for a tree at 1.0.0b1 — confidently wrong and varying by environment, which is worse than a literal that at least fails the same way everywhere. booth/__init__.py is also, it turns out, effectively stdlib-only: scripts/booth imports booth.links / booth.marks / booth.manifest under the system python3 with no venv, and every one of those executes the package root first. Nothing asserted it. test_stdlib_only now covers __init__, and the no-venv import path is verified under python3.11 reporting 1.0.0b1. 642 tests green.
This commit is contained in:
+6
-3
@@ -1,9 +1,12 @@
|
|||||||
# The Booth — roadmap
|
# The Booth — roadmap
|
||||||
|
|
||||||
Design: [`docs/design/information-architecture.md`](docs/design/information-architecture.md).
|
Design: [`docs/design/information-architecture.md`](docs/design/information-architecture.md).
|
||||||
Current version: `0.6.1` (**U1 through U7 landed — every v1 capability is in**;
|
Current version: `1.0.0b1` (**U1 through U7 landed — every v1 capability is
|
||||||
extracted from eshpfi 2026-09-21). **The 1.0 cut is now a decision, not a
|
in**; extracted from eshpfi 2026-09-21). **The v1 target is MET and staged as a
|
||||||
dependency**, and it is the operator's: a major bump needs his approval.
|
beta** (operator, 2026-09-22): feature-complete, external testing, no new
|
||||||
|
features — the remaining work is bugs. `1.0.0` final is cut when the beta
|
||||||
|
survives; per the canonical policy an rc would be cut from the same commit,
|
||||||
|
but a beta may still take fixes.
|
||||||
|
|
||||||
## v1 target
|
## v1 target
|
||||||
|
|
||||||
|
|||||||
+41
-2
@@ -1,3 +1,42 @@
|
|||||||
"""The Booth — ephemeral media drop board. See booth.app for the server."""
|
"""The Booth — ephemeral media drop board. See booth.app for the server.
|
||||||
|
|
||||||
__version__ = "0.1.0"
|
⚠ THIS FILE IS EFFECTIVELY STDLIB-ONLY and nothing used to say so. `scripts/booth`
|
||||||
|
imports `booth.links` / `booth.marks` / `booth.manifest` under the SYSTEM python3
|
||||||
|
with no venv, and importing any of them executes this module first — so a single
|
||||||
|
third-party import here breaks `booth ask` on every fleet host exactly as one in
|
||||||
|
those three would. `test_stdlib_only` now covers `__init__` for that reason.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import tomllib
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
_PYPROJECT = Path(__file__).resolve().parent.parent / "pyproject.toml"
|
||||||
|
|
||||||
|
|
||||||
|
def _declared_version() -> str:
|
||||||
|
"""The version of the code actually running, read from `pyproject.toml`.
|
||||||
|
|
||||||
|
⚠ NOT `importlib.metadata`, and the reason is this repo's own shape: there
|
||||||
|
is no build step and no install step — `booth.service` runs uvicorn with
|
||||||
|
WorkingDirectory set to the repo, so the running code IS this tree.
|
||||||
|
Installed metadata describes a DIFFERENT artifact and was found saying
|
||||||
|
`0.3.0` (a vestigial dist-info, three releases stale, with no package
|
||||||
|
directory behind it) while the tree was at `1.0.0b1`. A confidently wrong
|
||||||
|
number that varies by environment is worse than the hardcoded `0.1.0` this
|
||||||
|
replaced, which at least failed the same way everywhere.
|
||||||
|
|
||||||
|
Falls back to installed metadata for the case this repo does not have but a
|
||||||
|
consumer might: packaged as a wheel, where pyproject does not ship.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return tomllib.loads(_PYPROJECT.read_text())["project"]["version"]
|
||||||
|
except (OSError, KeyError, tomllib.TOMLDecodeError):
|
||||||
|
try:
|
||||||
|
from importlib.metadata import version
|
||||||
|
|
||||||
|
return version("booth")
|
||||||
|
except Exception:
|
||||||
|
return "0.0.0+unknown"
|
||||||
|
|
||||||
|
|
||||||
|
__version__ = _declared_version()
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "booth"
|
name = "booth"
|
||||||
version = "0.6.1"
|
version = "1.0.0b1"
|
||||||
description = "The Booth — a dead-simple standing web server that scans a data dir of drop-folders and renders each as an ephemeral media 'booth' (image/webm/audio auto-gallery, or a folder's own index.html verbatim). Also accepts browser/curl uploads for pickup under a human-readable id. 24h TTL, then the folder is wiped. Fleet tool for CC sessions to surface A/B and smoke results to the operator."
|
description = "The Booth — a dead-simple standing web server that scans a data dir of drop-folders and renders each as an ephemeral media 'booth' (image/webm/audio auto-gallery, or a folder's own index.html verbatim). Also accepts browser/curl uploads for pickup under a human-readable id. 24h TTL, then the folder is wiped. Fleet tool for CC sessions to surface A/B and smoke results to the operator."
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
+31
-1
@@ -7,6 +7,8 @@ See docs/contracts/u2_marks.contract.md.
|
|||||||
"""
|
"""
|
||||||
import ast
|
import ast
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
|
import tomllib
|
||||||
import pathlib
|
import pathlib
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -276,7 +278,7 @@ def test_as_dict_round_trips_through_json(tmp_path):
|
|||||||
# ---- the stdlib-only invariant (INV-5) --------------------------------------
|
# ---- the stdlib-only invariant (INV-5) --------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("module", ["marks", "asks", "links", "manifest", "benches"])
|
@pytest.mark.parametrize("module", ["marks", "asks", "links", "manifest", "benches", "__init__"])
|
||||||
def test_stdlib_only(module):
|
def test_stdlib_only(module):
|
||||||
"""INV-5. scripts/booth imports these under the system python3 with NO venv,
|
"""INV-5. scripts/booth imports these under the system python3 with NO venv,
|
||||||
through a `python3 -c` heredoc that no AST extractor can see — so nothing
|
through a `python3 -c` heredoc that no AST extractor can see — so nothing
|
||||||
@@ -1428,3 +1430,31 @@ def test_a_healthy_multi_answer_still_hydrates(tmp_path):
|
|||||||
by = {m.id: m for m in marks_for(tmp_path)}
|
by = {m.id: m for m in marks_for(tmp_path)}
|
||||||
assert by["multi"].error is None, by["multi"].error
|
assert by["multi"].error is None, by["multi"].error
|
||||||
assert by["single"].error is None, by["single"].error
|
assert by["single"].error is None, by["single"].error
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_package_version_carries_no_literal_of_its_own():
|
||||||
|
"""`booth.__version__` said `0.1.0` through six releases while pyproject
|
||||||
|
said `0.6.1` — a second copy of one fact, drifting silently, found only
|
||||||
|
while cutting 1.0.
|
||||||
|
|
||||||
|
THE ASSERTION IS THE ABSENCE OF A LITERAL, not agreement with pyproject:
|
||||||
|
`__version__` is now READ from pyproject, so comparing the two would be
|
||||||
|
circular and would prove only that the read works. The defeating change is
|
||||||
|
hardcoding a number back into this module, and that is what this catches.
|
||||||
|
"""
|
||||||
|
src = (pathlib.Path(__file__).parent.parent / "booth" / "__init__.py").read_text()
|
||||||
|
literals = re.findall(r'__version__\s*=\s*["\']([^"\']+)["\']', src)
|
||||||
|
assert not literals, f"booth/__init__.py hardcodes a version again: {literals}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_package_version_is_the_one_the_tree_declares():
|
||||||
|
"""And it resolves, from the tree, to what pyproject says — NOT to whatever
|
||||||
|
a stale dist-info in some venv happens to record. Found saying `0.3.0` from
|
||||||
|
installed metadata while the tree was at `1.0.0b1`."""
|
||||||
|
import booth
|
||||||
|
|
||||||
|
declared = tomllib.loads(
|
||||||
|
(pathlib.Path(__file__).parent.parent / "pyproject.toml").read_text()
|
||||||
|
)["project"]["version"]
|
||||||
|
assert booth.__version__ == declared
|
||||||
|
assert booth.__version__ != "0.0.0+unknown", "the pyproject read fell through"
|
||||||
|
|||||||
Reference in New Issue
Block a user