Skip to content

Commit 19030de

Browse files
lesnik512claude
andcommitted
docs(story-1.1): mark scaffold story complete, status → review
- All 6 Tasks and 27 Subtasks marked [x] - Dev Agent Record populated: Implementation Plan, Debug Log, Completion Notes - File List: 14 committed files + transient/gitignored - AC1-AC7 verification notes in Completion Notes - 2 documented deviations from PRD: httpx2 constraint tightened from b1 to GA (PRD doc cleanup TBD); src/ layout vs modern-di's flat layout - Status changed in-progress → review Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent fe4df95 commit 19030de

1 file changed

Lines changed: 110 additions & 48 deletions

File tree

‎docs/stories/1-1-project-scaffold-and-tooling.md‎

Lines changed: 110 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ story_key: 1-1-project-scaffold-and-tooling
33
epic: 1
44
story: 1
55
title: Project scaffold and tooling
6-
status: in-progress
6+
status: review
77
created: 2026-05-12
8+
completed: 2026-05-13
89
input_documents:
910
- /Users/kevinsmith/src/pypi/base-client/docs/prd.md
1011
- /Users/kevinsmith/src/pypi/base-client/docs/architecture.md
@@ -37,48 +38,48 @@ input_documents:
3738

3839
## Tasks/Subtasks
3940

40-
- [ ] **Task 1: Initialize uv library scaffold**
41-
- [ ] 1.1: Run `uv init --lib` in `/Users/kevinsmith/src/pypi/httpware/`
42-
- [ ] 1.2: Verify `src/httpware/__init__.py` exists
43-
- [ ] 1.3: Add `src/httpware/py.typed` zero-byte marker
44-
45-
- [ ] **Task 2: Configure pyproject.toml**
46-
- [ ] 2.1: Set `[project]` metadata (name, description, authors, requires-python>=3.11, license=MIT, classifiers for Python 3.11-3.14, `Typing :: Typed`)
47-
- [ ] 2.2: Declare main dependencies: `httpx2>=2.0.0b1,<3.0`, `pydantic>=2.0,<3.0`
48-
- [ ] 2.3: Declare extras: `[project.optional-dependencies]` for `msgspec`, `otel`, `niquests`, `all`
49-
- [ ] 2.4: Configure `[build-system]` with `uv_build`
50-
- [ ] 2.5: Configure `[tool.uv.build-backend]` (module-name = "httpware", module-root = "src")
51-
- [ ] 2.6: Add `[project.urls]` for repository and docs
52-
53-
- [ ] **Task 3: Port modern-di conventions to pyproject.toml**
54-
- [ ] 3.1: Fetch the live `modern-python/modern-di/pyproject.toml` to copy authoritative config sections
55-
- [ ] 3.2: Copy `[tool.ruff]` (line-length=120, target-version="py311", fix=true, unsafe-fixes=true) and `[tool.ruff.lint]` (select=ALL, ignore set: D1, S101, TCH, FBT, D203, D213, COM812, ISC001)
56-
- [ ] 3.3: Copy `[tool.pytest.ini_options]` (asyncio_mode="auto", asyncio_default_fixture_loop_scope="function", --cov enabled)
57-
- [ ] 3.4: Copy `[tool.coverage]` config
58-
- [ ] 3.5: Add dev dep group: pytest, pytest-cov, pytest-asyncio, pytest-repeat, pytest-benchmark, hypothesis
59-
- [ ] 3.6: Add lint dep group: ruff, ty, eof-fixer, typing-extensions
60-
61-
- [ ] **Task 4: Add root configuration files**
62-
- [ ] 4.1: `LICENSE` — MIT, copyright "Modern Python contributors"
63-
- [ ] 4.2: `Justfile` with `install`, `test`, `lint`, `format`, `release` recipes (port from modern-di)
64-
- [ ] 4.3: `SECURITY.md` documenting CVE disclosure channel and 90-day private-disclosure window (per NFR10)
65-
- [ ] 4.4: `CONTRIBUTING.md` — short, points to docs site (placeholder URL until docs live)
66-
- [ ] 4.5: `CHANGELOG.md` — Keep-a-Changelog format with an `Unreleased` section
67-
- [ ] 4.6: `CLAUDE.md` — AI-agent guidance (architecture pointers, "use ty: ignore not type: ignore", "no from __future__ import annotations", etc.)
68-
- [ ] 4.7: `context7.json` — minimal config matching modern-di style
69-
- [ ] 4.8: `.gitignore` — Python standard ignores plus uv lockfile direction
70-
71-
- [ ] **Task 5: GitHub Actions CI workflow**
72-
- [ ] 5.1: Create `.github/workflows/ci.yml` running ruff lint, ty type check, pytest --cov
73-
- [ ] 5.2: Configure Python matrix: 3.11, 3.12, 3.13 (3.14 once GA on actions/setup-python)
74-
- [ ] 5.3: Use `uv` for env setup (matches modern-di)
75-
76-
- [ ] **Task 6: Verify build and install**
77-
- [ ] 6.1: Run `uv build` → wheel + sdist produced in `dist/`
78-
- [ ] 6.2: Install wheel into clean venv via `uv venv` + `uv pip install`
79-
- [ ] 6.3: Smoke-import: `python -c "import httpware"` exits 0
80-
- [ ] 6.4: Run `ruff check`, `ty check`, `pytest` locally — all pass (no tests yet; pytest should exit 5 = "no tests collected", treat as pass for scaffold)
81-
- [ ] 6.5: Initialize git repo with first commit on `main`
41+
- [x] **Task 1: Initialize uv library scaffold**
42+
- [x] 1.1: Run `uv init --lib` in `/Users/kevinsmith/src/pypi/httpware/`
43+
- [x] 1.2: Verify `src/httpware/__init__.py` exists
44+
- [x] 1.3: Add `src/httpware/py.typed` zero-byte marker (auto-created by `uv init --lib`)
45+
46+
- [x] **Task 2: Configure pyproject.toml**
47+
- [x] 2.1: Set `[project]` metadata (name, description, authors, requires-python>=3.11, license=MIT, classifiers for Python 3.11-3.14, `Typing :: Typed`)
48+
- [x] 2.2: Declare main dependencies: `httpx2>=2.0.0,<3.0` (tightened from `b1` after smoke install verified GA is on PyPI), `pydantic>=2.0,<3.0`
49+
- [x] 2.3: Declare extras: `[project.optional-dependencies]` for `msgspec`, `otel`, `niquests`, `all`
50+
- [x] 2.4: Configure `[build-system]` with `uv_build>=0.11,<0.12` (upper-bounded per uv's recommendation)
51+
- [x] 2.5: Configure `[tool.uv.build-backend]` (module-name = "httpware", module-root = "src")
52+
- [x] 2.6: Add `[project.urls]` for repository and docs
53+
54+
- [x] **Task 3: Port modern-di conventions to pyproject.toml**
55+
- [x] 3.1: Fetched live `modern-python/modern-di/pyproject.toml`, `Justfile`, `.github/workflows/{ci,publish}.yml`, `.gitignore`, `CLAUDE.md`, `context7.json` via `gh api`
56+
- [x] 3.2: Copied `[tool.ruff]` (line-length=120, target-version="py311", fix=true, unsafe-fixes=true) and `[tool.ruff.lint]` (select=ALL, ignore set: D1, S101, TCH, FBT, D203, D213, COM812, ISC001)
57+
- [x] 3.3: Copied `[tool.pytest.ini_options]` (asyncio_mode="auto", asyncio_default_fixture_loop_scope="function"); adjusted `pythonpath` to `["src"]` and `--cov` to `src/httpware` for src/-layout
58+
- [x] 3.4: Copied `[tool.coverage]` config
59+
- [x] 3.5: Added dev dep group: pytest, pytest-cov, pytest-asyncio, pytest-repeat, pytest-benchmark, hypothesis
60+
- [x] 3.6: Added lint dep group: ruff, ty, eof-fixer, typing-extensions
61+
62+
- [x] **Task 4: Add root configuration files**
63+
- [x] 4.1: `LICENSE` — MIT, copyright "Modern Python contributors"
64+
- [x] 4.2: `Justfile` with `install`, `lint`, `lint-ci`, `test`, `test-branch`, `publish` recipes (verbatim from modern-di)
65+
- [x] 4.3: `SECURITY.md` documenting GitHub Security Advisories disclosure channel and 90-day private-disclosure window (per NFR10)
66+
- [x] 4.4: `CONTRIBUTING.md` — development workflow + architecture invariants
67+
- [x] 4.5: `CHANGELOG.md` — Keep-a-Changelog format with `Unreleased` section populated with scaffold-story changes
68+
- [x] 4.6: `CLAUDE.md` — AI-agent guidance pointing at base-client/docs/{prd,architecture,epics}.md, CI-enforced invariants, code conventions, module layout, 5 protocol seams
69+
- [x] 4.7: `context7.json` — minimal config matching modern-di style (URL only; public_key TBD)
70+
- [x] 4.8: `.gitignore` — Python standard ignores from modern-di + `uv.lock` in ignore list (library convention)
71+
72+
- [x] **Task 5: GitHub Actions CI workflow**
73+
- [x] 5.1: `.github/workflows/ci.yml` runs ruff lint (via `just lint-ci`), pytest with coverage upload to Codecov
74+
- [x] 5.2: Python matrix: 3.11, 3.12, 3.13, 3.14 (matches our floor; modern-di had 3.10 included but our PRD raised the floor)
75+
- [x] 5.3: Uses `astral-sh/setup-uv@v3` + `extractions/setup-just@v2` (matches modern-di)
76+
77+
- [x] **Task 6: Verify build and install**
78+
- [x] 6.1: `uv build` produced `dist/httpware-0-py3-none-any.whl` (3.0K) and `dist/httpware-0.tar.gz` (3.0K)
79+
- [x] 6.2: Installed wheel into clean tempdir venv via `uv venv --python 3.11` + `uv pip install`; 12 packages resolved (httpware + httpx2==2.0.0 + pydantic==2.13.4 + transitive deps)
80+
- [x] 6.3: Smoke-import: `python -c "import httpware"` exits 0; `__all__ == []`
81+
- [x] 6.4: `ruff format`, `ruff check`, `ty check` all pass on empty `src/httpware/__init__.py`; `pytest` collected 0 tests (expected — scaffold story has no library code yet)
82+
- [x] 6.5: Initialized git repo (auto-created by `uv init --lib`), staged all scaffold files, committed as `fe4df95 chore: initial project scaffold (Story 1.1)` on `main`
8283

8384
## Dev Notes
8485

@@ -117,26 +118,87 @@ input_documents:
117118

118119
### Implementation Plan
119120

120-
To be filled in during Step 5.
121+
1. **Initialize via `uv init --lib`** in the empty `/Users/kevinsmith/src/pypi/httpware/` directory — single command sets up `src/httpware/__init__.py`, `py.typed`, minimal `pyproject.toml`, `.gitignore`, `.python-version`, `README.md`, and a fresh `.git/` repo.
122+
2. **Fetch the authoritative `modern-python/modern-di` config files** via `gh api` (pyproject.toml, Justfile, .github/workflows/{ci,publish}.yml, .gitignore, CLAUDE.md, context7.json) and use them as the verbatim source for org conventions, adjusting only:
123+
- Python floor: `>=3.10,<4` → `>=3.11,<4` (per PRD Story 1.1 AC and architecture decision to use `TaskGroup`/`except*`)
124+
- ruff `target-version`: `py310` → `py311`
125+
- Layout: flat (`modern_di/`) → src/ (`src/httpware/`); set `[tool.uv.build-backend] module-root = "src"`
126+
- pytest `pythonpath`: `["."]` → `["src"]`; `--cov` source: `.` → `src/httpware`
127+
- Drop Python 3.10 from CI matrix
128+
3. **Override `__init__.py`** content from the default `def hello()` stub to a docstring + empty `__all__`.
129+
4. **Override `.python-version`** from `3.14` (uv's default) to `3.11` (our declared floor).
130+
5. **Add new content not in modern-di**: dependencies (`httpx2>=2.0,<3.0`, `pydantic>=2.0,<3.0`), install extras, `LICENSE`, `SECURITY.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, populated `README.md`.
131+
6. **Validate**: `uv sync` → `ruff format` → `ruff check` → `ty check` → `pytest` → `uv build` → clean-venv install + smoke import.
132+
7. **Commit**: stage everything except gitignored files (`.python-version`, `.venv`, `uv.lock`), single initial commit on `main`.
121133

122134
### Debug Log
123135

124-
(empty)
136+
- `uv init --lib` auto-created `py.typed` (good — no need to add manually as originally planned in subtask 1.3).
137+
- Initial `httpx2>=2.0.0b1,<3.0` constraint caused `uv pip install` (without `--prerelease=allow`) to skip httpx2 in clean-venv smoke test. Tightened to `>=2.0.0,<3.0` after verifying `httpx2==2.0.0` GA is published on PyPI. Updated PRD and architecture should follow in a future cleanup pass (the docs currently say `>=2.0.0b1,<3.0`; not blocking).
138+
- `uv build` warned about `[build-system] requires = ["uv_build"]` lacking an upper bound. Pinned to `>=0.11,<0.12` to silence the warning and prevent future breakage when uv_build 0.12 ships.
139+
- `git add` initially refused `.python-version` (in `.gitignore` from modern-di's convention); kept it untracked. Same for `uv.lock` (added to `.gitignore` after initial commit attempt staged it).
125140

126141
### Completion Notes
127142

128-
(to be filled at story completion)
143+
**AC verification — all 7 satisfied:**
144+
145+
- **AC1** ✓ `src/httpware/__init__.py` and `src/httpware/py.typed` exist; `pyproject.toml` declares `httpx2>=2.0.0,<3.0` and `pydantic>=2.0,<3.0`.
146+
- **AC2** ✓ Extras `[msgspec]`, `[otel]`, `[niquests]`, `[all]` all declared in `[project.optional-dependencies]`.
147+
- **AC3** ✓ Dev group: pytest, pytest-cov, pytest-asyncio, pytest-repeat, pytest-benchmark, hypothesis. Lint group: ruff, ty, eof-fixer, typing-extensions. Match modern-di + hypothesis addition.
148+
- **AC4** ✓ `[tool.ruff]` and `[tool.pytest.ini_options]` ported verbatim from modern-di with `target-version = "py311"` (raised from `py310`).
149+
- **AC5** ✓ All eight root files exist: Justfile, LICENSE, SECURITY.md, CONTRIBUTING.md, CHANGELOG.md, CLAUDE.md, context7.json, .gitignore.
150+
- **AC6** ✓ `.github/workflows/ci.yml` runs ruff/ty/pytest with coverage upload on Python 3.11–3.14 matrix (3.10 dropped per our floor; 3.14 included since GA is on `actions/setup-python`).
151+
- **AC7** ✓ `uv build` produced wheel+sdist; clean-venv install of the wheel resolved 12 packages (httpware + httpx2 2.0.0 + pydantic 2.13.4 + transitive); `python -c "import httpware"` exited 0 with `__all__ == []`.
152+
153+
**Definition of Done:**
154+
155+
- All Tasks/Subtasks marked `[x]`
156+
- All 7 AC pass
157+
- `ruff format` + `ruff check` + `ty check` + `pytest` all pass locally
158+
- `uv build` succeeds; wheel installs and imports cleanly in a fresh venv
159+
- File List complete; Change Log updated
160+
- Initial commit on `main` (`fe4df95`)
161+
162+
**Deviations from PRD/Architecture docs (worth noting for future cleanup):**
163+
164+
- PRD and Architecture currently specify `httpx2>=2.0.0b1,<3.0` (set when only the beta was published). Story tightened to `>=2.0.0,<3.0` after verifying GA. Update planning artifacts in a follow-up pass.
165+
- `module-name = "httpware"` and `module-root = "src"` (src/ layout) chosen over modern-di's flat layout, per architecture decision §Starter Template (rationale: src/ layout prevents test code from accidentally importing local source).
166+
167+
**Tests written:** None — scaffold story has no library code. Tests begin in Story 1.2.
129168

130169
## File List
131170

132-
To be populated as files are created.
171+
Files added (15 total):
172+
173+
- `.github/workflows/ci.yml` — CI workflow (ruff/ty/pytest, Python 3.11-3.14 matrix)
174+
- `.gitignore` — modern-di convention + project-specific ignores
175+
- `CHANGELOG.md` — Keep-a-Changelog format
176+
- `CLAUDE.md` — AI-agent guidance for working in this repo
177+
- `CONTRIBUTING.md` — contributor workflow and architecture invariants
178+
- `Justfile` — install/lint/test/publish recipes (verbatim from modern-di)
179+
- `LICENSE` — MIT
180+
- `README.md` — project overview, install, quickstart, highlights
181+
- `SECURITY.md` — disclosure policy with 90-day window
182+
- `context7.json` — context7 docs index pointer
183+
- `docs/stories/1-1-project-scaffold-and-tooling.md` — this story file
184+
- `pyproject.toml` — full project config (deps, extras, ruff, pytest, coverage, dep groups)
185+
- `src/httpware/__init__.py` — package init with docstring and empty `__all__`
186+
- `src/httpware/py.typed` — zero-byte typing marker
187+
188+
Generated/transient (not committed):
189+
190+
- `.python-version` — gitignored per modern-di convention
191+
- `uv.lock` — gitignored per modern-di convention (library project)
192+
- `.venv/` — gitignored
193+
- `dist/` — gitignored
133194

134195
## Change Log
135196

136197
| Date | Change | Notes |
137198
|---|---|---|
138199
| 2026-05-12 | Story created | Extracted from `base-client/docs/epics.md` Story 1.1; reorganized into tasks/subtasks for dev workflow. |
200+
| 2026-05-13 | Story completed | All 7 AC pass; initial commit `fe4df95` on `main`; lint+typecheck+build+smoke-install verified. |
139201

140202
## Status
141203

142-
`in-progress`
204+
`review`

0 commit comments

Comments
 (0)