Skip to content

Commit 7ac6816

Browse files
fix: include .cursor assets in PyPI wheel (bootstrap exit 1)
setuptools skipped dot-directories under assets/**; bootstrap installed CLI but init left projects without Cursor rules. v4.5.3 Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 553d470 commit 7ac6816

6 files changed

Lines changed: 73 additions & 34 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable changes to GraphStack are documented here.
44

55
---
66

7+
## [v4.5.3] — 2026-06-11
8+
9+
### Fixed
10+
- **PyPI wheel**`.cursor/` rules, commands, and skills were omitted from the wheel (setuptools skips dot-directories under `assets/**/*`). Bootstrap `irm … | iex` installed the CLI but `graphstack init` left the project without Cursor rules; doctor exited 1.
11+
- Explicit `package-data` entries + `MANIFEST.in` graft; wheel asset test added.
12+
13+
---
14+
715
## [v4.5.2] — 2026-06-11
816

917
### Changed

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Dot-directories under assets/ must be grafted for sdist + wheel discovery.
2+
graft scripts/graphstack/assets

pyproject.toml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "MertCapkin_GraphStack"
7-
version = "4.5.2"
7+
version = "4.5.3"
88
description = "Graph-first AI development workflow — board, gate, graph queries, one-shot init"
99
readme = "README.md"
1010
license = { text = "MIT" }
@@ -42,8 +42,24 @@ graphstack = "graphstack.cli:main"
4242
[tool.setuptools.packages.find]
4343
where = ["scripts"]
4444

45+
[tool.setuptools]
46+
include-package-data = true
47+
48+
# setuptools ``assets/**/*`` skips dot-directories (``.cursor/``) — list explicitly.
4549
[tool.setuptools.package-data]
46-
graphstack = ["assets/**/*", "compact/**/*"]
50+
graphstack = [
51+
"assets/.cursor/rules/graphstack.mdc",
52+
"assets/.cursor/commands/graphstack.md",
53+
"assets/.cursor/skills/architect/ARCHITECT.md",
54+
"assets/.cursor/skills/builder/BUILDER.md",
55+
"assets/.cursor/skills/reviewer/REVIEWER.md",
56+
"assets/.cursor/skills/qa/QA.md",
57+
"assets/.cursor/skills/ship/SHIP.md",
58+
"assets/.cursor/skills/bootstrapper/BOOTSTRAPPER.md",
59+
"assets/.graphstack-assets-version",
60+
"assets/**/*",
61+
"compact/**/*",
62+
]
4763

4864
[tool.pytest.ini_options]
4965
testpaths = ["scripts/graphstack/tests"]

scripts/bootstrap.ps1

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,12 @@ if ($LASTEXITCODE -ne 0) {
4848
Write-Host ''
4949
Write-Host 'Step 2/2: Initializing GraphStack in this project...'
5050
& $python.Exe @($python.PreArgs) -m graphstack init . -y --install-deps
51-
exit $LASTEXITCODE
51+
$initRc = $LASTEXITCODE
52+
if ($initRc -ne 0) {
53+
Write-Host ''
54+
Write-Host 'Bootstrap finished with errors (exit ' $initRc ').' -ForegroundColor Yellow
55+
Write-Host 'PyPI package may be installed, but project init or doctor failed.'
56+
Write-Host 'Check output above, then run: py -3 -m graphstack doctor'
57+
Write-Host 'If .cursor/rules/graphstack.mdc is missing, upgrade: pip install -U MertCapkin_GraphStack[graphify]'
58+
}
59+
exit $initRc

scripts/graphstack/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
``gate``, ``state``, ``graph``
99
"""
1010

11-
__version__ = "4.5.2"
11+
__version__ = "4.5.3"
1212
__all__ = ["__version__"]
Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,40 @@
1-
"""Tests for bundled assets and install source resolution."""
1+
"""PyPI wheel must ship ``.cursor`` workflow files inside ``graphstack/assets``."""
22

33
from __future__ import annotations
44

5+
import zipfile
56
from pathlib import Path
67

7-
from graphstack.installer import PACKAGE_ROOT, install_source_root
8-
9-
10-
def test_install_source_root_from_dev_repo() -> None:
11-
root = install_source_root()
12-
assert (root / "orchestrator" / "ORCHESTRATOR.md").is_file()
13-
14-
15-
def test_bundled_assets_exist_in_package() -> None:
16-
assets = PACKAGE_ROOT / "assets"
17-
assert (assets / "orchestrator" / "ORCHESTRATOR.md").is_file()
18-
assert (assets / ".cursor" / "rules" / "graphstack.mdc").is_file()
19-
20-
21-
def test_install_from_bundled_assets_only(tmp_path: Path, monkeypatch) -> None:
22-
from graphstack import installer
23-
24-
assets = PACKAGE_ROOT / "assets"
25-
monkeypatch.setattr(
26-
installer,
27-
"_source_root",
28-
lambda: assets,
29-
)
30-
target = tmp_path / "consumer"
31-
target.mkdir()
32-
assert installer.install(target, non_interactive=True) == 0
33-
assert (target / "orchestrator" / "ORCHESTRATOR.md").is_file()
34-
assert (target / ".cursor" / "rules" / "graphstack.mdc").is_file()
35-
assert (target / "handoff" / "BRIEF.md").is_file()
8+
import pytest
9+
10+
REPO_ROOT = Path(__file__).resolve().parents[3]
11+
WHEEL_GLOB = "mertcapkin_graphstack-*.whl"
12+
13+
REQUIRED_ASSET_PATHS = (
14+
"graphstack/assets/.cursor/rules/graphstack.mdc",
15+
"graphstack/assets/.cursor/commands/graphstack.md",
16+
"graphstack/assets/.cursor/skills/architect/ARCHITECT.md",
17+
"graphstack/assets/.cursor/skills/builder/BUILDER.md",
18+
)
19+
20+
21+
def _latest_wheel(dist_dir: Path) -> Path | None:
22+
wheels = sorted(dist_dir.glob(WHEEL_GLOB), key=lambda p: p.stat().st_mtime)
23+
return wheels[-1] if wheels else None
24+
25+
26+
@pytest.mark.parametrize("member", REQUIRED_ASSET_PATHS)
27+
def test_wheel_includes_cursor_assets(member: str) -> None:
28+
for dist_name in ("dist", "dist_test"):
29+
dist_dir = REPO_ROOT / dist_name
30+
wheel = _latest_wheel(dist_dir)
31+
if wheel is None:
32+
continue
33+
with zipfile.ZipFile(wheel) as archive:
34+
names = set(archive.namelist())
35+
assert member in names, (
36+
f"{member} missing from {wheel.name}; "
37+
"dot-directories under assets/ need explicit package-data"
38+
)
39+
return
40+
pytest.skip("no built wheel in dist/ or dist_test/ — run python -m build first")

0 commit comments

Comments
 (0)