diff --git a/bench/uv.lock b/bench/uv.lock index b169178..fca6c8c 100644 --- a/bench/uv.lock +++ b/bench/uv.lock @@ -848,7 +848,7 @@ wheels = [ [[package]] name = "docpull" -version = "6.5.3" +version = "6.5.4" source = { editable = "../" } dependencies = [ { name = "aiohttp" }, diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 33c44d3..7f55125 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [6.5.4] - 2026-09-04 + +### Fixed +- Treat a non-executable `docpull` path as an unavailable runtime and return the + same actionable setup guidance as a missing executable. + ## [6.5.3] - 2026-09-04 ### Fixed diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index cce8849..d3681cb 100644 --- a/plugin/.claude-plugin/plugin.json +++ b/plugin/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "docpull", - "version": "6.5.3", + "version": "6.5.4", "description": "Pull public web sources into Claude Code. Indexes static and server-rendered sites as local Markdown with conditional-GET caching, then exposes them as MCP tools. Local, browser-free, no API keys.", "author": { "name": "Raintree Technology", diff --git a/plugin/.codex-plugin/plugin.json b/plugin/.codex-plugin/plugin.json index ee266bb..bfc5641 100644 --- a/plugin/.codex-plugin/plugin.json +++ b/plugin/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "id": "docpull", "name": "docpull", - "version": "6.5.3", + "version": "6.5.4", "description": "Pull public web sources into Codex as local, searchable Markdown through docpull's MCP server.", "skills": "./skills/", "mcpServers": "./.mcp.json", diff --git a/plugin/README.md b/plugin/README.md index e544590..2f21129 100644 --- a/plugin/README.md +++ b/plugin/README.md @@ -20,8 +20,8 @@ for the boundary between the plugin's MCP tools and the broader CLI/SDK. The plugin wraps the `docpull` CLI. Install the MCP extra first: ```bash -pipx install 'docpull[mcp]==6.5.3' -docpull --version # should print 6.5.3 or newer +pipx install 'docpull[mcp]==6.5.4' +docpull --version # should print 6.5.4 or newer docpull mcp --help ``` diff --git a/plugin/scripts/launch-docpull-mcp.mjs b/plugin/scripts/launch-docpull-mcp.mjs index 27e4626..eb452c1 100644 --- a/plugin/scripts/launch-docpull-mcp.mjs +++ b/plugin/scripts/launch-docpull-mcp.mjs @@ -7,9 +7,9 @@ const child = spawn("docpull", ["mcp", ...process.argv.slice(2)], { }); child.on("error", (error) => { - if (error.code === "ENOENT") { + if (error.code === "ENOENT" || error.code === "EACCES") { console.error( - "DocPull is not installed. Run: pipx install 'docpull[mcp]==6.5.3'", + "DocPull is not installed or is not executable. Run: pipx install 'docpull[mcp]==6.5.4'", ); process.exitCode = 127; return; diff --git a/pyproject.toml b/pyproject.toml index a9dfc10..de7a19d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "docpull" -version = "6.5.3" +version = "6.5.4" dynamic = [] description = "Declare, sync, diff, and lock context dependencies for AI agents" readme = {file = "README.md", content-type = "text/markdown"} diff --git a/sdk/js/package.json b/sdk/js/package.json index 31a02f8..f4824cc 100644 --- a/sdk/js/package.json +++ b/sdk/js/package.json @@ -1,6 +1,6 @@ { "name": "@raintree-technology/docpull-sdk", - "version": "6.5.3", + "version": "6.5.4", "description": "TypeScript SDK for reading docpull context packs and running the docpull CLI", "license": "MIT", "type": "module", diff --git a/server.json b/server.json index aa0898c..30b186a 100644 --- a/server.json +++ b/server.json @@ -8,12 +8,12 @@ "source": "github" }, "websiteUrl": "https://github.com/raintree-technology/docpull", - "version": "6.5.3", + "version": "6.5.4", "packages": [ { "registryType": "pypi", "identifier": "docpull", - "version": "6.5.3", + "version": "6.5.4", "transport": { "type": "stdio" } diff --git a/src/docpull/__init__.py b/src/docpull/__init__.py index 2abcaba..a250f46 100644 --- a/src/docpull/__init__.py +++ b/src/docpull/__init__.py @@ -15,7 +15,7 @@ from .surface import PUBLIC_SDK_EXPORTS -__version__ = "6.5.3" +__version__ = "6.5.4" _LAZY_EXPORTS: dict[str, tuple[str, str]] = { **{ diff --git a/tests/test_ci_policy.py b/tests/test_ci_policy.py index 3ee4524..ae62219 100644 --- a/tests/test_ci_policy.py +++ b/tests/test_ci_policy.py @@ -310,20 +310,42 @@ def test_plugin_manifest_versions_match_project_version() -> None: assert manifest["version"] == project_version() -def test_plugin_launcher_reports_actionable_setup_when_docpull_is_missing() -> None: +def test_plugin_launcher_reports_actionable_setup_when_docpull_is_missing( + tmp_path: Path, +) -> None: launcher = REPO_ROOT / "plugin" / "scripts" / "launch-docpull-mcp.mjs" - node = shutil.which("node") - assert node is not None + node_shim = shutil.which("node") + assert node_shim is not None + node = subprocess.run( # nosec B603 + [node_shim, "-p", "process.execPath"], + check=True, + text=True, + capture_output=True, + ).stdout.strip() + proc = subprocess.run( # nosec B603 + [node, str(launcher)], + check=False, + text=True, + env={"PATH": ""}, + capture_output=True, + cwd=tmp_path, + ) + + assert proc.returncode == 127 + assert "pipx install 'docpull[mcp]==6.5.4'" in proc.stderr + + (tmp_path / "docpull").mkdir() proc = subprocess.run( # nosec B603 [node, str(launcher)], check=False, text=True, env={"PATH": ""}, capture_output=True, + cwd=tmp_path, ) assert proc.returncode == 127 - assert "pipx install 'docpull[mcp]==6.5.3'" in proc.stderr + assert "pipx install 'docpull[mcp]==6.5.4'" in proc.stderr def test_codex_plugin_default_prompt_fits_host_limit() -> None: diff --git a/uv.lock b/uv.lock index 4b1c125..3362f5b 100644 --- a/uv.lock +++ b/uv.lock @@ -1305,7 +1305,7 @@ wheels = [ [[package]] name = "docpull" -version = "6.5.3" +version = "6.5.4" source = { editable = "." } dependencies = [ { name = "aiohttp" },