You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Quality, skill system, adoption workflow, and pyproject best-practices overhaul
A broad improvement pass across the toolkit, its dogfooded config, the bundled
skills, and the new-project/adoption flow. Tree is green (pyclawd check) and the
dogfood golden baseline is unchanged.
Quality tooling & config model
- BuildConfig: group compile/dist/clean knobs into Project.build (BuildConfig | None);
compile/dist/clean exit 2 when unset. Scaffold, dogfood, reference example, CHANGELOG
updated (breaking config change).
- doctor: detect deps by distribution name via importlib.metadata (fixes the false WARN
for pytest-xdist/pytest-cov); remove the core->commands layering by extracting skill
install/drift logic into a new core module, skills_install.py.
- check: replace the positional 4-tuple with a StepResult dataclass (JSON unchanged).
- test: clean "unknown category" error; argparse for the timings flags.
- golden: pyclawd now dogfoods golden (GoldenConfig + a dedicated golden tier) with a
seeded baseline; fix golden_dir to an absolute repo-root path so the CLI and plugin
agree regardless of pytest rootdir.
- backfill tests: junit/reporting, GoldenStore IO, BuildConfig.
Skills: 7 -> 4 -> 5 (progressive disclosure)
- Collapse the umbrella + tests/quality/docs skills into one `pyclawd` router skill
(lean SKILL.md + references/{mental-model,tests,quality,docs,packaging}.md, on-demand).
- Keep golden/doctor/upgrade standalone; add a new `pyclawd-adopt` skill (the
field-tested red->green adoption playbook, self-contained).
- Add `pyclawd skills prune` + `install --prune` + a doctor orphan WARN so skills
dropped from the bundle don't linger in ~/.claude/skills.
- Consistency/completeness pass: router now routes to adopt; cross-link tables on every
standalone skill; document skills-prune, coverage, and the timings flags.
Adoption (existing repo -> pyclawd)
- `pyclawd new` adopt mode detects flat-vs-src layout, infers root_markers, prints a
Phase-0 readiness report, and offers opt-in `--scaffold-pyproject` (appends only
missing [tool.*] sections, never clobbers).
- Route the "not a project" errors to `pyclawd new` + the pyclawd-adopt skill.
- Golden adoption doctrine: existing tests are the primary oracle for mechanical
changes; golden is the targeted supplement for outputs tests don't lock.
pyproject best practices (researched, .claude/docs/pyproject-toml.md)
- PEP 639: drop the deprecated `License ::` classifier; add `license-files`.
- PEP 561: ship `py.typed` and include it in the wheel (pyclawd is a typed lib).
- mypy: scope `ignore_missing_imports` to jupyter_cache (no global); fix `mypy_path`
to `src` (correct for src layout). Stays non-strict by choice.
- pin build backend `hatchling>=1.27` (PEP 639); ruff `select` adds `W`.
- scaffold: line-length 100, `--import-mode=importlib`, `xfail_strict`, `exclude_also`,
and drop `-n auto` from addopts (pyclawd injects parallelism) so bare pytest / the
scaffolded CI no longer require pytest-xdist; CI installs the PEP 735 dev group.
- Verified by building the wheel: ships py.typed, METADATA carries License-Expression.
Copy file name to clipboardExpand all lines: .claude/CLAUDE.md
+6-2Lines changed: 6 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,7 +32,7 @@ all of these and reports OK/WARN/FAIL.
32
32
|`pyclawd test …`|**pytest**|`test fast` also wants **pytest-xdist** (`-n auto`) |
33
33
|`pyclawd lint` / `format`|**ruff**| argv set in `QualityConfig`|
34
34
|`pyclawd typecheck`|**mypy**| argv set in `QualityConfig`|
35
-
|`pyclawd compile` / `dist`| the project's build backend | only if `compile_cmd` / `dist_cmd` are set|
35
+
|`pyclawd compile` / `dist`| the project's build backend | only if `project.build` (a `BuildConfig`) sets `compile_cmd` / `dist_cmd`; `build=None` → exit 2|
36
36
|`pyclawd docs build/run/render/exec`| a **`./docs` runner** (sphinx + nbsphinx, via uvx or installed) | delegated to `DocsConfig.runner`; **`render` also needs the `pandoc` system binary**|
37
37
|`pyclawd docs failures` / `timings`| a **jupyter-cache** backend at `cache_db`; `failures` imports `jupyter_cache` + `nbformat`**in this env**| see the backend note on `DocsConfig`|
38
38
@@ -79,7 +79,11 @@ toolchain is the dogfooded one: ruff + mypy + pytest, all configured in
79
79
-**Commands degrade, never crash.** An unconfigured group (e.g. `docs`, `quality`)
80
80
self-reports and exits `2`; an undefined test tier applies no `-m` filter. Keep
81
81
that contract — prefer `dict.get(...)` / clean `typer.Exit` over raw `KeyError`s.
82
-
-**Exit-code contract:**`0` ok · `2` not-configured · otherwise the tool's own code.
82
+
-**Exit-code contract:**`0` ok · `2` = not-configured **or** a CLI usage error
83
+
(Typer's own convention) · otherwise the underlying tool's own code. Note that
84
+
`pyclawd docs` preflight uses distinct codes — `3` for a missing `pandoc` binary,
85
+
`1` for "no built docs yet" — so don't assume every nonzero from docs is the
86
+
runner's code.
83
87
-**Keep the dogfood honest.** If you add a command or config field, update
84
88
`.pyclawd/config.py`, `AGENTS.md`, `README.md`, and the scaffold templates so a
85
89
freshly-`pyclawd new`-ed project still matches reality.
test=TestConfig( # tests dir + tier marker expressions
109
111
tests_dir="tests/",
@@ -121,7 +123,7 @@ project = Project(
121
123
)
122
124
```
123
125
124
-
The nested configs (`QualityConfig`, `TestConfig`, `DocsConfig`, `DoctorConfig`) each gate their command group: leave one out and those commands self-report as unconfigured instead of crashing.
126
+
The nested configs (`QualityConfig`, `TestConfig`, `DocsConfig`, `DoctorConfig`, plus the optional `BuildConfig` via `project.build` and `GoldenConfig`) each gate their command group: leave one out and those commands self-report as unconfigured instead of crashing (e.g. `build=None` → `compile`/`dist`/`clean` exit 2).
125
127
126
128
Two worked examples bracket the range:
127
129
@@ -132,7 +134,7 @@ Copy whichever is closer and delete what you don't use.
132
134
133
135
## Skills
134
136
135
-
pyclawd ships agent-facing slash-command skills under [`skills/`](skills/): the start-here umbrella `pyclawd` skill plus the focused `pyclawd-doctor`, `pyclawd-tests`, `pyclawd-quality`, `pyclawd-golden`, `pyclawd-docs`, and `pyclawd-upgrade`. They are thin wrappers over the CLI. Copy or symlink the `pyclawd-*` directories into a project's `.claude/skills/` — see [`skills/README.md`](skills/README.md). Agent doctrine for any pyclawd project lives in [`AGENTS.md`](AGENTS.md).
137
+
pyclawd ships agent-facing slash-command skills under [`skills/`](skills/): the start-here umbrella `pyclawd`router skill (a lean overview plus on-demand `references/{mental-model,tests,quality,docs,packaging}.md` carrying the testing/quality/docs/packaging doctrine) plus the four focused standalone skills `pyclawd-adopt` (adopt pyclawd into an existing repo — red-to-green with zero behavior regression), `pyclawd-golden`, `pyclawd-doctor`, and `pyclawd-upgrade` (migrate *after* a pyclawd version bump — the upgrade counterpart to first-time adoption). They are thin wrappers over the CLI. `pyclawd skills install` copies (or symlinks) the `pyclawd-*` directories into your **user-scope**`~/.claude/skills/` by default — they are generic, so they are shared across every project rather than committed per-repo — see [`skills/README.md`](skills/README.md). Agent doctrine for any pyclawd project lives in [`AGENTS.md`](AGENTS.md).
0 commit comments