Skip to content

Commit 0564e1f

Browse files
committed
fix(ci): resolve PR 37 review failures
1 parent ea90cbe commit 0564e1f

18 files changed

Lines changed: 88 additions & 45 deletions

.github/workflows/homebrew-tap.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Update Homebrew tap
33
on:
44
push:
55
tags:
6-
- "v[0-9]+.[0-9]+.[0-9]+"
6+
- "v[0-9]*.[0-9]*.[0-9]*"
77
workflow_dispatch:
88
inputs:
99
version:

.github/workflows/linux-installer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
tags:
66
# Same scheme as release-pythinker-cli.yml and windows-installer.yml.
7-
- "v[0-9]+.[0-9]+.[0-9]+"
7+
- "v[0-9]*.[0-9]*.[0-9]*"
88
workflow_dispatch:
99
inputs:
1010
version:

.github/workflows/promote-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ name: Promote release
1616
on:
1717
push:
1818
tags:
19-
- "v[0-9]+.[0-9]+.[0-9]+"
19+
- "v[0-9]*.[0-9]*.[0-9]*"
2020
workflow_dispatch:
2121
inputs:
2222
tag:

.github/workflows/release-pythinker-cli.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Release (pythinker-code)
33
on:
44
push:
55
tags:
6-
- "v[0-9]+.[0-9]+.[0-9]+"
6+
- "v[0-9]*.[0-9]*.[0-9]*"
77

88
permissions:
99
contents: write

.github/workflows/windows-installer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
tags:
66
# Match the existing PyPI release workflow's tag scheme: v<MAJOR>.<MINOR>.<PATCH>.
7-
- "v[0-9]+.[0-9]+.[0-9]+"
7+
- "v[0-9]*.[0-9]*.[0-9]*"
88
workflow_dispatch:
99
inputs:
1010
version:

docs/superpowers/plans/2026-05-31-release-orchestration-p1-release-tool.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ There are no admin/secret/App actions in P1.
3737
- `tests/ui_and_conv/test_shell_update.py` — add the brew-unchanged + `PYTHINKER_MANAGED` regression tests (this is the file that actually imports `update`; `tests/test_release_update_pipeline.py` is workflow-text only and does NOT import `update`).
3838
- `tests/test_release_update_pipeline.py` — add a test asserting `changelog-entry-required.yml` skips on both the `chore(release)*` title (line 54) and the `release/*` head branch (line 57) — the skip-contract that `release.py.open_pr()` depends on. (Workflow-text file, the correct home for this assertion.)
3939
- `docs/en/release-notes/breaking-changes.md` — add a `## Unreleased` anchor (currently absent) so `release.py`'s heading promotion is uniform across all three changelog files.
40-
- `.agents/skills/release/SKILL.md` — repoint the `update_files` (lines 22-25) and `uv_sync` (line 35) nodes at `python scripts/release.py`.
40+
- `.agents/skills/release/SKILL.md` — repoint the `update_files` (lines 22-25) and `uv_sync` (line 35) nodes at `uv run python scripts/release.py`.
4141

4242
---
4343

@@ -140,24 +140,17 @@ There are no admin/secret/App actions in P1.
140140
):
141141
```
142142
6. - [ ] Run and see it pass. `uv run pytest tests/test_release_py.py -q``2 passed`.
143-
7. - [ ] Update the CI caller. In `.github/workflows/ci-pythinker-cli.yml`, change the block at lines 253-256 from:
143+
7. - [ ] Update the CI caller. In `.github/workflows/ci-pythinker-cli.yml`, change the existing dependency-check block to use the project-managed launcher and include review:
144144
```yaml
145-
python scripts/check_pythinker_dependency_versions.py \
146-
--root-pyproject pyproject.toml \
147-
--pythinker-core-pyproject packages/pythinker-core/pyproject.toml \
148-
--pythinker-host-pyproject packages/pythinker-host/pyproject.toml
149-
```
150-
to (append the review line; mind the trailing `\` on the host line):
151-
```yaml
152-
python scripts/check_pythinker_dependency_versions.py \
145+
uv run python scripts/check_pythinker_dependency_versions.py \
153146
--root-pyproject pyproject.toml \
154147
--pythinker-core-pyproject packages/pythinker-core/pyproject.toml \
155148
--pythinker-host-pyproject packages/pythinker-host/pyproject.toml \
156149
--pythinker-review-pyproject packages/pythinker-review/pyproject.toml
157150
```
158151
8. - [ ] Update the release caller. In `.github/workflows/release-pythinker-cli.yml`, apply the identical change to the block at lines 57-60 (same trailing-`\` addition on the host line + the new review line).
159-
9. - [ ] Sanity-check the real workspace passes. `python scripts/check_pythinker_dependency_versions.py --root-pyproject pyproject.toml --pythinker-core-pyproject packages/pythinker-core/pyproject.toml --pythinker-host-pyproject packages/pythinker-host/pyproject.toml --pythinker-review-pyproject packages/pythinker-review/pyproject.toml``ok: pythinker-code dependencies match workspace package versions`.
160-
10. - [ ] Lint the workflows. `uvx actionlint .github/workflows/ci-pythinker-cli.yml .github/workflows/release-pythinker-cli.yml` (if `actionlint` is unavailable, fall back to `python -c "import yaml,sys; [yaml.safe_load(open(f)) for f in sys.argv[1:]]" .github/workflows/ci-pythinker-cli.yml .github/workflows/release-pythinker-cli.yml`) → no output / exit 0.
152+
9. - [ ] Sanity-check the real workspace passes. `uv run python scripts/check_pythinker_dependency_versions.py --root-pyproject pyproject.toml --pythinker-core-pyproject packages/pythinker-core/pyproject.toml --pythinker-host-pyproject packages/pythinker-host/pyproject.toml --pythinker-review-pyproject packages/pythinker-review/pyproject.toml``ok: pythinker-code dependencies match workspace package versions`.
153+
10. - [ ] Lint the workflows. `uvx actionlint .github/workflows/ci-pythinker-cli.yml .github/workflows/release-pythinker-cli.yml` (if `actionlint` is unavailable, fall back to `uv run python -c "import yaml,sys; [yaml.safe_load(open(f)) for f in sys.argv[1:]]" .github/workflows/ci-pythinker-cli.yml .github/workflows/release-pythinker-cli.yml`) → no output / exit 0.
161154
11. - [ ] Commit. `git add scripts/check_pythinker_dependency_versions.py tests/test_release_py.py .github/workflows/ci-pythinker-cli.yml .github/workflows/release-pythinker-cli.yml && git commit -m "feat(release): enforce pythinker-review pin in dependency check"`
162155

163156
---
@@ -699,7 +692,7 @@ The git/gh/uv orchestration is genuine I/O and is verified by `--dry-run` + a re
699692
(No dead `text = ROOT_PYPROJECT` line — the anchor check is the `CHANGELOG_FILES` loop inside `validate()`.)
700693
2. - [ ] Lint the module. `uv run ruff check scripts/release.py && uv run ruff format --check scripts/release.py` → exit 0 (run `uv run ruff format scripts/release.py` first if formatting fails). There should be zero F841/unused-variable findings.
701694
3. - [ ] Confirm the unit tests still pass. `uv run pytest tests/test_release_py.py -q` → all pure-function tests pass (orchestration is not under pytest).
702-
4. - [ ] Dry-run verification (no writes). On a clean tree synced to origin/main: `python scripts/release.py --set-version 0.28.0 --dry-run`. Expected: prints the `warning` only if Unreleased body is empty, then `[dry-run] would rewrite SSOT -> 0.28.0`, `[dry-run] git switch -c release/0.28.0`, ... `[dry-run] gh pr create ...`, and the tag-order block ending `git tag v0.28.0 && git push origin v0.28.0`. Confirm `git status --porcelain` is still empty afterward (dry-run wrote nothing).
695+
4. - [ ] Dry-run verification (no writes). On a clean tree synced to origin/main: `uv run python scripts/release.py --set-version 0.28.0 --dry-run`. Expected: prints the `warning` only if Unreleased body is empty, then `[dry-run] would rewrite SSOT -> 0.28.0`, `[dry-run] git switch -c release/0.28.0`, ... `[dry-run] gh pr create ...`, and the tag-order block ending `git tag v0.28.0 && git push origin v0.28.0`. Confirm `git status --porcelain` is still empty afterward (dry-run wrote nothing).
703696
5. - [ ] Commit. `git add scripts/release.py && git commit -m "feat(release): add 4-phase orchestration with uv lock + frozen-sync gate"`
704697

705698
---
@@ -985,7 +978,7 @@ Brew must NOT set `PYTHINKER_MANAGED`; it keeps its existing cellar path-sniff (
985978
to:
986979
```
987980
update_files: |md
988-
Run `python scripts/release.py --set-version X.Y.Z [--bump-core A.B.C --bump-host A.B.C]`.
981+
Run `uv run python scripts/release.py --set-version X.Y.Z [--bump-core A.B.C --bump-host A.B.C]`.
989982
It rewrites pyproject.toml:3, the sub-package pins, uv.lock, all three changelog files
990983
(preserving the authored Unreleased body), and the README/asset names from the single
991984
source of truth, then runs the local gates and opens the `release/X.Y.Z` PR.
@@ -1012,7 +1005,7 @@ Brew must NOT set `PYTHINKER_MANAGED`; it keeps its existing cellar path-sniff (
10121005
Because every task committed to the single `p1/release-tool` branch (Task 1 onward), the required dep-check arg and both workflow-caller edits are atomic in one PR — there is no cherry-pick or stacked-PR reconciliation to do.
10131006

10141007
1. - [ ] Confirm the full local gate set is green before pushing. `uv run pytest tests/test_release_py.py tests/test_version_lockstep.py tests/ui_and_conv/test_shell_update.py tests/test_release_update_pipeline.py -q` → all pass; `uv run ruff check scripts/release.py tests/test_release_py.py tests/test_version_lockstep.py && uv run ruff format --check scripts/release.py tests/test_release_py.py tests/test_version_lockstep.py` → exit 0; `uv run pyright src/pythinker_code/ui/shell/update.py` → 0 errors.
1015-
2. - [ ] Confirm the workspace version checks pass exactly as CI will run them: `python scripts/check_pythinker_dependency_versions.py --root-pyproject pyproject.toml --pythinker-core-pyproject packages/pythinker-core/pyproject.toml --pythinker-host-pyproject packages/pythinker-host/pyproject.toml --pythinker-review-pyproject packages/pythinker-review/pyproject.toml``ok: pythinker-code dependencies match workspace package versions`.
1008+
2. - [ ] Confirm the workspace version checks pass exactly as CI will run them: `uv run python scripts/check_pythinker_dependency_versions.py --root-pyproject pyproject.toml --pythinker-core-pyproject packages/pythinker-core/pyproject.toml --pythinker-host-pyproject packages/pythinker-host/pyproject.toml --pythinker-review-pyproject packages/pythinker-review/pyproject.toml``ok: pythinker-code dependencies match workspace package versions`.
10161009
3. - [ ] Confirm the branch history is one coherent stack. `git log --oneline -8 p1/release-tool` shows the dep-check, release.py (validation/rewrites/promotion/asset/orchestration), lockstep, skip-contract, updater, and SKILL commits all on `p1/release-tool`. Push: `git push -u origin p1/release-tool`.
10171010
4. - [ ] Open the PR. `gh pr create --base main --head p1/release-tool --title "feat(release): release.py + version lockstep SSOT (P1)" --body "Adds scripts/release.py (4-phase SSOT release orchestrator), tests/test_version_lockstep.py (every-PR version guard), the pythinker-review dependency-check tuple (with both CI callers updated atomically), the changelog-workflow skip-contract assertion, and the PYTHINKER_MANAGED updater hook with a brew-unchanged regression test and a managed-channel rendered hint. No new agent runtime deps (C3)."`
10181011
5. - [ ] Wait for CI and CodeRabbit. Confirm required checks (`check`, `test`, `changelog`, `release-validate` as applicable) pass and the `CodeRabbit` commit status on the PR head SHA is `success` (C2) before merging. Read CodeRabbit's "Actionable comments" and resolve or surface them — do not merge past unresolved findings. Per the project CLAUDE.md / MEMORY note, reject a CodeRabbit camelCase-for-Python finding if one appears (false positive; codebase is snake_case).
@@ -1026,12 +1019,12 @@ Because every task committed to the single `p1/release-tool` branch (Task 1 onwa
10261019

10271020
**End-to-end rehearsal (the proof, no tag pushed):**
10281021

1029-
1. - [ ] On a clean tree synced to `origin/main`, run a real (non-dry-run) rehearsal to a throwaway version: `python scripts/release.py --set-version 0.28.0`. Expected: Phase 1 validates all three changelog anchors; Phase 2 rewrites the files + runs `uv lock`; Phase 3 runs all four gates (`check_version_tag`, the extended `check_pythinker_dependency_versions`, `uv sync --frozen --all-extras --all-packages`, `pytest tests/test_version_lockstep.py`) plus the `grep -qF` checks — all green; Phase 4 creates branch `release/0.28.0`, commits `chore(release): prepare 0.28.0`, pushes, and opens a PR, then prints `git tag v0.28.0 && git push origin v0.28.0`.
1022+
1. - [ ] On a clean tree synced to `origin/main`, run a real (non-dry-run) rehearsal to a throwaway version: `uv run python scripts/release.py --set-version 0.28.0`. Expected: Phase 1 validates all three changelog anchors; Phase 2 rewrites the files + runs `uv lock`; Phase 3 runs all four gates (`check_version_tag`, the extended `check_pythinker_dependency_versions`, `uv sync --frozen --all-extras --all-packages`, `pytest tests/test_version_lockstep.py`) plus the `grep -qF` checks — all green; Phase 4 creates branch `release/0.28.0`, commits `chore(release): prepare 0.28.0`, pushes, and opens a PR, then prints `git tag v0.28.0 && git push origin v0.28.0`.
10301023
2. - [ ] Prove the stress-test catch is covered: confirm `uv.lock` changed in the rehearsal commit (`git show --stat release/0.28.0 | grep uv.lock`) and that `uv sync --frozen --all-extras --all-packages` ran clean inside Phase 3 (no "lockfile out of date" error). This is the exact failure that would otherwise turn the release PR's own CI red.
10311024
3. - [ ] Confirm the documented exception held: `grep -n "version 0.28.0" docs/en/guides/getting-started.md` returns nothing — the `--version 0.27.0` flag example is unchanged (still `--version 0.27.0`), while `What's New in 0.28.0`, `pythinker-code==0.28.0`, and `PythinkerSetup-0.28.0.exe` are all present in their respective files.
10321025
4. - [ ] Confirm the skip-contract makes the rehearsal PR pass the changelog gate: the PR head branch is `release/0.28.0` and the title is `chore(release): prepare 0.28.0`, so `changelog-entry-required.yml` skips (matching the guards Task 9 asserts) and does not block on the now-empty `## Unreleased`.
10331026
5. - [ ] Tear down the rehearsal (no tag was pushed): `gh pr close release/0.28.0 --delete-branch` and `git switch main && git branch -D release/0.28.0` and `git push origin --delete release/0.28.0`. Verify `git log --oneline -1 origin/main` is untouched (C1: nothing reached main, no tag was created).
1034-
6. - [ ] Sub-package rehearsal (optional, validates `--bump-core`): `python scripts/release.py --set-version 0.28.0 --bump-core 1.2.0 --dry-run` → prints the ordered tag sequence (`pythinker-core-1.2.0` first, wait-for-PyPI note, then `v0.28.0`) and the intended pin rewrite `pythinker-core[contrib]==1.2.0`, writing nothing.
1027+
6. - [ ] Sub-package rehearsal (optional, validates `--bump-core`): `uv run python scripts/release.py --set-version 0.28.0 --bump-core 1.2.0 --dry-run` → prints the ordered tag sequence (`pythinker-core-1.2.0` first, wait-for-PyPI note, then `v0.28.0`) and the intended pin rewrite `pythinker-core[contrib]==1.2.0`, writing nothing.
10351028

10361029
**Files relevant to this phase (absolute paths):**
10371030
- `/home/ai/Projects/pythinker-code-main/scripts/release.py`

docs/superpowers/plans/2026-05-31-release-orchestration-p2-distribution-channels.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ name: Docker (GHCR)
191191
on:
192192
push:
193193
tags:
194-
- "v[0-9]+.[0-9]+.[0-9]+"
194+
- "v[0-9]*.[0-9]*.[0-9]*"
195195
workflow_dispatch:
196196
inputs:
197197
version:
@@ -830,7 +830,7 @@ name: Update Scoop bucket
830830
on:
831831
push:
832832
tags:
833-
- "v[0-9]+.[0-9]+.[0-9]+"
833+
- "v[0-9]*.[0-9]*.[0-9]*"
834834
workflow_dispatch:
835835
inputs:
836836
version:

docs/superpowers/plans/2026-05-31-welcome-banner-redesign.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ def test_welcome_chip_renders_in_footer_not_header(monkeypatch):
5959
assert "changelog" in lines[-1]
6060
assert all("changelog" not in ln for ln in lines[:3])
6161

62-
6362
def test_welcome_info_grid_has_no_pipe_separator(monkeypatch):
6463
from pythinker_code.ui.shell import WelcomeInfoItem
6564

@@ -76,7 +75,6 @@ def test_welcome_info_grid_has_no_pipe_separator(monkeypatch):
7675
assert dir_line.count("") == 2
7776
assert "/tmp/proj" in dir_line
7877

79-
8078
def test_welcome_strapline_and_help_on_separate_lines(monkeypatch):
8179
console = Console(record=True, width=120, color_system=None)
8280
monkeypatch.setattr(shell_module, "console", console)
@@ -96,6 +94,7 @@ def test_welcome_strapline_and_help_on_separate_lines(monkeypatch):
9694
- [ ] **Step 2: Run the new tests and confirm they fail against the current banner**
9795

9896
Run:
97+
9998
```bash
10099
uv run pytest tests/ui_and_conv/test_shell_welcome_info.py -q -k "footer or pipe_separator or separate_lines"
101100
```
@@ -108,6 +107,7 @@ Expected: all three FAIL.
108107
- [ ] **Step 3: Confirm the 5 existing tests still pass (no regression introduced by the new tests)**
109108

110109
Run:
110+
111111
```bash
112112
uv run pytest tests/ui_and_conv/test_shell_welcome_info.py -q -k "not (footer or pipe_separator or separate_lines)"
113113
```
@@ -131,8 +131,11 @@ git commit -m "test: lock welcome banner redesign (footer chip, no pipe, split s
131131
> `_WELCOME_PANEL_CHROME_WIDTH`), cell-aware truncation helpers
132132
> (`_truncate_middle_to_width`, `_welcome_value`, `_welcome_tip_lines`), a
133133
> `Table.grid(...)` build, and a `width >= 68` logo-beside-text vs stacked
134-
> branch. Read the block below as the original footer-chip intent, not the
135-
> literal final code.
134+
> branch. For the final implementation, open
135+
> `src/pythinker_code/ui/shell/__init__.py` and search for
136+
> `_print_welcome_info` to inspect the responsive/truncation logic and
137+
> logo layout. Read the block below as the original footer-chip intent,
138+
> not the literal final code.
136139
137140
**Files:**
138141
- Modify: `src/pythinker_code/ui/shell/__init__.py` (function `_print_welcome_info`, lines ~1934–2008; constant `_PYTHINKER_BORDER`, line 1864)
@@ -236,6 +239,7 @@ Leave the surrounding `_LOGO_*` color constants and `_LOGO` exactly as they are.
236239
- [ ] **Step 3: Confirm `_PYTHINKER_BORDER` has no remaining references**
237240

238241
Run:
242+
239243
```bash
240244
grep -rn "_PYTHINKER_BORDER" src/ tests/ tests_e2e/
241245
```
@@ -245,6 +249,7 @@ Expected: no output (zero matches). If any match remains, you removed the consta
245249
- [ ] **Step 4: Run the full banner test file**
246250

247251
Run:
252+
248253
```bash
249254
uv run pytest tests/ui_and_conv/test_shell_welcome_info.py -q
250255
```
@@ -299,6 +304,7 @@ for width in (80, 100, 120):
299304
```
300305

301306
Run:
307+
302308
```bash
303309
uv run python /tmp/verify_banner.py
304310
```
@@ -308,6 +314,7 @@ Expected: the antenna (`●`/`│`) floats above the headline; headline/straplin
308314
- [ ] **Step 2: Lint the changed file**
309315

310316
Run:
317+
311318
```bash
312319
uv run ruff check src/pythinker_code/ui/shell/__init__.py
313320
```
@@ -317,6 +324,7 @@ Expected: no errors. (Line-length limit is 100; the code blocks above are within
317324
- [ ] **Step 3: Type-check the changed file (project type gate)**
318325

319326
Run:
327+
320328
```bash
321329
uv run pyright src/pythinker_code/ui/shell/__init__.py
322330
```
@@ -326,6 +334,7 @@ Expected: no new errors introduced by this change. If `pyright` is not the confi
326334
- [ ] **Step 4: Run the broader UI test directory to catch unexpected fallout**
327335

328336
Run:
337+
329338
```bash
330339
uv run pytest tests/ui_and_conv/ -q
331340
```

0 commit comments

Comments
 (0)