Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5486b50
docs(36-03): record PR #11 merge, MAIN-01 CI evidence, and ancestry p…
thezoid Aug 2, 2026
c988483
docs(36): close phase 36 mainline reconciliation, all 7 MAIN requirem…
thezoid Aug 2, 2026
149a10b
docs(36): record phase 36 completion in STATE.md
thezoid Aug 2, 2026
f90c7f2
docs(36): record PR #21 SSE breakage under fastapi 0.141
thezoid Aug 2, 2026
c9392d4
docs(37): empirical wheel baseline, answers PKG-06 phase 43 gate
thezoid Aug 2, 2026
d816c8e
docs(37): smart discuss context with autonomous decisions
thezoid Aug 3, 2026
fc91154
docs(37): create phase plan for distributable artifact
thezoid Aug 3, 2026
8a350fa
refactor(37-01): relocate alert sounds into core/sounds package
thezoid Aug 3, 2026
48327ab
build(37-01): ship data files in the wheel via package-data globs
thezoid Aug 3, 2026
09dab0e
docs(37-01): complete data-files-in-the-wheel plan
thezoid Aug 3, 2026
a1fa5ee
build(37-02): declare the dependencies the code actually imports
thezoid Aug 3, 2026
c8c8655
docs(37-02): complete truthful-dependency-declaration plan
thezoid Aug 3, 2026
e33efa8
refactor(37-03): add bundled_plugins_dir() as the named plugin-root seam
thezoid Aug 3, 2026
cc3b4b8
docs(37-03): record the answered PKG-06 result in the Phase 43 resear…
thezoid Aug 3, 2026
6edce37
docs(37-03): complete bundled-plugin-root seam plan
thezoid Aug 3, 2026
6ca6d1e
feat(37-04): add scripts/verify_wheel.py, the five-assertion wheel gate
thezoid Aug 3, 2026
e013e55
ci(37-04): add a wheel job that installs without requirements.txt
thezoid Aug 3, 2026
6c8f0f6
docs(37-04): complete the wheel gate plan
thezoid Aug 3, 2026
db481cc
Merge remote-tracking branch 'origin/master' into chore/v4.0-mileston…
thezoid Aug 3, 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
37 changes: 37 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,40 @@
# workflow fail to compile -- instant failure, zero jobs scheduled.
SHOPBOT_DATA_DIR: ${{ runner.temp }}/shopbot
run: pytest --tb=short

# Builds the wheel and installs it into a clean virtualenv holding nothing but
# the wheel and its own declared dependencies. This job must NEVER install from
# requirements.txt and must never install the package with -e. The test job
# above does install from requirements.txt, deliberately; doing the same here
# would hide every dependency and data file that the wheel itself is missing,
# which is the entire class of defect this job exists to catch. Ubuntu is not
# optional either: colorama and pyyaml reach a Windows install transitively and
# a Windows-only run would keep missing exactly that failure mode.
wheel:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]

steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Install build tooling
# Only pip and build. Nothing here reaches the clean venv, which the
# verification script creates itself and installs the wheel into.
run: |
python -m pip install --upgrade pip
pip install build
- name: Build wheel
run: python -m build --wheel --outdir dist
- name: Verify wheel
env:
# Same step-level rule as the Test step above: the `runner` context does
# not exist in job-level `env:`, and using it there fails the whole
# workflow to compile rather than failing this one job.
SHOPBOT_DATA_DIR: ${{ runner.temp }}/shopbot-wheel
WHEEL_VENV: ${{ runner.temp }}/wheelenv
run: python scripts/verify_wheel.py --wheel-dir dist --venv "${{ env.WHEEL_VENV }}"
Comment on lines +56 to +82
24 changes: 12 additions & 12 deletions .planning/REQUIREMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@

The built wheel does not run. This is the precondition for release-please being worth anything.

- [ ] **PKG-01**: An installed wheel contains `web/static/*`, `web/templates/*`, and `sounds/*`, so `create_app()` does not raise `RuntimeError` on the `StaticFiles` mount
- [ ] **PKG-02**: `pyproject.toml` declares every actual runtime dependency, not just `platformdirs==4.10.0`
- [ ] **PKG-03**: `websockets`, `starlette`, `httpx`, and `requests` are each declared in the correct place (all four are imported or required today and none is declared where it is used)
- [ ] **PKG-04**: Dead `selenium` and `webdriver-manager` pins are removed from `requirements.txt`, which also removes a recurring Dependabot noise source
- [ ] **PKG-05**: A CI job installs the built wheel into a clean environment and asserts that `shoppybot web` starts and a sound file resolves
- [ ] **PKG-06**: `bundled_plugins_dir()` is verified to resolve correctly from an installed wheel (blocks EXT-03; if it fails, the fix is `importlib.resources` and belongs to this workstream)
- [x] **PKG-01**: An installed wheel contains `web/static/*`, `web/templates/*`, and `sounds/*`, so `create_app()` does not raise `RuntimeError` on the `StaticFiles` mount
- [x] **PKG-02**: `pyproject.toml` declares every actual runtime dependency, not just `platformdirs==4.10.0`
- [x] **PKG-03**: `websockets`, `starlette`, `httpx`, and `requests` are each declared in the correct place (all four are imported or required today and none is declared where it is used)
- [x] **PKG-04**: Dead `selenium` and `webdriver-manager` pins are removed from `requirements.txt`, which also removes a recurring Dependabot noise source
- [x] **PKG-05**: A CI job installs the built wheel into a clean environment and asserts that `shoppybot web` starts and a sound file resolves
- [x] **PKG-06**: `bundled_plugins_dir()` is verified to resolve correctly from an installed wheel (blocks EXT-03; if it fails, the fix is `importlib.resources` and belongs to this workstream)

### C. Public-Repo Readiness (PUB)

Expand Down Expand Up @@ -181,12 +181,12 @@ Populated during roadmap creation, 2026-08-02. Every v1 requirement maps to exac
| MAIN-05 | Phase 36 | Complete |
| MAIN-06 | Phase 36 | Complete |
| MAIN-07 | Phase 36 | Complete |
| PKG-01 | Phase 37 | Pending |
| PKG-02 | Phase 37 | Pending |
| PKG-03 | Phase 37 | Pending |
| PKG-04 | Phase 37 | Pending |
| PKG-05 | Phase 37 | Pending |
| PKG-06 | Phase 37 | Pending |
| PKG-01 | Phase 37 | Complete |
| PKG-02 | Phase 37 | Complete |
| PKG-03 | Phase 37 | Complete |
| PKG-04 | Phase 37 | Complete |
| PKG-05 | Phase 37 | Complete |
| PKG-06 | Phase 37 | Complete |
| PUB-01 | Phase 40 | Pending |
| PUB-02 | Phase 40 | Pending |
| PUB-03 | Phase 40 | Pending |
Expand Down
25 changes: 20 additions & 5 deletions .planning/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Audit: `.planning/milestones/v4.2-MILESTONE-AUDIT.md` (status: tech_debt — 20/
### 🔄 v5.0 Real Release & Plugin Ecosystem (Phases 36-50) — IN PROGRESS

- [x] **Phase 36: Mainline Reconciliation** — `master` becomes the real ShopPyBot and its suite runs in CI for the first time (MAIN-01..07) (completed 2026-08-02)
- [ ] **Phase 37: Distributable Artifact** — the built wheel actually runs, so publishing one is worth doing (PKG-01..06)
- [x] **Phase 37: Distributable Artifact** — the built wheel actually runs, so publishing one is worth doing (PKG-01..06) (completed 2026-08-03)
- [ ] **Phase 38: Scanning to Zero** — every scanner reports zero real findings and the checks that produce them are required (SCAN-01..11)
- [ ] **Phase 39: Quality Floor** — lint, format, typecheck, and coverage enforced in CI before the milestone's new code lands (QUAL-01..09)
- [ ] **Phase 40: Public-Repo Readiness** — LICENSE, current README, honest sample config, CODEOWNERS, drift corrected (PUB-01..09)
Expand Down Expand Up @@ -173,8 +173,22 @@ Plans:
4. `bundled_plugins_dir()` called from an installed wheel returns a directory containing the 7 bundled plugins, and that result is recorded as the input Phase 43 (EXT-03) depends on.
5. `requirements.txt` pins neither `selenium` nor `webdriver-manager`, and no Dependabot alert references either.

**Plans**: TBD
**Note**: PKG-06 is a hard gate on Phase 43. If the bundled root does not survive a wheel install, the `importlib.resources` fix belongs here, not to workstream H.
**Plans**: 4 plans (strictly sequential, waves 1 through 4; executors share the main working tree with no worktree isolation, so concurrent commits are not safe)
Plans:

- [x] 37-01-PLAN.md: relocate `sounds/` to `core/sounds/`, resolve it through `importlib.resources`, declare package-data so the wheel ships the sounds plus the six `web/static` and `web/templates` files (PKG-01)
- [x] 37-02-PLAN.md: declare the nine dependencies the production tree actually imports, move `pygame` and `httpx` to extras, delete the dead `selenium` and `webdriver-manager` pins, prove it in a clean venv (PKG-02, PKG-03, PKG-04)
- [x] 37-03-PLAN.md: create `core.paths.bundled_plugins_dir()` as the named seam, prove the refactor is behavior-preserving, record the answered PKG-06 result where Phase 43 reads it (PKG-06)
- [x] 37-04-PLAN.md: add `scripts/verify_wheel.py` and a `wheel` CI job on both runners that installs the built wheel with no `requirements.txt` and runs the five locked assertions (PKG-05)

**Planning corrections** (from `37-SCOUT.md`, verified against a real built-and-installed wheel 2026-08-02, these supersede the requirement text where they conflict):

- The wheel is not degraded, it is dead. `shoppybot --help` fails at import on `pydantic_settings` before any command dispatch, so execution never reaches the `StaticFiles` mount that PKG-01 and PKG-05 are written around. The cheapest correct first assertion is `shoppybot --help` exiting 0, not launching a server.
- PKG-03's named list is incomplete and partly wrong. `websockets` and `starlette` are already present transitively and are not the failure cause; `pydantic-settings` is the highest-impact omission and PKG-03 does not name it. `colorama` and `pyyaml` are also undeclared unconditional imports of `logger.py`, invisible to a Windows-only probe because `click` and `uvicorn[standard]` happen to supply them there but not on Linux.
- PKG-06 names `bundled_plugins_dir()` as though it exists. It does not; the real mechanism is a bare expression at `core/orchestrator.py:814`. Plan 37-03 creates the accessor for real.
- `sounds/` is structurally unshippable, not merely unshipped: `utils` is a top-level module, so `SOUNDS_DIR` resolves to `site-packages/sounds`, which cannot be package data of any package. Plan 37-01 relocates it rather than adding a config line.

**Note**: PKG-06 is a hard gate on Phase 43, and it is ANSWERED favorably. The bundled root resolves to `site-packages/plugins` with all 7 plugins intact on a real wheel install, so the `importlib.resources` fix is NOT needed and does not belong to this phase. Plan 37-03 converts that one-off observation into a named accessor, a regression test, and a CI assertion so it cannot rot before Phase 43 consumes it.

### Phase 38: Scanning to Zero

Expand Down Expand Up @@ -268,7 +282,8 @@ Plans:

**Plans**: TBD
**UI hint**: yes
**Research flag**: Blocked on PKG-06's factual answer. If `bundled_plugins_dir()` does not resolve from an installed wheel, the `importlib.resources` fix is Phase 37 work, not this phase's.
**Research flag**: ANSWERED by plan 37-03, this phase is unblocked. `core.paths.bundled_plugins_dir()` now exists as the named accessor, and calling it from a clean Python 3.13 venv holding only the built wheel (no extras, no `requirements.txt`) returns `<venv>/Lib/site-packages/plugins` containing exactly the 7 bundled `shopbot_plugin_*.py` files (amazon, bestbuy, gamestop, newegg, squareenix, target, walmart). No `importlib.resources` rewrite is needed and none belongs to Phase 37. `tests/test_paths.py` guards the result, `core/orchestrator.py` and `core/service.py` call the accessor rather than inlining the path, and a seam guard already enforces this phase's criterion 5.
**Caveat carried forward** (from `37-SCOUT.md` correction 2, retained deliberately): the bundled root lands as a top-level `site-packages/plugins` entry, so any other distribution shipping a top-level `plugins` package would collide with it. It resolves correctly today and does not block this phase, but the multi-root design here should treat the bundled root's location as something it owns rather than something it inherits.

### Phase 44: Provenance, Load-Boundary Integrity & Run Lock

Expand Down Expand Up @@ -399,7 +414,7 @@ All requirements satisfied across v1 (44) + v2.0 (22) + v3.0 (18) + v4.0 (17) +
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 36. Mainline Reconciliation | 5/5 | Complete | 2026-08-02 |
| 37. Distributable Artifact | 0/TBD | Not started | - |
| 37. Distributable Artifact | 4/4 | Complete | 2026-08-03 |
| 38. Scanning to Zero | 0/TBD | Not started | - |
| 39. Quality Floor | 0/TBD | Not started | - |
| 40. Public-Repo Readiness | 0/TBD | Not started | - |
Expand Down
Loading