Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
dc83c21
OpenSpec change release-tags-pypi: proposal (#228)
Oct 17, 2026
698cf30
OpenSpec change release-tags-pypi: alignment review fixes and Brett's…
Oct 17, 2026
56669c1
OpenSpec change release-tags-pypi: council verdicts applied, and clar…
Oct 17, 2026
ea306de
OpenSpec change release-tags-pypi: the wheel's LICENSE is held by the…
Oct 17, 2026
1fcb95c
OpenSpec change release-tags-pypi: delta specs for its two new capabi…
Oct 17, 2026
9571d9c
OpenSpec change release-tags-pypi: design.md (#228)
Oct 17, 2026
28a441a
OpenSpec change release-tags-pypi: tasks.md, the governance and hando…
Oct 17, 2026
8035d77
OpenSpec change release-tags-pypi: design.md records the lead's rulin…
Oct 17, 2026
eb12177
Speckit feature 006-release-pypi: spec.md and its quality checklist (…
Oct 17, 2026
760281b
OpenSpec change release-tags-pypi: tasks.md records the Speckit hando…
Oct 17, 2026
83c69ed
Speckit feature 006-release-pypi: plan, research, data model, contrac…
Oct 17, 2026
01ff6d6
Speckit feature 006-release-pypi: tasks.md, 25 tasks by user story an…
Oct 17, 2026
335d226
Speckit feature 006-release-pypi: /speckit.analyze findings fixed, no…
Oct 18, 2026
b0640a5
Release tags and PyPI: the lead's rulings of 2026-10-18 on 335d226, i…
Oct 18, 2026
5e592ca
Merge main d424b64 into 006-release-pypi (#228): bring the branch up …
Oct 18, 2026
140c5ab
T001: the package's docstring-only __init__ and its committed, unstam…
Oct 18, 2026
cf43b07
tasks.md: T001 done (accepted 140c5ab on model, scope and verify); T0…
Oct 18, 2026
b6ff505
T001: both package files open with the repository's SPDX line (lead's…
Oct 18, 2026
fd554d8
The stamp contract follows T001's SPDX line: the SPDX line, one docst…
Oct 18, 2026
8701f19
The workBenches condition is decided: Brett Heap's position (c), open…
Oct 18, 2026
f35ec31
T002: pyproject.toml declares the openrepotools wheel, per contracts/…
Oct 18, 2026
0da3386
tasks.md: T002 done (accepted f35ec31 on model, scope and verify) (#228)
Oct 18, 2026
0e99729
T003: tests/package_layout.py builds the package's fake installed lay…
Oct 18, 2026
0670b42
tasks.md: T003 done (accepted 0e99729 on model, scope and verify) (#228)
Oct 18, 2026
4ae999d
Merge main f595e44 into 006-release-pypi (#228)
Oct 18, 2026
7921a2e
T004: tests/test_install_pipx.py holds pipx's link, its skip and the …
Oct 18, 2026
d57b75d
T006: hold src/openrepotools to the standard library, and compile it …
Oct 18, 2026
fa44864
T010: rewrite the docstring of test_version_names_the_repository_and_…
Oct 18, 2026
b286953
T005: tests/test_package.py holds pyproject.toml, the payload map, a …
Oct 18, 2026
2e4a633
tasks.md: T005, T006 and T010 done, each built in its own lane-3 task…
Oct 18, 2026
2539a87
tasks.md: T004 done (accepted 7921a2e on model, scope and verify, 09:…
Oct 18, 2026
85ae5f0
Release tags and PyPI: the lead's ruling of 2026-10-18 on T007's repo…
Oct 18, 2026
a5c1538
T007: add the entry module, whose main() execs bash on the packaged i…
Oct 18, 2026
6b13ac2
tasks.md: T007 done (accepted 1134471 on model, scope and verify, 09:…
Oct 18, 2026
b67efa5
T008: openRepoTools leaves pipx's link to pipx, and refuses a venv-sh…
Oct 18, 2026
691c638
tasks.md: T008 done (accepted d5aa53b on model, scope and verify, 09:…
Oct 18, 2026
bf5e6e2
T026: put back the signals Python ignores before the exec, and refuse…
Oct 18, 2026
d3a6115
tasks.md: T026 done (accepted 28d9346 on model, scope and verify, 09:…
Oct 18, 2026
7ffd486
T009: tests/test_package_stamp.py holds the stamp reader, hatch's agr…
Oct 18, 2026
a8b5f7f
tasks.md: T009 done (accepted 55004f2 on model, scope and verify; che…
Oct 18, 2026
7e64851
T012: tests/test_install_pipx.py holds coexistence, pip's script, the…
Oct 18, 2026
e42c744
tasks.md: T012 done (accepted 75e27d0 on model, scope and verify; che…
Oct 18, 2026
902d199
T011: openRepoTools reads its package's stamp and prints its release …
Oct 18, 2026
628a46f
tasks.md: T011 done (accepted bf7264a on model, scope and verify; che…
Oct 18, 2026
3351007
Merge main 586dea2 into 006-release-pypi (#228)
Oct 18, 2026
03c3eb7
T013: openRepoTools names the other source beside pipx's link, refuse…
Oct 18, 2026
755ff9d
006 docs: the documents say what 628a46f does, and the counts follow …
Oct 18, 2026
32d9018
tasks.md: T013 done (accepted 55c9a02 on model, scope and verify: 538…
Oct 18, 2026
c1c1c71
006 docs 2: the stamp's readers say at run time, FR-047 is decided, T…
Oct 18, 2026
b7c111c
PR 1 review: tests for the guard's three non-ASCII folds, the count l…
Oct 18, 2026
65166ea
PR 1 review: the PATH report's silent skip is in cli-output.md, resea…
Oct 18, 2026
08743b0
PR 1 review: design.md's line citations are re-derived (#228)
Oct 18, 2026
fc8e37d
Merge main 08e7550 into 006-release-pypi (#228)
Oct 18, 2026
a3c300d
Merge main 55aae16 into 006-release-pypi (#228)
Oct 19, 2026
d10cfb1
#262: cli.py's exec line carries # NOSONAR for S8705, a false positiv…
Oct 19, 2026
992ece4
#262: cli.py's exec line ends in a bare # NOSONAR, the form SonarClou…
Oct 20, 2026
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
619 changes: 608 additions & 11 deletions openRepoTools

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions openspec/changes/release-tags-pypi/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-10-17
147 changes: 147 additions & 0 deletions openspec/changes/release-tags-pypi/clarifications.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Clarifications

_Captured during proposal council review. These constrain the design._
_Generated by /opsx:propose council on 2026-10-17_

The council reviewed `proposal.md` at `698cf30`. It had three read-only
reviewers: the product advocate (PA), the systems architect (SA) and the
adversary engineer (ADV). Lane openRepoTools-3, the lead, assigned the
verdicts on 2026-10-17 at about 22:4xZ. Its nine VALID verdicts are applied
to `proposal.md`, and its correction to the release owner's `LICENSE` check
followed lane openRepoTools-1's D3 and D4 (#186 comment 6242560541). The
five NOTED verdicts are below, and the three DISMISSED ones are at the end.

## Council-Identified Constraints

### N1: how the pipx link is detected

**Raised by:** systems-architect (SA1) and adversary-engineer (ADV3)

**Concern:** `plan_install_targets` runs first (`openRepoTools:1853`), and
the `jq` check comes only later, in `plan_hook_merge` (`openRepoTools:1863`,
its refusal at `:2500`). `unplaceable_kind` refuses every link, and the
generic refusal prints `rm -f -- "<dir>/openRepoTools"` (`openRepoTools:2466`).
On a machine with no `jq`, or under a future pipx metadata format, a
detection that read `pipx_metadata.json` would fail. The person would then
follow the printed `rm`, and nothing on `PATH` could run `--install` again.
Reading that file in bash without `jq` would also mean writing a JSON
parser: pipx writes it with sorted keys, so `injected_packages` comes before
`main_package`, and `"package"` keys appear more than once.

**Design impact:**
- The detection is the proposal's path rule ("The pipx link is skipped"). It
derives everything from the resolved link and asks only whether files and
directories exist. It parses no JSON, needs no `jq`, and takes nothing
from the environment or from the entry module.
- Moving the `jq` check ahead of `plan_install_targets` is the design's
call. If it moves, a missing `jq` refuses before any link advice is
printed.
- The fixtures mirror the venv layouts of pipx 1.11.1, 1.17.8 and 1.18.3,
under each of the three pipx homes the proposal names.

### N2: the grammar bash reads the stamp with

**Raised by:** systems-architect (SA2) and adversary-engineer (ADV4)

**Concern:** bash reads `_release.py` itself and trusts no environment
variable for the stamp. So the file needs a reader that cannot be talked
into a half-stamp, and that runs under the oldest bash the payload supports.

**Design impact:**
- The reader is a fixed grammar modelled on `pin_parse`
(`openRepoTools:458`). It reads lines, takes only the five names, and
never sources, imports or runs the file.
- It refuses, each with its own reason:
- an unreadable file;
- a partial stamp, meaning one that breaks the proposal's all-or-nothing
rule;
- a malformed field.
- It holds to bash 3.2: no `${x,,}`, `mapfile`, `declare -A` or `local -n`,
and an `awk -v` value carries one line only (AGENTS.md).
- The release build's stamp writer and this reader must agree. A test passes
the writer's output through the reader.

### N3: where the release notes live after the cutover

**Raised by:** systems-architect (SA3)

**Concern:** `docs/` goes to the spec leg
(`openspec/changes/migrate-to-triad/adoption-plan.yaml:183-184`). A release
step in the code leg that read `docs/release-notes/`, or a code-leg test of
the notes, would read across legs, like the follow-ups the plan already lists
(`adoption-plan.yaml:393-401`).

**Design impact:**
- There are two ways to meet the proposal's cutover invariant that no release
step reads across legs:
- the notes stay in `docs/release-notes/`, in the spec leg with `docs/`,
and `release.yml` reads none of them;
- or they move into the code leg, and the adoption plan carries an
exception.
- The design chooses. **The default** is that no release step reads them,
and the GitHub Release links to them.
- Lane openRepoTools-1's reading of the plan at openRepoShape v1.1.0 already
puts `docs/release-notes/` in spec (#186 comment 6242560541).

### N4: the file modes in hatchling's wheel

**Raised by:** systems-architect (SA4). The reviewer gave this point from
memory and marked it unverified.

**Concern:** the proposal's mode check (each packaged file's mode in the
wheel equals the commit's `100755` or `100644`) assumes that hatchling
1.27.0's reproducible wheel keeps 0644 and 0755.

**Design impact:**
- Check whether hatchling 1.27.0's reproducible wheel keeps 0644/0755. If it
does not, the installer must set each placed file's mode itself.
- Either way, the design relies on the installer for modes, never on the
wheel. `--install` already sets 755 on each command it places, and 644 or
600 on the rest.
- **Checked while writing this file.** In hatchling 1.27.0's published wheel
(sha256
`d3a2f3567c4f926ea39849cdf924c7e99e6686c9c8e288ae1037c8fa2a5d937b`),
`normalize_file_permissions`
(`hatchling/builders/utils.py:96-110`) maps any mode to 0644, or to 0755
when the owner's execute bit is set. The wheel builder applies it whenever
the target is reproducible (`hatchling/builders/wheel.py:97-101` and
`:140`), and `reproducible` defaults to true
(`hatchling/builders/config.py:377-383`). So the mode check can hold as
written. The design still relies on the installer.

### N5: the wording of VALID 9's refusal and report, and how pip's script is recognised

**Raised by:** adversary-engineer (ADV2)

**Concern:** the proposal makes `--install` refuse to replace pip's console
script for openrepotools, and makes a package-mode `--install` report when
the first `openRepoTools` on `PATH` is not the package's console script.
Neither line's text is fixed yet, and neither is the test that tells pip's
script from any other regular file.

**Design impact:**
- The design fixes the exact text of the refusal and of the shadow report.
- The refusal names the file and says it is pip's console script for
openrepotools. It says nothing was installed, and names the way out.
- The report names the `openRepoTools` that `PATH` finds first, and the
console script it expected.
- A console script is recognised by its shebang, a `#!` line naming a
Python, together with the import of the `openrepotools` entry point that
pip's console-script template writes.

## Considered and dismissed

These were raised and ruled out. The design does not reopen them.

- **D1: a sixth `--version` line read from the receipt** (PA3's first
option). This would be a new capability, out of scope for v1.1.0. The
proposal's non-goal "`--version` names the command's release, not the
placed files'" covers it.
- **D2: binding the stamp's environment variables to the payload
directory** (SA2's variant: pass the payload directory, compare it with
`pwd -P`, then unset the variables). Bash reading `_release.py` beside its
own payload replaces it, and leaves no environment surface at all.
- **D3: having the entry module pass its venv to bash** (ADV3's
suggestion). It only works when the package itself runs. A checkout's or
the one-line install's `--install` must recognise pipx's link too, and the
proposal's path rule covers every mode.
Loading
Loading