sphinx-vite-builder 0.0.1a16__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sphinx_vite_builder-0.0.1a16/.gitignore +233 -0
- sphinx_vite_builder-0.0.1a16/AGENTS.md +208 -0
- sphinx_vite_builder-0.0.1a16/CLAUDE.md +8 -0
- sphinx_vite_builder-0.0.1a16/PKG-INFO +344 -0
- sphinx_vite_builder-0.0.1a16/README.md +317 -0
- sphinx_vite_builder-0.0.1a16/pyproject.toml +55 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/__init__.py +93 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/_internal/__init__.py +7 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/_internal/bus.py +191 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/_internal/config.py +190 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/_internal/errors.py +42 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/_internal/hooks.py +297 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/_internal/process.py +260 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/_internal/vite.py +404 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/build.py +149 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/hatch_plugin.py +92 -0
- sphinx_vite_builder-0.0.1a16/src/sphinx_vite_builder/py.typed +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Node
|
|
2
|
+
node_modules/
|
|
3
|
+
*.tsbuildinfo
|
|
4
|
+
.vitest-cache/
|
|
5
|
+
|
|
6
|
+
# Byte-compiled / optimized / DLL files
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[codz]
|
|
9
|
+
*$py.class
|
|
10
|
+
|
|
11
|
+
# C extensions
|
|
12
|
+
*.so
|
|
13
|
+
|
|
14
|
+
# Distribution / packaging
|
|
15
|
+
.Python
|
|
16
|
+
build/
|
|
17
|
+
develop-eggs/
|
|
18
|
+
dist/
|
|
19
|
+
downloads/
|
|
20
|
+
eggs/
|
|
21
|
+
.eggs/
|
|
22
|
+
lib/
|
|
23
|
+
lib64/
|
|
24
|
+
parts/
|
|
25
|
+
sdist/
|
|
26
|
+
var/
|
|
27
|
+
wheels/
|
|
28
|
+
share/python-wheels/
|
|
29
|
+
*.egg-info/
|
|
30
|
+
.installed.cfg
|
|
31
|
+
*.egg
|
|
32
|
+
MANIFEST
|
|
33
|
+
|
|
34
|
+
# PyInstaller
|
|
35
|
+
# Usually these files are written by a python script from a template
|
|
36
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
37
|
+
*.manifest
|
|
38
|
+
*.spec
|
|
39
|
+
|
|
40
|
+
# Installer logs
|
|
41
|
+
pip-log.txt
|
|
42
|
+
pip-delete-this-directory.txt
|
|
43
|
+
|
|
44
|
+
# Unit test / coverage reports
|
|
45
|
+
htmlcov/
|
|
46
|
+
.tox/
|
|
47
|
+
.nox/
|
|
48
|
+
.coverage
|
|
49
|
+
.coverage.*
|
|
50
|
+
.cache
|
|
51
|
+
nosetests.xml
|
|
52
|
+
coverage.xml
|
|
53
|
+
*.cover
|
|
54
|
+
*.py.cover
|
|
55
|
+
.hypothesis/
|
|
56
|
+
.pytest_cache/
|
|
57
|
+
cover/
|
|
58
|
+
|
|
59
|
+
# Translations
|
|
60
|
+
*.mo
|
|
61
|
+
*.pot
|
|
62
|
+
|
|
63
|
+
# Django stuff:
|
|
64
|
+
*.log
|
|
65
|
+
local_settings.py
|
|
66
|
+
db.sqlite3
|
|
67
|
+
db.sqlite3-journal
|
|
68
|
+
|
|
69
|
+
# Flask stuff:
|
|
70
|
+
instance/
|
|
71
|
+
.webassets-cache
|
|
72
|
+
|
|
73
|
+
# Scrapy stuff:
|
|
74
|
+
.scrapy
|
|
75
|
+
|
|
76
|
+
# Sphinx documentation
|
|
77
|
+
docs/_build/
|
|
78
|
+
|
|
79
|
+
# PyBuilder
|
|
80
|
+
.pybuilder/
|
|
81
|
+
target/
|
|
82
|
+
|
|
83
|
+
# Jupyter Notebook
|
|
84
|
+
.ipynb_checkpoints
|
|
85
|
+
|
|
86
|
+
# IPython
|
|
87
|
+
profile_default/
|
|
88
|
+
ipython_config.py
|
|
89
|
+
|
|
90
|
+
# pyenv
|
|
91
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
92
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
93
|
+
# .python-version
|
|
94
|
+
|
|
95
|
+
# pipenv
|
|
96
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
97
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
98
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
99
|
+
# install all needed dependencies.
|
|
100
|
+
#Pipfile.lock
|
|
101
|
+
|
|
102
|
+
# UV
|
|
103
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
104
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
105
|
+
# commonly ignored for libraries.
|
|
106
|
+
#uv.lock
|
|
107
|
+
|
|
108
|
+
# poetry
|
|
109
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
110
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
111
|
+
# commonly ignored for libraries.
|
|
112
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
113
|
+
#poetry.lock
|
|
114
|
+
#poetry.toml
|
|
115
|
+
|
|
116
|
+
# pdm
|
|
117
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
118
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
119
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
120
|
+
#pdm.lock
|
|
121
|
+
#pdm.toml
|
|
122
|
+
.pdm-python
|
|
123
|
+
.pdm-build/
|
|
124
|
+
|
|
125
|
+
# pixi
|
|
126
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
127
|
+
#pixi.lock
|
|
128
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
129
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
130
|
+
.pixi
|
|
131
|
+
|
|
132
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
133
|
+
__pypackages__/
|
|
134
|
+
|
|
135
|
+
# Celery stuff
|
|
136
|
+
celerybeat-schedule
|
|
137
|
+
celerybeat.pid
|
|
138
|
+
|
|
139
|
+
# SageMath parsed files
|
|
140
|
+
*.sage.py
|
|
141
|
+
|
|
142
|
+
# Environments
|
|
143
|
+
.env
|
|
144
|
+
.envrc
|
|
145
|
+
.venv
|
|
146
|
+
env/
|
|
147
|
+
venv/
|
|
148
|
+
ENV/
|
|
149
|
+
env.bak/
|
|
150
|
+
venv.bak/
|
|
151
|
+
|
|
152
|
+
# Spyder project settings
|
|
153
|
+
.spyderproject
|
|
154
|
+
.spyproject
|
|
155
|
+
|
|
156
|
+
# Rope project settings
|
|
157
|
+
.ropeproject
|
|
158
|
+
|
|
159
|
+
# mkdocs documentation
|
|
160
|
+
/site
|
|
161
|
+
|
|
162
|
+
# mypy
|
|
163
|
+
.mypy_cache/
|
|
164
|
+
.dmypy.json
|
|
165
|
+
dmypy.json
|
|
166
|
+
|
|
167
|
+
# Pyre type checker
|
|
168
|
+
.pyre/
|
|
169
|
+
|
|
170
|
+
# pytype static type analyzer
|
|
171
|
+
.pytype/
|
|
172
|
+
|
|
173
|
+
# Cython debug symbols
|
|
174
|
+
cython_debug/
|
|
175
|
+
|
|
176
|
+
# PyCharm
|
|
177
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
178
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
179
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
180
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
181
|
+
#.idea/
|
|
182
|
+
|
|
183
|
+
# Abstra
|
|
184
|
+
# Abstra is an AI-powered process automation framework.
|
|
185
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
186
|
+
# Learn more at https://abstra.io/docs
|
|
187
|
+
.abstra/
|
|
188
|
+
|
|
189
|
+
# Visual Studio Code
|
|
190
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
191
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
192
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
193
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
194
|
+
# .vscode/
|
|
195
|
+
|
|
196
|
+
# Ruff stuff:
|
|
197
|
+
.ruff_cache/
|
|
198
|
+
|
|
199
|
+
# PyPI configuration file
|
|
200
|
+
.pypirc
|
|
201
|
+
|
|
202
|
+
# Cursor
|
|
203
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
204
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
205
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
206
|
+
.cursorignore
|
|
207
|
+
.cursorindexingignore
|
|
208
|
+
|
|
209
|
+
# Marimo
|
|
210
|
+
marimo/_static/
|
|
211
|
+
marimo/_lsp/
|
|
212
|
+
__marimo__/
|
|
213
|
+
|
|
214
|
+
# Generated by sphinx_fonts extension (downloaded at build time)
|
|
215
|
+
docs/_static/fonts/
|
|
216
|
+
docs/_static/css/fonts.css
|
|
217
|
+
|
|
218
|
+
# Claude Code
|
|
219
|
+
**/CLAUDE.local.md
|
|
220
|
+
**/CLAUDE.*.md
|
|
221
|
+
**/.claude/settings.local.json
|
|
222
|
+
|
|
223
|
+
# Playwright MCP
|
|
224
|
+
.playwright-mcp/
|
|
225
|
+
|
|
226
|
+
# Repo-local pytest mirror (do not track — validator-only)
|
|
227
|
+
out/
|
|
228
|
+
|
|
229
|
+
# Misc
|
|
230
|
+
.vim/
|
|
231
|
+
*.lprof
|
|
232
|
+
pip-wheel-metadata/
|
|
233
|
+
monkeytype.sqlite3
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# AGENTS.md — `sphinx-vite-builder`
|
|
2
|
+
|
|
3
|
+
Guidance for AI agents (Claude Code, Cursor, Copilot, Codex, …) and
|
|
4
|
+
human contributors working on this package. Mirrors the higher-level
|
|
5
|
+
guidance at `gp-sphinx/CLAUDE.md`; `packages/sphinx-vite-builder/CLAUDE.md`
|
|
6
|
+
points here so Claude Code reads the same content as other agent runners.
|
|
7
|
+
|
|
8
|
+
## What this package is
|
|
9
|
+
|
|
10
|
+
Two orthogonal entry points sharing one subprocess core:
|
|
11
|
+
|
|
12
|
+
1. **PEP 517 build backend** at `sphinx_vite_builder.build`. Runs
|
|
13
|
+
`pnpm exec vite build` before delegating wheel/sdist construction
|
|
14
|
+
to `hatchling.build`. Consumer packages declare it via
|
|
15
|
+
`[build-system].build-backend = "sphinx_vite_builder.build"`.
|
|
16
|
+
2. **Sphinx extension** at `sphinx_vite_builder:setup`. Hooks
|
|
17
|
+
`builder-inited` and `build-finished` so `sphinx-build` /
|
|
18
|
+
`sphinx-autobuild` automatically run vite — one-shot for prod, a
|
|
19
|
+
long-lived `vite build --watch` child process for autobuild — with
|
|
20
|
+
graceful teardown on signal / `atexit`.
|
|
21
|
+
|
|
22
|
+
Both heads consume the smart-subprocess core under
|
|
23
|
+
`sphinx_vite_builder._internal/`: `process.py` (`AsyncProcess` —
|
|
24
|
+
asyncio subprocess wrapper with POSIX session isolation,
|
|
25
|
+
SIGTERM-then-SIGKILL teardown, line-buffered stdout/stderr drainers,
|
|
26
|
+
captured stderr for error surfacing), `bus.py` (`AsyncioBus` — single
|
|
27
|
+
asyncio loop in a daemon thread for sync↔async bridging),
|
|
28
|
+
`vite.py` (orchestration: detect `web/`, check pnpm via `shutil.which`,
|
|
29
|
+
spawn install/build), and `errors.py` (`PnpmMissingError`,
|
|
30
|
+
`NodeModulesInstallError`, `ViteFailedError`).
|
|
31
|
+
|
|
32
|
+
**Phase 1 status:** The PEP 517 backend is fully implemented and
|
|
33
|
+
tested. The Sphinx extension `setup()` is a placeholder — it
|
|
34
|
+
registers cleanly in `conf.py` but doesn't yet hook the docs build
|
|
35
|
+
lifecycle. The full extension implementation (event handlers, vite
|
|
36
|
+
watch, teardown) lands in a follow-up release.
|
|
37
|
+
|
|
38
|
+
## The design contract — keep this invariant
|
|
39
|
+
|
|
40
|
+
> **Sources should check for node, pnpm, etc and error if it's not
|
|
41
|
+
> good, then build. Wheels should have the build files baked in and
|
|
42
|
+
> not need node and pnpm at all.**
|
|
43
|
+
|
|
44
|
+
This is the central invariant. When you change anything in the
|
|
45
|
+
backend, vite orchestration, or release pipeline, ask: "does this
|
|
46
|
+
preserve the source-vs-wheel asymmetry?"
|
|
47
|
+
|
|
48
|
+
### Source builds — fail loud, fail informatively
|
|
49
|
+
|
|
50
|
+
A consumer building from source (cloned tree, `[tool.uv.sources]` git
|
|
51
|
+
URL, `pip install <repo-path>`) goes through the PEP 517 chain. The
|
|
52
|
+
backend's `build_wheel` / `build_editable` / `build_sdist` hooks
|
|
53
|
+
**MUST** run vite, and vite **MUST** be available. If pnpm or Node is
|
|
54
|
+
missing:
|
|
55
|
+
|
|
56
|
+
- Raise the typed exception (`PnpmMissingError`,
|
|
57
|
+
`NodeModulesInstallError`, or `ViteFailedError`) — never a bare
|
|
58
|
+
`subprocess.CalledProcessError` or `FileNotFoundError`. The typed
|
|
59
|
+
exception lets consumers `except` cleanly via the
|
|
60
|
+
`SphinxViteBuilderError` base class.
|
|
61
|
+
- Each error's message MUST be a multi-line, copy-pasteable hint
|
|
62
|
+
formatted by `_format_*_hint()`. Include the canonical install
|
|
63
|
+
paths (`corepack enable`, `https://pnpm.io/installation`), the
|
|
64
|
+
resolved vite-root path, and the `SPHINX_VITE_BUILDER_SKIP=1`
|
|
65
|
+
escape-hatch line.
|
|
66
|
+
- Detect CI via `_detect_ci_provider()`. When CI is detected, append
|
|
67
|
+
the platform-specific YAML/config snippet from `_CI_SETUP_RECIPES`
|
|
68
|
+
so the consumer can copy-paste the fix into their pipeline.
|
|
69
|
+
Supported providers: GitHub Actions, CircleCI, Azure Pipelines,
|
|
70
|
+
GitLab CI, plus a generic fallback for `CI=true`.
|
|
71
|
+
|
|
72
|
+
### Wheel installs — zero toolchain required
|
|
73
|
+
|
|
74
|
+
A consumer doing `pip install <package>==<version>` from PyPI gets a
|
|
75
|
+
wheel that **already contains** the vite-built `static/` tree
|
|
76
|
+
(populated by the backend at release time, packed via hatchling's
|
|
77
|
+
`artifacts` directive). The PEP 517 chain doesn't run. No backend
|
|
78
|
+
invocation. No `_run_vite_build()`. No `shutil.which("pnpm")`. The
|
|
79
|
+
end user sees Python and only Python.
|
|
80
|
+
|
|
81
|
+
### Wheel-from-sdist — the bridge case
|
|
82
|
+
|
|
83
|
+
A consumer doing `pip install <pkg>.tar.gz` (or `--no-binary :all:`)
|
|
84
|
+
runs the wheel-from-sdist chain:
|
|
85
|
+
|
|
86
|
+
1. pip/uv unpacks the sdist into a temp dir
|
|
87
|
+
2. Calls our backend's `build_wheel` against the unpacked tree
|
|
88
|
+
3. The backend's vite-orchestration sees no `web/` (excluded from
|
|
89
|
+
sdist via `[tool.hatch.build.targets.sdist] exclude = ["web/"]`)
|
|
90
|
+
and short-circuits cleanly — `_resolve_vite_root()` returns
|
|
91
|
+
`None`, vite is never invoked
|
|
92
|
+
4. Hatchling packs the pre-baked `static/` (carried in the sdist via
|
|
93
|
+
`[tool.hatch.build] artifacts`) into the wheel
|
|
94
|
+
|
|
95
|
+
Net: **sdist install also requires zero toolchain**. The
|
|
96
|
+
`web/`-absent short-circuit is the load-bearing primitive.
|
|
97
|
+
|
|
98
|
+
## QA permutations — keep them green
|
|
99
|
+
|
|
100
|
+
The install-path permutations every change must keep green:
|
|
101
|
+
|
|
102
|
+
| # | Path | Toolchain | Expected |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| 1 | wheel install from PyPI | none | succeeds; static present |
|
|
105
|
+
| 2 | sdist install from PyPI (`--no-binary :all:`) | none | succeeds; static present (backend short-circuits) |
|
|
106
|
+
| 3 | source build (`uv build` from cloned tree) | with pnpm + Node | succeeds; wheel contains static |
|
|
107
|
+
| 4 | source build (`uv build` from cloned tree) | none | fails with `PnpmMissingError` + CI-platform recipe |
|
|
108
|
+
|
|
109
|
+
When you add a new failure mode or a new short-circuit branch, add a
|
|
110
|
+
new row here AND a corresponding test in
|
|
111
|
+
`tests/test_sphinx_vite_builder_vite.py`.
|
|
112
|
+
|
|
113
|
+
## Architecture map
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
sphinx_vite_builder/
|
|
117
|
+
├── __init__.py Sphinx extension entry: setup(app)
|
|
118
|
+
├── build.py PEP 517/660 hooks (delegate to hatchling)
|
|
119
|
+
├── py.typed
|
|
120
|
+
└── _internal/
|
|
121
|
+
├── errors.py SphinxViteBuilderError + 3 subclasses
|
|
122
|
+
├── process.py AsyncProcess (asyncio subprocess wrapper)
|
|
123
|
+
├── bus.py AsyncioBus (sync↔async bridge)
|
|
124
|
+
└── vite.py run_vite_build() + CI detection + hint formatters
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Neither head calls the other; both consume `_internal/`. The PEP 517
|
|
128
|
+
hooks in `build.py` MUST stay 1:1 mirrors of `flit_core.buildapi` and
|
|
129
|
+
`hatchling.build` — every hook runs `run_vite_build()` then delegates.
|
|
130
|
+
Optional hooks (`get_requires_for_build_*`, `prepare_metadata_for_build_*`)
|
|
131
|
+
alias to hatchling by identity — vite has no influence on dependency
|
|
132
|
+
resolution or distribution metadata, so wrapping them would be wrong.
|
|
133
|
+
|
|
134
|
+
## When you add a new public function
|
|
135
|
+
|
|
136
|
+
- Add doctests. Every public function MUST have working doctests
|
|
137
|
+
per the workspace convention. Use ELLIPSIS for variable output.
|
|
138
|
+
- Add NumPy-style docstrings: short summary, Parameters, Returns,
|
|
139
|
+
Raises, Examples.
|
|
140
|
+
- Add type annotations everywhere, including return types
|
|
141
|
+
(`-> None` on test functions). mypy runs strict mode.
|
|
142
|
+
|
|
143
|
+
## When you add a new error path
|
|
144
|
+
|
|
145
|
+
- Add a new `*Error` subclass in `errors.py` if the failure has a
|
|
146
|
+
distinct semantic meaning. Inherit from `SphinxViteBuilderError`.
|
|
147
|
+
- Add a `_format_*_hint(...)` function in `vite.py` for the
|
|
148
|
+
copy-pasteable diagnostic. Wrap the raise:
|
|
149
|
+
`raise NewError(_format_new_error_hint(...))`.
|
|
150
|
+
- If the new path is reachable in CI, ensure the message includes
|
|
151
|
+
enough context to fix-from-the-message-itself. Add a CI-recipe
|
|
152
|
+
block via `_format_ci_recipe_block()` if relevant.
|
|
153
|
+
- Add tests for: positive case (path triggers correctly), each error
|
|
154
|
+
branch (specific exception, with key strings present in message),
|
|
155
|
+
inheritance from `SphinxViteBuilderError`.
|
|
156
|
+
|
|
157
|
+
## When you change `release.yml` or the workspace
|
|
158
|
+
|
|
159
|
+
The workspace's `release.yml` MUST keep the pnpm + Node setup steps
|
|
160
|
+
that run before `uv build`, otherwise the wheels published to PyPI
|
|
161
|
+
would be empty of static (the prior broken-release pattern that
|
|
162
|
+
motivated this whole package). The required steps are:
|
|
163
|
+
|
|
164
|
+
```yaml
|
|
165
|
+
- uses: pnpm/action-setup@v6
|
|
166
|
+
with:
|
|
167
|
+
version: 10
|
|
168
|
+
- uses: actions/setup-node@v6
|
|
169
|
+
with:
|
|
170
|
+
node-version: 22
|
|
171
|
+
cache: pnpm
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
If you find yourself removing those, ask: "is the source-build path
|
|
175
|
+
still going to produce a populated `static/` in the wheel?" The
|
|
176
|
+
answer must be yes.
|
|
177
|
+
|
|
178
|
+
## When in doubt
|
|
179
|
+
|
|
180
|
+
- Read the full plan at gp-sphinx issue #28.
|
|
181
|
+
- Look at how PR #29 wired everything together initially.
|
|
182
|
+
- Look at how libtmux-mcp PR #33 exercises both consumer paths in
|
|
183
|
+
CI — the WITH-wheels and WITHOUT-wheels permutations both have
|
|
184
|
+
green runs that are good reference points.
|
|
185
|
+
- Run the local QA matrix: clean venv install of the published
|
|
186
|
+
wheel, clean venv install of the published sdist (`--no-binary`),
|
|
187
|
+
clean clone + `uv build` with toolchain stripped (must fail
|
|
188
|
+
loudly), clean clone + `uv build` with toolchain present (must
|
|
189
|
+
succeed).
|
|
190
|
+
|
|
191
|
+
## What NOT to do
|
|
192
|
+
|
|
193
|
+
- **Do not** add `web/` to the sdist. Excluding it is what makes the
|
|
194
|
+
wheel-from-sdist short-circuit work.
|
|
195
|
+
- **Do not** commit anything from `static/` to git. Build artefacts
|
|
196
|
+
are produced reproducibly; check-in is forbidden by workspace
|
|
197
|
+
policy.
|
|
198
|
+
- **Do not** silently swallow vite/pnpm subprocess failures. Every
|
|
199
|
+
non-zero exit goes through a typed exception with a
|
|
200
|
+
copy-pasteable hint.
|
|
201
|
+
- **Do not** auto-install pnpm via the backend (the maturin
|
|
202
|
+
`puccinialin`-style trick doesn't apply here — pnpm isn't
|
|
203
|
+
pip-installable). The contract is "pnpm is your responsibility,
|
|
204
|
+
here's how to install it on your platform".
|
|
205
|
+
- **Do not** change `SPHINX_VITE_BUILDER_SKIP=1` semantics without
|
|
206
|
+
thinking through the wheel-vs-source asymmetry. The escape hatch
|
|
207
|
+
is correct for wheel-only environments; using it during a real
|
|
208
|
+
source build silently produces broken artefacts.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Claude Code reads this file. Other agent runners (Cursor, Copilot,
|
|
4
|
+
Codex, …) read [`AGENTS.md`](AGENTS.md). The two files have identical
|
|
5
|
+
content via this passthrough — every guideline lives in `AGENTS.md`,
|
|
6
|
+
and edits go there.
|
|
7
|
+
|
|
8
|
+
→ See [`AGENTS.md`](AGENTS.md).
|